diff --git a/dep/gsoap/README.md b/dep/gsoap/README.md new file mode 100644 index 000000000000..7a6b2880b463 --- /dev/null +++ b/dep/gsoap/README.md @@ -0,0 +1,37 @@ +# gSOAP +SOAP is an older protocol that communicates over HTTP. +For MaNGOS it is used to execute commands on the world server. + +## How to update this + +Download the latest [gSOAP Toolkit Files](https://sourceforge.net/projects/gsoap2/files/) + +### Windows +1. Open a terminal in this folder +2. Execute `/gsoap/bin/win64/soapcpp2.exe -1 -S -L -w -x -y -c++11 gsoap.stub` +3. Remove `ns1.nsmap` +4. Copy `/gsoap/stdsoap2.h` +5. Copy `/gsoap/stdsoap2.cpp` + +### Linux +
+Build gSOAP on Ubuntu + +``` +unzip gsoap_2.8.135.zip +cd gsoap-2.8 +apt install yacc flex libbison-dev +./configure +./makemake +make +``` + +
+ +``` +cd +/gsoap/src/soapcpp2 -1 -S -L -w -x -y -c++11 gsoap.stub +rm ns1.nsmap +cp /gsoap/stdsoap2.h . +cp /gsoap/stdsoap2.cpp . +``` diff --git a/dep/gsoap/gsoap.stub b/dep/gsoap/gsoap.stub new file mode 100644 index 000000000000..be215b466556 --- /dev/null +++ b/dep/gsoap/gsoap.stub @@ -0,0 +1 @@ +int ns1__executeCommand(char* command, char** result); diff --git a/dep/gsoap/soapC.cpp b/dep/gsoap/soapC.cpp index 9196717858cd..07df0da51925 100644 --- a/dep/gsoap/soapC.cpp +++ b/dep/gsoap/soapC.cpp @@ -1,129 +1,162 @@ /* soapC.cpp - Generated by gSOAP 2.7.10 from stub.h - Copyright(C) 2000-2008, Robert van Engelen, Genivia Inc. All Rights Reserved. - This part of the software is released under one of the following licenses: - GPL, the gSOAP public license, or Genivia's license for commercial use. + Generated by gSOAP 2.8.135 for gsoap.stub + +gSOAP XML Web services tools +Copyright (C) 2000,2024, Robert van Engelen, Genivia Inc. All Rights Reserved. +The soapcpp2 tool and its generated software are released under the GPL. +This program is released under the GPL with the additional exemption that +compiling, linking, and/or using OpenSSL is allowed. +-------------------------------------------------------------------------------- +A commercial use license is available from Genivia Inc., contact@genivia.com +-------------------------------------------------------------------------------- */ +#if defined(__BORLANDC__) +#pragma option push -w-8060 +#pragma option push -w-8004 +#endif + #include "soapH.h" -SOAP_SOURCE_STAMP("@(#) soapC.cpp ver 2.7.10 2010-02-18 18:41:56 GMT") +SOAP_SOURCE_STAMP("@(#) soapC.cpp ver 2.8.135 2024-08-26 13:07:03 GMT") #ifndef WITH_NOGLOBAL -SOAP_FMAC3 void SOAP_FMAC4 soap_serializeheader(struct soap *soap) +SOAP_FMAC3 int SOAP_FMAC4 soap_getheader(struct soap *soap) { - if (soap->header) - soap_serialize_SOAP_ENV__Header(soap, soap->header); + soap->part = SOAP_IN_HEADER; + soap->header = soap_in_SOAP_ENV__Header(soap, "SOAP-ENV:Header", soap->header, NULL); + soap->part = SOAP_END_HEADER; + return soap->header == NULL; } SOAP_FMAC3 int SOAP_FMAC4 soap_putheader(struct soap *soap) { - if (soap->header) - { soap->part = SOAP_IN_HEADER; - if (soap_out_SOAP_ENV__Header(soap, "SOAP-ENV:Header", 0, soap->header, nullptr)) - return soap->error; - soap->part = SOAP_END_HEADER; - } - return SOAP_OK; + if (soap->version && soap->header) + { soap->part = SOAP_IN_HEADER; + if (soap_out_SOAP_ENV__Header(soap, "SOAP-ENV:Header", 0, soap->header, "")) + return soap->error; + soap->part = SOAP_END_HEADER; + } + return SOAP_OK; } -SOAP_FMAC3 int SOAP_FMAC4 soap_getheader(struct soap *soap) +SOAP_FMAC3 void SOAP_FMAC4 soap_serializeheader(struct soap *soap) { - soap->part = SOAP_IN_HEADER; - soap->header = soap_in_SOAP_ENV__Header(soap, "SOAP-ENV:Header", nullptr, nullptr); - soap->part = SOAP_END_HEADER; - return soap->header == nullptr; + if (soap->version && soap->header) + soap_serialize_SOAP_ENV__Header(soap, soap->header); } SOAP_FMAC3 void SOAP_FMAC4 soap_header(struct soap *soap) { - if (!soap->header) - { soap->header = soap_new_SOAP_ENV__Header(soap, -1); - soap_default_SOAP_ENV__Header(soap, soap->header); - } + if (soap->header == NULL) + { if ((soap->header = soap_new_SOAP_ENV__Header(soap))) + soap_default_SOAP_ENV__Header(soap, soap->header); + } } SOAP_FMAC3 void SOAP_FMAC4 soap_fault(struct soap *soap) { - if (!soap->fault) - { soap->fault = soap_new_SOAP_ENV__Fault(soap, -1); - soap_default_SOAP_ENV__Fault(soap, soap->fault); - } - if (soap->version == 2 && !soap->fault->SOAP_ENV__Code) - { soap->fault->SOAP_ENV__Code = soap_new_SOAP_ENV__Code(soap, -1); - soap_default_SOAP_ENV__Code(soap, soap->fault->SOAP_ENV__Code); - } - if (soap->version == 2 && !soap->fault->SOAP_ENV__Reason) - { soap->fault->SOAP_ENV__Reason = soap_new_SOAP_ENV__Reason(soap, -1); - soap_default_SOAP_ENV__Reason(soap, soap->fault->SOAP_ENV__Reason); - } + if (soap->fault == NULL) + { soap->fault = soap_new_SOAP_ENV__Fault(soap, -1); + if (soap->fault == NULL) + return; + } + if (soap->version == 2 && soap->fault->SOAP_ENV__Code == NULL) + soap->fault->SOAP_ENV__Code = soap_new_SOAP_ENV__Code(soap, -1); + if (soap->version == 2 && soap->fault->SOAP_ENV__Reason == NULL) + soap->fault->SOAP_ENV__Reason = soap_new_SOAP_ENV__Reason(soap, -1); } SOAP_FMAC3 void SOAP_FMAC4 soap_serializefault(struct soap *soap) { - soap_fault(soap); - if (soap->fault) - soap_serialize_SOAP_ENV__Fault(soap, soap->fault); + if (soap->fault) + soap_serialize_SOAP_ENV__Fault(soap, soap->fault); } SOAP_FMAC3 int SOAP_FMAC4 soap_putfault(struct soap *soap) { - if (soap->fault) - return soap_put_SOAP_ENV__Fault(soap, soap->fault, "SOAP-ENV:Fault", nullptr); - return SOAP_OK; + if (soap->fault) + return soap_put_SOAP_ENV__Fault(soap, soap->fault, "SOAP-ENV:Fault", ""); + return SOAP_OK; } SOAP_FMAC3 int SOAP_FMAC4 soap_getfault(struct soap *soap) { - return (soap->fault = soap_get_SOAP_ENV__Fault(soap, nullptr, "SOAP-ENV:Fault", nullptr)) == nullptr; + return (soap->fault = soap_get_SOAP_ENV__Fault(soap, NULL, "SOAP-ENV:Fault", NULL)) == NULL; } SOAP_FMAC3 const char ** SOAP_FMAC4 soap_faultcode(struct soap *soap) { - soap_fault(soap); - if (soap->version == 2) - return (const char**)&soap->fault->SOAP_ENV__Code->SOAP_ENV__Value; - return (const char**)&soap->fault->faultcode; + soap_fault(soap); + if (soap->fault == NULL) + return NULL; + if (soap->version == 2 && soap->fault->SOAP_ENV__Code) + return (const char**)(void*)&soap->fault->SOAP_ENV__Code->SOAP_ENV__Value; + return (const char**)(void*)&soap->fault->faultcode; } SOAP_FMAC3 const char ** SOAP_FMAC4 soap_faultsubcode(struct soap *soap) { - soap_fault(soap); - if (soap->version == 2) - { if (!soap->fault->SOAP_ENV__Code->SOAP_ENV__Subcode) - { soap->fault->SOAP_ENV__Code->SOAP_ENV__Subcode = soap_new_SOAP_ENV__Code(soap, -1); - soap_default_SOAP_ENV__Code(soap, soap->fault->SOAP_ENV__Code->SOAP_ENV__Subcode); - } - return (const char**)&soap->fault->SOAP_ENV__Code->SOAP_ENV__Subcode->SOAP_ENV__Value; - } - return (const char**)&soap->fault->faultcode; + soap_fault(soap); + if (soap->fault == NULL) + return NULL; + if (soap->version == 2 && soap->fault->SOAP_ENV__Code) + { if (soap->fault->SOAP_ENV__Code->SOAP_ENV__Subcode == NULL) + { soap->fault->SOAP_ENV__Code->SOAP_ENV__Subcode = soap_new_SOAP_ENV__Code(soap, -1); + if (soap->fault->SOAP_ENV__Code->SOAP_ENV__Subcode == NULL) + return NULL; + } + return (const char**)(void*)&soap->fault->SOAP_ENV__Code->SOAP_ENV__Subcode->SOAP_ENV__Value; + } + return (const char**)(void*)&soap->fault->faultcode; +} + +SOAP_FMAC3 const char * SOAP_FMAC4 soap_fault_subcode(struct soap *soap) +{ + if (!soap->fault) + return NULL; + if (soap->version == 2) + return soap->fault->SOAP_ENV__Code && soap->fault->SOAP_ENV__Code->SOAP_ENV__Subcode ? soap->fault->SOAP_ENV__Code->SOAP_ENV__Subcode->SOAP_ENV__Value : NULL; + return soap->fault->faultcode; } SOAP_FMAC3 const char ** SOAP_FMAC4 soap_faultstring(struct soap *soap) { - soap_fault(soap); - if (soap->version == 2) - return (const char**)&soap->fault->SOAP_ENV__Reason->SOAP_ENV__Text; - return (const char**)&soap->fault->faultstring; + soap_fault(soap); + if (soap->fault == NULL) + return NULL; + if (soap->version == 2 && soap->fault->SOAP_ENV__Reason) + return (const char**)(void*)&soap->fault->SOAP_ENV__Reason->SOAP_ENV__Text; + return (const char**)(void*)&soap->fault->faultstring; +} + +SOAP_FMAC3 const char * SOAP_FMAC4 soap_fault_string(struct soap *soap) +{ + const char **s = soap_faultstring(soap); + return s ? *s : NULL; } SOAP_FMAC3 const char ** SOAP_FMAC4 soap_faultdetail(struct soap *soap) { - soap_fault(soap); - if (soap->version == 1) - { if (!soap->fault->detail) - { soap->fault->detail = (struct SOAP_ENV__Detail*)soap_malloc(soap, sizeof(struct SOAP_ENV__Detail)); - soap_default_SOAP_ENV__Detail(soap, soap->fault->detail); - } - return (const char**)&soap->fault->detail->__any; - } - if (!soap->fault->SOAP_ENV__Detail) - { soap->fault->SOAP_ENV__Detail = soap_new_SOAP_ENV__Detail(soap, -1); - soap_default_SOAP_ENV__Detail(soap, soap->fault->SOAP_ENV__Detail); - } - return (const char**)&soap->fault->SOAP_ENV__Detail->__any; + soap_fault(soap); + if (soap->fault == NULL) + return NULL; + if (soap->version == 2) + { if (soap->fault->SOAP_ENV__Detail == NULL) + soap->fault->SOAP_ENV__Detail = soap_new_SOAP_ENV__Detail(soap, -1); + return (const char**)(void*)&soap->fault->SOAP_ENV__Detail->__any; + } + if (soap->fault->detail == NULL) + soap->fault->detail = soap_new_SOAP_ENV__Detail(soap, -1); + return (const char**)(void*)&soap->fault->detail->__any; +} + +SOAP_FMAC3 const char * SOAP_FMAC4 soap_fault_detail(struct soap *soap) +{ + const char **s = soap_faultdetail(soap); + return s ? *s : NULL; } #endif @@ -131,165 +164,170 @@ SOAP_FMAC3 const char ** SOAP_FMAC4 soap_faultdetail(struct soap *soap) #ifndef WITH_NOIDREF SOAP_FMAC3 int SOAP_FMAC4 soap_getindependent(struct soap *soap) { - int t; - for (;;) - if (!soap_getelement(soap, &t)) - if (soap->error || soap_ignore_element(soap)) - break; - if (soap->error == SOAP_NO_TAG || soap->error == SOAP_EOF) - soap->error = SOAP_OK; - return soap->error; + int t; + if (soap->version == 1) + { for (;;) + { if (!soap_getelement(soap, NULL, &t)) + if ((soap->error && soap->error != SOAP_TAG_MISMATCH) || soap_ignore_element(soap)) + break; + } + } + if (soap->error == SOAP_NO_TAG || soap->error == SOAP_EOF) + soap->error = SOAP_OK; + return soap->error; } #endif -#ifndef WITH_NOIDREF - #ifdef __cplusplus extern "C" { #endif -SOAP_FMAC3 void * SOAP_FMAC4 soap_getelement(struct soap *soap, int *type) -{ - if (soap_peek_element(soap)) - return nullptr; - if (!*soap->id || !(*type = soap_lookup_type(soap, soap->id))) - *type = soap_lookup_type(soap, soap->href); - switch (*type) - { - case SOAP_TYPE_byte: - return soap_in_byte(soap, nullptr, nullptr, "xsd:byte"); - case SOAP_TYPE_int: - return soap_in_int(soap, nullptr, nullptr, "xsd:int"); - case SOAP_TYPE_ns1__executeCommand: - return soap_in_ns1__executeCommand(soap, nullptr, nullptr, "ns1:executeCommand"); - case SOAP_TYPE_ns1__executeCommandResponse: - return soap_in_ns1__executeCommandResponse(soap, nullptr, nullptr, "ns1:executeCommandResponse"); - case SOAP_TYPE_PointerTostring: - return soap_in_PointerTostring(soap, nullptr, nullptr, "xsd:string"); - case SOAP_TYPE_string: - { char **s; - s = soap_in_string(soap, nullptr, nullptr, "xsd:string"); - return s ? *s : nullptr; - } - default: - { const char *t = soap->type; - if (!*t) - t = soap->tag; - if (!soap_match_tag(soap, t, "xsd:byte")) - { *type = SOAP_TYPE_byte; - return soap_in_byte(soap, nullptr, nullptr, nullptr); - } - if (!soap_match_tag(soap, t, "xsd:int")) - { *type = SOAP_TYPE_int; - return soap_in_int(soap, nullptr, nullptr, nullptr); - } - if (!soap_match_tag(soap, t, "ns1:executeCommand")) - { *type = SOAP_TYPE_ns1__executeCommand; - return soap_in_ns1__executeCommand(soap, nullptr, nullptr, nullptr); - } - if (!soap_match_tag(soap, t, "ns1:executeCommandResponse")) - { *type = SOAP_TYPE_ns1__executeCommandResponse; - return soap_in_ns1__executeCommandResponse(soap, nullptr, nullptr, nullptr); - } - if (!soap_match_tag(soap, t, "xsd:string")) - { char **s; - *type = SOAP_TYPE_string; - s = soap_in_string(soap, nullptr, nullptr, nullptr); - return s ? *s : nullptr; - } - t = soap->tag; - if (!soap_match_tag(soap, t, "xsd:QName")) - { char **s; - *type = SOAP_TYPE__QName; - s = soap_in__QName(soap, nullptr, nullptr, nullptr); - return s ? *s : nullptr; - } - } - } - soap->error = SOAP_TAG_MISMATCH; - return nullptr; +SOAP_FMAC3 void * SOAP_FMAC4 soap_getelement(struct soap *soap, const char *tag, int *type) +{ (void)type; + if (soap_peek_element(soap)) + return NULL; +#ifndef WITH_NOIDREF + if (!*soap->id || !(*type = soap_lookup_type(soap, soap->id))) + *type = soap_lookup_type(soap, soap->href); + switch (*type) + { + case SOAP_TYPE_byte: + return soap_in_byte(soap, tag, NULL, "xsd:byte"); + case SOAP_TYPE_int: + return soap_in_int(soap, tag, NULL, "xsd:int"); + case SOAP_TYPE_ns1__executeCommand: + return soap_in_ns1__executeCommand(soap, tag, NULL, "ns1:executeCommand"); + case SOAP_TYPE_ns1__executeCommandResponse: + return soap_in_ns1__executeCommandResponse(soap, tag, NULL, "ns1:executeCommandResponse"); + case SOAP_TYPE_PointerTostring: + return soap_in_PointerTostring(soap, tag, NULL, "xsd:string"); + case SOAP_TYPE__QName: + { char **s; + s = soap_in__QName(soap, tag, NULL, "xsd:QName"); + return s ? *s : NULL; + } + case SOAP_TYPE_string: + { char **s; + s = soap_in_string(soap, tag, NULL, "xsd:string"); + return s ? *s : NULL; + } + default: +#else + *type = 0; +#endif + { const char *t = soap->type; + if (!*t) + t = soap->tag; + if (!soap_match_tag(soap, t, "xsd:byte")) + { *type = SOAP_TYPE_byte; + return soap_in_byte(soap, tag, NULL, NULL); + } + if (!soap_match_tag(soap, t, "xsd:int")) + { *type = SOAP_TYPE_int; + return soap_in_int(soap, tag, NULL, NULL); + } + if (!soap_match_tag(soap, t, "ns1:executeCommand")) + { *type = SOAP_TYPE_ns1__executeCommand; + return soap_in_ns1__executeCommand(soap, tag, NULL, NULL); + } + if (!soap_match_tag(soap, t, "ns1:executeCommandResponse")) + { *type = SOAP_TYPE_ns1__executeCommandResponse; + return soap_in_ns1__executeCommandResponse(soap, tag, NULL, NULL); + } + if (!soap_match_tag(soap, t, "xsd:QName")) + { char **s; + *type = SOAP_TYPE__QName; + s = soap_in__QName(soap, tag, NULL, NULL); + return s ? *s : NULL; + } + if (!soap_match_tag(soap, t, "xsd:string")) + { char **s; + *type = SOAP_TYPE_string; + s = soap_in_string(soap, tag, NULL, NULL); + return s ? *s : NULL; + } + t = soap->tag; +#ifndef WITH_NOIDREF + } +#endif + } + soap->error = SOAP_TAG_MISMATCH; + return NULL; } #ifdef __cplusplus } #endif -#endif SOAP_FMAC3 int SOAP_FMAC4 soap_ignore_element(struct soap *soap) { - if (!soap_peek_element(soap)) - { int t; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unexpected element '%s' in input (level=%u, %d)\n", soap->tag, soap->level, soap->body)); - if (soap->mustUnderstand && !soap->other) - return soap->error = SOAP_MUSTUNDERSTAND; - if (((soap->mode & SOAP_XML_STRICT) && soap->part != SOAP_IN_HEADER) || !soap_match_tag(soap, soap->tag, "SOAP-ENV:")) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "REJECTING element '%s'\n", soap->tag)); - return soap->error = SOAP_TAG_MISMATCH; - } - if (!*soap->id || !soap_getelement(soap, &t)) - { soap->peeked = 0; - if (soap->fignore) - soap->error = soap->fignore(soap, soap->tag); - else - soap->error = SOAP_OK; - DBGLOG(TEST, if (!soap->error) SOAP_MESSAGE(fdebug, "IGNORING element '%s'\n", soap->tag)); - if (!soap->error && soap->body) - { soap->level++; - while (!soap_ignore_element(soap)) - ; - if (soap->error == SOAP_NO_TAG) - soap->error = soap_element_end_in(soap, nullptr); - } - } - } - return soap->error; + if (!soap_peek_element(soap)) + { int t; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unexpected element '%s' in input at level = %u body = %d)\n", soap->tag, soap->level, soap->body)); + if (soap->mustUnderstand && !soap->other && !soap->fignore) + return soap->error = SOAP_MUSTUNDERSTAND; + if (((soap->mode & SOAP_XML_STRICT) && !soap->fignore && soap->part != SOAP_IN_HEADER) || !soap_match_tag(soap, soap->tag, "SOAP-ENV:")) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "REJECTING element '%s'\n", soap->tag)); + return soap->error = SOAP_TAG_MISMATCH; + } + if (!*soap->id || !soap_getelement(soap, NULL, &t)) + { soap->peeked = 0; + if (soap->fignore) + soap->error = soap->fignore(soap, soap->tag); + else + soap->error = SOAP_OK; + DBGLOG(TEST, if (!soap->error) SOAP_MESSAGE(fdebug, "IGNORING element '%s'\n", soap->tag)); + if (!soap->error && soap->body && soap_ignore(soap)) + return soap->error; + } + } + return soap->error; } #ifndef WITH_NOIDREF SOAP_FMAC3 int SOAP_FMAC4 soap_putindependent(struct soap *soap) { - int i; - struct soap_plist *pp; - if (soap->version == 1 && soap->encodingStyle && !(soap->mode & (SOAP_XML_TREE | SOAP_XML_GRAPH))) - for (i = 0; i < SOAP_PTRHASH; i++) - for (pp = soap->pht[i]; pp; pp = pp->next) - if (pp->mark1 == 2 || pp->mark2 == 2) - if (soap_putelement(soap, pp->ptr, "id", pp->id, pp->type)) - return soap->error; - return SOAP_OK; + int i; + struct soap_plist *pp; + if (soap->version == 1 && soap->encodingStyle && !(soap->mode & (SOAP_XML_TREE | SOAP_XML_GRAPH))) + for (i = 0; i < SOAP_PTRHASH; i++) + for (pp = soap->pht[i]; pp; pp = pp->next) + if (pp->mark1 == 2 || pp->mark2 == 2) + if (soap_putelement(soap, pp->ptr, SOAP_MULTIREFTAG, pp->id, pp->type)) + return soap->error; + return SOAP_OK; } #endif -#ifndef WITH_NOIDREF - #ifdef __cplusplus extern "C" { #endif SOAP_FMAC3 int SOAP_FMAC4 soap_putelement(struct soap *soap, const void *ptr, const char *tag, int id, int type) -{ - switch (type) - { - case SOAP_TYPE_byte: - return soap_out_byte(soap, tag, id, (const char *)ptr, "xsd:byte"); - case SOAP_TYPE_int: - return soap_out_int(soap, tag, id, (const int *)ptr, "xsd:int"); - case SOAP_TYPE_ns1__executeCommand: - return soap_out_ns1__executeCommand(soap, tag, id, (const struct ns1__executeCommand *)ptr, "ns1:executeCommand"); - case SOAP_TYPE_ns1__executeCommandResponse: - return soap_out_ns1__executeCommandResponse(soap, tag, id, (const struct ns1__executeCommandResponse *)ptr, "ns1:executeCommandResponse"); - case SOAP_TYPE_PointerTostring: - return soap_out_PointerTostring(soap, tag, id, (char **const*)ptr, "xsd:string"); - case SOAP_TYPE__QName: - return soap_out_string(soap, "xsd:QName", id, (char*const*)&ptr, nullptr); - case SOAP_TYPE_string: - return soap_out_string(soap, tag, id, (char*const*)&ptr, "xsd:string"); - } - return SOAP_OK; +{ (void)tag; + switch (type) + { + case SOAP_TYPE_byte: + return soap_out_byte(soap, tag, id, (const char *)ptr, "xsd:byte"); + case SOAP_TYPE_int: + return soap_out_int(soap, tag, id, (const int *)ptr, "xsd:int"); + case SOAP_TYPE_ns1__executeCommand: + return soap_out_ns1__executeCommand(soap, tag, id, (const struct ns1__executeCommand *)ptr, "ns1:executeCommand"); + case SOAP_TYPE_ns1__executeCommandResponse: + return soap_out_ns1__executeCommandResponse(soap, tag, id, (const struct ns1__executeCommandResponse *)ptr, "ns1:executeCommandResponse"); + case SOAP_TYPE_PointerTostring: + return soap_out_PointerTostring(soap, tag, id, (char **const*)ptr, "xsd:string"); + case SOAP_TYPE__QName: + return soap_out_string(soap, tag, id, (char*const*)(void*)&ptr, "xsd:QName"); + case SOAP_TYPE_string: + return soap_out_string(soap, tag, id, (char*const*)(void*)&ptr, "xsd:string"); + case 0: + return SOAP_OK; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "soap_putelement '%s' failed for type %d in soapC.cpp\n", tag ? tag : "", type)); + return soap_element_empty(soap, tag, 0, NULL); /* unknown type to serialize */ } - #ifdef __cplusplus } #endif -#endif #ifndef WITH_NOIDREF @@ -298,371 +336,484 @@ extern "C" { #endif SOAP_FMAC3 void SOAP_FMAC4 soap_markelement(struct soap *soap, const void *ptr, int type) { - (void)soap; (void)ptr; (void)type; /* appease -Wall -Werror */ - switch (type) - { - case SOAP_TYPE_ns1__executeCommand: - soap_serialize_ns1__executeCommand(soap, (const struct ns1__executeCommand *)ptr); - break; - case SOAP_TYPE_ns1__executeCommandResponse: - soap_serialize_ns1__executeCommandResponse(soap, (const struct ns1__executeCommandResponse *)ptr); - break; - case SOAP_TYPE_PointerTostring: - soap_serialize_PointerTostring(soap, (char **const*)ptr); - break; - case SOAP_TYPE__QName: - soap_serialize_string(soap, (char*const*)&ptr); - break; - case SOAP_TYPE_string: - soap_serialize_string(soap, (char*const*)&ptr); - break; - } + (void)soap; (void)ptr; (void)type; /* appease -Wall -Werror */ + switch (type) + { + case SOAP_TYPE_ns1__executeCommand: + soap_serialize_ns1__executeCommand(soap, (const struct ns1__executeCommand *)ptr); + break; + case SOAP_TYPE_ns1__executeCommandResponse: + soap_serialize_ns1__executeCommandResponse(soap, (const struct ns1__executeCommandResponse *)ptr); + break; + case SOAP_TYPE_PointerTostring: + soap_serialize_PointerTostring(soap, (char **const*)ptr); + break; + case SOAP_TYPE__QName: + soap_serialize_string(soap, (char*const*)(void*)&ptr); + break; + case SOAP_TYPE_string: + soap_serialize_string(soap, (char*const*)(void*)&ptr); + break; + } } +#ifdef __cplusplus +} +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif +SOAP_FMAC3 void * SOAP_FMAC4 soap_dupelement(struct soap *soap, const void *ptr, int type) +{(void)soap; (void)ptr; (void)type; /* appease -Wall -Werror */ + return NULL; +} #ifdef __cplusplus } #endif + +#ifdef __cplusplus +extern "C" { +#endif + +SOAP_FMAC3 void SOAP_FMAC4 soap_delelement(const void *ptr, int type) +{(void)ptr; (void)type; /* appease -Wall -Werror */ +} +#ifdef __cplusplus +} #endif SOAP_FMAC3 void * SOAP_FMAC4 soap_instantiate(struct soap *soap, int t, const char *type, const char *arrayType, size_t *n) -{ - switch (t) - { - case SOAP_TYPE_ns1__executeCommandResponse: - return (void*)soap_instantiate_ns1__executeCommandResponse(soap, -1, type, arrayType, n); - case SOAP_TYPE_ns1__executeCommand: - return (void*)soap_instantiate_ns1__executeCommand(soap, -1, type, arrayType, n); +{ (void)type; + switch (t) + { + case SOAP_TYPE_ns1__executeCommandResponse: + return (void*)soap_instantiate_ns1__executeCommandResponse(soap, -1, type, arrayType, n); + case SOAP_TYPE_ns1__executeCommand: + return (void*)soap_instantiate_ns1__executeCommand(soap, -1, type, arrayType, n); #ifndef WITH_NOGLOBAL - case SOAP_TYPE_SOAP_ENV__Header: - return (void*)soap_instantiate_SOAP_ENV__Header(soap, -1, type, arrayType, n); + case SOAP_TYPE_SOAP_ENV__Header: + return (void*)soap_instantiate_SOAP_ENV__Header(soap, -1, type, arrayType, n); #endif #ifndef WITH_NOGLOBAL - case SOAP_TYPE_SOAP_ENV__Code: - return (void*)soap_instantiate_SOAP_ENV__Code(soap, -1, type, arrayType, n); + case SOAP_TYPE_SOAP_ENV__Code: + return (void*)soap_instantiate_SOAP_ENV__Code(soap, -1, type, arrayType, n); #endif #ifndef WITH_NOGLOBAL - case SOAP_TYPE_SOAP_ENV__Detail: - return (void*)soap_instantiate_SOAP_ENV__Detail(soap, -1, type, arrayType, n); + case SOAP_TYPE_SOAP_ENV__Detail: + return (void*)soap_instantiate_SOAP_ENV__Detail(soap, -1, type, arrayType, n); #endif #ifndef WITH_NOGLOBAL - case SOAP_TYPE_SOAP_ENV__Reason: - return (void*)soap_instantiate_SOAP_ENV__Reason(soap, -1, type, arrayType, n); + case SOAP_TYPE_SOAP_ENV__Reason: + return (void*)soap_instantiate_SOAP_ENV__Reason(soap, -1, type, arrayType, n); #endif #ifndef WITH_NOGLOBAL - case SOAP_TYPE_SOAP_ENV__Fault: - return (void*)soap_instantiate_SOAP_ENV__Fault(soap, -1, type, arrayType, n); + case SOAP_TYPE_SOAP_ENV__Fault: + return (void*)soap_instantiate_SOAP_ENV__Fault(soap, -1, type, arrayType, n); #endif - } - return nullptr; -} - -SOAP_FMAC3 int SOAP_FMAC4 soap_fdelete(struct soap_clist *p) -{ switch (p->type) - { - case SOAP_TYPE_ns1__executeCommandResponse: - if (p->size < 0) - delete (struct ns1__executeCommandResponse*)p->ptr; - else - delete[] (struct ns1__executeCommandResponse*)p->ptr; - break; - case SOAP_TYPE_ns1__executeCommand: - if (p->size < 0) - delete (struct ns1__executeCommand*)p->ptr; - else - delete[] (struct ns1__executeCommand*)p->ptr; - break; - case SOAP_TYPE_SOAP_ENV__Header: - if (p->size < 0) - delete (struct SOAP_ENV__Header*)p->ptr; - else - delete[] (struct SOAP_ENV__Header*)p->ptr; - break; - case SOAP_TYPE_SOAP_ENV__Code: - if (p->size < 0) - delete (struct SOAP_ENV__Code*)p->ptr; - else - delete[] (struct SOAP_ENV__Code*)p->ptr; - break; - case SOAP_TYPE_SOAP_ENV__Detail: - if (p->size < 0) - delete (struct SOAP_ENV__Detail*)p->ptr; - else - delete[] (struct SOAP_ENV__Detail*)p->ptr; - break; - case SOAP_TYPE_SOAP_ENV__Reason: - if (p->size < 0) - delete (struct SOAP_ENV__Reason*)p->ptr; - else - delete[] (struct SOAP_ENV__Reason*)p->ptr; - break; - case SOAP_TYPE_SOAP_ENV__Fault: - if (p->size < 0) - delete (struct SOAP_ENV__Fault*)p->ptr; - else - delete[] (struct SOAP_ENV__Fault*)p->ptr; - break; - default: return SOAP_ERR; - } - return SOAP_OK; -} - -SOAP_FMAC3 void* SOAP_FMAC4 soap_class_id_enter(struct soap *soap, const char *id, void *p, int t, size_t n, const char *type, const char *arrayType) -{ return soap_id_enter(soap, id, p, t, n, 0, type, arrayType, soap_instantiate); -} - -SOAP_FMAC3 void SOAP_FMAC4 soap_default_byte(struct soap *soap, char *a) -{ (void)soap; /* appease -Wall -Werror */ -#ifdef SOAP_DEFAULT_byte - *a = SOAP_DEFAULT_byte; -#else - *a = (char)0; + } + return NULL; +} + +SOAP_FMAC3 int SOAP_FMAC4 soap_fdelete(struct soap *soap, struct soap_clist *p) +{ + (void)soap; /* appease -Wall -Werror */ + if (!p->ptr) + return SOAP_OK; + switch (p->type) + { + case SOAP_TYPE_ns1__executeCommandResponse: + if (p->size < 0) + SOAP_DELETE(soap, static_cast(p->ptr), struct ns1__executeCommandResponse); + else + SOAP_DELETE_ARRAY(soap, static_cast(p->ptr), struct ns1__executeCommandResponse); + break; + case SOAP_TYPE_ns1__executeCommand: + if (p->size < 0) + SOAP_DELETE(soap, static_cast(p->ptr), struct ns1__executeCommand); + else + SOAP_DELETE_ARRAY(soap, static_cast(p->ptr), struct ns1__executeCommand); + break; +#ifndef WITH_NOGLOBAL + case SOAP_TYPE_SOAP_ENV__Header: + if (p->size < 0) + SOAP_DELETE(soap, static_cast(p->ptr), struct SOAP_ENV__Header); + else + SOAP_DELETE_ARRAY(soap, static_cast(p->ptr), struct SOAP_ENV__Header); + break; +#endif +#ifndef WITH_NOGLOBAL + case SOAP_TYPE_SOAP_ENV__Code: + if (p->size < 0) + SOAP_DELETE(soap, static_cast(p->ptr), struct SOAP_ENV__Code); + else + SOAP_DELETE_ARRAY(soap, static_cast(p->ptr), struct SOAP_ENV__Code); + break; #endif +#ifndef WITH_NOGLOBAL + case SOAP_TYPE_SOAP_ENV__Detail: + if (p->size < 0) + SOAP_DELETE(soap, static_cast(p->ptr), struct SOAP_ENV__Detail); + else + SOAP_DELETE_ARRAY(soap, static_cast(p->ptr), struct SOAP_ENV__Detail); + break; +#endif +#ifndef WITH_NOGLOBAL + case SOAP_TYPE_SOAP_ENV__Reason: + if (p->size < 0) + SOAP_DELETE(soap, static_cast(p->ptr), struct SOAP_ENV__Reason); + else + SOAP_DELETE_ARRAY(soap, static_cast(p->ptr), struct SOAP_ENV__Reason); + break; +#endif +#ifndef WITH_NOGLOBAL + case SOAP_TYPE_SOAP_ENV__Fault: + if (p->size < 0) + SOAP_DELETE(soap, static_cast(p->ptr), struct SOAP_ENV__Fault); + else + SOAP_DELETE_ARRAY(soap, static_cast(p->ptr), struct SOAP_ENV__Fault); + break; +#endif + default: + return SOAP_ERR; + } + return SOAP_OK; } -SOAP_FMAC3 int SOAP_FMAC4 soap_put_byte(struct soap *soap, const char *a, const char *tag, const char *type) +#ifdef WIN32 +#pragma warning(push) +// do not warn on switch w/o cases +#pragma warning(disable:4065) +#endif +SOAP_FMAC3 int SOAP_FMAC4 soap_fbase(int t, int b) { - int id = soap_embed(soap, (void*)a, nullptr, 0, tag, SOAP_TYPE_byte); - if (soap_out_byte(soap, tag, id, a, type)) - return soap->error; - return soap_putindependent(soap); + (void)t; (void)b; /* appease -Wall -Werror */ + return 0; } +#ifdef WIN32 +#pragma warning(pop) +#endif + +#ifndef WITH_NOIDREF +#ifdef WIN32 +#pragma warning(push) +// do not warn on switch w/o cases +#pragma warning(disable:4065) +#endif +SOAP_FMAC3 void SOAP_FMAC4 soap_finsert(struct soap *soap, int t, int tt, void *p, size_t index, const void *q, void **x) +{ + (void)soap; (void)t; (void)p; (void)index; (void)q; (void)x; /* appease -Wall -Werror */ + switch (tt) + { + case SOAP_TYPE_ns1__executeCommandResponse: + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy struct ns1__executeCommandResponse type=%d location=%p object=%p\n", t, p, q)); + *(struct ns1__executeCommandResponse*)p = *(struct ns1__executeCommandResponse*)q; + break; + case SOAP_TYPE_ns1__executeCommand: + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy struct ns1__executeCommand type=%d location=%p object=%p\n", t, p, q)); + *(struct ns1__executeCommand*)p = *(struct ns1__executeCommand*)q; + break; +#ifndef WITH_NOGLOBAL + case SOAP_TYPE_SOAP_ENV__Header: + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy struct SOAP_ENV__Header type=%d location=%p object=%p\n", t, p, q)); + *(struct SOAP_ENV__Header*)p = *(struct SOAP_ENV__Header*)q; + break; +#endif +#ifndef WITH_NOGLOBAL + case SOAP_TYPE_SOAP_ENV__Code: + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy struct SOAP_ENV__Code type=%d location=%p object=%p\n", t, p, q)); + *(struct SOAP_ENV__Code*)p = *(struct SOAP_ENV__Code*)q; + break; +#endif +#ifndef WITH_NOGLOBAL + case SOAP_TYPE_SOAP_ENV__Detail: + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy struct SOAP_ENV__Detail type=%d location=%p object=%p\n", t, p, q)); + *(struct SOAP_ENV__Detail*)p = *(struct SOAP_ENV__Detail*)q; + break; +#endif +#ifndef WITH_NOGLOBAL + case SOAP_TYPE_SOAP_ENV__Reason: + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy struct SOAP_ENV__Reason type=%d location=%p object=%p\n", t, p, q)); + *(struct SOAP_ENV__Reason*)p = *(struct SOAP_ENV__Reason*)q; + break; +#endif +#ifndef WITH_NOGLOBAL + case SOAP_TYPE_SOAP_ENV__Fault: + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy struct SOAP_ENV__Fault type=%d location=%p object=%p\n", t, p, q)); + *(struct SOAP_ENV__Fault*)p = *(struct SOAP_ENV__Fault*)q; + break; +#endif + default: + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not insert type=%d in %d\n", t, tt)); + } +} +#ifdef WIN32 +#pragma warning(pop) +#endif +#endif SOAP_FMAC3 int SOAP_FMAC4 soap_out_byte(struct soap *soap, const char *tag, int id, const char *a, const char *type) { - return soap_outbyte(soap, tag, id, a, type, SOAP_TYPE_byte); + return soap_outbyte(soap, tag, id, a, type, SOAP_TYPE_byte); } -SOAP_FMAC3 char * SOAP_FMAC4 soap_get_byte(struct soap *soap, char *p, const char *tag, const char *type) +SOAP_FMAC3 char * SOAP_FMAC4 soap_in_byte(struct soap *soap, const char *tag, char *a, const char *type) { - if ((p = soap_in_byte(soap, tag, p, type))) - if (soap_getindependent(soap)) - return nullptr; - return p; + a = soap_inbyte(soap, tag, a, type, SOAP_TYPE_byte); + return a; } -SOAP_FMAC3 char * SOAP_FMAC4 soap_in_byte(struct soap *soap, const char *tag, char *a, const char *type) +SOAP_FMAC3 char * SOAP_FMAC4 soap_new_byte(struct soap *soap, int n) { - return soap_inbyte(soap, tag, a, type, SOAP_TYPE_byte); + char *a = static_cast(soap_malloc(soap, (n = (n < 0 ? 1 : n)) * sizeof(char))); + for (char *p = a; p && n--; ++p) + soap_default_byte(soap, p); + return a; } -SOAP_FMAC3 void SOAP_FMAC4 soap_default_int(struct soap *soap, int *a) -{ (void)soap; /* appease -Wall -Werror */ -#ifdef SOAP_DEFAULT_int - *a = SOAP_DEFAULT_int; -#else - *a = (int)0; -#endif +SOAP_FMAC3 int SOAP_FMAC4 soap_put_byte(struct soap *soap, const char *a, const char *tag, const char *type) +{ + if (soap_out_byte(soap, tag ? tag : "byte", -2, a, type)) + return soap->error; + return soap_putindependent(soap); } -SOAP_FMAC3 int SOAP_FMAC4 soap_put_int(struct soap *soap, const int *a, const char *tag, const char *type) +SOAP_FMAC3 char * SOAP_FMAC4 soap_get_byte(struct soap *soap, char *p, const char *tag, const char *type) { - int id = soap_embed(soap, (void*)a, nullptr, 0, tag, SOAP_TYPE_int); - if (soap_out_int(soap, tag, id, a, type)) - return soap->error; - return soap_putindependent(soap); + if ((p = soap_in_byte(soap, tag, p, type))) + if (soap_getindependent(soap)) + return NULL; + return p; } SOAP_FMAC3 int SOAP_FMAC4 soap_out_int(struct soap *soap, const char *tag, int id, const int *a, const char *type) { - return soap_outint(soap, tag, id, a, type, SOAP_TYPE_int); + return soap_outint(soap, tag, id, a, type, SOAP_TYPE_int); } -SOAP_FMAC3 int * SOAP_FMAC4 soap_get_int(struct soap *soap, int *p, const char *tag, const char *type) +SOAP_FMAC3 int * SOAP_FMAC4 soap_in_int(struct soap *soap, const char *tag, int *a, const char *type) { - if ((p = soap_in_int(soap, tag, p, type))) - if (soap_getindependent(soap)) - return nullptr; - return p; + a = soap_inint(soap, tag, a, type, SOAP_TYPE_int); + return a; } -SOAP_FMAC3 int * SOAP_FMAC4 soap_in_int(struct soap *soap, const char *tag, int *a, const char *type) +SOAP_FMAC3 int * SOAP_FMAC4 soap_new_int(struct soap *soap, int n) +{ + int *a = static_cast(soap_malloc(soap, (n = (n < 0 ? 1 : n)) * sizeof(int))); + for (int *p = a; p && n--; ++p) + soap_default_int(soap, p); + return a; +} + +SOAP_FMAC3 int SOAP_FMAC4 soap_put_int(struct soap *soap, const int *a, const char *tag, const char *type) +{ + if (soap_out_int(soap, tag ? tag : "int", -2, a, type)) + return soap->error; + return soap_putindependent(soap); +} + +SOAP_FMAC3 int * SOAP_FMAC4 soap_get_int(struct soap *soap, int *p, const char *tag, const char *type) { - return soap_inint(soap, tag, a, type, SOAP_TYPE_int); + if ((p = soap_in_int(soap, tag, p, type))) + if (soap_getindependent(soap)) + return NULL; + return p; } #ifndef WITH_NOGLOBAL SOAP_FMAC3 void SOAP_FMAC4 soap_default_SOAP_ENV__Fault(struct soap *soap, struct SOAP_ENV__Fault *a) { - (void)soap; (void)a; /* appease -Wall -Werror */ - soap_default__QName(soap, &a->faultcode); - soap_default_string(soap, &a->faultstring); - soap_default_string(soap, &a->faultactor); - a->detail = nullptr; - a->SOAP_ENV__Code = nullptr; - a->SOAP_ENV__Reason = nullptr; - soap_default_string(soap, &a->SOAP_ENV__Node); - soap_default_string(soap, &a->SOAP_ENV__Role); - a->SOAP_ENV__Detail = nullptr; + (void)soap; (void)a; /* appease -Wall -Werror */ + soap_default__QName(soap, &a->faultcode); + soap_default_string(soap, &a->faultstring); + soap_default_string(soap, &a->faultactor); + a->detail = NULL; + a->SOAP_ENV__Code = NULL; + a->SOAP_ENV__Reason = NULL; + soap_default_string(soap, &a->SOAP_ENV__Node); + soap_default_string(soap, &a->SOAP_ENV__Role); + a->SOAP_ENV__Detail = NULL; } SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_SOAP_ENV__Fault(struct soap *soap, const struct SOAP_ENV__Fault *a) { - (void)soap; (void)a; /* appease -Wall -Werror */ - soap_serialize__QName(soap, &a->faultcode); - soap_serialize_string(soap, &a->faultstring); - soap_serialize_string(soap, &a->faultactor); - soap_serialize_PointerToSOAP_ENV__Detail(soap, &a->detail); - soap_serialize_PointerToSOAP_ENV__Code(soap, &a->SOAP_ENV__Code); - soap_serialize_PointerToSOAP_ENV__Reason(soap, &a->SOAP_ENV__Reason); - soap_serialize_string(soap, &a->SOAP_ENV__Node); - soap_serialize_string(soap, &a->SOAP_ENV__Role); - soap_serialize_PointerToSOAP_ENV__Detail(soap, &a->SOAP_ENV__Detail); + (void)soap; (void)a; /* appease -Wall -Werror */ +#ifndef WITH_NOIDREF + soap_serialize__QName(soap, (char*const*)&a->faultcode); + soap_serialize_string(soap, (char*const*)&a->faultstring); + soap_serialize_string(soap, (char*const*)&a->faultactor); + soap_serialize_PointerToSOAP_ENV__Detail(soap, &a->detail); + soap_serialize_PointerToSOAP_ENV__Code(soap, &a->SOAP_ENV__Code); + soap_serialize_PointerToSOAP_ENV__Reason(soap, &a->SOAP_ENV__Reason); + soap_serialize_string(soap, (char*const*)&a->SOAP_ENV__Node); + soap_serialize_string(soap, (char*const*)&a->SOAP_ENV__Role); + soap_serialize_PointerToSOAP_ENV__Detail(soap, &a->SOAP_ENV__Detail); +#endif } -SOAP_FMAC3 int SOAP_FMAC4 soap_put_SOAP_ENV__Fault(struct soap *soap, const struct SOAP_ENV__Fault *a, const char *tag, const char *type) +SOAP_FMAC3 int SOAP_FMAC4 soap_out_SOAP_ENV__Fault(struct soap *soap, const char *tag, int id, const struct SOAP_ENV__Fault *a, const char *type) { - int id = soap_embed(soap, (void*)a, nullptr, 0, tag, SOAP_TYPE_SOAP_ENV__Fault); - if (soap_out_SOAP_ENV__Fault(soap, tag, id, a, type)) - return soap->error; - return soap_putindependent(soap); + const char *soap_tmp_faultcode; + soap_tmp_faultcode = soap_QName2s(soap, a->faultcode); + (void)soap; (void)tag; (void)id; (void)a; (void)type; /* appease -Wall -Werror */ + if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_SOAP_ENV__Fault), type)) + return soap->error; + if (soap_out__QName(soap, "faultcode", -1, (char*const*)(void*)&soap_tmp_faultcode, "")) + return soap->error; + if (soap_out_string(soap, "faultstring", -1, (char*const*)&a->faultstring, "")) + return soap->error; + if (soap_out_string(soap, "faultactor", -1, (char*const*)&a->faultactor, "")) + return soap->error; + if (soap_out_PointerToSOAP_ENV__Detail(soap, "detail", -1, &a->detail, "")) + return soap->error; + if (soap_out_PointerToSOAP_ENV__Code(soap, "SOAP-ENV:Code", -1, &a->SOAP_ENV__Code, "")) + return soap->error; + if (soap_out_PointerToSOAP_ENV__Reason(soap, "SOAP-ENV:Reason", -1, &a->SOAP_ENV__Reason, "")) + return soap->error; + if (soap_out_string(soap, "SOAP-ENV:Node", -1, (char*const*)&a->SOAP_ENV__Node, "")) + return soap->error; + if (soap_out_string(soap, "SOAP-ENV:Role", -1, (char*const*)&a->SOAP_ENV__Role, "")) + return soap->error; + if (soap_out_PointerToSOAP_ENV__Detail(soap, "SOAP-ENV:Detail", -1, &a->SOAP_ENV__Detail, "")) + return soap->error; + return soap_element_end_out(soap, tag); } -SOAP_FMAC3 int SOAP_FMAC4 soap_out_SOAP_ENV__Fault(struct soap *soap, const char *tag, int id, const struct SOAP_ENV__Fault *a, const char *type) +SOAP_FMAC3 struct SOAP_ENV__Fault * SOAP_FMAC4 soap_in_SOAP_ENV__Fault(struct soap *soap, const char *tag, struct SOAP_ENV__Fault *a, const char *type) { - const char *soap_tmp_faultcode = soap_QName2s(soap, a->faultcode); - if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_SOAP_ENV__Fault), type)) - return soap->error; - if (soap_out__QName(soap, "faultcode", -1, (char*const*)&soap_tmp_faultcode, "")) - return soap->error; - if (soap_out_string(soap, "faultstring", -1, &a->faultstring, "")) - return soap->error; - if (soap_out_string(soap, "faultactor", -1, &a->faultactor, "")) - return soap->error; - if (soap_out_PointerToSOAP_ENV__Detail(soap, "detail", -1, &a->detail, "")) - return soap->error; - if (soap_out_PointerToSOAP_ENV__Code(soap, "SOAP-ENV:Code", -1, &a->SOAP_ENV__Code, "")) - return soap->error; - if (soap_out_PointerToSOAP_ENV__Reason(soap, "SOAP-ENV:Reason", -1, &a->SOAP_ENV__Reason, "")) - return soap->error; - if (soap_out_string(soap, "SOAP-ENV:Node", -1, &a->SOAP_ENV__Node, "")) - return soap->error; - if (soap_out_string(soap, "SOAP-ENV:Role", -1, &a->SOAP_ENV__Role, "")) - return soap->error; - if (soap_out_PointerToSOAP_ENV__Detail(soap, "SOAP-ENV:Detail", -1, &a->SOAP_ENV__Detail, "")) - return soap->error; - return soap_element_end_out(soap, tag); + size_t soap_flag_faultcode = 1; + size_t soap_flag_faultstring = 1; + size_t soap_flag_faultactor = 1; + size_t soap_flag_detail = 1; + size_t soap_flag_SOAP_ENV__Code = 1; + size_t soap_flag_SOAP_ENV__Reason = 1; + size_t soap_flag_SOAP_ENV__Node = 1; + size_t soap_flag_SOAP_ENV__Role = 1; + size_t soap_flag_SOAP_ENV__Detail = 1; + if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; + (void)type; /* appease -Wall -Werror */ + a = (struct SOAP_ENV__Fault*)soap_id_enter(soap, soap->id, a, SOAP_TYPE_SOAP_ENV__Fault, sizeof(struct SOAP_ENV__Fault), NULL, NULL, NULL, NULL); + if (!a) + return NULL; + soap_default_SOAP_ENV__Fault(soap, a); + if (soap->body && *soap->href != '#') + { + for (;;) + { soap->error = SOAP_TAG_MISMATCH; + if (soap_flag_faultcode && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG)) + { if (soap_in__QName(soap, "faultcode", (char**)&a->faultcode, "xsd:QName")) + { soap_flag_faultcode--; + continue; + } + } + if (soap_flag_faultstring && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG)) + { if (soap_in_string(soap, "faultstring", (char**)&a->faultstring, "xsd:string")) + { soap_flag_faultstring--; + continue; + } + } + if (soap_flag_faultactor && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG)) + { if (soap_in_string(soap, "faultactor", (char**)&a->faultactor, "xsd:string")) + { soap_flag_faultactor--; + continue; + } + } + if (soap_flag_detail && soap->error == SOAP_TAG_MISMATCH) + { if (soap_in_PointerToSOAP_ENV__Detail(soap, "detail", &a->detail, "")) + { soap_flag_detail--; + continue; + } + } + if (soap_flag_SOAP_ENV__Code && soap->error == SOAP_TAG_MISMATCH) + { if (soap_in_PointerToSOAP_ENV__Code(soap, "SOAP-ENV:Code", &a->SOAP_ENV__Code, "")) + { soap_flag_SOAP_ENV__Code--; + continue; + } + } + if (soap_flag_SOAP_ENV__Reason && soap->error == SOAP_TAG_MISMATCH) + { if (soap_in_PointerToSOAP_ENV__Reason(soap, "SOAP-ENV:Reason", &a->SOAP_ENV__Reason, "")) + { soap_flag_SOAP_ENV__Reason--; + continue; + } + } + if (soap_flag_SOAP_ENV__Node && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG)) + { if (soap_in_string(soap, "SOAP-ENV:Node", (char**)&a->SOAP_ENV__Node, "xsd:string")) + { soap_flag_SOAP_ENV__Node--; + continue; + } + } + if (soap_flag_SOAP_ENV__Role && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG)) + { if (soap_in_string(soap, "SOAP-ENV:Role", (char**)&a->SOAP_ENV__Role, "xsd:string")) + { soap_flag_SOAP_ENV__Role--; + continue; + } + } + if (soap_flag_SOAP_ENV__Detail && soap->error == SOAP_TAG_MISMATCH) + { if (soap_in_PointerToSOAP_ENV__Detail(soap, "SOAP-ENV:Detail", &a->SOAP_ENV__Detail, "")) + { soap_flag_SOAP_ENV__Detail--; + continue; + } + } + if (soap->error == SOAP_TAG_MISMATCH) + soap->error = soap_ignore_element(soap); + if (soap->error == SOAP_NO_TAG) + break; + if (soap->error) + return NULL; + } + if (soap_element_end_in(soap, tag)) + return NULL; + } + else + { a = (struct SOAP_ENV__Fault *)soap_id_forward(soap, soap->href, (void*)a, 0, SOAP_TYPE_SOAP_ENV__Fault, SOAP_TYPE_SOAP_ENV__Fault, sizeof(struct SOAP_ENV__Fault), 0, soap_finsert, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + } + return a; +} + +SOAP_FMAC1 struct SOAP_ENV__Fault * SOAP_FMAC2 soap_instantiate_SOAP_ENV__Fault(struct soap *soap, int n, const char *type, const char *arrayType, size_t *size) +{ + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "soap_instantiate_SOAP_ENV__Fault(%p, %d, %s, %s)\n", (void*)soap, n, type?type:"", arrayType?arrayType:"")); + (void)type; (void)arrayType; /* appease -Wall -Werror */ + struct SOAP_ENV__Fault *p; + size_t k = sizeof(struct SOAP_ENV__Fault); + struct soap_clist *cp = soap_link(soap, SOAP_TYPE_SOAP_ENV__Fault, n, soap_fdelete); + if (!cp && soap && n != SOAP_NO_LINK_TO_DELETE) + return NULL; + if (n < 0) + { p = SOAP_NEW(soap, struct SOAP_ENV__Fault); + } + else + { p = SOAP_NEW_ARRAY(soap, struct SOAP_ENV__Fault, n); + k *= n; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Instantiated struct SOAP_ENV__Fault location=%p n=%d\n", (void*)p, n)); + if (size) + *size = k; + if (!p) + soap->error = SOAP_EOM; + else if (cp) + cp->ptr = (void*)p; + return p; } -SOAP_FMAC3 struct SOAP_ENV__Fault * SOAP_FMAC4 soap_get_SOAP_ENV__Fault(struct soap *soap, struct SOAP_ENV__Fault *p, const char *tag, const char *type) +SOAP_FMAC3 int SOAP_FMAC4 soap_put_SOAP_ENV__Fault(struct soap *soap, const struct SOAP_ENV__Fault *a, const char *tag, const char *type) { - if ((p = soap_in_SOAP_ENV__Fault(soap, tag, p, type))) - if (soap_getindependent(soap)) - return nullptr; - return p; + if (soap_out_SOAP_ENV__Fault(soap, tag ? tag : "SOAP-ENV:Fault", -2, a, type)) + return soap->error; + return soap_putindependent(soap); } -SOAP_FMAC3 struct SOAP_ENV__Fault * SOAP_FMAC4 soap_in_SOAP_ENV__Fault(struct soap *soap, const char *tag, struct SOAP_ENV__Fault *a, const char *type) +SOAP_FMAC3 struct SOAP_ENV__Fault * SOAP_FMAC4 soap_get_SOAP_ENV__Fault(struct soap *soap, struct SOAP_ENV__Fault *p, const char *tag, const char *type) { - short soap_flag_faultcode = 1, soap_flag_faultstring = 1, soap_flag_faultactor = 1, soap_flag_detail = 1, soap_flag_SOAP_ENV__Code = 1, soap_flag_SOAP_ENV__Reason = 1, soap_flag_SOAP_ENV__Node = 1, soap_flag_SOAP_ENV__Role = 1, soap_flag_SOAP_ENV__Detail = 1; - if (soap_element_begin_in(soap, tag, 0, type)) - return nullptr; - a = (struct SOAP_ENV__Fault *)soap_id_enter(soap, soap->id, a, SOAP_TYPE_SOAP_ENV__Fault, sizeof(struct SOAP_ENV__Fault), 0, nullptr, nullptr, nullptr); - if (!a) - return nullptr; - soap_default_SOAP_ENV__Fault(soap, a); - if (soap->body && !*soap->href) - { - for (;;) - { soap->error = SOAP_TAG_MISMATCH; - if (soap_flag_faultcode && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG)) - if (soap_in__QName(soap, "faultcode", &a->faultcode, "")) - { soap_flag_faultcode--; - continue; - } - if (soap_flag_faultstring && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG)) - if (soap_in_string(soap, "faultstring", &a->faultstring, "xsd:string")) - { soap_flag_faultstring--; - continue; - } - if (soap_flag_faultactor && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG)) - if (soap_in_string(soap, "faultactor", &a->faultactor, "xsd:string")) - { soap_flag_faultactor--; - continue; - } - if (soap_flag_detail && soap->error == SOAP_TAG_MISMATCH) - if (soap_in_PointerToSOAP_ENV__Detail(soap, "detail", &a->detail, "")) - { soap_flag_detail--; - continue; - } - if (soap_flag_SOAP_ENV__Code && soap->error == SOAP_TAG_MISMATCH) - if (soap_in_PointerToSOAP_ENV__Code(soap, "SOAP-ENV:Code", &a->SOAP_ENV__Code, "")) - { soap_flag_SOAP_ENV__Code--; - continue; - } - if (soap_flag_SOAP_ENV__Reason && soap->error == SOAP_TAG_MISMATCH) - if (soap_in_PointerToSOAP_ENV__Reason(soap, "SOAP-ENV:Reason", &a->SOAP_ENV__Reason, "")) - { soap_flag_SOAP_ENV__Reason--; - continue; - } - if (soap_flag_SOAP_ENV__Node && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG)) - if (soap_in_string(soap, "SOAP-ENV:Node", &a->SOAP_ENV__Node, "xsd:string")) - { soap_flag_SOAP_ENV__Node--; - continue; - } - if (soap_flag_SOAP_ENV__Role && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG)) - if (soap_in_string(soap, "SOAP-ENV:Role", &a->SOAP_ENV__Role, "xsd:string")) - { soap_flag_SOAP_ENV__Role--; - continue; - } - if (soap_flag_SOAP_ENV__Detail && soap->error == SOAP_TAG_MISMATCH) - if (soap_in_PointerToSOAP_ENV__Detail(soap, "SOAP-ENV:Detail", &a->SOAP_ENV__Detail, "")) - { soap_flag_SOAP_ENV__Detail--; - continue; - } - if (soap->error == SOAP_TAG_MISMATCH) - soap->error = soap_ignore_element(soap); - if (soap->error == SOAP_NO_TAG) - break; - if (soap->error) - return nullptr; - } - if (soap_element_end_in(soap, tag)) - return nullptr; - } - else - { a = (struct SOAP_ENV__Fault *)soap_id_forward(soap, soap->href, (void*)a, 0, SOAP_TYPE_SOAP_ENV__Fault, 0, sizeof(struct SOAP_ENV__Fault), 0, nullptr); - if (soap->body && soap_element_end_in(soap, tag)) - return nullptr; - } - return a; -} - -SOAP_FMAC5 struct SOAP_ENV__Fault * SOAP_FMAC6 soap_new_SOAP_ENV__Fault(struct soap *soap, int n) -{ return soap_instantiate_SOAP_ENV__Fault(soap, n, nullptr, nullptr, nullptr); -} - -SOAP_FMAC5 void SOAP_FMAC6 soap_delete_SOAP_ENV__Fault(struct soap *soap, struct SOAP_ENV__Fault *p) -{ soap_delete(soap, p); -} - -SOAP_FMAC3 struct SOAP_ENV__Fault * SOAP_FMAC4 soap_instantiate_SOAP_ENV__Fault(struct soap *soap, int n, const char *type, const char *arrayType, size_t *size) -{ - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "soap_instantiate_SOAP_ENV__Fault(%d, %s, %s)\n", n, type?type:"", arrayType?arrayType:"")); - struct soap_clist *cp = soap_link(soap, nullptr, SOAP_TYPE_SOAP_ENV__Fault, n, soap_fdelete); - if (!cp) - return nullptr; - if (n < 0) - { cp->ptr = (void*)new struct SOAP_ENV__Fault; - if (size) - *size = sizeof(struct SOAP_ENV__Fault); - } - else - { cp->ptr = (void*)new struct SOAP_ENV__Fault[n]; - if (!cp->ptr) - { soap->error = SOAP_EOM; - return nullptr; - } - if (size) - *size = n * sizeof(struct SOAP_ENV__Fault); - } - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Instantiated location=%p\n", cp->ptr)); - return (struct SOAP_ENV__Fault*)cp->ptr; -} -SOAP_FMAC3 void SOAP_FMAC4 soap_copy_SOAP_ENV__Fault(struct soap *soap, int st, int tt, void *p, size_t len, const void *q, size_t n) -{ - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying struct SOAP_ENV__Fault %p -> %p\n", q, p)); - *(struct SOAP_ENV__Fault*)p = *(struct SOAP_ENV__Fault*)q; + if ((p = soap_in_SOAP_ENV__Fault(soap, tag, p, type))) + if (soap_getindependent(soap)) + return NULL; + return p; } #endif @@ -671,112 +822,107 @@ SOAP_FMAC3 void SOAP_FMAC4 soap_copy_SOAP_ENV__Fault(struct soap *soap, int st, SOAP_FMAC3 void SOAP_FMAC4 soap_default_SOAP_ENV__Reason(struct soap *soap, struct SOAP_ENV__Reason *a) { - (void)soap; (void)a; /* appease -Wall -Werror */ - soap_default_string(soap, &a->SOAP_ENV__Text); + (void)soap; (void)a; /* appease -Wall -Werror */ + soap_default_string(soap, &a->SOAP_ENV__Text); } SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_SOAP_ENV__Reason(struct soap *soap, const struct SOAP_ENV__Reason *a) { - (void)soap; (void)a; /* appease -Wall -Werror */ - soap_serialize_string(soap, &a->SOAP_ENV__Text); + (void)soap; (void)a; /* appease -Wall -Werror */ +#ifndef WITH_NOIDREF + soap_serialize_string(soap, (char*const*)&a->SOAP_ENV__Text); +#endif } -SOAP_FMAC3 int SOAP_FMAC4 soap_put_SOAP_ENV__Reason(struct soap *soap, const struct SOAP_ENV__Reason *a, const char *tag, const char *type) +SOAP_FMAC3 int SOAP_FMAC4 soap_out_SOAP_ENV__Reason(struct soap *soap, const char *tag, int id, const struct SOAP_ENV__Reason *a, const char *type) { - int id = soap_embed(soap, (void*)a, nullptr, 0, tag, SOAP_TYPE_SOAP_ENV__Reason); - if (soap_out_SOAP_ENV__Reason(soap, tag, id, a, type)) - return soap->error; - return soap_putindependent(soap); + (void)soap; (void)tag; (void)id; (void)a; (void)type; /* appease -Wall -Werror */ + if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_SOAP_ENV__Reason), type)) + return soap->error; + if (soap->lang) + soap_set_attr(soap, "xml:lang", soap->lang, 1); + if (soap_out_string(soap, "SOAP-ENV:Text", -1, (char*const*)&a->SOAP_ENV__Text, "")) + return soap->error; + return soap_element_end_out(soap, tag); } -SOAP_FMAC3 int SOAP_FMAC4 soap_out_SOAP_ENV__Reason(struct soap *soap, const char *tag, int id, const struct SOAP_ENV__Reason *a, const char *type) +SOAP_FMAC3 struct SOAP_ENV__Reason * SOAP_FMAC4 soap_in_SOAP_ENV__Reason(struct soap *soap, const char *tag, struct SOAP_ENV__Reason *a, const char *type) { - if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_SOAP_ENV__Reason), type)) - return soap->error; - if (soap_out_string(soap, "SOAP-ENV:Text", -1, &a->SOAP_ENV__Text, "")) - return soap->error; - return soap_element_end_out(soap, tag); + size_t soap_flag_SOAP_ENV__Text = 1; + if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; + (void)type; /* appease -Wall -Werror */ + a = (struct SOAP_ENV__Reason*)soap_id_enter(soap, soap->id, a, SOAP_TYPE_SOAP_ENV__Reason, sizeof(struct SOAP_ENV__Reason), NULL, NULL, NULL, NULL); + if (!a) + return NULL; + soap_default_SOAP_ENV__Reason(soap, a); + if (soap->body && *soap->href != '#') + { + for (;;) + { soap->error = SOAP_TAG_MISMATCH; + if (soap_flag_SOAP_ENV__Text && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG)) + { if (soap_in_string(soap, "SOAP-ENV:Text", (char**)&a->SOAP_ENV__Text, "xsd:string")) + { soap_flag_SOAP_ENV__Text--; + continue; + } + } + if (soap->error == SOAP_TAG_MISMATCH) + soap->error = soap_ignore_element(soap); + if (soap->error == SOAP_NO_TAG) + break; + if (soap->error) + return NULL; + } + if (soap_element_end_in(soap, tag)) + return NULL; + } + else + { a = (struct SOAP_ENV__Reason *)soap_id_forward(soap, soap->href, (void*)a, 0, SOAP_TYPE_SOAP_ENV__Reason, SOAP_TYPE_SOAP_ENV__Reason, sizeof(struct SOAP_ENV__Reason), 0, soap_finsert, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + } + return a; +} + +SOAP_FMAC1 struct SOAP_ENV__Reason * SOAP_FMAC2 soap_instantiate_SOAP_ENV__Reason(struct soap *soap, int n, const char *type, const char *arrayType, size_t *size) +{ + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "soap_instantiate_SOAP_ENV__Reason(%p, %d, %s, %s)\n", (void*)soap, n, type?type:"", arrayType?arrayType:"")); + (void)type; (void)arrayType; /* appease -Wall -Werror */ + struct SOAP_ENV__Reason *p; + size_t k = sizeof(struct SOAP_ENV__Reason); + struct soap_clist *cp = soap_link(soap, SOAP_TYPE_SOAP_ENV__Reason, n, soap_fdelete); + if (!cp && soap && n != SOAP_NO_LINK_TO_DELETE) + return NULL; + if (n < 0) + { p = SOAP_NEW(soap, struct SOAP_ENV__Reason); + } + else + { p = SOAP_NEW_ARRAY(soap, struct SOAP_ENV__Reason, n); + k *= n; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Instantiated struct SOAP_ENV__Reason location=%p n=%d\n", (void*)p, n)); + if (size) + *size = k; + if (!p) + soap->error = SOAP_EOM; + else if (cp) + cp->ptr = (void*)p; + return p; } -SOAP_FMAC3 struct SOAP_ENV__Reason * SOAP_FMAC4 soap_get_SOAP_ENV__Reason(struct soap *soap, struct SOAP_ENV__Reason *p, const char *tag, const char *type) +SOAP_FMAC3 int SOAP_FMAC4 soap_put_SOAP_ENV__Reason(struct soap *soap, const struct SOAP_ENV__Reason *a, const char *tag, const char *type) { - if ((p = soap_in_SOAP_ENV__Reason(soap, tag, p, type))) - if (soap_getindependent(soap)) - return nullptr; - return p; + if (soap_out_SOAP_ENV__Reason(soap, tag ? tag : "SOAP-ENV:Reason", -2, a, type)) + return soap->error; + return soap_putindependent(soap); } -SOAP_FMAC3 struct SOAP_ENV__Reason * SOAP_FMAC4 soap_in_SOAP_ENV__Reason(struct soap *soap, const char *tag, struct SOAP_ENV__Reason *a, const char *type) +SOAP_FMAC3 struct SOAP_ENV__Reason * SOAP_FMAC4 soap_get_SOAP_ENV__Reason(struct soap *soap, struct SOAP_ENV__Reason *p, const char *tag, const char *type) { - short soap_flag_SOAP_ENV__Text = 1; - if (soap_element_begin_in(soap, tag, 0, type)) - return nullptr; - a = (struct SOAP_ENV__Reason *)soap_id_enter(soap, soap->id, a, SOAP_TYPE_SOAP_ENV__Reason, sizeof(struct SOAP_ENV__Reason), 0, nullptr, nullptr, nullptr); - if (!a) - return nullptr; - soap_default_SOAP_ENV__Reason(soap, a); - if (soap->body && !*soap->href) - { - for (;;) - { soap->error = SOAP_TAG_MISMATCH; - if (soap_flag_SOAP_ENV__Text && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG)) - if (soap_in_string(soap, "SOAP-ENV:Text", &a->SOAP_ENV__Text, "xsd:string")) - { soap_flag_SOAP_ENV__Text--; - continue; - } - if (soap->error == SOAP_TAG_MISMATCH) - soap->error = soap_ignore_element(soap); - if (soap->error == SOAP_NO_TAG) - break; - if (soap->error) - return nullptr; - } - if (soap_element_end_in(soap, tag)) - return nullptr; - } - else - { a = (struct SOAP_ENV__Reason *)soap_id_forward(soap, soap->href, (void*)a, 0, SOAP_TYPE_SOAP_ENV__Reason, 0, sizeof(struct SOAP_ENV__Reason), 0, nullptr); - if (soap->body && soap_element_end_in(soap, tag)) - return nullptr; - } - return a; -} - -SOAP_FMAC5 struct SOAP_ENV__Reason * SOAP_FMAC6 soap_new_SOAP_ENV__Reason(struct soap *soap, int n) -{ return soap_instantiate_SOAP_ENV__Reason(soap, n, nullptr, nullptr, nullptr); -} - -SOAP_FMAC5 void SOAP_FMAC6 soap_delete_SOAP_ENV__Reason(struct soap *soap, struct SOAP_ENV__Reason *p) -{ soap_delete(soap, p); -} - -SOAP_FMAC3 struct SOAP_ENV__Reason * SOAP_FMAC4 soap_instantiate_SOAP_ENV__Reason(struct soap *soap, int n, const char *type, const char *arrayType, size_t *size) -{ - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "soap_instantiate_SOAP_ENV__Reason(%d, %s, %s)\n", n, type?type:"", arrayType?arrayType:"")); - struct soap_clist *cp = soap_link(soap, nullptr, SOAP_TYPE_SOAP_ENV__Reason, n, soap_fdelete); - if (!cp) - return nullptr; - if (n < 0) - { cp->ptr = (void*)new struct SOAP_ENV__Reason; - if (size) - *size = sizeof(struct SOAP_ENV__Reason); - } - else - { cp->ptr = (void*)new struct SOAP_ENV__Reason[n]; - if (!cp->ptr) - { soap->error = SOAP_EOM; - return nullptr; - } - if (size) - *size = n * sizeof(struct SOAP_ENV__Reason); - } - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Instantiated location=%p\n", cp->ptr)); - return (struct SOAP_ENV__Reason*)cp->ptr; -} -SOAP_FMAC3 void SOAP_FMAC4 soap_copy_SOAP_ENV__Reason(struct soap *soap, int st, int tt, void *p, size_t len, const void *q, size_t n) -{ - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying struct SOAP_ENV__Reason %p -> %p\n", q, p)); - *(struct SOAP_ENV__Reason*)p = *(struct SOAP_ENV__Reason*)q; + if ((p = soap_in_SOAP_ENV__Reason(soap, tag, p, type))) + if (soap_getindependent(soap)) + return NULL; + return p; } #endif @@ -785,120 +931,116 @@ SOAP_FMAC3 void SOAP_FMAC4 soap_copy_SOAP_ENV__Reason(struct soap *soap, int st, SOAP_FMAC3 void SOAP_FMAC4 soap_default_SOAP_ENV__Detail(struct soap *soap, struct SOAP_ENV__Detail *a) { - (void)soap; (void)a; /* appease -Wall -Werror */ - a->__type = 0; - a->fault = nullptr; - a->__any = nullptr; + (void)soap; (void)a; /* appease -Wall -Werror */ + a->__any = NULL; + a->__type = 0; + a->fault = NULL; } SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_SOAP_ENV__Detail(struct soap *soap, const struct SOAP_ENV__Detail *a) { - (void)soap; (void)a; /* appease -Wall -Werror */ - soap_markelement(soap, a->fault, a->__type); + (void)soap; (void)a; /* appease -Wall -Werror */ +#ifndef WITH_NOIDREF + soap_markelement(soap, a->fault, a->__type); +#endif } -SOAP_FMAC3 int SOAP_FMAC4 soap_put_SOAP_ENV__Detail(struct soap *soap, const struct SOAP_ENV__Detail *a, const char *tag, const char *type) +SOAP_FMAC3 int SOAP_FMAC4 soap_out_SOAP_ENV__Detail(struct soap *soap, const char *tag, int id, const struct SOAP_ENV__Detail *a, const char *type) { - int id = soap_embed(soap, (void*)a, nullptr, 0, tag, SOAP_TYPE_SOAP_ENV__Detail); - if (soap_out_SOAP_ENV__Detail(soap, tag, id, a, type)) - return soap->error; - return soap_putindependent(soap); + (void)soap; (void)tag; (void)id; (void)a; (void)type; /* appease -Wall -Werror */ + if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_SOAP_ENV__Detail), type)) + return soap->error; + if (soap_outliteral(soap, "-any", (char*const*)&a->__any, NULL)) + return soap->error; + if (soap_putelement(soap, a->fault, "fault", -1, a->__type)) + return soap->error; + return soap_element_end_out(soap, tag); } -SOAP_FMAC3 int SOAP_FMAC4 soap_out_SOAP_ENV__Detail(struct soap *soap, const char *tag, int id, const struct SOAP_ENV__Detail *a, const char *type) +SOAP_FMAC3 struct SOAP_ENV__Detail * SOAP_FMAC4 soap_in_SOAP_ENV__Detail(struct soap *soap, const char *tag, struct SOAP_ENV__Detail *a, const char *type) { - if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_SOAP_ENV__Detail), type)) - return soap->error; - if (soap_putelement(soap, a->fault, "fault", -1, a->__type)) - return soap->error; - soap_outliteral(soap, "-any", &a->__any, nullptr); - return soap_element_end_out(soap, tag); + size_t soap_flag___any = 1; + size_t soap_flag_fault = 1; + if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; + (void)type; /* appease -Wall -Werror */ + a = (struct SOAP_ENV__Detail*)soap_id_enter(soap, soap->id, a, SOAP_TYPE_SOAP_ENV__Detail, sizeof(struct SOAP_ENV__Detail), NULL, NULL, NULL, NULL); + if (!a) + return NULL; + soap_default_SOAP_ENV__Detail(soap, a); + if (soap->body && *soap->href != '#') + { + for (;;) + { soap->error = SOAP_TAG_MISMATCH; + if (soap_flag_fault && soap->error == SOAP_TAG_MISMATCH) + { if ((a->fault = soap_getelement(soap, "fault", &a->__type))) + { soap_flag_fault = 0; + continue; + } + } + if (soap_flag___any && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG)) + { if (soap_inliteral(soap, "-any", (char**)&a->__any)) + { soap_flag___any--; + continue; + } + } + if (soap->error == SOAP_TAG_MISMATCH) + soap->error = soap_ignore_element(soap); + if (soap->error == SOAP_NO_TAG) + break; + if (soap->error) + return NULL; + } + if (soap_element_end_in(soap, tag)) + return NULL; + } + else + { a = (struct SOAP_ENV__Detail *)soap_id_forward(soap, soap->href, (void*)a, 0, SOAP_TYPE_SOAP_ENV__Detail, SOAP_TYPE_SOAP_ENV__Detail, sizeof(struct SOAP_ENV__Detail), 0, soap_finsert, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + } + return a; +} + +SOAP_FMAC1 struct SOAP_ENV__Detail * SOAP_FMAC2 soap_instantiate_SOAP_ENV__Detail(struct soap *soap, int n, const char *type, const char *arrayType, size_t *size) +{ + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "soap_instantiate_SOAP_ENV__Detail(%p, %d, %s, %s)\n", (void*)soap, n, type?type:"", arrayType?arrayType:"")); + (void)type; (void)arrayType; /* appease -Wall -Werror */ + struct SOAP_ENV__Detail *p; + size_t k = sizeof(struct SOAP_ENV__Detail); + struct soap_clist *cp = soap_link(soap, SOAP_TYPE_SOAP_ENV__Detail, n, soap_fdelete); + if (!cp && soap && n != SOAP_NO_LINK_TO_DELETE) + return NULL; + if (n < 0) + { p = SOAP_NEW(soap, struct SOAP_ENV__Detail); + } + else + { p = SOAP_NEW_ARRAY(soap, struct SOAP_ENV__Detail, n); + k *= n; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Instantiated struct SOAP_ENV__Detail location=%p n=%d\n", (void*)p, n)); + if (size) + *size = k; + if (!p) + soap->error = SOAP_EOM; + else if (cp) + cp->ptr = (void*)p; + return p; } -SOAP_FMAC3 struct SOAP_ENV__Detail * SOAP_FMAC4 soap_get_SOAP_ENV__Detail(struct soap *soap, struct SOAP_ENV__Detail *p, const char *tag, const char *type) +SOAP_FMAC3 int SOAP_FMAC4 soap_put_SOAP_ENV__Detail(struct soap *soap, const struct SOAP_ENV__Detail *a, const char *tag, const char *type) { - if ((p = soap_in_SOAP_ENV__Detail(soap, tag, p, type))) - if (soap_getindependent(soap)) - return nullptr; - return p; + if (soap_out_SOAP_ENV__Detail(soap, tag ? tag : "SOAP-ENV:Detail", -2, a, type)) + return soap->error; + return soap_putindependent(soap); } -SOAP_FMAC3 struct SOAP_ENV__Detail * SOAP_FMAC4 soap_in_SOAP_ENV__Detail(struct soap *soap, const char *tag, struct SOAP_ENV__Detail *a, const char *type) +SOAP_FMAC3 struct SOAP_ENV__Detail * SOAP_FMAC4 soap_get_SOAP_ENV__Detail(struct soap *soap, struct SOAP_ENV__Detail *p, const char *tag, const char *type) { - short soap_flag_fault = 1, soap_flag___any = 1; - if (soap_element_begin_in(soap, tag, 0, type)) - return nullptr; - a = (struct SOAP_ENV__Detail *)soap_id_enter(soap, soap->id, a, SOAP_TYPE_SOAP_ENV__Detail, sizeof(struct SOAP_ENV__Detail), 0, nullptr, nullptr, nullptr); - if (!a) - return nullptr; - soap_default_SOAP_ENV__Detail(soap, a); - if (soap->body && !*soap->href) - { - for (;;) - { soap->error = SOAP_TAG_MISMATCH; - if (soap_flag_fault && soap->error == SOAP_TAG_MISMATCH) - if ((a->fault = soap_getelement(soap, &a->__type))) - { soap_flag_fault = 0; - continue; - } - if (soap_flag___any && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG)) - if (soap_inliteral(soap, "-any", &a->__any)) - { soap_flag___any--; - continue; - } - if (soap->error == SOAP_TAG_MISMATCH) - soap->error = soap_ignore_element(soap); - if (soap->error == SOAP_NO_TAG) - break; - if (soap->error) - return nullptr; - } - if (soap_element_end_in(soap, tag)) - return nullptr; - } - else - { a = (struct SOAP_ENV__Detail *)soap_id_forward(soap, soap->href, (void*)a, 0, SOAP_TYPE_SOAP_ENV__Detail, 0, sizeof(struct SOAP_ENV__Detail), 0, nullptr); - if (soap->body && soap_element_end_in(soap, tag)) - return nullptr; - } - return a; -} - -SOAP_FMAC5 struct SOAP_ENV__Detail * SOAP_FMAC6 soap_new_SOAP_ENV__Detail(struct soap *soap, int n) -{ return soap_instantiate_SOAP_ENV__Detail(soap, n, nullptr, nullptr, nullptr); -} - -SOAP_FMAC5 void SOAP_FMAC6 soap_delete_SOAP_ENV__Detail(struct soap *soap, struct SOAP_ENV__Detail *p) -{ soap_delete(soap, p); -} - -SOAP_FMAC3 struct SOAP_ENV__Detail * SOAP_FMAC4 soap_instantiate_SOAP_ENV__Detail(struct soap *soap, int n, const char *type, const char *arrayType, size_t *size) -{ - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "soap_instantiate_SOAP_ENV__Detail(%d, %s, %s)\n", n, type?type:"", arrayType?arrayType:"")); - struct soap_clist *cp = soap_link(soap, nullptr, SOAP_TYPE_SOAP_ENV__Detail, n, soap_fdelete); - if (!cp) - return nullptr; - if (n < 0) - { cp->ptr = (void*)new struct SOAP_ENV__Detail; - if (size) - *size = sizeof(struct SOAP_ENV__Detail); - } - else - { cp->ptr = (void*)new struct SOAP_ENV__Detail[n]; - if (!cp->ptr) - { soap->error = SOAP_EOM; - return nullptr; - } - if (size) - *size = n * sizeof(struct SOAP_ENV__Detail); - } - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Instantiated location=%p\n", cp->ptr)); - return (struct SOAP_ENV__Detail*)cp->ptr; -} -SOAP_FMAC3 void SOAP_FMAC4 soap_copy_SOAP_ENV__Detail(struct soap *soap, int st, int tt, void *p, size_t len, const void *q, size_t n) -{ - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying struct SOAP_ENV__Detail %p -> %p\n", q, p)); - *(struct SOAP_ENV__Detail*)p = *(struct SOAP_ENV__Detail*)q; + if ((p = soap_in_SOAP_ENV__Detail(soap, tag, p, type))) + if (soap_getindependent(soap)) + return NULL; + return p; } #endif @@ -907,122 +1049,118 @@ SOAP_FMAC3 void SOAP_FMAC4 soap_copy_SOAP_ENV__Detail(struct soap *soap, int st, SOAP_FMAC3 void SOAP_FMAC4 soap_default_SOAP_ENV__Code(struct soap *soap, struct SOAP_ENV__Code *a) { - (void)soap; (void)a; /* appease -Wall -Werror */ - soap_default__QName(soap, &a->SOAP_ENV__Value); - a->SOAP_ENV__Subcode = nullptr; + (void)soap; (void)a; /* appease -Wall -Werror */ + soap_default__QName(soap, &a->SOAP_ENV__Value); + a->SOAP_ENV__Subcode = NULL; } SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_SOAP_ENV__Code(struct soap *soap, const struct SOAP_ENV__Code *a) { - (void)soap; (void)a; /* appease -Wall -Werror */ - soap_serialize__QName(soap, &a->SOAP_ENV__Value); - soap_serialize_PointerToSOAP_ENV__Code(soap, &a->SOAP_ENV__Subcode); + (void)soap; (void)a; /* appease -Wall -Werror */ +#ifndef WITH_NOIDREF + soap_serialize__QName(soap, (char*const*)&a->SOAP_ENV__Value); + soap_serialize_PointerToSOAP_ENV__Code(soap, &a->SOAP_ENV__Subcode); +#endif } -SOAP_FMAC3 int SOAP_FMAC4 soap_put_SOAP_ENV__Code(struct soap *soap, const struct SOAP_ENV__Code *a, const char *tag, const char *type) +SOAP_FMAC3 int SOAP_FMAC4 soap_out_SOAP_ENV__Code(struct soap *soap, const char *tag, int id, const struct SOAP_ENV__Code *a, const char *type) { - int id = soap_embed(soap, (void*)a, nullptr, 0, tag, SOAP_TYPE_SOAP_ENV__Code); - if (soap_out_SOAP_ENV__Code(soap, tag, id, a, type)) - return soap->error; - return soap_putindependent(soap); + const char *soap_tmp_SOAP_ENV__Value; + soap_tmp_SOAP_ENV__Value = soap_QName2s(soap, a->SOAP_ENV__Value); + (void)soap; (void)tag; (void)id; (void)a; (void)type; /* appease -Wall -Werror */ + if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_SOAP_ENV__Code), type)) + return soap->error; + if (soap_out__QName(soap, "SOAP-ENV:Value", -1, (char*const*)(void*)&soap_tmp_SOAP_ENV__Value, "")) + return soap->error; + if (soap_out_PointerToSOAP_ENV__Code(soap, "SOAP-ENV:Subcode", -1, &a->SOAP_ENV__Subcode, "")) + return soap->error; + return soap_element_end_out(soap, tag); } -SOAP_FMAC3 int SOAP_FMAC4 soap_out_SOAP_ENV__Code(struct soap *soap, const char *tag, int id, const struct SOAP_ENV__Code *a, const char *type) +SOAP_FMAC3 struct SOAP_ENV__Code * SOAP_FMAC4 soap_in_SOAP_ENV__Code(struct soap *soap, const char *tag, struct SOAP_ENV__Code *a, const char *type) { - const char *soap_tmp_SOAP_ENV__Value = soap_QName2s(soap, a->SOAP_ENV__Value); - if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_SOAP_ENV__Code), type)) - return soap->error; - if (soap_out__QName(soap, "SOAP-ENV:Value", -1, (char*const*)&soap_tmp_SOAP_ENV__Value, "")) - return soap->error; - if (soap_out_PointerToSOAP_ENV__Code(soap, "SOAP-ENV:Subcode", -1, &a->SOAP_ENV__Subcode, "")) - return soap->error; - return soap_element_end_out(soap, tag); + size_t soap_flag_SOAP_ENV__Value = 1; + size_t soap_flag_SOAP_ENV__Subcode = 1; + if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; + (void)type; /* appease -Wall -Werror */ + a = (struct SOAP_ENV__Code*)soap_id_enter(soap, soap->id, a, SOAP_TYPE_SOAP_ENV__Code, sizeof(struct SOAP_ENV__Code), NULL, NULL, NULL, NULL); + if (!a) + return NULL; + soap_default_SOAP_ENV__Code(soap, a); + if (soap->body && *soap->href != '#') + { + for (;;) + { soap->error = SOAP_TAG_MISMATCH; + if (soap_flag_SOAP_ENV__Value && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG)) + { if (soap_in__QName(soap, "SOAP-ENV:Value", (char**)&a->SOAP_ENV__Value, "xsd:QName")) + { soap_flag_SOAP_ENV__Value--; + continue; + } + } + if (soap_flag_SOAP_ENV__Subcode && soap->error == SOAP_TAG_MISMATCH) + { if (soap_in_PointerToSOAP_ENV__Code(soap, "SOAP-ENV:Subcode", &a->SOAP_ENV__Subcode, "")) + { soap_flag_SOAP_ENV__Subcode--; + continue; + } + } + if (soap->error == SOAP_TAG_MISMATCH) + soap->error = soap_ignore_element(soap); + if (soap->error == SOAP_NO_TAG) + break; + if (soap->error) + return NULL; + } + if (soap_element_end_in(soap, tag)) + return NULL; + } + else + { a = (struct SOAP_ENV__Code *)soap_id_forward(soap, soap->href, (void*)a, 0, SOAP_TYPE_SOAP_ENV__Code, SOAP_TYPE_SOAP_ENV__Code, sizeof(struct SOAP_ENV__Code), 0, soap_finsert, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + } + return a; +} + +SOAP_FMAC1 struct SOAP_ENV__Code * SOAP_FMAC2 soap_instantiate_SOAP_ENV__Code(struct soap *soap, int n, const char *type, const char *arrayType, size_t *size) +{ + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "soap_instantiate_SOAP_ENV__Code(%p, %d, %s, %s)\n", (void*)soap, n, type?type:"", arrayType?arrayType:"")); + (void)type; (void)arrayType; /* appease -Wall -Werror */ + struct SOAP_ENV__Code *p; + size_t k = sizeof(struct SOAP_ENV__Code); + struct soap_clist *cp = soap_link(soap, SOAP_TYPE_SOAP_ENV__Code, n, soap_fdelete); + if (!cp && soap && n != SOAP_NO_LINK_TO_DELETE) + return NULL; + if (n < 0) + { p = SOAP_NEW(soap, struct SOAP_ENV__Code); + } + else + { p = SOAP_NEW_ARRAY(soap, struct SOAP_ENV__Code, n); + k *= n; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Instantiated struct SOAP_ENV__Code location=%p n=%d\n", (void*)p, n)); + if (size) + *size = k; + if (!p) + soap->error = SOAP_EOM; + else if (cp) + cp->ptr = (void*)p; + return p; } -SOAP_FMAC3 struct SOAP_ENV__Code * SOAP_FMAC4 soap_get_SOAP_ENV__Code(struct soap *soap, struct SOAP_ENV__Code *p, const char *tag, const char *type) +SOAP_FMAC3 int SOAP_FMAC4 soap_put_SOAP_ENV__Code(struct soap *soap, const struct SOAP_ENV__Code *a, const char *tag, const char *type) { - if ((p = soap_in_SOAP_ENV__Code(soap, tag, p, type))) - if (soap_getindependent(soap)) - return nullptr; - return p; + if (soap_out_SOAP_ENV__Code(soap, tag ? tag : "SOAP-ENV:Code", -2, a, type)) + return soap->error; + return soap_putindependent(soap); } -SOAP_FMAC3 struct SOAP_ENV__Code * SOAP_FMAC4 soap_in_SOAP_ENV__Code(struct soap *soap, const char *tag, struct SOAP_ENV__Code *a, const char *type) +SOAP_FMAC3 struct SOAP_ENV__Code * SOAP_FMAC4 soap_get_SOAP_ENV__Code(struct soap *soap, struct SOAP_ENV__Code *p, const char *tag, const char *type) { - short soap_flag_SOAP_ENV__Value = 1, soap_flag_SOAP_ENV__Subcode = 1; - if (soap_element_begin_in(soap, tag, 0, type)) - return nullptr; - a = (struct SOAP_ENV__Code *)soap_id_enter(soap, soap->id, a, SOAP_TYPE_SOAP_ENV__Code, sizeof(struct SOAP_ENV__Code), 0, nullptr, nullptr, nullptr); - if (!a) - return nullptr; - soap_default_SOAP_ENV__Code(soap, a); - if (soap->body && !*soap->href) - { - for (;;) - { soap->error = SOAP_TAG_MISMATCH; - if (soap_flag_SOAP_ENV__Value && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG)) - if (soap_in__QName(soap, "SOAP-ENV:Value", &a->SOAP_ENV__Value, "")) - { soap_flag_SOAP_ENV__Value--; - continue; - } - if (soap_flag_SOAP_ENV__Subcode && soap->error == SOAP_TAG_MISMATCH) - if (soap_in_PointerToSOAP_ENV__Code(soap, "SOAP-ENV:Subcode", &a->SOAP_ENV__Subcode, "")) - { soap_flag_SOAP_ENV__Subcode--; - continue; - } - if (soap->error == SOAP_TAG_MISMATCH) - soap->error = soap_ignore_element(soap); - if (soap->error == SOAP_NO_TAG) - break; - if (soap->error) - return nullptr; - } - if (soap_element_end_in(soap, tag)) - return nullptr; - } - else - { a = (struct SOAP_ENV__Code *)soap_id_forward(soap, soap->href, (void*)a, 0, SOAP_TYPE_SOAP_ENV__Code, 0, sizeof(struct SOAP_ENV__Code), 0, nullptr); - if (soap->body && soap_element_end_in(soap, tag)) - return nullptr; - } - return a; -} - -SOAP_FMAC5 struct SOAP_ENV__Code * SOAP_FMAC6 soap_new_SOAP_ENV__Code(struct soap *soap, int n) -{ return soap_instantiate_SOAP_ENV__Code(soap, n, nullptr, nullptr, nullptr); -} - -SOAP_FMAC5 void SOAP_FMAC6 soap_delete_SOAP_ENV__Code(struct soap *soap, struct SOAP_ENV__Code *p) -{ soap_delete(soap, p); -} - -SOAP_FMAC3 struct SOAP_ENV__Code * SOAP_FMAC4 soap_instantiate_SOAP_ENV__Code(struct soap *soap, int n, const char *type, const char *arrayType, size_t *size) -{ - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "soap_instantiate_SOAP_ENV__Code(%d, %s, %s)\n", n, type?type:"", arrayType?arrayType:"")); - struct soap_clist *cp = soap_link(soap, nullptr, SOAP_TYPE_SOAP_ENV__Code, n, soap_fdelete); - if (!cp) - return nullptr; - if (n < 0) - { cp->ptr = (void*)new struct SOAP_ENV__Code; - if (size) - *size = sizeof(struct SOAP_ENV__Code); - } - else - { cp->ptr = (void*)new struct SOAP_ENV__Code[n]; - if (!cp->ptr) - { soap->error = SOAP_EOM; - return nullptr; - } - if (size) - *size = n * sizeof(struct SOAP_ENV__Code); - } - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Instantiated location=%p\n", cp->ptr)); - return (struct SOAP_ENV__Code*)cp->ptr; -} -SOAP_FMAC3 void SOAP_FMAC4 soap_copy_SOAP_ENV__Code(struct soap *soap, int st, int tt, void *p, size_t len, const void *q, size_t n) -{ - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying struct SOAP_ENV__Code %p -> %p\n", q, p)); - *(struct SOAP_ENV__Code*)p = *(struct SOAP_ENV__Code*)q; + if ((p = soap_in_SOAP_ENV__Code(soap, tag, p, type))) + if (soap_getindependent(soap)) + return NULL; + return p; } #endif @@ -1031,377 +1169,358 @@ SOAP_FMAC3 void SOAP_FMAC4 soap_copy_SOAP_ENV__Code(struct soap *soap, int st, i SOAP_FMAC3 void SOAP_FMAC4 soap_default_SOAP_ENV__Header(struct soap *soap, struct SOAP_ENV__Header *a) { - (void)soap; (void)a; /* appease -Wall -Werror */ + (void)soap; (void)a; /* appease -Wall -Werror */ } SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_SOAP_ENV__Header(struct soap *soap, const struct SOAP_ENV__Header *a) { - (void)soap; (void)a; /* appease -Wall -Werror */ + (void)soap; (void)a; /* appease -Wall -Werror */ +#ifndef WITH_NOIDREF +#endif } -SOAP_FMAC3 int SOAP_FMAC4 soap_put_SOAP_ENV__Header(struct soap *soap, const struct SOAP_ENV__Header *a, const char *tag, const char *type) +SOAP_FMAC3 int SOAP_FMAC4 soap_out_SOAP_ENV__Header(struct soap *soap, const char *tag, int id, const struct SOAP_ENV__Header *a, const char *type) { - int id = soap_embed(soap, (void*)a, nullptr, 0, tag, SOAP_TYPE_SOAP_ENV__Header); - if (soap_out_SOAP_ENV__Header(soap, tag, id, a, type)) - return soap->error; - return soap_putindependent(soap); + (void)soap; (void)tag; (void)id; (void)a; (void)type; /* appease -Wall -Werror */ + if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_SOAP_ENV__Header), type)) + return soap->error; + return soap_element_end_out(soap, tag); } -SOAP_FMAC3 int SOAP_FMAC4 soap_out_SOAP_ENV__Header(struct soap *soap, const char *tag, int id, const struct SOAP_ENV__Header *a, const char *type) +SOAP_FMAC3 struct SOAP_ENV__Header * SOAP_FMAC4 soap_in_SOAP_ENV__Header(struct soap *soap, const char *tag, struct SOAP_ENV__Header *a, const char *type) { - if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_SOAP_ENV__Header), type)) - return soap->error; - return soap_element_end_out(soap, tag); + if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; + (void)type; /* appease -Wall -Werror */ + a = (struct SOAP_ENV__Header*)soap_id_enter(soap, soap->id, a, SOAP_TYPE_SOAP_ENV__Header, sizeof(struct SOAP_ENV__Header), NULL, NULL, NULL, NULL); + if (!a) + return NULL; + soap_default_SOAP_ENV__Header(soap, a); + if (soap->body && *soap->href != '#') + { + for (;;) + { soap->error = SOAP_TAG_MISMATCH; + if (soap->error == SOAP_TAG_MISMATCH) + soap->error = soap_ignore_element(soap); + if (soap->error == SOAP_NO_TAG) + break; + if (soap->error) + return NULL; + } + if (soap_element_end_in(soap, tag)) + return NULL; + } + else + { a = (struct SOAP_ENV__Header *)soap_id_forward(soap, soap->href, (void*)a, 0, SOAP_TYPE_SOAP_ENV__Header, SOAP_TYPE_SOAP_ENV__Header, sizeof(struct SOAP_ENV__Header), 0, soap_finsert, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + } + return a; +} + +SOAP_FMAC1 struct SOAP_ENV__Header * SOAP_FMAC2 soap_instantiate_SOAP_ENV__Header(struct soap *soap, int n, const char *type, const char *arrayType, size_t *size) +{ + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "soap_instantiate_SOAP_ENV__Header(%p, %d, %s, %s)\n", (void*)soap, n, type?type:"", arrayType?arrayType:"")); + (void)type; (void)arrayType; /* appease -Wall -Werror */ + struct SOAP_ENV__Header *p; + size_t k = sizeof(struct SOAP_ENV__Header); + struct soap_clist *cp = soap_link(soap, SOAP_TYPE_SOAP_ENV__Header, n, soap_fdelete); + if (!cp && soap && n != SOAP_NO_LINK_TO_DELETE) + return NULL; + if (n < 0) + { p = SOAP_NEW(soap, struct SOAP_ENV__Header); + } + else + { p = SOAP_NEW_ARRAY(soap, struct SOAP_ENV__Header, n); + k *= n; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Instantiated struct SOAP_ENV__Header location=%p n=%d\n", (void*)p, n)); + if (size) + *size = k; + if (!p) + soap->error = SOAP_EOM; + else if (cp) + cp->ptr = (void*)p; + return p; } -SOAP_FMAC3 struct SOAP_ENV__Header * SOAP_FMAC4 soap_get_SOAP_ENV__Header(struct soap *soap, struct SOAP_ENV__Header *p, const char *tag, const char *type) +SOAP_FMAC3 int SOAP_FMAC4 soap_put_SOAP_ENV__Header(struct soap *soap, const struct SOAP_ENV__Header *a, const char *tag, const char *type) { - if ((p = soap_in_SOAP_ENV__Header(soap, tag, p, type))) - if (soap_getindependent(soap)) - return nullptr; - return p; + if (soap_out_SOAP_ENV__Header(soap, tag ? tag : "SOAP-ENV:Header", -2, a, type)) + return soap->error; + return soap_putindependent(soap); } -SOAP_FMAC3 struct SOAP_ENV__Header * SOAP_FMAC4 soap_in_SOAP_ENV__Header(struct soap *soap, const char *tag, struct SOAP_ENV__Header *a, const char *type) +SOAP_FMAC3 struct SOAP_ENV__Header * SOAP_FMAC4 soap_get_SOAP_ENV__Header(struct soap *soap, struct SOAP_ENV__Header *p, const char *tag, const char *type) { - if (soap_element_begin_in(soap, tag, 0, type)) - return nullptr; - a = (struct SOAP_ENV__Header *)soap_id_enter(soap, soap->id, a, SOAP_TYPE_SOAP_ENV__Header, sizeof(struct SOAP_ENV__Header), 0, nullptr, nullptr, nullptr); - if (!a) - return nullptr; - soap_default_SOAP_ENV__Header(soap, a); - if (soap->body && !*soap->href) - { - for (;;) - { soap->error = SOAP_TAG_MISMATCH; - if (soap->error == SOAP_TAG_MISMATCH) - soap->error = soap_ignore_element(soap); - if (soap->error == SOAP_NO_TAG) - break; - if (soap->error) - return nullptr; - } - if (soap_element_end_in(soap, tag)) - return nullptr; - } - else - { a = (struct SOAP_ENV__Header *)soap_id_forward(soap, soap->href, (void*)a, 0, SOAP_TYPE_SOAP_ENV__Header, 0, sizeof(struct SOAP_ENV__Header), 0, nullptr); - if (soap->body && soap_element_end_in(soap, tag)) - return nullptr; - } - return a; -} - -SOAP_FMAC5 struct SOAP_ENV__Header * SOAP_FMAC6 soap_new_SOAP_ENV__Header(struct soap *soap, int n) -{ return soap_instantiate_SOAP_ENV__Header(soap, n, nullptr, nullptr, nullptr); -} - -SOAP_FMAC5 void SOAP_FMAC6 soap_delete_SOAP_ENV__Header(struct soap *soap, struct SOAP_ENV__Header *p) -{ soap_delete(soap, p); -} - -SOAP_FMAC3 struct SOAP_ENV__Header * SOAP_FMAC4 soap_instantiate_SOAP_ENV__Header(struct soap *soap, int n, const char *type, const char *arrayType, size_t *size) -{ - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "soap_instantiate_SOAP_ENV__Header(%d, %s, %s)\n", n, type?type:"", arrayType?arrayType:"")); - struct soap_clist *cp = soap_link(soap, nullptr, SOAP_TYPE_SOAP_ENV__Header, n, soap_fdelete); - if (!cp) - return nullptr; - if (n < 0) - { cp->ptr = (void*)new struct SOAP_ENV__Header; - if (size) - *size = sizeof(struct SOAP_ENV__Header); - } - else - { cp->ptr = (void*)new struct SOAP_ENV__Header[n]; - if (!cp->ptr) - { soap->error = SOAP_EOM; - return nullptr; - } - if (size) - *size = n * sizeof(struct SOAP_ENV__Header); - } - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Instantiated location=%p\n", cp->ptr)); - return (struct SOAP_ENV__Header*)cp->ptr; -} -SOAP_FMAC3 void SOAP_FMAC4 soap_copy_SOAP_ENV__Header(struct soap *soap, int st, int tt, void *p, size_t len, const void *q, size_t n) -{ - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying struct SOAP_ENV__Header %p -> %p\n", q, p)); - *(struct SOAP_ENV__Header*)p = *(struct SOAP_ENV__Header*)q; + if ((p = soap_in_SOAP_ENV__Header(soap, tag, p, type))) + if (soap_getindependent(soap)) + return NULL; + return p; } #endif SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__executeCommand(struct soap *soap, struct ns1__executeCommand *a) { - (void)soap; (void)a; /* appease -Wall -Werror */ - soap_default_string(soap, &a->command); + (void)soap; (void)a; /* appease -Wall -Werror */ + soap_default_string(soap, &a->command); } SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__executeCommand(struct soap *soap, const struct ns1__executeCommand *a) { - (void)soap; (void)a; /* appease -Wall -Werror */ - soap_serialize_string(soap, &a->command); + (void)soap; (void)a; /* appease -Wall -Werror */ +#ifndef WITH_NOIDREF + soap_serialize_string(soap, (char*const*)&a->command); +#endif } -SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__executeCommand(struct soap *soap, const struct ns1__executeCommand *a, const char *tag, const char *type) +SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__executeCommand(struct soap *soap, const char *tag, int id, const struct ns1__executeCommand *a, const char *type) { - int id = soap_embed(soap, (void*)a, nullptr, 0, tag, SOAP_TYPE_ns1__executeCommand); - if (soap_out_ns1__executeCommand(soap, tag, id, a, type)) - return soap->error; - return soap_putindependent(soap); + (void)soap; (void)tag; (void)id; (void)a; (void)type; /* appease -Wall -Werror */ + if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_ns1__executeCommand), type)) + return soap->error; + if (soap_out_string(soap, "command", -1, (char*const*)&a->command, "")) + return soap->error; + return soap_element_end_out(soap, tag); } -SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__executeCommand(struct soap *soap, const char *tag, int id, const struct ns1__executeCommand *a, const char *type) +SOAP_FMAC3 struct ns1__executeCommand * SOAP_FMAC4 soap_in_ns1__executeCommand(struct soap *soap, const char *tag, struct ns1__executeCommand *a, const char *type) { - if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_ns1__executeCommand), type)) - return soap->error; - if (soap_out_string(soap, "command", -1, &a->command, "")) - return soap->error; - return soap_element_end_out(soap, tag); + size_t soap_flag_command = 1; + if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; + (void)type; /* appease -Wall -Werror */ + a = (struct ns1__executeCommand*)soap_id_enter(soap, soap->id, a, SOAP_TYPE_ns1__executeCommand, sizeof(struct ns1__executeCommand), NULL, NULL, NULL, NULL); + if (!a) + return NULL; + soap_default_ns1__executeCommand(soap, a); + if (soap->body && *soap->href != '#') + { + for (;;) + { soap->error = SOAP_TAG_MISMATCH; + if (soap_flag_command && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG)) + { if (soap_in_string(soap, "command", (char**)&a->command, "xsd:string")) + { soap_flag_command--; + continue; + } + } + if (soap->error == SOAP_TAG_MISMATCH) + soap->error = soap_ignore_element(soap); + if (soap->error == SOAP_NO_TAG) + break; + if (soap->error) + return NULL; + } + if (soap_element_end_in(soap, tag)) + return NULL; + } + else + { a = (struct ns1__executeCommand *)soap_id_forward(soap, soap->href, (void*)a, 0, SOAP_TYPE_ns1__executeCommand, SOAP_TYPE_ns1__executeCommand, sizeof(struct ns1__executeCommand), 0, soap_finsert, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + } + return a; +} + +SOAP_FMAC1 struct ns1__executeCommand * SOAP_FMAC2 soap_instantiate_ns1__executeCommand(struct soap *soap, int n, const char *type, const char *arrayType, size_t *size) +{ + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "soap_instantiate_ns1__executeCommand(%p, %d, %s, %s)\n", (void*)soap, n, type?type:"", arrayType?arrayType:"")); + (void)type; (void)arrayType; /* appease -Wall -Werror */ + struct ns1__executeCommand *p; + size_t k = sizeof(struct ns1__executeCommand); + struct soap_clist *cp = soap_link(soap, SOAP_TYPE_ns1__executeCommand, n, soap_fdelete); + if (!cp && soap && n != SOAP_NO_LINK_TO_DELETE) + return NULL; + if (n < 0) + { p = SOAP_NEW(soap, struct ns1__executeCommand); + } + else + { p = SOAP_NEW_ARRAY(soap, struct ns1__executeCommand, n); + k *= n; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Instantiated struct ns1__executeCommand location=%p n=%d\n", (void*)p, n)); + if (size) + *size = k; + if (!p) + soap->error = SOAP_EOM; + else if (cp) + cp->ptr = (void*)p; + return p; } -SOAP_FMAC3 struct ns1__executeCommand * SOAP_FMAC4 soap_get_ns1__executeCommand(struct soap *soap, struct ns1__executeCommand *p, const char *tag, const char *type) +SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__executeCommand(struct soap *soap, const struct ns1__executeCommand *a, const char *tag, const char *type) { - if ((p = soap_in_ns1__executeCommand(soap, tag, p, type))) - if (soap_getindependent(soap)) - return nullptr; - return p; + if (soap_out_ns1__executeCommand(soap, tag ? tag : "ns1:executeCommand", -2, a, type)) + return soap->error; + return soap_putindependent(soap); } -SOAP_FMAC3 struct ns1__executeCommand * SOAP_FMAC4 soap_in_ns1__executeCommand(struct soap *soap, const char *tag, struct ns1__executeCommand *a, const char *type) +SOAP_FMAC3 struct ns1__executeCommand * SOAP_FMAC4 soap_get_ns1__executeCommand(struct soap *soap, struct ns1__executeCommand *p, const char *tag, const char *type) { - short soap_flag_command = 1; - if (soap_element_begin_in(soap, tag, 0, type)) - return nullptr; - a = (struct ns1__executeCommand *)soap_id_enter(soap, soap->id, a, SOAP_TYPE_ns1__executeCommand, sizeof(struct ns1__executeCommand), 0, nullptr, nullptr, nullptr); - if (!a) - return nullptr; - soap_default_ns1__executeCommand(soap, a); - if (soap->body && !*soap->href) - { - for (;;) - { soap->error = SOAP_TAG_MISMATCH; - if (soap_flag_command && (soap->error == SOAP_TAG_MISMATCH || soap->error == SOAP_NO_TAG)) - if (soap_in_string(soap, "command", &a->command, "xsd:string")) - { soap_flag_command--; - continue; - } - if (soap->error == SOAP_TAG_MISMATCH) - soap->error = soap_ignore_element(soap); - if (soap->error == SOAP_NO_TAG) - break; - if (soap->error) - return nullptr; - } - if (soap_element_end_in(soap, tag)) - return nullptr; - } - else - { a = (struct ns1__executeCommand *)soap_id_forward(soap, soap->href, (void*)a, 0, SOAP_TYPE_ns1__executeCommand, 0, sizeof(struct ns1__executeCommand), 0, nullptr); - if (soap->body && soap_element_end_in(soap, tag)) - return nullptr; - } - return a; -} - -SOAP_FMAC5 struct ns1__executeCommand * SOAP_FMAC6 soap_new_ns1__executeCommand(struct soap *soap, int n) -{ return soap_instantiate_ns1__executeCommand(soap, n, nullptr, nullptr, nullptr); -} - -SOAP_FMAC5 void SOAP_FMAC6 soap_delete_ns1__executeCommand(struct soap *soap, struct ns1__executeCommand *p) -{ soap_delete(soap, p); -} - -SOAP_FMAC3 struct ns1__executeCommand * SOAP_FMAC4 soap_instantiate_ns1__executeCommand(struct soap *soap, int n, const char *type, const char *arrayType, size_t *size) -{ - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "soap_instantiate_ns1__executeCommand(%d, %s, %s)\n", n, type?type:"", arrayType?arrayType:"")); - struct soap_clist *cp = soap_link(soap, nullptr, SOAP_TYPE_ns1__executeCommand, n, soap_fdelete); - if (!cp) - return nullptr; - if (n < 0) - { cp->ptr = (void*)new struct ns1__executeCommand; - if (size) - *size = sizeof(struct ns1__executeCommand); - } - else - { cp->ptr = (void*)new struct ns1__executeCommand[n]; - if (!cp->ptr) - { soap->error = SOAP_EOM; - return nullptr; - } - if (size) - *size = n * sizeof(struct ns1__executeCommand); - } - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Instantiated location=%p\n", cp->ptr)); - return (struct ns1__executeCommand*)cp->ptr; -} -SOAP_FMAC3 void SOAP_FMAC4 soap_copy_ns1__executeCommand(struct soap *soap, int st, int tt, void *p, size_t len, const void *q, size_t n) -{ - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying struct ns1__executeCommand %p -> %p\n", q, p)); - *(struct ns1__executeCommand*)p = *(struct ns1__executeCommand*)q; + if ((p = soap_in_ns1__executeCommand(soap, tag, p, type))) + if (soap_getindependent(soap)) + return NULL; + return p; } SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__executeCommandResponse(struct soap *soap, struct ns1__executeCommandResponse *a) { - (void)soap; (void)a; /* appease -Wall -Werror */ - a->result = nullptr; + (void)soap; (void)a; /* appease -Wall -Werror */ + a->result = NULL; } SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__executeCommandResponse(struct soap *soap, const struct ns1__executeCommandResponse *a) { - (void)soap; (void)a; /* appease -Wall -Werror */ - soap_serialize_PointerTostring(soap, &a->result); + (void)soap; (void)a; /* appease -Wall -Werror */ +#ifndef WITH_NOIDREF + soap_serialize_PointerTostring(soap, &a->result); +#endif } -SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__executeCommandResponse(struct soap *soap, const struct ns1__executeCommandResponse *a, const char *tag, const char *type) +SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__executeCommandResponse(struct soap *soap, const char *tag, int id, const struct ns1__executeCommandResponse *a, const char *type) { - int id = soap_embed(soap, (void*)a, nullptr, 0, tag, SOAP_TYPE_ns1__executeCommandResponse); - if (soap_out_ns1__executeCommandResponse(soap, tag, id, a, type)) - return soap->error; - return soap_putindependent(soap); + (void)soap; (void)tag; (void)id; (void)a; (void)type; /* appease -Wall -Werror */ + if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_ns1__executeCommandResponse), type)) + return soap->error; + if (soap_out_PointerTostring(soap, "result", -1, &a->result, "")) + return soap->error; + return soap_element_end_out(soap, tag); } -SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__executeCommandResponse(struct soap *soap, const char *tag, int id, const struct ns1__executeCommandResponse *a, const char *type) +SOAP_FMAC3 struct ns1__executeCommandResponse * SOAP_FMAC4 soap_in_ns1__executeCommandResponse(struct soap *soap, const char *tag, struct ns1__executeCommandResponse *a, const char *type) { - if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, a, SOAP_TYPE_ns1__executeCommandResponse), type)) - return soap->error; - if (soap_out_PointerTostring(soap, "result", -1, &a->result, "")) - return soap->error; - return soap_element_end_out(soap, tag); + size_t soap_flag_result = 1; + if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; + (void)type; /* appease -Wall -Werror */ + a = (struct ns1__executeCommandResponse*)soap_id_enter(soap, soap->id, a, SOAP_TYPE_ns1__executeCommandResponse, sizeof(struct ns1__executeCommandResponse), NULL, NULL, NULL, NULL); + if (!a) + return NULL; + soap_default_ns1__executeCommandResponse(soap, a); + if (soap->body && *soap->href != '#') + { + for (;;) + { soap->error = SOAP_TAG_MISMATCH; + if (soap_flag_result && soap->error == SOAP_TAG_MISMATCH) + { if (soap_in_PointerTostring(soap, "result", &a->result, "xsd:string")) + { soap_flag_result--; + continue; + } + } + if (soap->error == SOAP_TAG_MISMATCH) + soap->error = soap_ignore_element(soap); + if (soap->error == SOAP_NO_TAG) + break; + if (soap->error) + return NULL; + } + if (soap_element_end_in(soap, tag)) + return NULL; + } + else + { a = (struct ns1__executeCommandResponse *)soap_id_forward(soap, soap->href, (void*)a, 0, SOAP_TYPE_ns1__executeCommandResponse, SOAP_TYPE_ns1__executeCommandResponse, sizeof(struct ns1__executeCommandResponse), 0, soap_finsert, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + } + return a; +} + +SOAP_FMAC1 struct ns1__executeCommandResponse * SOAP_FMAC2 soap_instantiate_ns1__executeCommandResponse(struct soap *soap, int n, const char *type, const char *arrayType, size_t *size) +{ + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "soap_instantiate_ns1__executeCommandResponse(%p, %d, %s, %s)\n", (void*)soap, n, type?type:"", arrayType?arrayType:"")); + (void)type; (void)arrayType; /* appease -Wall -Werror */ + struct ns1__executeCommandResponse *p; + size_t k = sizeof(struct ns1__executeCommandResponse); + struct soap_clist *cp = soap_link(soap, SOAP_TYPE_ns1__executeCommandResponse, n, soap_fdelete); + if (!cp && soap && n != SOAP_NO_LINK_TO_DELETE) + return NULL; + if (n < 0) + { p = SOAP_NEW(soap, struct ns1__executeCommandResponse); + } + else + { p = SOAP_NEW_ARRAY(soap, struct ns1__executeCommandResponse, n); + k *= n; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Instantiated struct ns1__executeCommandResponse location=%p n=%d\n", (void*)p, n)); + if (size) + *size = k; + if (!p) + soap->error = SOAP_EOM; + else if (cp) + cp->ptr = (void*)p; + return p; } -SOAP_FMAC3 struct ns1__executeCommandResponse * SOAP_FMAC4 soap_get_ns1__executeCommandResponse(struct soap *soap, struct ns1__executeCommandResponse *p, const char *tag, const char *type) +SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__executeCommandResponse(struct soap *soap, const struct ns1__executeCommandResponse *a, const char *tag, const char *type) { - if ((p = soap_in_ns1__executeCommandResponse(soap, tag, p, type))) - if (soap_getindependent(soap)) - return nullptr; - return p; + if (soap_out_ns1__executeCommandResponse(soap, tag ? tag : "ns1:executeCommandResponse", -2, a, type)) + return soap->error; + return soap_putindependent(soap); } -SOAP_FMAC3 struct ns1__executeCommandResponse * SOAP_FMAC4 soap_in_ns1__executeCommandResponse(struct soap *soap, const char *tag, struct ns1__executeCommandResponse *a, const char *type) +SOAP_FMAC3 struct ns1__executeCommandResponse * SOAP_FMAC4 soap_get_ns1__executeCommandResponse(struct soap *soap, struct ns1__executeCommandResponse *p, const char *tag, const char *type) { - short soap_flag_result = 1; - if (soap_element_begin_in(soap, tag, 0, type)) - return nullptr; - a = (struct ns1__executeCommandResponse *)soap_id_enter(soap, soap->id, a, SOAP_TYPE_ns1__executeCommandResponse, sizeof(struct ns1__executeCommandResponse), 0, nullptr, nullptr, nullptr); - if (!a) - return nullptr; - soap_default_ns1__executeCommandResponse(soap, a); - if (soap->body && !*soap->href) - { - for (;;) - { soap->error = SOAP_TAG_MISMATCH; - if (soap_flag_result && soap->error == SOAP_TAG_MISMATCH) - if (soap_in_PointerTostring(soap, "result", &a->result, "xsd:string")) - { soap_flag_result--; - continue; - } - if (soap->error == SOAP_TAG_MISMATCH) - soap->error = soap_ignore_element(soap); - if (soap->error == SOAP_NO_TAG) - break; - if (soap->error) - return nullptr; - } - if (soap_element_end_in(soap, tag)) - return nullptr; - } - else - { a = (struct ns1__executeCommandResponse *)soap_id_forward(soap, soap->href, (void*)a, 0, SOAP_TYPE_ns1__executeCommandResponse, 0, sizeof(struct ns1__executeCommandResponse), 0, nullptr); - if (soap->body && soap_element_end_in(soap, tag)) - return nullptr; - } - return a; -} - -SOAP_FMAC5 struct ns1__executeCommandResponse * SOAP_FMAC6 soap_new_ns1__executeCommandResponse(struct soap *soap, int n) -{ return soap_instantiate_ns1__executeCommandResponse(soap, n, nullptr, nullptr, nullptr); -} - -SOAP_FMAC5 void SOAP_FMAC6 soap_delete_ns1__executeCommandResponse(struct soap *soap, struct ns1__executeCommandResponse *p) -{ soap_delete(soap, p); -} - -SOAP_FMAC3 struct ns1__executeCommandResponse * SOAP_FMAC4 soap_instantiate_ns1__executeCommandResponse(struct soap *soap, int n, const char *type, const char *arrayType, size_t *size) -{ - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "soap_instantiate_ns1__executeCommandResponse(%d, %s, %s)\n", n, type?type:"", arrayType?arrayType:"")); - struct soap_clist *cp = soap_link(soap, nullptr, SOAP_TYPE_ns1__executeCommandResponse, n, soap_fdelete); - if (!cp) - return nullptr; - if (n < 0) - { cp->ptr = (void*)new struct ns1__executeCommandResponse; - if (size) - *size = sizeof(struct ns1__executeCommandResponse); - } - else - { cp->ptr = (void*)new struct ns1__executeCommandResponse[n]; - if (!cp->ptr) - { soap->error = SOAP_EOM; - return nullptr; - } - if (size) - *size = n * sizeof(struct ns1__executeCommandResponse); - } - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Instantiated location=%p\n", cp->ptr)); - return (struct ns1__executeCommandResponse*)cp->ptr; -} -SOAP_FMAC3 void SOAP_FMAC4 soap_copy_ns1__executeCommandResponse(struct soap *soap, int st, int tt, void *p, size_t len, const void *q, size_t n) -{ - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying struct ns1__executeCommandResponse %p -> %p\n", q, p)); - *(struct ns1__executeCommandResponse*)p = *(struct ns1__executeCommandResponse*)q; + if ((p = soap_in_ns1__executeCommandResponse(soap, tag, p, type))) + if (soap_getindependent(soap)) + return NULL; + return p; } #ifndef WITH_NOGLOBAL SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_PointerToSOAP_ENV__Reason(struct soap *soap, struct SOAP_ENV__Reason *const*a) { - if (!soap_reference(soap, *a, SOAP_TYPE_SOAP_ENV__Reason)) - soap_serialize_SOAP_ENV__Reason(soap, *a); + (void)soap; (void)a; /* appease -Wall -Werror */ +#ifndef WITH_NOIDREF + if (!soap_reference(soap, *a, SOAP_TYPE_SOAP_ENV__Reason)) + soap_serialize_SOAP_ENV__Reason(soap, *a); +#endif } -SOAP_FMAC3 int SOAP_FMAC4 soap_put_PointerToSOAP_ENV__Reason(struct soap *soap, struct SOAP_ENV__Reason *const*a, const char *tag, const char *type) +SOAP_FMAC3 int SOAP_FMAC4 soap_out_PointerToSOAP_ENV__Reason(struct soap *soap, const char *tag, int id, struct SOAP_ENV__Reason *const*a, const char *type) { - int id = soap_embed(soap, (void*)a, nullptr, 0, tag, SOAP_TYPE_PointerToSOAP_ENV__Reason); - if (soap_out_PointerToSOAP_ENV__Reason(soap, tag, id, a, type)) - return soap->error; - return soap_putindependent(soap); + id = soap_element_id(soap, tag, id, *a, NULL, 0, type, SOAP_TYPE_SOAP_ENV__Reason, NULL); + if (id < 0) + return soap->error; + return soap_out_SOAP_ENV__Reason(soap, tag, id, *a, type); } -SOAP_FMAC3 int SOAP_FMAC4 soap_out_PointerToSOAP_ENV__Reason(struct soap *soap, const char *tag, int id, struct SOAP_ENV__Reason *const*a, const char *type) +SOAP_FMAC3 struct SOAP_ENV__Reason ** SOAP_FMAC4 soap_in_PointerToSOAP_ENV__Reason(struct soap *soap, const char *tag, struct SOAP_ENV__Reason **a, const char *type) { - id = soap_element_id(soap, tag, id, *a, nullptr, 0, type, SOAP_TYPE_SOAP_ENV__Reason); - if (id < 0) - return soap->error; - return soap_out_SOAP_ENV__Reason(soap, tag, id, *a, type); + (void)type; /* appease -Wall -Werror */ + if (soap_element_begin_in(soap, tag, 1, NULL)) + return NULL; + if (!a) + if (!(a = (struct SOAP_ENV__Reason **)soap_malloc(soap, sizeof(struct SOAP_ENV__Reason *)))) + return NULL; + *a = NULL; + if (!soap->null && *soap->href != '#') + { soap_revert(soap); + if (!(*a = soap_in_SOAP_ENV__Reason(soap, tag, *a, type))) + return NULL; + } + else + { a = (struct SOAP_ENV__Reason **)soap_id_lookup(soap, soap->href, (void**)a, SOAP_TYPE_SOAP_ENV__Reason, sizeof(struct SOAP_ENV__Reason), 0, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + } + return a; } -SOAP_FMAC3 struct SOAP_ENV__Reason ** SOAP_FMAC4 soap_get_PointerToSOAP_ENV__Reason(struct soap *soap, struct SOAP_ENV__Reason **p, const char *tag, const char *type) +SOAP_FMAC3 int SOAP_FMAC4 soap_put_PointerToSOAP_ENV__Reason(struct soap *soap, struct SOAP_ENV__Reason *const*a, const char *tag, const char *type) { - if ((p = soap_in_PointerToSOAP_ENV__Reason(soap, tag, p, type))) - if (soap_getindependent(soap)) - return nullptr; - return p; + if (soap_out_PointerToSOAP_ENV__Reason(soap, tag ? tag : "SOAP-ENV:Reason", -2, a, type)) + return soap->error; + return soap_putindependent(soap); } -SOAP_FMAC3 struct SOAP_ENV__Reason ** SOAP_FMAC4 soap_in_PointerToSOAP_ENV__Reason(struct soap *soap, const char *tag, struct SOAP_ENV__Reason **a, const char *type) +SOAP_FMAC3 struct SOAP_ENV__Reason ** SOAP_FMAC4 soap_get_PointerToSOAP_ENV__Reason(struct soap *soap, struct SOAP_ENV__Reason **p, const char *tag, const char *type) { - if (soap_element_begin_in(soap, tag, 1, nullptr)) - return nullptr; - if (!a) - if (!(a = (struct SOAP_ENV__Reason **)soap_malloc(soap, sizeof(struct SOAP_ENV__Reason *)))) - return nullptr; - *a = nullptr; - if (!soap->null && *soap->href != '#') - { soap_revert(soap); - if (!(*a = soap_in_SOAP_ENV__Reason(soap, tag, *a, type))) - return nullptr; - } - else - { a = (struct SOAP_ENV__Reason **)soap_id_lookup(soap, soap->href, (void**)a, SOAP_TYPE_SOAP_ENV__Reason, sizeof(struct SOAP_ENV__Reason), 0); - if (soap->body && soap_element_end_in(soap, tag)) - return nullptr; - } - return a; + if ((p = soap_in_PointerToSOAP_ENV__Reason(soap, tag, p, type))) + if (soap_getindependent(soap)) + return NULL; + return p; } #endif @@ -1410,53 +1529,56 @@ SOAP_FMAC3 struct SOAP_ENV__Reason ** SOAP_FMAC4 soap_in_PointerToSOAP_ENV__Reas SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_PointerToSOAP_ENV__Detail(struct soap *soap, struct SOAP_ENV__Detail *const*a) { - if (!soap_reference(soap, *a, SOAP_TYPE_SOAP_ENV__Detail)) - soap_serialize_SOAP_ENV__Detail(soap, *a); + (void)soap; (void)a; /* appease -Wall -Werror */ +#ifndef WITH_NOIDREF + if (!soap_reference(soap, *a, SOAP_TYPE_SOAP_ENV__Detail)) + soap_serialize_SOAP_ENV__Detail(soap, *a); +#endif } -SOAP_FMAC3 int SOAP_FMAC4 soap_put_PointerToSOAP_ENV__Detail(struct soap *soap, struct SOAP_ENV__Detail *const*a, const char *tag, const char *type) +SOAP_FMAC3 int SOAP_FMAC4 soap_out_PointerToSOAP_ENV__Detail(struct soap *soap, const char *tag, int id, struct SOAP_ENV__Detail *const*a, const char *type) { - int id = soap_embed(soap, (void*)a, nullptr, 0, tag, SOAP_TYPE_PointerToSOAP_ENV__Detail); - if (soap_out_PointerToSOAP_ENV__Detail(soap, tag, id, a, type)) - return soap->error; - return soap_putindependent(soap); + id = soap_element_id(soap, tag, id, *a, NULL, 0, type, SOAP_TYPE_SOAP_ENV__Detail, NULL); + if (id < 0) + return soap->error; + return soap_out_SOAP_ENV__Detail(soap, tag, id, *a, type); } -SOAP_FMAC3 int SOAP_FMAC4 soap_out_PointerToSOAP_ENV__Detail(struct soap *soap, const char *tag, int id, struct SOAP_ENV__Detail *const*a, const char *type) +SOAP_FMAC3 struct SOAP_ENV__Detail ** SOAP_FMAC4 soap_in_PointerToSOAP_ENV__Detail(struct soap *soap, const char *tag, struct SOAP_ENV__Detail **a, const char *type) { - id = soap_element_id(soap, tag, id, *a, nullptr, 0, type, SOAP_TYPE_SOAP_ENV__Detail); - if (id < 0) - return soap->error; - return soap_out_SOAP_ENV__Detail(soap, tag, id, *a, type); + (void)type; /* appease -Wall -Werror */ + if (soap_element_begin_in(soap, tag, 1, NULL)) + return NULL; + if (!a) + if (!(a = (struct SOAP_ENV__Detail **)soap_malloc(soap, sizeof(struct SOAP_ENV__Detail *)))) + return NULL; + *a = NULL; + if (!soap->null && *soap->href != '#') + { soap_revert(soap); + if (!(*a = soap_in_SOAP_ENV__Detail(soap, tag, *a, type))) + return NULL; + } + else + { a = (struct SOAP_ENV__Detail **)soap_id_lookup(soap, soap->href, (void**)a, SOAP_TYPE_SOAP_ENV__Detail, sizeof(struct SOAP_ENV__Detail), 0, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + } + return a; } -SOAP_FMAC3 struct SOAP_ENV__Detail ** SOAP_FMAC4 soap_get_PointerToSOAP_ENV__Detail(struct soap *soap, struct SOAP_ENV__Detail **p, const char *tag, const char *type) +SOAP_FMAC3 int SOAP_FMAC4 soap_put_PointerToSOAP_ENV__Detail(struct soap *soap, struct SOAP_ENV__Detail *const*a, const char *tag, const char *type) { - if ((p = soap_in_PointerToSOAP_ENV__Detail(soap, tag, p, type))) - if (soap_getindependent(soap)) - return nullptr; - return p; + if (soap_out_PointerToSOAP_ENV__Detail(soap, tag ? tag : "SOAP-ENV:Detail", -2, a, type)) + return soap->error; + return soap_putindependent(soap); } -SOAP_FMAC3 struct SOAP_ENV__Detail ** SOAP_FMAC4 soap_in_PointerToSOAP_ENV__Detail(struct soap *soap, const char *tag, struct SOAP_ENV__Detail **a, const char *type) +SOAP_FMAC3 struct SOAP_ENV__Detail ** SOAP_FMAC4 soap_get_PointerToSOAP_ENV__Detail(struct soap *soap, struct SOAP_ENV__Detail **p, const char *tag, const char *type) { - if (soap_element_begin_in(soap, tag, 1, nullptr)) - return nullptr; - if (!a) - if (!(a = (struct SOAP_ENV__Detail **)soap_malloc(soap, sizeof(struct SOAP_ENV__Detail *)))) - return nullptr; - *a = nullptr; - if (!soap->null && *soap->href != '#') - { soap_revert(soap); - if (!(*a = soap_in_SOAP_ENV__Detail(soap, tag, *a, type))) - return nullptr; - } - else - { a = (struct SOAP_ENV__Detail **)soap_id_lookup(soap, soap->href, (void**)a, SOAP_TYPE_SOAP_ENV__Detail, sizeof(struct SOAP_ENV__Detail), 0); - if (soap->body && soap_element_end_in(soap, tag)) - return nullptr; - } - return a; + if ((p = soap_in_PointerToSOAP_ENV__Detail(soap, tag, p, type))) + if (soap_getindependent(soap)) + return NULL; + return p; } #endif @@ -1465,180 +1587,196 @@ SOAP_FMAC3 struct SOAP_ENV__Detail ** SOAP_FMAC4 soap_in_PointerToSOAP_ENV__Deta SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_PointerToSOAP_ENV__Code(struct soap *soap, struct SOAP_ENV__Code *const*a) { - if (!soap_reference(soap, *a, SOAP_TYPE_SOAP_ENV__Code)) - soap_serialize_SOAP_ENV__Code(soap, *a); + (void)soap; (void)a; /* appease -Wall -Werror */ +#ifndef WITH_NOIDREF + if (!soap_reference(soap, *a, SOAP_TYPE_SOAP_ENV__Code)) + soap_serialize_SOAP_ENV__Code(soap, *a); +#endif } -SOAP_FMAC3 int SOAP_FMAC4 soap_put_PointerToSOAP_ENV__Code(struct soap *soap, struct SOAP_ENV__Code *const*a, const char *tag, const char *type) +SOAP_FMAC3 int SOAP_FMAC4 soap_out_PointerToSOAP_ENV__Code(struct soap *soap, const char *tag, int id, struct SOAP_ENV__Code *const*a, const char *type) { - int id = soap_embed(soap, (void*)a, nullptr, 0, tag, SOAP_TYPE_PointerToSOAP_ENV__Code); - if (soap_out_PointerToSOAP_ENV__Code(soap, tag, id, a, type)) - return soap->error; - return soap_putindependent(soap); + char *mark; + id = soap_element_id(soap, tag, id, *a, NULL, 0, type, SOAP_TYPE_SOAP_ENV__Code, &mark); + if (id < 0) + return soap->error; + (void)soap_out_SOAP_ENV__Code(soap, tag, id, *a, type); + soap_unmark(soap, mark); + return soap->error; } -SOAP_FMAC3 int SOAP_FMAC4 soap_out_PointerToSOAP_ENV__Code(struct soap *soap, const char *tag, int id, struct SOAP_ENV__Code *const*a, const char *type) +SOAP_FMAC3 struct SOAP_ENV__Code ** SOAP_FMAC4 soap_in_PointerToSOAP_ENV__Code(struct soap *soap, const char *tag, struct SOAP_ENV__Code **a, const char *type) { - id = soap_element_id(soap, tag, id, *a, nullptr, 0, type, SOAP_TYPE_SOAP_ENV__Code); - if (id < 0) - return soap->error; - return soap_out_SOAP_ENV__Code(soap, tag, id, *a, type); + (void)type; /* appease -Wall -Werror */ + if (soap_element_begin_in(soap, tag, 1, NULL)) + return NULL; + if (!a) + if (!(a = (struct SOAP_ENV__Code **)soap_malloc(soap, sizeof(struct SOAP_ENV__Code *)))) + return NULL; + *a = NULL; + if (!soap->null && *soap->href != '#') + { soap_revert(soap); + if (!(*a = soap_in_SOAP_ENV__Code(soap, tag, *a, type))) + return NULL; + } + else + { a = (struct SOAP_ENV__Code **)soap_id_lookup(soap, soap->href, (void**)a, SOAP_TYPE_SOAP_ENV__Code, sizeof(struct SOAP_ENV__Code), 0, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + } + return a; } -SOAP_FMAC3 struct SOAP_ENV__Code ** SOAP_FMAC4 soap_get_PointerToSOAP_ENV__Code(struct soap *soap, struct SOAP_ENV__Code **p, const char *tag, const char *type) +SOAP_FMAC3 int SOAP_FMAC4 soap_put_PointerToSOAP_ENV__Code(struct soap *soap, struct SOAP_ENV__Code *const*a, const char *tag, const char *type) { - if ((p = soap_in_PointerToSOAP_ENV__Code(soap, tag, p, type))) - if (soap_getindependent(soap)) - return nullptr; - return p; + if (soap_out_PointerToSOAP_ENV__Code(soap, tag ? tag : "SOAP-ENV:Code", -2, a, type)) + return soap->error; + return soap_putindependent(soap); } -SOAP_FMAC3 struct SOAP_ENV__Code ** SOAP_FMAC4 soap_in_PointerToSOAP_ENV__Code(struct soap *soap, const char *tag, struct SOAP_ENV__Code **a, const char *type) +SOAP_FMAC3 struct SOAP_ENV__Code ** SOAP_FMAC4 soap_get_PointerToSOAP_ENV__Code(struct soap *soap, struct SOAP_ENV__Code **p, const char *tag, const char *type) { - if (soap_element_begin_in(soap, tag, 1, nullptr)) - return nullptr; - if (!a) - if (!(a = (struct SOAP_ENV__Code **)soap_malloc(soap, sizeof(struct SOAP_ENV__Code *)))) - return nullptr; - *a = nullptr; - if (!soap->null && *soap->href != '#') - { soap_revert(soap); - if (!(*a = soap_in_SOAP_ENV__Code(soap, tag, *a, type))) - return nullptr; - } - else - { a = (struct SOAP_ENV__Code **)soap_id_lookup(soap, soap->href, (void**)a, SOAP_TYPE_SOAP_ENV__Code, sizeof(struct SOAP_ENV__Code), 0); - if (soap->body && soap_element_end_in(soap, tag)) - return nullptr; - } - return a; + if ((p = soap_in_PointerToSOAP_ENV__Code(soap, tag, p, type))) + if (soap_getindependent(soap)) + return NULL; + return p; } #endif SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_PointerTostring(struct soap *soap, char **const*a) { - if (!soap_reference(soap, *a, SOAP_TYPE_string)) - soap_serialize_string(soap, *a); + (void)soap; (void)a; /* appease -Wall -Werror */ +#ifndef WITH_NOIDREF + if (!soap_reference(soap, *a, SOAP_TYPE_string)) + soap_serialize_string(soap, *a); +#endif } -SOAP_FMAC3 int SOAP_FMAC4 soap_put_PointerTostring(struct soap *soap, char **const*a, const char *tag, const char *type) +SOAP_FMAC3 int SOAP_FMAC4 soap_out_PointerTostring(struct soap *soap, const char *tag, int id, char **const*a, const char *type) { - int id = soap_embed(soap, (void*)a, nullptr, 0, tag, SOAP_TYPE_PointerTostring); - if (soap_out_PointerTostring(soap, tag, id, a, type)) - return soap->error; - return soap_putindependent(soap); + id = soap_element_id(soap, tag, id, *a, NULL, 0, type, SOAP_TYPE_string, NULL); + if (id < 0) + return soap->error; + return soap_out_string(soap, tag, id, *a, type); } -SOAP_FMAC3 int SOAP_FMAC4 soap_out_PointerTostring(struct soap *soap, const char *tag, int id, char **const*a, const char *type) +SOAP_FMAC3 char *** SOAP_FMAC4 soap_in_PointerTostring(struct soap *soap, const char *tag, char ***a, const char *type) { - id = soap_element_id(soap, tag, id, *a, nullptr, 0, type, SOAP_TYPE_string); - if (id < 0) - return soap->error; - return soap_out_string(soap, tag, id, *a, type); + (void)type; /* appease -Wall -Werror */ + if (soap_element_begin_in(soap, tag, 1, NULL)) + return NULL; + if (!a) + if (!(a = (char ***)soap_malloc(soap, sizeof(char **)))) + return NULL; + *a = NULL; + if (!soap->null && *soap->href != '#') + { soap_revert(soap); + if (!(*a = soap_in_string(soap, tag, *a, type))) + return NULL; + } + else + { a = (char ***)soap_id_lookup(soap, soap->href, (void**)a, SOAP_TYPE_string, sizeof(char *), 1, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + } + return a; } -SOAP_FMAC3 char *** SOAP_FMAC4 soap_get_PointerTostring(struct soap *soap, char ***p, const char *tag, const char *type) +SOAP_FMAC3 int SOAP_FMAC4 soap_put_PointerTostring(struct soap *soap, char **const*a, const char *tag, const char *type) { - if ((p = soap_in_PointerTostring(soap, tag, p, type))) - if (soap_getindependent(soap)) - return nullptr; - return p; + if (soap_out_PointerTostring(soap, tag ? tag : "string", -2, a, type)) + return soap->error; + return soap_putindependent(soap); } -SOAP_FMAC3 char *** SOAP_FMAC4 soap_in_PointerTostring(struct soap *soap, const char *tag, char ***a, const char *type) +SOAP_FMAC3 char *** SOAP_FMAC4 soap_get_PointerTostring(struct soap *soap, char ***p, const char *tag, const char *type) { - if (soap_element_begin_in(soap, tag, 1, nullptr)) - return nullptr; - if (!a) - if (!(a = (char ***)soap_malloc(soap, sizeof(char **)))) - return nullptr; - *a = nullptr; - if (!soap->null && *soap->href != '#') - { soap_revert(soap); - if (!(*a = soap_in_string(soap, tag, *a, type))) - return nullptr; - } - else - { a = (char ***)soap_id_lookup(soap, soap->href, (void**)a, SOAP_TYPE_string, sizeof(char *), 1); - if (soap->body && soap_element_end_in(soap, tag)) - return nullptr; - } - return a; -} - -SOAP_FMAC3 void SOAP_FMAC4 soap_default__QName(struct soap *soap, char **a) -{ soap_default_string(soap, a); + if ((p = soap_in_PointerTostring(soap, tag, p, type))) + if (soap_getindependent(soap)) + return NULL; + return p; } SOAP_FMAC3 void SOAP_FMAC4 soap_serialize__QName(struct soap *soap, char *const*a) -{ soap_serialize_string(soap, a); +{ + (void)soap; (void)a; /* appease -Wall -Werror */ +#ifndef WITH_NOIDREF + (void)soap_reference(soap, *a, SOAP_TYPE__QName); +#endif } -SOAP_FMAC3 int SOAP_FMAC4 soap_put__QName(struct soap *soap, char *const*a, const char *tag, const char *type) +SOAP_FMAC3 int SOAP_FMAC4 soap_out__QName(struct soap *soap, const char *tag, int id, char *const*a, const char *type) { - int id = soap_embed(soap, (void*)a, nullptr, 0, tag, SOAP_TYPE__QName); - if (soap_out__QName(soap, tag, id, a, type)) - return soap->error; - return soap_putindependent(soap); + return soap_outstring(soap, tag, id, a, type, SOAP_TYPE__QName); } -SOAP_FMAC3 int SOAP_FMAC4 soap_out__QName(struct soap *soap, const char *tag, int id, char *const*a, const char *type) +SOAP_FMAC3 char * * SOAP_FMAC4 soap_in__QName(struct soap *soap, const char *tag, char **a, const char *type) { - return soap_outstring(soap, tag, id, a, type, SOAP_TYPE__QName); + a = soap_instring(soap, tag, a, type, SOAP_TYPE__QName, 2, 0, -1, NULL); + return a; } -SOAP_FMAC3 char ** SOAP_FMAC4 soap_get__QName(struct soap *soap, char **p, const char *tag, const char *type) +SOAP_FMAC3 int SOAP_FMAC4 soap_put__QName(struct soap *soap, char *const*a, const char *tag, const char *type) { - if ((p = soap_in__QName(soap, tag, p, type))) - if (soap_getindependent(soap)) - return nullptr; - return p; + if (soap_out__QName(soap, tag ? tag : "QName", -2, a, type)) + return soap->error; + return soap_putindependent(soap); } -SOAP_FMAC3 char ** SOAP_FMAC4 soap_in__QName(struct soap *soap, const char *tag, char **a, const char *type) +SOAP_FMAC3 char ** SOAP_FMAC4 soap_get__QName(struct soap *soap, char **p, const char *tag, const char *type) { - return soap_instring(soap, tag, a, type, SOAP_TYPE__QName, 2, -1, -1); + if ((p = soap_in__QName(soap, tag, p, type))) + if (soap_getindependent(soap)) + return NULL; + return p; } -SOAP_FMAC3 void SOAP_FMAC4 soap_default_string(struct soap *soap, char **a) -{ (void)soap; /* appease -Wall -Werror */ -#ifdef SOAP_DEFAULT_string - *a = SOAP_DEFAULT_string; -#else - *a = (char *)0; +SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_string(struct soap *soap, char *const*a) +{ + (void)soap; (void)a; /* appease -Wall -Werror */ +#ifndef WITH_NOIDREF + (void)soap_reference(soap, *a, SOAP_TYPE_string); #endif } -SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_string(struct soap *soap, char *const*a) +SOAP_FMAC3 int SOAP_FMAC4 soap_out_string(struct soap *soap, const char *tag, int id, char *const*a, const char *type) { - soap_reference(soap, *a, SOAP_TYPE_string); + return soap_outstring(soap, tag, id, a, type, SOAP_TYPE_string); } -SOAP_FMAC3 int SOAP_FMAC4 soap_put_string(struct soap *soap, char *const*a, const char *tag, const char *type) +SOAP_FMAC3 char * * SOAP_FMAC4 soap_in_string(struct soap *soap, const char *tag, char **a, const char *type) { - int id = soap_embed(soap, (void*)a, nullptr, 0, tag, SOAP_TYPE_string); - if (soap_out_string(soap, tag, id, a, type)) - return soap->error; - return soap_putindependent(soap); + a = soap_instring(soap, tag, a, type, SOAP_TYPE_string, 1, 0, -1, NULL); + return a; } -SOAP_FMAC3 int SOAP_FMAC4 soap_out_string(struct soap *soap, const char *tag, int id, char *const*a, const char *type) +SOAP_FMAC3 char * * SOAP_FMAC4 soap_new_string(struct soap *soap, int n) { - return soap_outstring(soap, tag, id, a, type, SOAP_TYPE_string); + char * *a = static_cast(soap_malloc(soap, (n = (n < 0 ? 1 : n)) * sizeof(char *))); + for (char * *p = a; p && n--; ++p) + soap_default_string(soap, p); + return a; } -SOAP_FMAC3 char ** SOAP_FMAC4 soap_get_string(struct soap *soap, char **p, const char *tag, const char *type) +SOAP_FMAC3 int SOAP_FMAC4 soap_put_string(struct soap *soap, char *const*a, const char *tag, const char *type) { - if ((p = soap_in_string(soap, tag, p, type))) - if (soap_getindependent(soap)) - return nullptr; - return p; + if (soap_out_string(soap, tag ? tag : "string", -2, a, type)) + return soap->error; + return soap_putindependent(soap); } -SOAP_FMAC3 char ** SOAP_FMAC4 soap_in_string(struct soap *soap, const char *tag, char **a, const char *type) +SOAP_FMAC3 char ** SOAP_FMAC4 soap_get_string(struct soap *soap, char **p, const char *tag, const char *type) { - return soap_instring(soap, tag, a, type, SOAP_TYPE_string, 1, -1, -1); + if ((p = soap_in_string(soap, tag, p, type))) + if (soap_getindependent(soap)) + return NULL; + return p; } +#if defined(__BORLANDC__) +#pragma option pop +#pragma option pop +#endif + /* End of soapC.cpp */ diff --git a/dep/gsoap/soapH.h b/dep/gsoap/soapH.h index 01d3e7bab63d..681575a679e6 100644 --- a/dep/gsoap/soapH.h +++ b/dep/gsoap/soapH.h @@ -1,8 +1,14 @@ /* soapH.h - Generated by gSOAP 2.7.10 from stub.h - Copyright(C) 2000-2008, Robert van Engelen, Genivia Inc. All Rights Reserved. - This part of the software is released under one of the following licenses: - GPL, the gSOAP public license, or Genivia's license for commercial use. + Generated by gSOAP 2.8.135 for gsoap.stub + +gSOAP XML Web services tools +Copyright (C) 2000,2024, Robert van Engelen, Genivia Inc. All Rights Reserved. +The soapcpp2 tool and its generated software are released under the GPL. +This program is released under the GPL with the additional exemption that +compiling, linking, and/or using OpenSSL is allowed. +-------------------------------------------------------------------------------- +A commercial use license is available from Genivia Inc., contact@genivia.com +-------------------------------------------------------------------------------- */ #ifndef soapH_H @@ -14,8 +20,6 @@ extern "C" { #endif SOAP_FMAC3 void SOAP_FMAC4 soap_markelement(struct soap*, const void*, int); -SOAP_FMAC3 int SOAP_FMAC4 soap_putelement(struct soap*, const void*, const char*, int, int); -SOAP_FMAC3 void *SOAP_FMAC4 soap_getelement(struct soap*, int*); #ifdef __cplusplus } @@ -23,215 +27,1099 @@ SOAP_FMAC3 void *SOAP_FMAC4 soap_getelement(struct soap*, int*); SOAP_FMAC3 int SOAP_FMAC4 soap_putindependent(struct soap*); SOAP_FMAC3 int SOAP_FMAC4 soap_getindependent(struct soap*); #endif -SOAP_FMAC3 int SOAP_FMAC4 soap_ignore_element(struct soap*); +#ifdef __cplusplus +extern "C" { +#endif +SOAP_FMAC3 void * SOAP_FMAC4 soap_getelement(struct soap*, const char*, int*); +SOAP_FMAC3 int SOAP_FMAC4 soap_putelement(struct soap*, const void*, const char*, int, int); +SOAP_FMAC3 void * SOAP_FMAC4 soap_dupelement(struct soap*, const void*, int); +SOAP_FMAC3 void SOAP_FMAC4 soap_delelement(const void*, int); + +#ifdef __cplusplus +} +#endif +SOAP_FMAC3 int SOAP_FMAC4 soap_ignore_element(struct soap*); SOAP_FMAC3 void * SOAP_FMAC4 soap_instantiate(struct soap*, int, const char*, const char*, size_t*); -SOAP_FMAC3 int SOAP_FMAC4 soap_fdelete(struct soap_clist*); -SOAP_FMAC3 void* SOAP_FMAC4 soap_class_id_enter(struct soap*, const char*, void*, int, size_t, const char*, const char*); +SOAP_FMAC3 int SOAP_FMAC4 soap_fdelete(struct soap *soap, struct soap_clist*); +SOAP_FMAC3 int SOAP_FMAC4 soap_fbase(int, int); +SOAP_FMAC3 void SOAP_FMAC4 soap_finsert(struct soap*, int, int, void*, size_t, const void*, void**); + +#ifndef SOAP_TYPE_byte_DEFINED +#define SOAP_TYPE_byte_DEFINED -#ifndef SOAP_TYPE_byte -#define SOAP_TYPE_byte (3) +inline void soap_default_byte(struct soap *soap, char *a) +{ + (void)soap; /* appease -Wall -Werror */ +#ifdef SOAP_DEFAULT_byte + *a = SOAP_DEFAULT_byte; +#else + *a = (char)0; #endif -SOAP_FMAC3 void SOAP_FMAC4 soap_default_byte(struct soap*, char *); -SOAP_FMAC3 int SOAP_FMAC4 soap_put_byte(struct soap*, const char *, const char*, const char*); +} SOAP_FMAC3 int SOAP_FMAC4 soap_out_byte(struct soap*, const char*, int, const char *, const char*); -SOAP_FMAC3 char * SOAP_FMAC4 soap_get_byte(struct soap*, char *, const char*, const char*); SOAP_FMAC3 char * SOAP_FMAC4 soap_in_byte(struct soap*, const char*, char *, const char*); -#ifndef SOAP_TYPE_int -#define SOAP_TYPE_int (1) +SOAP_FMAC3 char * SOAP_FMAC4 soap_new_byte(struct soap *soap, int n = -1); +SOAP_FMAC3 int SOAP_FMAC4 soap_put_byte(struct soap*, const char *, const char*, const char*); + +inline int soap_write_byte(struct soap *soap, char const*p) +{ + soap_free_temp(soap); + if (p) + { if (soap_begin_send(soap) || ::soap_put_byte(soap, p, "byte", "") || soap_end_send(soap)) + return soap->error; + } + return SOAP_OK; +} + +inline int soap_PUT_byte(struct soap *soap, const char *URL, char const*p) +{ + soap_free_temp(soap); + if (soap_PUT(soap, URL, NULL, "text/xml; charset=utf-8") || ::soap_put_byte(soap, p, "byte", "") || soap_end_send(soap) || soap_recv_empty_response(soap)) + return soap_closesock(soap); + return SOAP_OK; +} + +inline int soap_PATCH_byte(struct soap *soap, const char *URL, char const*p) +{ + soap_free_temp(soap); + if (soap_PATCH(soap, URL, NULL, "text/xml; charset=utf-8") || ::soap_put_byte(soap, p, "byte", "") || soap_end_send(soap) || soap_recv_empty_response(soap)) + return soap_closesock(soap); + return SOAP_OK; +} + +inline int soap_POST_send_byte(struct soap *soap, const char *URL, char const*p) +{ + soap_free_temp(soap); + if (soap_POST(soap, URL, NULL, "text/xml; charset=utf-8") || ::soap_put_byte(soap, p, "byte", "") || soap_end_send(soap)) + return soap_closesock(soap); + return SOAP_OK; +} +SOAP_FMAC3 char * SOAP_FMAC4 soap_get_byte(struct soap*, char *, const char*, const char*); + +inline int soap_read_byte(struct soap *soap, char *p) +{ + if (p) + { if (soap_begin_recv(soap) || ::soap_get_byte(soap, p, NULL, NULL) == NULL || soap_end_recv(soap)) + return soap->error; + } + return SOAP_OK; +} + +inline int soap_GET_byte(struct soap *soap, const char *URL, char *p) +{ + if (soap_GET(soap, URL, NULL) || ::soap_read_byte(soap, p)) + return soap_closesock(soap); + return soap_closesock(soap); +} + +inline int soap_POST_recv_byte(struct soap *soap, char *p) +{ + if (::soap_read_byte(soap, p)) + return soap_closesock(soap); + return soap_closesock(soap); +} #endif -SOAP_FMAC3 void SOAP_FMAC4 soap_default_int(struct soap*, int *); -SOAP_FMAC3 int SOAP_FMAC4 soap_put_int(struct soap*, const int *, const char*, const char*); + +#ifndef SOAP_TYPE_int_DEFINED +#define SOAP_TYPE_int_DEFINED + +inline void soap_default_int(struct soap *soap, int *a) +{ + (void)soap; /* appease -Wall -Werror */ +#ifdef SOAP_DEFAULT_int + *a = SOAP_DEFAULT_int; +#else + *a = (int)0; +#endif +} SOAP_FMAC3 int SOAP_FMAC4 soap_out_int(struct soap*, const char*, int, const int *, const char*); -SOAP_FMAC3 int * SOAP_FMAC4 soap_get_int(struct soap*, int *, const char*, const char*); SOAP_FMAC3 int * SOAP_FMAC4 soap_in_int(struct soap*, const char*, int *, const char*); -#ifndef WITH_NOGLOBAL +SOAP_FMAC3 int * SOAP_FMAC4 soap_new_int(struct soap *soap, int n = -1); +SOAP_FMAC3 int SOAP_FMAC4 soap_put_int(struct soap*, const int *, const char*, const char*); + +inline int soap_write_int(struct soap *soap, int const*p) +{ + soap_free_temp(soap); + if (p) + { if (soap_begin_send(soap) || ::soap_put_int(soap, p, "int", "") || soap_end_send(soap)) + return soap->error; + } + return SOAP_OK; +} + +inline int soap_PUT_int(struct soap *soap, const char *URL, int const*p) +{ + soap_free_temp(soap); + if (soap_PUT(soap, URL, NULL, "text/xml; charset=utf-8") || ::soap_put_int(soap, p, "int", "") || soap_end_send(soap) || soap_recv_empty_response(soap)) + return soap_closesock(soap); + return SOAP_OK; +} + +inline int soap_PATCH_int(struct soap *soap, const char *URL, int const*p) +{ + soap_free_temp(soap); + if (soap_PATCH(soap, URL, NULL, "text/xml; charset=utf-8") || ::soap_put_int(soap, p, "int", "") || soap_end_send(soap) || soap_recv_empty_response(soap)) + return soap_closesock(soap); + return SOAP_OK; +} + +inline int soap_POST_send_int(struct soap *soap, const char *URL, int const*p) +{ + soap_free_temp(soap); + if (soap_POST(soap, URL, NULL, "text/xml; charset=utf-8") || ::soap_put_int(soap, p, "int", "") || soap_end_send(soap)) + return soap_closesock(soap); + return SOAP_OK; +} +SOAP_FMAC3 int * SOAP_FMAC4 soap_get_int(struct soap*, int *, const char*, const char*); -#ifndef SOAP_TYPE_SOAP_ENV__Fault -#define SOAP_TYPE_SOAP_ENV__Fault (18) +inline int soap_read_int(struct soap *soap, int *p) +{ + if (p) + { if (soap_begin_recv(soap) || ::soap_get_int(soap, p, NULL, NULL) == NULL || soap_end_recv(soap)) + return soap->error; + } + return SOAP_OK; +} + +inline int soap_GET_int(struct soap *soap, const char *URL, int *p) +{ + if (soap_GET(soap, URL, NULL) || ::soap_read_int(soap, p)) + return soap_closesock(soap); + return soap_closesock(soap); +} + +inline int soap_POST_recv_int(struct soap *soap, int *p) +{ + if (::soap_read_int(soap, p)) + return soap_closesock(soap); + return soap_closesock(soap); +} #endif + +#ifndef WITH_NOGLOBAL + +#ifndef SOAP_TYPE_SOAP_ENV__Fault_DEFINED +#define SOAP_TYPE_SOAP_ENV__Fault_DEFINED SOAP_FMAC3 void SOAP_FMAC4 soap_default_SOAP_ENV__Fault(struct soap*, struct SOAP_ENV__Fault *); SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_SOAP_ENV__Fault(struct soap*, const struct SOAP_ENV__Fault *); -SOAP_FMAC3 int SOAP_FMAC4 soap_put_SOAP_ENV__Fault(struct soap*, const struct SOAP_ENV__Fault *, const char*, const char*); SOAP_FMAC3 int SOAP_FMAC4 soap_out_SOAP_ENV__Fault(struct soap*, const char*, int, const struct SOAP_ENV__Fault *, const char*); -SOAP_FMAC3 struct SOAP_ENV__Fault * SOAP_FMAC4 soap_get_SOAP_ENV__Fault(struct soap*, struct SOAP_ENV__Fault *, const char*, const char*); SOAP_FMAC3 struct SOAP_ENV__Fault * SOAP_FMAC4 soap_in_SOAP_ENV__Fault(struct soap*, const char*, struct SOAP_ENV__Fault *, const char*); -SOAP_FMAC5 struct SOAP_ENV__Fault * SOAP_FMAC6 soap_new_SOAP_ENV__Fault(struct soap*, int); -SOAP_FMAC5 void SOAP_FMAC6 soap_delete_SOAP_ENV__Fault(struct soap*, struct SOAP_ENV__Fault*); -SOAP_FMAC3 struct SOAP_ENV__Fault * SOAP_FMAC4 soap_instantiate_SOAP_ENV__Fault(struct soap*, int, const char*, const char*, size_t*); -SOAP_FMAC3 void SOAP_FMAC4 soap_copy_SOAP_ENV__Fault(struct soap*, int, int, void*, size_t, const void*, size_t); +SOAP_FMAC1 struct SOAP_ENV__Fault * SOAP_FMAC2 soap_instantiate_SOAP_ENV__Fault(struct soap*, int, const char*, const char*, size_t*); + +inline struct SOAP_ENV__Fault * soap_new_SOAP_ENV__Fault(struct soap *soap, int n = -1) +{ + return soap_instantiate_SOAP_ENV__Fault(soap, n, NULL, NULL, NULL); +} + +inline struct SOAP_ENV__Fault * soap_new_req_SOAP_ENV__Fault( + struct soap *soap) +{ + struct SOAP_ENV__Fault *_p = ::soap_new_SOAP_ENV__Fault(soap); + if (_p) + { ::soap_default_SOAP_ENV__Fault(soap, _p); + } + return _p; +} + +inline struct SOAP_ENV__Fault * soap_new_set_SOAP_ENV__Fault( + struct soap *soap, + char *faultcode, + char *faultstring, + char *faultactor, + struct SOAP_ENV__Detail *detail, + struct SOAP_ENV__Code *SOAP_ENV__Code, + struct SOAP_ENV__Reason *SOAP_ENV__Reason, + char *SOAP_ENV__Node, + char *SOAP_ENV__Role, + struct SOAP_ENV__Detail *SOAP_ENV__Detail) +{ + struct SOAP_ENV__Fault *_p = ::soap_new_SOAP_ENV__Fault(soap); + if (_p) + { ::soap_default_SOAP_ENV__Fault(soap, _p); + _p->faultcode = faultcode; + _p->faultstring = faultstring; + _p->faultactor = faultactor; + _p->detail = detail; + _p->SOAP_ENV__Code = SOAP_ENV__Code; + _p->SOAP_ENV__Reason = SOAP_ENV__Reason; + _p->SOAP_ENV__Node = SOAP_ENV__Node; + _p->SOAP_ENV__Role = SOAP_ENV__Role; + _p->SOAP_ENV__Detail = SOAP_ENV__Detail; + } + return _p; +} +SOAP_FMAC3 int SOAP_FMAC4 soap_put_SOAP_ENV__Fault(struct soap*, const struct SOAP_ENV__Fault *, const char*, const char*); + +inline int soap_write_SOAP_ENV__Fault(struct soap *soap, struct SOAP_ENV__Fault const*p) +{ + soap_free_temp(soap); + if (soap_begin_send(soap) || (::soap_serialize_SOAP_ENV__Fault(soap, p), 0) || ::soap_put_SOAP_ENV__Fault(soap, p, "SOAP-ENV:Fault", "") || soap_end_send(soap)) + return soap->error; + return SOAP_OK; +} + +inline int soap_PUT_SOAP_ENV__Fault(struct soap *soap, const char *URL, struct SOAP_ENV__Fault const*p) +{ + soap_free_temp(soap); + if (soap_PUT(soap, URL, NULL, "text/xml; charset=utf-8") || (::soap_serialize_SOAP_ENV__Fault(soap, p), 0) || ::soap_put_SOAP_ENV__Fault(soap, p, "SOAP-ENV:Fault", "") || soap_end_send(soap) || soap_recv_empty_response(soap)) + return soap_closesock(soap); + return SOAP_OK; +} + +inline int soap_PATCH_SOAP_ENV__Fault(struct soap *soap, const char *URL, struct SOAP_ENV__Fault const*p) +{ + soap_free_temp(soap); + if (soap_PATCH(soap, URL, NULL, "text/xml; charset=utf-8") || (::soap_serialize_SOAP_ENV__Fault(soap, p), 0) || ::soap_put_SOAP_ENV__Fault(soap, p, "SOAP-ENV:Fault", "") || soap_end_send(soap) || soap_recv_empty_response(soap)) + return soap_closesock(soap); + return SOAP_OK; +} + +inline int soap_POST_send_SOAP_ENV__Fault(struct soap *soap, const char *URL, struct SOAP_ENV__Fault const*p) +{ + soap_free_temp(soap); + if (soap_POST(soap, URL, NULL, "text/xml; charset=utf-8") || (::soap_serialize_SOAP_ENV__Fault(soap, p), 0) || ::soap_put_SOAP_ENV__Fault(soap, p, "SOAP-ENV:Fault", "") || soap_end_send(soap)) + return soap_closesock(soap); + return SOAP_OK; +} +SOAP_FMAC3 struct SOAP_ENV__Fault * SOAP_FMAC4 soap_get_SOAP_ENV__Fault(struct soap*, struct SOAP_ENV__Fault *, const char*, const char*); + +inline int soap_read_SOAP_ENV__Fault(struct soap *soap, struct SOAP_ENV__Fault *p) +{ + if (p) + { ::soap_default_SOAP_ENV__Fault(soap, p); + if (soap_begin_recv(soap) || ::soap_get_SOAP_ENV__Fault(soap, p, NULL, NULL) == NULL || soap_end_recv(soap)) + return soap->error; + } + return SOAP_OK; +} + +inline int soap_GET_SOAP_ENV__Fault(struct soap *soap, const char *URL, struct SOAP_ENV__Fault *p) +{ + if (soap_GET(soap, URL, NULL) || ::soap_read_SOAP_ENV__Fault(soap, p)) + return soap_closesock(soap); + return soap_closesock(soap); +} + +inline int soap_POST_recv_SOAP_ENV__Fault(struct soap *soap, struct SOAP_ENV__Fault *p) +{ + if (::soap_read_SOAP_ENV__Fault(soap, p)) + return soap_closesock(soap); + return soap_closesock(soap); +} +#endif #endif #ifndef WITH_NOGLOBAL -#ifndef SOAP_TYPE_SOAP_ENV__Reason -#define SOAP_TYPE_SOAP_ENV__Reason (17) -#endif +#ifndef SOAP_TYPE_SOAP_ENV__Reason_DEFINED +#define SOAP_TYPE_SOAP_ENV__Reason_DEFINED SOAP_FMAC3 void SOAP_FMAC4 soap_default_SOAP_ENV__Reason(struct soap*, struct SOAP_ENV__Reason *); SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_SOAP_ENV__Reason(struct soap*, const struct SOAP_ENV__Reason *); -SOAP_FMAC3 int SOAP_FMAC4 soap_put_SOAP_ENV__Reason(struct soap*, const struct SOAP_ENV__Reason *, const char*, const char*); SOAP_FMAC3 int SOAP_FMAC4 soap_out_SOAP_ENV__Reason(struct soap*, const char*, int, const struct SOAP_ENV__Reason *, const char*); -SOAP_FMAC3 struct SOAP_ENV__Reason * SOAP_FMAC4 soap_get_SOAP_ENV__Reason(struct soap*, struct SOAP_ENV__Reason *, const char*, const char*); SOAP_FMAC3 struct SOAP_ENV__Reason * SOAP_FMAC4 soap_in_SOAP_ENV__Reason(struct soap*, const char*, struct SOAP_ENV__Reason *, const char*); -SOAP_FMAC5 struct SOAP_ENV__Reason * SOAP_FMAC6 soap_new_SOAP_ENV__Reason(struct soap*, int); -SOAP_FMAC5 void SOAP_FMAC6 soap_delete_SOAP_ENV__Reason(struct soap*, struct SOAP_ENV__Reason*); -SOAP_FMAC3 struct SOAP_ENV__Reason * SOAP_FMAC4 soap_instantiate_SOAP_ENV__Reason(struct soap*, int, const char*, const char*, size_t*); -SOAP_FMAC3 void SOAP_FMAC4 soap_copy_SOAP_ENV__Reason(struct soap*, int, int, void*, size_t, const void*, size_t); +SOAP_FMAC1 struct SOAP_ENV__Reason * SOAP_FMAC2 soap_instantiate_SOAP_ENV__Reason(struct soap*, int, const char*, const char*, size_t*); + +inline struct SOAP_ENV__Reason * soap_new_SOAP_ENV__Reason(struct soap *soap, int n = -1) +{ + return soap_instantiate_SOAP_ENV__Reason(soap, n, NULL, NULL, NULL); +} + +inline struct SOAP_ENV__Reason * soap_new_req_SOAP_ENV__Reason( + struct soap *soap) +{ + struct SOAP_ENV__Reason *_p = ::soap_new_SOAP_ENV__Reason(soap); + if (_p) + { ::soap_default_SOAP_ENV__Reason(soap, _p); + } + return _p; +} + +inline struct SOAP_ENV__Reason * soap_new_set_SOAP_ENV__Reason( + struct soap *soap, + char *SOAP_ENV__Text) +{ + struct SOAP_ENV__Reason *_p = ::soap_new_SOAP_ENV__Reason(soap); + if (_p) + { ::soap_default_SOAP_ENV__Reason(soap, _p); + _p->SOAP_ENV__Text = SOAP_ENV__Text; + } + return _p; +} +SOAP_FMAC3 int SOAP_FMAC4 soap_put_SOAP_ENV__Reason(struct soap*, const struct SOAP_ENV__Reason *, const char*, const char*); + +inline int soap_write_SOAP_ENV__Reason(struct soap *soap, struct SOAP_ENV__Reason const*p) +{ + soap_free_temp(soap); + if (soap_begin_send(soap) || (::soap_serialize_SOAP_ENV__Reason(soap, p), 0) || ::soap_put_SOAP_ENV__Reason(soap, p, "SOAP-ENV:Reason", "") || soap_end_send(soap)) + return soap->error; + return SOAP_OK; +} + +inline int soap_PUT_SOAP_ENV__Reason(struct soap *soap, const char *URL, struct SOAP_ENV__Reason const*p) +{ + soap_free_temp(soap); + if (soap_PUT(soap, URL, NULL, "text/xml; charset=utf-8") || (::soap_serialize_SOAP_ENV__Reason(soap, p), 0) || ::soap_put_SOAP_ENV__Reason(soap, p, "SOAP-ENV:Reason", "") || soap_end_send(soap) || soap_recv_empty_response(soap)) + return soap_closesock(soap); + return SOAP_OK; +} + +inline int soap_PATCH_SOAP_ENV__Reason(struct soap *soap, const char *URL, struct SOAP_ENV__Reason const*p) +{ + soap_free_temp(soap); + if (soap_PATCH(soap, URL, NULL, "text/xml; charset=utf-8") || (::soap_serialize_SOAP_ENV__Reason(soap, p), 0) || ::soap_put_SOAP_ENV__Reason(soap, p, "SOAP-ENV:Reason", "") || soap_end_send(soap) || soap_recv_empty_response(soap)) + return soap_closesock(soap); + return SOAP_OK; +} + +inline int soap_POST_send_SOAP_ENV__Reason(struct soap *soap, const char *URL, struct SOAP_ENV__Reason const*p) +{ + soap_free_temp(soap); + if (soap_POST(soap, URL, NULL, "text/xml; charset=utf-8") || (::soap_serialize_SOAP_ENV__Reason(soap, p), 0) || ::soap_put_SOAP_ENV__Reason(soap, p, "SOAP-ENV:Reason", "") || soap_end_send(soap)) + return soap_closesock(soap); + return SOAP_OK; +} +SOAP_FMAC3 struct SOAP_ENV__Reason * SOAP_FMAC4 soap_get_SOAP_ENV__Reason(struct soap*, struct SOAP_ENV__Reason *, const char*, const char*); + +inline int soap_read_SOAP_ENV__Reason(struct soap *soap, struct SOAP_ENV__Reason *p) +{ + if (p) + { ::soap_default_SOAP_ENV__Reason(soap, p); + if (soap_begin_recv(soap) || ::soap_get_SOAP_ENV__Reason(soap, p, NULL, NULL) == NULL || soap_end_recv(soap)) + return soap->error; + } + return SOAP_OK; +} + +inline int soap_GET_SOAP_ENV__Reason(struct soap *soap, const char *URL, struct SOAP_ENV__Reason *p) +{ + if (soap_GET(soap, URL, NULL) || ::soap_read_SOAP_ENV__Reason(soap, p)) + return soap_closesock(soap); + return soap_closesock(soap); +} + +inline int soap_POST_recv_SOAP_ENV__Reason(struct soap *soap, struct SOAP_ENV__Reason *p) +{ + if (::soap_read_SOAP_ENV__Reason(soap, p)) + return soap_closesock(soap); + return soap_closesock(soap); +} +#endif #endif #ifndef WITH_NOGLOBAL -#ifndef SOAP_TYPE_SOAP_ENV__Detail -#define SOAP_TYPE_SOAP_ENV__Detail (14) -#endif +#ifndef SOAP_TYPE_SOAP_ENV__Detail_DEFINED +#define SOAP_TYPE_SOAP_ENV__Detail_DEFINED SOAP_FMAC3 void SOAP_FMAC4 soap_default_SOAP_ENV__Detail(struct soap*, struct SOAP_ENV__Detail *); SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_SOAP_ENV__Detail(struct soap*, const struct SOAP_ENV__Detail *); -SOAP_FMAC3 int SOAP_FMAC4 soap_put_SOAP_ENV__Detail(struct soap*, const struct SOAP_ENV__Detail *, const char*, const char*); SOAP_FMAC3 int SOAP_FMAC4 soap_out_SOAP_ENV__Detail(struct soap*, const char*, int, const struct SOAP_ENV__Detail *, const char*); -SOAP_FMAC3 struct SOAP_ENV__Detail * SOAP_FMAC4 soap_get_SOAP_ENV__Detail(struct soap*, struct SOAP_ENV__Detail *, const char*, const char*); SOAP_FMAC3 struct SOAP_ENV__Detail * SOAP_FMAC4 soap_in_SOAP_ENV__Detail(struct soap*, const char*, struct SOAP_ENV__Detail *, const char*); -SOAP_FMAC5 struct SOAP_ENV__Detail * SOAP_FMAC6 soap_new_SOAP_ENV__Detail(struct soap*, int); -SOAP_FMAC5 void SOAP_FMAC6 soap_delete_SOAP_ENV__Detail(struct soap*, struct SOAP_ENV__Detail*); -SOAP_FMAC3 struct SOAP_ENV__Detail * SOAP_FMAC4 soap_instantiate_SOAP_ENV__Detail(struct soap*, int, const char*, const char*, size_t*); -SOAP_FMAC3 void SOAP_FMAC4 soap_copy_SOAP_ENV__Detail(struct soap*, int, int, void*, size_t, const void*, size_t); +SOAP_FMAC1 struct SOAP_ENV__Detail * SOAP_FMAC2 soap_instantiate_SOAP_ENV__Detail(struct soap*, int, const char*, const char*, size_t*); + +inline struct SOAP_ENV__Detail * soap_new_SOAP_ENV__Detail(struct soap *soap, int n = -1) +{ + return soap_instantiate_SOAP_ENV__Detail(soap, n, NULL, NULL, NULL); +} + +inline struct SOAP_ENV__Detail * soap_new_req_SOAP_ENV__Detail( + struct soap *soap, + int __type, + void *fault) +{ + struct SOAP_ENV__Detail *_p = ::soap_new_SOAP_ENV__Detail(soap); + if (_p) + { ::soap_default_SOAP_ENV__Detail(soap, _p); + _p->__type = __type; + _p->fault = fault; + } + return _p; +} + +inline struct SOAP_ENV__Detail * soap_new_set_SOAP_ENV__Detail( + struct soap *soap, + char *__any, + int __type, + void *fault) +{ + struct SOAP_ENV__Detail *_p = ::soap_new_SOAP_ENV__Detail(soap); + if (_p) + { ::soap_default_SOAP_ENV__Detail(soap, _p); + _p->__any = __any; + _p->__type = __type; + _p->fault = fault; + } + return _p; +} +SOAP_FMAC3 int SOAP_FMAC4 soap_put_SOAP_ENV__Detail(struct soap*, const struct SOAP_ENV__Detail *, const char*, const char*); + +inline int soap_write_SOAP_ENV__Detail(struct soap *soap, struct SOAP_ENV__Detail const*p) +{ + soap_free_temp(soap); + if (soap_begin_send(soap) || (::soap_serialize_SOAP_ENV__Detail(soap, p), 0) || ::soap_put_SOAP_ENV__Detail(soap, p, "SOAP-ENV:Detail", "") || soap_end_send(soap)) + return soap->error; + return SOAP_OK; +} + +inline int soap_PUT_SOAP_ENV__Detail(struct soap *soap, const char *URL, struct SOAP_ENV__Detail const*p) +{ + soap_free_temp(soap); + if (soap_PUT(soap, URL, NULL, "text/xml; charset=utf-8") || (::soap_serialize_SOAP_ENV__Detail(soap, p), 0) || ::soap_put_SOAP_ENV__Detail(soap, p, "SOAP-ENV:Detail", "") || soap_end_send(soap) || soap_recv_empty_response(soap)) + return soap_closesock(soap); + return SOAP_OK; +} + +inline int soap_PATCH_SOAP_ENV__Detail(struct soap *soap, const char *URL, struct SOAP_ENV__Detail const*p) +{ + soap_free_temp(soap); + if (soap_PATCH(soap, URL, NULL, "text/xml; charset=utf-8") || (::soap_serialize_SOAP_ENV__Detail(soap, p), 0) || ::soap_put_SOAP_ENV__Detail(soap, p, "SOAP-ENV:Detail", "") || soap_end_send(soap) || soap_recv_empty_response(soap)) + return soap_closesock(soap); + return SOAP_OK; +} + +inline int soap_POST_send_SOAP_ENV__Detail(struct soap *soap, const char *URL, struct SOAP_ENV__Detail const*p) +{ + soap_free_temp(soap); + if (soap_POST(soap, URL, NULL, "text/xml; charset=utf-8") || (::soap_serialize_SOAP_ENV__Detail(soap, p), 0) || ::soap_put_SOAP_ENV__Detail(soap, p, "SOAP-ENV:Detail", "") || soap_end_send(soap)) + return soap_closesock(soap); + return SOAP_OK; +} +SOAP_FMAC3 struct SOAP_ENV__Detail * SOAP_FMAC4 soap_get_SOAP_ENV__Detail(struct soap*, struct SOAP_ENV__Detail *, const char*, const char*); + +inline int soap_read_SOAP_ENV__Detail(struct soap *soap, struct SOAP_ENV__Detail *p) +{ + if (p) + { ::soap_default_SOAP_ENV__Detail(soap, p); + if (soap_begin_recv(soap) || ::soap_get_SOAP_ENV__Detail(soap, p, NULL, NULL) == NULL || soap_end_recv(soap)) + return soap->error; + } + return SOAP_OK; +} + +inline int soap_GET_SOAP_ENV__Detail(struct soap *soap, const char *URL, struct SOAP_ENV__Detail *p) +{ + if (soap_GET(soap, URL, NULL) || ::soap_read_SOAP_ENV__Detail(soap, p)) + return soap_closesock(soap); + return soap_closesock(soap); +} + +inline int soap_POST_recv_SOAP_ENV__Detail(struct soap *soap, struct SOAP_ENV__Detail *p) +{ + if (::soap_read_SOAP_ENV__Detail(soap, p)) + return soap_closesock(soap); + return soap_closesock(soap); +} +#endif #endif #ifndef WITH_NOGLOBAL -#ifndef SOAP_TYPE_SOAP_ENV__Code -#define SOAP_TYPE_SOAP_ENV__Code (12) -#endif +#ifndef SOAP_TYPE_SOAP_ENV__Code_DEFINED +#define SOAP_TYPE_SOAP_ENV__Code_DEFINED SOAP_FMAC3 void SOAP_FMAC4 soap_default_SOAP_ENV__Code(struct soap*, struct SOAP_ENV__Code *); SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_SOAP_ENV__Code(struct soap*, const struct SOAP_ENV__Code *); -SOAP_FMAC3 int SOAP_FMAC4 soap_put_SOAP_ENV__Code(struct soap*, const struct SOAP_ENV__Code *, const char*, const char*); SOAP_FMAC3 int SOAP_FMAC4 soap_out_SOAP_ENV__Code(struct soap*, const char*, int, const struct SOAP_ENV__Code *, const char*); -SOAP_FMAC3 struct SOAP_ENV__Code * SOAP_FMAC4 soap_get_SOAP_ENV__Code(struct soap*, struct SOAP_ENV__Code *, const char*, const char*); SOAP_FMAC3 struct SOAP_ENV__Code * SOAP_FMAC4 soap_in_SOAP_ENV__Code(struct soap*, const char*, struct SOAP_ENV__Code *, const char*); -SOAP_FMAC5 struct SOAP_ENV__Code * SOAP_FMAC6 soap_new_SOAP_ENV__Code(struct soap*, int); -SOAP_FMAC5 void SOAP_FMAC6 soap_delete_SOAP_ENV__Code(struct soap*, struct SOAP_ENV__Code*); -SOAP_FMAC3 struct SOAP_ENV__Code * SOAP_FMAC4 soap_instantiate_SOAP_ENV__Code(struct soap*, int, const char*, const char*, size_t*); -SOAP_FMAC3 void SOAP_FMAC4 soap_copy_SOAP_ENV__Code(struct soap*, int, int, void*, size_t, const void*, size_t); +SOAP_FMAC1 struct SOAP_ENV__Code * SOAP_FMAC2 soap_instantiate_SOAP_ENV__Code(struct soap*, int, const char*, const char*, size_t*); + +inline struct SOAP_ENV__Code * soap_new_SOAP_ENV__Code(struct soap *soap, int n = -1) +{ + return soap_instantiate_SOAP_ENV__Code(soap, n, NULL, NULL, NULL); +} + +inline struct SOAP_ENV__Code * soap_new_req_SOAP_ENV__Code( + struct soap *soap) +{ + struct SOAP_ENV__Code *_p = ::soap_new_SOAP_ENV__Code(soap); + if (_p) + { ::soap_default_SOAP_ENV__Code(soap, _p); + } + return _p; +} + +inline struct SOAP_ENV__Code * soap_new_set_SOAP_ENV__Code( + struct soap *soap, + char *SOAP_ENV__Value, + struct SOAP_ENV__Code *SOAP_ENV__Subcode) +{ + struct SOAP_ENV__Code *_p = ::soap_new_SOAP_ENV__Code(soap); + if (_p) + { ::soap_default_SOAP_ENV__Code(soap, _p); + _p->SOAP_ENV__Value = SOAP_ENV__Value; + _p->SOAP_ENV__Subcode = SOAP_ENV__Subcode; + } + return _p; +} +SOAP_FMAC3 int SOAP_FMAC4 soap_put_SOAP_ENV__Code(struct soap*, const struct SOAP_ENV__Code *, const char*, const char*); + +inline int soap_write_SOAP_ENV__Code(struct soap *soap, struct SOAP_ENV__Code const*p) +{ + soap_free_temp(soap); + if (soap_begin_send(soap) || (::soap_serialize_SOAP_ENV__Code(soap, p), 0) || ::soap_put_SOAP_ENV__Code(soap, p, "SOAP-ENV:Code", "") || soap_end_send(soap)) + return soap->error; + return SOAP_OK; +} + +inline int soap_PUT_SOAP_ENV__Code(struct soap *soap, const char *URL, struct SOAP_ENV__Code const*p) +{ + soap_free_temp(soap); + if (soap_PUT(soap, URL, NULL, "text/xml; charset=utf-8") || (::soap_serialize_SOAP_ENV__Code(soap, p), 0) || ::soap_put_SOAP_ENV__Code(soap, p, "SOAP-ENV:Code", "") || soap_end_send(soap) || soap_recv_empty_response(soap)) + return soap_closesock(soap); + return SOAP_OK; +} + +inline int soap_PATCH_SOAP_ENV__Code(struct soap *soap, const char *URL, struct SOAP_ENV__Code const*p) +{ + soap_free_temp(soap); + if (soap_PATCH(soap, URL, NULL, "text/xml; charset=utf-8") || (::soap_serialize_SOAP_ENV__Code(soap, p), 0) || ::soap_put_SOAP_ENV__Code(soap, p, "SOAP-ENV:Code", "") || soap_end_send(soap) || soap_recv_empty_response(soap)) + return soap_closesock(soap); + return SOAP_OK; +} + +inline int soap_POST_send_SOAP_ENV__Code(struct soap *soap, const char *URL, struct SOAP_ENV__Code const*p) +{ + soap_free_temp(soap); + if (soap_POST(soap, URL, NULL, "text/xml; charset=utf-8") || (::soap_serialize_SOAP_ENV__Code(soap, p), 0) || ::soap_put_SOAP_ENV__Code(soap, p, "SOAP-ENV:Code", "") || soap_end_send(soap)) + return soap_closesock(soap); + return SOAP_OK; +} +SOAP_FMAC3 struct SOAP_ENV__Code * SOAP_FMAC4 soap_get_SOAP_ENV__Code(struct soap*, struct SOAP_ENV__Code *, const char*, const char*); + +inline int soap_read_SOAP_ENV__Code(struct soap *soap, struct SOAP_ENV__Code *p) +{ + if (p) + { ::soap_default_SOAP_ENV__Code(soap, p); + if (soap_begin_recv(soap) || ::soap_get_SOAP_ENV__Code(soap, p, NULL, NULL) == NULL || soap_end_recv(soap)) + return soap->error; + } + return SOAP_OK; +} + +inline int soap_GET_SOAP_ENV__Code(struct soap *soap, const char *URL, struct SOAP_ENV__Code *p) +{ + if (soap_GET(soap, URL, NULL) || ::soap_read_SOAP_ENV__Code(soap, p)) + return soap_closesock(soap); + return soap_closesock(soap); +} + +inline int soap_POST_recv_SOAP_ENV__Code(struct soap *soap, struct SOAP_ENV__Code *p) +{ + if (::soap_read_SOAP_ENV__Code(soap, p)) + return soap_closesock(soap); + return soap_closesock(soap); +} +#endif #endif #ifndef WITH_NOGLOBAL -#ifndef SOAP_TYPE_SOAP_ENV__Header -#define SOAP_TYPE_SOAP_ENV__Header (11) -#endif +#ifndef SOAP_TYPE_SOAP_ENV__Header_DEFINED +#define SOAP_TYPE_SOAP_ENV__Header_DEFINED SOAP_FMAC3 void SOAP_FMAC4 soap_default_SOAP_ENV__Header(struct soap*, struct SOAP_ENV__Header *); SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_SOAP_ENV__Header(struct soap*, const struct SOAP_ENV__Header *); -SOAP_FMAC3 int SOAP_FMAC4 soap_put_SOAP_ENV__Header(struct soap*, const struct SOAP_ENV__Header *, const char*, const char*); SOAP_FMAC3 int SOAP_FMAC4 soap_out_SOAP_ENV__Header(struct soap*, const char*, int, const struct SOAP_ENV__Header *, const char*); -SOAP_FMAC3 struct SOAP_ENV__Header * SOAP_FMAC4 soap_get_SOAP_ENV__Header(struct soap*, struct SOAP_ENV__Header *, const char*, const char*); SOAP_FMAC3 struct SOAP_ENV__Header * SOAP_FMAC4 soap_in_SOAP_ENV__Header(struct soap*, const char*, struct SOAP_ENV__Header *, const char*); -SOAP_FMAC5 struct SOAP_ENV__Header * SOAP_FMAC6 soap_new_SOAP_ENV__Header(struct soap*, int); -SOAP_FMAC5 void SOAP_FMAC6 soap_delete_SOAP_ENV__Header(struct soap*, struct SOAP_ENV__Header*); -SOAP_FMAC3 struct SOAP_ENV__Header * SOAP_FMAC4 soap_instantiate_SOAP_ENV__Header(struct soap*, int, const char*, const char*, size_t*); -SOAP_FMAC3 void SOAP_FMAC4 soap_copy_SOAP_ENV__Header(struct soap*, int, int, void*, size_t, const void*, size_t); +SOAP_FMAC1 struct SOAP_ENV__Header * SOAP_FMAC2 soap_instantiate_SOAP_ENV__Header(struct soap*, int, const char*, const char*, size_t*); + +inline struct SOAP_ENV__Header * soap_new_SOAP_ENV__Header(struct soap *soap, int n = -1) +{ + return soap_instantiate_SOAP_ENV__Header(soap, n, NULL, NULL, NULL); +} + +inline struct SOAP_ENV__Header * soap_new_req_SOAP_ENV__Header( + struct soap *soap) +{ + struct SOAP_ENV__Header *_p = ::soap_new_SOAP_ENV__Header(soap); + if (_p) + { ::soap_default_SOAP_ENV__Header(soap, _p); + } + return _p; +} + +inline struct SOAP_ENV__Header * soap_new_set_SOAP_ENV__Header( + struct soap *soap) +{ + struct SOAP_ENV__Header *_p = ::soap_new_SOAP_ENV__Header(soap); + if (_p) + { ::soap_default_SOAP_ENV__Header(soap, _p); + } + return _p; +} +SOAP_FMAC3 int SOAP_FMAC4 soap_put_SOAP_ENV__Header(struct soap*, const struct SOAP_ENV__Header *, const char*, const char*); + +inline int soap_write_SOAP_ENV__Header(struct soap *soap, struct SOAP_ENV__Header const*p) +{ + soap_free_temp(soap); + if (soap_begin_send(soap) || (::soap_serialize_SOAP_ENV__Header(soap, p), 0) || ::soap_put_SOAP_ENV__Header(soap, p, "SOAP-ENV:Header", "") || soap_end_send(soap)) + return soap->error; + return SOAP_OK; +} + +inline int soap_PUT_SOAP_ENV__Header(struct soap *soap, const char *URL, struct SOAP_ENV__Header const*p) +{ + soap_free_temp(soap); + if (soap_PUT(soap, URL, NULL, "text/xml; charset=utf-8") || (::soap_serialize_SOAP_ENV__Header(soap, p), 0) || ::soap_put_SOAP_ENV__Header(soap, p, "SOAP-ENV:Header", "") || soap_end_send(soap) || soap_recv_empty_response(soap)) + return soap_closesock(soap); + return SOAP_OK; +} +inline int soap_PATCH_SOAP_ENV__Header(struct soap *soap, const char *URL, struct SOAP_ENV__Header const*p) +{ + soap_free_temp(soap); + if (soap_PATCH(soap, URL, NULL, "text/xml; charset=utf-8") || (::soap_serialize_SOAP_ENV__Header(soap, p), 0) || ::soap_put_SOAP_ENV__Header(soap, p, "SOAP-ENV:Header", "") || soap_end_send(soap) || soap_recv_empty_response(soap)) + return soap_closesock(soap); + return SOAP_OK; +} + +inline int soap_POST_send_SOAP_ENV__Header(struct soap *soap, const char *URL, struct SOAP_ENV__Header const*p) +{ + soap_free_temp(soap); + if (soap_POST(soap, URL, NULL, "text/xml; charset=utf-8") || (::soap_serialize_SOAP_ENV__Header(soap, p), 0) || ::soap_put_SOAP_ENV__Header(soap, p, "SOAP-ENV:Header", "") || soap_end_send(soap)) + return soap_closesock(soap); + return SOAP_OK; +} +SOAP_FMAC3 struct SOAP_ENV__Header * SOAP_FMAC4 soap_get_SOAP_ENV__Header(struct soap*, struct SOAP_ENV__Header *, const char*, const char*); + +inline int soap_read_SOAP_ENV__Header(struct soap *soap, struct SOAP_ENV__Header *p) +{ + if (p) + { ::soap_default_SOAP_ENV__Header(soap, p); + if (soap_begin_recv(soap) || ::soap_get_SOAP_ENV__Header(soap, p, NULL, NULL) == NULL || soap_end_recv(soap)) + return soap->error; + } + return SOAP_OK; +} + +inline int soap_GET_SOAP_ENV__Header(struct soap *soap, const char *URL, struct SOAP_ENV__Header *p) +{ + if (soap_GET(soap, URL, NULL) || ::soap_read_SOAP_ENV__Header(soap, p)) + return soap_closesock(soap); + return soap_closesock(soap); +} + +inline int soap_POST_recv_SOAP_ENV__Header(struct soap *soap, struct SOAP_ENV__Header *p) +{ + if (::soap_read_SOAP_ENV__Header(soap, p)) + return soap_closesock(soap); + return soap_closesock(soap); +} #endif -#ifndef SOAP_TYPE_ns1__executeCommand -#define SOAP_TYPE_ns1__executeCommand (10) #endif + +#ifndef SOAP_TYPE_ns1__executeCommand_DEFINED +#define SOAP_TYPE_ns1__executeCommand_DEFINED SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__executeCommand(struct soap*, struct ns1__executeCommand *); SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__executeCommand(struct soap*, const struct ns1__executeCommand *); -SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__executeCommand(struct soap*, const struct ns1__executeCommand *, const char*, const char*); SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__executeCommand(struct soap*, const char*, int, const struct ns1__executeCommand *, const char*); -SOAP_FMAC3 struct ns1__executeCommand * SOAP_FMAC4 soap_get_ns1__executeCommand(struct soap*, struct ns1__executeCommand *, const char*, const char*); SOAP_FMAC3 struct ns1__executeCommand * SOAP_FMAC4 soap_in_ns1__executeCommand(struct soap*, const char*, struct ns1__executeCommand *, const char*); -SOAP_FMAC5 struct ns1__executeCommand * SOAP_FMAC6 soap_new_ns1__executeCommand(struct soap*, int); -SOAP_FMAC5 void SOAP_FMAC6 soap_delete_ns1__executeCommand(struct soap*, struct ns1__executeCommand*); -SOAP_FMAC3 struct ns1__executeCommand * SOAP_FMAC4 soap_instantiate_ns1__executeCommand(struct soap*, int, const char*, const char*, size_t*); -SOAP_FMAC3 void SOAP_FMAC4 soap_copy_ns1__executeCommand(struct soap*, int, int, void*, size_t, const void*, size_t); +SOAP_FMAC1 struct ns1__executeCommand * SOAP_FMAC2 soap_instantiate_ns1__executeCommand(struct soap*, int, const char*, const char*, size_t*); + +inline struct ns1__executeCommand * soap_new_ns1__executeCommand(struct soap *soap, int n = -1) +{ + return soap_instantiate_ns1__executeCommand(soap, n, NULL, NULL, NULL); +} -#ifndef SOAP_TYPE_ns1__executeCommandResponse -#define SOAP_TYPE_ns1__executeCommandResponse (9) +inline struct ns1__executeCommand * soap_new_req_ns1__executeCommand( + struct soap *soap) +{ + struct ns1__executeCommand *_p = ::soap_new_ns1__executeCommand(soap); + if (_p) + { ::soap_default_ns1__executeCommand(soap, _p); + } + return _p; +} + +inline struct ns1__executeCommand * soap_new_set_ns1__executeCommand( + struct soap *soap, + char *command) +{ + struct ns1__executeCommand *_p = ::soap_new_ns1__executeCommand(soap); + if (_p) + { ::soap_default_ns1__executeCommand(soap, _p); + _p->command = command; + } + return _p; +} +SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__executeCommand(struct soap*, const struct ns1__executeCommand *, const char*, const char*); + +inline int soap_write_ns1__executeCommand(struct soap *soap, struct ns1__executeCommand const*p) +{ + soap_free_temp(soap); + if (soap_begin_send(soap) || (::soap_serialize_ns1__executeCommand(soap, p), 0) || ::soap_put_ns1__executeCommand(soap, p, "ns1:executeCommand", "") || soap_end_send(soap)) + return soap->error; + return SOAP_OK; +} + +inline int soap_PUT_ns1__executeCommand(struct soap *soap, const char *URL, struct ns1__executeCommand const*p) +{ + soap_free_temp(soap); + if (soap_PUT(soap, URL, NULL, "text/xml; charset=utf-8") || (::soap_serialize_ns1__executeCommand(soap, p), 0) || ::soap_put_ns1__executeCommand(soap, p, "ns1:executeCommand", "") || soap_end_send(soap) || soap_recv_empty_response(soap)) + return soap_closesock(soap); + return SOAP_OK; +} + +inline int soap_PATCH_ns1__executeCommand(struct soap *soap, const char *URL, struct ns1__executeCommand const*p) +{ + soap_free_temp(soap); + if (soap_PATCH(soap, URL, NULL, "text/xml; charset=utf-8") || (::soap_serialize_ns1__executeCommand(soap, p), 0) || ::soap_put_ns1__executeCommand(soap, p, "ns1:executeCommand", "") || soap_end_send(soap) || soap_recv_empty_response(soap)) + return soap_closesock(soap); + return SOAP_OK; +} + +inline int soap_POST_send_ns1__executeCommand(struct soap *soap, const char *URL, struct ns1__executeCommand const*p) +{ + soap_free_temp(soap); + if (soap_POST(soap, URL, NULL, "text/xml; charset=utf-8") || (::soap_serialize_ns1__executeCommand(soap, p), 0) || ::soap_put_ns1__executeCommand(soap, p, "ns1:executeCommand", "") || soap_end_send(soap)) + return soap_closesock(soap); + return SOAP_OK; +} +SOAP_FMAC3 struct ns1__executeCommand * SOAP_FMAC4 soap_get_ns1__executeCommand(struct soap*, struct ns1__executeCommand *, const char*, const char*); + +inline int soap_read_ns1__executeCommand(struct soap *soap, struct ns1__executeCommand *p) +{ + if (p) + { ::soap_default_ns1__executeCommand(soap, p); + if (soap_begin_recv(soap) || ::soap_get_ns1__executeCommand(soap, p, NULL, NULL) == NULL || soap_end_recv(soap)) + return soap->error; + } + return SOAP_OK; +} + +inline int soap_GET_ns1__executeCommand(struct soap *soap, const char *URL, struct ns1__executeCommand *p) +{ + if (soap_GET(soap, URL, NULL) || ::soap_read_ns1__executeCommand(soap, p)) + return soap_closesock(soap); + return soap_closesock(soap); +} + +inline int soap_POST_recv_ns1__executeCommand(struct soap *soap, struct ns1__executeCommand *p) +{ + if (::soap_read_ns1__executeCommand(soap, p)) + return soap_closesock(soap); + return soap_closesock(soap); +} #endif + +#ifndef SOAP_TYPE_ns1__executeCommandResponse_DEFINED +#define SOAP_TYPE_ns1__executeCommandResponse_DEFINED SOAP_FMAC3 void SOAP_FMAC4 soap_default_ns1__executeCommandResponse(struct soap*, struct ns1__executeCommandResponse *); SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_ns1__executeCommandResponse(struct soap*, const struct ns1__executeCommandResponse *); -SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__executeCommandResponse(struct soap*, const struct ns1__executeCommandResponse *, const char*, const char*); SOAP_FMAC3 int SOAP_FMAC4 soap_out_ns1__executeCommandResponse(struct soap*, const char*, int, const struct ns1__executeCommandResponse *, const char*); -SOAP_FMAC3 struct ns1__executeCommandResponse * SOAP_FMAC4 soap_get_ns1__executeCommandResponse(struct soap*, struct ns1__executeCommandResponse *, const char*, const char*); SOAP_FMAC3 struct ns1__executeCommandResponse * SOAP_FMAC4 soap_in_ns1__executeCommandResponse(struct soap*, const char*, struct ns1__executeCommandResponse *, const char*); -SOAP_FMAC5 struct ns1__executeCommandResponse * SOAP_FMAC6 soap_new_ns1__executeCommandResponse(struct soap*, int); -SOAP_FMAC5 void SOAP_FMAC6 soap_delete_ns1__executeCommandResponse(struct soap*, struct ns1__executeCommandResponse*); -SOAP_FMAC3 struct ns1__executeCommandResponse * SOAP_FMAC4 soap_instantiate_ns1__executeCommandResponse(struct soap*, int, const char*, const char*, size_t*); -SOAP_FMAC3 void SOAP_FMAC4 soap_copy_ns1__executeCommandResponse(struct soap*, int, int, void*, size_t, const void*, size_t); +SOAP_FMAC1 struct ns1__executeCommandResponse * SOAP_FMAC2 soap_instantiate_ns1__executeCommandResponse(struct soap*, int, const char*, const char*, size_t*); -#ifndef WITH_NOGLOBAL +inline struct ns1__executeCommandResponse * soap_new_ns1__executeCommandResponse(struct soap *soap, int n = -1) +{ + return soap_instantiate_ns1__executeCommandResponse(soap, n, NULL, NULL, NULL); +} + +inline struct ns1__executeCommandResponse * soap_new_req_ns1__executeCommandResponse( + struct soap *soap) +{ + struct ns1__executeCommandResponse *_p = ::soap_new_ns1__executeCommandResponse(soap); + if (_p) + { ::soap_default_ns1__executeCommandResponse(soap, _p); + } + return _p; +} + +inline struct ns1__executeCommandResponse * soap_new_set_ns1__executeCommandResponse( + struct soap *soap, + char **result) +{ + struct ns1__executeCommandResponse *_p = ::soap_new_ns1__executeCommandResponse(soap); + if (_p) + { ::soap_default_ns1__executeCommandResponse(soap, _p); + _p->result = result; + } + return _p; +} +SOAP_FMAC3 int SOAP_FMAC4 soap_put_ns1__executeCommandResponse(struct soap*, const struct ns1__executeCommandResponse *, const char*, const char*); + +inline int soap_write_ns1__executeCommandResponse(struct soap *soap, struct ns1__executeCommandResponse const*p) +{ + soap_free_temp(soap); + if (soap_begin_send(soap) || (::soap_serialize_ns1__executeCommandResponse(soap, p), 0) || ::soap_put_ns1__executeCommandResponse(soap, p, "ns1:executeCommandResponse", "") || soap_end_send(soap)) + return soap->error; + return SOAP_OK; +} + +inline int soap_PUT_ns1__executeCommandResponse(struct soap *soap, const char *URL, struct ns1__executeCommandResponse const*p) +{ + soap_free_temp(soap); + if (soap_PUT(soap, URL, NULL, "text/xml; charset=utf-8") || (::soap_serialize_ns1__executeCommandResponse(soap, p), 0) || ::soap_put_ns1__executeCommandResponse(soap, p, "ns1:executeCommandResponse", "") || soap_end_send(soap) || soap_recv_empty_response(soap)) + return soap_closesock(soap); + return SOAP_OK; +} + +inline int soap_PATCH_ns1__executeCommandResponse(struct soap *soap, const char *URL, struct ns1__executeCommandResponse const*p) +{ + soap_free_temp(soap); + if (soap_PATCH(soap, URL, NULL, "text/xml; charset=utf-8") || (::soap_serialize_ns1__executeCommandResponse(soap, p), 0) || ::soap_put_ns1__executeCommandResponse(soap, p, "ns1:executeCommandResponse", "") || soap_end_send(soap) || soap_recv_empty_response(soap)) + return soap_closesock(soap); + return SOAP_OK; +} + +inline int soap_POST_send_ns1__executeCommandResponse(struct soap *soap, const char *URL, struct ns1__executeCommandResponse const*p) +{ + soap_free_temp(soap); + if (soap_POST(soap, URL, NULL, "text/xml; charset=utf-8") || (::soap_serialize_ns1__executeCommandResponse(soap, p), 0) || ::soap_put_ns1__executeCommandResponse(soap, p, "ns1:executeCommandResponse", "") || soap_end_send(soap)) + return soap_closesock(soap); + return SOAP_OK; +} +SOAP_FMAC3 struct ns1__executeCommandResponse * SOAP_FMAC4 soap_get_ns1__executeCommandResponse(struct soap*, struct ns1__executeCommandResponse *, const char*, const char*); + +inline int soap_read_ns1__executeCommandResponse(struct soap *soap, struct ns1__executeCommandResponse *p) +{ + if (p) + { ::soap_default_ns1__executeCommandResponse(soap, p); + if (soap_begin_recv(soap) || ::soap_get_ns1__executeCommandResponse(soap, p, NULL, NULL) == NULL || soap_end_recv(soap)) + return soap->error; + } + return SOAP_OK; +} + +inline int soap_GET_ns1__executeCommandResponse(struct soap *soap, const char *URL, struct ns1__executeCommandResponse *p) +{ + if (soap_GET(soap, URL, NULL) || ::soap_read_ns1__executeCommandResponse(soap, p)) + return soap_closesock(soap); + return soap_closesock(soap); +} -#ifndef SOAP_TYPE_PointerToSOAP_ENV__Reason -#define SOAP_TYPE_PointerToSOAP_ENV__Reason (20) +inline int soap_POST_recv_ns1__executeCommandResponse(struct soap *soap, struct ns1__executeCommandResponse *p) +{ + if (::soap_read_ns1__executeCommandResponse(soap, p)) + return soap_closesock(soap); + return soap_closesock(soap); +} #endif + +#ifndef WITH_NOGLOBAL + +#ifndef SOAP_TYPE_PointerToSOAP_ENV__Reason_DEFINED +#define SOAP_TYPE_PointerToSOAP_ENV__Reason_DEFINED SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_PointerToSOAP_ENV__Reason(struct soap*, struct SOAP_ENV__Reason *const*); -SOAP_FMAC3 int SOAP_FMAC4 soap_put_PointerToSOAP_ENV__Reason(struct soap*, struct SOAP_ENV__Reason *const*, const char*, const char*); SOAP_FMAC3 int SOAP_FMAC4 soap_out_PointerToSOAP_ENV__Reason(struct soap*, const char *, int, struct SOAP_ENV__Reason *const*, const char *); -SOAP_FMAC3 struct SOAP_ENV__Reason ** SOAP_FMAC4 soap_get_PointerToSOAP_ENV__Reason(struct soap*, struct SOAP_ENV__Reason **, const char*, const char*); SOAP_FMAC3 struct SOAP_ENV__Reason ** SOAP_FMAC4 soap_in_PointerToSOAP_ENV__Reason(struct soap*, const char*, struct SOAP_ENV__Reason **, const char*); +SOAP_FMAC3 int SOAP_FMAC4 soap_put_PointerToSOAP_ENV__Reason(struct soap*, struct SOAP_ENV__Reason *const*, const char*, const char*); +SOAP_FMAC3 struct SOAP_ENV__Reason ** SOAP_FMAC4 soap_get_PointerToSOAP_ENV__Reason(struct soap*, struct SOAP_ENV__Reason **, const char*, const char*); +#endif #endif #ifndef WITH_NOGLOBAL -#ifndef SOAP_TYPE_PointerToSOAP_ENV__Detail -#define SOAP_TYPE_PointerToSOAP_ENV__Detail (19) -#endif +#ifndef SOAP_TYPE_PointerToSOAP_ENV__Detail_DEFINED +#define SOAP_TYPE_PointerToSOAP_ENV__Detail_DEFINED SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_PointerToSOAP_ENV__Detail(struct soap*, struct SOAP_ENV__Detail *const*); -SOAP_FMAC3 int SOAP_FMAC4 soap_put_PointerToSOAP_ENV__Detail(struct soap*, struct SOAP_ENV__Detail *const*, const char*, const char*); SOAP_FMAC3 int SOAP_FMAC4 soap_out_PointerToSOAP_ENV__Detail(struct soap*, const char *, int, struct SOAP_ENV__Detail *const*, const char *); -SOAP_FMAC3 struct SOAP_ENV__Detail ** SOAP_FMAC4 soap_get_PointerToSOAP_ENV__Detail(struct soap*, struct SOAP_ENV__Detail **, const char*, const char*); SOAP_FMAC3 struct SOAP_ENV__Detail ** SOAP_FMAC4 soap_in_PointerToSOAP_ENV__Detail(struct soap*, const char*, struct SOAP_ENV__Detail **, const char*); +SOAP_FMAC3 int SOAP_FMAC4 soap_put_PointerToSOAP_ENV__Detail(struct soap*, struct SOAP_ENV__Detail *const*, const char*, const char*); +SOAP_FMAC3 struct SOAP_ENV__Detail ** SOAP_FMAC4 soap_get_PointerToSOAP_ENV__Detail(struct soap*, struct SOAP_ENV__Detail **, const char*, const char*); +#endif #endif #ifndef WITH_NOGLOBAL -#ifndef SOAP_TYPE_PointerToSOAP_ENV__Code -#define SOAP_TYPE_PointerToSOAP_ENV__Code (13) -#endif +#ifndef SOAP_TYPE_PointerToSOAP_ENV__Code_DEFINED +#define SOAP_TYPE_PointerToSOAP_ENV__Code_DEFINED SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_PointerToSOAP_ENV__Code(struct soap*, struct SOAP_ENV__Code *const*); -SOAP_FMAC3 int SOAP_FMAC4 soap_put_PointerToSOAP_ENV__Code(struct soap*, struct SOAP_ENV__Code *const*, const char*, const char*); SOAP_FMAC3 int SOAP_FMAC4 soap_out_PointerToSOAP_ENV__Code(struct soap*, const char *, int, struct SOAP_ENV__Code *const*, const char *); -SOAP_FMAC3 struct SOAP_ENV__Code ** SOAP_FMAC4 soap_get_PointerToSOAP_ENV__Code(struct soap*, struct SOAP_ENV__Code **, const char*, const char*); SOAP_FMAC3 struct SOAP_ENV__Code ** SOAP_FMAC4 soap_in_PointerToSOAP_ENV__Code(struct soap*, const char*, struct SOAP_ENV__Code **, const char*); - +SOAP_FMAC3 int SOAP_FMAC4 soap_put_PointerToSOAP_ENV__Code(struct soap*, struct SOAP_ENV__Code *const*, const char*, const char*); +SOAP_FMAC3 struct SOAP_ENV__Code ** SOAP_FMAC4 soap_get_PointerToSOAP_ENV__Code(struct soap*, struct SOAP_ENV__Code **, const char*, const char*); #endif -#ifndef SOAP_TYPE_PointerTostring -#define SOAP_TYPE_PointerTostring (7) #endif + +#ifndef SOAP_TYPE_PointerTostring_DEFINED +#define SOAP_TYPE_PointerTostring_DEFINED SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_PointerTostring(struct soap*, char **const*); -SOAP_FMAC3 int SOAP_FMAC4 soap_put_PointerTostring(struct soap*, char **const*, const char*, const char*); SOAP_FMAC3 int SOAP_FMAC4 soap_out_PointerTostring(struct soap*, const char *, int, char **const*, const char *); -SOAP_FMAC3 char *** SOAP_FMAC4 soap_get_PointerTostring(struct soap*, char ***, const char*, const char*); SOAP_FMAC3 char *** SOAP_FMAC4 soap_in_PointerTostring(struct soap*, const char*, char ***, const char*); +SOAP_FMAC3 int SOAP_FMAC4 soap_put_PointerTostring(struct soap*, char **const*, const char*, const char*); +SOAP_FMAC3 char *** SOAP_FMAC4 soap_get_PointerTostring(struct soap*, char ***, const char*, const char*); +#endif -#ifndef SOAP_TYPE__QName -#define SOAP_TYPE__QName (5) +#ifndef SOAP_TYPE__QName_DEFINED +#define SOAP_TYPE__QName_DEFINED + +inline void soap_default__QName(struct soap *soap, char **a) +{ + (void)soap; /* appease -Wall -Werror */ +#ifdef SOAP_DEFAULT__QName + *a = SOAP_DEFAULT__QName; +#else + *a = (char *)0; #endif -SOAP_FMAC3 void SOAP_FMAC4 soap_default__QName(struct soap*, char **); +} SOAP_FMAC3 void SOAP_FMAC4 soap_serialize__QName(struct soap*, char *const*); -SOAP_FMAC3 int SOAP_FMAC4 soap_put__QName(struct soap*, char *const*, const char*, const char*); + +#define soap__QName2s(soap, a) soap_QName2s(soap, (a)) SOAP_FMAC3 int SOAP_FMAC4 soap_out__QName(struct soap*, const char*, int, char*const*, const char*); + +#define soap_s2_QName(soap, s, a) soap_s2QName((soap), (s), (char**)(a), 0, -1, NULL) +SOAP_FMAC3 char * * SOAP_FMAC4 soap_in__QName(struct soap*, const char*, char **, const char*); + +#define soap_instantiate__QName soap_instantiate_string + + +#define soap_new__QName soap_new_string + +SOAP_FMAC3 int SOAP_FMAC4 soap_put__QName(struct soap*, char *const*, const char*, const char*); + +inline int soap_write__QName(struct soap *soap, char *const*p) +{ + soap_free_temp(soap); + if (p) + { if (soap_begin_send(soap) || ::soap_put__QName(soap, p, "QName", "") || soap_end_send(soap)) + return soap->error; + } + return SOAP_OK; +} + +inline int soap_PUT__QName(struct soap *soap, const char *URL, char *const*p) +{ + soap_free_temp(soap); + if (soap_PUT(soap, URL, NULL, "text/xml; charset=utf-8") || ::soap_put__QName(soap, p, "QName", "") || soap_end_send(soap) || soap_recv_empty_response(soap)) + return soap_closesock(soap); + return SOAP_OK; +} + +inline int soap_PATCH__QName(struct soap *soap, const char *URL, char *const*p) +{ + soap_free_temp(soap); + if (soap_PATCH(soap, URL, NULL, "text/xml; charset=utf-8") || ::soap_put__QName(soap, p, "QName", "") || soap_end_send(soap) || soap_recv_empty_response(soap)) + return soap_closesock(soap); + return SOAP_OK; +} + +inline int soap_POST_send__QName(struct soap *soap, const char *URL, char *const*p) +{ + soap_free_temp(soap); + if (soap_POST(soap, URL, NULL, "text/xml; charset=utf-8") || ::soap_put__QName(soap, p, "QName", "") || soap_end_send(soap)) + return soap_closesock(soap); + return SOAP_OK; +} SOAP_FMAC3 char ** SOAP_FMAC4 soap_get__QName(struct soap*, char **, const char*, const char*); -SOAP_FMAC3 char ** SOAP_FMAC4 soap_in__QName(struct soap*, const char*, char **, const char*); -#ifndef SOAP_TYPE_string -#define SOAP_TYPE_string (4) +inline int soap_read__QName(struct soap *soap, char **p) +{ + if (p) + { if (soap_begin_recv(soap) || ::soap_get__QName(soap, p, NULL, NULL) == NULL || soap_end_recv(soap)) + return soap->error; + } + return SOAP_OK; +} + +inline int soap_GET__QName(struct soap *soap, const char *URL, char **p) +{ + if (soap_GET(soap, URL, NULL) || ::soap_read__QName(soap, p)) + return soap_closesock(soap); + return soap_closesock(soap); +} + +inline int soap_POST_recv__QName(struct soap *soap, char **p) +{ + if (::soap_read__QName(soap, p)) + return soap_closesock(soap); + return soap_closesock(soap); +} #endif -SOAP_FMAC3 void SOAP_FMAC4 soap_default_string(struct soap*, char **); + +#ifndef SOAP_TYPE__XML_DEFINED +#define SOAP_TYPE__XML_DEFINED +#endif + +#ifndef SOAP_TYPE_string_DEFINED +#define SOAP_TYPE_string_DEFINED + +inline void soap_default_string(struct soap *soap, char **a) +{ + (void)soap; /* appease -Wall -Werror */ +#ifdef SOAP_DEFAULT_string + *a = SOAP_DEFAULT_string; +#else + *a = (char *)0; +#endif +} SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_string(struct soap*, char *const*); -SOAP_FMAC3 int SOAP_FMAC4 soap_put_string(struct soap*, char *const*, const char*, const char*); + +#define soap_string2s(soap, a) (a) SOAP_FMAC3 int SOAP_FMAC4 soap_out_string(struct soap*, const char*, int, char*const*, const char*); + +#define soap_s2string(soap, s, a) soap_s2char((soap), (s), (char**)(a), 1, 0, -1, NULL) +SOAP_FMAC3 char * * SOAP_FMAC4 soap_in_string(struct soap*, const char*, char **, const char*); + +SOAP_FMAC3 char * * SOAP_FMAC4 soap_new_string(struct soap *soap, int n = -1); +SOAP_FMAC3 int SOAP_FMAC4 soap_put_string(struct soap*, char *const*, const char*, const char*); + +inline int soap_write_string(struct soap *soap, char *const*p) +{ + soap_free_temp(soap); + if (p) + { if (soap_begin_send(soap) || ::soap_put_string(soap, p, "string", "") || soap_end_send(soap)) + return soap->error; + } + return SOAP_OK; +} + +inline int soap_PUT_string(struct soap *soap, const char *URL, char *const*p) +{ + soap_free_temp(soap); + if (soap_PUT(soap, URL, NULL, "text/xml; charset=utf-8") || ::soap_put_string(soap, p, "string", "") || soap_end_send(soap) || soap_recv_empty_response(soap)) + return soap_closesock(soap); + return SOAP_OK; +} + +inline int soap_PATCH_string(struct soap *soap, const char *URL, char *const*p) +{ + soap_free_temp(soap); + if (soap_PATCH(soap, URL, NULL, "text/xml; charset=utf-8") || ::soap_put_string(soap, p, "string", "") || soap_end_send(soap) || soap_recv_empty_response(soap)) + return soap_closesock(soap); + return SOAP_OK; +} + +inline int soap_POST_send_string(struct soap *soap, const char *URL, char *const*p) +{ + soap_free_temp(soap); + if (soap_POST(soap, URL, NULL, "text/xml; charset=utf-8") || ::soap_put_string(soap, p, "string", "") || soap_end_send(soap)) + return soap_closesock(soap); + return SOAP_OK; +} SOAP_FMAC3 char ** SOAP_FMAC4 soap_get_string(struct soap*, char **, const char*, const char*); -SOAP_FMAC3 char ** SOAP_FMAC4 soap_in_string(struct soap*, const char*, char **, const char*); + +inline int soap_read_string(struct soap *soap, char **p) +{ + if (p) + { if (soap_begin_recv(soap) || ::soap_get_string(soap, p, NULL, NULL) == NULL || soap_end_recv(soap)) + return soap->error; + } + return SOAP_OK; +} + +inline int soap_GET_string(struct soap *soap, const char *URL, char **p) +{ + if (soap_GET(soap, URL, NULL) || ::soap_read_string(soap, p)) + return soap_closesock(soap); + return soap_closesock(soap); +} + +inline int soap_POST_recv_string(struct soap *soap, char **p) +{ + if (::soap_read_string(soap, p)) + return soap_closesock(soap); + return soap_closesock(soap); +} +#endif #endif diff --git a/dep/gsoap/soapServer.cpp b/dep/gsoap/soapServer.cpp index 99c224a6cce9..1acfd7e46f6d 100644 --- a/dep/gsoap/soapServer.cpp +++ b/dep/gsoap/soapServer.cpp @@ -1,126 +1,114 @@ /* soapServer.cpp - Generated by gSOAP 2.7.10 from stub.h - Copyright(C) 2000-2008, Robert van Engelen, Genivia Inc. All Rights Reserved. - This part of the software is released under one of the following licenses: - GPL, the gSOAP public license, or Genivia's license for commercial use. -*/ -#include "soapH.h" + Generated by gSOAP 2.8.135 for gsoap.stub -SOAP_SOURCE_STAMP("@(#) soapServer.cpp ver 2.7.10 2010-02-18 18:41:56 GMT") +gSOAP XML Web services tools +Copyright (C) 2000,2024, Robert van Engelen, Genivia Inc. All Rights Reserved. +The soapcpp2 tool and its generated software are released under the GPL. +This program is released under the GPL with the additional exemption that +compiling, linking, and/or using OpenSSL is allowed. +-------------------------------------------------------------------------------- +A commercial use license is available from Genivia Inc., contact@genivia.com +-------------------------------------------------------------------------------- +*/ +#if defined(__BORLANDC__) +#pragma option push -w-8060 +#pragma option push -w-8004 +#endif +#include "soapH.h" -SOAP_FMAC5 int SOAP_FMAC6 soap_serve(struct soap *soap) +SOAP_SOURCE_STAMP("@(#) soapServer.cpp ver 2.8.135 2024-08-26 13:07:03 GMT") +extern "C" SOAP_FMAC5 int SOAP_FMAC6 soap_serve(struct soap *soap) { #ifndef WITH_FASTCGI - unsigned int k = soap->max_keep_alive; + soap->keep_alive = soap->max_keep_alive + 1; #endif - - do - { -#ifdef WITH_FASTCGI - if (FCGI_Accept() < 0) - { - soap->error = SOAP_EOF; - return soap_send_fault(soap); - } -#endif - - soap_begin(soap); - + do + { #ifndef WITH_FASTCGI - if (soap->max_keep_alive > 0 && !--k) - soap->keep_alive = 0; + if (soap->keep_alive > 0 && soap->max_keep_alive > 0) + soap->keep_alive--; #endif - - if (soap_begin_recv(soap)) - { if (soap->error < SOAP_STOP) - { + if (soap_begin_serve(soap)) + { if (soap->error >= SOAP_STOP) + continue; + return soap->error; + } + if ((soap_serve_request(soap) || (soap->fserveloop && soap->fserveloop(soap))) && soap->error && soap->error < SOAP_STOP) + { #ifdef WITH_FASTCGI - soap_send_fault(soap); + soap_send_fault(soap); #else - return soap_send_fault(soap); + return soap_send_fault(soap); #endif - } - soap_closesock(soap); - - continue; - } - - if (soap_envelope_begin_in(soap) - || soap_recv_header(soap) - || soap_body_begin_in(soap) - || soap_serve_request(soap) - || (soap->fserveloop && soap->fserveloop(soap))) - { + } #ifdef WITH_FASTCGI - soap_send_fault(soap); + soap_destroy(soap); + soap_end(soap); + } while (1); #else - return soap_send_fault(soap); + } while (soap->keep_alive); #endif - } - -#ifdef WITH_FASTCGI - soap_destroy(soap); - soap_end(soap); - } while (1); -#else - } while (soap->keep_alive); -#endif - return SOAP_OK; + return SOAP_OK; } #ifndef WITH_NOSERVEREQUEST -SOAP_FMAC5 int SOAP_FMAC6 soap_serve_request(struct soap *soap) +extern "C" SOAP_FMAC5 int SOAP_FMAC6 soap_serve_request(struct soap *soap) { - soap_peek_element(soap); - if (!soap_match_tag(soap, soap->tag, "ns1:executeCommand")) - return soap_serve_ns1__executeCommand(soap); - return soap->error = SOAP_NO_METHOD; + (void)soap_peek_element(soap); + if (!soap_match_tag(soap, soap->tag, "ns1:executeCommand")) + return soap_serve_ns1__executeCommand(soap); + return soap->error = SOAP_NO_METHOD; } #endif SOAP_FMAC5 int SOAP_FMAC6 soap_serve_ns1__executeCommand(struct soap *soap) -{ struct ns1__executeCommand soap_tmp_ns1__executeCommand; - struct ns1__executeCommandResponse soap_tmp_ns1__executeCommandResponse; - char * soap_tmp_string; - soap_default_ns1__executeCommandResponse(soap, &soap_tmp_ns1__executeCommandResponse); - soap_tmp_string = nullptr; - soap_tmp_ns1__executeCommandResponse.result = &soap_tmp_string; - soap_default_ns1__executeCommand(soap, &soap_tmp_ns1__executeCommand); - soap->encodingStyle = nullptr; - if (!soap_get_ns1__executeCommand(soap, &soap_tmp_ns1__executeCommand, "ns1:executeCommand", nullptr)) - return soap->error; - if (soap_body_end_in(soap) - || soap_envelope_end_in(soap) - || soap_end_recv(soap)) - return soap->error; - soap->error = ns1__executeCommand(soap, soap_tmp_ns1__executeCommand.command, &soap_tmp_string); - if (soap->error) - return soap->error; - soap_serializeheader(soap); - soap_serialize_ns1__executeCommandResponse(soap, &soap_tmp_ns1__executeCommandResponse); - if (soap_begin_count(soap)) - return soap->error; - if (soap->mode & SOAP_IO_LENGTH) - { if (soap_envelope_begin_out(soap) - || soap_putheader(soap) - || soap_body_begin_out(soap) - || soap_put_ns1__executeCommandResponse(soap, &soap_tmp_ns1__executeCommandResponse, "ns1:executeCommandResponse", "") - || soap_body_end_out(soap) - || soap_envelope_end_out(soap)) - return soap->error; - }; - if (soap_end_count(soap) - || soap_response(soap, SOAP_OK) - || soap_envelope_begin_out(soap) - || soap_putheader(soap) - || soap_body_begin_out(soap) - || soap_put_ns1__executeCommandResponse(soap, &soap_tmp_ns1__executeCommandResponse, "ns1:executeCommandResponse", "") - || soap_body_end_out(soap) - || soap_envelope_end_out(soap) - || soap_end_send(soap)) - return soap->error; - return soap_closesock(soap); +{ struct ns1__executeCommand soap_tmp_ns1__executeCommand; + struct ns1__executeCommandResponse soap_tmp_ns1__executeCommandResponse; + char * soap_tmp_string; + soap_default_ns1__executeCommandResponse(soap, &soap_tmp_ns1__executeCommandResponse); + soap_tmp_string = NULL; + soap_tmp_ns1__executeCommandResponse.result = &soap_tmp_string; + soap_default_ns1__executeCommand(soap, &soap_tmp_ns1__executeCommand); + if (!soap_get_ns1__executeCommand(soap, &soap_tmp_ns1__executeCommand, "ns1:executeCommand", NULL)) + return soap->error; + if (soap_body_end_in(soap) + || soap_envelope_end_in(soap) + || soap_end_recv(soap)) + return soap->error; + soap->error = ns1__executeCommand(soap, soap_tmp_ns1__executeCommand.command, soap_tmp_ns1__executeCommandResponse.result); + if (soap->error) + return soap->error; + soap->encodingStyle = NULL; /* use SOAP literal style */ + soap_serializeheader(soap); + soap_serialize_ns1__executeCommandResponse(soap, &soap_tmp_ns1__executeCommandResponse); + if (soap_begin_count(soap)) + return soap->error; + if ((soap->mode & SOAP_IO_LENGTH)) + { if (soap_envelope_begin_out(soap) + || soap_putheader(soap) + || soap_body_begin_out(soap) + || soap_put_ns1__executeCommandResponse(soap, &soap_tmp_ns1__executeCommandResponse, "ns1:executeCommandResponse", "") + || soap_body_end_out(soap) + || soap_envelope_end_out(soap)) + return soap->error; + }; + if (soap_end_count(soap) + || soap_response(soap, SOAP_OK) + || soap_envelope_begin_out(soap) + || soap_putheader(soap) + || soap_body_begin_out(soap) + || soap_put_ns1__executeCommandResponse(soap, &soap_tmp_ns1__executeCommandResponse, "ns1:executeCommandResponse", "") + || soap_body_end_out(soap) + || soap_envelope_end_out(soap) + || soap_end_send(soap)) + return soap->error; + return soap_closesock(soap); } +#if defined(__BORLANDC__) +#pragma option pop +#pragma option pop +#endif + /* End of soapServer.cpp */ diff --git a/dep/gsoap/soapStub.h b/dep/gsoap/soapStub.h index 08ee17cc5651..f17dfde52851 100644 --- a/dep/gsoap/soapStub.h +++ b/dep/gsoap/soapStub.h @@ -1,121 +1,195 @@ /* soapStub.h - Generated by gSOAP 2.7.10 from stub.h - Copyright(C) 2000-2008, Robert van Engelen, Genivia Inc. All Rights Reserved. - This part of the software is released under one of the following licenses: - GPL, the gSOAP public license, or Genivia's license for commercial use. + Generated by gSOAP 2.8.135 for gsoap.stub + +gSOAP XML Web services tools +Copyright (C) 2000,2024, Robert van Engelen, Genivia Inc. All Rights Reserved. +The soapcpp2 tool and its generated software are released under the GPL. +This program is released under the GPL with the additional exemption that +compiling, linking, and/or using OpenSSL is allowed. +-------------------------------------------------------------------------------- +A commercial use license is available from Genivia Inc., contact@genivia.com +-------------------------------------------------------------------------------- */ + #ifndef soapStub_H #define soapStub_H #include "stdsoap2.h" +#if GSOAP_VERSION != 208135 +# error "GSOAP VERSION 208135 MISMATCH IN GENERATED CODE VERSUS LIBRARY CODE: PLEASE REINSTALL PACKAGE" +#endif + /******************************************************************************\ * * - * Enumerations * + * Types with Custom Serializers * * * \******************************************************************************/ /******************************************************************************\ * * - * Classes and Structs * + * Classes, Structs and Unions * * * \******************************************************************************/ +struct ns1__executeCommandResponse; /* gsoap.stub:1 */ +struct ns1__executeCommand; /* gsoap.stub:1 */ -#if 0 /* volatile type: do not redeclare here */ - -#endif - +/* gsoap.stub:1 */ #ifndef SOAP_TYPE_ns1__executeCommandResponse #define SOAP_TYPE_ns1__executeCommandResponse (9) -/* ns1:executeCommandResponse */ -struct ns1__executeCommandResponse -{ -public: - char **result; /* SOAP 1.2 RPC return element (when namespace qualified) */ /* optional element of type xsd:string */ +/* complex XML schema type 'ns1:executeCommandResponse': */ +struct SOAP_CMAC ns1__executeCommandResponse { + public: + /** Optional element 'result' of XML schema type 'xsd:string' */ + char **result; + public: + /** Return unique type id SOAP_TYPE_ns1__executeCommandResponse */ + long soap_type() const { return SOAP_TYPE_ns1__executeCommandResponse; } + /** Constructor with member initializations */ + ns1__executeCommandResponse() : result() { } + /** Friend allocator */ + friend SOAP_FMAC1 ns1__executeCommandResponse * SOAP_FMAC2 soap_instantiate_ns1__executeCommandResponse(struct soap*, int, const char*, const char*, size_t*); }; #endif +/* gsoap.stub:1 */ #ifndef SOAP_TYPE_ns1__executeCommand #define SOAP_TYPE_ns1__executeCommand (10) -/* ns1:executeCommand */ -struct ns1__executeCommand -{ -public: - char *command; /* optional element of type xsd:string */ +/* complex XML schema type 'ns1:executeCommand': */ +struct SOAP_CMAC ns1__executeCommand { + public: + /** Optional element 'command' of XML schema type 'xsd:string' */ + char *command; + public: + /** Return unique type id SOAP_TYPE_ns1__executeCommand */ + long soap_type() const { return SOAP_TYPE_ns1__executeCommand; } + /** Constructor with member initializations */ + ns1__executeCommand() : command() { } + /** Friend allocator */ + friend SOAP_FMAC1 ns1__executeCommand * SOAP_FMAC2 soap_instantiate_ns1__executeCommand(struct soap*, int, const char*, const char*, size_t*); }; #endif +/* gsoap.stub:2 */ +#ifndef WITH_NOGLOBAL #ifndef SOAP_TYPE_SOAP_ENV__Header #define SOAP_TYPE_SOAP_ENV__Header (11) -/* SOAP Header: */ -struct SOAP_ENV__Header -{ -#ifdef WITH_NOEMPTYSTRUCT -private: - char dummy; /* dummy member to enable compilation */ -#endif +/* SOAP_ENV__Header: */ +struct SOAP_CMAC SOAP_ENV__Header { + public: + /** Return unique type id SOAP_TYPE_SOAP_ENV__Header */ + long soap_type() const { return SOAP_TYPE_SOAP_ENV__Header; } + /** Constructor with member initializations */ + SOAP_ENV__Header() { } + /** Friend allocator */ + friend SOAP_FMAC1 SOAP_ENV__Header * SOAP_FMAC2 soap_instantiate_SOAP_ENV__Header(struct soap*, int, const char*, const char*, size_t*); }; #endif +#endif +/* gsoap.stub:2 */ +#ifndef WITH_NOGLOBAL #ifndef SOAP_TYPE_SOAP_ENV__Code #define SOAP_TYPE_SOAP_ENV__Code (12) -/* SOAP Fault Code: */ -struct SOAP_ENV__Code -{ -public: - char *SOAP_ENV__Value; /* optional element of type xsd:QName */ - struct SOAP_ENV__Code *SOAP_ENV__Subcode; /* optional element of type SOAP-ENV:Code */ +/* Type SOAP_ENV__Code is a recursive data type, (in)directly referencing itself through its (base or derived class) members */ +/* SOAP_ENV__Code: */ +struct SOAP_CMAC SOAP_ENV__Code { + public: + /** Optional element 'SOAP-ENV:Value' of XML schema type 'xsd:QName' */ + char *SOAP_ENV__Value; + /** Optional element 'SOAP-ENV:Subcode' of XML schema type 'SOAP-ENV:Code' */ + struct SOAP_ENV__Code *SOAP_ENV__Subcode; + public: + /** Return unique type id SOAP_TYPE_SOAP_ENV__Code */ + long soap_type() const { return SOAP_TYPE_SOAP_ENV__Code; } + /** Constructor with member initializations */ + SOAP_ENV__Code() : SOAP_ENV__Value(), SOAP_ENV__Subcode() { } + /** Friend allocator */ + friend SOAP_FMAC1 SOAP_ENV__Code * SOAP_FMAC2 soap_instantiate_SOAP_ENV__Code(struct soap*, int, const char*, const char*, size_t*); }; #endif +#endif +/* gsoap.stub:2 */ +#ifndef WITH_NOGLOBAL #ifndef SOAP_TYPE_SOAP_ENV__Detail #define SOAP_TYPE_SOAP_ENV__Detail (14) -/* SOAP-ENV:Detail */ -struct SOAP_ENV__Detail -{ -public: - int __type; /* any type of element (defined below) */ - void *fault; /* transient */ - char *__any; +/* SOAP_ENV__Detail: */ +struct SOAP_CMAC SOAP_ENV__Detail { + public: + char *__any; + /** Any type of element 'fault' assigned to fault with its SOAP_TYPE_ assigned to __type */ + /** Do not create a cyclic data structure through this member unless SOAP encoding or SOAP_XML_GRAPH are used for id-ref serialization */ + int __type; + void *fault; + public: + /** Return unique type id SOAP_TYPE_SOAP_ENV__Detail */ + long soap_type() const { return SOAP_TYPE_SOAP_ENV__Detail; } + /** Constructor with member initializations */ + SOAP_ENV__Detail() : __any(), __type(), fault() { } + /** Friend allocator */ + friend SOAP_FMAC1 SOAP_ENV__Detail * SOAP_FMAC2 soap_instantiate_SOAP_ENV__Detail(struct soap*, int, const char*, const char*, size_t*); }; #endif +#endif +/* gsoap.stub:2 */ +#ifndef WITH_NOGLOBAL #ifndef SOAP_TYPE_SOAP_ENV__Reason #define SOAP_TYPE_SOAP_ENV__Reason (17) -/* SOAP-ENV:Reason */ -struct SOAP_ENV__Reason -{ -public: - char *SOAP_ENV__Text; /* optional element of type xsd:string */ +/* SOAP_ENV__Reason: */ +struct SOAP_CMAC SOAP_ENV__Reason { + public: + /** Optional element 'SOAP-ENV:Text' of XML schema type 'xsd:string' */ + char *SOAP_ENV__Text; + public: + /** Return unique type id SOAP_TYPE_SOAP_ENV__Reason */ + long soap_type() const { return SOAP_TYPE_SOAP_ENV__Reason; } + /** Constructor with member initializations */ + SOAP_ENV__Reason() : SOAP_ENV__Text() { } + /** Friend allocator */ + friend SOAP_FMAC1 SOAP_ENV__Reason * SOAP_FMAC2 soap_instantiate_SOAP_ENV__Reason(struct soap*, int, const char*, const char*, size_t*); }; #endif +#endif +/* gsoap.stub:2 */ +#ifndef WITH_NOGLOBAL #ifndef SOAP_TYPE_SOAP_ENV__Fault #define SOAP_TYPE_SOAP_ENV__Fault (18) -/* SOAP Fault: */ -struct SOAP_ENV__Fault -{ -public: - char *faultcode; /* optional element of type xsd:QName */ - char *faultstring; /* optional element of type xsd:string */ - char *faultactor; /* optional element of type xsd:string */ - struct SOAP_ENV__Detail *detail; /* optional element of type SOAP-ENV:Detail */ - struct SOAP_ENV__Code *SOAP_ENV__Code; /* optional element of type SOAP-ENV:Code */ - struct SOAP_ENV__Reason *SOAP_ENV__Reason; /* optional element of type SOAP-ENV:Reason */ - char *SOAP_ENV__Node; /* optional element of type xsd:string */ - char *SOAP_ENV__Role; /* optional element of type xsd:string */ - struct SOAP_ENV__Detail *SOAP_ENV__Detail; /* optional element of type SOAP-ENV:Detail */ +/* SOAP_ENV__Fault: */ +struct SOAP_CMAC SOAP_ENV__Fault { + public: + /** Optional element 'faultcode' of XML schema type 'xsd:QName' */ + char *faultcode; + /** Optional element 'faultstring' of XML schema type 'xsd:string' */ + char *faultstring; + /** Optional element 'faultactor' of XML schema type 'xsd:string' */ + char *faultactor; + /** Optional element 'detail' of XML schema type 'SOAP-ENV:Detail' */ + struct SOAP_ENV__Detail *detail; + /** Optional element 'SOAP-ENV:Code' of XML schema type 'SOAP-ENV:Code' */ + struct SOAP_ENV__Code *SOAP_ENV__Code; + /** Optional element 'SOAP-ENV:Reason' of XML schema type 'SOAP-ENV:Reason' */ + struct SOAP_ENV__Reason *SOAP_ENV__Reason; + /** Optional element 'SOAP-ENV:Node' of XML schema type 'xsd:string' */ + char *SOAP_ENV__Node; + /** Optional element 'SOAP-ENV:Role' of XML schema type 'xsd:string' */ + char *SOAP_ENV__Role; + /** Optional element 'SOAP-ENV:Detail' of XML schema type 'SOAP-ENV:Detail' */ + struct SOAP_ENV__Detail *SOAP_ENV__Detail; + public: + /** Return unique type id SOAP_TYPE_SOAP_ENV__Fault */ + long soap_type() const { return SOAP_TYPE_SOAP_ENV__Fault; } + /** Constructor with member initializations */ + SOAP_ENV__Fault() : faultcode(), faultstring(), faultactor(), detail(), SOAP_ENV__Code(), SOAP_ENV__Reason(), SOAP_ENV__Node(), SOAP_ENV__Role(), SOAP_ENV__Detail() { } + /** Friend allocator */ + friend SOAP_FMAC1 SOAP_ENV__Fault * SOAP_FMAC2 soap_instantiate_SOAP_ENV__Fault(struct soap*, int, const char*, const char*, size_t*); }; #endif - -/******************************************************************************\ - * * - * Types with Custom Serializers * - * * -\******************************************************************************/ - +#endif /******************************************************************************\ * * @@ -123,58 +197,131 @@ struct SOAP_ENV__Fault * * \******************************************************************************/ -#ifndef SOAP_TYPE__QName -#define SOAP_TYPE__QName (5) -typedef char *_QName; -#endif +/* (built-in):0 */ #ifndef SOAP_TYPE__XML -#define SOAP_TYPE__XML (6) +#define SOAP_TYPE__XML (5) typedef char *_XML; #endif +/* (built-in):0 */ +#ifndef SOAP_TYPE__QName +#define SOAP_TYPE__QName (6) +typedef char *_QName; +#endif /******************************************************************************\ * * - * Typedef Synonyms * + * Serializable Types * * * \******************************************************************************/ -/******************************************************************************\ - * * - * Externals * - * * -\******************************************************************************/ +/* char has binding name 'byte' for type 'xsd:byte' */ +#ifndef SOAP_TYPE_byte +#define SOAP_TYPE_byte (3) +#endif + +/* int has binding name 'int' for type 'xsd:int' */ +#ifndef SOAP_TYPE_int +#define SOAP_TYPE_int (1) +#endif + +/* struct SOAP_ENV__Fault has binding name 'SOAP_ENV__Fault' for type '' */ +#ifndef SOAP_TYPE_SOAP_ENV__Fault +#define SOAP_TYPE_SOAP_ENV__Fault (18) +#endif + +/* struct SOAP_ENV__Reason has binding name 'SOAP_ENV__Reason' for type '' */ +#ifndef SOAP_TYPE_SOAP_ENV__Reason +#define SOAP_TYPE_SOAP_ENV__Reason (17) +#endif + +/* struct SOAP_ENV__Detail has binding name 'SOAP_ENV__Detail' for type '' */ +#ifndef SOAP_TYPE_SOAP_ENV__Detail +#define SOAP_TYPE_SOAP_ENV__Detail (14) +#endif + +/* struct SOAP_ENV__Code has binding name 'SOAP_ENV__Code' for type '' */ +#ifndef SOAP_TYPE_SOAP_ENV__Code +#define SOAP_TYPE_SOAP_ENV__Code (12) +#endif + +/* struct SOAP_ENV__Header has binding name 'SOAP_ENV__Header' for type '' */ +#ifndef SOAP_TYPE_SOAP_ENV__Header +#define SOAP_TYPE_SOAP_ENV__Header (11) +#endif + +/* struct ns1__executeCommand has binding name 'ns1__executeCommand' for type 'ns1:executeCommand' */ +#ifndef SOAP_TYPE_ns1__executeCommand +#define SOAP_TYPE_ns1__executeCommand (10) +#endif + +/* struct ns1__executeCommandResponse has binding name 'ns1__executeCommandResponse' for type 'ns1:executeCommandResponse' */ +#ifndef SOAP_TYPE_ns1__executeCommandResponse +#define SOAP_TYPE_ns1__executeCommandResponse (9) +#endif + +/* struct SOAP_ENV__Reason * has binding name 'PointerToSOAP_ENV__Reason' for type '' */ +#ifndef SOAP_TYPE_PointerToSOAP_ENV__Reason +#define SOAP_TYPE_PointerToSOAP_ENV__Reason (20) +#endif + +/* struct SOAP_ENV__Detail * has binding name 'PointerToSOAP_ENV__Detail' for type '' */ +#ifndef SOAP_TYPE_PointerToSOAP_ENV__Detail +#define SOAP_TYPE_PointerToSOAP_ENV__Detail (19) +#endif + +/* struct SOAP_ENV__Code * has binding name 'PointerToSOAP_ENV__Code' for type '' */ +#ifndef SOAP_TYPE_PointerToSOAP_ENV__Code +#define SOAP_TYPE_PointerToSOAP_ENV__Code (13) +#endif + +/* char ** has binding name 'PointerTostring' for type 'xsd:string' */ +#ifndef SOAP_TYPE_PointerTostring +#define SOAP_TYPE_PointerTostring (7) +#endif +/* _QName has binding name '_QName' for type 'xsd:QName' */ +#ifndef SOAP_TYPE__QName +#define SOAP_TYPE__QName (6) +#endif + +/* _XML has binding name '_XML' for type '' */ +#ifndef SOAP_TYPE__XML +#define SOAP_TYPE__XML (5) +#endif + +/* char * has binding name 'string' for type 'xsd:string' */ +#ifndef SOAP_TYPE_string +#define SOAP_TYPE_string (4) +#endif /******************************************************************************\ * * - * Service Operations * + * Externals * * * \******************************************************************************/ -SOAP_FMAC5 int SOAP_FMAC6 ns1__executeCommand(struct soap*, char *command, char **result); - /******************************************************************************\ * * - * Stubs * + * Server-Side Operations * * * \******************************************************************************/ - -SOAP_FMAC5 int SOAP_FMAC6 soap_call_ns1__executeCommand(struct soap *soap, const char *soap_endpoint, const char *soap_action, char *command, char **result); + /** Web service operation 'ns1__executeCommand' implementation, should return SOAP_OK or error code */ + SOAP_FMAC5 int SOAP_FMAC6 ns1__executeCommand(struct soap*, char *command, char **result); /******************************************************************************\ * * - * Skeletons * + * Server-Side Skeletons to Invoke Service Operations * * * \******************************************************************************/ -SOAP_FMAC5 int SOAP_FMAC6 soap_serve(struct soap*); +extern "C" SOAP_FMAC5 int SOAP_FMAC6 soap_serve(struct soap*); -SOAP_FMAC5 int SOAP_FMAC6 soap_serve_request(struct soap*); +extern "C" SOAP_FMAC5 int SOAP_FMAC6 soap_serve_request(struct soap*); SOAP_FMAC5 int SOAP_FMAC6 soap_serve_ns1__executeCommand(struct soap*); diff --git a/dep/gsoap/stdsoap2.cpp b/dep/gsoap/stdsoap2.cpp index 83196586f7b5..cafbb3e69e5c 100644 --- a/dep/gsoap/stdsoap2.cpp +++ b/dep/gsoap/stdsoap2.cpp @@ -1,17 +1,18 @@ /* - stdsoap2.c[pp] 2.7.15 + stdsoap2.c[pp] 2.8.135 - gSOAP runtime engine + gSOAP runtime engine gSOAP XML Web services tools -Copyright (C) 2000-2009, Robert van Engelen, Genivia Inc., All Rights Reserved. +Copyright (C) 2000,2024, 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. +GPL or the gSOAP public license. -------------------------------------------------------------------------------- Contributors: -Wind River Systems Inc., for the following additions under gSOAP public license: - - vxWorks compatible +Wind River Systems, Inc., for the following addition licensed under the gSOAP +public license: + - vxWorks compatible, enabled with compiler option -DVXWORKS -------------------------------------------------------------------------------- gSOAP public license. @@ -24,7 +25,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-2009, Robert van Engelen, Genivia Inc., All Rights Reserved. +Copyright (C) 2000,2024, Robert van Engelen, Genivia Inc., All Rights Reserved. -------------------------------------------------------------------------------- GPL license. @@ -49,71 +50,87 @@ compiling, linking, and/or using OpenSSL is allowed. -------------------------------------------------------------------------------- A commercial use license is available from Genivia, Inc., contact@genivia.com -------------------------------------------------------------------------------- +*/ -Installation note: - -Win32 build needs winsock.dll (Visual C++ "wsock32.lib") -To do this in Visual C++ 6.0, go to "Project", "settings", select the "Link" -tab (the project file needs to be selected in the file view) and add -"wsock32.lib" to the "Object/library modules" entry - -On Mac OS X with gcc (GCC) 3.1 20020420 (prerelease) you MUST compile with --fstack_check when using -O2 because gcc 3.1 has a bug that smashes the stack -when locally allocated data exceeds 64K. +#define GSOAP_LIB_VERSION 208135 -*/ +/* silence GNU's warnings on format nonliteral strings and truncation (snprintf truncates on purpose for safety) */ +#ifdef __GNUC__ +# define GCC_VERSION_AT_LEAST(major, minor, patch) (GCC_VERSION >= (major * 10000 + minor * 100 + patch)) +# pragma GCC diagnostic ignored "-Wformat-nonliteral" +# if GCC_VERSION_AT_LEAST(7, 0, 0) +# pragma GCC diagnostic ignored "-Wformat-truncation" +# endif +#endif +/* convert EBCDIC to ASCII */ #ifdef AS400 -# pragma convert(819) /* EBCDIC to ASCII */ +# pragma convert(819) +#endif + +#if defined(__gnu_linux__) && !defined(_GNU_SOURCE) +# define _GNU_SOURCE 1 #endif #include "stdsoap2.h" +#if GSOAP_VERSION != GSOAP_LIB_VERSION +# error "GSOAP VERSION MISMATCH IN LIBRARY: PLEASE REINSTALL PACKAGE" +#endif + +#if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE) +# include /* vxWorks compatible */ +#endif + #ifdef __BORLANDC__ # pragma warn -8060 #else # ifdef WIN32 # ifdef UNDER_CE -# pragma comment(lib, "winsock.lib") +# pragma comment(lib, "ws2.lib") /* WinCE */ # else -# pragma comment(lib, "wsock32.lib") +# pragma comment(lib, "Ws2_32.lib") # endif -# pragma warning(disable : 4996) /* disable deprecation warnings */ +# pragma warning(disable : 4996) /* disable visual studio POSIX deprecation warnings */ # endif #endif #ifdef __cplusplus -SOAP_SOURCE_STAMP("@(#) stdsoap2.cpp ver 2.7.15 2009-11-07 00:00:00 GMT") +SOAP_SOURCE_STAMP("@(#) stdsoap2.cpp ver 2.8.135 2024-07-01 00:00:00 GMT") extern "C" { #else -SOAP_SOURCE_STAMP("@(#) stdsoap2.c ver 2.7.15 2009-11-07 00:00:00 GMT") +SOAP_SOURCE_STAMP("@(#) stdsoap2.c ver 2.8.135 2024-07-01 00:00:00 GMT") #endif -/* 8bit character representing unknown/nonrepresentable character data (e.g. not supported by current locale with multibyte support enabled) */ +/* 8bit character representing unknown character entity or multibyte data */ #ifndef SOAP_UNKNOWN_CHAR -#define SOAP_UNKNOWN_CHAR (127) +# define SOAP_UNKNOWN_CHAR (0x7F) +#endif + +/* unicode character representing unknown characters outside the XML 1.0 UTF8 unicode space */ +#ifdef WITH_REPLACE_ILLEGAL_UTF8 +# ifndef SOAP_UNKNOWN_UNICODE_CHAR +# define SOAP_UNKNOWN_UNICODE_CHAR (0xFFFD) +# endif #endif /* EOF=-1 */ -#define SOAP_LT (soap_wchar)(-2) /* XML character '<' */ -#define SOAP_TT (soap_wchar)(-3) /* XML character '' */ -#define SOAP_QT (soap_wchar)(-5) /* XML character '"' */ -#define SOAP_AP (soap_wchar)(-6) /* XML character ''' */ +#define SOAP_LT (soap_wchar)(-2) /* XML-specific '<' */ +#define SOAP_TT (soap_wchar)(-3) /* XML-specific '' */ +#define SOAP_QT (soap_wchar)(-5) /* XML-specific '"' */ +#define SOAP_AP (soap_wchar)(-6) /* XML-specific ''' */ -#define soap_blank(c) ((c) >= 0 && (c) <= 32) -#define soap_notblank(c) ((c) > 32) +#define soap_coblank(c) ((c)+1 > 0 && (c) <= 32) #if defined(WIN32) && !defined(UNDER_CE) -#define soap_hash_ptr(p) ((PtrToUlong(p) >> 3) & (SOAP_PTRHASH - 1)) +#define soap_hash_ptr(p) ((size_t)((PtrToUlong(p) >> 3) & (SOAP_PTRHASH - 1))) #else -#define soap_hash_ptr(p) ((size_t)(((unsigned long)(p) >> 3) & (SOAP_PTRHASH-1))) +#define soap_hash_ptr(p) ((size_t)(((unsigned long)(p) >> 3) & (SOAP_PTRHASH-1))) #endif -#ifndef PALM_1 -static void soap_init_logs(struct soap*); -#endif #ifdef SOAP_DEBUG +static void soap_init_logs(struct soap*); static void soap_close_logfile(struct soap*, int); static void soap_set_logfile(struct soap*, int, const char*); #endif @@ -124,96 +141,141 @@ static void soap_free_mht(struct soap*); static void soap_track_unlink(struct soap*, const void*); #endif -#ifndef PALM_2 static int soap_set_error(struct soap*, const char*, const char*, const char*, const char*, int); static int soap_copy_fault(struct soap*, const char*, const char*, const char*, const char*); -static int soap_getattrval(struct soap*, char*, size_t, soap_wchar); -#endif - -#ifndef PALM_1 -static void soap_free_ns(struct soap *soap); +static int soap_getattrval(struct soap*, char*, size_t*, soap_wchar); +static void soap_version(struct soap*); +static void soap_free_ns(struct soap*); static soap_wchar soap_char(struct soap*); -static soap_wchar soap_get_pi(struct soap*); +static soap_wchar soap_getpi(struct soap*); static int soap_isxdigit(int); static void *fplugin(struct soap*, const char*); -static char *soap_get_http_body(struct soap*); -static size_t soap_count_attachments(struct soap *soap); +static ULONG64 soap_count_attachments(struct soap*); static int soap_try_connect_command(struct soap*, int http_command, const char *endpoint, const char *action); +static int soap_init_send(struct soap*); + +#ifdef WITH_NTLM +static int soap_ntlm_handshake(struct soap *soap, int command, const char *endpoint, const char *host, int port); +#endif + #ifndef WITH_NOIDREF -static void soap_update_ptrs(struct soap*, char*, char*, char*, char*); static int soap_has_copies(struct soap*, const char*, const char*); +static int soap_type_punned(struct soap*, const struct soap_ilist*); +static int soap_is_shaky(struct soap*, void*); static void soap_init_iht(struct soap*); static void soap_free_iht(struct soap*); +#endif static void soap_init_pht(struct soap*); static void soap_free_pht(struct soap*); -#endif -#endif #ifndef WITH_LEAN static const char *soap_set_validation_fault(struct soap*, const char*, const char*); static int soap_isnumeric(struct soap*, const char*); -static struct soap_nlist *soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized); -static void soap_utilize_ns(struct soap *soap, const char *tag, size_t n); +static struct soap_nlist *soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized, short isearly); +static void soap_utilize_ns(struct soap *soap, const char *tag, short isearly); +static const wchar_t* soap_wstring(struct soap *soap, const char *s, int flag, long minlen, long maxlen, const char *pattern); +static wchar_t* soap_wcollapse(struct soap *soap, wchar_t *s, int flag, int insitu); #endif +static const char* soap_string(struct soap *soap, const char *s, int flag, long minlen, long maxlen, const char *pattern); +static char* soap_collapse(struct soap *soap, char *s, int flag, int insitu); +static const char* soap_QName(struct soap *soap, const char *s, long minlen, long maxlen, const char *pattern); + #ifndef WITH_LEANER -#ifndef PALM_1 -static struct soap_multipart *soap_new_multipart(struct soap*, struct soap_multipart**, struct soap_multipart**, char*, size_t); +static int soap_begin_attachments(struct soap*); +static int soap_end_attachments(struct soap *soap); +static struct soap_multipart *soap_alloc_multipart(struct soap*, struct soap_multipart**, struct soap_multipart**, const char*, size_t); static int soap_putdimefield(struct soap*, const char*, size_t); static char *soap_getdimefield(struct soap*, size_t); static void soap_select_mime_boundary(struct soap*); static int soap_valid_mime_boundary(struct soap*); static void soap_resolve_attachment(struct soap*, struct soap_multipart*); #endif -#endif #ifdef WITH_GZIP static int soap_getgziphdr(struct soap*); #endif #ifdef WITH_OPENSSL -int soap_ssl_init_done = 0; - +# ifndef SOAP_SSL_RSA_BITS +# define SOAP_SSL_RSA_BITS 2048 +# endif +static int soap_ssl_init_done = 0; static int ssl_auth_init(struct soap*); static int ssl_verify_callback(int, X509_STORE_CTX*); static int ssl_verify_callback_allow_expired_certificate(int, X509_STORE_CTX*); -static int ssl_password(char*, int, int, void *); -/* The callback below is included for future references: -static DH *ssl_tmp_dh(SSL*, int, int); -*/ +static int ssl_password(char*, int, int, void*); #endif -#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) -#ifndef PALM_1 -static const char *soap_decode(char*, size_t, const char*, const char*); +#ifdef WITH_GNUTLS +# ifndef SOAP_SSL_RSA_BITS +# define SOAP_SSL_RSA_BITS 2048 +# endif +static int soap_ssl_init_done = 0; +static int ssl_auth_init(struct soap*); +static const char *ssl_verify(struct soap *soap, const char *host); +# if GNUTLS_VERSION_NUMBER < 0x020b00 +# if defined(HAVE_PTHREAD_H) +# include + /* make GNUTLS thread safe with pthreads */ + GCRY_THREAD_OPTION_PTHREAD_IMPL; +# elif defined(HAVE_PTH_H) + #include + /* make GNUTLS thread safe with PTH */ + GCRY_THREAD_OPTION_PTH_IMPL; +# endif +# endif +#endif + +#ifdef WITH_WOLFSSL +static int soap_ssl_init_done = 0; +static int ssl_auth_init(struct soap*); +static int ssl_verify_callback(int, WOLFSSL_X509_STORE_CTX*); +static int ssl_verify_callback_allow_expired_certificate(int, WOLFSSL_X509_STORE_CTX*); +static int ssl_password(char*, int, int, void*); +#endif + +#ifdef WITH_SYSTEMSSL +static int soap_ssl_init_done = 0; +static int ssl_auth_init(struct soap*); +static int ssl_recv(int sk, void *s, int n, char *user); +static int ssl_send(int sk, void *s, int n, char *user); #endif + +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +static const char * soap_decode(char*, size_t, const char*, const char*); #endif #ifndef WITH_NOHTTP -#ifndef PALM_1 static soap_wchar soap_getchunkchar(struct soap*); static const char *http_error(struct soap*, int); static int http_get(struct soap*); -static int http_405(struct soap*); -static int http_post(struct soap*, const char*, const char*, int, const char*, const char*, size_t); +static int http_put(struct soap*); +static int http_patch(struct soap*); +static int http_del(struct soap*); +static int http_200(struct soap*); +static int http_post(struct soap*, const char*, const char*, int, const char*, const char*, ULONG64); static int http_send_header(struct soap*, const char*); static int http_post_header(struct soap*, const char*, const char*); -static int http_response(struct soap*, int, size_t); +static int http_response(struct soap*, int, ULONG64); static int http_parse(struct soap*); static int http_parse_header(struct soap*, const char*, const char*); #endif -#endif #ifndef WITH_NOIO -#ifndef PALM_1 static int fsend(struct soap*, const char*, size_t); static size_t frecv(struct soap*, char*, size_t); static int tcp_init(struct soap*); static const char *tcp_error(struct soap*); -#ifndef WITH_IPV6 + +#if !defined(WITH_IPV6) static int tcp_gethost(struct soap*, const char *addr, struct in_addr *inaddr); #endif +#if !defined(WITH_IPV6) || defined(WITH_COOKIES) +static int tcp_gethostbyname(struct soap*, const char *addr, struct hostent *hostent, struct in_addr *inaddr); +#endif + static SOAP_SOCKET tcp_connect(struct soap*, const char *endpoint, const char *host, int port); static SOAP_SOCKET tcp_accept(struct soap*, SOAP_SOCKET, struct sockaddr*, int*); static int tcp_select(struct soap*, SOAP_SOCKET, int, int); @@ -221,72 +283,78 @@ static int tcp_disconnect(struct soap*); static int tcp_closesocket(struct soap*, SOAP_SOCKET); static int tcp_shutdownsocket(struct soap*, SOAP_SOCKET, int); static const char *soap_strerror(struct soap*); -#endif #define SOAP_TCP_SELECT_RCV 0x1 #define SOAP_TCP_SELECT_SND 0x2 #define SOAP_TCP_SELECT_ERR 0x4 #define SOAP_TCP_SELECT_ALL 0x7 +#define SOAP_TCP_SELECT_PIP 0x8 #if defined(WIN32) #define SOAP_SOCKBLOCK(fd) \ - { u_long blocking = 0; \ + { \ + u_long blocking = 0; \ ioctlsocket(fd, FIONBIO, &blocking); \ } #define SOAP_SOCKNONBLOCK(fd) \ - { u_long nonblocking = 1; \ + { \ + u_long nonblocking = 1; \ ioctlsocket(fd, FIONBIO, &nonblocking); \ } #elif defined(VXWORKS) #define SOAP_SOCKBLOCK(fd) \ - { u_long blocking = 0; \ - ioctl(fd, FIONBIO, (int)(&blocking)); \ + { \ + u_long blocking = 0; \ + ioctl(fd, FIONBIO, (void*)(&blocking)); \ + } + #define SOAP_SOCKNONBLOCK(fd) \ + { \ + u_long nonblocking = 1; \ + ioctl(fd, FIONBIO, (void*)(&nonblocking)); \ + } +#elif defined(__VMS) + #define SOAP_SOCKBLOCK(fd) \ + { \ + int blocking = 0; \ + ioctl(fd, FIONBIO, &blocking); \ } #define SOAP_SOCKNONBLOCK(fd) \ - { u_long nonblocking = 1; \ - ioctl(fd, FIONBIO, (int)(&nonblocking)); \ + { \ + int nonblocking = 1; \ + ioctl(fd, FIONBIO, &nonblocking); \ } -#elif defined(PALM) - #define SOAP_SOCKBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)&~O_NONBLOCK); - #define SOAP_SOCKNONBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)|O_NONBLOCK); #elif defined(SYMBIAN) #define SOAP_SOCKBLOCK(fd) \ - { long blocking = 0; \ + { \ + long blocking = 0; \ ioctl(fd, 0/*FIONBIO*/, &blocking); \ } #define SOAP_SOCKNONBLOCK(fd) \ - { long nonblocking = 1; \ + { \ + long nonblocking = 1; \ ioctl(fd, 0/*FIONBIO*/, &nonblocking); \ } #else - #define SOAP_SOCKBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)&~O_NONBLOCK); - #define SOAP_SOCKNONBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)|O_NONBLOCK); -#endif - + #define SOAP_SOCKBLOCK(fd) (void)fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)&~O_NONBLOCK); + #define SOAP_SOCKNONBLOCK(fd) (void)fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)|O_NONBLOCK); #endif -#if defined(PALM) && !defined(PALM_2) -unsigned short errno; #endif -#ifndef PALM_1 static const char soap_env1[42] = "http://schemas.xmlsoap.org/soap/envelope/"; static const char soap_enc1[42] = "http://schemas.xmlsoap.org/soap/encoding/"; static const char soap_env2[40] = "http://www.w3.org/2003/05/soap-envelope"; static const char soap_enc2[40] = "http://www.w3.org/2003/05/soap-encoding"; static const char soap_rpc[35] = "http://www.w3.org/2003/05/soap-rpc"; -#endif -#ifndef PALM_1 -const struct soap_double_nan soap_double_nan = {0xFFFFFFFF, 0xFFFFFFFF}; -static const char soap_base64o[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -static const char soap_base64i[81] = "\76XXX\77\64\65\66\67\70\71\72\73\74\75XXXXXXX\00\01\02\03\04\05\06\07\10\11\12\13\14\15\16\17\20\21\22\23\24\25\26\27\30\31XXXXXX\32\33\34\35\36\37\40\41\42\43\44\45\46\47\50\51\52\53\54\55\56\57\60\61\62\63"; -#endif +const union soap_double_nan soap_double_nan = {{0xFFFFFFFF, 0xFFFFFFFF}}; +const char soap_base64o[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +const char soap_base64i[81] = "\76XXX\77\64\65\66\67\70\71\72\73\74\75XXXXXXX\00\01\02\03\04\05\06\07\10\11\12\13\14\15\16\17\20\21\22\23\24\25\26\27\30\31XXXXXX\32\33\34\35\36\37\40\41\42\43\44\45\46\47\50\51\52\53\54\55\56\57\60\61\62\63"; #ifndef WITH_LEAN -static const char soap_indent[11] = "\n\t\t\t\t\t\t\t\t\t"; -/* Alternative indentation form for SOAP_XML_INDENT: -static const char soap_indent[21] = "\n "; +static const char soap_indent[21] = "\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"; +/* Alternative indentation form for SOAP_XML_INDENT with spaces instead of tabs: +static const char soap_indent[41] = "\n "; */ #endif @@ -301,7 +369,8 @@ static const char soap_padding[4] = "\0\0\0"; #ifndef WITH_LEAN static const struct soap_code_map html_entity_codes[] = /* entities for XHTML parsing */ -{ { 160, "nbsp" }, +{ + { 160, "nbsp" }, { 161, "iexcl" }, { 162, "cent" }, { 163, "pound" }, @@ -428,7 +497,10 @@ static const struct soap_code_map h_error_codes[] = #ifndef WITH_NOHTTP #ifndef WITH_LEAN static const struct soap_code_map h_http_error_codes[] = -{ { 200, "OK" }, +{ + { 100, "Continue" }, + { 101, "Switching Protocols" }, + { 200, "OK" }, { 201, "Created" }, { 202, "Accepted" }, { 203, "Non-Authoritative Information" }, @@ -460,12 +532,18 @@ static const struct soap_code_map h_http_error_codes[] = { 415, "Unsupported Media Type" }, { 416, "Requested range not satisfiable" }, { 417, "Expectation Failed" }, + { 422, "Unprocessable Entity" }, + { 426, "Upgrade Required" }, + { 428, "Precondition Required" }, + { 429, "Too Many Requests" }, + { 431, "Request Header Fields Too Large" }, { 500, "Internal Server Error" }, { 501, "Not Implemented" }, { 502, "Bad Gateway" }, { 503, "Service Unavailable" }, { 504, "Gateway Time-out" }, { 505, "HTTP Version not supported" }, + { 511, "Network Authentication Required" }, { 0, NULL } }; #endif @@ -488,14 +566,15 @@ static const struct soap_code_map h_ssl_error_codes[] = #ifndef WITH_LEANER static const struct soap_code_map mime_codes[] = -{ { SOAP_MIME_7BIT, "7bit" }, - { SOAP_MIME_8BIT, "8bit" }, - { SOAP_MIME_BINARY, "binary" }, +{ + { SOAP_MIME_7BIT, "7bit" }, + { SOAP_MIME_8BIT, "8bit" }, + { SOAP_MIME_BINARY, "binary" }, { SOAP_MIME_QUOTED_PRINTABLE, "quoted-printable" }, - { SOAP_MIME_BASE64, "base64" }, - { SOAP_MIME_IETF_TOKEN, "ietf-token" }, - { SOAP_MIME_X_TOKEN, "x-token" }, - { 0, NULL } + { SOAP_MIME_BASE64, "base64" }, + { SOAP_MIME_IETF_TOKEN, "ietf-token" }, + { SOAP_MIME_X_TOKEN, "x-token" }, + { 0, NULL } }; #endif @@ -503,49 +582,111 @@ static const struct soap_code_map mime_codes[] = static int tcp_done = 0; #endif -#if defined(HP_UX) && defined(HAVE_GETHOSTBYNAME_R) +#if (defined(_AIX43) || defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R) +#ifndef h_errno extern int h_errno; #endif +#endif /******************************************************************************/ + #ifndef WITH_NOIO -#ifndef PALM_1 static int fsend(struct soap *soap, const char *s, size_t n) -{ int nwritten, err; -#if defined(__cplusplus) && !defined(WITH_LEAN) && !defined(WITH_COMPAT) +{ + int nwritten, err; + SOAP_SOCKET sk; + soap->errnum = 0; +#if defined(__cplusplus) && !defined(WITH_COMPAT) if (soap->os) - { soap->os->write(s, (std::streamsize)n); + { + soap->os->write(s, (std::streamsize)n); if (soap->os->good()) return SOAP_OK; - soap->errnum = 0; return SOAP_EOF; } #endif + sk = soap->sendsk; + if (!soap_valid_socket(sk)) + sk = soap->socket; while (n) - { if (soap_valid_socket(soap->socket)) + { + if (soap_valid_socket(sk)) { -#ifndef WITH_LEAN if (soap->send_timeout) - { for (;;) - { int r; + { + for (;;) + { + int r; +#ifdef WITH_SELF_PIPE +#ifdef WITH_OPENSSL + if (soap->ssl) + r = tcp_select(soap, sk, SOAP_TCP_SELECT_ALL | SOAP_TCP_SELECT_PIP, soap->send_timeout); + else +#endif +#ifdef WITH_GNUTLS + if (soap->session) + r = tcp_select(soap, sk, SOAP_TCP_SELECT_ALL | SOAP_TCP_SELECT_PIP, soap->send_timeout); + else +#endif +#ifdef WITH_WOLFSSL + if (soap->ssl) + r = tcp_select(soap, sk, SOAP_TCP_SELECT_ALL | SOAP_TCP_SELECT_PIP, soap->send_timeout); + else +#endif +#ifdef WITH_SYSTEMSSL + if (soap->ssl) + r = tcp_select(soap, sk, SOAP_TCP_SELECT_ALL | SOAP_TCP_SELECT_PIP, soap->send_timeout); + else +#endif + r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR | SOAP_TCP_SELECT_PIP, soap->send_timeout); + if ((r & SOAP_TCP_SELECT_PIP)) /* abort if data is pending on pipe */ + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connection closed by self pipe\n")); + return SOAP_EOF; + } +#else #ifdef WITH_OPENSSL if (soap->ssl) - r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_ALL, soap->send_timeout); + r = tcp_select(soap, sk, SOAP_TCP_SELECT_ALL, soap->send_timeout); + else +#endif +#ifdef WITH_GNUTLS + if (soap->session) + r = tcp_select(soap, sk, SOAP_TCP_SELECT_ALL, soap->send_timeout); + else +#endif +#ifdef WITH_WOLFSSL + if (soap->ssl) + r = tcp_select(soap, sk, SOAP_TCP_SELECT_ALL, soap->send_timeout); else #endif - r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->send_timeout); +#ifdef WITH_SYSTEMSSL + if (soap->ssl) + r = tcp_select(soap, sk, SOAP_TCP_SELECT_ALL, soap->send_timeout); + else +#endif + r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->send_timeout); +#endif if (r > 0) break; if (!r) return SOAP_EOF; - err = soap->errnum; - if (!err) + 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; } } +#ifndef WITH_LEAN + if (soap->transfer_timeout) + { + time_t now = time(NULL); + if ((soap->transfer_timeout > 0 && difftime(now, (time_t)soap->start) > (double)soap->transfer_timeout) + || (soap->transfer_timeout < 0 && difftime(now, (time_t)soap->start) > -1000000.0 * (double)soap->transfer_timeout)) + return SOAP_EOF; + } #endif #ifdef WITH_OPENSSL if (soap->ssl) @@ -554,73 +695,126 @@ fsend(struct soap *soap, const char *s, size_t n) nwritten = BIO_write(soap->bio, s, (int)n); else #endif +#ifdef WITH_GNUTLS + if (soap->session) + nwritten = gnutls_record_send(soap->session, s, n); + else +#endif +#ifdef WITH_WOLFSSL + if (soap->ssl) + nwritten = wolfSSL_write(soap->ssl, s, n); + else +#endif +#ifdef WITH_SYSTEMSSL + if (soap->ssl) + { + err = gsk_secure_socket_write(soap->ssl, (char*)s, n, &nwritten); + if (err != GSK_OK) + nwritten = 0; + } + else +#endif #ifndef WITH_LEAN if ((soap->omode & SOAP_IO_UDP)) - { if (soap->peerlen) - nwritten = sendto(soap->socket, (char*)s, (SOAP_WINSOCKINT)n, soap->socket_flags, (struct sockaddr*)&soap->peer, (SOAP_WINSOCKINT)soap->peerlen); + { + if (soap->peerlen) + nwritten = sendto(sk, (char*)s, (SOAP_WINSOCKINT)n, soap->socket_flags, &soap->peer.addr, (SOAP_WINSOCKINT)soap->peerlen); else - nwritten = send(soap->socket, s, (SOAP_WINSOCKINT)n, soap->socket_flags); + nwritten = send(sk, s, (SOAP_WINSOCKINT)n, soap->socket_flags); /* retry and back-off algorithm */ /* TODO: this is not very clear from specs so verify and limit conditions under which we should loop (e.g. ENOBUFS) */ if (nwritten < 0) - { int udp_repeat; + { + int udp_repeat; int udp_delay; if ((soap->connect_flags & SO_BROADCAST)) - udp_repeat = 3; /* SOAP-over-UDP MULTICAST_UDP_REPEAT - 1 */ + udp_repeat = 2; /* SOAP-over-UDP MULTICAST_UDP_REPEAT - 1 */ else udp_repeat = 1; /* SOAP-over-UDP UNICAST_UDP_REPEAT - 1 */ - udp_delay = (soap_random % 201) + 50; /* UDP_MIN_DELAY .. UDP_MAX_DELAY */ + udp_delay = ((unsigned int)soap_random % 201) + 50; /* UDP_MIN_DELAY .. UDP_MAX_DELAY */ do - { tcp_select(soap, soap->socket, SOAP_TCP_SELECT_ERR, -1000 * udp_delay); + { + tcp_select(soap, sk, SOAP_TCP_SELECT_ERR, -1000 * udp_delay); if (soap->peerlen) - nwritten = sendto(soap->socket, s, (SOAP_WINSOCKINT)n, soap->socket_flags, (struct sockaddr*)&soap->peer, (SOAP_WINSOCKINT)soap->peerlen); + nwritten = sendto(sk, (char*)s, (SOAP_WINSOCKINT)n, soap->socket_flags, &soap->peer.addr, (SOAP_WINSOCKINT)soap->peerlen); else - nwritten = send(soap->socket, s, (SOAP_WINSOCKINT)n, soap->socket_flags); + nwritten = send(sk, s, (SOAP_WINSOCKINT)n, soap->socket_flags); udp_delay <<= 1; if (udp_delay > 500) /* UDP_UPPER_DELAY */ udp_delay = 500; + } while (nwritten < 0 && udp_repeat-- > 1); + } + if (nwritten < 0) + { + err = soap_socket_errno; + if (err && err != SOAP_EINTR) + { + soap->errnum = err; + return SOAP_EOF; } - while (nwritten < 0 && --udp_repeat > 0); + nwritten = 0; /* and call write() again */ } } else #endif -#if !defined(PALM) && !defined(AS400) - nwritten = send(soap->socket, s, (int)n, soap->socket_flags); +#if !defined(AS400) + nwritten = send(sk, s, (int)n, soap->socket_flags); #else - nwritten = send(soap->socket, (void*)s, n, soap->socket_flags); + nwritten = send(sk, (void*)s, n, soap->socket_flags); #endif if (nwritten <= 0) { -#if defined(WITH_OPENSSL) || !defined(WITH_LEAN) int r = 0; -#endif - err = soap_socket_errno(soap->socket); + err = soap_socket_errno; #ifdef WITH_OPENSSL if (soap->ssl && (r = SSL_get_error(soap->ssl, nwritten)) != SSL_ERROR_NONE && r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE) - { soap->errnum = err; + { + soap->errnum = err; + return SOAP_EOF; + } +#endif +#ifdef WITH_GNUTLS + if (soap->session) + { + if (nwritten == GNUTLS_E_INTERRUPTED) + err = SOAP_EINTR; + else if (nwritten == GNUTLS_E_AGAIN) + err = SOAP_EAGAIN; + } +#endif +#ifdef WITH_WOLFSSL + if (soap->ssl && (r = wolfSSL_get_error(soap->ssl, nwritten)) != SSL_ERROR_NONE && r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE) + { + soap->errnum = err; return SOAP_EOF; } #endif if (err == SOAP_EWOULDBLOCK || err == SOAP_EAGAIN) { -#ifndef WITH_LEAN #ifdef WITH_OPENSSL if (soap->ssl && r == SSL_ERROR_WANT_READ) - r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->send_timeout ? soap->send_timeout : -10000); + r = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->send_timeout ? soap->send_timeout : -10000); else - r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->send_timeout ? soap->send_timeout : -10000); -#else - r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->send_timeout ? soap->send_timeout : -10000); #endif - if (!r && soap->send_timeout) +#ifdef WITH_GNUTLS + if (soap->session && !gnutls_record_get_direction(soap->session)) + r = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->send_timeout ? soap->send_timeout : -10000); + else +#endif +#ifdef WITH_WOLFSSL + if (soap->ssl && r == SSL_ERROR_WANT_READ) + r = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->send_timeout ? soap->send_timeout : -10000); + else +#endif + 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; -#endif } else if (err && err != SOAP_EINTR) - { soap->errnum = err; + { + soap->errnum = err; return SOAP_EOF; } nwritten = 0; /* and call write() again */ @@ -635,21 +829,18 @@ fsend(struct soap *soap, const char *s, size_t n) #ifdef UNDER_CE nwritten = fwrite(s, 1, n, soap->sendfd); #else -#ifdef VXWORKS #ifdef WMW_RPM_IO + /* vxWorks compatible */ if (soap->rpmreqid) - nwritten = (httpBlockPut(soap->rpmreqid, s, n) == 0) ? n : -1; + nwritten = (httpBlockPut(soap->rpmreqid, (char*)s, n) == 0) ? n : -1; else #endif - nwritten = fwrite(s, sizeof(char), n, fdopen(soap->sendfd, "w")); -#else #ifdef WIN32 nwritten = _write(soap->sendfd, s, (unsigned int)n); #else nwritten = write(soap->sendfd, s, (unsigned int)n); #endif #endif -#endif #endif if (nwritten <= 0) { @@ -659,7 +850,8 @@ fsend(struct soap *soap, const char *s, size_t n) err = EOF; #endif if (err && err != SOAP_EINTR && err != SOAP_EWOULDBLOCK && err != SOAP_EAGAIN) - { soap->errnum = err; + { + soap->errnum = err; return SOAP_EOF; } nwritten = 0; /* and call write() again */ @@ -671,198 +863,389 @@ fsend(struct soap *soap, const char *s, size_t n) return SOAP_OK; } #endif -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 int SOAP_FMAC2 soap_send_raw(struct soap *soap, const char *s, size_t n) -{ if (!n) +{ + if (!s || !n) return SOAP_OK; - if (soap->mode & SOAP_IO_LENGTH) - { soap->count += n; #ifndef WITH_LEANER - if (soap->fpreparesend && (soap->mode & SOAP_IO) != SOAP_IO_STORE) - return soap->error = soap->fpreparesend(soap, s, n); + if (soap->fpreparesend && (soap->mode & SOAP_IO) != SOAP_IO_STORE && (soap->mode & SOAP_IO_LENGTH) && (soap->error = soap->fpreparesend(soap, s, n)) != SOAP_OK) + return soap->error; + if (soap->ffiltersend && (soap->error = soap->ffiltersend(soap, &s, &n)) != SOAP_OK) + return soap->error; #endif - return SOAP_OK; + if ((soap->mode & SOAP_IO_LENGTH)) + { + soap->count += n; } - if (soap->mode & SOAP_IO) - { size_t i = SOAP_BUFLEN - soap->bufidx; + else if ((soap->mode & SOAP_IO)) + { + size_t i = sizeof(soap->buf) - soap->bufidx; while (n >= i) - { memcpy(soap->buf + soap->bufidx, s, i); - soap->bufidx = SOAP_BUFLEN; + { + (void)soap_memcpy((void*)(soap->buf + soap->bufidx), i, (const void*)s, i); + soap->bufidx = sizeof(soap->buf); if (soap_flush(soap)) return soap->error; s += i; n -= i; - i = SOAP_BUFLEN; + i = sizeof(soap->buf); } - memcpy(soap->buf + soap->bufidx, s, n); + (void)soap_memcpy((void*)(soap->buf + soap->bufidx), sizeof(soap->buf) - soap->bufidx, (const void*)s, n); soap->bufidx += n; - return SOAP_OK; } - return soap_flush_raw(soap, s, n); + else + { + return soap_flush_raw(soap, s, n); + } + return SOAP_OK; } -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 int SOAP_FMAC2 soap_flush(struct soap *soap) -{ size_t n = soap->bufidx; - if (n) - { soap->bufidx = 0; +{ + size_t n = soap->bufidx; + if (!n) + return soap->error = soap->fsend(soap, SOAP_STR_EOS, 0); /* force a zero send for HTTP GET and DELETE */ +#ifndef WITH_LEANER + if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) + { + int r; + if (soap->fpreparesend && (r = soap->fpreparesend(soap, soap->buf, n)) != SOAP_OK) + return soap->error = r; + } +#endif + soap->bufidx = 0; #ifdef WITH_ZLIB - if (soap->mode & SOAP_ENC_ZLIB) - { soap->d_stream->next_in = (Byte*)soap->buf; - soap->d_stream->avail_in = (unsigned int)n; + if ((soap->mode & SOAP_ENC_ZLIB) && soap->d_stream) + { + soap->d_stream->next_in = (Byte*)soap->buf; + soap->d_stream->avail_in = (unsigned int)n; #ifdef WITH_GZIP - soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)n); -#endif - do - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating %u bytes\n", soap->d_stream->avail_in)); - if (deflate(soap->d_stream, Z_NO_FLUSH) != Z_OK) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to deflate: %s\n", soap->d_stream->msg?soap->d_stream->msg:SOAP_STR_EOS)); - return soap->error = SOAP_ZLIB_ERROR; - } - if (!soap->d_stream->avail_out) - { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN)) - return soap->error; - soap->d_stream->next_out = (Byte*)soap->z_buf; - soap->d_stream->avail_out = SOAP_BUFLEN; - } - } while (soap->d_stream->avail_in); - } - else + soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)n); #endif - return soap_flush_raw(soap, soap->buf, n); + do + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating %u bytes\n", soap->d_stream->avail_in)); + if (deflate(soap->d_stream, Z_NO_FLUSH) != Z_OK) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to deflate: %s\n", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS)); + return soap->error = SOAP_ZLIB_ERROR; + } + if (!soap->d_stream->avail_out) + { + if (soap_flush_raw(soap, soap->z_buf, sizeof(soap->buf))) + return soap->error; + soap->d_stream->next_out = (Byte*)soap->z_buf; + soap->d_stream->avail_out = sizeof(soap->buf); + } + } while (soap->d_stream->avail_in); + return SOAP_OK; } - return SOAP_OK; -} #endif + return soap_flush_raw(soap, soap->buf, n); +} /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 int SOAP_FMAC2 soap_flush_raw(struct soap *soap, const char *s, size_t n) -{ if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) - { char *t; - if (!(t = (char*)soap_push_block(soap, NULL, n))) +{ + if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) + { + void *t; + t = soap_push_block(soap, NULL, n); + if (!t) return soap->error = SOAP_EOM; - memcpy(t, s, n); -#ifndef WITH_LEANER - if (soap->fpreparesend) - return soap->error = soap->fpreparesend(soap, s, n); -#endif + (void)soap_memcpy(t, n, (const void*)s, n); return SOAP_OK; } #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); + { + char t[24]; /* note: actually the value of n <= SOAP_BUFLEN, which is 65536 or smaller */ + (SOAP_SNPRINTF(t, sizeof(t), 20), &"\r\n%lX\r\n"[soap->chunksize ? 0 : 2], (unsigned long)n); DBGMSG(SENT, t, strlen(t)); - if ((soap->error = soap->fsend(soap, t, strlen(t)))) + soap->error = soap->fsend(soap, t, strlen(t)); + if (soap->error) return soap->error; soap->chunksize += n; } DBGMSG(SENT, s, n); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Send %lu bytes to socket=%d/fd=%d\n", (unsigned long)n, (int)soap->socket, soap->sendfd)); #endif return soap->error = soap->fsend(soap, s, n); } -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 int SOAP_FMAC2 soap_send(struct soap *soap, const char *s) -{ if (s) - return soap_send_raw(soap, s, strlen(s)); - return SOAP_OK; +{ + if (!s) + return SOAP_OK; + return soap_send_raw(soap, s, strlen(s)); } -#endif /******************************************************************************/ + #ifndef WITH_LEANER -#ifndef PALM_1 SOAP_FMAC1 int SOAP_FMAC2 soap_send2(struct soap *soap, const char *s1, const char *s2) -{ if (soap_send(soap, s1)) +{ + if (soap_send(soap, s1)) return soap->error; return soap_send(soap, s2); } #endif -#endif /******************************************************************************/ + #ifndef WITH_LEANER -#ifndef PALM_1 SOAP_FMAC1 int SOAP_FMAC2 soap_send3(struct soap *soap, const char *s1, const char *s2, const char *s3) -{ if (soap_send(soap, s1) +{ + if (soap_send(soap, s1) || soap_send(soap, s2)) return soap->error; return soap_send(soap, s3); } #endif -#endif /******************************************************************************/ -#ifndef WITH_NOIO -#ifndef PALM_1 -static size_t -frecv(struct soap *soap, char *s, size_t n) -{ int r; -#ifndef WITH_LEAN - int retries = 100; /* max 100 retries with non-blocking sockets */ + +#ifndef WITH_LEANER +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_query_send_key(struct soap *soap, const char *s) +{ + if (!s) + return SOAP_OK; + if (!soap->body && soap_send_raw(soap, "&", 1)) + return soap->error; + soap->body = 0; + (void)soap_encode_url(s, soap->msgbuf, (int)sizeof(soap->msgbuf)); /* msgbuf length is max SOAP_TMPLEN or just 1024 bytes */ + return soap_send(soap, soap->msgbuf); +} #endif - soap->errnum = 0; -#if defined(__cplusplus) && !defined(WITH_LEAN) && !defined(WITH_COMPAT) - if (soap->is) - { if (soap->is->good()) - return soap->is->read(s, (std::streamsize)n).gcount(); - return 0; - } + +/******************************************************************************/ + +#ifndef WITH_LEANER +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_query_send_val(struct soap *soap, const char *s) +{ + if (!s) + return SOAP_OK; + if (soap_send_raw(soap, "=", 1)) + return soap->error; + (void)soap_encode_url(s, soap->msgbuf, (int)sizeof(soap->msgbuf)); /* msgbuf length is max SOAP_TMPLEN or just 1024 bytes */ + return soap_send(soap, soap->msgbuf); +} #endif - if (soap_valid_socket(soap->socket)) - { for (;;) - { -#ifdef WITH_OPENSSL - int err = 0; + +/******************************************************************************/ + +#ifndef WITH_LEANER +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_query(struct soap *soap) +{ + return strchr(soap->path, '?'); +} #endif -#ifndef WITH_LEAN -#ifdef WITH_OPENSSL - if (soap->recv_timeout && !soap->ssl) /* SSL: sockets are nonblocking */ -#else - if (soap->recv_timeout) + +/******************************************************************************/ + +#ifndef WITH_LEANER +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_query_key(struct soap *soap, char **s) +{ + char *t = *s; + (void)soap; + if (t && *t) + { + *s = (char*)soap_query_decode(t, strlen(t), t + 1); + return t; + } + return *s = NULL; +} +#endif + +/******************************************************************************/ + +#ifndef WITH_LEANER +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_query_val(struct soap *soap, char **s) +{ + char *t = *s; + (void)soap; + if (t && *t == '=') + { + *s = (char*)soap_query_decode(t, strlen(t), t + 1); + return t; + } + return NULL; +} +#endif + +/******************************************************************************/ + +#ifndef WITH_LEANER +SOAP_FMAC1 +const char * +SOAP_FMAC2 +soap_query_decode(char *buf, size_t len, const char *val) +{ + const char *s; + char *t; + for (s = val; *s; s++) + if (*s != ' ' && *s != '=') + break; + if (*s == '"') + { + t = buf; + s++; + while (*s && *s != '"' && len-- > 1) + *t++ = *s++; + *t = '\0'; + do s++; + while (*s && *s != '&' && *s != '='); + } + else + { + t = buf; + while (*s && *s != '&' && *s != '=' && len-- > 1) + { + switch (*s) + { + case '+': + *t++ = ' '; + s++; + break; + case '\t': + case '\n': + case '\r': + case ' ': + s++; + break; + case '%': + *t++ = ((s[1] >= 'A' ? (s[1]&0x7) + 9 : s[1] - '0') << 4) + (s[2] >= 'A' ? (s[2]&0x7) + 9 : s[2] - '0'); + s += 3; + break; + default: + *t++ = *s++; + } + } + *t = '\0'; + } + return s; +} +#endif + +/******************************************************************************/ + +#ifndef WITH_NOIO +static size_t +frecv(struct soap *soap, char *s, size_t n) +{ + int r; + int retries = 100; /* max 100 retries with non-blocking sockets */ + SOAP_SOCKET sk; + soap->errnum = 0; +#if defined(__cplusplus) && !defined(WITH_COMPAT) + if (soap->is) /* recv from C++ stream */ + { + if (soap->is->good()) + return (size_t)soap->is->read(s, (std::streamsize)n).gcount(); /* downcast to std::streamsize is OK: gcount() returns how much we got in s[] */ + return 0; + } +#else + if (soap->is) /* recv from C buffer until NUL */ + { + size_t l = strlen(soap->is); + if (l > n) + l = n; + (void)soap_memcpy((void*)s, n, soap->is, l); + soap->is += l; + return l; + } +#endif + sk = soap->recvsk; + if (!soap_valid_socket(sk)) + sk = soap->socket; + if (soap_valid_socket(sk)) + { + for (;;) + { +#if defined(WITH_OPENSSL) || defined(WITH_SYSTEMSSL) + int err = 0; +#endif +#ifdef WITH_OPENSSL + if (soap->recv_timeout && !soap->ssl) /* OpenSSL: sockets are nonblocking so go ahead to read */ +#else + if (soap->recv_timeout) +#endif + { + for (;;) + { +#ifdef WITH_SELF_PIPE + r = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR | SOAP_TCP_SELECT_PIP, soap->recv_timeout); + if ((r & SOAP_TCP_SELECT_PIP)) /* abort if data is pending on pipe */ + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connection closed by self pipe\n")); + return 0; + } +#else + r = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->recv_timeout); #endif - { for (;;) - { r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->recv_timeout); if (r > 0) break; if (!r) return 0; - r = soap->errnum; - if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK) + r = soap->errnum; + if (r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK) return 0; } } +#ifndef WITH_LEAN + if (soap->transfer_timeout) + { + time_t now = time(NULL); + if ((soap->transfer_timeout > 0 && difftime(now, (time_t)soap->start) > (double)soap->transfer_timeout) + || (soap->transfer_timeout < 0 && difftime(now, (time_t)soap->start) > -1000000.0 * (double)soap->transfer_timeout)) + return 0; + } #endif #ifdef WITH_OPENSSL if (soap->ssl) - { r = SSL_read(soap->ssl, s, (int)n); + { + r = SSL_read(soap->ssl, s, (int)n); if (r > 0) return (size_t)r; err = SSL_get_error(soap->ssl, r); @@ -870,66 +1253,106 @@ frecv(struct soap *soap, char *s, size_t n) return 0; } else if (soap->bio) - { r = BIO_read(soap->bio, s, (int)n); + { + r = BIO_read(soap->bio, s, (int)n); if (r > 0) return (size_t)r; return 0; } else +#endif +#ifdef WITH_GNUTLS + if (soap->session) + { + r = (int)gnutls_record_recv(soap->session, s, n); + if (r >= 0) + return (size_t)r; + } + else +#endif +#ifdef WITH_WOLFSSL + if (soap->ssl) + { + r = wolfSSL_read(soap->ssl, s, n); + if (r >= 0) + return (size_t)r; + } + else +#endif +#ifdef WITH_SYSTEMSSL + if (soap->ssl) + { + err = gsk_secure_socket_read(soap->ssl, s, n, &r); + if (err == GSK_OK && r > 0) + return (size_t)r; + if (err != GSK_OK && err != GSK_WOULD_BLOCK && err != GSK_WOULD_BLOCK_WRITE) + return 0; + } + else #endif { #ifndef WITH_LEAN if ((soap->omode & SOAP_IO_UDP)) - { SOAP_SOCKLEN_T k = (SOAP_SOCKLEN_T)sizeof(soap->peer); + { + SOAP_SOCKLEN_T k = (SOAP_SOCKLEN_T)sizeof(soap->peer.addr); memset((void*)&soap->peer, 0, sizeof(soap->peer)); - r = recvfrom(soap->socket, s, (SOAP_WINSOCKINT)n, soap->socket_flags, (struct sockaddr*)&soap->peer, &k); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */ + r = recvfrom(sk, s, (SOAP_WINSOCKINT)n, soap->socket_flags, &soap->peer.addr, &k); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h, SOAP_WINSOCKINT cast is safe due to limited range of n in the engine (64K) */ soap->peerlen = (size_t)k; -#ifndef WITH_IPV6 - soap->ip = ntohl(soap->peer.sin_addr.s_addr); +#ifdef WITH_IPV6 + soap->ip = 0; + soap->ip6[0] = 0; + soap->ip6[1] = 0; + soap->ip6[2] = 0; + soap->ip6[3] = 0; +#else + soap->ip = ntohl(soap->peer.in.sin_addr.s_addr); + soap->ip6[0] = 0; + soap->ip6[1] = 0; + soap->ip6[2] = 0xFFFF; + soap->ip6[3] = soap->ip; #endif } else #endif - r = recv(soap->socket, s, (int)n, soap->socket_flags); -#ifdef PALM - /* CycleSyncDisplay(curStatusMsg); */ -#endif + r = recv(sk, s, (SOAP_WINSOCKINT)n, soap->socket_flags); /* SOAP_WINSOCKINT cast is safe due to limited range of n in the engine (64K) */ if (r >= 0) return (size_t)r; - r = soap_socket_errno(soap->socket); + r = soap_socket_errno; if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK) - { soap->errnum = r; + { + soap->errnum = r; return 0; } } -#ifndef WITH_LEAN - { -#ifdef WITH_OPENSSL - if (soap->ssl && err == SSL_ERROR_WANT_WRITE) - r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5); - else - r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5); -#else - r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5); +#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); + 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); + else +#ifdef WITH_WOLFSSL + 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); + else #endif - if (!r && soap->recv_timeout) - return 0; - if (r < 0) - { r = soap->errnum; - if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK) - return 0; - } - if (retries-- <= 0) - return 0; - } +#elif defined(WITH_SYSTEMSSL) + if (soap->ssl && err == GSK_WOULD_BLOCK_WRITE) + r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5); + else #endif -#ifdef PALM - r = soap_socket_errno(soap->socket); - if (r != SOAP_EINTR && retries-- <= 0) - { soap->errnum = r; + r = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5); + if (!r && soap->recv_timeout) return 0; + if (r < 0) + { + r = soap->errnum; + if (r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK) + return 0; } -#endif + if (retries-- <= 0) + return 0; } } #ifdef WITH_FASTCGI @@ -946,7 +1369,7 @@ frecv(struct soap *soap, char *s, size_t n) #ifdef WIN32 r = _read(soap->recvfd, s, (unsigned int)n); #else - r = read(soap->recvfd, s, (unsigned int)n); + r = read(soap->recvfd, s, n); #endif if (r >= 0) return (size_t)r; @@ -956,83 +1379,105 @@ frecv(struct soap *soap, char *s, size_t n) #endif } #endif -#endif /******************************************************************************/ + #ifndef WITH_NOHTTP -#ifndef PALM_1 static soap_wchar soap_getchunkchar(struct soap *soap) -{ if (soap->bufidx < soap->buflen) +{ + if (soap->bufidx < soap->buflen) return soap->buf[soap->bufidx++]; soap->bufidx = 0; - soap->buflen = soap->chunkbuflen = soap->frecv(soap, soap->buf, SOAP_BUFLEN); - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket %d\n", (unsigned int)soap->buflen, soap->socket)); + soap->buflen = soap->chunkbuflen = soap->frecv(soap, soap->buf, sizeof(soap->buf)); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket=%d/fd=%d\n", (unsigned int)soap->buflen, (int)soap->socket, soap->recvfd)); DBGMSG(RECV, soap->buf, soap->buflen); if (soap->buflen) return soap->buf[soap->bufidx++]; return EOF; } #endif -#endif /******************************************************************************/ -#ifndef PALM_1 + static int soap_isxdigit(int c) -{ return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); +{ + return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); } -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 int SOAP_FMAC2 soap_recv_raw(struct soap *soap) -{ size_t ret; +{ + size_t ret; #if !defined(WITH_LEANER) || defined(WITH_ZLIB) int r; #endif #ifdef WITH_ZLIB - if (soap->mode & SOAP_ENC_ZLIB) - { if (soap->d_stream->next_out == Z_NULL) + if ((soap->mode & SOAP_ENC_ZLIB) && soap->d_stream) + { + if (soap->d_stream->next_out == Z_NULL) + { + soap->bufidx = soap->buflen = 0; return EOF; + } if (soap->d_stream->avail_in || !soap->d_stream->avail_out) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflating\n")); + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflating\n")); soap->d_stream->next_out = (Byte*)soap->buf; - soap->d_stream->avail_out = SOAP_BUFLEN; + soap->d_stream->avail_out = sizeof(soap->buf); r = inflate(soap->d_stream, Z_NO_FLUSH); if (r == Z_NEED_DICT && soap->z_dict) - r = inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len); + r = inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len); if (r == Z_OK || r == Z_STREAM_END) - { soap->bufidx = 0; - ret = soap->buflen = SOAP_BUFLEN - soap->d_stream->avail_out; + { + soap->bufidx = 0; + ret = soap->buflen = sizeof(soap->buf) - soap->d_stream->avail_out; if (soap->zlib_in == SOAP_ZLIB_GZIP) soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)ret); if (r == Z_STREAM_END) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out)); - soap->z_ratio_in = (float)soap->d_stream->total_in / (float)soap->d_stream->total_out; + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out)); soap->d_stream->next_out = Z_NULL; } - if (ret) - { soap->count += ret; + if (ret || r == Z_STREAM_END) + { + if (soap->count + ret < soap->count) + return soap->error = SOAP_EOF; + soap->count += ret; + if (soap->recv_maxlength && soap->count > soap->recv_maxlength) + return soap->error = SOAP_EOF; + soap->z_ratio_in = (float)soap->d_stream->total_in / (float)soap->d_stream->total_out; + if (soap->count > SOAP_MAXINFLATESIZE && soap->z_ratio_in < SOAP_MINDEFLATERATIO) + { + soap->d_stream->msg = (char*)"caught SOAP_MINDEFLATERATIO explosive decompression guard (remedy: increase SOAP_MAXINFLATESIZE and/or decrease SOAP_MINDEFLATERATIO)"; + return soap->error = SOAP_ZLIB_ERROR; + } DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- decompressed ----\n")); DBGMSG(RECV, soap->buf, ret); DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n----\n")); +#ifndef WITH_LEANER + if (soap->fpreparerecv && (r = soap->fpreparerecv(soap, soap->buf, ret)) != SOAP_OK) + return soap->error = r; +#endif return SOAP_OK; } } else if (r != Z_BUF_ERROR) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate error: %s\n", soap->d_stream->msg?soap->d_stream->msg:SOAP_STR_EOS)); + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate error: %s\n", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS)); soap->d_stream->next_out = Z_NULL; - soap->error = SOAP_ZLIB_ERROR; - return EOF; + return soap->error = SOAP_ZLIB_ERROR; } } zlib_again: if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK && !soap->chunksize) - { memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN); + { + (void)soap_memcpy((void*)soap->buf, sizeof(soap->buf), (const void*)soap->z_buf, sizeof(soap->buf)); soap->buflen = soap->z_buflen; } DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- compressed ----\n")); @@ -1040,63 +1485,94 @@ soap_recv_raw(struct soap *soap) #endif #ifndef WITH_NOHTTP if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) /* read HTTP chunked transfer */ - { for (;;) - { soap_wchar c; - char *t, tmp[8]; + { + for (;;) + { + soap_wchar c; + char *t, tmp[17]; + unsigned long chunksize; if (soap->chunksize) - { soap->buflen = ret = soap->frecv(soap, soap->buf, soap->chunksize > SOAP_BUFLEN ? SOAP_BUFLEN : soap->chunksize); + { + soap->buflen = ret = soap->frecv(soap, soap->buf, soap->chunksize > sizeof(soap->buf) ? sizeof(soap->buf) : soap->chunksize); DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk: read %u bytes\n", (unsigned int)ret)); DBGMSG(RECV, soap->buf, ret); soap->bufidx = 0; + if (!ret) + { + soap->ahead = EOF; + return EOF; + } soap->chunksize -= ret; break; } - 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)); + { + soap->chunkbuflen = ret = soap->frecv(soap, soap->buf, sizeof(soap->buf)); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes (chunked) from socket=%d\n", (unsigned int)ret, (int)soap->socket)); DBGMSG(RECV, soap->buf, ret); soap->bufidx = 0; if (!ret) - return soap->ahead = EOF; + { + soap->ahead = EOF; + return EOF; + } } else + { soap->bufidx = soap->buflen; + } soap->buflen = soap->chunkbuflen; DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk size (idx=%u len=%u)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen)); while (!soap_isxdigit((int)(c = soap_getchunkchar(soap)))) - { if ((int)c == EOF) - return soap->ahead = EOF; + { + if ((int)c == EOF) + { + soap->ahead = EOF; + return EOF; + } } + t = tmp; do + { *t++ = (char)c; - while (soap_isxdigit((int)(c = soap_getchunkchar(soap))) && t - tmp < 7); + } while (soap_isxdigit((int)(c = soap_getchunkchar(soap))) && (size_t)(t - tmp) < sizeof(tmp)-1); while ((int)c != EOF && c != '\n') c = soap_getchunkchar(soap); if ((int)c == EOF) - return soap->ahead = EOF; + { + soap->ahead = EOF; + return EOF; + } *t = '\0'; DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunk size = %s (hex)\n", tmp)); - soap->chunksize = soap_strtoul(tmp, &t, 16); - if (!soap->chunksize) - { soap->chunkbuflen = 0; + chunksize = soap_strtoul(tmp, &t, 16); + if (*t || chunksize > SOAP_MAXHTTPCHUNK || (soap->recv_maxlength && chunksize > soap->recv_maxlength)) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunk size %lu exceeds max\n", chunksize)); + return soap->error = SOAP_HTTP_ERROR; + } + soap->chunksize = (size_t)chunksize; + soap->buflen = soap->bufidx + soap->chunksize; + if (soap->buflen <= soap->bufidx) + { + soap->bufidx = soap->buflen = soap->chunkbuflen = 0; DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of chunked message\n")); - while ((int)c != EOF && c != '\n') - c = soap_getchunkchar(soap); ret = 0; soap->ahead = EOF; - break; + break; } - soap->buflen = soap->bufidx + soap->chunksize; DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving buf len to idx=%u len=%u (%s)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen, tmp)); if (soap->buflen > soap->chunkbuflen) - { soap->buflen = soap->chunkbuflen; + { + soap->buflen = soap->chunkbuflen; soap->chunksize -= soap->buflen - soap->bufidx; soap->chunkbuflen = 0; DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Passed end of buffer for chunked HTTP (%u bytes left)\n", (unsigned int)(soap->buflen - soap->bufidx))); } else if (soap->chunkbuflen) + { soap->chunksize = 0; + } ret = soap->buflen - soap->bufidx; if (ret) break; @@ -1104,29 +1580,28 @@ soap_recv_raw(struct soap *soap) } else #endif - { soap->bufidx = 0; - soap->buflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN); - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket %d\n", (unsigned int)ret, soap->socket)); + { + soap->bufidx = 0; + soap->buflen = ret = soap->frecv(soap, soap->buf, sizeof(soap->buf)); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket=%d/fd=%d\n", (unsigned int)ret, (int)soap->socket, soap->recvfd)); DBGMSG(RECV, soap->buf, ret); } -#ifndef WITH_LEANER - if (soap->fpreparerecv && (r = soap->fpreparerecv(soap, soap->buf, ret))) - return soap->error = r; -#endif #ifdef WITH_ZLIB - if (soap->mode & SOAP_ENC_ZLIB) - { memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); + if ((soap->mode & SOAP_ENC_ZLIB) && soap->d_stream) + { + (void)soap_memcpy((void*)soap->z_buf, sizeof(soap->buf), (const void*)soap->buf, sizeof(soap->buf)); soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx); soap->d_stream->avail_in = (unsigned int)ret; soap->d_stream->next_out = (Byte*)soap->buf; - soap->d_stream->avail_out = SOAP_BUFLEN; + soap->d_stream->avail_out = sizeof(soap->buf); r = inflate(soap->d_stream, Z_NO_FLUSH); if (r == Z_NEED_DICT && soap->z_dict) r = inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len); if (r == Z_OK || r == Z_STREAM_END) - { soap->bufidx = 0; + { + soap->bufidx = 0; soap->z_buflen = soap->buflen; - soap->buflen = SOAP_BUFLEN - soap->d_stream->avail_out; + soap->buflen = sizeof(soap->buf) - soap->d_stream->avail_out; if (soap->zlib_in == SOAP_ZLIB_GZIP) soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen); DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %u bytes\n", (unsigned int)soap->buflen)); @@ -1134,178 +1609,270 @@ soap_recv_raw(struct soap *soap) goto zlib_again; ret = soap->buflen; if (r == Z_STREAM_END) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated total %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out)); - soap->z_ratio_in = (float)soap->d_stream->total_in / (float)soap->d_stream->total_out; + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated total %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out)); soap->d_stream->next_out = Z_NULL; } + soap->z_ratio_in = (float)soap->d_stream->total_in / (float)soap->d_stream->total_out; + if (soap->count + ret > SOAP_MAXINFLATESIZE && soap->z_ratio_in < SOAP_MINDEFLATERATIO) + { + soap->d_stream->msg = (char*)"caught SOAP_MINDEFLATERATIO explosive decompression guard (remedy: increase SOAP_MAXINFLATESIZE and/or decrease SOAP_MINDEFLATERATIO)"; + return soap->error = SOAP_ZLIB_ERROR; + } DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- decompressed ----\n")); DBGMSG(RECV, soap->buf, ret); +#ifndef WITH_LEANER + if (soap->fpreparerecv && (r = soap->fpreparerecv(soap, soap->buf, ret)) != SOAP_OK) + return soap->error = r; +#endif } else - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to inflate: (%d) %s\n", r, soap->d_stream->msg?soap->d_stream->msg:SOAP_STR_EOS)); + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to inflate: (%d) %s\n", r, soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS)); soap->d_stream->next_out = Z_NULL; - soap->error = SOAP_ZLIB_ERROR; - return EOF; + return soap->error = SOAP_ZLIB_ERROR; } } #endif - soap->count += ret; - return !ret; -} +#ifndef WITH_LEANER + if (soap->fpreparerecv +#ifdef WITH_ZLIB + && soap->zlib_in == SOAP_ZLIB_NONE #endif + && (r = soap->fpreparerecv(soap, soap->buf + soap->bufidx, ret))) + return soap->error = r; +#endif + if (ret) + { + if (soap->count + ret < soap->count) + return EOF; + soap->count += ret; + if (soap->recv_maxlength && soap->count > soap->recv_maxlength) + return EOF; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read count=" SOAP_ULONG_FORMAT " (+%lu)\n", soap->count, (unsigned long)ret)); + return SOAP_OK; + } + return EOF; +} /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 int SOAP_FMAC2 soap_recv(struct soap *soap) { #ifndef WITH_LEANER - if (soap->mode & SOAP_ENC_DIME) - { if (soap->dime.buflen) - { char *s; + if ((soap->mode & SOAP_ENC_DIME)) + { + if (soap->dime.buflen) + { + char *s; int i; unsigned char tmp[12]; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME hdr for chunked DIME is in buffer\n")); - soap->count += soap->dime.buflen - soap->buflen; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME hdr for chunked SOAP in DIME is in buffer\n")); soap->buflen = soap->dime.buflen; + soap->dime.buflen = 0; + soap->dime.chunksize = 0; DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Skip padding (%ld bytes)\n", -(long)soap->dime.size&3)); for (i = -(long)soap->dime.size&3; i > 0; i--) - { soap->bufidx++; + { + soap->bufidx++; if (soap->bufidx >= soap->buflen) if (soap_recv_raw(soap)) return EOF; } - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME hdr for next chunk\n")); + if (!(soap->dime.flags & SOAP_DIME_CF)) + return SOAP_OK; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME hdr for next SOAP in DIME chunk\n")); s = (char*)tmp; for (i = 12; i > 0; i--) - { *s++ = soap->buf[soap->bufidx++]; + { + *s++ = soap->buf[soap->bufidx++]; if (soap->bufidx >= soap->buflen) if (soap_recv_raw(soap)) return EOF; } - soap->dime.flags = tmp[0] & 0x7; + if ((tmp[0] & 0xF8) != SOAP_DIME_VERSION) + return soap->error = SOAP_DIME_MISMATCH; + soap->dime.flags = (tmp[0] & 0x7) | (tmp[1] & 0xF0); 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, "Get DIME chunk (%u bytes)\n", (unsigned int)soap->dime.size)); - if (soap->dime.flags & SOAP_DIME_CF) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "More chunking\n")); - soap->dime.chunksize = soap->dime.size; - if (soap->buflen - soap->bufidx >= soap->dime.size) - { soap->dime.buflen = soap->buflen; - soap->buflen = soap->bufidx + soap->dime.chunksize; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get SOAP in DIME chunk (%u bytes)\n", (unsigned int)soap->dime.size)); + soap->dime.chunksize = soap->dime.size; + if (soap->buflen - soap->bufidx >= soap->dime.size) + { + if ((soap->dime.flags & SOAP_DIME_ME)) + { + soap->mode &= ~SOAP_ENC_DIME; } else - soap->dime.chunksize -= soap->buflen - soap->bufidx; + { + soap->dime.buflen = soap->buflen; + soap->buflen = soap->bufidx + soap->dime.chunksize; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked SOAP in DIME (%u bytes buffered)\n", (unsigned int)soap->buflen)); + } } else - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Last chunk\n")); - soap->dime.buflen = 0; - soap->dime.chunksize = 0; + { + soap->dime.chunksize -= soap->buflen - soap->bufidx; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked SOAP in DIME (%u bytes in chunk left)\n", (unsigned int)soap->dime.chunksize)); } - soap->count = soap->buflen - soap->bufidx; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%u bytes remaining\n", (unsigned int)soap->count)); return SOAP_OK; } if (soap->dime.chunksize) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get next DIME hdr for chunked DIME (%u bytes chunk)\n", (unsigned int)soap->dime.chunksize)); + { if (soap_recv_raw(soap)) return EOF; if (soap->buflen - soap->bufidx >= soap->dime.chunksize) - { soap->dime.buflen = soap->buflen; - soap->count -= soap->buflen - soap->bufidx - soap->dime.chunksize; - soap->buflen = soap->bufidx + soap->dime.chunksize; - } - else - soap->dime.chunksize -= soap->buflen - soap->bufidx; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%lu bytes remaining, count=%u\n", (unsigned long)(soap->buflen-soap->bufidx), (unsigned int)soap->count)); - return SOAP_OK; - } + { + if ((soap->dime.flags & SOAP_DIME_ME)) + { + soap->dime.chunksize = 0; + soap->mode &= ~SOAP_ENC_DIME; + } + else + { + soap->dime.buflen = soap->buflen; + soap->buflen = soap->bufidx + soap->dime.chunksize; + soap->dime.chunksize = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked SOAP in DIME (%u bytes buffered)\n", (unsigned int)soap->buflen)); + } + } + else + { + soap->dime.chunksize -= soap->buflen - soap->bufidx; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked SOAP in DIME (%u bytes in chunk left)\n", (unsigned int)soap->dime.chunksize)); + } + return SOAP_OK; + } } -#endif + if (soap->ffilterrecv) + { + int err; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Filter recverror = %d bufidx = %lu buflen = %lu\n", soap->recverror, (unsigned long)soap->bufidx, (unsigned long)soap->buflen)); + if (soap->recverror) + { + soap->bufidx = soap->buflen = 0; + } + else + { + soap->bufidx = soap->buflen = 0; + err = soap->ffilterrecv(soap, soap->buf, &soap->buflen, sizeof(soap->buf)); + if (err) + { + if (err == SOAP_EOF) + return SOAP_EOF; + return soap->error = err; + } + if (soap->buflen) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Filtered output continued %lu bytes\n", (unsigned long)soap->buflen)); + return SOAP_OK; + } + soap->recverror = soap_recv_raw(soap); + soap->buflen -= soap->bufidx; /* chunked may set bufidx > 0 to skip hex chunk length */ + } + while (soap->ffilterrecv) + { + err = soap->ffilterrecv(soap, soap->buf + soap->bufidx, &soap->buflen, sizeof(soap->buf) - soap->bufidx); + if (err) + { + if (err == SOAP_EOF) + return SOAP_EOF; + return soap->error = err; + } + if (soap->buflen) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Filtered output %lu bytes\n", (unsigned long)soap->buflen)); + soap->buflen += soap->bufidx; + return SOAP_OK; + } + if (soap->recverror) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Returning postponed error %d\n", soap->recverror)); + return soap->recverror; + } + soap->recverror = soap_recv_raw(soap); + soap->buflen -= soap->bufidx; /* chunked may set bufidx > 0 to skip hex chunk length */ + } + } + return soap->recverror = soap_recv_raw(soap); +#else return soap_recv_raw(soap); -} #endif - -/******************************************************************************/ -#ifndef PALM_1 -SOAP_FMAC1 -soap_wchar -SOAP_FMAC2 -soap_getchar(struct soap *soap) -{ soap_wchar c; - c = soap->ahead; - if (c) - { if (c != EOF) - soap->ahead = 0; - return c; - } - return soap_get1(soap); } -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 const struct soap_code_map* SOAP_FMAC2 soap_code(const struct soap_code_map *code_map, const char *str) -{ if (code_map && str) - { while (code_map->string) - { if (!strcmp(str, code_map->string)) /* case sensitive */ +{ + if (code_map && str) + { + while (code_map->string) + { + if (!strcmp(str, code_map->string)) /* case sensitive */ return code_map; code_map++; } } return NULL; } -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 -long +LONG64 SOAP_FMAC2 -soap_code_int(const struct soap_code_map *code_map, const char *str, long other) -{ if (code_map) - { while (code_map->string) - { if (!soap_tag_cmp(str, code_map->string)) /* case insensitive */ +soap_code_int(const struct soap_code_map *code_map, const char *str, LONG64 other) +{ + if (code_map) + { + while (code_map->string) + { + if (!soap_tag_cmp(str, code_map->string)) /* case insensitive */ return code_map->code; code_map++; } } return other; } -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 const char* SOAP_FMAC2 soap_code_str(const struct soap_code_map *code_map, long code) -{ if (!code_map) +{ + if (!code_map) return NULL; while (code_map->code != code && code_map->string) code_map++; return code_map->string; } -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 -long +LONG64 SOAP_FMAC2 soap_code_bits(const struct soap_code_map *code_map, const char *str) -{ long bits = 0; +{ + LONG64 bits = 0; if (code_map) - { while (str && *str) - { const struct soap_code_map *p; + { + while (str && *str) + { + const struct soap_code_map *p; for (p = code_map; p->string; p++) - { size_t n = strlen(p->string); - if (!strncmp(p->string, str, n) && soap_blank(str[n])) - { bits |= p->code; + { + size_t n = strlen(p->string); + if (!strncmp(p->string, str, n) && soap_coblank((soap_wchar)str[n])) + { + bits |= p->code; str += n; while (*str > 0 && *str <= 32) str++; @@ -1318,19 +1885,22 @@ soap_code_bits(const struct soap_code_map *code_map, const char *str) } return bits; } -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 const char* SOAP_FMAC2 soap_code_list(struct soap *soap, const struct soap_code_map *code_map, long code) -{ char *t = soap->tmpbuf; +{ + char *t = soap->tmpbuf; if (code_map) - { while (code_map->string) - { if (code_map->code & code) - { const char *s = code_map->string; + { + while (code_map->string) + { + if ((code_map->code & code)) + { + const char *s = code_map->string; if (t != soap->tmpbuf) *t++ = ' '; while (*s && t < soap->tmpbuf + sizeof(soap->tmpbuf) - 1) @@ -1344,27 +1914,51 @@ soap_code_list(struct soap *soap, const struct soap_code_map *code_map, long cod *t = '\0'; return soap->tmpbuf; } -#endif /******************************************************************************/ -#ifndef PALM_1 + +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_binary_search_string(const char **a, int n, const char *s) +{ + int min = 0, max = n-1; + while (min <= max) + { + int mid = (min+max)/2; + int r = strcmp(s, a[mid]); + if (r < 0) + max = mid - 1; + else if (r > 0) + min = mid + 1; + else + return mid; + } + return -1; +} + +/******************************************************************************/ + static soap_wchar soap_char(struct soap *soap) -{ char tmp[8]; +{ + char tmp[8]; int i; soap_wchar c; char *s = tmp; - for (i = 0; i < 7; i++) - { c = soap_get1(soap); + for (i = 0; i < (int)sizeof(tmp)-1; i++) + { + c = soap_get1(soap); if (c == ';' || (int)c == EOF) break; *s++ = (char)c; } *s = '\0'; if (*tmp == '#') - { if (tmp[1] == 'x' || tmp[1] == 'X') - return soap_strtol(tmp + 2, NULL, 16); - return atol(tmp + 1); + { + if (tmp[1] == 'x' || tmp[1] == 'X') + return (soap_wchar)soap_strtol(tmp + 2, NULL, 16); + return (soap_wchar)soap_strtol(tmp + 1, NULL, 10); } if (!strcmp(tmp, "lt")) return '<'; @@ -1377,86 +1971,133 @@ soap_char(struct soap *soap) if (!strcmp(tmp, "apos")) return '\''; #ifndef WITH_LEAN - return (soap_wchar)soap_code_int(html_entity_codes, tmp, SOAP_UNKNOWN_CHAR); + return (soap_wchar)soap_code_int(html_entity_codes, tmp, (LONG64)SOAP_UNKNOWN_CHAR); #else return SOAP_UNKNOWN_CHAR; /* use this to represent unknown code */ #endif } -#endif /******************************************************************************/ + #ifdef WITH_LEAN -#ifndef PALM_1 soap_wchar soap_get0(struct soap *soap) -{ if (soap->bufidx >= soap->buflen && soap_recv(soap)) - return EOF; - return (unsigned char)soap->buf[soap->bufidx]; +{ + return (soap->bufidx >= soap->buflen && soap_recv(soap)) ? EOF : (unsigned char)soap->buf[soap->bufidx]; } #endif -#endif /******************************************************************************/ + #ifdef WITH_LEAN -#ifndef PALM_1 soap_wchar soap_get1(struct soap *soap) -{ if (soap->bufidx >= soap->buflen && soap_recv(soap)) - return EOF; - return (unsigned char)soap->buf[soap->bufidx++]; +{ + return (soap->bufidx >= soap->buflen && soap_recv(soap)) ? EOF : (unsigned char)soap->buf[soap->bufidx++]; } #endif + +/******************************************************************************/ + +#ifdef WITH_LEAN +SOAP_FMAC1 +soap_wchar +SOAP_FMAC2 +soap_getchar(struct soap *soap) +{ + soap_wchar c; + c = soap->ahead; + if (c) + { + if ((int)c != EOF) + soap->ahead = 0; + return c; + } + return soap_get1(soap); +} +#else +SOAP_FMAC1 +soap_wchar +SOAP_FMAC2 +soap_getahead(struct soap *soap) +{ + soap_wchar c = soap->ahead; + if ((int)c != EOF) + soap->ahead = 0; + return c; +} #endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_get(struct soap *soap) -{ soap_wchar c; +{ + soap_wchar c; c = soap->ahead; if (c) - { if ((int)c != EOF) + { + if ((int)c != EOF) soap->ahead = 0; } else + { c = soap_get1(soap); + } while ((int)c != EOF) - { if (soap->cdata) - { if (c == ']') - { c = soap_get1(soap); + { + if (soap->cdata) + { + if (c == ']') + { + c = soap_get1(soap); if (c == ']') - { c = soap_get0(soap); + { + c = soap_get0(soap); if (c == '>') - { soap->cdata = 0; - soap_get1(soap); + { + soap->cdata = 0; + c = soap_get1(soap); c = soap_get1(soap); } else - { soap_unget(soap, ']'); + { + soap_unget(soap, ']'); return ']'; } } else - { soap_revget1(soap); + { + soap_revget1(soap); return ']'; } } else + { return c; + } } switch (c) - { case '<': - do c = soap_get1(soap); - while (soap_blank(c)); + { + case '<': + do + { + c = soap_get1(soap); + } while (soap_coblank(c)); if (c == '!' || c == '?' || c == '%') - { int k = 1; + { + int k = 1; if (c == '!') - { c = soap_get1(soap); + { + c = soap_get1(soap); if (c == '[') - { do c = soap_get1(soap); - while ((int)c != EOF && c != '['); + { + do + { + c = soap_get1(soap); + } while ((int)c != EOF && c != '['); if ((int)c == EOF) break; soap->cdata = 1; @@ -1464,20 +2105,28 @@ soap_get(struct soap *soap) continue; } if (c == '-' && (c = soap_get1(soap)) == '-') - { do - { c = soap_get1(soap); + { + do + { + c = soap_get1(soap); if (c == '-' && (c = soap_get1(soap)) == '-') break; } while ((int)c != EOF); } } else if (c == '?') - c = soap_get_pi(soap); + { + c = soap_getpi(soap); + } while ((int)c != EOF) - { if (c == '<') + { + if (c == '<') + { k++; + } else if (c == '>') - { if (--k <= 0) + { + if (--k <= 0) break; } c = soap_get1(soap); @@ -1504,103 +2153,132 @@ soap_get(struct soap *soap) } return c; } -#endif /******************************************************************************/ -#ifndef PALM_1 + static soap_wchar -soap_get_pi(struct soap *soap) -{ char buf[64]; +soap_getpi(struct soap *soap) +{ + char buf[64]; char *s = buf; - int i = sizeof(buf); - soap_wchar c = soap_getchar(soap); - /* This is a quick way to parse XML PI and we could use a callback instead to - * enable applications to intercept processing instructions */ - while ((int)c != EOF && c != '?') - { if (--i > 0) - { if (soap_blank(c)) + size_t i = sizeof(buf); + soap_wchar c; + while ((int)(c = soap_getchar(soap)) != EOF && c != '?') + { + if (i > 1) + { + if (soap_coblank(c)) c = ' '; *s++ = (char)c; + i--; } - c = soap_getchar(soap); } *s = '\0'; DBGLOG(TEST, SOAP_MESSAGE(fdebug, "XML PI \n", buf)); if (!strncmp(buf, "xml ", 4)) - { s = strstr(buf, " encoding="); + { + s = strstr(buf, " encoding="); if (s && s[10]) - { if (!soap_tag_cmp(s + 11, "iso-8859-1*") - || !soap_tag_cmp(s + 11, "latin1*")) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to latin1 encoding\n")); + { + int err; + if (!soap_tag_cmp(s + 11, "iso-8859-*") + || !soap_tag_cmp(s + 11, "latin*")) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to latin encoding\n")); soap->mode |= SOAP_ENC_LATIN; } else if (!soap_tag_cmp(s + 11, "utf-8*")) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to utf-8 encoding\n")); + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to utf-8 encoding\n")); soap->mode &= ~SOAP_ENC_LATIN; } + else if (soap->fencoding && ((err = soap->fencoding(soap, s + 11)) != SOAP_OK)) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Callback fencoding returned %d\n", err)); + soap->error = err; + c = EOF; + } } } if ((int)c != EOF) c = soap_getchar(soap); return c; } -#endif /******************************************************************************/ + #ifndef WITH_LEANER -#ifndef PALM_1 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, ULONG64 n) +{ + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving " SOAP_ULONG_FORMAT " bytes forward\n", n)); + for (; n; n--) if ((int)soap_getchar(soap) == EOF) return SOAP_EOF; return SOAP_OK; } #endif -#endif /******************************************************************************/ + #ifndef WITH_LEANER -#ifndef PALM_1 SOAP_FMAC1 -size_t +ULONG64 SOAP_FMAC2 soap_tell(struct soap *soap) -{ return soap->count - soap->buflen + soap->bufidx - (soap->ahead != 0); +{ + return soap->count - soap->buflen + soap->bufidx - (soap->ahead != 0); } #endif -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 int SOAP_FMAC2 soap_pututf8(struct soap *soap, unsigned long c) -{ char tmp[16]; - if (c < 0x80 && c > 0) - { *tmp = (char)c; +{ + char tmp[24]; + if ((c < 0x7F && c > 0x1F)) + { + *tmp = (char)c; return soap_send_raw(soap, tmp, 1); } +#ifdef WITH_REPLACE_ILLEGAL_UTF8 + if (!(c == 0x09 || c == 0x0A || c == 0x0D || (c >= 0x80 && c <= 0xD7FF) || (c >= 0xE000 && c <= 0xFFFD) || (c >= 0x10000 && c <= 0x10FFFF))) + c = SOAP_UNKNOWN_UNICODE_CHAR; +#endif #ifndef WITH_LEAN - if (c >= 0x80) - { char *t = tmp; + if (c > 0x9F) + { + char *t = tmp; if (c < 0x0800) + { *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); + } else - { if (c < 0x010000) + { + if (c < 0x010000) + { *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); + } else - { if (c < 0x200000) + { + if (c < 0x200000) + { *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + } else - { if (c < 0x04000000) + { + if (c < 0x04000000) + { *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + } else - { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); + { + *t++ = (char)(0xFC | ((c >> 30) & 0x01)); *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); } *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); @@ -1612,31 +2290,63 @@ soap_pututf8(struct soap *soap, unsigned long c) *t++ = (char)(0x80 | (c & 0x3F)); *t = '\0'; } -#else - sprintf(tmp, "&#%lu;", c); + else #endif + (SOAP_SNPRINTF(tmp, sizeof(tmp), 20), "&#x%lX;", c); return soap_send(soap, tmp); } -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_getutf8(struct soap *soap) -{ soap_wchar c, c1, c2, c3, c4; +{ +#ifdef WITH_REPLACE_ILLEGAL_UTF8 + soap_wchar c, c1, c2, c3; +#else + soap_wchar c, c1, c2, c3, c4; +#endif c = soap->ahead; - if (c > 0x7F) - { soap->ahead = 0; + if (c >= 0x80) + soap->ahead = 0; + else + c = (soap_wchar)soap_get(soap); + if (c < 0x80 || c > 0xFF || (soap->mode & SOAP_ENC_LATIN)) return c; +#ifdef WITH_REPLACE_ILLEGAL_UTF8 + c1 = (soap_wchar)soap_get1(soap); + if (c <= 0xC1 || (c1 & 0xC0) != 0x80) + { + soap_revget1(soap); + return SOAP_UNKNOWN_UNICODE_CHAR; } - c = soap_get(soap); - if (c < 0x80 || (soap->mode & SOAP_ENC_LATIN)) - return c; - c1 = soap_get1(soap); - if (c1 < 0x80) - { soap_revget1(soap); /* doesn't look like this is UTF8 */ + c1 &= 0x3F; + if (c < 0xE0) + return (((c & 0x1F) << 6) | c1); + c2 = (soap_wchar)soap_get1(soap); + if ((c == 0xE0 && c1 < 0x20) || (c2 & 0xC0) != 0x80) + { + soap_revget1(soap); + return SOAP_UNKNOWN_UNICODE_CHAR; + } + c2 &= 0x3F; + if (c < 0xF0) + return (((c & 0x0F) << 12) | (c1 << 6) | c2); + c3 = (soap_wchar)soap_get1(soap); + if ((c == 0xF0 && c1 < 0x10) || (c == 0xF4 && c1 >= 0x10) || c >= 0xF5 || (c3 & 0xC0) != 0x80) + { + soap_revget1(soap); + return SOAP_UNKNOWN_UNICODE_CHAR; + } + return (((c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | (c3 & 0x3F)); +#else + c1 = (soap_wchar)soap_get1(soap); + if (c < 0xC0 || (c1 & 0xC0) != 0x80) + { + soap_revget1(soap); + /* doesn't look like this is UTF-8, try continue as if ISO-8859-1 */ return c; } c1 &= 0x3F; @@ -1652,53 +2362,79 @@ soap_getutf8(struct soap *soap) if (c < 0xFC) return ((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4; return ((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(soap_get1(soap) & 0x3F); -} #endif +} + +/******************************************************************************/ + +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_utf8len(const char *s) +{ + size_t l = 0; + while (*s) + if ((*s++ & 0xC0) != 0x80) + l++; + return l; +} /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 int SOAP_FMAC2 soap_puthex(struct soap *soap, const unsigned char *s, int n) -{ char d[2]; - int i; +{ + char d[2 * SOAP_BINARY_BUFLEN], *p = d; #ifdef WITH_DOM if ((soap->mode & SOAP_XML_DOM) && soap->dom) - { if (!(soap->dom->data = soap_s2hex(soap, s, NULL, n))) + { + soap->dom->text = soap_s2hex(soap, s, NULL, n); + if (!soap->dom->text) return soap->error; return SOAP_OK; } #endif - for (i = 0; i < n; i++) - { int m = *s++; - d[0] = (char)((m >> 4) + (m > 159 ? '7' : '0')); + for (; n > 0; n--) + { + int m = *s++; + p[0] = (char)((m >> 4) + (m > 159 ? '7' : '0')); m &= 0x0F; - d[1] = (char)(m + (m > 9 ? '7' : '0')); - if (soap_send_raw(soap, d, 2)) - return soap->error; + p[1] = (char)(m + (m > 9 ? '7' : '0')); + p += 2; + if (p - d == sizeof(d)) + { + if (soap_send_raw(soap, d, sizeof(d))) + return soap->error; + p = d; + } } + if (p != d && soap_send_raw(soap, d, p - d)) + return soap->error; return SOAP_OK; } -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 unsigned char* SOAP_FMAC2 soap_gethex(struct soap *soap, int *n) { + size_t l = 0; #ifdef WITH_DOM if ((soap->mode & SOAP_XML_DOM) && soap->dom) - { soap->dom->data = soap_string_in(soap, 0, -1, -1); - return (unsigned char*)soap_hex2s(soap, soap->dom->data, NULL, 0, n); + { + soap->dom->text = soap_string_in(soap, 1, -1, -1, NULL); + return (unsigned char*)soap_hex2s(soap, soap->dom->text, NULL, 0, n); } #endif #ifdef WITH_FAST soap->labidx = 0; for (;;) - { char *s; + { + char *s; size_t i, k; if (soap_append_lab(soap, NULL, 0)) return NULL; @@ -1706,150 +2442,207 @@ soap_gethex(struct soap *soap, int *n) k = soap->lablen - soap->labidx; soap->labidx = soap->lablen; for (i = 0; i < k; i++) - { char d1, d2; + { + char d1, d2; soap_wchar c; c = soap_get(soap); if (soap_isxdigit(c)) - { d1 = (char)c; + { + d1 = (char)c; c = soap_get(soap); if (soap_isxdigit(c)) + { d2 = (char)c; + } else - { soap->error = SOAP_TYPE; + { + soap->error = SOAP_TYPE; return NULL; } } else - { unsigned char *p; + { + unsigned char *p = NULL; + l = soap->lablen + i - k; soap_unget(soap, c); if (n) - *n = (int)(soap->lablen + i - k); - p = (unsigned char*)soap_malloc(soap, soap->lablen + i - k); - if (p) - memcpy(p, soap->labbuf, soap->lablen + i - k); - return p; - } - *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'); + *n = (int)l; + if (soap->maxlength > 0 && l > (size_t)soap->maxlength) + { + soap->error = SOAP_LENGTH; + } + else + { + p = (unsigned char*)soap_malloc(soap, l); + if (p) + (void)soap_memcpy((void*)p, l, (const void*)soap->labbuf, l); + } + return p; + } + *s++ = (char)(((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0')); + } + l = soap->lablen; + if (soap->maxlength > 0 && l > (size_t)soap->maxlength) + { + soap->error = SOAP_LENGTH; + return NULL; } } #else - if (soap_new_block(soap) == NULL) + if (soap_alloc_block(soap) == NULL) return NULL; for (;;) - { int i; + { + int i; char *s = (char*)soap_push_block(soap, NULL, SOAP_BLKLEN); if (!s) - { soap_end_block(soap, NULL); + { + soap_end_block(soap, NULL); return NULL; } for (i = 0; i < SOAP_BLKLEN; i++) - { char d1, d2; + { + char d1, d2; soap_wchar c = soap_get(soap); if (soap_isxdigit(c)) - { d1 = (char)c; + { + d1 = (char)c; c = soap_get(soap); if (soap_isxdigit(c)) d2 = (char)c; else - { soap_end_block(soap, NULL); + { + soap_end_block(soap, NULL); soap->error = SOAP_TYPE; return NULL; } } else - { unsigned char *p; + { + unsigned char *p; soap_unget(soap, c); + if (soap->maxlength > 0 && l > (size_t)soap->maxlength) + { + soap->error = SOAP_LENGTH; + soap_end_block(soap, NULL); + return NULL; + } if (n) *n = (int)soap_size_block(soap, NULL, i); - p = (unsigned char*)soap_save_block(soap, NULL, 0); + p = (unsigned char*)soap_save_block(soap, NULL, NULL, 0); return p; } *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'); + l++; + } + if (soap->maxlength > 0 && l > (size_t)soap->maxlength) + { + soap->error = SOAP_LENGTH; + soap_end_block(soap, NULL); + return NULL; } } #endif } -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 int SOAP_FMAC2 soap_putbase64(struct soap *soap, const unsigned char *s, int n) -{ int i; - unsigned long m; - char d[4]; +{ + char d[4 * SOAP_BINARY_BUFLEN], *p = d; if (!s) return SOAP_OK; #ifdef WITH_DOM if ((soap->mode & SOAP_XML_DOM) && soap->dom) - { if (!(soap->dom->data = soap_s2base64(soap, s, NULL, n))) + { + soap->dom->text = soap_s2base64(soap, s, NULL, n); + if (!soap->dom->text) return soap->error; return SOAP_OK; } #endif for (; n > 2; n -= 3, s += 3) - { m = s[0]; - m = (m << 8) | s[1]; - m = (m << 8) | s[2]; - for (i = 4; i > 0; m >>= 6) - d[--i] = soap_base64o[m & 0x3F]; - if (soap_send_raw(soap, d, 4)) - return soap->error; + { + p[0] = soap_base64o[(s[0] & 0xFC) >> 2]; + p[1] = soap_base64o[((s[0] & 0x03) << 4) | ((s[1] & 0xF0) >> 4)]; + p[2] = soap_base64o[((s[1] & 0x0F) << 2) | ((s[2] & 0xC0) >> 6)]; + p[3] = soap_base64o[s[2] & 0x3F]; + p += 4; + if (p - d == sizeof(d)) + { + if (soap_send_raw(soap, d, sizeof(d))) + return soap->error; + p = d; + } } - if (n > 0) - { m = 0; - for (i = 0; i < n; i++) - m = (m << 8) | *s++; - for (; i < 3; i++) - m <<= 8; - for (i++; i > 0; m >>= 6) - d[--i] = soap_base64o[m & 0x3F]; - for (i = 3; i > n; i--) - d[i] = '='; - if (soap_send_raw(soap, d, 4)) - return soap->error; + if (n == 2) + { + p[0] = soap_base64o[(s[0] & 0xFC) >> 2]; + p[1] = soap_base64o[((s[0] & 0x03) << 4) | ((s[1] & 0xF0) >> 4)]; + p[2] = soap_base64o[(s[1] & 0x0F) << 2]; + p[3] = '='; + p += 4; + } + else if (n == 1) + { + p[0] = soap_base64o[(s[0] & 0xFC) >> 2]; + p[1] = soap_base64o[(s[0] & 0x03) << 4]; + p[2] = '='; + p[3] = '='; + p += 4; } + if (p != d && soap_send_raw(soap, d, p - d)) + return soap->error; return SOAP_OK; } -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 unsigned char* SOAP_FMAC2 soap_getbase64(struct soap *soap, int *n, int malloc_flag) { + size_t l = 0; + (void)malloc_flag; #ifdef WITH_DOM if ((soap->mode & SOAP_XML_DOM) && soap->dom) - { soap->dom->data = soap_string_in(soap, 0, -1, -1); - return (unsigned char*)soap_base642s(soap, soap->dom->data, NULL, 0, n); + { + soap->dom->text = soap_string_in(soap, 1, -1, -1, NULL); + return (unsigned char*)soap_base642s(soap, soap->dom->text, NULL, 0, n); } #endif #ifdef WITH_FAST soap->labidx = 0; for (;;) - { size_t i, k; + { + size_t i, k; char *s; if (soap_append_lab(soap, NULL, 2)) return NULL; s = soap->labbuf + soap->labidx; k = soap->lablen - soap->labidx; soap->labidx = 3 * (soap->lablen / 3); - if (!s) - return NULL; if (k > 2) - { for (i = 0; i < k - 2; i += 3) - { unsigned long m = 0; + { + for (i = 0; i < k - 2; i += 3) + { + unsigned long m = 0; int j = 0; do - { soap_wchar c = soap_get(soap); + { + soap_wchar c = soap_get(soap); + if (c < SOAP_AP) + c &= 0x7FFFFFFF; if (c == '=' || c < 0) - { unsigned char *p; + { + unsigned char *p = NULL; switch (j) - { case 2: + { + case 2: *s++ = (char)((m >> 4) & 0xFF); i++; break; @@ -1858,30 +2651,40 @@ soap_getbase64(struct soap *soap, int *n, int malloc_flag) *s++ = (char)((m >> 2) & 0xFF); i += 2; } + l = soap->lablen + i - k; if (n) - *n = (int)(soap->lablen + i - k); - p = (unsigned char*)soap_malloc(soap, soap->lablen + i - k); - if (p) - memcpy(p, soap->labbuf, soap->lablen + i - k); + *n = (int)l; + if (soap->maxlength > 0 && l > (size_t)soap->maxlength) + soap->error = SOAP_LENGTH; + else + { + p = (unsigned char*)soap_malloc(soap, l); + if (p) + (void)soap_memcpy((void*)p, l, (const void*)soap->labbuf, l); + } if (c >= 0) - { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT) - ; + { + while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT) + continue; } soap_unget(soap, c); return p; } c -= '+'; if (c >= 0 && c <= 79) - { int b = soap_base64i[c]; + { + int b = soap_base64i[c]; if (b >= 64) - { soap->error = SOAP_TYPE; + { + soap->error = SOAP_TYPE; return NULL; } m = (m << 6) + b; j++; } - else if (!soap_blank(c + '+')) - { soap->error = SOAP_TYPE; + else if (!soap_coblank(c + '+')) + { + soap->error = SOAP_TYPE; return NULL; } } while (j < 4); @@ -1889,102 +2692,140 @@ soap_getbase64(struct soap *soap, int *n, int malloc_flag) *s++ = (char)((m >> 8) & 0xFF); *s++ = (char)(m & 0xFF); } + l = soap->lablen; + if (soap->maxlength > 0 && l > (size_t)soap->maxlength) + { + soap->error = SOAP_LENGTH; + return NULL; + } } } #else - if (soap_new_block(soap) == NULL) + if (soap_alloc_block(soap) == NULL) return NULL; for (;;) - { int i; + { + int i; char *s = (char*)soap_push_block(soap, NULL, 3 * SOAP_BLKLEN); /* must be multiple of 3 */ if (!s) - { soap_end_block(soap, NULL); + { + soap_end_block(soap, NULL); return NULL; } for (i = 0; i < SOAP_BLKLEN; i++) - { unsigned long m = 0; + { + unsigned long m = 0; int j = 0; do - { soap_wchar c = soap_get(soap); + { + soap_wchar c = soap_get(soap); + if (c < SOAP_AP) + c &= 0x7FFFFFFF; if (c == '=' || c < 0) - { unsigned char *p; + { + unsigned char *p; i *= 3; switch (j) - { case 2: + { + case 2: *s++ = (char)((m >> 4) & 0xFF); i++; + l++; break; case 3: *s++ = (char)((m >> 10) & 0xFF); *s++ = (char)((m >> 2) & 0xFF); + l += 2; i += 2; } if (n) *n = (int)soap_size_block(soap, NULL, i); - p = (unsigned char*)soap_save_block(soap, NULL, 0); + if (soap->maxlength > 0 && l > (size_t)soap->maxlength) + { + soap->error = SOAP_LENGTH; + soap_end_block(soap, NULL); + return NULL; + } + p = (unsigned char*)soap_save_block(soap, NULL, NULL, 0); if (c >= 0) - { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT) - ; + { + while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT) + continue; } soap_unget(soap, c); return p; } c -= '+'; if (c >= 0 && c <= 79) - { int b = soap_base64i[c]; + { + int b = soap_base64i[c]; if (b >= 64) - { soap->error = SOAP_TYPE; + { + soap->error = SOAP_TYPE; return NULL; } m = (m << 6) + b; j++; } - else if (!soap_blank(c)) - { soap->error = SOAP_TYPE; + else if (!soap_coblank(c + '+')) + { + soap->error = SOAP_TYPE; return NULL; } } while (j < 4); *s++ = (char)((m >> 16) & 0xFF); *s++ = (char)((m >> 8) & 0xFF); *s++ = (char)(m & 0xFF); + l += 3; + } + if (soap->maxlength > 0 && l > (size_t)soap->maxlength) + { + soap->error = SOAP_LENGTH; + soap_end_block(soap, NULL); + return NULL; } } #endif } -#endif /******************************************************************************/ + #ifndef WITH_LEANER -#ifndef PALM_1 SOAP_FMAC1 int SOAP_FMAC2 soap_xop_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options) -{ /* Check MTOM xop:Include element (within hex/base64Binary) */ +{ + /* Check MTOM xop:Include element (within hex/base64Binary) */ /* TODO: this code to be obsoleted with new import/xop.h conventions */ - int body = soap->body; /* should save type too? */ + short body = soap->body; /* should save type too? */ if (!soap_peek_element(soap)) - { if (!soap_element_begin_in(soap, "xop:Include", 0, NULL) && *soap->href) - { if (soap_dime_forward(soap, ptr, size, id, type, options)) + { + if (!soap_element_begin_in(soap, ":Include", 0, NULL)) + { + if (soap_attachment_forward(soap, ptr, size, id, type, options) + || (soap->body && soap_element_end_in(soap, ":Include"))) return soap->error; } - if (soap->body && soap_element_end_in(soap, NULL)) + else if (soap->error == SOAP_TAG_MISMATCH) + soap_retry(soap); + else return soap->error; } soap->body = body; return SOAP_OK; } #endif -#endif /******************************************************************************/ + #ifndef WITH_LEANER -#ifndef PALM_1 SOAP_FMAC1 int SOAP_FMAC2 -soap_dime_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options) -{ struct soap_xlist *xp; +soap_attachment_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options) +{ + struct soap_xlist *xp; *ptr = NULL; *size = 0; *id = NULL; @@ -2006,400 +2847,603 @@ soap_dime_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, return SOAP_OK; } #endif -#endif /******************************************************************************/ -#ifndef PALM_1 + +SOAP_FMAC1 +void * +SOAP_FMAC2 +soap_memdup(struct soap *soap, const void *s, size_t n) +{ + void *t = NULL; + if (s) + { + t = soap_malloc(soap, n); + if (t) + (void)soap_memcpy(t, n, s, n); + } + return t; +} + +/******************************************************************************/ + SOAP_FMAC1 char * SOAP_FMAC2 soap_strdup(struct soap *soap, const char *s) -{ char *t = NULL; - if (s && (t = (char*)soap_malloc(soap, strlen(s) + 1))) - strcpy(t, s); +{ + char *t = NULL; + if (s) + { + size_t n = strlen(s) + 1; + if (n > 0) + { + t = (char*)soap_malloc(soap, n); + if (t) + { + (void)soap_memcpy((void*)t, n, (const void*)s, n); + t[n - 1] = '\0'; + } + } + } return t; } -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 wchar_t * SOAP_FMAC2 soap_wstrdup(struct soap *soap, const wchar_t *s) -{ wchar_t *t = NULL; +{ + wchar_t *t = NULL; if (s) - { size_t n = 0; + { + size_t n = 0, m; while (s[n]) n++; - if ((t = (wchar_t*)soap_malloc(soap, sizeof(wchar_t)*(n+1)))) - memcpy(t, s, sizeof(wchar_t)*(n+1)); + n++; + m = sizeof(wchar_t) * n; + if (n > 0) + { + t = (wchar_t*)soap_malloc(soap, m); + if (t) + { + (void)soap_memcpy((void*)t, m, (const void*)s, m); + t[n - 1] = L'\0'; + } + } } return t; } -#endif /******************************************************************************/ -#ifndef PALM_1 + +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_strtrim(struct soap *soap, char *s) +{ + (void)soap; + if (s) + { + char *t; + while ((*s >= 9 && *s <= 13) || *s == 32) + s++; + t = s; + while (*t) + t++; + while (--t > s && ((*t >= 9 && *t <= 13) || *t == 32)) + continue; + t[1] = '\0'; + } + return s; +} + +/******************************************************************************/ + +SOAP_FMAC1 +wchar_t * +SOAP_FMAC2 +soap_wstrtrim(struct soap *soap, wchar_t *s) +{ + (void)soap; + if (s) + { + wchar_t *t; + while ((*s >= 9 && *s <= 13) || *s == 32) + s++; + t = s; + while (*t) + t++; + while (--t > s && ((*t >= 9 && *t <= 13) || *t == 32)) + continue; + t[1] = L'\0'; + } + return s; +} + +/******************************************************************************/ + SOAP_FMAC1 struct soap_blist* SOAP_FMAC2 -soap_new_block(struct soap *soap) -{ struct soap_blist *p; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New block sequence (prev=%p)\n", soap->blist)); - if (!(p = (struct soap_blist*)SOAP_MALLOC(soap, sizeof(struct soap_blist)))) - { soap->error = SOAP_EOM; +soap_alloc_block(struct soap *soap) +{ + struct soap_blist *p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New block sequence (prev=%p)\n", (void*)soap->blist)); + p = (struct soap_blist*)SOAP_MALLOC(soap, sizeof(struct soap_blist)); + if (!p) + { + soap->error = SOAP_EOM; return NULL; } p->next = soap->blist; - p->ptr = NULL; + p->head = NULL; p->size = 0; + p->item = 0; soap->blist = p; return p; } -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 void* SOAP_FMAC2 soap_push_block(struct soap *soap, struct soap_blist *b, size_t n) -{ char *p; +{ + struct soap_bhead *p; if (!b) b = soap->blist; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push block of %u bytes (%u bytes total)\n", (unsigned int)n, (unsigned int)b->size + (unsigned int)n)); - if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(char*) + sizeof(size_t)))) - { soap->error = SOAP_EOM; + if (!b + || b->size + n < b->size + || sizeof(struct soap_bhead) + n < n + || (SOAP_MAXALLOCSIZE > 0 && sizeof(struct soap_bhead) + n > SOAP_MAXALLOCSIZE)) + { + soap->error = SOAP_EOM; + return NULL; + } + p = (struct soap_bhead*)SOAP_MALLOC(soap, sizeof(struct soap_bhead) + n); + if (!p) + { + soap->error = SOAP_EOM; return NULL; } - *(char**)p = b->ptr; - *(size_t*)(p + sizeof(char*)) = n; - b->ptr = p; + p->next = b->head; + b->head = p; + p->size = n; b->size += n; - return p + sizeof(char*) + sizeof(size_t); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push block %p of %u bytes on %lu previous blocks (%lu bytes total)\n", (void*)p, (unsigned int)n, (unsigned long)b->item, (unsigned long)b->size)); + b->item++; + return (void*)(p + 1); /* skip block header and point to n allocated bytes */ +} + +/******************************************************************************/ + +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_push_block_max(struct soap *soap, struct soap_blist *b, size_t n) +{ + if (b && b->item >= soap->maxoccurs) /* restrict block array length */ + { + soap->error = SOAP_OCCURS; + return NULL; + } + return soap_push_block(soap, b, n); } -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 void SOAP_FMAC2 soap_pop_block(struct soap *soap, struct soap_blist *b) -{ char *p; +{ + struct soap_bhead *p; if (!b) b = soap->blist; - if (!b->ptr) + if (!b || !b->head) return; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop block\n")); - p = b->ptr; - b->size -= *(size_t*)(p + sizeof(char*)); - b->ptr = *(char**)p; + p = b->head; + b->size -= p->size; + b->head = p->next; + b->item--; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop block %p (%lu items of %lu bytes total)\n", (void*)p, (unsigned long)b->item, (unsigned long)b->size)); SOAP_FREE(soap, p); } -#endif /******************************************************************************/ -#ifndef WITH_NOIDREF -#ifndef PALM_1 -static void -soap_update_ptrs(struct soap *soap, char *start, char *end, char *p1, char *p2) -{ int i; - struct soap_ilist *ip = NULL; - struct soap_flist *fp = NULL; + +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_update_pointers(struct soap *soap, const char *dst, const char *src, size_t len) +{ + const void *start = src, *end = src + len; #ifndef WITH_LEANER - struct soap_xlist *xp = NULL; + struct soap_xlist *xp; #endif - void *p, **q; - for (i = 0; i < SOAP_IDHASH; i++) - { for (ip = soap->iht[i]; ip; ip = ip->next) - { if (ip->ptr && (char*)ip->ptr >= start && (char*)ip->ptr < end) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", ip->id, ip->ptr, (char*)ip->ptr + (p1-p2))); - ip->ptr = (char*)ip->ptr + (p1-p2); - } - for (q = &ip->link; q; q = (void**)p) - { p = *q; - if (p && (char*)p >= start && (char*)p < end) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Link update id='%s' %p\n", ip->id, p)); - *q = (char*)p + (p1-p2); - } - } - for (q = &ip->copy; q; q = (void**)p) - { p = *q; - if (p && (char*)p >= start && (char*)p < end) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy chain update id='%s' %p\n", ip->id, p)); - *q = (char*)p + (p1-p2); - } - } - for (fp = ip->flist; fp; fp = fp->next) - { if ((char*)fp->ptr >= start && (char*)fp->ptr < end) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy list update id='%s' %p\n", ip->id, fp)); - fp->ptr = (char*)fp->ptr + (p1-p2); +#ifndef WITH_NOIDREF + if ((soap->version && !(soap->imode & SOAP_XML_TREE)) || (soap->mode & SOAP_XML_GRAPH)) + { + int i; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update pointers %p (%lu bytes) -> %p\n", (void*)src, (unsigned long)len, (void*)dst)); + for (i = 0; i < SOAP_IDHASH; i++) + { + struct soap_ilist *ip; + for (ip = soap->iht[i]; ip; ip = ip->next) + { + struct soap_flist *fp; + void *p, **q; + if (ip->shaky) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update shaky id='%s'\n", ip->id)); + if (ip->ptr && ip->ptr >= start && ip->ptr < end) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update ptr %p -> %p\n", ip->ptr, (void*)((const char*)ip->ptr + (dst-src)))); + ip->ptr = (void*)((const char*)ip->ptr + (dst-src)); + } + for (q = &ip->link; q; q = (void**)p) + { + p = *q; + if (p && p >= start && p < end) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Link update id='%s' %p -> %p\n", ip->id, p, (void*)((const char*)p + (dst-src)))); + *q = (void*)((const char*)p + (dst-src)); + } + } + for (q = &ip->copy; q; q = (void**)p) + { + p = *q; + if (p && p >= start && p < end) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy chain update id='%s' %p -> %p\n", ip->id, p, (void*)((const char*)p + (dst-src)))); + *q = (void*)((const char*)p + (dst-src)); + } + } + for (fp = ip->flist; fp; fp = fp->next) + { + if (fp->ptr >= start && fp->ptr < end) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy list update id='%s' target type=%d %p -> %p\n", ip->id, fp->type, fp->ptr, (void*)((char*)fp->ptr + (dst-src)))); + fp->ptr = (void*)((const char*)fp->ptr + (dst-src)); + } + } + if (ip->smart && ip->smart >= start && ip->smart < end) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Smart shared pointer update %p -> %p\n", ip->smart, (void*)((const char*)ip->smart + (dst-src)))); + ip->smart = (void*)((const char*)ip->smart + (dst-src)); + } } } } } +#else + (void)soap; (void)start; (void)end; (void)dst; (void)src; +#endif #ifndef WITH_LEANER for (xp = soap->xlist; xp; xp = xp->next) - { if (xp->ptr && (char*)xp->ptr >= start && (char*)xp->ptr < end) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", xp->id?xp->id:SOAP_STR_EOS, xp->ptr, (char*)xp->ptr + (p1-p2))); - xp->ptr = (unsigned char**)((char*)xp->ptr + (p1-p2)); - xp->size = (int*)((char*)xp->size + (p1-p2)); - xp->type = (char**)((char*)xp->type + (p1-p2)); - xp->options = (char**)((char*)xp->options + (p1-p2)); + { + if (xp->ptr && (void*)xp->ptr >= start && (void*)xp->ptr < end) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update attachment id='%s' %p -> %p\n", xp->id ? xp->id : SOAP_STR_EOS, (void*)xp->ptr, (void*)((char*)xp->ptr + (dst-src)))); + xp->ptr = (unsigned char**)((char*)xp->ptr + (dst-src)); + xp->size = (int*)((char*)xp->size + (dst-src)); + xp->type = (char**)((char*)xp->type + (dst-src)); + xp->options = (char**)((char*)xp->options + (dst-src)); } } #endif } -#endif -#endif /******************************************************************************/ + #ifndef WITH_NOIDREF -#ifndef PALM_1 static int soap_has_copies(struct soap *soap, const char *start, const char *end) -{ int i; +{ + int i; struct soap_ilist *ip = NULL; struct soap_flist *fp = NULL; const char *p; for (i = 0; i < SOAP_IDHASH; i++) - { for (ip = soap->iht[i]; ip; ip = ip->next) - { for (p = (const char*)ip->copy; p; p = *(const char**)p) + { + for (ip = soap->iht[i]; ip; ip = ip->next) + { + for (p = (const char*)ip->copy; p; p = *(const char**)p) if (p >= start && p < end) return SOAP_ERR; for (fp = ip->flist; fp; fp = fp->next) - if ((const char*)fp->ptr >= start && (const char*)fp->ptr < end) + if (fp->type == ip->type && (const char*)fp->ptr >= start && (const char*)fp->ptr < end) return SOAP_ERR; } } return SOAP_OK; } #endif -#endif /******************************************************************************/ + #ifndef WITH_NOIDREF -#ifndef PALM_1 SOAP_FMAC1 int SOAP_FMAC2 soap_resolve(struct soap *soap) -{ int i; - struct soap_ilist *ip = NULL; - struct soap_flist *fp = NULL; +{ + int i; short flag; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data\n")); + const char *id; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded refs\n")); for (i = 0; i < SOAP_IDHASH; i++) - { for (ip = soap->iht[i]; ip; ip = ip->next) - { if (ip->ptr) - { void *p, **q, *r; + { + struct soap_ilist *ip; + for (ip = soap->iht[i]; ip; ip = ip->next) + { + if (ip->ptr) + { + void **q; + struct soap_flist *fp, **fpp = &ip->flist; + if (ip->spine) + ip->spine[0] = ip->ptr; q = (void**)ip->link; ip->link = NULL; - r = ip->ptr; - DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing link chain to resolve id='%s'\n", ip->id)); + DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing link chain to resolve id='%s' type=%d\n", ip->id, ip->type)); while (q) - { p = *q; - *q = r; - DBGLOG(TEST,SOAP_MESSAGE(fdebug, "... link %p -> %p\n", q, r)); + { + void *p = *q; + *q = ip->ptr; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... link %p -> %p\n", (void*)q, ip->ptr)); q = (void**)p; } + while ((fp = *fpp)) + { + if (fp->level > 0 && fp->finsert) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... insert type=%d link %p -> %p\n", fp->type, fp->ptr, ip->ptr)); + if (ip->spine && fp->level <= SOAP_MAXPTRS) + fp->finsert(soap, ip->type, fp->type, fp->ptr, fp->index, &ip->spine[fp->level - 1], &ip->smart); + else if (fp->level == 1) + fp->finsert(soap, ip->type, fp->type, fp->ptr, fp->index, &ip->ptr, &ip->smart); + else if (fp->level <= SOAP_MAXPTRS) + { + int i; + ip->spine = (void**)soap_malloc(soap, SOAP_MAXPTRS * sizeof(void*)); + if (!ip->spine) + return soap->error = SOAP_EOM; + ip->spine[0] = ip->ptr; + for (i = 1; i < SOAP_MAXPTRS; i++) + ip->spine[i] = &ip->spine[i - 1]; + fp->finsert(soap, ip->type, fp->type, fp->ptr, fp->index, &ip->spine[fp->level - 1], &ip->smart); + } + *fpp = fp->next; + SOAP_FREE(soap, fp); + } + else + fpp = &fp->next; + } } else if (*ip->id == '#') - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Missing data for id='%s'\n", ip->id)); - strcpy(soap->id, ip->id + 1); + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Missing id='%s'\n", ip->id)); + soap_strcpy(soap->id, sizeof(soap->id), ip->id + 1); return soap->error = SOAP_MISSING_ID; } } } do - { flag = 0; + { + flag = 0; + id = NULL; DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution phase\n")); for (i = 0; i < SOAP_IDHASH; i++) - { for (ip = soap->iht[i]; ip; ip = ip->next) - { if (ip->ptr && !soap_has_copies(soap, (const char*)ip->ptr, (const char*)ip->ptr + ip->size)) - { if (ip->copy) - { void *p, **q = (void**)ip->copy; - DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing copy chain to resolve id='%s'\n", ip->id)); - ip->copy = NULL; - do - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... copy %p -> %p (%u bytes)\n", ip->ptr, q, (unsigned int)ip->size)); - p = *q; - memcpy(q, ip->ptr, ip->size); - q = (void**)p; - } while (q); - flag = 1; - } - for (fp = ip->flist; fp; fp = ip->flist) - { unsigned int k = fp->level; - void *p = ip->ptr; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data type=%d location=%p level=%u,%u id='%s'\n", ip->type, p, ip->level, fp->level, ip->id)); - while (ip->level < k) - { void **q = (void**)soap_malloc(soap, sizeof(void*)); - if (!q) - return soap->error; - *q = p; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level, new location=%p holds=%p...\n", q, *q)); - p = (void*)q; - k--; + { + struct soap_ilist *ip; + for (ip = soap->iht[i]; ip; ip = ip->next) + { + if (ip->copy || ip->flist) + { + if (ip->ptr && !soap_has_copies(soap, (const char*)ip->ptr, (const char*)ip->ptr + ip->size)) + { + struct soap_flist *fp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving id='%s' type=%d ptr=%p size=%lu ...\n", ip->id, ip->type, ip->ptr, (unsigned long)ip->size)); + if (ip->copy) + { + void *p, **q = (void**)ip->copy; + DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing copy chain to resolve id='%s'\n", ip->id)); + ip->copy = NULL; + do + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... copy %p -> %p (%u bytes)\n", ip->ptr, (void*)q, (unsigned int)ip->size)); + p = *q; + (void)soap_memcpy((void*)q, ip->size, (const void*)ip->ptr, ip->size); + q = (void**)p; + } while (q); + flag = 1; + } + while ((fp = ip->flist)) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data type=%d target type=%d location=%p level=%u id='%s'\n", ip->type, fp->type, ip->ptr, fp->level, ip->id)); + if (fp->level == 0) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... copy %p -> %p (%lu bytes)\n", ip->ptr, fp->ptr, (unsigned long)ip->size)); + if (fp->finsert) + fp->finsert(soap, ip->type, fp->type, fp->ptr, fp->index, ip->ptr, &ip->smart); + else + (void)soap_memcpy((void*)fp->ptr, ip->size, (const void*)ip->ptr, ip->size); + } + ip->flist = fp->next; + SOAP_FREE(soap, fp); + flag = 1; } - if (fp->fcopy) - fp->fcopy(soap, ip->type, fp->type, fp->ptr, fp->len, p, ip->size); - else - soap_fcopy(soap, ip->type, fp->type, fp->ptr, fp->len, p, ip->size); - ip->flist = fp->next; - SOAP_FREE(soap, fp); - flag = 1; } + else if (*ip->id == '#') + id = ip->id; } } } } while (flag); -#ifdef SOAP_DEBUG - for (i = 0; i < SOAP_IDHASH; i++) - { for (ip = soap->iht[i]; ip; ip = ip->next) - { if (ip->copy || ip->flist) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution error: forwarded data for id='%s' could not be propagated, please report this problem to the developers\n", ip->id)); - } - } + if (id) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution error: forwarded data for id='%s' could not be propagated, please report this problem to the gSOAP developers\n", id)); + return soap_id_nullify(soap, id); } -#endif DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution done\n")); return SOAP_OK; } #endif -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 size_t SOAP_FMAC2 soap_size_block(struct soap *soap, struct soap_blist *b, size_t n) -{ if (!b) +{ + if (!b) b = soap->blist; - if (b->ptr) - { b->size -= *(size_t*)(b->ptr + sizeof(char*)) - n; - *(size_t*)(b->ptr + sizeof(char*)) = n; + if (b->head) + { + b->size -= b->head->size - n; + b->head->size = n; } return b->size; } -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 char* SOAP_FMAC2 soap_first_block(struct soap *soap, struct soap_blist *b) -{ char *p, *q, *r; +{ + struct soap_bhead *p, *q, *r; if (!b) b = soap->blist; - p = b->ptr; + p = b->head; if (!p) return NULL; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "First block\n")); r = NULL; do - { q = *(char**)p; - *(char**)p = r; + { + q = p->next; + p->next = r; r = p; p = q; } while (p); - b->ptr = r; - return r + sizeof(char*) + sizeof(size_t); + b->head = r; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "First block %p\n", (void*)(r + 1))); + return (char*)(r + 1); } -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 char* SOAP_FMAC2 soap_next_block(struct soap *soap, struct soap_blist *b) -{ char *p; +{ + struct soap_bhead *p; if (!b) b = soap->blist; - p = b->ptr; + p = b->head; if (p) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Next block\n")); - b->ptr = *(char**)p; + { + b->head = p->next; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Next block %p, deleting current block\n", (void*)(b->head ? b->head + 1 : NULL))); SOAP_FREE(soap, p); - if (b->ptr) - return b->ptr + sizeof(char*) + sizeof(size_t); + if (b->head) + return (char*)(b->head + 1); } return NULL; } -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 size_t SOAP_FMAC2 soap_block_size(struct soap *soap, struct soap_blist *b) -{ if (!b) +{ + if (!b) b = soap->blist; - return *(size_t*)(b->ptr + sizeof(char*)); + return b->head->size; } -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 void SOAP_FMAC2 soap_end_block(struct soap *soap, struct soap_blist *b) -{ char *p, *q; +{ + struct soap_bhead *p, *q; if (!b) b = soap->blist; if (b) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of block sequence, free all remaining blocks\n")); - for (p = b->ptr; p; p = q) - { q = *(char**)p; + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of block sequence, free all remaining blocks\n")); + for (p = b->head; p; p = q) + { + q = p->next; SOAP_FREE(soap, p); } if (soap->blist == b) soap->blist = b->next; else - { struct soap_blist *bp; + { + struct soap_blist *bp; for (bp = soap->blist; bp; bp = bp->next) - { if (bp->next == b) - { bp->next = b->next; - break; + { + if (bp->next == b) + { + bp->next = b->next; + break; } } } SOAP_FREE(soap, b); } - DBGLOG(TEST, if (soap->blist) SOAP_MESSAGE(fdebug, "Restore previous block sequence\n")); -} + DBGLOG(TEST, if (soap->blist) SOAP_MESSAGE(fdebug, "Restored previous block sequence\n")); +#ifndef WITH_NOIDREF + if (!soap->blist && ((soap->version && !(soap->imode & SOAP_XML_TREE)) || (soap->mode & SOAP_XML_GRAPH))) + { + int i; + struct soap_ilist *ip = NULL; + for (i = 0; i < SOAP_IDHASH; i++) + for (ip = soap->iht[i]; ip; ip = ip->next) + ip->shaky = 0; + } #endif +} /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 -char* +void* SOAP_FMAC2 soap_save_block(struct soap *soap, struct soap_blist *b, char *p, int flag) -{ size_t n; +{ + size_t n; char *q, *s; if (!b) b = soap->blist; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Save all blocks in contiguous memory space of %u bytes (%p->%p)\n", (unsigned int)b->size, b->ptr, p)); if (b->size) - { if (!p) + { + if (!p) p = (char*)soap_malloc(soap, b->size); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Save all %lu blocks in contiguous memory space of %u bytes (%p->%p)\n", (unsigned long)b->item, (unsigned int)b->size, (void*)b->head, (void*)p)); if (p) - { for (s = p, q = soap_first_block(soap, b); q; q = soap_next_block(soap, b)) - { n = soap_block_size(soap, b); -#ifndef WITH_NOIDREF + { + s = p; + for (q = soap_first_block(soap, b); q; q = soap_next_block(soap, b)) + { + n = soap_block_size(soap, b); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy %u bytes from %p to %p\n", (unsigned int)n, (void*)q, (void*)s)); if (flag) - soap_update_ptrs(soap, q, q + n, s, q); -#endif - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy %u bytes from %p to %p\n", (unsigned int)n, q, s)); - memcpy(s, q, n); + soap_update_pointers(soap, s, q, n); + (void)soap_memcpy((void*)s, n, (const void*)q, n); s += n; } } @@ -2409,198 +3453,156 @@ soap_save_block(struct soap *soap, struct soap_blist *b, char *p, int flag) soap_end_block(soap, b); return p; } -#endif - -/******************************************************************************/ -#ifndef PALM_2 -SOAP_FMAC1 -char * -SOAP_FMAC2 -soap_putsize(struct soap *soap, const char *type, int size) -{ return soap_putsizes(soap, type, &size, 1); -} -#endif /******************************************************************************/ -#ifndef PALM_2 -SOAP_FMAC1 -char * -SOAP_FMAC2 -soap_putsizes(struct soap *soap, const char *type, const int *size, int dim) -{ return soap_putsizesoffsets(soap, type, size, NULL, dim); -} -#endif -/******************************************************************************/ -#ifndef PALM_2 SOAP_FMAC1 char * SOAP_FMAC2 soap_putsizesoffsets(struct soap *soap, const char *type, const int *size, const int *offset, int dim) -{ int i; +{ + int i; + const char *t = ",%d"; if (!type) return NULL; if (soap->version == 2) - { sprintf(soap->type, "%s[%d", type, size[0]); + t = " %d"; + if (soap->version != 2 && offset) + { + (SOAP_SNPRINTF(soap->type, sizeof(soap->type) - 1, strlen(type) + 20), "%s[%d", type, size[0] + offset[0]); for (i = 1; i < dim; i++) - sprintf(soap->type + strlen(soap->type), " %d", size[i]); + { + size_t l = strlen(soap->type); + (SOAP_SNPRINTF(soap->type + l, sizeof(soap->type) - l - 1, 20), t, size[i] + offset[i]); + } } else - { if (offset) - { sprintf(soap->type, "%s[%d", type, size[0] + offset[0]); - for (i = 1; i < dim; i++) - sprintf(soap->type + strlen(soap->type), ",%d", size[i] + offset[i]); - } - else - { sprintf(soap->type, "%s[%d", type, size[0]); - for (i = 1; i < dim; i++) - sprintf(soap->type + strlen(soap->type), ",%d", size[i]); + { + (SOAP_SNPRINTF(soap->type, sizeof(soap->type) - 1, strlen(type) + 20), "%s[%d", type, size[0]); + for (i = 1; i < dim; i++) + { + size_t l = strlen(soap->type); + (SOAP_SNPRINTF(soap->type + l, sizeof(soap->type) - l - 1, 20), t, size[i]); } - strcat(soap->type, "]"); } + soap_strcat(soap->type, sizeof(soap->type), "]"); return soap->type; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 char * SOAP_FMAC2 -soap_putoffset(struct soap *soap, int offset) -{ return soap_putoffsets(soap, &offset, 1); +soap_putoffsets(struct soap *soap, const int *offset, int dim) +{ + int i; + soap->arrayOffset[0] = '\0'; + if (soap->version == 1) + { + (SOAP_SNPRINTF(soap->arrayOffset, sizeof(soap->arrayOffset) - 1, 20), "[%d", offset[0]); + for (i = 1; i < dim; i++) + { + size_t l = strlen(soap->arrayOffset); + (SOAP_SNPRINTF(soap->arrayOffset + l, sizeof(soap->arrayOffset) - l - 1, 20), ",%d", offset[i]); + } + soap_strcat(soap->arrayOffset, sizeof(soap->arrayOffset), "]"); + } + return soap->arrayOffset; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 -char * +size_t SOAP_FMAC2 -soap_putoffsets(struct soap *soap, const int *offset, int dim) -{ int i; - sprintf(soap->arrayOffset, "[%d", offset[0]); +soap_size(const int *size, int dim) +{ + int i; + size_t n = 0; + if (size[0] <= 0) + return 0; + n = (size_t)size[0]; for (i = 1; i < dim; i++) - sprintf(soap->arrayOffset + strlen(soap->arrayOffset), ",%d", offset[i]); - strcat(soap->arrayOffset, "]"); - return soap->arrayOffset; + { + if (size[i] <= 0) + return 0; + n *= (size_t)size[i]; + } + return (size_t)n; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 -int +size_t SOAP_FMAC2 -soap_size(const int *size, int dim) -{ int i, n = size[0]; - for (i = 1; i < dim; i++) - n *= size[i]; +soap_getsizes(const char *attr, int *size, int dim) +{ + size_t i, k, n; + if (!attr || !*attr || dim < 1) /* actually attr != NULL and dim is guaranteed >= 1 by soapcpp2-generated code */ + return 0; + i = strlen(attr); + n = 1; + do + { + for (; i > 0; i--) + if (attr[i - 1] == '[' || attr[i - 1] == ',' || attr[i - 1] == ' ') + break; + n *= k = (size_t)soap_strtoul(attr + i, NULL, 10); + size[--dim] = (int)k; + if (n > SOAP_MAXARRAYSIZE) + return 0; + } while (dim > 0 && i-- > 1 && attr[i] != '['); return n; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 soap_getoffsets(const char *attr, const int *size, int *offset, int dim) -{ int i, j = 0; +{ + int i, j = 0; if (offset) + { for (i = 0; i < dim && attr && *attr; i++) - { attr++; + { + attr++; j *= size[i]; - j += offset[i] = (int)atol(attr); + j += offset[i] = (int)soap_strtol(attr, NULL, 10); attr = strchr(attr, ','); } + } else + { for (i = 0; i < dim && attr && *attr; i++) - { attr++; + { + attr++; j *= size[i]; - j += (int)atol(attr); + j += (int)soap_strtol(attr, NULL, 10); attr = strchr(attr, ','); } - return j; -} -#endif - -/******************************************************************************/ -#ifndef PALM_2 -SOAP_FMAC1 -int -SOAP_FMAC2 -soap_getsize(const char *attr1, const char *attr2, int *j) -{ int n, k; - char *s; - *j = 0; - if (!*attr1) - return -1; - if (*attr1 == '[') - attr1++; - n = 1; - for (;;) - { k = (int)soap_strtol(attr1, &s, 10); - n *= k; - if (k < 0 || n > SOAP_MAXARRAYSIZE || s == attr1) - return -1; - attr1 = strchr(s, ','); - if (!attr1) - attr1 = strchr(s, ' '); - if (attr2 && *attr2) - { attr2++; - *j *= k; - k = (int)soap_strtol(attr2, &s, 10); - *j += k; - if (k < 0) - return -1; - attr2 = s; - } - if (!attr1) - break; - attr1++; } - return n - *j; + return j; } -#endif /******************************************************************************/ -#ifndef PALM_2 -SOAP_FMAC1 -int -SOAP_FMAC2 -soap_getsizes(const char *attr, int *size, int dim) -{ int i, k, n; - if (!*attr) - return -1; - i = (int)strlen(attr); - n = 1; - do - { for (i = i-1; i >= 0; i--) - if (attr[i] == '[' || attr[i] == ',' || attr[i] == ' ') - break; - k = (int)atol(attr + i + 1); - n *= size[--dim] = k; - if (k < 0 || n > SOAP_MAXARRAYSIZE) - return -1; - } while (i >= 0 && attr[i] != '['); - return n; -} -#endif -/******************************************************************************/ -#ifndef PALM_2 SOAP_FMAC1 int SOAP_FMAC2 soap_getposition(const char *attr, int *pos) -{ int i, n; +{ + int i, n; if (!*attr) return -1; n = 0; i = 1; do - { pos[n++] = (int)atol(attr + i); + { + pos[n++] = (int)soap_strtol(attr + i, NULL, 10); while (attr[i] && attr[i] != ',' && attr[i] != ']') i++; if (attr[i] == ',') @@ -2608,15 +3610,15 @@ soap_getposition(const char *attr, int *pos) } while (n < SOAP_MAXDIMS && attr[i] && attr[i] != ']'); return n; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 struct soap_nlist * SOAP_FMAC2 soap_push_namespace(struct soap *soap, const char *id, const char *ns) -{ struct soap_nlist *np; +{ + struct soap_nlist *np = NULL; struct Namespace *p; short i = -1; size_t n, k; @@ -2624,161 +3626,222 @@ soap_push_namespace(struct soap *soap, const char *id, const char *ns) k = strlen(ns) + 1; p = soap->local_namespaces; if (p) - { for (i = 0; p->id; p++, i++) - { if (p->ns && !strcmp(ns, p->ns)) - { if (p->out) - { SOAP_FREE(soap, p->out); - p->out = NULL; - } + { + for (i = 0; p->id; p++, i++) + { + if (p->ns && !strcmp(ns, p->ns)) break; - } if (p->out) - { if (!strcmp(ns, p->out)) + { + if (!strcmp(ns, p->out)) break; } else if (p->in) - { if (!soap_tag_cmp(ns, p->in)) - { if ((p->out = (char*)SOAP_MALLOC(soap, k))) - strcpy(p->out, ns); + { + if (!soap_tag_cmp(ns, p->in)) + { + if (SOAP_MAXALLOCSIZE <= 0 || k <= SOAP_MAXALLOCSIZE) + p->out = (char*)SOAP_MALLOC(soap, k); + if (p->out) + soap_strcpy(p->out, k, ns); break; } } } - if (!p || !p->id) + if (!p->id) i = -1; } if (i >= 0) k = 0; - np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k); + if (sizeof(struct soap_nlist) + n + k > n && (SOAP_MAXALLOCSIZE <= 0 || sizeof(struct soap_nlist) + n + k <= SOAP_MAXALLOCSIZE)) + np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k); if (!np) - { soap->error = SOAP_EOM; + { + soap->error = SOAP_EOM; return NULL; } np->next = soap->nlist; soap->nlist = np; np->level = soap->level; np->index = i; - strcpy(np->id, id); - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push namespace binding (level=%u) '%s' '%s'\n", soap->level, id, ns)); + soap_strcpy((char*)np->id, n + 1, id); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push namespace binding (level=%u,index=%hd) '%s'='%s'\n", soap->level, i, id, ns)); if (i < 0) - { np->ns = strcpy(np->id + n + 1, ns); + { + np->ns = np->id + n + 1; + soap_strcpy((char*)np->ns, k, ns); DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push NOT OK: no match found for '%s' in namespace mapping table (added to stack anyway)\n", ns)); } else - { np->ns = NULL; + { + np->ns = NULL; DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push OK ('%s' matches '%s' in namespace table)\n", id, p->id)); } return np; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 void SOAP_FMAC2 soap_pop_namespace(struct soap *soap) -{ struct soap_nlist *np, *nq; +{ + struct soap_nlist *np, *nq; for (np = soap->nlist; np && np->level >= soap->level; np = nq) - { nq = np->next; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop namespace binding (level=%u) '%s'\n", soap->level, np->id)); + { + nq = np->next; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop namespace binding (level=%u) '%s' level=%u\n", soap->level, np->id, np->level)); SOAP_FREE(soap, np); } soap->nlist = np; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 soap_match_namespace(struct soap *soap, const char *id1, const char *id2, size_t n1, size_t n2) -{ struct soap_nlist *np = soap->nlist; +{ + struct soap_nlist *np = soap->nlist; + const char *s; while (np && (strncmp(np->id, id1, n1) || np->id[n1])) np = np->next; if (np) - { if (np->index < 0 - || (soap->local_namespaces[np->index].id - && (strncmp(soap->local_namespaces[np->index].id, id2, n2) - || soap->local_namespaces[np->index].id[n2]))) - return SOAP_NAMESPACE; + { + if (!(soap->mode & SOAP_XML_IGNORENS) && (n2 > 0 || !np->ns || *np->ns)) + { + if (np->index < 0 + || ((s = soap->local_namespaces[np->index].id) && (strncmp(s, id2, n2) || (s[n2] && s[n2] != '_')))) + return SOAP_NAMESPACE; + } return SOAP_OK; } - if (n1 == 3 && n1 == n2 && !strncmp(id1, "xml", 3) && !strncmp(id1, id2, 3)) + if (n1 == 0) + return n2 == 0 || (soap->mode & SOAP_XML_IGNORENS) ? SOAP_OK : SOAP_NAMESPACE; + if ((n1 == 3 && n1 == n2 && !strncmp(id1, "xml", 3) && !strncmp(id1, id2, 3)) + || (soap->mode & SOAP_XML_IGNORENS)) return SOAP_OK; return soap->error = SOAP_SYNTAX_ERROR; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 const char* SOAP_FMAC2 -soap_current_namespace(struct soap *soap, const char *tag) -{ struct soap_nlist *np; +soap_current_namespace_tag(struct soap *soap, const char *tag) +{ + struct soap_nlist *np; const char *s; if (!tag || !strncmp(tag, "xml", 3)) return NULL; np = soap->nlist; - if (!(s = strchr(tag, ':'))) - { while (np && *np->id) /* find default namespace, if present */ + s = strchr(tag, ':'); + if (!s) + { + while (np && *np->id) /* find default namespace, if present */ np = np->next; } else - { while (np && (strncmp(np->id, tag, s - tag) || np->id[s - tag])) + { + while (np && (strncmp(np->id, tag, s - tag) || np->id[s - tag])) np = np->next; if (!np) soap->error = SOAP_NAMESPACE; } if (np) - { if (np->index >= 0) + { + if (np->index >= 0) return soap->namespaces[np->index].ns; if (np->ns) + { + s = np->ns; + if (*s) + return soap_strdup(soap, s); + do + np = np->next; + while (np && *np->id); /* find if there is any other default namespace */ + if (np) + return soap_strdup(soap, s); + } + } + return NULL; +} + +/******************************************************************************/ + +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_current_namespace_att(struct soap *soap, const char *tag) +{ + struct soap_nlist *np; + const char *s; + if (!tag || !strncmp(tag, "xml", 3)) + return NULL; + s = strchr(tag, ':'); + if (!s) + return NULL; + np = soap->nlist; + while (np && (strncmp(np->id, tag, s - tag) || np->id[s - tag])) + np = np->next; + if (!np) + soap->error = SOAP_NAMESPACE; + if (np) + { + if (np->index >= 0) + return soap->namespaces[np->index].ns; + if (np->ns && *np->ns) return soap_strdup(soap, np->ns); } return NULL; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 soap_tag_cmp(const char *s, const char *t) -{ for (;;) - { int c1 = *s; +{ + const char *a = NULL; + const char *b = NULL; + for (;;) + { + int c1 = *s; int c2 = *t; if (!c1 || c1 == '"') break; if (c2 != '-') - { if (c1 != c2) - { if (c1 >= 'A' && c1 <= 'Z') + { + if (c1 < c2) + { + if (c1 >= 'A' && c1 <= 'Z') c1 += 'a' - 'A'; + } + else if (c1 > c2) + { if (c2 >= 'A' && c2 <= 'Z') c2 += 'a' - 'A'; } - if (c1 != c2) - { if (c2 != '*') - return 1; + if (c2 == '*') + { c2 = *++t; if (!c2) return 0; - if (c2 >= 'A' && c2 <= 'Z') - c2 += 'a' - 'A'; - for (;;) - { c1 = *s; - if (!c1 || c1 == '"') - break; - if (c1 >= 'A' && c1 <= 'Z') - c1 += 'a' - 'A'; - if (c1 == c2 && !soap_tag_cmp(s + 1, t + 1)) - return 0; - s++; - } - break; + a = s; + b = t; + continue; + } + if (c1 != c2) + { + if (!a) + return 1; + s = ++a; + t = b; + continue; } } s++; @@ -2788,322 +3851,812 @@ soap_tag_cmp(const char *s, const char *t) return 0; return *t; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 soap_match_tag(struct soap *soap, const char *tag1, const char *tag2) -{ const char *s, *t; +{ + const char *s, *t; int err; if (!tag1 || !tag2 || !*tag2) return SOAP_OK; s = strchr(tag1, ':'); t = strchr(tag2, ':'); if (t) - { if (s) - { if (t[1] && SOAP_STRCMP(s + 1, t + 1)) + { + if (s) + { + if (t[1] && SOAP_STRCMP(s + 1, t + 1)) return SOAP_TAG_MISMATCH; - if (t != tag2 && (err = soap_match_namespace(soap, tag1, tag2, s - tag1, t - tag2))) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2)); - if (err == SOAP_NAMESPACE) - return SOAP_TAG_MISMATCH; - return err; + if (t != tag2 && !(soap->mode & SOAP_XML_IGNORENS)) + { + err = soap_match_namespace(soap, tag1, tag2, s - tag1, t - tag2); + if (err) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2)); + if (err == SOAP_NAMESPACE) + return SOAP_TAG_MISMATCH; + return err; + } } } - else if (SOAP_STRCMP(tag1, t + 1)) - { return SOAP_TAG_MISMATCH; - } - else if (t != tag2 && (err = soap_match_namespace(soap, tag1, tag2, 0, t - tag2))) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2)); - if (err == SOAP_NAMESPACE) + else if (!t[1]) + { + if ((soap->mode & SOAP_XML_IGNORENS) || soap_match_namespace(soap, tag1, tag2, 0, t - tag2)) return SOAP_TAG_MISMATCH; - return err; } - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags and (default) namespaces match: '%s' '%s'\n", tag1, tag2)); - return SOAP_OK; - } + else if (SOAP_STRCMP(tag1, t + 1)) + { + return SOAP_TAG_MISMATCH; + } + else if (t != tag2) + { + err = soap_match_namespace(soap, tag1, tag2, 0, t - tag2); + if (err) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2)); + if (err == SOAP_NAMESPACE) + return SOAP_TAG_MISMATCH; + return err; + } + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags and (default) namespaces match: '%s' '%s'\n", tag1, tag2)); + return SOAP_OK; + } if (s) - { if (SOAP_STRCMP(s + 1, tag2)) + { + if (!(soap->mode & SOAP_XML_IGNORENS) || SOAP_STRCMP(s + 1, tag2)) /* always fails (except when ignoring ns) */ return SOAP_TAG_MISMATCH; } - else if (SOAP_STRCMP(tag1, tag2)) + else if (SOAP_STRCMP(tag1, tag2) +#ifndef WITH_NOEMPTYNAMESPACES + || ((soap->mode & SOAP_XML_STRICT) && !(soap->mode & SOAP_XML_IGNORENS) && soap_match_namespace(soap, tag1, tag2, 0, 0)) /* strict checking: default namespace must be null namespace */ +#endif + ) + { return SOAP_TAG_MISMATCH; + } DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags match: '%s' '%s'\n", tag1, tag2)); return SOAP_OK; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 -soap_match_array(struct soap *soap, const char *type) -{ if (*soap->arrayType) - if (soap_match_tag(soap, soap->arrayType, type) - && soap_match_tag(soap, soap->arrayType, "xsd:anyType") - && soap_match_tag(soap, soap->arrayType, "xsd:ur-type") - ) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array type mismatch: '%s' '%s'\n", soap->arrayType, type)); +soap_match_att(struct soap *soap, const char *tag1, const char *tag2) +{ + const char *s, *t; + int err; + if (!tag1 || !tag2 || !*tag2) + return SOAP_OK; + s = strchr(tag1, ':'); + t = strchr(tag2, ':'); + if (t) + { + if (s) + { + if (t[1] && SOAP_STRCMP(s + 1, t + 1)) + return SOAP_TAG_MISMATCH; + if (t != tag2 && !(soap->mode & SOAP_XML_IGNORENS)) + { + err = soap_match_namespace(soap, tag1, tag2, s - tag1, t - tag2); + if (err) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Atts '%s' and '%s' match but namespaces differ\n", tag1, tag2)); + if (err == SOAP_NAMESPACE) + return SOAP_TAG_MISMATCH; + return err; + } + } + } + else if (!t[1] || t != tag2 || SOAP_STRCMP(tag1, t + 1)) + return SOAP_TAG_MISMATCH; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Atts and (default) namespaces match: '%s' '%s'\n", tag1, tag2)); + return SOAP_OK; + } + if (s) + { + if (!(soap->mode & SOAP_XML_IGNORENS) || SOAP_STRCMP(s + 1, tag2)) /* always fails (except when ignoring ns) */ return SOAP_TAG_MISMATCH; + } + else if (SOAP_STRCMP(tag1, tag2)) + return SOAP_TAG_MISMATCH; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Atts match: '%s' '%s'\n", tag1, tag2)); + return SOAP_OK; +} + +/******************************************************************************/ + +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_match_array(struct soap *soap, const char *type) +{ + if (type && *soap->arrayType) + { + if (soap->version == 1 || !strchr(type, '[')) + { + if (soap_match_tag(soap, soap->arrayType, type) + && soap_match_tag(soap, soap->arrayType, "xsd:anyType") + && soap_match_tag(soap, soap->arrayType, "xsd:ur-type")) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SOAP array type mismatch: '%s' '%s'\n", soap->arrayType, type)); + return SOAP_TAG_MISMATCH; + } } + } return SOAP_OK; } -#endif /******************************************************************************\ * - * SSL + * SSL/TLS * \******************************************************************************/ #ifdef WITH_OPENSSL -/******************************************************************************/ -#ifndef PALM_2 SOAP_FMAC1 int SOAP_FMAC2 soap_rand() -{ unsigned char buf[4]; +{ + int r; if (!soap_ssl_init_done) soap_ssl_init(); - RAND_pseudo_bytes(buf, 4); - return *(int*)buf; +#if OPENSSL_VERSION_NUMBER < 0x10100000L + RAND_pseudo_bytes((unsigned char*)&r, sizeof(int)); +#else + RAND_bytes((unsigned char*)&r, sizeof(int)); +#endif + return r; } #endif /******************************************************************************/ -#ifndef PALM_2 + +#if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) || defined(WITH_WOLFSSL) || defined(WITH_SYSTEMSSL) 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) -{ int err; +#endif +{ + int err; soap->keyfile = keyfile; +#if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE) + soap->keyid = keyid; /* vxWorks compatible */ +#endif soap->password = password; soap->cafile = cafile; soap->capath = capath; +#ifdef WITH_OPENSSL soap->dhfile = dhfile; soap->randfile = randfile; + if (!soap->fsslverify) + soap->fsslverify = ssl_verify_callback; +#endif soap->ssl_flags = flags | (dhfile == NULL ? SOAP_SSL_RSA : 0); - if (!(err = soap->fsslauth(soap))) - { if (sid) +#ifdef WITH_GNUTLS + (void)randfile; (void)sid; + if (dhfile) + { + char *s = NULL; + int n = (int)soap_strtoul(dhfile, &s, 10); + if (!soap->dh_params) + gnutls_dh_params_init(&soap->dh_params); + /* 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') + gnutls_dh_params_generate2(soap->dh_params, (unsigned int)n); + else + { + unsigned int dparams_len; + unsigned char dparams_buf[1024]; + FILE *fd = fopen(dhfile, "r"); + if (!fd) + return soap_set_receiver_error(soap, "SSL/TLS error", "Invalid DH file", SOAP_SSL_ERROR); + dparams_len = (unsigned int)fread(dparams_buf, 1, sizeof(dparams_buf), fd); + fclose(fd); + gnutls_datum_t dparams = { + dparams_buf, dparams_len }; + if (gnutls_dh_params_import_pkcs3(soap->dh_params, &dparams, GNUTLS_X509_FMT_PEM)) + return soap_set_receiver_error(soap, "SSL/TLS error", "Invalid DH file", SOAP_SSL_ERROR); + } + } + else + { +#if GNUTLS_VERSION_NUMBER < 0x030300 + if (!soap->rsa_params) + gnutls_rsa_params_init(&soap->rsa_params); + gnutls_rsa_params_generate2(soap->rsa_params, SOAP_SSL_RSA_BITS); +#endif + } + if (soap->session) + { + gnutls_deinit(soap->session); + soap->session = NULL; + } + if (soap->xcred) + { + gnutls_certificate_free_credentials(soap->xcred); + soap->xcred = NULL; + } +#endif +#ifdef WITH_WOLFSSL + (void)randfile; (void)sid; + if (!soap->fsslverify) + soap->fsslverify = ssl_verify_callback; + if (soap->ctx) + wolfSSL_CTX_free(soap->ctx); + soap->ctx = NULL; +#endif +#ifdef WITH_SYSTEMSSL + (void)randfile; (void)sid; + if (soap->ctx) + gsk_environment_close(&soap->ctx); + soap->ctx = NULL; +#endif + err = soap->fsslauth(soap); +#ifdef WITH_OPENSSL + if (!err) + { + if (sid) SSL_CTX_set_session_id_context(soap->ctx, (unsigned char*)sid, (unsigned int)strlen(sid)); + else + SSL_CTX_set_session_cache_mode(soap->ctx, SSL_SESS_CACHE_OFF); } +#endif return err; } #endif /******************************************************************************/ -#ifndef PALM_2 + +#if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) || defined(WITH_WOLFSSL) || defined(WITH_SYSTEMSSL) 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) -{ soap->keyfile = keyfile; +#endif +{ + soap->keyfile = keyfile; +#if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE) + soap->keyid = keyid; /* vxWorks compatible */ +#endif soap->password = password; soap->cafile = cafile; soap->capath = capath; + soap->ssl_flags = SOAP_SSL_CLIENT | flags; +#ifdef WITH_OPENSSL soap->dhfile = NULL; - soap->ssl_flags = flags; soap->randfile = randfile; - soap->fsslverify = (flags & SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE) == 0 ? ssl_verify_callback : ssl_verify_callback_allow_expired_certificate; + if (!soap->fsslverify) + soap->fsslverify = (flags & SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE) == 0 ? ssl_verify_callback : ssl_verify_callback_allow_expired_certificate; +#endif +#ifdef WITH_GNUTLS + (void)randfile; + if (soap->session) + { + gnutls_deinit(soap->session); + soap->session = NULL; + } + if (soap->xcred) + { + gnutls_certificate_free_credentials(soap->xcred); + soap->xcred = NULL; + } +#endif +#ifdef WITH_WOLFSSL + (void)randfile; + if (!soap->fsslverify) + soap->fsslverify = (flags & SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE) == 0 ? ssl_verify_callback : ssl_verify_callback_allow_expired_certificate; + if (soap->ctx) + wolfSSL_CTX_free(soap->ctx); + soap->ctx = NULL; +#endif +#ifdef WITH_SYSTEMSSL + (void)randfile; + if (soap->ctx) + gsk_environment_close(&soap->ctx); + soap->ctx = NULL; +#endif return soap->fsslauth(soap); } #endif /******************************************************************************/ -#ifndef PALM_2 + +#if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) || defined(WITH_WOLFSSL) || defined(WITH_SYSTEMSSL) +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_ssl_crl(struct soap *soap, const char *crlfile) +{ +#ifdef WITH_OPENSSL + if (crlfile && soap->ctx) + { +#if OPENSSL_VERSION_NUMBER > 0x00907000L + X509_STORE *store = SSL_CTX_get_cert_store(soap->ctx); + if (*crlfile) + { + int ret; + X509_LOOKUP *lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); + if (!lookup) + return soap_set_receiver_error(soap, "SSL/TLS error", "Can't create X509_LOOKUP object", SOAP_SSL_ERROR); + ret = X509_load_crl_file(lookup, crlfile, X509_FILETYPE_PEM); + if (ret <= 0) + return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CRL PEM file", SOAP_SSL_ERROR); + } + X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); +#endif + } + else + { + soap->crlfile = crlfile; /* activate later when store is available */ + } +#endif +#ifdef WITH_GNUTLS + if (crlfile && soap->xcred) + { + if (*crlfile) + { + if (gnutls_certificate_set_x509_crl_file(soap->xcred, crlfile, GNUTLS_X509_FMT_PEM) < 0) + return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CRL PEM file", SOAP_SSL_ERROR); + } + } + else + { + soap->crlfile = crlfile; /* activate later when xcred is available */ + } +#endif +#ifdef WITH_WOLFSSL + if (crlfile && soap->ctx) + { + if (*crlfile) + { +#if defined(HAVE_CRL) && !defined(NO_FILESYSTEM) + if (wolfSSL_X509_load_crl_file(soap->ctx, crlfile) != SSL_SUCCESS) +#endif + return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CRL PEM file", SOAP_SSL_ERROR); + } + } + else + { + soap->crlfile = crlfile; /* activate later when store is available */ + } +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ + +#if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) || defined(WITH_WOLFSSL) || defined(WITH_SYSTEMSSL) SOAP_FMAC1 void SOAP_FMAC2 soap_ssl_init() -{ /* Note: for MT systems, the main program MUST call soap_ssl_init() before any threads are started */ +{ + /* Note: for multi-threaded applications, the main program should call soap_ssl_init() before any threads are started */ if (!soap_ssl_init_done) - { soap_ssl_init_done = 1; + { + soap_ssl_init_done = 1; +#ifdef WITH_OPENSSL +#if OPENSSL_VERSION_NUMBER < 0x10100000L SSL_library_init(); + OpenSSL_add_all_algorithms(); /* we keep ciphers and digests for the program's lifetime */ #ifndef WITH_LEAN SSL_load_error_strings(); #endif +#endif +#if !defined(WIN32) && !defined(CYGWIN) && !defined(__MINGW32__) && !defined(__MINGW64__) && !defined(VXWORKS) if (!RAND_load_file("/dev/urandom", 1024)) - { char buf[1024]; +#else + if (1) +#endif + { + /* if /dev/urandom does not exist we need to do at least some pertubations to seed the OpenSSL PRNG */ + char buf[1024]; RAND_seed(buf, sizeof(buf)); - while (!RAND_status()) - { int r = rand(); +#ifdef HAVE_RANDOM + srandom((unsigned long)time(NULL)); +#else + srand((unsigned int)time(NULL)); +#endif + do + { +#ifdef HAVE_RANDOM + long r = random(); /* we actually do no use random() anywhere, except to further seed the OpenSSL PRNG */ + RAND_seed(&r, sizeof(long)); +#else + int r = rand(); /* we actually do no use rand() anywhere, except when random() is not available and to further seed the OpenSSL PRNG */ RAND_seed(&r, sizeof(int)); - } +#endif + } while (!RAND_status()); } +#endif +#ifdef WITH_GNUTLS +# if GNUTLS_VERSION_NUMBER < 0x020b00 +# if defined(HAVE_PTHREAD_H) + gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); +# elif defined(HAVE_PTH_H) + gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth); +# endif + gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM, 0); + gcry_control(GCRYCTL_DISABLE_SECMEM, 0); + gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); /* libgcrypt init done */ +# endif +# if GNUTLS_VERSION_NUMBER < 0x030300 + gnutls_global_init(); +# endif +#endif +#ifdef WITH_WOLFSSL + wolfSSL_Init(); +#endif } } #endif /******************************************************************************/ -#ifndef PALM_1 + +#if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) || defined(WITH_WOLFSSL) || defined(WITH_SYSTEMSSL) +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_ssl_noinit() +{ + /* Call this first to bypass SSL init is SSL is already initialized elsewhere */ + soap_ssl_init_done = 1; +} +#endif + +/******************************************************************************/ + +#if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) || defined(WITH_WOLFSSL) SOAP_FMAC1 const char * SOAP_FMAC2 -soap_ssl_error(struct soap *soap, int ret) -{ int err = SSL_get_error(soap->ssl, ret); +soap_ssl_error(struct soap *soap, int ret, int err) +{ +#ifdef WITH_OPENSSL const char *msg = soap_code_str(h_ssl_error_codes, err); - if (msg) - strcpy(soap->msgbuf, msg); - else + if (!msg) return ERR_error_string(err, soap->msgbuf); + (SOAP_SNPRINTF(soap->msgbuf, sizeof(soap->msgbuf), strlen(msg) + 1), "%s\n", msg); if (ERR_peek_error()) - { unsigned long r; - strcat(soap->msgbuf, "\n"); + { + unsigned long r; while ((r = ERR_get_error())) - ERR_error_string_n(r, soap->msgbuf + strlen(soap->msgbuf), sizeof(soap->msgbuf) - strlen(soap->msgbuf)); + { + size_t l = strlen(soap->msgbuf); + ERR_error_string_n(r, soap->msgbuf + l, sizeof(soap->msgbuf) - l); + l = strlen(soap->msgbuf); + if (l + 1 < sizeof(soap->msgbuf)) + { + soap->msgbuf[l++] = '\n'; + soap->msgbuf[l] = '\0'; + } + if (ERR_GET_REASON(r) == SSL_R_CERTIFICATE_VERIFY_FAILED && l < sizeof(soap->msgbuf)) + { + const char *s = X509_verify_cert_error_string(SSL_get_verify_result(soap->ssl)); + (SOAP_SNPRINTF(soap->msgbuf + l, sizeof(soap->msgbuf) - l, strlen(s)), "%s", s); + } + } } else - { switch (ret) - { case 0: - strcpy(soap->msgbuf, "EOF was observed that violates the protocol. The client probably provided invalid authentication information."); + { + size_t l = strlen(soap->msgbuf); + switch (ret) + { + case 0: + soap_strcpy(soap->msgbuf + l, sizeof(soap->msgbuf) - l, "EOF was observed that violates the SSL/TLS protocol. The client probably provided invalid authentication information."); break; case -1: - sprintf(soap->msgbuf, "Error observed by underlying BIO: %s", strerror(errno)); + { + const char *s = strerror(soap_errno); + (SOAP_SNPRINTF(soap->msgbuf + l, sizeof(soap->msgbuf) - l, strlen(s) + 42), "Error observed by underlying SSL/TLS BIO: %s", s); + } break; } } + ERR_clear_error(); return soap->msgbuf; +#endif +#ifdef WITH_GNUTLS + (void)soap; + (void)err; + return gnutls_strerror(ret); +#endif +#ifdef WITH_WOLFSSL + err = wolfSSL_get_error(soap->ssl, ret); + return wolfSSL_ERR_error_string(err, soap->msgbuf); /* msgbuf size is at least 80 bytes (>=1024) */ +#endif } #endif /******************************************************************************/ -#ifndef PALM_1 + +#ifdef WITH_SYSTEMSSL static int -ssl_password(char *buf, int num, int rwflag, void *userdata) -{ if (num < (int)strlen((char*)userdata) + 1) - return 0; - return (int)strlen(strcpy(buf, (char*)userdata)); +ssl_recv(int sk, void *s, int n, char *user) +{ + (void)user; + return recv(sk, s, n, 0); } #endif /******************************************************************************/ -/* This callback is included for future references. It should not be deleted -#ifndef PALM_2 -static DH * -ssl_tmp_dh(SSL *ssl, int is_export, int keylength) -{ static DH *dh512 = NULL; - static DH *dh1024 = NULL; - DH *dh; - switch (keylength) - { case 512: - if (!dh512) - { BIO *bio = BIO_new_file("dh512.pem", "r"); - if (bio) - { dh512 = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); - BIO_free(bio); - return dh512; - } - } - else - return dh512; - default: - if (!dh1024) - { BIO *bio = BIO_new_file("dh1024.pem", "r"); - if (bio) - { dh1024 = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); - BIO_free(bio); - } - } - dh = dh1024; - } - return dh; + +#ifdef WITH_SYSTEMSSL +static int +ssl_send(int sk, void *s, int n, char *user) +{ + (void)user; + return send(sk, s, n, 0); } #endif -*/ /******************************************************************************/ -#ifndef PALM_1 + +#if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) || defined(WITH_WOLFSSL) || defined(WITH_SYSTEMSSL) static int ssl_auth_init(struct soap *soap) -{ long flags; +{ +#ifdef WITH_OPENSSL +#if OPENSSL_VERSION_NUMBER >= 0x10101000L + int minv = 0, maxv = 0; +#endif + long flags = SSL_OP_ALL; int mode; +#if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE) + EVP_PKEY* pkey; /* vxWorks compatible */ +#endif if (!soap_ssl_init_done) soap_ssl_init(); ERR_clear_error(); if (!soap->ctx) - { if (!(soap->ctx = SSL_CTX_new(SSLv23_method()))) - return soap_set_receiver_error(soap, "SSL error", "Can't setup context", SOAP_SSL_ERROR); - /* Alters the behavior of SSL read/write: + { +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + /* TLS_method: a TLS/SSL connection established may understand the SSLv3, TLSv1, TLSv1.1, TLSv1.2 and TLSv1.3 protocols. */ + soap->ctx = SSL_CTX_new(TLS_method()); +#else + /* SSLv23_method: a TLS/SSL connection established may understand the SSLv3, TLSv1, TLSv1.1 and TLSv1.2 protocols. */ + soap->ctx = SSL_CTX_new(SSLv23_method()); +#endif + if (!soap->ctx) + return soap_set_receiver_error(soap, "SSL/TLS error", "Can't setup context", SOAP_SSL_ERROR); + /* The following alters the behavior of SSL read/write: */ +#if 0 SSL_CTX_set_mode(soap->ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY); - */ +#endif } if (soap->randfile) - { if (!RAND_load_file(soap->randfile, -1)) - return soap_set_receiver_error(soap, "SSL error", "Can't load randomness", SOAP_SSL_ERROR); + { + if (!RAND_load_file(soap->randfile, -1)) + return soap_set_receiver_error(soap, "SSL/TLS error", "Can't load randomness", SOAP_SSL_ERROR); } if (soap->cafile || soap->capath) - { if (!SSL_CTX_load_verify_locations(soap->ctx, soap->cafile, soap->capath)) - return soap_set_receiver_error(soap, "SSL error", "Can't read CA file and directory", SOAP_SSL_ERROR); + { + if (!SSL_CTX_load_verify_locations(soap->ctx, soap->cafile, soap->capath)) + return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CA PEM file", SOAP_SSL_ERROR); if (soap->cafile && (soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION)) SSL_CTX_set_client_CA_list(soap->ctx, SSL_load_client_CA_file(soap->cafile)); } if (!(soap->ssl_flags & SOAP_SSL_NO_DEFAULT_CA_PATH)) - { if (!SSL_CTX_set_default_verify_paths(soap->ctx)) - return soap_set_receiver_error(soap, "SSL error", "Can't read default CA file and/or directory", SOAP_SSL_ERROR); + { + if (!SSL_CTX_set_default_verify_paths(soap->ctx)) + return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read default CA PEM file and/or directory", SOAP_SSL_ERROR); + } + if (soap->crlfile) + { + if (soap_ssl_crl(soap, soap->crlfile)) + return soap->error; } -/* This code assumes a typical scenario, see alternative code below */ +/* This code assumes a typical scenario with key and cert combined in one PEM file */ +#if 1 if (soap->keyfile) - { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile)) - return soap_set_receiver_error(soap, "SSL error", "Can't read certificate key file", SOAP_SSL_ERROR); + { + if (SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile) != 1) + return soap_set_receiver_error(soap, "SSL/TLS error", "Can't find or read certificate in private key PEM file", SOAP_SSL_ERROR); if (soap->password) - { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password); + { + SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password); SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password); } - if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM)) - return soap_set_receiver_error(soap, "SSL 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) != 1) + return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read private key PEM file", SOAP_SSL_ERROR); +#endif } -/* Suggested alternative approach to check the key file for certs (cafile=NULL): +#else +/* Alternative approach to check the key file for cert only when cafile==NULL */ +#ifndef WM_SECURE_KEY_STORAGE if (soap->password) - { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password); + { + SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password); SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password); } - if (!soap->cafile || !SSL_CTX_use_certificate_chain_file(soap->ctx, soap->cafile)) - { if (soap->keyfile) - { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile)) - return soap_set_receiver_error(soap, "SSL error", "Can't read certificate or key file", SOAP_SSL_ERROR); - if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM)) - return soap_set_receiver_error(soap, "SSL error", "Can't read key file", SOAP_SSL_ERROR); +#endif + if (!soap->cafile) + { + if (soap->keyfile) + { + if (SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile) != 1) + return soap_set_receiver_error(soap, "SSL/TLS error", "Can't find or read certificate in private key PEM file", SOAP_SSL_ERROR); +#ifndef WM_SECURE_KEY_STORAGE + if (SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM) != 1) + return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read private key PEM file", SOAP_SSL_ERROR); +#endif } } -*/ + else /* use cafile for the root CA and (server) cert, and keyfile for (server) key */ + { + if (SSL_CTX_use_certificate_chain_file(soap->ctx, soap->cafile) != 1) + return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CA PEM file", SOAP_SSL_ERROR); +#ifndef WM_SECURE_KEY_STORAGE + if (soap->keyfile) + if (SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM) != 1) + return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read private key PEM file", SOAP_SSL_ERROR); +#endif + } +#endif +#if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE) + /* vxWorks compatible */ + pkey = ipcom_key_db_pkey_get(soap->keyid); + if (!pkey) + return soap_set_receiver_error(soap, "SSL error", "Can't find key", SOAP_SSL_ERROR); + if (!SSL_CTX_use_PrivateKey(soap->ctx, pkey)) + return soap_set_receiver_error(soap, "SSL error", "Can't read key", SOAP_SSL_ERROR); +#endif if ((soap->ssl_flags & SOAP_SSL_RSA)) - { RSA *rsa = RSA_generate_key(1024, RSA_F4, NULL, NULL); - if (!SSL_CTX_set_tmp_rsa(soap->ctx, rsa)) - { if (rsa) + { + /* OpenSSL v3 deprecated low-level RSA key generation: ignore SOAP_SSL_RSA flag */ +#if OPENSSL_VERSION_NUMBER < 0x30000000L +#if OPENSSL_VERSION_NUMBER >= 0x10002000L + if (SSL_CTX_need_tmp_RSA(soap->ctx)) + { + unsigned long e = RSA_F4; + BIGNUM *bne = BN_new(); + RSA *rsa = RSA_new(); + if (!bne || !rsa || !BN_set_word(bne, e) || !RSA_generate_key_ex(rsa, SOAP_SSL_RSA_BITS, bne, NULL) || !SSL_CTX_set_tmp_rsa(soap->ctx, rsa)) + { + if (bne) + BN_free(bne); + if (rsa) + RSA_free(rsa); + return soap_set_receiver_error(soap, "SSL/TLS error", "Can't generate RSA key", SOAP_SSL_ERROR); + } + BN_free(bne); + RSA_free(rsa); + } +#else + RSA *rsa = RSA_generate_key(SOAP_SSL_RSA_BITS, RSA_F4, NULL, NULL); + if (!rsa || !SSL_CTX_set_tmp_rsa(soap->ctx, rsa)) + { + if (rsa) RSA_free(rsa); - return soap_set_receiver_error(soap, "SSL error", "Can't set RSA key", SOAP_SSL_ERROR); + return soap_set_receiver_error(soap, "SSL/TLS error", "Can't generate RSA key", SOAP_SSL_ERROR); } RSA_free(rsa); +#endif +#endif } else if (soap->dhfile) - { DH *dh = 0; - BIO *bio; - bio = BIO_new_file(soap->dhfile, "r"); - if (!bio) - return soap_set_receiver_error(soap, "SSL error", "Can't read DH file", SOAP_SSL_ERROR); - dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); - BIO_free(bio); - if (SSL_CTX_set_tmp_dh(soap->ctx, dh) < 0) - { if (dh) + { + char *s = (char*)soap->dhfile; + int n = (int)soap_strtoul(soap->dhfile, &s, 10); +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + /* if dhfile is numeric, set auto DH selection regardless of the value of n */ + if (n >= 1 && *s == '\0') + { + if (!SSL_CTX_set_dh_auto(soap->ctx, 1)) + return soap_set_receiver_error(soap, "SSL/TLS error", "Can't generate DH parameters", SOAP_SSL_ERROR); + } + else + { + EVP_PKEY *dh; + BIO *bio = BIO_new_file(soap->dhfile, "r"); + if (!bio) + return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read DH PEM file", SOAP_SSL_ERROR); + dh = PEM_read_bio_Parameters(bio, NULL); + BIO_free(bio); + if (!dh || !SSL_CTX_set0_tmp_dh_pkey(soap->ctx, dh)) + { + if (dh) + EVP_PKEY_free(dh); + return soap_set_receiver_error(soap, "SSL/TLS error", "Can't set DH parameters", SOAP_SSL_ERROR); + } + } +#else + DH *dh = NULL; + /* if dhfile is numeric, treat it as a key length to generate DH params which can take a while */ + if (n >= 512 && *s == '\0') + { +#if OPENSSL_VERSION_NUMBER >= 0x10002000L + dh = DH_new(); + if (!DH_generate_parameters_ex(dh, n, 2/*or 5*/, NULL)) + { + DH_free(dh); + return soap_set_receiver_error(soap, "SSL/TLS error", "Can't generate DH parameters", SOAP_SSL_ERROR); + } +#elif defined(VXWORKS) + dh = DH_new(); + 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"); + if (!bio) + return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read DH PEM file", SOAP_SSL_ERROR); + dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + } + if (!dh || !DH_check(dh, &n) || !SSL_CTX_set_tmp_dh(soap->ctx, dh)) + { + if (dh) DH_free(dh); - return soap_set_receiver_error(soap, "SSL error", "Can't set DH parameters", SOAP_SSL_ERROR); + return soap_set_receiver_error(soap, "SSL/TLS error", "Can't set DH parameters", SOAP_SSL_ERROR); } DH_free(dh); +#endif } - flags = (SSL_OP_ALL | SSL_OP_NO_SSLv2); + /* enable all TSLv1 protocols and disable SSLv3 by default if no SSL/TLS flags are set */ + if ((soap->ssl_flags & SOAP_SSLv3_TLSv1) == 0) + soap->ssl_flags |= SOAP_TLSv1; +#if OPENSSL_VERSION_NUMBER >= 0x10101000L if ((soap->ssl_flags & SOAP_SSLv3)) - flags |= SSL_OP_NO_TLSv1; - if ((soap->ssl_flags & SOAP_TLSv1)) + minv = SSL3_VERSION; + else if ((soap->ssl_flags & SOAP_TLSv1_0)) + minv = TLS1_VERSION; + else if ((soap->ssl_flags & SOAP_TLSv1_1)) + minv = TLS1_1_VERSION; + else if ((soap->ssl_flags & SOAP_TLSv1_2)) + minv = TLS1_2_VERSION; + else if ((soap->ssl_flags & SOAP_TLSv1_3)) + minv = TLS1_3_VERSION; + if ((soap->ssl_flags & SOAP_TLSv1_3) && OpenSSL_version_num() >= 0x10101000L) + maxv = TLS1_3_VERSION; + else if ((soap->ssl_flags & SOAP_TLSv1_2)) + maxv = TLS1_2_VERSION; + else if ((soap->ssl_flags & SOAP_TLSv1_1)) + maxv = TLS1_1_VERSION; + else if ((soap->ssl_flags & SOAP_TLSv1_0)) + maxv = TLS1_VERSION; + else + maxv = SSL3_VERSION; + if (!SSL_CTX_set_min_proto_version(soap->ctx, minv) + || !SSL_CTX_set_max_proto_version(soap->ctx, maxv)) + return soap_set_receiver_error(soap, "SSL/TLS error", "Can't set protocol version", SOAP_SSL_ERROR); +#else + /* disable SSL v2 by default and enable specific protos */ + flags = SSL_OP_NO_SSLv2; + if (!(soap->ssl_flags & SOAP_SSLv3)) flags |= SSL_OP_NO_SSLv3; +#if OPENSSL_VERSION_NUMBER >= 0x10001000L + if (!(soap->ssl_flags & SOAP_TLSv1_0)) + flags |= SSL_OP_NO_TLSv1; + if (!(soap->ssl_flags & SOAP_TLSv1_1)) + flags |= SSL_OP_NO_TLSv1_1; + if (!(soap->ssl_flags & SOAP_TLSv1_2)) + flags |= SSL_OP_NO_TLSv1_2; +#endif +#endif #ifdef SSL_OP_NO_TICKET - /* TLS extension is enabled by default in OPENSSL v0.9.8k - Disable it by adding SSL_OP_NO_TICKET */ + /* TLS extension is enabled by default in OPENSSL v0.9.8k disable it by */ flags |= SSL_OP_NO_TICKET; #endif SSL_CTX_set_options(soap->ctx, flags); @@ -3114,306 +4667,766 @@ ssl_auth_init(struct soap *soap) else mode = SSL_VERIFY_NONE; SSL_CTX_set_verify(soap->ctx, mode, soap->fsslverify); -#if (OPENSSL_VERSION_NUMBER < 0x00905100L) +#if OPENSSL_VERSION_NUMBER < 0x00905100L SSL_CTX_set_verify_depth(soap->ctx, 1); #else SSL_CTX_set_verify_depth(soap->ctx, 9); +#endif +#endif +#ifdef WITH_GNUTLS + int ret; + char priority[80]; + soap_strcpy(priority, sizeof(priority), "PERFORMANCE"); + if (!soap_ssl_init_done) + soap_ssl_init(); + if (!soap->xcred) + { + if (gnutls_certificate_allocate_credentials(&soap->xcred) != GNUTLS_E_SUCCESS) + return soap_set_receiver_error(soap, "SSL/TLS error", "Can't allocate credentials or trust", SOAP_SSL_ERROR); +#if GNUTLS_VERSION_NUMBER >= 0x030300 + gnutls_certificate_set_x509_system_trust(soap->xcred); +#endif + if (soap->cafile) + { + if (gnutls_certificate_set_x509_trust_file(soap->xcred, soap->cafile, GNUTLS_X509_FMT_PEM) < 0) + return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CA PEM file", SOAP_SSL_ERROR); + } + if (soap->crlfile) + { + if (soap_ssl_crl(soap, soap->crlfile)) + return soap->error; + } + if (soap->keyfile) + { + if (gnutls_certificate_set_x509_key_file2(soap->xcred, soap->keyfile, soap->keyfile, GNUTLS_X509_FMT_PEM, soap->password, GNUTLS_PKCS_PKCS12_3DES | GNUTLS_PKCS_PKCS12_ARCFOUR | GNUTLS_PKCS_PKCS12_RC2_40 | GNUTLS_PKCS_PBES2_AES_128 | GNUTLS_PKCS_PBES2_AES_192 | GNUTLS_PKCS_PBES2_AES_256 | GNUTLS_PKCS_PBES2_DES) < 0) /* Assumes that key and cert(s) are concatenated in the keyfile and the key is encrypted with one of these algorithms */ + return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read private key PEM file", SOAP_SSL_ERROR); + } + } + if ((soap->ssl_flags & SOAP_SSL_CLIENT)) + { + gnutls_init(&soap->session, GNUTLS_CLIENT); + if (soap->cafile || soap->crlfile || soap->keyfile) + { + ret = gnutls_priority_set_direct(soap->session, "PERFORMANCE", NULL); + if (ret != GNUTLS_E_SUCCESS) + return soap_set_receiver_error(soap, soap_ssl_error(soap, ret, 0), "SSL/TLS set priority error", SOAP_SSL_ERROR); + gnutls_credentials_set(soap->session, GNUTLS_CRD_CERTIFICATE, soap->xcred); + } + else + { + if (!soap->acred) + gnutls_anon_allocate_client_credentials(&soap->acred); + ret = gnutls_priority_set_direct(soap->session, "PERFORMANCE:+ANON-DH:!ARCFOUR-128", NULL); + if (ret != GNUTLS_E_SUCCESS) + return soap_set_receiver_error(soap, soap_ssl_error(soap, ret, 0), "SSL/TLS set priority error", SOAP_SSL_ERROR); + gnutls_credentials_set(soap->session, GNUTLS_CRD_ANON, soap->acred); + } + } + else if (!soap->keyfile) + { + return soap_set_receiver_error(soap, "SSL/TLS error", "No key file: anonymous server authentication not supported in this release", SOAP_SSL_ERROR); + } + else + { +#if GNUTLS_VERSION_NUMBER < 0x030300 + int protocol_priority[] = { 0, 0, 0, 0, 0 }; + int *protocol = protocol_priority; + if ((soap->ssl_flags & SOAP_SSL_RSA) && soap->rsa_params) + gnutls_certificate_set_rsa_export_params(soap->xcred, soap->rsa_params); +#endif + if (!(soap->ssl_flags & SOAP_SSL_RSA) && soap->dh_params) + gnutls_certificate_set_dh_params(soap->xcred, soap->dh_params); + if (!soap->cache) + gnutls_priority_init(&soap->cache, "NORMAL", NULL); + gnutls_init(&soap->session, GNUTLS_SERVER); + gnutls_priority_set(soap->session, soap->cache); + gnutls_credentials_set(soap->session, GNUTLS_CRD_CERTIFICATE, soap->xcred); + if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION)) + gnutls_certificate_server_set_request(soap->session, GNUTLS_CERT_REQUEST); + gnutls_session_enable_compatibility_mode(soap->session); + /* enable all TSLv1 protocols and disable SSLv3 by default if no SSL/TLS flags are set */ + if ((soap->ssl_flags & SOAP_SSLv3_TLSv1) == 0) + soap->ssl_flags |= SOAP_TLSv1; +#if GNUTLS_VERSION_NUMBER < 0x030300 + if ((soap->ssl_flags & SOAP_SSLv3)) + *protocol++ = GNUTLS_SSL3; + if ((soap->ssl_flags & SOAP_TLSv1_0)) + *protocol++ = GNUTLS_TLS1_0; + if ((soap->ssl_flags & SOAP_TLSv1_1)) + *protocol++ = GNUTLS_TLS1_1; + if ((soap->ssl_flags & SOAP_TLSv1_2)) + *protocol++ = GNUTLS_TLS1_2; + if (gnutls_protocol_set_priority(soap->session, protocol_priority) != GNUTLS_E_SUCCESS) + return soap_set_receiver_error(soap, "SSL/TLS error", "Can't set protocol", SOAP_SSL_ERROR); +#else + soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), "NORMAL:+VERS-ALL"); + if (!(soap->ssl_flags & SOAP_TLSv1_0)) + soap_strcat(soap->tmpbuf, sizeof(soap->tmpbuf), ":-VERS-TLS1.0"); + if (!(soap->ssl_flags & SOAP_TLSv1_1)) + soap_strcat(soap->tmpbuf, sizeof(soap->tmpbuf), ":-VERS-TLS1.1"); + if (!(soap->ssl_flags & SOAP_TLSv1_2)) + soap_strcat(soap->tmpbuf, sizeof(soap->tmpbuf), ":-VERS-TLS1.2"); + if (gnutls_priority_set_direct(soap->session, soap->tmpbuf, NULL) != GNUTLS_E_SUCCESS) + return soap_set_receiver_error(soap, "SSL/TLS error", "Can't set protocol priority", SOAP_SSL_ERROR); +#endif + } +#endif +#ifdef WITH_WOLFSSL + WOLFSSL_METHOD *method = NULL; + int verify = WOLFSSL_VERIFY_PEER; + if (soap->ssl_flags & SOAP_SSL_CLIENT) + verify = (soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION) ? WOLFSSL_VERIFY_PEER : SSL_VERIFY_NONE; + else + verify = (soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION) ? SSL_VERIFY_PEER | WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT : SSL_VERIFY_NONE; + /* enable all TSLv1 protocols and disable SSLv3 by default if no SSL/TLS flags are set */ + if ((soap->ssl_flags & SOAP_SSLv3_TLSv1) == 0) + soap->ssl_flags |= SOAP_SSLv3_TLSv1; + if ((soap->ssl_flags & SOAP_SSL_CLIENT)) + { + if ((soap->ssl_flags & SOAP_SSLv3_TLSv1) == SOAP_SSLv3_TLSv1) + method = wolfSSLv23_client_method(); /* select all available protocols */ +#ifdef WOLFSSL_TLS13 + else if ((soap->ssl_flags & SOAP_TLSv1_3)) + method = wolfTLSv1_3_client_method(); /* TLSv1.3 only or upgrade to TLSv1.3 */ +#endif +#ifndef WOLFSSL_NO_TLS12 + else if ((soap->ssl_flags & SOAP_TLSv1_2)) + method = wolfTLSv1_2_client_method(); /* TLSv1.2 only or upgrade to TLSv1.2 */ +#endif +#ifndef NO_OLD_TLS + else if ((soap->ssl_flags & SOAP_TLSv1_1)) + method = wolfTLSv1_1_client_method(); /* TLSv1.1 only or upgrade to TLSv1.1 */ +#endif +#ifdef WOLFSSL_ALLOW_TLSV10 + else if ((soap->ssl_flags & SOAP_TLSv1_0)) + method = wolfTLSv1_client_method(); /* TLSv1.0 only or upgrade to TLSv1.0 */ +#endif +#ifdef WOLFSSL_ALLOW_SSLV3 + else if ((soap->ssl_flags & SOAP_SSLv3)) + method = wolfSSLv3_client_method(); /* SSLv3 only */ +#endif + } + else + { + if ((soap->ssl_flags & SOAP_SSLv3_TLSv1) == SOAP_SSLv3_TLSv1) + method = wolfSSLv23_server_method(); /* select all available protocols */ +#ifdef WOLFSSL_TLS13 + else if ((soap->ssl_flags & SOAP_TLSv1_3)) + method = wolfTLSv1_3_server_method(); /* TLSv1.3 only or upgrade to TLSv1.3 */ +#endif +#ifndef WOLFSSL_NO_TLS12 + else if ((soap->ssl_flags & SOAP_TLSv1_2)) + method = wolfTLSv1_2_server_method(); /* TLSv1.2 only or upgrade to TLSv1.2 */ +#endif +#ifndef NO_OLD_TLS + else if ((soap->ssl_flags & SOAP_TLSv1_1)) + method = wolfTLSv1_1_server_method(); /* TLSv1.1 only or upgrade to TLSv1.1 */ +#endif +#ifdef WOLFSSL_ALLOW_TLSV10 + else if ((soap->ssl_flags & SOAP_TLSv1_0)) + method = wolfTLSv1_server_method(); /* TLSv1.0 only or upgrade to TLSv1.0 */ +#endif +#ifdef WOLFSSL_ALLOW_SSLV3 + else if ((soap->ssl_flags & SOAP_SSLv3)) + method = wolfSSLv3_server_method(); /* SSLv3 only */ +#endif + } + if (!method) + return soap_set_receiver_error(soap, "SSL/TLS error", "Can't setup method, the specified TLS protocol is unsupported", SOAP_SSL_ERROR); + if (soap->ctx) + { + wolfSSL_CTX_free(soap->ctx); + soap->ctx = NULL; + } + soap->ctx = wolfSSL_CTX_new(method); + if (!soap->ctx) + return soap_set_receiver_error(soap, "SSL/TLS error", "Can't setup context", SOAP_SSL_ERROR); + if (soap->cafile || soap->capath) + { + if (wolfSSL_CTX_load_verify_locations(soap->ctx, soap->cafile, soap->capath) != SSL_SUCCESS) + return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CA PEM file", SOAP_SSL_ERROR); + } + if (soap->keyfile) + { + if (wolfSSL_CTX_use_certificate_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM) != SSL_SUCCESS) + return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read server CA PEM file", SOAP_SSL_ERROR); +#ifdef WOLFSSL_ENCRYPTED_KEYS + if (soap->password) + { + wolfSSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password); + wolfSSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password); + } +#else +#warning "Encrypted private keys are not supported, define WOLFSSL_ENCRYPTED_KEYS in WolfSSL build settings to enable" +#endif + if (wolfSSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM) != SSL_SUCCESS) + return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read private key PEM file", SOAP_SSL_ERROR); +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + /* post handshake authentication sets a flag in the ClientHello message, which is required for post-handshake authentication, only when we are connecting as a client */ + if ((soap->ssl_flags & SOAP_TLSv1_3) && (soap->ssl_flags & SOAP_SSL_CLIENT) && wolfSSL_CTX_allow_post_handshake_auth(soap->ctx)) + return soap_set_receiver_error(soap, "SSL/TLS error", "Can't enable post-handshake authentication", SOAP_SSL_ERROR); +#endif + } + if (soap->crlfile) + { + if (soap_ssl_crl(soap, soap->crlfile)) + return soap->error; + } + wolfSSL_CTX_set_verify(soap->ctx, verify, soap->fsslverify); +#endif +#ifdef WITH_SYSTEMSSL + if (!soap->ctx) + { + int err; + err = gsk_environment_open(&soap->ctx); + if (err == GSK_OK) + err = gsk_attribute_set_enum(soap->ctx, GSK_PROTOCOL_SSLV2, GSK_PROTOCOL_SSLV2_OFF); + /* enable all TSLv1 protocols and disable SSLv3 by default if no SSL/TLS flags are set */ + if ((soap->ssl_flags & SOAP_SSLv3_TLSv1) == 0) + soap->ssl_flags |= SOAP_TLSv1; + if (err == GSK_OK) + { + if ((soap->ssl_flags & SOAP_SSLv3)) + err = gsk_attribute_set_enum(soap->ctx, GSK_PROTOCOL_SSLV3, GSK_PROTOCOL_SSLV3_ON); + else + err = gsk_attribute_set_enum(soap->ctx, GSK_PROTOCOL_SSLV3, GSK_PROTOCOL_SSLV3_OFF); + } + if (err == GSK_OK) + { + if ((soap->ssl_flags & SOAP_TLSv1_0)) + err = gsk_attribute_set_enum(soap->ctx, GSK_PROTOCOL_TLSV1, GSK_PROTOCOL_TLSV1_ON); + else + err = gsk_attribute_set_enum(soap->ctx, GSK_PROTOCOL_TLSV1, GSK_PROTOCOL_TLSV1_OFF); + } + if (err == GSK_OK) + { + if ((soap->ssl_flags & SOAP_TLSv1_1)) + err = gsk_attribute_set_enum(soap->ctx, GSK_PROTOCOL_TLSV1, GSK_PROTOCOL_TLSV1_1_ON); + else + err = gsk_attribute_set_enum(soap->ctx, GSK_PROTOCOL_TLSV1, GSK_PROTOCOL_TLSV1_1_OFF); + } + if (err == GSK_OK) + { + if ((soap->ssl_flags & SOAP_TLSv1_2)) + err = gsk_attribute_set_enum(soap->ctx, GSK_PROTOCOL_TLSV1, GSK_PROTOCOL_TLSV1_2_ON); + else + err = gsk_attribute_set_enum(soap->ctx, GSK_PROTOCOL_TLSV1, GSK_PROTOCOL_TLSV1_2_OFF); + } + if (err == GSK_OK) + err = gsk_attribute_set_buffer(soap->ctx, GSK_KEYRING_FILE, soap->keyfile, 0); /* keyfile is a keyring .kdb file */ + if (err == GSK_OK) + err = gsk_attribute_set_buffer(soap->ctx, GSK_KEYRING_PW, soap->password, 0); /* locked by password */ + if (err == GSK_OK) + err = gsk_environment_init(soap->ctx); + if (err != GSK_OK) + return soap_set_receiver_error(soap, gsk_strerror(err), "SYSTEM SSL error in ssl_auth_init()", SOAP_SSL_ERROR); + } #endif return SOAP_OK; } #endif /******************************************************************************/ -#ifndef PALM_1 + +#if defined(WITH_OPENSSL) || defined(WITH_WOLFSSL) +static int +ssl_password(char *buf, int num, int rwflag, void *userdata) +{ + (void)rwflag; + if (!buf || !userdata) + return 0; + soap_strcpy(buf, (size_t)num, (char*)userdata); + return (int)strlen(buf); +} +#endif + +/******************************************************************************/ + +#ifdef WITH_OPENSSL static int ssl_verify_callback(int ok, X509_STORE_CTX *store) { + (void)store; #ifdef SOAP_DEBUG if (!ok) - { char data[256]; + { + int err = X509_STORE_CTX_get_error(store); X509 *cert = X509_STORE_CTX_get_current_cert(store); - fprintf(stderr, "SSL verify error or warning with certificate at depth %d: %s\n", X509_STORE_CTX_get_error_depth(store), X509_verify_cert_error_string(X509_STORE_CTX_get_error(store))); - X509_NAME_oneline(X509_get_issuer_name(cert), data, sizeof(data)); - fprintf(stderr, "certificate issuer %s\n", data); - X509_NAME_oneline(X509_get_subject_name(cert), data, sizeof(data)); - fprintf(stderr, "certificate subject %s\n", data); + fprintf(stderr, "\nDEBUG mode TLS/SSL warnings:\nSSL verify error %d or warning with certificate at depth %d: %s\n", err, X509_STORE_CTX_get_error_depth(store), X509_verify_cert_error_string(err)); + if (cert) + { + char buf[1024]; + X509_NAME_oneline(X509_get_issuer_name(cert), buf, sizeof(buf)-1); + fprintf(stderr, " certificate issuer: %s\n", buf); + X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)-1); + fprintf(stderr, " certificate subject: %s\n", buf); + /* accept self-signed certificates and certificates out of date */ + switch (err) + { + case X509_V_ERR_CERT_NOT_YET_VALID: + case X509_V_ERR_CERT_HAS_EXPIRED: + case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: + case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: + case X509_V_ERR_UNABLE_TO_GET_CRL: + case X509_V_ERR_CRL_NOT_YET_VALID: + case X509_V_ERR_CRL_HAS_EXPIRED: + X509_STORE_CTX_set_error(store, X509_V_OK); + ok = 1; + fprintf(stderr, "Initialize soap_ssl_client_context with SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE to allow this verification error to pass without DEBUG mode enabled\n"); + } + } + else + { + fprintf(stderr, " no certificate in store\n"); + } } #endif - /* Note: return 1 to continue, but unsafe progress will be terminated by SSL */ + /* Note: return 1 to continue, whether it is safe or not to do so is up to you to verify, or 0 to cancel the handshake */ return ok; } #endif /******************************************************************************/ -#ifndef PALM_1 + +#ifdef WITH_OPENSSL static int ssl_verify_callback_allow_expired_certificate(int ok, X509_STORE_CTX *store) -{ ok = ssl_verify_callback(ok, store); - if (ok == 0 && X509_STORE_CTX_get_error(store) == X509_V_ERR_CERT_HAS_EXPIRED) +{ + ok = ssl_verify_callback(ok, store); + if (!ok) + { + /* accept self signed certificates, expired certificates, and certficiates w/o CRL */ + switch (X509_STORE_CTX_get_error(store)) + { + case X509_V_ERR_CERT_NOT_YET_VALID: + case X509_V_ERR_CERT_HAS_EXPIRED: + case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: + case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: + case X509_V_ERR_UNABLE_TO_GET_CRL: + case X509_V_ERR_CRL_NOT_YET_VALID: + case X509_V_ERR_CRL_HAS_EXPIRED: + X509_STORE_CTX_set_error(store, X509_V_OK); + ok = 1; + } + } + /* Note: return 1 to continue, but unsafe progress will be terminated by SSL */ + return ok; +} +#endif + +/******************************************************************************/ + +#ifdef WITH_GNUTLS +static const char * +ssl_verify(struct soap *soap, const char *host) +{ + unsigned int status; + const char *err = NULL; + int r = gnutls_certificate_verify_peers2(soap->session, &status); + if (r < 0) + err = "Certificate verify error"; + else if ((status & GNUTLS_CERT_INVALID)) + err = "The certificate is not trusted"; + else if ((status & GNUTLS_CERT_SIGNER_NOT_FOUND)) + err = "The certificate hasn't got a known issuer"; + else if ((status & GNUTLS_CERT_REVOKED)) + err = "The certificate has been revoked"; + else if (gnutls_certificate_type_get(soap->session) == GNUTLS_CRT_X509) { + gnutls_x509_crt_t cert; + const gnutls_datum_t *cert_list; + unsigned int cert_list_size; + if (gnutls_x509_crt_init(&cert) < 0) + err = "Could not get X509 certificates"; + else if ((cert_list = gnutls_certificate_get_peers(soap->session, &cert_list_size)) == NULL) + err = "Could not get X509 certificates"; + else if (gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0) + err = "Error parsing X509 certificate"; + else if (!(soap->ssl_flags & SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE) && gnutls_x509_crt_get_expiration_time(cert) < time(NULL)) + err = "The certificate has expired"; + else if (!(soap->ssl_flags & SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE) && gnutls_x509_crt_get_activation_time(cert) > time(NULL)) + err = "The certificate is not yet activated"; + else if (host && !(soap->ssl_flags & SOAP_SSL_SKIP_HOST_CHECK)) + { + if (!gnutls_x509_crt_check_hostname(cert, host)) + err = "Certificate host name mismatch"; + } + gnutls_x509_crt_deinit(cert); + } + return err; +} +#endif + +/******************************************************************************/ + +#ifdef WITH_WOLFSSL +static int +ssl_verify_callback(int ok, WOLFSSL_X509_STORE_CTX *store) +{ + (void)store; #ifdef SOAP_DEBUG - fprintf(stderr, "ignoring certificate expiration\n"); + if (!ok) + { + int err = store->error; +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + WOLFSSL_X509 *cert = store->current_cert; + fprintf(stderr, "\nDEBUG mode TLS/SSL warnings:\nSSL verify error %d or warning with certificate at depth %d: %s\n", err, store->error_depth, wolfSSL_X509_verify_cert_error_string(err)); + if (cert) + { + char buf[1024]; + wolfSSL_X509_NAME_oneline(wolfSSL_X509_get_issuer_name(cert), buf, sizeof(buf)-1); + fprintf(stderr, " certificate issuer: %s\n", buf); + wolfSSL_X509_NAME_oneline(wolfSSL_X509_get_subject_name(cert), buf, sizeof(buf)-1); + fprintf(stderr, " certificate subject: %s\n", buf); + } + else + { + fprintf(stderr, " no certificate in store\n"); + } +#else + fprintf(stderr, "\nDEBUG mode TLS/SSL warnings:\nSSL verify error %d or warning with certificate at depth %d\n", err, store->error_depth); #endif - X509_STORE_CTX_set_error(store, X509_V_OK); - ok = 1; } - /* Note: return 1 to continue, but unsafe progress will be terminated by SSL */ +#endif + /* Note: return 1 to continue, whether it is safe or not to do so is up to you to verify, or 0 to cancel the handshake */ + return ok; +} +#endif + +/******************************************************************************/ + +#ifdef WITH_WOLFSSL +static int +ssl_verify_callback_allow_expired_certificate(int ok, WOLFSSL_X509_STORE_CTX *store) +{ + ok = ssl_verify_callback(ok, store); + if (!ok) + { + /* accept expired certificates */ + switch (store->error) + { + case ASN_BEFORE_DATE_E: + case ASN_AFTER_DATE_E: + ok = 1; + } + } + /* Note: return 1 to continue, whether it is safe or not to do so is up to you to verify, or 0 to cancel the handshake */ return ok; } #endif /******************************************************************************/ + +#if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) || defined(WITH_WOLFSSL) || defined(WITH_SYSTEMSSL) #ifndef WITH_NOIO -#ifndef PALM_1 SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_accept(struct soap *soap) -{ BIO *bio; +{ + SOAP_SOCKET sk = soap->socket; +#ifdef WITH_OPENSSL + BIO *bio; + int err = SSL_ERROR_NONE; int retries, r, s; - if (!soap_valid_socket(soap->socket)) - return soap_set_receiver_error(soap, "SSL error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR); - if (!soap->ctx && (soap->error = soap->fsslauth(soap))) - return SOAP_SSL_ERROR; + ERR_clear_error(); + if (!soap_valid_socket(sk)) + return soap_set_receiver_error(soap, "SSL/TLS error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR); + soap->ssl_flags &= ~SOAP_SSL_CLIENT; + if (!soap->ctx && (soap->error = soap->fsslauth(soap)) != SOAP_OK) + return soap_closesock(soap); if (!soap->ssl) - { soap->ssl = SSL_new(soap->ctx); + { + soap->ssl = SSL_new(soap->ctx); if (!soap->ssl) - return soap_set_receiver_error(soap, "SSL error", "SSL_new() failed in soap_ssl_accept()", SOAP_SSL_ERROR); + { + (void)soap_closesock(soap); + return soap_set_receiver_error(soap, "SSL/TLS error", "SSL_new() failed in soap_ssl_accept()", SOAP_SSL_ERROR); + } } else + { SSL_clear(soap->ssl); - soap->imode |= SOAP_ENC_SSL; - soap->omode |= SOAP_ENC_SSL; - /* Set SSL sockets to non-blocking */ - SOAP_SOCKNONBLOCK(soap->socket) - bio = BIO_new_socket((int)soap->socket, BIO_NOCLOSE); + } + bio = BIO_new_socket((int)sk, BIO_NOCLOSE); SSL_set_bio(soap->ssl, bio, bio); - retries = 100; /* SSL_accept timeout: 10 sec retries, 100 times 0.1 sec */ + /* Default timeout: 10 sec retries, 100 times 0.1 sec */ + retries = 100; + if (soap->recv_timeout || soap->send_timeout) + { + int t = soap->recv_timeout > soap->send_timeout ? soap->recv_timeout : soap->send_timeout; + if (t > 0) + retries = 10 * t; + else if (t > -100000) + retries = 1; + else + retries = t/-100000; + } + SOAP_SOCKNONBLOCK(sk) while ((r = SSL_accept(soap->ssl)) <= 0) - { int err = SSL_get_error(soap->ssl, r); + { + err = SSL_get_error(soap->ssl, r); if (err == SSL_ERROR_WANT_ACCEPT || err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) - { if (err == SSL_ERROR_WANT_READ) - s = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000); + { + if (err == SSL_ERROR_WANT_READ) + s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000); else - s = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000); - if (s < 0 && soap->errnum != SOAP_EINTR) + s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000); + if (s < 0) break; } else - { soap->errnum = soap_socket_errno(soap->socket); + { + soap->errnum = soap_socket_errno; break; } if (retries-- <= 0) break; } + if (!soap->recv_timeout && !soap->send_timeout) + SOAP_SOCKBLOCK(sk) if (r <= 0) - { soap_set_receiver_error(soap, soap_ssl_error(soap, r), "SSL_accept() failed in soap_ssl_accept()", SOAP_SSL_ERROR); - soap_closesock(soap); - return SOAP_SSL_ERROR; + { + (void)soap_set_receiver_error(soap, soap_ssl_error(soap, r, err), "SSL_accept() failed in soap_ssl_accept()", SOAP_SSL_ERROR); + return soap_closesock(soap); } if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION)) - { X509 *peer; + { + X509 *peer; int err; if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK) - { soap_closesock(soap); + { + (void)soap_closesock(soap); return soap_set_sender_error(soap, X509_verify_cert_error_string(err), "SSL certificate presented by peer cannot be verified in soap_ssl_accept()", SOAP_SSL_ERROR); } peer = SSL_get_peer_certificate(soap->ssl); if (!peer) - { soap_closesock(soap); - return soap_set_sender_error(soap, "SSL error", "No SSL certificate was presented by the peer in soap_ssl_accept()", SOAP_SSL_ERROR); + { + (void)soap_closesock(soap); + return soap_set_sender_error(soap, "SSL/TLS error", "No SSL certificate was presented by the peer in soap_ssl_accept()", SOAP_SSL_ERROR); } X509_free(peer); } - return SOAP_OK; -} -#endif #endif - -/******************************************************************************/ -#endif /* WITH_OPENSSL */ - -/******************************************************************************/ -#ifndef WITH_NOIO -#ifndef PALM_1 -static int -tcp_init(struct soap *soap) -{ soap->errmode = 1; -#ifdef WIN32 - if (tcp_done) - return 0; - else - { WSADATA w; - if (WSAStartup(MAKEWORD(1, 1), &w)) - return -1; - tcp_done = 1; +#ifdef WITH_GNUTLS + int retries, r, s; + if (!soap_valid_socket(sk)) + return soap_set_receiver_error(soap, "SSL/TLS error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR); + soap->ssl_flags &= ~SOAP_SSL_CLIENT; + if (!soap->session && (soap->error = soap->fsslauth(soap)) != SOAP_OK) + return soap_closesock(soap); + gnutls_transport_set_ptr(soap->session, (gnutls_transport_ptr_t)(long)sk); + /* default timeout: 10 sec retries, 100 times 0.1 sec */ + retries = 100; + if (soap->recv_timeout || soap->send_timeout) + { + int t = soap->recv_timeout > soap->send_timeout ? soap->recv_timeout : soap->send_timeout; + if (t > 0) + retries = 10 * t; + else if (t > -100000) + retries = 1; + else + retries = t/-100000; + } + SOAP_SOCKNONBLOCK(sk) + while ((r = gnutls_handshake(soap->session))) + { + /* GNUTLS repeat handhake when GNUTLS_E_AGAIN */ + if (r == GNUTLS_E_AGAIN || r == GNUTLS_E_INTERRUPTED) + { + if (!gnutls_record_get_direction(soap->session)) + 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) + break; + } + else + { + soap->errnum = soap_socket_errno; + break; + } + if (retries-- <= 0) + break; + } + if (!soap->recv_timeout && !soap->send_timeout) + SOAP_SOCKBLOCK(sk) + if (r) + { + (void)soap_set_receiver_error(soap, soap_ssl_error(soap, r, 0), "SSL/TLS handshake failed", SOAP_SSL_ERROR); + return soap_closesock(soap); + } + if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION)) + { + const char *err = ssl_verify(soap, NULL); + if (err) + { + (void)soap_closesock(soap); + return soap_set_receiver_error(soap, "SSL/TLS error", err, SOAP_SSL_ERROR); + } } #endif - return 0; -} -#endif -#endif - -/******************************************************************************/ -#ifndef PALM_1 -SOAP_FMAC1 -void -SOAP_FMAC2 -soap_done(struct soap *soap) -{ -#ifdef SOAP_DEBUG - int i; -#endif - if (soap_check_state(soap)) - return; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Done with context\n")); - soap_free_temp(soap); - while (soap->clist) - { struct soap_clist *p = soap->clist->next; - SOAP_FREE(soap, soap->clist); - soap->clist = p; - } - if (soap->state == SOAP_INIT) - soap->omode &= ~SOAP_IO_UDP; /* to force close the socket */ - soap->keep_alive = 0; /* to force close the socket */ - soap_closesock(soap); -#ifdef WITH_COOKIES - soap_free_cookies(soap); -#endif - while (soap->plugins) - { struct soap_plugin *p = soap->plugins->next; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Removing plugin '%s'\n", soap->plugins->id)); - if (soap->plugins->fcopy || soap->state == SOAP_INIT) - soap->plugins->fdelete(soap, soap->plugins); - SOAP_FREE(soap, soap->plugins); - soap->plugins = p; - } - soap->fplugin = fplugin; - soap->fmalloc = NULL; -#ifndef WITH_NOHTTP - soap->fpost = http_post; - soap->fget = http_get; - soap->fput = http_405; - soap->fdel = http_405; - soap->fhead = http_405; - soap->fform = NULL; - soap->fposthdr = http_post_header; - soap->fresponse = http_response; - soap->fparse = http_parse; - soap->fparsehdr = http_parse_header; -#endif - soap->fheader = NULL; -#ifndef WITH_NOIO -#ifndef WITH_IPV6 - soap->fresolve = tcp_gethost; -#else - soap->fresolve = NULL; -#endif - soap->faccept = tcp_accept; - soap->fopen = tcp_connect; - soap->fclose = tcp_disconnect; - soap->fclosesocket = tcp_closesocket; - soap->fshutdownsocket = tcp_shutdownsocket; - soap->fsend = fsend; - soap->frecv = frecv; - soap->fpoll = soap_poll; -#else - soap->fopen = NULL; - soap->fclose = NULL; - soap->fpoll = NULL; -#endif -#ifndef WITH_LEANER - soap->fprepareinit = NULL; - soap->fpreparesend = NULL; - soap->fpreparerecv = NULL; - soap->fpreparefinal = NULL; -#endif - soap->fseterror = NULL; - soap->fignore = NULL; - soap->fserveloop = NULL; -#ifdef WITH_OPENSSL - if (soap->session) - { SSL_SESSION_free(soap->session); - soap->session = NULL; - } -#endif - if (soap->state == SOAP_INIT) - { if (soap_valid_socket(soap->master)) - { soap->fclosesocket(soap, soap->master); - soap->master = SOAP_INVALID_SOCKET; +#ifdef WITH_WOLFSSL + int err = SSL_ERROR_NONE; + int retries, r, s; + if (!soap_valid_socket(sk)) + return soap_set_receiver_error(soap, "SSL/TLS error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR); + if (!soap->ssl) + { + soap->ssl = wolfSSL_new(soap->ctx); + if (!soap->ssl) + { + (void)soap_closesock(soap); + return soap_set_receiver_error(soap, "SSL/TLS error", "wolfSSL_new() failed in soap_ssl_accept()", SOAP_SSL_ERROR); } } -#ifdef WITH_OPENSSL - if (soap->ssl) - { SSL_free(soap->ssl); - soap->ssl = NULL; + soap->ssl_flags &= ~SOAP_SSL_CLIENT; + /* default timeout: 10 sec retries, 100 times 0.1 sec */ + retries = 100; + if (soap->recv_timeout || soap->send_timeout) + { + int t = soap->recv_timeout > soap->send_timeout ? soap->recv_timeout : soap->send_timeout; + if (t > 0) + retries = 10 * t; + else if (t > -100000) + retries = 1; + else + retries = t/-100000; } - if (soap->state == SOAP_INIT) - { if (soap->ctx) - { SSL_CTX_free(soap->ctx); - soap->ctx = NULL; + wolfSSL_set_fd(soap->ssl, sk); + SOAP_SOCKNONBLOCK(sk) + while ((r = wolfSSL_accept(soap->ssl)) != SSL_SUCCESS) + { + err = wolfSSL_get_error(soap->ssl, r); + if (err == SSL_ERROR_WANT_ACCEPT || err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) + { + if (err == SSL_ERROR_WANT_READ) + 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) + break; } + else + { + soap->errnum = soap_socket_errno; + break; + } + if (retries-- <= 0) + break; } -#endif -#ifdef WITH_OPENSSL - ERR_remove_state(0); -#endif -#ifdef WITH_C_LOCALE - freelocale(soap->c_locale); -#endif -#ifdef WITH_ZLIB - if (soap->d_stream) - { SOAP_FREE(soap, (void*)soap->d_stream); - soap->d_stream = NULL; - } - if (soap->z_buf) - { SOAP_FREE(soap, (void*)soap->z_buf); - soap->z_buf = NULL; + if (!soap->recv_timeout && !soap->send_timeout) + SOAP_SOCKBLOCK(sk) + if (r != SSL_SUCCESS) + { + (void)soap_set_receiver_error(soap, soap_ssl_error(soap, r, 0), "SSL/TLS handshake failed", SOAP_SSL_ERROR); + return soap_closesock(soap); } #endif -#ifdef SOAP_DEBUG - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free logfiles\n")); - for (i = 0; i < SOAP_MAXLOGS; i++) - { if (soap->logfile[i]) - { SOAP_FREE(soap, (void*)soap->logfile[i]); - soap->logfile[i] = NULL; +#ifdef WITH_SYSTEMSSL + gsk_iocallback local_io = { ssl_recv, ssl_send, NULL, NULL, NULL, NULL }; + int retries, r, s; + if (!soap_valid_socket(sk)) + return soap_set_receiver_error(soap, "SSL/TLS error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR); + soap->ssl_flags &= ~SOAP_SSL_CLIENT; + /* default timeout: 10 sec retries, 100 times 0.1 sec */ + retries = 100; + if (soap->recv_timeout || soap->send_timeout) + { + int t = soap->recv_timeout > soap->send_timeout ? soap->recv_timeout : soap->send_timeout; + if (t > 0) + retries = 10 * t; + else if (t > -100000) + retries = 1; + else + retries = t/-100000; + } + SOAP_SOCKNONBLOCK(sk) + r = gsk_secure_socket_open(soap->ctx, &soap->ssl); + if (r == GSK_OK) + r = gsk_attribute_set_numeric_value(soap->ssl, GSK_FD, sk); + if (r == GSK_OK) + r = gsk_attribute_set_buffer(soap->ssl, GSK_KEYRING_LABEL, soap->cafile, 0); + if (r == GSK_OK) + r = gsk_attribute_set_enum(soap->ssl, GSK_SESSION_TYPE, GSK_SERVER_SESSION); + if (r == GSK_OK) + r = gsk_attribute_set_buffer(soap->ssl, GSK_V3_CIPHER_SPECS_EXPANDED, "0035002F000A", 0); + if (r == GSK_OK) + r = gsk_attribute_set_enum(soap->ssl, GSK_V3_CIPHERS, GSK_V3_CIPHERS_CHAR4); + if (r == GSK_OK) + r = gsk_attribute_set_callback(soap->ssl, GSK_IO_CALLBACK, &local_io); + if (r != GSK_OK) + return soap_set_receiver_error(soap, gsk_strerror(r), "SYSTEM SSL error in soap_ssl_accept()", SOAP_SSL_ERROR); + while ((r = gsk_secure_socket_init(soap->ssl)) != GSK_OK) + { + if (r == GSK_WOULD_BLOCK_READ || r == GSK_WOULD_BLOCK_WRITE) + { + if (r == GSK_WOULD_BLOCK_READ) + 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) + break; } - soap_close_logfile(soap, i); + else + { + soap->errnum = soap_socket_errno; + break; + } + if (retries-- <= 0) + break; + } + if (!soap->recv_timeout && !soap->send_timeout) + SOAP_SOCKBLOCK(sk) + if (r != GSK_OK) + { + (void)soap_set_receiver_error(soap, gsk_strerror(r), "gsk_secure_socket_init() failed in soap_ssl_accept()", SOAP_SSL_ERROR); + return soap_closesock(soap); } - soap->state = SOAP_NONE; -#endif -#ifdef SOAP_MEM_DEBUG - soap_free_mht(soap); #endif + soap->imode |= SOAP_ENC_SSL; + soap->omode |= SOAP_ENC_SSL; + return SOAP_OK; } #endif +#endif + +/******************************************************************************\ + * + * TCP/UDP [SSL/TLS] IPv4 and IPv6 + * +\******************************************************************************/ -/******************************************************************************/ #ifndef WITH_NOIO -#ifndef PALM_2 -SOAP_FMAC1 -void -SOAP_FMAC2 -soap_cleanup(struct soap *soap) -{ soap_done(soap); +static int +tcp_init(struct soap *soap) +{ + soap->errmode = 1; #ifdef WIN32 - if (!tcp_done) - return; - tcp_done = 0; - WSACleanup(); + if (tcp_done) + return 0; + else + { + WSADATA w; + if (WSAStartup(MAKEWORD(1, 1), &w)) + return -1; + tcp_done = 1; + } #endif + return 0; } #endif -#endif /******************************************************************************/ + #ifndef WITH_NOIO -#ifndef PALM_1 static const char* tcp_error(struct soap *soap) -{ const char *msg = NULL; +{ + const char *msg = NULL; switch (soap->errmode) - { case 0: + { + case 0: msg = soap_strerror(soap); break; case 1: @@ -3425,7 +5438,8 @@ 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); + { + (SOAP_SNPRINTF(soap->msgbuf, sizeof(soap->msgbuf), 37), "TCP/UDP IP error %d", soap->errnum); msg = soap->msgbuf; } } @@ -3433,140 +5447,250 @@ tcp_error(struct soap *soap) return msg; } #endif -#endif /******************************************************************************/ -#ifndef WITH_NOHTTP -#ifndef PALM_1 -static const char* -http_error(struct soap *soap, int status) -{ const char *msg = SOAP_STR_EOS; -#ifndef WITH_LEAN - msg = soap_code_str(h_http_error_codes, status); - if (!msg) - msg = SOAP_STR_EOS; -#endif - return msg; -} -#endif -#endif -/******************************************************************************/ -#ifndef WITH_IPV6 +#if !defined(WITH_IPV6) || defined(WITH_COOKIES) #ifndef WITH_NOIO -#ifndef PALM_1 static int -tcp_gethost(struct soap *soap, const char *addr, struct in_addr *inaddr) -{ soap_int32 iadd = -1; - struct hostent hostent, *host = &hostent; -#ifdef VXWORKS - int hostint; - /* inet_addr(), and hostGetByName() expect "char *"; addr is a "const char *". */ - iadd = inet_addr((char*)addr); -#else -#if defined(_AIX43) || ((defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R)) +tcp_gethostbyname(struct soap *soap, const char *addr, struct hostent *hostent, struct in_addr *inaddr) +{ +#if (defined(_AIX43) || defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R) struct hostent_data ht_data; +#elif (!defined(_GNU_SOURCE) || (!(~_GNU_SOURCE+1) && !defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)) || _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 || defined(__ANDROID__) || defined(FREEBSD) || defined(__FreeBSD__)) && !defined(SUN_OS) && !defined(__QNX__) && !defined(QNX) && defined(HAVE_GETHOSTBYNAME_R) + int r; + char *tmpbuf = soap->tmpbuf; + size_t tmplen = sizeof(soap->tmpbuf); +#elif defined(HAVE_GETHOSTBYNAME_R) + char *tmpbuf = soap->tmpbuf; + size_t tmplen = sizeof(soap->tmpbuf); #endif +#ifdef VXWORKS + int hostint; /* vxWorks compatible */ +#endif + if (inaddr) + { + soap_int32 iadd = -1; #ifdef AS400 - iadd = inet_addr((void*)addr); + iadd = inet_addr((void*)addr); #else - iadd = inet_addr(addr); -#endif + iadd = inet_addr((char*)addr); #endif - if (iadd != -1) - { memcpy(inaddr, &iadd, sizeof(iadd)); - return SOAP_OK; + if (iadd != -1) + { + if (soap_memcpy((void*)inaddr, sizeof(struct in_addr), (const void*)&iadd, sizeof(iadd))) + return soap->error = SOAP_EOM; + return SOAP_OK; + } } -#if defined(__GLIBC__) || (defined(HAVE_GETHOSTBYNAME_R) && (defined(FREEBSD) || defined(__FreeBSD__))) - 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)) +#if (defined(_AIX43) || defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R) memset((void*)&ht_data, 0, sizeof(ht_data)); - if (gethostbyname_r(addr, &hostent, &ht_data) < 0) - { host = NULL; + if (gethostbyname_r(addr, hostent, &ht_data) < 0) + { + hostent = NULL; soap->errnum = h_errno; } +#elif (!defined(_GNU_SOURCE) || (!(~_GNU_SOURCE+1) && !defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)) || _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 || defined(__ANDROID__) || defined(FREEBSD) || defined(__FreeBSD__)) && !defined(SUN_OS) && !defined(__QNX__) && !defined(QNX) && defined(HAVE_GETHOSTBYNAME_R) + while ((r = gethostbyname_r(addr, hostent, tmpbuf, tmplen, &hostent, &soap->errnum)) < 0) + { + if (tmpbuf != soap->tmpbuf) + SOAP_FREE(soap, tmpbuf); + if (r != SOAP_ERANGE) + { + hostent = NULL; + break; + } + tmplen *= 2; + tmpbuf = (char*)SOAP_MALLOC(soap, tmplen); + if (!tmpbuf) + break; + } #elif defined(HAVE_GETHOSTBYNAME_R) - host = gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &soap->errnum); + hostent = gethostbyname_r(addr, hostent, tmpbuf, tmplen, &soap->errnum); #elif defined(VXWORKS) + /* vxWorks compatible */ /* If the DNS resolver library resolvLib has been configured in the vxWorks * image, a query for the host IP address is sent to the DNS server, if the * name was not found in the local host table. */ hostint = hostGetByName((char*)addr); if (hostint == ERROR) - { host = NULL; + { + hostent = NULL; soap->errnum = soap_errno; } #else + { + struct hostent *temp; #ifdef AS400 - if (!(host = gethostbyname((void*)addr))) - soap->errnum = h_errno; + temp = gethostbyname((void*)addr); #else - if (!(host = gethostbyname(addr))) - soap->errnum = h_errno; + temp = gethostbyname((char*)addr); #endif + if (!temp) + { + soap->errnum = h_errno; + hostent = NULL; + } + else + { + *hostent = *temp; + } + } #endif - if (!host) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Host name not found\n")); + if (!hostent) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Host name not found\n")); return SOAP_ERR; } + if (inaddr) + { #ifdef VXWORKS - inaddr->s_addr = hostint; + inaddr->s_addr = hostint; /* vxWorks compatible */ #else - memcpy(inaddr, host->h_addr, host->h_length); + if (soap_memcpy((void*)inaddr, sizeof(struct in_addr), (const void*)hostent->h_addr, (size_t)hostent->h_length)) + { +#if (!defined(_AIX43) && !defined(TRU64) && !defined(HP_UX)) || !defined(HAVE_GETHOSTBYNAME_R) +#if (!defined(_GNU_SOURCE) || (!(~_GNU_SOURCE+1) && !defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)) || _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 || defined(__ANDROID__) || defined(FREEBSD) || defined(__FreeBSD__)) && defined(HAVE_GETHOSTBYNAME_R) + if (tmpbuf && tmpbuf != soap->tmpbuf) + SOAP_FREE(soap, tmpbuf); +#endif +#endif + return soap->error = SOAP_EOM; + } +#endif + } +#if (!defined(_GNU_SOURCE) || (!(~_GNU_SOURCE+1) && !defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)) || _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 || defined(__ANDROID__) || defined(FREEBSD) || defined(__FreeBSD__)) && defined(HAVE_GETHOSTBYNAME_R) + if (tmpbuf && tmpbuf != soap->tmpbuf) + SOAP_FREE(soap, tmpbuf); #endif return SOAP_OK; } #endif #endif + +/******************************************************************************/ + +#if !defined(WITH_IPV6) +#ifndef WITH_NOIO +static int +tcp_gethost(struct soap *soap, const char *addr, struct in_addr *inaddr) +{ + struct hostent hostent; + return tcp_gethostbyname(soap, addr, &hostent, inaddr); +} +#endif #endif /******************************************************************************/ + #ifndef WITH_NOIO -#ifndef PALM_1 static SOAP_SOCKET tcp_connect(struct soap *soap, const char *endpoint, const char *host, int port) { #ifdef WITH_IPV6 struct addrinfo hints, *res, *ressave; #endif - SOAP_SOCKET fd; + SOAP_SOCKET sk; int err = 0; #ifndef WITH_LEAN - int len = SOAP_BUFLEN; int set = 1; +#endif +#if !defined(WITH_LEAN) || defined(WITH_OPENSSL) || defined(WITH_GNUTLS) || defined(WITH_WOLFSSL) || defined(WITH_SYSTEMSSL) int retries; #endif - if (soap_valid_socket(soap->socket)) - soap->fclosesocket(soap, soap->socket); - soap->socket = SOAP_INVALID_SOCKET; - if (tcp_init(soap)) - { soap->errnum = 0; - soap_set_sender_error(soap, tcp_error(soap), "TCP init failed in tcp_connect()", SOAP_TCP_ERROR); - return SOAP_INVALID_SOCKET; - } + soap->errnum = 0; soap->errmode = 0; -#ifdef WITH_IPV6 - memset((void*)&hints, 0, sizeof(hints)); - hints.ai_family = PF_UNSPEC; -#ifndef WITH_LEAN - if ((soap->omode & SOAP_IO_UDP)) - hints.ai_socktype = SOCK_DGRAM; - else -#endif + if (soap_valid_socket(soap->socket)) + { + if ((soap->omode & SOAP_IO_UDP) && soap->socket == soap->master) + { +#ifdef IP_MULTICAST_TTL +#ifndef WITH_IPV6 + soap->errmode = 2; + if (soap->fresolve(soap, host, &soap->peer.in.sin_addr)) + { + (void)soap_set_receiver_error(soap, tcp_error(soap), "get host by name failed in tcp_connect()", SOAP_TCP_ERROR); + (void)soap->fclosesocket(soap, soap->socket); + return soap->socket = SOAP_INVALID_SOCKET; + } + soap->peer.in.sin_port = htons((short)port); + soap->peer.in.sin_family = AF_INET; + soap->errmode = 0; +#else + memset((void*)&hints, 0, sizeof(hints)); + err = getaddrinfo(host, soap_int2s(soap, port), &hints, &res); + if (err || !res) + { + (void)soap_set_receiver_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in tcp_connect()", SOAP_TCP_ERROR); + (void)soap->fclosesocket(soap, soap->socket); + return soap->socket = SOAP_INVALID_SOCKET; + } + if (soap_memcpy((void*)&soap->peer.storage, sizeof(soap->peer.storage), (const void*)res->ai_addr, res->ai_addrlen)) + { + soap->error = SOAP_EOM; + (void)soap->fclosesocket(soap, soap->socket); + freeaddrinfo(res); + return soap->socket = SOAP_INVALID_SOCKET; + } + soap->peerlen = res->ai_addrlen; + freeaddrinfo(res); +#endif + if (soap->ipv4_multicast_ttl) + { + unsigned char ttl = soap->ipv4_multicast_ttl; + if (setsockopt(soap->socket, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ttl, sizeof(ttl))) + { + soap->errnum = soap_socket_errno; + (void)soap_set_receiver_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_TTL failed in tcp_connect()", SOAP_TCP_ERROR); + (void)soap->fclosesocket(soap, soap->socket); + return soap->socket = SOAP_INVALID_SOCKET; + } + } + if (soap->ipv4_multicast_if && !soap->ipv6_multicast_if) + { + if (setsockopt(soap->socket, IPPROTO_IP, IP_MULTICAST_IF, (char*)soap->ipv4_multicast_if, sizeof(struct in_addr))) + { + soap->errnum = soap_socket_errno; + (void)soap_set_receiver_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR); + (void)soap->fclosesocket(soap, soap->socket); + return soap->socket = SOAP_INVALID_SOCKET; + } + } +#endif + return soap->socket; + } + (void)soap->fclosesocket(soap, soap->socket); + soap->socket = SOAP_INVALID_SOCKET; + } + if (tcp_init(soap)) + { + (void)soap_set_receiver_error(soap, tcp_error(soap), "TCP init failed in tcp_connect()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + soap->errmode = 0; +#ifdef WITH_IPV6 + memset((void*)&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; +#ifndef WITH_LEAN + if ((soap->omode & SOAP_IO_UDP)) + hints.ai_socktype = SOCK_DGRAM; + else +#endif hints.ai_socktype = SOCK_STREAM; soap->errmode = 2; if (soap->proxy_host) err = getaddrinfo(soap->proxy_host, soap_int2s(soap, soap->proxy_port), &hints, &res); else err = getaddrinfo(host, soap_int2s(soap, port), &hints, &res); - if (err) - { soap_set_sender_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in tcp_connect()", SOAP_TCP_ERROR); + if (err || !res) + { + (void)soap_set_receiver_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in tcp_connect()", SOAP_TCP_ERROR); return SOAP_INVALID_SOCKET; } ressave = res; again: - fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + sk = soap->socket = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + soap->error = SOAP_OK; soap->errmode = 0; #else #ifndef WITH_LEAN @@ -3574,222 +5698,400 @@ tcp_connect(struct soap *soap, const char *endpoint, const char *host, int port) #endif #ifndef WITH_LEAN if ((soap->omode & SOAP_IO_UDP)) - fd = socket(AF_INET, SOCK_DGRAM, 0); + sk = soap->socket = socket(AF_INET, SOCK_DGRAM, 0); else #endif - fd = socket(AF_INET, SOCK_STREAM, 0); + sk = soap->socket = socket(AF_INET, SOCK_STREAM, 0); #endif - if (!soap_valid_socket(fd)) + if (!soap_valid_socket(sk)) { #ifdef WITH_IPV6 if (res->ai_next) - { res = res->ai_next; + { + res = res->ai_next; goto again; } #endif - soap->errnum = soap_socket_errno(fd); - soap_set_sender_error(soap, tcp_error(soap), "socket failed in tcp_connect()", SOAP_TCP_ERROR); + soap->errnum = soap_socket_errno; + (void)soap_set_receiver_error(soap, tcp_error(soap), "socket failed in tcp_connect()", SOAP_TCP_ERROR); #ifdef WITH_IPV6 freeaddrinfo(ressave); #endif return SOAP_INVALID_SOCKET; } -#ifdef SOCKET_CLOSE_ON_EXEC +#ifdef WITH_SOCKET_CLOSE_ON_EXIT #ifdef WIN32 #ifndef UNDER_CE - SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0); + SetHandleInformation((HANDLE)sk, HANDLE_FLAG_INHERIT, 0); #endif #else - fcntl(fd, F_SETFD, 1); + fcntl(sk, F_SETFD, 1); #endif #endif #ifndef WITH_LEAN - if (soap->connect_flags == SO_LINGER) - { struct linger linger; + if ((soap->connect_flags & SO_LINGER)) + { + struct linger linger; memset((void*)&linger, 0, sizeof(linger)); linger.l_onoff = 1; linger.l_linger = soap->linger_time; - if (setsockopt(fd, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger))) - { soap->errnum = soap_socket_errno(fd); - soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in tcp_connect()", SOAP_TCP_ERROR); - soap->fclosesocket(soap, fd); + if (setsockopt(sk, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger))) + { + soap->errnum = soap_socket_errno; + (void)soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in tcp_connect()", SOAP_TCP_ERROR); + (void)soap->fclosesocket(soap, sk); #ifdef WITH_IPV6 freeaddrinfo(ressave); #endif - return SOAP_INVALID_SOCKET; + return soap->socket = SOAP_INVALID_SOCKET; } } - else if (soap->connect_flags && setsockopt(fd, SOL_SOCKET, soap->connect_flags, (char*)&set, sizeof(int))) - { soap->errnum = soap_socket_errno(fd); - soap_set_sender_error(soap, tcp_error(soap), "setsockopt failed in tcp_connect()", SOAP_TCP_ERROR); - soap->fclosesocket(soap, fd); + if ((soap->connect_flags & ~SO_LINGER) && setsockopt(sk, SOL_SOCKET, soap->connect_flags & ~SO_LINGER, (char*)&set, sizeof(int))) + { + soap->errnum = soap_socket_errno; #ifdef WITH_IPV6 freeaddrinfo(ressave); #endif - return SOAP_INVALID_SOCKET; + (void)soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in tcp_connect()", SOAP_TCP_ERROR); + (void)soap->fclosesocket(soap, sk); + return soap->socket = SOAP_INVALID_SOCKET; } - if ((soap->keep_alive || soap->tcp_keep_alive) && setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) - { soap->errnum = soap_socket_errno(fd); - soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in tcp_connect()", SOAP_TCP_ERROR); - soap->fclosesocket(soap, fd); +#ifndef UNDER_CE + if ((soap->keep_alive || soap->tcp_keep_alive) && setsockopt(sk, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) + { + soap->errnum = soap_socket_errno; #ifdef WITH_IPV6 freeaddrinfo(ressave); #endif - return SOAP_INVALID_SOCKET; + (void)soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in tcp_connect()", SOAP_TCP_ERROR); + (void)soap->fclosesocket(soap, sk); + return soap->socket = SOAP_INVALID_SOCKET; } - if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) - { soap->errnum = soap_socket_errno(fd); - soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in tcp_connect()", SOAP_TCP_ERROR); - soap->fclosesocket(soap, fd); + if (soap->sndbuf > 0 && setsockopt(sk, SOL_SOCKET, SO_SNDBUF, (char*)&soap->sndbuf, sizeof(int))) + { + soap->errnum = soap_socket_errno; #ifdef WITH_IPV6 freeaddrinfo(ressave); #endif - return SOAP_INVALID_SOCKET; + (void)soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in tcp_connect()", SOAP_TCP_ERROR); + (void)soap->fclosesocket(soap, sk); + return soap->socket = SOAP_INVALID_SOCKET; } - if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) - { soap->errnum = soap_socket_errno(fd); - soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in tcp_connect()", SOAP_TCP_ERROR); - soap->fclosesocket(soap, fd); + if (soap->rcvbuf > 0 && setsockopt(sk, SOL_SOCKET, SO_RCVBUF, (char*)&soap->rcvbuf, sizeof(int))) + { + soap->errnum = soap_socket_errno; #ifdef WITH_IPV6 freeaddrinfo(ressave); #endif - return SOAP_INVALID_SOCKET; + (void)soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in tcp_connect()", SOAP_TCP_ERROR); + (void)soap->fclosesocket(soap, sk); + return soap->socket = SOAP_INVALID_SOCKET; } #ifdef TCP_KEEPIDLE - if (soap->tcp_keep_idle && setsockopt((SOAP_SOCKET)fd, IPPROTO_TCP, TCP_KEEPIDLE, (char*)&(soap->tcp_keep_idle), sizeof(int))) - { soap->errnum = soap_socket_errno(fd); - soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPIDLE failed in tcp_connect()", SOAP_TCP_ERROR); - soap->fclosesocket(soap, (SOAP_SOCKET)fd); + if (soap->tcp_keep_idle && setsockopt(sk, IPPROTO_TCP, TCP_KEEPIDLE, (char*)&(soap->tcp_keep_idle), sizeof(int))) + { + soap->errnum = soap_socket_errno; #ifdef WITH_IPV6 freeaddrinfo(ressave); #endif - return SOAP_INVALID_SOCKET; + (void)soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_KEEPIDLE failed in tcp_connect()", SOAP_TCP_ERROR); + (void)soap->fclosesocket(soap, sk); + return soap->socket = SOAP_INVALID_SOCKET; } #endif #ifdef TCP_KEEPINTVL - if (soap->tcp_keep_intvl && setsockopt((SOAP_SOCKET)fd, IPPROTO_TCP, TCP_KEEPINTVL, (char*)&(soap->tcp_keep_intvl), sizeof(int))) - { soap->errnum = soap_socket_errno(fd); - soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPINTVL failed in tcp_connect()", SOAP_TCP_ERROR); - soap->fclosesocket(soap, (SOAP_SOCKET)fd); + if (soap->tcp_keep_intvl && setsockopt(sk, IPPROTO_TCP, TCP_KEEPINTVL, (char*)&(soap->tcp_keep_intvl), sizeof(int))) + { + soap->errnum = soap_socket_errno; #ifdef WITH_IPV6 freeaddrinfo(ressave); #endif - return SOAP_INVALID_SOCKET; + (void)soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_KEEPINTVL failed in tcp_connect()", SOAP_TCP_ERROR); + (void)soap->fclosesocket(soap, sk); + return soap->socket = SOAP_INVALID_SOCKET; } #endif #ifdef TCP_KEEPCNT - if (soap->tcp_keep_cnt && setsockopt((SOAP_SOCKET)fd, IPPROTO_TCP, TCP_KEEPCNT, (char*)&(soap->tcp_keep_cnt), sizeof(int))) - { soap->errnum = soap_socket_errno(fd); - soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPCNT failed in tcp_connect()", SOAP_TCP_ERROR); - soap->fclosesocket(soap, (SOAP_SOCKET)fd); + if (soap->tcp_keep_cnt && setsockopt(sk, IPPROTO_TCP, TCP_KEEPCNT, (char*)&(soap->tcp_keep_cnt), sizeof(int))) + { + soap->errnum = soap_socket_errno; #ifdef WITH_IPV6 freeaddrinfo(ressave); #endif - return SOAP_INVALID_SOCKET; + (void)soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_KEEPCNT failed in tcp_connect()", SOAP_TCP_ERROR); + (void)soap->fclosesocket(soap, sk); + return soap->socket = SOAP_INVALID_SOCKET; } #endif #ifdef TCP_NODELAY - if (!(soap->omode & SOAP_IO_UDP) && setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) - { soap->errnum = soap_socket_errno(fd); - soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in tcp_connect()", SOAP_TCP_ERROR); - soap->fclosesocket(soap, fd); + if (!(soap->omode & SOAP_IO_UDP) && setsockopt(sk, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) + { + soap->errnum = soap_socket_errno; #ifdef WITH_IPV6 freeaddrinfo(ressave); #endif - return SOAP_INVALID_SOCKET; + (void)soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in tcp_connect()", SOAP_TCP_ERROR); + (void)soap->fclosesocket(soap, sk); + return soap->socket = SOAP_INVALID_SOCKET; } #endif #ifdef WITH_IPV6 if ((soap->omode & SOAP_IO_UDP) && soap->ipv6_multicast_if) - { struct sockaddr_in6 *in6addr = (struct sockaddr_in6*)res->ai_addr; + { + struct sockaddr_in6 *in6addr = (struct sockaddr_in6*)res->ai_addr; in6addr->sin6_scope_id = soap->ipv6_multicast_if; } #endif +#endif #ifdef IP_MULTICAST_TTL - if ((soap->omode & SOAP_IO_UDP) && soap->ipv4_multicast_if && !soap->ipv6_multicast_if) - { if (soap->ipv4_multicast_ttl > 0) - { char ttl = (char)(soap->ipv4_multicast_ttl); - if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ttl, sizeof(ttl))) - { soap->errnum = soap_socket_errno(fd); - soap_set_sender_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_TTL failed in tcp_connect()", SOAP_TCP_ERROR); - soap->fclosesocket(soap, fd); - return SOAP_INVALID_SOCKET; + if ((soap->omode & SOAP_IO_UDP)) + { + if (soap->ipv4_multicast_ttl) + { + unsigned char ttl = soap->ipv4_multicast_ttl; + if (setsockopt(sk, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ttl, sizeof(ttl))) + { + soap->errnum = soap_socket_errno; +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + (void)soap_set_receiver_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_TTL failed in tcp_connect()", SOAP_TCP_ERROR); + (void)soap->fclosesocket(soap, sk); + return soap->socket = SOAP_INVALID_SOCKET; } } -#ifndef WINDOWS - if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, (char*)soap->ipv4_multicast_if, sizeof(struct in_addr))) - { soap->errnum = soap_socket_errno(fd); - soap_set_sender_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR); - soap->fclosesocket(soap, fd); - return SOAP_INVALID_SOCKET; - } -#else -#ifndef IP_MULTICAST_IF -#define IP_MULTICAST_IF 2 + if (soap->ipv4_multicast_if && !soap->ipv6_multicast_if) + { + if (setsockopt(sk, IPPROTO_IP, IP_MULTICAST_IF, (char*)soap->ipv4_multicast_if, sizeof(struct in_addr))) + { + soap->errnum = soap_socket_errno; +#ifdef WITH_IPV6 + freeaddrinfo(ressave); #endif - if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, (char*)soap->ipv4_multicast_if, sizeof(struct in_addr))) - { soap->errnum = soap_socket_errno(fd); - soap_set_sender_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR); - soap->fclosesocket(soap, fd); - return SOAP_INVALID_SOCKET; + (void)soap_set_receiver_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR); + (void)soap->fclosesocket(soap, sk); + return soap->socket = SOAP_INVALID_SOCKET; + } } -#endif } #endif #endif - DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Opening socket %d to host='%s' port=%d\n", fd, host, port)); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Opening socket=%d to host='%s' port=%d\n", (int)sk, host, port)); #ifndef WITH_IPV6 - soap->peerlen = sizeof(soap->peer); - memset((void*)&soap->peer, 0, sizeof(soap->peer)); - soap->peer.sin_family = AF_INET; + soap->peerlen = sizeof(soap->peer.in); + memset((void*)&soap->peer.in, 0, sizeof(soap->peer.in)); + soap->peer.in.sin_family = AF_INET; +#ifndef WIN32 + if (soap->client_addr) + { + struct sockaddr_in addr; + memset((void*)&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + if (soap->client_port >= 0) + addr.sin_port = htons(soap->client_port); + if (inet_pton(AF_INET, soap->client_addr, (void*)&addr.sin_addr) != 1 || bind(sk, (struct sockaddr*)&addr, sizeof(addr))) + { + soap->errnum = soap_socket_errno; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind before connect\n")); + (void)soap_set_receiver_error(soap, tcp_error(soap), "bind failed in tcp_connect()", SOAP_TCP_ERROR); + (void)soap->fclosesocket(soap, sk); + soap->client_addr = NULL; + soap->client_port = -1; + return soap->socket = SOAP_INVALID_SOCKET; + } + soap->client_addr = NULL; /* disable bind before connect, so need to set it again before the next connect */ + soap->client_port = -1; /* disable bind before connect, so need to set it again before the next connect */ + } + else +#endif + if (soap->client_port >= 0) + { + struct sockaddr_in addr; + memset((void*)&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(soap->client_port); + if (bind(sk, (struct sockaddr*)&addr, sizeof(addr))) + { + soap->errnum = soap_socket_errno; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind before connect\n")); + (void)soap_set_receiver_error(soap, tcp_error(soap), "bind failed in tcp_connect()", SOAP_TCP_ERROR); + (void)soap->fclosesocket(soap, sk); + soap->client_port = -1; + return soap->socket = SOAP_INVALID_SOCKET; + } + soap->client_port = -1; /* disable bind before connect, so need to set it again before the next connect */ + } +#ifndef WIN32 + if (soap->client_interface) + { + if (inet_pton(AF_INET, soap->client_interface, &soap->peer.in.sin_addr) != 1) + { + soap->errnum = soap_socket_errno; + (void)soap_set_receiver_error(soap, tcp_error(soap), "inet_pton() failed in tcp_connect()", SOAP_TCP_ERROR); + (void)soap->fclosesocket(soap, sk); + soap->client_interface = NULL; + return soap->socket = SOAP_INVALID_SOCKET; + } + soap->client_interface = NULL; /* disable client interface, so need to set it again before the next connect */ + } +#endif soap->errmode = 2; if (soap->proxy_host) - { if (soap->fresolve(soap, soap->proxy_host, &soap->peer.sin_addr)) - { soap_set_sender_error(soap, tcp_error(soap), "get proxy host by name failed in tcp_connect()", SOAP_TCP_ERROR); - soap->fclosesocket(soap, fd); - return SOAP_INVALID_SOCKET; + { + if (soap->fresolve(soap, soap->proxy_host, &soap->peer.in.sin_addr)) + { + (void)soap_set_receiver_error(soap, tcp_error(soap), "get proxy host by name failed in tcp_connect()", SOAP_TCP_ERROR); + (void)soap->fclosesocket(soap, sk); + return soap->socket = SOAP_INVALID_SOCKET; } - soap->peer.sin_port = htons((short)soap->proxy_port); + soap->peer.in.sin_port = htons((short)soap->proxy_port); } else - { if (soap->fresolve(soap, host, &soap->peer.sin_addr)) - { soap_set_sender_error(soap, tcp_error(soap), "get host by name failed in tcp_connect()", SOAP_TCP_ERROR); - soap->fclosesocket(soap, fd); - return SOAP_INVALID_SOCKET; + { + if (soap->fresolve(soap, host, &soap->peer.in.sin_addr)) + { + (void)soap_set_receiver_error(soap, tcp_error(soap), "get host by name failed in tcp_connect()", SOAP_TCP_ERROR); + (void)soap->fclosesocket(soap, sk); + return soap->socket = SOAP_INVALID_SOCKET; } - soap->peer.sin_port = htons((short)port); + soap->peer.in.sin_port = htons((short)port); } soap->errmode = 0; #ifndef WITH_LEAN if ((soap->omode & SOAP_IO_UDP)) - return fd; + return sk; #endif #else +#ifndef WIN32 + if (soap->client_addr) + { + struct sockaddr_in6 addr; + memset((void*)&addr, 0, sizeof(addr)); + addr.sin6_family = AF_INET6; + if ((soap->client_addr_ipv6 && res->ai_family == AF_INET6 && inet_pton(AF_INET6, soap->client_addr_ipv6, (void*)&addr.sin6_addr.s6_addr) == 1) + || (!soap->client_addr_ipv6 && inet_pton(AF_INET6, soap->client_addr, (void*)&addr.sin6_addr.s6_addr) == 1) + ) + { + if (soap->client_port >= 0) + addr.sin6_port = htons(soap->client_port); + if (bind(sk, (struct sockaddr*)&addr, sizeof(addr))) + { + soap->errnum = soap_socket_errno; + freeaddrinfo(ressave); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind before connect\n")); + (void)soap_set_receiver_error(soap, tcp_error(soap), "bind failed in tcp_connect()", SOAP_TCP_ERROR); + (void)soap->fclosesocket(soap, sk); + soap->client_addr = NULL; + soap->client_addr_ipv6 = NULL; + soap->client_port = -1; + return soap->socket = SOAP_INVALID_SOCKET; + } + } + else /* not an IPv6 address, must be IPv4 */ + { + struct sockaddr_in addr; + memset((void*)&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + if (soap->client_port >= 0) + addr.sin_port = htons(soap->client_port); + if (inet_pton(AF_INET, soap->client_addr, (void*)&addr.sin_addr) != 1 || bind(sk, (struct sockaddr*)&addr, sizeof(addr))) + { + soap->errnum = soap_socket_errno; + freeaddrinfo(ressave); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind before connect\n")); + (void)soap_set_receiver_error(soap, tcp_error(soap), "bind failed in tcp_connect()", SOAP_TCP_ERROR); + (void)soap->fclosesocket(soap, sk); + soap->client_addr = NULL; + soap->client_addr_ipv6 = NULL; + soap->client_port = -1; + return soap->socket = SOAP_INVALID_SOCKET; + } + } + soap->client_addr = NULL; /* disable bind before connect, so need to set it again before the next connect */ + soap->client_addr_ipv6 = NULL; /* disable bind before connect, so need to set it again before the next connect */ + soap->client_port = -1; /* disable bind before connect, so need to set it again before the next connect */ + } + else +#endif + if (soap->client_port >= 0) + { + struct sockaddr_in6 addr; + memset((void*)&addr, 0, sizeof(addr)); + addr.sin6_family = AF_INET6; + addr.sin6_port = htons(soap->client_port); + if (bind(sk, (struct sockaddr*)&addr, sizeof(addr))) + { + soap->errnum = soap_socket_errno; + freeaddrinfo(ressave); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind before connect\n")); + (void)soap_set_receiver_error(soap, tcp_error(soap), "bind failed in tcp_connect()", SOAP_TCP_ERROR); + (void)soap->fclosesocket(soap, sk); + soap->client_port = -1; + return soap->socket = SOAP_INVALID_SOCKET; + } + soap->client_port = -1; /* disable bind before connect, so need to set it again before the next connect */ + } +#ifndef WIN32 + if (soap->client_interface) + { + if (inet_pton(AF_INET6, soap->client_interface, res->ai_addr) != 1) + { + if (inet_pton(AF_INET, soap->client_interface, res->ai_addr) != 1) + { + soap->errnum = soap_socket_errno; + freeaddrinfo(ressave); + (void)soap_set_receiver_error(soap, tcp_error(soap), "inet_pton() failed in tcp_connect()", SOAP_TCP_ERROR); + (void)soap->fclosesocket(soap, sk); + soap->client_interface = NULL; + return soap->socket = SOAP_INVALID_SOCKET; + } + } + soap->client_interface = NULL; /* disable client interface, so need to set it again before the next connect */ + } +#endif +#ifndef WITH_LEAN if ((soap->omode & SOAP_IO_UDP)) - { memcpy(&soap->peer, res->ai_addr, res->ai_addrlen); + { + if (soap_memcpy((void*)&soap->peer.storage, sizeof(soap->peer.storage), (const void*)res->ai_addr, res->ai_addrlen)) + { + soap->error = SOAP_EOM; + (void)soap->fclosesocket(soap, sk); + soap->socket = sk = SOAP_INVALID_SOCKET; + } soap->peerlen = res->ai_addrlen; freeaddrinfo(ressave); - return fd; + return sk; } #endif +#endif #ifndef WITH_LEAN if (soap->connect_timeout) - SOAP_SOCKNONBLOCK(fd) + SOAP_SOCKNONBLOCK(sk) else - SOAP_SOCKBLOCK(fd) + SOAP_SOCKBLOCK(sk) retries = 10; #endif for (;;) { #ifdef WITH_IPV6 - if (connect(fd, res->ai_addr, (int)res->ai_addrlen)) + if (connect(sk, res->ai_addr, (int)res->ai_addrlen)) #else - if (connect(fd, (struct sockaddr*)&soap->peer, sizeof(soap->peer))) + if (connect(sk, &soap->peer.addr, sizeof(soap->peer.in))) +#endif + { + err = soap_socket_errno; +#ifdef WITH_IPV6 + if (err == SOAP_ECONNREFUSED && res->ai_next) + { + (void)soap->fclosesocket(soap, sk); + res = res->ai_next; + goto again; + } #endif - { err = soap_socket_errno(fd); #ifndef WITH_LEAN if (err == SOAP_EADDRINUSE) - { soap->fclosesocket(soap, fd); + { + (void)soap->fclosesocket(soap, sk); if (retries-- > 0) goto again; } @@ -3797,297 +6099,494 @@ tcp_connect(struct soap *soap, const char *endpoint, const char *host, int port) { SOAP_SOCKLEN_T k; for (;;) - { int r; - r = tcp_select(soap, fd, SOAP_TCP_SELECT_SND, soap->connect_timeout); + { + int r; +#ifdef WITH_SELF_PIPE + r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_PIP, soap->connect_timeout); + if ((r & SOAP_TCP_SELECT_PIP)) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connection closed by self pipe\n")); + (void)soap->fclosesocket(soap, sk); + return soap->socket = SOAP_INVALID_SOCKET; + } +#else + r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND, soap->connect_timeout); +#endif if (r > 0) break; if (!r) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n")); - soap_set_sender_error(soap, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR); - soap->fclosesocket(soap, fd); + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n")); + (void)soap_set_receiver_error(soap, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR); + (void)soap->fclosesocket(soap, sk); #ifdef WITH_IPV6 + if (res->ai_next) + { + res = res->ai_next; + goto again; + } freeaddrinfo(ressave); #endif - return SOAP_INVALID_SOCKET; + return soap->socket = SOAP_INVALID_SOCKET; } - r = soap->errnum; + r = soap->errnum = soap_socket_errno; 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); - soap->fclosesocket(soap, fd); + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); + (void)soap_set_receiver_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR); + (void)soap->fclosesocket(soap, sk); #ifdef WITH_IPV6 + if (res->ai_next) + { + res = res->ai_next; + goto again; + } freeaddrinfo(ressave); #endif - return SOAP_INVALID_SOCKET; + return soap->socket = SOAP_INVALID_SOCKET; } } k = (SOAP_SOCKLEN_T)sizeof(soap->errnum); - if (!getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*)&soap->errnum, &k) && !soap->errnum) /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */ + if (!getsockopt(sk, SOL_SOCKET, SO_ERROR, (char*)&soap->errnum, &k) && !soap->errnum) /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */ break; DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); if (!soap->errnum) - soap->errnum = soap_socket_errno(fd); - soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR); - soap->fclosesocket(soap, fd); + soap->errnum = soap_socket_errno; + (void)soap_set_receiver_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR); + (void)soap->fclosesocket(soap, sk); #ifdef WITH_IPV6 + if (res->ai_next) + { + res = res->ai_next; + goto again; + } freeaddrinfo(ressave); #endif - return SOAP_INVALID_SOCKET; + return soap->socket = SOAP_INVALID_SOCKET; } #endif #ifdef WITH_IPV6 if (res->ai_next) - { res = res->ai_next; - soap->fclosesocket(soap, fd); + { + res = res->ai_next; + (void)soap->fclosesocket(soap, sk); goto again; } #endif if (err && err != SOAP_EINTR) - { soap->errnum = err; - 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); - soap->fclosesocket(soap, fd); + { + soap->errnum = err; #ifdef WITH_IPV6 freeaddrinfo(ressave); #endif - return SOAP_INVALID_SOCKET; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); + (void)soap_set_receiver_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR); + (void)soap->fclosesocket(soap, sk); + return soap->socket = SOAP_INVALID_SOCKET; } } else + { break; + } } #ifdef WITH_IPV6 soap->peerlen = 0; /* IPv6: already connected so use send() */ freeaddrinfo(ressave); #endif -#ifndef WITH_LEAN - if (soap->recv_timeout || soap->send_timeout) - SOAP_SOCKNONBLOCK(fd) - else - SOAP_SOCKBLOCK(fd) -#endif - soap->socket = fd; soap->imode &= ~SOAP_ENC_SSL; soap->omode &= ~SOAP_ENC_SSL; - if (!soap_tag_cmp(endpoint, "https:*")) + if (endpoint && !soap_tag_cmp(endpoint, "https:*")) { +#if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) || defined(WITH_WOLFSSL) || defined(WITH_SYSTEMSSL) #ifdef WITH_OPENSSL BIO *bio; +#endif +#ifdef WITH_SYSTEMSSL + gsk_iocallback local_io = { ssl_recv, ssl_send, NULL, NULL, NULL, NULL }; +#endif int r; if (soap->proxy_host) - { soap_mode m = soap->mode; /* preserve settings */ + { + soap_mode m = soap->mode; /* preserve settings */ soap_mode om = soap->omode; /* make sure we only parse HTTP */ - size_t n = soap->count; /* save the content length */ + ULONG64 count = soap->count; /* save the content length */ + const char *http_content = soap->http_content; /* save http_content when set */ + const char *http_extra_header = soap->http_extra_header; /* save http_extra_header when set */ + const char *bearer = soap->bearer; /* save bearer when set */ + int status = soap->status; /* save the current status/command */ + int keep_alive = soap->keep_alive; /* save the KA status */ const char *userid, *passwd; 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)); - sprintf(soap->tmpbuf, "CONNECT %s:%d HTTP/%s", host, port, soap->proxy_http_version); - if (soap_begin_send(soap) - || (soap->error = soap->fposthdr(soap, soap->tmpbuf, NULL))) - { soap->fclosesocket(soap, fd); - return SOAP_INVALID_SOCKET; - } -#ifndef WITH_LEAN - if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761) - { sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd); - strcpy(soap->tmpbuf, "Basic "); - soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262)); - if ((soap->error = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf))) - { soap->fclosesocket(soap, fd); - return soap->error; - } + 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 && soap_ntlm_handshake(soap, SOAP_CONNECT, endpoint, host, port)) + { + (void)soap->fclosesocket(soap, sk); + return soap->socket = SOAP_INVALID_SOCKET; } #endif - if ((soap->error = soap->fposthdr(soap, NULL, NULL)) - || soap_flush(soap)) - { soap->fclosesocket(soap, fd); - return SOAP_INVALID_SOCKET; + if (soap_init_send(soap)) + { + (void)soap->fclosesocket(soap, sk); + return soap->socket = SOAP_INVALID_SOCKET; } + soap->status = SOAP_CONNECT; + if (!soap->keep_alive) + soap->keep_alive = -1; /* must keep alive */ + soap->error = soap->fpost(soap, endpoint, host, port, NULL, NULL, 0); + if (soap->error || soap_end_send_flush(soap)) + { + (void)soap->fclosesocket(soap, sk); + return soap->socket = SOAP_INVALID_SOCKET; + } + soap->keep_alive = keep_alive; soap->omode = om; - om = soap->imode; + om = soap->imode; /* preserve */ soap->imode &= ~SOAP_ENC; /* mask IO and ENC */ userid = soap->userid; /* preserve */ passwd = soap->passwd; /* preserve */ - if ((soap->error = soap->fparse(soap))) - { soap->fclosesocket(soap, fd); - return SOAP_INVALID_SOCKET; + soap->error = soap->fparse(soap); + if (soap->error) + { + (void)soap->fclosesocket(soap, sk); + return soap->socket = SOAP_INVALID_SOCKET; } + soap->status = status; /* restore */ soap->userid = userid; /* restore */ soap->passwd = passwd; /* restore */ soap->imode = om; /* restore */ - soap->count = n; /* restore */ - if (soap_begin_send(soap)) - { soap->fclosesocket(soap, fd); - return SOAP_INVALID_SOCKET; + soap->count = count; /* restore */ + soap->http_content = http_content; /* restore */ + soap->http_extra_header = http_extra_header; /* restore */ + soap->bearer = bearer; /* restore */ + if (soap_init_send(soap)) + { + (void)soap->fclosesocket(soap, sk); + return soap->socket = SOAP_INVALID_SOCKET; } if (endpoint) - strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint)-1); /* restore */ + soap_strcpy(soap->endpoint, sizeof(soap->endpoint), endpoint); /* restore */ soap->mode = m; } - if (!soap->ctx && (soap->error = soap->fsslauth(soap))) - { soap_set_sender_error(soap, "SSL error", "SSL authentication failed in tcp_connect(): check password, key file, and ca file.", SOAP_SSL_ERROR); - soap->fclosesocket(soap, fd); - return SOAP_INVALID_SOCKET; +#ifdef WITH_OPENSSL + ERR_clear_error(); + soap->ssl_flags |= SOAP_SSL_CLIENT; + if (!soap->ctx && (soap->error = soap->fsslauth(soap)) != SOAP_OK) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL required, but no ctx set\n")); + (void)soap->fclosesocket(soap, sk); + soap->error = SOAP_SSL_ERROR; + return soap->socket = SOAP_INVALID_SOCKET; } if (!soap->ssl) - { soap->ssl = SSL_new(soap->ctx); + { + soap->ssl = SSL_new(soap->ctx); if (!soap->ssl) - { soap->fclosesocket(soap, fd); + { + (void)soap->fclosesocket(soap, sk); soap->error = SOAP_SSL_ERROR; - return SOAP_INVALID_SOCKET; + return soap->socket = SOAP_INVALID_SOCKET; } } else + { SSL_clear(soap->ssl); + } if (soap->session) - { if (!strcmp(soap->session_host, host) && soap->session_port == port) + { + if (!strcmp(soap->session_host, host) && soap->session_port == port) SSL_set_session(soap->ssl, soap->session); SSL_SESSION_free(soap->session); soap->session = NULL; } - soap->imode |= SOAP_ENC_SSL; - soap->omode |= SOAP_ENC_SSL; - bio = BIO_new_socket((int)fd, BIO_NOCLOSE); +#if OPENSSL_VERSION_NUMBER >= 0x1000000aL + if (!(soap->ssl_flags & SOAP_SSLv3)) + { + const char *name = host; + if ((soap->ssl_flags & SOAP_SSL_SNI_HOST_CHECK)) + { + /* do not use IP address with SNI (RFC 6066), perform a host check */ + const size_t MAX_LABEL_LEN = 63; + size_t i; + size_t len = strlen(host); + size_t label_len = 0; + int ip = 1; + for (i = 0; i < len && label_len < MAX_LABEL_LEN; ++i) + { + int c = host[i]; + if (c >= '0' && c <= '9') + { + label_len += 1; + continue; + } + if (i > 0 && i < len - 1) + { + if (c == '-') + { + label_len += 1; + continue; + } + if (c == '.' && host[i + 1] != '.' && host[i - 1] != '-' && host[i + 1] != '-') + { + label_len = 0; + continue; + } + } + if (c >= '\0' && c <= '@') + { + name = NULL; + break; + } + label_len += 1; + ip = 0; + } + if (ip || label_len >= MAX_LABEL_LEN) + name = NULL; + } + if (name != NULL && !SSL_set_tlsext_host_name(soap->ssl, name)) + { + (void)soap_set_receiver_error(soap, "SSL/TLS error", "SNI failed", SOAP_SSL_ERROR); + (void)soap->fclosesocket(soap, sk); + return soap->socket = SOAP_INVALID_SOCKET; + } + } +#elif (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && defined(SSL_CTRL_SET_TLSEXT_HOSTNAME) + if (!SSL_ctrl(soap->ssl, SSL_CTRL_SET_TLSEXT_HOSTNAME, TLSEXT_NAMETYPE_host_name, (void*)host)) + { + (void)soap_set_receiver_error(soap, "SSL/TLS error", "SNI failed", SOAP_SSL_ERROR); + (void)soap->fclosesocket(soap, sk); + return soap->socket = SOAP_INVALID_SOCKET; + } +#endif + bio = BIO_new_socket((int)sk, BIO_NOCLOSE); SSL_set_bio(soap->ssl, bio, bio); -#ifndef WITH_LEAN - /* Connect timeout: set SSL sockets to non-blocking */ - if (soap->connect_timeout) - SOAP_SOCKNONBLOCK(fd) + if (soap->connect_timeout || soap->recv_timeout || soap->send_timeout) + { + /* Set SSL connect timeout and set SSL sockets to non-blocking */ + int t = soap->recv_timeout > soap->send_timeout ? soap->recv_timeout : soap->send_timeout; + if (soap->connect_timeout > 0 && t < soap->connect_timeout) + t = soap->connect_timeout; + if (t > 0) + retries = 10 * t; + else if (t > -100000) + retries = 1; + else + retries = t/-100000; + SOAP_SOCKNONBLOCK(sk) + } else - SOAP_SOCKBLOCK(fd) - retries = 100; /* SSL connect timeout: 10 sec retries, 100 times 0.1 sec */ -#endif - /* Try connecting until success or timeout (when nonblocking) */ + { + /* Set sockets to blocking */ + retries = 1; + SOAP_SOCKBLOCK(sk) + } + err = SSL_ERROR_NONE; + /* Try connecting until success or timeout */ do - { if ((r = SSL_connect(soap->ssl)) <= 0) - { int err = SSL_get_error(soap->ssl, r); + { + if ((r = SSL_connect(soap->ssl)) <= 0) + { + err = SSL_get_error(soap->ssl, r); if (err == SSL_ERROR_WANT_CONNECT || err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) - { int s; - if (err == SSL_ERROR_WANT_READ) - s = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000); + { + int s; + if (err == SSL_ERROR_WANT_READ) + s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000); else - s = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000); - if (s < 0 && soap->errnum != SOAP_EINTR) - { 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, fd); - return SOAP_INVALID_SOCKET; - } - if (s == 0 && retries-- <= 0) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL connect timeout\n")); - soap_set_sender_error(soap, "Timeout", "SSL connect failed in tcp_connect()", SOAP_TCP_ERROR); - soap->fclosesocket(soap, fd); - return SOAP_INVALID_SOCKET; + s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000); + if (s < 0) + break; + if (s == 0 && retries-- <= 0) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL/TLS connect timeout\n")); + (void)soap_set_receiver_error(soap, "Timeout", "SSL_connect() failed in tcp_connect()", SOAP_TCP_ERROR); + (void)soap->fclosesocket(soap, sk); + return soap->socket = SOAP_INVALID_SOCKET; } } - else - { soap_set_sender_error(soap, soap_ssl_error(soap, r), "SSL_connect error in tcp_connect()", SOAP_SSL_ERROR); - soap->fclosesocket(soap, fd); - return SOAP_INVALID_SOCKET; + else + { + soap->errnum = soap_socket_errno; + break; } } } while (!SSL_is_init_finished(soap->ssl)); -#ifndef WITH_LEAN - /* Set SSL sockets to nonblocking */ - SOAP_SOCKNONBLOCK(fd) -#endif + if (r <= 0) + { + (void)soap_set_sender_error(soap, soap_ssl_error(soap, r, err), "SSL/TLS handshake failed", SOAP_SSL_ERROR); + (void)soap->fclosesocket(soap, sk); + return soap->socket = SOAP_INVALID_SOCKET; + } /* Check server credentials when required */ if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION)) - { int err; + { if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK) - { soap_set_sender_error(soap, X509_verify_cert_error_string(err), "SSL certificate presented by peer cannot be verified in tcp_connect()", SOAP_SSL_ERROR); - soap->fclosesocket(soap, fd); - return SOAP_INVALID_SOCKET; + { + (void)soap_set_sender_error(soap, X509_verify_cert_error_string(err), "SSL/TLS certificate presented by peer cannot be verified in tcp_connect()", SOAP_SSL_ERROR); + (void)soap->fclosesocket(soap, sk); + return soap->socket = SOAP_INVALID_SOCKET; } if (!(soap->ssl_flags & SOAP_SSL_SKIP_HOST_CHECK)) - { X509_NAME *subj; + { + 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 error", "No SSL certificate was presented by the peer in tcp_connect()", SOAP_SSL_ERROR); - soap->fclosesocket(soap, fd); - return SOAP_INVALID_SOCKET; + { + (void)soap_set_sender_error(soap, "SSL/TLS error", "No SSL/TLS certificate was presented by the peer in tcp_connect()", SOAP_SSL_ERROR); + (void)soap->fclosesocket(soap, sk); + return soap->socket = SOAP_INVALID_SOCKET; } +#if OPENSSL_VERSION_NUMBER < 0x0090800fL ext_count = X509_get_ext_count(peer); if (ext_count > 0) - { int i; + { + int i; for (i = 0; i < ext_count; i++) - { X509_EXTENSION *ext = X509_get_ext(peer, i); + { + X509_EXTENSION *ext = X509_get_ext(peer, i); 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_get(ext); - void *ext_data; -#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) - const unsigned char *data; -#else + { + X509V3_EXT_METHOD *meth = (X509V3_EXT_METHOD*)X509V3_EXT_get(ext); unsigned char *data; -#endif - STACK_OF(CONF_VALUE) *val; - int j; if (!meth) break; data = ext->value->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); - } + if (data) + { +#if OPENSSL_VERSION_NUMBER > 0x00907000L + void *ext_data; + if (meth->it) + ext_data = ASN1_item_d2i(NULL, &data, ext->value->length, ASN1_ITEM_ptr(meth->it)); + else + { +#if OPENSSL_VERSION_NUMBER > 0x0090800fL + ext_data = meth->d2i(NULL, (const unsigned char **)&data, ext->value->length); #else - ext_data = meth->d2i(NULL, &data, ext->value->length); + ext_data = meth->d2i(NULL, &data, ext->value->length); #endif - if (ext_data) - { val = meth->i2v(meth, ext_data, NULL); - if (val) - { 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); } -#if (OPENSSL_VERSION_NUMBER > 0x00907000L) + 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 + 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 (val) + { + int j; + for (j = 0; j < sk_CONF_VALUE_num(val); j++) + { + CONF_VALUE *nval = sk_CONF_VALUE_value(val, j); + if (nval && nval->name && && (!strcmp(nval->name, "DNS") || !strcmp(nval->name, "IP Address")) && !soap_tag_cmp(host, nval->value)) + { + ok = 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL: host name %s match with certificate %s %s\n", host, nval->name, nval->value)); + break; + } + else + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL: host name %s mismatch with certificate %s %s\n", host, nval->name, nval->value)); + } + } + sk_CONF_VALUE_pop_free(val, X509V3_conf_free); + } + } } if (ok) break; } } - if (!ok && (subj = X509_get_subject_name(peer))) - { int i = -1; +#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 && nval->name && (!strcmp(nval->name, "DNS") || !strcmp(nval->name, "IP Address")) && !soap_tag_cmp(host, nval->value)) + { + ok = 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL: host name %s match with certificate %s %s\n", host, nval->name, nval->value)); + break; + } + else + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL: host name %s mismatch with certificate %s %s\n", host, nval->name, nval->value)); + } + } + sk_CONF_VALUE_pop_free(val, X509V3_conf_free); + } +#endif + if (!ok && (subj = X509_get_subject_name(peer)) != 0) + { + int i = -1; do - { ASN1_STRING *name; + { + ASN1_STRING *name; i = X509_NAME_get_index_by_NID(subj, NID_commonName, i); if (i == -1) break; name = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subj, i)); if (name) - { if (!soap_tag_cmp(host, (const char*)name)) + { +#if OPENSSL_VERSION_NUMBER < 0x10100000L + const char *tmp = (const char*)ASN1_STRING_data(name); +#else + const char *tmp = (const char*)ASN1_STRING_get0_data(name); +#endif + if (!soap_tag_cmp(host, tmp)) + { ok = 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL: host name %s match with certificate subject %s\n", host, tmp)); + } else - { unsigned char *tmp = NULL; + { + unsigned char *tmp = NULL; ASN1_STRING_to_UTF8(&tmp, name); if (tmp) - { if (!soap_tag_cmp(host, (const char*)tmp)) + { + if (!soap_tag_cmp(host, (const char*)tmp)) + { ok = 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL: host name %s match with certificate subject %s\n", host, tmp)); + } + else if (tmp[0] == '*') /* wildcard domain */ + { + const char *t = strchr(host, '.'); + if (t && !soap_tag_cmp(t, (const char*)tmp + 1)) + { + ok = 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL: host name %s match with certificate subject %s\n", host, tmp)); + } + } + else + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL: host name %s mismatch with certificate %s\n", host, tmp)); + } OPENSSL_free(tmp); } } @@ -4096,1009 +6595,3911 @@ tcp_connect(struct soap *soap, const char *endpoint, const char *host, int port) } X509_free(peer); if (!ok) - { soap_set_sender_error(soap, "SSL error", "SSL certificate host name mismatch in tcp_connect()", SOAP_SSL_ERROR); - soap->fclosesocket(soap, fd); - return SOAP_INVALID_SOCKET; + { + (void)soap_set_sender_error(soap, "SSL/TLS error", "SSL/TLS certificate host name mismatch in tcp_connect()", SOAP_SSL_ERROR); + (void)soap->fclosesocket(soap, sk); + return soap->socket = SOAP_INVALID_SOCKET; + } + } + } +#endif +#ifdef WITH_GNUTLS + soap->ssl_flags |= SOAP_SSL_CLIENT; + if (!soap->session && (soap->error = soap->fsslauth(soap)) != SOAP_OK) + { + (void)soap->fclosesocket(soap, sk); + return soap->socket = SOAP_INVALID_SOCKET; + } + gnutls_transport_set_ptr(soap->session, (gnutls_transport_ptr_t)(long)sk); + if (soap->connect_timeout || soap->recv_timeout || soap->send_timeout) + { + /* Set SSL connect timeout and set SSL sockets to non-blocking */ + int t = soap->recv_timeout > soap->send_timeout ? soap->recv_timeout : soap->send_timeout; + if (soap->connect_timeout > 0 && t < soap->connect_timeout) + t = soap->connect_timeout; + if (t > 0) + retries = 10 * t; + else if (t > -100000) + retries = 1; + else + retries = t/-100000; + SOAP_SOCKNONBLOCK(sk) + } + else + { + /* Set sockets to blocking */ + retries = 1; + SOAP_SOCKBLOCK(sk) + } + /* Try connecting until success or timeout */ + while ((r = gnutls_handshake(soap->session))) + { + /* GNUTLS repeat handhake when GNUTLS_E_AGAIN */ + if (r == GNUTLS_E_AGAIN || r == GNUTLS_E_INTERRUPTED) + { + int s; + if (!gnutls_record_get_direction(soap->session)) + 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) + break; + if (s == 0 && retries-- <= 0) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL/TLS connect timeout\n")); + (void)soap_set_receiver_error(soap, "Timeout", "SSL_connect() failed in tcp_connect()", SOAP_TCP_ERROR); + (void)soap->fclosesocket(soap, sk); + return soap->socket = SOAP_INVALID_SOCKET; + } + } + else + { + soap->errnum = soap_socket_errno; + break; + } + } + if (r) + { + (void)soap_set_sender_error(soap, soap_ssl_error(soap, r, 0), "SSL/TLS handshake failed", SOAP_SSL_ERROR); + (void)soap->fclosesocket(soap, sk); + return soap->socket = SOAP_INVALID_SOCKET; + } + if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION)) + { + const char *s = ssl_verify(soap, host); + if (s) + { + (void)soap->fclosesocket(soap, sk); + soap->error = soap_set_sender_error(soap, "SSL/TLS verify error", s, SOAP_SSL_ERROR); + return soap->socket = SOAP_INVALID_SOCKET; + } + } +#endif +#ifdef WITH_WOLFSSL + soap->ssl_flags |= SOAP_SSL_CLIENT; + if (!soap->session && (soap->error = soap->fsslauth(soap)) != SOAP_OK) + { + (void)soap->fclosesocket(soap, sk); + return soap->socket = SOAP_INVALID_SOCKET; + } + if (!soap->ssl) + { + soap->ssl = wolfSSL_new(soap->ctx); + if (!soap->ssl) + { + (void)soap->fclosesocket(soap, sk); + soap->error = SOAP_SSL_ERROR; + return soap->socket = SOAP_INVALID_SOCKET; + } +#ifdef HAVE_SECURE_RENEGOTIATION +#warning "Client-side secure renegotiation not recommended, undefine HAVE_SECURE_RENEGOTIATION to disable" + if (wolfSSL_UseSecureRenegotiation(soap->ssl) != SSL_SUCCESS) + { + (void)soap->fclosesocket(soap, sk); + (void)soap_set_receiver_error(soap, "SSL/TLS error", "failed to enable secure renegotiation in soap_ssl_accept()", SOAP_SSL_ERROR); + wolfSSL_free(soap->ssl); + soap->ssl = NULL; + return soap->socket = SOAP_INVALID_SOCKET; + } +#endif + /* Set the expected domain name so that the peer server's can be verified when we connect. */ + if (!(soap->ssl_flags & SOAP_SSL_SKIP_HOST_CHECK)) + { + if (wolfSSL_check_domain_name(soap->ssl, host) != SSL_SUCCESS) + { + (void)soap->fclosesocket(soap, sk); + (void)soap_set_receiver_error(soap, "SSL/TLS error", "wolfSSL_check_domain_name() failed in tcp_connect()", SOAP_TCP_ERROR); + wolfSSL_free(soap->ssl); + soap->ssl = NULL; + return soap->socket = SOAP_INVALID_SOCKET; + } + } + } + wolfSSL_set_fd(soap->ssl, sk); + if (soap->connect_timeout || soap->recv_timeout || soap->send_timeout) + { + /* Set SSL connect timeout and set SSL sockets to non-blocking */ + int t = soap->recv_timeout > soap->send_timeout ? soap->recv_timeout : soap->send_timeout; + if (soap->connect_timeout > 0 && t < soap->connect_timeout) + t = soap->connect_timeout; + if (t > 0) + retries = 10 * t; + else if (t > -100000) + retries = 1; + else + retries = t/-100000; + SOAP_SOCKNONBLOCK(sk) + } + else + { + /* Set sockets to blocking */ + retries = 1; + SOAP_SOCKBLOCK(sk) + } + err = SSL_ERROR_NONE; + /* Try connecting until success or timeout */ + do + { + if ((r = wolfSSL_connect(soap->ssl)) <= 0) + { + err = wolfSSL_get_error(soap->ssl, r); + if (err == SSL_ERROR_WANT_CONNECT || err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) + { + int s; + if (err == SSL_ERROR_WANT_READ) + 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) + break; + if (s == 0 && retries-- <= 0) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL/TLS connect timeout\n")); + (void)soap_set_receiver_error(soap, "Timeout", "wolfSSL_connect() failed in tcp_connect()", SOAP_TCP_ERROR); + (void)soap->fclosesocket(soap, sk); + return soap->socket = SOAP_INVALID_SOCKET; + } + } + else + { + soap->errnum = soap_socket_errno; + break; + } + } + } while (!wolfSSL_is_init_finished(soap->ssl)); + if (r != SSL_SUCCESS) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL_connect/select error in tcp_connect\n")); + (void)soap_set_receiver_error(soap, soap_ssl_error(soap, r, 0), "SSL/TLS handshake failed", SOAP_SSL_ERROR); + (void)soap->fclosesocket(soap, sk); + return soap->socket = SOAP_INVALID_SOCKET; + } +#endif +#ifdef WITH_SYSTEMSSL + soap->ssl_flags |= SOAP_SSL_CLIENT; + if (!soap->ctx && (soap->error = soap->fsslauth(soap)) != SOAP_OK) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL required, but no ctx set\n")); + (void)soap->fclosesocket(soap, sk); + soap->error = SOAP_SSL_ERROR; + return soap->socket = SOAP_INVALID_SOCKET; + } + if (soap->connect_timeout || soap->recv_timeout || soap->send_timeout) + { + /* Set SSL connect timeout and set SSL sockets to non-blocking */ + int t = soap->recv_timeout > soap->send_timeout ? soap->recv_timeout : soap->send_timeout; + if (soap->connect_timeout > 0 && t < soap->connect_timeout) + t = soap->connect_timeout; + if (t > 0) + retries = 10 * t; + else if (t > -100000) + retries = 1; + else + retries = t/-100000; + SOAP_SOCKNONBLOCK(sk) + } + else + { + /* Set sockets to blocking */ + retries = 1; + SOAP_SOCKBLOCK(sk) + } + r = gsk_secure_socket_open(soap->ctx, &soap->ssl); + if (r == GSK_OK) + r = gsk_attribute_set_numeric_value(soap->ssl, GSK_FD, sk); + if (r == GSK_OK) + r = gsk_attribute_set_buffer(soap->ssl, GSK_KEYRING_LABEL, soap->cafile, 0); /* Certificate label */ + if (r == GSK_OK) + r = gsk_attribute_set_enum(soap->ssl, GSK_SESSION_TYPE, GSK_CLIENT_SESSION); + if (r == GSK_OK) + r = gsk_attribute_set_buffer(soap->ssl, GSK_V3_CIPHER_SPECS_EXPANDED, "0035002F000A", 0); + if (r == GSK_OK) + r = gsk_attribute_set_enum(soap->ssl, GSK_V3_CIPHERS, GSK_V3_CIPHERS_CHAR4); + if (r == GSK_OK) + r = gsk_attribute_set_callback(soap->ssl, GSK_IO_CALLBACK, &local_io); + if (r != GSK_OK) + { + (void)soap_set_receiver_error(soap, gsk_strerror(r), "SYSTEM SSL error in tcp_connect()", SOAP_SSL_ERROR); + return soap->socket = SOAP_INVALID_SOCKET; + } + /* Try connecting until success or timeout */ + while ((r = gsk_secure_socket_init(soap->ssl)) != GSK_OK) + { + if (r == GSK_WOULD_BLOCK_READ || r == GSK_WOULD_BLOCK_WRITE) + { + int s; + if (r == GSK_WOULD_BLOCK_READ) + 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) + break; + if (s == 0 && retries-- <= 0) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL/TLS connect timeout\n")); + (void)soap_set_receiver_error(soap, "Timeout", "SSL_connect() failed in tcp_connect()", SOAP_TCP_ERROR); + (void)soap->fclosesocket(soap, sk); + return soap->socket = SOAP_INVALID_SOCKET; } } + else + { + soap->errnum = soap_socket_errno; + break; + } } + if (r != GSK_OK) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL_connect/select error in tcp_connect\n")); + (void)soap_set_receiver_error(soap, gsk_strerror(r), "SSL/TLS handshake failed", SOAP_SSL_ERROR); + (void)soap->fclosesocket(soap, sk); + return soap->socket = SOAP_INVALID_SOCKET; + } +#endif + soap->imode |= SOAP_ENC_SSL; + soap->omode |= SOAP_ENC_SSL; #else - soap->fclosesocket(soap, fd); + (void)soap->fclosesocket(soap, sk); soap->error = SOAP_SSL_ERROR; - return SOAP_INVALID_SOCKET; + return soap->socket = SOAP_INVALID_SOCKET; #endif } - return fd; + if (soap->recv_timeout || soap->send_timeout) + SOAP_SOCKNONBLOCK(sk) + else + SOAP_SOCKBLOCK(sk) + return sk; } #endif -#endif /******************************************************************************/ + #ifndef WITH_NOIO -#ifndef PALM_1 -SOAP_FMAC1 -SOAP_SOCKET -SOAP_FMAC2 -soap_bind(struct soap *soap, const char *host, int port, int backlog) +static int +tcp_select(struct soap *soap, SOAP_SOCKET sk, int flags, int timeout) { -#ifdef WITH_IPV6 - struct addrinfo *addrinfo = NULL; - struct addrinfo hints; - struct addrinfo res; - int err; -#ifdef IPV6_V6ONLY - int unset = 0; -#ifdef SOL_IP - int level = SOL_IP; + int r; + struct timeval tv; + fd_set fd[3], *rfd, *sfd, *efd; + int retries = 0; + int eintr = SOAP_MAXEINTR; + soap->errnum = 0; + if (!soap_valid_socket(sk)) + { + soap->error = SOAP_EOF; + return -1; + } +#ifndef WIN32 +#if !defined(FD_SETSIZE) || defined(__QNX__) || defined(QNX) + /* no FD_SETSIZE or select() is not MT safe on some QNX: always poll */ + if (1) #else - int level = IPPROTO_IPV6; -#endif -#endif + /* if fd max set size exceeded, use poll() when available */ + if ((int)sk >= (int)FD_SETSIZE) #endif -#ifndef WITH_LEAN - int len = SOAP_BUFLEN; - int set = 1; +#ifdef HAVE_POLL + { +#ifdef WITH_SELF_PIPE + struct pollfd pollfd[2]; + pollfd[1].fd = soap->pipe_fd[0]; + pollfd[1].events = POLLIN; +#else + struct pollfd pollfd[1]; +#endif + pollfd[0].fd = (int)sk; + pollfd[0].events = 0; + if ((flags & SOAP_TCP_SELECT_RCV)) + pollfd[0].events |= POLLIN; + if ((flags & SOAP_TCP_SELECT_SND)) + pollfd[0].events |= POLLOUT; + if ((flags & SOAP_TCP_SELECT_ERR)) + pollfd[0].events |= POLLERR; + if (timeout <= 0) + timeout /= -1000; /* -usec -> ms */ + else + { + retries = timeout - 1; + timeout = 1000; + } + do + { +#ifdef WITH_SELF_PIPE + r = poll(pollfd, 2, timeout); +#else + r = poll(pollfd, 1, timeout); #endif - if (soap_valid_socket(soap->master)) - { soap->fclosesocket(soap, soap->master); - soap->master = SOAP_INVALID_SOCKET; - } - soap->socket = SOAP_INVALID_SOCKET; - soap->errmode = 1; - if (tcp_init(soap)) - { soap_set_receiver_error(soap, tcp_error(soap), "TCP init failed in soap_bind()", SOAP_TCP_ERROR); - return SOAP_INVALID_SOCKET; - } -#ifdef WITH_IPV6 - memset((void*)&hints, 0, sizeof(hints)); - hints.ai_family = PF_UNSPEC; -#ifndef WITH_LEAN - if ((soap->omode & SOAP_IO_UDP)) - hints.ai_socktype = SOCK_DGRAM; - else + if (r < 0 && (soap->errnum = soap_socket_errno) == SOAP_EINTR && eintr > 0) + { + eintr--; + r = 0; + } + else if (retries-- <= 0) + { + break; + } + } while (r == 0); + if (r > 0) + { + r = 0; + if ((flags & SOAP_TCP_SELECT_RCV) && (pollfd[0].revents & POLLIN)) + r |= SOAP_TCP_SELECT_RCV; + if ((flags & SOAP_TCP_SELECT_SND) && (pollfd[0].revents & POLLOUT)) + r |= SOAP_TCP_SELECT_SND; + if ((flags & SOAP_TCP_SELECT_ERR) && (pollfd[0].revents & POLLERR)) + r |= SOAP_TCP_SELECT_ERR; +#ifdef WITH_SELF_PIPE + if ((flags & SOAP_TCP_SELECT_PIP) && (pollfd[1].revents & POLLIN)) + { + char ch; + for (;;) + { + if (read(soap->pipe_fd[0], &ch, 1) == -1) + { + if (soap_socket_errno == SOAP_EAGAIN) + break; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Self pipe read error\n")); + return -1; + } + } + r |= SOAP_TCP_SELECT_PIP; + } #endif - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_PASSIVE; - soap->errmode = 2; - err = getaddrinfo(host, soap_int2s(soap, port), &hints, &addrinfo); - if (addrinfo) - { res = *addrinfo; - memcpy(&soap->peer, addrinfo->ai_addr, addrinfo->ai_addrlen); - soap->peerlen = addrinfo->ai_addrlen; - res.ai_addr = (struct sockaddr*)&soap->peer; - res.ai_addrlen = soap->peerlen; - freeaddrinfo(addrinfo); - } - if (err || !addrinfo) - { soap_set_receiver_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in soap_bind()", SOAP_TCP_ERROR); - return SOAP_INVALID_SOCKET; + } + else if (r == 0) + { + soap->errnum = 0; + } + return r; } - soap->master = (int)socket(res.ai_family, res.ai_socktype, res.ai_protocol); #else -#ifndef WITH_LEAN - if ((soap->omode & SOAP_IO_UDP)) - soap->master = (int)socket(AF_INET, SOCK_DGRAM, 0); - else -#endif - soap->master = (int)socket(AF_INET, SOCK_STREAM, 0); -#endif - soap->errmode = 0; - if (!soap_valid_socket(soap->master)) - { soap->errnum = soap_socket_errno(soap->master); - soap_set_receiver_error(soap, tcp_error(soap), "socket failed in soap_bind()", SOAP_TCP_ERROR); - return SOAP_INVALID_SOCKET; + { + soap->error = SOAP_FD_EXCEEDED; + return -1; } -#ifndef WITH_LEAN - if ((soap->omode & SOAP_IO_UDP)) - soap->socket = soap->master; #endif -#ifdef SOCKET_CLOSE_ON_EXEC -#ifdef WIN32 -#ifndef UNDER_CE - SetHandleInformation((HANDLE)soap->master, HANDLE_FLAG_INHERIT, 0); #endif + if (timeout > 0) + retries = timeout - 1; + do + { + rfd = sfd = efd = NULL; +#ifdef WITH_SELF_PIPE + if ((flags & SOAP_TCP_SELECT_PIP) || (flags & SOAP_TCP_SELECT_RCV)) + { + rfd = &fd[0]; + FD_ZERO(rfd); + if ((flags & SOAP_TCP_SELECT_PIP)) + FD_SET(soap->pipe_fd[0], rfd); + if ((flags & SOAP_TCP_SELECT_RCV)) + FD_SET(sk, rfd); + } #else - fcntl(soap->master, F_SETFD, 1); -#endif + if ((flags & SOAP_TCP_SELECT_RCV)) + { + rfd = &fd[0]; + FD_ZERO(rfd); + FD_SET(sk, rfd); + } #endif -#ifndef WITH_LEAN - if (soap->bind_flags && setsockopt(soap->master, SOL_SOCKET, soap->bind_flags, (char*)&set, sizeof(int))) - { soap->errnum = soap_socket_errno(soap->master); - soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_bind()", SOAP_TCP_ERROR); - return SOAP_INVALID_SOCKET; - } - if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt(soap->master, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) - { soap->errnum = soap_socket_errno(soap->master); - soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_bind()", SOAP_TCP_ERROR); - return SOAP_INVALID_SOCKET; - } - if (setsockopt(soap->master, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) - { soap->errnum = soap_socket_errno(soap->master); - soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_bind()", SOAP_TCP_ERROR); - return SOAP_INVALID_SOCKET; - } - if (setsockopt(soap->master, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) - { soap->errnum = soap_socket_errno(soap->master); - soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_bind()", SOAP_TCP_ERROR); - return SOAP_INVALID_SOCKET; - } -#ifdef TCP_NODELAY - if (!(soap->omode & SOAP_IO_UDP) && setsockopt(soap->master, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) - { soap->errnum = soap_socket_errno(soap->master); - soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_bind()", SOAP_TCP_ERROR); - return SOAP_INVALID_SOCKET; - } -#endif -#endif -#ifdef WITH_IPV6 -#ifdef IPV6_V6ONLY - if (setsockopt(soap->master, level, IPV6_V6ONLY, (char*)&unset, sizeof(int))) - { soap->errnum = soap_socket_errno(soap->master); - soap_set_receiver_error(soap, tcp_error(soap), "setsockopt IPV6_V6ONLY failed in soap_bind()", SOAP_TCP_ERROR); - return SOAP_INVALID_SOCKET; - } -#endif - soap->errmode = 0; - if (bind(soap->master, res.ai_addr, (int)res.ai_addrlen)) - { soap->errnum = soap_socket_errno(soap->master); - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n")); - soap_closesock(soap); - soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR); - return SOAP_INVALID_SOCKET; - } -#else - soap->peerlen = sizeof(soap->peer); - memset((void*)&soap->peer, 0, sizeof(soap->peer)); - soap->peer.sin_family = AF_INET; - soap->errmode = 2; - if (host) - { if (soap->fresolve(soap, host, &soap->peer.sin_addr)) - { soap_set_receiver_error(soap, tcp_error(soap), "get host by name failed in soap_bind()", SOAP_TCP_ERROR); - return SOAP_INVALID_SOCKET; + if ((flags & SOAP_TCP_SELECT_SND)) + { + sfd = &fd[1]; + FD_ZERO(sfd); + FD_SET(sk, sfd); } - } - else - soap->peer.sin_addr.s_addr = htonl(INADDR_ANY); - soap->peer.sin_port = htons((short)port); - soap->errmode = 0; - if (bind(soap->master, (struct sockaddr*)&soap->peer, (int)soap->peerlen)) - { soap->errnum = soap_socket_errno(soap->master); - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n")); - soap_closesock(soap); - soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR); - return SOAP_INVALID_SOCKET; - } -#endif - if (!(soap->omode & SOAP_IO_UDP) && listen(soap->master, backlog)) - { soap->errnum = soap_socket_errno(soap->master); - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n")); - soap_closesock(soap); - soap_set_receiver_error(soap, tcp_error(soap), "listen failed in soap_bind()", SOAP_TCP_ERROR); - return SOAP_INVALID_SOCKET; - } - return soap->master; -} -#endif -#endif - -/******************************************************************************/ -#ifndef WITH_NOIO -#ifndef PALM_1 -SOAP_FMAC1 -int -SOAP_FMAC2 -soap_poll(struct soap *soap) -{ -#ifndef WITH_LEAN - int r; - if (soap_valid_socket(soap->socket)) - { r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_ALL, 0); - if (r > 0 && (r & SOAP_TCP_SELECT_ERR)) - r = -1; - } - else if (soap_valid_socket(soap->master)) - r = tcp_select(soap, soap->master, SOAP_TCP_SELECT_SND, 0); - else - return SOAP_OK; - if (r > 0) - { -#ifdef WITH_OPENSSL - if (soap->imode & SOAP_ENC_SSL) + if ((flags & SOAP_TCP_SELECT_ERR)) { - if (soap_valid_socket(soap->socket) - && (r & SOAP_TCP_SELECT_SND) - && (!(r & SOAP_TCP_SELECT_RCV) - || SSL_peek(soap->ssl, soap->tmpbuf, 1) > 0)) - return SOAP_OK; + efd = &fd[2]; + FD_ZERO(efd); + FD_SET(sk, efd); + } + if (timeout <= 0) + { + tv.tv_sec = -timeout / 1000000; + tv.tv_usec = -timeout % 1000000; } else -#endif - 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)) - 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) - { soap_set_receiver_error(soap, tcp_error(soap), "select failed in soap_poll()", SOAP_TCP_ERROR); - return soap->error = SOAP_TCP_ERROR; + { + tv.tv_sec = 1; + tv.tv_usec = 0; } - } - DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Polling: other end down on socket=%d select=%d\n", soap->socket, r)); - return SOAP_EOF; -#else - return SOAP_OK; -#endif -} -#endif -#endif - -/******************************************************************************/ -#ifndef WITH_LEAN -#ifndef WITH_NOIO -#ifndef PALM_1 -static int -tcp_select(struct soap *soap, SOAP_SOCKET s, int flags, int timeout) -{ int r; - struct timeval tv; - fd_set fd[3], *rfd, *sfd, *efd; - soap->errnum = 0; -#ifndef WIN32 - /* if fd max set size exceeded, use poll() when available */ -#if defined(__QNX__) || defined(QNX) /* select() is not MT safe on some QNX */ - if (1) +#ifdef WITH_SELF_PIPE + r = select((int)(sk > soap->pipe_fd[0] ? sk : soap->pipe_fd[0]) + 1, rfd, sfd, efd, &tv); #else - if ((int)s >= (int)FD_SETSIZE) + r = select((int)sk + 1, rfd, sfd, efd, &tv); #endif -#ifdef HAVE_POLL - { struct pollfd pollfd; - int retries = 0; - pollfd.fd = (int)s; - pollfd.events = 0; - if (flags & SOAP_TCP_SELECT_RCV) - pollfd.events |= POLLIN; - if (flags & SOAP_TCP_SELECT_SND) - pollfd.events |= POLLOUT; - if (flags & SOAP_TCP_SELECT_ERR) - pollfd.events |= POLLERR; - if (timeout < 0) - timeout /= -1000; /* -usec -> ms */ - else if (timeout <= 1000000) /* avoid overflow */ - timeout *= 1000; /* sec -> ms */ - else - { retries = timeout / 1000000; - timeout = 1000000000; + if (r < 0 && (soap->errnum = soap_socket_errno) == SOAP_EINTR && eintr > 0) + { + eintr--; + r = 0; } - do r = poll(&pollfd, 1, timeout); - while (r == 0 && retries--); - if (r > 0) - { r = 0; - if ((flags & SOAP_TCP_SELECT_RCV) && (pollfd.revents & POLLIN)) - r |= SOAP_TCP_SELECT_RCV; - if ((flags & SOAP_TCP_SELECT_SND) && (pollfd.revents & POLLOUT)) - r |= SOAP_TCP_SELECT_SND; - if ((flags & SOAP_TCP_SELECT_ERR) && (pollfd.revents & POLLERR)) - r |= SOAP_TCP_SELECT_ERR; + else if (retries-- <= 0) + { + break; } - else if (r < 0) - soap->errnum = soap_socket_errno(s); - return r; - } -#else - { soap->error = SOAP_FD_EXCEEDED; - return -1; - } -#endif -#endif - rfd = sfd = efd = NULL; - if (flags & SOAP_TCP_SELECT_RCV) - { rfd = &fd[0]; - FD_ZERO(rfd); - FD_SET(s, rfd); - } - if (flags & SOAP_TCP_SELECT_SND) - { sfd = &fd[1]; - FD_ZERO(sfd); - FD_SET(s, sfd); - } - if (flags & SOAP_TCP_SELECT_ERR) - { efd = &fd[2]; - FD_ZERO(efd); - FD_SET(s, 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)s + 1, rfd, sfd, efd, &tv); + } while (r == 0); if (r > 0) - { r = 0; - if ((flags & SOAP_TCP_SELECT_RCV) && FD_ISSET(s, rfd)) + { + r = 0; + if ((flags & SOAP_TCP_SELECT_RCV) && FD_ISSET(sk, rfd)) r |= SOAP_TCP_SELECT_RCV; - if ((flags & SOAP_TCP_SELECT_SND) && FD_ISSET(s, sfd)) + if ((flags & SOAP_TCP_SELECT_SND) && FD_ISSET(sk, sfd)) r |= SOAP_TCP_SELECT_SND; - if ((flags & SOAP_TCP_SELECT_ERR) && FD_ISSET(s, efd)) + if ((flags & SOAP_TCP_SELECT_ERR) && FD_ISSET(sk, efd)) r |= SOAP_TCP_SELECT_ERR; +#ifdef WITH_SELF_PIPE + if ((flags & SOAP_TCP_SELECT_PIP) && FD_ISSET(soap->pipe_fd[0], rfd)) + { + char ch; + for (;;) + { + if (read(soap->pipe_fd[0], &ch, 1) == -1) + { + if (soap_socket_errno == SOAP_EAGAIN) + break; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Self pipe read error\n")); + return -1; + } + } + r |= SOAP_TCP_SELECT_PIP; + } +#endif + } + else if (r == 0) + { + soap->errnum = 0; } - else if (r < 0) - soap->errnum = soap_socket_errno(s); return r; } #endif -#endif -#endif /******************************************************************************/ + #ifndef WITH_NOIO -#ifndef PALM_1 static SOAP_SOCKET -tcp_accept(struct soap *soap, SOAP_SOCKET s, struct sockaddr *a, int *n) -{ SOAP_SOCKET fd; - fd = accept(s, a, (SOAP_SOCKLEN_T*)n); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */ -#ifdef SOCKET_CLOSE_ON_EXEC +tcp_accept(struct soap *soap, SOAP_SOCKET sk, struct sockaddr *addr, int *len) +{ + SOAP_SOCKLEN_T n = (SOAP_SOCKLEN_T)*len; + SOAP_SOCKET s; + (void)soap; + s = accept(sk, addr, &n); +#ifdef WITH_SOCKET_CLOSE_ON_EXIT #ifdef WIN32 #ifndef UNDER_CE - SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0); + SetHandleInformation((HANDLE)s, HANDLE_FLAG_INHERIT, 0); #endif #else - fcntl(fd, F_SETFD, FD_CLOEXEC); + fcntl(s, F_SETFD, FD_CLOEXEC); #endif #endif - return fd; + return s; } #endif -#endif /******************************************************************************/ -#ifndef WITH_NOIO -#ifndef PALM_1 -SOAP_FMAC1 -SOAP_SOCKET -SOAP_FMAC2 -soap_accept(struct soap *soap) -{ int n = (int)sizeof(soap->peer); -#ifndef WITH_LEAN - int len = SOAP_BUFLEN; - int set = 1; -#endif - soap->error = SOAP_OK; -#ifndef WITH_LEAN - if ((soap->omode & SOAP_IO_UDP)) - return soap->socket = soap->master; -#endif - memset((void*)&soap->peer, 0, sizeof(soap->peer)); - soap->socket = SOAP_INVALID_SOCKET; - soap->errmode = 0; - soap->keep_alive = 0; - if (soap_valid_socket(soap->master)) - { int err; - for (;;) - { -#ifndef WITH_LEAN - if (soap->accept_timeout || soap->send_timeout || soap->recv_timeout) - { for (;;) - { int r; - r = tcp_select(soap, soap->master, SOAP_TCP_SELECT_ALL, soap->accept_timeout ? soap->accept_timeout : 60); - if (r > 0) - break; - if (!r && soap->accept_timeout) - { soap_set_receiver_error(soap, "Timeout", "accept failed in soap_accept()", SOAP_TCP_ERROR); - return SOAP_INVALID_SOCKET; - } - if (r < 0) - { r = soap->errnum; - if (r != SOAP_EINTR) - { soap_closesock(soap); - soap_set_sender_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR); - return SOAP_INVALID_SOCKET; - } - } - } - } - if (soap->accept_timeout || soap->send_timeout || soap->recv_timeout) - SOAP_SOCKNONBLOCK(soap->master) - else - SOAP_SOCKBLOCK(soap->master) -#endif - soap->socket = soap->faccept(soap, soap->master, (struct sockaddr*)&soap->peer, &n); - soap->peerlen = (size_t)n; - if (soap_valid_socket(soap->socket)) - { -#ifdef WITH_IPV6 -/* Use soap->host to store the numeric form of the remote host */ - getnameinfo((struct sockaddr*)&soap->peer, n, soap->host, sizeof(soap->host), NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV); - DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket %d from %s\n", soap->socket, soap->host)); - soap->ip = 0; /* info stored in soap->peer and soap->host */ - soap->port = 0; /* info stored in soap->peer and soap->host */ -#else - soap->ip = ntohl(soap->peer.sin_addr.s_addr); - soap->port = (int)ntohs(soap->peer.sin_port); /* does not return port number on some systems */ - DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket %d at port %d from IP %d.%d.%d.%d\n", soap->socket, soap->port, (int)(soap->ip>>24)&0xFF, (int)(soap->ip>>16)&0xFF, (int)(soap->ip>>8)&0xFF, (int)soap->ip&0xFF)); -#endif -#ifndef WITH_LEAN - if (soap->accept_flags == SO_LINGER) - { struct linger linger; - memset((void*)&linger, 0, sizeof(linger)); - linger.l_onoff = 1; - linger.l_linger = soap->linger_time; - if (setsockopt(soap->socket, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger))) - { soap->errnum = soap_socket_errno(soap->socket); - soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in soap_accept()", SOAP_TCP_ERROR); - soap_closesock(soap); - return SOAP_INVALID_SOCKET; - } - } - else if (soap->accept_flags && setsockopt(soap->socket, SOL_SOCKET, soap->accept_flags, (char*)&set, sizeof(int))) - { soap->errnum = soap_socket_errno(soap->socket); - soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_accept()", SOAP_TCP_ERROR); - soap_closesock(soap); - return SOAP_INVALID_SOCKET; - } - if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt(soap->socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) - { soap->errnum = soap_socket_errno(soap->socket); - soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_accept()", SOAP_TCP_ERROR); - soap_closesock(soap); - return SOAP_INVALID_SOCKET; - } - if (setsockopt(soap->socket, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) - { soap->errnum = soap_socket_errno(soap->socket); - soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_accept()", SOAP_TCP_ERROR); - soap_closesock(soap); - return SOAP_INVALID_SOCKET; - } - if (setsockopt(soap->socket, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) - { soap->errnum = soap_socket_errno(soap->socket); - soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_accept()", SOAP_TCP_ERROR); - soap_closesock(soap); - return SOAP_INVALID_SOCKET; - } -#ifdef TCP_NODELAY - if (!(soap->omode & SOAP_IO_UDP) && setsockopt(soap->socket, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) - { soap->errnum = soap_socket_errno(soap->socket); - soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_accept()", SOAP_TCP_ERROR); - soap_closesock(soap); - return SOAP_INVALID_SOCKET; - } -#endif -#endif - soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0); - return soap->socket; - } - err = soap_socket_errno(soap->socket); - if (err != 0 && err != SOAP_EINTR && err != SOAP_EAGAIN && err != SOAP_EWOULDBLOCK) - { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept failed from %s\n", soap->host)); - soap->errnum = err; - soap_set_receiver_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR); - soap_closesock(soap); - return SOAP_INVALID_SOCKET; - } - } - } - else - { soap->errnum = 0; - soap_set_receiver_error(soap, tcp_error(soap), "no master socket in soap_accept()", SOAP_TCP_ERROR); - return SOAP_INVALID_SOCKET; - } -} -#endif -#endif -/******************************************************************************/ #ifndef WITH_NOIO -#ifndef PALM_1 static int tcp_disconnect(struct soap *soap) { #ifdef WITH_OPENSSL if (soap->ssl) - { int r, s = 0; + { + int r; if (soap->session) - { SSL_SESSION_free(soap->session); + { + SSL_SESSION_free(soap->session); soap->session = NULL; } if (*soap->host) - { soap->session = SSL_get1_session(soap->ssl); + { + soap->session = SSL_get1_session(soap->ssl); if (soap->session) - { strcpy(soap->session_host, soap->host); + { + soap_strcpy(soap->session_host, sizeof(soap->session_host), soap->host); soap->session_port = soap->port; } } - r = SSL_shutdown(soap->ssl); - /* SSL shutdown does not work when reads are pending */ - while (SSL_want_read(soap->ssl)) - { SSL_read(soap->ssl, NULL, 0); - if (soap_socket_errno(soap->socket) != SOAP_EAGAIN) - { r = SSL_shutdown(soap->ssl); - break; - } - } - if (r == 0) - { if (soap_valid_socket(soap->socket)) - { if (!soap->fshutdownsocket(soap, soap->socket, 1)) - { /* - wait up to 10 seconds for close_notify to be sent by peer (if peer not - present, this avoids calling SSL_shutdown() which has a lengthy return - timeout) - */ - r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, 10); - if (r <= 0 && soap->errnum != SOAP_EINTR) - { soap->errnum = 0; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connection lost...\n")); - soap->fclosesocket(soap, soap->socket); - soap->socket = SOAP_INVALID_SOCKET; - ERR_remove_state(0); - return SOAP_OK; + if (soap_valid_socket(soap->socket)) + { + r = SSL_shutdown(soap->ssl); + /* SSL shutdown does not work when reads are pending, non-blocking */ + if (r == 0) + { + while (SSL_want_read(soap->ssl)) + { + if (SSL_read(soap->ssl, NULL, 0) + || soap_socket_errno != SOAP_EAGAIN) + { + r = SSL_shutdown(soap->ssl); + break; } } } - } - if (r != 1) - { s = ERR_get_error(); - if (s) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown failed: %d\n", SSL_get_error(soap->ssl, r))); - if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP)) - { soap->fclosesocket(soap, soap->socket); + if (r == 0 && !soap->fshutdownsocket(soap, soap->socket, SOAP_SHUT_WR)) + { +#if !defined(WITH_LEAN) && !defined(WIN32) + /* + wait up to 5 seconds for close_notify to be sent by peer (if peer not + present, this avoids calling SSL_shutdown() which has a lengthy return + timeout) + */ + r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, 5); + if (r <= 0) + { + soap->errnum = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connection lost...\n")); + (void)soap->fclosesocket(soap, soap->socket); soap->socket = SOAP_INVALID_SOCKET; + ERR_clear_error(); + SSL_free(soap->ssl); + soap->ssl = NULL; + return SOAP_OK; + } +#ifdef WITH_SSL_FULL_SHUTDOWN + if (!SSL_want_read(soap->ssl) || SSL_read(soap->ssl, NULL, 0)) + { + r = SSL_shutdown(soap->ssl); + if (r <= 0) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown failed: %d\n", SSL_get_error(soap->ssl, r))); + if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP)) + { + (void)soap->fclosesocket(soap, soap->socket); + soap->socket = SOAP_INVALID_SOCKET; + } + } + } +#endif +#else + r = SSL_shutdown(soap->ssl); + if (r <= 0) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown failed: %d\n", SSL_get_error(soap->ssl, r))); + if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP)) + { + (void)soap->fclosesocket(soap, soap->socket); + soap->socket = SOAP_INVALID_SOCKET; + } } +#endif } } SSL_free(soap->ssl); soap->ssl = NULL; - if (s) - return SOAP_SSL_ERROR; - ERR_remove_state(0); + ERR_clear_error(); + } +#endif +#ifdef WITH_GNUTLS + if (soap->session) + { + gnutls_bye(soap->session, GNUTLS_SHUT_RDWR); + gnutls_deinit(soap->session); + soap->session = NULL; + } +#endif +#ifdef WITH_WOLFSSL + if (soap->ssl) + { + wolfSSL_free(soap->ssl); + soap->ssl = NULL; + } +#endif +#ifdef WITH_SYSTEMSSL + if (soap->ssl) + { + gsk_secure_socket_shutdown(soap->ssl); + gsk_secure_socket_close(&soap->ssl); } #endif if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP)) - { soap->fshutdownsocket(soap, soap->socket, 2); - soap->fclosesocket(soap, soap->socket); + { + (void)soap->fshutdownsocket(soap, soap->socket, SOAP_SHUT_RDWR); + (void)soap->fclosesocket(soap, soap->socket); soap->socket = SOAP_INVALID_SOCKET; } return SOAP_OK; } #endif -#endif /******************************************************************************/ + #ifndef WITH_NOIO -#ifndef PALM_1 static int -tcp_closesocket(struct soap *soap, SOAP_SOCKET fd) -{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Close socket %d\n", (int)fd)); - return soap_closesocket(fd); +tcp_closesocket(struct soap *soap, SOAP_SOCKET sk) +{ + (void)soap; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Close socket=%d\n", (int)sk)); + return soap_closesocket(sk); } #endif -#endif /******************************************************************************/ + #ifndef WITH_NOIO -#ifndef PALM_1 static int -tcp_shutdownsocket(struct soap *soap, SOAP_SOCKET fd, int how) -{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown socket %d how=%d\n", (int)fd, how)); - return shutdown(fd, how); +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)); + return shutdown(sk, how); } #endif -#endif /******************************************************************************/ -#ifndef PALM_1 + +#ifndef WITH_NOIO SOAP_FMAC1 -int +SOAP_SOCKET SOAP_FMAC2 -soap_closesock(struct soap *soap) -{ int status = soap->error; - if (status == SOAP_EOF || status == SOAP_TCP_ERROR || status == SOAP_SSL_ERROR || !soap->keep_alive) - { if (soap->fclose && (soap->error = soap->fclose(soap))) - return soap->error; - 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; +soap_bind(struct soap *soap, const char *host, int port, int backlog) +{ +#if defined(WITH_IPV6) + struct addrinfo *addrinfo = NULL; + struct addrinfo hints; + struct addrinfo res; + int err; + int set = 1; + int unset = 0; +#elif !defined(WITH_LEAN) + int set = 1; #endif - return soap->error = status; -} + if (soap_valid_socket(soap->master)) + { + (void)soap->fclosesocket(soap, soap->master); + soap->master = SOAP_INVALID_SOCKET; + } + soap->socket = SOAP_INVALID_SOCKET; + soap->errnum = 0; + soap->errmode = 1; + if (tcp_init(soap)) + { + (void)soap_set_receiver_error(soap, tcp_error(soap), "TCP init failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#ifdef WITH_IPV6 + memset((void*)&hints, 0, sizeof(hints)); + hints.ai_family = soap->bind_inet6 ? AF_INET6 : PF_UNSPEC; +#ifndef WITH_LEAN + if ((soap->omode & SOAP_IO_UDP)) + hints.ai_socktype = SOCK_DGRAM; + else #endif - -/******************************************************************************/ -#ifndef WITH_NOIDREF -#ifndef PALM_2 -SOAP_FMAC1 -size_t -SOAP_FMAC2 -soap_hash(const char *s) -{ size_t h = 0; - while (*s) - h = 65599*h + *s++; - return h % SOAP_IDHASH; -} + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + soap->errmode = 2; + err = getaddrinfo(host, soap_int2s(soap, port), &hints, &addrinfo); + if (err || !addrinfo) + { + (void)soap_set_receiver_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in soap_bind()", SOAP_TCP_ERROR); + if (addrinfo) + freeaddrinfo(addrinfo); + return SOAP_INVALID_SOCKET; + } + res = *addrinfo; + if (soap_memcpy((void*)&soap->peer.storage, sizeof(soap->peer.storage), (const void*)addrinfo->ai_addr, addrinfo->ai_addrlen)) + { + freeaddrinfo(addrinfo); + soap->error = SOAP_EOM; + return SOAP_INVALID_SOCKET; + } + soap->peerlen = addrinfo->ai_addrlen; + res.ai_addr = &soap->peer.addr; + res.ai_addrlen = soap->peerlen; + freeaddrinfo(addrinfo); + soap->master = (int)socket(res.ai_family, res.ai_socktype, res.ai_protocol); +#else +#ifndef WITH_LEAN + if ((soap->omode & SOAP_IO_UDP)) + soap->master = (int)socket(AF_INET, SOCK_DGRAM, 0); + else #endif + soap->master = (int)socket(AF_INET, SOCK_STREAM, 0); #endif - -/******************************************************************************/ -#ifndef WITH_NOIDREF -#ifndef PALM_1 -static void -soap_init_pht(struct soap *soap) -{ int i; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing pointer hashtable\n")); - soap->pblk = NULL; - soap->pidx = 0; - for (i = 0; i < (int)SOAP_PTRHASH; i++) - soap->pht[i] = NULL; -} + soap->errmode = 0; + if (!soap_valid_socket(soap->master)) + { + soap->errnum = soap_socket_errno; + (void)soap_set_receiver_error(soap, tcp_error(soap), "socket failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + soap->port = port; +#ifndef WITH_LEAN + if ((soap->omode & SOAP_IO_UDP)) + soap->socket = soap->master; #endif +#ifdef WITH_SOCKET_CLOSE_ON_EXIT +#ifdef WIN32 +#ifndef UNDER_CE + SetHandleInformation((HANDLE)soap->master, HANDLE_FLAG_INHERIT, 0); #endif - -/******************************************************************************/ -#ifndef PALM_1 -SOAP_FMAC1 -struct soap* -SOAP_FMAC2 -soap_new1(soap_mode mode) -{ return soap_new2(mode, mode); -} +#else + fcntl(soap->master, F_SETFD, 1); #endif - -/******************************************************************************/ -#ifndef PALM_1 -SOAP_FMAC1 -struct soap* -SOAP_FMAC2 -soap_new() -{ return soap_new2(SOAP_IO_DEFAULT, SOAP_IO_DEFAULT); -} #endif - -/******************************************************************************/ -#ifndef PALM_1 -SOAP_FMAC1 -struct soap* -SOAP_FMAC2 -soap_new2(soap_mode imode, soap_mode omode) -{ struct soap *soap = (struct soap*)malloc(sizeof(struct soap)); - if (soap) - soap_init2(soap, imode, omode); - return soap; -} +#ifndef WITH_LEAN + if (soap->bind_flags && setsockopt(soap->master, SOL_SOCKET, soap->bind_flags, (char*)&set, sizeof(int))) + { + soap->errnum = soap_socket_errno; + (void)soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#ifndef UNDER_CE + if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && (!((soap->imode | soap->omode) & SOAP_IO_UDP)) && setsockopt(soap->master, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) + { + soap->errnum = soap_socket_errno; + (void)soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + if (soap->sndbuf > 0 && setsockopt(soap->master, SOL_SOCKET, SO_SNDBUF, (char*)&soap->sndbuf, sizeof(int))) + { + soap->errnum = soap_socket_errno; + (void)soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + if (soap->rcvbuf > 0 && setsockopt(soap->master, SOL_SOCKET, SO_RCVBUF, (char*)&soap->rcvbuf, sizeof(int))) + { + soap->errnum = soap_socket_errno; + (void)soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#ifdef TCP_NODELAY + if (!(soap->omode & SOAP_IO_UDP) && setsockopt(soap->master, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) + { + soap->errnum = soap_socket_errno; + (void)soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } #endif - -/******************************************************************************/ -#ifndef PALM_1 -SOAP_FMAC1 -void -SOAP_FMAC2 -soap_free(struct soap *soap) -{ soap_done(soap); - free(soap); -} +#ifdef TCP_FASTOPEN + if (!(soap->omode & SOAP_IO_UDP) && setsockopt(soap->master, IPPROTO_TCP, TCP_FASTOPEN, (char*)&set, sizeof(int))) + { + /* silently ignore */ + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "setsockopt TCP_FASTOPEN failed in soap_bind()\n")); + } #endif - -/******************************************************************************/ -#ifndef PALM_1 -SOAP_FMAC1 -void -SOAP_FMAC2 -soap_del(struct soap *soap) -{ free(soap); -} #endif - -/******************************************************************************/ -#ifndef WITH_NOIDREF -#ifndef PALM_1 -static void -soap_free_pht(struct soap *soap) -{ struct soap_pblk *pb, *next; - int i; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free pointer hashtable\n")); - for (pb = soap->pblk; pb; pb = next) - { next = pb->next; - SOAP_FREE(soap, pb); +#endif +#ifdef WITH_IPV6 + if (res.ai_family == AF_INET6 && setsockopt(soap->master, IPPROTO_IPV6, IPV6_V6ONLY, soap->bind_v6only ? (char*)&set : (char*)&unset, sizeof(int))) + { + soap->errnum = soap_socket_errno; + (void)soap_set_receiver_error(soap, tcp_error(soap), "setsockopt IPV6_V6ONLY failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + soap->errmode = 0; + if (bind(soap->master, res.ai_addr, (int)res.ai_addrlen)) + { + soap->errnum = soap_socket_errno; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host, bind failed\n")); + (void)soap_closesock(soap); + (void)soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#else + soap->peerlen = sizeof(soap->peer.in); + memset((void*)&soap->peer.in, 0, sizeof(soap->peer.in)); + soap->peer.in.sin_family = AF_INET; + soap->errmode = 2; + if (host) + { + if (soap->fresolve(soap, host, &soap->peer.in.sin_addr)) + { + (void)soap_set_receiver_error(soap, tcp_error(soap), "get host by name failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + } + else + { + soap->peer.in.sin_addr.s_addr = htonl(INADDR_ANY); + } + soap->peer.in.sin_port = htons((short)port); + soap->errmode = 0; + if (bind(soap->master, &soap->peer.addr, (int)soap->peerlen)) + { + soap->errnum = soap_socket_errno; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host, bind failed\n")); + (void)soap_closesock(soap); + (void)soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; } - soap->pblk = NULL; - soap->pidx = 0; - for (i = 0; i < (int)SOAP_PTRHASH; i++) - soap->pht[i] = NULL; -} #endif + if (!(soap->omode & SOAP_IO_UDP) && listen(soap->master, backlog)) + { + soap->errnum = soap_socket_errno; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host, listen failed\n")); + (void)soap_closesock(soap); + (void)soap_set_receiver_error(soap, tcp_error(soap), "listen failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + return soap->master; +} #endif /******************************************************************************/ -#ifndef WITH_NOIDREF -#ifndef PALM_2 + +#ifndef WITH_NOIO SOAP_FMAC1 int SOAP_FMAC2 -soap_embed(struct soap *soap, const void *p, const struct soap_array *a, int n, const char *tag, int type) -{ int i; - struct soap_plist *pp; - if (soap->version == 2) - soap->encoding = 1; - if (a) - i = soap_array_pointer_lookup(soap, p, a, n, type, &pp); +soap_poll(struct soap *soap) +{ +#ifndef WITH_LEAN + int r; + if (soap_valid_socket(soap->socket)) + { + r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_ALL, 0); + if (r > 0 && (r & SOAP_TCP_SELECT_ERR)) + r = -1; + } + else if (soap_valid_socket(soap->master)) + { + r = tcp_select(soap, soap->master, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, 0); + } else - i = soap_pointer_lookup(soap, p, type, &pp); - if (i) - { if (soap_is_embedded(soap, pp) - || soap_is_single(soap, pp)) - return 0; - soap_set_embedded(soap, pp); + { + return SOAP_OK; /* OK when no socket! */ } - return i; -} -#endif + if (r > 0) + { + int t; +#ifdef WITH_OPENSSL + if ((soap->imode & SOAP_ENC_SSL) && soap->ssl) + { + if (soap_valid_socket(soap->socket) + && (r & SOAP_TCP_SELECT_SND) + && (!(r & SOAP_TCP_SELECT_RCV) + || SSL_peek(soap->ssl, (char*)&t, 1) > 0)) + return SOAP_OK; + } + else #endif - -/******************************************************************************/ -#ifndef WITH_NOIDREF -#ifndef PALM_2 -SOAP_FMAC1 -int -SOAP_FMAC2 -soap_pointer_lookup(struct soap *soap, const void *p, int type, struct soap_plist **ppp) -{ struct soap_plist *pp; - *ppp = NULL; - if (p) - { for (pp = soap->pht[soap_hash_ptr(p)]; pp; pp = pp->next) - { if (pp->ptr == p && pp->type == type) - { *ppp = pp; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d id=%d\n", p, type, pp->id)); - return pp->id; - } + { + if (soap_valid_socket(soap->socket) + && (r & SOAP_TCP_SELECT_SND) + && (!(r & SOAP_TCP_SELECT_RCV) + || recv(soap->socket, (char*)&t, 1, MSG_PEEK) > 0)) + return SOAP_OK; } } - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d: not found\n", p, type)); - return 0; -} + else if (r < 0) + { + if ((soap_valid_socket(soap->master) && soap_socket_errno != SOAP_EINTR) + || (soap_valid_socket(soap->socket) && soap_socket_errno != SOAP_EINTR)) + return soap_set_receiver_error(soap, tcp_error(soap), "select failed in soap_poll()", SOAP_TCP_ERROR); + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "soap_poll: other end down on socket=%d select=%d\n", (int)soap->socket, r)); + return SOAP_EOF; +#else + (void)soap; + return SOAP_OK; #endif +} #endif /******************************************************************************/ -#ifndef WITH_NOIDREF -#ifndef PALM_2 + +#ifndef WITH_NOIO SOAP_FMAC1 int SOAP_FMAC2 -soap_pointer_enter(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp) -{ size_t h; - struct soap_plist *pp; - if (!soap->pblk || soap->pidx >= SOAP_PTRBLK) - { struct soap_pblk *pb = (struct soap_pblk*)SOAP_MALLOC(soap, sizeof(struct soap_pblk)); - if (!pb) - { soap->error = SOAP_EOM; - return 0; - } - pb->next = soap->pblk; - soap->pblk = pb; - soap->pidx = 0; - } - *ppp = pp = &soap->pblk->plist[soap->pidx++]; - if (a) - h = soap_hash_ptr(a->__ptr); - else - h = soap_hash_ptr(p); - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pointer enter location=%p array=%p size=%d dim=%d type=%d id=%d\n", p, a?a->__ptr:NULL, a?a->__size:0, n, type, soap->idnum+1)); - pp->next = soap->pht[h]; - pp->type = type; - pp->mark1 = 0; - pp->mark2 = 0; - pp->ptr = p; - pp->array = a; - soap->pht[h] = pp; - pp->id = ++soap->idnum; - return pp->id; -} +soap_ready(struct soap *soap) +{ +#ifndef WITH_LEAN + int r; + if (!soap_valid_socket(soap->socket)) + return SOAP_OK; /* OK when no socket! */ + r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, 0); + if (r > 0 && (r & SOAP_TCP_SELECT_ERR)) + r = -1; + if (r < 0 && soap_socket_errno != SOAP_EINTR) + return soap_set_receiver_error(soap, tcp_error(soap), "select failed in soap_ready()", SOAP_TCP_ERROR); + if (r > 0) + { + char t; +#ifdef WITH_OPENSSL + if ((soap->imode & SOAP_ENC_SSL) && soap->ssl) + { + if (SSL_peek(soap->ssl, &t, 1) > 0) + return SOAP_OK; + } + else +#endif + { + if (recv(soap->socket, &t, 1, MSG_PEEK) > 0) + return SOAP_OK; + } + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "soap_ready: other end not ready to send on socket=%d select=%d\n", (int)soap->socket, r)); + return SOAP_EOF; +#else + (void)soap; + return SOAP_OK; #endif +} #endif - /******************************************************************************/ -#ifndef WITH_NOIDREF -#ifndef PALM_2 + +#ifndef WITH_NOIO SOAP_FMAC1 -int +SOAP_SOCKET SOAP_FMAC2 -soap_array_pointer_lookup(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp) -{ struct soap_plist *pp; - *ppp = NULL; - if (!p || !a->__ptr) - return 0; - for (pp = soap->pht[soap_hash_ptr(a->__ptr)]; pp; pp = pp->next) - { if (pp->type == type && pp->array && pp->array->__ptr == a->__ptr) - { int i; - for (i = 0; i < n; i++) - if (((const int*)&pp->array->__size)[i] != ((const int*)&a->__size)[i]) +soap_accept(struct soap *soap) +{ + int n = (int)sizeof(soap->peer); + int err; +#ifndef WITH_LEAN + int set = 1; +#endif + soap->error = SOAP_OK; + memset((void*)&soap->peer, 0, sizeof(soap->peer)); + soap->socket = SOAP_INVALID_SOCKET; + soap->errmode = 0; + soap_reset_errno; + soap->errnum = 0; + soap->keep_alive = 0; + if (!soap_valid_socket(soap->master)) + { + (void)soap_set_receiver_error(soap, tcp_error(soap), "no master socket in soap_accept()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#ifndef WITH_LEAN + if ((soap->omode & SOAP_IO_UDP)) + return soap->socket = soap->master; +#endif + for (;;) + { + if (soap->accept_timeout) + { + for (;;) + { + int r; + r = tcp_select(soap, soap->master, SOAP_TCP_SELECT_ALL, soap->accept_timeout); + if (r > 0) break; - if (i == n) - { *ppp = pp; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d id=%d\n", a->__ptr, type, pp->id)); - return pp->id; + if (!r) + { + (void)soap_set_receiver_error(soap, "Timeout", "accept failed in soap_accept()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + if (r < 0) + { + r = soap->errnum; + if (r != SOAP_EINTR) + { + (void)soap_closesock(soap); + (void)soap_set_receiver_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + } + } + } + n = (int)sizeof(soap->peer); + soap->socket = soap->faccept(soap, soap->master, &soap->peer.addr, &n); + soap->peerlen = (size_t)n; + if (soap_valid_socket(soap->socket)) + { +#ifdef WITH_IPV6 + char port[16]; + struct addrinfo *res = NULL; + struct addrinfo hints; + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV; + getnameinfo(&soap->peer.addr, n, soap->host, sizeof(soap->host), port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV); + soap->ip = 0; + soap->ip6[0] = 0; + soap->ip6[1] = 0; + soap->ip6[2] = 0; + soap->ip6[3] = 0; + if (getaddrinfo(soap->host, NULL, &hints, &res) == 0 && res) + { + struct sockaddr_storage result; + memset((void*)&result, 0, sizeof(result)); + (void)soap_memcpy(&result, sizeof(result), res->ai_addr, res->ai_addrlen); + freeaddrinfo(res); + if (result.ss_family == AF_INET6) + { + struct sockaddr_in6 *addr = (struct sockaddr_in6*)&result; + struct in6_addr *inaddr = &addr->sin6_addr; + int i; + for (i = 0; i < 16; i++) + soap->ip6[i/4] = (soap->ip6[i/4] << 8) + inaddr->s6_addr[i]; + } + else if (result.ss_family == AF_INET) + { + struct sockaddr_in *addr = (struct sockaddr_in*)&result; + soap->ip = ntohl(addr->sin_addr.s_addr); + soap->ip6[2] = 0xFFFF; + soap->ip6[3] = soap->ip; + } + } + soap->port = soap_strtol(port, NULL, 10); +#else + soap->ip = ntohl(soap->peer.in.sin_addr.s_addr); + soap->ip6[0] = 0; + soap->ip6[1] = 0; + soap->ip6[2] = 0xFFFF; + soap->ip6[3] = soap->ip; + (SOAP_SNPRINTF(soap->host, sizeof(soap->host), 80), "%u.%u.%u.%u", (int)(soap->ip>>24)&0xFF, (int)(soap->ip>>16)&0xFF, (int)(soap->ip>>8)&0xFF, (int)soap->ip&0xFF); + soap->port = (int)ntohs(soap->peer.in.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", (int)soap->socket, soap->port, soap->host)); +#ifndef WITH_LEAN + if ((soap->accept_flags & SO_LINGER)) + { + struct linger linger; + memset((void*)&linger, 0, sizeof(linger)); + linger.l_onoff = 1; + linger.l_linger = soap->linger_time; + if (setsockopt(soap->socket, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger))) + { + soap->errnum = soap_socket_errno; + (void)soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in soap_accept()", SOAP_TCP_ERROR); + (void)soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } + } + if ((soap->accept_flags & ~SO_LINGER) && setsockopt(soap->socket, SOL_SOCKET, soap->accept_flags & ~SO_LINGER, (char*)&set, sizeof(int))) + { + soap->errnum = soap_socket_errno; + (void)soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_accept()", SOAP_TCP_ERROR); + (void)soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } +#ifndef UNDER_CE + if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt(soap->socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) + { + soap->errnum = soap_socket_errno; + (void)soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_accept()", SOAP_TCP_ERROR); + (void)soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } + if (soap->sndbuf > 0 && setsockopt(soap->socket, SOL_SOCKET, SO_SNDBUF, (char*)&soap->sndbuf, sizeof(int))) + { + soap->errnum = soap_socket_errno; + (void)soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_accept()", SOAP_TCP_ERROR); + (void)soap_closesock(soap); + return SOAP_INVALID_SOCKET; } + if (soap->rcvbuf > 0 && setsockopt(soap->socket, SOL_SOCKET, SO_RCVBUF, (char*)&soap->rcvbuf, sizeof(int))) + { + soap->errnum = soap_socket_errno; + (void)soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_accept()", SOAP_TCP_ERROR); + (void)soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } +#ifdef TCP_NODELAY + if (setsockopt(soap->socket, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) + { + soap->errnum = soap_socket_errno; + (void)soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_accept()", SOAP_TCP_ERROR); + (void)soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } +#endif +#endif +#endif + soap->keep_alive = -(((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0); + if (soap->send_timeout || soap->recv_timeout) + SOAP_SOCKNONBLOCK(soap->socket) + else + SOAP_SOCKBLOCK(soap->socket) + return soap->socket; + } + err = soap_socket_errno; + if (err != 0 && err != SOAP_EINTR && err != SOAP_EAGAIN && err != SOAP_EWOULDBLOCK) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Accept failed from %s\n", soap->host)); + soap->errnum = err; + (void)soap_set_receiver_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR); + (void)soap_closesock(soap); + return SOAP_INVALID_SOCKET; } } - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d: not found\n", a->__ptr, type)); - return 0; } #endif -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 int SOAP_FMAC2 -soap_begin_count(struct soap *soap) -{ soap_free_ns(soap); -#ifndef WITH_LEANER - if ((soap->mode & SOAP_ENC_DIME) || (soap->omode & SOAP_ENC_DIME)) - soap->mode = soap->omode | SOAP_IO_LENGTH | SOAP_ENC_DIME; - else -#endif - { soap->mode = soap->omode; - if ((soap->mode & SOAP_IO) == SOAP_IO_STORE - || (((soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_ENC_XML)) +soap_closesock(struct soap *soap) +{ + int status = soap->error; + int err = SOAP_OK; + soap->part = SOAP_END; #ifndef WITH_LEANER - && !soap->fpreparesend + if (status && status < 200) /* attachment state is not to be trusted */ + { + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->dime.first = NULL; + soap->dime.last = NULL; + } #endif - )) - soap->mode &= ~SOAP_IO_LENGTH; - else - soap->mode |= SOAP_IO_LENGTH; + if (soap->fdisconnect) + err = soap->fdisconnect(soap); + if (err || status == SOAP_EOF || status == SOAP_TCP_ERROR || status == SOAP_SSL_ERROR || !soap->keep_alive) + { + soap->keep_alive = 0; + if (soap->fclose && (soap->error = soap->fclose(soap)) != SOAP_OK) + return soap->error; + if (err) + return soap->error = err; } #ifdef WITH_ZLIB - if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH) - { if (!(soap->mode & SOAP_ENC_DIME)) - soap->mode &= ~SOAP_IO_LENGTH; - if (soap->mode & SOAP_ENC_XML) - soap->mode |= SOAP_IO_BUFFER; - else - soap->mode |= SOAP_IO_STORE; + 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 - 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; - else if (!(soap->mode & SOAP_ENC_MIME)) - soap->mode &= ~SOAP_ENC_MTOM; - if (soap->mode & SOAP_ENC_MIME) - soap_select_mime_boundary(soap); - soap->dime.list = soap->dime.last; /* keep track of last DIME attachment */ -#endif - soap->count = 0; - soap->ns = 0; - soap->null = 0; - soap->position = 0; - soap->mustUnderstand = 0; - soap->encoding = 0; - soap->part = SOAP_BEGIN; - 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, 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->fprepareinit && (soap->mode & SOAP_IO) != SOAP_IO_STORE) - return soap->error = soap->fprepareinit(soap); -#endif - return SOAP_OK; + return soap->error = status; } -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 int SOAP_FMAC2 -soap_end_count(struct soap *soap) +soap_force_closesock(struct soap *soap) { -#ifndef WITH_LEANER - if (soap->fpreparefinal) - return soap->error = soap->fpreparefinal(soap); -#endif - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of count phase\n")); - return SOAP_OK; + soap->keep_alive = 0; + if (soap_valid_socket(soap->socket) && soap->fclosesocket) + { + (void)soap->fclosesocket(soap, soap->socket); + soap->socket = SOAP_INVALID_SOCKET; + } + return soap->error; } -#endif /******************************************************************************/ -#ifndef PALM_1 + +#ifdef WITH_SELF_PIPE SOAP_FMAC1 -int +void SOAP_FMAC2 -soap_begin_send(struct soap *soap) -{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing for output\n")); - soap_free_ns(soap); - soap->error = SOAP_OK; - soap->mode = soap->omode | (soap->mode & (SOAP_IO_LENGTH | SOAP_ENC_DIME)); -#ifdef WITH_ZLIB - if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH) - { if (soap->mode & SOAP_ENC_XML) - soap->mode |= SOAP_IO_BUFFER; - else - soap->mode |= SOAP_IO_STORE; - } -#endif -#ifndef WITH_LEAN - if ((soap->mode & SOAP_IO_UDP)) - { soap->mode |= SOAP_ENC_XML; - if (soap->count > SOAP_BUFLEN) - return soap->error = SOAP_UDP_ERROR; - } +soap_close_connection(struct soap *soap) +{ + if (soap_valid_socket(soap->socket)) + write(soap->pipe_fd[1], "1", 1); +} #endif - if ((soap->mode & SOAP_IO) == SOAP_IO_FLUSH && soap_valid_socket(soap->socket)) - { if (soap->count || (soap->mode & SOAP_IO_LENGTH) || (soap->mode & SOAP_ENC_XML)) - soap->mode |= SOAP_IO_BUFFER; - else - soap->mode |= SOAP_IO_STORE; - } - soap->mode &= ~SOAP_IO_LENGTH; - if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) - if (soap_new_block(soap) == NULL) - 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; - soap->mode &= ~SOAP_ENC_DIME; - } - else if (!(soap->mode & SOAP_ENC_MIME)) - soap->mode &= ~SOAP_ENC_MTOM; - if (soap->mode & SOAP_ENC_MIME) - soap_select_mime_boundary(soap); + +/******************************************************************************/ + +#ifndef WITH_NOIO +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_cleanup(struct soap *soap) +{ + soap_done(soap); #ifdef WIN32 -#ifndef UNDER_CE -#ifndef WITH_FASTCGI - if (!soap_valid_socket(soap->socket)) /* Set win32 stdout or soap->sendfd to BINARY, e.g. to support DIME */ -#ifdef __BORLANDC__ - setmode(soap->sendfd, _O_BINARY); -#else - _setmode(soap->sendfd, _O_BINARY); + if (!tcp_done) + return; + tcp_done = 0; + WSACleanup(); #endif +} #endif + +/******************************************************************************/ + +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_done(struct soap *soap) +{ +#ifdef SOAP_DEBUG + int i; #endif + if (soap_check_state(soap)) + return; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Done with context%s\n", soap->state == SOAP_COPY ? " copy" : "")); + soap_free_temp(soap); +#ifdef SOAP_DEBUG + if (soap->clist) + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Warning: managed C++ data was not deallocated with soap_destroy() from the heap managed by context %p\n", (void*)soap)); + if (soap->alist) + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Warning: managed C data was not deallocated with soap_end() from the heap managed by context %p\n", (void*)soap)); #endif + soap->alist = NULL; + while (soap->clist) + { + struct soap_clist *p = soap->clist->next; + SOAP_FREE(soap, soap->clist); + soap->clist = p; + } + 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; + (void)soap_closesock(soap); +#ifdef WITH_COOKIES + soap_free_cookies(soap); +#endif + while (soap->plugins) + { + struct soap_plugin *p = soap->plugins->next; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Removing plugin '%s'\n", soap->plugins->id)); + if (soap->plugins->fcopy || soap->state == SOAP_INIT) + soap->plugins->fdelete(soap, soap->plugins); + SOAP_FREE(soap, soap->plugins); + soap->plugins = p; + } + soap->fplugin = fplugin; +#ifndef WITH_NOHTTP + soap->fpost = http_post; + soap->fget = http_get; + soap->fput = http_put; + soap->fpatch = http_patch; + soap->fdel = http_del; + soap->fopt = http_200; + soap->fhead = http_200; + soap->fform = NULL; + soap->fposthdr = http_post_header; + soap->fresponse = http_response; + soap->fparse = http_parse; + soap->fparsehdr = http_parse_header; +#endif + soap->fheader = NULL; +#ifndef WITH_NOIO +#ifndef WITH_IPV6 + soap->fresolve = tcp_gethost; +#else + soap->fresolve = NULL; +#endif + soap->faccept = tcp_accept; + soap->fopen = tcp_connect; + soap->fclose = tcp_disconnect; + soap->fclosesocket = tcp_closesocket; + soap->fshutdownsocket = tcp_shutdownsocket; + soap->fsend = fsend; + soap->frecv = frecv; + soap->fpoll = soap_poll; +#else + soap->fopen = NULL; + soap->fclose = NULL; + soap->fpoll = NULL; +#endif +#ifndef WITH_LEANER + soap->fsvalidate = NULL; + soap->fwvalidate = NULL; + soap->feltbegin = NULL; + soap->feltendin = NULL; + soap->feltbegout = NULL; + soap->feltendout = NULL; + soap->fprepareinitsend = NULL; + soap->fprepareinitrecv = NULL; + soap->fpreparesend = NULL; + soap->fpreparerecv = NULL; + soap->fpreparefinalsend = NULL; + soap->fpreparefinalrecv = NULL; + soap->ffiltersend = NULL; + soap->ffilterrecv = NULL; +#endif + soap->fseterror = NULL; + soap->fignore = NULL; + soap->fencoding = NULL; + soap->fserveloop = NULL; +#ifdef WITH_OPENSSL + if (soap->session) + { + SSL_SESSION_free(soap->session); + soap->session = NULL; + } +#endif + if (soap->state == SOAP_INIT) + { + if (soap_valid_socket(soap->master)) + { + (void)soap->fclosesocket(soap, soap->master); + soap->master = SOAP_INVALID_SOCKET; + } + } +#ifdef WITH_OPENSSL + if (soap->ssl) + { + SSL_free(soap->ssl); + soap->ssl = NULL; + } + if (soap->state == SOAP_INIT) + { + if (soap->ctx) + { + SSL_CTX_free(soap->ctx); + soap->ctx = NULL; + } + } + ERR_clear_error(); +# if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) + /* OpenSSL libraries handle thread init and deinit */ +# elif OPENSSL_VERSION_NUMBER >= 0x10000000L + ERR_remove_thread_state(NULL); +# else + ERR_remove_state(0); +# endif +#endif +#ifdef WITH_GNUTLS + if (soap->state == SOAP_INIT) + { + if (soap->xcred) + { + gnutls_certificate_free_credentials(soap->xcred); + soap->xcred = NULL; + } + if (soap->acred) + { + gnutls_anon_free_client_credentials(soap->acred); + soap->acred = NULL; + } + if (soap->cache) + { + gnutls_priority_deinit(soap->cache); + soap->cache = NULL; + } + if (soap->dh_params) + { + gnutls_dh_params_deinit(soap->dh_params); + soap->dh_params = NULL; + } +# if GNUTLS_VERSION_NUMBER < 0x030300 + if (soap->rsa_params) + { + gnutls_rsa_params_deinit(soap->rsa_params); + soap->rsa_params = NULL; + } +#endif + } + if (soap->session) + { + gnutls_deinit(soap->session); + soap->session = NULL; + } +#endif +#ifdef WITH_WOLFSSL + if (soap->ssl) + { + wolfSSL_free(soap->ssl); + soap->ssl = NULL; + } + if (soap->state == SOAP_INIT) + { + if (soap->ctx) + { + wolfSSL_CTX_free(soap->ctx); + soap->ctx = NULL; + } + } +#endif +#ifdef WITH_SYSTEMSSL + if (soap->ssl) + gsk_secure_socket_close(&soap->ssl); + if (soap->state == SOAP_INIT) + if (soap->ctx) + gsk_environment_close(&soap->ctx); +#endif +#ifdef WITH_C_LOCALE + SOAP_FREELOCALE(soap); +#endif +#ifdef WITH_ZLIB + if (soap->d_stream) + { + SOAP_FREE(soap, soap->d_stream); + soap->d_stream = NULL; + } + if (soap->z_buf) + { + SOAP_FREE(soap, soap->z_buf); + soap->z_buf = NULL; + } +#endif +#ifdef SOAP_DEBUG + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free logfiles\n")); + for (i = 0; i < SOAP_MAXLOGS; i++) + { + soap_close_logfile(soap, i); + if (soap->logfile[i]) + { + SOAP_FREE_UNMANAGED(soap->logfile[i]); + soap->logfile[i] = NULL; + } + } +#endif +#ifdef WITH_SELF_PIPE + close(soap->pipe_fd[0]); + close(soap->pipe_fd[1]); +#endif +#ifdef SOAP_MEM_DEBUG + soap_free_mht(soap); +#endif + soap->state = SOAP_NONE; +} + +/******************************************************************************\ + * + * HTTP + * +\******************************************************************************/ + +#ifndef WITH_NOHTTP +static int +http_parse(struct soap *soap) +{ + char header[SOAP_HDRLEN], *s; + int err = SOAP_OK; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Waiting for HTTP request/response...\n")); + soap->fform = NULL; + *soap->endpoint = '\0'; + soap->bearer = NULL; +#ifdef WITH_NTLM + if (!soap->ntlm_challenge) +#endif + { + soap->userid = NULL; + soap->passwd = NULL; + soap->authrealm = NULL; + } +#ifdef WITH_NTLM + soap->ntlm_challenge = NULL; +#endif + soap->proxy_from = NULL; + soap->cors_origin = NULL; + soap->cors_method = NULL; + soap->cors_header = NULL; + do + { + 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; + } + s = strchr(soap->msgbuf, ' '); + if (s) + { + soap->status = (unsigned short)soap_strtoul(s, &s, 10); + if (!soap_coblank((soap_wchar)*s)) + soap->status = 0; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "HTTP status: %s\n", soap->msgbuf)); + for (;;) + { + if (soap_getline(soap, header, SOAP_HDRLEN)) + { + if (soap->error == SOAP_EOF) + { + soap->error = SOAP_OK; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "EOF in HTTP header, try to continue anyway\n")); + break; + } + return soap->error; + } + if (!*header) + break; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "HTTP header: %s\n", header)); + s = strchr(header, ':'); + if (s) + { + char *t; + *s = '\0'; + while (*++s && *s <= 32) + continue; + t = s + strlen(s) - 1; + while (t > s && *t <= 32) + t--; + if (t > s && *s == '"' && *t == '"') + s++,t--; + t[1] = '\0'; + soap->error = soap->fparsehdr(soap, header, s); + if (soap->error) + { + if (soap->error < SOAP_STOP) + return soap->error; + err = soap->error; + soap->error = SOAP_OK; + } + } + } + } while (soap->status == 100); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Finished HTTP header parsing, status = %d\n", soap->status)); + s = strstr(soap->msgbuf, "HTTP/"); + if (s && s[5] == '1' && s[6] == '.' && s[7] == '0') + { + soap->keep_alive = 0; /* HTTP 1.0 does not support keep-alive */ + if (soap->status == 0 && (soap->omode & SOAP_IO) == SOAP_IO_CHUNK) /* soap->status == 0 for HTTP request */ + soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE; /* HTTP 1.0 does not support chunked transfers */ + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Keep alive connection = %d\n", soap->keep_alive)); + if (soap->status == 0) + { + size_t l = 0; + if (s) + { + if (!strncmp(soap->msgbuf, "POST ", l = 5)) + soap->status = SOAP_POST; + else if (!strncmp(soap->msgbuf, "GET ", l = 4)) + soap->status = SOAP_GET; + else if (!strncmp(soap->msgbuf, "PUT ", l = 4)) + soap->status = SOAP_PUT; + else if (!strncmp(soap->msgbuf, "PATCH ", l = 4)) + soap->status = SOAP_PATCH; + else if (!strncmp(soap->msgbuf, "DELETE ", l = 7)) + soap->status = SOAP_DEL; + else if (!strncmp(soap->msgbuf, "HEAD ", l = 5)) + soap->status = SOAP_HEAD; + else if (!strncmp(soap->msgbuf, "OPTIONS ", l = 8)) + soap->status = SOAP_OPTIONS; + } + if (s && soap->status) + { + size_t m, n, k; + int r; + while (soap->msgbuf[l] && soap_coblank((soap_wchar)soap->msgbuf[l])) + l++; + m = strlen(soap->endpoint); + n = m + (s - soap->msgbuf) - l - 1; + if (n >= sizeof(soap->endpoint)) + n = sizeof(soap->endpoint) - 1; + if (m > n) + m = n; + k = n - m + 1; + if (k >= sizeof(soap->path)) + k = sizeof(soap->path) - 1; + while (k > 0 && soap_coblank((soap_wchar)soap->msgbuf[l + k - 1])) + k--; + if (soap_strncpy(soap->path, sizeof(soap->path), soap->msgbuf + l, k)) + return soap->error = 414; + if (*soap->path && *soap->path != '/') + r = soap_strncpy(soap->endpoint, sizeof(soap->endpoint), soap->path, k); + else + r = soap_strncat(soap->endpoint, sizeof(soap->endpoint), soap->path, k); + if (r) + return soap->error = 414; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Target endpoint='%s' path='%s'\n", soap->endpoint, soap->path)); + if (err) + return soap->error = err; + } + else if (err) + { + return soap->error = err; + } + else if (s) + { + return soap->error = 405; + } + return SOAP_OK; + } + if ((soap->status >= 200 && soap->status <= 299) /* OK, Accepted, etc */ + || soap->status == 400 /* Bad Request */ + || soap->status == 500) /* Internal Server Error */ + return soap->error = SOAP_OK; + return soap->error = soap->status; +} +#endif + +/******************************************************************************/ + +#ifndef WITH_NOHTTP +static int +http_parse_header(struct soap *soap, const char *key, const char *val) +{ + if (!soap_tag_cmp(key, "Host")) + { +#if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) || defined(WITH_WOLFSSL) + if ((soap->imode & SOAP_ENC_SSL)) + soap_strcpy(soap->endpoint, sizeof(soap->endpoint), "https://"); + else +#endif + soap_strcpy(soap->endpoint, sizeof(soap->endpoint), "http://"); + if (soap_strncat(soap->endpoint, sizeof(soap->endpoint), val, sizeof(soap->endpoint) - 9)) + return soap->error = SOAP_HDR; + } +#ifndef WITH_LEANER + else if (!soap_tag_cmp(key, "Content-Type")) + { + const char *action; + soap->http_content = soap_strdup(soap, val); + if (soap_http_header_attribute(soap, val, "application/dime")) + soap->imode |= SOAP_ENC_DIME; + else if (soap_http_header_attribute(soap, val, "multipart/related") + || soap_http_header_attribute(soap, val, "multipart/form-data")) + { + const char *type; + soap->mime.boundary = soap_strdup(soap, soap_http_header_attribute(soap, val, "boundary")); + soap->mime.start = soap_strdup(soap, soap_http_header_attribute(soap, val, "start")); + soap->imode |= SOAP_ENC_MIME; + type = soap_http_header_attribute(soap, val, "type"); + if (type && !strcmp(type, "application/xop+xml")) + soap->imode |= SOAP_ENC_MTOM; + } + action = soap_http_header_attribute(soap, val, "action"); + if (action) + { + if (*action == '"') + { + soap->action = soap_strdup(soap, action + 1); + if (soap->action && *soap->action) + soap->action[strlen(soap->action) - 1] = '\0'; + } + else + soap->action = soap_strdup(soap, action); + } + } +#endif + else if (!soap_tag_cmp(key, "Content-Length")) + { + soap->length = soap_strtoull(val, NULL, 10); + if (soap->length == 0) + soap->body = 0; + } + else if (!soap_tag_cmp(key, "Content-Encoding")) + { + if (!soap_tag_cmp(val, "deflate")) +#ifdef WITH_ZLIB + soap->zlib_in = SOAP_ZLIB_DEFLATE; +#else + return SOAP_ZLIB_ERROR; +#endif + else if (!soap_tag_cmp(val, "gzip")) +#ifdef WITH_GZIP + soap->zlib_in = SOAP_ZLIB_GZIP; +#else + return SOAP_ZLIB_ERROR; +#endif + } +#ifdef WITH_ZLIB + else if (!soap_tag_cmp(key, "Accept-Encoding")) + { +#ifdef WITH_GZIP + if (strchr(val, '*') || soap_http_header_attribute(soap, val, "gzip")) + soap->zlib_out = SOAP_ZLIB_GZIP; + else +#endif + if (strchr(val, '*') || soap_http_header_attribute(soap, val, "deflate")) + soap->zlib_out = SOAP_ZLIB_DEFLATE; + else + soap->zlib_out = SOAP_ZLIB_NONE; + } +#endif + else if (!soap_tag_cmp(key, "Transfer-Encoding")) + { + soap->imode &= ~SOAP_IO; + if (!soap_tag_cmp(val, "chunked")) + soap->imode |= SOAP_IO_CHUNK; + } + else if (!soap_tag_cmp(key, "Connection")) + { + if (!soap_tag_cmp(val, "close")) + soap->keep_alive = 0; + } +#if !defined(WITH_LEAN) || defined(WITH_NTLM) + 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, "Bearer *")) + { + soap->bearer = soap_strdup(soap, val + 7); + } + else if (!soap_tag_cmp(val, "Basic *")) + { + int n; + char *s; + soap_base642s(soap, val + 6, soap->tmpbuf, sizeof(soap->tmpbuf) - 1, &n); + soap->tmpbuf[n] = '\0'; + s = strchr(soap->tmpbuf, ':'); + if (s) + { + *s = '\0'; + soap->userid = soap_strdup(soap, soap->tmpbuf); + soap->passwd = soap_strdup(soap, s + 1); + } + } + } + else if (!soap_tag_cmp(key, "WWW-Authenticate") || !soap_tag_cmp(key, "Proxy-Authenticate")) + { +#ifdef WITH_NTLM + if (!soap_tag_cmp(val, "NTLM*")) + soap->ntlm_challenge = soap_strdup(soap, val + 4); + else +#endif + soap->authrealm = soap_strdup(soap, soap_http_header_attribute(soap, val + 6, "realm")); + } + else if (!soap_tag_cmp(key, "Expect")) + { + if (!soap_tag_cmp(val, "100-continue")) + { + if ((soap->error = soap->fposthdr(soap, "HTTP/1.1 100 Continue", NULL)) != SOAP_OK + || (soap->error = soap->fposthdr(soap, NULL, NULL)) != SOAP_OK) + return soap->error; + } + } +#endif + else if (!soap_tag_cmp(key, "SOAPAction")) + { + if (*val == '"') + { + soap->action = soap_strdup(soap, val + 1); + if (*soap->action) + soap->action[strlen(soap->action) - 1] = '\0'; + } + else + soap->action = soap_strdup(soap, val); + } + else if (!soap_tag_cmp(key, "Location")) + { + soap_strcpy(soap->endpoint, sizeof(soap->endpoint), val); + } + else if (!soap_tag_cmp(key, "X-Forwarded-For")) + { + soap->proxy_from = soap_strdup(soap, val); + } + else if (!soap_tag_cmp(key, "Origin")) + { + soap->origin = soap_strdup(soap, val); + soap->cors_origin = soap->cors_allow; + } + else if (!soap_tag_cmp(key, "Access-Control-Request-Method")) + { + soap->cors_method = soap_strdup(soap, val); + } + else if (!soap_tag_cmp(key, "Access-Control-Request-Headers")) + { + soap->cors_header = soap_strdup(soap, val); + } +#ifdef WITH_COOKIES + else if (!soap_tag_cmp(key, "Cookie") + || !soap_tag_cmp(key, "Cookie2") + || !soap_tag_cmp(key, "Set-Cookie") + || !soap_tag_cmp(key, "Set-Cookie2")) + { + soap_getcookies(soap, val); + } +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ + +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_http_header_attribute(struct soap *soap, const char *line, const char *key) +{ + const char *s = line; + if (s) + { + while (*s) + { + short flag; + s = soap_decode_key(soap->tmpbuf, sizeof(soap->tmpbuf), s); + flag = soap_tag_cmp(soap->tmpbuf, key); + s = soap_decode_val(soap->tmpbuf, sizeof(soap->tmpbuf), s); + if (!flag) + return soap->tmpbuf; + } + } + return NULL; +} +#endif + +/******************************************************************************/ + +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_decode_key(char *buf, size_t len, const char *val) +{ + return soap_decode(buf, len, val, "=,;"); +} +#endif + +/******************************************************************************/ + +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_decode_val(char *buf, size_t len, const char *val) +{ + if (*val != '=') + { + *buf = '\0'; + return val; + } + return soap_decode(buf, len, val + 1, ",;"); +} +#endif + +/******************************************************************************/ + +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +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; + if (!buf || !val || !sep || len == 0) + return val; + for (s = val; *s; s++) + if (*s != ' ' && *s != '\t' && !strchr(sep, *s)) + break; + if (*s == '"') + { + s++; + while (*s && *s != '"' && i-- > 1) + *t++ = *s++; + } + else + { + while (*s && !strchr(sep, *s) && i-- > 1) + { + 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 static checkers that get confused */ + *t = '\0'; + while (*s && !strchr(sep, *s)) + s++; + return s; +} +#endif + +/******************************************************************************/ + +#ifndef WITH_NOHTTP +static const char* +http_error(struct soap *soap, int status) +{ + const char *msg = SOAP_STR_EOS; + (void)soap; + (void)status; +#ifndef WITH_LEAN + msg = soap_code_str(h_http_error_codes, status); + if (!msg) + msg = SOAP_STR_EOS; +#endif + return msg; +} +#endif + +/******************************************************************************/ + +#ifndef WITH_NOHTTP +static int +http_get(struct soap *soap) +{ + (void)soap; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "HTTP GET request\n")); + return SOAP_GET_METHOD; +} +#endif + +/******************************************************************************/ + +#ifndef WITH_NOHTTP +static int +http_put(struct soap *soap) +{ + (void)soap; + return SOAP_PUT_METHOD; +} +#endif + +/******************************************************************************/ + +#ifndef WITH_NOHTTP +static int +http_patch(struct soap *soap) +{ + (void)soap; + return SOAP_PATCH_METHOD; +} +#endif +/******************************************************************************/ + +#ifndef WITH_NOHTTP +static int +http_del(struct soap *soap) +{ + (void)soap; + return SOAP_DEL_METHOD; +} +#endif +/******************************************************************************/ + +#ifndef WITH_NOHTTP +static int +http_200(struct soap *soap) +{ + if (soap->origin && soap->cors_method) /* CORS Origin and Access-Control-Request-Method headers */ + { + soap->cors_origin = soap->cors_allow; /* modify this code or hook your own soap->fopt() callback with logic */ + soap->cors_methods = "GET, PUT, PATCH, POST, HEAD, OPTIONS"; + soap->cors_headers = soap->cors_header; + } + return soap_send_empty_response(soap, 200); +} +#endif + +/******************************************************************************/ + +#ifndef WITH_NOHTTP +static int +http_post(struct soap *soap, const char *endpoint, const char *host, int port, const char *path, const char *action, ULONG64 count) +{ + const char *s; + int err; + size_t l; + switch (soap->status) + { + case SOAP_GET: + s = "GET"; + break; + case SOAP_PUT: + s = "PUT"; + break; + case SOAP_PATCH: + s = "PATCH"; + break; + case SOAP_DEL: + s = "DELETE"; + break; + case SOAP_CONNECT: + s = "CONNECT"; + break; + case SOAP_HEAD: + s = "HEAD"; + break; + case SOAP_OPTIONS: + s = "OPTIONS"; + break; + default: + s = "POST"; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "HTTP %s to %s\n", s, endpoint ? endpoint : "(null)")); + if (!endpoint || (soap_tag_cmp(endpoint, "http:*") && soap_tag_cmp(endpoint, "https:*") && soap_tag_cmp(endpoint, "httpg:*"))) + return SOAP_OK; + /* set l to prevent overruns ('host' and 'soap->host' are substrings of 'endpoint') */ + l = strlen(endpoint) + strlen(soap->http_version) + 80; + if (l > sizeof(soap->tmpbuf)) + return soap->error = SOAP_EOM; + if (soap->status == SOAP_CONNECT) + (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), l), "%s %s:%d HTTP/%s", s, soap->host, soap->port, soap->http_version); + else if (soap->proxy_host && endpoint) + (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), l), "%s %s HTTP/%s", s, endpoint, soap->http_version); + else + (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), l), "%s /%s HTTP/%s", s, (*path == '/' ? path + 1 : path), soap->http_version); + err = soap->fposthdr(soap, soap->tmpbuf, NULL); + if (err) + return err; +#if defined(WITH_OPENSSL) || defined(WITH_WOLFSSL) + if ((soap->ssl && port != 443) || (!soap->ssl && port != 80)) +#else + if (port != 80) +#endif + { +#ifdef WITH_IPV6 + if (*host != '[' && strchr(host, ':')) + (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), l), "[%s]:%d", host, port); /* RFC 2732 */ + else +#endif + (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), l), "%s:%d", host, port); + } + else + { +#ifdef WITH_IPV6 + if (*host != '[' && strchr(host, ':')) + (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), l), "[%s]", host); /* RFC 2732 */ + else +#endif + soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), host); + } + err = soap->fposthdr(soap, "Host", soap->tmpbuf); + if (err) + return err; + err = soap->fposthdr(soap, "User-Agent", "gSOAP/2.8"); + if (err) + return err; + if (soap->origin) + { + err = soap->fposthdr(soap, "Origin", soap->origin); + if (err) + return err; + if (soap->status == SOAP_OPTIONS) + { + err = soap->fposthdr(soap, "Access-Control-Request-Method", soap->cors_method ? soap->cors_method : "POST"); + if (err) + return err; + if (soap->cors_header) + { + err = soap->fposthdr(soap, "Access-Control-Request-Headers", soap->cors_header); + if (err) + return err; + } + } + } + err = soap_puthttphdr(soap, SOAP_OK, count); + if (err) + return err; +#ifndef WITH_LEANER + if ((soap->imode & SOAP_ENC_MTOM)) + { + err = soap->fposthdr(soap, "Accept", "multipart/related,application/xop+xml,*/*;q=0.8"); + if (err) + return err; + } +#endif +#ifdef WITH_ZLIB +#ifdef WITH_GZIP + err = soap->fposthdr(soap, "Accept-Encoding", "gzip,deflate"); +#else + err = soap->fposthdr(soap, "Accept-Encoding", "deflate"); +#endif + if (err) + return err; +#endif +#if !defined(WITH_LEAN) || defined(WITH_NTLM) + if (soap->bearer) + { + l = strlen(soap->bearer); + (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), l + 7), "Bearer %s", soap->bearer); + err = soap->fposthdr(soap, "Authorization", soap->tmpbuf); + if (err) + return err; + } +#ifdef WITH_NTLM + if (soap->ntlm_challenge) + { + l = strlen(soap->ntlm_challenge); + if (l) + { + (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), l + 5), "NTLM %s", soap->ntlm_challenge); + if (soap->proxy_host) + { + err = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf); + if (err) + return err; + } + else + { + err = soap->fposthdr(soap, "Authorization", soap->tmpbuf); + if (err) + return err; + } + } + } + else + { +#endif + if (soap->userid && soap->passwd) + { + soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), "Basic "); + (SOAP_SNPRINTF(soap->tmpbuf + 262, sizeof(soap->tmpbuf) - 262, strlen(soap->userid) + strlen(soap->passwd) + 1), "%s:%s", soap->userid, soap->passwd); + soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262)); + err = soap->fposthdr(soap, "Authorization", soap->tmpbuf); + if (err) + return err; + } + if (soap->proxy_userid && soap->proxy_passwd) + { + soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), "Basic "); + (SOAP_SNPRINTF(soap->tmpbuf + 262, sizeof(soap->tmpbuf) - 262, strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) + 1), "%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)); + err = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf); + if (err) + return err; + } +#ifdef WITH_NTLM + } +#endif +#endif +#ifdef WITH_COOKIES +#if defined(WITH_OPENSSL) || defined(WITH_WOLFSSL) + if (soap_putcookies(soap, host, path, soap->ssl != NULL)) + return soap->error; +#else + if (soap_putcookies(soap, host, path, 0)) + return soap->error; +#endif +#endif + if (action && soap->status != SOAP_GET && soap->status != SOAP_DEL) + { + (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), strlen(action) + 2), "\"%s\"", action); + err = soap->fposthdr(soap, "SOAPAction", soap->tmpbuf); + if (err) + return err; + } + return soap->fposthdr(soap, NULL, NULL); +} +#endif + +/******************************************************************************/ + +#ifndef WITH_NOHTTP +static int +http_send_header(struct soap *soap, const char *s) +{ + const char *t; + do + { + t = strchr(s, '\n'); /* disallow \n in HTTP headers */ + if (!t) + t = s + strlen(s); + if (soap_send_raw(soap, s, t - s)) + return soap->error; + s = t + 1; + } while (*t); + return SOAP_OK; +} +#endif + +/******************************************************************************/ + +#ifndef WITH_NOHTTP +static int +http_post_header(struct soap *soap, const char *key, const char *val) +{ + if (key) + { + if (http_send_header(soap, key)) + return soap->error; + if (val && (soap_send_raw(soap, ": ", 2) || http_send_header(soap, val))) + return soap->error; + } + return soap_send_raw(soap, "\r\n", 2); +} +#endif + +/******************************************************************************/ + +#ifndef WITH_NOHTTP +static int +http_response(struct soap *soap, int status, ULONG64 count) +{ + int err; + char http[32]; + int code = status; + const char *line; +#ifdef WMW_RPM_IO + if (soap->rpmreqid) + httpOutputEnable(soap->rpmreqid); + if (soap->rpmreqid + || soap_valid_socket(soap->master) + || soap_valid_socket(soap->socket) + || soap->recvfd != 0 + || soap->sendfd != 1 + || soap->os) /* RPM behaves as if standalone */ +#else + if (soap_valid_socket(soap->master) + || soap_valid_socket(soap->socket) +#ifndef UNDER_CE + || soap->recvfd != 0 + || soap->sendfd != 1 +#else + || soap->recvfd != stdin + || soap->sendfd != stdout +#endif + || soap->os) /* standalone server application (over sockets), not CGI (over stdin/out) */ +#endif + (SOAP_SNPRINTF(http, sizeof(http), strlen(soap->http_version) + 5), "HTTP/%s", soap->http_version); + else + soap_strcpy(http, sizeof(http), "Status:"); + if (status >= SOAP_FILE && status < SOAP_FILE + 600) + { + code = status - SOAP_FILE; + if (code == 0) + code = 200; + } + else if (!status || status == SOAP_HTML) + { + 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) + code = 405; + else if (soap->version == 2 && (!s || !strcmp(s, "SOAP-ENV:Sender"))) + code = 400; + else + code = 500; + } + line = http_error(soap, code); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "HTTP Status = %d %s\n", code, line)); + (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), sizeof(http) + 22 + strlen(line)), "%s %d %s", http, code, line); + err = soap->fposthdr(soap, soap->tmpbuf, NULL); + if (err) + return err; +#ifndef WITH_LEAN + if (status == 401) + { + (SOAP_SNPRINTF_SAFE(soap->tmpbuf, sizeof(soap->tmpbuf)), "Basic realm=\"%s\"", (soap->authrealm && strlen(soap->authrealm) + 14 < sizeof(soap->tmpbuf)) ? soap->authrealm : "gSOAP Web Service"); + err = soap->fposthdr(soap, "WWW-Authenticate", soap->tmpbuf); + if (err) + return err; + } + else if ((status >= 301 && status <= 303) || status == 307) + { + err = soap->fposthdr(soap, "Location", soap->endpoint); + if (err) + return err; + } +#endif + err = soap->fposthdr(soap, "Server", "gSOAP/2.8"); + if (err) + return err; + if (soap->cors_origin) + { + err = soap->fposthdr(soap, "Access-Control-Allow-Origin", soap->cors_origin); + if (err) + return err; + err = soap->fposthdr(soap, "Access-Control-Allow-Credentials", "true"); + if (err) + return err; + if (soap->cors_methods) + { + err = soap->fposthdr(soap, "Access-Control-Allow-Methods", soap->cors_methods); + if (err) + return err; + if (soap->cors_headers) + { + err = soap->fposthdr(soap, "Access-Control-Allow-Headers", soap->cors_headers); + if (err) + return err; + } + } + } + if (soap->x_frame_options) + { + err = soap->fposthdr(soap, "X-Frame-Options", soap->x_frame_options); + if (err) + return err; + } + soap->cors_origin = NULL; + soap->cors_methods = NULL; + soap->cors_headers = NULL; + err = soap_puthttphdr(soap, status, count); + if (err) + return err; +#ifdef WITH_COOKIES + if (soap_putsetcookies(soap)) + return soap->error; + soap_free_cookies(soap); +#endif + return soap->fposthdr(soap, NULL, NULL); +} +#endif + +/******************************************************************************/ + +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_response(struct soap *soap, int status) +{ + ULONG64 count; + if (!(soap->omode & (SOAP_ENC_PLAIN | SOAP_IO_STORE /* this tests for chunking too */)) + && (status == SOAP_HTML || (status >= SOAP_FILE && status < SOAP_FILE + 600))) + soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE; + soap->status = status; + count = soap_count_attachments(soap); + if (soap_init_send(soap)) + return soap->error; +#ifndef WITH_NOHTTP + if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_PLAIN)) + { + int k = soap->mode; + soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB); + if ((k & SOAP_IO) != SOAP_IO_FLUSH) + soap->mode |= SOAP_IO_BUFFER; + soap->error = soap->fresponse(soap, status, count); + if (soap->error) + return soap->error; +#ifndef WITH_LEANER + if ((k & SOAP_IO) == SOAP_IO_CHUNK) + { + if (soap_flush(soap)) + return soap->error; + } +#endif + soap->mode = k; + } +#endif +#ifndef WITH_LEANER + if (soap_begin_attachments(soap)) + return soap->error; +#endif + return SOAP_OK; +} + +/******************************************************************************/ + +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_extend_url(struct soap *soap, const char *s, const char *t) +{ + if (s) + soap_strcpy(soap->msgbuf, sizeof(soap->msgbuf), s); + else + *soap->msgbuf = '\0'; + if (t && (*t == '/' || *t == '?')) + { + char *r = strchr(soap->msgbuf, '?'); + if (r) + { + if (*t == '?') + { + soap_strcat(soap->msgbuf, sizeof(soap->msgbuf), "&"); + soap_strcat(soap->msgbuf, sizeof(soap->msgbuf), t + 1); + } + else /* *t == '/' */ + { + size_t l = r - soap->msgbuf; + *r = '\0'; + soap_strcat(soap->msgbuf, sizeof(soap->msgbuf), t); + if (s) + soap_strcat(soap->msgbuf, sizeof(soap->msgbuf), s + l); + } + } + else + { + soap_strcat(soap->msgbuf, sizeof(soap->msgbuf), t); + } + } + return soap->msgbuf; +} + +/******************************************************************************/ + +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_extend_url_query(struct soap *soap, const char *s, const char *t) +{ + (void)soap_extend_url(soap, s, t); /* fills and returns soap->msgbuf */ + if (strchr(soap->msgbuf, '?')) + soap_strcat(soap->msgbuf, sizeof(soap->msgbuf), "&"); + else + soap_strcat(soap->msgbuf, sizeof(soap->msgbuf), "?"); + return soap->msgbuf; +} + +/******************************************************************************/ + +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_url_query(struct soap *soap, const char *s, const char *t) +{ + size_t n = strlen(s); + if (n) + { + char *r = soap->msgbuf; + size_t k = n - (s[n-1] == '='); + while ((r = strchr(r, '{')) != NULL) + if (!strncmp(++r, s, k) && r[k] == '}') + break; + if (r) + { + size_t m = t ? strlen(t) : 0; + (void)soap_memmove(r + m - 1, soap->msgbuf + sizeof(soap->msgbuf) - (r + n + 1), r + k + 1, strlen(r + k + 1) + 1); + if (m) + (void)soap_memmove(r - 1, soap->msgbuf + sizeof(soap->msgbuf) - (r - 1), t, m); + } + else + { + soap_strcat(soap->msgbuf, sizeof(soap->msgbuf), s); + if (t) + { + int m = (int)strlen(soap->msgbuf); /* msgbuf length is max SOAP_TMPLEN or just 1024 bytes */ + (void)soap_encode_url(t, soap->msgbuf + m, (int)sizeof(soap->msgbuf) - m); + } + soap_strcat(soap->msgbuf, sizeof(soap->msgbuf), "&"); + } + } +} + +/******************************************************************************/ + +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_encode_url(const char *s, char *t, int len) +{ + int c; + int n = len; + if (s && n > 0) + { + while ((c = *s++) && n-- > 1) + { + if (c == '-' + || c == '.' + || (c >= '0' && c <= '9') + || (c >= 'A' && c <= 'Z') + || c == '_' + || (c >= 'a' && c <= 'z') + || c == '~') + { + *t++ = c; + } + else if (n > 2) + { + *t++ = '%'; + *t++ = (c >> 4) + (c > 159 ? '7' : '0'); + c &= 0xF; + *t++ = c + (c > 9 ? '7' : '0'); + n -= 2; + } + else + { + break; + } + } + *t = '\0'; + } + return len - n; +} + +/******************************************************************************/ + +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_encode_url_string(struct soap *soap, const char *s) +{ + if (s) + { + int n = 3 * (int)strlen(s) + 1; + char *t = (char*)soap_malloc(soap, n); + if (t) + { + (void)soap_encode_url(s, t, n); + return t; + } + } + return SOAP_STR_EOS; +} + +/******************************************************************************\ + * + * HTTP Cookies RFC 6265 + * +\******************************************************************************/ + +#ifdef WITH_COOKIES + +SOAP_FMAC1 +struct soap_cookie* +SOAP_FMAC2 +soap_cookie(struct soap *soap, const char *name, const char *domain, const char *path) +{ + return soap_cookie_env(soap, name, domain, path, 0); +} + +/******************************************************************************/ + +SOAP_FMAC1 +struct soap_cookie* +SOAP_FMAC2 +soap_cookie_env(struct soap *soap, const char *name, const char *domain, const char *path, short env) +{ + struct soap_cookie *p; + if (!domain && !env) + domain = soap->cookie_domain; + if (!path) + path = soap->cookie_path; + if (!path) + path = SOAP_STR_EOS; + else if (*path == '/') + path++; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Search cookie='%s' domain='%s' path='%s' env=%hd\n", name, domain ? domain : "(null)", path ? path : "(null)", env)); + 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)); + if ((!env || p->env) + && !strcmp(p->name, name) + && (!domain || (domain && p->domain && !strcmp(p->domain, domain))) + && (!path || (path && p->path && !strncmp(p->path, path, strlen(p->path))))) + break; + } + return p; +} + +/******************************************************************************/ + +SOAP_FMAC1 +struct soap_cookie* +SOAP_FMAC2 +soap_set_cookie(struct soap *soap, const char *name, const char *value, const char *domain, const char *path) +{ + struct soap_cookie **p, *q; + int n; + if (!domain) + domain = soap->cookie_domain; + if (!path) + path = soap->cookie_path; + if (!path) + path = SOAP_STR_EOS; + 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)")); + if (!q) + { + q = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie)); + if (q) + { + size_t l = strlen(name) + 1; + q->name = NULL; + if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE) + q->name = (char*)SOAP_MALLOC(soap, l); + if (q->name) + (void)soap_memcpy(q->name, l, name, l); + q->value = NULL; + q->domain = NULL; + q->path = NULL; + q->expire = 0; + q->maxage = -1; + q->version = 1; + q->secure = 0; + q->modified = 0; + for (p = &soap->cookies, n = soap->cookie_max; *p && n; p = &(*p)->next, n--) + if ((*p)->name && !strcmp((*p)->name, name) && (*p)->path && path && strcmp((*p)->path, path) < 0) + break; + if (n) + { + q->next = *p; + *p = q; + } + else + { + if (q->name) + SOAP_FREE(soap, q->name); + SOAP_FREE(soap, q); + q = NULL; + } + } + } + else + { + q->modified = 1; + } + if (q) + { + if (q->value) + { + if (!value || strcmp(value, q->value)) + { + SOAP_FREE(soap, q->value); + q->value = NULL; + } + } + if (value && *value && !q->value) + { + size_t l = strlen(value) + 1; + q->value = NULL; + if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE) + q->value = (char*)SOAP_MALLOC(soap, l); + if (q->value) + soap_strcpy(q->value, l, value); + } + if (q->domain) + { + if (!domain || strcmp(domain, q->domain)) + { + SOAP_FREE(soap, q->domain); + q->domain = NULL; + } + } + if (domain && !q->domain) + { + size_t l = strlen(domain) + 1; + q->domain = NULL; + if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE) + q->domain = (char*)SOAP_MALLOC(soap, l); + if (q->domain) + soap_strcpy(q->domain, l, domain); + } + if (q->path) + { + if (!path || strncmp(path, q->path, strlen(q->path))) + { + SOAP_FREE(soap, q->path); + q->path = NULL; + } + } + if (path && !q->path) + { + size_t l = strlen(path) + 1; + q->path = NULL; + if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE) + q->path = (char*)SOAP_MALLOC(soap, l); + if (q->path) + soap_strcpy(q->path, l, path); + } + q->session = 1; + q->env = 0; + } + return q; +} + +/******************************************************************************/ + +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_clr_cookie(struct soap *soap, const char *name, const char *domain, const char *path) +{ + struct soap_cookie **p, *q; + 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)")); + return; + } + if (!path) + path = soap->cookie_path; + if (!path) + path = SOAP_STR_EOS; + else if (*path == '/') + path++; + for (p = &soap->cookies, q = *p; q; q = *p) + { + if (q->name && !strcmp(q->name, name) && (!q->domain || !strcmp(q->domain, domain)) && (!q->path || !strncmp(q->path, path, strlen(q->path)))) + { + SOAP_FREE(soap, q->name); + if (q->value) + SOAP_FREE(soap, q->value); + if (q->domain) + SOAP_FREE(soap, q->domain); + if (q->path) + SOAP_FREE(soap, q->path); + *p = q->next; + SOAP_FREE(soap, q); + } + else + { + p = &q->next; + } + } +} + +/******************************************************************************/ + +SOAP_FMAC1 +const char * +SOAP_FMAC2 +soap_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path) +{ + struct soap_cookie *p; + p = soap_cookie(soap, name, domain, path); + if (p) + return p->value; + return NULL; +} + +/******************************************************************************/ + +SOAP_FMAC1 +const char * +SOAP_FMAC2 +soap_env_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path) +{ + struct soap_cookie *p; + p = soap_cookie(soap, name, domain, path); + if (p && p->env) + return p->value; + return NULL; +} + +/******************************************************************************/ + +SOAP_FMAC1 +time_t +SOAP_FMAC2 +soap_cookie_expire(struct soap *soap, const char *name, const char *domain, const char *path) +{ + struct soap_cookie *p; + p = soap_cookie(soap, name, domain, path); + if (p) + return (time_t)p->expire; + return -1; +} + +/******************************************************************************/ + +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_cookie_expire(struct soap *soap, const char *name, long maxage, const char *domain, const char *path) +{ + struct soap_cookie *p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set cookie expiration max-age=%ld: cookie='%s' domain='%s' path='%s'\n", maxage, name, domain ? domain : "(null)", path ? path : "(null)")); + p = soap_cookie(soap, name, domain, path); + if (p) + { + p->maxage = maxage; + p->modified = 1; + return SOAP_OK; + } + return SOAP_ERR; +} + +/******************************************************************************/ + +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_cookie_secure(struct soap *soap, const char *name, const char *domain, const char *path) +{ + struct soap_cookie *p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set cookie secure: cookie='%s' domain='%s' path='%s'\n", name, domain ? domain : "(null)", path ? path : "(null)")); + p = soap_cookie(soap, name, domain, path); + if (p) + { + p->secure = 1; + p->modified = 1; + return SOAP_OK; + } + return SOAP_ERR; +} +/******************************************************************************/ + +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path) +{ + struct soap_cookie *p; + p = soap_cookie(soap, name, domain, path); + if (p) + { + p->session = 1; + p->modified = 1; + return SOAP_OK; + } + return SOAP_ERR; +} + +/******************************************************************************/ + +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_clr_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path) +{ + struct soap_cookie *p; + p = soap_cookie(soap, name, domain, path); + if (p) + { + p->session = 0; + p->modified = 1; + return SOAP_OK; + } + return SOAP_ERR; +} + +/******************************************************************************/ + +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putsetcookies(struct soap *soap) +{ + char tmp[4096]; + struct soap_cookie *p; + for (p = soap->cookies; p; p = p->next) + { + if ((p->modified +#if defined(WITH_OPENSSL) || defined(WITH_WOLFSSL) + || (!p->env && !soap->ssl == !p->secure) +#endif + ) && p->name && p->value && *p->name && *p->value) + { + char *s = tmp; + const char *t; + s += soap_encode_url(p->name, s, 3967); + *s++ = '='; + s += soap_encode_url(p->value, s, 3968 - (int)(s-tmp)); + t = p->domain ? p->domain : soap->cookie_domain; + if (t && (int)strlen(t) < 3968 - (int)(s-tmp)) + { + soap_strcpy(s, 4096 - (s-tmp), ";Domain="); + s += 8; + soap_strcpy(s, 4096 - (s-tmp), t); + s += strlen(s); + } + t = p->path ? p->path : soap->cookie_path; + if (t && (int)strlen(t) < 3976 - (int)(s-tmp)) + { + soap_strcpy(s, 4096 - (s-tmp), ";Path=/"); + s += 7; + if (*t == '/') + t++; + if (strchr(t, '%')) /* already URL encoded? */ + { + soap_strcpy(s, 4096 - (s-tmp), t); + s += strlen(s); + } + else + { + s += soap_encode_url(t, s, 4096 - (int)(s-tmp)); + } + } + if (p->version > 0 && s-tmp < 3983) + { + (SOAP_SNPRINTF(s, 4096 - (s-tmp), 29), ";Version=%u", p->version); + s += strlen(s); + } + if (p->maxage >= 0 && s-tmp < 4012) + { + (SOAP_SNPRINTF(s, 4096 - (s-tmp), 29), ";Max-Age=%ld", p->maxage); + s += strlen(s); + } +#if !defined(WITH_LEAN) +#if defined(HAVE_GMTIME_R) || defined(HAVE_GMTIME) + if (p->maxage >= 0 && s-tmp < 4041) + { + time_t n = time(NULL) + p->maxage; + struct tm T, *pT = &T; + size_t l = 0; + /* format is Wed, 09 Jun 2021 10:18:14 GMT */ +#if defined(HAVE_GMTIME_R) + if (gmtime_r(&n, pT) != SOAP_FUNC_R_ERR) + l = strftime(s, 4096 - (s-tmp), ";Expires=%a, %d %b %Y %H:%M:%S GMT", pT); +#else + pT = gmtime(&n); + if (pT) + l = strftime(s, 4096 - (s-tmp), ";Expires=%a, %d %b %Y %H:%M:%S GMT", pT); +#endif + s += l; + } +#endif +#endif + if (s-tmp < 4079 + && (p->secure +#if defined(WITH_OPENSSL) || defined(WITH_WOLFSSL) + || soap->ssl +#endif + )) + { + soap_strcpy(s, 4096 - (s-tmp), ";Secure"); + s += strlen(s); + } + if (s-tmp < 4086) + soap_strcpy(s, 4096 - (s-tmp), ";HttpOnly"); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set-Cookie: %s\n", tmp)); + soap->error = soap->fposthdr(soap, "Set-Cookie", tmp); + if (soap->error) + return soap->error; + } + } + return SOAP_OK; +} + +/******************************************************************************/ + +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putcookies(struct soap *soap, const char *domain, const char *path, int secure) +{ + struct soap_cookie **p, *q; + char tmp[4096]; + unsigned int version = 0; + time_t now = time(NULL); + char *s = tmp; + if (!domain || !path) + return SOAP_OK; + p = &soap->cookies; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending cookies for domain='%s' path='%s'\n", domain, path)); + if (*path == '/') + path++; + while ((q = *p)) + { + if (q->expire && now >= (time_t)q->expire) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie %s expired\n", q->name)); + SOAP_FREE(soap, q->name); + if (q->value) + SOAP_FREE(soap, q->value); + if (q->domain) + SOAP_FREE(soap, q->domain); + if (q->path) + SOAP_FREE(soap, q->path); + *p = q->next; + SOAP_FREE(soap, q); + } + else + { + int flag; + char *t = q->domain; + size_t n = 0; + if (!t) + { + flag = 1; + } + else + { + const char *r = strchr(t, ':'); + if (r) + n = r - t; + else + n = strlen(t); + flag = !strncmp(t, domain, n); + } + /* domain-level cookies, cannot compile when WITH_NOIO set */ +#ifndef WITH_NOIO + if (!flag) + { + struct hostent hostent; + if (!tcp_gethostbyname(soap, (char*)domain, &hostent, NULL)) + { + const char *r = hostent.h_name; + if (*t == '.') + { + size_t k = strlen(hostent.h_name); + if (k >= n) + r = hostent.h_name + k - n; + } + flag = !strncmp(t, r, n); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Domain cookie %s host %s (match=%d)\n", t, r, flag)); + } + } +#endif + if (flag + && (!q->path || !strncmp(q->path, path, strlen(q->path))) +#ifndef WITH_INSECURE_COOKIES + && (!q->secure || secure) +#endif + ) + { + 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->path && *q->path) + n += strlen(q->path) + 9; + if (q->domain) + n += strlen(q->domain) + 11; + if (s + n >= tmp + sizeof(tmp)) + { + if (s == tmp) + return SOAP_OK; /* header too big, cannot split */ + /* split up HTTP header */ + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie: %s\n", tmp)); + soap->error = soap->fposthdr(soap, "Cookie", tmp); + if (soap->error) + return soap->error; + s = tmp; + } + else if (s != tmp) + { + *s++ = ';'; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending cookie %s=%s path=\"/%s\" domain=\"%s\"\n", q->name ? q->name : "(null)", q->value ? q->value : "(null)", q->path ? q->path : "(null)", q->domain ? q->domain : "(null)")); + if (q->version != version && (s-tmp) + (size_t)36 < sizeof(tmp)) + { + (SOAP_SNPRINTF_SAFE(s, sizeof(tmp) - (s-tmp)), "$Version=%u;", q->version); + version = q->version; + s += strlen(s); + } + if (q->name && (s-tmp) + strlen(q->name) + (size_t)15 < sizeof(tmp)) + { + s += soap_encode_url(q->name, s, (int)(tmp+sizeof(tmp)-s)-15); + } + if (q->value && *q->value && (s-tmp) + strlen(q->value) + (size_t)16 < sizeof(tmp)) + { + *s++ = '='; + s += soap_encode_url(q->value, s, (int)(tmp+sizeof(tmp)-s)-16); + } + if (q->path && (s-tmp) + strlen(q->path) + (size_t)36 < sizeof(tmp)) + { + (SOAP_SNPRINTF_SAFE(s, sizeof(tmp) - (s-tmp)), ";$Path=\"/%s\"", (*q->path == '/' ? q->path + 1 : q->path)); + s += strlen(s); + } + if (q->domain && (s-tmp) + strlen(q->domain) + (size_t)36 < sizeof(tmp)) + { + (SOAP_SNPRINTF_SAFE(s, sizeof(tmp) - (s-tmp)), ";$Domain=\"%s\"", q->domain); + s += strlen(s); + } + } + p = &q->next; + } + } + if (s != tmp) + { + soap->error = soap->fposthdr(soap, "Cookie", tmp); + if (soap->error) + return soap->error; + } + return SOAP_OK; +} + +/******************************************************************************/ + +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_getcookies(struct soap *soap, const char *val) +{ + struct soap_cookie *p = NULL, *q = NULL; + const char *s = val; + char tmp[4096]; /* cookie size is up to 4096 bytes [RFC2109] */ + char *domain = NULL; + char *path = NULL; + unsigned int version = 0; + time_t now = time(NULL); + if (!s) + return; + while (*s) + { + s = soap_decode_key(tmp, sizeof(tmp), s); + if (!soap_tag_cmp(tmp, "$Version")) + { + s = soap_decode_val(tmp, sizeof(tmp), s); + if (s) + { + if (p) + p->version = (int)soap_strtol(tmp, NULL, 10); + else + version = (int)soap_strtol(tmp, NULL, 10); + } + } + else if (!soap_tag_cmp(tmp, "$Path")) + { + char *t = NULL; + s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { + size_t l = strlen(tmp) + 1; + if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE) + t = (char*)SOAP_MALLOC(soap, l); + if (t) + (void)soap_memcpy((void*)t, l, (const void*)tmp, l); + } + if (p) + { + if (p->path) + SOAP_FREE(soap, p->path); + p->path = t; + } + else + { + if (path) + SOAP_FREE(soap, path); + path = t; + } + } + else if (!soap_tag_cmp(tmp, "$Domain")) + { + char *t = NULL; + s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { + size_t l = strlen(tmp) + 1; + if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE) + t = (char*)SOAP_MALLOC(soap, l); + if (t) + (void)soap_memcpy((void*)t, l, (const void*)tmp, l); + } + if (p) + { + if (p->domain) + SOAP_FREE(soap, p->domain); + p->domain = t; + } + else + { + if (domain) + SOAP_FREE(soap, domain); + domain = t; + } + } + else if (p && !soap_tag_cmp(tmp, "Path")) + { + if (p->path) + SOAP_FREE(soap, p->path); + p->path = NULL; + s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { + size_t l = strlen(tmp) + 1; + if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE) + p->path = (char*)SOAP_MALLOC(soap, l); + if (p->path) + (void)soap_memcpy((void*)p->path, l, (const void*)tmp, l); + } + } + else if (p && !soap_tag_cmp(tmp, "Domain")) + { + if (p->domain) + SOAP_FREE(soap, p->domain); + p->domain = NULL; + s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { + size_t l = strlen(tmp) + 1; + if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE) + p->domain = (char*)SOAP_MALLOC(soap, l); + if (p->domain) + (void)soap_memcpy((void*)p->domain, l, (const void*)tmp, l); + } + } + else if (p && !soap_tag_cmp(tmp, "Version")) + { + s = soap_decode_val(tmp, sizeof(tmp), s); + p->version = (unsigned int)soap_strtoul(tmp, NULL, 10); + } + else if (p && !soap_tag_cmp(tmp, "Max-Age")) + { + s = soap_decode_val(tmp, sizeof(tmp), s); + p->expire = (ULONG64)(now + soap_strtol(tmp, NULL, 10)); + } + else if (p && !soap_tag_cmp(tmp, "Expires")) + { + if (*s == '=') + { + s = soap_decode(tmp, sizeof(tmp), s + 1, ";"); + if (!p->expire && strlen(tmp) >= 23) + { + char a[3]; + struct tm T; + static const char mns[] = "anebarprayunulugepctovec"; + const char *t = strchr(tmp, ' '); + if (t) + { + a[2] = '\0'; + memset((void*)&T, 0, sizeof(T)); + if (t[1] >= 'A') + { + /* format is Sun Nov 6 08:49:37 94 */ + a[0] = t[2]; + a[1] = t[3]; + T.tm_mon = (int)(strstr(mns, a) - mns) / 2; + a[0] = t[5]; + a[1] = t[6]; + T.tm_mday = (int)soap_strtol(a, NULL, 10); + if (t[17] && t[18] && t[19] != ' ') + t += 2; /* format is Sun Nov 6 08:49:37 2017 - ANSI-C */ + a[0] = t[17]; + a[1] = t[18]; + T.tm_year = 100 + (int)soap_strtol(a, NULL, 10); + t += 6; + } + else + { + /* format is Sunday, 06-Nov-17 08:49:37 GMT - RFC 850 */ + a[0] = t[1]; + a[1] = t[2]; + T.tm_mday = (int)soap_strtol(a, NULL, 10); + a[0] = t[5]; + a[1] = t[6]; + T.tm_mon = (int)(strstr(mns, a) - mns) / 2; + if (t[10] != ' ') + t += 2; /* format is Wed, 09 Jun 2021 10:18:14 GMT - RFC 822 */ + a[0] = t[8]; + a[1] = t[9]; + T.tm_year = 100 + (int)soap_strtol(a, NULL, 10); + t += 11; + } + a[0] = t[0]; + a[1] = t[1]; + T.tm_hour = (int)soap_strtol(a, NULL, 10); + a[0] = t[3]; + a[1] = t[4]; + T.tm_min = (int)soap_strtol(a, NULL, 10); + a[0] = t[6]; + a[1] = t[7]; + T.tm_sec = (int)soap_strtol(a, NULL, 10); + p->expire = (ULONG64)soap_timegm(&T); + } + } + } + } + else if (p && !soap_tag_cmp(tmp, "Secure")) + { + p->secure = 1; + s = soap_decode_val(tmp, sizeof(tmp), s); + } + else if (p && !soap_tag_cmp(tmp, "HttpOnly")) + { + s = soap_decode_val(tmp, sizeof(tmp), s); + } + else if (p && !soap_tag_cmp(tmp, "Comment")) + { + s = soap_decode_val(tmp, sizeof(tmp), s); + } + else if (*tmp) + { + if (p) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie='%s' value='%s' domain='%s' path='%s' expire=" SOAP_ULONG_FORMAT " secure=%d\n", p->name, p->value ? p->value : "(null)", p->domain ? p->domain : "(null)", p->path ? p->path : "(null)", p->expire, p->secure)); + q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path); + if (q) + { + q->version = p->version; + q->expire = p->expire; + q->secure = p->secure; + q->env = 1; + } + if (p->name) + SOAP_FREE(soap, p->name); + if (p->value) + SOAP_FREE(soap, p->value); + if (p->domain) + SOAP_FREE(soap, p->domain); + if (p->path) + SOAP_FREE(soap, p->path); + SOAP_FREE(soap, p); + } + p = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie)); + if (p) + { + size_t l = strlen(tmp) + 1; + p->name = NULL; + if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE) + p->name = (char*)SOAP_MALLOC(soap, l); + if (p->name) + (void)soap_memcpy(p->name, l, tmp, l); + s = soap_decode_val(tmp, sizeof(tmp), s); + p->value = NULL; + if (*tmp) + { + l = strlen(tmp) + 1; + if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE) + p->value = (char*)SOAP_MALLOC(soap, l); + if (p->value) + (void)soap_memcpy((void*)p->value, l, (const void*)tmp, l); + } + if (domain) + { + p->domain = domain; + domain = NULL; + } + else + { + p->domain = NULL; + } + if (path) + { + p->path = path; + path = NULL; + } + else if (*soap->path) + { + l = strlen(soap->path) + 1; + p->path = NULL; + if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE) + p->path = (char*)SOAP_MALLOC(soap, l); + if (p->path) + (void)soap_memcpy((void*)p->path, l, (const void*)soap->path, l); + } + else + { + p->path = (char*)SOAP_MALLOC(soap, 2); + if (p->path) + (void)soap_memcpy((void*)p->path, 2, (const void*)"/", 2); + } + p->expire = 0; + p->secure = 0; + p->version = version; + } + } + } + if (p) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie='%s' value='%s' domain='%s' path='%s' expire=" SOAP_ULONG_FORMAT " secure=%d\n", p->name, p->value ? p->value : "(null)", p->domain ? p->domain : "(null)", p->path ? p->path : "(null)", p->expire, p->secure)); + q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path); + if (q) + { + q->version = p->version; + q->expire = p->expire; + q->secure = p->secure; + q->env = 1; + } + if (p->name) + SOAP_FREE(soap, p->name); + if (p->value) + SOAP_FREE(soap, p->value); + if (p->domain) + SOAP_FREE(soap, p->domain); + if (p->path) + SOAP_FREE(soap, p->path); + SOAP_FREE(soap, p); + } + if (domain) + SOAP_FREE(soap, domain); + if (path) + SOAP_FREE(soap, path); +} + +/******************************************************************************/ + +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getenv_cookies(struct soap *soap) +{ + struct soap_cookie *p; + const char *s; + char key[4096], val[4096]; /* cookie size is up to 4096 bytes [RFC2109] */ + s = getenv("HTTP_COOKIE"); + if (!s) + return SOAP_ERR; + do + { + s = soap_decode_key(key, sizeof(key), s); + s = soap_decode_val(val, sizeof(val), s); + p = soap_set_cookie(soap, key, val, NULL, NULL); + if (p) + p->env = 1; + } while (*s); + return SOAP_OK; +} + +/******************************************************************************/ + +SOAP_FMAC1 +struct soap_cookie* +SOAP_FMAC2 +soap_copy_cookies(struct soap *copy, const struct soap *soap) +{ + struct soap_cookie *p, **q, *r; + (void)copy; + q = &r; + for (p = soap->cookies; p; p = p->next) + { + *q = (struct soap_cookie*)SOAP_MALLOC(copy, sizeof(struct soap_cookie)); + if (!*q) + return r; + **q = *p; + if (p->name) + { + size_t l = strlen(p->name) + 1; + (*q)->name = NULL; + if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE) + (*q)->name = (char*)SOAP_MALLOC(copy, l); + if ((*q)->name) + (void)soap_memcpy((*q)->name, l, p->name, l); + } + if (p->value) + { + size_t l = strlen(p->value) + 1; + (*q)->value = NULL; + if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE) + (*q)->value = (char*)SOAP_MALLOC(copy, l); + if ((*q)->value) + (void)soap_memcpy((*q)->value, l, p->value, l); + } + if (p->domain) + { + size_t l = strlen(p->domain) + 1; + (*q)->domain = NULL; + if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE) + (*q)->domain = (char*)SOAP_MALLOC(copy, l); + if ((*q)->domain) + (void)soap_memcpy((*q)->domain, l, p->domain, l); + } + if (p->path) + { + size_t l = strlen(p->path) + 1; + (*q)->path = NULL; + if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE) + (*q)->path = (char*)SOAP_MALLOC(copy, l); + if ((*q)->path) + (void)soap_memcpy((*q)->path, l, p->path, l); + } + q = &(*q)->next; + } + *q = NULL; + return r; +} + +/******************************************************************************/ + +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_free_cookies(struct soap *soap) +{ + struct soap_cookie *p; + for (p = soap->cookies; p; p = soap->cookies) + { + soap->cookies = p->next; + SOAP_FREE(soap, p->name); + if (p->value) + SOAP_FREE(soap, p->value); + if (p->domain) + SOAP_FREE(soap, p->domain); + if (p->path) + SOAP_FREE(soap, p->path); + SOAP_FREE(soap, p); + } +} + +/******************************************************************************/ + +#endif /* WITH_COOKIES */ + +/******************************************************************************/ + +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_hash(const char *s) +{ + size_t h = 0; + while (*s) + h = *s++ + (h << 6) + (h << 16) - h; /* Red Dragon book h = 65599*h + c */ + return h % SOAP_IDHASH; +} + +/******************************************************************************/ + +static void +soap_init_pht(struct soap *soap) +{ + int i; + soap->pblk = NULL; + soap->pidx = 0; + for (i = 0; i < (int)SOAP_PTRHASH; i++) + soap->pht[i] = NULL; +} + +/******************************************************************************/ + +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_versioning(soap_new)(soap_mode imode, soap_mode omode) +{ + struct soap *soap; +#ifdef __cplusplus + soap = SOAP_NEW_UNMANAGED(struct soap); +#else + soap = (struct soap*)SOAP_MALLOC_UNMANAGED(sizeof(struct soap)); +#endif + if (soap) + soap_versioning(soap_init)(soap, imode, omode); + return soap; +} + +/******************************************************************************/ + +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_free(struct soap *soap) +{ + soap_done(soap); +#ifdef __cplusplus + SOAP_DELETE_UNMANAGED(soap); +#else + SOAP_FREE_UNMANAGED(soap); +#endif +} + +/******************************************************************************/ + +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_del(struct soap *soap) +{ + free(soap); +} + +/******************************************************************************/ + +static void +soap_free_pht(struct soap *soap) +{ + struct soap_pblk *pb, *next; + int i; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free pointer hashtable\n")); + for (pb = soap->pblk; pb; pb = next) + { + next = pb->next; + SOAP_FREE(soap, pb); + } + soap->pblk = NULL; + soap->pidx = 0; + for (i = 0; i < (int)SOAP_PTRHASH; i++) + soap->pht[i] = NULL; +} + +/******************************************************************************/ + +#ifndef WITH_NOIDREF +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_embed(struct soap *soap, const void *p, const void *a, int n, int t) +{ + int id; + struct soap_plist *pp; + if (soap->version == 2) + soap->encoding = 1; + if (!p || (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH)) || (soap->mode & SOAP_XML_TREE)) + return 0; + if (a) + id = soap_array_pointer_lookup(soap, p, a, n, t, &pp); + else + id = soap_pointer_lookup(soap, p, t, &pp); + if (id) + { + if (soap_is_embedded(soap, pp) || soap_is_single(soap, pp)) + return 0; + soap_set_embedded(soap, pp); + } + return id; +} +#endif + +/******************************************************************************/ + +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_pointer_lookup(struct soap *soap, const void *p, int type, struct soap_plist **ppp) +{ + struct soap_plist *pp; + *ppp = NULL; + if (p) + { + for (pp = soap->pht[soap_hash_ptr(p)]; pp; pp = pp->next) + { + if (pp->ptr == p && pp->type == type) + { + *ppp = pp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d id=%d\n", p, type, pp->id)); + return pp->id; + } + } + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d: not found\n", p, type)); + return 0; +} + +/******************************************************************************/ + +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_pointer_enter(struct soap *soap, const void *p, const void *a, int n, int type, struct soap_plist **ppp) +{ + size_t h; + struct soap_plist *pp; + (void)n; + if (!soap->pblk || soap->pidx >= SOAP_PTRBLK) + { + struct soap_pblk *pb = (struct soap_pblk*)SOAP_MALLOC(soap, sizeof(struct soap_pblk)); + if (!pb) + { + soap->error = SOAP_EOM; + return 0; + } + pb->next = soap->pblk; + soap->pblk = pb; + soap->pidx = 0; + } + *ppp = pp = &soap->pblk->plist[soap->pidx++]; + if (a) + h = soap_hash_ptr(a); + else + h = soap_hash_ptr(p); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pointer enter location=%p array=%p size=%lu type=%d id=%d\n", p, a, (unsigned long)n, type, soap->idnum+1)); + pp->next = soap->pht[h]; + pp->type = type; + pp->mark1 = 0; + pp->mark2 = 0; + pp->ptr = p; + pp->dup = NULL; + pp->array = a; + pp->size = n; + soap->pht[h] = pp; + pp->id = ++soap->idnum; + return pp->id; +} + +/******************************************************************************/ + +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_array_pointer_lookup(struct soap *soap, const void *p, const void *a, int n, int type, struct soap_plist **ppp) +{ + struct soap_plist *pp; + *ppp = NULL; + if (!p || !a) + return 0; + for (pp = soap->pht[soap_hash_ptr(a)]; pp; pp = pp->next) + { + if (pp->type == type && pp->array == a && pp->size == n) + { + *ppp = pp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d id=%d\n", a, type, pp->id)); + return pp->id; + } + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d: not found\n", a, type)); + return 0; +} + +/******************************************************************************/ + +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_begin_count(struct soap *soap) +{ + soap_free_ns(soap); + soap->error = SOAP_OK; +#ifndef WITH_LEANER + if ((soap->mode & SOAP_ENC_DIME) || (soap->omode & SOAP_ENC_DIME)) + { + soap->mode = soap->omode | SOAP_IO_LENGTH | SOAP_ENC_DIME; + } + else +#endif + { + soap->mode = soap->omode; + if ((soap->mode & SOAP_IO_UDP)) + { + soap->mode &= SOAP_IO; + soap->mode |= SOAP_IO_BUFFER | SOAP_ENC_PLAIN; + } + if ((soap->mode & SOAP_IO) == SOAP_IO_STORE + || (((soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_ENC_PLAIN)) +#ifndef WITH_LEANER + && !soap->fpreparesend +#endif + )) + soap->mode &= ~SOAP_IO_LENGTH; + else + soap->mode |= SOAP_IO_LENGTH; + } +#ifdef WITH_ZLIB + if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH) + { + if (!(soap->mode & SOAP_ENC_DIME)) + soap->mode &= ~SOAP_IO_LENGTH; + if ((soap->mode & SOAP_ENC_PLAIN)) + soap->mode |= SOAP_IO_BUFFER; + else + soap->mode |= SOAP_IO_STORE; + } +#endif +#ifndef WITH_LEANER + if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME)) + soap->mode |= SOAP_ENC_MIME; + else if (!(soap->mode & SOAP_ENC_MIME)) + soap->mode &= ~SOAP_ENC_MTOM; + if ((soap->mode & SOAP_ENC_MIME)) + soap_select_mime_boundary(soap); + soap->dime.list = soap->dime.last; /* keep track of last DIME attachment */ +#endif + soap->count = 0; + soap->ns = 0; + soap->null = 0; + soap->position = 0; + soap->mustUnderstand = 0; + soap->encoding = 0; + soap->part = SOAP_BEGIN_SEND; + soap->event = 0; + soap->evlev = 0; + soap->idnum = 0; + soap->body = 1; + soap->level = 0; + soap_clr_attr(soap); + soap_set_local_namespaces(soap); +#ifndef WITH_LEANER + soap->dime.size = 0; /* accumulate total size of attachments */ + if (soap->fprepareinitsend && (soap->mode & SOAP_IO) != SOAP_IO_STORE && (soap->error = soap->fprepareinitsend(soap)) != SOAP_OK) + return soap->error; #endif - if (soap->mode & SOAP_IO) - { soap->bufidx = 0; - soap->buflen = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin count phase (socket=%d mode=0x%x count=" SOAP_ULONG_FORMAT ")\n", (int)soap->socket, (unsigned int)soap->mode, soap->count)); +#ifndef WITH_LEANER + if ((soap->mode & SOAP_IO_LENGTH)) + return soap_begin_attachments(soap); +#endif + return SOAP_OK; +} + +/******************************************************************************/ + +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_end_count(struct soap *soap) +{ + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of count phase\n")); +#ifndef WITH_LEANER + if ((soap->mode & SOAP_IO_LENGTH)) + { + if (soap_end_attachments(soap)) + return soap->error; + if (soap->fpreparefinalsend && (soap->error = soap->fpreparefinalsend(soap)) != SOAP_OK) + return soap->error; + } +#else + (void)soap; +#endif + return SOAP_OK; +} + +/******************************************************************************/ + +static int +soap_init_send(struct soap *soap) +{ + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing for output to socket=%d/fd=%d\n", (int)soap->socket, soap->sendfd)); + *soap->tag = '\0'; + soap_free_ns(soap); + soap->error = SOAP_OK; + soap->mode = soap->omode | (soap->mode & (SOAP_IO_LENGTH | SOAP_ENC_DIME)); +#ifndef WITH_LEAN + if ((soap->mode & SOAP_IO_UDP)) + { + soap->mode &= ~SOAP_IO; + soap->mode |= SOAP_IO_BUFFER | SOAP_ENC_PLAIN; + if ((soap->mode & SOAP_IO_LENGTH) && soap->count > sizeof(soap->buf)) + return soap->error = SOAP_UDP_ERROR; + } +#endif +#ifdef WITH_ZLIB + if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH) + { + if ((soap->mode & SOAP_ENC_PLAIN)) + soap->mode |= SOAP_IO_BUFFER; + else + soap->mode |= SOAP_IO_STORE; + } +#endif +#if !defined(__cplusplus) || defined(WITH_COMPAT) + if (soap->os) + { + *soap->os = NULL; + soap->mode = (soap->mode & ~SOAP_IO) | SOAP_IO_STORE; + } + else +#endif + if ((soap->mode & SOAP_IO) == SOAP_IO_FLUSH && soap_valid_socket(soap->socket)) + { + if ((soap->mode & SOAP_IO_LENGTH) || (soap->mode & SOAP_ENC_PLAIN)) + soap->mode |= SOAP_IO_BUFFER; + else + soap->mode |= SOAP_IO_STORE; + } + soap->mode &= ~SOAP_IO_LENGTH; + if ((soap->mode & SOAP_IO) == SOAP_IO_STORE && soap_alloc_block(soap) == NULL) + return soap->error; + if (!(soap->mode & SOAP_IO_KEEPALIVE)) + soap->keep_alive = 0; +#ifndef WITH_LEANER + if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME)) + { + soap->mode |= SOAP_ENC_MIME; + soap->mode &= ~SOAP_ENC_DIME; + } + else if (!(soap->mode & SOAP_ENC_MIME)) + { + soap->mode &= ~SOAP_ENC_MTOM; } + if ((soap->mode & SOAP_ENC_MIME)) + soap_select_mime_boundary(soap); +#ifdef WIN32 +#ifndef UNDER_CE +#ifndef WITH_FASTCGI + if (!soap_valid_socket(soap->socket) && !soap->os && soap->sendfd >= 0) /* Set win32 stdout or soap->sendfd to BINARY, e.g. to support DIME */ +#ifdef __BORLANDC__ + setmode(soap->sendfd, _O_BINARY); +#else + _setmode(soap->sendfd, _O_BINARY); +#endif +#endif +#endif +#endif +#endif + if ((soap->mode & SOAP_IO)) + soap->buflen = soap->bufidx = 0; soap->chunksize = 0; soap->ns = 0; soap->null = 0; soap->position = 0; soap->mustUnderstand = 0; soap->encoding = 0; + soap->event = 0; + soap->evlev = 0; soap->idnum = 0; + soap->body = 1; soap->level = 0; soap_clr_attr(soap); soap_set_local_namespaces(soap); #ifdef WITH_ZLIB soap->z_ratio_out = 1.0; if ((soap->mode & SOAP_ENC_ZLIB) && soap->zlib_state != SOAP_ZLIB_DEFLATE) - { if (!soap->z_buf) - soap->z_buf = (char*)SOAP_MALLOC(soap, SOAP_BUFLEN); + { + if (!soap->d_stream) + { + soap->d_stream = (z_stream*)SOAP_MALLOC(soap, sizeof(z_stream)); + if (!soap->d_stream) + return soap->error = SOAP_EOM; + soap->d_stream->zalloc = Z_NULL; + soap->d_stream->zfree = Z_NULL; + soap->d_stream->opaque = Z_NULL; + soap->d_stream->next_in = Z_NULL; + } + if (!soap->z_buf) + soap->z_buf = (char*)SOAP_MALLOC(soap, sizeof(soap->buf)); + if (!soap->z_buf) + return soap->error = SOAP_EOM; soap->d_stream->next_out = (Byte*)soap->z_buf; - soap->d_stream->avail_out = SOAP_BUFLEN; + soap->d_stream->avail_out = sizeof(soap->buf); #ifdef WITH_GZIP if (soap->zlib_out != SOAP_ZLIB_DEFLATE) - { memcpy(soap->z_buf, "\37\213\10\0\0\0\0\0\0\377", 10); + { + (void)soap_memcpy((void*)soap->z_buf, sizeof(soap->buf), (const void*)"\37\213\10\0\0\0\0\0\0\377", 10); soap->d_stream->next_out = (Byte*)soap->z_buf + 10; - soap->d_stream->avail_out = SOAP_BUFLEN - 10; + soap->d_stream->avail_out = sizeof(soap->buf) - 10; soap->z_crc = crc32(0L, NULL, 0); soap->zlib_out = SOAP_ZLIB_GZIP; if (soap->z_dict) @@ -5111,7 +10512,8 @@ soap_begin_send(struct soap *soap) if (deflateInit(soap->d_stream, soap->z_level) != Z_OK) return soap->error = SOAP_ZLIB_ERROR; if (soap->z_dict) - { if (deflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len) != Z_OK) + { + if (deflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len) != Z_OK) return soap->error = SOAP_ZLIB_ERROR; } DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflate initialized\n")); @@ -5122,107 +10524,160 @@ soap_begin_send(struct soap *soap) if (soap->ssl) ERR_clear_error(); #endif - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin send phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count)); - soap->part = SOAP_BEGIN; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin send phase (socket=%d mode=0x%x count=" SOAP_ULONG_FORMAT ")\n", (int)soap->socket, soap->mode, soap->count)); + soap->part = SOAP_BEGIN_SEND; #ifndef WITH_LEANER - if (soap->fprepareinit && (soap->mode & SOAP_IO) == SOAP_IO_STORE) - soap->fprepareinit(soap); + if (soap->fprepareinitsend && (soap->mode & SOAP_IO) == SOAP_IO_STORE && (soap->error = soap->fprepareinitsend(soap)) != SOAP_OK) + return soap->error; +#endif +#ifndef WITH_LEAN + soap->start = (ULONG64)time(NULL); #endif return SOAP_OK; } + +/******************************************************************************/ + +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_begin_send(struct soap *soap) +{ +#ifndef WITH_LEANER + if (soap_init_send(soap)) + return soap->error; + return soap_begin_attachments(soap); +#else + return soap_init_send(soap); #endif +} /******************************************************************************/ + #ifndef WITH_NOIDREF -#ifndef PALM_2 SOAP_FMAC1 void SOAP_FMAC2 soap_embedded(struct soap *soap, const void *p, int t) -{ struct soap_plist *pp; +{ + struct soap_plist *pp; if (soap_pointer_lookup(soap, p, t, &pp)) - { pp->mark1 = 1; + { + pp->mark1 = 1; pp->mark2 = 1; DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded %p type=%d mark set to 1\n", p, t)); } } #endif -#endif /******************************************************************************/ + #ifndef WITH_NOIDREF -#ifndef PALM_2 SOAP_FMAC1 int SOAP_FMAC2 soap_reference(struct soap *soap, const void *p, int t) -{ struct soap_plist *pp; - if (!p || (soap->mode & SOAP_XML_TREE)) +{ + struct soap_plist *pp; + 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) - { pp->mark1 = 2; + { + if (pp->mark1 == 0) + { + pp->mark1 = 2; 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; } #endif -#endif /******************************************************************************/ + #ifndef WITH_NOIDREF -#ifndef PALM_2 SOAP_FMAC1 int SOAP_FMAC2 -soap_array_reference(struct soap *soap, const void *p, const struct soap_array *a, int n, int t) -{ int i; +soap_array_reference(struct soap *soap, const void *p, const void *a, int n, int t) +{ struct soap_plist *pp; - if (!p || !a->__ptr) + if (!p || !a || (!soap->encodingStyle && !(soap->omode & SOAP_XML_GRAPH)) || (soap->omode & SOAP_XML_TREE)) return 1; - i = soap_array_pointer_lookup(soap, p, a, n, t, &pp); - if (i) - { if (pp->mark1 == 0) - { pp->mark1 = 2; + if (soap_array_pointer_lookup(soap, p, a, n, t, &pp)) + { + if (pp->mark1 == 0) + { + pp->mark1 = 2; pp->mark2 = 2; } } 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)); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array reference %p ptr=%p n=%lu t=%d (%d %d)\n", p, a, (unsigned long)n, t, (int)pp->mark1, (int)pp->mark2)); return pp->mark1; } #endif + +/******************************************************************************/ + +#ifndef WITH_NOIDREF +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_attachment_reference(struct soap *soap, const void *p, const void *a, int n, int t, const char *id, const char *type) +{ + struct soap_plist *pp; + if (!p || !a || (!soap->encodingStyle && !(soap->omode & SOAP_XML_GRAPH) && !id && !type) || (soap->omode & SOAP_XML_TREE)) + return 1; + if (soap_array_pointer_lookup(soap, p, a, n, t, &pp)) + { + if (pp->mark1 == 0) + { + pp->mark1 = 2; + pp->mark2 = 2; + } + } + else if (!soap_pointer_enter(soap, p, a, n, t, &pp)) + { + return 1; + } + if (id || type) + soap->mode |= SOAP_ENC_DIME; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attachment reference %p ptr=%p n=%lu t=%d (%d %d)\n", p, a, (unsigned long)n, t, (int)pp->mark1, (int)pp->mark2)); + return pp->mark1; +} #endif /******************************************************************************/ + #ifndef WITH_NOIDREF -#ifndef PALM_2 SOAP_FMAC1 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) +{ + struct soap_plist *pp = NULL; + if (id >= 0 || (!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 (id < 0) - { id = soap_pointer_lookup(soap, p, t, &pp); + if (id < -1) + return soap_embed(soap, p, NULL, 0, t); + if (id < 0) + { + id = soap_pointer_lookup(soap, p, t, &pp); + if (soap->version == 1 && soap->part != SOAP_IN_HEADER) + { if (id) - { if (soap->mode & SOAP_IO_LENGTH) + { + if ((soap->mode & SOAP_IO_LENGTH)) pp->mark1 = 2; else pp->mark2 = 2; @@ -5230,145 +10685,161 @@ soap_embedded_id(struct soap *soap, int id, const void *p, int t) } return -1; } - return id; - } - if (id < 0) - id = soap_pointer_lookup(soap, p, t, &pp); - else if (id && !soap_pointer_lookup(soap, p, t, &pp)) - return 0; - if (id && pp) - { if (soap->mode & SOAP_IO_LENGTH) - pp->mark1 = 1; - else - pp->mark2 = 1; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id embedded ref id=%d %p type=%d = (%d %d)\n", id, p, t, (int)pp->mark1, (int)pp->mark2)); + else if (id) + { + if ((soap->mode & SOAP_IO_LENGTH)) + pp->mark1 = 1; + else + pp->mark2 = 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id embedded ref id=%d %p type=%d = (%d %d)\n", id, p, t, (int)pp->mark1, (int)pp->mark2)); + } } return id; } #endif -#endif /******************************************************************************/ + #ifndef WITH_NOIDREF -#ifndef PALM_2 SOAP_FMAC1 int SOAP_FMAC2 soap_is_embedded(struct soap *soap, struct soap_plist *pp) -{ if (!pp) +{ + if (!pp) return 0; DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Is embedded? %d %d\n", (int)pp->mark1, (int)pp->mark2)); - if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER) - { if (soap->mode & SOAP_IO_LENGTH) + if (soap->version == 1 && soap->encodingStyle && !(soap->omode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER) + { + if ((soap->mode & SOAP_IO_LENGTH)) return pp->mark1 != 0; return pp->mark2 != 0; } - if (soap->mode & SOAP_IO_LENGTH) + if ((soap->mode & SOAP_IO_LENGTH)) return pp->mark1 == 1; return pp->mark2 == 1; } #endif -#endif /******************************************************************************/ + #ifndef WITH_NOIDREF -#ifndef PALM_2 SOAP_FMAC1 int SOAP_FMAC2 soap_is_single(struct soap *soap, struct soap_plist *pp) -{ if (soap->part == SOAP_IN_HEADER) +{ + if (soap->part == SOAP_IN_HEADER) return 1; if (!pp) return 0; - if (soap->mode & SOAP_IO_LENGTH) + if ((soap->mode & SOAP_IO_LENGTH)) return pp->mark1 == 0; return pp->mark2 == 0; } #endif -#endif /******************************************************************************/ + #ifndef WITH_NOIDREF -#ifndef PALM_2 SOAP_FMAC1 void SOAP_FMAC2 soap_set_embedded(struct soap *soap, struct soap_plist *pp) -{ if (!pp) +{ + if (!pp) return; - if (soap->mode & SOAP_IO_LENGTH) + if ((soap->mode & SOAP_IO_LENGTH)) pp->mark1 = 1; else pp->mark2 = 1; } #endif -#endif /******************************************************************************/ + #ifndef WITH_LEANER -#ifndef PALM_1 SOAP_FMAC1 int SOAP_FMAC2 -soap_attachment(struct soap *soap, const char *tag, int id, const void *p, const struct soap_array *a, const char *aid, const char *atype, const char *aoptions, int n, const char *type, int t) +soap_attachment(struct soap *soap, const char *tag, int id, const void *p, const void *a, int n, const char *aid, const char *atype, const char *aoptions, const char *type, int t) { -#ifndef WITH_NOIDREF struct soap_plist *pp; int i; - if (!p || !a->__ptr || (!aid && !atype)) - return soap_element_id(soap, tag, id, p, a, n, type, t); - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attachment tag='%s' id='%s' (%d) type='%s'\n", tag, aid?aid:SOAP_STR_EOS, id, atype?atype:SOAP_STR_EOS)); + if (!p || !a || (!aid && !atype) || (!soap->encodingStyle && !(soap->omode & (SOAP_ENC_DIME | SOAP_ENC_MIME | SOAP_ENC_MTOM | SOAP_XML_GRAPH))) || (soap->omode & SOAP_XML_TREE)) + return soap_element_id(soap, tag, id, p, a, n, type, t, NULL); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attachment tag='%s' id='%s' (%d) type='%s'\n", tag, aid ? aid : SOAP_STR_EOS, id, atype ? atype : SOAP_STR_EOS)); i = soap_array_pointer_lookup(soap, p, a, n, t, &pp); if (!i) - { i = soap_pointer_enter(soap, p, a, n, t, &pp); + { + i = soap_pointer_enter(soap, p, a, n, t, &pp); if (!i) - { soap->error = SOAP_EOM; + { + soap->error = SOAP_EOM; return -1; } } if (id <= 0) id = i; if (!aid) - { sprintf(soap->tmpbuf, soap->dime_id_format, id); + { + (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), strlen(soap->dime_id_format) + 20), soap->dime_id_format, id); aid = soap_strdup(soap, soap->tmpbuf); + if (!aid) + return -1; } /* Add MTOM xop:Include element when necessary */ - /* TODO: this code to be obsoleted with new import/xop.h conventions */ - if ((soap->mode & SOAP_ENC_MTOM) && strcmp(tag, "xop:Include")) - { if (soap_element_begin_out(soap, tag, 0, type) + if ((soap->omode & SOAP_ENC_MTOM) && strcmp(tag, "xop:Include")) + { + if (soap_element(soap, tag, 0, type) + || soap_attribute(soap, "xmlns:xop", "http://www.w3.org/2004/08/xop/include") + || soap_element_start_end_out(soap, NULL) || soap_element_href(soap, "xop:Include", 0, "href", aid) || soap_element_end_out(soap, tag)) return soap->error; } else if (soap_element_href(soap, tag, 0, "href", aid)) + { return soap->error; - if (soap->mode & SOAP_IO_LENGTH) - { if (pp->mark1 != 3) - { struct soap_multipart *content; - if (soap->mode & SOAP_ENC_MTOM) - content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, (char*)a->__ptr, a->__size); + } + if ((soap->mode & SOAP_IO_LENGTH)) + { + if (pp->mark1 != 3) + { + struct soap_multipart *content; + if ((soap->omode & SOAP_ENC_MTOM)) + content = soap_alloc_multipart(soap, &soap->mime.first, &soap->mime.last, (const char*)a, n); else - content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, (char*)a->__ptr, a->__size); + content = soap_alloc_multipart(soap, &soap->dime.first, &soap->dime.last, (const char*)a, n); if (!content) - { soap->error = SOAP_EOM; + { + soap->error = SOAP_EOM; return -1; } if (!strncmp(aid, "cid:", 4)) /* RFC 2111 */ - { if (soap->mode & SOAP_ENC_MTOM) - { char *s = (char*)soap_malloc(soap, strlen(aid) - 1); + { + if ((soap->omode & SOAP_ENC_MTOM)) + { + size_t l = strlen(aid) - 1; + char *s = (char*)soap_malloc(soap, l); if (s) - { *s = '<'; - strcpy(s + 1, aid + 4); - strcat(s, ">"); + { + s[0] = '<'; + (void)soap_strncpy(s + 1, l - 1, aid + 4, l - 3); + s[l - 2] = '>'; + s[l - 1] = '\0'; content->id = s; } } else + { content->id = aid + 4; + } } else + { content->id = aid; + } content->type = atype; content->options = aoptions; content->encoding = SOAP_MIME_BINARY; @@ -5376,39 +10847,42 @@ soap_attachment(struct soap *soap, const char *tag, int id, const void *p, const } } else + { pp->mark2 = 3; -#endif + } return -1; } #endif -#endif /******************************************************************************/ + #ifndef WITH_NOIDREF -#ifndef PALM_1 static void soap_init_iht(struct soap *soap) -{ int i; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing ID hashtable\n")); +{ + int i; for (i = 0; i < SOAP_IDHASH; i++) soap->iht[i] = NULL; } #endif -#endif /******************************************************************************/ + #ifndef WITH_NOIDREF -#ifndef PALM_1 static void soap_free_iht(struct soap *soap) -{ int i; +{ + int i; struct soap_ilist *ip = NULL, *p = NULL; struct soap_flist *fp = NULL, *fq = NULL; DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free ID hashtable\n")); for (i = 0; i < SOAP_IDHASH; i++) - { for (ip = soap->iht[i]; ip; ip = p) - { for (fp = ip->flist; fp; fp = fq) - { fq = fp->next; + { + for (ip = soap->iht[i]; ip; ip = p) + { + for (fp = ip->flist; fp; fp = fq) + { + fq = fp->next; SOAP_FREE(soap, fp); } p = ip->next; @@ -5418,96 +10892,120 @@ soap_free_iht(struct soap *soap) } } #endif -#endif /******************************************************************************/ + #ifndef WITH_NOIDREF -#ifndef PALM_2 SOAP_FMAC1 struct soap_ilist * SOAP_FMAC2 soap_lookup(struct soap *soap, const char *id) -{ struct soap_ilist *ip = NULL; +{ + struct soap_ilist *ip = NULL; for (ip = soap->iht[soap_hash(id)]; ip; ip = ip->next) if (!strcmp(ip->id, id)) return ip; return NULL; } #endif -#endif /******************************************************************************/ + #ifndef WITH_NOIDREF -#ifndef PALM_2 SOAP_FMAC1 struct soap_ilist * SOAP_FMAC2 -soap_enter(struct soap *soap, const char *id) -{ size_t h; - struct soap_ilist *ip; - ip = (struct soap_ilist*)SOAP_MALLOC(soap, sizeof(struct soap_ilist) + strlen(id)); +soap_enter(struct soap *soap, const char *id, int t, size_t n) +{ + size_t h; + struct soap_ilist *ip = NULL; + size_t l = strlen(id); + if (sizeof(struct soap_ilist) + l > l && (SOAP_MAXALLOCSIZE <= 0 || sizeof(struct soap_ilist) + l <= SOAP_MAXALLOCSIZE)) + ip = (struct soap_ilist*)SOAP_MALLOC(soap, sizeof(struct soap_ilist) + l); if (ip) - { h = soap_hash(id); - strcpy(ip->id, id); + { + ip->type = t; + ip->size = n; + ip->ptr = NULL; + ip->spine = NULL; + ip->link = NULL; + ip->copy = NULL; + ip->flist = NULL; + ip->smart = NULL; + ip->shaky = 0; + (void)soap_memcpy((char*)ip->id, l + 1, id, l + 1); + h = soap_hash(id); /* h = (HASH(id) % SOAP_IDHASH) so soap->iht[h] is safe */ ip->next = soap->iht[h]; soap->iht[h] = ip; } return ip; } #endif -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 void* SOAP_FMAC2 soap_malloc(struct soap *soap, size_t n) -{ char *p; - if (!n) - return (void*)SOAP_NON_NULL; +{ + char *p; + size_t k = n; + if (SOAP_MAXALLOCSIZE > 0 && n > SOAP_MAXALLOCSIZE) + { + if (soap) + soap->error = SOAP_EOM; + return NULL; + } if (!soap) return SOAP_MALLOC(soap, n); - if (soap->fmalloc) - p = (char*)soap->fmalloc(soap, n); - else - { n += sizeof(short); - n += (-(long)n) & (sizeof(void*)-1); /* align at 4-, 8- or 16-byte boundary */ - if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(void*) + sizeof(size_t)))) - { soap->error = SOAP_EOM; - return NULL; - } - /* set the canary to detect corruption */ - *(short*)(p + n - sizeof(short)) = (short)SOAP_CANARY; - /* keep chain of alloced cells for destruction */ - *(void**)(p + n) = soap->alist; - *(size_t*)(p + n + sizeof(void*)) = n; - soap->alist = p + n; + n += sizeof(short); + n += (~n+1) & (sizeof(void*)-1); /* align at 4-, 8- or 16-byte boundary by rounding up */ + if (n + sizeof(void*) + sizeof(size_t) < k) + { + soap->error = SOAP_EOM; + return NULL; + } + p = (char*)SOAP_MALLOC(soap, n + sizeof(void*) + sizeof(size_t)); + if (!p) + { + soap->error = SOAP_EOM; + return NULL; } - soap->alloced = 1; + /* set a canary word to detect memory overruns and data corruption */ + *(unsigned short*)(p + n - sizeof(unsigned short)) = (unsigned short)SOAP_CANARY; + /* keep chain of alloced cells for destruction */ + *(void**)(p + n) = soap->alist; + *(size_t*)(p + n + sizeof(void*)) = n; + soap->alist = p + n; return p; } -#endif /******************************************************************************/ + #ifdef SOAP_MEM_DEBUG static void soap_init_mht(struct soap *soap) -{ int i; +{ + int i; for (i = 0; i < (int)SOAP_PTRHASH; i++) soap->mht[i] = NULL; } #endif /******************************************************************************/ + #ifdef SOAP_MEM_DEBUG static void soap_free_mht(struct soap *soap) -{ int i; +{ + int i; struct soap_mlist *mp, *mq; for (i = 0; i < (int)SOAP_PTRHASH; i++) - { for (mp = soap->mht[i]; mp; mp = mq) - { mq = mp->next; + { + for (mp = soap->mht[i]; mp; mp = mq) + { + mq = mp->next; if (mp->live) fprintf(stderr, "%s(%d): malloc() = %p not freed (memory leak or forgot to call soap_end()?)\n", mp->file, mp->line, mp->ptr); free(mp); @@ -5518,16 +11016,22 @@ soap_free_mht(struct soap *soap) #endif /******************************************************************************/ + #ifdef SOAP_MEM_DEBUG SOAP_FMAC1 void* SOAP_FMAC2 soap_track_malloc(struct soap *soap, const char *file, int line, size_t size) -{ void *p = malloc(size); +{ + void *p = malloc(size); if (soap) - { size_t h = soap_hash_ptr(p); + { + size_t h = soap_hash_ptr(p); struct soap_mlist *mp = (struct soap_mlist*)malloc(sizeof(struct soap_mlist)); - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): malloc(%lu) = %p\n", file, line, (unsigned long)size, p)); + if (soap->fdebug[SOAP_INDEX_TEST]) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): malloc(%lu) = %p\n", file, line, (unsigned long)size, p)); + } mp->next = soap->mht[h]; mp->ptr = p; mp->file = file; @@ -5540,37 +11044,55 @@ soap_track_malloc(struct soap *soap, const char *file, int line, size_t size) #endif /******************************************************************************/ + #ifdef SOAP_MEM_DEBUG SOAP_FMAC1 void SOAP_FMAC2 soap_track_free(struct soap *soap, const char *file, int line, void *p) -{ size_t h = soap_hash_ptr(p); - struct soap_mlist *mp; - for (mp = soap->mht[h]; mp; mp = mp->next) - if (mp->ptr == p) - break; - if (mp) - { if (mp->live) - { free(p); - if (soap->fdebug[SOAP_INDEX_TEST]) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): free(%p)\n", file, line, p)); +{ + if (!soap) + { + free(p); + } + else + { + size_t h = soap_hash_ptr(p); + struct soap_mlist *mp; + for (mp = soap->mht[h]; mp; mp = mp->next) + if (mp->ptr == p) + break; + if (mp) + { + if (mp->live) + { + if (soap->fdebug[SOAP_INDEX_TEST]) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): free(%p)\n", file, line, p)); + } + free(p); + mp->live = 0; + } + else + { + fprintf(stderr, "%s(%d): free(%p) double free of pointer malloced at %s(%d)\n", file, line, p, mp->file, mp->line); } - mp->live = 0; } else - fprintf(stderr, "%s(%d): free(%p) double free of pointer malloced at %s(%d)\n", file, line, p, mp->file, mp->line); + { + fprintf(stderr, "%s(%d): free(%p) pointer not malloced\n", file, line, p); + } } - else - fprintf(stderr, "%s(%d): free(%p) pointer not malloced\n", file, line, p); } #endif /******************************************************************************/ + #ifdef SOAP_MEM_DEBUG static void soap_track_unlink(struct soap *soap, const void *p) -{ size_t h = soap_hash_ptr(p); +{ + size_t h = soap_hash_ptr(p); struct soap_mlist *mp; for (mp = soap->mht[h]; mp; mp = mp->next) if (mp->ptr == p) @@ -5581,18 +11103,20 @@ soap_track_unlink(struct soap *soap, const void *p) #endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 void SOAP_FMAC2 soap_dealloc(struct soap *soap, void *p) -{ if (soap_check_state(soap)) +{ + if (soap_check_state(soap)) return; if (p) - { char **q; - for (q = (char**)&soap->alist; *q; q = *(char***)q) + { + char **q; + for (q = (char**)(void*)&soap->alist; *q; q = *(char***)q) { - if (*(short*)(char*)(*q - sizeof(short)) != (short)SOAP_CANARY) + if (*(unsigned short*)(char*)(*q - sizeof(unsigned short)) != (unsigned short)SOAP_CANARY) { #ifdef SOAP_MEM_DEBUG fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n"); @@ -5604,7 +11128,8 @@ soap_dealloc(struct soap *soap, void *p) return; } if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*)))) - { *q = **(char***)q; + { + *q = **(char***)q; DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Freed data at %p\n", p)); SOAP_FREE(soap, p); return; @@ -5613,11 +11138,12 @@ soap_dealloc(struct soap *soap, void *p) soap_delete(soap, p); } else - { char *q; + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free all soap_malloc() data\n")); while (soap->alist) - { q = (char*)soap->alist; - if (*(short*)(char*)(q - sizeof(short)) != (short)SOAP_CANARY) + { + char *q = (char*)soap->alist; + if (*(unsigned short*)(char*)(q - sizeof(unsigned short)) != (unsigned short)SOAP_CANARY) { #ifdef SOAP_MEM_DEBUG fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n"); @@ -5632,40 +11158,48 @@ soap_dealloc(struct soap *soap, void *p) q -= *(size_t*)(q + sizeof(void*)); SOAP_FREE(soap, q); } - /* we must assume these were deallocated: */ + /* assume these were deallocated: */ + soap->http_content = NULL; soap->action = NULL; soap->fault = NULL; soap->header = NULL; + soap->bearer = NULL; soap->userid = NULL; soap->passwd = NULL; soap->authrealm = NULL; - soap->http_content = NULL; +#ifdef WITH_NTLM + soap->ntlm_challenge = NULL; +#endif #ifndef WITH_LEANER soap_clr_mime(soap); #endif } } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 void SOAP_FMAC2 soap_delete(struct soap *soap, void *p) -{ struct soap_clist **cp; +{ + struct soap_clist **cp; if (soap_check_state(soap)) return; cp = &soap->clist; if (p) - { while (*cp) - { if (p == (*cp)->ptr) - { struct soap_clist *q = *cp; + { + while (*cp) + { + if (p == (*cp)->ptr) + { + struct soap_clist *q = *cp; *cp = q->next; - if (q->fdelete(q)) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: deletion callback failed for object type %d\n", q->ptr, q->type)); + if (q->fdelete(soap, q)) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: deletion callback failed for object type=%d\n", q->ptr, q->type)); #ifdef SOAP_MEM_DEBUG - fprintf(stderr, "new(object type = %d) = %p not freed: deletion callback failed\n", q->type, q->ptr); + fprintf(stderr, "new(object type=%d) = %p not freed: deletion callback failed\n", q->type, q->ptr); #endif } SOAP_FREE(soap, q); @@ -5676,39 +11210,43 @@ soap_delete(struct soap *soap, void *p) DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: address not in list\n", p)); } else - { while (*cp) - { struct soap_clist *q = *cp; + { + while (*cp) + { + struct soap_clist *q = *cp; *cp = q->next; - if (q->fdelete(q)) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: deletion callback failed for object type %d\n", q->ptr, q->type)); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Delete %p type=%d (cp=%p)\n", q->ptr, q->type, (void*)q)); + if (q->fdelete(soap, q)) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: deletion callback failed for object type=%d\n", q->ptr, q->type)); #ifdef SOAP_MEM_DEBUG - fprintf(stderr, "new(object type = %d) = %p not freed: deletion callback failed\n", q->type, q->ptr); + fprintf(stderr, "new(object type=%d) = %p not freed: deletion callback failed\n", q->type, q->ptr); #endif } SOAP_FREE(soap, q); } } - soap->fault = NULL; /* this was possibly deallocated */ - soap->header = NULL; /* this was possibly deallocated */ + soap->fault = NULL; /* assume this was deallocated */ + soap->header = NULL; /* assume this was deallocated */ } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 void SOAP_FMAC2 soap_delegate_deletion(struct soap *soap, struct soap *soap_to) -{ struct soap_clist *cp; +{ + struct soap_clist *cp; char **q; #ifdef SOAP_MEM_DEBUG void *p; struct soap_mlist **mp, *mq; size_t h; #endif - for (q = (char**)&soap->alist; *q; q = *(char***)q) + for (q = (char**)(void*)&soap->alist; *q; q = *(char***)q) { - if (*(short*)(char*)(*q - sizeof(short)) != (short)SOAP_CANARY) + if (*(unsigned short*)(char*)(*q - sizeof(unsigned short)) != (unsigned short)SOAP_CANARY) { #ifdef SOAP_MEM_DEBUG fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n"); @@ -5723,10 +11261,12 @@ soap_delegate_deletion(struct soap *soap, struct soap *soap_to) p = (void*)(*q - *(size_t*)(*q + sizeof(void*))); h = soap_hash_ptr(p); for (mp = &soap->mht[h]; *mp; mp = &(*mp)->next) - { if ((*mp)->ptr == p) - { mq = *mp; + { + if ((*mp)->ptr == p) + { + mq = *mp; *mp = mq->next; - mq->next = soap_to->mht[h]; + mq->next = soap_to->mht[h]; soap_to->mht[h] = mq; break; } @@ -5736,81 +11276,124 @@ 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) + { + while (cp->next) cp = cp->next; cp->next = soap->clist; } else + { soap_to->clist = soap->clist; + } soap->clist = NULL; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 struct soap_clist * SOAP_FMAC2 -soap_link(struct soap *soap, void *p, int t, int n, int (*fdelete)(struct soap_clist*)) -{ struct soap_clist *cp; - if ((cp = (struct soap_clist*)SOAP_MALLOC(soap, sizeof(struct soap_clist)))) - { cp->next = soap->clist; - cp->type = t; - cp->size = n; - cp->ptr = p; - cp->fdelete = fdelete; - soap->clist = cp; +soap_link(struct soap *soap, int t, int n, int (*fdelete)(struct soap*, struct soap_clist*)) +{ + struct soap_clist *cp = NULL; + if (soap) + { + if (n != SOAP_NO_LINK_TO_DELETE) + { + cp = (struct soap_clist*)SOAP_MALLOC(soap, sizeof(struct soap_clist)); + if (!cp) + { + soap->error = SOAP_EOM; + } + else + { + cp->next = soap->clist; + cp->type = t; + cp->size = n; + cp->ptr = NULL; + cp->fdelete = fdelete; + soap->clist = cp; + } + } + soap->alloced = t; } return cp; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 -void +int SOAP_FMAC2 soap_unlink(struct soap *soap, const void *p) -{ char **q; - struct soap_clist **cp; - if (!soap || !p) - return; - for (q = (char**)&soap->alist; *q; q = *(char***)q) - { if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*)))) - { *q = **(char***)q; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked data %p\n", p)); +{ + if (soap && p) + { + char **q; + struct soap_clist **cp; + for (q = (char**)(void*)&soap->alist; *q; q = *(char***)q) + { + if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*)))) + { + *q = **(char***)q; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked data %p\n", p)); #ifdef SOAP_MEM_DEBUG - soap_track_unlink(soap, p); + soap_track_unlink(soap, p); #endif - return; + return SOAP_OK; /* found and removed from dealloc chain */ + } } - } - for (cp = &soap->clist; *cp; cp = &(*cp)->next) - { if (p == (*cp)->ptr) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked class instance %p\n", p)); - q = (char**)*cp; - *cp = (*cp)->next; - SOAP_FREE(soap, q); - return; + for (cp = &soap->clist; *cp; cp = &(*cp)->next) + { + if (p == (*cp)->ptr) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked class instance %p\n", p)); + q = (char**)*cp; + *cp = (*cp)->next; + SOAP_FREE(soap, q); + return SOAP_OK; /* found and removed from dealloc chain */ + } } } + return SOAP_ERR; } -#endif /******************************************************************************/ + #ifndef WITH_NOIDREF -#ifndef PALM_2 SOAP_FMAC1 int SOAP_FMAC2 soap_lookup_type(struct soap *soap, const char *id) -{ struct soap_ilist *ip; +{ + struct soap_ilist *ip; if (id && *id) - { ip = soap_lookup(soap, id); + { + ip = soap_lookup(soap, id); if (ip) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup id='%s' type=%d\n", id, ip->type)); + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup id='%s' type=%d\n", id, ip->type)); return ip->type; } } @@ -5818,172 +11401,225 @@ soap_lookup_type(struct soap *soap, const char *id) return 0; } #endif + +/******************************************************************************/ + +#ifndef WITH_NOIDREF +SOAP_FMAC1 +short +SOAP_FMAC2 +soap_begin_shaky(struct soap *soap) +{ + short f = soap->shaky; + soap->shaky = 1; + return f; +} +#endif + +/******************************************************************************/ + +#ifndef WITH_NOIDREF +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_end_shaky(struct soap *soap, short f) +{ + soap->shaky = f; +} +#endif + +/******************************************************************************/ + +#ifndef WITH_NOIDREF +static int +soap_is_shaky(struct soap *soap, void *p) +{ + (void)p; + if (!soap->blist && !soap->shaky) + return 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shaky %p\n", p)); + return 1; +} #endif /******************************************************************************/ + #ifndef WITH_NOIDREF -#ifndef PALM_2 SOAP_FMAC1 void* SOAP_FMAC2 -soap_id_lookup(struct soap *soap, const char *id, void **p, int t, size_t n, unsigned int k) -{ struct soap_ilist *ip; - void **q; +soap_id_lookup(struct soap *soap, const char *id, void **p, int t, size_t n, unsigned int k, int (*fbase)(int, int)) +{ + struct soap_ilist *ip; if (!p || !id || !*id) return p; ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */ if (!ip) - { if (!(ip = soap_enter(soap, id))) /* new hash table entry for string id */ + { + ip = soap_enter(soap, id, t, n); /* new hash table entry for string id */ + if (!ip) return NULL; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding first href='%s' type=%d %p (%u bytes)\n", id, t, p, (unsigned int)n)); - ip->type = t; - ip->size = n; - ip->link = p; - ip->copy = NULL; - ip->flist = NULL; - ip->ptr = NULL; - ip->level = k; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding first href='%s' type=%d location=%p (%u bytes) level=%u\n", id, t, (void*)p, (unsigned int)n, k)); *p = NULL; - } - else if (ip->ptr) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolved href='%s' type=%d location=%p (%u bytes)\n", id, t, ip->ptr, (unsigned int)n)); - if (ip->type != t) - { strcpy(soap->id, id); - soap->error = SOAP_HREF; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility: href='%s' id-type=%d href-type=%d\n", id, ip->type, t)); - return NULL; - } - while (ip->level < k) - { q = (void**)soap_malloc(soap, sizeof(void*)); - if (!q) + if (k) + { + int i; + if (k > SOAP_MAXPTRS) + return NULL; + ip->spine = (void**)soap_malloc(soap, SOAP_MAXPTRS * sizeof(void*)); + if (!ip->spine) return NULL; - *p = (void*)q; - p = q; - k--; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); + ip->spine[0] = NULL; + for (i = 1; i < SOAP_MAXPTRS; i++) + ip->spine[i] = &ip->spine[i - 1]; + *p = &ip->spine[k - 1]; } + else + { + ip->link = p; + ip->shaky = soap_is_shaky(soap, (void*)p); + } + } + else if (ip->type != t && (!fbase || !fbase(ip->type, t)) && (!fbase || !fbase(t, ip->type) || soap_type_punned(soap, ip))) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup type incompatibility: ref='%s' id-type=%d ref-type=%d\n", id, ip->type, t)); + (void)soap_id_nullify(soap, id); + return NULL; + } + else if (k == 0 && ip->ptr && !ip->shaky) /* when block lists are in use, ip->ptr will change */ + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolved href='%s' type=%d location=%p (%u bytes) level=%u\n", id, t, ip->ptr, (unsigned int)n, k)); *p = ip->ptr; } - else if (ip->level > k) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving level %u pointers to href='%s'\n", ip->level, id)); - while (ip->level > k) - { void *s, **r = &ip->link; - q = (void**)ip->link; - while (q) - { *r = (void*)soap_malloc(soap, sizeof(void*)); - if (!*r) - return NULL; - s = *q; - *q = *r; - r = (void**)*r; - q = (void**)s; - } - *r = NULL; + else + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarded href='%s' type=%d location=%p (%u bytes) level=%u\n", id, t, (void*)p, (unsigned int)n, k)); + if (fbase && fbase(t, ip->type) && !soap_type_punned(soap, ip)) + { + ip->type = t; ip->size = n; - ip->copy = NULL; - ip->level = ip->level - 1; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); } - q = (void**)ip->link; - ip->link = p; - *p = (void*)q; - } - else - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarded href='%s' type=%d location=%p (%u bytes)\n", id, t, p, (unsigned int)n)); - while (ip->level < k) - { q = (void**)soap_malloc(soap, sizeof(void*)); - if (!q) - return NULL; + *p = NULL; + if (k) + { + if (!ip->spine) + { + int i; + if (k > SOAP_MAXPTRS) + return NULL; + ip->spine = (void**)soap_malloc(soap, SOAP_MAXPTRS * sizeof(void*)); + if (!ip->spine) + return NULL; + ip->spine[0] = NULL; + for (i = 1; i < SOAP_MAXPTRS; i++) + ip->spine[i] = &ip->spine[i - 1]; + } + *p = &ip->spine[k - 1]; + if (ip->ptr && !ip->shaky) + ip->spine[0] = ip->ptr; + } + else + { + void *q = ip->link; + ip->link = p; + ip->shaky = soap_is_shaky(soap, (void*)p); *p = q; - p = q; - k--; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); } - q = (void**)ip->link; - ip->link = p; - *p = (void*)q; } return p; } #endif -#endif /******************************************************************************/ + #ifndef WITH_NOIDREF -#ifndef PALM_2 SOAP_FMAC1 void* SOAP_FMAC2 -soap_id_forward(struct soap *soap, const char *href, void *p, size_t len, int st, int tt, size_t n, unsigned int k, void (*fcopy)(struct soap*, int, int, void*, size_t, const void*, size_t)) -{ struct soap_ilist *ip; +soap_id_forward(struct soap *soap, const char *href, void *p, size_t i, int t, int tt, size_t n, unsigned int k, void (*finsert)(struct soap*, int, int, void*, size_t, const void*, void**), int (*fbase)(int, int)) +{ + struct soap_ilist *ip; if (!p || !href || !*href) return p; ip = soap_lookup(soap, href); /* lookup pointer to hash table entry for string id */ if (!ip) - { if (!(ip = soap_enter(soap, href))) /* new hash table entry for string id */ + { + ip = soap_enter(soap, href, t, n); /* new hash table entry for string id */ + if (!ip) return NULL; - ip->type = st; - ip->size = n; - ip->link = NULL; - ip->copy = NULL; - ip->ptr = NULL; - ip->level = 0; - ip->flist = NULL; - DBGLOG(TEST,SOAP_MESSAGE(fdebug, "New entry href='%s' type=%d size=%lu level=%d location=%p\n", href, st, (unsigned long)n, k, p)); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New entry href='%s' type=%d size=%lu level=%d location=%p\n", href, t, (unsigned long)n, k, p)); } - else if (ip->type != st || (ip->level == k && ip->size != n)) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n", href, ip->type, (unsigned long)ip->size, k, st, (unsigned long)n)); - strcpy(soap->id, href); - soap->error = SOAP_HREF; + else if ((ip->type != t || ip->size != n) && k == 0) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forward type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n", href, ip->type, (unsigned long)ip->size, k, t, (unsigned long)n)); + (void)soap_id_nullify(soap, href); return NULL; } - if (fcopy || n < sizeof(void*) || *href != '#') - { struct soap_flist *fp = (struct soap_flist*)SOAP_MALLOC(soap, sizeof(struct soap_flist)); + if (finsert || n < sizeof(void*)) + { + struct soap_flist *fp = (struct soap_flist*)SOAP_MALLOC(soap, sizeof(struct soap_flist)); if (!fp) - { soap->error = SOAP_EOM; + { + soap->error = SOAP_EOM; + return NULL; + } + if (fbase && fbase(t, ip->type) && !soap_type_punned(soap, ip)) + { + ip->type = t; + ip->size = n; + } + if ((ip->type != t || ip->size != n) && (!fbase || !fbase(ip->type, t))) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forward type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n", href, ip->type, (unsigned long)ip->size, k, t, (unsigned long)n)); + SOAP_FREE(soap, fp); + (void)soap_id_nullify(soap, href); return NULL; } fp->next = ip->flist; fp->type = tt; fp->ptr = p; fp->level = k; - fp->len = len; - if (fcopy) - fp->fcopy = fcopy; - else - fp->fcopy = soap_fcopy; + fp->index = i; + fp->finsert = finsert; ip->flist = fp; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding type=%d (target type=%d) size=%lu location=%p level=%u len=%lu href='%s'\n", st, tt, (unsigned long)n, p, k, (unsigned long)len, href)); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding type=%d (target type=%d) size=%lu location=%p level=%u index=%lu href='%s'\n", t, tt, (unsigned long)n, p, k, (unsigned long)i, href)); } else - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding copying address %p for type=%d href='%s'\n", p, st, href)); + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding copying address %p for type=%d href='%s'\n", p, t, href)); *(void**)p = ip->copy; ip->copy = p; } + ip->shaky = soap_is_shaky(soap, p); return p; } #endif -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 void* SOAP_FMAC2 -soap_id_enter(struct soap *soap, const char *id, void *p, int t, size_t n, unsigned int k, const char *type, const char *arrayType, void *(*finstantiate)(struct soap*, int, const char*, const char*, size_t*)) +soap_id_enter(struct soap *soap, const char *id, void *p, int t, size_t n, const char *type, const char *arrayType, void *(*finstantiate)(struct soap*, int, const char*, const char*, size_t*), int (*fbase)(int, int)) { #ifndef WITH_NOIDREF struct soap_ilist *ip; #endif - DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Enter id='%s' type=%d loc=%p size=%lu level=%u\n", id, t, p, (unsigned long)n, k)); + (void)id; (void)fbase; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enter id='%s' type=%d location=%p size=%lu\n", id, t, p, (unsigned long)n)); soap->alloced = 0; if (!p) - { if (finstantiate) - p = finstantiate(soap, t, type, arrayType, &n); + { + if (finstantiate) + { + p = finstantiate(soap, t, type, arrayType, &n); /* soap->alloced is set in soap_link() */ + t = soap->alloced; + } else + { p = soap_malloc(soap, n); - if (p) - soap->alloced = 1; + soap->alloced = t; + } } #ifndef WITH_NOIDREF if (!id || !*id) @@ -5991,83 +11627,178 @@ soap_id_enter(struct soap *soap, const char *id, void *p, int t, size_t n, unsig return p; #ifndef WITH_NOIDREF ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */ - DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Lookup entry id='%s for location=%p'\n", id, p)); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup entry id='%s' for location=%p type=%d\n", id, p, t)); if (!ip) - { if (!(ip = soap_enter(soap, id))) /* new hash table entry for string id */ + { + ip = soap_enter(soap, id, t, n); /* new hash table entry for string id */ + if (!ip) return NULL; - ip->type = t; - ip->link = NULL; - ip->copy = NULL; - ip->flist = NULL; - ip->size = n; ip->ptr = p; - ip->level = k; - DBGLOG(TEST,SOAP_MESSAGE(fdebug, "New entry id='%s' type=%d size=%lu level=%u location=%p\n", id, t, (unsigned long)n, k, p)); - } - else if ((ip->type != t || (ip->level == k && ip->size != n)) && (ip->copy || ip->flist)) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n", id, ip->type, (unsigned long)ip->size, k, t, (unsigned long)n)); - strcpy(soap->id, id); - soap->error = SOAP_HREF; - return NULL; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New entry id='%s' type=%d size=%lu location=%p\n", id, t, (unsigned long)n, p)); + if (!soap->alloced) + ip->shaky = soap_is_shaky(soap, p); } else if (ip->ptr) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Multiply defined id='%s'\n", id)); - strcpy(soap->id, id); + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Multiply defined id='%s'\n", id)); + soap_strcpy(soap->id, sizeof(soap->id), id); soap->error = SOAP_DUPLICATE_ID; return NULL; } + else if ((ip->type != t && (!fbase || !fbase(t, ip->type) || soap_type_punned(soap, ip))) + || (ip->type == t && ip->size != n && soap_type_punned(soap, ip))) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enter type incompatibility id='%s' expect type=%d size=%lu got type=%d size=%lu\n", id, ip->type, (unsigned long)ip->size, t, (unsigned long)n)); + (void)soap_id_nullify(soap, id); + return NULL; + } else - { ip->size = n; + { + ip->type = t; + ip->size = n; ip->ptr = p; - ip->level = k; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update entry id='%s' type=%d location=%p size=%lu level=%u\n", id, t, p, (unsigned long)n, k)); + if (!soap->alloced) + ip->shaky = soap_is_shaky(soap, p); + if (soap->alloced || !ip->shaky) + { + void **q; /* ptr will not change later, so resolve links now */ + if (ip->spine) + ip->spine[0] = p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Traversing link chain to resolve id='%s' type=%d\n", ip->id, ip->type)); + q = (void**)ip->link; + while (q) + { + void *r = *q; + *q = p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... link %p -> %p\n", (void*)q, p)); + q = (void**)r; + } + ip->link = NULL; + } } return ip->ptr; #endif } + +/******************************************************************************/ + +SOAP_FMAC1 +void** +SOAP_FMAC2 +soap_id_smart(struct soap *soap, const char *id, int t, size_t n) +{ + (void)soap; (void)id; (void)t; (void)n; +#ifndef WITH_NOIDREF + if (id && *id) + { + struct soap_ilist *ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */ + if (!ip) + { + ip = soap_enter(soap, id, t, n); /* new hash table entry for string id */ + if (!ip) + return NULL; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New smart shared pointer entry id='%s' type=%d size=%lu smart=%p\n", id, t, (unsigned long)n, ip->smart)); + return &ip->smart; + } +#endif + return NULL; +} + +/******************************************************************************/ + +#ifndef WITH_NOIDREF +static int +soap_type_punned(struct soap *soap, const struct soap_ilist *ip) +{ + const struct soap_flist *fp; + (void)soap; + if (ip->ptr || ip->copy) + return 1; + for (fp = ip->flist; fp; fp = fp->next) + if (fp->level == 0) + return 1; + return 0; +} #endif /******************************************************************************/ -#ifndef PALM_2 + +#ifndef WITH_NOIDREF SOAP_FMAC1 -void +int SOAP_FMAC2 -soap_fcopy(struct soap *soap, int st, int tt, void *p, size_t len, const void *q, size_t n) -{ DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Copying data type=%d (target type=%d) %p -> %p (%lu bytes)\n", st, tt, q, p, (unsigned long)n)); - memcpy(p, q, n); +soap_id_nullify(struct soap *soap, const char *id) +{ + int i; + for (i = 0; i < SOAP_IDHASH; i++) + { + struct soap_ilist *ip; + for (ip = soap->iht[i]; ip; ip = ip->next) + { + void *p, *q; + for (p = ip->link; p; p = q) + { + q = *(void**)p; + *(void**)p = NULL; + } + ip->link = NULL; + } + } + soap_strcpy(soap->id, sizeof(soap->id), id); + return soap->error = SOAP_HREF; } #endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 int SOAP_FMAC2 soap_end_send(struct soap *soap) { #ifndef WITH_LEANER + int err = soap_end_attachments(soap); if (soap->dime.list) - { /* SOAP body referenced attachments must appear first */ + { + /* SOAP body referenced attachments must appear first */ soap->dime.last->next = soap->dime.first; soap->dime.first = soap->dime.list->next; soap->dime.list->next = NULL; soap->dime.last = soap->dime.list; } - if (soap_putdime(soap) || soap_putmime(soap)) - return soap->error; + if (!err) + err = soap_putdime(soap); + if (!err) + err = soap_putmime(soap); soap->mime.list = NULL; soap->mime.first = NULL; soap->mime.last = NULL; soap->dime.list = NULL; soap->dime.first = NULL; soap->dime.last = NULL; + if (err) + return err; #endif - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End send\n")); - if (soap->mode & SOAP_IO) /* need to flush the remaining data in buffer */ - { if (soap_flush(soap)) + return soap_end_send_flush(soap); +} + +/******************************************************************************/ + +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 - { if (soap->mode & SOAP_ENC_ZLIB && soap->zlib_state == SOAP_ZLIB_DEFLATE) - { soap->zlib_state = SOAP_ZLIB_NONE; + { + if ((soap->mode & SOAP_ENC_ZLIB) && soap->zlib_state == SOAP_ZLIB_DEFLATE) + { + soap->zlib_state = SOAP_ZLIB_NONE; deflateEnd(soap->d_stream); } return soap->error; @@ -6076,20 +11807,24 @@ soap_end_send(struct soap *soap) return soap->error; #endif #ifdef WITH_ZLIB - if (soap->mode & SOAP_ENC_ZLIB) - { int r; + if ((soap->mode & SOAP_ENC_ZLIB) && soap->d_stream) + { + int r; soap->d_stream->avail_in = 0; do - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating remainder\n")); + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating remainder\n")); r = deflate(soap->d_stream, Z_FINISH); - if (soap->d_stream->avail_out != SOAP_BUFLEN) - { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN - soap->d_stream->avail_out)) - { soap->zlib_state = SOAP_ZLIB_NONE; + if (soap->d_stream->avail_out != sizeof(soap->buf)) + { + if (soap_flush_raw(soap, soap->z_buf, sizeof(soap->buf) - soap->d_stream->avail_out)) + { + soap->zlib_state = SOAP_ZLIB_NONE; deflateEnd(soap->d_stream); return soap->error; } soap->d_stream->next_out = (Byte*)soap->z_buf; - soap->d_stream->avail_out = SOAP_BUFLEN; + soap->d_stream->avail_out = sizeof(soap->buf); } } while (r == Z_OK); DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflated total %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out)); @@ -6097,12 +11832,14 @@ soap_end_send(struct soap *soap) soap->mode &= ~SOAP_ENC_ZLIB; soap->zlib_state = SOAP_ZLIB_NONE; if (deflateEnd(soap->d_stream) != Z_OK || r != Z_STREAM_END) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to end deflate: %s\n", soap->d_stream->msg?soap->d_stream->msg:SOAP_STR_EOS)); + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to end deflate: %s\n", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS)); return soap->error = SOAP_ZLIB_ERROR; } #ifdef WITH_GZIP if (soap->zlib_out != SOAP_ZLIB_DEFLATE) - { soap->z_buf[0] = soap->z_crc & 0xFF; + { + soap->z_buf[0] = soap->z_crc & 0xFF; soap->z_buf[1] = (soap->z_crc >> 8) & 0xFF; soap->z_buf[2] = (soap->z_crc >> 16) & 0xFF; soap->z_buf[3] = (soap->z_crc >> 24) & 0xFF; @@ -6118,79 +11855,121 @@ soap_end_send(struct soap *soap) } #endif if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) - { char *p; -#ifndef WITH_NOHTTP - if (!(soap->mode & SOAP_ENC_XML)) - { soap->mode--; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending buffered message of length %u\n", (unsigned int)soap->blist->size)); - if (soap->status >= SOAP_POST) - soap->error = soap->fpost(soap, soap->endpoint, soap->host, soap->port, soap->path, soap->action, soap->blist->size); - else if (soap->status != SOAP_STOP) - soap->error = soap->fresponse(soap, soap->status, soap->blist->size); - if (soap->error || soap_flush(soap)) - return soap->error; - soap->mode++; + { +#if !defined(__cplusplus) || defined(WITH_COMPAT) + if (soap->os) + { + char *b = (char*)soap_push_block(soap, NULL, 1); + if (b) + { + *b = '\0'; + *soap->os = (char*)soap_save_block(soap, NULL, NULL, 0); + } } + else #endif - for (p = soap_first_block(soap, NULL); p; p = soap_next_block(soap, NULL)) - { DBGMSG(SENT, p, soap_block_size(soap, NULL)); - if ((soap->error = soap->fsend(soap, p, soap_block_size(soap, NULL)))) - { soap_end_block(soap, NULL); - return soap->error; + { + char *p; +#ifndef WITH_NOHTTP + if (!(soap->mode & SOAP_ENC_PLAIN)) + { + soap->mode--; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending buffered message of length %u\n", (unsigned int)soap->blist->size)); + if (soap->status >= SOAP_POST) + soap->error = soap->fpost(soap, soap->endpoint, soap->host, soap->port, soap->path, soap->action, soap->blist->size); + else if (soap->status != SOAP_STOP) + soap->error = soap->fresponse(soap, soap->status, soap->blist->size); + if (soap->error || soap_flush(soap)) + return soap->error; + soap->mode++; } +#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), (int)soap->socket, soap->sendfd)); + soap->error = soap->fsend(soap, p, soap_block_size(soap, NULL)); + if (soap->error) + { + soap_end_block(soap, NULL); + return soap->error; + } + } + soap_end_block(soap, NULL); } - soap_end_block(soap, NULL); +#ifndef WITH_LEANER + if (soap->fpreparefinalsend && (soap->error = soap->fpreparefinalsend(soap)) != SOAP_OK) + return soap->error; +#endif + if ((soap->omode & SOAP_IO) == SOAP_IO_STORE && (soap->imode & SOAP_IO) != SOAP_IO_STORE) + soap->omode = (soap->omode & ~SOAP_IO) | (soap->imode & SOAP_IO); } #ifndef WITH_LEANER else if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) - { DBGMSG(SENT, "\r\n0\r\n\r\n", 7); - if ((soap->error = soap->fsend(soap, "\r\n0\r\n\r\n", 7))) + { + DBGMSG(SENT, "\r\n0\r\n\r\n", 7); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Send 7 bytes to socket=%d/fd=%d\n", (int)soap->socket, soap->sendfd)); + soap->error = soap->fsend(soap, "\r\n0\r\n\r\n", 7); + if (soap->error) return soap->error; } #endif } #ifdef WITH_TCPFIN -#ifdef WITH_OPENSSL - if (!soap->ssl && soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP)) - soap->fshutdownsocket(soap, soap->socket, 1); /* Send TCP FIN */ -#else - if (soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP)) - soap->fshutdownsocket(soap, soap->socket, 1); /* Send TCP FIN */ +#if defined(WITH_OPENSSL) || defined(WITH_WOLFSSL) || defined(WITH_SYSTEMSSL) + if (!soap->ssl) #endif + if (soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP)) + (void)soap->fshutdownsocket(soap, soap->socket, SOAP_SHUT_WR); /* Send TCP FIN */ +#endif +#if defined(__cplusplus) && !defined(WITH_COMPAT) + if (soap->os) + soap->os->flush(); #endif DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of send phase\n")); - soap->omode &= ~SOAP_XML_SEC; + soap->omode &= ~SOAP_SEC_WSUID; soap->count = 0; soap->part = SOAP_END; return SOAP_OK; } -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 int SOAP_FMAC2 soap_end_recv(struct soap *soap) -{ soap->part = SOAP_END; +{ + soap->part = SOAP_END; +#ifndef WITH_LEAN + soap->wsuid = NULL; /* reset before next send */ + soap->c14nexclude = NULL; /* reset before next send */ + soap->c14ninclude = NULL; /* reset before next send */ +#endif #ifndef WITH_LEANER + soap->ffilterrecv = NULL; if ((soap->mode & SOAP_ENC_DIME) && soap_getdime(soap)) - { soap->dime.first = NULL; + { + soap->dime.first = NULL; soap->dime.last = NULL; return soap->error; } soap->dime.list = soap->dime.first; soap->dime.first = NULL; soap->dime.last = NULL; - /* Check if MIME attachments and mime-post-check flag is set, if set call soap_resolve() and return */ - if (soap->mode & SOAP_ENC_MIME) + /* Check if MIME attachments and mime-post-check flag is set, if so call soap_resolve() and return */ + if ((soap->mode & SOAP_ENC_MIME)) { + if ((soap->mode & SOAP_MIME_POSTCHECK)) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Post checking MIME attachments\n")); + if (!soap->keep_alive) + soap->keep_alive = -2; /* special case to keep alive */ #ifndef WITH_NOIDREF - if (soap->mode & SOAP_MIME_POSTCHECK) - { soap_resolve(soap); + soap_resolve(soap); +#endif return SOAP_OK; } -#endif if (soap_getmime(soap)) return soap->error; } @@ -6199,42 +11978,51 @@ soap_end_recv(struct soap *soap) soap->mime.last = NULL; soap->mime.boundary = NULL; if (soap->xlist) - { struct soap_multipart *content; + { + struct soap_multipart *content; for (content = soap->mime.list; content; content = content->next) soap_resolve_attachment(soap, content); } #endif - DBGLOG(TEST,SOAP_MESSAGE(fdebug, "End of receive message ok\n")); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of receive message ok\n")); #ifdef WITH_ZLIB - if (soap->mode & SOAP_ENC_ZLIB) - { /* Make sure end of compressed content is reached */ + if ((soap->mode & SOAP_ENC_ZLIB) && soap->d_stream) + { + /* Make sure end of compressed content is reached */ while (soap->d_stream->next_out != Z_NULL) if ((int)soap_get1(soap) == EOF) break; soap->mode &= ~SOAP_ENC_ZLIB; - memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN); + (void)soap_memcpy((void*)soap->buf, sizeof(soap->buf), (const void*)soap->z_buf, sizeof(soap->buf)); soap->bufidx = (char*)soap->d_stream->next_in - soap->z_buf; soap->buflen = soap->z_buflen; soap->zlib_state = SOAP_ZLIB_NONE; if (inflateEnd(soap->d_stream) != Z_OK) return soap->error = SOAP_ZLIB_ERROR; - DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Inflate end ok\n")); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate end ok\n")); #ifdef WITH_GZIP if (soap->zlib_in == SOAP_ZLIB_GZIP) - { soap_wchar c; + { + soap_wchar c; short i; - DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Inflate gzip crc check\n")); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate gzip crc check\n")); for (i = 0; i < 8; i++) - { if ((int)(c = soap_get1(soap)) == EOF) - return soap->error = SOAP_EOF; + { + if ((int)(c = soap_get1(soap)) == EOF) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Gzip error: unable to read crc value\n")); + return soap->error = SOAP_ZLIB_ERROR; + } soap->z_buf[i] = (char)c; } if (soap->z_crc != ((uLong)(unsigned char)soap->z_buf[0] | ((uLong)(unsigned char)soap->z_buf[1] << 8) | ((uLong)(unsigned char)soap->z_buf[2] << 16) | ((uLong)(unsigned char)soap->z_buf[3] << 24))) - { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: crc check failed, message corrupted? (crc32=%lu)\n", (unsigned long)soap->z_crc)); + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Gzip inflate error: crc check failed, message corrupted? (crc32=%lu)\n", (unsigned long)soap->z_crc)); return soap->error = SOAP_ZLIB_ERROR; } if (soap->d_stream->total_out != ((uLong)(unsigned char)soap->z_buf[4] | ((uLong)(unsigned char)soap->z_buf[5] << 8) | ((uLong)(unsigned char)soap->z_buf[6] << 16) | ((uLong)(unsigned char)soap->z_buf[7] << 24))) - { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: incorrect message length\n")); + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Gzip inflate error: incorrect message length\n")); return soap->error = SOAP_ZLIB_ERROR; } } @@ -6243,33 +12031,36 @@ soap_end_recv(struct soap *soap) } #endif if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) - while ((int)soap_getchar(soap) != EOF) /* advance to last chunk */ - ; - if (soap->fdisconnect && (soap->error = soap->fdisconnect(soap))) - return soap->error; + while ((int)soap->ahead != EOF && !soap_recv_raw(soap)) + continue; #ifndef WITH_NOIDREF if (soap_resolve(soap)) return soap->error; #endif #ifndef WITH_LEANER if (soap->xlist) - { if (soap->mode & SOAP_ENC_MTOM) + { + if ((soap->mode & SOAP_ENC_MTOM)) return soap->error = SOAP_MIME_HREF; return soap->error = SOAP_DIME_HREF; } #endif soap_free_ns(soap); +#ifndef WITH_LEANER + if (soap->fpreparefinalrecv) + return soap->error = soap->fpreparefinalrecv(soap); +#endif return SOAP_OK; } -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 void SOAP_FMAC2 soap_free_temp(struct soap *soap) -{ struct soap_attribute *tp, *tq; +{ + struct soap_attribute *tp, *tq; struct Namespace *ns; soap_free_ns(soap); DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free any remaining temp blocks\n")); @@ -6277,7 +12068,8 @@ soap_free_temp(struct soap *soap) soap_end_block(soap, NULL); DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute storage\n")); for (tp = soap->attributes; tp; tp = tq) - { tq = tp->next; + { + tq = tp->next; if (tp->value) SOAP_FREE(soap, tp->value); SOAP_FREE(soap, tp); @@ -6292,172 +12084,216 @@ soap_free_temp(struct soap *soap) #endif ns = soap->local_namespaces; if (ns) - { for (; ns->id; ns++) - { if (ns->out) - { if (soap->encodingStyle == ns->out) - soap->encodingStyle = SOAP_STR_EOS; + { + for (; ns->id; ns++) + { + if (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; } #ifndef WITH_LEANER while (soap->xlist) - { struct soap_xlist *xp = soap->xlist->next; + { + struct soap_xlist *xp = soap->xlist->next; SOAP_FREE(soap, soap->xlist); soap->xlist = xp; } #endif #ifndef WITH_NOIDREF - soap_free_pht(soap); soap_free_iht(soap); #endif + soap_free_pht(soap); } -#endif /******************************************************************************/ -#ifndef PALM_1 + static void soap_free_ns(struct soap *soap) -{ struct soap_nlist *np, *nq; +{ + struct soap_nlist *np, *nq; DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free namespace stack\n")); for (np = soap->nlist; np; np = nq) - { nq = np->next; + { + nq = np->next; SOAP_FREE(soap, np); } soap->nlist = NULL; } -#endif /******************************************************************************/ -#ifndef PALM_1 -#if !defined(WITH_LEAN) || defined(SOAP_DEBUG) + +#ifdef SOAP_DEBUG static void soap_init_logs(struct soap *soap) -{ int i; +{ + int i; for (i = 0; i < SOAP_MAXLOGS; i++) - { soap->logfile[i] = NULL; + { + soap->logfile[i] = NULL; soap->fdebug[i] = NULL; } } #endif -#endif /******************************************************************************/ -#if !defined(WITH_LEAN) || defined(SOAP_DEBUG) + +#ifdef SOAP_DEBUG SOAP_FMAC1 void SOAP_FMAC2 soap_open_logfile(struct soap *soap, int i) -{ if (soap->logfile[i]) +{ + if (soap->logfile[i]) soap->fdebug[i] = fopen(soap->logfile[i], i < 2 ? "ab" : "a"); } #endif /******************************************************************************/ + #ifdef SOAP_DEBUG static void soap_close_logfile(struct soap *soap, int i) -{ if (soap->fdebug[i]) - { fclose(soap->fdebug[i]); +{ + if (soap->fdebug[i]) + { + fclose(soap->fdebug[i]); soap->fdebug[i] = NULL; } } #endif /******************************************************************************/ + #ifdef SOAP_DEBUG SOAP_FMAC1 void SOAP_FMAC2 soap_close_logfiles(struct soap *soap) -{ int i; +{ + int i; for (i = 0; i < SOAP_MAXLOGS; i++) soap_close_logfile(soap, i); } #endif /******************************************************************************/ + #ifdef SOAP_DEBUG static void soap_set_logfile(struct soap *soap, int i, const char *logfile) -{ const char *s; +{ + const char *s; char *t = NULL; soap_close_logfile(soap, i); s = soap->logfile[i]; - soap->logfile[i] = logfile; if (s) - SOAP_FREE(soap, (void*)s); + SOAP_FREE_UNMANAGED(s); if (logfile) - if ((t = (char*)SOAP_MALLOC(soap, strlen(logfile) + 1))) - strcpy(t, logfile); + { + size_t l = strlen(logfile) + 1; + t = (char*)SOAP_MALLOC_UNMANAGED(l); + if (t) + (void)soap_memcpy((void*)t, l, (const void*)logfile, l); + } soap->logfile[i] = t; } #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); -} +{ + (void)soap; (void)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); -} +{ + (void)soap; (void)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); -} +{ + (void)soap; (void)logfile; +#ifdef SOAP_DEBUG + soap_set_logfile(soap, SOAP_INDEX_TEST, logfile); #endif +} /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 struct soap* SOAP_FMAC2 soap_copy(const struct soap *soap) -{ return soap_copy_context((struct soap*)malloc(sizeof(struct soap)), soap); +{ + struct soap *copy = soap_versioning(soap_new)(SOAP_IO_DEFAULT, SOAP_IO_DEFAULT); + soap_set_test_logfile(copy, NULL); + soap_set_sent_logfile(copy, NULL); + soap_set_recv_logfile(copy, NULL); + soap_done(copy); + if (soap_copy_context(copy, soap) != NULL) + return copy; + soap_free(copy); + return NULL; } -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 struct soap* SOAP_FMAC2 soap_copy_context(struct soap *copy, const struct soap *soap) -{ if (soap_check_state(soap)) +{ + if (copy == soap) + return copy; + if (soap_check_state(soap)) return NULL; if (copy) - { struct soap_plugin *p = NULL; -#ifdef __cplusplus - *copy = *soap; -#else - memcpy(copy, soap, sizeof(struct soap)); -#endif + { + struct soap_plugin *p = NULL; + (void)soap_memcpy((void*)copy, sizeof(struct soap), (const void*)soap, sizeof(struct soap)); copy->state = SOAP_COPY; +#ifdef SOAP_MEM_DEBUG + soap_init_mht(copy); +#endif +#ifdef SOAP_DEBUG + soap_init_logs(copy); + soap_set_test_logfile(copy, soap->logfile[SOAP_INDEX_TEST]); + soap_set_sent_logfile(copy, soap->logfile[SOAP_INDEX_SENT]); + soap_set_recv_logfile(copy, soap->logfile[SOAP_INDEX_RECV]); +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying context\n")); copy->error = SOAP_OK; + copy->bearer = NULL; copy->userid = NULL; copy->passwd = NULL; +#ifdef WITH_NTLM + copy->ntlm_challenge = NULL; +#endif copy->nlist = NULL; copy->blist = NULL; copy->clist = NULL; @@ -6466,39 +12302,32 @@ soap_copy_context(struct soap *copy, const struct soap *soap) copy->labbuf = NULL; copy->lablen = 0; copy->labidx = 0; -#ifdef SOAP_MEM_DEBUG - soap_init_mht(copy); -#endif -#if !defined(WITH_LEAN) || defined(SOAP_DEBUG) - soap_init_logs(copy); -#endif -#ifdef SOAP_DEBUG - soap_set_test_logfile(copy, soap->logfile[SOAP_INDEX_TEST]); - soap_set_sent_logfile(copy, soap->logfile[SOAP_INDEX_SENT]); - soap_set_recv_logfile(copy, soap->logfile[SOAP_INDEX_RECV]); -#endif -#ifdef WITH_C_LOCALE - copy->c_locale = duplocale(soap->c_locale); -#else + copy->namespaces = soap->local_namespaces; + copy->local_namespaces = NULL; + soap_set_local_namespaces(copy); /* copy content of soap->local_namespaces */ + copy->namespaces = soap->namespaces; /* point to shared read-only namespaces table */ copy->c_locale = NULL; -#endif #ifdef WITH_OPENSSL copy->bio = NULL; copy->ssl = NULL; copy->session = NULL; + copy->session_host[0] = '\0'; + copy->session_port = 443; +#endif +#ifdef WITH_WOLFSSL + copy->ssl = NULL; +#endif +#ifdef WITH_GNUTLS + copy->session = NULL; #endif #ifdef WITH_ZLIB - copy->d_stream = (z_stream*)SOAP_MALLOC(copy, sizeof(z_stream)); - copy->d_stream->zalloc = Z_NULL; - copy->d_stream->zfree = Z_NULL; - copy->d_stream->opaque = Z_NULL; + copy->d_stream = NULL; copy->z_buf = NULL; #endif - copy->local_namespaces = NULL; #ifndef WITH_NOIDREF soap_init_iht(copy); - soap_init_pht(copy); #endif + soap_init_pht(copy); copy->header = NULL; copy->fault = NULL; copy->action = NULL; @@ -6511,40 +12340,75 @@ soap_copy_context(struct soap *copy, const struct soap *soap) #endif copy->plugins = NULL; for (p = soap->plugins; p; p = p->next) - { struct soap_plugin *q = (struct soap_plugin*)SOAP_MALLOC(copy, sizeof(struct soap_plugin)); + { + struct soap_plugin *q = (struct soap_plugin*)SOAP_MALLOC(copy, sizeof(struct soap_plugin)); if (!q) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not allocate plugin '%s'\n", p->id)); + soap_end(copy); + soap_done(copy); return NULL; + } DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying plugin '%s'\n", p->id)); *q = *p; - if (p->fcopy && p->fcopy(copy, q, p)) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not copy plugin '%s'\n", p->id)); + if (p->fcopy && (copy->error = p->fcopy(copy, q, p)) != SOAP_OK) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not copy plugin '%s' error = %d\n", p->id, copy->error)); SOAP_FREE(copy, q); + soap_end(copy); + soap_done(copy); return NULL; } q->next = copy->plugins; copy->plugins = q; } } +#ifdef WITH_SELF_PIPE + pipe(copy->pipe_fd); + SOAP_SOCKNONBLOCK(copy->pipe_fd[0]) + SOAP_SOCKNONBLOCK(copy->pipe_fd[1]) +#endif return copy; } -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 void SOAP_FMAC2 soap_copy_stream(struct soap *copy, struct soap *soap) -{ copy->mode = soap->mode; +{ + 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; copy->socket = soap->socket; + copy->sendsk = soap->sendsk; + copy->recvsk = soap->recvsk; + copy->transfer_timeout = soap->transfer_timeout; + copy->recv_maxlength = soap->recv_maxlength; copy->recv_timeout = soap->recv_timeout; copy->send_timeout = soap->send_timeout; -#if defined(__cplusplus) && !defined(WITH_LEAN) + copy->connect_timeout = soap->connect_timeout; + copy->accept_timeout = soap->accept_timeout; + copy->socket_flags = soap->socket_flags; + copy->connect_flags = soap->connect_flags; + copy->connect_retry = soap->connect_retry; + copy->bind_flags = soap->bind_flags; + copy->bind_inet6 = soap->bind_inet6; + copy->bind_v6only = soap->bind_v6only; + copy->accept_flags = soap->accept_flags; + copy->sndbuf = soap->sndbuf; + copy->rcvbuf = soap->rcvbuf; + copy->linger_time = soap->linger_time; + copy->maxlevel = soap->maxlevel; + copy->maxlength = soap->maxlength; + copy->maxoccurs = soap->maxoccurs; copy->os = soap->os; copy->is = soap->is; -#endif copy->sendfd = soap->sendfd; copy->recvfd = soap->recvfd; copy->bufidx = soap->bufidx; @@ -6562,67 +12426,233 @@ soap_copy_stream(struct soap *copy, struct soap *soap) #ifndef WITH_NOIO copy->peer = soap->peer; copy->peerlen = soap->peerlen; + copy->ip = soap->ip; + copy->ip6[0] = soap->ip6[0]; + copy->ip6[1] = soap->ip6[1]; + copy->ip6[2] = soap->ip6[2]; + copy->ip6[3] = soap->ip6[3]; + copy->port = soap->port; + (void)soap_memcpy((void*)copy->host, sizeof(copy->host), (const void*)soap->host, sizeof(soap->host)); + (void)soap_memcpy((void*)copy->endpoint, sizeof(copy->endpoint), (const void*)soap->endpoint, sizeof(soap->endpoint)); #endif #ifdef WITH_OPENSSL copy->bio = soap->bio; copy->ssl = soap->ssl; copy->ctx = soap->ctx; #endif +#ifdef WITH_GNUTLS + copy->session = soap->session; +#endif +#ifdef WITH_WOLFSSL + copy->ssl = soap->ssl; + copy->ctx = soap->ctx; +#endif +#ifdef WITH_SYSTEMSSL + copy->ssl = soap->ssl; + copy->ctx = soap->ctx; +#endif #ifdef WITH_ZLIB copy->zlib_state = soap->zlib_state; copy->zlib_in = soap->zlib_in; copy->zlib_out = soap->zlib_out; - copy->d_stream = (z_stream*)SOAP_MALLOC(copy, sizeof(z_stream)); - memcpy(copy->d_stream, soap->d_stream, sizeof(z_stream)); + if (soap->d_stream && soap->zlib_state != SOAP_ZLIB_NONE) + { + if (!copy->d_stream) + copy->d_stream = (z_stream*)SOAP_MALLOC(copy, sizeof(z_stream)); + if (copy->d_stream) + (void)soap_memcpy((void*)copy->d_stream, sizeof(z_stream), (const void*)soap->d_stream, sizeof(z_stream)); + } copy->z_crc = soap->z_crc; copy->z_ratio_in = soap->z_ratio_in; copy->z_ratio_out = soap->z_ratio_out; - copy->z_buf = NULL; - copy->z_buflen = soap->z_buflen; copy->z_level = soap->z_level; if (soap->z_buf && soap->zlib_state != SOAP_ZLIB_NONE) - { copy->z_buf = (char*)SOAP_MALLOC(copy, SOAP_BUFLEN); - memcpy(copy->z_buf, soap->z_buf, sizeof(soap->z_buf)); + { + if (!copy->z_buf) + copy->z_buf = (char*)SOAP_MALLOC(copy, sizeof(soap->buf)); + if (copy->z_buf) + (void)soap_memcpy((void*)copy->z_buf, sizeof(soap->buf), (const void*)soap->z_buf, sizeof(soap->buf)); + else + copy->z_buflen = 0; + } + else + { + copy->z_buf = NULL; + copy->z_buflen = 0; } copy->z_dict = soap->z_dict; copy->z_dict_len = soap->z_dict_len; #endif - memcpy(copy->buf, soap->buf, sizeof(soap->buf)); -} + (void)soap_memcpy((void*)copy->buf, sizeof(copy->buf), (const void*)soap->buf, sizeof(soap->buf)); + /* copy XML parser state */ + soap_free_ns(copy); + soap_set_local_namespaces(copy); + copy->version = soap->version; + if (soap->nlist && soap->local_namespaces) + { + struct soap_nlist *np = NULL, *nq; + /* copy reversed nlist */ + for (nq = soap->nlist; nq; nq = nq->next) + { + struct soap_nlist *nr = np; + size_t n = sizeof(struct soap_nlist) + strlen(nq->id); + np = (struct soap_nlist*)SOAP_MALLOC(copy, n); + if (!np) + { + np = nr; + break; + } + (void)soap_memcpy((void*)np, n, (const void*)nq, n); + np->next = nr; + } + while (np) + { + const char *s = np->ns; + copy->level = np->level; /* preserve element nesting level */ + if (!s && np->index >= 0) + { + s = soap->local_namespaces[np->index].out; + if (!s) + s = soap->local_namespaces[np->index].ns; + } + if (s) + (void)soap_push_namespace(copy, np->id, s); + nq = np; + np = np->next; + SOAP_FREE(copy, nq); + } + } + (void)soap_memcpy((void*)copy->tag, sizeof(copy->tag), (const void*)soap->tag, sizeof(soap->tag)); + (void)soap_memcpy((void*)copy->id, sizeof(copy->id), (const void*)soap->id, sizeof(soap->id)); + (void)soap_memcpy((void*)copy->href, sizeof(copy->href), (const void*)soap->href, sizeof(soap->href)); + (void)soap_memcpy((void*)copy->type, sizeof(copy->type), (const void*)soap->type, sizeof(soap->type)); + copy->other = soap->other; + copy->root = soap->root; + copy->null = soap->null; + copy->body = soap->body; + copy->part = soap->part; + copy->mustUnderstand = soap->mustUnderstand; + copy->level = soap->level; + copy->peeked = soap->peeked; + /* copy attributes */ + for (tq = soap->attributes; tq; tq = tq->next) + { + struct soap_attribute *tr = tp; + size_t n = sizeof(struct soap_attribute) + strlen(tq->name); + tp = (struct soap_attribute*)SOAP_MALLOC(copy, n); + (void)soap_memcpy((void*)tp, n, (const void*)tq, n); + if (tp->size) + { + tp->value = (char*)SOAP_MALLOC(copy, tp->size); + if (tp->value) + (void)soap_memcpy((void*)tp->value, tp->size, (const void*)tq->value, tp->size); + } + tp->ns = NULL; + tp->next = tr; + } + copy->attributes = tp; +} + +/******************************************************************************/ + +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_free_stream(struct soap *soap) +{ + soap->socket = SOAP_INVALID_SOCKET; + soap->sendsk = SOAP_INVALID_SOCKET; + soap->recvsk = SOAP_INVALID_SOCKET; +#ifdef WITH_OPENSSL + soap->bio = NULL; + soap->ssl = NULL; + soap->ctx = NULL; +#endif +#ifdef WITH_GNUTLS + soap->xcred = NULL; + soap->acred = NULL; + soap->cache = NULL; + soap->session = NULL; + soap->dh_params = NULL; + soap->rsa_params = NULL; +#endif +#ifdef WITH_WOLFSSL + soap->ssl = NULL; + soap->ctx = NULL; +#endif +#ifdef WITH_SYSTEMSSL + soap->ssl = (gsk_handle)NULL; + soap->ctx = (gsk_handle)NULL; +#endif +#ifdef WITH_ZLIB + if (soap->z_buf) + SOAP_FREE(soap, soap->z_buf); + soap->z_buf = NULL; #endif +} + +/******************************************************************************/ + +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_initialize(struct soap *soap) +{ + soap_versioning(soap_init)(soap, SOAP_IO_DEFAULT, SOAP_IO_DEFAULT); +} /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 void SOAP_FMAC2 -soap_init(struct soap *soap) -{ soap->state = SOAP_INIT; +soap_versioning(soap_init)(struct soap *soap, soap_mode imode, soap_mode omode) +{ + size_t i; + soap->state = SOAP_INIT; #ifdef SOAP_MEM_DEBUG soap_init_mht(soap); #endif -#if !defined(WITH_LEAN) || defined(SOAP_DEBUG) +#ifdef SOAP_DEBUG soap_init_logs(soap); #endif -#ifdef SOAP_DEBUG +#ifdef TANDEM_NONSTOP + soap_set_test_logfile(soap, "TESTLOG"); + soap_set_sent_logfile(soap, "SENTLOG"); + soap_set_recv_logfile(soap, "RECVLOG"); +#else soap_set_test_logfile(soap, "TEST.log"); soap_set_sent_logfile(soap, "SENT.log"); soap_set_recv_logfile(soap, "RECV.log"); - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing context\n")); +#endif +#ifdef WITH_SELF_PIPE + pipe(soap->pipe_fd); + SOAP_SOCKNONBLOCK(soap->pipe_fd[0]) + SOAP_SOCKNONBLOCK(soap->pipe_fd[1]) #endif soap->version = 0; - soap_imode(soap, SOAP_IO_DEFAULT); - soap_omode(soap, SOAP_IO_DEFAULT); + soap->imode = imode; + soap->omode = omode; + soap->mode = imode; soap->plugins = NULL; soap->user = NULL; + for (i = 0; i < sizeof(soap->data)/sizeof(*soap->data); i++) + soap->data[i] = NULL; + soap->bearer = NULL; soap->userid = NULL; soap->passwd = NULL; + soap->authrealm = NULL; +#ifdef WITH_NTLM + soap->ntlm_challenge = NULL; +#endif #ifndef WITH_NOHTTP soap->fpost = http_post; soap->fget = http_get; - soap->fput = http_405; - soap->fdel = http_405; - soap->fhead = http_405; + soap->fput = http_put; + soap->fpatch = http_patch; + soap->fdel = http_del; + soap->fopt = http_200; + soap->fhead = http_200; soap->fform = NULL; soap->fposthdr = http_post_header; soap->fresponse = http_response; @@ -6633,8 +12663,13 @@ soap_init(struct soap *soap) 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 */ + soap->client_addr = NULL; /* client address (IPv4 or IPv6 or host name) to bind before connect, NULL for none */ + soap->client_addr_ipv6 = NULL; /* client address IPv6 or host name to bind before connect, NULL for none */ + soap->client_port = -1; /* client port to bind before connect, -1 for none */ + soap->client_interface = NULL; /* client interface address, NULL for none */ #ifndef WITH_IPV6 soap->fresolve = tcp_gethost; #else @@ -6655,14 +12690,24 @@ soap_init(struct soap *soap) #endif soap->fseterror = NULL; soap->fignore = NULL; + soap->fencoding = NULL; soap->fserveloop = NULL; soap->fplugin = fplugin; - soap->fmalloc = NULL; #ifndef WITH_LEANER - soap->fprepareinit = NULL; + soap->fsvalidate = NULL; + soap->fwvalidate = NULL; + soap->feltbegin = NULL; + soap->feltendin = NULL; + soap->feltbegout = NULL; + soap->feltendout = NULL; + soap->fprepareinitsend = NULL; + soap->fprepareinitrecv = NULL; soap->fpreparesend = NULL; soap->fpreparerecv = NULL; - soap->fpreparefinal = NULL; + soap->fpreparefinalsend = NULL; + soap->fpreparefinalrecv = NULL; + soap->ffiltersend = NULL; + soap->ffilterrecv = NULL; soap->fdimereadopen = NULL; soap->fdimewriteopen = NULL; soap->fdimereadclose = NULL; @@ -6678,10 +12723,41 @@ soap_init(struct soap *soap) #endif soap->float_format = "%.9G"; /* Alternative: use "%G" */ soap->double_format = "%.17lG"; /* Alternative: use "%lG" */ - soap->dime_id_format = "cid:id%d"; /* default DIME id format */ + soap->long_double_format = NULL; /* Defined in custom serializer custom/long_double.c */ + soap->dime_id_format = "cid:id%d"; /* default DIME id format for int id index */ + soap->recv_maxlength = 0x7FFFFFFF; /* default max length of messages received (2GB) */ + soap->recv_timeout = 0; + soap->send_timeout = 0; + soap->transfer_timeout = 0; + soap->connect_timeout = 0; + soap->accept_timeout = 0; + soap->socket_flags = 0; + soap->connect_flags = 0; + soap->connect_retry = 0; + soap->bind_flags = 0; +#ifdef WITH_IPV6_V6ONLY + soap->bind_inet6 = 1; + soap->bind_v6only = 1; +#else + soap->bind_inet6 = 0; + soap->bind_v6only = 0; +#endif + soap->accept_flags = 0; +#ifdef WIN32 + soap->sndbuf = SOAP_BUFLEN + 1; /* this size speeds up windows xfer */ + soap->rcvbuf = SOAP_BUFLEN + 1; +#else + soap->sndbuf = SOAP_BUFLEN; + soap->rcvbuf = SOAP_BUFLEN; +#endif + soap->linger_time = 0; + soap->maxlevel = SOAP_MAXLEVEL; + soap->maxlength = SOAP_MAXLENGTH; + soap->maxoccurs = SOAP_MAXOCCURS; soap->http_version = "1.1"; soap->proxy_http_version = "1.0"; soap->http_content = NULL; + soap->http_extra_header = NULL; soap->actor = NULL; soap->lang = "en"; soap->keep_alive = 0; @@ -6690,20 +12766,15 @@ soap_init(struct soap *soap) soap->tcp_keep_intvl = 0; soap->tcp_keep_cnt = 0; soap->max_keep_alive = SOAP_MAXKEEPALIVE; - soap->recv_timeout = 0; - soap->send_timeout = 0; - soap->connect_timeout = 0; - soap->accept_timeout = 0; - soap->socket_flags = 0; - soap->connect_flags = 0; - soap->bind_flags = 0; - soap->accept_flags = 0; - soap->linger_time = 0; soap->ip = 0; + soap->ip6[0] = 0; + soap->ip6[1] = 0; + soap->ip6[2] = 0; + soap->ip6[3] = 0; soap->labbuf = NULL; soap->lablen = 0; soap->labidx = 0; - soap->encodingStyle = SOAP_STR_EOS; + soap->encodingStyle = NULL; #ifndef WITH_NONAMESPACES soap->namespaces = namespaces; #else @@ -6714,11 +12785,14 @@ soap_init(struct soap *soap) soap->blist = NULL; soap->clist = NULL; soap->alist = NULL; + soap->shaky = 0; soap->attributes = NULL; soap->header = NULL; soap->fault = NULL; soap->master = SOAP_INVALID_SOCKET; soap->socket = SOAP_INVALID_SOCKET; + soap->sendsk = SOAP_INVALID_SOCKET; + soap->recvsk = SOAP_INVALID_SOCKET; soap->os = NULL; soap->is = NULL; #ifndef WITH_LEANER @@ -6740,31 +12814,46 @@ soap_init(struct soap *soap) soap->recvfd = stdin; soap->sendfd = stdout; #endif + soap->tag[0] = '\0'; + soap->id[0] = '\0'; + soap->href[0] = '\0'; + soap->type[0] = '\0'; + soap->arrayType[0] = '\0'; + soap->arraySize[0] = '\0'; + soap->arrayOffset[0] = '\0'; + soap->endpoint[0] = '\0'; soap->host[0] = '\0'; + soap->path[0] = '\0'; soap->port = 0; + soap->override_host = NULL; + soap->override_port = 0; soap->action = NULL; soap->proxy_host = NULL; soap->proxy_port = 8080; soap->proxy_userid = NULL; soap->proxy_passwd = NULL; - soap->authrealm = NULL; - soap->prolog = NULL; -#ifdef WITH_ZLIB + soap->proxy_from = NULL; + soap->origin = NULL; + soap->cors_origin = NULL; + soap->cors_allow = "*"; + soap->cors_method = NULL; + soap->cors_header = NULL; + soap->cors_methods = NULL; + soap->cors_headers = NULL; + soap->x_frame_options = "SAMEORIGIN"; + soap->prolog = "\n"; soap->zlib_state = SOAP_ZLIB_NONE; soap->zlib_in = SOAP_ZLIB_NONE; soap->zlib_out = SOAP_ZLIB_NONE; - soap->d_stream = (z_stream*)SOAP_MALLOC(soap, sizeof(z_stream)); - soap->d_stream->zalloc = Z_NULL; - soap->d_stream->zfree = Z_NULL; - soap->d_stream->opaque = Z_NULL; + soap->d_stream = NULL; soap->z_buf = NULL; soap->z_level = 6; soap->z_dict = NULL; soap->z_dict_len = 0; -#endif #ifndef WITH_LEAN - soap->c14ninclude = NULL; + soap->wsuid = NULL; soap->c14nexclude = NULL; + soap->c14ninclude = NULL; soap->cookies = NULL; soap->cookie_domain = NULL; soap->cookie_path = NULL; @@ -6773,133 +12862,234 @@ soap_init(struct soap *soap) #ifdef WMW_RPM_IO soap->rpmreqid = NULL; #endif -#ifdef PALM - palmNetLibOpen(); -#endif #ifndef WITH_NOIDREF soap_init_iht(soap); - soap_init_pht(soap); #endif + soap_init_pht(soap); #ifdef WITH_OPENSSL if (!soap_ssl_init_done) - { soap_ssl_init(); - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing OpenSSL, version=%ld\n", (long)OPENSSL_VERSION_NUMBER)); - } + soap_ssl_init(); soap->fsslauth = ssl_auth_init; - soap->fsslverify = ssl_verify_callback; + soap->fsslverify = NULL; soap->bio = NULL; soap->ssl = NULL; soap->ctx = NULL; + soap->session = NULL; + soap->dhfile = NULL; + soap->randfile = NULL; + soap->session_host[0] = '\0'; + soap->session_port = 443; soap->ssl_flags = SOAP_SSL_DEFAULT; soap->keyfile = NULL; + soap->keyid = NULL; + soap->password = NULL; + soap->cafile = NULL; + soap->capath = NULL; + soap->crlfile = NULL; +#endif +#ifdef WITH_GNUTLS + if (!soap_ssl_init_done) + soap_ssl_init(); + soap->fsslauth = ssl_auth_init; + soap->fsslverify = NULL; + soap->xcred = NULL; + soap->acred = NULL; + soap->cache = NULL; + soap->session = NULL; + soap->dh_params = NULL; + soap->rsa_params = NULL; + soap->ssl_flags = SOAP_SSL_DEFAULT; + soap->keyfile = NULL; + soap->keyid = NULL; soap->password = NULL; - soap->dhfile = NULL; soap->cafile = NULL; soap->capath = NULL; soap->crlfile = NULL; +#endif +#ifdef WITH_WOLFSSL + if (!soap_ssl_init_done) + soap_ssl_init(); + soap->fsslauth = ssl_auth_init; + soap->fsslverify = NULL; + soap->ssl = NULL; + soap->ctx = NULL; + soap->session = NULL; + soap->dhfile = NULL; soap->randfile = NULL; + soap->ssl_flags = SOAP_SSL_DEFAULT; + soap->keyfile = NULL; + soap->keyid = NULL; + soap->password = NULL; + soap->cafile = NULL; + soap->capath = NULL; + soap->crlfile = NULL; +#endif +#ifdef WITH_SYSTEMSSL + soap->fsslauth = ssl_auth_init; + soap->fsslverify = NULL; + soap->bio = NULL; + soap->ssl = (gsk_handle)NULL; + soap->ctx = (gsk_handle)NULL; soap->session = NULL; + soap->ssl_flags = SOAP_SSL_DEFAULT; + soap->keyfile = NULL; + soap->keyid = NULL; + soap->password = NULL; + soap->cafile = NULL; + soap->capath = NULL; + soap->crlfile = NULL; + soap->dhfile = NULL; + soap->randfile = NULL; #endif -#ifdef WITH_C_LOCALE - soap->c_locale = newlocale(LC_ALL_MASK, "C", NULL); -#else soap->c_locale = NULL; + soap->buflen = 0; + soap->bufidx = 0; +#ifndef WITH_LEANER + soap->dime.chunksize = 0; + soap->dime.buflen = 0; #endif - soap_begin(soap); -} -#endif - -/******************************************************************************/ -#ifndef PALM_1 -SOAP_FMAC1 -void -SOAP_FMAC2 -soap_init1(struct soap *soap, soap_mode mode) -{ soap_init2(soap, mode, mode); + soap->other = 0; + soap->root = -1; + soap->null = 0; + soap->position = 0; + soap->encoding = 0; + soap->mustUnderstand = 0; + soap->ns = 0; + soap->part = SOAP_END; + soap->event = 0; + soap->evlev = 0; + soap->alloced = 0; + soap->count = 0; + soap->length = 0; + soap->cdata = 0; + soap->peeked = 0; + soap->ahead = 0; + soap->idnum = 0; + soap->level = 0; + soap->status = 0; + soap->error = SOAP_OK; + soap->errmode = 0; + soap->errnum = 0; } -#endif /******************************************************************************/ -#ifndef PALM_1 -SOAP_FMAC1 -void -SOAP_FMAC2 -soap_init2(struct soap *soap, soap_mode imode, soap_mode omode) -{ soap_init(soap); - soap_imode(soap, imode); - soap_omode(soap, omode); -} -#endif -/******************************************************************************/ -#ifndef PALM_2 SOAP_FMAC1 void SOAP_FMAC2 soap_begin(struct soap *soap) -{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reinitializing context\n")); +{ + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Clean up for input/output\n")); + soap->error = SOAP_OK; if (!soap->keep_alive) - { soap->buflen = 0; + { + soap->buflen = 0; soap->bufidx = 0; } - soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0); - soap->null = 0; - soap->position = 0; soap->encoding = 0; - soap->mustUnderstand = 0; soap->mode = 0; - soap->ns = 0; soap->part = SOAP_END; - soap->alloced = 0; - soap->count = 0; - soap->length = 0; - soap->cdata = 0; - soap->error = SOAP_OK; soap->peeked = 0; soap->ahead = 0; - soap->idnum = 0; soap->level = 0; - soap->endpoint[0] = '\0'; -#ifndef WITH_LEANER - soap->dime.chunksize = 0; - soap->dime.buflen = 0; -#endif + soap->encodingStyle = SOAP_STR_EOS; soap_free_temp(soap); } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 void SOAP_FMAC2 soap_end(struct soap *soap) -{ if (soap_check_state(soap)) +{ + if (soap_check_state(soap)) return; soap_free_temp(soap); soap_dealloc(soap, NULL); while (soap->clist) - { struct soap_clist *cp = soap->clist->next; + { + struct soap_clist *cp = soap->clist->next; SOAP_FREE(soap, soap->clist); soap->clist = cp; } - soap_closesock(soap); + (void)soap_closesock(soap); #ifdef SOAP_DEBUG soap_close_logfiles(soap); #endif -#ifdef PALM - palmNetLibClose(); -#endif } -#endif /******************************************************************************/ -#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 && soap->local_namespaces && soap->local_namespaces[0].id && soap->local_namespaces[1].id) + { + 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; + } + if (version == 0) + soap->encodingStyle = SOAP_STR_EOS; + else + soap->encodingStyle = NULL; +} + +/******************************************************************************/ + +static void +soap_version(struct soap *soap) +{ + struct Namespace *p = soap->local_namespaces; + if (p) + { + const char *ns = p[0].out; + if (!ns) + ns = p[0].ns; + if (ns) + { + if (!strcmp(ns, soap_env1)) + { + soap->version = 1; /* make sure we use SOAP 1.1 */ + if (p[1].out) + SOAP_FREE(soap, p[1].out); + p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc1)); + if (p[1].out) + (void)soap_memcpy(p[1].out, sizeof(soap_enc1), soap_enc1, sizeof(soap_enc1)); + } + else if (!strcmp(ns, soap_env2)) + { + soap->version = 2; /* make sure we use SOAP 1.2 */ + if (p[1].out) + SOAP_FREE(soap, p[1].out); + p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc2)); + if (p[1].out) + (void)soap_memcpy(p[1].out, sizeof(soap_enc2), soap_enc2, sizeof(soap_enc2)); + } + } + } +} + +/******************************************************************************/ + SOAP_FMAC1 int SOAP_FMAC2 soap_set_namespaces(struct soap *soap, const struct Namespace *p) -{ struct Namespace *ns = soap->local_namespaces; +{ + struct Namespace *ns = soap->local_namespaces; struct soap_nlist *np, *nq, *nr; unsigned int level = soap->level; soap->namespaces = p; @@ -6909,10 +13099,12 @@ soap_set_namespaces(struct soap *soap, const struct Namespace *p) np = soap->nlist; soap->nlist = NULL; if (np) - { nq = np->next; + { + nq = np->next; np->next = NULL; while (nq) - { nr = nq->next; + { + nr = nq->next; nq->next = np; np = nq; nq = nr; @@ -6920,25 +13112,30 @@ soap_set_namespaces(struct soap *soap, const struct Namespace *p) } /* then push on new stack */ while (np) - { const char *s; + { + const char *s; soap->level = np->level; /* preserve element nesting level */ s = np->ns; if (!s && np->index >= 0 && ns) - { s = ns[np->index].out; + { + s = ns[np->index].out; if (!s) s = ns[np->index].ns; } - if (s && soap_push_namespace(soap, np->id, s) == NULL) - return soap->error; + if (s) + (void)soap_push_namespace(soap, np->id, s); nq = np; np = np->next; SOAP_FREE(soap, nq); } if (ns) - { int i; + { + int i; for (i = 0; ns[i].id; i++) - { if (ns[i].out) - { SOAP_FREE(soap, ns[i].out); + { + if (ns[i].out) + { + SOAP_FREE(soap, ns[i].out); ns[i].out = NULL; } } @@ -6947,16 +13144,17 @@ soap_set_namespaces(struct soap *soap, const struct Namespace *p) soap->level = level; /* restore level */ return SOAP_OK; } -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 void SOAP_FMAC2 soap_set_local_namespaces(struct soap *soap) -{ if (soap->namespaces && !soap->local_namespaces) - { const struct Namespace *ns1; +{ + if (soap->namespaces && !soap->local_namespaces) + { + const struct Namespace *ns1; struct Namespace *ns2; size_t n = 1; for (ns1 = soap->namespaces; ns1->id; ns1++) @@ -6964,197 +13162,320 @@ soap_set_local_namespaces(struct soap *soap) n *= sizeof(struct Namespace); ns2 = (struct Namespace*)SOAP_MALLOC(soap, n); if (ns2) - { memcpy(ns2, soap->namespaces, n); + { + (void)soap_memcpy((void*)ns2, n, (const void*)soap->namespaces, n); if (ns2[0].ns) - { if (!strcmp(ns2[0].ns, soap_env1)) + { + 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; + for (; ns2->id; ns2++) + ns2->out = NULL; } } } -#endif /******************************************************************************/ + #ifndef WITH_LEAN -#ifndef PALM_1 SOAP_FMAC1 const char * SOAP_FMAC2 -soap_strsearch(const char *big, const char *little) -{ size_t n = strlen(little); - const char *s = big; - while (s) - { if (!strncmp(s, little, n) && (s[n] == '\0' || s[n] == ' ')) - return s; - s = strchr(s, ' '); - if (s) - s++; +soap_tagsearch(const char *big, const char *little) +{ + if (big && little) + { + size_t n = strlen(little); + const char *s = big; + while (s) + { + const char *t = s; + size_t i; + for (i = 0; i < n; i++, t++) + { + if (*t != little[i]) + break; + } + if (*t == '\0' || *t == ' ') + { + if (i == n || (i > 0 && little[i-1] == ':')) + return s; + } + s = strchr(t, ' '); + if (s) + s++; + } } return NULL; } #endif -#endif /******************************************************************************/ -#ifndef WITH_LEAN -#ifndef PALM_1 + SOAP_FMAC1 struct soap_nlist * SOAP_FMAC2 soap_lookup_ns(struct soap *soap, const char *tag, size_t n) -{ struct soap_nlist *np; +{ + struct soap_nlist *np; for (np = soap->nlist; np; np = np->next) - { if (!strncmp(np->id, tag, n) && !np->id[n]) + if (!strncmp(np->id, tag, n) && !np->id[n]) return np; - } return NULL; } -#endif -#endif /******************************************************************************/ + #ifndef WITH_LEAN static struct soap_nlist * -soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized) -{ struct soap_nlist *np; +soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized, short isearly) +{ + struct soap_nlist *np = NULL; size_t n, k; - if (soap_strsearch(soap->c14nexclude, id)) + unsigned int level = soap->level + isearly; + if (soap_tagsearch(soap->c14nexclude, id)) return NULL; if (!utilized) - { for (np = soap->nlist; np; np = np->next) - { if (!strcmp(np->id, id) && (!np->ns || !strcmp(np->ns, ns))) + { + for (np = soap->nlist; np; np = np->next) + { + if (!strcmp(np->id, id) && ((!np->ns && *id) || (ns && np->ns && !strcmp(np->ns, ns)))) break; } if (np) - { if ((np->level < soap->level || !np->ns) && np->index == 1) + { + if ((np->level < level || (!np->ns && *id)) && np->index == 1) utilized = 1; else return NULL; } } - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Adding namespace binding (level=%u) '%s' '%s' utilized=%d\n", soap->level, id, ns?ns:"(null)", utilized)); + else if (!*id) + { + for (np = soap->nlist; np; np = np->next) + { + if (!*np->id && np->level == level && np->index != 1) + return NULL; + } + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Adding namespace binding (level=%u) '%s' '%s' utilized=%d\n", level, id, ns ? ns : "(null)", utilized)); n = strlen(id); if (ns) - k = strlen(ns); + k = strlen(ns) + 1; else k = 0; - np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k + 1); + if (sizeof(struct soap_nlist) + n + k > n && (SOAP_MAXALLOCSIZE <= 0 || sizeof(struct soap_nlist) + n + k <= SOAP_MAXALLOCSIZE)) + np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k); if (!np) - { soap->error = SOAP_EOM; + { + soap->error = SOAP_EOM; return NULL; } np->next = soap->nlist; soap->nlist = np; - strcpy(np->id, id); + soap_strcpy((char*)np->id, n + 1, id); if (ns) - np->ns = strcpy(np->id + n + 1, ns); + { + np->ns = np->id + n + 1; + soap_strcpy((char*)np->ns, k, ns); + } else + { np->ns = NULL; - np->level = soap->level; + } + np->level = level; np->index = utilized; return np; } #endif /******************************************************************************/ + #ifndef WITH_LEAN static void -soap_utilize_ns(struct soap *soap, const char *tag, size_t n) -{ struct soap_nlist *np = soap_lookup_ns(soap, tag, n); - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Utilizing namespace of '%s'\n", tag)); +soap_utilize_ns(struct soap *soap, const char *tag, short isearly) +{ + struct soap_nlist *np; + size_t n = 0; + if (!strncmp(tag, "xmlns:", 6)) + { + tag += 6; + n = strlen(tag); + } + else + { + const char *t = strchr(tag, ':'); + if (t) + n = t - tag; + } + np = soap_lookup_ns(soap, tag, n); if (np) - { if (np->index == 0) - soap_push_ns(soap, np->id, np->ns, 1); + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Utilizing namespace '%s' of '%s' at level %u utilized=%d at level=%u\n", np->ns ? np->ns : "", tag, soap->level + isearly, np->index, np->level)); + if (np->index <= 0) + { + if (np->level == soap->level + isearly) + np->index = 1; + else + (void)soap_push_ns(soap, np->id, np->ns, 1, isearly); + } } else if (strncmp(tag, "xml", 3)) - { strncpy(soap->tmpbuf, tag, n); - soap->tmpbuf[n] = '\0'; - soap_push_ns(soap, soap->tmpbuf, NULL, 1); + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Utilizing default namespace of '%s' at level %u\n", tag, soap->level + isearly)); + (void)soap_strncpy(soap->tag, sizeof(soap->tag), tag, n); + (void)soap_push_ns(soap, soap->tag, NULL, 1, isearly); } } #endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 soap_element(struct soap *soap, const char *tag, int id, const char *type) { +#ifndef WITH_LEAN const char *s; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element begin tag='%s' id='%d' type='%s'\n", tag, id, type?type:SOAP_STR_EOS)); -#ifdef WITH_DOM - if (soap->part == SOAP_BEGIN_SECURITY && (soap->mode & SOAP_XML_CANONICAL) && !(soap->mode & SOAP_DOM_ASIS)) - { struct soap_nlist *np; - /* wsu:Id found: clear xmlns renderings, so re-emit them for exc-c14n */ - for (np = soap->nlist; np; np = np->next) - { if (np->index == 2) - np->index = 0; +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element begin tag='%s' level='%u' id='%d' type='%s'\n", tag, soap->level, id, type ? type : SOAP_STR_EOS)); +#ifndef WITH_LEAN + if (soap_tagsearch(soap->wsuid, tag)) + { + size_t i; + for (s = tag, i = 0; *s && i < sizeof(soap->href) - 1; s++, i++) + soap->href[i] = *s == ':' ? '-' : *s; + soap->href[i] = '\0'; + if (soap_set_attr(soap, "wsu:Id", soap->href, 1)) + return soap->error; + } +#endif + soap->level++; + if (soap->level > soap->maxlevel) + return soap->error = SOAP_LEVEL; +#ifndef WITH_LEAN + if ((soap->mode & SOAP_XML_CANONICAL) && !(soap->mode & SOAP_DOM_ASIS)) + { + if (soap->evlev >= soap->level) + soap->evlev = 0; + if (soap->event == SOAP_SEC_BEGIN && !soap->evlev) + { + struct soap_nlist *np; + /* non-nested wsu:Id found: clear xmlns, re-emit them for exc-c14n */ + for (np = soap->nlist; np; np = np->next) + { + int p = soap->c14ninclude ? *soap->c14ninclude == '+' || soap_tagsearch(soap->c14ninclude, np->id) != NULL : 0; + if (np->index == 2 || p) + { + struct soap_nlist *np1 = soap_push_ns(soap, np->id, np->ns, 1, 0); + if (np1 && !p) + np1->index = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reset binding %s='%s' utilized=%d to utilized=%d\n", np->id, np->ns ? np->ns : SOAP_STR_EOS, np->index, np1 ? np1->index : np->index)); + } + } + soap->evlev = soap->level; } } - if (soap->mode & SOAP_XML_DOM) - { struct soap_dom_element *elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element)); +#endif +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM)) + { + struct soap_dom_element *elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element)); if (!elt) - return soap->error; + return soap->error = SOAP_EOM; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Adding DOM element tag='%s' %p (parent='%s' %p)\n", tag, elt, soap->dom ? soap->dom->name : "(null)", soap->dom)); elt->soap = soap; elt->next = NULL; elt->prnt = soap->dom; - elt->name = soap_strdup(soap, tag); elt->elts = NULL; elt->atts = NULL; elt->nstr = NULL; - elt->data = NULL; - elt->wide = NULL; + elt->name = soap_strdup(soap, tag); + elt->lead = NULL; + elt->text = NULL; + elt->code = NULL; + elt->tail = NULL; elt->node = NULL; elt->type = 0; - elt->head = NULL; - elt->tail = NULL; if (soap->dom) - { struct soap_dom_element *p = soap->dom->elts; + { + struct soap_dom_element *p = soap->dom->elts; if (p) - { while (p->next) + { + while (p->next) p = p->next; p->next = elt; } else + { soap->dom->elts = elt; + } } soap->dom = elt; + if (!elt->name) + return soap->error = SOAP_EOM; } else { #endif - soap->level++; #ifndef WITH_LEAN if (!soap->ns) - { if (!(soap->mode & SOAP_XML_CANONICAL) - && soap_send(soap, soap->prolog ? soap->prolog : "\n")) + { + if (!(soap->mode & SOAP_XML_CANONICAL) && soap_send(soap, soap->prolog)) return soap->error; } - else if (soap->mode & SOAP_XML_INDENT) - { if (soap->ns == 1 && soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1)) + else if ((soap->mode & SOAP_XML_INDENT)) + { + if (soap->ns == 1 && soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1)) return soap->error; soap->body = 1; } - if ((soap->mode & SOAP_XML_DEFAULTNS) && (s = strchr(tag, ':'))) - { struct Namespace *ns = soap->local_namespaces; - size_t n = s - tag; + if ((soap->mode & SOAP_XML_DEFAULTNS)) + { + size_t n = 0; + s = strchr(tag, ':'); + if (s) + { + n = s++ - tag; + if (type && !strncmp(type, tag, n + 1)) + type += n + 1; + } + else + { + s = tag; + } if (soap_send_raw(soap, "<", 1) - || soap_send(soap, s + 1)) + || soap_send(soap, s)) return soap->error; - if (soap->nlist && !strncmp(soap->nlist->id, tag, n) && !soap->nlist->id[n]) - ns = NULL; - for (; ns && ns->id; ns++) - { if (*ns->id && (ns->out || ns->ns) && !strncmp(ns->id, tag, n) && !ns->id[n]) - { soap_push_ns(soap, ns->id, ns->out ? ns->out : ns->ns, 0); - if (soap_attribute(soap, "xmlns", ns->out ? ns->out : ns->ns)) - return soap->error; - break; + if (n) + { + struct Namespace *ns = soap->local_namespaces; + for (; ns && ns->id; ns++) + { + if (*ns->id && ns->ns && !strncmp(ns->id, tag, n) && !ns->id[n]) + { + if (!soap->nlist || *soap->nlist->id || (soap->nlist->ns && strcmp(soap->nlist->ns, ns->ns))) + { + (void)soap_push_ns(soap, SOAP_STR_EOS, ns->out ? ns->out : ns->ns, 0, 0); + if (soap_attribute(soap, "xmlns", ns->out ? ns->out : ns->ns)) + return soap->error; + } + break; + } } } +#ifndef WITH_NOEMPTYNAMESPACES + else if (!soap->nlist || *soap->nlist->id || (soap->nlist->ns && *soap->nlist->ns)) + { + (void)soap_push_ns(soap, SOAP_STR_EOS, SOAP_STR_EOS, 0, 0); + if (soap_attribute(soap, "xmlns", SOAP_STR_EOS)) + return soap->error; + } +#endif } else #endif @@ -7165,56 +13486,71 @@ soap_element(struct soap *soap, const char *tag, int id, const char *type) } #endif if (!soap->ns) - { struct Namespace *ns; - int k = -1; -#ifndef WITH_LEAN - if ((soap->mode & SOAP_XML_DEFAULTNS)) - k = 4; /* only produce the first four required 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)) + { + struct Namespace *ns = soap->local_namespaces; + for (; ns && ns->id; ns++) + { + const char *t = ns->out; + if (!t) + t = ns->ns; + if (*ns->id && t && *t) + { + (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), strlen(ns->id) + 6), "xmlns:%s", ns->id); + if (soap_attribute(soap, soap->tmpbuf, t)) return soap->error; } } } soap->ns = 1; /* namespace table control: ns = 0 or 2 to start, then 1 to stop dumping the table */ #ifndef WITH_LEAN - if (soap->mode & SOAP_XML_CANONICAL) - { const char *t = strchr(tag, ':'); - if (t) - soap_utilize_ns(soap, tag, t - tag); + if ((soap->mode & SOAP_XML_CANONICAL)) + { + if ((soap->mode & SOAP_XML_DEFAULTNS)) + soap_utilize_ns(soap, SOAP_STR_EOS, 0); + else + soap_utilize_ns(soap, tag, 0); } #endif if (id > 0) - { sprintf(soap->tmpbuf, "_%d", id); - if (soap_attribute(soap, "id", soap->tmpbuf)) + { + (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), sizeof(SOAP_BASEREFNAME) + 20), SOAP_BASEREFNAME "%d", id); + 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_SEC) || soap->part == SOAP_IN_BODY)) - { if (soap_attribute(soap, "xsi:type", type)) - return soap->error; + if (type && *type && !(soap->mode & SOAP_XML_NOTYPE)) + { #ifndef WITH_LEAN - if (soap->mode & SOAP_XML_CANONICAL) - { const char *t = strchr(type, ':'); - if (t) - soap_utilize_ns(soap, type, t - type); - } + if ((soap->mode & SOAP_XML_CANONICAL) && !(soap->mode & SOAP_XML_CANONICAL_NA)) + soap_utilize_ns(soap, type, 0); #endif + if (soap_attribute(soap, "xsi:type", type)) + return soap->error; } - if (soap->null && soap->position > 0) - { int i; - sprintf(soap->tmpbuf, "[%d", soap->positions[0]); + if (soap->null && soap->position > 0 && soap->version == 1) + { + int i; + (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf) - 1, 20), "[%d", soap->positions[0]); for (i = 1; i < soap->position; i++) - sprintf(soap->tmpbuf + strlen(soap->tmpbuf), ",%d", soap->positions[i]); - strcat(soap->tmpbuf, "]"); + { + size_t l = strlen(soap->tmpbuf); + (SOAP_SNPRINTF(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l - 1, 20), ",%d", soap->positions[i]); + } + soap_strcat(soap->tmpbuf, sizeof(soap->tmpbuf), "]"); if (soap_attribute(soap, "SOAP-ENC:position", soap->tmpbuf)) return soap->error; } if (soap->mustUnderstand) - { if (soap->actor && *soap->actor) - { if (soap_attribute(soap, soap->version == 2 ? "SOAP-ENV:role" : "SOAP-ENV:actor", soap->actor)) + { + if (soap->actor && *soap->actor) + { + if (soap_attribute(soap, soap->version == 2 ? "SOAP-ENV:role" : "SOAP-ENV:actor", soap->actor)) return soap->error; } if (soap_attribute(soap, "SOAP-ENV:mustUnderstand", soap->version == 2 ? "true" : "1")) @@ -7222,9 +13558,12 @@ 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) - { if (soap->local_namespaces[1].out) + { + 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; else soap->encodingStyle = soap->local_namespaces[1].ns; @@ -7232,84 +13571,274 @@ 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; soap->position = 0; - if (soap->part == SOAP_BEGIN_SECURITY && (soap->mode & SOAP_XML_CANONICAL)) - soap->part = SOAP_IN_SECURITY; return SOAP_OK; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 soap_element_begin_out(struct soap *soap, const char *tag, int id, const char *type) -{ if (*tag == '-') +{ + if (*tag == '-') return SOAP_OK; +#ifdef WITH_DOM + if (soap->feltbegout) + return soap->error = soap->feltbegout(soap, tag, id, type); +#endif if (soap_element(soap, tag, id, type)) return soap->error; return soap_element_start_end_out(soap, NULL); } + +/******************************************************************************/ + +#if _MSC_VER < 1400 && !defined(HAVE_STRLCAT) +/* concat string (truncating the result, strings must not be NULL) */ +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_strcat(char *t, size_t n, const char *s) +{ + size_t k = strlen(t); + if (k < n) + { + t += k; + n -= k; + while (n-- > 1 && *s) + *t++ = *s++; + *t = '\0'; + } +} +#endif + +/******************************************************************************/ + +#if _MSC_VER < 1400 +/* concat string up to m chars (leaves destination intact on overrun and returns nonzero, zero if OK) */ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_strncat(char *t, size_t n, const char *s, size_t m) +{ + size_t k; + if (!t || !s) + return 1; + k = strlen(t); + if (n <= k + m) + return 1; + t += k; + n -= k; + while (n-- > 1 && *s) + *t++ = *s++; + *t = '\0'; + return 0; +} #endif /******************************************************************************/ -#ifndef PALM_2 + #ifndef HAVE_STRRCHR SOAP_FMAC1 char* SOAP_FMAC2 soap_strrchr(const char *s, int t) -{ char *r = NULL; +{ + char *r = NULL; while (*s) if (*s++ == t) r = (char*)s - 1; return r; } #endif -#endif /******************************************************************************/ -#ifndef PALM_2 + #ifndef HAVE_STRTOL SOAP_FMAC1 long SOAP_FMAC2 soap_strtol(const char *s, char **t, int b) -{ long n = 0; +{ + long n = 0; + int c; + while (*s > 0 && *s <= 32) + s++; + if (b == 10) + { + short neg = 0; + if (*s == '-') + { + s++; + neg = 1; + } + else if (*s == '+') + { + s++; + } + while ((c = *s) && c >= '0' && c <= '9') + { + if (n >= 214748364 && (n > 214748364 || c >= '8')) + { + if (neg && n == 214748364 && c == '8') + { + if (t) + *t = (char*)(s + 1); + return -2147483648; + } + break; + } + n *= 10; + n += c - '0'; + s++; + } + if (neg) + n = -n; + } + else /* assume b == 16 and value is always positive */ + { + while ((c = *s)) + { + if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'F') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'f') + c -= 'a' - 10; + if (n > 0x07FFFFFF) + break; + n <<= 4; + n += c; + s++; + } + } + if (t) + *t = (char*)s; + return n; +} +#endif + +/******************************************************************************/ + +#ifndef HAVE_STRTOUL +SOAP_FMAC1 +unsigned long +SOAP_FMAC2 +soap_strtoul(const char *s, char **t, int b) +{ + unsigned long n = 0; + int c; + while (*s > 0 && *s <= 32) + s++; + if (b == 10) + { + short neg = 0; + if (*s == '-') + { + s++; + neg = 1; + } + else if (*s == '+') + { + s++; + } + while ((c = *s) && c >= '0' && c <= '9') + { + if (n >= 429496729 && (n > 429496729 || c >= '6')) + break; + n *= 10; + n += c - '0'; + s++; + } + if (neg && n > 0) + s--; + } + else /* b == 16 */ + { + while ((c = *s)) + { + if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'F') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'f') + c -= 'a' - 10; + if (n > 0x0FFFFFFF) + break; + n <<= 4; + n += c; + s++; + } + } + if (t) + *t = (char*)s; + return n; +} +#endif + +/******************************************************************************/ + +#ifndef soap_strtoll +SOAP_FMAC1 +LONG64 +SOAP_FMAC2 +soap_strtoll(const char *s, char **t, int b) +{ + LONG64 n = 0LL; int c; while (*s > 0 && *s <= 32) s++; if (b == 10) - { short neg = 0; + { + short neg = 0; if (*s == '-') - { s++; + { + s++; neg = 1; } else if (*s == '+') + { s++; + } while ((c = *s) && c >= '0' && c <= '9') - { if (n >= 214748364 && (n > 214748364 || c >= '8')) + { + if (n >= 922337203685477580LL && (n > 922337203685477580LL || c >= '8')) + { + if (neg && n == 922337203685477580LL && c == '8') + { + if (t) + *t = (char*)(s + 1); + return -9223372036854775807LL - 1LL; /* appease compilers that complain */ + } break; - n *= 10; + } + n *= 10LL; n += c - '0'; s++; } if (neg) n = -n; } - else /* b == 16 and value is always positive */ - { while ((c = *s)) - { if (c >= '0' && c <= '9') + else /* assume b == 16 and value is always positive */ + { + while ((c = *s)) + { + if (c >= '0' && c <= '9') c -= '0'; else if (c >= 'A' && c <= 'F') c -= 'A' - 10; else if (c >= 'a' && c <= 'f') c -= 'a' - 10; - if (n > 0x07FFFFFF) + if (n > 0x07FFFFFFFFFFFFFFLL) break; n <<= 4; n += c; @@ -7321,39 +13850,53 @@ soap_strtol(const char *s, char **t, int b) return n; } #endif -#endif /******************************************************************************/ -#ifndef PALM_2 -#ifndef HAVE_STRTOUL + +#ifndef soap_strtoull SOAP_FMAC1 -unsigned long +ULONG64 SOAP_FMAC2 -soap_strtoul(const char *s, char **t, int b) -{ unsigned long n = 0; +soap_strtoull(const char *s, char **t, int b) +{ + ULONG64 n = 0UL; int c; while (*s > 0 && *s <= 32) s++; if (b == 10) - { if (*s == '+') + { + short neg = 0; + if (*s == '-') + { + s++; + neg = 1; + } + else if (*s == '+') + { s++; + } while ((c = *s) && c >= '0' && c <= '9') - { if (n >= 429496729 && (n > 429496729 || c >= '6')) + { + if (n >= 1844674407370955161ULL && (n > 1844674407370955161ULL || c >= '6')) break; - n *= 10; + n *= 10UL; n += c - '0'; s++; } + if (neg && n > 0UL) + s--; } else /* b == 16 */ - { while ((c = *s)) - { if (c >= '0' && c <= '9') + { + while ((c = *s)) + { + if (c >= '0' && c <= '9') c -= '0'; else if (c >= 'A' && c <= 'F') c -= 'A' - 10; else if (c >= 'a' && c <= 'f') c -= 'a' - 10; - if (n > 0x0FFFFFFF) + if (n > 0x0FFFFFFFFFFFFFFFULL) break; n <<= 4; n += c; @@ -7365,89 +13908,118 @@ soap_strtoul(const char *s, char **t, int b) return n; } #endif -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 int SOAP_FMAC2 soap_array_begin_out(struct soap *soap, const char *tag, int id, const char *type, const char *offset) -{ if (!type || !*type) +{ + if (!type || !*type || soap->version == 0) return soap_element_begin_out(soap, tag, id, NULL); - if (soap_element(soap, tag, id, "SOAP-ENC:Array")) + if (soap_element(soap, tag, id, NULL)) return soap->error; - if (soap->version == 2) - { const char *s; - s = soap_strrchr(type, '['); - if ((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; - } - } - else - { if (offset && soap_attribute(soap, "SOAP-ENC:offset", offset)) + if (soap->version == 1) + { + if (offset && soap_attribute(soap, "SOAP-ENC:offset", offset)) return soap->error; if (soap_attribute(soap, "SOAP-ENC:arrayType", type)) return soap->error; } -#ifndef WITH_LEAN - if ((soap->mode & SOAP_XML_CANONICAL)) - { const char *s = strchr(type, ':'); - if (s) - soap_utilize_ns(soap, type, s - type); + else + { + const char *s; + s = strchr(type, '['); + if (s && (size_t)(s - type) < sizeof(soap->tmpbuf)) + { + (void)soap_strncpy(soap->tmpbuf, sizeof(soap->tmpbuf), type, s - type); + if (soap_attribute(soap, "SOAP-ENC:itemType", soap->tmpbuf)) + return soap->error; + s++; + if (*s && *s != ']') + { + soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), s); + soap->tmpbuf[strlen(soap->tmpbuf) - 1] = '\0'; + if (soap_attribute(soap, "SOAP-ENC:arraySize", soap->tmpbuf)) + return soap->error; + } + } } +#ifndef WITH_LEAN + if ((soap->mode & SOAP_XML_CANONICAL) && !(soap->mode & SOAP_XML_CANONICAL_NA)) + soap_utilize_ns(soap, type, 0); #endif return soap_element_start_end_out(soap, NULL); } -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 int SOAP_FMAC2 soap_element_start_end_out(struct soap *soap, const char *tag) -{ struct soap_attribute *tp; +{ + struct soap_attribute *tp; #ifndef WITH_LEAN - if (soap->mode & SOAP_XML_CANONICAL) - { struct soap_nlist *np; + if ((soap->mode & SOAP_XML_CANONICAL)) + { + struct soap_nlist *np; for (tp = soap->attributes; tp; tp = tp->next) - { if (tp->visible && tp->name) - { const char *s = strchr(tp->name, ':'); - if (s) - soap_utilize_ns(soap, tp->name, s - tp->name); - } + { + if (tp->visible && *tp->name && strchr(tp->name, ':')) + soap_utilize_ns(soap, tp->name, 0); + } + if (soap->event == SOAP_SEC_BEGIN) + { + for (np = soap->nlist; np; np = np->next) + if (soap_tagsearch(soap->c14ninclude, np->id)) + (void)soap_push_ns(soap, np->id, np->ns, 1, 0); + soap->event = 0; + soap->evlev = 0; } for (np = soap->nlist; np; np = np->next) - { if (np->index == 1 && np->ns) - { sprintf(soap->tmpbuf, "xmlns:%s", np->id); - 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); + { + if (np->ns && np->index == 1) + { + if (*np->id) + (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), strlen(np->id) + 6), "xmlns:%s", np->id); + else + soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), "xmlns"); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enabling utilized binding (level=%u) %s='%s' SEC-BEGIN=%d c14ninclude='%s'\n", np->level, soap->tmpbuf, np->ns, soap->event == SOAP_SEC_BEGIN, soap->c14ninclude ? soap->c14ninclude : "(null)")); np->index = 2; + soap->level--; + if (*np->id || *np->ns || soap->level > 1) + if (soap_set_attr(soap, soap->tmpbuf, np->ns, 1)) + return soap->error; + soap->level++; + } + else + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Binding (level=%u) %s='%s' utilized=%d\n", np->level, np->id, np->ns ? np->ns : SOAP_STR_EOS, np->index)); } } } #endif #ifdef WITH_DOM if ((soap->mode & SOAP_XML_DOM) && soap->dom) - { struct soap_dom_attribute **att; + { + struct soap_dom_attribute **att; att = &soap->dom->atts; for (tp = soap->attributes; tp; tp = tp->next) - { if (tp->visible) - { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); + { + if (tp->visible) + { + *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); if (!*att) return soap->error; (*att)->next = NULL; (*att)->nstr = NULL; (*att)->name = soap_strdup(soap, tp->name); - (*att)->data = soap_strdup(soap, tp->value); - (*att)->wide = NULL; + (*att)->text = soap_strdup(soap, tp->value); (*att)->soap = soap; + if (!(*att)->name || (tp->value && !(*att)->text)) + return soap->error = SOAP_EOM; att = &(*att)->next; tp->visible = 0; } @@ -7456,189 +14028,359 @@ soap_element_start_end_out(struct soap *soap, const char *tag) } #endif for (tp = soap->attributes; tp; tp = tp->next) - { if (tp->visible) - { const char *s; -#ifndef WITH_LEAN - if ((soap->mode & SOAP_XML_DEFAULTNS) && (s = strchr(tp->name, ':'))) - { size_t n = s - tp->name; - if (soap->nlist && !strncmp(soap->nlist->id, tp->name, n) && !soap->nlist->id[n]) - s++; - else - s = tp->name; - if (soap_send(soap, " ") || soap_send(soap, s)) - return soap->error; - } - else -#endif - if (soap_send(soap, " ") || soap_send(soap, tp->name)) + { + if (tp->visible) + { + if (soap_send_raw(soap, " ", 1) || soap_send(soap, tp->name)) return soap->error; if (tp->visible == 2 && tp->value) + { if (soap_send_raw(soap, "=\"", 2) - || soap_string_out(soap, tp->value, 1) + || soap_string_out(soap, tp->value, tp->flag) || soap_send_raw(soap, "\"", 1)) return soap->error; + } + else + { + if (soap_send_raw(soap, "=\"\"", 3)) + return soap->error; + } tp->visible = 0; } } if (tag) { #ifndef WITH_LEAN - if (soap->mode & SOAP_XML_CANONICAL) - { if (soap_send_raw(soap, ">", 1) + if ((soap->mode & SOAP_XML_CANONICAL)) + { + if (soap_send_raw(soap, ">", 1) || soap_element_end_out(soap, tag)) return soap->error; return SOAP_OK; } #endif - soap->level--; /* decrement level just before /> */ - if (soap_send_raw(soap, "/>", 2)) - return soap->error; - return SOAP_OK; + if (soap->nlist) + soap_pop_namespace(soap); + soap->level--; /* decrement level just before /> */ + soap->body = 0; + return soap_send_raw(soap, "/>", 2); } return soap_send_raw(soap, ">", 1); } -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 int SOAP_FMAC2 soap_element_end_out(struct soap *soap, const char *tag) -{ const char *s; +{ if (*tag == '-') return SOAP_OK; +#ifdef WITH_DOM + if (soap->feltendout) + return soap->error = soap->feltendout(soap, tag); +#endif + return soap_element_end(soap, tag); +} + +/******************************************************************************/ + +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_end(struct soap *soap, const char *tag) +{ +#ifndef WITH_LEAN + const char *s; +#endif DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element ending tag='%s'\n", tag)); #ifdef WITH_DOM if ((soap->mode & SOAP_XML_DOM) && soap->dom) - { if (soap->dom->prnt) + { + if (soap->dom->prnt) soap->dom = soap->dom->prnt; return SOAP_OK; } #endif #ifndef WITH_LEAN - if (soap->mode & SOAP_XML_CANONICAL) + if (soap->nlist) soap_pop_namespace(soap); - if (soap->mode & SOAP_XML_INDENT) - { if (!soap->body) - { if (soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1)) + if ((soap->mode & SOAP_XML_INDENT)) + { + if (!soap->body) + { + if (soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1)) return soap->error; } soap->body = 0; } - if ((soap->mode & SOAP_XML_DEFAULTNS) && (s = strchr(tag, ':'))) - { soap_pop_namespace(soap); + if ((soap->mode & SOAP_XML_DEFAULTNS) && (s = strchr(tag, ':')) != NULL) tag = s + 1; - } #endif if (soap_send_raw(soap, "error; - soap->level--; /* decrement level just before > */ + soap->level--; /* decrement level just before > */ return soap_send_raw(soap, ">", 1); } -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 int SOAP_FMAC2 soap_element_ref(struct soap *soap, const char *tag, int id, int href) -{ int n = 0; - const char *s = "href"; - if (soap->version == 2) - { s = "SOAP-ENC:ref"; - n = 1; +{ + const char *s = "ref"; + int n = 1; + if (soap->version == 1) + { + s = "href"; + n = 0; + } + else if (soap->version == 2) + { + s = "SOAP-ENC:ref"; } - sprintf(soap->href, "#_%d", href); + (SOAP_SNPRINTF(soap->href, sizeof(soap->href), sizeof(SOAP_BASEREFNAME) + 21), "#" SOAP_BASEREFNAME "%d", href); return soap_element_href(soap, tag, id, s, soap->href + n); } -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 int SOAP_FMAC2 soap_element_href(struct soap *soap, const char *tag, int id, const char *ref, const char *val) -{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element '%s' reference %s='%s'\n", tag, ref, val)); +{ + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element '%s' reference %s='%s'\n", tag, ref, val)); if (soap_element(soap, tag, id, NULL) || soap_attribute(soap, ref, val) || soap_element_start_end_out(soap, tag)) return soap->error; + soap->body = 0; return SOAP_OK; } -#endif + /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 int SOAP_FMAC2 soap_element_null(struct soap *soap, const char *tag, int id, const char *type) -{ struct soap_attribute *tp; +{ + struct soap_attribute *tp = NULL; for (tp = soap->attributes; tp; tp = tp->next) if (tp->visible) break; if (tp || (soap->version == 2 && soap->position > 0) || id > 0 || (soap->mode & SOAP_XML_NIL)) - { if (soap_element(soap, tag, id, type)) - return soap->error; - if (!tp && soap_attribute(soap, "xsi:nil", "true")) + { + if (soap_element(soap, tag, id, type) + || (!tp && soap_attribute(soap, "xsi:nil", "true")) + || soap_element_start_end_out(soap, tag)) return soap->error; - return soap_element_start_end_out(soap, tag); + soap->body = 0; + } + else + { + soap->null = 1; + soap->position = 0; + soap->mustUnderstand = 0; } - soap->null = 1; - soap->position = 0; - soap->mustUnderstand = 0; return SOAP_OK; } -#endif /******************************************************************************/ -#ifndef PALM_1 + +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_empty(struct soap *soap, const char *tag, int id, const char *type) +{ + if (!tag || *tag == '-') + return SOAP_OK; +#ifdef WITH_DOM + if (soap->feltbegout) + return soap->error = soap->feltbegout(soap, tag, id, type); +#endif + if (soap_element(soap, tag, id, type)) + return soap->error; + return soap_element_start_end_out(soap, tag); +} + +/******************************************************************************/ + +SOAP_FMAC1 +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"))) + return soap->error; + return soap_element_start_end_out(soap, tag); +} + +/******************************************************************************/ + +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_id(struct soap *soap, const char *tag, int id, const void *p, const void *a, int n, const char *type, int t, char **mark) +{ + (void)a; (void)n; + if (!p) + { + soap->error = soap_element_null(soap, tag, id, type); + return -1; + } +#ifndef WITH_NOIDREF + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element_id %p type=%d id=%d\n", p, t, id)); + if ((!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH)) || (soap->mode & SOAP_XML_TREE)) + return soap_check_and_mark(soap, p, t, mark); + if (mark) + *mark = NULL; + if (id < -1) + return soap_embed(soap, p, a, n, t); + else if (id <= 0) + { + struct soap_plist *pp; + if (a) + id = soap_array_pointer_lookup(soap, p, a, n, t, &pp); + else + id = soap_pointer_lookup(soap, p, t, &pp); + if (id) + { + if (soap_is_embedded(soap, pp)) + { + soap_element_ref(soap, tag, 0, id); + return -1; + } + if (soap_is_single(soap, pp)) + return 0; + soap_set_embedded(soap, pp); + } + } + return id; +#else + return soap_check_and_mark(soap, p, t, mark); +#endif +} + +/******************************************************************************/ + +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_check_and_mark(struct soap *soap, const void *p, int t, char **mark) +{ + if (mark) + { + struct soap_plist *pp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Check %p and mark %p\n", p, (void*)mark)); + if (!soap_pointer_lookup(soap, p, t, &pp)) + if (!soap_pointer_enter(soap, p, NULL, 0, t, &pp)) + return -1; + if ((soap->mode & SOAP_IO_LENGTH)) + { + if (pp->mark1 > 0) + return -1; + pp->mark1 = 1; + *mark = &pp->mark1; + } + else + { + if (pp->mark2 > 0) + return -1; + pp->mark2 = 1; + *mark = &pp->mark2; + } + } + return 0; +} + +/******************************************************************************/ + +SOAP_FMAC1 +void * +SOAP_FMAC2 +soap_mark_lookup(struct soap *soap, const void *p, int t, struct soap_plist **ppp, char **mark) +{ + if (!soap) + return NULL; + if (mark || !(soap->mode & SOAP_XML_TREE)) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Mark lookup %p type=%d\n", p, t)); + if (!soap_pointer_lookup(soap, p, t, ppp)) + { + if (!soap_pointer_enter(soap, p, NULL, 0, t, ppp)) + return NULL; + } + else if (!(soap->mode & SOAP_XML_TREE)) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Mark found %p\n", (*ppp)->dup)); + return (*ppp)->dup; + } + if (mark) + { + if ((*ppp)->mark1 > 0) + (*ppp)->mark1 = 2; /* cycle */ + else + (*ppp)->mark1 = 1; /* cycle detection */ + *mark = &(*ppp)->mark1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Mark cycle %d\n", (*ppp)->mark1)); + } + } + return NULL; +} + +/******************************************************************************/ + +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_mark_cycle(struct soap *soap, struct soap_plist *pp) +{ + (void)soap; + return pp && pp->mark1 == 2 && (soap->mode & SOAP_XML_TREE); +} + +/******************************************************************************/ + +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_mark_dup(struct soap *soap, void *a, struct soap_plist *pp) +{ + (void)soap; + if (pp) + pp->dup = a; +} + +/******************************************************************************/ + SOAP_FMAC1 -int +void 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); - return -1; - } -#ifndef WITH_NOIDREF - if (soap->mode & SOAP_XML_TREE) - return 0; - if (id < 0) - { struct soap_plist *pp; - if (a) - id = soap_array_pointer_lookup(soap, p, a, n, t, &pp); - else - id = soap_pointer_lookup(soap, p, t, &pp); - if (id) - { if (soap_is_embedded(soap, pp)) - { soap_element_ref(soap, tag, 0, id); - return -1; - } - if (soap_is_single(soap, pp)) - return 0; - soap_set_embedded(soap, pp); - } - } - return id; -#else - return 0; -#endif +soap_unmark(struct soap *soap, char *mark) +{ + (void)soap; + if (mark) + *mark = 0; /* release detection */ } -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 int SOAP_FMAC2 soap_element_result(struct soap *soap, const char *tag) -{ if (soap->version == 2 && soap->encodingStyle) - { if (soap_element(soap, "SOAP-RPC:result", 0, NULL) +{ + if (soap->version == 2 && soap->encodingStyle) + { + if (soap_element(soap, "SOAP-RPC:result", 0, NULL) || soap_attribute(soap, "xmlns:SOAP-RPC", soap_rpc) || soap_element_start_end_out(soap, NULL) || soap_string_out(soap, tag, 0) @@ -7647,23 +14389,24 @@ soap_element_result(struct soap *soap, const char *tag) } return SOAP_OK; } -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 void SOAP_FMAC2 soap_check_result(struct soap *soap, const char *tag) -{ if (soap->version == 2 && soap->encodingStyle) - { soap_instring(soap, ":result", NULL, NULL, 0, 2, -1, -1); +{ + (void)tag; + if (soap->version == 2 && soap->encodingStyle) + { + soap_instring(soap, ":result", NULL, NULL, 0, 2, -1, -1, NULL); /* just ignore content for compliance reasons, but should compare tag to element's QName value? */ } } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 @@ -7672,37 +14415,46 @@ soap_attribute(struct soap *soap, const char *name, const char *value) DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attribute '%s'='%s'\n", name, value)); #ifdef WITH_DOM if ((soap->mode & SOAP_XML_DOM) && !(soap->mode & SOAP_XML_CANONICAL) && soap->dom) - { struct soap_dom_attribute *a = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); + { + struct soap_dom_attribute *a = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); if (!a) return soap->error; a->next = soap->dom->atts; a->nstr = NULL; a->name = soap_strdup(soap, name); - a->data = soap_strdup(soap, value); - a->wide = NULL; + a->text = soap_strdup(soap, value); a->soap = soap; soap->dom->atts = a; + if (!a->name || (value && !a->text)) + return soap->error = SOAP_EOM; return SOAP_OK; } #endif #ifndef WITH_LEAN - if (soap->mode & SOAP_XML_CANONICAL) - { /* TODO: consider using this code to handle default namespace bindings - if (!strncmp(name, "xmlns", 5) && (name[5] == ':' || name[5] == '\0')) - { if (name[5] == ':') - soap_push_ns(soap, name + 6, value, 0); - else - soap_push_ns(soap, "", value, 0); + if ((soap->mode & SOAP_XML_CANONICAL)) + { + /* push namespace */ + if (value && !strncmp(name, "xmlns", 5) && ((name[5] == ':') || name[5] == '\0')) + { + (void)soap_push_ns(soap, name + 5 + (name[5] == ':'), value, 0, 0); + if (name[5] == '\0') + soap_utilize_ns(soap, SOAP_STR_EOS, 0); + else if (soap->c14ninclude && ((*soap->c14ninclude == '*' || soap_tagsearch(soap->c14ninclude, name + 6)))) + soap_utilize_ns(soap, name, 0); + } + else + { + soap->level--; + if (soap_set_attr(soap, name, value, 1)) + return soap->error; + soap->level++; } - */ - if (!strncmp(name, "xmlns:", 6)) - soap_push_ns(soap, name + 6, value, 0); - else if (soap_set_attr(soap, name, value)) - return soap->error; } else #endif - { if (soap_send(soap, " ") || soap_send(soap, name)) + { + if (soap_send_raw(soap, " ", 1) + || soap_send(soap, name)) return soap->error; if (value) if (soap_send_raw(soap, "=\"", 2) @@ -7712,177 +14464,251 @@ soap_attribute(struct soap *soap, const char *name, const char *value) } return SOAP_OK; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 soap_element_begin_in(struct soap *soap, const char *tag, int nillable, const char *type) -{ if (!soap_peek_element(soap)) - { if (soap->other) +{ + if (!soap_peek_element(soap)) + { + if (soap->other) return soap->error = SOAP_TAG_MISMATCH; if (tag && *tag == '-') return SOAP_OK; - if (!(soap->error = soap_match_tag(soap, soap->tag, tag))) - { soap->peeked = 0; + soap->error = soap_match_tag(soap, soap->tag, tag); + if (!soap->error) + { if (type && *soap->type && soap_match_tag(soap, soap->type, type)) return soap->error = SOAP_TYPE; + soap->peeked = 0; if (!nillable && soap->null && (soap->mode & SOAP_XML_STRICT)) return soap->error = SOAP_NULL; if (soap->body) + { soap->level++; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:SOAP_STR_EOS )); + if (soap->level > soap->maxlevel) + return soap->error = SOAP_LEVEL; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin tag found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag ? tag : SOAP_STR_EOS)); + soap->error = SOAP_OK; } } else if (soap->error == SOAP_NO_TAG && tag && *tag == '-') + { soap->error = SOAP_OK; + } return soap->error; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 soap_element_end_in(struct soap *soap, const char *tag) -{ soap_wchar c; - char *s; +{ + soap_wchar c; + char *s = NULL; int n = 0; - if (tag && *tag == '-') - return SOAP_OK; if (soap->error == SOAP_NO_TAG) soap->error = SOAP_OK; #ifdef WITH_DOM - /* this whitespace or mixed content is not insignificant for DOM */ + /* this whitespace or mixed content is significant for DOM "as-is" */ if ((soap->mode & SOAP_XML_DOM) && soap->dom) - { if (!soap->peeked && !soap_string_in(soap, 3, -1, -1)) + { + s = soap_string_in(soap, 0, -1, -1, NULL); + if (!soap->peeked && !s) return soap->error; if (soap->dom->prnt) soap->dom = soap->dom->prnt; + if (s && (soap->mode & SOAP_XML_STRICT)) + { + for (; *s; s++) + if (!soap_coblank((soap_wchar)*s)) + return soap->error = SOAP_END_TAG; /* reject mixed content before ending tag */ + } } #endif + if (tag && *tag == '-') + return SOAP_OK; if (soap->peeked) - { if (*soap->tag) + { + if (*soap->tag) n++; soap->peeked = 0; } do - { while (((c = soap_get(soap)) != SOAP_TT)) - { if ((int)c == EOF) - return soap->error = SOAP_EOF; - if (c == SOAP_LT) - n++; - else if (c == '/') - { c = soap_get(soap); - if (c == SOAP_GT) - n--; - else - soap_unget(soap, c); + { + while (((c = soap_get(soap)) != SOAP_TT)) + { + if ((int)c == EOF) + return soap->error = SOAP_CHK_EOF; + if (!soap_coblank(c)) + { + if ((soap->mode & SOAP_XML_STRICT)) + return soap->error = SOAP_END_TAG; /* reject mixed content before ending tag */ + if (c == SOAP_LT) + n++; + else if (c == '/') + { + c = soap_get(soap); + if (c == SOAP_GT && n > 0) + n--; + else + soap_unget(soap, c); + } } } - } while (n--); + } while (n-- > 0); s = soap->tag; n = sizeof(soap->tag); - while (soap_notblank(c = soap_get(soap))) - { if (--n > 0) + while ((c = soap_get(soap)) > 32) + { + if (n > 1) + { *s++ = (char)c; + n--; + } } *s = '\0'; if ((int)c == EOF) - return soap->error = SOAP_EOF; - while (soap_blank(c)) + return soap->error = SOAP_CHK_EOF; + while (soap_coblank(c)) c = soap_get(soap); if (c != SOAP_GT) return soap->error = SOAP_SYNTAX_ERROR; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:SOAP_STR_EOS)); #ifndef WITH_LEAN +#ifdef WITH_DOM + if (soap->feltendin) + { + int err = soap->error; + soap->error = soap->feltendin(soap, soap->tag, tag); + if (soap->error) + return soap->error; + if (err) + return soap->error = err; /* restore error */ + } +#endif +#endif if (tag && (soap->mode & SOAP_XML_STRICT)) - { soap_pop_namespace(soap); + { + soap_pop_namespace(soap); if (soap_match_tag(soap, soap->tag, tag)) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element tag name does not match\n")); + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End tag '%s' does not match '%s'\n", soap->tag, tag ? tag : SOAP_STR_EOS)); return soap->error = SOAP_SYNTAX_ERROR; } } -#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End tag found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag ? tag : SOAP_STR_EOS)); soap->level--; return SOAP_OK; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 const char * SOAP_FMAC2 -soap_attr_value(struct soap *soap, const char *name, int flag) -{ struct soap_attribute *tp; +soap_attr_value(struct soap *soap, const char *name, int flag, int occurs) +{ + struct soap_attribute *tp; if (*name == '-') return SOAP_STR_EOS; for (tp = soap->attributes; tp; tp = tp->next) - { if (tp->visible && !soap_match_tag(soap, tp->name, name)) + { + if (tp->visible == 2 && !soap_match_att(soap, tp->name, name)) break; } if (tp) - { if (flag == 2 && (soap->mode & SOAP_XML_STRICT)) + { + if (occurs == 4 || (occurs == 2 && (soap->mode & SOAP_XML_STRICT))) soap->error = SOAP_PROHIBITED; + else if (flag >= 4) + return soap_collapse(soap, tp->value, flag, 1); else return tp->value; } - else if (flag == 1 && (soap->mode & SOAP_XML_STRICT)) + else if (occurs == 3 || (occurs == 1 && (soap->mode & SOAP_XML_STRICT))) + { soap->error = SOAP_REQUIRED; + } else + { soap->error = SOAP_OK; + } return NULL; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 -soap_set_attr(struct soap *soap, const char *name, const char *value) -{ struct soap_attribute *tp; +soap_set_attr(struct soap *soap, const char *name, const char *value, int flag) +{ + struct soap_attribute *tp, *tq; if (*name == '-') return SOAP_OK; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set attribute %s='%s'\n", name, value?value:SOAP_STR_EOS)); - for (tp = soap->attributes; tp; tp = tp->next) - { if (!strcmp(tp->name, name)) + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set attribute %s='%s'\n", name, value ? value : SOAP_STR_EOS)); + tq = NULL; + for (tp = soap->attributes; tp; tq = tp, tp = tp->next) + { + if (!strcmp(tp->name, name)) break; } if (!tp) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute %s\n", name)); - if (!(tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(name)))) + { + size_t l = strlen(name); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute %s\n", name)); + if (sizeof(struct soap_attribute) + l > l && (SOAP_MAXALLOCSIZE <= 0 || sizeof(struct soap_attribute) + l <= SOAP_MAXALLOCSIZE)) + tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + l); + if (!tp) return soap->error = SOAP_EOM; tp->ns = NULL; #ifndef WITH_LEAN - if (soap->mode & SOAP_XML_CANONICAL) - { struct soap_attribute **tpp = &soap->attributes; + 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) + { + for (; *tpp; tpp = &(*tpp)->next) if (strncmp((*tpp)->name, "xmlns", 5) || strcmp((*tpp)->name + 5, name + 5) > 0) break; } else if (!s) - { for (; *tpp; tpp = &(*tpp)->next) + { + for (; *tpp; tpp = &(*tpp)->next) if (strncmp((*tpp)->name, "xmlns", 5) && ((*tpp)->ns || strcmp((*tpp)->name, name) > 0)) break; } else - { int k; - for (; *tpp; tpp = &(*tpp)->next) - { if (!strncmp((*tpp)->name, "xmlns:", 6) && !strncmp((*tpp)->name + 6, name, s - name) && !(*tpp)->name[6 + s - name]) - { if (!tp->ns) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Canonicalization: prefix %s=%p (%s)\n", name, (*tpp)->ns, (*tpp)->ns)); - tp->ns = (*tpp)->ns; + { + struct soap_nlist *np = soap_lookup_ns(soap, name, s - name); + if (np) + { + tp->ns = np->ns; + } + else + { + struct soap_attribute *tq; + for (tq = soap->attributes; tq; tq = tq->next) + { + if (!strncmp(tq->name, "xmlns:", 6) && !strncmp(tq->name + 6, name, s - name) && !tq->name[6 + s - name]) + { + tp->ns = tq->ns; + break; } } - else if (strncmp((*tpp)->name, "xmlns", 5) && (*tpp)->ns && tp->ns && ((k = strcmp((*tpp)->ns, tp->ns)) > 0 || (!k && strcmp((*tpp)->name, name) > 0))) + } + for (; *tpp; tpp = &(*tpp)->next) + { + int k; + if (strncmp((*tpp)->name, "xmlns", 5) && (*tpp)->ns && tp->ns && ((k = strcmp((*tpp)->ns, tp->ns)) > 0 || (!k && strcmp((*tpp)->name, name) > 0))) break; } } @@ -7891,57 +14717,89 @@ soap_set_attr(struct soap *soap, const char *name, const char *value) } else #endif - { tp->next = soap->attributes; + if (tq) + { + tq->next = tp; + tp->next = NULL; + } + else + { + tp->next = soap->attributes; soap->attributes = tp; } - strcpy(tp->name, name); + soap_strcpy((char*)tp->name, l + 1, name); tp->value = NULL; } else if (tp->visible) - { return SOAP_OK; + { + return SOAP_OK; } else if (value && tp->value && tp->size <= strlen(value)) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute value of %s (free %p)\n", name, tp->value)); + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute value of %s (free %p)\n", name, (void*)tp->value)); SOAP_FREE(soap, tp->value); tp->value = NULL; tp->ns = NULL; } if (value) - { if (!tp->value) - { tp->size = strlen(value) + 1; - if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size))) + { + if (!tp->value) + { + tp->size = strlen(value) + 1; + if (SOAP_MAXALLOCSIZE <= 0 || tp->size <= SOAP_MAXALLOCSIZE) + tp->value = (char*)SOAP_MALLOC(soap, tp->size); + if (!tp->value) return soap->error = SOAP_EOM; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute value for %s (%p)\n", tp->name, tp->value)); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute value for %s (%p)\n", tp->name, (void*)tp->value)); } - strcpy(tp->value, value); + soap_strcpy(tp->value, tp->size, value); if (!strncmp(tp->name, "xmlns:", 6)) tp->ns = tp->value; tp->visible = 2; + tp->flag = (short)flag; #ifndef WITH_LEAN if (!strcmp(name, "wsu:Id")) - { soap->part = SOAP_BEGIN_SECURITY; - strncpy(soap->id, value, sizeof(soap->id)); - soap->id[sizeof(soap->id)-1] = '\0'; + { + soap->event = SOAP_SEC_BEGIN; + soap_strcpy(soap->id, sizeof(soap->id), value); + } + if ((soap->mode & SOAP_XML_CANONICAL) && !(soap->mode & SOAP_XML_CANONICAL_NA)) + { + const char *s = strchr(name, ':'); + if (s && strchr(value, ':')) + { + struct soap_nlist *np = soap_lookup_ns(soap, name, s - name); + if (np && np->ns && soap->local_namespaces) + { + if ((!strcmp(s + 1, "type") && !strcmp(np->ns, soap->local_namespaces[2].ns)) /* xsi:type QName */ + || ((!strcmp(s + 1, "arrayType") || !strcmp(s + 1, "itemType")) && !strcmp(np->ns, soap->local_namespaces[1].ns))) /* SOAP-ENC:arrayType and SOAP-ENC:itemType QName */ + soap_utilize_ns(soap, value, 1); + } + } } #endif } else + { tp->visible = 1; + } return SOAP_OK; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 void SOAP_FMAC2 soap_clr_attr(struct soap *soap) -{ struct soap_attribute *tp; +{ + struct soap_attribute *tp; #ifndef WITH_LEAN if ((soap->mode & SOAP_XML_CANONICAL)) - { while (soap->attributes) - { tp = soap->attributes->next; + { + while (soap->attributes) + { + tp = soap->attributes->next; if (soap->attributes->value) SOAP_FREE(soap, soap->attributes->value); SOAP_FREE(soap, soap->attributes); @@ -7950,19 +14808,90 @@ soap_clr_attr(struct soap *soap) } else #endif - { for (tp = soap->attributes; tp; tp = tp->next) + { + for (tp = soap->attributes; tp; tp = tp->next) tp->visible = 0; } } -#endif /******************************************************************************/ -#ifndef PALM_2 + static int -soap_getattrval(struct soap *soap, char *s, size_t n, soap_wchar d) -{ size_t i; - for (i = 0; i < n; i++) - { soap_wchar c = soap_get(soap); +soap_getattrval(struct soap *soap, char *s, size_t *n, soap_wchar d) +{ + char buf[8]; + size_t i; + size_t k = *n; + size_t m = 0; + char *t = buf; + for (i = 0; i < k; i++) + { + soap_wchar c; + if (m) + { + *s++ = *t++; + m--; + continue; + } + if ((soap->mode & SOAP_C_UTFSTRING)) + { + c = soap_get(soap); + if ((c & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP) + { + t = buf; + c &= 0x7FFFFFFF; + if (c < 0x0800) + *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); + else + { +#ifdef WITH_REPLACE_ILLEGAL_UTF8 + if (!((c >= 0x80 && c <= 0xD7FF) || (c >= 0xE000 && c <= 0xFFFD) || (c >= 0x10000 && c <= 0x10FFFF))) + c = SOAP_UNKNOWN_UNICODE_CHAR; +#endif + if (c < 0x010000) + { + *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); + } + else + { + if (c < 0x200000) + { + *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + } + else + { + if (c < 0x04000000) + { + *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + } + else + { + *t++ = (char)(0xFC | ((c >> 30) & 0x01)); + *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); + } + *t++ = (char)(0x80 | (c & 0x3F)); + m = t - buf - 1; + if (i + m >= k) + { + soap_unget(soap, c | 0x80000000); + *n = i; + return soap->error = SOAP_EOM; + } + t = buf; + *s++ = *t++; + continue; + } + } + else + { + c = soap_getutf8(soap); + } switch (c) { case SOAP_TT: @@ -7974,22 +14903,28 @@ soap_getattrval(struct soap *soap, char *s, size_t n, soap_wchar d) break; case SOAP_GT: if (d == ' ') - { soap_unget(soap, c); + { + soap_unget(soap, c); *s = '\0'; + *n = i + 1; return SOAP_OK; } *s++ = '>'; break; case SOAP_QT: if (c == d) - { *s = '\0'; + { + *s = '\0'; + *n = i + 1; return SOAP_OK; } *s++ = '"'; break; case SOAP_AP: if (c == d) - { *s = '\0'; + { + *s = '\0'; + *n = i + 1; return SOAP_OK; } *s++ = '\''; @@ -8000,70 +14935,89 @@ soap_getattrval(struct soap *soap, char *s, size_t n, soap_wchar d) case ' ': case '/': if (d == ' ') - { soap_unget(soap, c); + { + soap_unget(soap, c); *s = '\0'; + *n = i + 1; return SOAP_OK; } + *s++ = (char)c; + break; default: if ((int)c == EOF) - return soap->error = SOAP_EOF; + { + *s = '\0'; + *n = i + 1; + return soap->error = SOAP_CHK_EOF; + } *s++ = (char)c; } } return soap->error = SOAP_EOM; } -#endif /******************************************************************************/ + #ifdef WITH_FAST -#ifndef PALM_2 SOAP_FMAC1 int SOAP_FMAC2 soap_store_lab(struct soap *soap, const char *s, size_t n) -{ soap->labidx = 0; +{ + soap->labidx = 0; return soap_append_lab(soap, s, n); } #endif -#endif /******************************************************************************/ + #ifdef WITH_FAST -#ifndef PALM_2 SOAP_FMAC1 int SOAP_FMAC2 soap_append_lab(struct soap *soap, const char *s, size_t n) -{ if (soap->labidx + n >= soap->lablen) - { char *t = soap->labbuf; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enlarging look-aside buffer to append data, old size=%lu", (unsigned long)soap->lablen)); +{ + if (soap->labidx + n < soap->labidx) + return soap->error = SOAP_EOM; + if (soap->labidx + n >= soap->lablen) + { + char *t = soap->labbuf; + 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) + { + if (soap->lablen << 1 < soap->lablen) + return soap->error = SOAP_EOM; 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)); + if (SOAP_MAXALLOCSIZE > 0 && soap->lablen > SOAP_MAXALLOCSIZE) + return soap->error = SOAP_EOM; soap->labbuf = (char*)SOAP_MALLOC(soap, soap->lablen); if (!soap->labbuf) - { if (t) + { + if (t) SOAP_FREE(soap, t); return soap->error = SOAP_EOM; } if (t) - { memcpy(soap->labbuf, t, soap->labidx); + { + (void)soap_memcpy((void*)soap->labbuf, soap->lablen, (const void*)t, soap->labidx); SOAP_FREE(soap, t); } } if (s) - { memcpy(soap->labbuf + soap->labidx, s, n); + { + (void)soap_memcpy((void*)(soap->labbuf + soap->labidx), soap->lablen - soap->labidx, (const void*)s, n); soap->labidx += n; } return SOAP_OK; } #endif -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 @@ -8079,7 +15033,8 @@ soap_peek_element(struct soap *soap) soap_wchar c; int i; if (soap->peeked) - { if (!*soap->tag) + { + if (!*soap->tag) return soap->error = SOAP_NO_TAG; return SOAP_OK; } @@ -8095,101 +15050,151 @@ soap_peek_element(struct soap *soap) soap->position = 0; soap->null = 0; soap->mustUnderstand = 0; - /* skip BOM */ - if ((c = soap_getchar(soap)) != 0xEF || (c = soap_get1(soap)) != 0xBB || (c = soap_get1(soap)) != 0xBF) + /* UTF-8 BOM? */ + c = soap_getchar(soap); + if (c == 0xEF && soap_get0(soap) == 0xBB) + { + soap_get1(soap); + c = soap_get1(soap); + if (c == 0xBF) + soap->mode &= ~SOAP_ENC_LATIN; + else + soap_unget(soap, (0x0F << 12) | (0xBB << 6) | (c & 0x3F)); /* UTF-8 */ + } + else if ((c == 0xFE && soap_get0(soap) == 0xFF) /* UTF-16 BE */ + || (c == 0xFF && soap_get0(soap) == 0xFE)) /* UTF-16 LE */ + { + return soap->error = SOAP_UTF_ERROR; + } + else + { soap_unget(soap, c); + } c = soap_get(soap); #ifdef WITH_DOM - /* whitespace leading to start tag is not insignificant for DOM */ - if (soap_blank(c)) - { soap->labidx = 0; + /* whitespace leading up to the start tag is significant for DOM as-is (but comments and PIs are removed from this lead) */ + if (soap_coblank(c)) + { + soap->labidx = 0; do - { if (soap_append_lab(soap, NULL, 0)) + { + if (soap_append_lab(soap, NULL, 0)) return soap->error; s = soap->labbuf + soap->labidx; i = soap->lablen - soap->labidx; soap->labidx = soap->lablen; - while (soap_blank(c) && i--) - { *s++ = c; + while (soap_coblank(c)) + { + if (c != '\r') + { + if (i-- <= 0) + break; + *s++ = c; + } c = soap_get(soap); } - } - while (soap_blank(c)); + } while (soap_coblank(c) || i == 0); *s = '\0'; - if (*soap->labbuf) - lead = soap->labbuf; + lead = soap->labbuf; } #else /* skip space */ - while (soap_blank(c)) + while (soap_coblank(c)) c = soap_get(soap); #endif if (c != SOAP_LT) - { *soap->tag = '\0'; + { + *soap->tag = '\0'; if ((int)c == EOF) - return soap->error = SOAP_EOF; + return soap->error = SOAP_CHK_EOF; soap_unget(soap, c); #ifdef WITH_DOM - /* whitespace leading to end tag is not insignificant for DOM */ + /* whitespace leading up to the end tag is significant for DOM as-is */ if ((soap->mode & SOAP_XML_DOM) && soap->dom) - soap->dom->tail = soap_strdup(soap, lead); + { + if (lead && *lead) + soap->dom->tail = soap_strdup(soap, lead); + else + soap->dom->tail = SOAP_STR_EOS; /* body with closing tag instead of */ + } #endif return soap->error = SOAP_NO_TAG; } + do + { + c = soap_get1(soap); + } while (soap_coblank(c)); s = soap->tag; - do c = soap_get1(soap); - while (soap_blank(c)); i = sizeof(soap->tag); - while (c != '>' && c != '/' && soap_notblank(c) && (int)c != EOF) - { if (--i > 0) + while (c != '>' && c != '/' && c > 32 && (int)c != EOF) + { + if (i > 1) + { *s++ = (char)c; + i--; + } c = soap_get1(soap); } - while (soap_blank(c)) - c = soap_get1(soap); *s = '\0'; + while (soap_coblank(c)) + c = soap_get1(soap); #ifdef WITH_DOM - if (soap->mode & SOAP_XML_DOM) - { struct soap_dom_element *elt; + if ((soap->mode & SOAP_XML_DOM)) + { + struct soap_dom_element *elt; elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element)); if (!elt) return soap->error; elt->next = NULL; - elt->nstr = NULL; - elt->name = soap_strdup(soap, soap->tag); elt->prnt = soap->dom; elt->elts = NULL; elt->atts = NULL; - elt->data = NULL; - elt->wide = NULL; - elt->type = 0; - elt->node = NULL; - elt->head = soap_strdup(soap, lead); + elt->nstr = NULL; + elt->name = soap_strdup(soap, soap->tag); + elt->text = NULL; + elt->code = NULL; elt->tail = NULL; + elt->node = NULL; + elt->type = 0; + if (lead && *lead) + elt->lead = soap_strdup(soap, lead); + else + elt->lead = NULL; elt->soap = soap; if (soap->dom) - { struct soap_dom_element *p = soap->dom->elts; + { + struct soap_dom_element *p = soap->dom->elts; if (p) - { while (p->next) + { + while (p->next) p = p->next; p->next = elt; } else + { soap->dom->elts = elt; + } } soap->dom = elt; att = &elt->atts; + if (!elt->name) + return soap->error = SOAP_EOM; } #endif soap_pop_namespace(soap); for (tp = soap->attributes; tp; tp = tp->next) tp->visible = 0; while ((int)c != EOF && c != '>' && c != '/') - { s = soap->tmpbuf; + { + s = soap->tmpbuf; i = sizeof(soap->tmpbuf); - while (c != '=' && c != '>' && c != '/' && soap_notblank(c) && (int)c != EOF) - { if (--i > 0) + while (c != '=' && c != '>' && c != '/' && c > 32 && (int)c != EOF) + { + if (i > 1) + { *s++ = (char)c; + i--; + } c = soap_get1(soap); } *s = '\0'; @@ -8198,19 +15203,22 @@ soap_peek_element(struct soap *soap) #ifdef WITH_DOM /* add attribute name to dom */ if (att) - { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); + { + *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); if (!*att) return soap->error; (*att)->next = NULL; (*att)->nstr = NULL; (*att)->name = soap_strdup(soap, soap->tmpbuf); - (*att)->data = NULL; - (*att)->wide = NULL; + (*att)->text = NULL; (*att)->soap = soap; + if (!(*att)->name) + return soap->error = SOAP_EOM; } #endif if (!strncmp(soap->tmpbuf, "xmlns", 5)) - { if (soap->tmpbuf[5] == ':') + { + if (soap->tmpbuf[5] == ':') t = soap->tmpbuf + 6; else if (soap->tmpbuf[5]) t = NULL; @@ -8218,51 +15226,80 @@ soap_peek_element(struct soap *soap) t = SOAP_STR_EOS; } else + { t = NULL; + } tq = NULL; for (tp = soap->attributes; tp; tq = tp, tp = tp->next) - { if (!SOAP_STRCMP(tp->name, soap->tmpbuf)) + { + if (!SOAP_STRCMP(tp->name, soap->tmpbuf)) break; } if (!tp) - { tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(soap->tmpbuf)); + { + size_t l = strlen(soap->tmpbuf); + tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + l); if (!tp) return soap->error = SOAP_EOM; - strcpy(tp->name, soap->tmpbuf); + (void)soap_memcpy((char*)tp->name, l + 1, soap->tmpbuf, l + 1); tp->value = NULL; tp->size = 0; - /* if attribute name is qualified, append it to the end of the list */ - if (tq && strchr(soap->tmpbuf, ':')) - { tq->next = tp; + tp->ns = NULL; + tp->visible = 0; + /* append attribute to the end of the list */ + if (tq) + { + tq->next = tp; tp->next = NULL; } else - { tp->next = soap->attributes; + { + tp->next = soap->attributes; soap->attributes = tp; } } - while (soap_blank(c)) + else if (tp->visible) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Duplicate attribute in %s\n", soap->tag)); + return soap->error = SOAP_SYNTAX_ERROR; /* redefined (duplicate) attribute */ + } + while (soap_coblank(c)) c = soap_get1(soap); if (c == '=') - { do c = soap_getutf8(soap); - while (soap_blank(c)); + { + size_t k; + do + { + c = soap_getutf8(soap); + } while (soap_coblank(c)); if (c != SOAP_QT && c != SOAP_AP) - { soap_unget(soap, c); - c = ' '; /* blank delimiter */ + { + if ((soap->mode & SOAP_XML_STRICT)) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unquoted attribute value in %s\n", soap->tag)); + return soap->error = SOAP_SYNTAX_ERROR; + } + soap_unget(soap, c); + c = ' '; /* allow blank delimiter for non-well formed XML like HTML */ } - if (soap_getattrval(soap, tp->value, tp->size, c)) + k = tp->size; + if (soap_getattrval(soap, tp->value, &k, c)) { #ifdef WITH_FAST if (soap->error != SOAP_EOM) return soap->error; soap->error = SOAP_OK; - if (soap_store_lab(soap, tp->value, tp->size)) + if (soap_store_lab(soap, tp->value, k)) return soap->error; if (tp->value) SOAP_FREE(soap, tp->value); + tp->value = NULL; for (;;) - { if (soap_getattrval(soap, soap->labbuf + soap->labidx, soap->lablen - soap->labidx, c)) - { if (soap->error != SOAP_EOM) + { + k = soap->lablen - soap->labidx; + if (soap_getattrval(soap, soap->labbuf + soap->labidx, &k, c)) + { + if (soap->error != SOAP_EOM) return soap->error; soap->error = SOAP_OK; soap->labidx = soap->lablen; @@ -8270,142 +15307,210 @@ soap_peek_element(struct soap *soap) return soap->error; } else + { break; + } } if (soap->labidx) + { tp->size = soap->lablen; + } else - { tp->size = strlen(soap->labbuf) + 1; + { + tp->size = strlen(soap->labbuf) + 1; if (tp->size < SOAP_LABLEN) tp->size = SOAP_LABLEN; } - if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size))) + tp->value = (char*)SOAP_MALLOC(soap, tp->size); + if (!tp->value) return soap->error = SOAP_EOM; - strcpy(tp->value, soap->labbuf); + soap_strcpy(tp->value, tp->size, soap->labbuf); #else - size_t n; + tp->size = k; if (soap->error != SOAP_EOM) return soap->error; soap->error = SOAP_OK; - if (soap_new_block(soap) == NULL) + if (soap_alloc_block(soap) == NULL) return soap->error; for (;;) - { if (!(s = (char*)soap_push_block(soap, NULL, SOAP_BLKLEN))) + { + s = (char*)soap_push_block(soap, NULL, SOAP_BLKLEN); + if (!s) return soap->error; - if (soap_getattrval(soap, s, SOAP_BLKLEN, c)) - { if (soap->error != SOAP_EOM) + k = SOAP_BLKLEN; + if (soap_getattrval(soap, s, &k, c)) + { + if (soap->error != SOAP_EOM) return soap->error; soap->error = SOAP_OK; + soap_size_block(soap, NULL, k); } else + { break; + } } - n = tp->size + soap->blist->size; - if (!(s = (char*)SOAP_MALLOC(soap, n))) + k = tp->size + soap->blist->size; + if (SOAP_MAXALLOCSIZE > 0 && k > SOAP_MAXALLOCSIZE) + return soap->error = SOAP_EOM; + s = (char*)SOAP_MALLOC(soap, k); + if (!s) return soap->error = SOAP_EOM; if (tp->value) - { memcpy(s, tp->value, tp->size); + { + (void)soap_memcpy((void*)s, k, (const void*)tp->value, tp->size); SOAP_FREE(soap, tp->value); } - soap_save_block(soap, NULL, s + tp->size, 0); + (void)soap_save_block(soap, NULL, s + tp->size, 0); tp->value = s; - tp->size = n; + tp->size = k; #endif } - do c = soap_get1(soap); - while (soap_blank(c)); tp->visible = 2; /* seen this attribute w/ value */ + do + { + c = soap_get1(soap); + } while (soap_coblank(c)); #ifdef WITH_DOM - if (att) - (*att)->data = soap_strdup(soap, tp->value); + if (att && tp->value) + { + (*att)->text = soap_strdup(soap, tp->value); + if (!(*att)->text) + return soap->error = SOAP_EOM; + } #endif } else + { + if ((soap->mode & SOAP_XML_STRICT)) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attribute withput a value in %s\n", soap->tag)); + return soap->error = SOAP_SYNTAX_ERROR; + } tp->visible = 1; /* seen this attribute w/o value */ + } #ifdef WITH_DOM if (att) att = &(*att)->next; #endif if (t && tp->value) - { if (soap_push_namespace(soap, t, tp->value) == NULL) + { + if (soap_push_namespace(soap, t, tp->value) == NULL) return soap->error; } } #ifdef WITH_DOM if (att) - { soap->dom->nstr = soap_current_namespace(soap, soap->tag); + { + soap->dom->nstr = soap_current_namespace_tag(soap, soap->tag); for (att = &soap->dom->atts; *att; att = &(*att)->next) - (*att)->nstr = soap_current_namespace(soap, (*att)->name); + (*att)->nstr = soap_current_namespace_att(soap, (*att)->name); } #endif if ((int)c == EOF) - return soap->error = SOAP_EOF; - if (!(soap->body = (c != '/'))) - do c = soap_get1(soap); - while (soap_blank(c)); + return soap->error = SOAP_CHK_EOF; + soap->body = (c != '/'); + if (!soap->body) + { + do + { + c = soap_get1(soap); + } while (soap_coblank(c)); + } #ifdef WITH_DOM - if (soap->mode & SOAP_XML_DOM) - { if (!soap->body && soap->dom->prnt) + if ((soap->mode & SOAP_XML_DOM)) + { + if (!soap->body && soap->dom->prnt) soap->dom = soap->dom->prnt; } #endif for (tp = soap->attributes; tp; tp = tp->next) - { if (tp->visible && tp->value) + { + if (tp->visible && tp->value) { #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 = '#'; + soap_strcpy(soap->id + 1, sizeof(soap->id) - 1, tp->value); } } 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->mode & (SOAP_ENC_MTOM | SOAP_ENC_DIME)) && *tp->value != '#')) + soap_strcpy(soap->href, sizeof(soap->href), tp->value); + } + else if (!strcmp(tp->name, "ref")) + { + if ((soap->version == 2 && !(soap->imode & SOAP_XML_TREE)) + || (soap->mode & SOAP_XML_GRAPH)) + { + *soap->href = '#'; + soap_strcpy(soap->href + (*tp->value != '#'), sizeof(soap->href) - 1, tp->value); } } - else +#else + if (!strcmp(tp->name, "href")) + { + if ((soap->mode & (SOAP_ENC_MTOM | SOAP_ENC_DIME)) && *tp->value != '#') + soap_strcpy(soap->href, sizeof(soap->href), tp->value); + } #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'; + else if (!soap_match_tag(soap, tp->name, "xsi:type")) + { + soap_strcpy(soap->type, sizeof(soap->type), tp->value); } else if ((!soap_match_tag(soap, tp->name, "xsi:null") || !soap_match_tag(soap, tp->name, "xsi:nil")) && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true"))) - { soap->null = 1; + { + soap->null = 1; + } + else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:encodingStyle")) + { + if (!soap->encodingStyle) + soap->encodingStyle = SOAP_STR_EOS; + soap_version(soap); } else if (soap->version == 1) - { if (!soap_match_tag(soap, tp->name, "SOAP-ENC:arrayType")) - { s = soap_strrchr(tp->value, '['); + { + if (!soap_match_tag(soap, tp->name, "SOAP-ENC:arrayType")) + { + s = soap_strrchr(tp->value, '['); 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); + { + (void)soap_strncpy(soap->arrayType, sizeof(soap->arrayType), tp->value, s - tp->value); + soap_strcpy(soap->arraySize, sizeof(soap->arraySize), s); } else - strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1); - soap->arraySize[sizeof(soap->arrayType)-1] = '\0'; - soap->arrayType[sizeof(soap->arrayType)-1] = '\0'; + soap_strcpy(soap->arrayType, sizeof(soap->arrayType), tp->value); } else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:offset")) - strncpy(soap->arrayOffset, tp->value, sizeof(soap->arrayOffset)); + { + soap_strcpy(soap->arrayOffset, sizeof(soap->arrayOffset), tp->value); + } else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:position")) + { soap->position = soap_getposition(tp->value, soap->positions); + } else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:root")) + { soap->root = ((!strcmp(tp->value, "1") || !strcmp(tp->value, "true"))); + } else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand") && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true"))) + { soap->mustUnderstand = 1; + } else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:actor")) - { if ((!soap->actor || strcmp(soap->actor, tp->value)) + { + if ((!soap->actor || strcmp(soap->actor, tp->value)) && strcmp(tp->value, "http://schemas.xmlsoap.org/soap/actor/next")) soap->other = 1; } @@ -8413,103 +15518,195 @@ 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")) - { *soap->href = '#'; - strncpy(soap->href + 1, tp->value, sizeof(soap->href) - 2); - soap->href[sizeof(soap->href)-1] = '\0'; + if (!soap_match_tag(soap, tp->name, "SOAP-ENC:id")) + { + *soap->id = '#'; + soap_strcpy(soap->id + 1, sizeof(soap->id) - 1, tp->value); + } + else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:ref")) + { + *soap->href = '#'; + soap_strcpy(soap->href + (*tp->value != '#'), sizeof(soap->href) - 1, tp->value); } else #endif - if (!soap_match_tag(soap, tp->name, "SOAP-ENC:itemType")) - strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1); + if (!soap_match_tag(soap, tp->name, "SOAP-ENC:itemType")) + { + soap_strcpy(soap->arrayType, sizeof(soap->arrayType), tp->value); + } else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:arraySize")) - strncpy(soap->arraySize, tp->value, sizeof(soap->arraySize) - 1); + { + soap_strcpy(soap->arraySize, sizeof(soap->arraySize), tp->value); + } else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand") && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true"))) + { soap->mustUnderstand = 1; + } else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:role")) - { if ((!soap->actor || strcmp(soap->actor, tp->value)) + { + if ((!soap->actor || strcmp(soap->actor, tp->value)) && strcmp(tp->value, "http://www.w3.org/2003/05/soap-envelope/role/next")) soap->other = 1; } } else - { if (!soap_match_tag(soap, tp->name, "wsdl:required") && !strcmp(tp->value, "true")) + { + if (!soap_match_tag(soap, tp->name, "wsdl:required") && !strcmp(tp->value, "true")) soap->mustUnderstand = 1; } } } +#ifdef WITH_DOM + if (soap->feltbegin) + return soap->error = soap->feltbegin(soap, soap->tag); +#endif return soap->error = SOAP_OK; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 void SOAP_FMAC2 soap_retry(struct soap *soap) -{ soap->error = SOAP_OK; +{ + soap->error = SOAP_OK; soap_revert(soap); } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 void SOAP_FMAC2 soap_revert(struct soap *soap) -{ if (!soap->peeked) - { soap->peeked = 1; +{ + if (!soap->peeked) + { + soap->peeked = 1; if (soap->body) soap->level--; } - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reverting last element (level=%u)\n", soap->level)); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reverting to last element '%s' (level=%u)\n", soap->tag, soap->level)); } + +/******************************************************************************/ + +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_ignore(struct soap *soap) +{ + int n = 0; + soap_wchar c; + soap->level++; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Ignoring XML content at level=%u\n", soap->level)); +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { + if (!soap_string_in(soap, -1, -1, -1, NULL)) + return soap->error; + } + else #endif + { + for (;;) + { + c = soap_get(soap); + switch (c) + { + case SOAP_TT: + if (n == 0) + goto end; + n--; + break; + case SOAP_LT: + n++; + break; + case '/': + if (n > 0) + { + c = soap_get0(soap); + if (c == '>') + n--; + } + break; + default: + if ((int)c == EOF) + return soap->error = SOAP_EOF; + } + } +end: + soap_unget(soap, c); + } + return soap_element_end_in(soap, NULL); +} /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 soap_string_out(struct soap *soap, const char *s, int flag) -{ const char *t; +{ + const char *t; soap_wchar c; soap_wchar mask = (soap_wchar)0xFFFFFF80UL; #ifdef WITH_DOM if ((soap->mode & SOAP_XML_DOM) && soap->dom) - { soap->dom->data = soap_strdup(soap, s); + { + soap->dom->text = soap_strdup(soap, s); + if (!soap->dom->text) + return soap->error = SOAP_EOM; return SOAP_OK; } #endif - if (soap->mode & SOAP_C_UTFSTRING) + if (flag == 2 || (soap->mode & SOAP_C_UTFSTRING)) mask = 0; t = s; while ((c = *t++)) - { switch (c) + { + switch (c) { case 0x09: if (flag) - { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, " ", 5)) + { + if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, " ", 5)) return soap->error; s = t; } break; case 0x0A: - if (flag || !(soap->mode & SOAP_XML_CANONICAL)) - { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, " ", 5)) + if (flag) + { + if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, " ", 5)) return soap->error; s = t; } break; +#ifdef WITH_CRTOLF case 0x0D: - if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, " ", 5)) - return soap->error; - s = t; + if (*t == 0x0A) + { + if (soap_send_raw(soap, s, t - s - 1)) + return soap->error; + s = t; + } + else if (flag) + { + if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, " ", 5)) + return soap->error; + s = t; + } + else + { + if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "\n", 1)) + return soap->error; + s = t; + } break; +#endif case '&': if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&", 5)) return soap->error; @@ -8522,26 +15719,35 @@ soap_string_out(struct soap *soap, const char *s, int flag) break; case '>': if (!flag) - { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, ">", 4)) + { + if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, ">", 4)) return soap->error; s = t; } break; case '"': if (flag) - { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, """, 6)) + { + if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, """, 6)) return soap->error; s = t; } break; + case 0x7F: + if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "", 6)) + return soap->error; + s = t; + break; default: #ifndef WITH_LEANER #ifdef HAVE_MBTOWC - if (soap->mode & SOAP_C_MBSTRING) - { wchar_t wc; + if ((soap->mode & SOAP_C_MBSTRING)) + { + wchar_t wc; int m = mbtowc(&wc, t - 1, MB_CUR_MAX); - if (m > 0 && wc != c) - { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, wc)) + if (m > 0 && !((soap_wchar)wc == c && m == 1 && c < 0x80)) + { + if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned long)wc)) return soap->error; s = t += m - 1; continue; @@ -8551,7 +15757,8 @@ soap_string_out(struct soap *soap, const char *s, int flag) #endif #ifndef WITH_NOSTRINGTOUTF8 if ((c & mask) || !(c & 0xFFFFFFE0UL)) - { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned char)c)) + { + if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned char)c)) return soap->error; s = t; } @@ -8560,18 +15767,18 @@ soap_string_out(struct soap *soap, const char *s, int flag) } return soap_send_raw(soap, s, t - s - 1); } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 char * SOAP_FMAC2 -soap_string_in(struct soap *soap, int flag, long minlen, long maxlen) -{ char *s; +soap_string_in(struct soap *soap, int flag, long minlen, long maxlen, const char *pattern) +{ + char *s = NULL; char *t = NULL; size_t i; - long l = 0; + ULONG64 l = 0; int n = 0, f = 0, m = 0; soap_wchar c; #if !defined(WITH_LEANER) && defined(HAVE_WCTOMB) @@ -8579,30 +15786,37 @@ soap_string_in(struct soap *soap, int flag, long minlen, long maxlen) #else char buf[8]; #endif - DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading string content, flag=%d\n", flag)); - if (soap->peeked && *soap->tag) - { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String content includes tag '%s' and attributes\n", soap->tag)); + if (maxlen < 0 && soap->maxlength > 0) + maxlen = soap->maxlength; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reading string content, flag=%d\n", flag)); + if (flag <= 0 && soap->peeked && *soap->tag) + { #ifndef WITH_LEAN struct soap_attribute *tp; + 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); + soap_strcpy(t + 1, sizeof(soap->tmpbuf) - 1, soap->tag); t += strlen(t); for (tp = soap->attributes; tp; tp = tp->next) - { if (tp->visible) - { if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2) - break; + { + if (tp->visible) + { + size_t k = strlen(tp->name); + if (t + k + 1 >= soap->tmpbuf + sizeof(soap->tmpbuf)) + break; /* too many or attribute values to large */ *t++ = ' '; - strcpy(t, tp->name); - t += strlen(t); - if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2) - break; /* too many or large attribute values */ + (void)soap_strncpy(t, sizeof(soap->tmpbuf) - (t - soap->tmpbuf), tp->name, k); + t += k; if (tp->value) - { *t++ = '='; + { + k = strlen(tp->value); + if (t + k + 3 >= soap->tmpbuf + sizeof(soap->tmpbuf)) + break; /* too many or attribute values to large */ + *t++ = '='; *t++ = '"'; - strcpy(t, tp->value); - t += strlen(t); + (void)soap_strncpy(t, sizeof(soap->tmpbuf) - (t - soap->tmpbuf), tp->value, k); + t += k; *t++ = '"'; } } @@ -8620,56 +15834,79 @@ soap_string_in(struct soap *soap, int flag, long minlen, long maxlen) soap->peeked = 0; } #ifdef WITH_CDATA - if (!flag) - { int state = 0; + if (flag <= 0) + { + int state = 0; #ifdef WITH_FAST - soap->labidx = 0; /* use look-aside buffer */ + soap->labidx = 0; /* use look-aside buffer */ #else - if (soap_new_block(soap) == NULL) + if (soap_alloc_block(soap) == NULL) return NULL; #endif for (;;) { #ifdef WITH_FAST size_t k; - if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */ + if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */ return NULL; - s = soap->labbuf + soap->labidx; /* space to populate */ - k = soap->lablen - soap->labidx; /* number of bytes available */ - soap->labidx = soap->lablen; /* claim this space */ + s = soap->labbuf + soap->labidx; /* space to populate */ + k = soap->lablen - soap->labidx; /* number of bytes available */ + soap->labidx = soap->lablen; /* claim this space */ #else size_t k = SOAP_BLKLEN; - if (!(s = (char*)soap_push_block(soap, NULL, k))) + s = (char*)soap_push_block(soap, NULL, k); + if (!s) return NULL; #endif for (i = 0; i < k; i++) - { if (m > 0) - { *s++ = *t++; /* copy multibyte characters */ + { + if (m > 0) + { + *s++ = *t++; /* copy multibyte characters */ m--; continue; } c = soap_getchar(soap); if ((int)c == EOF) goto end; - if (c >= 0x80 && state != 1 && !(soap->mode & SOAP_ENC_LATIN)) - { soap_unget(soap, c); - c = soap_getutf8(soap); - if (soap->mode & SOAP_C_UTFSTRING) - { c &= 0x7FFFFFFF; + if ((c >= 0x80 || c < SOAP_AP) && state != 1) + { + if ((c & 0x7FFFFFFF) >= 0x80) + { + soap_unget(soap, c); + c = soap_getutf8(soap); + } + if ((c & 0x7FFFFFFF) >= 0x80 && (flag <= 0 || (soap->mode & SOAP_C_UTFSTRING))) + { + c &= 0x7FFFFFFF; t = buf; if (c < 0x0800) *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); else - { if (c < 0x010000) + { +#ifdef WITH_REPLACE_ILLEGAL_UTF8 + if (!((c >= 0x80 && c <= 0xD7FF) || (c >= 0xE000 && c <= 0xFFFD) || (c >= 0x10000 && c <= 0x10FFFF))) + c = SOAP_UNKNOWN_UNICODE_CHAR; +#endif + if (c < 0x010000) + { *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); + } else - { if (c < 0x200000) + { + if (c < 0x200000) + { *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + } else - { if (c < 0x04000000) + { + if (c < 0x04000000) + { *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + } else - { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); + { + *t++ = (char)(0xFC | ((c >> 30) & 0x01)); *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); } *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); @@ -8686,20 +15923,21 @@ soap_string_in(struct soap *soap, int flag, long minlen, long maxlen) } } switch (state) - { case 1: + { + case 1: if (c == ']') state = 4; - *s++ = c; + *s++ = (char)c; continue; case 2: if (c == '-') state = 6; - *s++ = c; + *s++ = (char)c; continue; case 3: if (c == '?') state = 8; - *s++ = c; + *s++ = (char)c; continue; /* CDATA */ case 4: @@ -8707,14 +15945,14 @@ soap_string_in(struct soap *soap, int flag, long minlen, long maxlen) state = 5; else state = 1; - *s++ = c; + *s++ = (char)c; continue; case 5: if (c == '>') state = 0; - else + else if (c != ']') state = 1; - *s++ = c; + *s++ = (char)c; continue; /* comment */ case 6: @@ -8722,22 +15960,22 @@ soap_string_in(struct soap *soap, int flag, long minlen, long maxlen) state = 7; else state = 2; - *s++ = c; + *s++ = (char)c; continue; case 7: if (c == '>') state = 0; - else + else if (c != '-') state = 2; - *s++ = c; + *s++ = (char)c; continue; /* PI */ case 8: if (c == '>') state = 0; - else + else if (c != '?') state = 3; - *s++ = c; + *s++ = (char)c; continue; } switch (c) @@ -8751,14 +15989,24 @@ soap_string_in(struct soap *soap, int flag, long minlen, long maxlen) m = 1; break; case SOAP_LT: - if (f && n == 0) - goto end; + if (flag == 3 || (f && n == 0)) + goto end; n++; *s++ = '<'; break; + case SOAP_GT: + *s++ = '>'; + break; + case SOAP_QT: + *s++ = '"'; + break; + case SOAP_AP: + *s++ = '\''; + break; case '/': if (n > 0) - { c = soap_getchar(soap); + { + c = soap_getchar(soap); if (c == '>') n--; soap_unget(soap, c); @@ -8768,17 +16016,23 @@ soap_string_in(struct soap *soap, int flag, long minlen, long maxlen) case '<': c = soap_getchar(soap); if (c == '/') - { if (n == 0) - { c = SOAP_TT; + { + if (n == 0) + { + c = SOAP_TT; goto end; } n--; } else if (c == '!') - { c = soap_getchar(soap); + { + c = soap_getchar(soap); if (c == '[') - { do c = soap_getchar(soap); - while ((int)c != EOF && c != '['); + { + do + { + c = soap_getchar(soap); + } while ((int)c != EOF && c != '['); if ((int)c == EOF) goto end; t = (char*)"![CDATA["; @@ -8786,14 +16040,17 @@ soap_string_in(struct soap *soap, int flag, long minlen, long maxlen) state = 1; } else if (c == '-') - { if ((c = soap_getchar(soap)) == '-') + { + c = soap_getchar(soap); + if (c == '-') state = 2; t = (char*)"!-"; m = 2; soap_unget(soap, c); } else - { t = (char*)"!"; + { + t = (char*)"!"; m = 1; soap_unget(soap, c); } @@ -8801,13 +16058,16 @@ soap_string_in(struct soap *soap, int flag, long minlen, long maxlen) break; } else if (c == '?') + { state = 3; - else if (f && n == 0) - { soap_revget1(soap); - c = '<'; - goto end; - } - else + } + else if (flag == 3 || (f && n == 0)) + { + soap_revget1(soap); + c = '<'; + goto end; + } + else n++; soap_unget(soap, c); *s++ = '<'; @@ -8821,15 +16081,23 @@ soap_string_in(struct soap *soap, int flag, long minlen, long maxlen) default: #ifndef WITH_LEANER #ifdef HAVE_WCTOMB - if (soap->mode & SOAP_C_MBSTRING) - { m = wctomb(buf, c & 0x7FFFFFFF); + if ((soap->mode & SOAP_C_MBSTRING)) + { +#if defined(WIN32) && !defined(CYGWIN) && !defined(__MINGW32__) && !defined(__MINGW64__) && !defined(__BORLANDC__) + m = 0; + wctomb_s(&m, buf, sizeof(buf), (wchar_t)(c & 0x7FFFFFFF)); +#else + m = wctomb(buf, (wchar_t)(c & 0x7FFFFFFF)); +#endif if (m >= 1 && m <= (int)MB_CUR_MAX) - { t = buf; + { + t = buf; *s++ = *t++; m--; } else - { *s++ = SOAP_UNKNOWN_CHAR; + { + *s++ = SOAP_UNKNOWN_CHAR; m = 0; } } @@ -8839,8 +16107,9 @@ soap_string_in(struct soap *soap, int flag, long minlen, long maxlen) *s++ = (char)(c & 0xFF); } l++; - if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen) - { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); + if (maxlen >= 0 && l > (size_t)maxlen) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); soap->error = SOAP_LENGTH; return NULL; } @@ -8849,65 +16118,99 @@ soap_string_in(struct soap *soap, int flag, long minlen, long maxlen) } #endif #ifdef WITH_FAST - soap->labidx = 0; /* use look-aside buffer */ + soap->labidx = 0; /* use look-aside buffer */ #else - if (soap_new_block(soap) == NULL) + if (soap_alloc_block(soap) == NULL) return NULL; #endif for (;;) { #ifdef WITH_FAST size_t k; - if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */ + if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */ return NULL; - s = soap->labbuf + soap->labidx; /* space to populate */ - k = soap->lablen - soap->labidx; /* number of bytes available */ - soap->labidx = soap->lablen; /* claim this space */ + s = soap->labbuf + soap->labidx; /* space to populate */ + k = soap->lablen - soap->labidx; /* number of bytes available */ + soap->labidx = soap->lablen; /* claim this space */ #else size_t k = SOAP_BLKLEN; - if (!(s = (char*)soap_push_block(soap, NULL, k))) + s = (char*)soap_push_block(soap, NULL, k); + if (!s) return NULL; #endif for (i = 0; i < k; i++) - { if (m > 0) - { *s++ = *t++; /* copy multibyte characters */ + { + if (m > 0) + { + *s++ = *t++; /* copy multibyte characters */ m--; continue; } - if (soap->mode & SOAP_C_UTFSTRING) - { if (((c = soap_get(soap)) & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP) - { c &= 0x7FFFFFFF; - t = buf; - if (c < 0x0800) - *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); - else - { if (c < 0x010000) - *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); +#ifndef WITH_CDATA + if (flag <= 0) + c = soap_getchar(soap); + else +#endif + { + c = soap_getutf8(soap); + if ((soap->mode & SOAP_C_UTFSTRING)) + { + if (c >= 0x80 || (c < SOAP_AP && c >= -0x7FFFFF80)) + { + c &= 0x7FFFFFFF; + t = buf; + if (c < 0x0800) + { + *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); + } else - { if (c < 0x200000) - *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + { +#ifdef WITH_REPLACE_ILLEGAL_UTF8 + if (!((c >= 0x80 && c <= 0xD7FF) || (c >= 0xE000 && c <= 0xFFFD) || (c >= 0x10000 && c <= 0x10FFFF))) + c = SOAP_UNKNOWN_UNICODE_CHAR; +#endif + if (c < 0x010000) + { + *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); + } else - { if (c < 0x04000000) - *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + { + if (c < 0x200000) + { + *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + } else - { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); - *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); + { + if (c < 0x04000000) + { + *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + } + else + { + *t++ = (char)(0xFC | ((c >> 30) & 0x01)); + *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); } - *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); + *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); } - *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); + *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); + } + *t++ = (char)(0x80 | (c & 0x3F)); + m = (int)(t - buf) - 1; + t = buf; + *s++ = *t++; + l++; + if (maxlen >= 0 && l > (size_t)maxlen) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); + soap->error = SOAP_LENGTH; + return NULL; } - *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); + continue; } - *t++ = (char)(0x80 | (c & 0x3F)); - m = (int)(t - buf) - 1; - t = buf; - *s++ = *t++; - continue; } } - else - c = soap_getutf8(soap); switch (c) { case SOAP_TT: @@ -8919,8 +16222,8 @@ soap_string_in(struct soap *soap, int flag, long minlen, long maxlen) m = 1; break; case SOAP_LT: - if (f && n == 0) - goto end; + if (flag == 3 || (f && n == 0)) + goto end; n++; *s++ = '<'; break; @@ -8935,54 +16238,79 @@ 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 > 0) + { + c = soap_get(soap); + if (c == SOAP_GT) + n--; + } + else + { + c = soap_getchar(soap); + if (c == '>') + n--; + } soap_unget(soap, c); } *s++ = '/'; break; case (soap_wchar)('<' | 0x80000000): - if (flag) + if (flag > 0) + { *s++ = '<'; + } else - { *s++ = '&'; + { + *s++ = '&'; t = (char*)"lt;"; m = 3; } break; case (soap_wchar)('>' | 0x80000000): - if (flag) + if (flag > 0) + { *s++ = '>'; + } else - { *s++ = '&'; + { + *s++ = '&'; t = (char*)"gt;"; m = 3; } break; case (soap_wchar)('&' | 0x80000000): - if (flag) + if (flag > 0) + { *s++ = '&'; + } else - { *s++ = '&'; + { + *s++ = '&'; t = (char*)"amp;"; m = 4; } break; case (soap_wchar)('"' | 0x80000000): - if (flag) + if (flag > 0) + { *s++ = '"'; + } else - { *s++ = '&'; + { + *s++ = '&'; t = (char*)"quot;"; m = 5; } break; case (soap_wchar)('\'' | 0x80000000): - if (flag) + if (flag > 0) + { *s++ = '\''; + } else - { *s++ = '&'; + { + *s++ = '&'; t = (char*)"apos;"; m = 5; } @@ -8990,17 +16318,45 @@ soap_string_in(struct soap *soap, int flag, long minlen, long maxlen) default: if ((int)c == EOF) goto end; +#ifndef WITH_CDATA + if (c == '<') + { + c = soap_getchar(soap); + soap_unget(soap, c); + if (c == '/') + { + c = SOAP_TT; + if (n == 0) + goto end; + n--; + } + else + { + n++; + } + *s++ = '<'; + } + else +#endif #ifndef WITH_LEANER #ifdef HAVE_WCTOMB - if (soap->mode & SOAP_C_MBSTRING) - { m = wctomb(buf, c & 0x7FFFFFFF); + if ((soap->mode & SOAP_C_MBSTRING)) + { +#if defined(WIN32) && !defined(CYGWIN) && !defined(__MINGW32__) && !defined(__MINGW64__) && !defined(__BORLANDC__) + m = 0; + wctomb_s(&m, buf, sizeof(buf), (wchar_t)(c & 0x7FFFFFFF)); +#else + m = wctomb(buf, (wchar_t)(c & 0x7FFFFFFF)); +#endif if (m >= 1 && m <= (int)MB_CUR_MAX) - { t = buf; + { + t = buf; *s++ = *t++; m--; } else - { *s++ = SOAP_UNKNOWN_CHAR; + { + *s++ = SOAP_UNKNOWN_CHAR; m = 0; } } @@ -9010,8 +16366,9 @@ soap_string_in(struct soap *soap, int flag, long minlen, long maxlen) *s++ = (char)(c & 0xFF); } l++; - if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen) - { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); + if (maxlen >= 0 && l > (size_t)maxlen) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); soap->error = SOAP_LENGTH; return NULL; } @@ -9022,54 +16379,78 @@ soap_string_in(struct soap *soap, int flag, long minlen, long maxlen) *s = '\0'; #ifdef WITH_FAST t = soap_strdup(soap, soap->labbuf); + if (!t) + return NULL; #else - soap_size_block(soap, NULL, i+1); - t = soap_save_block(soap, NULL, 0); + soap_size_block(soap, NULL, i + 1); + t = (char*)soap_save_block(soap, NULL, NULL, 0); #endif - if ((soap->mode & SOAP_XML_STRICT) && l < minlen) - { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen)); + if (minlen > 0 && l < (size_t)minlen) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "String too short: %lu chars, minlen=%ld\n", (unsigned long)l, minlen)); soap->error = SOAP_LENGTH; return NULL; } #ifdef WITH_DOM - if ((soap->mode & SOAP_XML_DOM) && soap->dom) - { if (flag == 3) - soap->dom->tail = t; + if ((soap->mode & SOAP_XML_DOM) && soap->dom && *t) + { + if (flag > 0) + { + soap->dom->text = t; + } else - soap->dom->data = t; + { + soap->dom->code = t; + if (flag < 0) + { + /* the tag URI and name are already in the XML code string */ + soap->dom->nstr = NULL; + soap->dom->name = NULL; + } + } } #endif if (flag == 2) - if (soap_s2QName(soap, t, &t, minlen, maxlen)) + { + if (soap_s2QName(soap, t, &t, minlen, maxlen, pattern)) + return NULL; + } + else if (flag >= 4 && t) + { + t = soap_collapse(soap, t, flag, 1); + } +#ifndef WITH_LEANER + else if (pattern && soap->fsvalidate) + { + soap->error = soap->fsvalidate(soap, pattern, t); + if (soap->error) return NULL; + } +#endif return t; } -#endif /******************************************************************************/ + #ifndef WITH_LEANER -#ifndef PALM_2 SOAP_FMAC1 int SOAP_FMAC2 soap_wstring_out(struct soap *soap, const wchar_t *s, int flag) -{ const char *t; +{ + const char *t; char tmp; soap_wchar c; #ifdef WITH_DOM if ((soap->mode & SOAP_XML_DOM) && soap->dom) - { wchar_t *r = (wchar_t*)s; - int n = 1; - while (*r++) - n++; - soap->dom->wide = r = (wchar_t*)soap_malloc(soap, n * sizeof(wchar_t)); - while (n--) - *r++ = *s++; + { + soap->dom->text = soap_wchar2s(soap, s); return SOAP_OK; } #endif while ((c = *s++)) - { switch (c) + { + switch (c) { case 0x09: if (flag) @@ -9078,14 +16459,21 @@ soap_wstring_out(struct soap *soap, const wchar_t *s, int flag) t = "\t"; break; case 0x0A: - if (flag || !(soap->mode & SOAP_XML_CANONICAL)) + if (flag) t = " "; else t = "\n"; break; +#ifdef WITH_CR_TO_LF case 0x0D: - t = " "; + if (*s == 0x0A) + continue; + if (flag) + t = " "; + else + t = "\n"; break; +#endif case '&': t = "&"; break; @@ -9106,12 +16494,32 @@ soap_wstring_out(struct soap *soap, const wchar_t *s, int flag) break; default: if (c >= 0x20 && c < 0x80) - { tmp = (char)c; + { + tmp = (char)c; if (soap_send_raw(soap, &tmp, 1)) return soap->error; } - else if (soap_pututf8(soap, (unsigned long)c)) - return soap->error; + else + { + /* check for UTF16 encoding when wchar_t is too small to hold UCS */ + if (sizeof(wchar_t) < 4 && (c & 0xFC00) == 0xD800) + { + soap_wchar d = *s; + if ((d & 0xFC00) == 0xDC00) + { + c = ((c - 0xD800) << 10) + (d - 0xDC00) + 0x10000; + s++; + } +#ifdef WITH_REPLACE_ILLEGAL_UTF8 + else + { + c = SOAP_UNKNOWN_UNICODE_CHAR; /* Malformed UTF-16 */ + } +#endif + } + if (soap_pututf8(soap, (unsigned long)c)) + return soap->error; + } continue; } if (soap_send(soap, t)) @@ -9120,69 +16528,77 @@ soap_wstring_out(struct soap *soap, const wchar_t *s, int flag) return SOAP_OK; } #endif -#endif /******************************************************************************/ + #ifndef WITH_LEANER -#ifndef PALM_2 SOAP_FMAC1 wchar_t * SOAP_FMAC2 -soap_wstring_in(struct soap *soap, int flag, long minlen, long maxlen) -{ wchar_t *s; +soap_wstring_in(struct soap *soap, int flag, long minlen, long maxlen, const char *pattern) +{ + wchar_t *s; int i, n = 0, f = 0; - long l = 0; + ULONG64 l = 0; soap_wchar c; char *t = NULL; - DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading wide string content\n")); - if (soap->peeked) - { if (*soap->tag) - { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reading wide string content\n")); + if (maxlen < 0 && soap->maxlength > 0) + maxlen = soap->maxlength; + if (flag <= 0 && soap->peeked && *soap->tag) + { #ifndef WITH_LEAN - struct soap_attribute *tp; - t = soap->tmpbuf; - *t = '<'; - t[sizeof(soap->tmpbuf)-1] = '\0'; - strncpy(t + 1, soap->tag, sizeof(soap->tmpbuf) - 2); - t += strlen(t); - for (tp = soap->attributes; tp; tp = tp->next) - { if (tp->visible) - { if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2) - break; - *t++ = ' '; - strcpy(t, tp->name); - t += strlen(t); - if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2) + struct soap_attribute *tp; + t = soap->tmpbuf; + *t = '<'; + soap_strcpy(t + 1, sizeof(soap->tmpbuf) - 1, soap->tag); + t += strlen(t); + for (tp = soap->attributes; tp; tp = tp->next) + { + if (tp->visible) + { + size_t k = strlen(tp->name); + if (t + k + 1 >= soap->tmpbuf + sizeof(soap->tmpbuf)) + break; + *t++ = ' '; + (void)soap_strncpy(t, sizeof(soap->tmpbuf) - (t - soap->tmpbuf), tp->name, k); + t += k; + if (tp->value) + { + k = strlen(tp->value); + if (t + k + 3 >= soap->tmpbuf + sizeof(soap->tmpbuf)) break; - if (tp->value) - { *t++ = '='; - *t++ = '"'; - strcpy(t, tp->value); - t += strlen(t); - *t++ = '"'; - } + *t++ = '='; + *t++ = '"'; + (void)soap_strncpy(t, sizeof(soap->tmpbuf) - (t - soap->tmpbuf), tp->value, k); + t += k; + *t++ = '"'; } } - if (!soap->body) - *t++ = '/'; - *t++ = '>'; - *t = '\0'; - t = soap->tmpbuf; -#endif - if (soap->body) - n = 1; - f = 1; - soap->peeked = 0; } + if (!soap->body) + *t++ = '/'; + *t++ = '>'; + *t = '\0'; + t = soap->tmpbuf; +#endif + if (soap->body) + n = 1; + f = 1; + soap->peeked = 0; } - if (soap_new_block(soap) == NULL) + if (soap_alloc_block(soap) == NULL) return NULL; for (;;) - { if (!(s = (wchar_t*)soap_push_block(soap, NULL, sizeof(wchar_t)*SOAP_BLKLEN))) + { + s = (wchar_t*)soap_push_block(soap, NULL, sizeof(wchar_t)*SOAP_BLKLEN); + if (!s) return NULL; for (i = 0; i < SOAP_BLKLEN; i++) - { if (t) - { *s++ = (wchar_t)*t++; + { + if (t) + { + *s++ = (wchar_t)*t++; if (!*t) t = NULL; continue; @@ -9194,65 +16610,85 @@ soap_wstring_in(struct soap *soap, int flag, long minlen, long maxlen) if (n == 0) goto end; n--; - *s++ = '<'; + *s++ = L'<'; soap_unget(soap, '/'); break; case SOAP_LT: - if (f && n == 0) - goto end; + if (flag == 3 || (f && n == 0)) + goto end; n++; - *s++ = '<'; + *s++ = L'<'; break; case SOAP_GT: - *s++ = '>'; + *s++ = L'>'; break; case SOAP_QT: - *s++ = '"'; + *s++ = L'"'; break; case SOAP_AP: - *s++ = '\''; + *s++ = L'\''; break; case '/': if (n > 0) - { c = soap_getutf8(soap); + { + c = soap_getutf8(soap); if (c == SOAP_GT) n--; soap_unget(soap, c); } - *s++ = '/'; + *s++ = L'/'; break; case '<': - if (flag) - *s++ = (soap_wchar)'<'; + if (flag > 0) + { + *s++ = L'<'; + } else - { *s++ = (soap_wchar)'&'; + { + *s++ = L'&'; t = (char*)"lt;"; } break; case '>': - if (flag) - *s++ = (soap_wchar)'>'; + if (flag > 0) + { + *s++ = L'>'; + } else - { *s++ = (soap_wchar)'&'; + { + *s++ = (wchar_t)'&'; t = (char*)"gt;"; } break; case '"': - if (flag) - *s++ = (soap_wchar)'"'; + if (flag > 0) + { + *s++ = L'"'; + } else - { *s++ = (soap_wchar)'&'; + { + *s++ = L'&'; t = (char*)"quot;"; } break; default: if ((int)c == EOF) goto end; - *s++ = (wchar_t)c & 0x7FFFFFFF; + /* use UTF16 encoding when wchar_t is too small to hold UCS */ + if (sizeof(wchar_t) < 4 && c > 0xFFFF) + { + soap_wchar c1, c2; + c1 = 0xD800 - (0x10000 >> 10) + (c >> 10); + c2 = 0xDC00 + (c & 0x3FF); + c = c1; + soap_unget(soap, c2); + } + *s++ = (wchar_t)(c & 0x7FFFFFFF); } l++; - if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen) - { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); + if (maxlen >= 0 && l > (size_t)maxlen) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); soap->error = SOAP_LENGTH; return NULL; } @@ -9260,80 +16696,101 @@ soap_wstring_in(struct soap *soap, int flag, long minlen, long maxlen) } end: soap_unget(soap, c); - *s = '\0'; + *s = L'\0'; soap_size_block(soap, NULL, sizeof(wchar_t) * (i + 1)); - if ((soap->mode & SOAP_XML_STRICT) && l < minlen) - { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen)); + if (minlen > 0 && l < (size_t)minlen) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "String too short: %lu chars, minlen=%ld\n", (unsigned long)l, minlen)); soap->error = SOAP_LENGTH; return NULL; } s = (wchar_t*)soap_save_block(soap, NULL, NULL, 0); +#ifndef WITH_LEAN + if (flag >= 4 && s) + s = soap_wcollapse(soap, s, flag, 1); +#endif +#ifndef WITH_LEANER + if (pattern && soap->fwvalidate) + { + soap->error = soap->fwvalidate(soap, pattern, s); + if (soap->error) + return NULL; + } +#endif #ifdef WITH_DOM if ((soap->mode & SOAP_XML_DOM) && soap->dom) - soap->dom->wide = s; + soap->dom->text = soap_wchar2s(soap, s); #endif return s; } #endif -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 const char* SOAP_FMAC2 soap_int2s(struct soap *soap, int n) -{ return soap_long2s(soap, (long)n); +{ + return soap_long2s(soap, (long)n); } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 soap_outint(struct soap *soap, const char *tag, int id, const int *p, const char *type, int n) -{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) +{ + if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) || soap_string_out(soap, soap_long2s(soap, (long)*p), 0)) return soap->error; return soap_element_end_out(soap, tag); } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 soap_s2int(struct soap *soap, const char *s, int *p) -{ if (s) - { char *r; +{ + if (s) + { + long n; + char *r; + if (!*s) + return soap->error = SOAP_EMPTY; #ifndef WITH_NOIO #ifndef WITH_LEAN soap_reset_errno; #endif #endif - *p = (int)soap_strtol(s, &r, 10); - if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r + n = soap_strtol(s, &r, 10); + if (s == r || *r +#ifndef WITH_LEAN + || n != (int)n +#endif #ifndef WITH_NOIO #ifndef WITH_LEAN - || soap_errno == SOAP_ERANGE + || soap_errno == SOAP_ERANGE #endif #endif ) soap->error = SOAP_TYPE; + *p = (int)n; } return soap->error; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int * SOAP_FMAC2 soap_inint(struct soap *soap, const char *tag, int *p, const char *type, int t) -{ if (soap_element_begin_in(soap, tag, 0, NULL)) +{ + if (soap_element_begin_in(soap, tag, 0, NULL)) return NULL; #ifndef WITH_LEAN if (*soap->type @@ -9341,66 +16798,78 @@ soap_inint(struct soap *soap, const char *tag, int *p, const char *type, int t) && soap_match_tag(soap, soap->type, ":int") && soap_match_tag(soap, soap->type, ":short") && soap_match_tag(soap, soap->type, ":byte")) - { soap->error = SOAP_TYPE; + { + soap->error = SOAP_TYPE; soap_revert(soap); return NULL; } +#else + (void)type; #endif - p = (int*)soap_id_enter(soap, soap->id, p, t, sizeof(int), 0, NULL, NULL, NULL); - if (*soap->href) - p = (int*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(int), 0, NULL); - else if (p) - { if (soap_s2int(soap, soap_value(soap), p)) + p = (int*)soap_id_enter(soap, soap->id, p, t, sizeof(int), NULL, NULL, NULL, NULL); + if (!p) + return NULL; + if (*soap->href != '#') + { + int err = soap_s2int(soap, soap_value(soap), p); + if ((soap->body && soap_element_end_in(soap, tag)) || err) + return NULL; + } + else + { + p = (int*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(int), 0, NULL, NULL); + if (soap->body && soap_element_end_in(soap, tag)) return NULL; } - if (soap->body && soap_element_end_in(soap, tag)) - return NULL; return p; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 const char* SOAP_FMAC2 soap_long2s(struct soap *soap, long n) -{ sprintf(soap->tmpbuf, "%ld", n); +{ + (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 20), "%ld", n); return soap->tmpbuf; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 soap_outlong(struct soap *soap, const char *tag, int id, const long *p, const char *type, int n) -{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) +{ + if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) || soap_string_out(soap, soap_long2s(soap, *p), 0)) return soap->error; return soap_element_end_out(soap, tag); } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 soap_s2long(struct soap *soap, const char *s, long *p) -{ if (s) - { char *r; +{ + if (s) + { + char *r; + if (!*s) + return soap->error = SOAP_EMPTY; #ifndef WITH_NOIO #ifndef WITH_LEAN soap_reset_errno; #endif #endif *p = soap_strtol(s, &r, 10); - if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r + if (s == r || *r #ifndef WITH_NOIO #ifndef WITH_LEAN - || soap_errno == SOAP_ERANGE + || soap_errno == SOAP_ERANGE #endif #endif ) @@ -9408,15 +16877,15 @@ soap_s2long(struct soap *soap, const char *s, long *p) } return soap->error; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 long * SOAP_FMAC2 soap_inlong(struct soap *soap, const char *tag, long *p, const char *type, int t) -{ if (soap_element_begin_in(soap, tag, 0, NULL)) +{ + if (soap_element_begin_in(soap, tag, 0, NULL)) return NULL; #ifndef WITH_LEAN if (*soap->type @@ -9424,89 +16893,94 @@ soap_inlong(struct soap *soap, const char *tag, long *p, const char *type, int t && soap_match_tag(soap, soap->type, ":int") && soap_match_tag(soap, soap->type, ":short") && soap_match_tag(soap, soap->type, ":byte")) - { soap->error = SOAP_TYPE; + { + soap->error = SOAP_TYPE; soap_revert(soap); return NULL; } +#else + (void)type; #endif - p = (long*)soap_id_enter(soap, soap->id, p, t, sizeof(long), 0, NULL, NULL, NULL); - if (*soap->href) - p = (long*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(long), 0, NULL); - else if (p) - { if (soap_s2long(soap, soap_value(soap), p)) + p = (long*)soap_id_enter(soap, soap->id, p, t, sizeof(long), NULL, NULL, NULL, NULL); + if (!p) + return NULL; + if (*soap->href != '#') + { + int err = soap_s2long(soap, soap_value(soap), p); + if ((soap->body && soap_element_end_in(soap, tag)) || err) + return NULL; + } + else + { + p = (long*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(long), 0, NULL, NULL); + if (soap->body && soap_element_end_in(soap, tag)) return NULL; } - if (soap->body && soap_element_end_in(soap, tag)) - return NULL; return p; } -#endif /******************************************************************************/ -#ifndef WITH_LEAN + SOAP_FMAC1 const char* SOAP_FMAC2 soap_LONG642s(struct soap *soap, LONG64 n) -{ sprintf(soap->tmpbuf, SOAP_LONG_FORMAT, n); +{ + (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 20), SOAP_LONG_FORMAT, n); return soap->tmpbuf; } -#endif /******************************************************************************/ -#ifndef WITH_LEAN + SOAP_FMAC1 int SOAP_FMAC2 soap_outLONG64(struct soap *soap, const char *tag, int id, const LONG64 *p, const char *type, int n) -{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) +{ + if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) || soap_string_out(soap, soap_LONG642s(soap, *p), 0)) return soap->error; return soap_element_end_out(soap, tag); } -#endif /******************************************************************************/ -#ifndef WITH_LEAN + SOAP_FMAC1 int SOAP_FMAC2 soap_s2LONG64(struct soap *soap, const char *s, LONG64 *p) -{ if (s) +{ + if (s) { -#ifdef HAVE_STRTOLL char *r; + if (!*s) + return soap->error = SOAP_EMPTY; #ifndef WITH_NOIO #ifndef WITH_LEAN soap_reset_errno; #endif #endif - *p = strtoll(s, &r, 10); - if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r + *p = soap_strtoll(s, &r, 10); + if (s == r || *r #ifndef WITH_NOIO #ifndef WITH_LEAN - || soap_errno == SOAP_ERANGE + || soap_errno == SOAP_ERANGE #endif #endif ) -#else -# ifdef HAVE_SSCANF - if (sscanf(s, SOAP_LONG_FORMAT, p) != 1) -# endif -#endif soap->error = SOAP_TYPE; } return soap->error; } -#endif /******************************************************************************/ -#ifndef WITH_LEAN + SOAP_FMAC1 LONG64 * SOAP_FMAC2 soap_inLONG64(struct soap *soap, const char *tag, LONG64 *p, const char *type, int t) -{ if (soap_element_begin_in(soap, tag, 0, NULL)) +{ + if (soap_element_begin_in(soap, tag, 0, NULL)) return NULL; #ifndef WITH_LEAN if (*soap->type @@ -9520,56 +16994,68 @@ soap_inLONG64(struct soap *soap, const char *tag, LONG64 *p, const char *type, i && soap_match_tag(soap, soap->type, ":int") && soap_match_tag(soap, soap->type, ":short") && soap_match_tag(soap, soap->type, ":byte")) - { soap->error = SOAP_TYPE; + { + soap->error = SOAP_TYPE; soap_revert(soap); return NULL; } +#else + (void)type; #endif - p = (LONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(LONG64), 0, NULL, NULL, NULL); - if (*soap->href) - p = (LONG64*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(LONG64), 0, NULL); - else if (p) - { if (soap_s2LONG64(soap, soap_value(soap), p)) + p = (LONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(LONG64), NULL, NULL, NULL, NULL); + if (!p) + return NULL; + if (*soap->href != '#') + { + int err = soap_s2LONG64(soap, soap_value(soap), p); + if ((soap->body && soap_element_end_in(soap, tag)) || err) + return NULL; + } + else + { + p = (LONG64*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(LONG64), 0, NULL, NULL); + if (soap->body && soap_element_end_in(soap, tag)) return NULL; } - if (soap->body && soap_element_end_in(soap, tag)) - return NULL; return p; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 const char* SOAP_FMAC2 soap_byte2s(struct soap *soap, char n) -{ return soap_long2s(soap, (long)n); +{ + return soap_long2s(soap, (long)n); } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 soap_outbyte(struct soap *soap, const char *tag, int id, const char *p, const char *type, int n) -{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) +{ + if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) || soap_string_out(soap, soap_long2s(soap, (long)*p), 0)) return soap->error; return soap_element_end_out(soap, tag); } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 soap_s2byte(struct soap *soap, const char *s, char *p) -{ if (s) - { long n; +{ + if (s) + { + long n; char *r; + if (!*s) + return soap->error = SOAP_EMPTY; n = soap_strtol(s, &r, 10); if (s == r || *r || n < -128 || n > 127) soap->error = SOAP_TYPE; @@ -9577,70 +17063,82 @@ soap_s2byte(struct soap *soap, const char *s, char *p) } return soap->error; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 char * SOAP_FMAC2 soap_inbyte(struct soap *soap, const char *tag, char *p, const char *type, int t) -{ if (soap_element_begin_in(soap, tag, 0, NULL)) +{ + if (soap_element_begin_in(soap, tag, 0, NULL)) return NULL; #ifndef WITH_LEAN if (*soap->type && soap_match_tag(soap, soap->type, type) && soap_match_tag(soap, soap->type, ":byte")) - { soap->error = SOAP_TYPE; + { + soap->error = SOAP_TYPE; soap_revert(soap); return NULL; } +#else + (void)type; #endif - p = (char*)soap_id_enter(soap, soap->id, p, t, sizeof(char), 0, NULL, NULL, NULL); - if (*soap->href) - p = (char*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(char), 0, NULL); - else if (p) - { if (soap_s2byte(soap, soap_value(soap), p)) + p = (char*)soap_id_enter(soap, soap->id, p, t, sizeof(char), NULL, NULL, NULL, NULL); + if (!p) + return NULL; + if (*soap->href != '#') + { + int err = soap_s2byte(soap, soap_value(soap), p); + if ((soap->body && soap_element_end_in(soap, tag)) || err) + return NULL; + } + else + { + p = (char*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(char), 0, NULL, NULL); + if (soap->body && soap_element_end_in(soap, tag)) return NULL; } - if (soap->body && soap_element_end_in(soap, tag)) - return NULL; return p; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 const char* SOAP_FMAC2 soap_short2s(struct soap *soap, short n) -{ return soap_long2s(soap, (long)n); +{ + return soap_long2s(soap, (long)n); } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 soap_outshort(struct soap *soap, const char *tag, int id, const short *p, const char *type, int n) -{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) +{ + if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) || soap_string_out(soap, soap_long2s(soap, (long)*p), 0)) return soap->error; return soap_element_end_out(soap, tag); } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 soap_s2short(struct soap *soap, const char *s, short *p) -{ if (s) - { long n; +{ + if (s) + { + long n; char *r; + if (!*s) + return soap->error = SOAP_EMPTY; n = soap_strtol(s, &r, 10); if (s == r || *r || n < -32768 || n > 32767) soap->error = SOAP_TYPE; @@ -9648,136 +17146,200 @@ soap_s2short(struct soap *soap, const char *s, short *p) } return soap->error; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 short * SOAP_FMAC2 soap_inshort(struct soap *soap, const char *tag, short *p, const char *type, int t) -{ if (soap_element_begin_in(soap, tag, 0, NULL)) +{ + if (soap_element_begin_in(soap, tag, 0, NULL)) return NULL; #ifndef WITH_LEAN if (*soap->type && soap_match_tag(soap, soap->type, type) && soap_match_tag(soap, soap->type, ":short") && soap_match_tag(soap, soap->type, ":byte")) - { soap->error = SOAP_TYPE; + { + soap->error = SOAP_TYPE; soap_revert(soap); return NULL; } +#else + (void)type; #endif - p = (short*)soap_id_enter(soap, soap->id, p, t, sizeof(short), 0, NULL, NULL, NULL); - if (*soap->href) - p = (short*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(short), 0, NULL); - else if (p) - { if (soap_s2short(soap, soap_value(soap), p)) + p = (short*)soap_id_enter(soap, soap->id, p, t, sizeof(short), NULL, NULL, NULL, NULL); + if (!p) + return NULL; + if (*soap->href != '#') + { + int err = soap_s2short(soap, soap_value(soap), p); + if ((soap->body && soap_element_end_in(soap, tag)) || err) + return NULL; + } + else + { + p = (short*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(short), 0, NULL, NULL); + if (soap->body && soap_element_end_in(soap, tag)) return NULL; } - if (soap->body && soap_element_end_in(soap, tag)) - return NULL; return p; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 const char* SOAP_FMAC2 soap_float2s(struct soap *soap, float n) -{ char *s; +{ +#if defined(WITH_C_LOCALE) +# if !defined(WIN32) + SOAP_LOCALE_T locale; +# endif +#else + char *s; +#endif if (soap_isnan((double)n)) return "NaN"; if (soap_ispinff(n)) return "INF"; if (soap_isninff(n)) return "-INF"; - s = soap->tmpbuf; -#if defined(HAVE_SPRINTF_L) - sprintf_l(s, soap->c_locale, soap->float_format, n); +#if defined(WITH_C_LOCALE) +# ifdef WIN32 + _sprintf_s_l(soap->tmpbuf, _countof(soap->tmpbuf), soap->float_format, SOAP_LOCALE(soap), n); +# else + locale = uselocale(SOAP_LOCALE(soap)); + (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 80), soap->float_format, n); + uselocale(locale); +# endif #else - sprintf(s, soap->float_format, n); - s = strchr(s, ','); /* convert decimal comma to DP */ + (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 80), soap->float_format, n); + s = strchr(soap->tmpbuf, ','); /* convert decimal comma to DP */ if (s) *s = '.'; #endif return soap->tmpbuf; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 soap_outfloat(struct soap *soap, const char *tag, int id, const float *p, const char *type, int n) -{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) +{ + if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) || soap_string_out(soap, soap_float2s(soap, *p), 0)) return soap->error; return soap_element_end_out(soap, tag); } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 soap_s2float(struct soap *soap, const char *s, float *p) -{ if (s) - { if (!*s) - return soap->error = SOAP_TYPE; +{ + if (s) + { + if (!*s) + return soap->error = SOAP_EMPTY; if (!soap_tag_cmp(s, "INF")) + { *p = FLT_PINFTY; + } else if (!soap_tag_cmp(s, "+INF")) + { *p = FLT_PINFTY; + } else if (!soap_tag_cmp(s, "-INF")) + { *p = FLT_NINFTY; + } else if (!soap_tag_cmp(s, "NaN")) + { *p = FLT_NAN; + } else { -/* On some systems strtof requires -std=c99 or does not even link: so we try to use strtod first */ -#if defined(HAVE_STRTOD_L) +/* On some systems strtof requires -std=c99 or does not even link: so we try strtod first */ +#if defined(WITH_C_LOCALE) +# if defined(HAVE_STRTOD_L) + char *r; +# ifdef WIN32 + *p = (float)_strtod_l(s, &r, SOAP_LOCALE(soap)); +# else + *p = (float)strtod_l(s, &r, SOAP_LOCALE(soap)); +# endif + if (*r) + soap->error = SOAP_TYPE; +# elif defined(HAVE_STRTOF_L) char *r; - *p = (float)strtod_l(s, &r, soap->c_locale); + *p = strtof_l((char*)s, &r, SOAP_LOCALE(soap)); if (*r) -#elif defined(HAVE_STRTOD) + soap->error = SOAP_TYPE; +# elif defined(HAVE_SSCANF_L) + double n; + if (sscanf_l(s, SOAP_LOCALE(soap), "%lf", &n) != 1) + soap->error = SOAP_TYPE; + *p = (float)n; +# elif defined(HAVE_STRTOD) char *r; - *p = (float)strtod(s, &r); + SOAP_LOCALE_T locale = uselocale(SOAP_LOCALE(soap)); + *p = (float)strtod((char*)s, &r); + uselocale(locale); if (*r) -#elif defined(HAVE_STRTOF_L) + soap->error = SOAP_TYPE; +# elif defined(HAVE_STRTOF) + char *r; + SOAP_LOCALE_T locale = uselocale(SOAP_LOCALE(soap)); + *p = strtof((char*)s, &r); + uselocale(locale); + if (*r) + soap->error = SOAP_TYPE; +# elif defined(HAVE_SSCANF) + double n; + SOAP_LOCALE_T locale = uselocale(SOAP_LOCALE(soap)); + if (sscanf(s, "%lf", &n) != 1) + soap->error = SOAP_TYPE; + uselocale(locale); + *p = (float)n; +# else + soap->error = SOAP_TYPE; +# endif +#elif defined(HAVE_STRTOD) char *r; - *p = strtof_l((char*)s, &r, soap->c_locale); + *p = (float)strtod(s, &r); if (*r) + soap->error = SOAP_TYPE; #elif defined(HAVE_STRTOF) char *r; *p = strtof((char*)s, &r); if (*r) -#endif - { -#if defined(HAVE_SSCANF_L) && !defined(HAVE_STRTOF_L) && !defined(HAVE_STRTOD_L) - if (sscanf_l(s, soap->c_locale, "%g", p) != 1) - soap->error = SOAP_TYPE; + soap->error = SOAP_TYPE; #elif defined(HAVE_SSCANF) - if (sscanf(s, "%g", p) != 1) - soap->error = SOAP_TYPE; -#else + double n; + if (sscanf(s, "%lf", &n) != 1) soap->error = SOAP_TYPE; + *p = (float)n; +#else + soap->error = SOAP_TYPE; #endif - } } } return soap->error; } -#endif /******************************************************************************/ + #ifndef WITH_LEAN static int soap_isnumeric(struct soap *soap, const char *type) -{ if (soap_match_tag(soap, soap->type, type) +{ + if (soap_match_tag(soap, soap->type, type) && soap_match_tag(soap, soap->type, ":float") && soap_match_tag(soap, soap->type, ":double") && soap_match_tag(soap, soap->type, ":decimal") @@ -9794,7 +17356,8 @@ static int soap_isnumeric(struct soap *soap, const char *type) && soap_match_tag(soap, soap->type, ":unsignedInt") && soap_match_tag(soap, soap->type, ":unsignedShort") && soap_match_tag(soap, soap->type, ":unsignedByte")) - { soap->error = SOAP_TYPE; + { + soap->error = SOAP_TYPE; soap_revert(soap); return SOAP_ERR; } @@ -9803,339 +17366,428 @@ static int soap_isnumeric(struct soap *soap, const char *type) #endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 float * SOAP_FMAC2 soap_infloat(struct soap *soap, const char *tag, float *p, const char *type, int t) -{ if (soap_element_begin_in(soap, tag, 0, NULL)) +{ + if (soap_element_begin_in(soap, tag, 0, NULL)) return NULL; #ifndef WITH_LEAN if (*soap->type != '\0' && soap_isnumeric(soap, type)) return NULL; +#else + (void)type; #endif - p = (float*)soap_id_enter(soap, soap->id, p, t, sizeof(float), 0, NULL, NULL, NULL); - if (*soap->href) - p = (float*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(float), 0, NULL); - else if (p) - { if (soap_s2float(soap, soap_value(soap), p)) + p = (float*)soap_id_enter(soap, soap->id, p, t, sizeof(float), NULL, NULL, NULL, NULL); + if (!p) + return NULL; + if (*soap->href != '#') + { + int err = soap_s2float(soap, soap_value(soap), p); + if ((soap->body && soap_element_end_in(soap, tag)) || err) + return NULL; + } + else + { + p = (float*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(float), 0, NULL, NULL); + if (soap->body && soap_element_end_in(soap, tag)) return NULL; } - if (soap->body && soap_element_end_in(soap, tag)) - return NULL; return p; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 const char* SOAP_FMAC2 soap_double2s(struct soap *soap, double n) -{ char *s; +{ +#if defined(WITH_C_LOCALE) +# if !defined(WIN32) + SOAP_LOCALE_T locale; +# endif +#else + char *s; +#endif if (soap_isnan(n)) return "NaN"; if (soap_ispinfd(n)) return "INF"; if (soap_isninfd(n)) return "-INF"; - s = soap->tmpbuf; -#if defined(HAVE_SPRINTF_L) - sprintf_l(s, soap->c_locale, soap->double_format, n); +#if defined(WITH_C_LOCALE) +# ifdef WIN32 + _sprintf_s_l(soap->tmpbuf, _countof(soap->tmpbuf), soap->double_format, SOAP_LOCALE(soap), n); +# else + locale = uselocale(SOAP_LOCALE(soap)); + (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 80), soap->double_format, n); + uselocale(locale); +# endif #else - sprintf(s, soap->double_format, n); - s = strchr(s, ','); /* convert decimal comma to DP */ + (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 80), soap->double_format, n); + s = strchr(soap->tmpbuf, ','); /* convert decimal comma to DP */ if (s) *s = '.'; #endif return soap->tmpbuf; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 soap_outdouble(struct soap *soap, const char *tag, int id, const double *p, const char *type, int n) -{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) +{ + if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) || soap_string_out(soap, soap_double2s(soap, *p), 0)) return soap->error; return soap_element_end_out(soap, tag); } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 soap_s2double(struct soap *soap, const char *s, double *p) -{ if (s) - { if (!*s) - return soap->error = SOAP_TYPE; +{ + if (s) + { + if (!*s) + return soap->error = SOAP_EMPTY; if (!soap_tag_cmp(s, "INF")) + { *p = DBL_PINFTY; + } else if (!soap_tag_cmp(s, "+INF")) + { *p = DBL_PINFTY; + } else if (!soap_tag_cmp(s, "-INF")) + { *p = DBL_NINFTY; + } else if (!soap_tag_cmp(s, "NaN")) + { *p = DBL_NAN; + } else { -#if defined(HAVE_STRTOD_L) +#if defined(WITH_C_LOCALE) +# if defined(HAVE_STRTOD_L) + char *r; +# ifdef WIN32 + *p = _strtod_l(s, &r, SOAP_LOCALE(soap)); +# else + *p = strtod_l(s, &r, SOAP_LOCALE(soap)); +# endif + if (*r) + soap->error = SOAP_TYPE; +# elif defined(HAVE_STRTOD) char *r; - *p = strtod_l(s, &r, soap->c_locale); + SOAP_LOCALE_T locale = uselocale(SOAP_LOCALE(soap)); + *p = strtod(s, &r); + uselocale(locale); if (*r) + soap->error = SOAP_TYPE; +# elif defined(HAVE_SSCANF_L) + SOAP_LOCALE_T locale = uselocale(SOAP_LOCALE(soap)); + if (sscanf_l(s, SOAP_LOCALE(soap), "%lf", p) != 1) + soap->error = SOAP_TYPE; + uselocale(locale); +# else + soap->error = SOAP_TYPE; +# endif #elif defined(HAVE_STRTOD) char *r; *p = strtod(s, &r); if (*r) -#endif - { -#if defined(HAVE_SSCANF_L) && !defined(HAVE_STRTOF_L) && !defined(HAVE_STRTOD_L) - if (sscanf_l(s, soap->c_locale, "%lg", p) != 1) - soap->error = SOAP_TYPE; + soap->error = SOAP_TYPE; #elif defined(HAVE_SSCANF) - if (sscanf(s, "%lg", p) != 1) - soap->error = SOAP_TYPE; -#else + if (sscanf(s, "%lf", p) != 1) soap->error = SOAP_TYPE; +#else + soap->error = SOAP_TYPE; #endif - } } } return soap->error; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 double * SOAP_FMAC2 soap_indouble(struct soap *soap, const char *tag, double *p, const char *type, int t) -{ if (soap_element_begin_in(soap, tag, 0, NULL)) +{ + if (soap_element_begin_in(soap, tag, 0, NULL)) return NULL; #ifndef WITH_LEAN if (*soap->type != '\0' && soap_isnumeric(soap, type)) return NULL; +#else + (void)type; #endif - p = (double*)soap_id_enter(soap, soap->id, p, t, sizeof(double), 0, NULL, NULL, NULL); - if (*soap->href) - p = (double*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(double), 0, NULL); - else if (p) - { if (soap_s2double(soap, soap_value(soap), p)) + p = (double*)soap_id_enter(soap, soap->id, p, t, sizeof(double), NULL, NULL, NULL, NULL); + if (!p) + return NULL; + if (*soap->href != '#') + { + int err = soap_s2double(soap, soap_value(soap), p); + if ((soap->body && soap_element_end_in(soap, tag)) || err) + return NULL; + } + else + { + p = (double*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(double), 0, NULL, NULL); + if (soap->body && soap_element_end_in(soap, tag)) return NULL; } - if (soap->body && soap_element_end_in(soap, tag)) - return NULL; return p; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedByte2s(struct soap *soap, unsigned char n) -{ return soap_unsignedLong2s(soap, (unsigned long)n); +{ + return soap_unsignedLong2s(soap, (unsigned long)n); } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedByte(struct soap *soap, const char *tag, int id, const unsigned char *p, const char *type, int n) -{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) +{ + if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0)) return soap->error; return soap_element_end_out(soap, tag); } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedByte(struct soap *soap, const char *s, unsigned char *p) -{ if (s) - { unsigned long n; +{ + if (s) + { + long n; char *r; - n = soap_strtoul(s, &r, 10); - if (s == r || *r || n > 255) + if (!*s) + return soap->error = SOAP_EMPTY; + n = soap_strtol(s, &r, 10); + if (s == r || *r || n < 0 || n > 255) soap->error = SOAP_TYPE; *p = (unsigned char)n; } return soap->error; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 unsigned char * SOAP_FMAC2 soap_inunsignedByte(struct soap *soap, const char *tag, unsigned char *p, const char *type, int t) -{ if (soap_element_begin_in(soap, tag, 0, NULL)) +{ + if (soap_element_begin_in(soap, tag, 0, NULL)) return NULL; #ifndef WITH_LEAN if (*soap->type && soap_match_tag(soap, soap->type, type) && soap_match_tag(soap, soap->type, ":unsignedByte")) - { soap->error = SOAP_TYPE; + { + soap->error = SOAP_TYPE; soap_revert(soap); return NULL; } +#else + (void)type; #endif - p = (unsigned char*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned char), 0, NULL, NULL, NULL); - if (*soap->href) - p = (unsigned char*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned char), 0, NULL); - else if (p) - { if (soap_s2unsignedByte(soap, soap_value(soap), p)) + p = (unsigned char*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned char), NULL, NULL, NULL, NULL); + if (!p) + return NULL; + if (*soap->href != '#') + { + int err = soap_s2unsignedByte(soap, soap_value(soap), p); + if ((soap->body && soap_element_end_in(soap, tag)) || err) + return NULL; + } + else + { + p = (unsigned char*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(unsigned char), 0, NULL, NULL); + if (soap->body && soap_element_end_in(soap, tag)) return NULL; } - if (soap->body && soap_element_end_in(soap, tag)) - return NULL; return p; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedShort2s(struct soap *soap, unsigned short n) -{ return soap_unsignedLong2s(soap, (unsigned long)n); +{ + return soap_unsignedLong2s(soap, (unsigned long)n); } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedShort(struct soap *soap, const char *tag, int id, const unsigned short *p, const char *type, int n) -{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) +{ + if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0)) return soap->error; return soap_element_end_out(soap, tag); } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedShort(struct soap *soap, const char *s, unsigned short *p) -{ if (s) - { unsigned long n; +{ + if (s) + { + long n; char *r; - n = soap_strtoul(s, &r, 10); - if (s == r || *r || n > 65535) + if (!*s) + return soap->error = SOAP_EMPTY; + n = soap_strtol(s, &r, 10); + if (s == r || *r || n < 0 || n > 65535) soap->error = SOAP_TYPE; *p = (unsigned short)n; } return soap->error; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 unsigned short * SOAP_FMAC2 soap_inunsignedShort(struct soap *soap, const char *tag, unsigned short *p, const char *type, int t) -{ if (soap_element_begin_in(soap, tag, 0, NULL)) +{ + if (soap_element_begin_in(soap, tag, 0, NULL)) return NULL; #ifndef WITH_LEAN if (*soap->type && soap_match_tag(soap, soap->type, type) && soap_match_tag(soap, soap->type, ":unsignedShort") && soap_match_tag(soap, soap->type, ":unsignedByte")) - { soap->error = SOAP_TYPE; + { + soap->error = SOAP_TYPE; soap_revert(soap); return NULL; } +#else + (void)type; #endif - p = (unsigned short*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned short), 0, NULL, NULL, NULL); - if (*soap->href) - p = (unsigned short*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned short), 0, NULL); - else if (p) - { if (soap_s2unsignedShort(soap, soap_value(soap), p)) + p = (unsigned short*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned short), NULL, NULL, NULL, NULL); + if (!p) + return NULL; + if (*soap->href != '#') + { + int err = soap_s2unsignedShort(soap, soap_value(soap), p); + if ((soap->body && soap_element_end_in(soap, tag)) || err) + return NULL; + } + else + { + p = (unsigned short*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(unsigned short), 0, NULL, NULL); + if (soap->body && soap_element_end_in(soap, tag)) return NULL; } - if (soap->body && soap_element_end_in(soap, tag)) - return NULL; return p; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedInt2s(struct soap *soap, unsigned int n) -{ return soap_unsignedLong2s(soap, (unsigned long)n); +{ + return soap_unsignedLong2s(soap, (unsigned long)n); } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedInt(struct soap *soap, const char *tag, int id, const unsigned int *p, const char *type, int n) -{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) +{ + if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0)) return soap->error; return soap_element_end_out(soap, tag); } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedInt(struct soap *soap, const char *s, unsigned int *p) -{ if (s) - { char *r; +{ + if (s) + { + unsigned long n; + char *r; + if (!*s) + return soap->error = SOAP_EMPTY; #ifndef WITH_NOIO #ifndef WITH_LEAN soap_reset_errno; #endif #endif - *p = (unsigned int)soap_strtoul(s, &r, 10); - if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r + n = soap_strtoul(s, &r, 10); + if (s == r || *r +#ifndef WITH_LEAN + || n != (unsigned int)n +#endif #ifndef WITH_NOIO #ifndef WITH_LEAN - || soap_errno == SOAP_ERANGE + || soap_errno == SOAP_ERANGE #endif #endif ) soap->error = SOAP_TYPE; +#ifdef HAVE_STRTOUL + if (n > 0 && strchr(s, '-')) + return soap->error = SOAP_TYPE; +#endif + *p = (unsigned int)n; } return soap->error; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 unsigned int * SOAP_FMAC2 soap_inunsignedInt(struct soap *soap, const char *tag, unsigned int *p, const char *type, int t) -{ if (soap_element_begin_in(soap, tag, 0, NULL)) +{ + if (soap_element_begin_in(soap, tag, 0, NULL)) return NULL; #ifndef WITH_LEAN if (*soap->type @@ -10143,82 +17795,98 @@ soap_inunsignedInt(struct soap *soap, const char *tag, unsigned int *p, const ch && soap_match_tag(soap, soap->type, ":unsignedInt") && soap_match_tag(soap, soap->type, ":unsignedShort") && soap_match_tag(soap, soap->type, ":unsignedByte")) - { soap->error = SOAP_TYPE; + { + soap->error = SOAP_TYPE; soap_revert(soap); return NULL; } +#else + (void)type; #endif - p = (unsigned int*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned int), 0, NULL, NULL, NULL); - if (*soap->href) - p = (unsigned int*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned int), 0, NULL); - else if (p) - { if (soap_s2unsignedInt(soap, soap_value(soap), p)) + p = (unsigned int*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned int), NULL, NULL, NULL, NULL); + if (!p) + return NULL; + if (*soap->href != '#') + { + int err = soap_s2unsignedInt(soap, soap_value(soap), p); + if ((soap->body && soap_element_end_in(soap, tag)) || err) + return NULL; + } + else + { + p = (unsigned int*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(unsigned int), 0, NULL, NULL); + if (soap->body && soap_element_end_in(soap, tag)) return NULL; } - if (soap->body && soap_element_end_in(soap, tag)) - return NULL; return p; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedLong2s(struct soap *soap, unsigned long n) -{ sprintf(soap->tmpbuf, "%lu", n); +{ + (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 20), "%lu", n); return soap->tmpbuf; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedLong(struct soap *soap, const char *tag, int id, const unsigned long *p, const char *type, int n) -{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) +{ + if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) || soap_string_out(soap, soap_unsignedLong2s(soap, *p), 0)) return soap->error; return soap_element_end_out(soap, tag); } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedLong(struct soap *soap, const char *s, unsigned long *p) -{ if (s) - { char *r; +{ + if (s) + { + char *r; + if (!*s) + return soap->error = SOAP_EMPTY; #ifndef WITH_NOIO #ifndef WITH_LEAN soap_reset_errno; #endif #endif *p = soap_strtoul(s, &r, 10); - if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r + if (s == r || *r #ifndef WITH_NOIO #ifndef WITH_LEAN - || soap_errno == SOAP_ERANGE + || soap_errno == SOAP_ERANGE #endif #endif ) soap->error = SOAP_TYPE; +#ifdef HAVE_STRTOUL + if (*p > 0 && strchr(s, '-')) + return soap->error = SOAP_TYPE; +#endif } return soap->error; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 unsigned long * SOAP_FMAC2 soap_inunsignedLong(struct soap *soap, const char *tag, unsigned long *p, const char *type, int t) -{ if (soap_element_begin_in(soap, tag, 0, NULL)) +{ + if (soap_element_begin_in(soap, tag, 0, NULL)) return NULL; #ifndef WITH_LEAN if (*soap->type @@ -10226,90 +17894,98 @@ soap_inunsignedLong(struct soap *soap, const char *tag, unsigned long *p, const && soap_match_tag(soap, soap->type, ":unsignedInt") && soap_match_tag(soap, soap->type, ":unsignedShort") && soap_match_tag(soap, soap->type, ":unsignedByte")) - { soap->error = SOAP_TYPE; + { + soap->error = SOAP_TYPE; soap_revert(soap); return NULL; } +#else + (void)type; #endif - p = (unsigned long*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned long), 0, NULL, NULL, NULL); - if (*soap->href) - p = (unsigned long*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned long), 0, NULL); - else if (p) - { if (soap_s2unsignedLong(soap, soap_value(soap), p)) + p = (unsigned long*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned long), NULL, NULL, NULL, NULL); + if (!p) + return NULL; + if (*soap->href != '#') + { + int err = soap_s2unsignedLong(soap, soap_value(soap), p); + if ((soap->body && soap_element_end_in(soap, tag)) || err) + return NULL; + } + else + { + p = (unsigned long*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(unsigned long), 0, NULL, NULL); + if (soap->body && soap_element_end_in(soap, tag)) return NULL; } - if (soap->body && soap_element_end_in(soap, tag)) - return NULL; return p; } -#endif /******************************************************************************/ -#ifndef WITH_LEAN + SOAP_FMAC1 const char* SOAP_FMAC2 soap_ULONG642s(struct soap *soap, ULONG64 n) -{ sprintf(soap->tmpbuf, SOAP_ULONG_FORMAT, n); +{ + (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 20), SOAP_ULONG_FORMAT, n); return soap->tmpbuf; } -#endif /******************************************************************************/ -#ifndef WITH_LEAN + SOAP_FMAC1 int SOAP_FMAC2 soap_outULONG64(struct soap *soap, const char *tag, int id, const ULONG64 *p, const char *type, int n) -{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) +{ + if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) || soap_string_out(soap, soap_ULONG642s(soap, *p), 0)) return soap->error; return soap_element_end_out(soap, tag); } -#endif /******************************************************************************/ -#ifndef WITH_LEAN + SOAP_FMAC1 int SOAP_FMAC2 soap_s2ULONG64(struct soap *soap, const char *s, ULONG64 *p) -{ if (s) +{ + if (s) { -#ifdef HAVE_STRTOULL char *r; + if (!*s) + return soap->error = SOAP_EMPTY; #ifndef WITH_NOIO #ifndef WITH_LEAN soap_reset_errno; #endif #endif - *p = strtoull(s, &r, 10); - if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r + *p = soap_strtoull(s, &r, 10); + if (s == r || *r #ifndef WITH_NOIO #ifndef WITH_LEAN - || soap_errno == SOAP_ERANGE + || soap_errno == SOAP_ERANGE #endif #endif ) -#else -#ifdef HAVE_SSCANF - if (sscanf(s, SOAP_ULONG_FORMAT, p) != 1) -#endif -#endif soap->error = SOAP_TYPE; + if (*p > 0 && strchr(s, '-')) + return soap->error = SOAP_TYPE; } return soap->error; } -#endif /******************************************************************************/ -#ifndef WITH_LEAN + SOAP_FMAC1 ULONG64 * SOAP_FMAC2 soap_inULONG64(struct soap *soap, const char *tag, ULONG64 *p, const char *type, int t) -{ if (soap_element_begin_in(soap, tag, 0, NULL)) +{ + if (soap_element_begin_in(soap, tag, 0, NULL)) return NULL; +#ifndef WITH_LEAN if (*soap->type && soap_match_tag(soap, soap->type, type) && soap_match_tag(soap, soap->type, ":positiveInteger") @@ -10318,2638 +17994,3160 @@ soap_inULONG64(struct soap *soap, const char *tag, ULONG64 *p, const char *type, && soap_match_tag(soap, soap->type, ":unsignedInt") && soap_match_tag(soap, soap->type, ":unsignedShort") && soap_match_tag(soap, soap->type, ":unsignedByte")) - { soap->error = SOAP_TYPE; + { + soap->error = SOAP_TYPE; soap_revert(soap); return NULL; } - p = (ULONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(ULONG64), 0, NULL, NULL, NULL); - if (*soap->href) - p = (ULONG64*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(ULONG64), 0, NULL); - else if (p) - { if (soap_s2ULONG64(soap, soap_value(soap), p)) +#else + (void)type; +#endif + p = (ULONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(ULONG64), NULL, NULL, NULL, NULL); + if (!p) + return NULL; + if (*soap->href != '#') + { + int err = soap_s2ULONG64(soap, soap_value(soap), p); + if ((soap->body && soap_element_end_in(soap, tag)) || err) + return NULL; + } + else + { + p = (ULONG64*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(ULONG64), 0, NULL, NULL); + if (soap->body && soap_element_end_in(soap, tag)) return NULL; } - if (soap->body && soap_element_end_in(soap, tag)) - return NULL; return p; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 -soap_s2string(struct soap *soap, const char *s, char **t, long minlen, long maxlen) -{ if (s) - { if (!(*t = soap_strdup(soap, s))) +soap_s2char(struct soap *soap, const char *s, char **t, int flag, long minlen, long maxlen, const char *pattern) +{ + if (s) + { + const char *r = soap_string(soap, s, flag, minlen, maxlen, pattern); + if (r && (*t = soap_strdup(soap, r)) == NULL) return soap->error = SOAP_EOM; - if (!(soap->mode & (SOAP_ENC_LATIN | SOAP_C_UTFSTRING))) - { char *r = *t; - /* remove non-ASCII chars */ - for (s = *t; *s; s++) - if (!(*s & 0x80)) - *r++ = *s; - *r = '\0'; - } - if ((soap->mode & SOAP_XML_STRICT)) - { long l = (long)strlen(*t); - if ((maxlen >= 0 && l > maxlen) || l < minlen) + } + return soap->error; +} + +/******************************************************************************/ + +#ifndef WITH_COMPAT +#ifdef __cplusplus +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2stdchar(struct soap *soap, const char *s, std::string *t, int flag, long minlen, long maxlen, const char *pattern) +{ + if (s) + { + const char *r = soap_string(soap, s, flag, minlen, maxlen, pattern); + if (r) + t->assign(r); + } + return soap->error; +} +#endif +#endif + +/******************************************************************************/ + +static const char* +soap_string(struct soap *soap, const char *s, int flag, long minlen, long maxlen, const char *pattern) +{ + if (s) + { + if (maxlen < 0 && soap->maxlength > 0) + maxlen = soap->maxlength; + if (minlen > 0 || maxlen >= 0) + { + size_t l; + if ((soap->mode & SOAP_C_UTFSTRING)) + l = soap_utf8len(s); + else + l = strlen(s); + if ((maxlen >= 0 && l > (size_t)maxlen) || (minlen > 0 && l < (size_t)minlen)) + { soap->error = SOAP_LENGTH; + return NULL; + } + } + if (flag >= 4) + s = soap_collapse(soap, (char*)s, flag, 0); +#ifndef WITH_LEANER + if (pattern && soap->fsvalidate) + { + soap->error = soap->fsvalidate(soap, pattern, s); + if (soap->error) + return NULL; + } +#else + (void)pattern; +#endif + } + return s; +} + +/******************************************************************************/ + +static char* +soap_collapse(struct soap *soap, char *s, int flag, int insitu) +{ + /* flag 4=normalizedString (replace), 5=token (collapse) */ + char *t; + size_t n; + if (!s) + return NULL; + if (flag == 4) + { + for (t = s; *t && (!soap_coblank((soap_wchar)*t) || *t == 32); t++) + continue; + if (*t) + { + /* replace white space and control chars by blanks */ + if (!insitu) + s = soap_strdup(soap, s); + for (t = s; *t; t++) + if (soap_coblank((soap_wchar)*t)) + *t = ' '; + } + return s; + } + /* collapse white space */ + for (t = s; *t && soap_coblank((soap_wchar)*t); t++) + continue; + n = strlen(t); + if (insitu && s < t) + (void)soap_memmove(s, n + 1, t, n + 1); + else + s = t; + if (n > 0) + { + if (!soap_coblank((soap_wchar)s[n-1])) + { + for (t = s; (*t && !soap_coblank((soap_wchar)*t)) || (*t == 32 && (!t[1] || !soap_coblank((soap_wchar)t[1]))); t++) + continue; + if (!*t) + return s; + } + if (!insitu) + s = soap_strdup(soap, s); + for (t = s; *t; t++) + { + if (soap_coblank((soap_wchar)*t)) + { + char *r; + *t = ' '; + for (r = t + 1; *r && soap_coblank((soap_wchar)*r); r++) + continue; + if (r > t + 1) + (void)soap_memmove(t + 1, n - (t-s), r, n - (r-s) + 1); + } } + t--; + if (t >= s && *t == 32) + *t = '\0'; + } + return s; +} + +/******************************************************************************/ + +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2QName(struct soap *soap, const char *s, char **t, long minlen, long maxlen, const char *pattern) +{ + *t = NULL; + if (s) + { + const char *r = soap_QName(soap, s, minlen, maxlen, pattern); + if (r && (*t = soap_strdup(soap, r)) == NULL) + return soap->error = SOAP_EOM; } return soap->error; } -#endif /******************************************************************************/ -#ifndef PALM_2 + +#ifndef WITH_COMPAT +#ifdef __cplusplus SOAP_FMAC1 int SOAP_FMAC2 -soap_s2QName(struct soap *soap, const char *s, char **t, long minlen, long maxlen) -{ if (s) - { soap->labidx = 0; +soap_s2stdQName(struct soap *soap, const char *s, std::string *t, long minlen, long maxlen, const char *pattern) +{ + t->clear(); + if (s) + { + const char *r = soap_QName(soap, s, minlen, maxlen, pattern); + if (r) + t->assign(r); + } + return soap->error; +} +#endif +#endif + +/******************************************************************************/ + +static const char* +soap_QName(struct soap *soap, const char *s, long minlen, long maxlen, const char *pattern) +{ + if (s) + { + char *b; + if (maxlen < 0 && soap->maxlength > 0) + maxlen = soap->maxlength; + if (minlen > 0 || maxlen >= 0) + { + size_t l; + if ((soap->mode & SOAP_C_UTFSTRING)) + l = soap_utf8len(s); + else + l = strlen(s); + if ((maxlen >= 0 && l > (size_t)maxlen) || (minlen > 0 && l < (size_t)minlen)) + { + soap->error = SOAP_LENGTH; + return NULL; + } + } +#ifdef WITH_FAST + soap->labidx = 0; +#else + if (soap_alloc_block(soap) == NULL) + return NULL; +#endif DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Normalized namespace(s) of QNames '%s'", s)); /* convert (by prefix normalize prefix) all QNames in s */ for (;;) - { size_t n; + { + size_t n; struct soap_nlist *np; - const char *p; + const char *p = NULL; + short flag = 0; + const char *r = NULL; + size_t m = 0; +#ifndef WITH_FAST + size_t k = 0; +#endif /* skip blanks */ - while (*s && soap_blank(*s)) + while (*s && soap_coblank((soap_wchar)*s)) s++; if (!*s) break; /* find next QName */ n = 1; - while (s[n] && !soap_blank(s[n])) + while (s[n] && !soap_coblank((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)) - { soap_append_lab(soap, s, n); + /* if there is no namespace stack, or prefix is "#" or "xml" then copy string */ + if (!np || *s == '#' || !strncmp(s, "xml:", 4)) + { + r = s; + m = n; } else /* we normalize the QName by replacing its prefix */ - { for (p = s; *p && p < s + n; p++) + { + const char *q; + for (p = s; *p && p < s + n; p++) if (*p == ':') - break; + break; if (*p == ':') - { size_t k = p - s; + { + size_t k = p - s; while (np && (strncmp(np->id, s, k) || np->id[k])) np = np->next; p++; } else - { while (np && *np->id) + { + while (np && *np->id) np = np->next; p = s; } /* replace prefix */ if (np) - { if (np->index >= 0 && soap->local_namespaces) - { const char *q = soap->local_namespaces[np->index].id; - if (q) - soap_append_lab(soap, q, strlen(q)); + { + if (np->index >= 0 && soap->local_namespaces && (q = soap->local_namespaces[np->index].id) != NULL) + { + size_t k = strlen(q); + if (q[k-1] != '_') + { + r = q; + m = k; + } + else + { + flag = 1; + r = soap->local_namespaces[np->index].ns; + m = strlen(r); + } } else if (np->ns) - { soap_append_lab(soap, "\"", 1); - soap_append_lab(soap, np->ns, strlen(np->ns)); - soap_append_lab(soap, "\"", 1); + { + flag = 1; + r = np->ns; + m = strlen(r); } 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)); - return soap->error = SOAP_NAMESPACE; + { + 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)); + soap->error = SOAP_NAMESPACE; + return NULL; } } else if (s[n]) /* no namespace, part of string */ - { soap_append_lab(soap, s, n); + { + r = s; + m = n; + } + else /* no namespace: assume "" namespace */ + { + flag = 1; + } + } +#ifdef WITH_FAST + if ((flag && soap_append_lab(soap, "\"", 1)) + || (m && soap_append_lab(soap, r, m)) + || (flag && soap_append_lab(soap, "\"", 1)) + || (p && (soap_append_lab(soap, ":", 1) || soap_append_lab(soap, p, n - (p-s))))) + return NULL; +#else + k = 2*flag + m + (p ? n - (p-s) + 1 : 0) + (s[n] != '\0'); + b = (char*)soap_push_block(soap, NULL, k); + if (!b) + return NULL; + if (flag) + *b++ = '"'; + if (m) + { + if (soap_memcpy((void*)b, k, (const void*)r, m)) + { + soap->error = SOAP_EOM; + return NULL; + } + b += m; + } + if (flag) + *b++ = '"'; + if (p) + { + *b++ = ':'; + if (soap_memcpy((void*)b, k - m - flag - 1, (const void*)p, n - (p-s))) + { + soap->error = SOAP_EOM; + return NULL; } - else /* no namespace: assume "" namespace */ - { soap_append_lab(soap, "\"\"", 2); - } - soap_append_lab(soap, ":", 1); - soap_append_lab(soap, p, n - (p-s)); + b += n - (p-s); } +#endif /* advance to next and add spacing */ s += n; + while (*s && soap_coblank(*s)) + s++; if (*s) - soap_append_lab(soap, " ", 1); - } - soap_append_lab(soap, SOAP_STR_EOS, 1); - *t = soap_strdup(soap, soap->labbuf); - DBGLOG(TEST, SOAP_MESSAGE(fdebug, " into '%s'\n", *t)); - if ((soap->mode & SOAP_XML_STRICT)) - { long l = (long)soap->labidx - 1; - if ((maxlen >= 0 && l > maxlen) || l < minlen) - soap->error = SOAP_LENGTH; + { +#ifdef WITH_FAST + if (soap_append_lab(soap, " ", 1)) + return NULL; +#else + *b = ' '; +#endif + } + } +#ifdef WITH_FAST + if (soap_append_lab(soap, SOAP_STR_EOS, 1)) + return NULL; + b = soap->labbuf; +#else + b = (char*)soap_push_block(soap, NULL, 1); + if (!b) + return NULL; + *b = '\0'; + b = (char*)soap_save_block(soap, NULL, NULL, 0); +#endif +#ifndef WITH_LEANER + if (pattern && soap->fsvalidate) + { + soap->error = soap->fsvalidate(soap, pattern, b); + if (soap->error) + return NULL; } +#else + (void)pattern; +#endif + return b; } - return soap->error; + return NULL; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 const char* SOAP_FMAC2 soap_QName2s(struct soap *soap, const char *s) -{ const char *t = NULL; +{ + const char *t = NULL; if (s) - { soap->labidx = 0; + { +#ifdef WITH_FAST + soap_store_lab(soap, SOAP_STR_EOS, 1); + soap->labidx = 0; +#else + char *b = NULL; + if (soap_alloc_block(soap) == NULL) + return NULL; +#endif for (;;) - { size_t n; + { + size_t n; + const char *q = NULL; + const char *r = NULL; + size_t m = 0; +#ifndef WITH_FAST + size_t k = 0; +#endif /* skip blanks */ - while (*s && soap_blank(*s)) + while (*s && soap_coblank((soap_wchar)*s)) s++; if (!*s) + { +#ifdef WITH_FAST + soap->labbuf[soap->labidx > 0 ? soap->labidx - 1 : 0] = '\0'; +#else + if (!b) + return soap_strdup(soap, SOAP_STR_EOS); + --b; + *b = '\0'; +#endif break; + } /* find next QName */ - n = 1; - while (s[n] && !soap_blank(s[n])) + n = 0; + while (s[n] && !soap_coblank((soap_wchar)s[n])) + { + if (s[n] == ':') + r = s; n++; - /* normal prefix: pass string as is */ - if (*s != '"') - { soap_append_lab(soap, s, n); + } + if (*s != '"') /* non-quoted: pass string as is */ + { #ifndef WITH_LEAN - if ((soap->mode & SOAP_XML_CANONICAL)) - { const char *r = strchr(s, ':'); - if (r) - soap_utilize_ns(soap, s, r - s); - } + if (r && (soap->mode & SOAP_XML_CANONICAL) && !(soap->mode & SOAP_XML_CANONICAL_NA)) + soap_utilize_ns(soap, s, 1); #endif + r = s; + m = n + 1; } - else /* URL-based string prefix */ - { const char *q; - s++; - q = strchr(s, '"'); + else /* prefix quoted URI-based string */ + { + q = strchr(s + 1, '"'); if (q) - { struct Namespace *p = soap->local_namespaces; + { + struct Namespace *p = soap->local_namespaces; if (p) - { for (; p->id; p++) - { if (p->ns) - if (!soap_tag_cmp(s, p->ns)) + { + for (; p->id; p++) + { + if (p->ns) + if (!soap_tag_cmp(s + 1, p->ns)) break; if (p->in) - if (!soap_tag_cmp(s, p->in)) + if (!soap_tag_cmp(s + 1, p->in)) break; } } + q++; /* URL is in the namespace table? */ if (p && p->id) - { soap_append_lab(soap, p->id, strlen(p->id)); + { + r = p->id; + m = strlen(r); } else /* not in namespace table: create xmlns binding */ - { char *r = soap_strdup(soap, s); - r[q-s] = '\0'; - sprintf(soap->tmpbuf, "xmlns:_%d", soap->idnum++); - soap_set_attr(soap, soap->tmpbuf, r); - soap_append_lab(soap, soap->tmpbuf + 6, strlen(soap->tmpbuf + 6)); + { + char *x = soap_strdup(soap, s + 1); + if (!x) + return NULL; + x[q - s - 2] = '\0'; + (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 27), "xmlns:_%d", soap->idnum++); + soap_set_attr(soap, soap->tmpbuf, x, 1); + r = soap->tmpbuf + 6; + m = strlen(r); } - soap_append_lab(soap, q + 1, n - (q-s) - 1); } } - /* advance to next and add spacing */ - s += n; - if (*s) - soap_append_lab(soap, " ", 1); - } - soap_append_lab(soap, SOAP_STR_EOS, 1); - t = soap_strdup(soap, soap->labbuf); - } - return t; -} -#endif - -/******************************************************************************/ -#ifndef WITH_LEAN -SOAP_FMAC1 -int -SOAP_FMAC2 -soap_s2wchar(struct soap *soap, const char *s, wchar_t **t, long minlen, long maxlen) -{ if (s) - { wchar_t *r; - *t = r = (wchar_t*)soap_malloc(soap, sizeof(wchar_t) * (strlen(s) + 1)); - if (!r) - return soap->error; - if (soap->mode & SOAP_ENC_LATIN) - { while (*s) - *r++ = (wchar_t)*s++; - } - else - { /* Convert UTF8 to wchar */ - while (*s) - { soap_wchar c, c1, c2, c3, c4; - c = (unsigned char)*s++; - if (c < 0x80) - *r++ = (wchar_t)c; - else - { c1 = (soap_wchar)*s++ & 0x3F; - if (c < 0xE0) - *r++ = (wchar_t)(((soap_wchar)(c & 0x1F) << 6) | c1); - else - { c2 = (soap_wchar)*s++ & 0x3F; - if (c < 0xF0) - *r++ = (wchar_t)(((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2); - else - { c3 = (soap_wchar)*s++ & 0x3F; - if (c < 0xF8) - *r++ = (wchar_t)(((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3); - else - { c4 = (soap_wchar)*s++ & 0x3F; - if (c < 0xFC) - *r++ = (wchar_t)(((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4); - else - *r++ = (wchar_t)(((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(*s++ & 0x3F)); - } - } - } - } + /* copy normalized QName into buffer, including the ending blank or NUL */ +#ifdef WITH_FAST + if ((m && soap_append_lab(soap, r, m)) + || (q && soap_append_lab(soap, q, n - (q - s) + 1))) + return NULL; +#else + k = m + (q ? n - (q - s) + 1 : 0); + b = (char*)soap_push_block(soap, NULL, k); + if (!b) + { + soap->error = SOAP_EOM; + return NULL; } - } - *r = L'\0'; - if ((soap->mode & SOAP_XML_STRICT)) - { long l = (long)(r - *t); - if ((maxlen >= 0 && l > maxlen) || l < minlen) - soap->error = SOAP_LENGTH; - } - } - return soap->error; -} -#endif - -/******************************************************************************/ -#ifndef WITH_LEAN -SOAP_FMAC1 -const char* -SOAP_FMAC2 -soap_wchar2s(struct soap *soap, const wchar_t *s) -{ soap_wchar c; - char *r, *t; - const wchar_t *q = s; - size_t n = 0; - while ((c = *q++)) - { if (c > 0 && c < 0x80) - n++; - else - n += 6; - } - r = t = (char*)soap_malloc(soap, n + 1); - if (r) - { /* Convert wchar to UTF8 */ - while ((c = *s++)) - { if (c > 0 && c < 0x80) - *t++ = (char)c; - else - { if (c < 0x0800) - *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); - else - { if (c < 0x010000) - *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); - else - { if (c < 0x200000) - *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); - else - { if (c < 0x04000000) - *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); - else - { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); - *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); - } - *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); - } - *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); - } - *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); + if (soap_memcpy((void*)b, k, (const void*)r, m)) + { + soap->error = SOAP_EOM; + return NULL; + } + b += m; + if (q) + { + if (soap_memcpy((void*)b, k - m, (const void*)q, n - (q - s) + 1)) + { + soap->error = SOAP_EOM; + return NULL; } - *t++ = (char)(0x80 | (c & 0x3F)); + b += n - (q - s) + 1; } - } - *t = '\0'; - } - return r; -} -#endif - -/******************************************************************************/ -#ifndef PALM_2 -SOAP_FMAC1 -int -SOAP_FMAC2 -soap_outstring(struct soap *soap, const char *tag, int id, char *const*p, const char *type, int n) -{ id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n); - if (id < 0) - return soap->error; - if (!**p && (soap->mode & SOAP_C_NILSTRING)) - return soap_element_null(soap, tag, id, type); - if (soap_element_begin_out(soap, tag, id, type) - || soap_string_out(soap, *p, 0) - || soap_element_end_out(soap, tag)) - return soap->error; - return SOAP_OK; -} -#endif - -/******************************************************************************/ -#ifndef PALM_2 -SOAP_FMAC1 -char ** -SOAP_FMAC2 -soap_instring(struct soap *soap, const char *tag, char **p, const char *type, int t, int flag, long minlen, long maxlen) -{ if (soap_element_begin_in(soap, tag, 1, NULL)) - { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG) - return NULL; - soap->error = SOAP_OK; - } - if (!p) - { if (!(p = (char**)soap_malloc(soap, sizeof(char*)))) - return NULL; - } - if (soap->null) - *p = NULL; - else if (soap->body) - { *p = soap_string_in(soap, flag, minlen, maxlen); - if (!*p || !(char*)soap_id_enter(soap, soap->id, *p, t, sizeof(char*), 0, NULL, NULL, NULL)) - return NULL; - if (!**p && tag && *tag == '-') - { soap->error = SOAP_NO_TAG; - return NULL; - } - } - else if (tag && *tag == '-') - { soap->error = SOAP_NO_TAG; - return NULL; - } - else - *p = soap_strdup(soap, SOAP_STR_EOS); - if (*soap->href) - p = (char**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(char**), 0); - if (soap->body && soap_element_end_in(soap, tag)) - return NULL; - return p; -} -#endif - -/******************************************************************************/ -#ifndef WITH_LEANER -#ifndef PALM_2 -SOAP_FMAC1 -int -SOAP_FMAC2 -soap_outwstring(struct soap *soap, const char *tag, int id, wchar_t *const*p, const char *type, int n) -{ id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n); - if (id < 0) - return soap->error; - if (!**p && (soap->mode & SOAP_C_NILSTRING)) - return soap_element_null(soap, tag, id, type); - if (soap_element_begin_out(soap, tag, id, type) - || soap_wstring_out(soap, *p, 0) - || soap_element_end_out(soap, tag)) - return soap->error; - return SOAP_OK; -} -#endif #endif - -/******************************************************************************/ -#ifndef WITH_LEANER -#ifndef PALM_2 -SOAP_FMAC1 -wchar_t ** -SOAP_FMAC2 -soap_inwstring(struct soap *soap, const char *tag, wchar_t **p, const char *type, int t, long minlen, long maxlen) -{ if (soap_element_begin_in(soap, tag, 1, NULL)) - { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG) - return NULL; - soap->error = SOAP_OK; - } - if (!p) - { if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*)))) - return NULL; - } - if (soap->body) - { *p = soap_wstring_in(soap, 1, minlen, maxlen); - if (!*p || !(wchar_t*)soap_id_enter(soap, soap->id, *p, t, sizeof(wchar_t*), 0, NULL, NULL, NULL)) - return NULL; - if (!**p && tag && *tag == '-') - { soap->error = SOAP_NO_TAG; - return NULL; + /* advance to next */ + s += n; } - } - else if (tag && *tag == '-') - { soap->error = SOAP_NO_TAG; - return NULL; - } - else if (soap->null) - *p = NULL; - else - *p = soap_wstrdup(soap, (wchar_t*)SOAP_STR_EOS); - if (*soap->href) - p = (wchar_t**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(wchar_t**), 0); - if (soap->body && soap_element_end_in(soap, tag)) - return NULL; - return p; -} -#endif -#endif - -/******************************************************************************/ -#ifndef WITH_LEAN -SOAP_FMAC1 -time_t -SOAP_FMAC2 -soap_timegm(struct tm *T) -{ -#if defined(HAVE_TIMEGM) - return timegm(T); -#else - time_t t, g, z; - struct tm tm; - t = mktime(T); - if (t == (time_t)-1) - return (time_t)-1; -#ifdef HAVE_GMTIME_R - gmtime_r(&t, &tm); -#else - tm = *gmtime(&t); -#endif - tm.tm_isdst = 0; - g = mktime(&tm); - if (g == (time_t)-1) - return (time_t)-1; - z = g - t; - return t - z; +#ifdef WITH_FAST + t = soap_strdup(soap, soap->labbuf); + if (!t) + soap->error = SOAP_EOM; +#else + t = (char*)soap_save_block(soap, NULL, NULL, 0); #endif + } + return t; } -#endif /******************************************************************************/ + #ifndef WITH_LEAN SOAP_FMAC1 -const char* +int SOAP_FMAC2 -soap_dateTime2s(struct soap *soap, time_t n) -{ struct tm T, *pT = &T; -#if defined(HAVE_GMTIME_R) - if (gmtime_r(&n, pT)) - strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); -#elif defined(HAVE_GMTIME) - if ((pT = gmtime(&n))) - strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); -#elif defined(HAVE_GETTIMEOFDAY) - struct timezone tz; - memset((void*)&tz, 0, sizeof(tz)); -#if defined(HAVE_LOCALTIME_R) - if (localtime_r(&n, pT)) - { struct timeval tv; - gettimeofday(&tv, &tz); - strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); - sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60); - } -#else - if ((pT = localtime(&n))) - { struct timeval tv; - gettimeofday(&tv, &tz); - strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); - sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60); - } -#endif -#elif defined(HAVE_FTIME) - struct timeb t; - memset((void*)&t, 0, sizeof(t)); -#if defined(HAVE_LOCALTIME_R) - if (localtime_r(&n, pT)) - { -#ifdef __BORLANDC__ - ::ftime(&t); -#else - ftime(&t); -#endif - strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); - sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60); - } -#else - if ((pT = localtime(&n))) +soap_s2wchar(struct soap *soap, const char *s, wchar_t **t, int flag, long minlen, long maxlen, const char *pattern) +{ + if (s) { -#ifdef __BORLANDC__ - ::ftime(&t); -#else - ftime(&t); -#endif - strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); - sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60); + const wchar_t *r = soap_wstring(soap, s, flag, minlen, maxlen, pattern); + if (r && (*t = soap_wstrdup(soap, r)) == NULL) + return soap->error = SOAP_EOM; } -#endif -#elif defined(HAVE_LOCALTIME_R) - if (localtime_r(&n, pT)) - strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); -#else - if ((pT = localtime(&n))) - strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); -#endif - else - strcpy(soap->tmpbuf, "1969-12-31T23:59:59Z"); - return soap->tmpbuf; + return soap->error; } #endif /******************************************************************************/ + +#ifndef WITH_COMPAT +#ifdef __cplusplus #ifndef WITH_LEAN SOAP_FMAC1 int SOAP_FMAC2 -soap_outdateTime(struct soap *soap, const char *tag, int id, const time_t *p, const char *type, int n) -{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) - || soap_string_out(soap, soap_dateTime2s(soap, *p), 0)) - return soap->error; - return soap_element_end_out(soap, tag); +soap_s2stdwchar(struct soap *soap, const char *s, std::wstring *t, int flag, long minlen, long maxlen, const char *pattern) +{ + if (s) + { + const wchar_t *r = soap_wstring(soap, s, flag, minlen, maxlen, pattern); + if (r) + t->assign(r); + } + return soap->error; } #endif +#endif +#endif /******************************************************************************/ + #ifndef WITH_LEAN -SOAP_FMAC1 -int -SOAP_FMAC2 -soap_s2dateTime(struct soap *soap, const char *s, time_t *p) -{ if (s) - { char zone[32]; - struct tm T; - const char *t; - *zone = '\0'; - memset((void*)&T, 0, sizeof(T)); - if (strchr(s, '-')) - t = "%d-%d-%dT%d:%d:%d%31s"; - else if (strchr(s, ':')) - t = "%4d%2d%2dT%d:%d:%d%31s"; - else /* parse non-XSD-standard alternative ISO 8601 format */ - t = "%4d%2d%2dT%2d%2d%2d%31s"; - if (sscanf(s, t, &T.tm_year, &T.tm_mon, &T.tm_mday, &T.tm_hour, &T.tm_min, &T.tm_sec, zone) < 6) - return soap->error = SOAP_TYPE; - if (T.tm_year == 1) - T.tm_year = 70; - else - T.tm_year -= 1900; - T.tm_mon--; - if (*zone == '.') - { for (s = zone + 1; *s; s++) - if (*s < '0' || *s > '9') - break; +static const wchar_t* +soap_wstring(struct soap *soap, const char *s, int flag, long minlen, long maxlen, const char *pattern) +{ + if (s) + { + size_t l; + soap_wchar c; + wchar_t *t; + if (maxlen < 0 && soap->maxlength > 0) + maxlen = soap->maxlength; + soap->labidx = 0; + if ((soap->mode & SOAP_ENC_LATIN)) + { + wchar_t *r; + if (soap_append_lab(soap, NULL, sizeof(wchar_t) * (strlen(s) + 1))) + return NULL; + r = (wchar_t*)(void*)soap->labbuf; + while (*s) + *r++ = (wchar_t)*s++; } else - s = zone; - if (*s) { -#ifndef WITH_NOZONE - if (*s == '+' || *s == '-') - { int h = 0, m = 0; - if (s[3] == ':') - { /* +hh:mm */ - sscanf(s, "%d:%d", &h, &m); - if (h < 0) - m = -m; + /* Convert UTF8 to wchar_t */ + while (*s) + { + c = (unsigned char)*s++; + if (c >= 0x80) + { +#ifdef WITH_REPLACE_ILLEGAL_UTF8 + soap_wchar c1, c2, c3; + c1 = (unsigned char)*s; + if (c <= 0xC1 || (c1 & 0xC0) != 0x80) + { + c = SOAP_UNKNOWN_UNICODE_CHAR; + } + else + { + ++s; + c1 &= 0x3F; + if (c < 0xE0) + { + c = (((c & 0x1F) << 6) | c1); + } + else + { + c2 = (unsigned char)*s; + if ((c == 0xE0 && c1 < 0x20) || (c2 & 0xC0) != 0x80) + { + c = SOAP_UNKNOWN_UNICODE_CHAR; + } + else + { + ++s; + c2 &= 0x3F; + if (c < 0xF0) + { + c = (((c & 0x0F) << 12) | (c1 << 6) | c2); + } + else + { + c3 = (unsigned char)*s; + if ((c == 0xF0 && c1 < 0x10) || (c == 0xF4 && c1 >= 0x10) || c >= 0xF5 || (c3 & 0xC0) != 0x80) + { + c = SOAP_UNKNOWN_UNICODE_CHAR; + } + else + { + ++s; + c = (((c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | (c3 & 0x3F)); + } + } + } + } + } +#else + soap_wchar c1, c2, c3, c4; + c1 = (unsigned char)*s; + if (c1) + { + s++; + c1 &= 0x3F; + if (c < 0xE0) + { + c = (wchar_t)(((soap_wchar)(c & 0x1F) << 6) | c1); + } + else + { + c2 = (unsigned char)*s; + if (c2) + { + s++; + c2 &= 0x3F; + if (c < 0xF0) + { + c = (wchar_t)(((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2); + } + else + { + c3 = (unsigned char)*s; + if (c3) + { + s++; + c3 &= 0x3F; + if (c < 0xF8) + { + c = (wchar_t)(((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3); + } + else + { + c4 = (unsigned char)*s; + if (c4) + { + s++; + c4 &= 0x3F; + if (c < 0xFC) + { + c = (wchar_t)(((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4); + } + else + { + c = (wchar_t)(((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (unsigned char)(*s & 0x3F)); + if (*s) + s++; + } + } + } + } + } + } + } + } +#endif } - else /* +hhmm */ - { m = (int)atol(s); - h = m / 100; - m = m % 100; + /* use UTF16 encoding when wchar_t is too small to hold UCS */ + if (sizeof(wchar_t) < 4 && c > 0xFFFF) + { + wchar_t c1, c2; + c1 = 0xD800 - (0x10000 >> 10) + (c >> 10); + c2 = 0xDC00 + (c & 0x3FF); + if (soap_append_lab(soap, (const char*)&c1, sizeof(wchar_t)) || soap_append_lab(soap, (const char*)&c2, sizeof(wchar_t))) + return NULL; + } + else if (soap_append_lab(soap, (const char*)&c, sizeof(wchar_t))) + { + return NULL; } - T.tm_min -= m; - T.tm_hour -= h; - /* put hour and min in range */ - T.tm_hour += T.tm_min / 60; - T.tm_min %= 60; - if (T.tm_min < 0) - { T.tm_min += 60; - T.tm_hour--; - } - T.tm_mday += T.tm_hour / 24; - T.tm_hour %= 24; - if (T.tm_hour < 0) - { T.tm_hour += 24; - T.tm_mday--; - } - /* note: day of the month may be out of range, timegm() handles it */ } -#endif - *p = soap_timegm(&T); } - else /* no UTC or timezone, so assume we got a localtime */ - { T.tm_isdst = -1; - *p = mktime(&T); + l = soap->labidx / sizeof(wchar_t); + c = L'\0'; + if (soap_append_lab(soap, (const char*)&c, sizeof(wchar_t))) + return NULL; + if ((maxlen >= 0 && l > (size_t)maxlen) || (minlen > 0 && l < (size_t)minlen)) + { + soap->error = SOAP_LENGTH; + return NULL; + } + t = (wchar_t*)(void*)soap->labbuf; +#ifndef WITH_LEAN + if (flag >= 4 && t) + t = soap_wcollapse(soap, t, flag, 1); +#endif +#ifndef WITH_LEANER + if (pattern && soap->fwvalidate) + { + soap->error = soap->fwvalidate(soap, pattern, t); + if (soap->error) + return NULL; } +#endif + return t; } - return soap->error; + return NULL; } #endif /******************************************************************************/ + #ifndef WITH_LEAN -SOAP_FMAC1 -time_t * -SOAP_FMAC2 -soap_indateTime(struct soap *soap, const char *tag, time_t *p, const char *type, int t) -{ if (soap_element_begin_in(soap, tag, 0, NULL)) - return NULL; - if (*soap->type - && soap_match_tag(soap, soap->type, type) - && soap_match_tag(soap, soap->type, ":dateTime")) - { soap->error = SOAP_TYPE; - soap_revert(soap); +static wchar_t* +soap_wcollapse(struct soap *soap, wchar_t *s, int flag, int insitu) +{ + /* flag 4=normalizedString (replace), 5=token (collapse) */ + wchar_t *t; + size_t n; + if (!s) return NULL; + if (flag == 4) + { + for (t = s; *t && (!soap_coblank((soap_wchar)*t) || *t == 32); t++) + continue; + if (*t) + { + /* replace blanks and control char by space */ + if (!insitu) + s = soap_wstrdup(soap, s); + if (s) + for (t = s; *t; t++) + if (soap_coblank((soap_wchar)*t)) + *t = L' '; + } + return s; } - p = (time_t*)soap_id_enter(soap, soap->id, p, t, sizeof(time_t), 0, NULL, NULL, NULL); - if (*soap->href) - p = (time_t*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(time_t), 0, NULL); - else if (p) - { if (soap_s2dateTime(soap, soap_value(soap), p)) - return NULL; + /* collapse white space */ + for (t = s; *t && soap_coblank((soap_wchar)*t); t++) + continue; + n = 0; + while (t[n]) + n++; + if (insitu && s < t) + (void)soap_memmove(s, n + 1, t, n + 1); + else + s = t; + if (n > 0) + { + if (!soap_coblank((soap_wchar)s[n-1])) + { + for (t = s; (*t && !soap_coblank((soap_wchar)*t)) || (*t == 32 && (!t[1] || !soap_coblank((soap_wchar)t[1]))); t++) + continue; + if (!*t) + return s; + } + if (!insitu) + s = soap_wstrdup(soap, s); + if (s) + { + for (t = s; *t; t++) + { + if (soap_coblank((soap_wchar)*t)) + { + wchar_t *r; + *t = L' '; + for (r = t + 1; *r && soap_coblank((soap_wchar)*r); r++) + continue; + if (r > t + 1) + (void)soap_memmove(t + 1, sizeof(wchar_t) * (n - (t-s)), r, sizeof(wchar_t) * (n - (r-s) + 1)); + } + } + t--; + if (t >= s && *t == 32) + *t = L'\0'; + } } - if (soap->body && soap_element_end_in(soap, tag)) - return NULL; - return p; + return s; } #endif /******************************************************************************/ -#ifndef PALM_2 + +#ifndef WITH_LEAN SOAP_FMAC1 -int +const char* SOAP_FMAC2 -soap_outliteral(struct soap *soap, const char *tag, char *const*p, const char *type) -{ int i; - 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'; - for (i = 0; soap->local_namespaces[i].id; i++) - if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id)) - break; - t++; - if (soap_element(soap, t, 0, type) - || soap_attribute(soap, "xmlns", soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS) - || soap_element_start_end_out(soap, NULL)) - return soap->error; - } +soap_wchar2s(struct soap *soap, const wchar_t *s) +{ + soap_wchar c; + char *r, *t; + const wchar_t *q = s; + size_t n = 0; + if (!s) + return NULL; + while ((c = *q++)) + { + if (c > 0 && c < 0x80) + n++; else - { t = tag; - if (soap_element_begin_out(soap, t, 0, type)) - return soap->error; +#ifdef WITH_REPLACE_ILLEGAL_UTF8 + n += 4; +#else + n += 6; +#endif + } + r = t = (char*)soap_malloc(soap, n + 1); + if (r) + { + /* Convert wchar to UTF8 (chars above U+10FFFF are silently converted, but should not be used) */ + while ((c = *s++)) + { + if (c > 0 && c < 0x80) + { + *t++ = (char)c; + } + else + { + /* check for UTF16 encoding when wchar_t is too small to hold UCS */ + if (sizeof(wchar_t) < 4 && (c & 0xFC00) == 0xD800) + { + soap_wchar d = *s; + if ((d & 0xFC00) == 0xDC00) + { + c = ((c - 0xD800) << 10) + (d - 0xDC00) + 0x10000; + s++; + } +#ifdef WITH_REPLACE_ILLEGAL_UTF8 + else + { + c = SOAP_UNKNOWN_UNICODE_CHAR; /* Malformed UTF-16 */ + } +#endif + } + if (c < 0x0800) + { + *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); + } + else + { +#ifdef WITH_REPLACE_ILLEGAL_UTF8 + if (!((c >= 0x80 && c <= 0xD7FF) || (c >= 0xE000 && c <= 0xFFFD) || (c >= 0x10000 && c <= 0x10FFFF))) + c = SOAP_UNKNOWN_UNICODE_CHAR; +#endif + if (c < 0x010000) + { + *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); + } + else + { + if (c < 0x200000) + { + *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + } + else + { + if (c < 0x04000000) + { + *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + } + else + { + *t++ = (char)(0xFC | ((c >> 30) & 0x01)); + *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); + } + *t++ = (char)(0x80 | (c & 0x3F)); + } } + *t = '\0'; } - if (p && *p) - { if (soap_send(soap, *p)) - return soap->error; + return r; +} +#endif + +/******************************************************************************/ + +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outstring(struct soap *soap, const char *tag, int id, char *const*p, const char *type, int n) +{ + id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n, NULL); + if (id < 0) + return soap->error; + if (!**p) + { + if ((soap->mode & SOAP_C_NILSTRING)) + return soap_element_null(soap, tag, id, type); + return soap_element_empty(soap, tag, id, type); } - if (t) - return soap_element_end_out(soap, t); + if (soap_element_begin_out(soap, tag, id, type) + || soap_string_out(soap, *p, 0) + || soap_element_end_out(soap, tag)) + return soap->error; return SOAP_OK; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 char ** SOAP_FMAC2 -soap_inliteral(struct soap *soap, const char *tag, char **p) -{ if (soap_element_begin_in(soap, tag, 1, NULL)) - { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT) +soap_instring(struct soap *soap, const char *tag, char **p, const char *type, int t, int flag, long minlen, long maxlen, const char *pattern) +{ + (void)type; + if (soap_element_begin_in(soap, tag, 1, NULL)) + { + if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG) return NULL; soap->error = SOAP_OK; } if (!p) - { if (!(p = (char**)soap_malloc(soap, sizeof(char*)))) + { + p = (char**)soap_malloc(soap, sizeof(char*)); + if (!p) return NULL; } - if (soap->body || (tag && *tag == '-')) - { *p = soap_string_in(soap, 0, -1, -1); - if (!*p) + if (soap->null) + { + *p = NULL; + } + else if (soap->body) + { + *p = soap_string_in(soap, flag, minlen, maxlen, pattern); + if (!*p || !(char*)soap_id_enter(soap, soap->id, *p, t, sizeof(char*), NULL, NULL, NULL, NULL)) return NULL; if (!**p && tag && *tag == '-') - { soap->error = SOAP_NO_TAG; + { + soap->error = SOAP_NO_TAG; return NULL; } } - else if (soap->null) - *p = NULL; - else + else if (tag && *tag == '-') + { + soap->error = SOAP_NO_TAG; + return NULL; + } + else if (*soap->href != '#') + { + if (minlen > 0) + { + soap->error = SOAP_LENGTH; + return NULL; + } *p = soap_strdup(soap, SOAP_STR_EOS); + if (!*p) + return NULL; + } + if (*soap->href == '#') + p = (char**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(char**), 0, NULL); if (soap->body && soap_element_end_in(soap, tag)) return NULL; return p; } -#endif /******************************************************************************/ + #ifndef WITH_LEANER -#ifndef PALM_2 SOAP_FMAC1 int SOAP_FMAC2 -soap_outwliteral(struct soap *soap, const char *tag, wchar_t *const*p, const char *type) -{ int i; - 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'; - for (i = 0; soap->local_namespaces[i].id; i++) - if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id)) - break; - t++; - if (soap_element(soap, t, 0, type) - || soap_attribute(soap, "xmlns", soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS) - || soap_element_start_end_out(soap, NULL)) - return soap->error; - } - else - { t = tag; - 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)) - return soap->error; - } +soap_outwstring(struct soap *soap, const char *tag, int id, wchar_t *const*p, const char *type, int n) +{ + id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n, NULL); + if (id < 0) + return soap->error; + if (!**p) + { + if ((soap->mode & SOAP_C_NILSTRING)) + return soap_element_null(soap, tag, id, type); + return soap_element_empty(soap, tag, id, type); } - if (t) - return soap_element_end_out(soap, t); + if (soap_element_begin_out(soap, tag, id, type) + || soap_wstring_out(soap, *p, 0) + || soap_element_end_out(soap, tag)) + return soap->error; return SOAP_OK; } #endif -#endif /******************************************************************************/ + #ifndef WITH_LEANER -#ifndef PALM_2 SOAP_FMAC1 wchar_t ** SOAP_FMAC2 -soap_inwliteral(struct soap *soap, const char *tag, wchar_t **p) -{ if (soap_element_begin_in(soap, tag, 1, NULL)) - { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT) +soap_inwstring(struct soap *soap, const char *tag, wchar_t **p, const char *type, int t, int flag, long minlen, long maxlen, const char *pattern) +{ + (void)type; + if (soap_element_begin_in(soap, tag, 1, NULL)) + { + if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG) return NULL; soap->error = SOAP_OK; } if (!p) - { if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*)))) + { + p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*)); + if (!p) return NULL; } - if (soap->body) - { *p = soap_wstring_in(soap, 0, -1, -1); - if (!*p) + if (soap->null) + { + *p = NULL; + } + else if (soap->body) + { + *p = soap_wstring_in(soap, flag, minlen, maxlen, pattern); + if (!*p || !(wchar_t*)soap_id_enter(soap, soap->id, *p, t, sizeof(wchar_t*), NULL, NULL, NULL, NULL)) return NULL; if (!**p && tag && *tag == '-') - { soap->error = SOAP_NO_TAG; + { + soap->error = SOAP_NO_TAG; return NULL; } } else if (tag && *tag == '-') - { soap->error = SOAP_NO_TAG; + { + soap->error = SOAP_NO_TAG; return NULL; } - else if (soap->null) - *p = NULL; - else - *p = soap_wstrdup(soap, (wchar_t*)SOAP_STR_EOS); + else if (*soap->href != '#') + { + if (minlen > 0) + { + soap->error = SOAP_LENGTH; + return NULL; + } + *p = soap_wstrdup(soap, L""); + } + if (*soap->href == '#') + p = (wchar_t**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(wchar_t**), 0, NULL); if (soap->body && soap_element_end_in(soap, tag)) return NULL; return p; } #endif + +/******************************************************************************/ + +#ifndef WITH_LEAN +#ifdef UNDER_CE +/* WinCE mktime (based on the mingw-runtime, public domain) */ +#define __FILETIME_to_ll(f) ((long long)(f).dwHighDateTime << 32 | (long long)(f).dwLowDateTime) +static time_t +mktime(struct tm *pt) +{ + SYSTEMTIME s, s1, s2; + FILETIME f, f1, f2; + long long diff; + GetSystemTime(&s1); + GetLocalTime(&s2); + SystemTimeToFileTime(&s1, &f1); + SystemTimeToFileTime(&s2, &f2); + diff = (__FILETIME_to_ll(f2) - __FILETIME_to_ll(f1)) / 10000000LL; + s.wYear = pt->tm_year + 1900; + s.wMonth = pt->tm_mon + 1; + s.wDayOfWeek = pt->tm_wday; + s.wDay = pt->tm_mday; + s.wHour = pt->tm_hour; + s.wMinute = pt->tm_min; + s.wSecond = pt->tm_sec; + s.wMilliseconds = 0; + SystemTimeToFileTime(&s, &f); + return (time_t)((__FILETIME_to_ll(f) - 116444736000000000LL) / 10000000LL) - (time_t)diff; +} +#endif #endif /******************************************************************************/ -#ifndef PALM_2 -SOAP_FMAC1 -const char * -SOAP_FMAC2 -soap_value(struct soap *soap) -{ size_t i; - soap_wchar c = 0; - char *s = soap->tmpbuf; - if (!soap->body) - return SOAP_STR_EOS; - do c = soap_get(soap); - while (soap_blank(c)); - for (i = 0; i < sizeof(soap->tmpbuf) - 1; i++) - { if (c == SOAP_TT || (int)c == EOF) - break; - *s++ = (char)c; - c = soap_get(soap); - } - for (s--; i > 0; i--, s--) - { if (!soap_blank(*s)) - break; - } - s[1] = '\0'; - if ((int)c == EOF || c == SOAP_TT) - soap_unget(soap, c); - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element content value='%s'\n", soap->tmpbuf)); -#ifdef WITH_DOM - if ((soap->mode & SOAP_XML_DOM) && soap->dom) - soap->dom->data = soap_strdup(soap, soap->tmpbuf); + +#ifndef WITH_LEAN +#ifdef UNDER_CE +/* WinCE gmtime_r (based on the mingw-runtime, public domain) */ +#define HAVE_GMTIME_R +static struct tm* +gmtime_r(const time_t *t, struct tm *pt) +{ + FILETIME f, f1, f2; + SYSTEMTIME s, s1 = {0}; + long long time = (long long)(*t) * 10000000LL + 116444736000000000LL; + f.dwHighDateTime = (DWORD)((time >> 32) & 0x00000000FFFFFFFF); + f.dwLowDateTime = (DWORD)(time & 0x00000000FFFFFFFF); + FileTimeToSystemTime(&f, &s); + pt->tm_year = s.wYear - 1900; + pt->tm_mon = s.wMonth - 1; + pt->tm_wday = s.wDayOfWeek; + pt->tm_mday = s.wDay; + s1.wYear = s.wYear; + s1.wMonth = 1; + s1.wDayOfWeek = 1; + s1.wDay = 1; + SystemTimeToFileTime(&s1, &f1); + SystemTimeToFileTime(&s, &f2); + pt->tm_yday = (((__FILETIME_to_ll(f2) - __FILETIME_to_ll(f1)) / 10000000LL) / (60 * 60 * 24)); + pt->tm_hour = s.wHour; + pt->tm_min = s.wMinute; + pt->tm_sec = s.wSecond; + pt->tm_isdst = 0; + return pt; +} #endif - return soap->tmpbuf; /* return non-null pointer */ +#endif + +/******************************************************************************/ + +#ifndef WITH_LEAN +#ifdef UNDER_CE +/* WinCE very simple strftime for format "%Y-%m-%dT%H:%M:%SZ", note: %F and %T not supported by MS */ +static size_t +strftime(char *buf, size_t len, const char *format, const struct tm *pT) +{ + (void)len; (void)format; +#ifndef WITH_NOZONE + (SOAP_SNPRINTF(buf, len, 20), "%04d-%02d-%02dT%02d:%02d:%02dZ", pT->tm_year + 1900, pT->tm_mon + 1, pT->tm_mday, pT->tm_hour, pT->tm_min, pT->tm_sec); +#else + (SOAP_SNPRINTF(buf, len, 20), "%04d-%02d-%02dT%02d:%02d:%02d", pT->tm_year + 1900, pT->tm_mon + 1, pT->tm_mday, pT->tm_hour, pT->tm_min, pT->tm_sec); +#endif + return len; } #endif +#endif /******************************************************************************/ -#if !defined(WITH_LEANER) || !defined(WITH_NOHTTP) -#ifndef PALM_2 + +#if !defined(WITH_LEAN) || defined(WITH_COOKIES) SOAP_FMAC1 -int +time_t SOAP_FMAC2 -soap_getline(struct soap *soap, char *s, int len) -{ int i = len; - soap_wchar c = 0; - for (;;) - { while (--i > 0) - { c = soap_getchar(soap); - if (c == '\r' || c == '\n') - break; - if ((int)c == EOF) - return soap->error = SOAP_EOF; - *s++ = (char)c; - } - 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 */ - break; - c = soap_get0(soap); - if (c != ' ' && c != '\t') /* HTTP line continuation? */ - break; - } - else if ((int)c == EOF) - return soap->error = SOAP_EOF; - if (i < 0) - return soap->error = SOAP_HDR; - } - return SOAP_OK; -} +soap_timegm(struct tm *T) +{ +#if defined(HAVE_TIMEGM) + return timegm(T); +#else + time_t t, g, z; + struct tm tm; +#ifndef HAVE_GMTIME_R + struct tm *tp; +#endif + t = mktime(T); + if (t == (time_t)-1) + return (time_t)-1; +#ifdef HAVE_GMTIME_R + if (gmtime_r(&t, &tm) == SOAP_FUNC_R_ERR) + return (time_t)-1; +#else + tp = gmtime(&t); + if (!tp) + return (time_t)-1; + tm = *tp; +#endif + tm.tm_isdst = 0; + g = mktime(&tm); + if (g == (time_t)-1) + return (time_t)-1; + z = g - t; + return t - z; #endif +} #endif /******************************************************************************/ -#ifndef PALM_1 -static size_t -soap_count_attachments(struct soap *soap) + +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_dateTime2s(struct soap *soap, time_t n) { -#ifndef WITH_LEANER - struct soap_multipart *content; - size_t count = soap->count; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the message size with attachments, current count=%lu\n", (unsigned long)count)); - if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of DIME attachments\n")); - for (content = soap->dime.first; content; content = content->next) - { count += 12 + ((content->size+3)&(~3)); - if (content->id) - count += ((strlen(content->id)+3)&(~3)); - if (content->type) - count += ((strlen(content->type)+3)&(~3)); - if (content->options) - count += ((((unsigned char)content->options[2] << 8) | ((unsigned char)content->options[3]))+7)&(~3); - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of DIME attachment content is %lu bytes\n", (unsigned long)content->size)); + struct tm T, *pT = &T; + size_t l = 0; +#if defined(HAVE_GMTIME_R) && !defined(WITH_NOZONE) + if (gmtime_r(&n, pT) != SOAP_FUNC_R_ERR) + l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); +#elif defined(HAVE_GMTIME) && !defined(WITH_NOZONE) + pT = gmtime(&n); + if (pT) + l = 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)) && !defined(WITH_NOZONE) +#if defined(HAVE_LOCALTIME_R) + if (localtime_r(&n, pT) != SOAP_FUNC_R_ERR) + { + l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S%z", pT); + if (l) + { + (void)soap_memmove(soap->tmpbuf + 23, sizeof(soap->tmpbuf) - 23, soap->tmpbuf + 22, 3); /* 2000-03-01T02:00:00+0300 */ + soap->tmpbuf[22] = ':'; /* 2000-03-01T02:00:00+03:00 */ } } - if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary) - { size_t n = strlen(soap->mime.boundary); - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of MIME attachments\n")); - for (content = soap->mime.first; content; content = content->next) - { const char *s; - /* count \r\n--boundary\r\n */ - count += 6 + n; - /* count Content-Type: ...\r\n */ - if (content->type) - count += 16 + strlen(content->type); - /* count Content-Transfer-Encoding: ...\r\n */ - s = soap_code_str(mime_codes, content->encoding); - if (s) - count += 29 + strlen(s); - /* count Content-ID: ...\r\n */ - if (content->id) - count += 14 + strlen(content->id); - /* count Content-Location: ...\r\n */ - if (content->location) - count += 20 + strlen(content->location); - /* count Content-Description: ...\r\n */ - if (content->description) - count += 23 + strlen(content->description); - /* count \r\n...content */ - count += 2 + content->size; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of MIME attachment content is %lu bytes\n", (unsigned long)content->size)); +#else + pT = localtime(&n); + if (pT) + { + l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S%z", pT); + if (l) + { + (void)soap_memmove(soap->tmpbuf + 23, sizeof(soap->tmpbuf) - 23, soap->tmpbuf + 22, 3); /* 2000-03-01T02:00:00+0300 */ + soap->tmpbuf[22] = ':'; /* 2000-03-01T02:00:00+03:00 */ } - /* count \r\n--boundary-- */ - count += 6 + n; } - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New count is %lu bytes\n", (unsigned long)count)); - return count; +#endif +#elif defined(HAVE_GETTIMEOFDAY) && !defined(WITH_NOZONE) +#if defined(HAVE_LOCALTIME_R) + if (localtime_r(&n, pT) != SOAP_FUNC_R_ERR) + { + struct timeval tv; + struct timezone tz; + memset((void*)&tz, 0, sizeof(tz)); + gettimeofday(&tv, &tz); + l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + if (l) + (SOAP_SNPRINTF(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, 7), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60); + } +#else + pT = localtime(&n); + if (pT) + { + struct timeval tv; + struct timezone tz; + memset((void*)&tz, 0, sizeof(tz)); + gettimeofday(&tv, &tz); + l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + if (l) + (SOAP_SNPRINTF(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, 7), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60); + } +#endif +#elif defined(HAVE_FTIME) && !defined(WITH_NOZONE) +#if defined(HAVE_LOCALTIME_R) + if (localtime_r(&n, pT) != SOAP_FUNC_R_ERR) + { + struct timeb t; + memset((void*)&t, 0, sizeof(t)); +#ifdef __BORLANDC__ + ::ftime(&t); +#else + ftime(&t); +#endif + l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + if (l) + (SOAP_SNPRINTF(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, 7), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60); + } #else - return soap->count; + pT = localtime(&n); + if (pT) + { + struct timeb t; + memset((void*)&t, 0, sizeof(t)); +#ifdef __BORLANDC__ + ::ftime(&t); +#else + ftime(&t); +#endif + l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + if (l) + (SOAP_SNPRINTF(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, 7), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60); + } +#endif +#elif defined(HAVE_LOCALTIME_R) + if (localtime_r(&n, pT) != SOAP_FUNC_R_ERR) + l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); +#else + pT = localtime(&n); + if (pT) + l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); #endif + if (!l) + soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), "1969-12-31T23:59:59Z"); + return soap->tmpbuf; } #endif /******************************************************************************/ -#ifndef WITH_LEANER -#ifndef PALM_1 -static int -soap_putdimefield(struct soap *soap, const char *s, size_t n) -{ if (soap_send_raw(soap, s, n)) + +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outdateTime(struct soap *soap, const char *tag, int id, const time_t *p, const char *type, int n) +{ + if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_dateTime2s(soap, *p), 0)) return soap->error; - return soap_send_raw(soap, SOAP_STR_PADDING, -(long)n&3); + return soap_element_end_out(soap, tag); } #endif -#endif /******************************************************************************/ -#ifndef WITH_LEANER -#ifndef PALM_1 + +#ifndef WITH_LEAN SOAP_FMAC1 -char * +int SOAP_FMAC2 -soap_dime_option(struct soap *soap, unsigned short optype, const char *option) -{ size_t n; - char *s = NULL; - if (option) - { n = strlen(option); - s = (char*)soap_malloc(soap, n + 5); - if (s) - { s[0] = (char)(optype >> 8); - s[1] = (char)(optype & 0xFF); - s[2] = (char)(n >> 8); - s[3] = (char)(n & 0xFF); - strcpy(s + 4, option); +soap_s2dateTime(struct soap *soap, const char *s, time_t *p) +{ + *p = 0; + if (s) + { + unsigned long d; + struct tm T; + char *t; + if (!*s) + return soap->error = SOAP_EMPTY; + memset((void*)&T, 0, sizeof(T)); + d = soap_strtoul(s, &t, 10); + if (*t == '-') + { + /* YYYY-MM-DD */ + T.tm_year = (int)d; + T.tm_mon = (int)soap_strtoul(t + 1, &t, 10); + T.tm_mday = (int)soap_strtoul(t + 1, &t, 10); + } + else if (!(soap->mode & SOAP_XML_STRICT)) + { + /* YYYYMMDD */ + T.tm_year = (int)(d / 10000); + T.tm_mon = (int)(d / 100 % 100); + T.tm_mday = (int)(d % 100); + } + else + { + return soap->error = SOAP_TYPE; + } + if (*t == 'T' || ((*t == 't' || *t == ' ') && !(soap->mode & SOAP_XML_STRICT))) + { + d = soap_strtoul(t + 1, &t, 10); + if (*t == ':') + { + /* Thh:mm:ss */ + T.tm_hour = (int)d; + T.tm_min = (int)soap_strtoul(t + 1, &t, 10); + T.tm_sec = (int)soap_strtoul(t + 1, &t, 10); + } + else if (!(soap->mode & SOAP_XML_STRICT)) + { + /* Thhmmss */ + T.tm_hour = (int)(d / 10000); + T.tm_min = (int)(d / 100 % 100); + T.tm_sec = (int)(d % 100); + } + else + { + return soap->error = SOAP_TYPE; + } + } + if (T.tm_year == 1) + T.tm_year = 70; + else + T.tm_year -= 1900; + T.tm_mon--; + if (*t == '.') + { + for (t++; *t; t++) + if (*t < '0' || *t > '9') + break; + } + if (*t == ' ' && !(soap->mode & SOAP_XML_STRICT)) + t++; + if (*t) + { +#ifndef WITH_NOZONE + if (*t == '+' || *t == '-') + { + int h, m; + m = (int)soap_strtol(t, &t, 10); + if (*t == ':') + { + /* +hh:mm */ + h = m; + m = (int)soap_strtol(t + 1, &t, 10); + if (h < 0) + m = -m; + } + else if (!(soap->mode & SOAP_XML_STRICT)) + { + /* +hhmm */ + h = m / 100; + m = m % 100; + } + else + { + /* +hh */ + h = m; + m = 0; + } + if (*t) + return soap->error = SOAP_TYPE; + T.tm_min -= m; + T.tm_hour -= h; + /* put hour and min in range */ + T.tm_hour += T.tm_min / 60; + T.tm_min %= 60; + if (T.tm_min < 0) + { + T.tm_min += 60; + T.tm_hour--; + } + T.tm_mday += T.tm_hour / 24; + T.tm_hour %= 24; + if (T.tm_hour < 0) + { + T.tm_hour += 24; + T.tm_mday--; + } + /* note: day of the month may be out of range, timegm() handles it */ + } + else if (*t != 'Z') + { + return soap->error = SOAP_TYPE; + } +#endif + *p = soap_timegm(&T); + } + else /* no UTC or timezone, so assume we got a localtime */ + { + T.tm_isdst = -1; + *p = mktime(&T); } } - return s; + return soap->error; } #endif -#endif /******************************************************************************/ -#ifndef WITH_LEANER -#ifndef PALM_1 + +#ifndef WITH_LEAN SOAP_FMAC1 -int +time_t * SOAP_FMAC2 -soap_putdimehdr(struct soap *soap) -{ unsigned char tmp[12]; - size_t optlen = 0, idlen = 0, typelen = 0; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Put DIME header id='%s'\n", soap->dime.id?soap->dime.id:SOAP_STR_EOS)); - if (soap->dime.options) - optlen = (((unsigned char)soap->dime.options[2] << 8) | ((unsigned char)soap->dime.options[3])) + 4; - if (soap->dime.id) - { idlen = strlen(soap->dime.id); - if (idlen > 0x0000FFFF) - idlen = 0x0000FFFF; +soap_indateTime(struct soap *soap, const char *tag, time_t *p, const char *type, int t) +{ + if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":dateTime")) + { + soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; } - if (soap->dime.type) - { typelen = strlen(soap->dime.type); - if (typelen > 0x0000FFFF) - typelen = 0x0000FFFF; + p = (time_t*)soap_id_enter(soap, soap->id, p, t, sizeof(time_t), NULL, NULL, NULL, NULL); + if (!p) + return NULL; + if (*soap->href != '#') + { + int err = soap_s2dateTime(soap, soap_value(soap), p); + if ((soap->body && soap_element_end_in(soap, tag)) || err) + return NULL; } - tmp[0] = SOAP_DIME_VERSION | (soap->dime.flags & 0x7); - tmp[1] = soap->dime.flags & 0xF0; - tmp[2] = (char)(optlen >> 8); - tmp[3] = (char)(optlen & 0xFF); - tmp[4] = (char)(idlen >> 8); - tmp[5] = (char)(idlen & 0xFF); - tmp[6] = (char)(typelen >> 8); - tmp[7] = (char)(typelen & 0xFF); - tmp[8] = (char)(soap->dime.size >> 24); - tmp[9] = (char)((soap->dime.size >> 16) & 0xFF); - tmp[10] = (char)((soap->dime.size >> 8) & 0xFF); - tmp[11] = (char)(soap->dime.size & 0xFF); - if (soap_send_raw(soap, (char*)tmp, 12) - || soap_putdimefield(soap, soap->dime.options, optlen) - || soap_putdimefield(soap, soap->dime.id, idlen) - || soap_putdimefield(soap, soap->dime.type, typelen)) - return soap->error; - return SOAP_OK; + else + { + p = (time_t*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(time_t), 0, NULL, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + } + return p; } #endif -#endif /******************************************************************************/ -#ifndef WITH_LEANER -#ifndef PALM_1 + SOAP_FMAC1 int SOAP_FMAC2 -soap_putdime(struct soap *soap) -{ struct soap_multipart *content; - if (!(soap->mode & SOAP_ENC_DIME)) - return SOAP_OK; - for (content = soap->dime.first; content; content = content->next) - { void *handle; - soap->dime.size = content->size; - soap->dime.id = content->id; - soap->dime.type = content->type; - soap->dime.options = content->options; - soap->dime.flags = SOAP_DIME_VERSION | SOAP_DIME_MEDIA; - if (soap->fdimereadopen && ((handle = soap->fdimereadopen(soap, (void*)content->ptr, content->id, content->type, content->options)) || soap->error)) - { size_t size = content->size; - if (!handle) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadopen failed\n")); - return soap->error; - } - if (!size && ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE)) - { size_t chunksize = sizeof(soap->tmpbuf); - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming DIME\n")); - do - { size = soap->fdimeread(soap, handle, soap->tmpbuf, chunksize); - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread returned %lu bytes\n", (unsigned long)size)); - if (size < chunksize) - { soap->dime.flags &= ~SOAP_DIME_CF; - if (!content->next) - soap->dime.flags |= SOAP_DIME_ME; - } - else - soap->dime.flags |= SOAP_DIME_CF; - soap->dime.size = size; - if (soap_putdimehdr(soap) - || soap_putdimefield(soap, soap->tmpbuf, size)) - break; - if (soap->dime.id) - { soap->dime.flags &= ~(SOAP_DIME_MB | SOAP_DIME_MEDIA); - soap->dime.id = NULL; - soap->dime.type = NULL; - soap->dime.options = NULL; - } - } while (size >= chunksize); - } - else - { if (!content->next) - soap->dime.flags |= SOAP_DIME_ME; - if (soap_putdimehdr(soap)) - return soap->error; - do - { size_t bufsize; - if (size < sizeof(soap->tmpbuf)) - bufsize = size; - else - bufsize = sizeof(soap->tmpbuf); - if (!(bufsize = soap->fdimeread(soap, handle, soap->tmpbuf, bufsize))) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size)); - soap->error = SOAP_EOF; - break; - } - if (soap_send_raw(soap, soap->tmpbuf, bufsize)) - break; - size -= bufsize; - } while (size); - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n")); - soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3); - } - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n")); - if (soap->fdimereadclose) - soap->fdimereadclose(soap, handle); - } +soap_outliteral(struct soap *soap, const char *tag, char *const*p, const char *type) +{ + if (tag && *tag != '-') + if (soap_element_begin_out(soap, tag, 0, type)) + return soap->error; + if (p && *p) + if (soap_send(soap, *p)) /* send as-is */ + return soap->error; + if (tag && *tag != '-') + return soap_element_end_out(soap, tag); + return SOAP_OK; +} + +/******************************************************************************/ + +SOAP_FMAC1 +char ** +SOAP_FMAC2 +soap_inliteral(struct soap *soap, const char *tag, char **p) +{ + if (soap_element_begin_in(soap, tag, 1, NULL)) + { + if (soap->error != SOAP_NO_TAG || soap_peek(soap) == SOAP_TT) + return NULL; + soap->error = SOAP_OK; + } + if (!p) + { + p = (char**)soap_malloc(soap, sizeof(char*)); + if (!p) + return NULL; + } + if (soap->body || (tag && *tag == '-')) + { + if (tag && *tag != '-') + *p = soap_string_in(soap, 0, -1, -1, NULL); else - { if (!content->next) - soap->dime.flags |= SOAP_DIME_ME; - if (soap_putdimehdr(soap) - || soap_putdimefield(soap, (char*)content->ptr, content->size)) + *p = soap_string_in(soap, -1, -1, -1, NULL); + if (!*p) + return NULL; + if (!**p && tag && *tag == '-') + { + soap->error = SOAP_NO_TAG; + return NULL; + } + } + else if (soap->null) + { + *p = NULL; + } + else + { + *p = soap_strdup(soap, SOAP_STR_EOS); + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} + +/******************************************************************************/ + +#ifndef WITH_LEANER +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outwliteral(struct soap *soap, const char *tag, wchar_t *const*p, const char *type) +{ + if (tag && *tag != '-') + if (soap_element_begin_out(soap, tag, 0, type)) + return soap->error; + if (p) + { + wchar_t c; + const wchar_t *s = *p; + while ((c = *s++)) + { + if (soap_pututf8(soap, (unsigned long)c)) /* send as-is in UTF8 */ return soap->error; } } + if (tag && *tag != '-') + return soap_element_end_out(soap, tag); return SOAP_OK; } #endif -#endif /******************************************************************************/ + #ifndef WITH_LEANER -#ifndef PALM_1 -static char * -soap_getdimefield(struct soap *soap, size_t n) -{ soap_wchar c; - size_t i; - char *s; - char *p = NULL; - if (n) - { p = (char*)soap_malloc(soap, n + 1); - if (p) - { s = p; - for (i = n; i > 0; i--) - { if ((int)(c = soap_get1(soap)) == EOF) - { soap->error = SOAP_EOF; - return NULL; - } - *s++ = (char)c; - } - *s = '\0'; - if ((soap->error = soap_move(soap, -(long)n&3))) - return NULL; - } +SOAP_FMAC1 +wchar_t ** +SOAP_FMAC2 +soap_inwliteral(struct soap *soap, const char *tag, wchar_t **p) +{ + if (soap_element_begin_in(soap, tag, 1, NULL)) + { + if (soap->error != SOAP_NO_TAG || soap_peek(soap) == SOAP_TT) + return NULL; + soap->error = SOAP_OK; + } + if (!p) + { + p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*)); + if (!p) + return NULL; + } + if (soap->body) + { + if (tag && *tag != '-') + *p = soap_wstring_in(soap, 0, -1, -1, NULL); else - soap->error = SOAP_EOM; + *p = soap_wstring_in(soap, -1, -1, -1, NULL); + if (!*p) + return NULL; + if (!**p && tag && *tag == '-') + { + soap->error = SOAP_NO_TAG; + return NULL; + } + } + else if (tag && *tag == '-') + { + soap->error = SOAP_NO_TAG; + return NULL; + } + else if (soap->null) + { + *p = NULL; + } + else + { + *p = soap_wstrdup(soap, L""); } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; return p; } #endif -#endif /******************************************************************************/ -#ifndef WITH_LEANER -#ifndef PALM_1 + SOAP_FMAC1 -int +const char * SOAP_FMAC2 -soap_getdimehdr(struct soap *soap) -{ soap_wchar c; - char *s; - int i; - unsigned char tmp[12]; - size_t optlen, idlen, typelen; - if (!(soap->mode & SOAP_ENC_DIME)) - 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)))) - return soap->error = SOAP_EOF; - soap_unget(soap, soap_getchar(soap)); /* skip padding and get hdr */ - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... From chunked\n")); - return SOAP_OK; - } - s = (char*)tmp; - for (i = 12; i > 0; i--) - { if ((int)(c = soap_getchar(soap)) == EOF) - return soap->error = SOAP_EOF; +soap_value(struct soap *soap) +{ + size_t i; + soap_wchar c = 0; + char *s = soap->tmpbuf; + if (!soap->body) + return SOAP_STR_EOS; + do + { + c = soap_get(soap); + } while (soap_coblank(c)); + for (i = 0; i < sizeof(soap->tmpbuf) - 1; i++) + { + if (c == SOAP_TT || c == SOAP_LT || (int)c == EOF) + break; *s++ = (char)c; + c = soap_get(soap); + } + for (s--; i > 0; i--, s--) + { + if (!soap_coblank((soap_wchar)*s)) + 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); + } + else + { + soap->error = SOAP_LENGTH; + return NULL; + } +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { + soap->dom->text = soap_strdup(soap, soap->tmpbuf); + if (!soap->dom->text) + return NULL; } - if ((tmp[0] & 0xF8) != SOAP_DIME_VERSION) - return soap->error = SOAP_DIME_MISMATCH; - soap->dime.flags = (tmp[0] & 0x7) | (tmp[1] & 0xF0); - 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]; - 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; - if (!(soap->dime.id = soap_getdimefield(soap, idlen)) && soap->error) - 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)); - if (soap->dime.flags & SOAP_DIME_ME) - soap->mode &= ~SOAP_ENC_DIME; - return SOAP_OK; -} -#endif #endif + return soap->tmpbuf; /* return non-null pointer */ +} /******************************************************************************/ -#ifndef WITH_LEANER -#ifndef PALM_1 + +#if !defined(WITH_LEANER) || !defined(WITH_NOHTTP) SOAP_FMAC1 int SOAP_FMAC2 -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)) - return soap->error = SOAP_EOF; - } - if (soap_move(soap, (long)(((soap->dime.size+3)&(~3))-soap_tell(soap)))) - return soap->error = SOAP_EOF; +soap_getline(struct soap *soap, char *buf, int len) +{ + char *s = buf; + int i = len; + soap_wchar c = 0; for (;;) - { struct soap_multipart *content; - if (soap_getdimehdr(soap)) - break; - if (soap->fdimewriteopen && ((soap->dime.ptr = (char*)soap->fdimewriteopen(soap, soap->dime.id, soap->dime.type, soap->dime.options)) || soap->error)) - { const char *id, *type, *options; - size_t size, n; - if (!soap->dime.ptr) - return soap->error; - id = soap->dime.id; - type = soap->dime.type; - options = soap->dime.options; - for (;;) - { size = soap->dime.size; - for (;;) - { n = soap->buflen - soap->bufidx; - if (size < n) - n = size; - if ((soap->error = soap->fdimewrite(soap, (void*)soap->dime.ptr, soap->buf + soap->bufidx, n))) - break; - size -= n; - if (!size) - { soap->bufidx += n; - break; - } - if (soap_recv(soap)) - { soap->error = SOAP_EOF; - goto end; - } - } - if (soap_move(soap, -(long)soap->dime.size&3)) - { soap->error = SOAP_EOF; - break; - } - if (!(soap->dime.flags & SOAP_DIME_CF)) - break; - if (soap_getdimehdr(soap)) - break; - } -end: - if (soap->fdimewriteclose) - soap->fdimewriteclose(soap, (void*)soap->dime.ptr); - soap->dime.size = 0; - soap->dime.id = id; - soap->dime.type = type; - soap->dime.options = options; + { + while (i > 1) + { + c = soap_getchar(soap); + if (c == '\r' || c == '\n') + break; + if ((int)c == EOF) + return soap->error = SOAP_CHK_EOF; + *s++ = (char)c; + i--; } - else if (soap->dime.flags & SOAP_DIME_CF) - { const char *id, *type, *options; - id = soap->dime.id; - type = soap->dime.type; - options = soap->dime.options; - if (soap_new_block(soap) == NULL) - return SOAP_EOM; - for (;;) - { soap_wchar c; - size_t i; - char *s; - s = (char*)soap_push_block(soap, NULL, soap->dime.size); - if (!s) - return soap->error = SOAP_EOM; - for (i = soap->dime.size; i > 0; i--) - { if ((int)(c = soap_get1(soap)) == EOF) - return soap->error = SOAP_EOF; - *s++ = (char)c; - } - if (soap_move(soap, -(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' */ - 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.id = id; - soap->dime.type = type; - soap->dime.options = options; + *s = '\0'; + if (c != '\n') + c = soap_getchar(soap); /* got \r or something else, now get \n */ + if (c == '\n') + { + if (i == len) /* empty line: end of HTTP/MIME header */ + break; + c = soap_get0(soap); + if (c != ' ' && c != '\t') /* HTTP line continuation? */ + break; + } + else if ((int)c == EOF) + { + return soap->error = SOAP_CHK_EOF; + } + else if (i <= 1) + { + return soap->error = SOAP_HDR; } - else - soap->dime.ptr = soap_getdimefield(soap, soap->dime.size); - content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, soap->dime.ptr, soap->dime.size); - if (!content) - return soap->error = SOAP_EOM; - content->id = soap->dime.id; - content->type = soap->dime.type; - content->options = soap->dime.options; - if (soap->error) - return soap->error; - soap_resolve_attachment(soap, content); } - if (soap->error != SOAP_DIME_END) - return soap->error; - return soap->error = SOAP_OK; + return SOAP_OK; } #endif -#endif /******************************************************************************/ + +static ULONG64 +soap_count_attachments(struct soap *soap) +{ #ifndef WITH_LEANER -#ifndef PALM_1 -SOAP_FMAC1 -int -SOAP_FMAC2 -soap_getmimehdr(struct soap *soap) -{ struct soap_multipart *content; - do - { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) - return soap->error; - } - while (!*soap->msgbuf); - if (soap->msgbuf[0] == '-' && soap->msgbuf[1] == '-') - { char *s = soap->msgbuf + strlen(soap->msgbuf) - 1; - /* remove white space */ - while (soap_blank(*s)) - s--; - s[1] = '\0'; - if (soap->mime.boundary) - { if (strcmp(soap->msgbuf + 2, soap->mime.boundary)) - return soap->error = SOAP_MIME_ERROR; + struct soap_multipart *content; + ULONG64 count = soap->count; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the message size with attachments, current count=" SOAP_ULONG_FORMAT "\n", count)); + if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of DIME attachments\n")); + for (content = soap->dime.first; content; content = content->next) + { + count += 12 + ((content->size+3)&(~3)); + if (content->id) + count += ((strlen(content->id)+3)&(~3)); + if (content->type) + count += ((strlen(content->type)+3)&(~3)); + if (content->options) + count += ((((unsigned char)content->options[2] << 8) | ((unsigned char)content->options[3]))+7)&(~3); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of DIME attachment content is %lu bytes\n", (unsigned long)content->size)); } - else - soap->mime.boundary = soap_strdup(soap, soap->msgbuf + 2); - if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) - return soap->error; } - if (soap_set_mime_attachment(soap, NULL, 0, SOAP_MIME_NONE, NULL, NULL, NULL, NULL)) - return soap->error = SOAP_EOM; - content = soap->mime.last; - for (;;) - { char *key = soap->msgbuf; - char *val; - if (!*key) - break; - DBGLOG(TEST,SOAP_MESSAGE(fdebug, "MIME header: %s\n", key)); - val = strchr(soap->msgbuf, ':'); - if (val) - { *val = '\0'; - do val++; - while (*val && *val <= 32); - if (!soap_tag_cmp(key, "Content-ID")) - content->id = soap_strdup(soap, val); - else if (!soap_tag_cmp(key, "Content-Location")) - content->location = soap_strdup(soap, val); - else if (!soap_tag_cmp(key, "Content-Disposition")) - content->id = soap_strdup(soap, soap_get_header_attribute(soap, val, "name")); - else if (!soap_tag_cmp(key, "Content-Type")) - content->type = soap_strdup(soap, val); - else if (!soap_tag_cmp(key, "Content-Description")) - content->description = soap_strdup(soap, val); - else if (!soap_tag_cmp(key, "Content-Transfer-Encoding")) - content->encoding = (enum soap_mime_encoding)soap_code_int(mime_codes, val, (long)SOAP_MIME_NONE); + if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary) + { + size_t n = strlen(soap->mime.boundary); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of MIME attachments\n")); + for (content = soap->mime.first; content; content = content->next) + { + const char *s; + /* count \r\n--boundary\r\n */ + count += 6 + n; + /* count Content-Type: ...\r\n */ + if (content->type) + count += 16 + strlen(content->type); + /* count Content-Transfer-Encoding: ...\r\n */ + s = soap_code_str(mime_codes, content->encoding); + if (s) + count += 29 + strlen(s); + /* count Content-ID: ...\r\n */ + if (content->id) + count += 14 + strlen(content->id); + /* count Content-Location: ...\r\n */ + if (content->location) + count += 20 + strlen(content->location); + /* count Content-Description: ...\r\n */ + if (content->description) + count += 23 + strlen(content->description); + /* count \r\n...content */ + count += 2 + content->size; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of MIME attachment content is %lu bytes\n", (unsigned long)content->size)); } - if (soap_getline(soap, key, sizeof(soap->msgbuf))) - return soap->error; + /* count \r\n--boundary-- */ + count += 6 + n; } - return SOAP_OK; -} -#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New count=" SOAP_ULONG_FORMAT "\n", count)); + return count; +#else + return soap->count; #endif +} /******************************************************************************/ + #ifndef WITH_LEANER -#ifndef PALM_1 -SOAP_FMAC1 -int -SOAP_FMAC2 -soap_getmime(struct soap *soap) -{ while (soap_get_mime_attachment(soap, NULL)) - ; - return soap->error; +static int +soap_putdimefield(struct soap *soap, const char *s, size_t n) +{ + if (soap_send_raw(soap, s, n)) + return soap->error; + return soap_send_raw(soap, SOAP_STR_PADDING, -(long)n&3); } #endif -#endif /******************************************************************************/ + #ifndef WITH_LEANER -#ifndef PALM_1 SOAP_FMAC1 -void +char * SOAP_FMAC2 -soap_post_check_mime_attachments(struct soap *soap) -{ soap->imode |= SOAP_MIME_POSTCHECK; +soap_dime_option(struct soap *soap, unsigned short optype, const char *option) +{ + size_t n; + char *s = NULL; + if (option) + { + n = strlen(option); + s = (char*)soap_malloc(soap, n + 5); + if (s) + { + s[0] = (char)(optype >> 8); + s[1] = (char)(optype & 0xFF); + s[2] = (char)(n >> 8); + s[3] = (char)(n & 0xFF); + soap_strcpy(s + 4, n + 1, option); + } + } + return s; } #endif -#endif /******************************************************************************/ + #ifndef WITH_LEANER -#ifndef PALM_1 SOAP_FMAC1 int SOAP_FMAC2 -soap_check_mime_attachments(struct soap *soap) -{ if (soap->mode & SOAP_MIME_POSTCHECK) - return soap_get_mime_attachment(soap, NULL) != NULL; - return 0; +soap_putdimehdr(struct soap *soap) +{ + unsigned char tmp[12]; + size_t optlen = 0, idlen = 0, typelen = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Put DIME header id='%s'\n", soap->dime.id ? soap->dime.id : SOAP_STR_EOS)); + if (soap->dime.options) + optlen = (((unsigned char)soap->dime.options[2] << 8) | ((unsigned char)soap->dime.options[3])) + 4; + if (soap->dime.id) + { + idlen = strlen(soap->dime.id); + if (idlen > 0x0000FFFF) + idlen = 0x0000FFFF; + } + if (soap->dime.type) + { + typelen = strlen(soap->dime.type); + if (typelen > 0x0000FFFF) + typelen = 0x0000FFFF; + } + tmp[0] = SOAP_DIME_VERSION | (soap->dime.flags & 0x7); + tmp[1] = soap->dime.flags & 0xF0; + tmp[2] = (char)(optlen >> 8); + tmp[3] = (char)(optlen & 0xFF); + tmp[4] = (char)(idlen >> 8); + tmp[5] = (char)(idlen & 0xFF); + tmp[6] = (char)(typelen >> 8); + tmp[7] = (char)(typelen & 0xFF); + tmp[8] = (char)(soap->dime.size >> 24); + tmp[9] = (char)((soap->dime.size >> 16) & 0xFF); + tmp[10] = (char)((soap->dime.size >> 8) & 0xFF); + tmp[11] = (char)(soap->dime.size & 0xFF); + if (soap_send_raw(soap, (char*)tmp, 12) + || soap_putdimefield(soap, soap->dime.options, optlen) + || soap_putdimefield(soap, soap->dime.id, idlen) + || soap_putdimefield(soap, soap->dime.type, typelen)) + return soap->error; + return SOAP_OK; } #endif -#endif /******************************************************************************/ + #ifndef WITH_LEANER -#ifndef PALM_1 SOAP_FMAC1 -struct soap_multipart * +int SOAP_FMAC2 -soap_get_mime_attachment(struct soap *soap, void *handle) -{ soap_wchar c = 0; - size_t i, m = 0; - char *s, *t = NULL; +soap_putdime(struct soap *soap) +{ struct soap_multipart *content; - short flag = 0; - if (!(soap->mode & SOAP_ENC_MIME)) - return NULL; - content = soap->mime.last; - if (!content) - { if (soap_getmimehdr(soap)) - return NULL; - content = soap->mime.last; - } - else if (content != soap->mime.first) - { if (soap->fmimewriteopen && ((content->ptr = (char*)soap->fmimewriteopen(soap, (void*)handle, content->id, content->type, content->description, content->encoding)) || soap->error)) - { if (!content->ptr) - 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)); - if (!content->ptr && soap_new_block(soap) == NULL) - { soap->error = SOAP_EOM; - return NULL; - } - for (;;) - { if (content->ptr) - s = soap->tmpbuf; - else if (!(s = (char*)soap_push_block(soap, NULL, sizeof(soap->tmpbuf)))) - { soap->error = SOAP_EOM; - return NULL; - } - for (i = 0; i < sizeof(soap->tmpbuf); i++) - { if (m > 0) - { *s++ = *t++; - m--; + if (!(soap->mode & SOAP_ENC_DIME)) + return SOAP_OK; + for (content = soap->dime.first; content; content = content->next) + { + void *handle; + soap->dime.size = content->size; + soap->dime.id = content->id; + soap->dime.type = content->type; + soap->dime.options = content->options; + soap->dime.flags = SOAP_DIME_VERSION | SOAP_DIME_MEDIA; + if (soap->fdimereadopen && ((handle = soap->fdimereadopen(soap, (void*)content->ptr, content->id, content->type, content->options)) != NULL || soap->error)) + { + size_t size = content->size; + if (!handle) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadopen failed\n")); + return soap->error; } - else - { if (!flag) - { c = soap_get1(soap); - if ((int)c == EOF) - { soap->error = SOAP_EOF; - return NULL; + if (!size && ((soap->mode & SOAP_ENC_PLAIN) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE)) + { + size_t chunksize = sizeof(soap->tmpbuf); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming DIME\n")); + do + { + size = soap->fdimeread(soap, handle, soap->tmpbuf, chunksize); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread returned %lu bytes\n", (unsigned long)size)); + if (size < chunksize) + { + soap->dime.flags &= ~SOAP_DIME_CF; + if (!content->next) + soap->dime.flags |= SOAP_DIME_ME; } - } - if (flag || c == '\r') - { t = soap->msgbuf; - memset(t, 0, sizeof(soap->msgbuf)); - strcpy(t, "\n--"); - if (soap->mime.boundary) - strncat(t, soap->mime.boundary, sizeof(soap->msgbuf)-4); - do c = soap_getchar(soap); - while (c == *t++); - if ((int)c == EOF) - { soap->error = SOAP_EOF; - return NULL; + else + { + soap->dime.flags |= SOAP_DIME_CF; } - if (!*--t) - goto end; - *t = (char)c; - flag = (c == '\r'); - m = t - soap->msgbuf + 1 - flag; - t = soap->msgbuf; - c = '\r'; - } - *s++ = (char)c; + soap->dime.size = size; + if (soap_putdimehdr(soap) + || soap_putdimefield(soap, soap->tmpbuf, size)) + break; + if (soap->dime.id) + { + soap->dime.flags &= ~(SOAP_DIME_MB | SOAP_DIME_MEDIA); + soap->dime.id = NULL; + soap->dime.type = NULL; + soap->dime.options = NULL; + } + } while (size >= chunksize); } + else + { + if (!content->next) + soap->dime.flags |= SOAP_DIME_ME; + if (soap_putdimehdr(soap)) + return soap->error; + do + { + size_t bufsize; + if (size < sizeof(soap->tmpbuf)) + bufsize = size; + else + bufsize = sizeof(soap->tmpbuf); + bufsize = soap->fdimeread(soap, handle, soap->tmpbuf, bufsize); + if (!bufsize) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size)); + soap->error = SOAP_CHK_EOF; + break; + } + if (soap_send_raw(soap, soap->tmpbuf, bufsize)) + break; + size -= bufsize; + } while (size); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n")); + if (soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3)) + return soap->error; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n")); + if (soap->fdimereadclose) + soap->fdimereadclose(soap, handle); } - if (content->ptr && soap->fmimewrite) - { if ((soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i))) - break; - } - } -end: - *s = '\0'; /* force 0-terminated */ - if (content->ptr) - { if (!soap->error && soap->fmimewrite) - soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i); - if (soap->fmimewriteclose) - soap->fmimewriteclose(soap, (void*)content->ptr); - if (soap->error) - return NULL; - } - else - { content->size = soap_size_block(soap, NULL, i+1)-1; - content->ptr = soap_save_block(soap, NULL, NULL, 0); - } - soap_resolve_attachment(soap, content); - if (c == '-' && soap_getchar(soap) == '-') - { soap->mode &= ~SOAP_ENC_MIME; - if ((soap->mode & SOAP_MIME_POSTCHECK) && soap_end_recv(soap)) - return NULL; - } - else - { while (c != '\r' && (int)c != EOF && soap_blank(c)) - c = soap_getchar(soap); - if (c != '\r' || soap_getchar(soap) != '\n') - { soap->error = SOAP_MIME_ERROR; - return NULL; + else + { + if (!content->next) + soap->dime.flags |= SOAP_DIME_ME; + if (soap_putdimehdr(soap) + || soap_putdimefield(soap, (char*)content->ptr, content->size)) + return soap->error; } - if (soap_getmimehdr(soap)) - return NULL; } - return content; + return SOAP_OK; } #endif -#endif /******************************************************************************/ -#ifndef WITH_LEANER -#ifndef PALM_1 -SOAP_FMAC1 -int -SOAP_FMAC2 -soap_match_cid(struct soap *soap, const char *s, const char *t) -{ size_t n; - if (!s) - return 1; - if (!strcmp(s, t)) - return 0; - if (!strncmp(s, "cid:", 4)) - s += 4; - n = strlen(t); - if (*t == '<') - { t++; - n -= 2; - } - if (!strncmp(s, t, n) && !s[n]) - return 0; - soap_decode(soap->tmpbuf, sizeof(soap->tmpbuf), s, SOAP_STR_EOS); - if (!strncmp(soap->tmpbuf, t, n) && !soap->tmpbuf[n]) - return 0; - return 1; -} -#endif -#endif -/******************************************************************************/ #ifndef WITH_LEANER -#ifndef PALM_1 -static void -soap_resolve_attachment(struct soap *soap, struct soap_multipart *content) -{ if (content->id) - { struct soap_xlist **xp = &soap->xlist; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving attachment data for id=%s\n", content->id)); - while (*xp) - { 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)); - *xp = xq->next; - *xq->ptr = (unsigned char*)content->ptr; - *xq->size = (int)content->size; - *xq->type = (char*)content->type; - if (content->options) - *xq->options = (char*)content->options; - else - *xq->options = (char*)content->description; - SOAP_FREE(soap, xq); +static char * +soap_getdimefield(struct soap *soap, size_t n) +{ + char *p = NULL; + if (n > 0) + { + p = (char*)soap_malloc(soap, n + 1 > n ? n + 1 : n); + if (p) + { + char *s = p; + size_t i; + for (i = n; i > 0; i--) + { + soap_wchar c = soap_get1(soap); + if ((int)c == EOF) + { + soap->error = SOAP_CHK_EOF; + return NULL; + } + *s++ = (char)c; } - else - xp = &(*xp)->next; + if (n + 1 > n) + *s = '\0'; /* force NUL terminated */ + soap->error = soap_move(soap, (size_t)(-(long)n&3)); + if (soap->error) + return NULL; + } + else + { + soap->error = SOAP_EOM; } } + return p; } #endif -#endif /******************************************************************************/ + #ifndef WITH_LEANER -#ifndef PALM_1 SOAP_FMAC1 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)); - 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")) - return soap->error; - s = soap_code_str(mime_codes, content->encoding); - if (s && soap_send3(soap, "Content-Transfer-Encoding: ", s, "\r\n")) - return soap->error; - if (content->id && soap_send3(soap, "Content-ID: ", content->id, "\r\n")) +soap_getdimehdr(struct soap *soap) +{ + soap_wchar c; + char *s; + int i; + unsigned char tmp[12]; + size_t optlen, idlen, typelen; + if (!(soap->mode & SOAP_ENC_DIME)) + return soap->error = SOAP_DIME_END; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME header\n")); + s = (char*)tmp; + for (i = 12; i > 0; i--) + { + c = soap_getchar(soap); + if ((int)c == EOF) + return soap->error = SOAP_CHK_EOF; + *s++ = (char)c; + } + if ((tmp[0] & 0xF8) != SOAP_DIME_VERSION) + return soap->error = SOAP_DIME_MISMATCH; + soap->dime.flags = (tmp[0] & 0x7) | (tmp[1] & 0xF0); + optlen = (tmp[2] << 8) | tmp[3]; + idlen = (tmp[4] << 8) | tmp[5]; + typelen = (tmp[6] << 8) | tmp[7]; + 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)); + soap->dime.options = soap_getdimefield(soap, optlen); + if (!soap->dime.options && soap->error) return soap->error; - if (content->location && soap_send3(soap, "Content-Location: ", content->location, "\r\n")) + soap->dime.id = soap_getdimefield(soap, idlen); + if (!soap->dime.id && soap->error) return soap->error; - if (content->description && soap_send3(soap, "Content-Description: ", content->description, "\r\n")) + soap->dime.type = soap_getdimefield(soap, typelen); + if (!soap->dime.type && soap->error) return soap->error; - return soap_send_raw(soap, "\r\n", 2); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME flags=%x id='%s', type='%s', options='%s'\n", soap->dime.flags, 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; } #endif -#endif /******************************************************************************/ + #ifndef WITH_LEANER -#ifndef PALM_1 SOAP_FMAC1 int SOAP_FMAC2 -soap_putmime(struct soap *soap) -{ struct soap_multipart *content; - if (!(soap->mode & SOAP_ENC_MIME) || !soap->mime.boundary) - return SOAP_OK; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending MIME attachments\n")); - for (content = soap->mime.first; content; content = content->next) - { void *handle; - if (soap->fmimereadopen && ((handle = soap->fmimereadopen(soap, (void*)content->ptr, content->id, content->type, content->description)) || soap->error)) - { size_t size = content->size; - if (!handle) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimereadopen failed\n")); - return soap->error; - } - if (soap_putmimehdr(soap, content)) +soap_getdime(struct soap *soap) +{ + if (soap->dime.buflen || soap->dime.chunksize) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Skip remainder of SOAP in DIME (%u bytes or %u bytes in chunk left)\n", (unsigned int)soap->dime.buflen, (unsigned int)soap->dime.chunksize)); + do + if (soap_get1(soap) == (int)EOF) + return soap->error = SOAP_CHK_EOF; + while (soap->dime.buflen || soap->dime.chunksize); + if (soap_move(soap, (size_t)(-(long)soap->dime.size&3))) + return soap->error = SOAP_CHK_EOF; + if (!(soap->mode & SOAP_ENC_DIME)) + return SOAP_OK; + } + else + { + if (soap_move(soap, (size_t)(((soap->dime.size+3)&(~3)) - soap_tell(soap)))) + return soap->error = SOAP_CHK_EOF; + } + for (;;) + { + struct soap_multipart *content; + if (soap_getdimehdr(soap)) + break; + if (soap->fdimewriteopen && ((soap->dime.ptr = (char*)soap->fdimewriteopen(soap, soap->dime.id, soap->dime.type, soap->dime.options)) != NULL || soap->error)) + { + const char *id, *type, *options; + size_t size, n; + if (!soap->dime.ptr) return soap->error; - if (!size) - { if ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming MIME\n")); - do - { size = soap->fmimeread(soap, handle, soap->tmpbuf, sizeof(soap->tmpbuf)); - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread returned %lu bytes\n", (unsigned long)size)); - if (soap_send_raw(soap, soap->tmpbuf, size)) - break; - } while (size); + id = soap->dime.id; + type = soap->dime.type; + options = soap->dime.options; + for (;;) + { + size = soap->dime.size; + for (;;) + { + n = soap->buflen - soap->bufidx; + if (size < n) + n = size; + soap->error = soap->fdimewrite(soap, (void*)soap->dime.ptr, soap->buf + soap->bufidx, n); + if (soap->error) + break; + size -= n; + if (!size) + { + soap->bufidx += n; + break; + } + if (soap_recv(soap)) + { + soap->error = SOAP_EOF; + goto end; + } } - else - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error: cannot chunk streaming MIME (no HTTP chunking)\n")); + if (soap_move(soap, (size_t)(-(long)soap->dime.size&3))) + { + soap->error = SOAP_EOF; + break; } + if (!(soap->dime.flags & SOAP_DIME_CF)) + break; + if (soap_getdimehdr(soap)) + break; } - else - { do - { size_t bufsize; - if (size < sizeof(soap->tmpbuf)) - bufsize = size; - else - bufsize = sizeof(soap->tmpbuf); - if (!(bufsize = soap->fmimeread(soap, handle, soap->tmpbuf, bufsize))) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size)); - soap->error = SOAP_EOF; - break; - } - if (soap_send_raw(soap, soap->tmpbuf, bufsize)) - break; - size -= bufsize; - } while (size); +end: + if (soap->fdimewriteclose) + soap->fdimewriteclose(soap, (void*)soap->dime.ptr); + soap->dime.size = 0; + soap->dime.id = id; + soap->dime.type = type; + soap->dime.options = options; + } + else if ((soap->dime.flags & SOAP_DIME_CF)) + { + const char *id, *type, *options; + id = soap->dime.id; + type = soap->dime.type; + options = soap->dime.options; + if (soap_alloc_block(soap) == NULL) + return soap->error = SOAP_EOM; + for (;;) + { + soap_wchar c; + size_t i; + 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; + for (i = soap->dime.size; i > 0; i--) + { + c = soap_get1(soap); + if ((int)c == EOF) + return soap->error = SOAP_EOF; + *s++ = (char)c; + } + 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; } - if (soap->fmimereadclose) - soap->fmimereadclose(soap, handle); + soap->dime.size = soap->blist->size; + if (soap->dime.size + 1 > soap->dime.size) + soap->blist->size++; /* allocate one more byte in blist for the terminating '\0' */ + soap->dime.ptr = (char*)soap_save_block(soap, NULL, NULL, 0); + if (!soap->dime.ptr) + return soap->error; + if (soap->dime.size + 1 > soap->dime.size) + soap->dime.ptr[soap->dime.size] = '\0'; /* make 0-terminated, just in case even though this is binary data */ + soap->dime.id = id; + soap->dime.type = type; + soap->dime.options = options; } else - { if (soap_putmimehdr(soap, content) - || soap_send_raw(soap, content->ptr, content->size)) - return soap->error; + { + soap->dime.ptr = soap_getdimefield(soap, soap->dime.size); } + content = soap_alloc_multipart(soap, &soap->dime.first, &soap->dime.last, soap->dime.ptr, soap->dime.size); + if (!content) + return soap->error = SOAP_EOM; + content->id = soap->dime.id; + content->type = soap->dime.type; + content->options = soap->dime.options; + if (soap->error) + return soap->error; + soap_resolve_attachment(soap, content); } - return soap_send3(soap, "\r\n--", soap->mime.boundary, "--"); + if (soap->error != SOAP_DIME_END) + return soap->error; + return soap->error = SOAP_OK; } #endif -#endif /******************************************************************************/ -#ifndef WITH_LEANER -#ifndef PALM_1 -SOAP_FMAC1 -void -SOAP_FMAC2 -soap_set_dime(struct soap *soap) -{ soap->omode |= SOAP_ENC_DIME; - soap->dime.first = NULL; - soap->dime.last = NULL; -} -#endif -#endif -/******************************************************************************/ #ifndef WITH_LEANER -#ifndef PALM_1 SOAP_FMAC1 -void +int SOAP_FMAC2 -soap_set_mime(struct soap *soap, const char *boundary, const char *start) -{ soap->omode |= SOAP_ENC_MIME; - soap->mime.first = NULL; - soap->mime.last = NULL; - soap->mime.boundary = soap_strdup(soap, boundary); - soap->mime.start = soap_strdup(soap, start); +soap_getmimehdr(struct soap *soap) +{ + struct soap_multipart *content; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get MIME header\n")); + do + { + if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) + return soap->error; + } while (!*soap->msgbuf); + if (soap->msgbuf[0] == '-' && soap->msgbuf[1] == '-') + { + char *s = soap->msgbuf + strlen(soap->msgbuf) - 1; + /* remove white space */ + while (soap_coblank((soap_wchar)*s)) + s--; + s[1] = '\0'; + if (soap->mime.boundary) + { + if (strcmp(soap->msgbuf + 2, soap->mime.boundary)) + return soap->error = SOAP_MIME_ERROR; + } + else + { + soap->mime.boundary = soap_strdup(soap, soap->msgbuf + 2); + if (!soap->mime.boundary) + return soap->error = SOAP_EOM; + } + if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) + return soap->error; + } + if (soap_set_mime_attachment(soap, NULL, 0, SOAP_MIME_NONE, NULL, NULL, NULL, NULL)) + return soap->error = SOAP_EOM; + content = soap->mime.last; + for (;;) + { + char *key = soap->msgbuf; + char *val; + if (!*key) + break; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "MIME header: %s\n", key)); + val = strchr(soap->msgbuf, ':'); + if (val) + { + *val = '\0'; + do + { + val++; + } while (*val && *val <= 32); + if (!soap_tag_cmp(key, "Content-ID")) + content->id = soap_strdup(soap, val); + else if (!soap_tag_cmp(key, "Content-Location")) + content->location = soap_strdup(soap, val); + else if (!content->id && !soap_tag_cmp(key, "Content-Disposition")) + content->id = soap_strdup(soap, soap_http_header_attribute(soap, val, "name")); + else if (!soap_tag_cmp(key, "Content-Type")) + content->type = soap_strdup(soap, val); + else if (!soap_tag_cmp(key, "Content-Description")) + content->description = soap_strdup(soap, val); + else if (!soap_tag_cmp(key, "Content-Transfer-Encoding")) + content->encoding = (enum soap_mime_encoding)soap_code_int(mime_codes, val, (LONG64)SOAP_MIME_NONE); + } + if (soap_getline(soap, key, sizeof(soap->msgbuf))) + return soap->error; + } + return SOAP_OK; } #endif -#endif /******************************************************************************/ + #ifndef WITH_LEANER -#ifndef PALM_1 SOAP_FMAC1 -void +int SOAP_FMAC2 -soap_clr_dime(struct soap *soap) -{ soap->omode &= ~SOAP_ENC_DIME; - soap->dime.first = NULL; - soap->dime.last = NULL; +soap_getmime(struct soap *soap) +{ + while (soap_recv_mime_attachment(soap, NULL)) + continue; + return soap->error; } #endif -#endif /******************************************************************************/ + #ifndef WITH_LEANER -#ifndef PALM_1 SOAP_FMAC1 void SOAP_FMAC2 -soap_clr_mime(struct soap *soap) -{ soap->omode &= ~SOAP_ENC_MIME; - soap->mime.first = NULL; - soap->mime.last = NULL; - soap->mime.boundary = NULL; - soap->mime.start = NULL; +soap_post_check_mime_attachments(struct soap *soap) +{ + soap->imode |= SOAP_MIME_POSTCHECK; } #endif -#endif /******************************************************************************/ -#ifndef WITH_LEANER -#ifndef PALM_1 -static struct soap_multipart* -soap_new_multipart(struct soap *soap, struct soap_multipart **first, struct soap_multipart **last, char *ptr, size_t size) -{ struct soap_multipart *content; - content = (struct soap_multipart*)soap_malloc(soap, sizeof(struct soap_multipart)); - if (content) - { content->next = NULL; - content->ptr = ptr; - content->size = size; - content->id = NULL; - content->type = NULL; - content->options = NULL; - content->encoding = SOAP_MIME_NONE; - content->location = NULL; - content->description = NULL; - if (!*first) - *first = content; - if (*last) - (*last)->next = content; - *last = content; - } - return content; -} -#endif -#endif -/******************************************************************************/ #ifndef WITH_LEANER -#ifndef PALM_1 SOAP_FMAC1 int SOAP_FMAC2 -soap_set_dime_attachment(struct soap *soap, char *ptr, size_t size, const char *type, const char *id, unsigned short optype, const char *option) -{ struct soap_multipart *content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, ptr, size); - if (!content) - return SOAP_EOM; - content->id = soap_strdup(soap, id); - content->type = soap_strdup(soap, type); - content->options = soap_dime_option(soap, optype, option); - return SOAP_OK; +soap_check_mime_attachments(struct soap *soap) +{ + if ((soap->mode & SOAP_MIME_POSTCHECK)) + return soap_recv_mime_attachment(soap, NULL) != NULL; + return 0; } #endif -#endif /******************************************************************************/ -#ifndef WITH_LEANER -#ifndef PALM_1 -SOAP_FMAC1 -int -SOAP_FMAC2 -soap_set_mime_attachment(struct soap *soap, char *ptr, size_t size, enum soap_mime_encoding encoding, const char *type, const char *id, const char *location, const char *description) -{ struct soap_multipart *content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, ptr, size); - if (!content) - return SOAP_EOM; - content->id = soap_strdup(soap, id); - content->type = soap_strdup(soap, type); - content->encoding = encoding; - content->location = soap_strdup(soap, location); - content->description = soap_strdup(soap, description); - return SOAP_OK; -} -#endif -#endif -/******************************************************************************/ #ifndef WITH_LEANER -#ifndef PALM_1 SOAP_FMAC1 -struct soap_multipart* +struct soap_multipart * SOAP_FMAC2 -soap_next_multipart(struct soap_multipart *content) -{ if (content) - return content->next; - return NULL; -} -#endif -#endif - -/******************************************************************************/ -#ifndef WITH_LEANER -#ifndef PALM_1 -static void -soap_select_mime_boundary(struct soap *soap) -{ while (!soap->mime.boundary || soap_valid_mime_boundary(soap)) - { char *s = soap->mime.boundary; - size_t n = 0; - if (s) - n = strlen(s); - if (n < 16) - { n = 64; - s = soap->mime.boundary = (char*)soap_malloc(soap, n + 1); +soap_recv_mime_attachment(struct soap *soap, void *handle) +{ + soap_wchar c = 0; + size_t i, m = 0; + char *s, *t = NULL; + struct soap_multipart *content; + short flag = 0; + if (!(soap->mode & SOAP_ENC_MIME)) + goto post_check_exit; + content = soap->mime.last; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get MIME (%p)\n", (void*)content)); + if (!content) + { + if (soap_getmimehdr(soap)) + goto post_check_exit; + content = soap->mime.last; + } + else if (content != soap->mime.first) + { + if (soap->fmimewriteopen && ((content->ptr = (char*)soap->fmimewriteopen(soap, (void*)handle, content->id, content->type, content->description, content->encoding)) != NULL || soap->error)) + { + if (!content->ptr) + goto post_check_exit; + } + } + 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_alloc_block(soap) == NULL) + { + soap->error = SOAP_EOM; + goto post_check_exit; + } + for (;;) + { + if (content->ptr) + { + s = soap->tmpbuf; + } + else + { + s = (char*)soap_push_block(soap, NULL, sizeof(soap->tmpbuf)); if (!s) - return; + { + soap->error = SOAP_EOM; + goto post_check_exit; + } } - strcpy(s, "=="); - s += 2; - n -= 4; - while (n) - { *s++ = soap_base64o[soap_random & 0x3F]; - n--; + for (i = 0; i < sizeof(soap->tmpbuf); i++) + { + if (m > 0) + { + *s++ = *t++; + m--; + } + else + { + if (!flag) + { + c = soap_getchar(soap); + if ((int)c == EOF) + { + if (content->ptr && soap->fmimewriteclose) + soap->fmimewriteclose(soap, (void*)content->ptr); + soap->error = SOAP_CHK_EOF; + goto post_check_exit; + } + } + if (flag || c == '\r') + { + memset((void*)soap->msgbuf, 0, sizeof(soap->msgbuf)); + soap_strcpy(soap->msgbuf, sizeof(soap->msgbuf), "\n--"); + if (soap->mime.boundary) + { + if (soap_strncat(soap->msgbuf, sizeof(soap->msgbuf), soap->mime.boundary, sizeof(soap->msgbuf) - 4)) + { + soap->error = SOAP_MIME_ERROR; + goto post_check_exit; + } + } + t = soap->msgbuf; + do + { + c = soap_getchar(soap); + } while (c == *t++); + if ((int)c == EOF) + { + if (content->ptr && soap->fmimewriteclose) + soap->fmimewriteclose(soap, (void*)content->ptr); + soap->error = SOAP_CHK_EOF; + goto post_check_exit; + } + if (!*--t) + goto end; + *t = (char)c; + flag = (c == '\r'); + m = t - soap->msgbuf + 1 - flag; + t = soap->msgbuf; + c = '\r'; + } + *s++ = (char)c; + } + } + if (content->ptr && soap->fmimewrite) + { + soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i); + if (soap->error) + break; + } + } +end: + if (content->ptr) + { + if (!soap->error && soap->fmimewrite) + soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i); + if (soap->fmimewriteclose) + soap->fmimewriteclose(soap, (void*)content->ptr); + if (soap->error) + goto post_check_exit; + } + else + { + *s = '\0'; /* make 0-terminated, just in case even though this is binary data */ + content->size = soap_size_block(soap, NULL, i + 1) - 1; /* last block with '\0' */ + content->ptr = (char*)soap_save_block(soap, NULL, NULL, 0); + } + soap_resolve_attachment(soap, content); + if (c == '-' && soap_getchar(soap) == '-') + { + soap->mode &= ~SOAP_ENC_MIME; + if ((soap->mode & SOAP_MIME_POSTCHECK)) + { + if (soap_end_recv(soap)) + goto post_check_exit; + if (soap->keep_alive == -2) /* special case to keep alive */ + soap->keep_alive = 0; + (void)soap_closesock(soap); + } + } + else + { + while (c != '\r' && (int)c != EOF && soap_coblank(c)) + c = soap_getchar(soap); + if (c != '\r' || soap_getchar(soap) != '\n') + { + soap->error = SOAP_MIME_ERROR; + goto post_check_exit; } - strcpy(s, "=="); + if (soap_getmimehdr(soap)) + goto post_check_exit; } - if (!soap->mime.start) - soap->mime.start = ""; -} -#endif -#endif - -/******************************************************************************/ -#ifndef WITH_LEANER -#ifndef PALM_1 -static int -soap_valid_mime_boundary(struct soap *soap) -{ struct soap_multipart *content; - size_t k; - if (soap->fmimeread) - return SOAP_OK; - k = strlen(soap->mime.boundary); - for (content = soap->mime.first; content; content = content->next) - { if (content->ptr && content->size >= k) - { const char *p = (const char*)content->ptr; - size_t i; - for (i = 0; i < content->size - k; i++, p++) - { if (!strncmp(p, soap->mime.boundary, k)) - return SOAP_ERR; - } - } + return content; +post_check_exit: + if ((soap->mode & SOAP_MIME_POSTCHECK)) + { + if (soap->keep_alive == -2) /* special case to keep alive */ + soap->keep_alive = 0; + (void)soap_closesock(soap); } - return SOAP_OK; + return NULL; } #endif -#endif - -/******************************************************************************\ - * - * HTTP cookie handling - * -\******************************************************************************/ -#ifdef WITH_COOKIES /******************************************************************************/ + +#ifndef WITH_LEANER SOAP_FMAC1 -size_t +int SOAP_FMAC2 -soap_encode_cookie(const char *s, char *t, size_t len) -{ int c; - size_t n = len; - while ((c = *s++) && --n > 0) - { if (c > ' ' && c < 128 && !strchr("()<>@,;:\\\"/[]?={}#!$&'*+", c)) - *t++ = c; - else if (n > 2) - { *t++ = '%'; - *t++ = (c >> 4) + (c > 159 ? '7' : '0'); - c &= 0xF; - *t++ = c + (c > 9 ? '7' : '0'); - n -= 2; - } - else - break; +soap_match_cid(struct soap *soap, const char *s, const char *t) +{ + size_t n; + if (!s) + return 1; + if (!strcmp(s, t)) + return 0; + if (!strncmp(s, "cid:", 4)) + s += 4; + n = strlen(t); + if (*t == '<') + { + t++; + n -= 2; } - *t = '\0'; - return len - n; + if (!strncmp(s, t, n) && !s[n]) + return 0; + (void)soap_decode(soap->tmpbuf, sizeof(soap->tmpbuf), s, SOAP_STR_EOS); + if (!strncmp(soap->tmpbuf, t, n) && !soap->tmpbuf[n]) + return 0; + return 1; } +#endif /******************************************************************************/ + +/* return UUID "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx" in a temporary buffer */ SOAP_FMAC1 -struct soap_cookie* +const char* SOAP_FMAC2 -soap_cookie(struct soap *soap, const char *name, const char *domain, const char *path) -{ struct soap_cookie *p; - if (!domain) - domain = soap->cookie_domain; - if (!path) - path = soap->cookie_path; - if (!path) - 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)")); - 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)); - if (!strcmp(p->name, name) - && p->domain - && p->path - && !strcmp(p->domain, domain) - && (!*p->path || !strncmp(p->path, path, strlen(p->path)))) - break; - } - return p; +soap_rand_uuid(struct soap *soap, const char *prefix) +{ + int r1, r2, r3, r4; +#ifdef WITH_OPENSSL + r1 = soap_random; + r2 = soap_random; +#else + size_t i; + static int k = 0xFACEB00C; + int lo = k % 127773; + int hi = k / 127773; +# if defined(HAVE_GETTIMEOFDAY) + struct timeval tv; + gettimeofday(&tv, NULL); + r1 = 10000000 * tv.tv_sec + tv.tv_usec; +# elif defined(UNDER_CE) + r1 = (int)Random(); +# elif !defined(WITH_LEAN) + r1 = (int)time(NULL); +# else + r1 = k; +# endif + k = 16807 * lo - 2836 * hi; + if (k <= 0) + k += 0x7FFFFFFF; + r2 = k; + /* k &= 0x8FFFFFFF; */ + for (i = 0; i < (sizeof(soap->buf) < 16UL ? sizeof(soap->buf) : 16UL); i++) + r2 += soap->buf[i]; +#endif + r3 = soap_random; + r4 = soap_random; + (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), prefix ? strlen(prefix) + 37 : 37), "%s%8.8x-%4.4hx-4%3.3hx-%4.4hx-%4.4hx%8.8x", prefix ? prefix : SOAP_STR_EOS, r1, (short)(r2 >> 16), (short)(((short)r2 >> 4) & 0x0FFF), (short)(((short)(r3 >> 16) & 0x3FFF) | 0x8000), (short)r3, r4); + return soap->tmpbuf; } /******************************************************************************/ -SOAP_FMAC1 -struct soap_cookie* -SOAP_FMAC2 -soap_set_cookie(struct soap *soap, const char *name, const char *value, const char *domain, const char *path) -{ struct soap_cookie **p, *q; - int n; - if (!domain) - domain = soap->cookie_domain; - if (!path) - path = soap->cookie_path; - if (!path) - path = SOAP_STR_EOS; - 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)")); - if (!q) - { if ((q = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie)))) - { if ((q->name = (char*)SOAP_MALLOC(soap, strlen(name)+1))) - strcpy(q->name, name); - q->value = NULL; - q->domain = NULL; - q->path = NULL; - q->expire = 0; - q->maxage = -1; - q->version = 1; - q->secure = 0; - q->modified = 0; - for (p = &soap->cookies, n = soap->cookie_max; *p && n; p = &(*p)->next, n--) - if (!strcmp((*p)->name, name) && (*p)->path && path && strcmp((*p)->path, path) < 0) - break; - if (n) - { q->next = *p; - *p = q; + +#ifndef WITH_LEANER +static void +soap_resolve_attachment(struct soap *soap, struct soap_multipart *content) +{ + if (content->id) + { + struct soap_xlist **xp = &soap->xlist; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving attachment data for id='%s'\n", content->id)); + while (*xp) + { + struct soap_xlist *xq = *xp; + if (!soap_match_cid(soap, 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; + *xq->type = (char*)content->type; + if (content->options) + *xq->options = (char*)content->options; + else + *xq->options = (char*)content->description; + SOAP_FREE(soap, xq); } else - { SOAP_FREE(soap, q->name); - SOAP_FREE(soap, q); - q = NULL; - } - } - } - else - q->modified = 1; - if (q) - { if (q->value) - { if (!value || strcmp(value, q->value)) - { SOAP_FREE(soap, q->value); - q->value = NULL; - } - } - if (value && *value && !q->value && (q->value = (char*)SOAP_MALLOC(soap, strlen(value)+1))) - strcpy(q->value, value); - if (q->domain) - { if (!domain || strcmp(domain, q->domain)) - { SOAP_FREE(soap, q->domain); - q->domain = NULL; - } - } - if (domain && !q->domain && (q->domain = (char*)SOAP_MALLOC(soap, strlen(domain)+1))) - strcpy(q->domain, domain); - if (q->path) - { if (!path || strncmp(path, q->path, strlen(q->path))) - { SOAP_FREE(soap, q->path); - q->path = NULL; + { + xp = &(*xp)->next; } } - if (path && !q->path && (q->path = (char*)SOAP_MALLOC(soap, strlen(path)+1))) - strcpy(q->path, path); - q->session = 1; - q->env = 0; } - return q; } +#endif /******************************************************************************/ + +#ifndef WITH_LEANER SOAP_FMAC1 -void +int SOAP_FMAC2 -soap_clr_cookie(struct soap *soap, const char *name, const char *domain, const char *path) -{ struct soap_cookie **p, *q; - 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)")); - 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)")); - return; - } - if (*path == '/') - path++; - for (p = &soap->cookies, q = *p; q; q = *p) - { if (!strcmp(q->name, name) && !strcmp(q->domain, domain) && !strncmp(q->path, path, strlen(q->path))) - { if (q->value) - SOAP_FREE(soap, q->value); - if (q->domain) - SOAP_FREE(soap, q->domain); - if (q->path) - SOAP_FREE(soap, q->path); - *p = q->next; - SOAP_FREE(soap, q); - } - else - p = &q->next; - } +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)); + 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")) + return soap->error; + s = soap_code_str(mime_codes, content->encoding); + if (s && soap_send3(soap, "Content-Transfer-Encoding: ", s, "\r\n")) + return soap->error; + if (content->id && soap_send3(soap, "Content-ID: ", content->id, "\r\n")) + return soap->error; + if (content->location && soap_send3(soap, "Content-Location: ", content->location, "\r\n")) + return soap->error; + if (content->description && soap_send3(soap, "Content-Description: ", content->description, "\r\n")) + return soap->error; + return soap_send_raw(soap, "\r\n", 2); } +#endif /******************************************************************************/ + +#ifndef WITH_LEANER SOAP_FMAC1 -char * +int SOAP_FMAC2 -soap_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path) -{ struct soap_cookie *p; - if ((p = soap_cookie(soap, name, domain, path))) - return p->value; - return NULL; +soap_putmime(struct soap *soap) +{ + struct soap_multipart *content; + if (!(soap->mode & SOAP_ENC_MIME) || !soap->mime.boundary) + return SOAP_OK; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending MIME attachments\n")); + for (content = soap->mime.first; content; content = content->next) + { + int err = SOAP_OK; + void *handle; + if (soap->fmimereadopen && ((handle = soap->fmimereadopen(soap, (void*)content->ptr, content->id, content->type, content->description)) != NULL || soap->error)) + { + size_t size = content->size; + if (!handle) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimereadopen failed\n")); + if (!soap->error) + soap->error = SOAP_MIME_ERROR; + return soap->error; + } + if (soap_putmimehdr(soap, content)) + return soap->error; + if (!size) /* streaming MIME is indicated by size zero content size when streaming MIME callbacks are set */ + { + if ((soap->mode & SOAP_ENC_PLAIN) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming MIME\n")); + do + { + size = soap->fmimeread(soap, handle, soap->tmpbuf, sizeof(soap->tmpbuf)); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread returned %lu bytes\n", (unsigned long)size)); + err = soap_send_raw(soap, soap->tmpbuf, size); + } while (!err && size); + } + else + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error: cannot chunk streaming MIME (no HTTP chunking)\n")); + } + } + else + { + do + { + size_t bufsize; + if (size < sizeof(soap->tmpbuf)) + bufsize = size; + else + bufsize = sizeof(soap->tmpbuf); + bufsize = soap->fmimeread(soap, handle, soap->tmpbuf, bufsize); + if (!bufsize) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size)); + err = SOAP_MIME_ERROR; /* used to be EOF, SOAP_MIME_ERROR is more appropriaate */ + break; + } + err = soap_send_raw(soap, soap->tmpbuf, bufsize); + size -= bufsize; + } while (!err && size); + } + if (soap->fmimereadclose) + soap->fmimereadclose(soap, handle); + if (err) + return soap->error = err; + } + else + { + if (soap_putmimehdr(soap, content) + || soap_send_raw(soap, content->ptr, content->size)) + return soap->error; + } + } + return soap_send3(soap, "\r\n--", soap->mime.boundary, "--"); } +#endif /******************************************************************************/ -SOAP_FMAC1 -char * -SOAP_FMAC2 -soap_env_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path) -{ struct soap_cookie *p; - if ((p = soap_cookie(soap, name, domain, path)) && p->env) - return p->value; - return NULL; -} -/******************************************************************************/ +#ifndef WITH_LEANER SOAP_FMAC1 -time_t +void SOAP_FMAC2 -soap_cookie_expire(struct soap *soap, const char *name, const char *domain, const char *path) -{ struct soap_cookie *p; - if ((p = soap_cookie(soap, name, domain, path))) - return p->expire; - return -1; +soap_set_dime(struct soap *soap) +{ + soap->omode |= SOAP_ENC_DIME; + soap->dime.first = NULL; + soap->dime.last = NULL; } +#endif /******************************************************************************/ -SOAP_FMAC1 -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)")); - if ((p = soap_cookie(soap, name, domain, path))) - { p->maxage = expire; - p->modified = 1; - return SOAP_OK; - } - return SOAP_ERR; -} -/******************************************************************************/ +#ifndef WITH_LEANER SOAP_FMAC1 -int +void SOAP_FMAC2 -soap_set_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path) -{ struct soap_cookie *p; - if ((p = soap_cookie(soap, name, domain, path))) - { p->session = 1; - p->modified = 1; - return SOAP_OK; - } - return SOAP_ERR; +soap_set_mime(struct soap *soap, const char *boundary, const char *start) +{ + soap->omode |= SOAP_ENC_MIME; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = soap_strdup(soap, boundary); + soap->mime.start = soap_strdup(soap, start); } +#endif /******************************************************************************/ -SOAP_FMAC1 -int -SOAP_FMAC2 -soap_clr_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path) -{ struct soap_cookie *p; - if ((p = soap_cookie(soap, name, domain, path))) - { p->session = 0; - p->modified = 1; - return SOAP_OK; - } - return SOAP_ERR; -} -/******************************************************************************/ +#ifndef WITH_LEANER SOAP_FMAC1 -int +void SOAP_FMAC2 -soap_putsetcookies(struct soap *soap) -{ struct soap_cookie *p; - char *s, tmp[4096]; - const char *t; - for (p = soap->cookies; p; p = p->next) - { - if (p->modified -#ifdef WITH_OPENSSL - || (!p->env && !soap->ssl == !p->secure) -#endif - ) - { s = tmp; - if (p->name) - s += soap_encode_cookie(p->name, s, tmp-s+4064); - if (p->value && *p->value) - { *s++ = '='; - s += soap_encode_cookie(p->value, s, tmp-s+4064); - } - if (p->domain && (int)strlen(p->domain) < tmp-s+4064) - { strcpy(s, ";Domain="); - strcat(s, p->domain); - } - else if (soap->cookie_domain && (int)strlen(soap->cookie_domain) < tmp-s+4064) - { strcpy(s, ";Domain="); - strcat(s, soap->cookie_domain); - } - strcat(s, ";Path=/"); - s += strlen(s); - if (p->path) - t = p->path; - else - t = soap->cookie_path; - if (t) - { if (*t == '/') - t++; - if ((int)strlen(t) < tmp-s+4064) - { if (strchr(t, '%')) /* already URL encoded? */ - { strcpy(s, t); - s += strlen(s); - } - else - s += soap_encode_cookie(t, s, tmp-s+4064); - } - } - if (p->version > 0 && s-tmp < 4060) - { sprintf(s, ";Version=%u", p->version); - s += strlen(s); - } - if (p->maxage >= 0 && s-tmp < 4060) - { sprintf(s, ";Max-Age=%ld", p->maxage); - s += strlen(s); - } - if (s-tmp < 4073 - && (p->secure -#ifdef WITH_OPENSSL - || soap->ssl -#endif - )) - strcpy(s, ";Secure"); - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set-Cookie: %s\n", tmp)); - if ((soap->error = soap->fposthdr(soap, "Set-Cookie", tmp))) - return soap->error; - } - } - return SOAP_OK; +soap_clr_dime(struct soap *soap) +{ + soap->omode &= ~SOAP_ENC_DIME; + soap->dime.first = NULL; + soap->dime.last = NULL; } +#endif /******************************************************************************/ + +#ifndef WITH_LEANER SOAP_FMAC1 -int +void SOAP_FMAC2 -soap_putcookies(struct soap *soap, const char *domain, const char *path, int secure) -{ struct soap_cookie **p, *q; - unsigned int version = 0; - time_t now = time(NULL); - char *s, tmp[4096]; - p = &soap->cookies; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending cookies for domain=%s path=%s\n", domain, path)); - if (*path == '/') - path++; - while ((q = *p)) - { if (q->expire && now > q->expire) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie %s expired\n", q->name)); - SOAP_FREE(soap, q->name); - if (q->value) - SOAP_FREE(soap, q->value); - if (q->domain) - SOAP_FREE(soap, q->domain); - if (q->path) - SOAP_FREE(soap, q->path); - *p = q->next; - SOAP_FREE(soap, q); - } - else - { int flag; - char *t = q->domain; - size_t n = 0; - if (!t) - flag = 1; - else - { const char *r = strchr(t, ':'); - if (r) - n = r - t; - else - n = strlen(t); - flag = !strncmp(t, domain, n); - } - /* domain-level cookies, cannot compile when WITH_NOIO set */ -#ifndef WITH_NOIO - if (!flag) - { struct hostent *hostent = gethostbyname((char*)domain); - if (hostent) - { const char *r = strchr(hostent->h_name, '.'); - if (!r) - r = hostent->h_name; - flag = !strncmp(t, r, n); - } - } -#endif - if (flag - && (!q->path || !strncmp(q->path, path, strlen(q->path))) - && (!q->secure || secure)) - { s = tmp; - if (q->version != version) - { sprintf(s, "$Version=%u;", q->version); - version = q->version; - } - if (q->name) - s += soap_encode_cookie(q->name, s, tmp-s+4080); - if (q->value && *q->value) - { *s++ = '='; - s += soap_encode_cookie(q->value, s, tmp-s+4080); - } - if (q->path && *q->path && (int)strlen(q->path) < tmp-s+4080) - { sprintf(s, ";$Path=\"/%s\"", (*q->path == '/' ? q->path + 1 : q->path)); - s += strlen(s); - } - if (q->domain && (int)strlen(q->domain) < tmp-s+4080) - sprintf(s, ";$Domain=\"%s\"", q->domain); - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie: %s\n", tmp)); - if ((soap->error = soap->fposthdr(soap, "Cookie", tmp))) - return soap->error; - } - p = &q->next; - } - } - return SOAP_OK; +soap_clr_mime(struct soap *soap) +{ + soap->omode &= ~SOAP_ENC_MIME; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = NULL; + soap->mime.start = NULL; } +#endif /******************************************************************************/ -SOAP_FMAC1 -void -SOAP_FMAC2 -soap_getcookies(struct soap *soap, const char *val) -{ struct soap_cookie *p = NULL, *q; - const char *s; - char *t, tmp[4096]; /* cookie size is up to 4096 bytes [RFC2109] */ - char *domain = NULL; - char *path = NULL; - unsigned int version = 0; - time_t now = time(NULL); - if (!val) - return; - s = val; - while (*s) - { s = soap_decode_key(tmp, sizeof(tmp), s); - if (!soap_tag_cmp(tmp, "$Version")) - { if ((s = soap_decode_val(tmp, sizeof(tmp), s))) - { if (p) - p->version = (int)atol(tmp); - else - version = (int)atol(tmp); - } - } - else if (!soap_tag_cmp(tmp, "$Path")) - { s = soap_decode_val(tmp, sizeof(tmp), s); - if (*tmp) - { if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) - strcpy(t, tmp); - } - else - t = NULL; - if (p) - { if (p->path) - SOAP_FREE(soap, p->path); - p->path = t; - } - else - { if (path) - SOAP_FREE(soap, path); - path = t; - } - } - else if (!soap_tag_cmp(tmp, "$Domain")) - { s = soap_decode_val(tmp, sizeof(tmp), s); - if (*tmp) - { if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) - strcpy(t, tmp); - } - else - t = NULL; - if (p) - { if (p->domain) - SOAP_FREE(soap, p->domain); - p->domain = t; - } - else - { if (domain) - SOAP_FREE(soap, domain); - domain = t; - } - } - else if (p && !soap_tag_cmp(tmp, "Path")) - { if (p->path) - SOAP_FREE(soap, p->path); - s = soap_decode_val(tmp, sizeof(tmp), s); - if (*tmp) - { if ((p->path = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) - strcpy(p->path, tmp); - } - else - p->path = NULL; - } - else if (p && !soap_tag_cmp(tmp, "Domain")) - { if (p->domain) - SOAP_FREE(soap, p->domain); - s = soap_decode_val(tmp, sizeof(tmp), s); - if (*tmp) - { if ((p->domain = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) - strcpy(p->domain, tmp); - } - else - p->domain = NULL; - } - else if (p && !soap_tag_cmp(tmp, "Version")) - { s = soap_decode_val(tmp, sizeof(tmp), s); - p->version = (unsigned int)atol(tmp); - } - else if (p && !soap_tag_cmp(tmp, "Max-Age")) - { s = soap_decode_val(tmp, sizeof(tmp), s); - p->expire = now + atol(tmp); - } - else if (p && !soap_tag_cmp(tmp, "Expires")) - { struct tm T; - char a[3]; - static const char mns[] = "anebarprayunulugepctovec"; - s = soap_decode_val(tmp, sizeof(tmp), s); - if (strlen(tmp) > 20) - { memset((void*)&T, 0, sizeof(T)); - a[0] = tmp[4]; - a[1] = tmp[5]; - a[2] = '\0'; - T.tm_mday = (int)atol(a); - a[0] = tmp[8]; - a[1] = tmp[9]; - T.tm_mon = (int)(strstr(mns, a) - mns) / 2; - a[0] = tmp[11]; - a[1] = tmp[12]; - T.tm_year = 100 + (int)atol(a); - a[0] = tmp[13]; - a[1] = tmp[14]; - T.tm_hour = (int)atol(a); - a[0] = tmp[16]; - a[1] = tmp[17]; - T.tm_min = (int)atol(a); - a[0] = tmp[19]; - a[1] = tmp[20]; - T.tm_sec = (int)atol(a); - p->expire = soap_timegm(&T); - } - } - else if (p && !soap_tag_cmp(tmp, "Secure")) - 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)); - if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path))) - { q->version = p->version; - q->expire = p->expire; - q->secure = p->secure; - q->env = 1; - } - if (p->name) - SOAP_FREE(soap, p->name); - if (p->value) - SOAP_FREE(soap, p->value); - if (p->domain) - SOAP_FREE(soap, p->domain); - if (p->path) - SOAP_FREE(soap, p->path); - SOAP_FREE(soap, p); - } - if ((p = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie)))) - { p->name = (char*)SOAP_MALLOC(soap, strlen(tmp)+1); - strcpy(p->name, tmp); - s = soap_decode_val(tmp, sizeof(tmp), s); - if (*tmp) - { p->value = (char*)SOAP_MALLOC(soap, strlen(tmp)+1); - strcpy(p->value, tmp); - } - else - p->value = NULL; - if (domain) - p->domain = domain; - else if (*soap->host) - { p->domain = (char*)SOAP_MALLOC(soap, strlen(soap->host)+1); - strcpy(p->domain, soap->host); - } - else - p->domain = NULL; - if (path) - p->path = path; - else if (soap->path && *soap->path) - { p->path = (char*)SOAP_MALLOC(soap, strlen(soap->path)+1); - strcpy(p->path, soap->path); - } - else - { p->path = (char*)SOAP_MALLOC(soap, 2); - strcpy(p->path, "/"); - } - p->expire = 0; - p->secure = 0; - p->version = version; - } + +#ifndef WITH_LEANER +static int +soap_begin_attachments(struct soap *soap) +{ + if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && soap->mime.start) + { + const char *s; + if (strlen(soap->mime.boundary) + strlen(soap->mime.start) + 140 > sizeof(soap->tmpbuf)) + return soap->error = SOAP_EOM; + if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) + { + s = "application/dime"; + } + else if (soap->version == 2) + { + if ((soap->mode & SOAP_ENC_MTOM)) + s = "application/xop+xml; charset=utf-8; type=\"application/soap+xml\""; + else + s = "application/soap+xml; charset=utf-8"; + } + else if ((soap->mode & SOAP_ENC_MTOM)) + { + s = "application/xop+xml; charset=utf-8; type=\"text/xml\""; + } + else + { + s = "text/xml; charset=utf-8"; } + (SOAP_SNPRINTF_SAFE(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); + if (soap_send(soap, soap->tmpbuf)) + return soap->error; } - 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)); - if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path))) - { q->version = p->version; - q->expire = p->expire; - q->secure = p->secure; - q->env = 1; + if ((soap->mode & SOAP_IO_LENGTH)) + soap->dime.size = (size_t)soap->count; /* DIME in MIME correction, soap->count is small */ + if (!(soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME)) + { + if (soap_putdimehdr(soap)) + return soap->error; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ + +#ifndef WITH_LEANER +static int +soap_end_attachments(struct soap *soap) +{ + if ((soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) + { + if (soap->count > 0xFFFFFFFF) + return soap->error = SOAP_DIME_ERROR; + soap->dime.size = (size_t)soap->count - soap->dime.size; /* DIME in MIME correction */ + (SOAP_SNPRINTF(soap->id, sizeof(soap->id), strlen(soap->dime_id_format) + 20), soap->dime_id_format, 0); + soap->dime.id = soap->id; + if (soap->local_namespaces && soap->local_namespaces[0].id) + { + if (soap->local_namespaces[0].out) + soap->dime.type = (char*)soap->local_namespaces[0].out; + else + soap->dime.type = (char*)soap->local_namespaces[0].ns; } - if (p->name) - SOAP_FREE(soap, p->name); - if (p->value) - SOAP_FREE(soap, p->value); - if (p->domain) - SOAP_FREE(soap, p->domain); - if (p->path) - SOAP_FREE(soap, p->path); - SOAP_FREE(soap, p); + soap->dime.options = NULL; + soap->dime.flags = SOAP_DIME_MB | SOAP_DIME_ABSURI; + if (!soap->dime.first) + soap->dime.flags |= SOAP_DIME_ME; + soap->count += 12 + ((strlen(soap->dime.id)+3)&(~3)) + (soap->dime.type ? ((strlen(soap->dime.type)+3)&(~3)) : 0); } - if (domain) - SOAP_FREE(soap, domain); - if (path) - SOAP_FREE(soap, path); + if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) + return soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3); + return SOAP_OK; +} +#endif + +/******************************************************************************/ + +#ifndef WITH_LEANER +static struct soap_multipart* +soap_alloc_multipart(struct soap *soap, struct soap_multipart **first, struct soap_multipart **last, const char *ptr, size_t size) +{ + struct soap_multipart *content; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New DIME/MIME attachment %p (%lu)\n", (void*)ptr, (unsigned long)size)); + content = (struct soap_multipart*)soap_malloc(soap, sizeof(struct soap_multipart)); + if (content) + { + content->next = NULL; + content->ptr = ptr; + content->size = size; + content->id = NULL; + content->type = NULL; + content->options = NULL; + content->encoding = SOAP_MIME_NONE; + content->location = NULL; + content->description = NULL; + if (!*first) + *first = content; + if (*last) + (*last)->next = content; + *last = content; + } + return content; } +#endif /******************************************************************************/ + +#ifndef WITH_LEANER SOAP_FMAC1 int SOAP_FMAC2 -soap_getenv_cookies(struct soap *soap) -{ struct soap_cookie *p; - const char *s; - char key[4096], val[4096]; /* cookie size is up to 4096 bytes [RFC2109] */ - if (!(s = getenv("HTTP_COOKIE"))) - return SOAP_ERR; - do - { s = soap_decode_key(key, sizeof(key), s); - s = soap_decode_val(val, sizeof(val), s); - p = soap_set_cookie(soap, key, val, NULL, NULL); - if (p) - p->env = 1; - } while (*s); +soap_set_dime_attachment(struct soap *soap, const char *ptr, size_t size, const char *type, const char *id, unsigned short optype, const char *option) +{ + struct soap_multipart *content = soap_alloc_multipart(soap, &soap->dime.first, &soap->dime.last, ptr, size); + if (!content) + return SOAP_EOM; + content->id = soap_strdup(soap, id); + content->type = soap_strdup(soap, type); + content->options = soap_dime_option(soap, optype, option); return SOAP_OK; } +#endif /******************************************************************************/ + +#ifndef WITH_LEANER SOAP_FMAC1 -struct soap_cookie* +int SOAP_FMAC2 -soap_copy_cookies(struct soap *copy, const struct soap *soap) -{ struct soap_cookie *p, **q, *r; - q = &r; - for (p = soap->cookies; p; p = p->next) - { if (!(*q = (struct soap_cookie*)SOAP_MALLOC(copy, sizeof(struct soap_cookie)))) - return r; - **q = *p; - if (p->name) - { if (((*q)->name = (char*)SOAP_MALLOC(copy, strlen(p->name)+1))) - strcpy((*q)->name, p->name); - } - if (p->value) - { if (((*q)->value = (char*)SOAP_MALLOC(copy, strlen(p->value)+1))) - strcpy((*q)->value, p->value); - } - if (p->domain) - { if (((*q)->domain = (char*)SOAP_MALLOC(copy, strlen(p->domain)+1))) - strcpy((*q)->domain, p->domain); - } - if (p->path) - { if (((*q)->path = (char*)SOAP_MALLOC(copy, strlen(p->path)+1))) - strcpy((*q)->path, p->path); - } - q = &(*q)->next; - } - *q = NULL; - return r; +soap_set_mime_attachment(struct soap *soap, const char *ptr, size_t size, enum soap_mime_encoding encoding, const char *type, const char *id, const char *location, const char *description) +{ + struct soap_multipart *content = soap_alloc_multipart(soap, &soap->mime.first, &soap->mime.last, ptr, size); + if (!content) + return SOAP_EOM; + content->id = soap_strdup(soap, id); + content->type = soap_strdup(soap, type); + content->encoding = encoding; + content->location = soap_strdup(soap, location); + content->description = soap_strdup(soap, description); + return SOAP_OK; } +#endif /******************************************************************************/ + +#ifndef WITH_LEANER SOAP_FMAC1 -void +struct soap_multipart* SOAP_FMAC2 -soap_free_cookies(struct soap *soap) -{ struct soap_cookie *p; - for (p = soap->cookies; p; p = soap->cookies) - { soap->cookies = p->next; - SOAP_FREE(soap, p->name); - if (p->value) - SOAP_FREE(soap, p->value); - if (p->domain) - SOAP_FREE(soap, p->domain); - if (p->path) - SOAP_FREE(soap, p->path); - SOAP_FREE(soap, p); +soap_next_multipart(struct soap_multipart *content) +{ + if (content) + return content->next; + return NULL; +} +#endif + +/******************************************************************************/ + +#ifndef WITH_LEANER +static void +soap_select_mime_boundary(struct soap *soap) +{ + while (!soap->mime.boundary || soap_valid_mime_boundary(soap)) + { + char *s = soap->mime.boundary; + size_t n = 0; + if (s) + n = strlen(s); + if (n < 16) + { + n = 64; + s = soap->mime.boundary = (char*)soap_malloc(soap, n + 1); + if (!s) + return; + } + *s++ = '='; + *s++ = '='; + n -= 4; + while (n) + { + *s++ = soap_base64o[soap_random & 0x3F]; + n--; + } + *s++ = '='; + *s++ = '='; + *s = '\0'; } + if (!soap->mime.start) + soap->mime.start = ""; } +#endif /******************************************************************************/ -#endif /* WITH_COOKIES */ + +#ifndef WITH_LEANER +static int +soap_valid_mime_boundary(struct soap *soap) +{ + struct soap_multipart *content; + size_t k; + if (soap->fmimeread) + return SOAP_OK; + k = strlen(soap->mime.boundary); + for (content = soap->mime.first; content; content = content->next) + { + if (content->ptr && content->size >= k) + { + const char *p = (const char*)content->ptr; + size_t i; + for (i = 0; i < content->size - k; i++, p++) + { + if (!strncmp(p, soap->mime.boundary, k)) + return SOAP_ERR; + } + } + } + return SOAP_OK; +} +#endif /******************************************************************************/ + #ifdef WITH_GZIP -#ifndef PALM_1 static int soap_getgziphdr(struct soap *soap) -{ int i; +{ + int i; soap_wchar c = 0, f = 0; DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get gzip header\n")); for (i = 0; i < 9; i++) - { if ((int)(c = soap_get1(soap) == EOF)) - return soap->error = SOAP_EOF; + { + c = soap_get1(soap); if (i == 1 && c == 8) soap->z_dict = 0; if (i == 2) f = c; } if (f & 0x04) /* FEXTRA */ - { for (i = soap_get1(soap) | (soap_get1(soap) << 8); i; i--) - { if ((int)soap_get1(soap) == EOF) - return soap->error = SOAP_EOF; + { + i = soap_get1(soap); + i |= soap_get1(soap) << 8; + while (i-- > 0) + { + if ((int)soap_get1(soap) == EOF) + return soap->error = SOAP_ZLIB_ERROR; } } - if (f & 0x08) /* FNAME */ - { do + if (f & 0x08) /* skip FNAME */ + { + do + { c = soap_get1(soap); - while (c && (int)c != EOF); + } while (c && (int)c != EOF); } - if ((int)c != EOF && (f & 0x10)) /* FCOMMENT */ - { do + if ((int)c != EOF && (f & 0x10)) /* skip FCOMMENT */ + { + do + { c = soap_get1(soap); - while (c && (int)c != EOF); + } while (c && (int)c != EOF); } - if ((int)c != EOF && (f & 0x01)) /* FHCRC */ - { if ((int)(c = soap_get1(soap)) != EOF) + if ((int)c != EOF && (f & 0x02)) /* skip FHCRC (CRC32 is used) */ + { + c = soap_get1(soap); + if ((int)c != EOF) c = soap_get1(soap); } - if ((int)c == EOF) - return soap->error = SOAP_EOF; + if ((int)c == EOF) + return soap->error = SOAP_ZLIB_ERROR; + return SOAP_OK; +} +#endif + +/******************************************************************************/ + +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_begin_serve(struct soap *soap) +{ +#ifdef WITH_FASTCGI + if (FCGI_Accept() < 0) + { + soap->error = SOAP_EOF; + return soap_send_fault(soap); + } +#endif + soap_begin(soap); + if (soap_begin_recv(soap) + || soap_envelope_begin_in(soap) + || soap_recv_header(soap) + || soap_body_begin_in(soap)) + { + if (soap->error < SOAP_STOP) + { +#ifdef WITH_FASTCGI + (void)soap_send_fault(soap); +#else + return soap_send_fault(soap); +#endif + } + return soap_closesock(soap); + } return SOAP_OK; } -#endif -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 int SOAP_FMAC2 soap_begin_recv(struct soap *soap) -{ soap_wchar c; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing for input\n")); +{ + soap_wchar c; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing for input from socket=%d/fd=%d\n", (int)soap->socket, soap->recvfd)); soap->error = SOAP_OK; +#ifndef WITH_LEANER + soap->recverror = SOAP_OK; +#endif soap_free_temp(soap); soap_set_local_namespaces(soap); - soap->version = 0; /* don't assume we're parsing SOAP content by default */ + soap->version = 0; /* don't assume we're parsing SOAP content by default */ #ifndef WITH_NOIDREF soap_free_iht(soap); #endif if ((soap->imode & SOAP_IO) == SOAP_IO_CHUNK) - soap->omode |= SOAP_IO_CHUNK; - soap->imode &= ~(SOAP_IO | SOAP_ENC_MIME); - soap->mode = soap->imode; - if (!soap->keep_alive) - { soap->buflen = 0; - soap->bufidx = 0; + { + soap->imode &= ~SOAP_IO; + soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_CHUNK; } + soap->imode &= ~(SOAP_ENC_DIME | SOAP_ENC_MIME | SOAP_ENC_ZLIB); + soap->mode = soap->imode; if (!(soap->mode & SOAP_IO_KEEPALIVE)) soap->keep_alive = 0; + if (!soap->keep_alive) + soap->buflen = soap->bufidx = 0; + soap->null = 0; + soap->position = 0; + soap->mustUnderstand = 0; + soap->shaky = 0; soap->ahead = 0; soap->peeked = 0; soap->level = 0; - soap->part = SOAP_BEGIN; - soap->alloced = 0; + soap->part = SOAP_BEGIN_RECV; soap->count = 0; soap->length = 0; soap->cdata = 0; - *soap->endpoint = '\0'; - soap->action = NULL; + if (!(soap->mode & SOAP_ENC_PLAIN)) + { + *soap->endpoint = '\0'; + soap->action = NULL; + soap->fform = NULL; + } soap->header = NULL; soap->fault = NULL; soap->status = 0; + soap->body = 1; #ifndef WITH_LEANER soap->dom = NULL; + soap->dime.count = 0; soap->dime.chunksize = 0; soap->dime.buflen = 0; soap->dime.list = NULL; @@ -12964,7 +21162,7 @@ soap_begin_recv(struct soap *soap) #ifdef WIN32 #ifndef UNDER_CE #ifndef WITH_FASTCGI - if (!soap_valid_socket(soap->socket)) + if (!soap_valid_socket(soap->socket) && !soap->is && soap->recvfd >= 0) /* Set win32 stdin or soap->recvfd to BINARY, e.g. to support DIME */ #ifdef __BORLANDC__ setmode(soap->recvfd, _O_BINARY); #else @@ -12974,32 +21172,46 @@ soap_begin_recv(struct soap *soap) #endif #endif #ifdef WITH_ZLIB - soap->mode &= ~SOAP_ENC_ZLIB; soap->zlib_in = SOAP_ZLIB_NONE; soap->zlib_out = SOAP_ZLIB_NONE; - soap->d_stream->next_in = Z_NULL; + if (!soap->d_stream) + { + soap->d_stream = (z_stream*)SOAP_MALLOC(soap, sizeof(z_stream)); + if (!soap->d_stream) + return soap->error = SOAP_EOM; + soap->d_stream->zalloc = Z_NULL; + soap->d_stream->zfree = Z_NULL; + soap->d_stream->opaque = Z_NULL; + soap->d_stream->next_in = Z_NULL; + soap->d_stream->msg = Z_NULL; + } soap->d_stream->avail_in = 0; soap->d_stream->next_out = (Byte*)soap->buf; - soap->d_stream->avail_out = SOAP_BUFLEN; + soap->d_stream->avail_out = sizeof(soap->buf); soap->z_ratio_in = 1.0; #endif #ifdef WITH_OPENSSL if (soap->ssl) ERR_clear_error(); #endif +#ifndef WITH_LEAN + soap->start = (ULONG64)time(NULL); +#endif #ifndef WITH_LEANER - if (soap->fprepareinit) - soap->fprepareinit(soap); + if (soap->fprepareinitrecv && (soap->error = soap->fprepareinitrecv(soap)) != SOAP_OK) + return soap->error; #endif c = soap_getchar(soap); #ifdef WITH_GZIP if (c == 0x1F) - { if (soap_getgziphdr(soap)) + { + if (soap_getgziphdr(soap)) return soap->error; if (inflateInit2(soap->d_stream, -MAX_WBITS) != Z_OK) return soap->error = SOAP_ZLIB_ERROR; if (soap->z_dict) - { if (inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len) != Z_OK) + { + if (inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len) != Z_OK) return soap->error = SOAP_ZLIB_ERROR; } soap->zlib_state = SOAP_ZLIB_INFLATE; @@ -13008,76 +21220,87 @@ soap_begin_recv(struct soap *soap) soap->z_crc = crc32(0L, NULL, 0); DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n")); if (!soap->z_buf) - soap->z_buf = (char*)SOAP_MALLOC(soap, SOAP_BUFLEN); - memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); + soap->z_buf = (char*)SOAP_MALLOC(soap, sizeof(soap->buf)); + (void)soap_memcpy((void*)soap->z_buf, sizeof(soap->buf), (const void*)soap->buf, sizeof(soap->buf)); /* should not chunk over plain transport, so why bother to check? */ /* if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) */ /* soap->z_buflen = soap->bufidx; */ /* else */ soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx); - soap->d_stream->avail_in = soap->buflen - soap->bufidx; + soap->d_stream->avail_in = (unsigned int)(soap->buflen - soap->bufidx); soap->z_buflen = soap->buflen; soap->buflen = soap->bufidx; - c = soap_getchar(soap); + c = ' '; } #endif + while (soap_coblank(c)) + c = soap_getchar(soap); #ifndef WITH_LEANER if (c == '-' && soap_get0(soap) == '-') + { soap->mode |= SOAP_ENC_MIME; + } else if ((c & 0xFFFC) == (SOAP_DIME_VERSION | SOAP_DIME_MB) && (soap_get0(soap) & 0xFFF0) == 0x20) + { soap->mode |= SOAP_ENC_DIME; + } else #endif - { /* skip BOM */ - if (c == 0xEF && (c = soap_getchar(soap)) == 0xBB && (c = soap_getchar(soap)) == 0xBF) - c = soap_getchar(soap); + { + /* skip BOM */ + if (c == 0xEF && soap_get0(soap) == 0xBB) + { + soap_get1(soap); + c = soap_get1(soap); + if (c == 0xBF) + { + soap->mode &= ~SOAP_ENC_LATIN; + c = soap_getchar(soap); + } + else + { + c = (0x0F << 12) | (0xBB << 6) | (c & 0x3F); /* UTF-8 */ + } + } + else if ((c == 0xFE && soap_get0(soap) == 0xFF) /* UTF-16 BE */ + || (c == 0xFF && soap_get0(soap) == 0xFE)) /* UTF-16 LE */ + { + return soap->error = SOAP_UTF_ERROR; + } /* skip space */ - while (soap_blank(c)) + while (soap_coblank(c)) c = soap_getchar(soap); } if ((int)c == EOF) - return soap->error = SOAP_EOF; + 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))) - { soap_mode m = soap->imode; - soap->mode &= ~SOAP_IO; + /* 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_PLAIN))) + { + soap_mode m = soap->imode; soap->error = soap->fparse(soap); - if (soap->error && soap->error < SOAP_STOP) - { soap->keep_alive = 0; /* force close later */ - return soap->error; - } - if (soap->error == SOAP_STOP) - return soap->error; soap->mode = soap->imode; /* if imode is changed, effectuate */ soap->imode = m; /* restore imode */ -#ifdef WITH_ZLIB - soap->mode &= ~SOAP_ENC_ZLIB; -#endif if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) - { soap->chunkbuflen = soap->buflen; + { + soap->chunkbuflen = soap->buflen; soap->buflen = soap->bufidx; soap->chunksize = 0; } -#ifndef WITH_LEANER - else if (soap->fpreparerecv && soap->buflen != soap->bufidx) - soap->fpreparerecv(soap, soap->buf + soap->bufidx, soap->buflen - soap->bufidx); -#endif - /* 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 */ - return soap->error = soap->status; - } #ifdef WITH_ZLIB + soap->mode &= ~SOAP_ENC_ZLIB; if (soap->zlib_in != SOAP_ZLIB_NONE) { #ifdef WITH_GZIP if (soap->zlib_in != SOAP_ZLIB_DEFLATE) - { c = soap_get1(soap); + { + c = soap_get1(soap); + if (c == (int)EOF) + return soap->error = SOAP_EOF; if (c == 0x1F) - { if (soap_getgziphdr(soap)) + { + if (soap_getgziphdr(soap)) return soap->error; if (inflateInit2(soap->d_stream, -MAX_WBITS) != Z_OK) return soap->error = SOAP_ZLIB_ERROR; @@ -13085,7 +21308,8 @@ soap_begin_recv(struct soap *soap) DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n")); } else - { soap_revget1(soap); + { + soap_revget1(soap); if (inflateInit(soap->d_stream) != Z_OK) return soap->error = SOAP_ZLIB_ERROR; soap->zlib_in = SOAP_ZLIB_DEFLATE; @@ -13096,696 +21320,532 @@ soap_begin_recv(struct soap *soap) if (inflateInit(soap->d_stream) != Z_OK) return soap->error = SOAP_ZLIB_ERROR; if (soap->z_dict) - { if (inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len) != Z_OK) + { + if (inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len) != Z_OK) return soap->error = SOAP_ZLIB_ERROR; } soap->zlib_state = SOAP_ZLIB_INFLATE; DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate initialized\n")); soap->mode |= SOAP_ENC_ZLIB; if (!soap->z_buf) - soap->z_buf = (char*)SOAP_MALLOC(soap, SOAP_BUFLEN); - memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); + soap->z_buf = (char*)SOAP_MALLOC(soap, sizeof(soap->buf)); + (void)soap_memcpy((void*)soap->z_buf, sizeof(soap->buf), (const void*)soap->buf, sizeof(soap->buf)); soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx); - soap->d_stream->avail_in = soap->buflen - soap->bufidx; + soap->d_stream->avail_in = (unsigned int)(soap->buflen - soap->bufidx); soap->z_buflen = soap->buflen; soap->buflen = soap->bufidx; } #endif - if (soap->error) - { if (soap->error == SOAP_FORM && soap->fform) - { soap->error = soap->fform(soap); - if (soap->error == SOAP_OK) - soap->error = SOAP_STOP; /* prevents further processing */ - } - return soap->error; +#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")); + r = soap->fpreparerecv(soap, soap->buf + soap->bufidx, soap->buflen - soap->bufidx); + if (r) + return soap->error = r; } - } #endif -#ifndef WITH_LEANER - if (soap->mode & SOAP_ENC_MIME) - { if (soap_getmimehdr(soap)) + if (soap->error && soap->error < SOAP_STOP) + { + if (soap->status >= 200 && soap->status < 600) + { + const char *s = soap_http_get_body(soap, NULL); + (void)soap_end_recv(soap); + if (soap->status >= 300) + soap->keep_alive = 0; /* to force close */ + return soap_set_receiver_error(soap, "HTTP Error", s, soap->status); + } return soap->error; - if (soap->mime.start) - { do - { if (!soap->mime.last->id) + } + if (!soap->body && soap->status >= 200 && soap->status < 600) + return soap->error = soap->status; /* client side received HTTP status code */ + if (soap->status > SOAP_POST) + { + soap->fform = NULL; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Invoking http method handler\n")); + switch (soap->status) + { + case SOAP_GET: + if (soap_http_skip_body(soap) || soap_end_recv(soap)) + return soap->error; + soap->error = soap->fget(soap); break; - if (!soap_match_cid(soap, soap->mime.start, soap->mime.last->id)) + case SOAP_PUT: + soap->error = soap->fput(soap); break; - } while (soap_get_mime_attachment(soap, NULL)); - } - if (soap_get_header_attribute(soap, soap->mime.first->type, "application/dime")) - soap->mode |= SOAP_ENC_DIME; - } - if (soap->mode & SOAP_ENC_DIME) - { if (soap_getdimehdr(soap)) - return soap->error; - if (soap->dime.flags & SOAP_DIME_CF) - { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked DIME SOAP message\n")); - soap->dime.chunksize = soap->dime.size; - if (soap->buflen - soap->bufidx >= soap->dime.chunksize) - { soap->dime.buflen = soap->buflen; - soap->buflen = soap->bufidx + soap->dime.chunksize; - } - else - soap->dime.chunksize -= soap->buflen - soap->bufidx; - } - soap->count = soap->buflen - soap->bufidx; - } -#endif - return SOAP_OK; -} -#endif - -/******************************************************************************/ -#ifndef WITH_NOHTTP -#ifndef PALM_1 -static int -http_parse(struct soap *soap) -{ char header[SOAP_HDRLEN], *s; - unsigned short httpcmd = 0, status = 0; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Waiting for HTTP request/response...\n")); - *soap->endpoint = '\0'; - soap->length = 0; - soap->userid = NULL; - soap->passwd = NULL; - soap->action = NULL; - soap->authrealm = NULL; - soap->proxy_from = NULL; - soap->http_content = NULL; - soap->status = 0; - do - { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) - { if (soap->error == SOAP_EOF) - return SOAP_EOF; - return soap->error = 414; - } - if ((s = strchr(soap->msgbuf, ' '))) - { soap->status = (unsigned short)soap_strtoul(s, &s, 10); - if (!soap_blank(*s)) - soap->status = 0; - } - else - soap->status = 0; - DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP status: %s\n", soap->msgbuf)); - for (;;) - { if (soap_getline(soap, header, SOAP_HDRLEN)) - { if (soap->error == SOAP_EOF) - { soap->error = SOAP_OK; - DBGLOG(TEST,SOAP_MESSAGE(fdebug, "EOF in HTTP header, continue anyway\n")); + case SOAP_PATCH: + soap->error = soap->fpatch(soap); break; - } - return soap->error; - } - if (!*header) - break; - DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP header: %s\n", header)); - s = strchr(header, ':'); - if (s) - { char *t; - *s = '\0'; - do s++; - while (*s && *s <= 32); - if (*s == '"') - s++; - t = s + strlen(s) - 1; - while (t > s && *t <= 32) - t--; - if (t >= s && *t == '"') - t--; - t[1] = '\0'; - if ((soap->error = soap->fparsehdr(soap, header, s))) - { if (soap->error < SOAP_STOP) + case SOAP_DEL: + if (soap_http_skip_body(soap) || soap_end_recv(soap)) return soap->error; - status = soap->error; - soap->error = SOAP_OK; - } + soap->error = soap->fdel(soap); + break; + case SOAP_HEAD: + if (soap_http_skip_body(soap) || soap_end_recv(soap)) + return soap->error; + soap->error = soap->fhead(soap); + break; + case SOAP_OPTIONS: + if (soap_http_skip_body(soap) || soap_end_recv(soap)) + return soap->error; + soap->error = soap->fopt(soap); + break; + default: + if (soap_http_skip_body(soap) || soap_end_recv(soap)) + return soap->error; + return 405; } - } - } while (soap->status == 100); - DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Finished HTTP header parsing, status = %d\n", soap->status)); - s = strstr(soap->msgbuf, "HTTP/"); - if (s && s[7] != '1') - { 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; - } - } - if (soap->keep_alive < 0) - soap->keep_alive = 1; - DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Keep alive connection = %d\n", soap->keep_alive)); - if (soap->status == 0) - { size_t l = 0; - if (s) - { if (!strncmp(soap->msgbuf, "POST ", l = 5)) - httpcmd = 1; - else if (!strncmp(soap->msgbuf, "GET ", l = 4)) - httpcmd = 2; - else if (!strncmp(soap->msgbuf, "PUT ", l = 4)) - httpcmd = 3; - else if (!strncmp(soap->msgbuf, "DELETE ", l = 7)) - httpcmd = 4; - else if (!strncmp(soap->msgbuf, "HEAD ", l = 5)) - httpcmd = 5; - } - if (s && httpcmd) - { size_t m = strlen(soap->endpoint); - size_t n = m + (s - soap->msgbuf) - l - 1; - if (m > n) - m = n; - if (n >= sizeof(soap->endpoint)) - n = sizeof(soap->endpoint) - 1; - strncpy(soap->path, soap->msgbuf + l, n - m); - soap->path[n - m] = '\0'; - strcat(soap->endpoint, soap->path); - DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Target endpoint='%s'\n", soap->endpoint)); - if (httpcmd > 1) - { switch (httpcmd) - { case 2: soap->error = soap->fget(soap); break; - case 3: soap->error = soap->fput(soap); break; - case 4: soap->error = soap->fdel(soap); break; - case 5: soap->error = soap->fhead(soap); break; - default: soap->error = 405; break; - } - if (soap->error == SOAP_OK) - soap->error = SOAP_STOP; /* prevents further processing */ + if (soap->error == SOAP_OK) + return soap->error = SOAP_STOP; /* prevents further processing and calls soap_closesock() */ + if (soap->error != SOAP_FORM || !soap->fform) /* continue if handler returned SOAP_FORM */ return soap->error; - } - if (status) - return soap->error = status; - } - else if (status) - 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 (soap->length > 0 || soap->http_content || (soap->imode & SOAP_IO) == SOAP_IO_CHUNK) - { if (((soap->status > 200 && soap->status <= 299) || soap->status == 400 || soap->status == 500)) - return SOAP_OK; - /* force close afterwards in soap_closesock() */ - soap->keep_alive = 0; - /* read HTTP body for error details */ - s = soap_get_http_body(soap); - if (s) - return soap_set_receiver_error(soap, soap->msgbuf, s, 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); -} -#endif -#endif - -/******************************************************************************/ -#ifndef WITH_NOHTTP -#ifndef PALM_1 -static int -http_parse_header(struct soap *soap, const char *key, const char *val) -{ if (!soap_tag_cmp(key, "Host")) - { -#ifdef WITH_OPENSSL - if (soap->imode & SOAP_ENC_SSL) - strcpy(soap->endpoint, "https://"); - else -#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")) - { const char *action; - soap->http_content = soap_strdup(soap, val); - if (soap_get_header_attribute(soap, val, "application/dime")) - soap->imode |= SOAP_ENC_DIME; - else if (soap_get_header_attribute(soap, val, "multipart/related") - || soap_get_header_attribute(soap, val, "multipart/form-data")) - { soap->mime.boundary = soap_strdup(soap, soap_get_header_attribute(soap, val, "boundary")); - soap->mime.start = soap_strdup(soap, soap_get_header_attribute(soap, val, "start")); - soap->imode |= SOAP_ENC_MIME; - } - action = soap_get_header_attribute(soap, val, "action"); - if (action) - { if (*action == '"') - { soap->action = soap_strdup(soap, action + 1); - soap->action[strlen(soap->action) - 1] = '\0'; - } - else - soap->action = soap_strdup(soap, action); - } - } -#endif - else if (!soap_tag_cmp(key, "Content-Length")) - { soap->length = soap_strtoul(val, NULL, 10); - } - else if (!soap_tag_cmp(key, "Content-Encoding")) - { if (!soap_tag_cmp(val, "deflate")) -#ifdef WITH_ZLIB - soap->zlib_in = SOAP_ZLIB_DEFLATE; -#else - return SOAP_ZLIB_ERROR; -#endif - else if (!soap_tag_cmp(val, "gzip")) -#ifdef WITH_GZIP - soap->zlib_in = SOAP_ZLIB_GZIP; -#else - return SOAP_ZLIB_ERROR; -#endif - } -#ifdef WITH_ZLIB - else if (!soap_tag_cmp(key, "Accept-Encoding")) - { -#ifdef WITH_GZIP - if (strchr(val, '*') || soap_get_header_attribute(soap, val, "gzip")) - soap->zlib_out = SOAP_ZLIB_GZIP; - else -#endif - if (strchr(val, '*') || soap_get_header_attribute(soap, val, "deflate")) - soap->zlib_out = SOAP_ZLIB_DEFLATE; - else - soap->zlib_out = SOAP_ZLIB_NONE; - } -#endif - else if (!soap_tag_cmp(key, "Transfer-Encoding")) - { soap->imode &= ~SOAP_IO; - if (!soap_tag_cmp(val, "chunked")) - soap->imode |= SOAP_IO_CHUNK; - } - else if (!soap_tag_cmp(key, "Connection")) - { if (!soap_tag_cmp(val, "keep-alive")) - soap->keep_alive = -soap->keep_alive; - else if (!soap_tag_cmp(val, "close")) - soap->keep_alive = 0; - } -#ifndef WITH_LEAN - else if (!soap_tag_cmp(key, "Authorization")) - { if (!soap_tag_cmp(val, "Basic *")) - { int n; - char *s; - soap_base642s(soap, val + 6, soap->tmpbuf, sizeof(soap->tmpbuf) - 1, &n); - soap->tmpbuf[n] = '\0'; - if ((s = strchr(soap->tmpbuf, ':'))) - { *s = '\0'; - soap->userid = soap_strdup(soap, soap->tmpbuf); - soap->passwd = soap_strdup(soap, s + 1); - } - } - } - else if (!soap_tag_cmp(key, "WWW-Authenticate")) - { soap->authrealm = soap_strdup(soap, soap_get_header_attribute(soap, val + 6, "realm")); - } - else if (!soap_tag_cmp(key, "Expect")) - { if (!soap_tag_cmp(val, "100-continue")) - { if ((soap->error = soap->fposthdr(soap, "HTTP/1.1 100 Continue", NULL)) - || (soap->error = soap->fposthdr(soap, NULL, NULL))) + soap->error = SOAP_OK; + } + if (soap->fform) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Invoking http post/form handler\n")); + soap->error = soap->fform(soap); + soap->fform = NULL; + if (soap->error == SOAP_OK) + return soap->error = SOAP_STOP; /* prevents further processing */ + if (soap->status != SOAP_POST || soap->error != 404) /* continue with POST if handler returned HTTP not found */ return soap->error; + soap->error = SOAP_OK; } + if (!soap->body) + return soap->error = SOAP_NO_DATA; + } + else if (soap->fform) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Invoking http form handler\n")); + soap->error = soap->fform(soap); + soap->fform = NULL; + if (soap->error == SOAP_OK) + return soap->error = SOAP_STOP; /* prevents further processing */ + if (soap->error != 404) /* continue with POST if handler returned HTTP not found */ + return soap->error; + soap->error = SOAP_OK; } #endif - else if (!soap_tag_cmp(key, "SOAPAction")) - { if (*val == '"') - { soap->action = soap_strdup(soap, val + 1); - soap->action[strlen(soap->action) - 1] = '\0'; +#ifndef WITH_LEANER + if ((soap->mode & SOAP_ENC_MIME)) + { + do /* skip preamble */ + { + c = soap_getchar(soap); + if ((int)c == EOF) + return soap->error = SOAP_CHK_EOF; + } while (c != '-' || soap_get0(soap) != '-'); + soap_unget(soap, c); + if (soap_getmimehdr(soap)) + return soap->error; + if (soap->mime.start) + { + do + { + if (!soap->mime.last->id) + break; + if (!soap_match_cid(soap, soap->mime.start, soap->mime.last->id)) + break; + } while (soap_recv_mime_attachment(soap, NULL)); } - else - soap->action = soap_strdup(soap, val); - } - else if (!soap_tag_cmp(key, "Location")) - { strncpy(soap->endpoint, val, sizeof(soap->endpoint)); - soap->endpoint[sizeof(soap->endpoint) - 1] = '\0'; - } - else if (!soap_tag_cmp(key, "X-Forwarded-For")) - { soap->proxy_from = soap_strdup(soap, val); + if (soap_http_header_attribute(soap, soap->mime.first->type, "application/dime")) + soap->mode |= SOAP_ENC_DIME; } -#ifdef WITH_COOKIES - else if (!soap_tag_cmp(key, "Cookie") - || !soap_tag_cmp(key, "Cookie2") - || !soap_tag_cmp(key, "Set-Cookie") - || !soap_tag_cmp(key, "Set-Cookie2")) - { soap_getcookies(soap, val); + if ((soap->mode & SOAP_ENC_DIME)) + { + if (soap_getdimehdr(soap)) + return soap->error; + if ((soap->dime.flags & SOAP_DIME_CF)) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked SOAP in DIME message\n")); + soap->dime.chunksize = soap->dime.size; + if (soap->buflen - soap->bufidx >= soap->dime.chunksize) + { + soap->dime.buflen = soap->buflen; + soap->buflen = soap->bufidx + soap->dime.chunksize; + } + else + { + soap->dime.chunksize -= soap->buflen - soap->bufidx; + } + } + soap->count = soap->buflen - soap->bufidx; + if (soap->recv_maxlength && soap->count > soap->recv_maxlength) + return soap->error = SOAP_EOF; } #endif return SOAP_OK; } -#endif -#endif /******************************************************************************/ -#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) -#ifndef PALM_1 + SOAP_FMAC1 -const char* +int SOAP_FMAC2 -soap_get_header_attribute(struct soap *soap, const char *line, const char *key) -{ const char *s = line; - if (s) - { while (*s) - { short flag; - s = soap_decode_key(soap->tmpbuf, sizeof(soap->tmpbuf), s); - flag = soap_tag_cmp(soap->tmpbuf, key); - s = soap_decode_val(soap->tmpbuf, sizeof(soap->tmpbuf), s); - if (!flag) - return soap->tmpbuf; - } - } - return NULL; +soap_envelope_begin_out(struct soap *soap) +{ + if (soap->version == 0) + return SOAP_OK; + soap->part = SOAP_IN_ENVELOPE; + return soap_element_begin_out(soap, "SOAP-ENV:Envelope", 0, NULL); } -#endif -#endif /******************************************************************************/ -#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) -#ifndef PALM_1 + SOAP_FMAC1 -const char* +int SOAP_FMAC2 -soap_decode_key(char *buf, size_t len, const char *val) -{ return soap_decode(buf, len, val, "=,;"); +soap_envelope_end_out(struct soap *soap) +{ + 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; + soap->part = SOAP_END_ENVELOPE; + return SOAP_OK; } -#endif -#endif /******************************************************************************/ -#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) -#ifndef PALM_1 + SOAP_FMAC1 -const char* +int SOAP_FMAC2 -soap_decode_val(char *buf, size_t len, const char *val) -{ if (*val != '=') - { *buf = '\0'; - return val; - } - return soap_decode(buf, len, val + 1, ",;"); +soap_http_has_body(struct soap *soap) +{ + return soap->length || (soap->mode & SOAP_ENC_ZLIB) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK; } -#endif -#endif /******************************************************************************/ -#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) -#ifndef PALM_1 -static const char* -soap_decode(char *buf, size_t len, const char *val, const char *sep) -{ const char *s; - char *t = buf; - for (s = val; *s; s++) - if (*s != ' ' && *s != '\t' && !strchr(sep, *s)) - break; - if (*s == '"') - { s++; - while (*s && *s != '"' && --len) - *t++ = *s++; + +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_http_skip_body(struct soap *soap) +{ + ULONG64 k = soap->length; + /* check HTTP body, return "" if none */ + if (!k && !(soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) != SOAP_IO_CHUNK) + return SOAP_OK; + /* do not consume DIME or MIME attachments, leave this to soap_end_recv */ + if ((soap->mode & SOAP_ENC_DIME) || (soap->mode & SOAP_ENC_MIME)) + return SOAP_OK; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Skipping HTTP body (mode=0x%x)\n", soap->mode)); + if (k && !(soap->mode & SOAP_ENC_ZLIB)) + { + ULONG64 i; + soap->length = 0; + for (i = 0; i < k; i++) + { + soap_wchar c = soap_get1(soap); + if ((int)c == EOF) + break; + } } else - { while (*s && !soap_blank(*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 - *t++ = *s++; + { + for (;;) + { + soap_wchar c = soap_get1(soap); + if ((int)c == EOF) + break; } } - *t = '\0'; - while (*s && !strchr(sep, *s)) - s++; - return s; + return SOAP_OK; } -#endif -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 -int +char * SOAP_FMAC2 -soap_envelope_begin_out(struct soap *soap) +soap_http_get_body(struct soap *soap, size_t *len) { -#ifndef WITH_LEANER - size_t n = 0; - if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && soap->mime.start && strlen(soap->mime.boundary) + strlen(soap->mime.start) < sizeof(soap->tmpbuf) - 80 ) - { const char *s; - if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) - s = "application/dime"; - else if (soap->version == 2) - { if (soap->mode & SOAP_ENC_MTOM) - s = "application/xop+xml; charset=utf-8; type=\"application/soap+xml\""; - else - s = "application/soap+xml; charset=utf-8"; - } - else if (soap->mode & SOAP_ENC_MTOM) - s = "application/xop+xml; charset=utf-8; type=\"text/xml\""; - else - s = "text/xml; charset=utf-8"; - 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); - n = strlen(soap->tmpbuf); - if (soap_send_raw(soap, soap->tmpbuf, n)) - return soap->error; - } - if (soap->mode & SOAP_IO_LENGTH) - soap->dime.size = soap->count; /* DIME in MIME correction */ - if (!(soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME)) - { if (soap_putdimehdr(soap)) - return soap->error; - } -#endif - soap->part = SOAP_IN_ENVELOPE; - return soap_element_begin_out(soap, "SOAP-ENV:Envelope", 0, NULL); + return soap_http_get_body_prefix(soap, len, NULL); } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 -int +char * SOAP_FMAC2 -soap_envelope_end_out(struct soap *soap) -{ if (soap_element_end_out(soap, "SOAP-ENV:Envelope")) - 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 */ - sprintf(soap->id, soap->dime_id_format, 0); - soap->dime.id = soap->id; - if (soap->local_namespaces) - { if (soap->local_namespaces[0].out) - soap->dime.type = (char*)soap->local_namespaces[0].out; - else - soap->dime.type = (char*)soap->local_namespaces[0].ns; - } - soap->dime.options = NULL; - soap->dime.flags = SOAP_DIME_MB | SOAP_DIME_ABSURI; - if (!soap->dime.first) - soap->dime.flags |= SOAP_DIME_ME; - soap->count += 12 + ((strlen(soap->dime.id)+3)&(~3)) + (soap->dime.type ? ((strlen(soap->dime.type)+3)&(~3)) : 0); - } - if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) - return soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3); -#endif - soap->part = SOAP_END_ENVELOPE; - return SOAP_OK; +soap_http_get_form(struct soap *soap) +{ + return soap_http_get_body_prefix(soap, NULL, "?"); } -#endif /******************************************************************************/ -#ifndef PALM_1 -static char* -soap_get_http_body(struct soap *soap) + +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_http_get_body_prefix(struct soap *soap, size_t *len, const char *prefix) { -#ifndef WITH_LEAN - size_t l = 0, n = 0; char *s; - /* get HTML body of HTTP error content */ - if (!(soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) != SOAP_IO_CHUNK) - { n = soap->length; - if (!n) - return NULL; - } -#ifdef WITH_FAST - soap->labidx = 0; /* use look-aside buffer */ -#else - if (soap_new_block(soap) == NULL) - return NULL; -#endif - for (;;) + ULONG64 k = soap->length; + size_t n = 0; + if (!prefix) + prefix = SOAP_STR_EOS; + else + n = strlen(prefix); + if (len) + *len = 0; + /* check HTTP body, return "" if none */ + if (!k && !(soap->mode & SOAP_ENC_PLAIN) && !(soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) != SOAP_IO_CHUNK) + return soap_strdup(soap, prefix); + /* do not consume DIME or MIME attachments, leave this to soap_end_recv */ + if ((soap->mode & SOAP_ENC_DIME) || (soap->mode & SOAP_ENC_MIME)) + return soap_strdup(soap, prefix); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Parsing HTTP body, prefixed with '%s' (mode=0x%x)\n", prefix, soap->mode)); + if (k && !(soap->mode & SOAP_ENC_ZLIB)) { -#ifdef WITH_FAST - size_t i, k; - if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */ + char *t; + size_t j; + soap->length = 0; + /* http content length != 0 and uncompressed body and body length does not exceed size_t max size */ + if ((SOAP_MAXALLOCSIZE != 0 && n + k > SOAP_MAXALLOCSIZE) || n + k > (ULONG64)((size_t)-2)) + { + soap->error = SOAP_EOM; return NULL; - s = soap->labbuf + soap->labidx; /* space to populate */ - k = soap->lablen - soap->labidx; /* number of bytes available */ - soap->labidx = soap->lablen; /* claim this space */ -#else - size_t i, k = SOAP_BLKLEN; - if (!(s = (char*)soap_push_block(soap, NULL, k))) + } + j = (size_t)k; /* safe cast: k is in size_t range as guarded above */ + s = t = (char*)soap_malloc(soap, j + n + 1); + if (s) + { + size_t i = 0; + if (n) + { + (void)soap_memcpy(t, n, prefix, n); + t += n; + } + if (soap->ahead && j > 0) + { + *t++ = soap->ahead; + ++i; + soap->ahead = 0; + } + while (i < j) + { + size_t m; + if (soap->bufidx >= soap->buflen) + if (soap_recv(soap)) + break; + if (soap->buflen - soap->bufidx > j - i) + m = j - i; + else + m = soap->buflen - soap->bufidx; + (void)soap_memcpy(t, j + n + 1 - i, soap->buf + soap->bufidx, m); + soap->bufidx += m; + t += m; + i += m; + } + *t = '\0'; + if (len) + *len = n + i; + } + else + { + soap->error = SOAP_EOM; return NULL; -#endif - for (i = 0; i < k; i++) - { soap_wchar c = soap_getchar(soap); - if ((int)c == EOF) - goto end; - *s++ = (char)(c & 0xFF); - l++; - if (n > 0 && l >= n) - goto end; } } + else + { + size_t i, l = 0; + if (soap_alloc_block(soap) == NULL) + return NULL; + if (n) + { + s = (char*)soap_push_block(soap, NULL, n); + if (!s) + return NULL; + (void)soap_memcpy(s, n, prefix, n); + l += n; + } + if (soap->ahead) + { + s = (char*)soap_push_block(soap, NULL, 1); + if (!s) + return NULL; + *s = soap->ahead; + ++l; + soap->ahead = 0; + } + for (;;) + { + size_t k = SOAP_BLKLEN; + s = (char*)soap_push_block(soap, NULL, k); + if (!s) + return NULL; + i = 0; + while (i < k) + { + size_t m; + if (soap->bufidx >= soap->buflen) + if (soap_recv(soap)) + goto end; + if (soap->buflen - soap->bufidx > k - i) + m = k - i; + else + m = soap->buflen - soap->bufidx; + (void)soap_memcpy(s, k - i, soap->buf + soap->bufidx, m); + soap->bufidx += m; + s += m; + i += m; + if (l + m < l) + { + soap->error = SOAP_EOM; + return NULL; + } + l += m; + } + } end: - *s = '\0'; -#ifdef WITH_FAST - s = soap_strdup(soap, soap->labbuf); -#else - soap_size_block(soap, NULL, i+1); - s = soap_save_block(soap, NULL, 0); -#endif + *s = '\0'; + if (len) + *len = l; + soap_size_block(soap, NULL, i + 1); + s = (char*)soap_save_block(soap, NULL, NULL, 0); + } return s; -#else - return NULL; -#endif } -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_begin_in(struct soap *soap) -{ 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; - else if (soap->status) + { + if (soap->error == SOAP_TAG_MISMATCH) + { + if (!soap_element_begin_in(soap, ":Envelope", 0, NULL)) + return soap->error = SOAP_VERSIONMISMATCH; + if (soap->status == 0 + || (soap->status >= 200 && soap->status <= 299) + || soap->status == 400 + || soap->status == 500 + || soap->status >= SOAP_POST) + return soap->error = SOAP_OK; /* allow non-SOAP (REST) XML content to be captured */ soap->error = soap->status; - return soap->error; - } - p = soap->local_namespaces; - if (p) - { const char *ns = p[0].out; - if (!ns) - ns = p[0].ns; - if (!strcmp(ns, soap_env1)) - { soap->version = 1; /* make sure we use SOAP 1.1 */ - if (p[1].out) - SOAP_FREE(soap, p[1].out); - if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc1)))) - strcpy(p[1].out, soap_enc1); } - else if (!strcmp(ns, soap_env2)) - { soap->version = 2; /* make sure we use SOAP 1.2 */ - if (p[1].out) - SOAP_FREE(soap, p[1].out); - if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc2)))) - strcpy(p[1].out, soap_enc2); + else if (soap->status) + { + soap->error = soap->status; } + return soap->error; } + soap_version(soap); return SOAP_OK; } -#endif /******************************************************************************/ -#ifndef PALM_1 + 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 /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 soap_body_begin_out(struct soap *soap) -{ soap->part = SOAP_IN_BODY; +{ if (soap->version == 1) soap->encoding = 1; #ifndef WITH_LEAN - if ((soap->mode & SOAP_XML_SEC) && soap_set_attr(soap, "wsu:Id", "Body")) + if ((soap->mode & SOAP_SEC_WSUID) && soap_set_attr(soap, "wsu:Id", "Body", 1)) return soap->error; #endif - if (soap_element(soap, "SOAP-ENV:Body", 0, NULL)) - return soap->error; - return soap_element_start_end_out(soap, NULL); + if (soap->version == 0) + return SOAP_OK; + soap->part = SOAP_IN_BODY; + return soap_element_begin_out(soap, "SOAP-ENV:Body", 0, NULL); } -#endif /******************************************************************************/ -#ifndef PALM_2 + 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; } -#endif /******************************************************************************/ -#ifndef PALM_2 + 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) soap->part = SOAP_NO_BODY; return SOAP_OK; } -#endif /******************************************************************************/ -#ifndef PALM_2 + 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"); } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 soap_recv_header(struct soap *soap) -{ if (soap_getheader(soap) && soap->error == SOAP_TAG_MISMATCH) +{ + if (soap_getheader(soap) && soap->error == SOAP_TAG_MISMATCH) soap->error = SOAP_OK; if (soap->error == SOAP_OK && soap->fheader) soap->error = soap->fheader(soap); return soap->error; } -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 void SOAP_FMAC2 soap_set_endpoint(struct soap *soap, const char *endpoint) -{ const char *s; +{ + const char *s, *t; size_t i, n; soap->endpoint[0] = '\0'; soap->host[0] = '\0'; @@ -13794,26 +21854,56 @@ soap_set_endpoint(struct soap *soap, const char *endpoint) soap->port = 80; if (!endpoint || !*endpoint) return; -#ifdef WITH_OPENSSL +#if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) || defined(WITH_WOLFSSL) || defined(WITH_SYSTEMSSL) if (!soap_tag_cmp(endpoint, "https:*")) soap->port = 443; #endif - strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint) - 1); - soap->endpoint[sizeof(soap->endpoint) - 1] = '\0'; + soap_strcpy(soap->endpoint, sizeof(soap->endpoint), endpoint); s = strchr(endpoint, ':'); if (s && s[1] == '/' && s[2] == '/') s += 3; else s = endpoint; +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) + t = strchr(s, '@'); + if (t && *s != ':' && *s != '@') + { + size_t l = t - s + 1; + char *r = (char*)soap_malloc(soap, l); + n = s - endpoint; + if (r) + { + s = soap_decode(r, l, s, ":@"); + soap->userid = r; + soap->passwd = SOAP_STR_EOS; + if (*s == ':') + { + s++; + if (*s != '@' && s < t) + { + l = t - s + 1; + r = r + strlen(r) + 1; + s = soap_decode(r, l, s, "@"); + soap->passwd = r; + } + } + } + s++; + soap_strcpy(soap->endpoint + n, sizeof(soap->endpoint) - n, s); + } +#endif n = strlen(s); if (n >= sizeof(soap->host)) n = sizeof(soap->host) - 1; #ifdef WITH_IPV6 if (s[0] == '[') - { s++; + { + s++; for (i = 0; i < n; i++) - { if (s[i] == ']') - { s++; + { + if (s[i] == ']') + { + s++; --n; break; } @@ -13821,149 +21911,391 @@ soap_set_endpoint(struct soap *soap, const char *endpoint) } } else - { for (i = 0; i < n; i++) - { soap->host[i] = s[i]; - if (s[i] == '/' || s[i] == ':') + { + for (i = 0; i < n; i++) + { + soap->host[i] = s[i]; + if (s[i] == '/' || s[i] == ':' || s[i] == '?') break; } } #else for (i = 0; i < n; i++) - { soap->host[i] = s[i]; - if (s[i] == '/' || s[i] == ':') + { + soap->host[i] = s[i]; + if (s[i] == '/' || s[i] == ':' || s[i] == '?') break; } #endif soap->host[i] = '\0'; if (s[i] == ':') - { soap->port = (int)atol(s + i + 1); + { + soap->port = (int)soap_strtol(s + i + 1, NULL, 10); for (i++; i < n; i++) if (s[i] == '/') break; } if (i < n && s[i]) - { strncpy(soap->path, s + i, sizeof(soap->path)); - soap->path[sizeof(soap->path) - 1] = '\0'; + soap_strcpy(soap->path, sizeof(soap->path), s + i); + if (soap->override_host && *soap->override_host) + { + soap_strcpy(soap->host, sizeof(soap->host), soap->override_host); + if (soap->override_port) + soap->port = soap->override_port; } + if (soap->userid && !soap->authrealm) + soap->authrealm = soap->host; +} + +/******************************************************************************/ + +#ifndef WITH_NOHTTP +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_GET(struct soap *soap, const char *endpoint, const char *action) +{ + return soap_connect_command(soap, SOAP_GET, endpoint, action); } #endif /******************************************************************************/ -#ifndef PALM_1 + +#ifndef WITH_NOHTTP SOAP_FMAC1 int SOAP_FMAC2 -soap_connect(struct soap *soap, const char *endpoint, const char *action) -{ return soap_connect_command(soap, SOAP_POST, endpoint, action); +soap_PUT(struct soap *soap, const char *endpoint, const char *action, const char *type) +{ + if (!soap->http_content) + soap->http_content = type; + if ((soap->omode & SOAP_IO) != SOAP_IO_CHUNK) + { + soap->omode &= ~SOAP_IO; + soap->omode |= SOAP_IO_STORE; + } + return soap_connect_command(soap, SOAP_PUT, endpoint, action); +} +#endif + +/******************************************************************************/ + +#ifndef WITH_NOHTTP +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_POST(struct soap *soap, const char *endpoint, const char *action, const char *type) +{ + if (!soap->http_content) + soap->http_content = type; + if ((soap->omode & SOAP_IO) != SOAP_IO_CHUNK) + { + soap->omode &= ~SOAP_IO; + soap->omode |= SOAP_IO_STORE; + } + return soap_connect_command(soap, SOAP_POST_FILE, endpoint, action); +} +#endif + +/******************************************************************************/ + +#ifndef WITH_NOHTTP +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_PATCH(struct soap *soap, const char *endpoint, const char *action, const char *type) +{ + if (!soap->http_content) + soap->http_content = type; + if ((soap->omode & SOAP_IO) != SOAP_IO_CHUNK) + { + soap->omode &= ~SOAP_IO; + soap->omode |= SOAP_IO_STORE; + } + return soap_connect_command(soap, SOAP_PATCH, endpoint, action); +} +#endif + +/******************************************************************************/ + +#ifndef WITH_NOHTTP +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_DELETE(struct soap *soap, const char *endpoint) +{ + if (soap_connect_command(soap, SOAP_DEL, endpoint, NULL) + || soap_recv_empty_response(soap)) + return soap_closesock(soap); + return SOAP_OK; } #endif /******************************************************************************/ -#ifndef PALM_1 + +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_connect(struct soap *soap, const char *endpoint, const char *action) +{ + return soap_connect_command(soap, SOAP_POST, endpoint, action); +} + +/******************************************************************************/ + SOAP_FMAC1 int SOAP_FMAC2 soap_connect_command(struct soap *soap, int http_command, const char *endpoints, const char *action) -{ char *endpoint; - const char *s; - if (endpoints && (s = strchr(endpoints, ' '))) - { endpoint = (char*)SOAP_MALLOC(soap, strlen(endpoints) + 1); +{ + if (endpoints) + { + int retry = soap->connect_retry; + unsigned int backoff = 1; for (;;) - { strncpy(endpoint, endpoints, s - endpoints); - endpoint[s - endpoints] = '\0'; - if (soap_try_connect_command(soap, http_command, endpoint, action) != SOAP_TCP_ERROR) - break; - if (!*s) + { + struct timeval tv; + const char *s; + s = strchr(endpoints, ' '); + if (s) + { + size_t l = strlen(endpoints); + char *endpoint = NULL; + if (SOAP_MAXALLOCSIZE == 0 || l <= SOAP_MAXALLOCSIZE) + endpoint = (char*)SOAP_MALLOC(soap, l + 1); + if (!endpoint) + return soap->error = SOAP_EOM; + for (;;) + { + (void)soap_strncpy(endpoint, l + 1, endpoints, s - endpoints); + endpoint[s - endpoints] = '\0'; + if (soap_try_connect_command(soap, http_command, endpoint, action) != SOAP_TCP_ERROR) + break; + while (*s == ' ') + s++; + if (!*s) + break; + soap->error = SOAP_OK; + endpoints = s; + s = strchr(endpoints, ' '); + if (!s) + s = endpoints + strlen(endpoints); + } + SOAP_FREE(soap, endpoint); + } + else + { + soap_try_connect_command(soap, http_command, endpoints, action); + } + if (soap->error != SOAP_TCP_ERROR || retry <= 0) break; soap->error = SOAP_OK; - while (*s == ' ') - s++; - endpoints = s; - s = strchr(endpoints, ' '); - if (!s) - s = endpoints + strlen(endpoints); + tv.tv_sec = backoff; + tv.tv_usec = 0; + select(0, NULL, NULL, NULL, &tv); + if (backoff < 32) + backoff *= 2; + --retry; } - SOAP_FREE(soap, endpoint); } - else - soap_try_connect_command(soap, http_command, endpoints, action); return soap->error; } -#endif /******************************************************************************/ -#ifndef PALM_1 + static int soap_try_connect_command(struct soap *soap, int http_command, const char *endpoint, const char *action) -{ char host[sizeof(soap->host)]; +{ + char host[sizeof(soap->host)]; int port; - size_t count; + ULONG64 count; soap->error = SOAP_OK; - strcpy(host, soap->host); /* save previous host name: if != then reconnect */ + soap_reset_errno; + soap->errnum = 0; + (void)soap_memcpy(host, sizeof(host), soap->host, sizeof(soap->host)); /* save previous host name: if != then reconnect */ port = soap->port; /* save previous port to compare */ soap->status = http_command; soap_set_endpoint(soap, endpoint); + soap->action = soap_strdup(soap, action); #ifndef WITH_LEANER if (soap->fconnect) - { if ((soap->error = soap->fconnect(soap, endpoint, soap->host, soap->port))) + { + soap->error = soap->fconnect(soap, endpoint, soap->host, soap->port); + if (soap->error) return soap->error; } else #endif if (soap->fopen && *soap->host) - { if (!soap->keep_alive || !soap_valid_socket(soap->socket) || strcmp(soap->host, host) || soap->port != port || !soap->fpoll || soap->fpoll(soap)) - { soap->keep_alive = 0; /* to force close */ - soap->omode &= ~SOAP_IO_UDP; /* to force close */ - soap_closesock(soap); - DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Connect/reconnect to host='%s' path='%s' port=%d\n", soap->host, soap->path, soap->port)); + { + if (!soap->keep_alive || !soap_valid_socket(soap->socket) || strcmp(soap->host, host) || soap->port != port || !soap->fpoll || soap->fpoll(soap)) + { + soap->error = SOAP_OK; #ifndef WITH_LEAN - if (!strncmp(endpoint, "soap.udp:", 9)) + if (!strncmp(endpoint, "soap.udp:", 9) || !strncmp(endpoint, "udp:", 4)) + { soap->omode |= SOAP_IO_UDP; + } + else #endif - soap->socket = soap->fopen(soap, endpoint, soap->host, soap->port); - if (soap->error) - return soap->error; - soap->keep_alive = ((soap->omode & SOAP_IO_KEEPALIVE) != 0); + { + soap->keep_alive = 0; /* to force close */ + soap->omode &= ~SOAP_IO_UDP; /* to force close */ + } + (void)soap_closesock(soap); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect/reconnect to '%s' host='%s' path='%s' port=%d\n", endpoint?endpoint:"(null)", soap->host, soap->path, soap->port)); + if (!soap->keep_alive || !soap_valid_socket(soap->socket)) + { + soap->socket = soap->fopen(soap, endpoint, soap->host, soap->port); + if (!soap_valid_socket(soap->socket) || soap->error) + { + if (soap->error) + return soap->error; + return soap->error = SOAP_TCP_ERROR; + } + soap->keep_alive = -((soap->omode & SOAP_IO_KEEPALIVE) != 0); + } } } +#ifdef WITH_NTLM + if (soap_ntlm_handshake(soap, SOAP_GET, endpoint, soap->host, soap->port)) + return soap->error; +#endif count = soap_count_attachments(soap); - if (soap_begin_send(soap)) + if (soap_init_send(soap)) return soap->error; - if (http_command == SOAP_GET) - { soap->mode &= ~SOAP_IO; +#ifndef WITH_NOHTTP + if (http_command == SOAP_GET || http_command == SOAP_DEL || http_command == SOAP_HEAD || http_command == SOAP_OPTIONS) + { + soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB); soap->mode |= SOAP_IO_BUFFER; } -#ifndef WITH_NOHTTP - soap->action = soap_strdup(soap, action); - if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML) && endpoint) - { unsigned int k = soap->mode; + if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_PLAIN) && endpoint) + { + soap_mode k = soap->mode; soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB); if ((k & SOAP_IO) != SOAP_IO_FLUSH) soap->mode |= SOAP_IO_BUFFER; - if ((soap->error = soap->fpost(soap, endpoint, soap->host, soap->port, soap->path, action, count))) + soap->error = soap->fpost(soap, endpoint, soap->host, soap->port, soap->path, action, count); + if (soap->error) return soap->error; -#ifndef WITH_LEANER if ((k & SOAP_IO) == SOAP_IO_CHUNK) - { if (soap_flush(soap)) + { + if (soap_flush(soap)) return soap->error; } -#endif soap->mode = k; } - if (http_command == SOAP_GET) - return soap_end_send(soap); + if (http_command == SOAP_GET || http_command == SOAP_DEL || http_command == SOAP_HEAD || http_command == SOAP_OPTIONS) + return soap_end_send_flush(soap); +#endif +#ifndef WITH_LEANER + if (soap_begin_attachments(soap)) + return soap->error; #endif return SOAP_OK; } + +/******************************************************************************/ + +#ifdef WITH_NTLM +static int +soap_ntlm_handshake(struct soap *soap, int command, const char *endpoint, const char *host, int port) +{ + /* requires libntlm from http://www.nongnu.org/libntlm/ */ + const char *userid = (soap->proxy_userid ? soap->proxy_userid : soap->userid); + const char *passwd = (soap->proxy_passwd ? soap->proxy_passwd : soap->passwd); + struct SOAP_ENV__Header *oldheader; + if (soap->ntlm_challenge && userid && passwd && soap->authrealm) + { + tSmbNtlmAuthRequest req; + tSmbNtlmAuthResponse res; + tSmbNtlmAuthChallenge ch; + int keep_alive = soap->keep_alive; + ULONG64 length = soap->length; + ULONG64 count = soap->count; + soap_mode m = soap->mode; + soap_mode om = soap->omode; + int status = soap->status; + char *action = soap->action; + short version = soap->version; + const char *http_content = soap->http_content; + const char *http_extra_header = soap->http_extra_header; + const char *bearer = soap->bearer; + 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")); + /* S -> C 401 Unauthorized + WWW-Authenticate: NTLM + */ + buildSmbNtlmAuthRequest(&req, userid, soap->authrealm); + soap->ntlm_challenge = soap_s2base64(soap, (unsigned char*)(void*)&req, NULL, SmbLength(&req)); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "NTLM C->S Type 2: sending NTLM authorization to server\nAuthorization: NTLM %s\n", soap->ntlm_challenge)); + /* C -> S GET ... + Authorization: NTLM TlRMTVNTUAABAAAAA7IAAAoACgApAAAACQAJACAAAABMSUdIVENJVFlVUlNBLU1JTk9S + */ + soap->omode = SOAP_IO_BUFFER; + if (soap_init_send(soap)) + return soap->error; + if (!soap->keep_alive) + soap->keep_alive = -1; /* client keep alive */ + soap->status = command; /* GET or CONNECT for proxy */ + if (soap->fpost(soap, endpoint, host, port, soap->path, soap->action, 0) + || soap_end_send_flush(soap)) + return soap->error; + soap->mode = m; + soap->keep_alive = keep_alive; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "NTLM S->C Type 2: waiting on server NTLM response\n")); + oldheader = soap->header; + if (soap_begin_recv(soap)) + if (soap->error == SOAP_EOF) + return soap->error; + (void)soap_end_recv(soap); + soap->header = oldheader; + soap->length = length; + if (soap->status != 401 && soap->status != 407) + return soap->error = SOAP_NTLM_ERROR; + soap->error = SOAP_OK; + } + /* S -> C 401 Unauthorized + WWW-Authenticate: NTLM TlRMTVNTUAACAAAAAAAAACgAAAABggAAU3J2Tm9uY2UAAAAAAAAAAA== + */ + soap_base642s(soap, soap->ntlm_challenge, (char*)&ch, sizeof(tSmbNtlmAuthChallenge), NULL); + buildSmbNtlmAuthResponse(&ch, &res, userid, passwd); + soap->ntlm_challenge = soap_s2base64(soap, (unsigned char*)(void*)&res, NULL, SmbLength(&res)); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "NTLM C->S Type 3: sending NTLM authorization to server\nAuthorization: NTLM %s\n", soap->ntlm_challenge)); + /* 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 = keep_alive; + soap->length = length; + soap->count = count; + soap->mode = m; + soap->omode = om; + soap->status = status; + soap->action = action; + soap->version = version; + soap->http_content = http_content; + soap->http_extra_header = http_extra_header; + soap->bearer = bearer; + } + return SOAP_OK; +} #endif /******************************************************************************/ -#ifndef WITH_LEAN + SOAP_FMAC1 char* SOAP_FMAC2 soap_s2base64(struct soap *soap, const unsigned char *s, char *t, int n) -{ int i; +{ + int i; unsigned long m; char *p; if (!t) @@ -13975,7 +22307,8 @@ soap_s2base64(struct soap *soap, const unsigned char *s, char *t, int n) if (!s) return p; for (; n > 2; n -= 3, s += 3) - { m = s[0]; + { + m = s[0]; m = (m << 8) | s[1]; m = (m << 8) | s[2]; for (i = 4; i > 0; m >>= 6) @@ -13983,13 +22316,14 @@ soap_s2base64(struct soap *soap, const unsigned char *s, char *t, int n) t += 4; } t[0] = '\0'; - if (n > 0) - { m = 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] = '='; @@ -13997,93 +22331,105 @@ soap_s2base64(struct soap *soap, const unsigned char *s, char *t, int n) } return p; } -#endif /******************************************************************************/ -#ifndef WITH_LEAN + SOAP_FMAC1 const char* SOAP_FMAC2 soap_base642s(struct soap *soap, const char *s, char *t, size_t l, int *n) -{ int i, j, c; +{ + size_t i, j; + soap_wchar c; unsigned long m; const char *p; + if (n) + *n = 0; if (!s || !*s) - { if (n) - *n = 0; + { if (soap->error) return NULL; return SOAP_NON_NULL; } if (!t) - { l = (strlen(s) + 3) / 4 * 3; + { + l = (strlen(s) + 3) / 4 * 3 + 1; /* space for raw binary and \0 */ t = (char*)soap_malloc(soap, l); } if (!t) return NULL; 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; + 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: + { + 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 += i; - 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 + '+')) - { soap->error = SOAP_TYPE; + 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++; } - *t++ = (char)((m >> 16) & 0xFF); - *t++ = (char)((m >> 8) & 0xFF); - *t++ = (char)(m & 0xFF); - if (l < 3) - { if (n) - *n += i; - return p; + else if (!soap_coblank(c + '+')) + { + soap->error = SOAP_TYPE; + return NULL; } - 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 /******************************************************************************/ -#ifndef WITH_LEAN + SOAP_FMAC1 char* SOAP_FMAC2 soap_s2hex(struct soap *soap, const unsigned char *s, char *t, int n) -{ char *p; +{ + char *p; if (!t) t = (char*)soap_malloc(soap, 2 * n + 1); if (!t) @@ -14091,8 +22437,10 @@ soap_s2hex(struct soap *soap, const unsigned char *s, char *t, int n) p = t; t[0] = '\0'; if (s) - { for (; n > 0; n--) - { int m = *s++; + { + for (; n > 0; n--) + { + int m = *s++; *t++ = (char)((m >> 4) + (m > 159 ? 'a' - 10 : '0')); m &= 0x0F; *t++ = (char)(m + (m > 9 ? 'a' - 10 : '0')); @@ -14101,102 +22449,147 @@ soap_s2hex(struct soap *soap, const unsigned char *s, char *t, int n) *t++ = '\0'; return p; } -#endif /******************************************************************************/ -#ifndef WITH_LEAN + SOAP_FMAC1 const char* SOAP_FMAC2 soap_hex2s(struct soap *soap, const char *s, char *t, size_t l, int *n) -{ const char *p; +{ + const char *p; + if (n) + *n = 0; if (!s || !*s) - { if (n) - *n = 0; + { if (soap->error) return NULL; return SOAP_NON_NULL; } if (!t) - { l = strlen(s) / 2; + { + l = strlen(s) / 2 + 1; /* make sure enough space for \0 */ t = (char*)soap_malloc(soap, l); } if (!t) return NULL; p = t; while (l) - { int d1, d2; + { + int d1, d2; d1 = *s++; if (!d1) break; d2 = *s++; if (!d2) break; - *t++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'); + *t++ = (char)(((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0')); l--; } if (n) *n = (int)(t - p); + if (l) + *t = '\0'; return p; } -#endif /******************************************************************************/ + #ifndef WITH_NOHTTP -#ifndef PALM_1 SOAP_FMAC1 -int +const char * SOAP_FMAC2 -soap_puthttphdr(struct soap *soap, int status, size_t count) -{ if (soap->status != SOAP_GET) - { const char *s = "text/xml; charset=utf-8"; - int err = SOAP_OK; +soap_http_content_type(struct soap *soap, int status) +{ + if (soap->status != SOAP_GET && soap->status != SOAP_DEL && soap->status != SOAP_CONNECT) + { + const char *s = "text/xml; charset=utf-8"; #ifndef WITH_LEANER const char *r = NULL; + size_t n; #endif - if ((status == SOAP_FILE || soap->status == SOAP_POST_FILE) && soap->http_content) + if (((status >= SOAP_FILE && status < SOAP_FILE + 600) || soap->status == SOAP_PUT || soap->status == SOAP_POST_FILE || soap->status == SOAP_PATCH) && soap->http_content && *soap->http_content && !strchr(soap->http_content, 10) && !strchr(soap->http_content, 13)) s = soap->http_content; else if (status == SOAP_HTML) s = "text/html; charset=utf-8"; - else if (count || ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK)) - { if (soap->version == 2) - s = "application/soap+xml; charset=utf-8"; - } + else if (soap->version == 2) + s = "application/soap+xml; charset=utf-8"; + soap->http_content = NULL; /* use http_content once (assign new value before each call) */ #ifndef WITH_LEANER if (soap->mode & (SOAP_ENC_DIME | SOAP_ENC_MTOM)) - { if (soap->mode & SOAP_ENC_MTOM) - { if (soap->version == 2) + { + if ((soap->mode & SOAP_ENC_MTOM)) + { + if (soap->version == 2) r = "application/soap+xml"; - else + else r = "text/xml"; s = "application/xop+xml"; } else + { 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) - { const char *t = strchr(s, ';'); - sprintf(soap->tmpbuf, "multipart/related; charset=utf-8; boundary=\"%s\"; type=\"", soap->mime.boundary); + if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary) + { + const char *t; + size_t l; + (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), strlen(soap->mime.boundary) + 53), "multipart/related; charset=utf-8; boundary=\"%s\"; type=\"", soap->mime.boundary); + t = strchr(s, ';'); if (t) - { strncat(soap->tmpbuf, s, t - s); - soap->tmpbuf[sizeof(soap->tmpbuf)-1] = '\0'; - } + n = t - s; else - strcat(soap->tmpbuf, s); + n = strlen(s); + l = strlen(soap->tmpbuf); + if (sizeof(soap->tmpbuf) > l + n) + (void)soap_strncpy(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, s, n); if (soap->mime.start) - { strcat(soap->tmpbuf, "\"; start=\""); - strcat(soap->tmpbuf, soap->mime.start); + { + l = strlen(soap->tmpbuf); + (SOAP_SNPRINTF(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, strlen(soap->mime.start) + 10), "\"; start=\"%s", soap->mime.start); } - strcat(soap->tmpbuf, "\""); if (r) - { strcat(soap->tmpbuf, "; start-info=\""); - strcat(soap->tmpbuf, r); - strcat(soap->tmpbuf, "\""); + { + l = strlen(soap->tmpbuf); + (SOAP_SNPRINTF(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, strlen(r) + 15), "\"; start-info=\"%s", r); } - s = soap->tmpbuf; + l = strlen(soap->tmpbuf); + if (sizeof(soap->tmpbuf) > l) + soap_strcpy(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, "\""); + } + else + { + soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), s); + } + if (status == SOAP_OK && soap->version == 2 && soap->action) + { + size_t l = strlen(soap->tmpbuf); + n = strlen(soap->action); + (SOAP_SNPRINTF(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, n + 11), "; action=\"%s\"", soap->action); } +#else + soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), s); +#endif + return soap->tmpbuf; + } + return NULL; +} #endif - if (s && (err = soap->fposthdr(soap, "Content-Type", s))) + +/******************************************************************************/ + +#ifndef WITH_NOHTTP +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_puthttphdr(struct soap *soap, int status, ULONG64 count) +{ + int err = SOAP_OK; + if (soap_http_content_type(soap, status)) + { + err = soap->fposthdr(soap, "Content-Type", soap->tmpbuf); + if (err) return err; #ifdef WITH_ZLIB if ((soap->omode & SOAP_ENC_ZLIB)) @@ -14212,304 +22605,107 @@ soap_puthttphdr(struct soap *soap, int status, size_t count) #endif #ifndef WITH_LEANER if ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK) + { err = soap->fposthdr(soap, "Transfer-Encoding", "chunked"); + } else #endif - if (s) - { sprintf(soap->tmpbuf, "%lu", (unsigned long)count); + { + (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 20), SOAP_ULONG_FORMAT, count); err = soap->fposthdr(soap, "Content-Length", soap->tmpbuf); } if (err) return err; } - return soap->fposthdr(soap, "Connection", soap->keep_alive ? "keep-alive" : "close"); -} -#endif -#endif - -/******************************************************************************/ -#ifndef WITH_NOHTTP -#ifndef PALM_1 -static int -http_get(struct soap *soap) -{ return SOAP_GET_METHOD; -} -#endif -#endif - -/******************************************************************************/ -#ifndef WITH_NOHTTP -#ifndef PALM_1 -static int -http_405(struct soap *soap) -{ return 405; -} -#endif -#endif - -/******************************************************************************/ -#ifndef WITH_NOHTTP -#ifndef PALM_1 -static int -http_post(struct soap *soap, const char *endpoint, const char *host, int port, const char *path, const char *action, size_t count) -{ const char *s; - int err; - if (soap->status == SOAP_GET) - s = "GET"; - else - s = "POST"; -#ifdef PALM - if (!endpoint || (soap_tag_cmp(endpoint, "http:*") && soap_tag_cmp(endpoint, "https:*") && strncmp(endpoint, "httpg:", 6)) && strncmp(endpoint, "_beam:", 6) && strncmp(endpoint, "_local:", 7) && strncmp(endpoint, "_btobex:", 8)) -#else - 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; - if (soap->proxy_host && soap_tag_cmp(endpoint, "https:*")) - sprintf(soap->tmpbuf, "%s %s HTTP/%s", s, endpoint, soap->http_version); - else - sprintf(soap->tmpbuf, "%s /%s HTTP/%s", s, (*path == '/' ? path + 1 : path), soap->http_version); - if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) - return err; -#ifdef WITH_OPENSSL - if ((soap->ssl && soap->port != 443) || (!soap->ssl && soap->port != 80)) - sprintf(soap->tmpbuf, "%s:%d", host, port); - else - strcpy(soap->tmpbuf, host); -#else - if (port != 80) - sprintf(soap->tmpbuf, "%s:%d", host, port); - else - strcpy(soap->tmpbuf, host); -#endif - if ((err = soap->fposthdr(soap, "Host", soap->tmpbuf)) - || (err = soap->fposthdr(soap, "User-Agent", "gSOAP/2.7")) - || (err = soap_puthttphdr(soap, SOAP_OK, count))) - return err; -#ifdef WITH_ZLIB -#ifdef WITH_GZIP - if ((err = soap->fposthdr(soap, "Accept-Encoding", "gzip, deflate"))) -#else - if ((err = soap->fposthdr(soap, "Accept-Encoding", "deflate"))) -#endif - return err; -#endif -#ifndef WITH_LEAN - if (soap->userid && soap->passwd && strlen(soap->userid) + strlen(soap->passwd) < 761) - { sprintf(soap->tmpbuf + 262, "%s:%s", soap->userid, soap->passwd); - strcpy(soap->tmpbuf, "Basic "); - 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) - { sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd); - strcpy(soap->tmpbuf, "Basic "); - 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; - } -#endif -#ifdef WITH_COOKIES -#ifdef WITH_OPENSSL - if (soap_putcookies(soap, host, path, soap->ssl != NULL)) - return soap->error; -#else - if (soap_putcookies(soap, host, path, 0)) - return soap->error; -#endif -#endif - if (soap->status != SOAP_GET && (soap->version == 1 || (action && *action))) - { sprintf(soap->tmpbuf, "\"%s\"", action && strlen(action) < sizeof(soap->tmpbuf) - 3 ? action : SOAP_STR_EOS); - if ((err = soap->fposthdr(soap, "SOAPAction", soap->tmpbuf))) - return err; - } - return soap->fposthdr(soap, NULL, NULL); -} -#endif -#endif - -/******************************************************************************/ -#ifndef WITH_NOHTTP -#ifndef PALM_1 -static int -http_send_header(struct soap *soap, const char *s) -{ const char *t; - do - { t = strchr(s, '\n'); /* disallow \n in HTTP headers */ - if (!t) - t = s + strlen(s); - if (soap_send_raw(soap, s, t - s)) - return soap->error; - s = t + 1; - } while (*t); - return SOAP_OK; -} -#endif -#endif - -/******************************************************************************/ -#ifndef WITH_NOHTTP -#ifndef PALM_1 -static int -http_post_header(struct soap *soap, const char *key, const char *val) -{ if (key) - { if (http_send_header(soap, key)) - return soap->error; - if (val && (soap_send_raw(soap, ": ", 2) || http_send_header(soap, val))) - return soap->error; - } - return soap_send_raw(soap, "\r\n", 2); -} -#endif -#endif - -/******************************************************************************/ -#ifndef WITH_NOHTTP -#ifndef PALM_1 -static int -http_response(struct soap *soap, int status, size_t count) -{ int err; -#ifdef WMW_RPM_IO - if (soap->rpmreqid) - httpOutputEnable(soap->rpmreqid); -#endif - if (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 */ -#else - 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; + if (soap->http_extra_header) + { + const char *header = soap->http_extra_header; + soap->http_extra_header = NULL; /* use http_extra_header once (assign new value before each call) */ + while (*header) + { + const char *s = strchr(header, ':'); + const char *t = strchr(header, '\n'); + if (t == NULL) + t = header + strlen(header); + if (s != NULL && s < t && t < header + sizeof(soap->tmpbuf)) + { + while (s < t && isspace(*(t - 1))) + --t; + soap_strncpy(soap->tmpbuf, sizeof(soap->tmpbuf), header, t - header); + soap->tmpbuf[s - header] = '\0'; + while (s < t && isspace(*++s)) + continue; + err = soap->fposthdr(soap, soap->tmpbuf, soap->tmpbuf + (s - header)); + if (err) + return err; + } + while (isspace(*t)) + ++t; + header = t; } -#endif } - else - { const char *s = *soap_faultcode(soap); - if (status >= SOAP_GET_METHOD && status <= SOAP_HTTP_METHOD) - s = "405 Method Not Allowed"; - else if (soap->version == 2 && (!s || !strcmp(s, "SOAP-ENV:Sender"))) - s = "400 Bad Request"; - 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 */ -#else - if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application */ -#endif - { sprintf(soap->tmpbuf, "HTTP/%s %s", soap->http_version, s); - if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) + if (soap->keep_alive) + { + if (soap->keep_alive > 0 && soap->recv_timeout) + { + int t = soap->recv_timeout; + if (t < 0) + t = 1; + (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 20), "timeout=%d, max=%d", soap->recv_timeout, soap->keep_alive); + err = soap->fposthdr(soap, "Keep-Alive", soap->tmpbuf); + if (err) return err; } - else if ((err = soap->fposthdr(soap, "Status", s))) /* CGI */ - return err; + return soap->fposthdr(soap, "Connection", "keep-alive"); } - if ((err = soap->fposthdr(soap, "Server", "gSOAP/2.7")) - || (err = soap_puthttphdr(soap, status, count))) - return err; -#ifdef WITH_COOKIES - if (soap_putsetcookies(soap)) - return soap->error; -#endif - return soap->fposthdr(soap, NULL, NULL); + return soap->fposthdr(soap, "Connection", "close"); } #endif -#endif /******************************************************************************/ -#ifndef PALM_1 -SOAP_FMAC1 -int -SOAP_FMAC2 -soap_response(struct soap *soap, int status) -{ size_t count; - if (!(soap->omode & (SOAP_ENC_XML | SOAP_IO_STORE /* this tests for chunking too */)) - && (status == SOAP_HTML || status == SOAP_FILE)) - soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE; - soap->status = status; - count = soap_count_attachments(soap); - if (soap_begin_send(soap)) - return soap->error; -#ifndef WITH_NOHTTP - if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML)) - { int n = soap->mode; - soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB); - if ((n & SOAP_IO) != SOAP_IO_FLUSH) - soap->mode |= SOAP_IO_BUFFER; - if ((soap->error = soap->fresponse(soap, status, count))) - return soap->error; -#ifndef WITH_LEANER - if ((n & SOAP_IO) == SOAP_IO_CHUNK) - { if (soap_flush(soap)) - return soap->error; - } -#endif - soap->mode = n; - } -#endif - return SOAP_OK; -} -#endif -/******************************************************************************/ #ifndef WITH_LEAN static const char* soap_set_validation_fault(struct soap *soap, const char *s, const char *t) -{ if (*soap->tag) - sprintf(soap->msgbuf, "Validation constraint violation: %s%s in element '%s'", s, t?t:SOAP_STR_EOS, soap->tag); +{ + if (!t) + t = SOAP_STR_EOS; + if (*soap->tag) + (SOAP_SNPRINTF(soap->msgbuf, sizeof(soap->msgbuf), strlen(s) + strlen(t) + strlen(soap->tag) + 47), "Validation constraint violation: %s%s in element '%s'", s, t, soap->tag); else - sprintf(soap->msgbuf, "Validation constraint violation: %s%s", s, t?t:SOAP_STR_EOS); + (SOAP_SNPRINTF(soap->msgbuf, sizeof(soap->msgbuf), strlen(s) + strlen(t) + 33), "Validation constraint violation: %s%s", s, t); return soap->msgbuf; } #endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 void SOAP_FMAC2 soap_set_fault(struct soap *soap) -{ const char **c = soap_faultcode(soap); - const char **s = soap_faultstring(soap); +{ + const char **c; + const char **s; + if (soap->version == 0) + soap_version(soap); + c = soap_faultcode(soap); + s = soap_faultstring(soap); if (soap->fseterror) soap->fseterror(soap, c, s); if (!*c) - { if (soap->version == 2) + { + if (soap->version == 2) *c = "SOAP-ENV:Sender"; - else + else if (soap->version == 1) *c = "SOAP-ENV:Client"; + else + *c = ""; } if (*s) return; + if (soap->error >= SOAP_POST) + soap->error = SOAP_HTTP_METHOD; switch (soap->error) { #ifndef WITH_LEAN @@ -14523,17 +22719,30 @@ soap_set_fault(struct soap *soap) *s = soap_set_validation_fault(soap, "tag name or namespace mismatch", NULL); break; case SOAP_TYPE: - *s = soap_set_validation_fault(soap, "data type mismatch ", soap->type); + if (*soap->type) + *s = soap_set_validation_fault(soap, "type mismatch ", soap->type); + else if (*soap->arrayType) + *s = soap_set_validation_fault(soap, "array type mismatch", NULL); + else + *s = soap_set_validation_fault(soap, "invalid value", NULL); break; case SOAP_SYNTAX_ERROR: - *s = "Well-formedness violation"; + *s = soap_set_validation_fault(soap, "syntax error", NULL); break; case SOAP_NO_TAG: - *s = "No XML element tag"; + if (soap->version == 0 && soap->level == 0) + *s = soap_set_validation_fault(soap, "root element expected", NULL); + else if (soap->level == 0) + *s = soap_set_validation_fault(soap, "SOAP message expected", NULL); + else + *s = soap_set_validation_fault(soap, "element tag expected", NULL); + break; + case SOAP_END_TAG: + *s = soap_set_validation_fault(soap, "closing tag expected", NULL); break; case SOAP_MUSTUNDERSTAND: *c = "SOAP-ENV:MustUnderstand"; - sprintf(soap->msgbuf, "The data in element '%s' must be understood but cannot be handled", soap->tag); + (SOAP_SNPRINTF(soap->msgbuf, sizeof(soap->msgbuf), strlen(soap->tag) + 65), "The data in element '%s' must be understood but cannot be processed", soap->tag); *s = soap->msgbuf; break; case SOAP_VERSIONMISMATCH: @@ -14548,13 +22757,10 @@ soap_set_fault(struct soap *soap) *s = soap_set_validation_fault(soap, "namespace error", NULL); break; case SOAP_USER_ERROR: - *s = "User error"; - break; - case SOAP_FATAL_ERROR: - *s = "Fatal error"; + *s = "User data access error"; break; case SOAP_NO_METHOD: - sprintf(soap->msgbuf, "Method '%s' not implemented: method name or namespace not recognized", soap->tag); + (SOAP_SNPRINTF(soap->msgbuf, sizeof(soap->msgbuf), strlen(soap->tag) + 66), "Method '%s' not implemented: method name or namespace not recognized", soap->tag); *s = soap->msgbuf; break; case SOAP_NO_DATA: @@ -14566,11 +22772,14 @@ soap_set_fault(struct soap *soap) case SOAP_PUT_METHOD: *s = "HTTP PUT method not implemented"; break; - case SOAP_HEAD_METHOD: - *s = "HTTP HEAD method not implemented"; + case SOAP_PATCH_METHOD: + *s = "HTTP PATCH method not implemented"; + break; + case SOAP_DEL_METHOD: + *s = "HTTP DELETE method not implemented"; break; case SOAP_HTTP_METHOD: - *s = "HTTP method not implemented"; + *s = "HTTP method error"; break; case SOAP_EOM: *s = "Out of memory"; @@ -14588,7 +22797,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 of 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; @@ -14598,7 +22807,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; @@ -14613,9 +22822,12 @@ soap_set_fault(struct soap *soap) case SOAP_HTTP_ERROR: *s = "An HTTP processing error occurred"; break; + case SOAP_NTLM_ERROR: + *s = "An HTTP NTLM authentication error occurred"; + break; case SOAP_SSL_ERROR: -#ifdef WITH_OPENSSL - *s = "SSL error"; +#if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) || defined(WITH_WOLFSSL) || defined(WITH_SYSTEMSSL) + *s = "SSL/TLS error"; #else *s = "OpenSSL not installed: recompile with -DWITH_OPENSSL"; #endif @@ -14624,7 +22836,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 currently set to " SOAP_XSTRINGIFY(SOAP_MAXDIMESIZE); break; case SOAP_DIME_HREF: *s = "DIME href to missing attachment"; @@ -14646,7 +22858,7 @@ soap_set_fault(struct soap *soap) break; case SOAP_ZLIB_ERROR: #ifdef WITH_ZLIB - sprintf(soap->msgbuf, "Zlib/gzip error: '%s'", soap->d_stream->msg?soap->d_stream->msg:SOAP_STR_EOS); + (SOAP_SNPRINTF(soap->msgbuf, sizeof(soap->msgbuf), (soap->d_stream && soap->d_stream->msg ? strlen(soap->d_stream->msg) : 0) + 19), "Zlib/gzip error: '%s'", soap->d_stream && soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS); *s = soap->msgbuf; #else *s = "Zlib/gzip not installed for (de)compression: recompile with -DWITH_GZIP"; @@ -14658,198 +22870,351 @@ soap_set_fault(struct soap *soap) case SOAP_PROHIBITED: *s = soap_set_validation_fault(soap, "prohibited attribute present", NULL); break; + case SOAP_LEVEL: + *s = "Maximum XML nesting depth level exceeded: increase maxlevel"; + break; + case SOAP_LENGTH: + *s = soap_set_validation_fault(soap, "value range or content length violation", NULL); + break; case SOAP_OCCURS: - *s = soap_set_validation_fault(soap, "occurrence violation", NULL); + *s = soap_set_validation_fault(soap, "occurrence constraint violation", NULL); break; - case SOAP_LENGTH: - *s = soap_set_validation_fault(soap, "content range or length violation", NULL); + case SOAP_FIXED: + *s = soap_set_validation_fault(soap, "value does not match the fixed value required", NULL); + break; + case SOAP_EMPTY: + *s = soap_set_validation_fault(soap, "empty value provided where a value is required", NULL); break; case SOAP_FD_EXCEEDED: - *s = "Maximum number of open connections was reached (no define HAVE_POLL): increase FD_SETSIZE"; + *s = "Maximum number of open connections was reached: increase FD_SETSIZE or define HAVE_POLL"; + break; + case SOAP_UTF_ERROR: + *s = "UTF content encoding error"; break; case SOAP_STOP: - *s = "Stopped: no response sent"; + *s = "Stopped: service request already handled by plugin (informative)"; break; #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); + { + (void)soap_memmove((void*)(soap->msgbuf + 25), sizeof(soap->tmpbuf) - 25, (const void*)soap->msgbuf, strlen(soap->msgbuf) + 1); + if (soap->is) +#if defined(__cplusplus) && !defined(WITH_COMPAT) + (void)soap_memcpy((void*)soap->msgbuf, sizeof(soap->msgbuf), (const void*)"End or bad std::istream: ", 25); +#else + (void)soap_memcpy((void*)soap->msgbuf, sizeof(soap->msgbuf), (const void*)"End at NUL buffer input: ", 25); +#endif + else + (void)soap_memcpy((void*)soap->msgbuf, sizeof(soap->msgbuf), (const void*)"End of file or no input: ", 25); } #endif - *s = soap->msgbuf; break; #else *s = "End of file or no input"; break; #endif + case SOAP_ERR: + *s = "An unspecified error occurred"; + break; default: #ifndef WITH_NOHTTP #ifndef WITH_LEAN - if (soap->error > 200 && soap->error < 600) - { sprintf(soap->msgbuf, "HTTP Error: %d %s", soap->error, http_error(soap, soap->error)); + if (soap->error >= 200 && soap->error < 600) + { + const char *t = http_error(soap, soap->error); + (SOAP_SNPRINTF(soap->msgbuf, sizeof(soap->msgbuf), strlen(t) + 54), "Error %d: HTTP %d %s", soap->error, soap->error, t); *s = soap->msgbuf; } else #endif #endif - { sprintf(soap->msgbuf, "Error %d", soap->error); + { + (SOAP_SNPRINTF(soap->msgbuf, sizeof(soap->msgbuf), 26), "Error %d", soap->error); *s = soap->msgbuf; } } } -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 int SOAP_FMAC2 soap_send_fault(struct soap *soap) -{ int status = soap->error; - if (status == SOAP_STOP) - return status; - DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Sending back fault struct for error code %d\n", soap->error)); - soap->keep_alive = 0; /* to terminate connection */ +{ + int status = soap->error; + if (status == SOAP_OK || status == SOAP_STOP) + return soap_closesock(soap); +#ifndef WITH_NOHTTP + if (status >= 200 && status <= 299) + return soap_send_empty_response(soap, status); +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending back fault struct for error code %d\n", soap->error)); + soap->keep_alive = 0; /* error: close connection later by disabling keep-alive here */ soap_set_fault(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; + { + int r = 1; #ifndef WITH_NOIO if (soap->fpoll && soap->fpoll(soap)) + { r = 0; + } #ifndef WITH_LEAN else if (soap_valid_socket(soap->socket)) - { r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_SND, 0); + { + r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_SND, 0); if (r > 0) - { if (!(r & SOAP_TCP_SELECT_SND) - || ((r & SOAP_TCP_SELECT_RCV) - && recv(soap->socket, soap->tmpbuf, 1, MSG_PEEK) < 0)) + { + int t; + if (!(r & SOAP_TCP_SELECT_SND) + || ((r & SOAP_TCP_SELECT_RCV) + && recv(soap->socket, (char*)&t, 1, MSG_PEEK) < 0)) r = 0; } } #endif #endif if (r > 0) - { soap->error = SOAP_OK; - soap_serializeheader(soap); - soap_serializefault(soap); - soap_begin_count(soap); - if (soap->mode & SOAP_IO_LENGTH) - { soap_envelope_begin_out(soap); - soap_putheader(soap); - soap_body_begin_out(soap); - soap_putfault(soap); - soap_body_end_out(soap); - soap_envelope_end_out(soap); - } - soap_end_count(soap); - if (soap_response(soap, status) - || soap_envelope_begin_out(soap) - || soap_putheader(soap) - || soap_body_begin_out(soap) - || soap_putfault(soap) - || soap_body_end_out(soap) - || soap_envelope_end_out(soap)) - return soap_closesock(soap); - soap_end_send(soap); + { + soap->error = SOAP_OK; + if (soap->version > 0) + { + soap->encodingStyle = NULL; /* no encodingStyle in Faults */ + soap_serializeheader(soap); + soap_serializefault(soap); + (void)soap_begin_count(soap); + if ((soap->mode & SOAP_IO_LENGTH)) + { + if (soap_envelope_begin_out(soap) + || soap_putheader(soap) + || soap_body_begin_out(soap) + || soap_putfault(soap) + || soap_body_end_out(soap) + || soap_envelope_end_out(soap)) + return soap_closesock(soap); + } + (void)soap_end_count(soap); + if (soap_response(soap, status) + || soap_envelope_begin_out(soap) + || soap_putheader(soap) + || soap_body_begin_out(soap) + || soap_putfault(soap) + || soap_body_end_out(soap) + || soap_envelope_end_out(soap) + || soap_end_send(soap)) + return soap_closesock(soap); + } + else + { + const char *s = *soap_faultstring(soap); + const char **d = soap_faultdetail(soap); + (void)soap_begin_count(soap); + if ((soap->mode & SOAP_IO_LENGTH)) + if (soap_element_begin_out(soap, "fault", 0, NULL) + || soap_outstring(soap, "reason", 0, (char*const*)&s, NULL, 0) + || (d && *d && soap_outliteral(soap, "detail", (char*const*)d, NULL)) + || soap_element_end_out(soap, "fault")) + return soap_closesock(soap); + (void)soap_end_count(soap); + if (soap_response(soap, status) + || soap_element_begin_out(soap, "fault", 0, NULL) + || soap_outstring(soap, "reason", 0, (char*const*)&s, NULL, 0) + || (d && *d && soap_outliteral(soap, "detail", (char*const*)d, NULL)) + || soap_element_end_out(soap, "fault") + || soap_end_send(soap)) + return soap_closesock(soap); + } } } soap->error = status; return soap_closesock(soap); } -#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 int SOAP_FMAC2 -soap_recv_fault(struct soap *soap) -{ int status = soap->error; - DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Receiving SOAP Fault\n")); +soap_recv_fault(struct soap *soap, int check) +{ + int status = soap->status; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Check (%d) if receiving SOAP Fault (status = %d)\n", check, status)); + if (!check) + { + /* try getfault when no tag or tag mismatched at level 2, otherwise close and return SOAP_TAG_MISMATCH or HTTP error code */ + if (soap->error != SOAP_NO_TAG && (soap->error != SOAP_TAG_MISMATCH || soap->level != 2)) + { + if (soap->error == SOAP_TAG_MISMATCH && soap->level == 0) + { + soap->error = SOAP_OK; + if (!soap_element_begin_in(soap, "fault", 0, NULL)) + { + char *s = NULL, *d = NULL; + (void)soap_instring(soap, "reason", &s, NULL, 0, 1, 0, -1, NULL); + (void)soap_inliteral(soap, "detail", &d); + if (!soap_element_end_in(soap, "fault") && !soap_end_recv(soap)) + { + *soap_faultstring(soap) = s; + if (d && *d) + *soap_faultdetail(soap) = d; + if (status) + soap->error = status; + else + soap->error = SOAP_FAULT; + soap_set_fault(soap); + return soap_closesock(soap); + } + } + soap->error = SOAP_TAG_MISMATCH; + } + if (status && (status < 200 || status > 299)) + soap->error = status; + return soap_closesock(soap); + } + } soap->error = SOAP_OK; if (soap_getfault(soap)) - { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Error: soap_get_soapfault() failed. Is this a SOAP message at all?\n")); + { + /* if check>0 and no SOAP Fault is present and no HTTP error then just return to parse request */ + if (check + && (status == 0 || (status >= 200 && status <= 299)) + && ((soap->error == SOAP_TAG_MISMATCH && soap->level <= 2) || soap->error == SOAP_NO_TAG)) + return soap->error = SOAP_OK; + /* if check=0 and empty SOAP Body and encodingStyle is NULL and no HTTP error then just return */ + if (!check + && (status == 0 || (status >= 200 && status <= 299)) + && !soap->encodingStyle + && (soap->error == SOAP_NO_TAG && soap->level <= 2)) + return soap->error = SOAP_OK; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error: soap_get_soapfault() failed with error %d at level %u tag '%s'\n", soap->error, soap->level, soap->tag)); *soap_faultcode(soap) = (soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client"); - soap->error = status; + if (status) + soap->error = status; + else + soap->error = status = SOAP_NO_DATA; soap_set_fault(soap); } else - { const char *s = *soap_faultcode(soap); - if (!soap_match_tag(soap, s, "SOAP-ENV:Server") || !soap_match_tag(soap, s, "SOAP-ENV:Receiver")) + { + const char *s = *soap_faultcode(soap); + if (!soap_match_tag(soap, s, "SOAP-ENV:Server") + || !soap_match_tag(soap, s, "SOAP-ENV:Receiver")) + { status = SOAP_SVR_FAULT; - else if (!soap_match_tag(soap, s, "SOAP-ENV:Client") || !soap_match_tag(soap, s, "SOAP-ENV:Sender")) + } + else if (!soap_match_tag(soap, s, "SOAP-ENV:Client") + || !soap_match_tag(soap, s, "SOAP-ENV:Sender")) + { status = SOAP_CLI_FAULT; + } else if (!soap_match_tag(soap, s, "SOAP-ENV:MustUnderstand")) + { status = SOAP_MUSTUNDERSTAND; + } else if (!soap_match_tag(soap, s, "SOAP-ENV:VersionMismatch")) + { status = SOAP_VERSIONMISMATCH; + } else - { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Fault code %s\n", s)); + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Received SOAP Fault code %s\n", s)); status = SOAP_FAULT; } - if (soap_body_end_in(soap) - || soap_envelope_end_in(soap) - || soap_end_recv(soap)) - return soap_closesock(soap); - soap->error = status; + if (!soap_body_end_in(soap)) + soap_envelope_end_in(soap); } + (void)soap_end_recv(soap); + soap->error = status; return soap_closesock(soap); } -#endif /******************************************************************************/ + #ifndef WITH_NOHTTP -#ifndef PALM_1 SOAP_FMAC1 int SOAP_FMAC2 soap_send_empty_response(struct soap *soap, int httpstatuscode) -{ soap_mode m = soap->omode; - 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->omode = m; - return soap_closesock(soap); +{ + soap_mode m = soap->omode; + if (!(m & SOAP_IO_UDP)) + { + soap->count = 0; + if ((m & SOAP_IO) == SOAP_IO_CHUNK) + soap->omode = (m & ~SOAP_IO) | SOAP_IO_BUFFER; + (void)soap_response(soap, httpstatuscode); + (void)soap_end_send(soap); /* force end of sends */ + soap->error = SOAP_STOP; /* stops the server from returning another response */ + soap->omode = m; } - soap->omode = m; - return SOAP_OK; + return soap_closesock(soap); } #endif -#endif /******************************************************************************/ + #ifndef WITH_NOHTTP -#ifndef PALM_1 SOAP_FMAC1 int SOAP_FMAC2 soap_recv_empty_response(struct soap *soap) -{ if (!soap_begin_recv(soap)) - soap_end_recv(soap); - else if (soap->error == SOAP_NO_DATA || soap->error == 202) - soap->error = SOAP_OK; +{ + soap->error = SOAP_OK; + if (!(soap->omode & SOAP_IO_UDP) && !(soap->omode & SOAP_ENC_PLAIN)) + { + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Receiving empty response\n")); + if (soap_begin_recv(soap) == SOAP_OK) + { + if (soap_http_skip_body(soap) || soap_end_recv(soap)) + return soap_closesock(soap); + if (soap->status < SOAP_STOP) + soap->error = soap->status; + } + if (soap->error == 200 || soap->error == 201 || soap->error == 202 || soap->error == 204) + { + soap->error = SOAP_OK; + } + } +#ifndef WITH_LEANER + else if ((soap->fprepareinitrecv && (soap->error = soap->fprepareinitrecv(soap))) + || (soap->fpreparefinalrecv && (soap->error = soap->fpreparefinalrecv(soap)))) + { + return soap->error; + } +#endif return soap_closesock(soap); } #endif -#endif /******************************************************************************/ + #ifndef WITH_NOIO -#ifndef PALM_1 static const char* soap_strerror(struct soap *soap) -{ int err = soap->errnum; +{ + int err = soap->errnum; + *soap->msgbuf = '\0'; if (err) { #ifndef WIN32 +# ifdef HAVE_STRERROR_R +# if !defined(_GNU_SOURCE) || (!(~_GNU_SOURCE+1) && ((!defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)) || (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600))) + err = strerror_r(err, soap->msgbuf, sizeof(soap->msgbuf)); /* XSI-compliant */ + if (err != 0) + soap_strcpy(soap->msgbuf, sizeof(soap->msgbuf), "unknown error"); +# else + return strerror_r(err, soap->msgbuf, sizeof(soap->msgbuf)); /* GNU-specific */ +# endif +# else return strerror(err); +# endif #else #ifndef UNDER_CE DWORD len; @@ -14860,71 +23225,113 @@ soap_strerror(struct soap *soap) *soap->msgbuf = '\0'; len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, 0, (LPTSTR)soap->msgbuf, (DWORD)(sizeof(soap->msgbuf)/sizeof(TCHAR)), NULL); for (i = 0; i <= len; i++) - { if (((TCHAR*)soap->msgbuf)[i] < 0x80) + { + if (((TCHAR*)soap->msgbuf)[i] < 0x80) soap->msgbuf[i] = (char)((TCHAR*)soap->msgbuf)[i]; else soap->msgbuf[i] = '?'; } #endif - return soap->msgbuf; #endif } -#ifndef WITH_LEAN - if (soap->recv_timeout > 0) - { if (soap->send_timeout > 0) - sprintf(soap->msgbuf, "Operation interrupted or timed out after %ds send or %ds receive delay", soap->send_timeout, soap->recv_timeout); + else + { + if (soap->recv_maxlength && soap->count > soap->recv_maxlength) + { + soap_strcpy(soap->msgbuf, sizeof(soap->msgbuf), "max message length exceeded"); + } else - sprintf(soap->msgbuf, "Operation interrupted or timed out after %ds receive delay", soap->recv_timeout); - return soap->msgbuf; - } + { + int tt = soap->transfer_timeout, rt = soap->recv_timeout, st = soap->send_timeout; +#ifndef WITH_LEAN + int tu = ' ', ru = ' ', su = ' '; #endif - return "Operation interrupted or timed out"; -} + soap_strcpy(soap->msgbuf, sizeof(soap->msgbuf), "message transfer interrupted"); + if (tt | rt || st) + soap_strcpy(soap->msgbuf + 28, sizeof(soap->msgbuf) - 28, " or timed out"); +#ifndef WITH_LEAN + if (tt < 0) + { + tt = -tt; + tu = 'u'; + } + if (rt < 0) + { + rt = -rt; + ru = 'u'; + } + if (st < 0) + { + st = -st; + su = 'u'; + } + if (tt) + { + size_t l = strlen(soap->msgbuf); + (SOAP_SNPRINTF(soap->msgbuf + l, sizeof(soap->msgbuf) - l, 43), " (%d%csec max transfer time)", tt, tu); + } + if (rt) + { + size_t l = strlen(soap->msgbuf); + (SOAP_SNPRINTF(soap->msgbuf + l, sizeof(soap->msgbuf) - l, 40), " (%d%csec max recv delay)", rt, ru); + } + if (st) + { + size_t l = strlen(soap->msgbuf); + (SOAP_SNPRINTF(soap->msgbuf + l, sizeof(soap->msgbuf) - l, 40), " (%d%csec max send delay)", st, su); + } #endif + } + } + return soap->msgbuf; +} #endif /******************************************************************************/ -#ifndef PALM_2 + static int soap_set_error(struct soap *soap, const char *faultcode, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML, int soaperror) -{ *soap_faultcode(soap) = faultcode; +{ + *soap_faultcode(soap) = faultcode; if (faultsubcodeQName) *soap_faultsubcode(soap) = faultsubcodeQName; *soap_faultstring(soap) = faultstring; if (faultdetailXML && *faultdetailXML) - { const char **s = soap_faultdetail(soap); + { + const char **s = soap_faultdetail(soap); if (s) *s = faultdetailXML; } return soap->error = soaperror; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 soap_set_sender_error(struct soap *soap, const char *faultstring, const char *faultdetailXML, int soaperror) -{ return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", NULL, faultstring, faultdetailXML, soaperror); +{ + return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Sender" : soap->version == 1 ? "SOAP-ENV:Client" : "at sender", NULL, faultstring, faultdetailXML, soaperror); } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 soap_set_receiver_error(struct soap *soap, const char *faultstring, const char *faultdetailXML, int soaperror) -{ return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", NULL, faultstring, faultdetailXML, soaperror); +{ + return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : soap->version == 1 ? "SOAP-ENV:Server" : "detected", NULL, faultstring, faultdetailXML, soaperror); } -#endif /******************************************************************************/ -#ifndef PALM_2 + static int soap_copy_fault(struct soap *soap, const char *faultcode, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML) -{ char *r = NULL, *s = NULL, *t = NULL; +{ + char *r = NULL, *s = NULL, *t = NULL; + DBGFUN2("soap_copy_fault", "code=%s", faultcode ? faultcode : "(null)", "string=%s", faultstring ? faultstring : "(null)") if (faultsubcodeQName) r = soap_strdup(soap, faultsubcodeQName); if (faultstring) @@ -14933,133 +23340,158 @@ soap_copy_fault(struct soap *soap, const char *faultcode, const char *faultsubco t = soap_strdup(soap, faultdetailXML); return soap_set_error(soap, faultcode, r, s, t, SOAP_FAULT); } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 soap_sender_fault(struct soap *soap, const char *faultstring, const char *faultdetailXML) -{ return soap_sender_fault_subcode(soap, NULL, faultstring, faultdetailXML); +{ + return soap_sender_fault_subcode(soap, NULL, faultstring, faultdetailXML); } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 soap_sender_fault_subcode(struct soap *soap, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML) -{ return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", faultsubcodeQName, faultstring, faultdetailXML); +{ + return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Sender" : soap->version == 1 ? "SOAP-ENV:Client" : "at source", faultsubcodeQName, faultstring, faultdetailXML); } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 soap_receiver_fault(struct soap *soap, const char *faultstring, const char *faultdetailXML) -{ return soap_receiver_fault_subcode(soap, NULL, faultstring, faultdetailXML); +{ + return soap_receiver_fault_subcode(soap, NULL, faultstring, faultdetailXML); } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 int SOAP_FMAC2 soap_receiver_fault_subcode(struct soap *soap, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML) -{ return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", faultsubcodeQName, faultstring, faultdetailXML); +{ + return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : soap->version == 1 ? "SOAP-ENV:Server" : "is internal", faultsubcodeQName, faultstring, faultdetailXML); } -#endif /******************************************************************************/ -#ifndef PALM_2 + #ifndef WITH_NOSTDLIB SOAP_FMAC1 void SOAP_FMAC2 soap_print_fault(struct soap *soap, FILE *fd) -{ if (soap_check_state(soap)) +{ + if (soap_check_state(soap)) + { fprintf(fd, "Error: soap struct state not initialized\n"); + } else if (soap->error) - { const char *c, *v = NULL, *s, **d; - d = soap_faultcode(soap); - if (!*d) + { + const char **c, *v = NULL, *s, *d; + c = soap_faultcode(soap); + if (!*c) + { soap_set_fault(soap); - c = *d; + c = soap_faultcode(soap); + } if (soap->version == 2) - v = *soap_faultsubcode(soap); - s = *soap_faultstring(soap); - d = soap_faultdetail(soap); - fprintf(fd, "%s%d fault: %s [%s]\n\"%s\"\nDetail: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, c, v ? v : "no subcode", s ? s : "[no reason]", d && *d ? *d : "[no detail]"); + v = soap_fault_subcode(soap); + s = soap_fault_string(soap); + d = soap_fault_detail(soap); + fprintf(fd, "%s%d fault %s [%s]\n\"%s\"\nDetail: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, *c, v ? v : "no subcode", s ? s : "[no reason]", d ? d : "[no detail]"); } } #endif -#endif /******************************************************************************/ + #ifdef __cplusplus #ifndef WITH_LEAN #ifndef WITH_NOSTDLIB +#ifndef WITH_COMPAT SOAP_FMAC1 void SOAP_FMAC2 soap_stream_fault(struct soap *soap, std::ostream& os) -{ if (soap_check_state(soap)) +{ + if (soap_check_state(soap)) + { os << "Error: soap struct state not initialized\n"; + } else if (soap->error) - { const char *c, *v = NULL, *s, **d; - d = soap_faultcode(soap); - if (!*d) + { + const char **c, *v = NULL, *s, *d; + c = soap_faultcode(soap); + if (!*c) + { soap_set_fault(soap); - c = *d; + c = soap_faultcode(soap); + } if (soap->version == 2) - v = *soap_faultsubcode(soap); - s = *soap_faultstring(soap); - d = soap_faultdetail(soap); + v = soap_fault_subcode(soap); + s = soap_fault_string(soap); + d = soap_fault_detail(soap); os << (soap->version ? "SOAP 1." : "Error ") << (soap->version ? (int)soap->version : soap->error) - << " fault: " << c + << " fault " << *c << "[" << (v ? v : "no subcode") << "]" << std::endl << "\"" << (s ? s : "[no reason]") << "\"" << std::endl - << "Detail: " << (d && *d ? *d : "[no detail]") + << "Detail: " << (d ? d : "[no detail]") << std::endl; } } #endif #endif #endif +#endif /******************************************************************************/ + #ifndef WITH_LEAN #ifndef WITH_NOSTDLIB SOAP_FMAC1 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); +{ + if (soap_check_state(soap)) + { + soap_strcpy(buf, len, "Error: soap struct not initialized"); + } else if (soap->error) - { const char *c, *v = NULL, *s, **d; - d = soap_faultcode(soap); - if (!*d) + { + const char **c, *v = NULL, *s, *d; + c = soap_faultcode(soap); + if (!*c) + { soap_set_fault(soap); - c = *d; + c = soap_faultcode(soap); + } if (soap->version == 2) - v = *soap_faultsubcode(soap); - s = *soap_faultstring(soap); - d = soap_faultdetail(soap); -#ifdef WIN32 - _snprintf -#else - snprintf -#endif - (buf, len, "%s%d fault: %s [%s]\n\"%s\"\nDetail: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, c, v ? v : "no subcode", s ? s : "[no reason]", d && *d ? *d : "[no detail]"); + v = soap_fault_subcode(soap); + if (!v) + v = "no subcode"; + s = soap_fault_string(soap); + if (!s) + s = "[no reason]"; + d = soap_fault_detail(soap); + if (!d) + d = "[no detail]"; + (SOAP_SNPRINTF(buf, len, strlen(*c) + strlen(v) + strlen(s) + strlen(d) + 72), "%s%d fault %s [%s]\n\"%s\"\nDetail: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, *c, v, s, d); + } + else if (len > 0) + { + *buf = '\0'; } return buf; } @@ -15067,7 +23499,7 @@ soap_sprint_fault(struct soap *soap, char *buf, size_t len) #endif /******************************************************************************/ -#ifndef PALM_1 + #ifndef WITH_NOSTDLIB SOAP_FMAC1 void @@ -15076,8 +23508,9 @@ soap_print_fault_location(struct soap *soap, FILE *fd) { #ifndef WITH_LEAN int i, j, c1, c2; - if (soap->error && soap->bufidx <= soap->buflen && soap->buflen > 0 && soap->buflen <= SOAP_BUFLEN) - { i = (int)soap->bufidx - 1; + if (soap_check_state(soap) == SOAP_OK && soap->error && soap->error != SOAP_STOP && soap->bufidx <= soap->buflen && soap->buflen > 0 && soap->buflen <= sizeof(soap->buf)) + { + i = (int)soap->bufidx - 1; if (i <= 0) i = 0; c1 = soap->buf[i]; @@ -15091,106 +23524,188 @@ soap_print_fault_location(struct soap *soap, FILE *fd) fprintf(fd, "%s%c\n\n", soap->buf, c1); if (soap->bufidx < soap->buflen) fprintf(fd, "%s\n", soap->buf + soap->bufidx); - soap->buf[i] = c1; - soap->buf[j] = c2; + soap->buf[i] = (char)c1; + soap->buf[j] = (char)c2; } +#else + (void)soap; + (void)fd; +#endif +} #endif + +/******************************************************************************/ + +#ifdef __cplusplus +#ifndef WITH_LEAN +#ifndef WITH_NOSTDLIB +#ifndef WITH_COMPAT +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_stream_fault_location(struct soap *soap, std::ostream& os) +{ + int i, j, c1, c2; + if (soap_check_state(soap) == SOAP_OK && soap->error && soap->error != SOAP_STOP && soap->bufidx <= soap->buflen && soap->buflen > 0 && soap->buflen <= sizeof(soap->buf)) + { + i = (int)soap->bufidx - 1; + if (i <= 0) + i = 0; + c1 = soap->buf[i]; + soap->buf[i] = '\0'; + if ((int)soap->buflen >= i + 1024) + j = i + 1023; + else + j = (int)soap->buflen - 1; + c2 = soap->buf[j]; + soap->buf[j] = '\0'; + os << soap->buf << (char)c1 << std::endl << "" << std::endl; + if (soap->bufidx < soap->buflen) + os << soap->buf + soap->bufidx << std::endl; + soap->buf[i] = (char)c1; + soap->buf[j] = (char)c2; + } } #endif #endif +#endif +#endif /******************************************************************************/ -#ifndef PALM_1 + SOAP_FMAC1 int SOAP_FMAC2 soap_register_plugin_arg(struct soap *soap, int (*fcreate)(struct soap*, struct soap_plugin*, void*), void *arg) -{ struct soap_plugin *p; - int r; - if (!(p = (struct soap_plugin*)SOAP_MALLOC(soap, sizeof(struct soap_plugin)))) +{ + struct soap_plugin *p; + int err; + p = (struct soap_plugin*)SOAP_MALLOC(soap, sizeof(struct soap_plugin)); + if (!p) return soap->error = SOAP_EOM; p->id = NULL; p->data = NULL; p->fcopy = NULL; p->fdelete = NULL; - r = fcreate(soap, p, arg); - if (!r && p->fdelete) - { p->next = soap->plugins; - soap->plugins = p; - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Registered '%s' plugin\n", p->id)); + err = fcreate(soap, p, arg); + if (!err && p->fdelete && p->id) + { + if (!soap_lookup_plugin(soap, p->id)) + { + p->next = soap->plugins; + soap->plugins = p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Registered '%s' plugin\n", p->id)); + return SOAP_OK; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not register plugin '%s': plugin with the same ID already registered\n", p->id)); + p->fdelete(soap, p); + SOAP_FREE(soap, p); return SOAP_OK; } - DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not plugin '%s': plugin returned error %d (or fdelete callback not set)\n", p->id?p->id:"?", r)); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not register plugin '%s': plugin returned error %d or plugin ID not set or fdelete callback not set\n", p->id ? p->id : "plugin ID not set", err)); SOAP_FREE(soap, p); - return r; + soap->error = err ? err : SOAP_PLUGIN_ERROR; + return soap->error; } -#endif /******************************************************************************/ -#ifndef PALM_1 + static void * fplugin(struct soap *soap, const char *id) -{ struct soap_plugin *p; +{ + struct soap_plugin *p; for (p = soap->plugins; p; p = p->next) if (p->id == id || !strcmp(p->id, id)) return p->data; return NULL; } -#endif /******************************************************************************/ -#ifndef PALM_2 + SOAP_FMAC1 void * SOAP_FMAC2 soap_lookup_plugin(struct soap *soap, const char *id) -{ return soap->fplugin(soap, id); +{ + return soap->fplugin(soap, id); } -#endif /******************************************************************************/ + #ifdef __cplusplus } #endif /******************************************************************************\ * - * C++ soap struct methods + * C++ soap struct methods * \******************************************************************************/ #ifdef __cplusplus soap::soap() -{ soap_init(this); +{ + soap_init(this); + /* no logs to prevent DEBUG mode leaks when the user calls a soap_init() on this context */ + soap_set_test_logfile(this, NULL); + soap_set_sent_logfile(this, NULL); + soap_set_recv_logfile(this, NULL); } #endif /******************************************************************************/ + #ifdef __cplusplus soap::soap(soap_mode m) -{ soap_init1(this, m); +{ + soap_init1(this, m); } #endif /******************************************************************************/ + #ifdef __cplusplus soap::soap(soap_mode im, soap_mode om) -{ soap_init2(this, im, om); +{ + soap_init2(this, im, om); } #endif /******************************************************************************/ + #ifdef __cplusplus soap::soap(const struct soap& soap) -{ soap_copy_context(this, &soap); +{ + soap_copy_context(this, &soap); } #endif /******************************************************************************/ + #ifdef __cplusplus -soap::~soap() -{ soap_destroy(this); +struct soap& soap::operator=(const struct soap& soap) +{ + soap_done(this); + soap_copy_context(this, &soap); + return *this; +} +#endif + +/******************************************************************************/ + +#ifdef __cplusplus +void soap::destroy() +{ + soap_destroy(this); soap_end(this); +} +#endif + +/******************************************************************************/ + +#ifdef __cplusplus +soap::~soap() +{ soap_done(this); } #endif diff --git a/dep/gsoap/stdsoap2.h b/dep/gsoap/stdsoap2.h index 8b1f92298e52..f8b89f76c943 100644 --- a/dep/gsoap/stdsoap2.h +++ b/dep/gsoap/stdsoap2.h @@ -1,17 +1,18 @@ /* - stdsoap2.h 2.7.15 + stdsoap2.h 2.8.125 - gSOAP runtime engine + gSOAP runtime engine gSOAP XML Web services tools -Copyright (C) 2000-2009, Robert van Engelen, Genivia Inc., All Rights Reserved. +Copyright (C) 2000-2024, 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. +GPL or the gSOAP public license. -------------------------------------------------------------------------------- Contributors: -Wind River Systems, Inc., for the following additions - - vxWorks compatible +Wind River Systems, Inc., for the following addition licensed under the gSOAP +public license: + - vxWorks compatible, enabled with compiler option -DVXWORKS -------------------------------------------------------------------------------- gSOAP public license. @@ -24,7 +25,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-2009, Robert van Engelen, Genivia Inc., All Rights Reserved. +Copyright (C) 2000-2024, Robert van Engelen, Genivia Inc., All Rights Reserved. -------------------------------------------------------------------------------- GPL license. @@ -51,8 +52,10 @@ A commercial use license is available from Genivia, Inc., contact@genivia.com -------------------------------------------------------------------------------- */ +#define GSOAP_VERSION 208135 + #ifdef WITH_SOAPDEFS_H -# include "soapdefs.h" /* include user-defined stuff */ +# include "soapdefs.h" /* include user-defined stuff in soapdefs.h */ #endif #ifndef _THREAD_SAFE @@ -65,43 +68,76 @@ A commercial use license is available from Genivia, Inc., contact@genivia.com # endif #endif -#ifndef SOAP_FMAC1 /* stdsoap2.h declaration macro */ +#ifdef _WIN32 +# ifndef WIN32 +# define WIN32 +# endif +#endif + +/* for legacy purposes we use WIN32 macro, even when WIN64 is supported */ +#ifdef _WIN64 +# ifndef WIN32 +# define WIN32 +# endif +#endif + +#ifdef WIN32 +# ifdef SOAP_STD_EXPORTS /* dllexport the API functions and classes */ +# ifndef SOAP_STD_API +# define SOAP_STD_API __declspec(dllexport) +# endif +# ifndef SOAP_CMAC +# define SOAP_CMAC SOAP_STD_API /* export soap struct and generated classes */ +# endif +# ifndef SOAP_FMAC1 +# define SOAP_FMAC1 SOAP_STD_API /* export stdsoap2.cpp API */ +# endif +# ifndef SOAP_FMAC3 +# define SOAP_FMAC3 SOAP_STD_API /* export soapC.cpp serializers API */ +# endif +# ifndef SOAP_FMAC5 +# define SOAP_FMAC5 SOAP_STD_API /* export soapClient.cpp and soapServer.cpp API */ +# endif +# endif +#endif + +#ifndef SOAP_FMAC1 /* stdsoap2.h declaration macro */ # define SOAP_FMAC1 #endif -#ifndef SOAP_FMAC2 /* stdsoap2.h declaration macro */ +#ifndef SOAP_FMAC2 /* stdsoap2.h declaration macro */ # define SOAP_FMAC2 #endif -#ifndef SOAP_FMAC3 /* (de)serializer declaration macro */ +#ifndef SOAP_FMAC3 /* (de)serializer declaration macro */ # define SOAP_FMAC3 #endif -#ifndef SOAP_FMAC3S /* string converter for (de)serializer declaration macro */ +#ifndef SOAP_FMAC3S /* string converter for (de)serializer declaration macro */ # define SOAP_FMAC3S SOAP_FMAC3 #endif -#ifndef SOAP_FMAC4 /* (de)serializer declaration macro */ +#ifndef SOAP_FMAC4 /* (de)serializer declaration macro */ # define SOAP_FMAC4 #endif -#ifndef SOAP_FMAC4S /* string converter for (de)serializer declaration macro */ +#ifndef SOAP_FMAC4S /* string converter for (de)serializer declaration macro */ # define SOAP_FMAC4S SOAP_FMAC4 #endif -#ifndef SOAP_FMAC5 /* stub/skeleton declaration macro */ +#ifndef SOAP_FMAC5 /* stub/skeleton declaration macro */ # define SOAP_FMAC5 #endif -#ifndef SOAP_FMAC6 /* stub/skeleton declaration macro */ +#ifndef SOAP_FMAC6 /* stub/skeleton declaration macro */ # define SOAP_FMAC6 #endif -#ifndef SOAP_CMAC /* class declaration macro */ +#ifndef SOAP_CMAC /* class declaration macro */ # define SOAP_CMAC #endif -#ifndef SOAP_NMAC /* namespace table declaration macro */ +#ifndef SOAP_NMAC /* namespace table declaration macro */ # define SOAP_NMAC #endif @@ -109,47 +145,22 @@ A commercial use license is available from Genivia, Inc., contact@genivia.com # define SOAP_SOURCE_STAMP(str) #endif -/* gSOAP 2.7.4 and higher: fast look-aside buffering is stable */ -#ifndef WITH_FAST -# define WITH_FAST -#endif - -/* gSOAP 2.7.15 and higher: always retain CDATA in literal XML, unless WITH_LEAN or WITH_NOCDATA */ -#ifndef WITH_LEAN -# ifndef WITH_NOCDATA -# ifndef WITH_CDATA -# define WITH_CDATA -# endif -# endif -#endif +#ifndef STDSOAP_H +#define STDSOAP_H -#ifdef WITH_LEANER -# ifndef WITH_LEAN -# define WITH_LEAN -# endif -#endif +#define SOAP_XSTRINGIFY(s) SOAP_STRINGIFY(s) +#define SOAP_STRINGIFY(s) #s -#ifdef WITH_LEAN -# ifdef WITH_COOKIES -# error "Cannot build WITH_LEAN code WITH_COOKIES enabled" -# endif +#if defined(SOAPDEFS_H) && !defined(WITH_SOAPDEFS_H) +# include SOAP_XSTRINGIFY(SOAPDEFS_H) /* include user-defined "SOAPDEFS_H" */ #endif -#ifndef STDSOAP_H -#define STDSOAP_H - #if defined(__vxworks) || defined(__VXWORKS__) # ifndef VXWORKS # define VXWORKS # endif #endif -#ifdef _WIN32 -# ifndef WIN32 -# define WIN32 -# endif -#endif - #ifdef _WIN32_WCE # ifndef UNDER_CE # define UNDER_CE _WIN32_WCE @@ -163,14 +174,22 @@ A commercial use license is available from Genivia, Inc., contact@genivia.com #endif #ifdef __BORLANDC__ -# ifdef __WIN32__ -# ifndef WIN32 -# define WIN32 +# ifdef __clang__ +# ifdef _WIN32 +# ifndef WIN32 +# define WIN32 +# endif +# endif +# else +# ifdef __WIN32__ +# ifndef WIN32 +# define WIN32 +# endif # endif # endif #endif -#ifdef __CYGWIN__ +#if defined(__CYGWIN__) || defined(__CYGWIN32__) # ifndef CYGWIN # define CYGWIN # endif @@ -181,12 +200,6 @@ A commercial use license is available from Genivia, Inc., contact@genivia.com # undef WIN32 #endif -#if defined(__palmos__) || defined(PALM_GCC) || defined(__PALMOS_TRAPS__) -# ifndef PALM -# define PALM -# endif -#endif - #if defined(__hpux) # ifndef HP_UX # define HP_UX @@ -205,38 +218,27 @@ A commercial use license is available from Genivia, Inc., contact@genivia.com # endif #endif +#if defined(__sun) && defined(__SVR4) +# ifndef SUN_OS +# define SUN_OS +# endif +#endif + #ifdef HAVE_CONFIG_H # include "config.h" -# if defined(WITH_OPENSSL) -# ifndef HAVE_OPENSSL_SSL_H -# undef WITH_OPENSSL -# endif -# endif -# if defined(WITH_ZLIB) || defined(WITH_GZIP) -# ifndef HAVE_ZLIB_H -# undef WITH_ZLIB -# undef WITH_GZIP -# endif -# endif #else # if defined(UNDER_CE) -# define WITH_LEAN -# define HAVE_SSCANF -# elif defined(WIN32) -# define HAVE_STRRCHR -# define HAVE_STRTOD +# define SOAP_BUFLEN (2048) +# define SOAP_PTRHASH (32) +# define SOAP_IDHASH (19) +# define SOAP_BLKLEN (32) +# define SOAP_TAGLEN (256) +# define SOAP_HDRLEN (1024) +# define SOAP_MAXDIMS (4) # define HAVE_SSCANF -# define HAVE_STRTOL -# define HAVE_STRTOUL -# define HAVE_SYS_TIMEB_H -# define HAVE_FTIME -# define HAVE_GMTIME -# define HAVE_WCTOMB -# define HAVE_MBTOWC -# define SOAP_LONG_FORMAT "%I64d" -# define SOAP_ULONG_FORMAT "%I64u" # elif defined(CYGWIN) # define HAVE_POLL +# define HAVE_SNPRINTF # define HAVE_STRRCHR # define HAVE_STRTOD # define HAVE_SSCANF @@ -246,68 +248,141 @@ A commercial use license is available from Genivia, Inc., contact@genivia.com # define HAVE_FTIME # define HAVE_RAND_R # define HAVE_GMTIME_R +# define HAVE_ASCTIME_R # define HAVE_LOCALTIME_R -# define HAVE_WCTOMB -# define HAVE_MBTOWC +# define HAVE_STRERROR_R +# define HAVE_INTTYPES_H +# define HAVE_LOCALE_H +# define HAVE_SOCKLEN_T +# elif defined(WIN32) +# ifdef __BORLANDC__ +# ifdef __clang__ +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOD_L +# define HAVE_STRTOL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_GMTIME +# define SOAP_LONG_FORMAT "%lld" +# define SOAP_ULONG_FORMAT "%llu" +# else +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOD_L +# define HAVE_STRTOL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_GMTIME +# define SOAP_LONG_FORMAT "%I64d" +# define SOAP_ULONG_FORMAT "%I64u" +# endif +# else +# if _MSC_VER >= 1400 +# define HAVE_SNPRINTF +# endif +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOD_L +# define HAVE_STRTOL +# define HAVE_STRTOUL +# if _MSC_VER >= 1300 +# define HAVE_STRTOLL /* use _strtoi64 */ +# define HAVE_STRTOULL /* use _strtoui64 */ +# endif +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_GMTIME +# define SOAP_LONG_FORMAT "%I64d" +# define SOAP_ULONG_FORMAT "%I64u" +# define HAVE_LOCALE_H +# endif # elif defined(__APPLE__) # define HAVE_POLL +# define HAVE_SNPRINTF +# define HAVE_STRLCPY # define HAVE_STRRCHR # define HAVE_STRTOD # define HAVE_SSCANF # define HAVE_STRTOD_L # define HAVE_SSCANF_L -# define HAVE_SPRINTF_L # define HAVE_STRTOL # define HAVE_STRTOUL +# define HAVE_STRTOLL +# define HAVE_STRTOULL # define HAVE_RAND_R # define HAVE_GMTIME_R +# define HAVE_ASCTIME_R +# define HAVE_TM_GMTOFF +# define HAVE_GETTIMEOFDAY # define HAVE_LOCALTIME_R +# define HAVE_STRERROR_R # define HAVE_TIMEGM -# define HAVE_WCTOMB -# define HAVE_MBTOWC -# elif defined(_AIX43) +# define HAVE_INTTYPES_H +# define HAVE_LOCALE_H +# define HAVE_XLOCALE_H +# define HAVE_RANDOM +# define HAVE_SOCKLEN_T +# elif defined(_AIX41) +# define HAVE_SNPRINTF # define HAVE_STRRCHR # define HAVE_STRTOD # define HAVE_SSCANF # define HAVE_STRTOL # define HAVE_STRTOUL -# define HAVE_SYS_TIMEB_H -# define HAVE_FTIME -# define HAVE_RAND_R -# define HAVE_GMTIME_R -# define HAVE_LOCALTIME_R -# define HAVE_WCTOMB -# define HAVE_MBTOWC -# elif defined(_AIX41) +# define HAVE_LOCALE_H +# elif defined(_AIX) +# define HAVE_SNPRINTF # define HAVE_STRRCHR # define HAVE_STRTOD # define HAVE_SSCANF # define HAVE_STRTOL # define HAVE_STRTOUL # define HAVE_SYS_TIMEB_H -# define HAVE_WCTOMB -# define HAVE_MBTOWC +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GETHOSTBYNAME_R +# define HAVE_GMTIME_R +# define HAVE_ASCTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_LOCALE_H +# define HAVE_SOCKLEN_T # elif defined(HP_UX) +# include +# if 0 /* enable if __strtoll and __strtoull are available */ +extern intmax_t __strtoll(const char*, char**, int); +extern intmax_t __strtoull(const char*, char**, int); +# define strtoll __strtoll +# define strtoull __strtoull +# endif +# define HAVE_SNPRINTF # define HAVE_STRRCHR # define HAVE_STRTOD # define HAVE_SSCANF # define HAVE_STRTOL # define HAVE_STRTOUL +# define HAVE_STRTOLL +# define HAVE_STRTOULL # define HAVE_SYS_TIMEB_H # define HAVE_FTIME # define HAVE_RAND_R # define HAVE_GMTIME_R +# define HAVE_ASCTIME_R # define HAVE_LOCALTIME_R -# define HAVE_WCTOMB -# define HAVE_MBTOWC +# define HAVE_ISNAN +# define HAVE_LOCALE_H # elif defined(FREEBSD) || defined(__FreeBSD__) || defined(OPENBSD) # define HAVE_POLL +# define HAVE_SNPRINTF +# define HAVE_STRLCPY # define HAVE_STRRCHR # define HAVE_STRTOD # define HAVE_SSCANF # define HAVE_STRTOD_L # define HAVE_SSCANF_L -# define HAVE_SPRINTF_L # define HAVE_STRTOL # define HAVE_STRTOUL # define HAVE_STRTOLL @@ -315,12 +390,21 @@ A commercial use license is available from Genivia, Inc., contact@genivia.com # define HAVE_GETTIMEOFDAY # define HAVE_RAND_R # define HAVE_GMTIME_R +# define HAVE_ASCTIME_R # define HAVE_LOCALTIME_R -# define HAVE_WCTOMB -# define HAVE_MBTOWC +# define HAVE_STRERROR_R # define SOAP_LONG_FORMAT "%qd" # define SOAP_ULONG_FORMAT "%qu" +# define HAVE_ISNAN +# define HAVE_ISINF +# define HAVE_INTTYPES_H +# define HAVE_LOCALE_H +# define HAVE_XLOCALE_H +# define HAVE_RANDOM +# define HAVE_SOCKLEN_T # elif defined(__VMS) +# include +# define HAVE_SNPRINTF # define HAVE_STRRCHR # define HAVE_STRTOD # define HAVE_SSCANF @@ -330,77 +414,44 @@ A commercial use license is available from Genivia, Inc., contact@genivia.com # define HAVE_FTIME # define HAVE_RAND_R # define HAVE_GMTIME_R +# define HAVE_ASCTIME_R # define HAVE_LOCALTIME_R -# define HAVE_WCTOMB -# define HAVE_MBTOWC -# elif defined(__GLIBC__) || defined(__GNU__) -# define HAVE_POLL -# define HAVE_STRRCHR -# define HAVE_STRTOD -# define HAVE_SSCANF -# define HAVE_STRTOD_L -# define HAVE_SSCANF_L -# define HAVE_SPRINTF_L -# define HAVE_STRTOL -# define HAVE_STRTOUL -# define HAVE_STRTOLL -# define HAVE_STRTOULL -# define HAVE_SYS_TIMEB_H -# define HAVE_FTIME -# define HAVE_RAND_R -# define HAVE_GMTIME_R -# define HAVE_LOCALTIME_R -# define HAVE_TIMEGM -# define HAVE_WCTOMB -# define HAVE_MBTOWC -# define HAVE_ISNAN # elif defined(TRU64) +# define HAVE_SNPRINTF # define HAVE_STRRCHR # define HAVE_STRTOD # define HAVE_SSCANF # define HAVE_STRTOL # define HAVE_STRTOUL # define HAVE_GETTIMEOFDAY -# define HAVE_SYS_TIMEB_H # define HAVE_RAND_R # define HAVE_GMTIME_R +# define HAVE_ASCTIME_R # define HAVE_LOCALTIME_R # define __USE_STD_IOSTREAM -# define HAVE_WCTOMB -# define HAVE_MBTOWC # define SOAP_LONG_FORMAT "%ld" # define SOAP_ULONG_FORMAT "%lu" +# define HAVE_LOCALE_H # elif defined(MAC_CARBON) # define WITH_NOIO +# define HAVE_SNPRINTF # define HAVE_STRRCHR # define HAVE_STRTOD # define HAVE_SSCANF -# define HAVE_STRTOD_L -# define HAVE_SSCANF_L -# define HAVE_SPRINTF_L # define HAVE_STRTOL # define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H # define HAVE_FTIME # define HAVE_RAND_R # define HAVE_GETHOSTBYNAME_R # define HAVE_GMTIME_R +# define HAVE_ASCTIME_R # define HAVE_LOCALTIME_R -# define HAVE_WCTOMB -# define HAVE_MBTOWC -# elif defined(PALM) -# define WITH_LEAN -# define HAVE_STRTOD /* strtod() is defined in palmFunctions.h */ -# include /* Needs to be included before unix headers */ -# include -# define IGNORE_STDIO_STUBS -# include -# define O_NONBLOCK FNONBIO -# include -# include "palmFunctions.h" +# define HAVE_STRERROR_R # elif defined(SYMBIAN) # define WITH_LEAN # define WITH_NONAMESPACES -# define HAVE_STRTOD /* use STRTOD since sscanf doesn't seem to work */ +# define HAVE_STRTOD /* use STRTOD since sscanf doesn't seem to work */ # include # include # elif defined(VXWORKS) @@ -416,6 +467,7 @@ A commercial use license is available from Genivia, Inc., contact@genivia.com # define HAVE_LOCALTIME # define HAVE_MKTIME # elif defined(OS390) +# define HAVE_SNPRINTF # define HAVE_STRRCHR # define HAVE_STRTOD # define HAVE_SSCANF @@ -425,10 +477,11 @@ A commercial use license is available from Genivia, Inc., contact@genivia.com # define HAVE_FTIME # define HAVE_RAND_R # define HAVE_GMTIME_R +# define HAVE_ASCTIME_R # define HAVE_LOCALTIME_R -# define HAVE_WCTOMB -# define HAVE_MBTOWC +# define HAVE_SOCKLEN_T # elif defined(AS400) +# define HAVE_SNPRINTF # define HAVE_STRRCHR # define HAVE_STRTOD # define HAVE_SSCANF @@ -438,32 +491,31 @@ A commercial use license is available from Genivia, Inc., contact@genivia.com # define HAVE_FTIME # define HAVE_RAND_R # define HAVE_GMTIME_R +# define HAVE_ASCTIME_R # define HAVE_LOCALTIME_R -# define HAVE_WCTOMB -# define HAVE_MBTOWC # elif defined(__QNX__) || defined(QNX) /* QNX does not have a working version of strtof */ # undef HAVE_STRTOF # define HAVE_POLL +# define HAVE_SNPRINTF +# define HAVE_STRLCPY # define HAVE_STRRCHR # define HAVE_STRTOD # define HAVE_SSCANF # define HAVE_STRTOL # define HAVE_STRTOUL -# define HAVE_SYS_TIMEB_H -# define HAVE_FTIME +# define HAVE_STRTOLL +# define HAVE_STRTOULL +# define HAVE_GETTIMEOFDAY # define HAVE_RAND_R # define HAVE_GETHOSTBYNAME_R # define HAVE_GMTIME_R +# define HAVE_ASCTIME_R # define HAVE_LOCALTIME_R -# define HAVE_WCTOMB -# define HAVE_MBTOWC -# define LONG64 long -# define ULONG64 unsigned LONG64 -# define SOAP_LONG_FORMAT "%ld" -# define SOAP_ULONG_FORMAT "%lu" -# else -/* Default asumptions on supported functions */ +# define HAVE_STRERROR_R +# define HAVE_SOCKLEN_T +# elif defined(SUN_OS) +# define HAVE_SNPRINTF # define HAVE_STRRCHR # define HAVE_STRTOD # define HAVE_SSCANF @@ -474,20 +526,99 @@ A commercial use license is available from Genivia, Inc., contact@genivia.com # define HAVE_RAND_R # define HAVE_GETHOSTBYNAME_R # define HAVE_GMTIME_R +# define HAVE_ASCTIME_R +# define HAVE_LOCALTIME_R +# elif defined(__GLIBC__) || defined(__GNU__) || defined(__GNUC__) +# define HAVE_POLL +# define HAVE_SNPRINTF +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_STRTOLL +# define HAVE_STRTOULL +# define HAVE_GETTIMEOFDAY +# define HAVE_RAND_R +# define HAVE_GETHOSTBYNAME_R +# define HAVE_GMTIME_R +# define HAVE_ASCTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_STRERROR_R +# define HAVE_TIMEGM +# define HAVE_ISNAN +# define HAVE_ISINF +# if !defined(__GNUC__) || __GNUC__ >= 4 /* gcc 3 and earlier often refuse to compile _l functions */ +# define HAVE_STRTOD_L +# define HAVE_SSCANF_L +# define HAVE_LOCALE_H +# endif +# define HAVE_SOCKLEN_T +# else /* Default assumptions for supported library functions when not including config.h */ +# ifndef WITH_C_LOCALE +# ifndef WITH_NO_C_LOCALE +# define WITH_NO_C_LOCALE /* turn locale support off by default */ +# endif +# endif +# define HAVE_SNPRINTF +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_STRTOLL +# define HAVE_STRTOULL +# define HAVE_GETTIMEOFDAY +# define HAVE_RAND_R +# define HAVE_GETHOSTBYNAME_R +# define HAVE_GMTIME_R +# define HAVE_ASCTIME_R # define HAVE_LOCALTIME_R -# define HAVE_WCTOMB -# define HAVE_MBTOWC +# define HAVE_STRERROR_R +# define HAVE_INTTYPES_H +# define HAVE_LOCALE_H # endif #endif -/* native Win and HP-UX compilers don't like empty structs */ -#if defined(WIN32) || defined(HP_UX) -# define WITH_NOEMPTYSTRUCT +#ifdef WITH_LEANER +# ifndef WITH_LEAN +# define WITH_LEAN +# endif #endif -#ifdef HP_UX -# undef HAVE_STRTOLL -# undef HAVE_STRTOULL +/* gSOAP 2.7.15 and higher: always use FAST and retain CDATA in literal XML, unless WITH_LEAN or WITH_NOCDATA */ +#ifndef WITH_LEAN +# ifndef WITH_FAST +# define WITH_FAST +# endif +# ifndef WITH_NOCDATA +# ifndef WITH_CDATA +# define WITH_CDATA +# endif +# endif +#endif + +#if !defined(__cplusplus) +/* allowing empty struct/union in C is a GNU extension */ +# if !defined(__GNU__) && !defined(__GNUC__) +# define WITH_NOEMPTYSTRUCT +# endif +#endif + +/* silence clang's C99 variadic macro warnings */ +#ifdef __clang__ +# pragma clang diagnostic ignored "-Wvariadic-macros" +#endif + +#if defined(WITH_PURE_VIRTUAL) +# define SOAP_PURE_VIRTUAL = 0 +# define SOAP_PURE_VIRTUAL_COPY = 0 +#elif defined(WITH_DEFAULT_VIRTUAL) +# define SOAP_PURE_VIRTUAL { return SOAP_NO_METHOD; } +# define SOAP_PURE_VIRTUAL_COPY +#else +# define SOAP_PURE_VIRTUAL +# define SOAP_PURE_VIRTUAL_COPY #endif /* older OpenVMS TCP/IP stacks cannot handle 65536 bytes */ @@ -497,32 +628,133 @@ A commercial use license is available from Genivia, Inc., contact@genivia.com # endif #endif +/* small buffer, to accelerate base64 and hex binary output */ +#ifndef SOAP_BINARY_BUFLEN +# define SOAP_BINARY_BUFLEN (128) +#endif + +/* if we have locale.h then we should use it WITH_C_LOCALE enabled to avoid decimal point conversion issues */ +#ifdef HAVE_LOCALE_H +# ifndef WITH_NO_C_LOCALE +# ifndef WITH_C_LOCALE +# define WITH_C_LOCALE +# endif +# endif +#endif + +/* MinGW does not support uselocale() and xlocale.h and gettimeofday() */ +#if defined(__MINGW32__) || defined(__MINGW64__) +# if !defined(WITH_NO_C_LOCALE) +# define WITH_NO_C_LOCALE +# endif +# undef HAVE_GETTIMEOFDAY +#endif + +/* user can set WITH_NO_C_LOCALE to force removal of locale (e.g. in case of compiler errors) */ +#ifdef WITH_NO_C_LOCALE +# undef WITH_C_LOCALE +#endif + +#ifndef WITH_NOSTDLIB +# include +# include +# include +# include +# if !defined(HAVE_CONFIG_H) || defined(HAVE_CTYPE_H) +# include +# endif +# if !defined(HAVE_CONFIG_H) || defined(HAVE_LIMITS_H) +# include /* for MB_LEN_MAX strtol strtoll strtoul strtoull */ +# endif +# if !defined(HAVE_CONFIG_H) || defined(HAVE_FLOAT_H) +# include /* for INFINITY */ +# endif +# if !defined(HAVE_CONFIG_H) || defined(HAVE_MATH_H) +# include /* for isnan() and isinf() */ +# endif +#endif + +/* force inclusion of xlocale.h when WITH_INCLUDE_XLOCALE_H is defined by the user for systems that require xlocale.h */ +#ifdef WITH_INCLUDE_XLOCALE_H +# ifndef HAVE_XLOCALE_H +# define HAVE_XLOCALE_H +# endif +#endif + #ifdef WITH_C_LOCALE -# include +# include +# if defined(WIN32) && !defined(CYGWIN) +# define SOAP_LOCALE_T _locale_t +# define SOAP_LOCALE(soap) ((soap)->c_locale ? (soap)->c_locale : ((soap)->c_locale = _create_locale(LC_ALL, "C"))) +# define SOAP_FREELOCALE(soap) (void)((soap)->c_locale && (_free_locale((soap)->c_locale), ((soap)->c_locale = NULL))) +# else +# if defined(HAVE_XLOCALE_H) +# include +# endif +# define SOAP_LOCALE_T locale_t +# define SOAP_LOCALE(soap) ((soap)->c_locale ? (soap)->c_locale : ((soap)->c_locale = newlocale(LC_ALL_MASK, "C", NULL))) +# define SOAP_FREELOCALE(soap) (void)((soap)->c_locale && (freelocale((soap)->c_locale), ((soap)->c_locale = NULL))) +# if defined(CYGWIN) +# undef HAVE_STRTOF_L /* Cygwin does not support strtof_l strtod_l */ +# undef HAVE_STRTOD_L +# endif +# endif #else # undef HAVE_STRTOF_L # undef HAVE_STRTOD_L # undef HAVE_SSCANF_L -# undef HAVE_SPRINTF_L #endif -#ifndef WITH_NOSTDLIB +#ifdef TANDEM_NONSTOP /* Support for Guardian */ +# define SOAP_BUFLEN (32767) +/*# define WITH_NOSTDLIB */ /* uncommment to remove stdlib dependences */ +# define WITH_NOIO /* no IO dependences, e.g. remove TCP/IP */ +# define int32_t int +# define int64_t long long +# define LONG64 long long +# define ULONG64 unsigned long long +# define DBL_PINFTY (1.1579208923716189e77) +# undef HAVE_GMTIME_R +# undef HAVE_ASCTIME_R +# undef HAVE_LOCALTIME_R +# undef HAVE_SNPRINTF +# define SOAP_BUFLEN (32767) +# define SOAP_SOCKET short +#pragma nolist +# include +# include +# include +# include +# include +# include +# include # include -# ifndef PALM -# include -# include -# endif -# include -# include +# include +# include +# include +# define INET_ERROR 4294967295 +#pragma list +#elif defined(__TANDEM) /* Support for OSS */ +# define int32_t int +# define SOAP_BUFLEN (32767) +#endif + +#ifdef WITH_NTLM +# include #endif #ifdef HAVE_POLL # include #endif -#if defined(__cplusplus) && !defined(WITH_LEAN) && !defined(WITH_COMPAT) -# include -# include +#ifdef __cplusplus +# include +# include +# include +# ifndef WITH_COMPAT +# include +# include +# endif #endif #ifdef WITH_NOHTTP @@ -538,17 +770,17 @@ A commercial use license is available from Genivia, Inc., contact@genivia.com */ #ifndef UNDER_CE -# ifndef PALM -# ifndef WITH_NOIO -# include -# include -# endif -# ifndef WITH_LEAN -# ifdef HAVE_SYS_TIMEB_H -# include /* for ftime() */ +# ifndef WITH_NOIO +# include +# include +# endif +# ifndef WITH_LEAN +# ifdef HAVE_SYS_TIMEB_H +# ifdef HAVE_FTIME +# include /* for ftime() */ # endif -# include # endif +# include # endif #endif @@ -559,40 +791,48 @@ A commercial use license is available from Genivia, Inc., contact@genivia.com extern int h_errno; #endif -#ifndef WITH_NOIO +#ifdef HAVE_GETTIMEOFDAY # ifndef WIN32 -# ifndef PALM -# include -# ifdef VXWORKS -# include -# include -# ifndef _WRS_KERNEL -# include -# endif -# else -# ifndef SYMBIAN -# include -# endif +# ifdef VXWORKS +# ifdef _WRS_KERNEL +# include # endif -# ifdef SUN_OS -# include /* SUN */ -# include /* SUN < 2.8 (?) */ +# else +# include /* for timeval and gettimeofday() */ +# endif +# endif +#endif + +#ifndef WITH_NOIO +# ifndef WIN32 +# include +# ifdef VXWORKS +# include +# include +# ifndef _WRS_KERNEL +# include # endif -# ifdef VXWORKS -# ifdef _WRS_KERNEL -# include -# endif -# else -# include +# else +# ifndef SYMBIAN +# include # endif -# include -# ifdef OS390 -# include -# else -# include /* TCP_NODELAY */ +# endif +# ifdef SUN_OS +# include /* SUN */ +# include /* only needed with SUN < 2.8 ? */ +# endif +# ifdef VXWORKS +# ifdef _WRS_KERNEL +# include # endif -# include # endif +# include +# ifdef OS390 +# include +# else +# include /* TCP_NODELAY, TCP_FASTOPEN */ +# endif +# include # endif #endif @@ -602,23 +842,35 @@ A commercial use license is available from Genivia, Inc., contact@genivia.com # define SOAP_WINSOCKINT size_t #endif +#ifdef WIN32 +# undef WITH_SELF_PIPE +#endif + +#if defined(WITH_IPV6_V6ONLY) +# ifndef WITH_IPV6 +# define WITH_IPV6 +# endif +#endif + #ifdef WIN32 # ifndef UNDER_CE # include # include # endif +// When you get macro redefinition errors when compiling the code below, then: +// a) try arrange your includes so is included after "stdsoap2.h" +// b) or define _WINSOCKAPI_ first: +// #define _WINSOCKAPI_ // stops windows.h including winsock.h +// #include +// #include "stdsoap2.h" +// c) or compile with the -DWIN32_LEAN_AND_MEAN switch +# include // Visual Studio 2005 users: install Platform SDK (R2) +# include +// # define _WSPIAPI_COUNTOF // DEV NOTE: enble to fix problems with VC6 +// # include +# include // DEV NOTE: replaces older wspiapi.h above # ifdef WITH_IPV6 -# include /* Visual Studio 2005 users: you must install the Platform SDK (R2) */ -# include -# include # define SOAP_GAI_STRERROR gai_strerrorA -# else -# ifndef __BORLANDC__ -# include /* Visual Studio 2005 users: you must install the Platform SDK (R2) */ -/* # include */ /* Alternative: use winsock2 (not available with eVC) */ -# else -# include /* Borland C */ -# endif # endif #else # ifdef VXWORKS @@ -627,14 +879,12 @@ A commercial use license is available from Genivia, Inc., contact@genivia.com # include # endif # ifndef WITH_NOIO -# ifndef PALM -# include -# include -# include -# include -# ifdef _AIX41 -# include -# endif +# include +# include +# include +# include +# ifdef _AIX41 +# include # endif # endif #endif @@ -644,17 +894,50 @@ A commercial use license is available from Genivia, Inc., contact@genivia.com #endif #ifdef WITH_OPENSSL +# ifdef __VMS +# pragma names save +# pragma names uppercase +# endif +# undef WITH_GNUTLS # define OPENSSL_NO_KRB5 # include # include # include # include +# include +# include +# include # include # ifndef ALLOW_OLD_VERSIONS # if (OPENSSL_VERSION_NUMBER < 0x00905100L) # error "Must use OpenSSL 0.9.6 or later" # endif # endif +# ifdef __VMS +# pragma names restore +# endif +#endif + +#ifdef WITH_GNUTLS +# include +# include +# if GNUTLS_VERSION_NUMBER < 0x020b00 +/* deprecated since GNUTLS 2.11.0 */ +# include +# endif +# ifndef HAVE_PTHREAD_H +# ifdef _POSIX_THREADS +# define HAVE_PTHREAD_H /* make GNUTLS thread safe */ +# endif +# endif +#endif + +#ifdef WITH_WOLFSSL +# include +#endif + +#ifdef WITH_SYSTEMSSL +# include #endif #ifdef WITH_GZIP @@ -664,29 +947,27 @@ A commercial use license is available from Genivia, Inc., contact@genivia.com #endif #ifdef WITH_CASEINSENSITIVETAGS -# define SOAP_STRCMP soap_tag_cmp /* case insensitve XML element/attribute names */ +# define SOAP_STRCMP soap_tag_cmp /* case insensitive XML element/attribute names */ #else -# define SOAP_STRCMP strcmp /* case sensitive XML element/attribute names */ +# define SOAP_STRCMP strcmp /* case sensitive XML element/attribute names */ #endif #ifdef WITH_ZLIB # include #endif -#ifndef WITH_NOSTDLIB -# ifndef PALM -# include /* for isnan() */ -# endif -#endif +/* #define DEBUG */ /* Uncomment to debug sending (in file SENT.log) receiving (in file RECV.log) and internal operations (in file TEST.log) */ -/* #define DEBUG */ /* Uncomment to debug sending (in file SENT.log) receiving (in file RECV.log) and messages (in file TEST.log) */ +/* #define DEBUG_STAMP */ /* Uncomment to debug sending (in file SENT.log) receiving (in file RECV.log) and time-stamped operations (in file TEST.log) */ #ifdef __cplusplus extern "C" { #endif -/* Portability: define SOAP_SOCKLEN_T */ -#if defined(_AIX) +/* Portability (X/Open, BSD sockets etc): define SOAP_SOCKLEN_T as socklen_t or int or ... */ +#if defined(HAVE_SOCKLEN_T) +# define SOAP_SOCKLEN_T socklen_t +#elif defined(_AIX) || defined(AIX) || defined(HP_UX) # if defined(_AIX43) # define SOAP_SOCKLEN_T socklen_t # else @@ -694,12 +975,19 @@ extern "C" { # endif #elif defined(SOCKLEN_T) # define SOAP_SOCKLEN_T SOCKLEN_T -#elif defined(__socklen_t_defined) || defined(_SOCKLEN_T) || defined(CYGWIN) || defined(FREEBSD) || defined(__FreeBSD__) || defined(OPENBSD) || defined(__QNX__) || defined(QNX) || defined(OS390) +#elif defined(__socklen_t_defined) || defined(_SOCKLEN_T) || defined(__ANDROID__) || !defined(_GNU_SOURCE) || (!(~_GNU_SOURCE+1) && !defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)) || _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 # define SOAP_SOCKLEN_T socklen_t -#elif defined(IRIX) || defined(WIN32) || defined(__APPLE__) || defined(HP_UX) || defined(SUN_OS) || defined(OPENSERVER) || defined(TRU64) || defined(VXWORKS) +#elif defined(IRIX) || defined(WIN32) || defined(SUN_OS) || defined(OPENSERVER) || defined(TRU64) || defined(VXWORKS) # define SOAP_SOCKLEN_T int -#else -# define SOAP_SOCKLEN_T size_t +#elif !defined(SOAP_SOCKLEN_T) +# define SOAP_SOCKLEN_T socklen_t +#endif + +/* AIX DCE threads portability: define SOAP_FUNC_R_ERR gmtime_r and localtime_r err ret val as -1 */ +#ifdef _AIX32_THREADS +# define SOAP_FUNC_R_ERR (-1) +#elif !defined(SOAP_FUNC_R_ERR) +# define SOAP_FUNC_R_ERR (NULL) #endif #ifndef SOAP_SOCKET @@ -713,7 +1001,10 @@ extern "C" { #endif #define SOAP_INVALID_SOCKET ((SOAP_SOCKET)-1) -#define soap_valid_socket(n) ((n) != SOAP_INVALID_SOCKET) +#define soap_valid_socket(sk) ((sk) != SOAP_INVALID_SOCKET) + +#define SOAP_SHUT_WR (1) +#define SOAP_SHUT_RDWR (2) #ifndef SOAP_GAI_STRERROR # define SOAP_GAI_STRERROR gai_strerror @@ -723,16 +1014,67 @@ extern "C" { # define FD_SETSIZE (1024) #endif +#ifdef WITH_LEAN +# define SOAP_CHK_EOF SOAP_EOF +#else +# define SOAP_CHK_EOF (soap->error ? soap->error : SOAP_EOF) +#endif + +#ifdef __cplusplus +# ifndef __STDC_FORMAT_MACROS +# define __STDC_FORMAT_MACROS +# endif +#endif + #if defined(SYMBIAN) +# warning "Symbian build: removing 64 bit integer support" # define LONG64 long # define ULONG64 unsigned LONG64 -#elif !defined(WIN32) || defined(CYGWIN) || defined(__GLIBC__) || defined(__GNU__) +# ifndef SOAP_LONG_FORMAT +# define SOAP_LONG_FORMAT "%ld" +# endif +# ifndef SOAP_ULONG_FORMAT +# define SOAP_ULONG_FORMAT "%lu" +# endif +#elif !defined(WIN32) || defined(CYGWIN) || defined(__GLIBC__) || defined(__GNU__) || defined(__GNUC__) # ifndef LONG64 -# if defined(HAVE_STDINT_H) +# if defined(HAVE_INTTYPES_H) +# include +# define LONG64 int64_t +# define ULONG64 uint64_t +# if defined(PRId64) && defined(PRIu64) +# ifndef SOAP_LONG_FORMAT +# define SOAP_LONG_FORMAT "%" PRId64 +# endif +# ifndef SOAP_ULONG_FORMAT +# define SOAP_ULONG_FORMAT "%" PRIu64 +# endif +# endif +# elif defined(HAVE_SYS_INTTYPES_H) +# include +# define LONG64 int64_t +# define ULONG64 uint64_t +# if defined(PRId64) && defined(PRIu64) +# ifndef SOAP_LONG_FORMAT +# define SOAP_LONG_FORMAT "%" PRId64 +# endif +# ifndef SOAP_ULONG_FORMAT +# define SOAP_ULONG_FORMAT "%" PRIu64 +# endif +# endif +# elif defined(HAVE_STDINT_H) # include # define LONG64 int64_t # define ULONG64 uint64_t -# elif defined(__GLIBC__) +# if defined(PRId64) && defined(PRIu64) +# ifndef SOAP_LONG_FORMAT +# define SOAP_LONG_FORMAT "%" PRId64 +# endif +# ifndef SOAP_ULONG_FORMAT +# define SOAP_ULONG_FORMAT "%" PRIu64 +# endif +# endif +# elif defined(CYGWIN) || defined(__GLIBC__) # include # if (__WORDSIZE == 64) # define LONG64 int64_t @@ -761,20 +1103,18 @@ extern "C" { #endif #ifndef SOAP_LONG_FORMAT -# define SOAP_LONG_FORMAT "%lld" /* printf format for 64 bit ints */ +# define SOAP_LONG_FORMAT "%lld" /* printf format for 64 bit long long ints */ #endif #ifndef SOAP_ULONG_FORMAT -# define SOAP_ULONG_FORMAT "%llu" /* printf format for unsigned 64 bit ints */ +# define SOAP_ULONG_FORMAT "%llu" /* printf format for unsigned 64 bit long long ints */ #endif #if defined(WIN32) && !defined(CYGWIN) # define soap_int32 __int32 #elif defined(SYMBIAN) # define soap_int32 long -#elif defined(PALM) -# define soap_int32 Int32 -#elif defined(_AIX) +#elif defined(_AIX) || defined(AIX) # if defined(_AIX43) # define soap_int32 int32_t # else @@ -791,11 +1131,17 @@ extern "C" { # define SOAP_EWOULDBLOCK WSAEWOULDBLOCK # define SOAP_EINPROGRESS WSAEINPROGRESS # define SOAP_EADDRINUSE WSAEADDRINUSE +# define SOAP_ECONNREFUSED WSAECONNREFUSED #else -# define SOAP_ERANGE ERANGE +# ifdef ERANGE +# define SOAP_ERANGE ERANGE +# else +# define SOAP_ERANGE (34) +# endif # define SOAP_EINTR EINTR # define SOAP_EAGAIN EAGAIN # define SOAP_EADDRINUSE EADDRINUSE +# define SOAP_ECONNREFUSED ECONNREFUSED # ifdef SYMBIAN # define SOAP_EWOULDBLOCK 9898 # define SOAP_EINPROGRESS 9899 @@ -808,28 +1154,28 @@ extern "C" { #ifdef WIN32 # ifdef UNDER_CE # define soap_errno GetLastError() -# define soap_socket_errno(s) GetLastError() +# define soap_socket_errno GetLastError() # define soap_reset_errno SetLastError(0) # else -# define soap_errno GetLastError() -# define soap_socket_errno(s) WSAGetLastError() -# define soap_reset_errno SetLastError(0) +# define soap_errno errno +# define soap_socket_errno WSAGetLastError() +# define soap_reset_errno _set_errno(0) # endif #else # ifndef WITH_NOIO # define soap_errno errno -# define soap_socket_errno(s) errno -# define soap_reset_errno (errno = 0) +# define soap_socket_errno errno +# define soap_reset_errno (errno = ENOENT) # else # define soap_errno 0 -# define soap_socket_errno(s) 0 +# define soap_socket_errno 0 # define soap_reset_errno # endif #endif #ifndef SOAP_BUFLEN -# if !defined(WITH_LEAN) || defined(WITH_UDP) -# define SOAP_BUFLEN (65536) /* buffer length for socket packets, also used by gethostbyname_r and UDP messages, so don't make this too small */ +# if !defined(WITH_LEAN) +# define SOAP_BUFLEN (65536) /* buffer length for socket packets, so don't make this too small */ # else # define SOAP_BUFLEN (2048) /* lean size */ # endif @@ -842,21 +1188,21 @@ extern "C" { #endif #ifndef SOAP_PTRHASH # ifndef WITH_LEAN -# define SOAP_PTRHASH (1024) /* size of pointer analysis hash table (must be power of 2) */ +# define SOAP_PTRHASH (4096) /* size of pointer analysis hash table (must be power of 2) */ # else # define SOAP_PTRHASH (32) # endif #endif #ifndef SOAP_IDHASH # ifndef WITH_LEAN -# define SOAP_IDHASH (1999) /* prime size of hash table for parsed id/ref */ +# define SOAP_IDHASH (1999) /* 1999, 8191: prime size of hash table for parsed id/ref */ # else -# define SOAP_IDHASH (19) /* 19, 199 */ +# define SOAP_IDHASH (19) /* 19, 199: small prime */ # endif #endif #ifndef SOAP_BLKLEN # ifndef WITH_LEAN -# define SOAP_BLKLEN (256) /* size of blocks to collect long strings and XML attributes */ +# define SOAP_BLKLEN (256) /* to collect long strings and XML attributes */ # else # define SOAP_BLKLEN (32) # endif @@ -865,79 +1211,182 @@ extern "C" { # ifndef WITH_LEAN # define SOAP_TAGLEN (1024) /* maximum length of XML element tag/attribute name or host/path name + 1 */ # else -# define SOAP_TAGLEN (64) +# define SOAP_TAGLEN (256) # endif #endif #ifndef SOAP_HDRLEN # ifndef WITH_LEAN -# define SOAP_HDRLEN (8192) /* maximum length of HTTP header line (must be >4096 to read cookies) */ +# define SOAP_HDRLEN (8192) /* maximum length of HTTP header line (must be >=4096 to read cookies) */ # else # define SOAP_HDRLEN (1024) # endif #endif +#ifndef SOAP_TMPLEN +# ifndef WITH_LEAN +# define SOAP_TMPLEN (2048) /* maximum length of msgbuf and tmpbuf short message buffers, must be >=1024 */ +# else +# define SOAP_TMPLEN (1024) +# endif +#endif #ifndef SOAP_MAXDIMS # ifndef WITH_LEAN -# define SOAP_MAXDIMS (16) /* maximum array dimensions (array nestings) must be less than 64 to protect soap->tmpbuf */ +# define SOAP_MAXDIMS (16) /* maximum array dimensions (array nestings) must be less than 64 to protect soap->tmpbuf */ # else -# define SOAP_MAXDIMS (4) +# define SOAP_MAXDIMS (4) +# endif +#endif +#ifndef SOAP_MAXPTRS +# ifndef WITH_LEAN +# define SOAP_MAXPTRS (4) /* maximum depth + 1 of id-ref deserialized pointer types (int* has depth 0, int*** has depth 2) */ +# else +# define SOAP_MAXPTRS (2) # endif #endif +#ifndef SOAP_MAXALLOCSIZE +# define SOAP_MAXALLOCSIZE (0) /* max size that malloc() can handle, zero for no limit */ +#endif + #ifndef SOAP_MAXLOGS -# define SOAP_MAXLOGS (3) /* max number of debug logs per struct soap environment */ +# define SOAP_MAXLOGS (3) /* max number of debug logs per struct soap environment */ # define SOAP_INDEX_RECV (0) # define SOAP_INDEX_SENT (1) # define SOAP_INDEX_TEST (2) #endif -/* Max iterations in soap_serve() to keep server connection alive */ +/* max HTTP chunk size is 2GB by default, can be larger but not to exceed size_t range max */ +#ifndef SOAP_MAXHTTPCHUNK +# define SOAP_MAXHTTPCHUNK (2147483647) +#endif + +/* Tag name of multiref elements in SOAP 1.1 encoding */ +#ifndef SOAP_MULTIREFTAG +# define SOAP_MULTIREFTAG "id" +#endif + +/* href-id value base name in multiref SOAP encoding */ +#ifndef SOAP_BASEREFNAME +# define SOAP_BASEREFNAME "_" +#endif + +/* Max number of EINTR interrupts to ignore while poll/select for pending activity on a socket */ +/* Each EINTR ignored may increase the I/O blocking time by at most one second */ +#ifndef SOAP_MAXEINTR +# define SOAP_MAXEINTR (10) +#endif + +/* SOAP_MAXKEEPALIVE: Max iterations in soap_serve() to keep server connection alive */ #ifndef SOAP_MAXKEEPALIVE # define SOAP_MAXKEEPALIVE (100) #endif -/* Trusted max size of inbound SOAP array for compound array allocation. - Increase if necessary to allow larger arrays. +/* SOAP_MAXARRAYSIZE: Trusted total max size of an inbound SOAP Array. + Arrays of larger size are not pre-allocated, but deserialized + on an element-by-element basis until XML validation contrains kick in. + This macro only affects the efficiency of parsing SOAP arrays. */ #ifndef SOAP_MAXARRAYSIZE -# define SOAP_MAXARRAYSIZE (1000000) +# define SOAP_MAXARRAYSIZE (100000) +#endif + +/* SOAP_MAXDIMESIZE: Trusted max size of inbound DIME data. + Increase if necessary to allow larger attachments, or decrease when server + resources are limited. This is to deny senders to allocate more than 8 MB + at the receiver without actually sending the whole message. +*/ +#ifndef SOAP_MAXDIMESIZE +# define SOAP_MAXDIMESIZE (8*1048576) /* 8 MB */ +#endif + +/* SOAP_MAXINFLATESIZE: Trusted inflated content size. + Larger content is subject to the SOAP_MINDEFLATERATIO constraint. + If SOAP_MINDEFLATERATIO is 1.0, SOAP_MAXINFLATESIZE is always the max + size of uncompressed content. +*/ +#ifndef SOAP_MAXINFLATESIZE +# define SOAP_MAXINFLATESIZE (1*1048576) /* 1 MB */ +#endif + +/* SOAP_MINDEFLATERATIO: Trusted deflation ratio after SOAP_MAXINFLATESIZE is reached. + Trust when compressed / deflated > SOAP_MINDEFLATERATIO + Sets a ratio > 0.00096899224806 (1032:1) + According to the zlib site: the limit (1032:1) comes from the fact that one + length/distance pair can represent at most 258 output bytes. A length + requires at least one bit and a distance requires at least one bit, so two + bits in can give 258 bytes out, or eight bits in give 1032 bytes out. A + dynamic block has no length restriction, so you could get arbitrarily close + to the limit of 1032:1. +*/ +#ifndef SOAP_MINDEFLATERATIO +# define SOAP_MINDEFLATERATIO (1.0/1032.0) /* ratio of deflated/inflated */ +#endif + +/* maximum XML nesting depth level allowed for inbound XML parsing, must be greater than zero (0) */ +#ifndef SOAP_MAXLEVEL +# define SOAP_MAXLEVEL (10000) +#endif + +/* maximum string content length if not already constrained by XML schema validation maxLength constraints, zero or negative means unlimited string lengths are allowed unless restricted by XML schema maxLength */ +#ifndef SOAP_MAXLENGTH +# define SOAP_MAXLENGTH (0) +#endif + +/* maximum number of array or container elements, must be greater than zero (0) */ +#ifndef SOAP_MAXOCCURS +# define SOAP_MAXOCCURS (100000) #endif #ifdef VXWORKS +# ifdef WMW_RPM_IO +# include "httpLib.h" +# endif # ifdef __INCmathh # include # ifndef HAVE_ISNAN # define HAVE_ISNAN # endif -# define soap_isnan(num) isNan(num) +# ifndef soap_isnan +# define soap_isnan(num) isNan(num) +# endif +# endif +# ifdef WM_SECURE_KEY_STORAGE +# include # endif #endif #ifdef WIN32 -# include # ifndef HAVE_ISNAN # define HAVE_ISNAN # endif -# define soap_isnan(num) _isnan(num) +# define soap_isnan(n) _isnan(n) +# ifndef HAVE_ISINF +# define HAVE_ISINF +# endif +# define soap_isinf(n) (!_finite(n)) #endif #ifdef SUN_OS -# define HAVE_ISNAN +# ifndef HAVE_ISNAN +# define HAVE_ISNAN +# endif #endif #ifdef __APPLE__ -# ifdef __cplusplus -# ifndef isnan -extern "C" int isnan(double); -# endif +# ifndef HAVE_ISNAN +# define HAVE_ISNAN +# endif +# ifndef HAVE_ISINF +# define HAVE_ISINF # endif -# define HAVE_ISNAN #endif #if !defined(HAVE_ISNAN) && (defined(_MATH_H) || defined(_MATH_INCLUDED)) # define HAVE_ISNAN #endif -extern const struct soap_double_nan { unsigned int n1, n2; } soap_double_nan; +union soap_double_nan {struct {unsigned int n1, n2;} iv; double dv; float fv;}; +extern const union soap_double_nan soap_double_nan; +extern const char soap_base64o[], soap_base64i[]; #ifdef VXWORKS # ifndef FLT_MAX @@ -949,11 +1398,13 @@ extern const struct soap_double_nan { unsigned int n1, n2; } soap_double_nan; #endif #ifndef FLT_NAN -# define FLT_NAN (*(float*)(void*)&soap_double_nan) +# define FLT_NAN (soap_double_nan.fv) #endif #ifndef FLT_PINFTY -# if defined(FLT_MAX) +# if defined(INFINITY) +# define FLT_PINFTY INFINITY +# elif defined(FLT_MAX) # define FLT_PINFTY FLT_MAX # elif defined(HUGE_VALF) # define FLT_PINFTY (float)HUGE_VALF @@ -970,99 +1421,238 @@ extern const struct soap_double_nan { unsigned int n1, n2; } soap_double_nan; # define FLT_NINFTY (-FLT_PINFTY) #endif -#ifndef DBL_NAN -# define DBL_NAN (*(double*)(void*)&soap_double_nan) +#ifndef DBL_NAN +# define DBL_NAN (soap_double_nan.dv) +#endif + +#ifndef DBL_PINFTY +# if defined(INFINITY) +# define DBL_PINFTY INFINITY +# elif defined(DBL_MAX) +# define DBL_PINFTY DBL_MAX +# elif defined(HUGE_VALF) +# define DBL_PINFTY (double)HUGE_VALF +# elif defined(HUGE_VAL) +# define DBL_PINFTY (double)HUGE_VAL +# elif defined(DOUBLE_MAX) +# define DBL_PINFTY DOUBLE_MAX +# else +# define DBL_PINFTY (1.7976931348623157e+308) +# endif +#endif + +#ifndef DBL_NINFTY +# define DBL_NINFTY (-DBL_PINFTY) +#endif + +#ifndef soap_isnan +# ifdef HAVE_ISNAN +# define soap_isnan(n) isnan(n) +# else +# define soap_isnan(n) ((n) != (n)) +# endif +#endif + +#ifndef soap_isinf +# ifdef HAVE_ISINF +# define soap_isinf(n) isinf(n) +# else +# define soap_isinf(n) (!soap_isnan(n) && soap_isnan((n) - (n))) +# endif +#endif + +#define soap_ispinfd(n) ((n) > 0 && soap_isinf(n)) +#define soap_ispinff(n) ((n) > 0 && soap_isinf(n)) +#define soap_isninfd(n) ((n) < 0 && soap_isinf(n)) +#define soap_isninff(n) ((n) < 0 && soap_isinf(n)) + +/* Safer str & mem functions */ + +/* The gSOAP code uses guards to ensure that these functions are well behaved + and do not raise errors. Therefore, the WIN _s functions should never + execute the "invalid parameter handler". +*/ + +/* use safer snprintf if possible or guard sprintf against overrun (assumes no variadic macros) */ +# ifdef HAVE_SNPRINTF +# if _MSC_VER >= 1400 +# define SOAP_SNPRINTF(buf, len, num) void)_snprintf_s((buf), (len), _TRUNCATE +# define SOAP_SNPRINTF_SAFE(buf, len) void)_snprintf_s((buf), (len), _TRUNCATE +# else +# define SOAP_SNPRINTF(buf, len, num) void)snprintf((buf), (len) +# define SOAP_SNPRINTF_SAFE(buf, len) void)snprintf((buf), (len) +# endif +# else +# define SOAP_SNPRINTF(buf, len, num) (len) <= (num)) ? (void)((buf)[0] = '\0') : (void)sprintf((buf) +# define SOAP_SNPRINTF_SAFE(buf, len) void)sprintf((buf) +# endif + +/* copy string (truncating the result, strings must not be NULL) */ +#if _MSC_VER >= 1400 +# define soap_strcpy(buf, len, src) (void)strncpy_s((buf), (len), (src), _TRUNCATE) +#elif defined(HAVE_STRLCPY) +# define soap_strcpy(buf, len, src) (void)strlcpy((buf), (src), (len)) +#else +# define soap_strcpy(buf, len, src) (void)(strncpy((buf), (src), (len)), (buf)[(len) - 1] = '\0') +#endif + +/* concat string (truncating the result, strings must not be NULL) */ +#if _MSC_VER >= 1400 +# define soap_strcat(buf, len, src) (void)strncat_s((buf), (len), (src), _TRUNCATE) +#elif defined(HAVE_STRLCAT) +# define soap_strcat(buf, len, src) (void)strlcat((buf), (src), (len)) +#else +SOAP_FMAC1 void SOAP_FMAC2 soap_strcat(char *buf, size_t len, const char *src); +#endif + +/* copy string up to num chars (sets string to empty on overrun and returns nonzero, zero if OK) */ +#if _MSC_VER >= 1400 +# define soap_strncpy(buf, len, src, num) ((buf) == NULL || ((size_t)(len) > (size_t)(num) ? strncpy_s((buf), (len), (src), (num)) : ((buf)[0] = '\0', 1))) +#else +# define soap_strncpy(buf, len, src, num) ((buf) == NULL || ((size_t)(len) > (size_t)(num) ? (strncpy((buf), (src), (num)), (buf)[(size_t)(num)] = '\0') : ((buf)[0] = '\0', 1))) #endif -#ifndef DBL_PINFTY -# if defined(DBL_MAX) -# define DBL_PINFTY DBL_MAX -# elif defined(HUGE_VALF) -# define DBL_PINFTY (double)HUGE_VALF -# elif defined(HUGE_VAL) -# define DBL_PINFTY (double)HUGE_VAL -# elif defined(DOUBLE_MAX) -# define DBL_PINFTY DOUBLE_MAX -# else -# define DBL_PINFTY (1.7976931348623157e+308) -# endif +/* concat string up to n chars (leaves destination intact on overrun and returns nonzero, zero if OK) */ +#if _MSC_VER >= 1400 +# define soap_strncat(buf, len, src, num) ((buf) == NULL || ((size_t)(len) > strlen((buf)) + (size_t)(num) ? strncat_s((buf), (len), (src), (num)) : 1)) +#else +SOAP_FMAC1 int SOAP_FMAC2 soap_strncat(char *buf, size_t len, const char *src, size_t num); #endif -#ifndef DBL_NINFTY -# define DBL_NINFTY (-DBL_PINFTY) +/* copy memory (returns SOAP_ERANGE on overrun, zero if OK, pointers must not be NULL) */ +#if _MSC_VER >= 1400 +# define soap_memcpy(buf, len, src, num) ((size_t)(len) >= (size_t)(num) ? memcpy_s((buf), (len), (src), (num)) : SOAP_ERANGE) +#else +# define soap_memcpy(buf, len, src, num) ((size_t)(len) >= (size_t)(num) ? !memcpy((buf), (src), (num)) : SOAP_ERANGE) #endif -#ifndef soap_isnan -# ifdef HAVE_ISNAN -# define soap_isnan(n) isnan(n) -# else -# define soap_isnan(n) (0) -# endif -#endif - -#define soap_ispinfd(n) ((n) >= DBL_PINFTY) -#define soap_ispinff(n) ((n) >= FLT_PINFTY) -#define soap_isninfd(n) ((n) <= DBL_NINFTY) -#define soap_isninff(n) ((n) <= FLT_NINFTY) - -/* gSOAP error codes */ - -#define SOAP_EOF EOF -#define SOAP_ERR EOF -#define SOAP_OK 0 -#define SOAP_CLI_FAULT 1 -#define SOAP_SVR_FAULT 2 -#define SOAP_TAG_MISMATCH 3 -#define SOAP_TYPE 4 -#define SOAP_SYNTAX_ERROR 5 -#define SOAP_NO_TAG 6 -#define SOAP_IOB 7 -#define SOAP_MUSTUNDERSTAND 8 -#define SOAP_NAMESPACE 9 -#define SOAP_USER_ERROR 10 -#define SOAP_FATAL_ERROR 11 -#define SOAP_FAULT 12 -#define SOAP_NO_METHOD 13 -#define SOAP_NO_DATA 14 -#define SOAP_GET_METHOD 15 -#define SOAP_PUT_METHOD 16 -#define SOAP_DEL_METHOD 17 -#define SOAP_HEAD_METHOD 18 -#define SOAP_HTTP_METHOD 19 -#define SOAP_EOM 20 -#define SOAP_MOE 21 -#define SOAP_HDR 22 -#define SOAP_NULL 23 -#define SOAP_DUPLICATE_ID 24 -#define SOAP_MISSING_ID 25 -#define SOAP_HREF 26 -#define SOAP_UDP_ERROR 27 -#define SOAP_TCP_ERROR 28 -#define SOAP_HTTP_ERROR 29 -#define SOAP_SSL_ERROR 30 -#define SOAP_ZLIB_ERROR 31 -#define SOAP_DIME_ERROR 32 -#define SOAP_DIME_HREF 33 -#define SOAP_DIME_MISMATCH 34 -#define SOAP_DIME_END 35 -#define SOAP_MIME_ERROR 36 -#define SOAP_MIME_HREF 37 -#define SOAP_MIME_END 38 -#define SOAP_VERSIONMISMATCH 39 -#define SOAP_PLUGIN_ERROR 40 -#define SOAP_DATAENCODINGUNKNOWN 41 -#define SOAP_REQUIRED 42 -#define SOAP_PROHIBITED 43 -#define SOAP_OCCURS 44 -#define SOAP_LENGTH 45 -#define SOAP_FD_EXCEEDED 46 - -#define soap_xml_error_check(e) ((e) == SOAP_TAG_MISMATCH || (e) == SOAP_NO_TAG || (e) == SOAP_SYNTAX_ERROR || (e) == SOAP_NAMESPACE || (e) == SOAP_DUPLICATE_ID || (e) == SOAP_MISSING_ID || (e) == SOAP_REQUIRED || (e) == SOAP_PROHIBITED || (e) == SOAP_OCCURS || (e) == SOAP_LENGTH || (e) == SOAP_NULL || (e) == SOAP_HREF) -#define soap_soap_error_check(e) ((e) == SOAP_CLI_FAULT || (e) == SOAP_SVR_FAULT || (e) == SOAP_VERSIONMISMATCH || (e) == SOAP_MUSTUNDERSTAND || (e) == SOAP_FAULT || (e) == SOAP_NO_METHOD) -#define soap_tcp_error_check(e) ((e) == SOAP_EOF || (e) == SOAP_TCP_ERROR) +/* move memory (returns SOAP_ERANGE on overrun, zero if OK, pointers must not be NULL) */ +#if _MSC_VER >= 1400 +# define soap_memmove(buf, len, src, num) ((size_t)(len) >= (size_t)(num) ? memmove_s((buf), (len), (src), (num)) : SOAP_ERANGE) +#else +# define soap_memmove(buf, len, src, num) ((size_t)(len) >= (size_t)(num) ? !memmove((buf), (src), (num)) : SOAP_ERANGE) +#endif + +/* gSOAP status and error codes */ + +typedef soap_int32 soap_status; + +#define SOAP_EOF EOF +#define SOAP_OK 0 +#define SOAP_CLI_FAULT 1 +#define SOAP_SVR_FAULT 2 +#define SOAP_TAG_MISMATCH 3 +#define SOAP_TYPE 4 +#define SOAP_SYNTAX_ERROR 5 +#define SOAP_NO_TAG 6 +#define SOAP_IOB 7 +#define SOAP_MUSTUNDERSTAND 8 +#define SOAP_NAMESPACE 9 +#define SOAP_USER_ERROR 10 +#define SOAP_FATAL_ERROR 11 /* deprecated */ +#define SOAP_FAULT 12 +#define SOAP_NO_METHOD 13 +#define SOAP_NO_DATA 14 +#define SOAP_GET_METHOD 15 +#define SOAP_PUT_METHOD 16 +#define SOAP_PATCH_METHOD 17 +#define SOAP_DEL_METHOD 18 +#define SOAP_HTTP_METHOD 19 +#define SOAP_EOM 20 +#define SOAP_MOE 21 +#define SOAP_HDR 22 +#define SOAP_NULL 23 +#define SOAP_DUPLICATE_ID 24 +#define SOAP_MISSING_ID 25 +#define SOAP_HREF 26 +#define SOAP_UDP_ERROR 27 +#define SOAP_TCP_ERROR 28 +#define SOAP_HTTP_ERROR 29 +#define SOAP_SSL_ERROR 30 +#define SOAP_ZLIB_ERROR 31 +#define SOAP_DIME_ERROR 32 +#define SOAP_DIME_HREF 33 +#define SOAP_DIME_MISMATCH 34 +#define SOAP_DIME_END 35 +#define SOAP_MIME_ERROR 36 +#define SOAP_MIME_HREF 37 +#define SOAP_MIME_END 38 +#define SOAP_VERSIONMISMATCH 39 +#define SOAP_PLUGIN_ERROR 40 +#define SOAP_DATAENCODINGUNKNOWN 41 /* unused */ +#define SOAP_REQUIRED 42 +#define SOAP_PROHIBITED 43 +#define SOAP_OCCURS 44 +#define SOAP_LENGTH 45 +#define SOAP_PATTERN 46 +#define SOAP_FD_EXCEEDED 47 +#define SOAP_UTF_ERROR 48 +#define SOAP_NTLM_ERROR 49 +#define SOAP_LEVEL 50 +#define SOAP_FIXED 51 +#define SOAP_EMPTY 52 +#define SOAP_END_TAG 53 +#define SOAP_ERR 99 + +#define soap_xml_error_check(e) \ + ((e) == SOAP_TAG_MISMATCH || \ + (e) == SOAP_NO_TAG || \ + (e) == SOAP_IOB || \ + (e) == SOAP_SYNTAX_ERROR || \ + (e) == SOAP_NAMESPACE || \ + (e) == SOAP_TYPE || \ + (e) == SOAP_DUPLICATE_ID || \ + (e) == SOAP_MISSING_ID || \ + (e) == SOAP_REQUIRED || \ + (e) == SOAP_PROHIBITED || \ + (e) == SOAP_OCCURS || \ + (e) == SOAP_LENGTH || \ + (e) == SOAP_LEVEL || \ + (e) == SOAP_PATTERN || \ + (e) == SOAP_NULL || \ + (e) == SOAP_HREF || \ + (e) == SOAP_FIXED || \ + (e) == SOAP_EMPTY || \ + (e) == SOAP_END_TAG || \ + (e) == SOAP_UTF_ERROR) + +#define soap_soap_error_check(e) \ + ((e) == SOAP_CLI_FAULT || \ + (e) == SOAP_SVR_FAULT || \ + (e) == SOAP_VERSIONMISMATCH || \ + (e) == SOAP_MUSTUNDERSTAND || \ + (e) == SOAP_FAULT || \ + (e) == SOAP_NO_METHOD || \ + (e) == SOAP_DATAENCODINGUNKNOWN) + +#define soap_http_error_check(e) \ + ((e) == SOAP_HTTP_ERROR || \ + (e) == SOAP_NO_DATA || \ + ((e) >= SOAP_GET_METHOD && (e) <= SOAP_HTTP_METHOD) || \ + ((e) >= 100 && (e) < 600)) + +#define soap_dime_error_check(e) \ + ((e) == SOAP_DIME_ERROR || \ + (e) == SOAP_DIME_HREF || \ + (e) == SOAP_DIME_MISMATCH || \ + (e) == SOAP_DIME_END) + +#define soap_mime_error_check(e) \ + ((e) == SOAP_MIME_ERROR || \ + (e) == SOAP_MIME_HREF || \ + (e) == SOAP_MIME_END) + +#define soap_tcp_error_check(e) \ + ((e) == SOAP_EOF || \ + (e) == SOAP_TCP_ERROR) + +#define soap_udp_error_check(e) \ + ((e) == SOAP_EOF || \ + (e) == SOAP_UDP_ERROR) + #define soap_ssl_error_check(e) ((e) == SOAP_SSL_ERROR) + #define soap_zlib_error_check(e) ((e) == SOAP_ZLIB_ERROR) -#define soap_http_error_check(e) ((e) == SOAP_HTTP_ERROR || (e) == SOAP_NO_DATA || ((e) >= SOAP_GET_METHOD && (e) <= SOAP_HTTP_METHOD) || ((e) >= 100 && (e) < 600)) /* gSOAP HTTP response status codes 100 to 599 are reserved */ @@ -1070,153 +1660,251 @@ extern const struct soap_double_nan { unsigned int n1, n2; } soap_double_nan; /* Exceptional gSOAP HTTP server response status codes >= 1000 */ -#define SOAP_STOP 1000 /* No HTTP response */ -#define SOAP_FORM 1001 /* Form request/response */ -#define SOAP_HTML 1002 /* Custom HTML response */ -#define SOAP_FILE 1003 /* Custom file-based response */ +#define SOAP_STOP 1000 /* No HTTP response should follow after SOAP_STOP is issued */ +#define SOAP_FORM 1001 /* Request (form) data is present, no HTTP response should follow */ +#define SOAP_HTML 1002 /* Custom HTML response */ +#define SOAP_FILE 1200 /* Custom file-based response with soap::http_content and optional http status */ /* gSOAP HTTP method codes (client) */ -#define SOAP_POST 2000 /* POST request */ -#define SOAP_POST_FILE 2001 /* Custom file-based POST request */ -#define SOAP_GET 2002 /* GET request */ +typedef int soap_http_command; + +#define SOAP_POST 2000 /* POST request */ +#define SOAP_POST_FILE 2001 /* Custom file-based POST request */ +#define SOAP_GET 2002 /* GET request */ +#define SOAP_PUT 2003 /* PUT request */ +#define SOAP_PATCH 2004 /* PATCH request */ +#define SOAP_DEL 2005 /* DELETE request */ +#define SOAP_HEAD 2006 /* HEAD request */ +#define SOAP_OPTIONS 2007 /* OPTIONS request */ +#define SOAP_CONNECT 2008 /* CONNECT request */ /* gSOAP DIME */ -#define SOAP_DIME_CF 0x01 -#define SOAP_DIME_ME 0x02 -#define SOAP_DIME_MB 0x04 -#define SOAP_DIME_VERSION 0x08 /* DIME version 1 */ -#define SOAP_DIME_MEDIA 0x10 -#define SOAP_DIME_ABSURI 0x20 +#define SOAP_DIME_CF 0x01 +#define SOAP_DIME_ME 0x02 +#define SOAP_DIME_MB 0x04 +#define SOAP_DIME_VERSION 0x08 /* DIME version 1 */ +#define SOAP_DIME_MEDIA 0x10 +#define SOAP_DIME_ABSURI 0x20 /* gSOAP ZLIB */ -#define SOAP_ZLIB_NONE 0x00 -#define SOAP_ZLIB_DEFLATE 0x01 -#define SOAP_ZLIB_INFLATE 0x02 -#define SOAP_ZLIB_GZIP 0x02 +#define SOAP_ZLIB_NONE 0x00 +#define SOAP_ZLIB_DEFLATE 0x01 +#define SOAP_ZLIB_INFLATE 0x02 +#define SOAP_ZLIB_GZIP 0x02 /* gSOAP transport, connection, and content encoding modes */ typedef soap_int32 soap_mode; -#define SOAP_IO 0x00000003 /* IO mask */ -#define SOAP_IO_FLUSH 0x00000000 /* flush output immediately, no buffering */ -#define SOAP_IO_BUFFER 0x00000001 /* buffer output in packets of size SOAP_BUFLEN */ -#define SOAP_IO_STORE 0x00000002 /* store entire output to determine length for transport */ -#define SOAP_IO_CHUNK 0x00000003 /* use HTTP chunked transfer AND buffer packets */ - -#define SOAP_IO_UDP 0x00000004 /* TCP or UDP */ - -#define SOAP_IO_LENGTH 0x00000008 /* calc message length (internal) */ -#define SOAP_IO_KEEPALIVE 0x00000010 /* keep connection alive */ - -#define SOAP_ENC_LATIN 0x00000020 /* accept iso-8859-1 encoding */ -#define SOAP_ENC_XML 0x00000040 /* plain XML encoding, no HTTP header */ -#define SOAP_ENC_DIME 0x00000080 -#define SOAP_ENC_MIME 0x00000100 -#define SOAP_ENC_MTOM 0x00000200 -#define SOAP_ENC_ZLIB 0x00000400 -#define SOAP_ENC_SSL 0x00000800 - -#define SOAP_ENC 0x00000FFF /* IO and ENC mask */ - -#define SOAP_XML_STRICT 0x00001000 /* apply strict validation */ -#define SOAP_XML_INDENT 0x00002000 /* emit indented XML */ -#define SOAP_XML_DEFAULTNS 0x00004000 /* emit xmlns="..." namesp. */ -#define SOAP_XML_CANONICAL 0x00008000 /* EXC C14N canonical XML */ -#define SOAP_XML_TREE 0x00010000 /* emit XML tree (no id/ref) */ -#define SOAP_XML_GRAPH 0x00020000 /* see DOM manual */ -#define SOAP_XML_NIL 0x00040000 /* serialize NULLs as xsi:nil */ -#define SOAP_XML_DOM 0x00080000 - -#define SOAP_C_NOIOB 0x00100000 /* don't fault on array index out of bounds (just ignore) */ -#define SOAP_C_UTFSTRING 0x00200000 /* (de)serialize strings with UTF8 content */ -#define SOAP_C_MBSTRING 0x00400000 /* (de)serialize strings with multi-byte content */ -#define SOAP_C_NILSTRING 0x00800000 /* serialize empty strings as nil (omitted) */ - -#define SOAP_DOM_TREE 0x01000000 -#define SOAP_DOM_NODE 0x02000000 -#define SOAP_DOM_ASIS 0x04000000 - -#define SOAP_MIME_POSTCHECK 0x10000000 /* MIME flag (internal) */ - -#define SOAP_XML_SEC 0x80000000 /* reserved for WS security */ +#define SOAP_IO 0x00000003 /* IO mask */ +#define SOAP_IO_FLUSH 0x00000000 /* out: flush output immediately, no buffering */ +#define SOAP_IO_BUFFER 0x00000001 /* out: buffer output in packets of size SOAP_BUFLEN */ +#define SOAP_IO_STORE 0x00000002 /* out: store entire output to determine length for transport */ +#define SOAP_IO_CHUNK 0x00000003 /* out: use HTTP chunked transfer AND buffer packets */ + +#define SOAP_IO_UDP 0x00000004 /* in/out: enable UDP instead of TCP */ +#define SOAP_IO_LENGTH 0x00000008 /* out: calc message length (internal) */ +#define SOAP_IO_KEEPALIVE 0x00000010 /* out: keep connection alive */ + +#define SOAP_ENC 0x00000FFF /* IO and ENC mask */ +#define SOAP_ENC_LATIN 0x00000020 /* in: accept iso-8859-1 */ +#define SOAP_ENC_PLAIN 0x00000040 /* out: plain (XML or other) body, no HTTP header, in: skip HTTP header (use soap::length) */ +#define SOAP_ENC_XML 0x00000040 /* deprecated, alias for SOAP_ENC_PLAIN */ +#define SOAP_ENC_DIME 0x00000080 +#define SOAP_ENC_MIME 0x00000100 +#define SOAP_ENC_MTOM 0x00000200 +#define SOAP_ENC_ZLIB 0x00000400 +#define SOAP_ENC_SSL 0x00000800 + +#define SOAP_XML_STRICT 0x00001000 /* in: strict validation */ +#define SOAP_XML_INDENT 0x00002000 /* out: emit indented XML */ +#define SOAP_XML_IGNORENS 0x00004000 /* in: ignore namespaces */ +#define SOAP_XML_DEFAULTNS 0x00008000 /* out: emit xmlns="..." */ +#define SOAP_XML_CANONICAL 0x00010000 /* out: exc-C14N exclusive canonical XML */ +#define SOAP_XML_TREE 0x00020000 /* in/out: XML tree (no id/ref) */ +#define SOAP_XML_NIL 0x00040000 /* out: all NULLs as xsi:nil */ +#define SOAP_XML_NOTYPE 0x00080000 /* out: do not add xsi:type */ + +#define SOAP_DOM_TREE 0x00100000 /* see DOM manual */ +#define SOAP_DOM_NODE 0x00200000 +#define SOAP_DOM_ASIS 0x00400000 + +#define SOAP_XML_CANONICAL_NA 0x00800000 /* out: (exc) C14N not QName aware */ + +#define SOAP_C_NOIOB 0x01000000 /* don't fault on array index out of bounds (just ignore) */ +#define SOAP_C_UTFSTRING 0x02000000 /* (de)serialize strings with UTF8 content */ +#define SOAP_C_MBSTRING 0x04000000 /* (de)serialize strings with multi-byte content */ +#define SOAP_C_NILSTRING 0x08000000 /* serialize empty strings as nil (omitted) */ + +#define SOAP_XML_DOM 0x10000000 /* enable internal DOM */ +#define SOAP_XML_GRAPH 0x20000000 /* force id-ref XML graph */ + +#define SOAP_MIME_POSTCHECK 0x40000000 /* MIME flag (internal) */ + +#define SOAP_SEC_WSUID 0x80000000 /* Add Body wsu:Id flag (internal) */ /* WITH_XMLNS backward compatibility: always use XML default namespaces */ #ifdef WITH_XMLNS -# define SOAP_IO_DEFAULT (SOAP_IO_FLUSH | SOAP_XML_DEFAULTNS) +# define SOAP_IO_DEFAULT (SOAP_IO_FLUSH | SOAP_XML_DEFAULTNS) #else -# define SOAP_IO_DEFAULT SOAP_IO_FLUSH +# define SOAP_IO_DEFAULT SOAP_IO_FLUSH #endif /* SSL client/server authentication settings */ -#define SOAP_SSL_NO_AUTHENTICATION 0x00 /* for testing purposes */ -#define SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION 0x01 /* client requires server to authenticate */ -#define SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION 0x02 /* server requires client to authenticate */ -#define SOAP_SSL_SKIP_HOST_CHECK 0x04 /* client does not check the common name of the host in certificate */ -#define SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE 0x08 /* client does not check the expiration date of the host certificate */ -#define SOAP_SSL_NO_DEFAULT_CA_PATH 0x10 /* don't use default_verify_paths */ -#define SOAP_SSL_RSA 0x20 /* use RSA */ -#define SOAP_SSLv3 0x40 /* SSL v3 only */ -#define SOAP_TLSv1 0x80 /* TLS v1 only */ -#define SOAP_SSLv3_TLSv1 0x00 /* SSL v3 and TLS v1 support by default */ +#define SOAP_SSL_NO_AUTHENTICATION (0x0000) /* no authentication */ +#define SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION (0x0001) /* client requires server to authenticate */ +#define SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION (0x0002) /* server requires client to authenticate */ +#define SOAP_SSL_SKIP_HOST_CHECK (0x0004) /* client skips common name check against host name */ +#define SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE (0x0008) /* allow self-signed and expired certificates and those w/o CRL */ +#define SOAP_SSL_NO_DEFAULT_CA_PATH (0x0010) /* don't use SSL_CTX_set_default_verify_paths */ +#define SOAP_SSL_RSA (0x0020) /* use RSA */ +#define SOAP_SSL_SNI_HOST_CHECK (0x0040) /* client SNI only with a valid hostname, reject IP */ +#define SOAP_SSLv3 (0x0080) /* enable SSL v3 */ +#define SOAP_TLSv1_0 (0x0100) /* enable TLS v1.0 */ +#define SOAP_TLSv1_1 (0x0200) /* enable TLS v1.1 */ +#define SOAP_TLSv1_2 (0x0400) /* enable TLS v1.2 */ +#define SOAP_TLSv1_3 (0x0800) /* enable TLS v1.3 */ +#define SOAP_TLSv1 (SOAP_TLSv1_0 | SOAP_TLSv1_1 | SOAP_TLSv1_2 | SOAP_TLSv1_3) +#define SOAP_SSLv3_TLSv1 (SOAP_SSLv3 | SOAP_TLSv1) + +#define SOAP_SSL_CLIENT (0x8000) /* client context flag for internal use */ + +#define SOAP_SSL_DEFAULT SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION -#define SOAP_SSL_DEFAULT (SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION | SOAP_SSLv3_TLSv1) +typedef unsigned short soap_ssl_flags; /* state */ -#define SOAP_NONE 0 -#define SOAP_INIT 1 -#define SOAP_COPY 2 +#define SOAP_NONE 0 +#define SOAP_INIT 1 +#define SOAP_COPY 2 #define soap_check_state(soap) (!(soap) || ((soap)->state != SOAP_INIT && (soap)->state != SOAP_COPY)) -/* part */ - -#define SOAP_BEGIN 0 -#define SOAP_IN_ENVELOPE 2 -#define SOAP_IN_HEADER 3 -#define SOAP_END_HEADER 4 -#define SOAP_NO_BODY 5 -#define SOAP_IN_BODY 6 -#define SOAP_END_BODY 7 -#define SOAP_END_ENVELOPE 8 -#define SOAP_END 9 -#define SOAP_BEGIN_SECURITY 10 -#define SOAP_IN_SECURITY 11 -#define SOAP_END_SECURITY 12 +/* parts */ + +#define SOAP_END 0 +#define SOAP_BEGIN_SEND 1 +#define SOAP_BEGIN_RECV 2 +#define SOAP_IN_ENVELOPE 3 +#define SOAP_IN_HEADER 4 +#define SOAP_END_HEADER 5 +#define SOAP_NO_BODY 6 +#define SOAP_IN_BODY 7 +#define SOAP_END_BODY 8 +#define SOAP_END_ENVELOPE 9 + +/* events */ + +#define SOAP_SEC_BEGIN 1 +#define SOAP_SEC_SIGN 2 +#define SOAP_SEC_DECRYPT 3 /* DEBUG macros */ -#ifndef WITH_LEAN -# ifdef DEBUG -# ifndef SOAP_DEBUG -# define SOAP_DEBUG -# endif -# ifndef SOAP_MEM_DEBUG -# define SOAP_MEM_DEBUG -# endif +#ifdef DEBUG_STAMP +# ifndef DEBUG +# define DEBUG +# endif +#endif + +#ifdef DEBUG +# ifndef SOAP_DEBUG +# define SOAP_DEBUG +# endif +# ifndef SOAP_MEM_DEBUG +# define SOAP_MEM_DEBUG # endif #endif #ifdef SOAP_MEM_DEBUG # ifndef SOAP_MALLOC -# define SOAP_MALLOC(soap, size) soap_track_malloc(soap, __FILE__, __LINE__, size) +# define SOAP_MALLOC(soap, size) soap_track_malloc((soap), __FILE__, __LINE__, (size)) # endif # ifndef SOAP_FREE -# define SOAP_FREE(soap, ptr) soap_track_free(soap, __FILE__, __LINE__, ptr) +# define SOAP_FREE(soap, ptr) soap_track_free((soap), __FILE__, __LINE__, (void*)(ptr)) +# endif +#endif + +#ifndef SOAP_MALLOC /* use libc malloc */ +# define SOAP_MALLOC(soap, size) malloc((size)) +#endif + +#ifndef SOAP_FREE /* use libc free */ +# define SOAP_FREE(soap, ptr) free((void*)(ptr)) +#endif + +#ifndef SOAP_MALLOC_UNMANAGED /* use libc malloc to alloc soap context with soap_new() */ +# define SOAP_MALLOC_UNMANAGED(size) malloc((size)) +#endif + +#ifndef SOAP_FREE_UNMANAGED /* use libc free to free soap context with soap_free() */ +# define SOAP_FREE_UNMANAGED(ptr) free((void*)(ptr)) +#endif + +#ifndef SOAP_NOTHROW +# if defined(__GNUC__) && (__GNUC__ <= 2) +# define SOAP_NOTHROW +# elif defined(WITH_LEAN) || defined(WITH_COMPAT) +# define SOAP_NOTHROW +# else +# define SOAP_NOTHROW (std::nothrow) +# endif +#endif + +#if defined(__BORLANDC__) && !defined(__clang__) +/* Embarcadero Classic compiler special case */ +# ifndef SOAP_NEW +# define SOAP_NEW(soap, type) new SOAP_NOTHROW (type) +# endif +# ifndef SOAP_NEW_ARRAY +# define SOAP_NEW_ARRAY(soap, type, n) new SOAP_NOTHROW (type[n]) +# endif +# ifndef SOAP_PLACEMENT_NEW +# define SOAP_PLACEMENT_NEW(soap, buf, type) new (buf) (type) +# endif +#elif (defined(__GNUC__) && (__GNUC__ <= 2)) || defined(__clang__) || defined(_AIX) || defined(AIX) +/* old form w/o parenthesis, soap context may be NULL */ +# ifndef SOAP_NEW +# define SOAP_NEW(soap, type) new SOAP_NOTHROW type # endif +# ifndef SOAP_NEW_ARRAY +# define SOAP_NEW_ARRAY(soap, type, n) new SOAP_NOTHROW type[n] +# endif +# ifndef SOAP_PLACEMENT_NEW +# define SOAP_PLACEMENT_NEW(soap, buf, type) new (buf) type +# endif +#else +/* new form with parenthesis for (type) but not type[n], soap context may be NULL */ +# ifndef SOAP_NEW +# define SOAP_NEW(soap, type) new SOAP_NOTHROW (type) +# endif +# ifndef SOAP_NEW_ARRAY +# define SOAP_NEW_ARRAY(soap, type, n) new SOAP_NOTHROW type[n] +# endif +# ifndef SOAP_PLACEMENT_NEW +# define SOAP_PLACEMENT_NEW(soap, buf, type) new (buf) (type) +# endif +#endif + +#ifndef SOAP_DELETE /* use C++ delete operator, soap context may be NULL */ +# define SOAP_DELETE(soap, obj, type) delete obj #endif -#ifndef SOAP_MALLOC /* use libc malloc */ -# define SOAP_MALLOC(soap, size) malloc(size) +#ifndef SOAP_DELETE_ARRAY /* use C++ delete[] operator, soap context may be NULL */ +# define SOAP_DELETE_ARRAY(soap, obj, type) delete[] obj #endif -#ifndef SOAP_FREE /* use libc free */ -# define SOAP_FREE(soap, ptr) free(ptr) +#ifndef SOAP_NEW_UNMANAGED /* use C++ unmanaged new operator for soap_new() and soap::copy() */ +# define SOAP_NEW_UNMANAGED(soap) new SOAP_NOTHROW soap +#endif + +#ifndef SOAP_DELETE_UNMANAGED /* use C++ unmanaged delete operator for soap_free() */ +# define SOAP_DELETE_UNMANAGED(soap) delete soap #endif #ifdef SOAP_DEBUG @@ -1224,7 +1912,42 @@ typedef soap_int32 soap_mode; # define SOAP_MESSAGE fprintf # endif # ifndef DBGLOG -# define DBGLOG(DBGFILE, CMD) \ +# ifdef DEBUG_STAMP +# ifdef WIN32 +# define DBGLOG(DBGFILE, CMD) \ +{ if (soap)\ + { if (!soap->fdebug[SOAP_INDEX_##DBGFILE])\ + soap_open_logfile((struct soap*)soap, SOAP_INDEX_##DBGFILE);\ + if (soap->fdebug[SOAP_INDEX_##DBGFILE])\ + { FILE *fdebug = soap->fdebug[SOAP_INDEX_##DBGFILE];\ + SYSTEMTIME _localTime;\ + ::GetLocalTime(&_localTime); \ + fprintf(fdebug, "%02d%02d%02d %02d:%02d:%02d.%03d|", (int)_localTime.wYear%100, (int)_localTime.wMonth, (int)_localTime.wDay, (int)_localTime.wHour, (int)_localTime.wMinute, (int)_localTime.wSecond, (int)_localTime.wMilliseconds);\ + CMD;\ + fflush(fdebug);\ + }\ + }\ +} +# else +# define DBGLOG(DBGFILE, CMD) \ +{ if (soap)\ + { if (!soap->fdebug[SOAP_INDEX_##DBGFILE])\ + soap_open_logfile((struct soap*)soap, SOAP_INDEX_##DBGFILE);\ + if (soap->fdebug[SOAP_INDEX_##DBGFILE])\ + { FILE *fdebug = soap->fdebug[SOAP_INDEX_##DBGFILE];\ + struct timeval _tv;\ + struct tm _tm;\ + gettimeofday(&_tv, NULL);\ + localtime_r(&_tv.tv_sec, &_tm);\ + fprintf(fdebug, "%02d%02d%02d %02d:%02d:%02d.%06ld|", (int)_tm.tm_year%100, (int)_tm.tm_mon+1, (int)_tm.tm_mday, (int)_tm.tm_hour, (int)_tm.tm_min, (int)_tm.tm_sec, (long)_tv.tv_usec);\ + CMD;\ + fflush(fdebug);\ + }\ + }\ +} +# endif +# else +# define DBGLOG(DBGFILE, CMD) \ { if (soap)\ { if (!soap->fdebug[SOAP_INDEX_##DBGFILE])\ soap_open_logfile((struct soap*)soap, SOAP_INDEX_##DBGFILE);\ @@ -1235,6 +1958,7 @@ typedef soap_int32 soap_mode; }\ }\ } +# endif # endif # ifndef DBGMSG # define DBGMSG(DBGFILE, MSG, LEN) \ @@ -1242,7 +1966,7 @@ typedef soap_int32 soap_mode; { if (!soap->fdebug[SOAP_INDEX_##DBGFILE])\ soap_open_logfile((struct soap*)soap, SOAP_INDEX_##DBGFILE);\ if (soap->fdebug[SOAP_INDEX_##DBGFILE])\ - { fwrite((MSG), 1, (LEN), soap->fdebug[SOAP_INDEX_##DBGFILE]);\ + { fwrite((void*)(MSG), 1, (size_t)(LEN), soap->fdebug[SOAP_INDEX_##DBGFILE]);\ fflush(soap->fdebug[SOAP_INDEX_##DBGFILE]);\ }\ }\ @@ -1250,9 +1974,10 @@ typedef soap_int32 soap_mode; # endif # ifndef DBGFUN # define DBGFUN(FNAME) DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): %s()\n", __FILE__, __LINE__, FNAME)) -# define DBGFUN1(FNAME, FMT, ARG) DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): %s("FMT")\n", __FILE__, __LINE__, FNAME, (ARG))) -# define DBGFUN2(FNAME, FMT1, ARG1, FMT2, ARG2) DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): %s("FMT1", "FMT2")\n", __FILE__, __LINE__, FNAME, (ARG1), (ARG2))) -# define DBGFUN3(FNAME, FMT1, ARG1, FMT2, ARG2, FMT3, ARG3) DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): %s("FMT1", "FMT2", "FMT3")\n", __FILE__, __LINE__, FNAME, (ARG1), (ARG2), (ARG3))) +# define DBGFUN1(FNAME, FMT, ARG) DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): %s(" FMT ")\n", __FILE__, __LINE__, FNAME, (ARG))) +# define DBGFUN2(FNAME, FMT1, ARG1, FMT2, ARG2) DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): %s(" FMT1 ", " FMT2 ")\n", __FILE__, __LINE__, FNAME, (ARG1), (ARG2))) +# define DBGFUN3(FNAME, FMT1, ARG1, FMT2, ARG2, FMT3, ARG3) DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): %s(" FMT1 ", " FMT2 ", " FMT3 ")\n", __FILE__, __LINE__, FNAME, (ARG1), (ARG2), (ARG3))) +# define DBGFUN4(FNAME, FMT1, ARG1, FMT2, ARG2, FMT3, ARG3, FMT4, ARG4) DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): %s(" FMT1 ", " FMT2 ", " FMT3 ", " FMT4 ")\n", __FILE__, __LINE__, FNAME, (ARG1), (ARG2), (ARG3), (ARG4))) # endif # ifndef DBGHEX # define DBGHEX(DBGFILE, MSG, LEN) \ @@ -1275,15 +2000,20 @@ typedef soap_int32 soap_mode; # define DBGFUN1(FNAME, FMT, ARG) # define DBGFUN2(FNAME, FMT1, ARG1, FMT2, ARG2) # define DBGFUN3(FNAME, FMT1, ARG1, FMT2, ARG2, FMT3, ARG3) +# define DBGFUN4(FNAME, FMT1, ARG1, FMT2, ARG2, FMT3, ARG3, FMT4, ARG4) # define DBGHEX(DBGFILE, MSG, LEN) #endif /* UCS-4 requires 32 bits (0-7FFFFFFF, the sign bit is used by gSOAP to distinguish XML entities) */ typedef soap_int32 soap_wchar; +/* forward declaration */ +struct SOAP_CMAC soap; + /* namespace table row */ -struct Namespace -{ const char *id; +struct SOAP_CMAC Namespace +{ + const char *id; const char *ns; const char *in; char *out; @@ -1291,47 +2021,56 @@ struct Namespace /* namespace stack */ struct soap_nlist -{ struct soap_nlist *next; +{ + struct soap_nlist *next; unsigned int level; /* nesting depth level */ short index; /* corresponding entry in ns mapping table */ const char *ns; /* only set when parsed ns URI is not in the ns mapping table */ - char id[1]; /* the actual string value flows into the allocated region below this struct */ + char id[1]; /* the actual string value flows into the allocated region id[0...] below this struct */ }; -/* block stack for nested block allocations */ -struct soap_blist -{ struct soap_blist *next; - char *ptr; +/* block header, the data flows into the allocated region below this struct */ +struct soap_bhead +{ + struct soap_bhead *next; size_t size; }; -/* array layout */ -struct soap_array -{ void *__ptr; - int __size; +/* block stack for nested block allocations */ +struct soap_blist +{ + struct soap_blist *next; + struct soap_bhead *head; + size_t size; + size_t item; }; /* pointer serialization management */ struct soap_plist -{ struct soap_plist *next; +{ + struct soap_plist *next; const void *ptr; - const struct soap_array *array; + void *dup; + const void *array; /* array pointer */ + int size; /* array size */ int type; int id; - char mark1; + char mark1; /* 0=single-ref, 1=embedded-multi-ref (SOAP1.1), 2=multi-ref, 3=attachment */ char mark2; }; /* block allocation for pointer serialization management */ struct soap_pblk -{ struct soap_pblk *next; +{ + struct soap_pblk *next; struct soap_plist plist[SOAP_PTRBLK]; }; #ifdef SOAP_MEM_DEBUG /* malloc/free tracking for debugging */ struct soap_mlist -{ struct soap_mlist *next; +{ + struct soap_mlist *next; const void *ptr; const char *file; int line; @@ -1341,65 +2080,71 @@ struct soap_mlist /* class allocation list */ struct soap_clist -{ struct soap_clist *next; +{ + struct soap_clist *next; void *ptr; int type; - int size; - int (*fdelete)(struct soap_clist*); + int size; /* array size */ + int (*fdelete)(struct soap*, struct soap_clist*); }; /* attributes */ struct soap_attribute -{ struct soap_attribute *next; +{ + struct soap_attribute *next; + short flag; /* soap_set_attr: 1 = normal, 2 = utf content */ char *value; size_t size; - char *ns; + const char *ns; short visible; char name[1]; /* the actual name string flows into the allocated region below this struct */ }; -#ifndef WITH_LEAN +#if !defined(WITH_LEAN) || defined(WITH_COOKIES) struct soap_cookie -{ struct soap_cookie *next; +{ + struct soap_cookie *next; char *name; char *value; char *domain; char *path; - time_t expire; /* client-side: local time to expire */ - long maxage; /* server-side: seconds to expire */ + ULONG64 expire; /* client-side: local time to expire (value cast to time_t) */ + long maxage; /* server-side: seconds to expire */ unsigned int version; short secure; - short session; /* server-side */ - short env; /* server-side: got cookie from client and should not be (re)send */ - short modified; /* server-side: client cookie was modified and should be send */ + short session; /* server-side */ + short env; /* server-side: got cookie from client and should not be (re)send */ + short modified; /* server-side: client cookie was modified and should be send */ }; #endif SOAP_FMAC1 struct soap_multipart* SOAP_FMAC2 soap_next_multipart(struct soap_multipart*); #ifdef __cplusplus - class soap_multipart_iterator -{ public: +{ + public: + typedef ptrdiff_t difference_type; + typedef soap_multipart value_type; + typedef soap_multipart& reference; + typedef soap_multipart* pointer; + typedef std::forward_iterator_tag iterator_category; struct soap_multipart *content; - bool operator==(const soap_multipart_iterator& iter) const - { return (bool)(content == iter.content); } - bool operator!=(const soap_multipart_iterator& iter) const - { return (bool)(content != iter.content); } - struct soap_multipart &operator*() const - { return *content; } - soap_multipart_iterator &operator++() - { content = soap_next_multipart(content); return *this; } - soap_multipart_iterator() : content(NULL) - { } - soap_multipart_iterator(struct soap_multipart *p) : content(p) - { } + soap_multipart_iterator() : content(NULL) { } + soap_multipart_iterator(struct soap_multipart *p) : content(p) { } + bool operator==(const soap_multipart_iterator& iter) const { return (bool)(content == iter.content); } + bool operator!=(const soap_multipart_iterator& iter) const { return (bool)(content != iter.content); } + struct soap_multipart& operator*() const { return *content; } + struct soap_multipart *operator->() const { return content; } + soap_multipart_iterator& operator++() { content = soap_next_multipart(content); return *this; } + soap_multipart_iterator operator++(int) { soap_multipart_iterator iter(*this); content = soap_next_multipart(content); return iter; } }; #endif #ifndef WITH_LEANER struct soap_dime -{ size_t count; +{ + size_t count; size_t size; size_t chunksize; size_t buflen; @@ -1408,28 +2153,33 @@ struct soap_dime const char *id; const char *type; const char *options; - struct soap_multipart *list; /* list of DIME attachments received */ - struct soap_multipart *first, *last; /* temporary in/out queue */ + struct soap_multipart *list; /* list of DIME attachments received */ + struct soap_multipart *first, *last; /* temporary in/out queue */ #ifdef __cplusplus - soap_multipart_iterator begin() - { soap_multipart_iterator iter(list); return iter; }; - soap_multipart_iterator end() - { soap_multipart_iterator iter(NULL); return iter; }; + typedef soap_multipart_iterator iterator; + typedef soap_multipart_iterator const_iterator; + const_iterator cbegin() const { soap_multipart_iterator iter(list); return iter; } + const_iterator cend() const { soap_multipart_iterator iter(NULL); return iter; } + iterator begin() { soap_multipart_iterator iter(list); return iter; } + iterator end() { soap_multipart_iterator iter(NULL); return iter; } #endif }; #endif #ifndef WITH_LEANER struct soap_mime -{ char *boundary; /* MIME boundary */ - const char *start; /* MIME start ID */ - struct soap_multipart *list; /* list of MIME attachments received */ - struct soap_multipart *first, *last; /* temporary in/out queue */ +{ + char *boundary; /* MIME boundary */ + const char *start; /* MIME start ID */ + struct soap_multipart *list; /* list of MIME attachments received */ + struct soap_multipart *first, *last; /* temporary in/out queue */ #ifdef __cplusplus - soap_multipart_iterator begin() - { soap_multipart_iterator iter(list); return iter; }; - soap_multipart_iterator end() - { soap_multipart_iterator iter(NULL); return iter; }; + typedef soap_multipart_iterator iterator; + typedef soap_multipart_iterator const_iterator; + const_iterator cbegin() const { soap_multipart_iterator iter(list); return iter; } + const_iterator cend() const { soap_multipart_iterator iter(NULL); return iter; } + iterator begin() { soap_multipart_iterator iter(list); return iter; } + iterator end() { soap_multipart_iterator iter(NULL); return iter; } #endif }; #endif @@ -1437,7 +2187,8 @@ struct soap_mime #ifndef WITH_LEANER /* RFC2045 MIME content transfer encodings */ enum soap_mime_encoding -{ SOAP_MIME_NONE, +{ + SOAP_MIME_NONE, SOAP_MIME_7BIT, SOAP_MIME_8BIT, SOAP_MIME_BINARY, @@ -1451,17 +2202,19 @@ enum soap_mime_encoding #ifndef WITH_LEANER /* DIME/MIME multipart list */ struct soap_multipart -{ struct soap_multipart *next; - char *ptr; /* points to raw data content */ - size_t size; /* size of data content */ - const char *id; /* DIME/MIME content ID or form data name */ - const char *type; /* DIME/MIME type (MIME type format) */ - const char *options; /* DIME options */ - enum soap_mime_encoding encoding; /* MIME Content-Transfer-Encoding */ - const char *location; /* MIME Content-Location (optional) */ - const char *description; /* MIME Content-Description (optional) */ +{ + struct soap_multipart *next; + const char *ptr; /* points to raw data content */ + size_t size; /* size of data content */ + const char *id; /* DIME/MIME content ID or form data name */ + const char *type; /* DIME/MIME type (MIME type format) */ + const char *options; /* DIME options */ + enum soap_mime_encoding encoding; /* MIME Content-Transfer-Encoding */ + const char *location; /* MIME Content-Location (optional) */ + const char *description; /* MIME Content-Description (optional) */ #ifdef __cplusplus typedef soap_multipart_iterator iterator; + typedef soap_multipart_iterator const_iterator; #endif }; #endif @@ -1469,7 +2222,8 @@ struct soap_multipart #ifndef WITH_LEANER /* attachment DIME and MTOM XOP forwarding */ struct soap_xlist -{ struct soap_xlist *next; +{ + struct soap_xlist *next; unsigned char **ptr; int *size; char *id; @@ -1480,17 +2234,160 @@ struct soap_xlist /******************************************************************************/ +#ifndef WITH_LEANER + +/* dom.c[pp] functions (optional, compile and link dom.c[pp] */ +struct SOAP_CMAC soap_dom_element; +struct SOAP_CMAC soap_dom_attribute; + +/* soap_dom_element construction */ + +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_elt_new(struct soap *soap, const char *ns, const char *tag); +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_elt_new_w(struct soap *soap, const char *ns, const wchar_t *tag); +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_elt_set(struct soap_dom_element *elt, const char *ns, const char *tag); +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_elt_set_w(struct soap_dom_element *elt, const char *ns, const wchar_t *tag); + +SOAP_FMAC1 struct soap_dom_attribute * SOAP_FMAC2 soap_att(struct soap_dom_element *elt, const char *ns, const char *tag); +SOAP_FMAC1 struct soap_dom_attribute * SOAP_FMAC2 soap_att_w(struct soap_dom_element *elt, const char *ns, const wchar_t *tag); +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_elt(struct soap_dom_element *elt, const char *ns, const char *tag); +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_elt_w(struct soap_dom_element *elt, const char *ns, const wchar_t *tag); +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_nth_elt(struct soap_dom_element *elt, const char *ns, const char *tag, size_t n); +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_nth_elt_w(struct soap_dom_element *elt, const char *ns, const wchar_t *tag, size_t n); +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_nth(struct soap_dom_element *elt, size_t n); +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_add_att(struct soap_dom_element *elt, const struct soap_dom_attribute *node); +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_add_elt(struct soap_dom_element *elt, const struct soap_dom_element *node); +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_add_atts(struct soap_dom_element *elt, const struct soap_dom_attribute *atts); +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_add_elts(struct soap_dom_element *elt, const struct soap_dom_element *elts); + +/* soap_dom_element assignment */ + +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_elt_bool(struct soap_dom_element *elt, LONG64 b); +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_elt_int(struct soap_dom_element *elt, LONG64 n); +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_elt_double(struct soap_dom_element *elt, double x); +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_elt_text(struct soap_dom_element *elt, const char *text); +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_elt_text_w(struct soap_dom_element *elt, const wchar_t *text); +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_elt_node(struct soap_dom_element *elt, const void *node, int type); +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_elt_copy(struct soap_dom_element *elt, const struct soap_dom_element *node); + +/* soap_dom_element properties */ + +SOAP_FMAC1 int SOAP_FMAC2 soap_elt_match(const struct soap_dom_element *elt, const char *ns, const char *patt); +SOAP_FMAC1 int SOAP_FMAC2 soap_elt_match_w(const struct soap_dom_element *elt, const char *ns, const wchar_t *patt); +SOAP_FMAC1 const char * SOAP_FMAC2 soap_elt_get_ns(const struct soap_dom_element *elt); +SOAP_FMAC1 const char * SOAP_FMAC2 soap_elt_get_tag(const struct soap_dom_element *elt); +SOAP_FMAC1 int SOAP_FMAC2 soap_elt_is_true(const struct soap_dom_element *elt); +SOAP_FMAC1 int SOAP_FMAC2 soap_elt_is_false(const struct soap_dom_element *elt); +SOAP_FMAC1 int SOAP_FMAC2 soap_elt_get_int(const struct soap_dom_element *elt); +SOAP_FMAC1 long SOAP_FMAC2 soap_elt_get_long(const struct soap_dom_element *elt); +SOAP_FMAC1 LONG64 SOAP_FMAC2 soap_elt_get_LONG64(const struct soap_dom_element *elt); +SOAP_FMAC1 double SOAP_FMAC2 soap_elt_get_double(const struct soap_dom_element *elt); +SOAP_FMAC1 const char * SOAP_FMAC2 soap_elt_get_text(const struct soap_dom_element *elt); +SOAP_FMAC1 const void * SOAP_FMAC2 soap_elt_get_node(const struct soap_dom_element *elt, int type); +SOAP_FMAC1 int SOAP_FMAC2 soap_elt_get_type(const struct soap_dom_element *elt, const void **node); +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_elt_parent(const struct soap_dom_element *elt); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_elt_depth(const struct soap_dom_element *elt); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_elt_index(const struct soap_dom_element *elt); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_elt_len(const struct soap_dom_element *elt); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_elt_nth(const struct soap_dom_element *elt); + +/* soap_dom_attribute construction */ + +SOAP_FMAC1 struct soap_dom_attribute * SOAP_FMAC2 soap_att_new(struct soap *soap, const char *ns, const char *tag); +SOAP_FMAC1 struct soap_dom_attribute * SOAP_FMAC2 soap_att_new_w(struct soap *soap, const char *ns, const wchar_t *tag); +SOAP_FMAC1 struct soap_dom_attribute * SOAP_FMAC2 soap_att_set(struct soap_dom_attribute *att, const char *ns, const char *tag); +SOAP_FMAC1 struct soap_dom_attribute * SOAP_FMAC2 soap_att_set_w(struct soap_dom_attribute *att, const char *ns, const wchar_t *tag); +SOAP_FMAC1 struct soap_dom_attribute * SOAP_FMAC2 soap_att_add(struct soap_dom_attribute *att, const char *ns, const char *tag); +SOAP_FMAC1 struct soap_dom_attribute * SOAP_FMAC2 soap_att_add_w(struct soap_dom_attribute *att, const char *ns, const wchar_t *tag); + +/* soap_dom_attribute assignment */ + +SOAP_FMAC1 struct soap_dom_attribute * SOAP_FMAC2 soap_att_bool(struct soap_dom_attribute *att, LONG64 b); +SOAP_FMAC1 struct soap_dom_attribute * SOAP_FMAC2 soap_att_int(struct soap_dom_attribute *att, LONG64 n); +SOAP_FMAC1 struct soap_dom_attribute * SOAP_FMAC2 soap_att_double(struct soap_dom_attribute *att, double x); +SOAP_FMAC1 struct soap_dom_attribute * SOAP_FMAC2 soap_att_text(struct soap_dom_attribute *att, const char *text); +SOAP_FMAC1 struct soap_dom_attribute * SOAP_FMAC2 soap_att_text_w(struct soap_dom_attribute *att, const wchar_t *text); +SOAP_FMAC1 struct soap_dom_attribute * SOAP_FMAC2 soap_att_copy(struct soap_dom_attribute *att, const struct soap_dom_attribute *node); + +/* soap_dom_attribute properties */ + +SOAP_FMAC1 int SOAP_FMAC2 soap_att_match(const struct soap_dom_attribute *att, const char *ns, const char *patt); +SOAP_FMAC1 int SOAP_FMAC2 soap_att_match_w(const struct soap_dom_attribute *att, const char *ns, const wchar_t *patt); +SOAP_FMAC1 const char * SOAP_FMAC2 soap_att_get_ns(const struct soap_dom_attribute *att); +SOAP_FMAC1 const char * SOAP_FMAC2 soap_att_get_tag(const struct soap_dom_attribute *att); +SOAP_FMAC1 int SOAP_FMAC2 soap_att_is_true(const struct soap_dom_attribute *att); +SOAP_FMAC1 int SOAP_FMAC2 soap_att_is_false(const struct soap_dom_attribute *att); +SOAP_FMAC1 int SOAP_FMAC2 soap_att_get_int(const struct soap_dom_attribute *att); +SOAP_FMAC1 long SOAP_FMAC2 soap_att_get_long(const struct soap_dom_attribute *att); +SOAP_FMAC1 LONG64 SOAP_FMAC2 soap_att_get_LONG64(const struct soap_dom_attribute *att); +SOAP_FMAC1 double SOAP_FMAC2 soap_att_get_double(const struct soap_dom_attribute *att); +SOAP_FMAC1 const char * SOAP_FMAC2 soap_att_get_text(const struct soap_dom_attribute *att); + +/* DOM local traversal */ + +SOAP_FMAC1 struct soap_dom_attribute * SOAP_FMAC2 soap_att_first(struct soap_dom_element *elt); +SOAP_FMAC1 struct soap_dom_attribute * SOAP_FMAC2 soap_att_next(const struct soap_dom_attribute *att); +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_elt_first(struct soap_dom_element *elt); +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_elt_next(const struct soap_dom_element *elt); + +/* DOM local retrieval */ + +SOAP_FMAC1 struct soap_dom_attribute * SOAP_FMAC2 soap_att_get(const struct soap_dom_element *elt, const char *ns, const char *tag); +SOAP_FMAC1 struct soap_dom_attribute * SOAP_FMAC2 soap_att_get_w(const struct soap_dom_element *elt, const char *ns, const wchar_t *tag); +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_elt_get(const struct soap_dom_element *elt, const char *ns, const char *tag); +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_elt_get_w(const struct soap_dom_element *elt, const char *ns, const wchar_t *tag); +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_elt_get_next(const struct soap_dom_element *elt); +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_elt_get_nth(struct soap_dom_element *elt, size_t n); + +/* DOM local search */ + +SOAP_FMAC1 struct soap_dom_attribute * SOAP_FMAC2 soap_att_find(struct soap_dom_element *elt, const char *ns, const char *patt); +SOAP_FMAC1 struct soap_dom_attribute * SOAP_FMAC2 soap_att_find_next(const struct soap_dom_attribute *att, const char *ns, const char *patt); +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_elt_find(struct soap_dom_element *elt, const char *ns, const char *patt); +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_elt_find_next(const struct soap_dom_element *elt, const char *ns, const char *patt); +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_elt_find_type(struct soap_dom_element *elt, const char *ns, const char *patt, int type); +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_elt_find_next_type(const struct soap_dom_element *elt, const char *ns, const char *patt, int type); + +/* DOM size of local search results */ + +SOAP_FMAC1 size_t SOAP_FMAC2 soap_att_size(struct soap_dom_element *elt, const char *ns, const char *patt); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_elt_size(struct soap_dom_element *elt, const char *ns, const char *patt); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_elt_size_type(struct soap_dom_element *elt, const char *ns, const char *patt, int type); + +/* DOM deep traversal */ + +SOAP_FMAC1 struct soap_dom_attribute * SOAP_FMAC2 soap_dom_next_attribute(const struct soap_dom_attribute *att); +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_dom_next_element(const struct soap_dom_element *elt, const struct soap_dom_element *end); + +/* DOM deep search */ + +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_dom_find(struct soap_dom_element *begin, const struct soap_dom_element *end, const char *ns, const char *patt, int type); +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_dom_find_next(const struct soap_dom_element *elt, const struct soap_dom_element *end, const char *ns, const char *patt, int type); + +#endif + +#if defined(__cplusplus) +} /* extern "C" */ +#endif + #ifndef WITH_LEANER #ifdef __cplusplus -class soap_dom_attribute_iterator -{ public: - struct soap_dom_attribute *att; +class SOAP_CMAC soap_dom_attribute_iterator +{ + public: + typedef ptrdiff_t difference_type; + typedef soap_dom_attribute value_type; + typedef soap_dom_attribute& reference; + typedef soap_dom_attribute* pointer; + typedef std::forward_iterator_tag iterator_category; + struct soap_dom_attribute *iter; const char *nstr; const char *name; bool operator==(const soap_dom_attribute_iterator&) const; bool operator!=(const soap_dom_attribute_iterator&) const; - struct soap_dom_attribute &operator*() const; - soap_dom_attribute_iterator &operator++(); + struct soap_dom_attribute& operator*() const; + struct soap_dom_attribute *operator->() const; + soap_dom_attribute_iterator& operator++(); + soap_dom_attribute_iterator operator++(int); soap_dom_attribute_iterator(); soap_dom_attribute_iterator(struct soap_dom_attribute*); ~soap_dom_attribute_iterator(); @@ -1499,41 +2396,113 @@ class soap_dom_attribute_iterator #endif #ifndef WITH_LEANER -struct soap_dom_attribute -{ struct soap_dom_attribute *next; +struct SOAP_CMAC soap_dom_attribute +{ + struct soap_dom_attribute *next; const char *nstr; - char *name; - char *data; - wchar_t *wide; + const char *name; + const char *text; struct soap *soap; #ifdef __cplusplus typedef soap_dom_attribute_iterator iterator; - struct soap_dom_attribute &set(const char *nstr, const char *name); /* set namespace and name */ - struct soap_dom_attribute &set(const char *data); /* set data */ - soap_dom_attribute_iterator begin(); - soap_dom_attribute_iterator end(); - soap_dom_attribute_iterator find(const char *nstr, const char *name); - void unlink(); - soap_dom_attribute(); - soap_dom_attribute(struct soap *soap); - soap_dom_attribute(struct soap *soap, const char *nstr, const char *name, const char *data); + typedef soap_dom_attribute_iterator const_iterator; + soap_dom_attribute(struct soap *soap = NULL); + soap_dom_attribute(const soap_dom_attribute& att); + soap_dom_attribute(struct soap *soap, const char *tag); + soap_dom_attribute(struct soap *soap, const wchar_t *tag); + soap_dom_attribute(struct soap *soap, const char *ns, const char *tag, const char *str); + soap_dom_attribute(struct soap *soap, const char *ns, const char *tag, const wchar_t *str); + soap_dom_attribute(struct soap *soap, const char *ns, const wchar_t *tag, const char *str); + soap_dom_attribute(struct soap *soap, const char *ns, const wchar_t *tag, const wchar_t *str); +#ifndef WITH_COMPAT + soap_dom_attribute(struct soap *soap, const char *ns, const char *tag, const std::string& str); + soap_dom_attribute(struct soap *soap, const char *ns, const char *tag, const std::wstring& str); + soap_dom_attribute(struct soap *soap, const char *ns, const wchar_t *tag, const std::string& str); + soap_dom_attribute(struct soap *soap, const char *ns, const wchar_t *tag, const std::wstring& str); +#endif ~soap_dom_attribute(); + soap_dom_attribute& set(const char *ns, const char *tag) { return *soap_att_set(this, ns, tag); } + soap_dom_attribute& set(const char *ns, const wchar_t *tag) { return *soap_att_set_w(this, ns, tag); } + soap_dom_attribute& set(bool b) { return *soap_att_bool(this, b); } + soap_dom_attribute& set(int n) { return *soap_att_int(this, n); } + soap_dom_attribute& set(LONG64 n) { return *soap_att_int(this, n); } + soap_dom_attribute& set(float x) { return *soap_att_double(this, x); } + soap_dom_attribute& set(double x) { return *soap_att_double(this, x); } + soap_dom_attribute& set(const char *str) { return *soap_att_text(this, str); } + soap_dom_attribute& set(const wchar_t *str) { return *soap_att_text_w(this, str); } +#ifndef WITH_COMPAT + soap_dom_attribute& set(const std::string& str) { return *soap_att_text(this, str.c_str()); } + soap_dom_attribute& set(const std::wstring& str) { return *soap_att_text_w(this, str.c_str()); } +#endif + soap_dom_attribute& operator=(bool b) { return *soap_att_bool(this, b); } + soap_dom_attribute& operator=(int n) { return *soap_att_int(this, n); } + soap_dom_attribute& operator=(LONG64 n) { return *soap_att_int(this, n); } + soap_dom_attribute& operator=(float x) { return *soap_att_double(this, x); } + soap_dom_attribute& operator=(double x) { return *soap_att_double(this, x); } + soap_dom_attribute& operator=(const char *str) { return *soap_att_text(this, str); } + soap_dom_attribute& operator=(const wchar_t *str) { return *soap_att_text_w(this, str); } +#ifndef WITH_COMPAT + soap_dom_attribute& operator=(const std::string& str) { return *soap_att_text(this, str.c_str()); } + soap_dom_attribute& operator=(const std::wstring& str) { return *soap_att_text_w(this, str.c_str()); } +#endif + soap_dom_attribute& operator=(const soap_dom_attribute& att) { return *soap_att_copy(this, &att); } + soap_dom_attribute& att(const char *tag) { return *soap_att_add(this, NULL, tag); } + soap_dom_attribute& att(const wchar_t *tag) { return *soap_att_add_w(this, NULL, tag); } + soap_dom_attribute& att(const char *ns, const char *tag) { return *soap_att_add(this, ns, tag); } + soap_dom_attribute& att(const char *ns, const wchar_t *tag) { return *soap_att_add_w(this, ns, tag); } + bool match(const char *patt) const { return soap_att_match(this, NULL, patt) != 0; } + bool match(const wchar_t *patt) const { return soap_att_match_w(this, NULL, patt) != 0; } + bool match(const char *ns, const char *patt) const { return soap_att_match(this, ns, patt) != 0; } + bool match(const char *ns, const wchar_t *patt) const { return soap_att_match_w(this, ns, patt) != 0; } + const char *ns() const { return this->nstr; } + const char *tag() const { return this->name; } + bool is_true() const { return soap_att_is_true(this) != 0; } + bool is_false() const { return soap_att_is_false(this) != 0; } + LONG64 get_int() const { return soap_att_get_LONG64(this); } + double get_double() const { return soap_att_get_double(this); } + const char *get_text() const { return this->text; } + operator bool() const { return soap_att_is_true(this) != 0; } + operator int() const { return soap_att_get_int(this); } + operator LONG64() const { return soap_att_get_LONG64(this); } + operator double() const { return soap_att_get_double(this); } + operator const char*() const { return this->text; } + const_iterator cbegin() { return this->att_begin(); } + const_iterator cend() { return this->att_end(); } + iterator begin() { return this->att_begin(); } + iterator end() { return this->att_end(); } + iterator att_begin() { return soap_dom_attribute_iterator(this); } + iterator att_end() { return soap_dom_attribute_iterator(NULL); } + iterator att_find(const char *patt) { return att_find(NULL, patt); } + iterator att_find(const wchar_t *patt) { return att_find(NULL, patt); } + iterator att_find(const char *ns, const char *patt); + iterator att_find(const char *ns, const wchar_t *patt); + void unlink(); #endif }; #endif #ifndef WITH_LEANER #ifdef __cplusplus -class soap_dom_element_iterator -{ public: - struct soap_dom_element *elt; +class SOAP_CMAC soap_dom_element_iterator +{ + public: + typedef ptrdiff_t difference_type; + typedef soap_dom_element value_type; + typedef soap_dom_element& reference; + typedef soap_dom_element* pointer; + typedef std::forward_iterator_tag iterator_category; + struct soap_dom_element *iter; + struct soap_dom_element *stop; const char *nstr; const char *name; int type; + bool deep; bool operator==(const soap_dom_element_iterator&) const; bool operator!=(const soap_dom_element_iterator&) const; - struct soap_dom_element &operator*() const; - soap_dom_element_iterator &operator++(); + struct soap_dom_element& operator*() const; + struct soap_dom_element *operator->() const; + soap_dom_element_iterator& operator++(); + soap_dom_element_iterator operator++(int); soap_dom_element_iterator(); soap_dom_element_iterator(struct soap_dom_element*); ~soap_dom_element_iterator(); @@ -1542,113 +2511,266 @@ class soap_dom_element_iterator #endif #ifndef WITH_LEANER -struct soap_dom_element -{ struct soap_dom_element *next; /* next sibling */ - struct soap_dom_element *prnt; /* parent */ - struct soap_dom_element *elts; /* list of child elements */ - struct soap_dom_attribute *atts; /* list of attributes */ - const char *nstr; /* namespace string */ - char *name; /* element tag name */ - char *data; /* element content data (with SOAP_C_UTFSTRING flag set) */ - wchar_t *wide; /* element content data */ - int type; /* optional: serialized C/C++ data type */ - void *node; /* optional: pointer to serialized C/C++ data */ - char *head; /* leading content before start tag */ - char *tail; /* leading content before end tag */ - struct soap *soap; /* soap context that manages this node */ +struct SOAP_CMAC soap_dom_element +{ + struct soap_dom_element *next; + struct soap_dom_element *prnt; + struct soap_dom_element *elts; + struct soap_dom_attribute *atts; + const char *nstr; + const char *name; + const char *lead; + const char *text; + const char *code; + const char *tail; + const void *node; + int type; + struct soap *soap; #ifdef __cplusplus typedef soap_dom_element_iterator iterator; - struct soap_dom_element &set(const char *nstr, const char *name); - struct soap_dom_element &set(const char *data); - struct soap_dom_element &set(void *node, int type); - struct soap_dom_element &add(struct soap_dom_element*); - struct soap_dom_element &add(struct soap_dom_element&); - struct soap_dom_element &add(struct soap_dom_attribute*); - struct soap_dom_element &add(struct soap_dom_attribute&); - soap_dom_element_iterator begin(); - soap_dom_element_iterator end(); - soap_dom_element_iterator find(const char *nstr, const char *name); - soap_dom_element_iterator find(int type); - void unlink(); - soap_dom_element(); - soap_dom_element(struct soap *soap); - soap_dom_element(struct soap *soap, const char *nstr, const char *name); - soap_dom_element(struct soap *soap, const char *nstr, const char *name, const char *data); - soap_dom_element(struct soap *soap, const char *nstr, const char *name, void *node, int type); + typedef soap_dom_element_iterator const_iterator; + soap_dom_element(struct soap *soap = NULL); + soap_dom_element(const soap_dom_element& elt); + soap_dom_element(struct soap *soap, const char *tag); + soap_dom_element(struct soap *soap, const wchar_t *tag); + soap_dom_element(struct soap *soap, const char *ns, const char *tag); + soap_dom_element(struct soap *soap, const char *ns, const wchar_t *tag); + soap_dom_element(struct soap *soap, const char *ns, const char *tag, const char *str); + soap_dom_element(struct soap *soap, const char *ns, const char *tag, const wchar_t *str); + soap_dom_element(struct soap *soap, const char *ns, const wchar_t *tag, const char *str); + soap_dom_element(struct soap *soap, const char *ns, const wchar_t *tag, const wchar_t *str); +#ifndef WITH_COMPAT + soap_dom_element(struct soap *soap, const char *ns, const char *tag, const std::string& str); + soap_dom_element(struct soap *soap, const char *ns, const char *tag, const std::wstring& str); + soap_dom_element(struct soap *soap, const char *ns, const wchar_t *tag, const std::string& str); + soap_dom_element(struct soap *soap, const char *ns, const wchar_t *tag, const std::wstring& str); +#endif + soap_dom_element(struct soap *soap, const char *ns, const char *tag, const void *nod, int typ); + soap_dom_element(struct soap *soap, const char *ns, const wchar_t *tag, const void *nod, int typ); ~soap_dom_element(); + soap_dom_element& set(const char *ns, const char *tag) { return *soap_elt_set(this, ns, tag); } + soap_dom_element& set(const char *ns, const wchar_t *tag) { return *soap_elt_set_w(this, ns, tag); } + soap_dom_element& set(bool b) { return *soap_elt_bool(this, b); } + soap_dom_element& set(int n) { return *soap_elt_int(this, n); } + soap_dom_element& set(LONG64 n) { return *soap_elt_int(this, n); } + soap_dom_element& set(float x) { return *soap_elt_double(this, x); } + soap_dom_element& set(double x) { return *soap_elt_double(this, x); } + soap_dom_element& set(const char *str) { return *soap_elt_text(this, str); } + soap_dom_element& set(const wchar_t *str) { return *soap_elt_text_w(this, str); } +#ifndef WITH_COMPAT + soap_dom_element& set(const std::string& str) { return *soap_elt_text(this, str.c_str()); } + soap_dom_element& set(const std::wstring& str) { return *soap_elt_text_w(this, str.c_str()); } +#endif + soap_dom_element& set(const void *nod, int typ) { return *soap_elt_node(this, nod, typ); } + soap_dom_element& add(soap_dom_element& elt) { return *soap_add_elt(this, &elt); } + soap_dom_element& add(soap_dom_element *elt) { return *soap_add_elt(this, elt); } + soap_dom_element& add(soap_dom_attribute& att) { return *soap_add_att(this, &att); } + soap_dom_element& add(soap_dom_attribute *att) { return *soap_add_att(this, att); } + soap_dom_element& adds(soap_dom_element& elt) { return *soap_add_elts(this, &elt); } + soap_dom_element& adds(soap_dom_element *elt) { return *soap_add_elts(this, elt); } + soap_dom_element& adds(soap_dom_attribute& att) { return *soap_add_atts(this, &att); } + soap_dom_element& adds(soap_dom_attribute *att) { return *soap_add_atts(this, att); } + soap_dom_element& operator=(bool b) { return *soap_elt_bool(this, b); } + soap_dom_element& operator=(int n) { return *soap_elt_int(this, n); } + soap_dom_element& operator=(LONG64 n) { return *soap_elt_int(this, n); } + soap_dom_element& operator=(float x) { return *soap_elt_double(this, x); } + soap_dom_element& operator=(double x) { return *soap_elt_double(this, x); } + soap_dom_element& operator=(const char *str) { return *soap_elt_text(this, str); } + soap_dom_element& operator=(const wchar_t *str) { return *soap_elt_text_w(this, str); } +#ifndef WITH_COMPAT + soap_dom_element& operator=(const std::string& str) { return *soap_elt_text(this, str.c_str()); } + soap_dom_element& operator=(const std::wstring& str) { return *soap_elt_text_w(this, str.c_str()); } +#endif + soap_dom_element& operator=(const soap_dom_element& elt) { return *soap_elt_copy(this, &elt); } + template soap_dom_element& operator=(const T& nod) { return this->set(&nod, nod.soap_type()); } + template soap_dom_element& operator=(const T *nod) { return this->set(nod, nod->soap_type()); } + template soap_dom_element& operator=(T *nod) { return this->set(nod, nod->soap_type()); } + soap_dom_attribute& att(const char *tag) { return *soap_att(this, NULL, tag); } + soap_dom_attribute& att(const wchar_t *tag) { return *soap_att_w(this, NULL, tag); } + soap_dom_attribute& att(const char *ns, const char *tag) { return *soap_att(this, ns, tag); } + soap_dom_attribute& att(const char *ns, const wchar_t *tag) { return *soap_att_w(this, ns, tag); } + soap_dom_element& elt() { return *soap_elt(this, NULL, NULL); } + soap_dom_element& elt(const char *tag) { return *soap_elt(this, NULL, tag); } + soap_dom_element& elt(const wchar_t *tag) { return *soap_elt_w(this, NULL, tag); } + soap_dom_element& elt(const char *ns, const char *tag) { return *soap_elt(this, ns, tag); } + soap_dom_element& elt(const char *ns, const wchar_t *tag) { return *soap_elt_w(this, ns, tag); } + soap_dom_element& operator[](const char *tag) { return *soap_elt(this, NULL, tag); } + soap_dom_element& operator[](const wchar_t *tag) { return *soap_elt_w(this, NULL, tag); } + soap_dom_element& operator[](size_t n) { return *soap_nth(this, n); } + soap_dom_attribute *att_get(const char *tag) const { return soap_att_get(this, NULL, tag); } + soap_dom_attribute *att_get(const wchar_t *tag) const { return soap_att_get_w(this, NULL, tag); } + soap_dom_attribute *att_get(const char *ns, const char *tag) const { return soap_att_get(this, ns, tag); } + soap_dom_attribute *att_get(const char *ns, const wchar_t *tag) const { return soap_att_get_w(this, ns, tag); } + soap_dom_element *elt_get() const { return soap_elt_get(this, NULL, NULL); } + soap_dom_element *elt_get(const char *tag) const { return soap_elt_get(this, NULL, tag); } + soap_dom_element *elt_get(const wchar_t *tag) const { return soap_elt_get_w(this, NULL, tag); } + soap_dom_element *elt_get(const char *ns, const char *tag) const { return soap_elt_get(this, ns, tag); } + soap_dom_element *elt_get(const char *ns, const wchar_t *tag) const { return soap_elt_get_w(this, ns, tag); } + soap_dom_element *get_next() const { return soap_elt_get_next(this); } + soap_dom_element *get_nth(size_t n) { return soap_elt_get_nth(this, n); } + bool match(const char *pat) const { return soap_elt_match(this, NULL, pat) != 0; } + bool match(const wchar_t *pat) const { return soap_elt_match_w(this, NULL, pat) != 0; } + bool match(const char *ns, const char *pat) const { return soap_elt_match(this, ns, pat) != 0; } + bool match(const char *ns, const wchar_t *pat) const { return soap_elt_match_w(this, ns, pat) != 0; } + const char *ns() const { return this->nstr; } + const char *tag() const { return this->name; } + soap_dom_element *parent() { return this->prnt; } + size_t depth() const { return soap_elt_depth(this); } + size_t index() const { return soap_elt_index(this); } + size_t len() const { return soap_elt_len(this); } + size_t nth() const { return soap_elt_nth(this); } + size_t elt_size() { return soap_elt_size(this, NULL, NULL); } + size_t elt_size(const char *pat, int typ = 0) { return elt_size(NULL, pat, typ); } + size_t elt_size(const char *ns, const char *pat, int typ = 0) { return soap_elt_size_type(this, ns, pat, typ); } + size_t att_size() { return soap_att_size(this, NULL, NULL); } + size_t att_size(const char *pat) { return att_size(NULL, pat); } +#ifndef WITH_COMPAT + size_t att_size(const std::string& pat) { return att_size(NULL, pat); } +#endif + size_t att_size(const char *ns, const char *pat) { return soap_att_size(this, ns, pat); } +#ifndef WITH_COMPAT + size_t att_size(const char *ns, const std::string& pat) { return soap_att_size(this, ns, pat.c_str()); } +#endif + bool is_true() const { return soap_elt_is_true(this) != 0; } + bool is_false() const { return soap_elt_is_false(this) != 0; } + LONG64 get_int() const { return soap_elt_get_LONG64(this); } + double get_double() const { return soap_elt_get_double(this); } + const char *get_text() const { return this->text; } + const void *get_node(int typ) const { return soap_elt_get_node(this, typ); } + int get_type(const void **nod) const { return soap_elt_get_type(this, nod); } + operator bool() const { return soap_elt_is_true(this) != 0; } + operator int() const { return soap_elt_get_int(this); } + operator LONG64() const { return soap_elt_get_LONG64(this); } + operator double() const { return soap_elt_get_double(this); } + operator const char*() const { return this->text; } + const_iterator cbegin() { return this->begin(); } + const_iterator cend() { return this->end(); } + iterator begin(); + iterator end() { return soap_dom_element_iterator(NULL); } + iterator elt_begin() { return soap_dom_element_iterator(this->elts); } + iterator elt_end() { return soap_dom_element_iterator(NULL); } + soap_dom_attribute::iterator att_begin() { return soap_dom_attribute_iterator(this->atts); } + soap_dom_attribute::iterator att_end() { return soap_dom_attribute_iterator(NULL); } + iterator find(const char *pat, int typ = 0) { return find(NULL, pat, typ); } + iterator find(const wchar_t *pat, int typ = 0) { return find(NULL, pat, typ); } + iterator find(const char *ns, const char *pat, int typ = 0); + iterator find(const char *ns, const wchar_t *pat, int typ = 0); + iterator find(int typ); + iterator elt_find(const char *pat, int typ = 0) { return elt_find(NULL, pat, typ); } + iterator elt_find(const wchar_t *pat, int typ = 0) { return elt_find(NULL, pat, typ); } + iterator elt_find(const char *ns, const char *pat, int typ = 0); + iterator elt_find(const char *ns, const wchar_t *pat, int typ = 0); + iterator elt_find(int typ); + soap_dom_attribute::iterator att_find(const char *pat) { return att_find(NULL, pat); } + soap_dom_attribute::iterator att_find(const wchar_t *pat) { return att_find(NULL, pat); } + soap_dom_attribute::iterator att_find(const char *ns, const char *pat); + soap_dom_attribute::iterator att_find(const char *ns, const wchar_t *pat); + void unlink(); #endif }; -SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_dom_next_element(struct soap_dom_element *elt); -SOAP_FMAC1 struct soap_dom_attribute * SOAP_FMAC2 soap_dom_next_attribute(struct soap_dom_attribute *att); #endif -#if defined(__cplusplus) && !defined(WITH_LEAN) && !defined(WITH_COMPAT) -} +#ifndef WITH_LEANER +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_dup_xsd__anyType(struct soap *soap, struct soap_dom_element *d, const struct soap_dom_element *a); +SOAP_FMAC1 void SOAP_FMAC2 soap_del_xsd__anyType(const struct soap_dom_element *a); +SOAP_FMAC1 struct soap_dom_attribute * SOAP_FMAC2 soap_dup_xsd__anyAttribute(struct soap *soap, struct soap_dom_attribute *d, const struct soap_dom_attribute *a); +SOAP_FMAC1 void SOAP_FMAC2 soap_del_xsd__anyAttribute(const struct soap_dom_attribute *a); +SOAP_FMAC1 int SOAP_FMAC2 soap_dom_call(struct soap *soap, const char *endpoint, const char *action, const struct soap_dom_element *in, struct soap_dom_element *out); +#endif + +#ifndef WITH_LEANER +#if defined(__cplusplus) && !defined(WITH_COMPAT) extern std::ostream &operator<<(std::ostream&, const struct soap_dom_element&); extern std::istream &operator>>(std::istream&, struct soap_dom_element&); + +SOAP_FMAC1 int SOAP_FMAC2 soap_dom_call(struct soap *soap, const char *endpoint, const char *action, const struct soap_dom_element& in, struct soap_dom_element& out); +SOAP_FMAC1 int SOAP_FMAC2 soap_dom_call(struct soap *soap, const char *endpoint, const char *action, const struct soap_dom_element *in, struct soap_dom_element& out); +SOAP_FMAC1 int SOAP_FMAC2 soap_dom_call(struct soap *soap, const char *endpoint, const char *action, const struct soap_dom_element& in, struct soap_dom_element *out); +#endif +#endif + +#if defined(__cplusplus) extern "C" { #endif /******************************************************************************/ -#ifdef WIN32 -# ifdef SOAP_STD_EXPORTS -# define SOAP_STD_API __declspec(dllexport) -# else -# define SOAP_STD_API -# endif -#else -# define SOAP_STD_API -#endif - -struct SOAP_STD_API soap -{ short state; /* 0 = uninitialized, 1 = initialized, 2 = copy of another soap struct */ - short version; /* 1 = SOAP1.1 and 2 = SOAP1.2 (set automatically from namespace URI in nsmap table) */ - soap_mode mode; - soap_mode imode; - soap_mode omode; - const char *float_format; /* user-definable format string for floats (<1024 chars) */ - const char *double_format; /* user-definable format string for doubles (<1024 chars) */ - const char *dime_id_format; /* user-definable format string for integer DIME id ( 0, gives socket recv timeout in seconds, < 0 in usec */ - int send_timeout; /* when > 0, gives socket send timeout in seconds, < 0 in usec */ - int connect_timeout; /* when > 0, gives socket connect() timeout in seconds, < 0 in usec */ - int accept_timeout; /* when > 0, gives socket accept() timeout in seconds, < 0 in usec */ - int socket_flags; /* socket recv() and send() flags, e.g. set to MSG_NOSIGNAL to disable sigpipe */ - int connect_flags; /* connect() SOL_SOCKET sockopt flags, e.g. set to SO_DEBUG to debug socket */ - int bind_flags; /* bind() SOL_SOCKET sockopt flags, e.g. set to SO_REUSEADDR to enable reuse */ - int accept_flags; /* accept() SOL_SOCKET sockopt flags */ - unsigned short linger_time; /* linger time for SO_LINGER option */ - const struct Namespace *namespaces; /* Pointer to global namespace mapping table */ - struct Namespace *local_namespaces; /* Local namespace mapping table */ - struct soap_nlist *nlist; /* namespace stack */ - struct soap_blist *blist; /* block allocation stack */ - struct soap_clist *clist; /* class instance allocation list */ - void *alist; /* memory allocation (malloc) list */ +struct SOAP_CMAC soap +{ + short state; /* 0 = uninitialized, 1 = initialized, 2 = copy of another soap struct */ + short version; /* 1 = SOAP1.1 and 2 = SOAP1.2 (set automatically from namespace URI in nsmap table), 0 indicates non-SOAP content */ + soap_mode mode; /* internal mode flag, combines imode/omode */ + soap_mode imode; /* input mode flag set with soap_init1(), soap_new1(), or soap_set_imode() */ + soap_mode omode; /* ouput mode flag set with soap_init1(), soap_new1(), or soap_set_omode() */ + const char *float_format; /* user-definable format string for floats (<1024 chars) */ + const char *double_format; /* user-definable format string for doubles (<1024 chars) */ + const char *long_double_format;/* user-definable format string for long doubles (<1024 chars) */ + const char *dime_id_format; /* user-definable format string for integer DIME id ( 0, sets max message size that can be received */ + int recv_timeout; /* user-definable, when > 0, sets socket recv stall timeout in seconds, < 0 in usec */ + int send_timeout; /* user-definable, when > 0, sets socket send stall timeout in seconds, < 0 in usec */ + int transfer_timeout; /* user-definable, when > 0, sets socket total transfer timeout in seconds, < 0 in usec */ + int connect_timeout; /* user-definable, when > 0, sets socket connect() timeout in seconds, < 0 in usec */ + int accept_timeout; /* user-definable, when > 0, sets socket accept() timeout in seconds, < 0 in usec */ + int socket_flags; /* user-definable socket recv() and send() flags, e.g. set to MSG_NOSIGNAL to disable sigpipe */ + int connect_flags; /* user-definable connect() SOL_SOCKET sockopt flags, e.g. set to SO_DEBUG to debug socket */ + int connect_retry; /* number of times to retry connecting (exponential backoff), zero by default */ + int bind_flags; /* user-definable bind() SOL_SOCKET sockopt flags, e.g. set to SO_REUSEADDR to enable reuse */ + short bind_inet6; /* user-definable, when > 0 use AF_INET6 instead of PF_UNSPEC (only with -DWITH_IPV6) */ + short bind_v6only; /* user-definable, when > 0 use IPPROTO_IPV6 sockopt IPV6_V6ONLY (only with -DWITH_IPV6) */ + int accept_flags; /* user-definable accept() SOL_SOCKET sockopt flags */ +#ifdef WITH_SELF_PIPE + int pipe_fd[2]; /* self pipe trick file descriptors used to close the select call from another thread */ +#endif + int sndbuf; /* user-definable SO_SNDBUF setsockopt value */ + int rcvbuf; /* user-definable SO_RCVBUF setsockopt value */ + unsigned short linger_time; /* user-definable linger time for SO_LINGER option */ + unsigned int maxlevel; /* user-definable max XML nesting depth levels, initialized to SOAP_MAXLEVEL */ + long maxlength; /* user-definable max string length, initialized to SOAP_MAXLENGTH, maxlength<=0 is unbounded */ + size_t maxoccurs; /* user-definable max array/container size, initialized to SOAP_MAXOCCURS */ + const char *http_version; /* HTTP version used "1.0" or "1.1" */ + const char *http_content; /* optional custom HTTP content type (with SOAP_PUT, SOAP_POST_FILE, SOAP_FILE) */ + const char *http_extra_header;/* optional custom HTTP header of the form 'key: val' (multiple headers should be separated in the string by \r\n - crlf) */ + const char *encodingStyle; /* default = "" which means that SOAP encoding is used */ + const char *actor; /* SOAP-ENV:actor or role attribute value */ + const char *lang; /* user-definable xml:lang attribute value of SOAP-ENV:Text */ + const struct Namespace *namespaces; /* Pointer to global namespace mapping table */ + struct Namespace *local_namespaces; /* Local namespace mapping table */ + struct soap_nlist *nlist; /* namespace stack */ + struct soap_blist *blist; /* block allocation stack */ + struct soap_clist *clist; /* class instance allocation list */ + void *alist; /* memory allocation (malloc) list */ +#if !defined(WITH_LEANER) || !defined(WITH_NOIDREF) struct soap_ilist *iht[SOAP_IDHASH]; +#endif struct soap_plist *pht[SOAP_PTRHASH]; - struct soap_pblk *pblk; /* plist block allocation */ - short pidx; /* plist block allocation */ + struct soap_pblk *pblk; /* plist block allocation */ + short pidx; /* plist block allocation */ + short shaky; /* objects in reallocatable containers are on shaky grounds */ struct SOAP_ENV__Header *header; struct SOAP_ENV__Fault *fault; int idnum; - void *user; /* to pass user-defined data */ - struct soap_plugin *plugins; /* linked list of plug-in data */ - const char *userid; /* HTTP Basic authorization userid */ - const char *passwd; /* HTTP Basic authorization passwd */ - int (*fpost)(struct soap*, const char*, const char*, int, const char*, const char*, size_t); - int (*fget)(struct soap*); - int (*fput)(struct soap*); - int (*fdel)(struct soap*); - int (*fhead)(struct soap*); - int (*fform)(struct soap*); + void *user; /* for user to pass user-defined data to callbacks */ + void *data[4]; /* extension data = {smdevp, mecevp, ...} */ + struct soap_plugin *plugins; /* linked list of plug-in data */ + const char *bearer; /* HTTP authorization bearer token value */ + const char *userid; /* HTTP Basic authorization userid */ + const char *passwd; /* HTTP Basic authorization passwd */ + const char *authrealm; /* HTTP authentication realm (and NTLM domain) */ +#if !defined(WITH_LEAN) || defined(WITH_NTLM) + const char *ntlm_challenge; /* HTTP NTLM challenge key string */ + short ntlm_auth; /* HTTP NTLM authentication type */ +#endif + int (*fpost)(struct soap*, const char*, const char*, int, const char*, const char*, ULONG64); + int (*fget)(struct soap*); /* HTTP GET hook (not set by default) */ + int (*fput)(struct soap*); /* HTTP PUT hook (handled as POST by default) */ + int (*fpatch)(struct soap*); /* HTTP PATCH hook (handled as POST by default) */ + int (*fdel)(struct soap*); /* HTTP DELETE hook (not set by default) */ + int (*fopt)(struct soap*); /* HTTP OPTIONS hook (not set by default) */ + int (*fhead)(struct soap*); /* HTTP HEAD hook (not set by default) */ + int (*fform)(struct soap*); /* HTTP/HTML form handler for plugins */ int (*fposthdr)(struct soap*, const char*, const char*); - int (*fresponse)(struct soap*, int, size_t); + int (*fresponse)(struct soap*, int, ULONG64); int (*fparse)(struct soap*); int (*fparsehdr)(struct soap*, const char*, const char*); int (*fheader)(struct soap*); @@ -1664,15 +2786,26 @@ struct SOAP_STD_API soap size_t (*frecv)(struct soap*, char*, size_t); int (*fpoll)(struct soap*); void (*fseterror)(struct soap*, const char **c, const char **s); + int (*fencoding)(struct soap*, const char*); int (*fignore)(struct soap*, const char*); int (*fserveloop)(struct soap*); void *(*fplugin)(struct soap*, const char*); - void *(*fmalloc)(struct soap*, size_t); #ifndef WITH_LEANER - int (*fprepareinit)(struct soap*); + int (*fsvalidate)(struct soap*, const char*, const char*); + int (*fwvalidate)(struct soap*, const char*, const wchar_t*); + int (*feltbegin)(struct soap*, const char*); + int (*feltendin)(struct soap*, const char*, const char*); + int (*feltbegout)(struct soap*, const char*, int, const char*); + int (*feltendout)(struct soap*, const char*); + int (*fprepareinitsend)(struct soap*); + int (*fprepareinitrecv)(struct soap*); int (*fpreparesend)(struct soap*, const char*, size_t); int (*fpreparerecv)(struct soap*, const char*, size_t); - int (*fpreparefinal)(struct soap*); + int (*fpreparefinalsend)(struct soap*); + int (*fpreparefinalrecv)(struct soap*); + int recverror; /* last soap_recv_raw error code for filterrecv */ + int (*ffiltersend)(struct soap*, const char**, size_t*); + int (*ffilterrecv)(struct soap*, char*, size_t*, size_t); void *(*fdimereadopen)(struct soap*, void*, const char*, const char*, const char*); void *(*fdimewriteopen)(struct soap*, const char*, const char*, const char*); void (*fdimereadclose)(struct soap*, void*); @@ -1686,36 +2819,96 @@ struct SOAP_STD_API soap size_t (*fmimeread)(struct soap*, void*, char*, size_t); int (*fmimewrite)(struct soap*, void*, const char*, size_t); #endif - SOAP_SOCKET master; - SOAP_SOCKET socket; -#if defined(__cplusplus) && !defined(WITH_LEAN) && !defined(WITH_COMPAT) - std::ostream *os; - std::istream *is; + SOAP_SOCKET master; /* socket bound to TCP/IP port */ + SOAP_SOCKET socket; /* socket to send and receive */ + SOAP_SOCKET sendsk; /* socket to send (overrides ::socket) */ + SOAP_SOCKET recvsk; /* socket to receive (overrides ::socket) */ +#if defined(__cplusplus) && !defined(WITH_COMPAT) + std::ostream *os; /* C++ only: ostream to send */ + std::istream *is; /* C++ only: istream to receive */ #else - void *os; /* preserve struct size */ - void *is; /* preserve struct size */ + const char **os; /* C only: pointer to a const char*, will be set to point to the string output */ + const char *is; /* C only: a const char* to read from (soap->is will advance) */ #endif #ifndef UNDER_CE - int sendfd; - int recvfd; + int sendfd; /* int file descriptor for sending */ + int recvfd; /* int file descriptor for receiving */ #else - FILE *sendfd; - FILE *recvfd; -#endif - size_t bufidx; /* index in soap.buf[] */ - size_t buflen; /* length of soap.buf[] content */ - soap_wchar ahead; /* parser lookahead */ - short cdata; /* CDATA parser state */ - short body; /* parsed XML element has a body or not */ - unsigned int level; /* XML nesting level */ - size_t count; /* message length counter */ - size_t length; /* message length as set by HTTP header */ - char *labbuf; /* look-aside buffer */ - size_t lablen; /* look-aside buffer allocated length */ - size_t labidx; /* look-aside buffer index to available part */ + FILE *sendfd; /* WinCE FILE* to send */ + FILE *recvfd; /* WinCE FILE* to receive */ +#endif +#if defined(WITH_OPENSSL) /* OpenSSL */ + int (*fsslauth)(struct soap*); + int (*fsslverify)(int, X509_STORE_CTX*); + BIO *bio; + SSL *ssl; + SSL_CTX *ctx; + SSL_SESSION *session; + const char *dhfile; + const char *randfile; +#elif defined(WITH_GNUTLS) /* GNUTLS */ + int (*fsslauth)(struct soap*); + void *fsslverify; + gnutls_certificate_credentials_t xcred; /* cert pointer */ + gnutls_anon_client_credentials_t acred; /* anon pointer */ + gnutls_priority_t cache; /* priority cache pointer */ + gnutls_session_t session; /* session pointer */ + gnutls_dh_params_t dh_params; + gnutls_rsa_params_t rsa_params; +#elif defined(WITH_WOLFSSL) /* WolfSSL */ + int (*fsslauth)(struct soap*); + VerifyCallback fsslverify; /* callback to verify certificates */ + void *bio; /* N/A */ + WOLFSSL *ssl; /* ssl socket */ + WOLFSSL_CTX *ctx; /* environment */ + void *session; /* N/A */ + const char *dhfile; /* N/A */ + const char *randfile; /* N/A */ +#elif defined(WITH_SYSTEMSSL) /* SYSTEM SSL */ + int (*fsslauth)(struct soap*); + void *fsslverify; /* N/A */ + void *bio; /* N/A */ + gsk_handle ssl; /* ssl socket */ + gsk_handle ctx; /* environment */ + void *session; /* N/A */ + const char *dhfile; /* N/A */ + const char *randfile; /* N/A */ +#else /* No SSL/TLS */ + void *fsslauth; /* dummy members, to preserve struct size */ + void *fsslverify; + void *bio; + void *ssl; + void *ctx; + void *session; + void *dh_params; + void *rsa_params; +#endif + unsigned short ssl_flags; + const char *keyfile; + const char *keyid; + const char *password; + const char *cafile; + const char *capath; + const char *crlfile; + char session_host[SOAP_TAGLEN]; + int session_port; + size_t bufidx; /* index in soap.buf[] */ + size_t buflen; /* length of soap.buf[] content */ + soap_wchar ahead; /* parser lookahead */ + short cdata; /* CDATA parser state */ + short body; /* HTTP or XML element has a body (1) or not (0) */ + unsigned int level; /* XML nesting level */ +#ifndef WITH_LEAN + ULONG64 start; /* start time of send/recv (value cast to time_t) */ +#endif + ULONG64 count; /* message length counter */ + ULONG64 length; /* message length as was set by HTTP header received */ + char *labbuf; /* look-aside buffer */ + size_t lablen; /* look-aside buffer allocated length */ + size_t labidx; /* look-aside buffer index to available part */ char buf[SOAP_BUFLEN];/* send and receive buffer */ - char msgbuf[1024]; /* in/out buffer for HTTP/MIME headers >=1024 bytes */ - char tmpbuf[1024]; /* in/out buffer for HTTP/MIME headers, simpleType values, element and attribute tag names, and DIME must be >=1024 bytes */ + char msgbuf[SOAP_TMPLEN]; /* in/out buffer for HTTP/MIME headers and short messages, must be >=1024 bytes */ + char tmpbuf[SOAP_TMPLEN]; /* in/out buffer for HTTP/MIME headers, simpleType values, element and attribute tag names, and DIME must be >=1024 bytes */ char tag[SOAP_TAGLEN]; char id[SOAP_TAGLEN]; char href[SOAP_TAGLEN]; @@ -1723,41 +2916,53 @@ struct SOAP_STD_API soap char arrayType[SOAP_TAGLEN]; char arraySize[SOAP_TAGLEN]; char arrayOffset[SOAP_TAGLEN]; - short other; - short position; + int position; int positions[SOAP_MAXDIMS]; + struct soap_attribute *attributes; /* attribute list */ + short other; short root; - struct soap_attribute *attributes; /* attribute list */ - short encoding; /* when set, output encodingStyle */ - short mustUnderstand; /* a mustUnderstand element was parsed or is output */ - short null; /* parsed XML is xsi:nil */ - short ns; /* when not set, output full xmlns bindings */ - short part; /* parsing state */ - short alloced; + short encoding; /* when set, output encodingStyle */ + short mustUnderstand; /* a mustUnderstand element was parsed or is output */ + short null; /* parsed XML is xsi:nil */ + short ns; /* zero to output all xmlns */ + short part; /* SOAP part state (header or body) */ + short event; /* engine events and states for use by plugins */ short peeked; + unsigned int evlev; /* event level */ + int alloced; size_t chunksize; size_t chunkbuflen; char endpoint[SOAP_TAGLEN]; char path[SOAP_TAGLEN]; char host[SOAP_TAGLEN]; - char *action; - char *authrealm; /* HTTP authentication realm */ - char *prolog; /* XML declaration prolog */ - unsigned long ip; /* IP number */ - int port; /* port number */ - short keep_alive; /* connection should be kept open */ - short tcp_keep_alive; /* enable SO_KEEPALIVE */ - unsigned int tcp_keep_idle; /* set TCP_KEEPIDLE */ - unsigned int tcp_keep_intvl; /* set TCP_KEEPINTVL */ - unsigned int tcp_keep_cnt; /* set TCP_KEEPCNT */ - unsigned int max_keep_alive; /* maximum keep-alive session (default=100) */ + char *action; /* SOAPAction string */ + const char *prolog; /* XML declaration prolog */ + unsigned int ip; /* IP number retrieved from request */ + unsigned int ip6[4]; /* same for IPv6: upper in ip6[0] to lower in ip6[3] requires WITH_IPV6 */ + int port; /* port number */ + const char *override_host; /* to override the client-side host name/IP when connecting */ + int override_port; /* to override client-side port number when connecting */ + int keep_alive; /* connection should be kept open (-1, 0, or counts down) */ + int tcp_keep_alive; /* enable SO_KEEPALIVE */ + unsigned int tcp_keep_idle; /* set TCP_KEEPIDLE */ + unsigned int tcp_keep_intvl; /* set TCP_KEEPINTVL */ + unsigned int tcp_keep_cnt; /* set TCP_KEEPCNT */ + int max_keep_alive; /* maximum keep-alive session (default=100) 0 to always keep open */ const char *proxy_http_version;/* HTTP version of proxy "1.0" or "1.1" */ - const char *proxy_host; /* Proxy Server host name */ - int proxy_port; /* Proxy Server port (default = 8080) */ - const char *proxy_userid; /* Proxy Authorization user name */ - const char *proxy_passwd; /* Proxy Authorization password */ - const char *proxy_from; /* X-Forwarding-For header returned by proxy */ - int status; /* -1 when request, else error code to be returned by server */ + const char *proxy_host; /* Proxy Server host name */ + int proxy_port; /* Proxy Server port (default = 8080) */ + const char *proxy_userid; /* Proxy Authorization user name */ + const char *proxy_passwd; /* Proxy Authorization password */ + const char *proxy_from; /* X-Forwarding-For header returned by proxy */ + const char *origin; /* Origin header received */ + const char *cors_origin; /* CORS Allow-Origin header returned by server */ + const char *cors_allow; /* CORS Allow-Origin header default value of "*" */ + const char *cors_method; /* CORS Request-Method header received */ + const char *cors_header; /* CORS Request-Headers header received */ + const char *cors_methods; /* CORS Allow-Methods header returned by server */ + const char *cors_headers; /* CORS Allow-Headers header returned by server */ + const char *x_frame_options; /* "DENY", "SAMEORIGIN" (default), or "ALLOW-FROM uri" */ + int status; /* HTTP status code, HTTP method, or other error code */ int error; int errmode; int errnum; @@ -1767,78 +2972,56 @@ struct SOAP_STD_API soap struct soap_mime mime; struct soap_xlist *xlist; #endif -#if !defined(WITH_LEAN) || defined(SOAP_DEBUG) const char *logfile[SOAP_MAXLOGS]; FILE *fdebug[SOAP_MAXLOGS]; struct soap_mlist *mht[SOAP_PTRHASH]; -#endif #ifndef WITH_LEAN - const char *c14ninclude; - const char *c14nexclude; + const char *wsuid; /* space-separated string of element tags */ + const char *c14nexclude; /* space-separated string of prefixes for c14n exclusion */ + const char *c14ninclude; /* space-separated string of prefixes for c14n inclusion */ +#endif struct soap_cookie *cookies; const char *cookie_domain; const char *cookie_path; int cookie_max; -#endif #ifndef WITH_NOIO - int ipv6_multicast_if; /* always include this to keep the soap struct size the same in v4 and v6 */ - char* ipv4_multicast_if; /* always include this to keep the soap struct size the same in v4 and v6 */ - int ipv4_multicast_ttl; /* multicast scope */ -#ifdef WITH_IPV6 - struct sockaddr_storage peer; /* IPv6: set by soap_accept and by UDP recv */ -#else - struct sockaddr_in peer; /* IPv4: set by soap_connect/soap_accept and by UDP recv */ -#endif -#endif + unsigned int ipv6_multicast_if; /* in_addr_t in6addr->sin6_scope_id IPv6 value */ + char* ipv4_multicast_if; /* IP_MULTICAST_IF IPv4 setsockopt interface_addr */ + unsigned char ipv4_multicast_ttl; /* IP_MULTICAST_TTL value 0..255 */ + const char *client_addr; /* when non-NULL, client binds to this address before connect */ + const char *client_addr_ipv6; /* WITH_IPV6: when non-NULL and client_addr is non-NULL and when connecting to a IPv6 server, client binds to this IPv6 address instead of client_addr */ + int client_port; /* when nonnegative, client binds to this port before connect */ + const char *client_interface; /* when non-NULL, override client-side interface address using this address */ + union { + struct sockaddr addr; + struct sockaddr_in in; + struct sockaddr_storage storage; + } peer; /* set by soap_connect/soap_accept and by UDP recv */ size_t peerlen; -#ifdef WITH_OPENSSL - int (*fsslauth)(struct soap*); - int (*fsslverify)(int, X509_STORE_CTX*); - BIO *bio; - SSL *ssl; - SSL_CTX *ctx; - SSL_SESSION *session; -#else - void *fsslauth; /* dummy members, to preserve struct size */ - void *fsslverify; - void *bio; - void *ssl; - void *ctx; - void *session; #endif - unsigned short ssl_flags; - const char *keyfile; - const char *password; - const char *dhfile; - const char *cafile; - const char *capath; - const char *crlfile; - const char *randfile; - char session_host[SOAP_TAGLEN]; - int session_port; -#ifdef WITH_C_LOCALE - locale_t c_locale; /* set to C locale by default */ +#ifdef SOAP_LOCALE_T + SOAP_LOCALE_T c_locale; /* if this does not compile, use ./configure --enable-xlocale or compile with -DWITH_INCLUDE_XLOCALE_H, or use -DWITH_NO_C_LOCALE to disable locale support */ #else void *c_locale; #endif #ifdef WITH_ZLIB - z_stream *d_stream; /* decompression stream */ - uLong z_crc; /* internal gzip crc */ + z_stream *d_stream; /* decompression stream */ + uLong z_crc; /* internal gzip crc */ #else - void *d_stream; /* dummy members, to preserve struct size */ + void *d_stream; /* dummy members, to preserve struct size */ soap_int32 z_crc; #endif - const char *z_dict; /* support for zlib static dictionaries */ + const char *z_dict; /* support for zlib static dictionaries */ unsigned int z_dict_len; - short zlib_state; /* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_INFLATE */ - short zlib_in; /* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_GZIP */ - short zlib_out; /* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_GZIP */ - char *z_buf; /* buffer */ + short zlib_state; /* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_INFLATE */ + short zlib_in; /* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_GZIP */ + short zlib_out; /* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_GZIP */ + char *z_buf; /* buffer */ size_t z_buflen; - unsigned short z_level; /* compression level to be used (0=none, 1=fast to 9=best) */ - float z_ratio_in; /* detected compression ratio compressed_length/length of inbound message */ - float z_ratio_out; /* detected compression ratio compressed_length/length of outbound message */ -#ifdef WMW_RPM_IO + unsigned short z_level; /* compression level to be used (0=none, 1=fast to 9=best) */ + float z_ratio_in; /* detected compression ratio compressed_length/length of inbound message */ + float z_ratio_out; /* detected compression ratio compressed_length/length of outbound message */ +#ifdef WMW_RPM_IO /* vxWorks compatibility */ void *rpmreqid; #endif #ifdef __cplusplus @@ -1846,73 +3029,96 @@ struct SOAP_STD_API soap soap(soap_mode); soap(soap_mode, soap_mode); soap(const struct soap&); - virtual ~soap(); -#else - void (*dummy)(); + struct soap& operator=(const struct soap&); + void destroy(); + ~soap(); /* no virtual methods, so sizeof(soap) should be the same in C and C++ */ #endif }; struct soap_code_map -{ long code; +{ + LONG64 code; const char *string; }; /* forwarding list */ struct soap_flist -{ struct soap_flist *next; +{ + struct soap_flist *next; int type; void *ptr; unsigned int level; - size_t len; - void (*fcopy)(struct soap*, int, int, void*, size_t, const void*, size_t); + size_t index; + void (*finsert)(struct soap*, int, int, void*, size_t, const void*, void**); }; /* id-ref forwarding list */ struct soap_ilist -{ struct soap_ilist *next; +{ + struct soap_ilist *next; int type; size_t size; + void *ptr; + void **spine; void *link; void *copy; struct soap_flist *flist; - void *ptr; - unsigned int level; + void *smart; + short shaky; char id[1]; /* the actual id string value flows into the allocated region below this struct */ }; struct soap_plugin -{ struct soap_plugin *next; +{ + struct soap_plugin *next; const char *id; void *data; int (*fcopy)(struct soap *soap, struct soap_plugin *dst, struct soap_plugin *src); void (*fdelete)(struct soap *soap, struct soap_plugin *p); /* should delete fields of plugin only and not free(p) */ }; -#ifndef WITH_NONAMESPACES extern SOAP_NMAC struct Namespace namespaces[]; -#endif #ifndef WITH_LEAN -# define soap_get0(soap) (((soap)->bufidx>=(soap)->buflen && soap_recv(soap)) ? EOF : (unsigned char)(soap)->buf[(soap)->bufidx]) -# define soap_get1(soap) (((soap)->bufidx>=(soap)->buflen && soap_recv(soap)) ? EOF : (unsigned char)(soap)->buf[(soap)->bufidx++]) +# define soap_get0(soap) (((soap)->bufidx>=(soap)->buflen && soap_recv((soap))) ? EOF : (unsigned char)(soap)->buf[(soap)->bufidx]) +# define soap_get1(soap) (((soap)->bufidx>=(soap)->buflen && soap_recv((soap))) ? EOF : (unsigned char)(soap)->buf[(soap)->bufidx++]) +# define soap_getchar(soap) ((soap)->ahead ? soap_getahead((soap)) : soap_get1((soap))) +SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_getahead(struct soap*); #else -soap_wchar soap_get0(struct soap*); -soap_wchar soap_get1(struct soap*); +SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_get0(struct soap*); +SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_get1(struct soap*); +SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_getchar(struct soap*); #endif +#define soap_versioning_paste(name, ext) name##_REQUIRE_lib_v##ext +#define soap_versioning_ext(name, ext) soap_versioning_paste(name, ext) +#define soap_versioning(name) soap_versioning_ext(name, GSOAP_VERSION) + +#define soap_init(soap) soap_init1(soap, SOAP_IO_DEFAULT) +#define soap_init1(soap, mode) soap_init2(soap, mode, mode) +#define soap_init2(soap, imode, omode) soap_versioning(soap_init)(soap, imode, omode) + +#define soap_new() soap_new1(SOAP_IO_DEFAULT) +#define soap_new1(mode) soap_new2(mode, mode) +#define soap_new2(imode, omode) soap_versioning(soap_new)(imode, omode) + #define soap_revget1(soap) ((soap)->bufidx--) #define soap_unget(soap, c) ((soap)->ahead = c) +#define soap_peek(soap) ((soap)->ahead = soap_get(soap)) #define soap_register_plugin(soap, plugin) soap_register_plugin_arg(soap, plugin, NULL) -#define soap_imode(soap, n) ((soap)->mode = (soap)->imode = (n)) +#define soap_mode(soap, n) ((soap)->mode = (soap)->imode = (soap)->omode = (n)) +#define soap_imode(soap, n) ((soap)->imode = (n)) +#define soap_omode(soap, n) ((soap)->omode = (n)) #define soap_set_imode(soap, n) ((soap)->imode |= (n)) #define soap_clr_imode(soap, n) ((soap)->imode &= ~(n)) -#define soap_omode(soap, n) ((soap)->mode = (soap)->omode = (n)) #define soap_set_omode(soap, n) ((soap)->omode |= (n)) #define soap_clr_omode(soap, n) ((soap)->omode &= ~(n)) -#define soap_set_mode(soap, n) ((soap)->imode |= (n), (soap)->omode |= (n)) -#define soap_clr_mode(soap, n) ((soap)->imode &= ~(n), (soap)->omode &= ~(n)) +#define soap_set_mode(soap, n) ((soap)->mode |= (n), (soap)->imode |= (n), (soap)->omode |= (n)) +#define soap_clr_mode(soap, n) ((soap)->mode &= ~(n), (soap)->imode &= ~(n), (soap)->omode &= ~(n)) #define soap_destroy(soap) soap_delete((soap), NULL) +#define SOAP_NO_LINK_TO_DELETE (-2) /* pass to soap_link() as size n: do not manage, smart pointers are self-managing */ + #ifdef HAVE_STRRCHR # define soap_strrchr(s, t) strrchr(s, t) #else @@ -1922,18 +3128,36 @@ soap_wchar soap_get1(struct soap*); #ifdef HAVE_STRTOL # define soap_strtol(s, t, b) strtol(s, t, b) #else - SOAP_FMAC1 long SOAP_FMAC2 soap_strtol(const char *s, char **t, int b); + SOAP_FMAC1 long SOAP_FMAC2 soap_strtol(const char*, char**, int); #endif #ifdef HAVE_STRTOUL # define soap_strtoul(s, t, b) strtoul(s, t, b) #else - SOAP_FMAC1 unsigned long SOAP_FMAC2 soap_strtoul(const char *s, char **t, int b); + SOAP_FMAC1 unsigned long SOAP_FMAC2 soap_strtoul(const char*, char**, int); +#endif + +#if defined(WIN32) && !defined(__MINGW32__) && !defined(__MINGW64__) && !defined(__BORLANDC__) +# define soap_strtoll _strtoi64 +#elif defined(HAVE_STRTOLL) && !defined(soap_strtoll) +# define soap_strtoll strtoll +#elif !defined(soap_strtoll) + SOAP_FMAC1 LONG64 SOAP_FMAC2 soap_strtoll(const char*, char**, int); +#endif + +#if defined(WIN32) && !defined(__MINGW32__) && !defined(__MINGW64__) && !defined(__BORLANDC__) +# define soap_strtoull _strtoui64 +#elif defined(HAVE_STRTOULL) && !defined(soap_strtoull) +# define soap_strtoull strtoull +#elif !defined(soap_strtoull) + SOAP_FMAC1 ULONG64 SOAP_FMAC2 soap_strtoull(const char*, char**, int); #endif #if defined(WITH_OPENSSL) # define soap_random soap_rand() -SOAP_FMAC1 int SOAP_FMAC2 soap_rand(void); + SOAP_FMAC1 int SOAP_FMAC2 soap_rand(void); +#elif defined(UNDER_CE) +# define soap_random (int)Random() #elif defined(HAVE_RANDOM) # define soap_random (int)random() #else @@ -1941,51 +3165,63 @@ SOAP_FMAC1 int SOAP_FMAC2 soap_rand(void); #endif #ifdef WITH_NOIDREF -# define soap_embedded(s, p, t) (0) -# define soap_id_lookup(s, i, p, t, n, k) (p) -# define soap_id_forward(s, h, p, len, st, tt, n, k, fc) (p) -# define soap_reference(s, a, t) (1) -# define soap_array_reference(s, p, a, n, t) (1) -# define soap_embed(s, p, a, n, t, pp) (0) -# define soap_embedded_id(s, i, p, t) (i) -# define soap_is_embedded(s, p) (0) -# define soap_is_single(s, p) (1) -# define soap_lookup_type(s, i) (0) -# define soap_getindependent(s) (0) -# define soap_putindependent(s) (0) -# define soap_getelement(s, n) (n) -# define soap_putelement(s, p, t, i, n) (0) -# define soap_markelement(s, p, n) (0) -#endif - -SOAP_FMAC1 void SOAP_FMAC2 soap_header(struct soap*); -SOAP_FMAC1 void SOAP_FMAC2 soap_fault(struct soap*); -SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultcode(struct soap*); -SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultsubcode(struct soap*); -SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultstring(struct soap*); -SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultdetail(struct soap*); -SOAP_FMAC1 void SOAP_FMAC2 soap_serializeheader(struct soap*); -SOAP_FMAC1 int SOAP_FMAC2 soap_putheader(struct soap*); -SOAP_FMAC1 int SOAP_FMAC2 soap_getheader(struct soap*); -SOAP_FMAC1 void SOAP_FMAC2 soap_serializefault(struct soap*); -SOAP_FMAC1 int SOAP_FMAC2 soap_putfault(struct soap*); -SOAP_FMAC1 int SOAP_FMAC2 soap_getfault(struct soap*); - -SOAP_FMAC1 void SOAP_FMAC2 soap_ssl_init(); -SOAP_FMAC1 int SOAP_FMAC2 soap_poll(struct soap*); +# define soap_embedded(s, p, t) ((void)(s), 0) +# define soap_id_lookup(s, i, p, t, n, k, fb) ((void)(s), (p)) +# define soap_id_forward(s, h, p, i, t, tt, n, k, fi, fb) ((void)(s), (p)) +# define soap_id_nullify(s, i) ((void)(s), (i)) +# define soap_reference(s, a, t) ((void)(s), 1) +# define soap_array_reference(s, p, a, n, t) ((void)(s), 1) +# define soap_attachment_reference(s, p, a, n, t, i, y) ((void)(s), 1) +# define soap_embed(s, p, a, n, t) ((void)(s), 0) +# define soap_embedded_id(s, i, p, t) ((void)(s), (void)(t), i) +# define soap_is_embedded(s, p) ((void)(s), 0) +# define soap_is_single(s, p) ((void)(s), 1) +# define soap_lookup_type(s, i) ((void)(s), 0) +# define soap_getindependent(s) ((void)(s), 0) +# define soap_putindependent(s) ((void)(s), 0) +# define soap_markelement(s, p, t) ((void)(s), 0) +# define soap_begin_shaky(s) ((void)(s), 0) +# define soap_end_shaky(s, f) ((void)(s), (void)(f), 0) +#endif + +/* soap_traverse() traversal/walker routines take walker function arguments */ +typedef void soap_walker(struct soap*, void*, int, const char*, const char*); + +SOAP_FMAC5 int SOAP_FMAC6 soap_serve(struct soap *soap); +SOAP_FMAC5 int SOAP_FMAC6 soap_serve_request(struct soap *soap); + +SOAP_FMAC1 void SOAP_FMAC2 soap_ssl_init(void); +SOAP_FMAC1 void SOAP_FMAC2 soap_ssl_noinit(void); +SOAP_FMAC1 int SOAP_FMAC2 soap_GET(struct soap*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_PUT(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_PATCH(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_POST(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_DELETE(struct soap*, const char*); SOAP_FMAC1 int SOAP_FMAC2 soap_connect_command(struct soap*, int, const char*, const char*); SOAP_FMAC1 int SOAP_FMAC2 soap_connect(struct soap*, const char*, const char*); SOAP_FMAC1 SOAP_SOCKET SOAP_FMAC2 soap_bind(struct soap*, const char*, int, int); SOAP_FMAC1 SOAP_SOCKET SOAP_FMAC2 soap_accept(struct soap*); SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_accept(struct soap*); -SOAP_FMAC1 const char * SOAP_FMAC2 soap_ssl_error(struct soap*, int); +SOAP_FMAC1 const char * SOAP_FMAC2 soap_ssl_error(struct soap*, int ret, int err); +SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_crl(struct soap*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_poll(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_ready(struct soap*); -SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_server_context(struct soap*, unsigned short, const char*, const char*, const char*, const char*, const char*, const char*, const char*); -SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_client_context(struct soap*, unsigned short, const char*, const char*, const char*, const char*, const char*); +#if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE) +SOAP_FMAC1 int SOAP_FMAC2 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_FMAC1 int SOAP_FMAC2 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 +#if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE) +SOAP_FMAC1 int SOAP_FMAC2 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_FMAC1 int SOAP_FMAC2 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_FMAC1 int SOAP_FMAC2 soap_puthttphdr(struct soap*, int status, size_t count); +SOAP_FMAC1 const char * SOAP_FMAC2 soap_http_content_type(struct soap *soap, int status); +SOAP_FMAC1 int SOAP_FMAC2 soap_puthttphdr(struct soap*, int status, ULONG64 count); -SOAP_FMAC1 const char* SOAP_FMAC2 soap_get_header_attribute(struct soap*, const char*, const char*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_http_header_attribute(struct soap*, const char*, const char*); SOAP_FMAC1 const char* SOAP_FMAC2 soap_decode_key(char*, size_t, const char*); SOAP_FMAC1 const char* SOAP_FMAC2 soap_decode_val(char*, size_t, const char*); @@ -1994,7 +3230,6 @@ SOAP_FMAC1 void SOAP_FMAC2 soap_set_endpoint(struct soap*, const char*); SOAP_FMAC1 int SOAP_FMAC2 soap_flush_raw(struct soap*, const char*, size_t); SOAP_FMAC1 int SOAP_FMAC2 soap_flush(struct soap*); SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_get(struct soap*); -SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_getchar(struct soap*); SOAP_FMAC1 int SOAP_FMAC2 soap_tag_cmp(const char*, const char*); SOAP_FMAC1 void SOAP_FMAC2 soap_set_fault(struct soap*); SOAP_FMAC1 int SOAP_FMAC2 soap_sender_fault(struct soap*, const char*, const char*); @@ -2008,11 +3243,21 @@ SOAP_FMAC1 int SOAP_FMAC2 soap_send_raw(struct soap*, const char*, size_t); SOAP_FMAC1 int SOAP_FMAC2 soap_recv_raw(struct soap*); SOAP_FMAC1 int SOAP_FMAC2 soap_recv(struct soap*); SOAP_FMAC1 int SOAP_FMAC2 soap_send(struct soap*, const char*); + +#ifndef WITH_LEANER SOAP_FMAC1 int SOAP_FMAC2 soap_send2(struct soap*, const char*, const char*); SOAP_FMAC1 int SOAP_FMAC2 soap_send3(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_query_send_key(struct soap*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_query_send_val(struct soap*, const char*); +SOAP_FMAC1 char * SOAP_FMAC2 soap_query(struct soap*); +SOAP_FMAC1 char * SOAP_FMAC2 soap_query_key(struct soap*, char**); +SOAP_FMAC1 char * SOAP_FMAC2 soap_query_val(struct soap*, char**); +SOAP_FMAC1 const char * SOAP_FMAC2 soap_query_decode(char*, size_t, const char*); +#endif SOAP_FMAC1 int SOAP_FMAC2 soap_pututf8(struct soap*, unsigned long); SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_getutf8(struct soap*); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_utf8len(const char*); SOAP_FMAC1 int SOAP_FMAC2 soap_putbase64(struct soap*, const unsigned char*, int); SOAP_FMAC1 unsigned char* SOAP_FMAC2 soap_getbase64(struct soap*, int*, int); @@ -2021,46 +3266,56 @@ SOAP_FMAC1 unsigned char* SOAP_FMAC2 soap_gethex(struct soap*, int*); #ifndef WITH_LEANER SOAP_FMAC1 int SOAP_FMAC2 soap_xop_forward(struct soap*, unsigned char**, int*, char**, char**, char**); -SOAP_FMAC1 int SOAP_FMAC2 soap_dime_forward(struct soap*, unsigned char**, int*, char**, char**, char**); +SOAP_FMAC1 int SOAP_FMAC2 soap_attachment_forward(struct soap*, unsigned char**, int*, char**, char**, char**); #endif +SOAP_FMAC1 int SOAP_FMAC2 soap_pointer_lookup(struct soap*, const void *p, int t, struct soap_plist**); +SOAP_FMAC1 int SOAP_FMAC2 soap_pointer_enter(struct soap*, const void *p, const void *a, int n, int t, struct soap_plist**); +SOAP_FMAC1 int SOAP_FMAC2 soap_array_pointer_lookup(struct soap*, const void *p, const void *a, int n, int t, struct soap_plist**); #ifndef WITH_NOIDREF SOAP_FMAC1 int SOAP_FMAC2 soap_pointer_lookup_id(struct soap*, void *p, int t, struct soap_plist**); -SOAP_FMAC1 int SOAP_FMAC2 soap_pointer_lookup(struct soap*, const void *p, int t, struct soap_plist**); -SOAP_FMAC1 int SOAP_FMAC2 soap_pointer_enter(struct soap*, const void *p, const struct soap_array *a, int n, int t, struct soap_plist**); -SOAP_FMAC1 int SOAP_FMAC2 soap_array_pointer_lookup(struct soap*, const void *p, const struct soap_array *a, int n, int t, struct soap_plist**); -SOAP_FMAC1 int SOAP_FMAC2 soap_embed(struct soap *soap, const void *p, const struct soap_array *a, int n, const char *tag, int type); +SOAP_FMAC1 int SOAP_FMAC2 soap_embed(struct soap *soap, const void *p, const void *a, int n, int t); SOAP_FMAC1 struct soap_ilist* SOAP_FMAC2 soap_lookup(struct soap*, const char*); -SOAP_FMAC1 struct soap_ilist* SOAP_FMAC2 soap_enter(struct soap*, const char*); +SOAP_FMAC1 struct soap_ilist* SOAP_FMAC2 soap_enter(struct soap*, const char*, int t, size_t n); SOAP_FMAC1 int SOAP_FMAC2 soap_resolve(struct soap*); SOAP_FMAC1 void SOAP_FMAC2 soap_embedded(struct soap*, const void *p, int t); SOAP_FMAC1 int SOAP_FMAC2 soap_reference(struct soap*, const void *p, int t); -SOAP_FMAC1 int SOAP_FMAC2 soap_array_reference(struct soap*, const void *p, const struct soap_array *a, int n, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_array_reference(struct soap*, const void *p, const void *a, int n, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_attachment_reference(struct soap *soap, const void *p, const void *a, int n, int t, const char *id, const char *type); SOAP_FMAC1 int SOAP_FMAC2 soap_embedded_id(struct soap*, int id, const void *p, int t); SOAP_FMAC1 int SOAP_FMAC2 soap_is_embedded(struct soap*, struct soap_plist*); SOAP_FMAC1 int SOAP_FMAC2 soap_is_single(struct soap*, struct soap_plist*); SOAP_FMAC1 void SOAP_FMAC2 soap_set_embedded(struct soap*, struct soap_plist*); #endif +SOAP_FMAC1 int SOAP_FMAC2 soap_check_and_mark(struct soap *soap, const void *p, int t, char **mark); +SOAP_FMAC1 void * SOAP_FMAC2 soap_mark_lookup(struct soap *soap, const void *p, int t, struct soap_plist **pp, char **mark); +SOAP_FMAC1 int SOAP_FMAC2 soap_mark_cycle(struct soap *soap, struct soap_plist *pp); +SOAP_FMAC1 void SOAP_FMAC2 soap_mark_dup(struct soap *soap, void *a, struct soap_plist *pp); +SOAP_FMAC1 void SOAP_FMAC2 soap_unmark(struct soap *soap, char *mark); SOAP_FMAC1 int SOAP_FMAC2 soap_begin_count(struct soap*); SOAP_FMAC1 int SOAP_FMAC2 soap_end_count(struct soap*); SOAP_FMAC1 int SOAP_FMAC2 soap_begin_send(struct soap*); SOAP_FMAC1 int SOAP_FMAC2 soap_end_send(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_end_send_flush(struct soap*); SOAP_FMAC1 const struct soap_code_map* SOAP_FMAC2 soap_code(const struct soap_code_map*, const char*); -SOAP_FMAC1 long SOAP_FMAC2 soap_code_int(const struct soap_code_map*, const char*, long); +SOAP_FMAC1 LONG64 SOAP_FMAC2 soap_code_int(const struct soap_code_map*, const char*, LONG64); SOAP_FMAC1 const char* SOAP_FMAC2 soap_code_str(const struct soap_code_map*, long); -SOAP_FMAC1 long SOAP_FMAC2 soap_code_bits(const struct soap_code_map*, const char*); +SOAP_FMAC1 LONG64 SOAP_FMAC2 soap_code_bits(const struct soap_code_map*, const char*); SOAP_FMAC1 const char* SOAP_FMAC2 soap_code_list(struct soap*, const struct soap_code_map*, long); +SOAP_FMAC1 int SOAP_FMAC2 soap_binary_search_string(const char**, int, const char*); + SOAP_FMAC1 int SOAP_FMAC2 soap_getline(struct soap*, char*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_begin_serve(struct soap*); SOAP_FMAC1 int SOAP_FMAC2 soap_begin_recv(struct soap*); SOAP_FMAC1 int SOAP_FMAC2 soap_end_recv(struct soap*); SOAP_FMAC1 void* SOAP_FMAC2 soap_malloc(struct soap*, size_t); SOAP_FMAC1 void SOAP_FMAC2 soap_dealloc(struct soap*, void*); -SOAP_FMAC1 struct soap_clist * SOAP_FMAC2 soap_link(struct soap*, void*, int, int, int (*fdelete)(struct soap_clist*)); -SOAP_FMAC1 void SOAP_FMAC2 soap_unlink(struct soap*, const void*); +SOAP_FMAC1 struct soap_clist * SOAP_FMAC2 soap_link(struct soap*, int, int, int (*fdelete)(struct soap*, struct soap_clist*)); +SOAP_FMAC1 int SOAP_FMAC2 soap_unlink(struct soap*, const void*); SOAP_FMAC1 void SOAP_FMAC2 soap_free_temp(struct soap*); SOAP_FMAC1 void SOAP_FMAC2 soap_del(struct soap*); @@ -2069,42 +3324,44 @@ SOAP_FMAC1 void SOAP_FMAC2 soap_track_free(struct soap*, const char*, int, void* #ifndef WITH_NOIDREF SOAP_FMAC1 int SOAP_FMAC2 soap_lookup_type(struct soap*, const char *id); -SOAP_FMAC1 void* SOAP_FMAC2 soap_id_lookup(struct soap*, const char *id, void **p, int t, size_t n, unsigned int k); -SOAP_FMAC1 void* SOAP_FMAC2 soap_id_forward(struct soap*, const char *id, void *p, size_t len, int st, int tt, size_t n, unsigned int k, void(*fcopy)(struct soap*, int, int, void*, size_t, const void*, size_t)); +SOAP_FMAC1 short SOAP_FMAC2 soap_begin_shaky(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_end_shaky(struct soap*, short); +SOAP_FMAC1 void* SOAP_FMAC2 soap_id_lookup(struct soap*, const char *id, void **p, int t, size_t n, unsigned int k, int (*fbase)(int, int)); +SOAP_FMAC1 void* SOAP_FMAC2 soap_id_forward(struct soap*, const char *id, void *p, size_t i, int t, int tt, size_t n, unsigned int k, void(*finsert)(struct soap*, int, int, void*, size_t, const void*, void**), int (*fbase)(int, int)); +SOAP_FMAC1 int SOAP_FMAC2 soap_id_nullify(struct soap*, const char*); #endif -SOAP_FMAC1 void* SOAP_FMAC2 soap_id_enter(struct soap*, const char *id, void *p, int t, size_t n, unsigned int k, const char *type, const char *arrayType, void *(*finstantiate)(struct soap*, int, const char*, const char*, size_t*)); -SOAP_FMAC1 void SOAP_FMAC2 soap_fcopy(struct soap *soap, int st, int tt, void *p, size_t, const void *q, size_t n); +SOAP_FMAC1 void* SOAP_FMAC2 soap_id_enter(struct soap*, const char *id, void *p, int t, size_t n, const char *type, const char *arrayType, void *(*finstantiate)(struct soap*, int, const char*, const char*, size_t*), int (*fbase)(int, int)); +SOAP_FMAC1 void** SOAP_FMAC2 soap_id_smart(struct soap *soap, const char*, int t, size_t n); -SOAP_FMAC1 int SOAP_FMAC2 soap_size(const int *, int); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_size(const int *, int); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_getsizes(const char *, int *, int); SOAP_FMAC1 int SOAP_FMAC2 soap_getoffsets(const char *, const int *, int *, int); -SOAP_FMAC1 int SOAP_FMAC2 soap_getsize(const char *, const char *, int *); -SOAP_FMAC1 int SOAP_FMAC2 soap_getsizes(const char *, int *, int); + SOAP_FMAC1 int SOAP_FMAC2 soap_getposition(const char *, int *); -SOAP_FMAC1 char* SOAP_FMAC2 soap_putsize(struct soap*, const char *, int); SOAP_FMAC1 char* SOAP_FMAC2 soap_putsizesoffsets(struct soap*, const char *, const int *, const int *, int); -SOAP_FMAC1 char* SOAP_FMAC2 soap_putsizes(struct soap*, const char *, const int *, int); -SOAP_FMAC1 char* SOAP_FMAC2 soap_putoffset(struct soap*, int); SOAP_FMAC1 char* SOAP_FMAC2 soap_putoffsets(struct soap*, const int *, int); SOAP_FMAC1 int SOAP_FMAC2 soap_closesock(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_force_closesock(struct soap*); -SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_new(void); -SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_new1(soap_mode); -SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_new2(soap_mode, soap_mode); +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_versioning(soap_new)(soap_mode, soap_mode); SOAP_FMAC1 void SOAP_FMAC2 soap_free(struct soap*); SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_copy(const struct soap*); SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_copy_context(struct soap*, const struct soap*); SOAP_FMAC1 void SOAP_FMAC2 soap_copy_stream(struct soap*, struct soap*); -SOAP_FMAC1 void SOAP_FMAC2 soap_init(struct soap*); -SOAP_FMAC1 void SOAP_FMAC2 soap_init1(struct soap*, soap_mode); -SOAP_FMAC1 void SOAP_FMAC2 soap_init2(struct soap*, soap_mode, soap_mode); +SOAP_FMAC1 void SOAP_FMAC2 soap_free_stream(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_versioning(soap_init)(struct soap*, soap_mode, soap_mode); +SOAP_FMAC1 void SOAP_FMAC2 soap_initialize(struct soap*); SOAP_FMAC1 void SOAP_FMAC2 soap_done(struct soap*); SOAP_FMAC1 void SOAP_FMAC2 soap_cleanup(struct soap*); SOAP_FMAC1 void SOAP_FMAC2 soap_begin(struct soap*); SOAP_FMAC1 void SOAP_FMAC2 soap_end(struct soap*); SOAP_FMAC1 void SOAP_FMAC2 soap_delete(struct soap*, void*); SOAP_FMAC1 void SOAP_FMAC2 soap_delegate_deletion(struct soap*, struct soap*); +#ifdef WITH_SELF_PIPE +SOAP_FMAC1 void SOAP_FMAC2 soap_close_connection(struct soap*); +#endif /* API functions available with DEBUG or SOAP_DEBUG defined: */ SOAP_FMAC1 void SOAP_FMAC2 soap_set_recv_logfile(struct soap*, const char*); @@ -2117,19 +3374,23 @@ SOAP_FMAC1 void SOAP_FMAC2 soap_open_logfile(struct soap*, int); SOAP_FMAC1 const char* SOAP_FMAC2 soap_value(struct soap*); SOAP_FMAC1 int SOAP_FMAC2 soap_match_tag(struct soap*, const char*, const char *); +SOAP_FMAC1 int SOAP_FMAC2 soap_match_att(struct soap*, const char*, const char *); SOAP_FMAC1 int SOAP_FMAC2 soap_match_array(struct soap*, const char*); SOAP_FMAC1 int SOAP_FMAC2 soap_element(struct soap*, const char*, int, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_start_end_out(struct soap*, const char *tag); SOAP_FMAC1 int SOAP_FMAC2 soap_element_begin_out(struct soap*, const char *tag, int id, const char *type); SOAP_FMAC1 int SOAP_FMAC2 soap_array_begin_out(struct soap*, const char *tag, int id, const char *type, const char *offset); SOAP_FMAC1 int SOAP_FMAC2 soap_element_ref(struct soap*, const char *tag, int id, int href); SOAP_FMAC1 int SOAP_FMAC2 soap_element_href(struct soap*, const char *tag, int id, const char *ref, const char *val); SOAP_FMAC1 int SOAP_FMAC2 soap_element_null(struct soap*, const char *tag, int id, const char *type); -SOAP_FMAC1 int SOAP_FMAC2 soap_element_id(struct soap*, const char *tag, int id, const void *p, const struct soap_array *a, int d, const char *type, int n); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_empty(struct soap*, const char *tag, int id, const char *type); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_nil(struct soap*, const char *tag); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_id(struct soap*, const char *tag, int id, const void *p, const void *a, int n, const char *type, int t, char **mark); SOAP_FMAC1 int SOAP_FMAC2 soap_element_result(struct soap*, const char *tag); SOAP_FMAC1 void SOAP_FMAC2 soap_check_result(struct soap*, const char *tag); SOAP_FMAC1 int SOAP_FMAC2 soap_element_end_out(struct soap*, const char *tag); -SOAP_FMAC1 int SOAP_FMAC2 soap_element_start_end_out(struct soap*, const char *tag); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_end(struct soap*, const char *tag); SOAP_FMAC1 int SOAP_FMAC2 soap_attribute(struct soap*, const char*, const char*); @@ -2141,45 +3402,59 @@ SOAP_FMAC1 int SOAP_FMAC2 soap_peek_element(struct soap*); SOAP_FMAC1 void SOAP_FMAC2 soap_retry(struct soap*); SOAP_FMAC1 void SOAP_FMAC2 soap_revert(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_ignore(struct soap*); +SOAP_FMAC1 void* SOAP_FMAC2 soap_memdup(struct soap*, const void*, size_t); SOAP_FMAC1 char* SOAP_FMAC2 soap_strdup(struct soap*, const char*); SOAP_FMAC1 wchar_t* SOAP_FMAC2 soap_wstrdup(struct soap*, const wchar_t*); -SOAP_FMAC1 const char * SOAP_FMAC2 soap_strsearch(const char *big, const char *little); +SOAP_FMAC1 char* SOAP_FMAC2 soap_strtrim(struct soap*, char*); +SOAP_FMAC1 wchar_t* SOAP_FMAC2 soap_wstrtrim(struct soap*, wchar_t*); +SOAP_FMAC1 const char * SOAP_FMAC2 soap_tagsearch(const char *big, const char *little); SOAP_FMAC1 int SOAP_FMAC2 soap_string_out(struct soap*, const char *s, int flag); -SOAP_FMAC1 char* SOAP_FMAC2 soap_string_in(struct soap*, int, long, long); +SOAP_FMAC1 char* SOAP_FMAC2 soap_string_in(struct soap*, int, long, long, const char*); #ifndef WITH_LEANER SOAP_FMAC1 int SOAP_FMAC2 soap_wstring_out(struct soap*, const wchar_t *s, int flag); -SOAP_FMAC1 wchar_t* SOAP_FMAC2 soap_wstring_in(struct soap*, int, long, long); +SOAP_FMAC1 wchar_t* SOAP_FMAC2 soap_wstring_in(struct soap*, int, long, long, const char*); #endif SOAP_FMAC1 int SOAP_FMAC2 soap_match_namespace(struct soap*, const char *, const char*, size_t n1, size_t n2); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_version(struct soap*, short); SOAP_FMAC1 int SOAP_FMAC2 soap_set_namespaces(struct soap*, const struct Namespace*); SOAP_FMAC1 void SOAP_FMAC2 soap_set_local_namespaces(struct soap*); SOAP_FMAC1 void SOAP_FMAC2 soap_pop_namespace(struct soap*); SOAP_FMAC1 struct soap_nlist* SOAP_FMAC2 soap_push_namespace(struct soap*, const char *,const char *); -SOAP_FMAC1 const char* SOAP_FMAC2 soap_current_namespace(struct soap *soap, const char *tag); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_current_namespace_tag(struct soap *soap, const char *tag); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_current_namespace_att(struct soap *soap, const char *tag); SOAP_FMAC1 struct soap_nlist* SOAP_FMAC2 soap_lookup_ns(struct soap *soap, const char *tag, size_t n); SOAP_FMAC1 int SOAP_FMAC2 soap_store_lab(struct soap*, const char*, size_t); SOAP_FMAC1 int SOAP_FMAC2 soap_append_lab(struct soap*, const char*, size_t); -SOAP_FMAC1 struct soap_blist* SOAP_FMAC2 soap_new_block(struct soap*); +SOAP_FMAC1 struct soap_blist* SOAP_FMAC2 soap_alloc_block(struct soap*); SOAP_FMAC1 void* SOAP_FMAC2 soap_push_block(struct soap*, struct soap_blist*, size_t); +SOAP_FMAC1 void* SOAP_FMAC2 soap_push_block_max(struct soap*, struct soap_blist*, size_t); SOAP_FMAC1 void SOAP_FMAC2 soap_pop_block(struct soap*, struct soap_blist*); SOAP_FMAC1 size_t SOAP_FMAC2 soap_size_block(struct soap*, struct soap_blist*, size_t); SOAP_FMAC1 char* SOAP_FMAC2 soap_first_block(struct soap*, struct soap_blist*); SOAP_FMAC1 char* SOAP_FMAC2 soap_next_block(struct soap*, struct soap_blist*); SOAP_FMAC1 size_t SOAP_FMAC2 soap_block_size(struct soap*, struct soap_blist*); -SOAP_FMAC1 char* SOAP_FMAC2 soap_save_block(struct soap*, struct soap_blist*, char*, int); +SOAP_FMAC1 void* SOAP_FMAC2 soap_save_block(struct soap*, struct soap_blist*, char*, int); SOAP_FMAC1 void SOAP_FMAC2 soap_end_block(struct soap*, struct soap_blist*); +SOAP_FMAC1 void SOAP_FMAC2 soap_update_pointers(struct soap *soap, const char *dst, const char *src, size_t len); SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_begin_out(struct soap*); -SOAP_FMAC1 int soap_envelope_end_out(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_end_out(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_http_has_body(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_http_skip_body(struct soap*); +SOAP_FMAC1 char * SOAP_FMAC2 soap_http_get_body(struct soap*, size_t *len); +SOAP_FMAC1 char * SOAP_FMAC2 soap_http_get_form(struct soap*); +SOAP_FMAC1 char * SOAP_FMAC2 soap_http_get_body_prefix(struct soap*, size_t *len, const char *prefix); SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_begin_in(struct soap*); SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_end_in(struct soap*); @@ -2198,14 +3473,17 @@ SOAP_FMAC1 int SOAP_FMAC2 soap_send_empty_response(struct soap*, int status); SOAP_FMAC1 int SOAP_FMAC2 soap_recv_empty_response(struct soap*); SOAP_FMAC1 int SOAP_FMAC2 soap_send_fault(struct soap*); -SOAP_FMAC1 int SOAP_FMAC2 soap_recv_fault(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_recv_fault(struct soap*, int check); #ifndef WITH_NOSTDLIB SOAP_FMAC1 void SOAP_FMAC2 soap_print_fault(struct soap*, FILE*); SOAP_FMAC1 void SOAP_FMAC2 soap_print_fault_location(struct soap*, FILE*); # ifndef WITH_LEAN -# ifdef __cplusplus +# ifndef WITH_COMPAT +# ifdef __cplusplus SOAP_FMAC1 void SOAP_FMAC2 soap_stream_fault(struct soap*, std::ostream&); +SOAP_FMAC1 void SOAP_FMAC2 soap_stream_fault_location(struct soap*, std::ostream&); +# endif # endif SOAP_FMAC1 char* SOAP_FMAC2 soap_sprint_fault(struct soap*, char*, size_t); # endif @@ -2223,15 +3501,24 @@ SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedShort(struct soap*, const char*, unsign SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedInt(struct soap*, const char*, unsigned int*); SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedLong(struct soap*, const char*, unsigned long*); SOAP_FMAC1 int SOAP_FMAC2 soap_s2ULONG64(struct soap*, const char*, ULONG64*); -SOAP_FMAC1 int SOAP_FMAC2 soap_s2string(struct soap*, const char*, char**, long minlen, long maxlen); -SOAP_FMAC1 int SOAP_FMAC2 soap_s2QName(struct soap*, const char*, char**, long minlen, long maxlen); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2char(struct soap*, const char*, char**, int, long minlen, long maxlen, const char *pattern); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2QName(struct soap*, const char*, char**, long minlen, long maxlen, const char *pattern); + +#ifndef WITH_COMPAT +#ifdef __cplusplus +SOAP_FMAC1 int SOAP_FMAC2 soap_s2stdQName(struct soap*, const char*, std::string*, long minlen, long maxlen, const char *pattern); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2stdchar(struct soap*, const char*, std::string*, int, long minlen, long maxlen, const char *pattern); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2stdwchar(struct soap*, const char*, std::wstring*, int, long minlen, long maxlen, const char *pattern); +#endif +#endif #ifndef WITH_LEAN -SOAP_FMAC1 int SOAP_FMAC2 soap_s2wchar(struct soap*, const char*, wchar_t**, long minlen, long maxlen); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2wchar(struct soap*, const char*, wchar_t**, int, long minlen, long maxlen, const char *pattern); SOAP_FMAC1 int SOAP_FMAC2 soap_s2dateTime(struct soap*, const char*, time_t*); +#endif + SOAP_FMAC1 char* SOAP_FMAC2 soap_s2base64(struct soap*, const unsigned char*, char*, int); SOAP_FMAC1 char* SOAP_FMAC2 soap_s2hex(struct soap*, const unsigned char*, char*, int); -#endif SOAP_FMAC1 const char* SOAP_FMAC2 soap_byte2s(struct soap*, char); SOAP_FMAC1 const char* SOAP_FMAC2 soap_short2s(struct soap*, short); @@ -2250,10 +3537,10 @@ SOAP_FMAC1 const char* SOAP_FMAC2 soap_QName2s(struct soap*, const char*); #ifndef WITH_LEAN SOAP_FMAC1 const char* SOAP_FMAC2 soap_wchar2s(struct soap*, const wchar_t*); SOAP_FMAC1 const char* SOAP_FMAC2 soap_dateTime2s(struct soap*, time_t); -SOAP_FMAC1 const char* SOAP_FMAC2 soap_base642s(struct soap*, const char*, char*, size_t, int*); -SOAP_FMAC1 const char* SOAP_FMAC2 soap_hex2s(struct soap*, const char*, char*, size_t, int*); #endif +SOAP_FMAC1 const char* SOAP_FMAC2 soap_base642s(struct soap*, const char*, char*, size_t, int*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_hex2s(struct soap*, const char*, char*, size_t, int*); SOAP_FMAC1 int* SOAP_FMAC2 soap_inint(struct soap*, const char *tag, int *p, const char *, int); SOAP_FMAC1 char* SOAP_FMAC2 soap_inbyte(struct soap*, const char *tag, char *p, const char *, int); @@ -2267,16 +3554,19 @@ SOAP_FMAC1 unsigned short* SOAP_FMAC2 soap_inunsignedShort(struct soap*, const c SOAP_FMAC1 unsigned int* SOAP_FMAC2 soap_inunsignedInt(struct soap*, const char *tag, unsigned int *p, const char *, int); SOAP_FMAC1 unsigned long* SOAP_FMAC2 soap_inunsignedLong(struct soap*, const char *tag, unsigned long *p, const char *, int); SOAP_FMAC1 ULONG64* SOAP_FMAC2 soap_inULONG64(struct soap*, const char *tag, ULONG64 *p, const char *, int); -SOAP_FMAC1 char** SOAP_FMAC2 soap_instring(struct soap*, const char *tag, char **p, const char *, int, int, long, long); +SOAP_FMAC1 char** SOAP_FMAC2 soap_instring(struct soap*, const char *tag, char **p, const char *, int, int, long, long, const char*); SOAP_FMAC1 char** SOAP_FMAC2 soap_inliteral(struct soap*, const char *tag, char **p); #ifndef WITH_LEAN SOAP_FMAC1 time_t* SOAP_FMAC2 soap_indateTime(struct soap*, const char *tag, time_t *p, const char *, int); +#endif + +#if !defined(WITH_LEAN) || defined(WITH_COOKIES) SOAP_FMAC1 time_t SOAP_FMAC2 soap_timegm(struct tm*); #endif #ifndef WITH_LEANER -SOAP_FMAC1 wchar_t** SOAP_FMAC2 soap_inwstring(struct soap*, const char *tag, wchar_t **p, const char *, int, long, long); +SOAP_FMAC1 wchar_t** SOAP_FMAC2 soap_inwstring(struct soap*, const char *tag, wchar_t **p, const char *, int, int, long, long, const char*); SOAP_FMAC1 wchar_t** SOAP_FMAC2 soap_inwliteral(struct soap*, const char *tag, wchar_t **p); #endif @@ -2305,9 +3595,9 @@ SOAP_FMAC1 int SOAP_FMAC2 soap_outwliteral(struct soap*, const char *tag, wchar_ #endif #ifndef WITH_LEANER -SOAP_FMAC1 int SOAP_FMAC2 soap_attachment(struct soap *, const char*, int, const void*, const struct soap_array*, const char*, const char*, const char*, int, const char*, int); -SOAP_FMAC1 int SOAP_FMAC2 soap_move(struct soap*, long); -SOAP_FMAC1 size_t SOAP_FMAC2 soap_tell(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_attachment(struct soap *, const char*, int, const void*, const void*, int, const char*, const char*, const char*, const char*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_move(struct soap*, ULONG64); +SOAP_FMAC1 ULONG64 SOAP_FMAC2 soap_tell(struct soap*); SOAP_FMAC1 char* SOAP_FMAC2 soap_dime_option(struct soap*, unsigned short, const char*); SOAP_FMAC1 int SOAP_FMAC2 soap_getdimehdr(struct soap*); SOAP_FMAC1 int SOAP_FMAC2 soap_getdime(struct soap*); @@ -2321,40 +3611,119 @@ SOAP_FMAC1 void SOAP_FMAC2 soap_set_dime(struct soap*); SOAP_FMAC1 void SOAP_FMAC2 soap_set_mime(struct soap*, const char *boundary, const char *start); SOAP_FMAC1 void SOAP_FMAC2 soap_clr_dime(struct soap*); SOAP_FMAC1 void SOAP_FMAC2 soap_clr_mime(struct soap*); -SOAP_FMAC1 int SOAP_FMAC2 soap_set_dime_attachment(struct soap*, char *ptr, size_t size, const char *type, const char *id, unsigned short optype, const char *option); -SOAP_FMAC1 int SOAP_FMAC2 soap_set_mime_attachment(struct soap*, char *ptr, size_t size, enum soap_mime_encoding encoding, const char *type, const char *id, const char *location, const char *description); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_dime_attachment(struct soap*, const char *ptr, size_t size, const char *type, const char *id, unsigned short optype, const char *option); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_mime_attachment(struct soap*, const char *ptr, size_t size, enum soap_mime_encoding encoding, const char *type, const char *id, const char *location, const char *description); SOAP_FMAC1 void SOAP_FMAC2 soap_post_check_mime_attachments(struct soap *soap); SOAP_FMAC1 int SOAP_FMAC2 soap_check_mime_attachments(struct soap *soap); -SOAP_FMAC1 struct soap_multipart* SOAP_FMAC2 soap_get_mime_attachment(struct soap *soap, void *handle); +SOAP_FMAC1 struct soap_multipart* SOAP_FMAC2 soap_recv_mime_attachment(struct soap *soap, void *handle); SOAP_FMAC1 int SOAP_FMAC2 soap_match_cid(struct soap*, const char*, const char*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_rand_uuid(struct soap*, const char*); #endif SOAP_FMAC1 int SOAP_FMAC2 soap_register_plugin_arg(struct soap*, int (*fcreate)(struct soap*, struct soap_plugin*, void*), void*); SOAP_FMAC1 void* SOAP_FMAC2 soap_lookup_plugin(struct soap*, const char*); -SOAP_FMAC1 const char* SOAP_FMAC2 soap_attr_value(struct soap *soap, const char *name, int flag); -SOAP_FMAC1 int SOAP_FMAC2 soap_set_attr(struct soap *soap, const char *name, const char *value); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_attr_value(struct soap *soap, const char *name, int flag, int occurs); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_attr(struct soap *soap, const char *name, const char *value, int flag); SOAP_FMAC1 void SOAP_FMAC2 soap_clr_attr(struct soap *soap); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_extend_url(struct soap *soap, const char*, const char*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_extend_url_query(struct soap *soap, const char*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_url_query(struct soap *soap, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_encode_url(const char*, char*, int); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_encode_url_string(struct soap*, const char*); #ifdef WITH_COOKIES SOAP_FMAC1 void SOAP_FMAC2 soap_getcookies(struct soap *soap, const char *val); -SOAP_FMAC1 size_t SOAP_FMAC2 soap_encode_cookie(const char*, char*, size_t); -SOAP_FMAC1 extern struct soap_cookie* SOAP_FMAC2 soap_set_cookie(struct soap*, const char*, const char*, const char*, const char*); -SOAP_FMAC1 extern struct soap_cookie* SOAP_FMAC2 soap_cookie(struct soap*, const char*, const char*, const char*); -SOAP_FMAC1 extern char* SOAP_FMAC2 soap_cookie_value(struct soap*, const char*, const char*, const char*); -SOAP_FMAC1 extern char* SOAP_FMAC2 soap_env_cookie_value(struct soap*, const char*, const char*, const char*); -SOAP_FMAC1 extern time_t SOAP_FMAC2 soap_cookie_expire(struct soap*, const char*, const char*, const char*); -SOAP_FMAC1 extern int SOAP_FMAC2 soap_set_cookie_expire(struct soap*, const char*, long, const char*, const char*); -SOAP_FMAC1 extern int SOAP_FMAC2 soap_set_cookie_session(struct soap*, const char*, const char*, const char*); -SOAP_FMAC1 extern int SOAP_FMAC2 soap_clr_cookie_session(struct soap*, const char*, const char*, const char*); -SOAP_FMAC1 extern void SOAP_FMAC2 soap_clr_cookie(struct soap*, const char*, const char*, const char*); -SOAP_FMAC1 extern int SOAP_FMAC2 soap_getenv_cookies(struct soap*); -SOAP_FMAC1 extern struct soap_cookie* SOAP_FMAC2 soap_copy_cookies(struct soap*, const struct soap*); -SOAP_FMAC1 extern void SOAP_FMAC2 soap_free_cookies(struct soap*); +SOAP_FMAC1 struct soap_cookie* SOAP_FMAC2 soap_set_cookie(struct soap*, const char*, const char*, const char*, const char*); +SOAP_FMAC1 struct soap_cookie* SOAP_FMAC2 soap_cookie(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 struct soap_cookie* SOAP_FMAC2 soap_cookie_env(struct soap*, const char*, const char*, const char*, short); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_cookie_value(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_env_cookie_value(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 time_t SOAP_FMAC2 soap_cookie_expire(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_cookie_expire(struct soap*, const char*, long, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_cookie_secure(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_cookie_session(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_clr_cookie_session(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_clr_cookie(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getenv_cookies(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_free_cookies(struct soap*); +SOAP_FMAC1 struct soap_cookie* SOAP_FMAC2 soap_copy_cookies(struct soap*, const struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putsetcookies(struct soap *soap); +SOAP_FMAC1 int SOAP_FMAC2 soap_putcookies(struct soap *soap, const char *domain, const char *path, int secure); #endif #ifdef __cplusplus } /* extern "C" */ #endif +/* declare global SOAP header and fault processing functions, unless WITH_STATIC is defined (generated in soapXYXLib code) */ +#ifndef WITH_STATIC +SOAP_FMAC3 void SOAP_FMAC4 soap_header(struct soap*); +SOAP_FMAC3 void SOAP_FMAC4 soap_fault(struct soap*); +SOAP_FMAC3 const char ** SOAP_FMAC4 soap_faultcode(struct soap*); +SOAP_FMAC3 const char ** SOAP_FMAC4 soap_faultsubcode(struct soap*); +SOAP_FMAC3 const char ** SOAP_FMAC4 soap_faultstring(struct soap*); +SOAP_FMAC3 const char ** SOAP_FMAC4 soap_faultdetail(struct soap*); +SOAP_FMAC3 const char * SOAP_FMAC4 soap_fault_subcode(struct soap*); +SOAP_FMAC3 const char * SOAP_FMAC4 soap_fault_string(struct soap*); +SOAP_FMAC3 const char * SOAP_FMAC4 soap_fault_detail(struct soap*); +SOAP_FMAC3 void SOAP_FMAC4 soap_serializefault(struct soap*); +SOAP_FMAC3 void SOAP_FMAC4 soap_serializeheader(struct soap*); +SOAP_FMAC3 int SOAP_FMAC4 soap_getheader(struct soap*); +SOAP_FMAC3 int SOAP_FMAC4 soap_putheader(struct soap*); +SOAP_FMAC3 int SOAP_FMAC4 soap_getfault(struct soap*); +SOAP_FMAC3 int SOAP_FMAC4 soap_putfault(struct soap*); +#endif + +#ifdef __cplusplus + +/* C++ templates (for generated C++ only, not needed nor used in generated C code) */ + +template +struct soap_block +{ + static T *push(struct soap *soap, struct soap_blist *b) + { + if (!b) + b = soap->blist; + if (!b) + return NULL; + T *p = (T*)soap_push_block_max(soap, b, sizeof(T)); + if (p) + SOAP_PLACEMENT_NEW(soap, p, T); + return p; + } + static void pop(struct soap *soap, struct soap_blist *b) + { + if (!b) + b = soap->blist; + if (!b || !b->head) + return; + ((T*)(b->head + 1))->~T(); + soap_pop_block(soap, b); + } + static void save(struct soap *soap, struct soap_blist *b, T *p) + { + if (!b) + b = soap->blist; + for (T *q = (T*)soap_first_block(soap, b); q; q = (T*)soap_next_block(soap, b)) + { + soap_update_pointers(soap, (const char*)p, (const char*)q, sizeof(T)); + *p++ = *q; + q->~T(); + } + soap_end_block(soap, b); + } + static void end(struct soap *soap, struct soap_blist *b) + { + if (!b) + b = soap->blist; + for (T *p = (T*)soap_first_block(soap, b); p; p = (T*)soap_next_block(soap, b)) + p->~T(); + soap_end_block(soap, b); + } +}; + #endif + +#endif /* STDSOAP_H */