Mercurial > repos > ktnyt > gembassy
comparison GEMBASSY-1.0.3/gsoap/stdsoap2.c @ 0:8300eb051bea draft
Initial upload
| author | ktnyt |
|---|---|
| date | Fri, 26 Jun 2015 05:19:29 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:8300eb051bea |
|---|---|
| 1 /* | |
| 2 stdsoap2.c[pp] 2.8.17r | |
| 3 | |
| 4 gSOAP runtime engine | |
| 5 | |
| 6 gSOAP XML Web services tools | |
| 7 Copyright (C) 2000-2013, Robert van Engelen, Genivia Inc., All Rights Reserved. | |
| 8 This part of the software is released under ONE of the following licenses: | |
| 9 GPL, or the gSOAP public license, or Genivia's license for commercial use. | |
| 10 -------------------------------------------------------------------------------- | |
| 11 Contributors: | |
| 12 | |
| 13 Wind River Systems Inc., for the following additions under gSOAP public license: | |
| 14 - vxWorks compatible options | |
| 15 -------------------------------------------------------------------------------- | |
| 16 gSOAP public license. | |
| 17 | |
| 18 The contents of this file are subject to the gSOAP Public License Version 1.3 | |
| 19 (the "License"); you may not use this file except in compliance with the | |
| 20 License. You may obtain a copy of the License at | |
| 21 http://www.cs.fsu.edu/~engelen/soaplicense.html | |
| 22 Software distributed under the License is distributed on an "AS IS" basis, | |
| 23 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |
| 24 for the specific language governing rights and limitations under the License. | |
| 25 | |
| 26 The Initial Developer of the Original Code is Robert A. van Engelen. | |
| 27 Copyright (C) 2000-2013, Robert van Engelen, Genivia Inc., All Rights Reserved. | |
| 28 -------------------------------------------------------------------------------- | |
| 29 GPL license. | |
| 30 | |
| 31 This program is free software; you can redistribute it and/or modify it under | |
| 32 the terms of the GNU General Public License as published by the Free Software | |
| 33 Foundation; either version 2 of the License, or (at your option) any later | |
| 34 version. | |
| 35 | |
| 36 This program is distributed in the hope that it will be useful, but WITHOUT ANY | |
| 37 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A | |
| 38 PARTICULAR PURPOSE. See the GNU General Public License for more details. | |
| 39 | |
| 40 You should have received a copy of the GNU General Public License along with | |
| 41 this program; if not, write to the Free Software Foundation, Inc., 59 Temple | |
| 42 Place, Suite 330, Boston, MA 02111-1307 USA | |
| 43 | |
| 44 Author contact information: | |
| 45 engelen@genivia.com / engelen@acm.org | |
| 46 | |
| 47 This program is released under the GPL with the additional exemption that | |
| 48 compiling, linking, and/or using OpenSSL is allowed. | |
| 49 -------------------------------------------------------------------------------- | |
| 50 A commercial use license is available from Genivia, Inc., contact@genivia.com | |
| 51 -------------------------------------------------------------------------------- | |
| 52 */ | |
| 53 | |
| 54 #define GSOAP_LIB_VERSION 20817 | |
| 55 | |
| 56 #ifdef AS400 | |
| 57 # pragma convert(819) /* EBCDIC to ASCII */ | |
| 58 #endif | |
| 59 | |
| 60 #include "stdsoap2.h" | |
| 61 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE) | |
| 62 #include <ipcom_key_db.h> | |
| 63 #endif | |
| 64 #if GSOAP_VERSION != GSOAP_LIB_VERSION | |
| 65 # error "GSOAP VERSION MISMATCH IN LIBRARY: PLEASE REINSTALL PACKAGE" | |
| 66 #endif | |
| 67 | |
| 68 #ifdef __BORLANDC__ | |
| 69 # pragma warn -8060 | |
| 70 #else | |
| 71 # ifdef WIN32 | |
| 72 # ifdef UNDER_CE | |
| 73 # pragma comment(lib, "ws2.lib") /* WinCE */ | |
| 74 # else | |
| 75 # pragma comment(lib, "ws2_32.lib") | |
| 76 # endif | |
| 77 # pragma warning(disable : 4996) /* disable deprecation warnings */ | |
| 78 # endif | |
| 79 #endif | |
| 80 | |
| 81 #ifdef __cplusplus | |
| 82 SOAP_SOURCE_STAMP("@(#) stdsoap2.cpp ver 2.8.17r 2013-12-18 00:00:00 GMT") | |
| 83 extern "C" { | |
| 84 #else | |
| 85 SOAP_SOURCE_STAMP("@(#) stdsoap2.c ver 2.8.17r 2013-12-18 00:00:00 GMT") | |
| 86 #endif | |
| 87 | |
| 88 /* 8bit character representing unknown/nonrepresentable character data (e.g. not supported by current locale with multibyte support enabled) */ | |
| 89 #ifndef SOAP_UNKNOWN_CHAR | |
| 90 #define SOAP_UNKNOWN_CHAR (127) | |
| 91 #endif | |
| 92 | |
| 93 /* EOF=-1 */ | |
| 94 #define SOAP_LT (soap_wchar)(-2) /* XML-specific '<' */ | |
| 95 #define SOAP_TT (soap_wchar)(-3) /* XML-specific '</' */ | |
| 96 #define SOAP_GT (soap_wchar)(-4) /* XML-specific '>' */ | |
| 97 #define SOAP_QT (soap_wchar)(-5) /* XML-specific '"' */ | |
| 98 #define SOAP_AP (soap_wchar)(-6) /* XML-specific ''' */ | |
| 99 | |
| 100 #define soap_blank(c) ((c)+1 > 0 && (c) <= 32) | |
| 101 #define soap_notblank(c) ((c) > 32) | |
| 102 | |
| 103 #if defined(WIN32) && !defined(UNDER_CE) | |
| 104 #define soap_hash_ptr(p) ((PtrToUlong(p) >> 3) & (SOAP_PTRHASH - 1)) | |
| 105 #else | |
| 106 #define soap_hash_ptr(p) ((size_t)(((unsigned long)(p) >> 3) & (SOAP_PTRHASH-1))) | |
| 107 #endif | |
| 108 | |
| 109 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG) | |
| 110 static void soap_init_logs(struct soap*); | |
| 111 #endif | |
| 112 #ifdef SOAP_DEBUG | |
| 113 static void soap_close_logfile(struct soap*, int); | |
| 114 static void soap_set_logfile(struct soap*, int, const char*); | |
| 115 #endif | |
| 116 | |
| 117 #ifdef SOAP_MEM_DEBUG | |
| 118 static void soap_init_mht(struct soap*); | |
| 119 static void soap_free_mht(struct soap*); | |
| 120 static void soap_track_unlink(struct soap*, const void*); | |
| 121 #endif | |
| 122 | |
| 123 #ifndef PALM_2 | |
| 124 static int soap_set_error(struct soap*, const char*, const char*, const char*, const char*, int); | |
| 125 static int soap_copy_fault(struct soap*, const char*, const char*, const char*, const char*); | |
| 126 static int soap_getattrval(struct soap*, char*, size_t, soap_wchar); | |
| 127 #endif | |
| 128 | |
| 129 #ifndef PALM_1 | |
| 130 static void soap_free_ns(struct soap *soap); | |
| 131 static soap_wchar soap_char(struct soap*); | |
| 132 static soap_wchar soap_get_pi(struct soap*); | |
| 133 static int soap_isxdigit(int); | |
| 134 static void *fplugin(struct soap*, const char*); | |
| 135 static size_t soap_count_attachments(struct soap *soap); | |
| 136 static int soap_try_connect_command(struct soap*, int http_command, const char *endpoint, const char *action); | |
| 137 #ifdef WITH_NTLM | |
| 138 static int soap_ntlm_handshake(struct soap *soap, int command, const char *endpoint, const char *host, int port); | |
| 139 #endif | |
| 140 #ifndef WITH_NOIDREF | |
| 141 static int soap_has_copies(struct soap*, const char*, const char*); | |
| 142 static void soap_init_iht(struct soap*); | |
| 143 static void soap_free_iht(struct soap*); | |
| 144 static void soap_init_pht(struct soap*); | |
| 145 static void soap_free_pht(struct soap*); | |
| 146 #endif | |
| 147 #endif | |
| 148 | |
| 149 #ifndef WITH_LEAN | |
| 150 static const char *soap_set_validation_fault(struct soap*, const char*, const char*); | |
| 151 static int soap_isnumeric(struct soap*, const char*); | |
| 152 static struct soap_nlist *soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized); | |
| 153 static void soap_utilize_ns(struct soap *soap, const char *tag); | |
| 154 #endif | |
| 155 | |
| 156 #ifndef WITH_LEANER | |
| 157 #ifndef PALM_1 | |
| 158 static struct soap_multipart *soap_new_multipart(struct soap*, struct soap_multipart**, struct soap_multipart**, char*, size_t); | |
| 159 static int soap_putdimefield(struct soap*, const char*, size_t); | |
| 160 static char *soap_getdimefield(struct soap*, size_t); | |
| 161 static void soap_select_mime_boundary(struct soap*); | |
| 162 static int soap_valid_mime_boundary(struct soap*); | |
| 163 static void soap_resolve_attachment(struct soap*, struct soap_multipart*); | |
| 164 #endif | |
| 165 #endif | |
| 166 | |
| 167 #ifdef WITH_GZIP | |
| 168 static int soap_getgziphdr(struct soap*); | |
| 169 #endif | |
| 170 | |
| 171 #ifdef WITH_OPENSSL | |
| 172 # ifndef SOAP_SSL_RSA_BITS | |
| 173 # define SOAP_SSL_RSA_BITS 2048 | |
| 174 # endif | |
| 175 static int soap_ssl_init_done = 0; | |
| 176 static int ssl_auth_init(struct soap*); | |
| 177 static int ssl_verify_callback(int, X509_STORE_CTX*); | |
| 178 static int ssl_verify_callback_allow_expired_certificate(int, X509_STORE_CTX*); | |
| 179 static int ssl_password(char*, int, int, void *); | |
| 180 #endif | |
| 181 | |
| 182 #ifdef WITH_GNUTLS | |
| 183 # ifndef SOAP_SSL_RSA_BITS | |
| 184 # define SOAP_SSL_RSA_BITS 2048 | |
| 185 # endif | |
| 186 static int soap_ssl_init_done = 0; | |
| 187 static const char *ssl_verify(struct soap *soap, const char *host); | |
| 188 # if defined(HAVE_PTHREAD_H) | |
| 189 # include <pthread.h> | |
| 190 /* make GNUTLS thread safe with pthreads */ | |
| 191 GCRY_THREAD_OPTION_PTHREAD_IMPL; | |
| 192 # elif defined(HAVE_PTH_H) | |
| 193 #include <pth.h> | |
| 194 /* make GNUTLS thread safe with PTH */ | |
| 195 GCRY_THREAD_OPTION_PTH_IMPL; | |
| 196 # endif | |
| 197 #endif | |
| 198 | |
| 199 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) | |
| 200 #ifndef PALM_1 | |
| 201 static const char *soap_decode(char*, size_t, const char*, const char*); | |
| 202 #endif | |
| 203 #endif | |
| 204 | |
| 205 #ifndef WITH_NOHTTP | |
| 206 #ifndef PALM_1 | |
| 207 static soap_wchar soap_getchunkchar(struct soap*); | |
| 208 static const char *http_error(struct soap*, int); | |
| 209 static int http_get(struct soap*); | |
| 210 static int http_405(struct soap*); | |
| 211 static int http_200(struct soap*); | |
| 212 static int http_post(struct soap*, const char*, const char*, int, const char*, const char*, size_t); | |
| 213 static int http_send_header(struct soap*, const char*); | |
| 214 static int http_post_header(struct soap*, const char*, const char*); | |
| 215 static int http_response(struct soap*, int, size_t); | |
| 216 static int http_parse(struct soap*); | |
| 217 static int http_parse_header(struct soap*, const char*, const char*); | |
| 218 #endif | |
| 219 #endif | |
| 220 | |
| 221 #ifndef WITH_NOIO | |
| 222 | |
| 223 #ifndef PALM_1 | |
| 224 static int fsend(struct soap*, const char*, size_t); | |
| 225 static size_t frecv(struct soap*, char*, size_t); | |
| 226 static int tcp_init(struct soap*); | |
| 227 static const char *tcp_error(struct soap*); | |
| 228 #ifndef WITH_IPV6 | |
| 229 static int tcp_gethost(struct soap*, const char *addr, struct in_addr *inaddr); | |
| 230 #endif | |
| 231 static SOAP_SOCKET tcp_connect(struct soap*, const char *endpoint, const char *host, int port); | |
| 232 static SOAP_SOCKET tcp_accept(struct soap*, SOAP_SOCKET, struct sockaddr*, int*); | |
| 233 static int tcp_select(struct soap*, SOAP_SOCKET, int, int); | |
| 234 static int tcp_disconnect(struct soap*); | |
| 235 static int tcp_closesocket(struct soap*, SOAP_SOCKET); | |
| 236 static int tcp_shutdownsocket(struct soap*, SOAP_SOCKET, int); | |
| 237 static const char *soap_strerror(struct soap*); | |
| 238 #endif | |
| 239 | |
| 240 #define SOAP_TCP_SELECT_RCV 0x1 | |
| 241 #define SOAP_TCP_SELECT_SND 0x2 | |
| 242 #define SOAP_TCP_SELECT_ERR 0x4 | |
| 243 #define SOAP_TCP_SELECT_ALL 0x7 | |
| 244 | |
| 245 #if defined(WIN32) | |
| 246 #define SOAP_SOCKBLOCK(fd) \ | |
| 247 { u_long blocking = 0; \ | |
| 248 ioctlsocket(fd, FIONBIO, &blocking); \ | |
| 249 } | |
| 250 #define SOAP_SOCKNONBLOCK(fd) \ | |
| 251 { u_long nonblocking = 1; \ | |
| 252 ioctlsocket(fd, FIONBIO, &nonblocking); \ | |
| 253 } | |
| 254 #elif defined(VXWORKS) | |
| 255 #define SOAP_SOCKBLOCK(fd) \ | |
| 256 { u_long blocking = 0; \ | |
| 257 ioctl(fd, FIONBIO, (int)(&blocking)); \ | |
| 258 } | |
| 259 #define SOAP_SOCKNONBLOCK(fd) \ | |
| 260 { u_long nonblocking = 1; \ | |
| 261 ioctl(fd, FIONBIO, (int)(&nonblocking)); \ | |
| 262 } | |
| 263 #elif defined(__VMS) | |
| 264 #define SOAP_SOCKBLOCK(fd) \ | |
| 265 { int blocking = 0; \ | |
| 266 ioctl(fd, FIONBIO, &blocking); \ | |
| 267 } | |
| 268 #define SOAP_SOCKNONBLOCK(fd) \ | |
| 269 { int nonblocking = 1; \ | |
| 270 ioctl(fd, FIONBIO, &nonblocking); \ | |
| 271 } | |
| 272 #elif defined(PALM) | |
| 273 #define SOAP_SOCKBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)&~O_NONBLOCK); | |
| 274 #define SOAP_SOCKNONBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)|O_NONBLOCK); | |
| 275 #elif defined(SYMBIAN) | |
| 276 #define SOAP_SOCKBLOCK(fd) \ | |
| 277 { long blocking = 0; \ | |
| 278 ioctl(fd, 0/*FIONBIO*/, &blocking); \ | |
| 279 } | |
| 280 #define SOAP_SOCKNONBLOCK(fd) \ | |
| 281 { long nonblocking = 1; \ | |
| 282 ioctl(fd, 0/*FIONBIO*/, &nonblocking); \ | |
| 283 } | |
| 284 #else | |
| 285 #define SOAP_SOCKBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)&~O_NONBLOCK); | |
| 286 #define SOAP_SOCKNONBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)|O_NONBLOCK); | |
| 287 #endif | |
| 288 | |
| 289 #endif | |
| 290 | |
| 291 #if defined(PALM) && !defined(PALM_2) | |
| 292 unsigned short errno; | |
| 293 #endif | |
| 294 | |
| 295 #ifndef PALM_1 | |
| 296 static const char soap_env1[42] = "http://schemas.xmlsoap.org/soap/envelope/"; | |
| 297 static const char soap_enc1[42] = "http://schemas.xmlsoap.org/soap/encoding/"; | |
| 298 static const char soap_env2[40] = "http://www.w3.org/2003/05/soap-envelope"; | |
| 299 static const char soap_enc2[40] = "http://www.w3.org/2003/05/soap-encoding"; | |
| 300 static const char soap_rpc[35] = "http://www.w3.org/2003/05/soap-rpc"; | |
| 301 #endif | |
| 302 | |
| 303 #ifndef PALM_1 | |
| 304 const union soap_double_nan soap_double_nan = {{0xFFFFFFFF, 0xFFFFFFFF}}; | |
| 305 const char soap_base64o[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | |
| 306 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"; | |
| 307 #endif | |
| 308 | |
| 309 #ifndef WITH_LEAN | |
| 310 static const char soap_indent[11] = "\n\t\t\t\t\t\t\t\t\t"; | |
| 311 /* Alternative indentation form for SOAP_XML_INDENT: | |
| 312 static const char soap_indent[21] = "\n "; | |
| 313 */ | |
| 314 #endif | |
| 315 | |
| 316 #ifndef SOAP_CANARY | |
| 317 # define SOAP_CANARY (0xC0DE) | |
| 318 #endif | |
| 319 | |
| 320 static const char soap_padding[4] = "\0\0\0"; | |
| 321 #define SOAP_STR_PADDING (soap_padding) | |
| 322 #define SOAP_STR_EOS (soap_padding) | |
| 323 #define SOAP_NON_NULL (soap_padding) | |
| 324 | |
| 325 #ifndef WITH_LEAN | |
| 326 static const struct soap_code_map html_entity_codes[] = /* entities for XHTML parsing */ | |
| 327 { { 160, "nbsp" }, | |
| 328 { 161, "iexcl" }, | |
| 329 { 162, "cent" }, | |
| 330 { 163, "pound" }, | |
| 331 { 164, "curren" }, | |
| 332 { 165, "yen" }, | |
| 333 { 166, "brvbar" }, | |
| 334 { 167, "sect" }, | |
| 335 { 168, "uml" }, | |
| 336 { 169, "copy" }, | |
| 337 { 170, "ordf" }, | |
| 338 { 171, "laquo" }, | |
| 339 { 172, "not" }, | |
| 340 { 173, "shy" }, | |
| 341 { 174, "reg" }, | |
| 342 { 175, "macr" }, | |
| 343 { 176, "deg" }, | |
| 344 { 177, "plusmn" }, | |
| 345 { 178, "sup2" }, | |
| 346 { 179, "sup3" }, | |
| 347 { 180, "acute" }, | |
| 348 { 181, "micro" }, | |
| 349 { 182, "para" }, | |
| 350 { 183, "middot" }, | |
| 351 { 184, "cedil" }, | |
| 352 { 185, "sup1" }, | |
| 353 { 186, "ordm" }, | |
| 354 { 187, "raquo" }, | |
| 355 { 188, "frac14" }, | |
| 356 { 189, "frac12" }, | |
| 357 { 190, "frac34" }, | |
| 358 { 191, "iquest" }, | |
| 359 { 192, "Agrave" }, | |
| 360 { 193, "Aacute" }, | |
| 361 { 194, "Acirc" }, | |
| 362 { 195, "Atilde" }, | |
| 363 { 196, "Auml" }, | |
| 364 { 197, "Aring" }, | |
| 365 { 198, "AElig" }, | |
| 366 { 199, "Ccedil" }, | |
| 367 { 200, "Egrave" }, | |
| 368 { 201, "Eacute" }, | |
| 369 { 202, "Ecirc" }, | |
| 370 { 203, "Euml" }, | |
| 371 { 204, "Igrave" }, | |
| 372 { 205, "Iacute" }, | |
| 373 { 206, "Icirc" }, | |
| 374 { 207, "Iuml" }, | |
| 375 { 208, "ETH" }, | |
| 376 { 209, "Ntilde" }, | |
| 377 { 210, "Ograve" }, | |
| 378 { 211, "Oacute" }, | |
| 379 { 212, "Ocirc" }, | |
| 380 { 213, "Otilde" }, | |
| 381 { 214, "Ouml" }, | |
| 382 { 215, "times" }, | |
| 383 { 216, "Oslash" }, | |
| 384 { 217, "Ugrave" }, | |
| 385 { 218, "Uacute" }, | |
| 386 { 219, "Ucirc" }, | |
| 387 { 220, "Uuml" }, | |
| 388 { 221, "Yacute" }, | |
| 389 { 222, "THORN" }, | |
| 390 { 223, "szlig" }, | |
| 391 { 224, "agrave" }, | |
| 392 { 225, "aacute" }, | |
| 393 { 226, "acirc" }, | |
| 394 { 227, "atilde" }, | |
| 395 { 228, "auml" }, | |
| 396 { 229, "aring" }, | |
| 397 { 230, "aelig" }, | |
| 398 { 231, "ccedil" }, | |
| 399 { 232, "egrave" }, | |
| 400 { 233, "eacute" }, | |
| 401 { 234, "ecirc" }, | |
| 402 { 235, "euml" }, | |
| 403 { 236, "igrave" }, | |
| 404 { 237, "iacute" }, | |
| 405 { 238, "icirc" }, | |
| 406 { 239, "iuml" }, | |
| 407 { 240, "eth" }, | |
| 408 { 241, "ntilde" }, | |
| 409 { 242, "ograve" }, | |
| 410 { 243, "oacute" }, | |
| 411 { 244, "ocirc" }, | |
| 412 { 245, "otilde" }, | |
| 413 { 246, "ouml" }, | |
| 414 { 247, "divide" }, | |
| 415 { 248, "oslash" }, | |
| 416 { 249, "ugrave" }, | |
| 417 { 250, "uacute" }, | |
| 418 { 251, "ucirc" }, | |
| 419 { 252, "uuml" }, | |
| 420 { 253, "yacute" }, | |
| 421 { 254, "thorn" }, | |
| 422 { 255, "yuml" }, | |
| 423 { 0, NULL } | |
| 424 }; | |
| 425 #endif | |
| 426 | |
| 427 #ifndef WITH_NOIO | |
| 428 #ifndef WITH_LEAN | |
| 429 static const struct soap_code_map h_error_codes[] = | |
| 430 { | |
| 431 #ifdef HOST_NOT_FOUND | |
| 432 { HOST_NOT_FOUND, "Host not found" }, | |
| 433 #endif | |
| 434 #ifdef TRY_AGAIN | |
| 435 { TRY_AGAIN, "Try Again" }, | |
| 436 #endif | |
| 437 #ifdef NO_RECOVERY | |
| 438 { NO_RECOVERY, "No Recovery" }, | |
| 439 #endif | |
| 440 #ifdef NO_DATA | |
| 441 { NO_DATA, "No Data" }, | |
| 442 #endif | |
| 443 #ifdef NO_ADDRESS | |
| 444 { NO_ADDRESS, "No Address" }, | |
| 445 #endif | |
| 446 { 0, NULL } | |
| 447 }; | |
| 448 #endif | |
| 449 #endif | |
| 450 | |
| 451 #ifndef WITH_NOHTTP | |
| 452 #ifndef WITH_LEAN | |
| 453 static const struct soap_code_map h_http_error_codes[] = | |
| 454 { { 200, "OK" }, | |
| 455 { 201, "Created" }, | |
| 456 { 202, "Accepted" }, | |
| 457 { 203, "Non-Authoritative Information" }, | |
| 458 { 204, "No Content" }, | |
| 459 { 205, "Reset Content" }, | |
| 460 { 206, "Partial Content" }, | |
| 461 { 300, "Multiple Choices" }, | |
| 462 { 301, "Moved Permanently" }, | |
| 463 { 302, "Found" }, | |
| 464 { 303, "See Other" }, | |
| 465 { 304, "Not Modified" }, | |
| 466 { 305, "Use Proxy" }, | |
| 467 { 307, "Temporary Redirect" }, | |
| 468 { 400, "Bad Request" }, | |
| 469 { 401, "Unauthorized" }, | |
| 470 { 402, "Payment Required" }, | |
| 471 { 403, "Forbidden" }, | |
| 472 { 404, "Not Found" }, | |
| 473 { 405, "Method Not Allowed" }, | |
| 474 { 406, "Not Acceptable" }, | |
| 475 { 407, "Proxy Authentication Required" }, | |
| 476 { 408, "Request Time-out" }, | |
| 477 { 409, "Conflict" }, | |
| 478 { 410, "Gone" }, | |
| 479 { 411, "Length Required" }, | |
| 480 { 412, "Precondition Failed" }, | |
| 481 { 413, "Request Entity Too Large" }, | |
| 482 { 414, "Request-URI Too Large" }, | |
| 483 { 415, "Unsupported Media Type" }, | |
| 484 { 416, "Requested range not satisfiable" }, | |
| 485 { 417, "Expectation Failed" }, | |
| 486 { 500, "Internal Server Error" }, | |
| 487 { 501, "Not Implemented" }, | |
| 488 { 502, "Bad Gateway" }, | |
| 489 { 503, "Service Unavailable" }, | |
| 490 { 504, "Gateway Time-out" }, | |
| 491 { 505, "HTTP Version not supported" }, | |
| 492 { 0, NULL } | |
| 493 }; | |
| 494 #endif | |
| 495 #endif | |
| 496 | |
| 497 #ifdef WITH_OPENSSL | |
| 498 static const struct soap_code_map h_ssl_error_codes[] = | |
| 499 { | |
| 500 #define _SSL_ERROR(e) { e, #e } | |
| 501 _SSL_ERROR(SSL_ERROR_SSL), | |
| 502 _SSL_ERROR(SSL_ERROR_ZERO_RETURN), | |
| 503 _SSL_ERROR(SSL_ERROR_WANT_READ), | |
| 504 _SSL_ERROR(SSL_ERROR_WANT_WRITE), | |
| 505 _SSL_ERROR(SSL_ERROR_WANT_CONNECT), | |
| 506 _SSL_ERROR(SSL_ERROR_WANT_X509_LOOKUP), | |
| 507 _SSL_ERROR(SSL_ERROR_SYSCALL), | |
| 508 { 0, NULL } | |
| 509 }; | |
| 510 #endif | |
| 511 | |
| 512 #ifndef WITH_LEANER | |
| 513 static const struct soap_code_map mime_codes[] = | |
| 514 { { SOAP_MIME_7BIT, "7bit" }, | |
| 515 { SOAP_MIME_8BIT, "8bit" }, | |
| 516 { SOAP_MIME_BINARY, "binary" }, | |
| 517 { SOAP_MIME_QUOTED_PRINTABLE, "quoted-printable" }, | |
| 518 { SOAP_MIME_BASE64, "base64" }, | |
| 519 { SOAP_MIME_IETF_TOKEN, "ietf-token" }, | |
| 520 { SOAP_MIME_X_TOKEN, "x-token" }, | |
| 521 { 0, NULL } | |
| 522 }; | |
| 523 #endif | |
| 524 | |
| 525 #ifdef WIN32 | |
| 526 static int tcp_done = 0; | |
| 527 #endif | |
| 528 | |
| 529 #if defined(HP_UX) && defined(HAVE_GETHOSTBYNAME_R) | |
| 530 extern int h_errno; | |
| 531 #endif | |
| 532 | |
| 533 /******************************************************************************/ | |
| 534 #ifndef WITH_NOIO | |
| 535 #ifndef PALM_1 | |
| 536 static int | |
| 537 fsend(struct soap *soap, const char *s, size_t n) | |
| 538 { register int nwritten, err; | |
| 539 SOAP_SOCKET sk; | |
| 540 #if defined(__cplusplus) && !defined(WITH_LEAN) && !defined(WITH_COMPAT) | |
| 541 if (soap->os) | |
| 542 { soap->os->write(s, (std::streamsize)n); | |
| 543 if (soap->os->good()) | |
| 544 return SOAP_OK; | |
| 545 soap->errnum = 0; | |
| 546 return SOAP_EOF; | |
| 547 } | |
| 548 #endif | |
| 549 sk = soap->sendsk; | |
| 550 if (!soap_valid_socket(sk)) | |
| 551 sk = soap->socket; | |
| 552 while (n) | |
| 553 { if (soap_valid_socket(sk)) | |
| 554 { | |
| 555 if (soap->send_timeout) | |
| 556 { for (;;) | |
| 557 { register int r; | |
| 558 #ifdef WITH_OPENSSL | |
| 559 if (soap->ssl) | |
| 560 r = tcp_select(soap, sk, SOAP_TCP_SELECT_ALL, soap->send_timeout); | |
| 561 else | |
| 562 #endif | |
| 563 #ifdef WITH_GNUTLS | |
| 564 if (soap->session) | |
| 565 r = tcp_select(soap, sk, SOAP_TCP_SELECT_ALL, soap->send_timeout); | |
| 566 else | |
| 567 #endif | |
| 568 r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->send_timeout); | |
| 569 if (r > 0) | |
| 570 break; | |
| 571 if (!r) | |
| 572 return SOAP_EOF; | |
| 573 err = soap->errnum; | |
| 574 if (!err) | |
| 575 return soap->error; | |
| 576 if (err != SOAP_EAGAIN && err != SOAP_EWOULDBLOCK) | |
| 577 return SOAP_EOF; | |
| 578 } | |
| 579 } | |
| 580 #ifdef WITH_OPENSSL | |
| 581 if (soap->ssl) | |
| 582 nwritten = SSL_write(soap->ssl, s, (int)n); | |
| 583 else if (soap->bio) | |
| 584 nwritten = BIO_write(soap->bio, s, (int)n); | |
| 585 else | |
| 586 #endif | |
| 587 #ifdef WITH_GNUTLS | |
| 588 if (soap->session) | |
| 589 nwritten = gnutls_record_send(soap->session, s, n); | |
| 590 else | |
| 591 #endif | |
| 592 #ifndef WITH_LEAN | |
| 593 if ((soap->omode & SOAP_IO_UDP)) | |
| 594 { if (soap->peerlen) | |
| 595 nwritten = sendto(sk, (char*)s, (SOAP_WINSOCKINT)n, soap->socket_flags, (struct sockaddr*)&soap->peer, (SOAP_WINSOCKINT)soap->peerlen); | |
| 596 else | |
| 597 nwritten = send(sk, s, (SOAP_WINSOCKINT)n, soap->socket_flags); | |
| 598 /* retry and back-off algorithm */ | |
| 599 /* TODO: this is not very clear from specs so verify and limit conditions under which we should loop (e.g. ENOBUFS) */ | |
| 600 if (nwritten < 0) | |
| 601 { int udp_repeat; | |
| 602 int udp_delay; | |
| 603 if ((soap->connect_flags & SO_BROADCAST)) | |
| 604 udp_repeat = 2; /* SOAP-over-UDP MULTICAST_UDP_REPEAT - 1 */ | |
| 605 else | |
| 606 udp_repeat = 1; /* SOAP-over-UDP UNICAST_UDP_REPEAT - 1 */ | |
| 607 udp_delay = ((unsigned int)soap_random % 201) + 50; /* UDP_MIN_DELAY .. UDP_MAX_DELAY */ | |
| 608 do | |
| 609 { tcp_select(soap, sk, SOAP_TCP_SELECT_ERR, -1000 * udp_delay); | |
| 610 if (soap->peerlen) | |
| 611 nwritten = sendto(sk, (char*)s, (SOAP_WINSOCKINT)n, soap->socket_flags, (struct sockaddr*)&soap->peer, (SOAP_WINSOCKINT)soap->peerlen); | |
| 612 else | |
| 613 nwritten = send(sk, s, (SOAP_WINSOCKINT)n, soap->socket_flags); | |
| 614 udp_delay <<= 1; | |
| 615 if (udp_delay > 500) /* UDP_UPPER_DELAY */ | |
| 616 udp_delay = 500; | |
| 617 } | |
| 618 while (nwritten < 0 && --udp_repeat > 0); | |
| 619 } | |
| 620 if (nwritten < 0) | |
| 621 { err = soap_socket_errno(sk); | |
| 622 if (err && err != SOAP_EINTR) | |
| 623 { soap->errnum = err; | |
| 624 return SOAP_EOF; | |
| 625 } | |
| 626 nwritten = 0; /* and call write() again */ | |
| 627 } | |
| 628 } | |
| 629 else | |
| 630 #endif | |
| 631 #if !defined(PALM) && !defined(AS400) | |
| 632 nwritten = send(sk, s, (int)n, soap->socket_flags); | |
| 633 #else | |
| 634 nwritten = send(sk, (void*)s, n, soap->socket_flags); | |
| 635 #endif | |
| 636 if (nwritten <= 0) | |
| 637 { | |
| 638 register int r = 0; | |
| 639 err = soap_socket_errno(sk); | |
| 640 #ifdef WITH_OPENSSL | |
| 641 if (soap->ssl && (r = SSL_get_error(soap->ssl, nwritten)) != SSL_ERROR_NONE && r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE) | |
| 642 { soap->errnum = err; | |
| 643 return SOAP_EOF; | |
| 644 } | |
| 645 #endif | |
| 646 #ifdef WITH_GNUTLS | |
| 647 if (soap->session) | |
| 648 { if (nwritten == GNUTLS_E_INTERRUPTED) | |
| 649 err = SOAP_EINTR; | |
| 650 else if (nwritten == GNUTLS_E_AGAIN) | |
| 651 err = SOAP_EAGAIN; | |
| 652 } | |
| 653 #endif | |
| 654 if (err == SOAP_EWOULDBLOCK || err == SOAP_EAGAIN) | |
| 655 { | |
| 656 #if defined(WITH_OPENSSL) | |
| 657 if (soap->ssl && r == SSL_ERROR_WANT_READ) | |
| 658 r = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->send_timeout ? soap->send_timeout : -10000); | |
| 659 else | |
| 660 #elif defined(WITH_GNUTLS) | |
| 661 if (soap->session && !gnutls_record_get_direction(soap->session)) | |
| 662 r = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->send_timeout ? soap->send_timeout : -10000); | |
| 663 else | |
| 664 #endif | |
| 665 r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->send_timeout ? soap->send_timeout : -10000); | |
| 666 if (!r && soap->send_timeout) | |
| 667 return SOAP_EOF; | |
| 668 if (r < 0) | |
| 669 return SOAP_EOF; | |
| 670 } | |
| 671 else if (err && err != SOAP_EINTR) | |
| 672 { soap->errnum = err; | |
| 673 return SOAP_EOF; | |
| 674 } | |
| 675 nwritten = 0; /* and call write() again */ | |
| 676 } | |
| 677 } | |
| 678 else | |
| 679 { | |
| 680 #ifdef WITH_FASTCGI | |
| 681 nwritten = fwrite((void*)s, 1, n, stdout); | |
| 682 fflush(stdout); | |
| 683 #else | |
| 684 #ifdef UNDER_CE | |
| 685 nwritten = fwrite(s, 1, n, soap->sendfd); | |
| 686 #else | |
| 687 #ifdef VXWORKS | |
| 688 #ifdef WMW_RPM_IO | |
| 689 if (soap->rpmreqid) | |
| 690 nwritten = (httpBlockPut(soap->rpmreqid, (char*)s, n) == 0) ? n : -1; | |
| 691 else | |
| 692 #endif | |
| 693 nwritten = fwrite(s, sizeof(char), n, fdopen(soap->sendfd, "w")); | |
| 694 #else | |
| 695 #ifdef WIN32 | |
| 696 nwritten = _write(soap->sendfd, s, (unsigned int)n); | |
| 697 #else | |
| 698 nwritten = write(soap->sendfd, s, (unsigned int)n); | |
| 699 #endif | |
| 700 #endif | |
| 701 #endif | |
| 702 #endif | |
| 703 if (nwritten <= 0) | |
| 704 { | |
| 705 #ifndef WITH_FASTCGI | |
| 706 err = soap_errno; | |
| 707 #else | |
| 708 err = EOF; | |
| 709 #endif | |
| 710 if (err && err != SOAP_EINTR && err != SOAP_EWOULDBLOCK && err != SOAP_EAGAIN) | |
| 711 { soap->errnum = err; | |
| 712 return SOAP_EOF; | |
| 713 } | |
| 714 nwritten = 0; /* and call write() again */ | |
| 715 } | |
| 716 } | |
| 717 n -= nwritten; | |
| 718 s += nwritten; | |
| 719 } | |
| 720 return SOAP_OK; | |
| 721 } | |
| 722 #endif | |
| 723 #endif | |
| 724 | |
| 725 /******************************************************************************/ | |
| 726 #ifndef PALM_1 | |
| 727 SOAP_FMAC1 | |
| 728 int | |
| 729 SOAP_FMAC2 | |
| 730 soap_send_raw(struct soap *soap, const char *s, size_t n) | |
| 731 { if (!n) | |
| 732 return SOAP_OK; | |
| 733 #ifndef WITH_LEANER | |
| 734 if (soap->fpreparesend && (soap->mode & SOAP_IO) != SOAP_IO_STORE && (soap->mode & SOAP_IO_LENGTH) && (soap->error = soap->fpreparesend(soap, s, n))) | |
| 735 return soap->error; | |
| 736 if (soap->ffiltersend && (soap->error = soap->ffiltersend(soap, &s, &n))) | |
| 737 return soap->error; | |
| 738 #endif | |
| 739 if (soap->mode & SOAP_IO_LENGTH) | |
| 740 soap->count += n; | |
| 741 else if (soap->mode & SOAP_IO) | |
| 742 { register size_t i = SOAP_BUFLEN - soap->bufidx; | |
| 743 while (n >= i) | |
| 744 { memcpy(soap->buf + soap->bufidx, s, i); | |
| 745 soap->bufidx = SOAP_BUFLEN; | |
| 746 if (soap_flush(soap)) | |
| 747 return soap->error; | |
| 748 s += i; | |
| 749 n -= i; | |
| 750 i = SOAP_BUFLEN; | |
| 751 } | |
| 752 memcpy(soap->buf + soap->bufidx, s, n); | |
| 753 soap->bufidx += n; | |
| 754 } | |
| 755 else | |
| 756 return soap_flush_raw(soap, s, n); | |
| 757 return SOAP_OK; | |
| 758 } | |
| 759 #endif | |
| 760 | |
| 761 /******************************************************************************/ | |
| 762 #ifndef PALM_1 | |
| 763 SOAP_FMAC1 | |
| 764 int | |
| 765 SOAP_FMAC2 | |
| 766 soap_flush(struct soap *soap) | |
| 767 { register size_t n = soap->bufidx; | |
| 768 if (n) | |
| 769 { | |
| 770 #ifndef WITH_LEANER | |
| 771 if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) | |
| 772 { register int r; | |
| 773 if (soap->fpreparesend && (r = soap->fpreparesend(soap, soap->buf, n))) | |
| 774 return soap->error = r; | |
| 775 } | |
| 776 #endif | |
| 777 soap->bufidx = 0; | |
| 778 #ifdef WITH_ZLIB | |
| 779 if (soap->mode & SOAP_ENC_ZLIB) | |
| 780 { soap->d_stream->next_in = (Byte*)soap->buf; | |
| 781 soap->d_stream->avail_in = (unsigned int)n; | |
| 782 #ifdef WITH_GZIP | |
| 783 soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)n); | |
| 784 #endif | |
| 785 do | |
| 786 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating %u bytes\n", soap->d_stream->avail_in)); | |
| 787 if (deflate(soap->d_stream, Z_NO_FLUSH) != Z_OK) | |
| 788 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to deflate: %s\n", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS)); | |
| 789 return soap->error = SOAP_ZLIB_ERROR; | |
| 790 } | |
| 791 if (!soap->d_stream->avail_out) | |
| 792 { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN)) | |
| 793 return soap->error; | |
| 794 soap->d_stream->next_out = (Byte*)soap->z_buf; | |
| 795 soap->d_stream->avail_out = SOAP_BUFLEN; | |
| 796 } | |
| 797 } while (soap->d_stream->avail_in); | |
| 798 } | |
| 799 else | |
| 800 #endif | |
| 801 return soap_flush_raw(soap, soap->buf, n); | |
| 802 } | |
| 803 return SOAP_OK; | |
| 804 } | |
| 805 #endif | |
| 806 | |
| 807 /******************************************************************************/ | |
| 808 #ifndef PALM_1 | |
| 809 SOAP_FMAC1 | |
| 810 int | |
| 811 SOAP_FMAC2 | |
| 812 soap_flush_raw(struct soap *soap, const char *s, size_t n) | |
| 813 { if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) | |
| 814 { register char *t; | |
| 815 if (!(t = (char*)soap_push_block(soap, NULL, n))) | |
| 816 return soap->error = SOAP_EOM; | |
| 817 memcpy(t, s, n); | |
| 818 return SOAP_OK; | |
| 819 } | |
| 820 #ifndef WITH_LEANER | |
| 821 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) | |
| 822 { char t[16]; | |
| 823 #ifdef HAVE_SNPRINTF | |
| 824 soap_snprintf(t, sizeof(t), &"\r\n%lX\r\n"[soap->chunksize ? 0 : 2], (unsigned long)n); | |
| 825 #else | |
| 826 sprintf(t, &"\r\n%lX\r\n"[soap->chunksize ? 0 : 2], (unsigned long)n); | |
| 827 #endif | |
| 828 DBGMSG(SENT, t, strlen(t)); | |
| 829 if ((soap->error = soap->fsend(soap, t, strlen(t)))) | |
| 830 return soap->error; | |
| 831 soap->chunksize += n; | |
| 832 } | |
| 833 DBGMSG(SENT, s, n); | |
| 834 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Send %u bytes to socket=%d/fd=%d\n", (unsigned int)n, soap->socket, soap->sendfd)); | |
| 835 #endif | |
| 836 return soap->error = soap->fsend(soap, s, n); | |
| 837 } | |
| 838 #endif | |
| 839 | |
| 840 /******************************************************************************/ | |
| 841 #ifndef PALM_1 | |
| 842 SOAP_FMAC1 | |
| 843 int | |
| 844 SOAP_FMAC2 | |
| 845 soap_send(struct soap *soap, const char *s) | |
| 846 { if (s) | |
| 847 return soap_send_raw(soap, s, strlen(s)); | |
| 848 return SOAP_OK; | |
| 849 } | |
| 850 #endif | |
| 851 | |
| 852 /******************************************************************************/ | |
| 853 #ifndef WITH_LEANER | |
| 854 #ifndef PALM_1 | |
| 855 SOAP_FMAC1 | |
| 856 int | |
| 857 SOAP_FMAC2 | |
| 858 soap_send2(struct soap *soap, const char *s1, const char *s2) | |
| 859 { if (soap_send(soap, s1)) | |
| 860 return soap->error; | |
| 861 return soap_send(soap, s2); | |
| 862 } | |
| 863 #endif | |
| 864 #endif | |
| 865 | |
| 866 /******************************************************************************/ | |
| 867 #ifndef WITH_LEANER | |
| 868 #ifndef PALM_1 | |
| 869 SOAP_FMAC1 | |
| 870 int | |
| 871 SOAP_FMAC2 | |
| 872 soap_send3(struct soap *soap, const char *s1, const char *s2, const char *s3) | |
| 873 { if (soap_send(soap, s1) | |
| 874 || soap_send(soap, s2)) | |
| 875 return soap->error; | |
| 876 return soap_send(soap, s3); | |
| 877 } | |
| 878 #endif | |
| 879 #endif | |
| 880 | |
| 881 /******************************************************************************/ | |
| 882 #ifndef WITH_NOIO | |
| 883 #ifndef PALM_1 | |
| 884 static size_t | |
| 885 frecv(struct soap *soap, char *s, size_t n) | |
| 886 { register int r; | |
| 887 register int retries = 100; /* max 100 retries with non-blocking sockets */ | |
| 888 SOAP_SOCKET sk; | |
| 889 soap->errnum = 0; | |
| 890 #if defined(__cplusplus) && !defined(WITH_LEAN) && !defined(WITH_COMPAT) | |
| 891 if (soap->is) | |
| 892 { if (soap->is->good()) | |
| 893 return soap->is->read(s, (std::streamsize)n).gcount(); | |
| 894 return 0; | |
| 895 } | |
| 896 #endif | |
| 897 sk = soap->recvsk; | |
| 898 if (!soap_valid_socket(sk)) | |
| 899 sk = soap->socket; | |
| 900 if (soap_valid_socket(sk)) | |
| 901 { for (;;) | |
| 902 { | |
| 903 #ifdef WITH_OPENSSL | |
| 904 register int err = 0; | |
| 905 #endif | |
| 906 #ifdef WITH_OPENSSL | |
| 907 if (soap->recv_timeout && !soap->ssl) /* SSL: sockets are nonblocking */ | |
| 908 #else | |
| 909 if (soap->recv_timeout) | |
| 910 #endif | |
| 911 { for (;;) | |
| 912 { r = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->recv_timeout); | |
| 913 if (r > 0) | |
| 914 break; | |
| 915 if (!r) | |
| 916 return 0; | |
| 917 r = soap->errnum; | |
| 918 if (r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK) | |
| 919 return 0; | |
| 920 } | |
| 921 } | |
| 922 #ifdef WITH_OPENSSL | |
| 923 if (soap->ssl) | |
| 924 { r = SSL_read(soap->ssl, s, (int)n); | |
| 925 if (r > 0) | |
| 926 return (size_t)r; | |
| 927 err = SSL_get_error(soap->ssl, r); | |
| 928 if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) | |
| 929 return 0; | |
| 930 } | |
| 931 else if (soap->bio) | |
| 932 { r = BIO_read(soap->bio, s, (int)n); | |
| 933 if (r > 0) | |
| 934 return (size_t)r; | |
| 935 return 0; | |
| 936 } | |
| 937 else | |
| 938 #endif | |
| 939 #ifdef WITH_GNUTLS | |
| 940 if (soap->session) | |
| 941 { r = (int)gnutls_record_recv(soap->session, s, n); | |
| 942 if (r >= 0) | |
| 943 return (size_t)r; | |
| 944 } | |
| 945 else | |
| 946 #endif | |
| 947 { | |
| 948 #ifndef WITH_LEAN | |
| 949 if ((soap->omode & SOAP_IO_UDP)) | |
| 950 { SOAP_SOCKLEN_T k = (SOAP_SOCKLEN_T)sizeof(soap->peer); | |
| 951 memset((void*)&soap->peer, 0, sizeof(soap->peer)); | |
| 952 r = recvfrom(sk, s, (SOAP_WINSOCKINT)n, soap->socket_flags, (struct sockaddr*)&soap->peer, &k); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */ | |
| 953 soap->peerlen = (size_t)k; | |
| 954 #ifndef WITH_IPV6 | |
| 955 soap->ip = ntohl(soap->peer.sin_addr.s_addr); | |
| 956 #endif | |
| 957 } | |
| 958 else | |
| 959 #endif | |
| 960 r = recv(sk, s, (int)n, soap->socket_flags); | |
| 961 #ifdef PALM | |
| 962 /* CycleSyncDisplay(curStatusMsg); */ | |
| 963 #endif | |
| 964 if (r >= 0) | |
| 965 return (size_t)r; | |
| 966 r = soap_socket_errno(sk); | |
| 967 if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK) | |
| 968 { soap->errnum = r; | |
| 969 return 0; | |
| 970 } | |
| 971 } | |
| 972 #if defined(WITH_OPENSSL) | |
| 973 if (soap->ssl && err == SSL_ERROR_WANT_WRITE) | |
| 974 r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5); | |
| 975 else | |
| 976 #elif defined(WITH_GNUTLS) | |
| 977 if (soap->session && gnutls_record_get_direction(soap->session)) | |
| 978 r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5); | |
| 979 else | |
| 980 #endif | |
| 981 r = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5); | |
| 982 if (!r && soap->recv_timeout) | |
| 983 return 0; | |
| 984 if (r < 0) | |
| 985 { r = soap->errnum; | |
| 986 if (r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK) | |
| 987 return 0; | |
| 988 } | |
| 989 if (retries-- <= 0) | |
| 990 return 0; | |
| 991 #ifdef PALM | |
| 992 r = soap_socket_errno(sk); | |
| 993 if (r != SOAP_EINTR && retries-- <= 0) | |
| 994 { soap->errnum = r; | |
| 995 return 0; | |
| 996 } | |
| 997 #endif | |
| 998 } | |
| 999 } | |
| 1000 #ifdef WITH_FASTCGI | |
| 1001 return fread(s, 1, n, stdin); | |
| 1002 #else | |
| 1003 #ifdef UNDER_CE | |
| 1004 return fread(s, 1, n, soap->recvfd); | |
| 1005 #else | |
| 1006 #ifdef WMW_RPM_IO | |
| 1007 if (soap->rpmreqid) | |
| 1008 r = httpBlockRead(soap->rpmreqid, s, n); | |
| 1009 else | |
| 1010 #endif | |
| 1011 #ifdef WIN32 | |
| 1012 r = _read(soap->recvfd, s, (unsigned int)n); | |
| 1013 #else | |
| 1014 r = read(soap->recvfd, s, (unsigned int)n); | |
| 1015 #endif | |
| 1016 if (r >= 0) | |
| 1017 return (size_t)r; | |
| 1018 soap->errnum = soap_errno; | |
| 1019 return 0; | |
| 1020 #endif | |
| 1021 #endif | |
| 1022 } | |
| 1023 #endif | |
| 1024 #endif | |
| 1025 | |
| 1026 /******************************************************************************/ | |
| 1027 #ifndef WITH_NOHTTP | |
| 1028 #ifndef PALM_1 | |
| 1029 static soap_wchar | |
| 1030 soap_getchunkchar(struct soap *soap) | |
| 1031 { if (soap->bufidx < soap->buflen) | |
| 1032 return soap->buf[soap->bufidx++]; | |
| 1033 soap->bufidx = 0; | |
| 1034 soap->buflen = soap->chunkbuflen = soap->frecv(soap, soap->buf, SOAP_BUFLEN); | |
| 1035 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket=%d/fd=%d\n", (unsigned int)soap->buflen, soap->socket, soap->recvfd)); | |
| 1036 DBGMSG(RECV, soap->buf, soap->buflen); | |
| 1037 if (soap->buflen) | |
| 1038 return soap->buf[soap->bufidx++]; | |
| 1039 return EOF; | |
| 1040 } | |
| 1041 #endif | |
| 1042 #endif | |
| 1043 | |
| 1044 /******************************************************************************/ | |
| 1045 #ifndef PALM_1 | |
| 1046 static int | |
| 1047 soap_isxdigit(int c) | |
| 1048 { return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); | |
| 1049 } | |
| 1050 #endif | |
| 1051 | |
| 1052 /******************************************************************************/ | |
| 1053 #ifndef PALM_1 | |
| 1054 SOAP_FMAC1 | |
| 1055 int | |
| 1056 SOAP_FMAC2 | |
| 1057 soap_recv_raw(struct soap *soap) | |
| 1058 { register size_t ret; | |
| 1059 #if !defined(WITH_LEANER) || defined(WITH_ZLIB) | |
| 1060 register int r; | |
| 1061 #endif | |
| 1062 #ifdef WITH_ZLIB | |
| 1063 if (soap->mode & SOAP_ENC_ZLIB) | |
| 1064 { if (soap->d_stream->next_out == Z_NULL) | |
| 1065 { soap->bufidx = soap->buflen = 0; | |
| 1066 return EOF; | |
| 1067 } | |
| 1068 if (soap->d_stream->avail_in || !soap->d_stream->avail_out) | |
| 1069 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflating\n")); | |
| 1070 soap->d_stream->next_out = (Byte*)soap->buf; | |
| 1071 soap->d_stream->avail_out = SOAP_BUFLEN; | |
| 1072 r = inflate(soap->d_stream, Z_NO_FLUSH); | |
| 1073 if (r == Z_NEED_DICT && soap->z_dict) | |
| 1074 r = inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len); | |
| 1075 if (r == Z_OK || r == Z_STREAM_END) | |
| 1076 { soap->bufidx = 0; | |
| 1077 ret = soap->buflen = SOAP_BUFLEN - soap->d_stream->avail_out; | |
| 1078 if (soap->zlib_in == SOAP_ZLIB_GZIP) | |
| 1079 soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)ret); | |
| 1080 if (r == Z_STREAM_END) | |
| 1081 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out)); | |
| 1082 soap->z_ratio_in = (float)soap->d_stream->total_in / (float)soap->d_stream->total_out; | |
| 1083 soap->d_stream->next_out = Z_NULL; | |
| 1084 } | |
| 1085 if (ret) | |
| 1086 { soap->count += ret; | |
| 1087 DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- decompressed ----\n")); | |
| 1088 DBGMSG(RECV, soap->buf, ret); | |
| 1089 DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n----\n")); | |
| 1090 #ifndef WITH_LEANER | |
| 1091 if (soap->fpreparerecv && (r = soap->fpreparerecv(soap, soap->buf, ret))) | |
| 1092 return soap->error = r; | |
| 1093 #endif | |
| 1094 return SOAP_OK; | |
| 1095 } | |
| 1096 } | |
| 1097 else if (r != Z_BUF_ERROR) | |
| 1098 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate error: %s\n", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS)); | |
| 1099 soap->d_stream->next_out = Z_NULL; | |
| 1100 return soap->error = SOAP_ZLIB_ERROR; | |
| 1101 } | |
| 1102 } | |
| 1103 zlib_again: | |
| 1104 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK && !soap->chunksize) | |
| 1105 { memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN); | |
| 1106 soap->buflen = soap->z_buflen; | |
| 1107 } | |
| 1108 DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- compressed ----\n")); | |
| 1109 } | |
| 1110 #endif | |
| 1111 #ifndef WITH_NOHTTP | |
| 1112 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) /* read HTTP chunked transfer */ | |
| 1113 { for (;;) | |
| 1114 { register soap_wchar c; | |
| 1115 char *t, tmp[17]; | |
| 1116 if (soap->chunksize) | |
| 1117 { soap->buflen = ret = soap->frecv(soap, soap->buf, soap->chunksize > SOAP_BUFLEN ? SOAP_BUFLEN : soap->chunksize); | |
| 1118 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk: read %u bytes\n", (unsigned int)ret)); | |
| 1119 DBGMSG(RECV, soap->buf, ret); | |
| 1120 soap->bufidx = 0; | |
| 1121 soap->chunksize -= ret; | |
| 1122 break; | |
| 1123 } | |
| 1124 t = tmp; | |
| 1125 if (!soap->chunkbuflen) | |
| 1126 { soap->chunkbuflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN); | |
| 1127 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes (chunked) from socket=%d\n", (unsigned int)ret, soap->socket)); | |
| 1128 DBGMSG(RECV, soap->buf, ret); | |
| 1129 soap->bufidx = 0; | |
| 1130 if (!ret) | |
| 1131 { soap->ahead = EOF; | |
| 1132 return EOF; | |
| 1133 } | |
| 1134 } | |
| 1135 else | |
| 1136 soap->bufidx = soap->buflen; | |
| 1137 soap->buflen = soap->chunkbuflen; | |
| 1138 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk size (idx=%u len=%u)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen)); | |
| 1139 while (!soap_isxdigit((int)(c = soap_getchunkchar(soap)))) | |
| 1140 { if ((int)c == EOF) | |
| 1141 { soap->ahead = EOF; | |
| 1142 return EOF; | |
| 1143 } | |
| 1144 } | |
| 1145 do | |
| 1146 *t++ = (char)c; | |
| 1147 while (soap_isxdigit((int)(c = soap_getchunkchar(soap))) && (size_t)(t - tmp) < sizeof(tmp)-1); | |
| 1148 while ((int)c != EOF && c != '\n') | |
| 1149 c = soap_getchunkchar(soap); | |
| 1150 if ((int)c == EOF) | |
| 1151 { soap->ahead = EOF; | |
| 1152 return EOF; | |
| 1153 } | |
| 1154 *t = '\0'; | |
| 1155 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunk size = %s (hex)\n", tmp)); | |
| 1156 soap->chunksize = (size_t)soap_strtoul(tmp, &t, 16); | |
| 1157 if (!soap->chunksize) | |
| 1158 { soap->bufidx = soap->buflen = soap->chunkbuflen = 0; | |
| 1159 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of chunked message\n")); | |
| 1160 while ((int)c != EOF && c != '\n') | |
| 1161 c = soap_getchunkchar(soap); | |
| 1162 ret = 0; | |
| 1163 soap->ahead = EOF; | |
| 1164 break; | |
| 1165 } | |
| 1166 soap->buflen = soap->bufidx + soap->chunksize; | |
| 1167 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving buf len to idx=%u len=%u (%s)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen, tmp)); | |
| 1168 if (soap->buflen > soap->chunkbuflen) | |
| 1169 { soap->buflen = soap->chunkbuflen; | |
| 1170 soap->chunksize -= soap->buflen - soap->bufidx; | |
| 1171 soap->chunkbuflen = 0; | |
| 1172 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Passed end of buffer for chunked HTTP (%u bytes left)\n", (unsigned int)(soap->buflen - soap->bufidx))); | |
| 1173 } | |
| 1174 else if (soap->chunkbuflen) | |
| 1175 soap->chunksize = 0; | |
| 1176 ret = soap->buflen - soap->bufidx; | |
| 1177 if (ret) | |
| 1178 break; | |
| 1179 } | |
| 1180 } | |
| 1181 else | |
| 1182 #endif | |
| 1183 { soap->bufidx = 0; | |
| 1184 soap->buflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN); | |
| 1185 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket=%d/fd=%d\n", (unsigned int)ret, soap->socket, soap->recvfd)); | |
| 1186 DBGMSG(RECV, soap->buf, ret); | |
| 1187 } | |
| 1188 #ifdef WITH_ZLIB | |
| 1189 if (soap->mode & SOAP_ENC_ZLIB) | |
| 1190 { memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); | |
| 1191 soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx); | |
| 1192 soap->d_stream->avail_in = (unsigned int)ret; | |
| 1193 soap->d_stream->next_out = (Byte*)soap->buf; | |
| 1194 soap->d_stream->avail_out = SOAP_BUFLEN; | |
| 1195 r = inflate(soap->d_stream, Z_NO_FLUSH); | |
| 1196 if (r == Z_NEED_DICT && soap->z_dict) | |
| 1197 r = inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len); | |
| 1198 if (r == Z_OK || r == Z_STREAM_END) | |
| 1199 { soap->bufidx = 0; | |
| 1200 soap->z_buflen = soap->buflen; | |
| 1201 soap->buflen = SOAP_BUFLEN - soap->d_stream->avail_out; | |
| 1202 if (soap->zlib_in == SOAP_ZLIB_GZIP) | |
| 1203 soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen); | |
| 1204 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %u bytes\n", (unsigned int)soap->buflen)); | |
| 1205 if (ret && !soap->buflen && r != Z_STREAM_END) | |
| 1206 goto zlib_again; | |
| 1207 ret = soap->buflen; | |
| 1208 if (r == Z_STREAM_END) | |
| 1209 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated total %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out)); | |
| 1210 soap->z_ratio_in = (float)soap->d_stream->total_in / (float)soap->d_stream->total_out; | |
| 1211 soap->d_stream->next_out = Z_NULL; | |
| 1212 } | |
| 1213 DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- decompressed ----\n")); | |
| 1214 DBGMSG(RECV, soap->buf, ret); | |
| 1215 #ifndef WITH_LEANER | |
| 1216 if (soap->fpreparerecv && (r = soap->fpreparerecv(soap, soap->buf, ret))) | |
| 1217 return soap->error = r; | |
| 1218 #endif | |
| 1219 } | |
| 1220 else | |
| 1221 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to inflate: (%d) %s\n", r, soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS)); | |
| 1222 soap->d_stream->next_out = Z_NULL; | |
| 1223 return soap->error = SOAP_ZLIB_ERROR; | |
| 1224 } | |
| 1225 } | |
| 1226 #endif | |
| 1227 #ifndef WITH_LEANER | |
| 1228 if (soap->fpreparerecv | |
| 1229 #ifdef WITH_ZLIB | |
| 1230 && soap->zlib_in == SOAP_ZLIB_NONE | |
| 1231 #endif | |
| 1232 && (r = soap->fpreparerecv(soap, soap->buf + soap->bufidx, ret))) | |
| 1233 return soap->error = r; | |
| 1234 #endif | |
| 1235 soap->count += ret; | |
| 1236 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read count=%lu (+%lu)\n", (unsigned long)soap->count, (unsigned long)ret)); | |
| 1237 return !ret; | |
| 1238 } | |
| 1239 #endif | |
| 1240 | |
| 1241 /******************************************************************************/ | |
| 1242 #ifndef PALM_1 | |
| 1243 SOAP_FMAC1 | |
| 1244 int | |
| 1245 SOAP_FMAC2 | |
| 1246 soap_recv(struct soap *soap) | |
| 1247 { | |
| 1248 #ifndef WITH_LEANER | |
| 1249 if (soap->mode & SOAP_ENC_DIME) | |
| 1250 { if (soap->dime.buflen) | |
| 1251 { char *s; | |
| 1252 int i; | |
| 1253 unsigned char tmp[12]; | |
| 1254 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME hdr for chunked DIME is in buffer\n")); | |
| 1255 soap->count += soap->dime.buflen - soap->buflen; | |
| 1256 soap->buflen = soap->dime.buflen; | |
| 1257 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Skip padding (%ld bytes)\n", -(long)soap->dime.size&3)); | |
| 1258 for (i = -(long)soap->dime.size&3; i > 0; i--) | |
| 1259 { soap->bufidx++; | |
| 1260 if (soap->bufidx >= soap->buflen) | |
| 1261 if (soap_recv_raw(soap)) | |
| 1262 return EOF; | |
| 1263 } | |
| 1264 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME hdr for next chunk\n")); | |
| 1265 s = (char*)tmp; | |
| 1266 for (i = 12; i > 0; i--) | |
| 1267 { *s++ = soap->buf[soap->bufidx++]; | |
| 1268 if (soap->bufidx >= soap->buflen) | |
| 1269 if (soap_recv_raw(soap)) | |
| 1270 return EOF; | |
| 1271 } | |
| 1272 soap->dime.flags = tmp[0] & 0x7; | |
| 1273 soap->dime.size = ((size_t)tmp[8] << 24) | ((size_t)tmp[9] << 16) | ((size_t)tmp[10] << 8) | ((size_t)tmp[11]); | |
| 1274 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME chunk (%u bytes)\n", (unsigned int)soap->dime.size)); | |
| 1275 if (soap->dime.flags & SOAP_DIME_CF) | |
| 1276 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "More chunking\n")); | |
| 1277 soap->dime.chunksize = soap->dime.size; | |
| 1278 if (soap->buflen - soap->bufidx >= soap->dime.size) | |
| 1279 { soap->dime.buflen = soap->buflen; | |
| 1280 soap->buflen = soap->bufidx + soap->dime.chunksize; | |
| 1281 } | |
| 1282 else | |
| 1283 soap->dime.chunksize -= soap->buflen - soap->bufidx; | |
| 1284 } | |
| 1285 else | |
| 1286 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Last chunk\n")); | |
| 1287 soap->dime.buflen = 0; | |
| 1288 soap->dime.chunksize = 0; | |
| 1289 } | |
| 1290 soap->count = soap->buflen - soap->bufidx; | |
| 1291 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%u bytes remaining\n", (unsigned int)soap->count)); | |
| 1292 return SOAP_OK; | |
| 1293 } | |
| 1294 if (soap->dime.chunksize) | |
| 1295 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get next DIME hdr for chunked DIME (%u bytes chunk)\n", (unsigned int)soap->dime.chunksize)); | |
| 1296 if (soap_recv_raw(soap)) | |
| 1297 return EOF; | |
| 1298 if (soap->buflen - soap->bufidx >= soap->dime.chunksize) | |
| 1299 { soap->dime.buflen = soap->buflen; | |
| 1300 soap->count -= soap->buflen - soap->bufidx - soap->dime.chunksize; | |
| 1301 soap->buflen = soap->bufidx + soap->dime.chunksize; | |
| 1302 } | |
| 1303 else | |
| 1304 soap->dime.chunksize -= soap->buflen - soap->bufidx; | |
| 1305 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%lu bytes remaining, count=%lu\n", (unsigned long)(soap->buflen-soap->bufidx), (unsigned long)soap->count)); | |
| 1306 return SOAP_OK; | |
| 1307 } | |
| 1308 } | |
| 1309 while (soap->ffilterrecv) | |
| 1310 { int err, last = soap->filterstop; | |
| 1311 if (last) | |
| 1312 soap->bufidx = soap->buflen = 0; | |
| 1313 if ((err = soap->ffilterrecv(soap, soap->buf, &soap->buflen, sizeof(soap->buf)))) | |
| 1314 return soap->error = err; | |
| 1315 if (soap->buflen) | |
| 1316 { soap->bufidx = 0; | |
| 1317 soap->filterstop = last; | |
| 1318 return SOAP_OK; | |
| 1319 } | |
| 1320 if (last) | |
| 1321 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Returning postponed error %d\n", last)); | |
| 1322 soap->filterstop = SOAP_OK; | |
| 1323 return last; | |
| 1324 } | |
| 1325 soap->filterstop = soap_recv_raw(soap); /* do not call again after EOF */ | |
| 1326 } | |
| 1327 #endif | |
| 1328 return soap_recv_raw(soap); | |
| 1329 } | |
| 1330 #endif | |
| 1331 | |
| 1332 /******************************************************************************/ | |
| 1333 #ifndef PALM_1 | |
| 1334 SOAP_FMAC1 | |
| 1335 soap_wchar | |
| 1336 SOAP_FMAC2 | |
| 1337 soap_getchar(struct soap *soap) | |
| 1338 { register soap_wchar c; | |
| 1339 c = soap->ahead; | |
| 1340 if (c) | |
| 1341 { if (c != EOF) | |
| 1342 soap->ahead = 0; | |
| 1343 return c; | |
| 1344 } | |
| 1345 return soap_get1(soap); | |
| 1346 } | |
| 1347 #endif | |
| 1348 | |
| 1349 /******************************************************************************/ | |
| 1350 #ifndef PALM_1 | |
| 1351 SOAP_FMAC1 | |
| 1352 const struct soap_code_map* | |
| 1353 SOAP_FMAC2 | |
| 1354 soap_code(const struct soap_code_map *code_map, const char *str) | |
| 1355 { if (code_map && str) | |
| 1356 { while (code_map->string) | |
| 1357 { if (!strcmp(str, code_map->string)) /* case sensitive */ | |
| 1358 return code_map; | |
| 1359 code_map++; | |
| 1360 } | |
| 1361 } | |
| 1362 return NULL; | |
| 1363 } | |
| 1364 #endif | |
| 1365 | |
| 1366 /******************************************************************************/ | |
| 1367 #ifndef PALM_1 | |
| 1368 SOAP_FMAC1 | |
| 1369 long | |
| 1370 SOAP_FMAC2 | |
| 1371 soap_code_int(const struct soap_code_map *code_map, const char *str, long other) | |
| 1372 { if (code_map) | |
| 1373 { while (code_map->string) | |
| 1374 { if (!soap_tag_cmp(str, code_map->string)) /* case insensitive */ | |
| 1375 return code_map->code; | |
| 1376 code_map++; | |
| 1377 } | |
| 1378 } | |
| 1379 return other; | |
| 1380 } | |
| 1381 #endif | |
| 1382 | |
| 1383 /******************************************************************************/ | |
| 1384 #ifndef PALM_1 | |
| 1385 SOAP_FMAC1 | |
| 1386 const char* | |
| 1387 SOAP_FMAC2 | |
| 1388 soap_code_str(const struct soap_code_map *code_map, long code) | |
| 1389 { if (!code_map) | |
| 1390 return NULL; | |
| 1391 while (code_map->code != code && code_map->string) | |
| 1392 code_map++; | |
| 1393 return code_map->string; | |
| 1394 } | |
| 1395 #endif | |
| 1396 | |
| 1397 /******************************************************************************/ | |
| 1398 #ifndef PALM_1 | |
| 1399 SOAP_FMAC1 | |
| 1400 long | |
| 1401 SOAP_FMAC2 | |
| 1402 soap_code_bits(const struct soap_code_map *code_map, const char *str) | |
| 1403 { register long bits = 0; | |
| 1404 if (code_map) | |
| 1405 { while (str && *str) | |
| 1406 { const struct soap_code_map *p; | |
| 1407 for (p = code_map; p->string; p++) | |
| 1408 { register size_t n = strlen(p->string); | |
| 1409 if (!strncmp(p->string, str, n) && soap_blank((soap_wchar)str[n])) | |
| 1410 { bits |= p->code; | |
| 1411 str += n; | |
| 1412 while (*str > 0 && *str <= 32) | |
| 1413 str++; | |
| 1414 break; | |
| 1415 } | |
| 1416 } | |
| 1417 if (!p->string) | |
| 1418 return 0; | |
| 1419 } | |
| 1420 } | |
| 1421 return bits; | |
| 1422 } | |
| 1423 #endif | |
| 1424 | |
| 1425 /******************************************************************************/ | |
| 1426 #ifndef PALM_1 | |
| 1427 SOAP_FMAC1 | |
| 1428 const char* | |
| 1429 SOAP_FMAC2 | |
| 1430 soap_code_list(struct soap *soap, const struct soap_code_map *code_map, long code) | |
| 1431 { register char *t = soap->tmpbuf; | |
| 1432 if (code_map) | |
| 1433 { while (code_map->string) | |
| 1434 { if (code_map->code & code) | |
| 1435 { register const char *s = code_map->string; | |
| 1436 if (t != soap->tmpbuf) | |
| 1437 *t++ = ' '; | |
| 1438 while (*s && t < soap->tmpbuf + sizeof(soap->tmpbuf) - 1) | |
| 1439 *t++ = *s++; | |
| 1440 if (t == soap->tmpbuf + sizeof(soap->tmpbuf) - 1) | |
| 1441 break; | |
| 1442 } | |
| 1443 code_map++; | |
| 1444 } | |
| 1445 } | |
| 1446 *t = '\0'; | |
| 1447 return soap->tmpbuf; | |
| 1448 } | |
| 1449 #endif | |
| 1450 | |
| 1451 /******************************************************************************/ | |
| 1452 #ifndef PALM_1 | |
| 1453 static soap_wchar | |
| 1454 soap_char(struct soap *soap) | |
| 1455 { char tmp[8]; | |
| 1456 register int i; | |
| 1457 register soap_wchar c; | |
| 1458 register char *s = tmp; | |
| 1459 for (i = 0; i < 7; i++) | |
| 1460 { c = soap_get1(soap); | |
| 1461 if (c == ';' || (int)c == EOF) | |
| 1462 break; | |
| 1463 *s++ = (char)c; | |
| 1464 } | |
| 1465 *s = '\0'; | |
| 1466 if (*tmp == '#') | |
| 1467 { if (tmp[1] == 'x' || tmp[1] == 'X') | |
| 1468 return (soap_wchar)soap_strtol(tmp + 2, NULL, 16); | |
| 1469 return (soap_wchar)soap_strtol(tmp + 1, NULL, 10); | |
| 1470 } | |
| 1471 if (!strcmp(tmp, "lt")) | |
| 1472 return '<'; | |
| 1473 if (!strcmp(tmp, "gt")) | |
| 1474 return '>'; | |
| 1475 if (!strcmp(tmp, "amp")) | |
| 1476 return '&'; | |
| 1477 if (!strcmp(tmp, "quot")) | |
| 1478 return '"'; | |
| 1479 if (!strcmp(tmp, "apos")) | |
| 1480 return '\''; | |
| 1481 #ifndef WITH_LEAN | |
| 1482 return (soap_wchar)soap_code_int(html_entity_codes, tmp, SOAP_UNKNOWN_CHAR); | |
| 1483 #else | |
| 1484 return SOAP_UNKNOWN_CHAR; /* use this to represent unknown code */ | |
| 1485 #endif | |
| 1486 } | |
| 1487 #endif | |
| 1488 | |
| 1489 /******************************************************************************/ | |
| 1490 #ifdef WITH_LEAN | |
| 1491 #ifndef PALM_1 | |
| 1492 soap_wchar | |
| 1493 soap_get0(struct soap *soap) | |
| 1494 { if (soap->bufidx >= soap->buflen && soap_recv(soap)) | |
| 1495 return EOF; | |
| 1496 return (unsigned char)soap->buf[soap->bufidx]; | |
| 1497 } | |
| 1498 #endif | |
| 1499 #endif | |
| 1500 | |
| 1501 /******************************************************************************/ | |
| 1502 #ifdef WITH_LEAN | |
| 1503 #ifndef PALM_1 | |
| 1504 soap_wchar | |
| 1505 soap_get1(struct soap *soap) | |
| 1506 { if (soap->bufidx >= soap->buflen && soap_recv(soap)) | |
| 1507 return EOF; | |
| 1508 return (unsigned char)soap->buf[soap->bufidx++]; | |
| 1509 } | |
| 1510 #endif | |
| 1511 #endif | |
| 1512 | |
| 1513 /******************************************************************************/ | |
| 1514 #ifndef PALM_1 | |
| 1515 SOAP_FMAC1 | |
| 1516 soap_wchar | |
| 1517 SOAP_FMAC2 | |
| 1518 soap_get(struct soap *soap) | |
| 1519 { register soap_wchar c; | |
| 1520 c = soap->ahead; | |
| 1521 if (c) | |
| 1522 { if ((int)c != EOF) | |
| 1523 soap->ahead = 0; | |
| 1524 } | |
| 1525 else | |
| 1526 c = soap_get1(soap); | |
| 1527 while ((int)c != EOF) | |
| 1528 { if (soap->cdata) | |
| 1529 { if (c == ']') | |
| 1530 { c = soap_get1(soap); | |
| 1531 if (c == ']') | |
| 1532 { c = soap_get0(soap); | |
| 1533 if (c == '>') | |
| 1534 { soap->cdata = 0; | |
| 1535 c = soap_get1(soap); | |
| 1536 c = soap_get1(soap); | |
| 1537 } | |
| 1538 else | |
| 1539 { soap_unget(soap, ']'); | |
| 1540 return ']'; | |
| 1541 } | |
| 1542 } | |
| 1543 else | |
| 1544 { soap_revget1(soap); | |
| 1545 return ']'; | |
| 1546 } | |
| 1547 } | |
| 1548 else | |
| 1549 return c; | |
| 1550 } | |
| 1551 switch (c) | |
| 1552 { case '<': | |
| 1553 do c = soap_get1(soap); | |
| 1554 while (soap_blank(c)); | |
| 1555 if (c == '!' || c == '?' || c == '%') | |
| 1556 { register int k = 1; | |
| 1557 if (c == '!') | |
| 1558 { c = soap_get1(soap); | |
| 1559 if (c == '[') | |
| 1560 { do c = soap_get1(soap); | |
| 1561 while ((int)c != EOF && c != '['); | |
| 1562 if ((int)c == EOF) | |
| 1563 break; | |
| 1564 soap->cdata = 1; | |
| 1565 c = soap_get1(soap); | |
| 1566 continue; | |
| 1567 } | |
| 1568 if (c == '-' && (c = soap_get1(soap)) == '-') | |
| 1569 { do | |
| 1570 { c = soap_get1(soap); | |
| 1571 if (c == '-' && (c = soap_get1(soap)) == '-') | |
| 1572 break; | |
| 1573 } while ((int)c != EOF); | |
| 1574 } | |
| 1575 } | |
| 1576 else if (c == '?') | |
| 1577 c = soap_get_pi(soap); | |
| 1578 while ((int)c != EOF) | |
| 1579 { if (c == '<') | |
| 1580 k++; | |
| 1581 else if (c == '>') | |
| 1582 { if (--k <= 0) | |
| 1583 break; | |
| 1584 } | |
| 1585 c = soap_get1(soap); | |
| 1586 } | |
| 1587 if ((int)c == EOF) | |
| 1588 break; | |
| 1589 c = soap_get1(soap); | |
| 1590 continue; | |
| 1591 } | |
| 1592 if (c == '/') | |
| 1593 return SOAP_TT; | |
| 1594 soap_revget1(soap); | |
| 1595 return SOAP_LT; | |
| 1596 case '>': | |
| 1597 return SOAP_GT; | |
| 1598 case '"': | |
| 1599 return SOAP_QT; | |
| 1600 case '\'': | |
| 1601 return SOAP_AP; | |
| 1602 case '&': | |
| 1603 return soap_char(soap) | 0x80000000; | |
| 1604 } | |
| 1605 break; | |
| 1606 } | |
| 1607 return c; | |
| 1608 } | |
| 1609 #endif | |
| 1610 | |
| 1611 /******************************************************************************/ | |
| 1612 #ifndef PALM_1 | |
| 1613 static soap_wchar | |
| 1614 soap_get_pi(struct soap *soap) | |
| 1615 { char buf[64]; | |
| 1616 register char *s = buf; | |
| 1617 register int i = sizeof(buf); | |
| 1618 register soap_wchar c = soap_getchar(soap); | |
| 1619 /* This is a quick way to parse XML PI and we could use a callback instead to | |
| 1620 * enable applications to intercept processing instructions */ | |
| 1621 while ((int)c != EOF && c != '?') | |
| 1622 { if (--i > 0) | |
| 1623 { if (soap_blank(c)) | |
| 1624 c = ' '; | |
| 1625 *s++ = (char)c; | |
| 1626 } | |
| 1627 c = soap_getchar(soap); | |
| 1628 } | |
| 1629 *s = '\0'; | |
| 1630 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "XML PI <?%s?>\n", buf)); | |
| 1631 if (!strncmp(buf, "xml ", 4)) | |
| 1632 { s = strstr(buf, " encoding="); | |
| 1633 if (s && s[10]) | |
| 1634 { if (!soap_tag_cmp(s + 11, "iso-8859-1*") | |
| 1635 || !soap_tag_cmp(s + 11, "latin1*")) | |
| 1636 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to latin1 encoding\n")); | |
| 1637 soap->mode |= SOAP_ENC_LATIN; | |
| 1638 } | |
| 1639 else if (!soap_tag_cmp(s + 11, "utf-8*")) | |
| 1640 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to utf-8 encoding\n")); | |
| 1641 soap->mode &= ~SOAP_ENC_LATIN; | |
| 1642 } | |
| 1643 } | |
| 1644 } | |
| 1645 if ((int)c != EOF) | |
| 1646 c = soap_getchar(soap); | |
| 1647 return c; | |
| 1648 } | |
| 1649 #endif | |
| 1650 | |
| 1651 /******************************************************************************/ | |
| 1652 #ifndef WITH_LEANER | |
| 1653 #ifndef PALM_1 | |
| 1654 SOAP_FMAC1 | |
| 1655 int | |
| 1656 SOAP_FMAC2 | |
| 1657 soap_move(struct soap *soap, size_t n) | |
| 1658 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving %lu bytes forward\n", (unsigned long)n)); | |
| 1659 for (; n; n--) | |
| 1660 if ((int)soap_getchar(soap) == EOF) | |
| 1661 return SOAP_EOF; | |
| 1662 return SOAP_OK; | |
| 1663 } | |
| 1664 #endif | |
| 1665 #endif | |
| 1666 | |
| 1667 /******************************************************************************/ | |
| 1668 #ifndef WITH_LEANER | |
| 1669 #ifndef PALM_1 | |
| 1670 SOAP_FMAC1 | |
| 1671 size_t | |
| 1672 SOAP_FMAC2 | |
| 1673 soap_tell(struct soap *soap) | |
| 1674 { return soap->count - soap->buflen + soap->bufidx - (soap->ahead != 0); | |
| 1675 } | |
| 1676 #endif | |
| 1677 #endif | |
| 1678 | |
| 1679 /******************************************************************************/ | |
| 1680 #ifndef PALM_1 | |
| 1681 SOAP_FMAC1 | |
| 1682 int | |
| 1683 SOAP_FMAC2 | |
| 1684 soap_pututf8(struct soap *soap, register unsigned long c) | |
| 1685 { char tmp[16]; | |
| 1686 if (c < 0x80 && c > 0) | |
| 1687 { *tmp = (char)c; | |
| 1688 return soap_send_raw(soap, tmp, 1); | |
| 1689 } | |
| 1690 #ifndef WITH_LEAN | |
| 1691 if (c >= 0x80) | |
| 1692 { register char *t = tmp; | |
| 1693 if (c < 0x0800) | |
| 1694 *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); | |
| 1695 else | |
| 1696 { if (c < 0x010000) | |
| 1697 *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); | |
| 1698 else | |
| 1699 { if (c < 0x200000) | |
| 1700 *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); | |
| 1701 else | |
| 1702 { if (c < 0x04000000) | |
| 1703 *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); | |
| 1704 else | |
| 1705 { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); | |
| 1706 *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); | |
| 1707 } | |
| 1708 *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); | |
| 1709 } | |
| 1710 *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); | |
| 1711 } | |
| 1712 *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); | |
| 1713 } | |
| 1714 *t++ = (char)(0x80 | (c & 0x3F)); | |
| 1715 *t = '\0'; | |
| 1716 } | |
| 1717 else | |
| 1718 #endif | |
| 1719 #ifdef HAVE_SNPRINTF | |
| 1720 soap_snprintf(tmp, sizeof(tmp), "&#%lu;", c); | |
| 1721 #else | |
| 1722 sprintf(tmp, "&#%lu;", c); | |
| 1723 #endif | |
| 1724 return soap_send(soap, tmp); | |
| 1725 } | |
| 1726 #endif | |
| 1727 | |
| 1728 /******************************************************************************/ | |
| 1729 #ifndef PALM_1 | |
| 1730 SOAP_FMAC1 | |
| 1731 soap_wchar | |
| 1732 SOAP_FMAC2 | |
| 1733 soap_getutf8(struct soap *soap) | |
| 1734 { register soap_wchar c, c1, c2, c3, c4; | |
| 1735 c = soap->ahead; | |
| 1736 if (c >= 0x80) | |
| 1737 soap->ahead = 0; | |
| 1738 else | |
| 1739 c = soap_get(soap); | |
| 1740 if (c < 0x80 || c > 0xFF || (soap->mode & SOAP_ENC_LATIN)) | |
| 1741 return c; | |
| 1742 c1 = soap_get1(soap); | |
| 1743 if (c1 < 0x80) | |
| 1744 { soap_revget1(soap); /* doesn't look like this is UTF8 */ | |
| 1745 return c; | |
| 1746 } | |
| 1747 c1 &= 0x3F; | |
| 1748 if (c < 0xE0) | |
| 1749 return ((soap_wchar)(c & 0x1F) << 6) | c1; | |
| 1750 c2 = (soap_wchar)soap_get1(soap) & 0x3F; | |
| 1751 if (c < 0xF0) | |
| 1752 return ((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2; | |
| 1753 c3 = (soap_wchar)soap_get1(soap) & 0x3F; | |
| 1754 if (c < 0xF8) | |
| 1755 return ((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3; | |
| 1756 c4 = (soap_wchar)soap_get1(soap) & 0x3F; | |
| 1757 if (c < 0xFC) | |
| 1758 return ((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4; | |
| 1759 return ((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(soap_get1(soap) & 0x3F); | |
| 1760 } | |
| 1761 #endif | |
| 1762 | |
| 1763 /******************************************************************************/ | |
| 1764 #ifndef PALM_1 | |
| 1765 SOAP_FMAC1 | |
| 1766 int | |
| 1767 SOAP_FMAC2 | |
| 1768 soap_puthex(struct soap *soap, const unsigned char *s, int n) | |
| 1769 { char d[2]; | |
| 1770 register int i; | |
| 1771 #ifdef WITH_DOM | |
| 1772 if ((soap->mode & SOAP_XML_DOM) && soap->dom) | |
| 1773 { if (!(soap->dom->data = soap_s2hex(soap, s, NULL, n))) | |
| 1774 return soap->error; | |
| 1775 return SOAP_OK; | |
| 1776 } | |
| 1777 #endif | |
| 1778 for (i = 0; i < n; i++) | |
| 1779 { register int m = *s++; | |
| 1780 d[0] = (char)((m >> 4) + (m > 159 ? '7' : '0')); | |
| 1781 m &= 0x0F; | |
| 1782 d[1] = (char)(m + (m > 9 ? '7' : '0')); | |
| 1783 if (soap_send_raw(soap, d, 2)) | |
| 1784 return soap->error; | |
| 1785 } | |
| 1786 return SOAP_OK; | |
| 1787 } | |
| 1788 #endif | |
| 1789 | |
| 1790 /******************************************************************************/ | |
| 1791 #ifndef PALM_1 | |
| 1792 SOAP_FMAC1 | |
| 1793 unsigned char* | |
| 1794 SOAP_FMAC2 | |
| 1795 soap_gethex(struct soap *soap, int *n) | |
| 1796 { | |
| 1797 #ifdef WITH_DOM | |
| 1798 if ((soap->mode & SOAP_XML_DOM) && soap->dom) | |
| 1799 { soap->dom->data = soap_string_in(soap, 0, -1, -1); | |
| 1800 return (unsigned char*)soap_hex2s(soap, soap->dom->data, NULL, 0, n); | |
| 1801 } | |
| 1802 #endif | |
| 1803 #ifdef WITH_FAST | |
| 1804 soap->labidx = 0; | |
| 1805 for (;;) | |
| 1806 { register char *s; | |
| 1807 register size_t i, k; | |
| 1808 if (soap_append_lab(soap, NULL, 0)) | |
| 1809 return NULL; | |
| 1810 s = soap->labbuf + soap->labidx; | |
| 1811 k = soap->lablen - soap->labidx; | |
| 1812 soap->labidx = soap->lablen; | |
| 1813 for (i = 0; i < k; i++) | |
| 1814 { register char d1, d2; | |
| 1815 register soap_wchar c; | |
| 1816 c = soap_get(soap); | |
| 1817 if (soap_isxdigit(c)) | |
| 1818 { d1 = (char)c; | |
| 1819 c = soap_get(soap); | |
| 1820 if (soap_isxdigit(c)) | |
| 1821 d2 = (char)c; | |
| 1822 else | |
| 1823 { soap->error = SOAP_TYPE; | |
| 1824 return NULL; | |
| 1825 } | |
| 1826 } | |
| 1827 else | |
| 1828 { unsigned char *p; | |
| 1829 soap_unget(soap, c); | |
| 1830 if (n) | |
| 1831 *n = (int)(soap->lablen + i - k); | |
| 1832 p = (unsigned char*)soap_malloc(soap, soap->lablen + i - k); | |
| 1833 if (p) | |
| 1834 memcpy(p, soap->labbuf, soap->lablen + i - k); | |
| 1835 return p; | |
| 1836 } | |
| 1837 *s++ = (char)(((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0')); | |
| 1838 } | |
| 1839 } | |
| 1840 #else | |
| 1841 if (soap_new_block(soap) == NULL) | |
| 1842 return NULL; | |
| 1843 for (;;) | |
| 1844 { register int i; | |
| 1845 register char *s = (char*)soap_push_block(soap, NULL, SOAP_BLKLEN); | |
| 1846 if (!s) | |
| 1847 { soap_end_block(soap, NULL); | |
| 1848 return NULL; | |
| 1849 } | |
| 1850 for (i = 0; i < SOAP_BLKLEN; i++) | |
| 1851 { register char d1, d2; | |
| 1852 register soap_wchar c = soap_get(soap); | |
| 1853 if (soap_isxdigit(c)) | |
| 1854 { d1 = (char)c; | |
| 1855 c = soap_get(soap); | |
| 1856 if (soap_isxdigit(c)) | |
| 1857 d2 = (char)c; | |
| 1858 else | |
| 1859 { soap_end_block(soap, NULL); | |
| 1860 soap->error = SOAP_TYPE; | |
| 1861 return NULL; | |
| 1862 } | |
| 1863 } | |
| 1864 else | |
| 1865 { unsigned char *p; | |
| 1866 soap_unget(soap, c); | |
| 1867 if (n) | |
| 1868 *n = (int)soap_size_block(soap, NULL, i); | |
| 1869 p = (unsigned char*)soap_save_block(soap, NULL, 0); | |
| 1870 return p; | |
| 1871 } | |
| 1872 *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'); | |
| 1873 } | |
| 1874 } | |
| 1875 #endif | |
| 1876 } | |
| 1877 #endif | |
| 1878 | |
| 1879 /******************************************************************************/ | |
| 1880 #ifndef PALM_1 | |
| 1881 SOAP_FMAC1 | |
| 1882 int | |
| 1883 SOAP_FMAC2 | |
| 1884 soap_putbase64(struct soap *soap, const unsigned char *s, int n) | |
| 1885 { register int i; | |
| 1886 register unsigned long m; | |
| 1887 char d[4]; | |
| 1888 if (!s) | |
| 1889 return SOAP_OK; | |
| 1890 #ifdef WITH_DOM | |
| 1891 if ((soap->mode & SOAP_XML_DOM) && soap->dom) | |
| 1892 { if (!(soap->dom->data = soap_s2base64(soap, s, NULL, n))) | |
| 1893 return soap->error; | |
| 1894 return SOAP_OK; | |
| 1895 } | |
| 1896 #endif | |
| 1897 for (; n > 2; n -= 3, s += 3) | |
| 1898 { m = s[0]; | |
| 1899 m = (m << 8) | s[1]; | |
| 1900 m = (m << 8) | s[2]; | |
| 1901 for (i = 4; i > 0; m >>= 6) | |
| 1902 d[--i] = soap_base64o[m & 0x3F]; | |
| 1903 if (soap_send_raw(soap, d, 4)) | |
| 1904 return soap->error; | |
| 1905 } | |
| 1906 if (n > 0) | |
| 1907 { m = 0; | |
| 1908 for (i = 0; i < n; i++) | |
| 1909 m = (m << 8) | *s++; | |
| 1910 for (; i < 3; i++) | |
| 1911 m <<= 8; | |
| 1912 for (i++; i > 0; m >>= 6) | |
| 1913 d[--i] = soap_base64o[m & 0x3F]; | |
| 1914 for (i = 3; i > n; i--) | |
| 1915 d[i] = '='; | |
| 1916 if (soap_send_raw(soap, d, 4)) | |
| 1917 return soap->error; | |
| 1918 } | |
| 1919 return SOAP_OK; | |
| 1920 } | |
| 1921 #endif | |
| 1922 | |
| 1923 /******************************************************************************/ | |
| 1924 #ifndef PALM_1 | |
| 1925 SOAP_FMAC1 | |
| 1926 unsigned char* | |
| 1927 SOAP_FMAC2 | |
| 1928 soap_getbase64(struct soap *soap, int *n, int malloc_flag) | |
| 1929 { (void)malloc_flag; | |
| 1930 #ifdef WITH_DOM | |
| 1931 if ((soap->mode & SOAP_XML_DOM) && soap->dom) | |
| 1932 { soap->dom->data = soap_string_in(soap, 0, -1, -1); | |
| 1933 return (unsigned char*)soap_base642s(soap, soap->dom->data, NULL, 0, n); | |
| 1934 } | |
| 1935 #endif | |
| 1936 #ifdef WITH_FAST | |
| 1937 soap->labidx = 0; | |
| 1938 for (;;) | |
| 1939 { register size_t i, k; | |
| 1940 register char *s; | |
| 1941 if (soap_append_lab(soap, NULL, 2)) | |
| 1942 return NULL; | |
| 1943 s = soap->labbuf + soap->labidx; | |
| 1944 k = soap->lablen - soap->labidx; | |
| 1945 soap->labidx = 3 * (soap->lablen / 3); | |
| 1946 if (!s) | |
| 1947 return NULL; | |
| 1948 if (k > 2) | |
| 1949 { for (i = 0; i < k - 2; i += 3) | |
| 1950 { register unsigned long m = 0; | |
| 1951 register int j = 0; | |
| 1952 do | |
| 1953 { register soap_wchar c = soap_get(soap); | |
| 1954 if (c < SOAP_AP) | |
| 1955 c &= 0x7FFFFFFF; | |
| 1956 if (c == '=' || c < 0) | |
| 1957 { unsigned char *p; | |
| 1958 switch (j) | |
| 1959 { case 2: | |
| 1960 *s++ = (char)((m >> 4) & 0xFF); | |
| 1961 i++; | |
| 1962 break; | |
| 1963 case 3: | |
| 1964 *s++ = (char)((m >> 10) & 0xFF); | |
| 1965 *s++ = (char)((m >> 2) & 0xFF); | |
| 1966 i += 2; | |
| 1967 } | |
| 1968 if (n) | |
| 1969 *n = (int)(soap->lablen + i - k); | |
| 1970 p = (unsigned char*)soap_malloc(soap, soap->lablen + i - k); | |
| 1971 if (p) | |
| 1972 memcpy(p, soap->labbuf, soap->lablen + i - k); | |
| 1973 if (c >= 0) | |
| 1974 { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT) | |
| 1975 ; | |
| 1976 } | |
| 1977 soap_unget(soap, c); | |
| 1978 return p; | |
| 1979 } | |
| 1980 c -= '+'; | |
| 1981 if (c >= 0 && c <= 79) | |
| 1982 { register int b = soap_base64i[c]; | |
| 1983 if (b >= 64) | |
| 1984 { soap->error = SOAP_TYPE; | |
| 1985 return NULL; | |
| 1986 } | |
| 1987 m = (m << 6) + b; | |
| 1988 j++; | |
| 1989 } | |
| 1990 else if (!soap_blank(c + '+')) | |
| 1991 { soap->error = SOAP_TYPE; | |
| 1992 return NULL; | |
| 1993 } | |
| 1994 } while (j < 4); | |
| 1995 *s++ = (char)((m >> 16) & 0xFF); | |
| 1996 *s++ = (char)((m >> 8) & 0xFF); | |
| 1997 *s++ = (char)(m & 0xFF); | |
| 1998 } | |
| 1999 } | |
| 2000 } | |
| 2001 #else | |
| 2002 if (soap_new_block(soap) == NULL) | |
| 2003 return NULL; | |
| 2004 for (;;) | |
| 2005 { register int i; | |
| 2006 register char *s = (char*)soap_push_block(soap, NULL, 3 * SOAP_BLKLEN); /* must be multiple of 3 */ | |
| 2007 if (!s) | |
| 2008 { soap_end_block(soap, NULL); | |
| 2009 return NULL; | |
| 2010 } | |
| 2011 for (i = 0; i < SOAP_BLKLEN; i++) | |
| 2012 { register unsigned long m = 0; | |
| 2013 register int j = 0; | |
| 2014 do | |
| 2015 { register soap_wchar c = soap_get(soap); | |
| 2016 if (c == '=' || c < 0) | |
| 2017 { unsigned char *p; | |
| 2018 i *= 3; | |
| 2019 switch (j) | |
| 2020 { case 2: | |
| 2021 *s++ = (char)((m >> 4) & 0xFF); | |
| 2022 i++; | |
| 2023 break; | |
| 2024 case 3: | |
| 2025 *s++ = (char)((m >> 10) & 0xFF); | |
| 2026 *s++ = (char)((m >> 2) & 0xFF); | |
| 2027 i += 2; | |
| 2028 } | |
| 2029 if (n) | |
| 2030 *n = (int)soap_size_block(soap, NULL, i); | |
| 2031 p = (unsigned char*)soap_save_block(soap, NULL, 0); | |
| 2032 if (c >= 0) | |
| 2033 { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT) | |
| 2034 ; | |
| 2035 } | |
| 2036 soap_unget(soap, c); | |
| 2037 return p; | |
| 2038 } | |
| 2039 c -= '+'; | |
| 2040 if (c >= 0 && c <= 79) | |
| 2041 { int b = soap_base64i[c]; | |
| 2042 if (b >= 64) | |
| 2043 { soap->error = SOAP_TYPE; | |
| 2044 return NULL; | |
| 2045 } | |
| 2046 m = (m << 6) + b; | |
| 2047 j++; | |
| 2048 } | |
| 2049 else if (!soap_blank(c)) | |
| 2050 { soap->error = SOAP_TYPE; | |
| 2051 return NULL; | |
| 2052 } | |
| 2053 } while (j < 4); | |
| 2054 *s++ = (char)((m >> 16) & 0xFF); | |
| 2055 *s++ = (char)((m >> 8) & 0xFF); | |
| 2056 *s++ = (char)(m & 0xFF); | |
| 2057 } | |
| 2058 } | |
| 2059 #endif | |
| 2060 } | |
| 2061 #endif | |
| 2062 | |
| 2063 /******************************************************************************/ | |
| 2064 #ifndef WITH_LEANER | |
| 2065 #ifndef PALM_1 | |
| 2066 SOAP_FMAC1 | |
| 2067 int | |
| 2068 SOAP_FMAC2 | |
| 2069 soap_xop_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options) | |
| 2070 { /* Check MTOM xop:Include element (within hex/base64Binary) */ | |
| 2071 /* TODO: this code to be obsoleted with new import/xop.h conventions */ | |
| 2072 short body = soap->body; /* should save type too? */ | |
| 2073 if (!soap_peek_element(soap)) | |
| 2074 { if (!soap_element_begin_in(soap, "xop:Include", 0, NULL)) | |
| 2075 { if (soap_dime_forward(soap, ptr, size, id, type, options) | |
| 2076 || (soap->body && soap_element_end_in(soap, "xop:Include"))) | |
| 2077 return soap->error; | |
| 2078 } | |
| 2079 } | |
| 2080 soap->body = body; | |
| 2081 return SOAP_OK; | |
| 2082 } | |
| 2083 #endif | |
| 2084 #endif | |
| 2085 | |
| 2086 /******************************************************************************/ | |
| 2087 #ifndef WITH_LEANER | |
| 2088 #ifndef PALM_1 | |
| 2089 SOAP_FMAC1 | |
| 2090 int | |
| 2091 SOAP_FMAC2 | |
| 2092 soap_dime_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options) | |
| 2093 { struct soap_xlist *xp; | |
| 2094 *ptr = NULL; | |
| 2095 *size = 0; | |
| 2096 *id = NULL; | |
| 2097 *type = NULL; | |
| 2098 *options = NULL; | |
| 2099 if (!*soap->href) | |
| 2100 return SOAP_OK; | |
| 2101 *id = soap_strdup(soap, soap->href); | |
| 2102 xp = (struct soap_xlist*)SOAP_MALLOC(soap, sizeof(struct soap_xlist)); | |
| 2103 if (!xp) | |
| 2104 return soap->error = SOAP_EOM; | |
| 2105 xp->next = soap->xlist; | |
| 2106 xp->ptr = ptr; | |
| 2107 xp->size = size; | |
| 2108 xp->id = *id; | |
| 2109 xp->type = type; | |
| 2110 xp->options = options; | |
| 2111 soap->xlist = xp; | |
| 2112 return SOAP_OK; | |
| 2113 } | |
| 2114 #endif | |
| 2115 #endif | |
| 2116 | |
| 2117 /******************************************************************************/ | |
| 2118 #ifndef PALM_1 | |
| 2119 SOAP_FMAC1 | |
| 2120 char * | |
| 2121 SOAP_FMAC2 | |
| 2122 soap_strdup(struct soap *soap, const char *s) | |
| 2123 { char *t = NULL; | |
| 2124 if (s && (t = (char*)soap_malloc(soap, strlen(s) + 1))) | |
| 2125 strcpy(t, s); | |
| 2126 return t; | |
| 2127 } | |
| 2128 #endif | |
| 2129 | |
| 2130 /******************************************************************************/ | |
| 2131 #ifndef PALM_1 | |
| 2132 SOAP_FMAC1 | |
| 2133 wchar_t * | |
| 2134 SOAP_FMAC2 | |
| 2135 soap_wstrdup(struct soap *soap, const wchar_t *s) | |
| 2136 { wchar_t *t = NULL; | |
| 2137 if (s) | |
| 2138 { size_t n = 0; | |
| 2139 while (s[n]) | |
| 2140 n++; | |
| 2141 if ((t = (wchar_t*)soap_malloc(soap, sizeof(wchar_t)*(n+1)))) | |
| 2142 memcpy(t, s, sizeof(wchar_t)*(n+1)); | |
| 2143 } | |
| 2144 return t; | |
| 2145 } | |
| 2146 #endif | |
| 2147 | |
| 2148 /******************************************************************************/ | |
| 2149 #ifndef PALM_1 | |
| 2150 SOAP_FMAC1 | |
| 2151 struct soap_blist* | |
| 2152 SOAP_FMAC2 | |
| 2153 soap_new_block(struct soap *soap) | |
| 2154 { struct soap_blist *p; | |
| 2155 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New block sequence (prev=%p)\n", soap->blist)); | |
| 2156 if (!(p = (struct soap_blist*)SOAP_MALLOC(soap, sizeof(struct soap_blist)))) | |
| 2157 { soap->error = SOAP_EOM; | |
| 2158 return NULL; | |
| 2159 } | |
| 2160 p->next = soap->blist; | |
| 2161 p->ptr = NULL; | |
| 2162 p->size = 0; | |
| 2163 soap->blist = p; | |
| 2164 return p; | |
| 2165 } | |
| 2166 #endif | |
| 2167 | |
| 2168 /******************************************************************************/ | |
| 2169 #ifndef PALM_1 | |
| 2170 SOAP_FMAC1 | |
| 2171 void* | |
| 2172 SOAP_FMAC2 | |
| 2173 soap_push_block(struct soap *soap, struct soap_blist *b, size_t n) | |
| 2174 { char *p; | |
| 2175 if (!b) | |
| 2176 b = soap->blist; | |
| 2177 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push block of %u bytes (%u bytes total)\n", (unsigned int)n, (unsigned int)b->size + (unsigned int)n)); | |
| 2178 if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(char*) + sizeof(size_t)))) | |
| 2179 { soap->error = SOAP_EOM; | |
| 2180 return NULL; | |
| 2181 } | |
| 2182 *(char**)p = b->ptr; | |
| 2183 *(size_t*)(p + sizeof(char*)) = n; | |
| 2184 b->ptr = p; | |
| 2185 b->size += n; | |
| 2186 return p + sizeof(char*) + sizeof(size_t); | |
| 2187 } | |
| 2188 #endif | |
| 2189 | |
| 2190 /******************************************************************************/ | |
| 2191 #ifndef PALM_1 | |
| 2192 SOAP_FMAC1 | |
| 2193 void | |
| 2194 SOAP_FMAC2 | |
| 2195 soap_pop_block(struct soap *soap, struct soap_blist *b) | |
| 2196 { char *p; | |
| 2197 if (!b) | |
| 2198 b = soap->blist; | |
| 2199 if (!b->ptr) | |
| 2200 return; | |
| 2201 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop block\n")); | |
| 2202 p = b->ptr; | |
| 2203 b->size -= *(size_t*)(p + sizeof(char*)); | |
| 2204 b->ptr = *(char**)p; | |
| 2205 SOAP_FREE(soap, p); | |
| 2206 } | |
| 2207 #endif | |
| 2208 | |
| 2209 /******************************************************************************/ | |
| 2210 #ifndef PALM_1 | |
| 2211 SOAP_FMAC1 | |
| 2212 void | |
| 2213 SOAP_FMAC2 | |
| 2214 soap_update_pointers(struct soap *soap, char *start, char *end, char *p1, char *p2) | |
| 2215 { | |
| 2216 #ifndef WITH_NOIDREF | |
| 2217 int i; | |
| 2218 register struct soap_ilist *ip = NULL; | |
| 2219 register struct soap_flist *fp = NULL; | |
| 2220 #ifndef WITH_LEANER | |
| 2221 register struct soap_xlist *xp = NULL; | |
| 2222 #endif | |
| 2223 register void *p, **q; | |
| 2224 for (i = 0; i < SOAP_IDHASH; i++) | |
| 2225 { for (ip = soap->iht[i]; ip; ip = ip->next) | |
| 2226 { if (ip->ptr && (char*)ip->ptr >= start && (char*)ip->ptr < end) | |
| 2227 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", ip->id, ip->ptr, (char*)ip->ptr + (p1-p2))); | |
| 2228 ip->ptr = (char*)ip->ptr + (p1-p2); | |
| 2229 } | |
| 2230 for (q = &ip->link; q; q = (void**)p) | |
| 2231 { p = *q; | |
| 2232 if (p && (char*)p >= start && (char*)p < end) | |
| 2233 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Link update id='%s' %p\n", ip->id, p)); | |
| 2234 *q = (char*)p + (p1-p2); | |
| 2235 } | |
| 2236 } | |
| 2237 for (q = &ip->copy; q; q = (void**)p) | |
| 2238 { p = *q; | |
| 2239 if (p && (char*)p >= start && (char*)p < end) | |
| 2240 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy chain update id='%s' %p\n", ip->id, p)); | |
| 2241 *q = (char*)p + (p1-p2); | |
| 2242 } | |
| 2243 } | |
| 2244 for (fp = ip->flist; fp; fp = fp->next) | |
| 2245 { if ((char*)fp->ptr >= start && (char*)fp->ptr < end) | |
| 2246 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy list update id='%s' %p\n", ip->id, fp)); | |
| 2247 fp->ptr = (char*)fp->ptr + (p1-p2); | |
| 2248 } | |
| 2249 } | |
| 2250 } | |
| 2251 } | |
| 2252 #ifndef WITH_LEANER | |
| 2253 for (xp = soap->xlist; xp; xp = xp->next) | |
| 2254 { if (xp->ptr && (char*)xp->ptr >= start && (char*)xp->ptr < end) | |
| 2255 { 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))); | |
| 2256 xp->ptr = (unsigned char**)((char*)xp->ptr + (p1-p2)); | |
| 2257 xp->size = (int*)((char*)xp->size + (p1-p2)); | |
| 2258 xp->type = (char**)((char*)xp->type + (p1-p2)); | |
| 2259 xp->options = (char**)((char*)xp->options + (p1-p2)); | |
| 2260 } | |
| 2261 } | |
| 2262 #endif | |
| 2263 #else | |
| 2264 (void)soap; (void)start; (void)end; (void)p1; (void)p2; | |
| 2265 #endif | |
| 2266 } | |
| 2267 #endif | |
| 2268 | |
| 2269 /******************************************************************************/ | |
| 2270 #ifndef WITH_NOIDREF | |
| 2271 #ifndef PALM_1 | |
| 2272 static int | |
| 2273 soap_has_copies(struct soap *soap, register const char *start, register const char *end) | |
| 2274 { register int i; | |
| 2275 register struct soap_ilist *ip = NULL; | |
| 2276 register struct soap_flist *fp = NULL; | |
| 2277 register const char *p; | |
| 2278 for (i = 0; i < SOAP_IDHASH; i++) | |
| 2279 { for (ip = soap->iht[i]; ip; ip = ip->next) | |
| 2280 { for (p = (const char*)ip->copy; p; p = *(const char**)p) | |
| 2281 if (p >= start && p < end) | |
| 2282 return SOAP_ERR; | |
| 2283 for (fp = ip->flist; fp; fp = fp->next) | |
| 2284 if ((const char*)fp->ptr >= start && (const char*)fp->ptr < end) | |
| 2285 return SOAP_ERR; | |
| 2286 } | |
| 2287 } | |
| 2288 return SOAP_OK; | |
| 2289 } | |
| 2290 #endif | |
| 2291 #endif | |
| 2292 | |
| 2293 /******************************************************************************/ | |
| 2294 #ifndef WITH_NOIDREF | |
| 2295 #ifndef PALM_1 | |
| 2296 SOAP_FMAC1 | |
| 2297 int | |
| 2298 SOAP_FMAC2 | |
| 2299 soap_resolve(struct soap *soap) | |
| 2300 { register int i; | |
| 2301 register struct soap_ilist *ip = NULL; | |
| 2302 register struct soap_flist *fp = NULL; | |
| 2303 short flag; | |
| 2304 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data\n")); | |
| 2305 for (i = 0; i < SOAP_IDHASH; i++) | |
| 2306 { for (ip = soap->iht[i]; ip; ip = ip->next) | |
| 2307 { if (ip->ptr) | |
| 2308 { register void *p, **q, *r; | |
| 2309 q = (void**)ip->link; | |
| 2310 ip->link = NULL; | |
| 2311 r = ip->ptr; | |
| 2312 DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing link chain to resolve id='%s'\n", ip->id)); | |
| 2313 while (q) | |
| 2314 { p = *q; | |
| 2315 *q = r; | |
| 2316 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "... link %p -> %p\n", q, r)); | |
| 2317 q = (void**)p; | |
| 2318 } | |
| 2319 } | |
| 2320 else if (*ip->id == '#') | |
| 2321 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Missing data for id='%s'\n", ip->id)); | |
| 2322 strcpy(soap->id, ip->id + 1); | |
| 2323 return soap->error = SOAP_MISSING_ID; | |
| 2324 } | |
| 2325 } | |
| 2326 } | |
| 2327 do | |
| 2328 { flag = 0; | |
| 2329 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution phase\n")); | |
| 2330 for (i = 0; i < SOAP_IDHASH; i++) | |
| 2331 { for (ip = soap->iht[i]; ip; ip = ip->next) | |
| 2332 { if (ip->ptr && !soap_has_copies(soap, (const char*)ip->ptr, (const char*)ip->ptr + ip->size)) | |
| 2333 { if (ip->copy) | |
| 2334 { register void *p, **q = (void**)ip->copy; | |
| 2335 DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing copy chain to resolve id='%s'\n", ip->id)); | |
| 2336 ip->copy = NULL; | |
| 2337 do | |
| 2338 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... copy %p -> %p (%u bytes)\n", ip->ptr, q, (unsigned int)ip->size)); | |
| 2339 p = *q; | |
| 2340 memcpy(q, ip->ptr, ip->size); | |
| 2341 q = (void**)p; | |
| 2342 } while (q); | |
| 2343 flag = 1; | |
| 2344 } | |
| 2345 for (fp = ip->flist; fp; fp = ip->flist) | |
| 2346 { register unsigned int k = fp->level; | |
| 2347 register void *p = ip->ptr; | |
| 2348 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)); | |
| 2349 while (ip->level < k) | |
| 2350 { register void **q = (void**)soap_malloc(soap, sizeof(void*)); | |
| 2351 if (!q) | |
| 2352 return soap->error; | |
| 2353 *q = p; | |
| 2354 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level, new location=%p holds=%p...\n", q, *q)); | |
| 2355 p = (void*)q; | |
| 2356 k--; | |
| 2357 } | |
| 2358 if (fp->fcopy) | |
| 2359 fp->fcopy(soap, ip->type, fp->type, fp->ptr, fp->len, p, ip->size); | |
| 2360 else | |
| 2361 soap_fcopy(soap, ip->type, fp->type, fp->ptr, fp->len, p, ip->size); | |
| 2362 ip->flist = fp->next; | |
| 2363 SOAP_FREE(soap, fp); | |
| 2364 flag = 1; | |
| 2365 } | |
| 2366 } | |
| 2367 } | |
| 2368 } | |
| 2369 } while (flag); | |
| 2370 #ifdef SOAP_DEBUG | |
| 2371 for (i = 0; i < SOAP_IDHASH; i++) | |
| 2372 { for (ip = soap->iht[i]; ip; ip = ip->next) | |
| 2373 { if (ip->copy || ip->flist) | |
| 2374 { 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)); | |
| 2375 } | |
| 2376 } | |
| 2377 } | |
| 2378 #endif | |
| 2379 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution done\n")); | |
| 2380 return SOAP_OK; | |
| 2381 } | |
| 2382 #endif | |
| 2383 #endif | |
| 2384 | |
| 2385 /******************************************************************************/ | |
| 2386 #ifndef PALM_1 | |
| 2387 SOAP_FMAC1 | |
| 2388 size_t | |
| 2389 SOAP_FMAC2 | |
| 2390 soap_size_block(struct soap *soap, struct soap_blist *b, size_t n) | |
| 2391 { if (!b) | |
| 2392 b = soap->blist; | |
| 2393 if (b->ptr) | |
| 2394 { b->size -= *(size_t*)(b->ptr + sizeof(char*)) - n; | |
| 2395 *(size_t*)(b->ptr + sizeof(char*)) = n; | |
| 2396 } | |
| 2397 return b->size; | |
| 2398 } | |
| 2399 #endif | |
| 2400 | |
| 2401 /******************************************************************************/ | |
| 2402 #ifndef PALM_1 | |
| 2403 SOAP_FMAC1 | |
| 2404 char* | |
| 2405 SOAP_FMAC2 | |
| 2406 soap_first_block(struct soap *soap, struct soap_blist *b) | |
| 2407 { char *p, *q, *r; | |
| 2408 if (!b) | |
| 2409 b = soap->blist; | |
| 2410 p = b->ptr; | |
| 2411 if (!p) | |
| 2412 return NULL; | |
| 2413 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "First block\n")); | |
| 2414 r = NULL; | |
| 2415 do | |
| 2416 { q = *(char**)p; | |
| 2417 *(char**)p = r; | |
| 2418 r = p; | |
| 2419 p = q; | |
| 2420 } while (p); | |
| 2421 b->ptr = r; | |
| 2422 return r + sizeof(char*) + sizeof(size_t); | |
| 2423 } | |
| 2424 #endif | |
| 2425 | |
| 2426 /******************************************************************************/ | |
| 2427 #ifndef PALM_1 | |
| 2428 SOAP_FMAC1 | |
| 2429 char* | |
| 2430 SOAP_FMAC2 | |
| 2431 soap_next_block(struct soap *soap, struct soap_blist *b) | |
| 2432 { char *p; | |
| 2433 if (!b) | |
| 2434 b = soap->blist; | |
| 2435 p = b->ptr; | |
| 2436 if (p) | |
| 2437 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Next block\n")); | |
| 2438 b->ptr = *(char**)p; | |
| 2439 SOAP_FREE(soap, p); | |
| 2440 if (b->ptr) | |
| 2441 return b->ptr + sizeof(char*) + sizeof(size_t); | |
| 2442 } | |
| 2443 return NULL; | |
| 2444 } | |
| 2445 #endif | |
| 2446 | |
| 2447 /******************************************************************************/ | |
| 2448 #ifndef PALM_1 | |
| 2449 SOAP_FMAC1 | |
| 2450 size_t | |
| 2451 SOAP_FMAC2 | |
| 2452 soap_block_size(struct soap *soap, struct soap_blist *b) | |
| 2453 { if (!b) | |
| 2454 b = soap->blist; | |
| 2455 return *(size_t*)(b->ptr + sizeof(char*)); | |
| 2456 } | |
| 2457 #endif | |
| 2458 | |
| 2459 /******************************************************************************/ | |
| 2460 #ifndef PALM_1 | |
| 2461 SOAP_FMAC1 | |
| 2462 void | |
| 2463 SOAP_FMAC2 | |
| 2464 soap_end_block(struct soap *soap, struct soap_blist *b) | |
| 2465 { char *p, *q; | |
| 2466 if (!b) | |
| 2467 b = soap->blist; | |
| 2468 if (b) | |
| 2469 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of block sequence, free all remaining blocks\n")); | |
| 2470 for (p = b->ptr; p; p = q) | |
| 2471 { q = *(char**)p; | |
| 2472 SOAP_FREE(soap, p); | |
| 2473 } | |
| 2474 if (soap->blist == b) | |
| 2475 soap->blist = b->next; | |
| 2476 else | |
| 2477 { struct soap_blist *bp; | |
| 2478 for (bp = soap->blist; bp; bp = bp->next) | |
| 2479 { if (bp->next == b) | |
| 2480 { bp->next = b->next; | |
| 2481 break; | |
| 2482 } | |
| 2483 } | |
| 2484 } | |
| 2485 SOAP_FREE(soap, b); | |
| 2486 } | |
| 2487 DBGLOG(TEST, if (soap->blist) SOAP_MESSAGE(fdebug, "Restore previous block sequence\n")); | |
| 2488 } | |
| 2489 #endif | |
| 2490 | |
| 2491 /******************************************************************************/ | |
| 2492 #ifndef PALM_1 | |
| 2493 SOAP_FMAC1 | |
| 2494 char* | |
| 2495 SOAP_FMAC2 | |
| 2496 soap_save_block(struct soap *soap, struct soap_blist *b, char *p, int flag) | |
| 2497 { register size_t n; | |
| 2498 register char *q, *s; | |
| 2499 if (!b) | |
| 2500 b = soap->blist; | |
| 2501 if (b->size) | |
| 2502 { if (!p) | |
| 2503 p = (char*)soap_malloc(soap, b->size); | |
| 2504 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)); | |
| 2505 if (p) | |
| 2506 { for (s = p, q = soap_first_block(soap, b); q; q = soap_next_block(soap, b)) | |
| 2507 { n = soap_block_size(soap, b); | |
| 2508 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy %u bytes from %p to %p\n", (unsigned int)n, q, s)); | |
| 2509 #ifndef WITH_NOIDREF | |
| 2510 if (flag) | |
| 2511 soap_update_pointers(soap, q, q + n, s, q); | |
| 2512 #endif | |
| 2513 memcpy(s, q, n); | |
| 2514 s += n; | |
| 2515 } | |
| 2516 } | |
| 2517 else | |
| 2518 soap->error = SOAP_EOM; | |
| 2519 } | |
| 2520 soap_end_block(soap, b); | |
| 2521 return p; | |
| 2522 } | |
| 2523 #endif | |
| 2524 | |
| 2525 /******************************************************************************/ | |
| 2526 #ifndef PALM_2 | |
| 2527 SOAP_FMAC1 | |
| 2528 char * | |
| 2529 SOAP_FMAC2 | |
| 2530 soap_putsize(struct soap *soap, const char *type, int size) | |
| 2531 { return soap_putsizes(soap, type, &size, 1); | |
| 2532 } | |
| 2533 #endif | |
| 2534 | |
| 2535 /******************************************************************************/ | |
| 2536 #ifndef PALM_2 | |
| 2537 SOAP_FMAC1 | |
| 2538 char * | |
| 2539 SOAP_FMAC2 | |
| 2540 soap_putsizes(struct soap *soap, const char *type, const int *size, int dim) | |
| 2541 { return soap_putsizesoffsets(soap, type, size, NULL, dim); | |
| 2542 } | |
| 2543 #endif | |
| 2544 | |
| 2545 /******************************************************************************/ | |
| 2546 #ifndef PALM_2 | |
| 2547 SOAP_FMAC1 | |
| 2548 char * | |
| 2549 SOAP_FMAC2 | |
| 2550 soap_putsizesoffsets(struct soap *soap, const char *type, const int *size, const int *offset, int dim) | |
| 2551 { register int i; | |
| 2552 register size_t l; | |
| 2553 if (!type || strlen(type) + 13 > sizeof(soap->type)) /* prevent overruns */ | |
| 2554 return NULL; | |
| 2555 if (soap->version == 2) | |
| 2556 { | |
| 2557 #ifdef HAVE_SNPRINTF | |
| 2558 soap_snprintf(soap->type, sizeof(soap->type) - 1, "%s[%d", type, size[0]); | |
| 2559 #else | |
| 2560 sprintf(soap->type, "%s[%d", type, size[0]); | |
| 2561 #endif | |
| 2562 for (i = 1; i < dim; i++) | |
| 2563 { | |
| 2564 #ifdef HAVE_SNPRINTF | |
| 2565 l = strlen(soap->type); | |
| 2566 soap_snprintf(soap->type + l, sizeof(soap->type) - l - 1, " %d", size[i]); | |
| 2567 #else | |
| 2568 if ((l = strlen(soap->type)) + 13 > sizeof(soap->type)) | |
| 2569 return NULL; | |
| 2570 sprintf(soap->type + l, " %d", size[i]); | |
| 2571 #endif | |
| 2572 } | |
| 2573 } | |
| 2574 else | |
| 2575 { if (offset) | |
| 2576 { | |
| 2577 #ifdef HAVE_SNPRINTF | |
| 2578 soap_snprintf(soap->type, sizeof(soap->type) - 1, "%s[%d", type, size[0] + offset[0]); | |
| 2579 #else | |
| 2580 sprintf(soap->type, "%s[%d", type, size[0] + offset[0]); | |
| 2581 #endif | |
| 2582 for (i = 1; i < dim; i++) | |
| 2583 { | |
| 2584 #ifdef HAVE_SNPRINTF | |
| 2585 l = strlen(soap->type); | |
| 2586 soap_snprintf(soap->type + l, sizeof(soap->type) - l - 1, ",%d", size[i] + offset[i]); | |
| 2587 #else | |
| 2588 if ((l = strlen(soap->type)) + 13 > sizeof(soap->type)) | |
| 2589 return NULL; | |
| 2590 sprintf(soap->type + l, ",%d", size[i] + offset[i]); | |
| 2591 #endif | |
| 2592 } | |
| 2593 } | |
| 2594 else | |
| 2595 { | |
| 2596 #ifdef HAVE_SNPRINTF | |
| 2597 soap_snprintf(soap->type, sizeof(soap->type) - 1, "%s[%d", type, size[0]); | |
| 2598 #else | |
| 2599 sprintf(soap->type, "%s[%d", type, size[0]); | |
| 2600 #endif | |
| 2601 for (i = 1; i < dim; i++) | |
| 2602 { | |
| 2603 #ifdef HAVE_SNPRINTF | |
| 2604 l = strlen(soap->type); | |
| 2605 soap_snprintf(soap->type + l, sizeof(soap->type) - l - 1, ",%d", size[i]); | |
| 2606 #else | |
| 2607 if ((l = strlen(soap->type)) + 13 > sizeof(soap->type)) | |
| 2608 return NULL; | |
| 2609 sprintf(soap->type + l, ",%d", size[i]); | |
| 2610 #endif | |
| 2611 } | |
| 2612 } | |
| 2613 } | |
| 2614 strcat(soap->type, "]"); | |
| 2615 return soap->type; | |
| 2616 } | |
| 2617 #endif | |
| 2618 | |
| 2619 /******************************************************************************/ | |
| 2620 #ifndef PALM_2 | |
| 2621 SOAP_FMAC1 | |
| 2622 char * | |
| 2623 SOAP_FMAC2 | |
| 2624 soap_putoffset(struct soap *soap, int offset) | |
| 2625 { return soap_putoffsets(soap, &offset, 1); | |
| 2626 } | |
| 2627 #endif | |
| 2628 | |
| 2629 /******************************************************************************/ | |
| 2630 #ifndef PALM_2 | |
| 2631 SOAP_FMAC1 | |
| 2632 char * | |
| 2633 SOAP_FMAC2 | |
| 2634 soap_putoffsets(struct soap *soap, const int *offset, int dim) | |
| 2635 { register int i; | |
| 2636 register size_t l; | |
| 2637 #ifdef HAVE_SNPRINTF | |
| 2638 soap_snprintf(soap->arrayOffset, sizeof(soap->arrayOffset) - 1, "[%d", offset[0]); | |
| 2639 #else | |
| 2640 if (sizeof(soap->arrayOffset) < 13) /* prevent overruns */ | |
| 2641 return NULL; | |
| 2642 sprintf(soap->arrayOffset, "[%d", offset[0]); | |
| 2643 #endif | |
| 2644 for (i = 1; i < dim; i++) | |
| 2645 { | |
| 2646 #ifdef HAVE_SNPRINTF | |
| 2647 l = strlen(soap->arrayOffset); | |
| 2648 soap_snprintf(soap->arrayOffset + l, sizeof(soap->arrayOffset) - l - 1, ",%d", offset[i]); | |
| 2649 #else | |
| 2650 if ((l = strlen(soap->arrayOffset)) + 13 > sizeof(soap->arrayOffset)) | |
| 2651 return NULL; | |
| 2652 sprintf(soap->arrayOffset + l, ",%d", offset[i]); | |
| 2653 #endif | |
| 2654 } | |
| 2655 strcat(soap->arrayOffset, "]"); | |
| 2656 return soap->arrayOffset; | |
| 2657 } | |
| 2658 #endif | |
| 2659 | |
| 2660 /******************************************************************************/ | |
| 2661 #ifndef PALM_2 | |
| 2662 SOAP_FMAC1 | |
| 2663 int | |
| 2664 SOAP_FMAC2 | |
| 2665 soap_size(const int *size, int dim) | |
| 2666 { register int i, n = size[0]; | |
| 2667 for (i = 1; i < dim; i++) | |
| 2668 n *= size[i]; | |
| 2669 return n; | |
| 2670 } | |
| 2671 #endif | |
| 2672 | |
| 2673 /******************************************************************************/ | |
| 2674 #ifndef PALM_2 | |
| 2675 SOAP_FMAC1 | |
| 2676 int | |
| 2677 SOAP_FMAC2 | |
| 2678 soap_getoffsets(const char *attr, const int *size, int *offset, int dim) | |
| 2679 { register int i, j = 0; | |
| 2680 if (offset) | |
| 2681 for (i = 0; i < dim && attr && *attr; i++) | |
| 2682 { attr++; | |
| 2683 j *= size[i]; | |
| 2684 j += offset[i] = (int)soap_strtol(attr, NULL, 10); | |
| 2685 attr = strchr(attr, ','); | |
| 2686 } | |
| 2687 else | |
| 2688 for (i = 0; i < dim && attr && *attr; i++) | |
| 2689 { attr++; | |
| 2690 j *= size[i]; | |
| 2691 j += (int)soap_strtol(attr, NULL, 10); | |
| 2692 attr = strchr(attr, ','); | |
| 2693 } | |
| 2694 return j; | |
| 2695 } | |
| 2696 #endif | |
| 2697 | |
| 2698 /******************************************************************************/ | |
| 2699 #ifndef PALM_2 | |
| 2700 SOAP_FMAC1 | |
| 2701 int | |
| 2702 SOAP_FMAC2 | |
| 2703 soap_getsize(const char *attr1, const char *attr2, int *j) | |
| 2704 { register int n, k; | |
| 2705 char *s; | |
| 2706 *j = 0; | |
| 2707 if (!*attr1) | |
| 2708 return -1; | |
| 2709 if (*attr1 == '[') | |
| 2710 attr1++; | |
| 2711 n = 1; | |
| 2712 for (;;) | |
| 2713 { k = (int)soap_strtol(attr1, &s, 10); | |
| 2714 n *= k; | |
| 2715 if (k < 0 || n > SOAP_MAXARRAYSIZE || s == attr1) | |
| 2716 return -1; | |
| 2717 attr1 = strchr(s, ','); | |
| 2718 if (!attr1) | |
| 2719 attr1 = strchr(s, ' '); | |
| 2720 if (attr2 && *attr2) | |
| 2721 { attr2++; | |
| 2722 *j *= k; | |
| 2723 k = (int)soap_strtol(attr2, &s, 10); | |
| 2724 *j += k; | |
| 2725 if (k < 0) | |
| 2726 return -1; | |
| 2727 attr2 = s; | |
| 2728 } | |
| 2729 if (!attr1) | |
| 2730 break; | |
| 2731 attr1++; | |
| 2732 } | |
| 2733 return n - *j; | |
| 2734 } | |
| 2735 #endif | |
| 2736 | |
| 2737 /******************************************************************************/ | |
| 2738 #ifndef PALM_2 | |
| 2739 SOAP_FMAC1 | |
| 2740 int | |
| 2741 SOAP_FMAC2 | |
| 2742 soap_getsizes(const char *attr, int *size, int dim) | |
| 2743 { register int i, k, n; | |
| 2744 if (!*attr) | |
| 2745 return -1; | |
| 2746 i = (int)strlen(attr); | |
| 2747 n = 1; | |
| 2748 do | |
| 2749 { for (i = i-1; i >= 0; i--) | |
| 2750 if (attr[i] == '[' || attr[i] == ',' || attr[i] == ' ') | |
| 2751 break; | |
| 2752 k = (int)soap_strtol(attr + i + 1, NULL, 10); | |
| 2753 n *= size[--dim] = k; | |
| 2754 if (k < 0 || n > SOAP_MAXARRAYSIZE) | |
| 2755 return -1; | |
| 2756 } while (i >= 0 && attr[i] != '['); | |
| 2757 return n; | |
| 2758 } | |
| 2759 #endif | |
| 2760 | |
| 2761 /******************************************************************************/ | |
| 2762 #ifndef PALM_2 | |
| 2763 SOAP_FMAC1 | |
| 2764 int | |
| 2765 SOAP_FMAC2 | |
| 2766 soap_getposition(const char *attr, int *pos) | |
| 2767 { register int i, n; | |
| 2768 if (!*attr) | |
| 2769 return -1; | |
| 2770 n = 0; | |
| 2771 i = 1; | |
| 2772 do | |
| 2773 { pos[n++] = (int)soap_strtol(attr + i, NULL, 10); | |
| 2774 while (attr[i] && attr[i] != ',' && attr[i] != ']') | |
| 2775 i++; | |
| 2776 if (attr[i] == ',') | |
| 2777 i++; | |
| 2778 } while (n < SOAP_MAXDIMS && attr[i] && attr[i] != ']'); | |
| 2779 return n; | |
| 2780 } | |
| 2781 #endif | |
| 2782 | |
| 2783 /******************************************************************************/ | |
| 2784 #ifndef PALM_2 | |
| 2785 SOAP_FMAC1 | |
| 2786 struct soap_nlist * | |
| 2787 SOAP_FMAC2 | |
| 2788 soap_push_namespace(struct soap *soap, const char *id, const char *ns) | |
| 2789 { register struct soap_nlist *np; | |
| 2790 register struct Namespace *p; | |
| 2791 register short i = -1; | |
| 2792 register size_t n, k; | |
| 2793 n = strlen(id); | |
| 2794 k = strlen(ns) + 1; | |
| 2795 p = soap->local_namespaces; | |
| 2796 if (p) | |
| 2797 { for (i = 0; p->id; p++, i++) | |
| 2798 { if (p->ns && !strcmp(ns, p->ns)) | |
| 2799 break; | |
| 2800 if (p->out) | |
| 2801 { if (!strcmp(ns, p->out)) | |
| 2802 break; | |
| 2803 } | |
| 2804 else if (p->in) | |
| 2805 { if (!soap_tag_cmp(ns, p->in)) | |
| 2806 { if ((p->out = (char*)SOAP_MALLOC(soap, k))) | |
| 2807 strcpy(p->out, ns); | |
| 2808 break; | |
| 2809 } | |
| 2810 } | |
| 2811 } | |
| 2812 if (!p || !p->id) | |
| 2813 i = -1; | |
| 2814 } | |
| 2815 if (i >= 0) | |
| 2816 k = 0; | |
| 2817 np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k); | |
| 2818 if (!np) | |
| 2819 { soap->error = SOAP_EOM; | |
| 2820 return NULL; | |
| 2821 } | |
| 2822 np->next = soap->nlist; | |
| 2823 soap->nlist = np; | |
| 2824 np->level = soap->level; | |
| 2825 np->index = i; | |
| 2826 strcpy((char*)np->id, id); | |
| 2827 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push namespace binding (level=%u) '%s' '%s'\n", soap->level, id, ns)); | |
| 2828 if (i < 0) | |
| 2829 { np->ns = strcpy((char*)np->id + n + 1, ns); | |
| 2830 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push NOT OK: no match found for '%s' in namespace mapping table (added to stack anyway)\n", ns)); | |
| 2831 } | |
| 2832 else | |
| 2833 { np->ns = NULL; | |
| 2834 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push OK ('%s' matches '%s' in namespace table)\n", id, p->id)); | |
| 2835 } | |
| 2836 return np; | |
| 2837 } | |
| 2838 #endif | |
| 2839 | |
| 2840 /******************************************************************************/ | |
| 2841 #ifndef PALM_2 | |
| 2842 SOAP_FMAC1 | |
| 2843 void | |
| 2844 SOAP_FMAC2 | |
| 2845 soap_pop_namespace(struct soap *soap) | |
| 2846 { register struct soap_nlist *np, *nq; | |
| 2847 for (np = soap->nlist; np && np->level >= soap->level; np = nq) | |
| 2848 { nq = np->next; | |
| 2849 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop namespace binding (level=%u) '%s'\n", soap->level, np->id)); | |
| 2850 SOAP_FREE(soap, np); | |
| 2851 } | |
| 2852 soap->nlist = np; | |
| 2853 } | |
| 2854 #endif | |
| 2855 | |
| 2856 /******************************************************************************/ | |
| 2857 #ifndef PALM_2 | |
| 2858 SOAP_FMAC1 | |
| 2859 int | |
| 2860 SOAP_FMAC2 | |
| 2861 soap_match_namespace(struct soap *soap, const char *id1, const char *id2, size_t n1, size_t n2) | |
| 2862 { register struct soap_nlist *np = soap->nlist; | |
| 2863 const char *s; | |
| 2864 while (np && (strncmp(np->id, id1, n1) || np->id[n1])) | |
| 2865 np = np->next; | |
| 2866 if (np) | |
| 2867 { if (!(soap->mode & SOAP_XML_IGNORENS)) | |
| 2868 if (np->index < 0 | |
| 2869 || ((s = soap->local_namespaces[np->index].id) && (strncmp(s, id2, n2) || (s[n2] && s[n2] != '_')))) | |
| 2870 return SOAP_NAMESPACE; | |
| 2871 return SOAP_OK; | |
| 2872 } | |
| 2873 if (n1 == 0) | |
| 2874 return (soap->mode & SOAP_XML_IGNORENS) ? SOAP_OK : SOAP_NAMESPACE; | |
| 2875 if ((n1 == 3 && n1 == n2 && !strncmp(id1, "xml", 3) && !strncmp(id1, id2, 3)) | |
| 2876 || (soap->mode & SOAP_XML_IGNORENS)) | |
| 2877 return SOAP_OK; | |
| 2878 return soap->error = SOAP_SYNTAX_ERROR; | |
| 2879 } | |
| 2880 #endif | |
| 2881 | |
| 2882 /******************************************************************************/ | |
| 2883 #ifndef PALM_2 | |
| 2884 SOAP_FMAC1 | |
| 2885 const char* | |
| 2886 SOAP_FMAC2 | |
| 2887 soap_current_namespace(struct soap *soap, const char *tag) | |
| 2888 { register struct soap_nlist *np; | |
| 2889 register const char *s; | |
| 2890 if (!tag || !strncmp(tag, "xml", 3)) | |
| 2891 return NULL; | |
| 2892 np = soap->nlist; | |
| 2893 if (!(s = strchr(tag, ':'))) | |
| 2894 { while (np && *np->id) /* find default namespace, if present */ | |
| 2895 np = np->next; | |
| 2896 } | |
| 2897 else | |
| 2898 { while (np && (strncmp(np->id, tag, s - tag) || np->id[s - tag])) | |
| 2899 np = np->next; | |
| 2900 if (!np) | |
| 2901 soap->error = SOAP_NAMESPACE; | |
| 2902 } | |
| 2903 if (np) | |
| 2904 { if (np->index >= 0) | |
| 2905 return soap->namespaces[np->index].ns; | |
| 2906 if (np->ns) | |
| 2907 return soap_strdup(soap, np->ns); | |
| 2908 } | |
| 2909 return NULL; | |
| 2910 } | |
| 2911 #endif | |
| 2912 | |
| 2913 /******************************************************************************/ | |
| 2914 #ifndef PALM_2 | |
| 2915 SOAP_FMAC1 | |
| 2916 int | |
| 2917 SOAP_FMAC2 | |
| 2918 soap_tag_cmp(const char *s, const char *t) | |
| 2919 { for (;;) | |
| 2920 { register int c1 = *s; | |
| 2921 register int c2 = *t; | |
| 2922 if (!c1 || c1 == '"') | |
| 2923 break; | |
| 2924 if (c2 != '-') | |
| 2925 { if (c1 != c2) | |
| 2926 { if (c1 >= 'A' && c1 <= 'Z') | |
| 2927 c1 += 'a' - 'A'; | |
| 2928 if (c2 >= 'A' && c2 <= 'Z') | |
| 2929 c2 += 'a' - 'A'; | |
| 2930 } | |
| 2931 if (c1 != c2) | |
| 2932 { if (c2 != '*') | |
| 2933 return 1; | |
| 2934 c2 = *++t; | |
| 2935 if (!c2) | |
| 2936 return 0; | |
| 2937 if (c2 >= 'A' && c2 <= 'Z') | |
| 2938 c2 += 'a' - 'A'; | |
| 2939 for (;;) | |
| 2940 { c1 = *s; | |
| 2941 if (!c1 || c1 == '"') | |
| 2942 break; | |
| 2943 if (c1 >= 'A' && c1 <= 'Z') | |
| 2944 c1 += 'a' - 'A'; | |
| 2945 if (c1 == c2 && !soap_tag_cmp(s + 1, t + 1)) | |
| 2946 return 0; | |
| 2947 s++; | |
| 2948 } | |
| 2949 break; | |
| 2950 } | |
| 2951 } | |
| 2952 s++; | |
| 2953 t++; | |
| 2954 } | |
| 2955 if (*t == '*' && !t[1]) | |
| 2956 return 0; | |
| 2957 return *t; | |
| 2958 } | |
| 2959 #endif | |
| 2960 | |
| 2961 /******************************************************************************/ | |
| 2962 #ifndef PALM_2 | |
| 2963 SOAP_FMAC1 | |
| 2964 int | |
| 2965 SOAP_FMAC2 | |
| 2966 soap_match_tag(struct soap *soap, const char *tag1, const char *tag2) | |
| 2967 { register const char *s, *t; | |
| 2968 register int err; | |
| 2969 if (!tag1 || !tag2 || !*tag2) | |
| 2970 return SOAP_OK; | |
| 2971 s = strchr(tag1, ':'); | |
| 2972 t = strchr(tag2, ':'); | |
| 2973 if (t) | |
| 2974 { if (s) | |
| 2975 { if (t[1] && SOAP_STRCMP(s + 1, t + 1)) | |
| 2976 return SOAP_TAG_MISMATCH; | |
| 2977 if (t != tag2 && (err = soap_match_namespace(soap, tag1, tag2, s - tag1, t - tag2))) | |
| 2978 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2)); | |
| 2979 if (err == SOAP_NAMESPACE) | |
| 2980 return SOAP_TAG_MISMATCH; | |
| 2981 return err; | |
| 2982 } | |
| 2983 } | |
| 2984 else if (!t[1]) | |
| 2985 { err = soap_match_namespace(soap, tag1, tag2, 0, t - tag2); | |
| 2986 if (err == SOAP_NAMESPACE) | |
| 2987 return SOAP_TAG_MISMATCH; | |
| 2988 } | |
| 2989 else if (SOAP_STRCMP(tag1, t + 1)) | |
| 2990 { return SOAP_TAG_MISMATCH; | |
| 2991 } | |
| 2992 else if (t != tag2 && (err = soap_match_namespace(soap, tag1, tag2, 0, t - tag2))) | |
| 2993 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2)); | |
| 2994 if (err == SOAP_NAMESPACE) | |
| 2995 return SOAP_TAG_MISMATCH; | |
| 2996 return err; | |
| 2997 } | |
| 2998 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags and (default) namespaces match: '%s' '%s'\n", tag1, tag2)); | |
| 2999 return SOAP_OK; | |
| 3000 } | |
| 3001 if (s) | |
| 3002 { if (SOAP_STRCMP(s + 1, tag2)) | |
| 3003 return SOAP_TAG_MISMATCH; | |
| 3004 } | |
| 3005 else if (SOAP_STRCMP(tag1, tag2)) | |
| 3006 return SOAP_TAG_MISMATCH; | |
| 3007 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags match: '%s' '%s'\n", tag1, tag2)); | |
| 3008 return SOAP_OK; | |
| 3009 } | |
| 3010 #endif | |
| 3011 | |
| 3012 /******************************************************************************/ | |
| 3013 #ifndef PALM_2 | |
| 3014 SOAP_FMAC1 | |
| 3015 int | |
| 3016 SOAP_FMAC2 | |
| 3017 soap_match_array(struct soap *soap, const char *type) | |
| 3018 { if (*soap->arrayType) | |
| 3019 if (soap_match_tag(soap, soap->arrayType, type) | |
| 3020 && soap_match_tag(soap, soap->arrayType, "xsd:anyType") | |
| 3021 && soap_match_tag(soap, soap->arrayType, "xsd:ur-type") | |
| 3022 ) | |
| 3023 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array type mismatch: '%s' '%s'\n", soap->arrayType, type)); | |
| 3024 return SOAP_TAG_MISMATCH; | |
| 3025 } | |
| 3026 return SOAP_OK; | |
| 3027 } | |
| 3028 #endif | |
| 3029 | |
| 3030 /******************************************************************************\ | |
| 3031 * | |
| 3032 * SSL/TLS | |
| 3033 * | |
| 3034 \******************************************************************************/ | |
| 3035 | |
| 3036 /******************************************************************************/ | |
| 3037 #ifdef WITH_OPENSSL | |
| 3038 #ifndef PALM_2 | |
| 3039 SOAP_FMAC1 | |
| 3040 int | |
| 3041 SOAP_FMAC2 | |
| 3042 soap_rand() | |
| 3043 { unsigned char buf[4]; | |
| 3044 if (!soap_ssl_init_done) | |
| 3045 soap_ssl_init(); | |
| 3046 RAND_pseudo_bytes(buf, 4); | |
| 3047 return *(int*)buf; | |
| 3048 } | |
| 3049 #endif | |
| 3050 #endif | |
| 3051 | |
| 3052 /******************************************************************************/ | |
| 3053 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) | |
| 3054 #ifndef PALM_2 | |
| 3055 SOAP_FMAC1 | |
| 3056 int | |
| 3057 SOAP_FMAC2 | |
| 3058 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE) | |
| 3059 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) | |
| 3060 #else | |
| 3061 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) | |
| 3062 #endif | |
| 3063 { int err; | |
| 3064 soap->keyfile = keyfile; | |
| 3065 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE) | |
| 3066 soap->keyid = keyid; | |
| 3067 #endif | |
| 3068 soap->password = password; | |
| 3069 soap->cafile = cafile; | |
| 3070 soap->capath = capath; | |
| 3071 soap->crlfile = NULL; | |
| 3072 #ifdef WITH_OPENSSL | |
| 3073 soap->dhfile = dhfile; | |
| 3074 soap->randfile = randfile; | |
| 3075 #endif | |
| 3076 soap->ssl_flags = flags | (dhfile == NULL ? SOAP_SSL_RSA : 0); | |
| 3077 #ifdef WITH_GNUTLS | |
| 3078 if (dhfile) | |
| 3079 { char *s; | |
| 3080 int n = (int)soap_strtoul(dhfile, &s, 10); | |
| 3081 if (!soap->dh_params) | |
| 3082 gnutls_dh_params_init(&soap->dh_params); | |
| 3083 /* if dhfile is numeric, treat it as a key length to generate DH params which can take a while */ | |
| 3084 if (n >= 512 && s && *s == '\0') | |
| 3085 gnutls_dh_params_generate2(soap->dh_params, (unsigned int)n); | |
| 3086 else | |
| 3087 { unsigned int dparams_len; | |
| 3088 unsigned char dparams_buf[1024]; | |
| 3089 FILE *fd = fopen(dhfile, "r"); | |
| 3090 if (!fd) | |
| 3091 return soap_set_receiver_error(soap, "SSL/TLS error", "Invalid DH file", SOAP_SSL_ERROR); | |
| 3092 dparams_len = (unsigned int)fread(dparams_buf, 1, sizeof(dparams_buf), fd); | |
| 3093 fclose(fd); | |
| 3094 gnutls_datum_t dparams = { dparams_buf, dparams_len }; | |
| 3095 if (gnutls_dh_params_import_pkcs3(soap->dh_params, &dparams, GNUTLS_X509_FMT_PEM)) | |
| 3096 return soap_set_receiver_error(soap, "SSL/TLS error", "Invalid DH file", SOAP_SSL_ERROR); | |
| 3097 } | |
| 3098 } | |
| 3099 else | |
| 3100 { if (!soap->rsa_params) | |
| 3101 gnutls_rsa_params_init(&soap->rsa_params); | |
| 3102 gnutls_rsa_params_generate2(soap->rsa_params, SOAP_SSL_RSA_BITS); | |
| 3103 } | |
| 3104 if (soap->session) | |
| 3105 { gnutls_deinit(soap->session); | |
| 3106 soap->session = NULL; | |
| 3107 } | |
| 3108 if (soap->xcred) | |
| 3109 { gnutls_certificate_free_credentials(soap->xcred); | |
| 3110 soap->xcred = NULL; | |
| 3111 } | |
| 3112 #endif | |
| 3113 err = soap->fsslauth(soap); | |
| 3114 #ifdef WITH_OPENSSL | |
| 3115 if (!err) | |
| 3116 { if (sid) | |
| 3117 SSL_CTX_set_session_id_context(soap->ctx, (unsigned char*)sid, (unsigned int)strlen(sid)); | |
| 3118 else | |
| 3119 SSL_CTX_set_session_cache_mode(soap->ctx, SSL_SESS_CACHE_OFF); | |
| 3120 } | |
| 3121 #endif | |
| 3122 return err; | |
| 3123 } | |
| 3124 #endif | |
| 3125 #endif | |
| 3126 | |
| 3127 /******************************************************************************/ | |
| 3128 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) | |
| 3129 #ifndef PALM_2 | |
| 3130 SOAP_FMAC1 | |
| 3131 int | |
| 3132 SOAP_FMAC2 | |
| 3133 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE) | |
| 3134 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) | |
| 3135 #else | |
| 3136 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) | |
| 3137 #endif | |
| 3138 { soap->keyfile = keyfile; | |
| 3139 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE) | |
| 3140 soap->keyid = keyid; | |
| 3141 #endif | |
| 3142 soap->password = password; | |
| 3143 soap->cafile = cafile; | |
| 3144 soap->capath = capath; | |
| 3145 soap->ssl_flags = SOAP_SSL_CLIENT | flags; | |
| 3146 #ifdef WITH_OPENSSL | |
| 3147 soap->dhfile = NULL; | |
| 3148 soap->randfile = randfile; | |
| 3149 soap->fsslverify = (flags & SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE) == 0 ? ssl_verify_callback : ssl_verify_callback_allow_expired_certificate; | |
| 3150 #endif | |
| 3151 #ifdef WITH_GNUTLS | |
| 3152 if (soap->session) | |
| 3153 { gnutls_deinit(soap->session); | |
| 3154 soap->session = NULL; | |
| 3155 } | |
| 3156 if (soap->xcred) | |
| 3157 { gnutls_certificate_free_credentials(soap->xcred); | |
| 3158 soap->xcred = NULL; | |
| 3159 } | |
| 3160 #endif | |
| 3161 return soap->fsslauth(soap); | |
| 3162 } | |
| 3163 #endif | |
| 3164 #endif | |
| 3165 | |
| 3166 /******************************************************************************/ | |
| 3167 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) | |
| 3168 #ifndef PALM_2 | |
| 3169 SOAP_FMAC1 | |
| 3170 void | |
| 3171 SOAP_FMAC2 | |
| 3172 soap_ssl_init() | |
| 3173 { /* Note: for MT systems, the main program MUST call soap_ssl_init() before any threads are started */ | |
| 3174 if (!soap_ssl_init_done) | |
| 3175 { soap_ssl_init_done = 1; | |
| 3176 #ifdef WITH_OPENSSL | |
| 3177 SSL_library_init(); | |
| 3178 OpenSSL_add_all_algorithms(); /* 2.8.1 change (wsseapi.c) */ | |
| 3179 OpenSSL_add_all_digests(); | |
| 3180 #ifndef WITH_LEAN | |
| 3181 SSL_load_error_strings(); | |
| 3182 #endif | |
| 3183 if (!RAND_load_file("/dev/urandom", 1024)) | |
| 3184 { char buf[1024]; | |
| 3185 RAND_seed(buf, sizeof(buf)); | |
| 3186 while (!RAND_status()) | |
| 3187 { int r = rand(); | |
| 3188 RAND_seed(&r, sizeof(int)); | |
| 3189 } | |
| 3190 } | |
| 3191 #endif | |
| 3192 #ifdef WITH_GNUTLS | |
| 3193 # if defined(HAVE_PTHREAD_H) | |
| 3194 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); | |
| 3195 # elif defined(HAVE_PTH_H) | |
| 3196 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth); | |
| 3197 # endif | |
| 3198 gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM, 0); | |
| 3199 gcry_control(GCRYCTL_DISABLE_SECMEM, 0); | |
| 3200 gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); /* libgcrypt init done */ | |
| 3201 gnutls_global_init(); | |
| 3202 #endif | |
| 3203 } | |
| 3204 } | |
| 3205 #endif | |
| 3206 #endif | |
| 3207 | |
| 3208 /******************************************************************************/ | |
| 3209 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) | |
| 3210 #ifndef PALM_1 | |
| 3211 SOAP_FMAC1 | |
| 3212 const char * | |
| 3213 SOAP_FMAC2 | |
| 3214 soap_ssl_error(struct soap *soap, int ret) | |
| 3215 { | |
| 3216 #ifdef WITH_OPENSSL | |
| 3217 int err = SSL_get_error(soap->ssl, ret); | |
| 3218 const char *msg = soap_code_str(h_ssl_error_codes, err); | |
| 3219 if (msg) | |
| 3220 strcpy(soap->msgbuf, msg); | |
| 3221 else | |
| 3222 return ERR_error_string(err, soap->msgbuf); | |
| 3223 if (ERR_peek_error()) | |
| 3224 { unsigned long r; | |
| 3225 strcat(soap->msgbuf, "\n"); | |
| 3226 while ((r = ERR_get_error())) | |
| 3227 ERR_error_string_n(r, soap->msgbuf + strlen(soap->msgbuf), sizeof(soap->msgbuf) - strlen(soap->msgbuf)); | |
| 3228 } | |
| 3229 else | |
| 3230 { switch (ret) | |
| 3231 { case 0: | |
| 3232 strcpy(soap->msgbuf, "EOF was observed that violates the SSL/TLS protocol. The client probably provided invalid authentication information."); | |
| 3233 break; | |
| 3234 case -1: | |
| 3235 #ifdef HAVE_SNPRINTF | |
| 3236 soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "Error observed by underlying SSL/TLS BIO: %s", strerror(errno)); | |
| 3237 #else | |
| 3238 { const char *s = strerror(errno); | |
| 3239 size_t l = strlen(s); | |
| 3240 sprintf(soap->msgbuf, "Error observed by underlying SSL/TLS BIO: %s", l + 44 < sizeof(soap->msgbuf) ? s : SOAP_STR_EOS); | |
| 3241 } | |
| 3242 #endif | |
| 3243 break; | |
| 3244 } | |
| 3245 } | |
| 3246 return soap->msgbuf; | |
| 3247 #endif | |
| 3248 #ifdef WITH_GNUTLS | |
| 3249 return gnutls_strerror(ret); | |
| 3250 #endif | |
| 3251 } | |
| 3252 #endif | |
| 3253 #endif | |
| 3254 | |
| 3255 /******************************************************************************/ | |
| 3256 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) | |
| 3257 #ifndef PALM_1 | |
| 3258 static int | |
| 3259 ssl_auth_init(struct soap *soap) | |
| 3260 { | |
| 3261 #ifdef WITH_OPENSSL | |
| 3262 long flags; | |
| 3263 int mode; | |
| 3264 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE) | |
| 3265 EVP_PKEY* pkey; | |
| 3266 #endif | |
| 3267 if (!soap_ssl_init_done) | |
| 3268 soap_ssl_init(); | |
| 3269 ERR_clear_error(); | |
| 3270 if (!soap->ctx) | |
| 3271 { if (!(soap->ctx = SSL_CTX_new(SSLv23_method()))) | |
| 3272 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't setup context", SOAP_SSL_ERROR); | |
| 3273 /* The following alters the behavior of SSL read/write: */ | |
| 3274 #if 0 | |
| 3275 SSL_CTX_set_mode(soap->ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY); | |
| 3276 #endif | |
| 3277 } | |
| 3278 if (soap->randfile) | |
| 3279 { if (!RAND_load_file(soap->randfile, -1)) | |
| 3280 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't load randomness", SOAP_SSL_ERROR); | |
| 3281 } | |
| 3282 if (soap->cafile || soap->capath) | |
| 3283 { if (!SSL_CTX_load_verify_locations(soap->ctx, soap->cafile, soap->capath)) | |
| 3284 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CA file", SOAP_SSL_ERROR); | |
| 3285 if (soap->cafile && (soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION)) | |
| 3286 SSL_CTX_set_client_CA_list(soap->ctx, SSL_load_client_CA_file(soap->cafile)); | |
| 3287 } | |
| 3288 if (!(soap->ssl_flags & SOAP_SSL_NO_DEFAULT_CA_PATH)) | |
| 3289 { if (!SSL_CTX_set_default_verify_paths(soap->ctx)) | |
| 3290 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read default CA file and/or directory", SOAP_SSL_ERROR); | |
| 3291 } | |
| 3292 /* This code assumes a typical scenario, see alternative code below */ | |
| 3293 if (soap->keyfile) | |
| 3294 { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile)) | |
| 3295 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read certificate key file", SOAP_SSL_ERROR); | |
| 3296 if (soap->password) | |
| 3297 { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password); | |
| 3298 SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password); | |
| 3299 } | |
| 3300 if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM)) | |
| 3301 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read key file", SOAP_SSL_ERROR); | |
| 3302 #ifndef WM_SECURE_KEY_STORAGE | |
| 3303 if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM)) | |
| 3304 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read key file", SOAP_SSL_ERROR); | |
| 3305 #endif | |
| 3306 } | |
| 3307 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE) | |
| 3308 if (NULL == (pkey = ipcom_key_db_pkey_get(soap->keyid))) | |
| 3309 return soap_set_receiver_error(soap, "SSL error", "Can't find key", SOAP_SSL_ERROR); | |
| 3310 if (0 == SSL_CTX_use_PrivateKey(soap->ctx, pkey)) | |
| 3311 return soap_set_receiver_error(soap, "SSL error", "Can't read key", SOAP_SSL_ERROR); | |
| 3312 #endif | |
| 3313 /* Suggested alternative approach to check the key file for certs (cafile=NULL):*/ | |
| 3314 #if 0 | |
| 3315 if (soap->password) | |
| 3316 { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password); | |
| 3317 SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password); | |
| 3318 } | |
| 3319 if (!soap->cafile || !SSL_CTX_use_certificate_chain_file(soap->ctx, soap->cafile)) | |
| 3320 { if (soap->keyfile) | |
| 3321 { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile)) | |
| 3322 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read certificate or key file", SOAP_SSL_ERROR); | |
| 3323 if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM)) | |
| 3324 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read key file", SOAP_SSL_ERROR); | |
| 3325 } | |
| 3326 } | |
| 3327 #endif | |
| 3328 if ((soap->ssl_flags & SOAP_SSL_RSA)) | |
| 3329 { RSA *rsa = RSA_generate_key(SOAP_SSL_RSA_BITS, RSA_F4, NULL, NULL); | |
| 3330 if (!SSL_CTX_set_tmp_rsa(soap->ctx, rsa)) | |
| 3331 { if (rsa) | |
| 3332 RSA_free(rsa); | |
| 3333 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't set RSA key", SOAP_SSL_ERROR); | |
| 3334 } | |
| 3335 RSA_free(rsa); | |
| 3336 } | |
| 3337 else if (soap->dhfile) | |
| 3338 { DH *dh = 0; | |
| 3339 char *s; | |
| 3340 int n = (int)soap_strtoul(soap->dhfile, &s, 10); | |
| 3341 /* if dhfile is numeric, treat it as a key length to generate DH params which can take a while */ | |
| 3342 if (n >= 512 && s && *s == '\0') | |
| 3343 #if defined(VXWORKS) | |
| 3344 DH_generate_parameters_ex(dh, n, 2/*or 5*/, NULL); | |
| 3345 #else | |
| 3346 dh = DH_generate_parameters(n, 2/*or 5*/, NULL, NULL); | |
| 3347 #endif | |
| 3348 else | |
| 3349 { BIO *bio; | |
| 3350 bio = BIO_new_file(soap->dhfile, "r"); | |
| 3351 if (!bio) | |
| 3352 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read DH file", SOAP_SSL_ERROR); | |
| 3353 dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); | |
| 3354 BIO_free(bio); | |
| 3355 } | |
| 3356 if (!dh || DH_check(dh, &n) != 1 || SSL_CTX_set_tmp_dh(soap->ctx, dh) < 0) | |
| 3357 { if (dh) | |
| 3358 DH_free(dh); | |
| 3359 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't set DH parameters", SOAP_SSL_ERROR); | |
| 3360 } | |
| 3361 DH_free(dh); | |
| 3362 } | |
| 3363 flags = (SSL_OP_ALL | SSL_OP_NO_SSLv2); /* disable SSL v2 */ | |
| 3364 if ((soap->ssl_flags & SOAP_SSLv3)) | |
| 3365 flags |= SSL_OP_NO_TLSv1; | |
| 3366 if ((soap->ssl_flags & SOAP_TLSv1)) | |
| 3367 flags |= SSL_OP_NO_SSLv3; | |
| 3368 #ifdef SSL_OP_NO_TICKET | |
| 3369 /* TLS extension is enabled by default in OPENSSL v0.9.8k | |
| 3370 Disable it by adding SSL_OP_NO_TICKET */ | |
| 3371 flags |= SSL_OP_NO_TICKET; | |
| 3372 #endif | |
| 3373 SSL_CTX_set_options(soap->ctx, flags); | |
| 3374 if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION)) | |
| 3375 mode = (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT); | |
| 3376 else if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION)) | |
| 3377 mode = SSL_VERIFY_PEER; | |
| 3378 else | |
| 3379 mode = SSL_VERIFY_NONE; | |
| 3380 SSL_CTX_set_verify(soap->ctx, mode, soap->fsslverify); | |
| 3381 #if (OPENSSL_VERSION_NUMBER < 0x00905100L) | |
| 3382 SSL_CTX_set_verify_depth(soap->ctx, 1); | |
| 3383 #else | |
| 3384 SSL_CTX_set_verify_depth(soap->ctx, 9); | |
| 3385 #endif | |
| 3386 #endif | |
| 3387 #ifdef WITH_GNUTLS | |
| 3388 int ret; | |
| 3389 if (!soap_ssl_init_done) | |
| 3390 soap_ssl_init(); | |
| 3391 if (!soap->xcred) | |
| 3392 { gnutls_certificate_allocate_credentials(&soap->xcred); | |
| 3393 if (soap->cafile) | |
| 3394 { if (gnutls_certificate_set_x509_trust_file(soap->xcred, soap->cafile, GNUTLS_X509_FMT_PEM) < 0) | |
| 3395 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CA file", SOAP_SSL_ERROR); | |
| 3396 } | |
| 3397 if (soap->crlfile) | |
| 3398 { if (gnutls_certificate_set_x509_crl_file(soap->xcred, soap->crlfile, GNUTLS_X509_FMT_PEM) < 0) | |
| 3399 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CRL file", SOAP_SSL_ERROR); | |
| 3400 } | |
| 3401 if (soap->keyfile) | |
| 3402 { if (gnutls_certificate_set_x509_key_file(soap->xcred, soap->keyfile, soap->keyfile, GNUTLS_X509_FMT_PEM) < 0) /* TODO: GNUTLS need to concat cert and key in single key file */ | |
| 3403 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read key file", SOAP_SSL_ERROR); | |
| 3404 } | |
| 3405 } | |
| 3406 if ((soap->ssl_flags & SOAP_SSL_CLIENT)) | |
| 3407 { gnutls_init(&soap->session, GNUTLS_CLIENT); | |
| 3408 if (soap->cafile || soap->crlfile || soap->keyfile) | |
| 3409 { ret = gnutls_priority_set_direct(soap->session, "PERFORMANCE", NULL); | |
| 3410 if (ret < 0) | |
| 3411 return soap_set_receiver_error(soap, soap_ssl_error(soap, ret), "SSL/TLS set priority error", SOAP_SSL_ERROR); | |
| 3412 gnutls_credentials_set(soap->session, GNUTLS_CRD_CERTIFICATE, soap->xcred); | |
| 3413 } | |
| 3414 else | |
| 3415 { if (!soap->acred) | |
| 3416 gnutls_anon_allocate_client_credentials(&soap->acred); | |
| 3417 gnutls_init(&soap->session, GNUTLS_CLIENT); | |
| 3418 gnutls_priority_set_direct(soap->session, "PERFORMANCE:+ANON-DH:!ARCFOUR-128", NULL); | |
| 3419 gnutls_credentials_set(soap->session, GNUTLS_CRD_ANON, soap->acred); | |
| 3420 } | |
| 3421 } | |
| 3422 else | |
| 3423 { if (!soap->keyfile) | |
| 3424 return soap_set_receiver_error(soap, "SSL/TLS error", "No key file: anonymous server authentication not supported in this release", SOAP_SSL_ERROR); | |
| 3425 if ((soap->ssl_flags & SOAP_SSL_RSA) && soap->rsa_params) | |
| 3426 gnutls_certificate_set_rsa_export_params(soap->xcred, soap->rsa_params); | |
| 3427 else if (soap->dh_params) | |
| 3428 gnutls_certificate_set_dh_params(soap->xcred, soap->dh_params); | |
| 3429 if (!soap->cache) | |
| 3430 gnutls_priority_init(&soap->cache, "NORMAL", NULL); | |
| 3431 gnutls_init(&soap->session, GNUTLS_SERVER); | |
| 3432 gnutls_priority_set(soap->session, soap->cache); | |
| 3433 gnutls_credentials_set(soap->session, GNUTLS_CRD_CERTIFICATE, soap->xcred); | |
| 3434 if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION)) | |
| 3435 gnutls_certificate_server_set_request(soap->session, GNUTLS_CERT_REQUEST); | |
| 3436 gnutls_session_enable_compatibility_mode(soap->session); | |
| 3437 if ((soap->ssl_flags & SOAP_TLSv1)) | |
| 3438 { int protocol_priority[] = { GNUTLS_TLS1_0, 0 }; | |
| 3439 if (gnutls_protocol_set_priority(soap->session, protocol_priority) != GNUTLS_E_SUCCESS) | |
| 3440 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't set TLS v1.0 protocol", SOAP_SSL_ERROR); | |
| 3441 } | |
| 3442 } | |
| 3443 #endif | |
| 3444 return SOAP_OK; | |
| 3445 } | |
| 3446 #endif | |
| 3447 #endif | |
| 3448 | |
| 3449 /******************************************************************************/ | |
| 3450 #ifdef WITH_OPENSSL | |
| 3451 #ifndef PALM_1 | |
| 3452 static int | |
| 3453 ssl_password(char *buf, int num, int rwflag, void *userdata) | |
| 3454 { if (num < (int)strlen((char*)userdata) + 1) | |
| 3455 return 0; | |
| 3456 return (int)strlen(strcpy(buf, (char*)userdata)); | |
| 3457 } | |
| 3458 #endif | |
| 3459 #endif | |
| 3460 | |
| 3461 /******************************************************************************/ | |
| 3462 #ifdef WITH_OPENSSL | |
| 3463 #ifndef PALM_1 | |
| 3464 static int | |
| 3465 ssl_verify_callback(int ok, X509_STORE_CTX *store) | |
| 3466 { | |
| 3467 #ifdef SOAP_DEBUG | |
| 3468 if (!ok) | |
| 3469 { char buf[1024]; | |
| 3470 int err = X509_STORE_CTX_get_error(store); | |
| 3471 X509 *cert = X509_STORE_CTX_get_current_cert(store); | |
| 3472 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(err)); | |
| 3473 X509_NAME_oneline(X509_get_issuer_name(cert), buf, sizeof(buf)); | |
| 3474 fprintf(stderr, "certificate issuer %s\n", buf); | |
| 3475 X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); | |
| 3476 fprintf(stderr, "certificate subject %s\n", buf); | |
| 3477 /* accept self signed certificates and certificates out of date */ | |
| 3478 switch (err) | |
| 3479 { case X509_V_ERR_CERT_NOT_YET_VALID: | |
| 3480 case X509_V_ERR_CERT_HAS_EXPIRED: | |
| 3481 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: | |
| 3482 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: | |
| 3483 X509_STORE_CTX_set_error(store, X509_V_OK); | |
| 3484 ok = 1; | |
| 3485 } | |
| 3486 } | |
| 3487 #endif | |
| 3488 /* Note: return 1 to continue, but unsafe progress will be terminated by OpenSSL */ | |
| 3489 return ok; | |
| 3490 } | |
| 3491 #endif | |
| 3492 #endif | |
| 3493 | |
| 3494 /******************************************************************************/ | |
| 3495 #ifdef WITH_OPENSSL | |
| 3496 #ifndef PALM_1 | |
| 3497 static int | |
| 3498 ssl_verify_callback_allow_expired_certificate(int ok, X509_STORE_CTX *store) | |
| 3499 { ok = ssl_verify_callback(ok, store); | |
| 3500 if (!ok) | |
| 3501 { /* accept self signed certificates and certificates out of date */ | |
| 3502 switch (X509_STORE_CTX_get_error(store)) | |
| 3503 { case X509_V_ERR_CERT_NOT_YET_VALID: | |
| 3504 case X509_V_ERR_CERT_HAS_EXPIRED: | |
| 3505 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: | |
| 3506 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: | |
| 3507 X509_STORE_CTX_set_error(store, X509_V_OK); | |
| 3508 ok = 1; | |
| 3509 } | |
| 3510 } | |
| 3511 /* Note: return 1 to continue, but unsafe progress will be terminated by SSL */ | |
| 3512 return ok; | |
| 3513 } | |
| 3514 #endif | |
| 3515 #endif | |
| 3516 | |
| 3517 /******************************************************************************/ | |
| 3518 #ifdef WITH_GNUTLS | |
| 3519 static const char * | |
| 3520 ssl_verify(struct soap *soap, const char *host) | |
| 3521 { unsigned int status; | |
| 3522 const char *err = NULL; | |
| 3523 int r = gnutls_certificate_verify_peers2(soap->session, &status); | |
| 3524 if (r < 0) | |
| 3525 err = "Certificate verify error"; | |
| 3526 else if ((status & GNUTLS_CERT_INVALID)) | |
| 3527 err = "The certificate is not trusted"; | |
| 3528 else if ((status & GNUTLS_CERT_SIGNER_NOT_FOUND)) | |
| 3529 err = "The certificate hasn't got a known issuer"; | |
| 3530 else if ((status & GNUTLS_CERT_REVOKED)) | |
| 3531 err = "The certificate has been revoked"; | |
| 3532 else if (gnutls_certificate_type_get(soap->session) == GNUTLS_CRT_X509) | |
| 3533 { gnutls_x509_crt_t cert; | |
| 3534 const gnutls_datum_t *cert_list; | |
| 3535 unsigned int cert_list_size; | |
| 3536 if (gnutls_x509_crt_init(&cert) < 0) | |
| 3537 err = "Could not get X509 certificates"; | |
| 3538 else if ((cert_list = gnutls_certificate_get_peers(soap->session, &cert_list_size)) == NULL) | |
| 3539 err = "Could not get X509 certificates"; | |
| 3540 else if (gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0) | |
| 3541 err = "Error parsing X509 certificate"; | |
| 3542 else if (!(soap->ssl_flags & SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE) && gnutls_x509_crt_get_expiration_time(cert) < time(NULL)) | |
| 3543 err = "The certificate has expired"; | |
| 3544 else if (!(soap->ssl_flags & SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE) && gnutls_x509_crt_get_activation_time(cert) > time(NULL)) | |
| 3545 err = "The certificate is not yet activated"; | |
| 3546 else if (host && !(soap->ssl_flags & SOAP_SSL_SKIP_HOST_CHECK)) | |
| 3547 { if (!gnutls_x509_crt_check_hostname(cert, host)) | |
| 3548 err = "Certificate host name mismatch"; | |
| 3549 } | |
| 3550 gnutls_x509_crt_deinit(cert); | |
| 3551 } | |
| 3552 return err; | |
| 3553 } | |
| 3554 #endif | |
| 3555 | |
| 3556 /******************************************************************************/ | |
| 3557 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) | |
| 3558 #ifndef WITH_NOIO | |
| 3559 #ifndef PALM_1 | |
| 3560 SOAP_FMAC1 | |
| 3561 int | |
| 3562 SOAP_FMAC2 | |
| 3563 soap_ssl_accept(struct soap *soap) | |
| 3564 { SOAP_SOCKET sk = soap->socket; | |
| 3565 #ifdef WITH_OPENSSL | |
| 3566 BIO *bio; | |
| 3567 int retries, r, s; | |
| 3568 if (!soap_valid_socket(sk)) | |
| 3569 return soap_set_receiver_error(soap, "SSL/TLS error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR); | |
| 3570 soap->ssl_flags &= ~SOAP_SSL_CLIENT; | |
| 3571 if (!soap->ctx && (soap->error = soap->fsslauth(soap))) | |
| 3572 return soap->error; | |
| 3573 if (!soap->ssl) | |
| 3574 { soap->ssl = SSL_new(soap->ctx); | |
| 3575 if (!soap->ssl) | |
| 3576 return soap_set_receiver_error(soap, "SSL/TLS error", "SSL_new() failed in soap_ssl_accept()", SOAP_SSL_ERROR); | |
| 3577 } | |
| 3578 else | |
| 3579 SSL_clear(soap->ssl); | |
| 3580 bio = BIO_new_socket((int)sk, BIO_NOCLOSE); | |
| 3581 SSL_set_bio(soap->ssl, bio, bio); | |
| 3582 /* Set SSL sockets to non-blocking */ | |
| 3583 retries = 0; | |
| 3584 if (soap->accept_timeout) | |
| 3585 { SOAP_SOCKNONBLOCK(sk) | |
| 3586 retries = 10*soap->accept_timeout; | |
| 3587 } | |
| 3588 if (retries <= 0) | |
| 3589 retries = 100; /* timeout: 10 sec retries, 100 times 0.1 sec */ | |
| 3590 while ((r = SSL_accept(soap->ssl)) <= 0) | |
| 3591 { int err; | |
| 3592 if (retries-- <= 0) | |
| 3593 break; | |
| 3594 err = SSL_get_error(soap->ssl, r); | |
| 3595 if (err == SSL_ERROR_WANT_ACCEPT || err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) | |
| 3596 { if (err == SSL_ERROR_WANT_READ) | |
| 3597 s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000); | |
| 3598 else | |
| 3599 s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000); | |
| 3600 if (s < 0) | |
| 3601 break; | |
| 3602 } | |
| 3603 else | |
| 3604 { soap->errnum = soap_socket_errno(sk); | |
| 3605 break; | |
| 3606 } | |
| 3607 } | |
| 3608 if (r <= 0) | |
| 3609 { soap_set_receiver_error(soap, soap_ssl_error(soap, r), "SSL_accept() failed in soap_ssl_accept()", SOAP_SSL_ERROR); | |
| 3610 soap_closesock(soap); | |
| 3611 return SOAP_SSL_ERROR; | |
| 3612 } | |
| 3613 if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION)) | |
| 3614 { X509 *peer; | |
| 3615 int err; | |
| 3616 if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK) | |
| 3617 { soap_closesock(soap); | |
| 3618 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); | |
| 3619 } | |
| 3620 peer = SSL_get_peer_certificate(soap->ssl); | |
| 3621 if (!peer) | |
| 3622 { soap_closesock(soap); | |
| 3623 return soap_set_sender_error(soap, "SSL/TLS error", "No SSL certificate was presented by the peer in soap_ssl_accept()", SOAP_SSL_ERROR); | |
| 3624 } | |
| 3625 X509_free(peer); | |
| 3626 } | |
| 3627 #endif | |
| 3628 #ifdef WITH_GNUTLS | |
| 3629 int retries = 0, r; | |
| 3630 if (!soap_valid_socket(sk)) | |
| 3631 return soap_set_receiver_error(soap, "SSL/TLS error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR); | |
| 3632 soap->ssl_flags &= ~SOAP_SSL_CLIENT; | |
| 3633 if (!soap->session && (soap->error = soap->fsslauth(soap))) | |
| 3634 { soap_closesock(soap); | |
| 3635 return soap->error; | |
| 3636 } | |
| 3637 gnutls_transport_set_ptr(soap->session, (gnutls_transport_ptr_t)(long)sk); | |
| 3638 /* Set SSL sockets to non-blocking */ | |
| 3639 if (soap->accept_timeout) | |
| 3640 { SOAP_SOCKNONBLOCK(sk) | |
| 3641 retries = 10*soap->accept_timeout; | |
| 3642 } | |
| 3643 if (retries <= 0) | |
| 3644 retries = 100; /* timeout: 10 sec retries, 100 times 0.1 sec */ | |
| 3645 while ((r = gnutls_handshake(soap->session))) | |
| 3646 { int s; | |
| 3647 /* GNUTLS repeat handhake when GNUTLS_E_AGAIN */ | |
| 3648 if (retries-- <= 0) | |
| 3649 break; | |
| 3650 if (r == GNUTLS_E_AGAIN || r == GNUTLS_E_INTERRUPTED) | |
| 3651 { if (!gnutls_record_get_direction(soap->session)) | |
| 3652 s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000); | |
| 3653 else | |
| 3654 s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000); | |
| 3655 if (s < 0) | |
| 3656 break; | |
| 3657 } | |
| 3658 else | |
| 3659 { soap->errnum = soap_socket_errno(sk); | |
| 3660 break; | |
| 3661 } | |
| 3662 } | |
| 3663 if (r) | |
| 3664 { soap_closesock(soap); | |
| 3665 return soap_set_receiver_error(soap, soap_ssl_error(soap, r), "SSL/TLS handshake failed", SOAP_SSL_ERROR); | |
| 3666 } | |
| 3667 if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION)) | |
| 3668 { const char *err = ssl_verify(soap, NULL); | |
| 3669 if (err) | |
| 3670 { soap_closesock(soap); | |
| 3671 return soap_set_receiver_error(soap, "SSL/TLS error", err, SOAP_SSL_ERROR); | |
| 3672 } | |
| 3673 } | |
| 3674 #endif | |
| 3675 if (soap->recv_timeout || soap->send_timeout) | |
| 3676 SOAP_SOCKNONBLOCK(sk) | |
| 3677 else | |
| 3678 SOAP_SOCKBLOCK(sk) | |
| 3679 soap->imode |= SOAP_ENC_SSL; | |
| 3680 soap->omode |= SOAP_ENC_SSL; | |
| 3681 return SOAP_OK; | |
| 3682 } | |
| 3683 #endif | |
| 3684 #endif | |
| 3685 #endif | |
| 3686 | |
| 3687 /******************************************************************************\ | |
| 3688 * | |
| 3689 * TCP/UDP [SSL/TLS] IPv4 and IPv6 | |
| 3690 * | |
| 3691 \******************************************************************************/ | |
| 3692 | |
| 3693 /******************************************************************************/ | |
| 3694 #ifndef WITH_NOIO | |
| 3695 #ifndef PALM_1 | |
| 3696 static int | |
| 3697 tcp_init(struct soap *soap) | |
| 3698 { soap->errmode = 1; | |
| 3699 #ifdef WIN32 | |
| 3700 if (tcp_done) | |
| 3701 return 0; | |
| 3702 else | |
| 3703 { WSADATA w; | |
| 3704 if (WSAStartup(MAKEWORD(1, 1), &w)) | |
| 3705 return -1; | |
| 3706 tcp_done = 1; | |
| 3707 } | |
| 3708 #endif | |
| 3709 return 0; | |
| 3710 } | |
| 3711 #endif | |
| 3712 #endif | |
| 3713 | |
| 3714 /******************************************************************************/ | |
| 3715 #ifndef WITH_NOIO | |
| 3716 #ifndef PALM_1 | |
| 3717 static const char* | |
| 3718 tcp_error(struct soap *soap) | |
| 3719 { register const char *msg = NULL; | |
| 3720 switch (soap->errmode) | |
| 3721 { case 0: | |
| 3722 msg = soap_strerror(soap); | |
| 3723 break; | |
| 3724 case 1: | |
| 3725 msg = "WSAStartup failed"; | |
| 3726 break; | |
| 3727 case 2: | |
| 3728 { | |
| 3729 #ifndef WITH_LEAN | |
| 3730 msg = soap_code_str(h_error_codes, soap->errnum); | |
| 3731 if (!msg) | |
| 3732 #endif | |
| 3733 { | |
| 3734 #ifdef HAVE_SNPRINTF | |
| 3735 soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "TCP/UDP IP error %d", soap->errnum); | |
| 3736 #else | |
| 3737 sprintf(soap->msgbuf, "TCP/UDP IP error %d", soap->errnum); | |
| 3738 #endif | |
| 3739 msg = soap->msgbuf; | |
| 3740 } | |
| 3741 } | |
| 3742 } | |
| 3743 return msg; | |
| 3744 } | |
| 3745 #endif | |
| 3746 #endif | |
| 3747 | |
| 3748 /******************************************************************************/ | |
| 3749 #ifndef WITH_IPV6 | |
| 3750 #ifndef WITH_NOIO | |
| 3751 #ifndef PALM_1 | |
| 3752 static int | |
| 3753 tcp_gethost(struct soap *soap, const char *addr, struct in_addr *inaddr) | |
| 3754 { soap_int32 iadd = -1; | |
| 3755 struct hostent hostent, *host = &hostent; | |
| 3756 #ifdef VXWORKS | |
| 3757 int hostint; | |
| 3758 /* inet_addr(), and hostGetByName() expect "char *"; addr is a "const char *". */ | |
| 3759 iadd = inet_addr((char*)addr); | |
| 3760 #else | |
| 3761 #if defined(_AIX43) || ((defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R)) | |
| 3762 struct hostent_data ht_data; | |
| 3763 #endif | |
| 3764 #ifdef AS400 | |
| 3765 iadd = inet_addr((void*)addr); | |
| 3766 #else | |
| 3767 iadd = inet_addr(addr); | |
| 3768 #endif | |
| 3769 #endif | |
| 3770 if (iadd != -1) | |
| 3771 { memcpy(inaddr, &iadd, sizeof(iadd)); | |
| 3772 return SOAP_OK; | |
| 3773 } | |
| 3774 #if defined(__GLIBC__) || (defined(HAVE_GETHOSTBYNAME_R) && (defined(FREEBSD) || defined(__FreeBSD__))) || defined(__ANDROID__) | |
| 3775 if (gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &host, &soap->errnum) < 0) | |
| 3776 host = NULL; | |
| 3777 #elif defined(_AIX43) || ((defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R)) | |
| 3778 memset((void*)&ht_data, 0, sizeof(ht_data)); | |
| 3779 if (gethostbyname_r(addr, &hostent, &ht_data) < 0) | |
| 3780 { host = NULL; | |
| 3781 soap->errnum = h_errno; | |
| 3782 } | |
| 3783 #elif defined(HAVE_GETHOSTBYNAME_R) | |
| 3784 host = gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &soap->errnum); | |
| 3785 #elif defined(VXWORKS) | |
| 3786 /* If the DNS resolver library resolvLib has been configured in the vxWorks | |
| 3787 * image, a query for the host IP address is sent to the DNS server, if the | |
| 3788 * name was not found in the local host table. */ | |
| 3789 hostint = hostGetByName((char*)addr); | |
| 3790 if (hostint == ERROR) | |
| 3791 { host = NULL; | |
| 3792 soap->errnum = soap_errno; | |
| 3793 } | |
| 3794 #else | |
| 3795 #ifdef AS400 | |
| 3796 if (!(host = gethostbyname((void*)addr))) | |
| 3797 soap->errnum = h_errno; | |
| 3798 #else | |
| 3799 if (!(host = gethostbyname(addr))) | |
| 3800 soap->errnum = h_errno; | |
| 3801 #endif | |
| 3802 #endif | |
| 3803 if (!host) | |
| 3804 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Host name not found\n")); | |
| 3805 return SOAP_ERR; | |
| 3806 } | |
| 3807 #ifdef VXWORKS | |
| 3808 inaddr->s_addr = hostint; | |
| 3809 #else | |
| 3810 memcpy(inaddr, host->h_addr, host->h_length); | |
| 3811 #endif | |
| 3812 return SOAP_OK; | |
| 3813 } | |
| 3814 #endif | |
| 3815 #endif | |
| 3816 #endif | |
| 3817 | |
| 3818 /******************************************************************************/ | |
| 3819 #ifndef WITH_NOIO | |
| 3820 #ifndef PALM_1 | |
| 3821 static SOAP_SOCKET | |
| 3822 tcp_connect(struct soap *soap, const char *endpoint, const char *host, int port) | |
| 3823 { | |
| 3824 #ifdef WITH_IPV6 | |
| 3825 struct addrinfo hints, *res, *ressave; | |
| 3826 #endif | |
| 3827 SOAP_SOCKET sk; | |
| 3828 int err = 0; | |
| 3829 #ifndef WITH_LEAN | |
| 3830 #ifndef WIN32 | |
| 3831 int len = SOAP_BUFLEN; | |
| 3832 #else | |
| 3833 int len = SOAP_BUFLEN + 1; /* speeds up windows xfer */ | |
| 3834 #endif | |
| 3835 int set = 1; | |
| 3836 #endif | |
| 3837 #if !defined(WITH_LEAN) || defined(WITH_OPENSSL) || defined(WITH_GNUTLS) | |
| 3838 int retries; | |
| 3839 #endif | |
| 3840 if (soap_valid_socket(soap->socket)) | |
| 3841 soap->fclosesocket(soap, soap->socket); | |
| 3842 soap->socket = SOAP_INVALID_SOCKET; | |
| 3843 if (tcp_init(soap)) | |
| 3844 { soap->errnum = 0; | |
| 3845 soap_set_sender_error(soap, tcp_error(soap), "TCP init failed in tcp_connect()", SOAP_TCP_ERROR); | |
| 3846 return SOAP_INVALID_SOCKET; | |
| 3847 } | |
| 3848 soap->errmode = 0; | |
| 3849 #ifdef WITH_IPV6 | |
| 3850 memset((void*)&hints, 0, sizeof(hints)); | |
| 3851 hints.ai_family = PF_UNSPEC; | |
| 3852 #ifndef WITH_LEAN | |
| 3853 if ((soap->omode & SOAP_IO_UDP)) | |
| 3854 hints.ai_socktype = SOCK_DGRAM; | |
| 3855 else | |
| 3856 #endif | |
| 3857 hints.ai_socktype = SOCK_STREAM; | |
| 3858 soap->errmode = 2; | |
| 3859 if (soap->proxy_host) | |
| 3860 err = getaddrinfo(soap->proxy_host, soap_int2s(soap, soap->proxy_port), &hints, &res); | |
| 3861 else | |
| 3862 err = getaddrinfo(host, soap_int2s(soap, port), &hints, &res); | |
| 3863 if (err) | |
| 3864 { soap_set_sender_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in tcp_connect()", SOAP_TCP_ERROR); | |
| 3865 return SOAP_INVALID_SOCKET; | |
| 3866 } | |
| 3867 ressave = res; | |
| 3868 again: | |
| 3869 sk = socket(res->ai_family, res->ai_socktype, res->ai_protocol); | |
| 3870 soap->errmode = 0; | |
| 3871 #else | |
| 3872 #ifndef WITH_LEAN | |
| 3873 again: | |
| 3874 #endif | |
| 3875 #ifndef WITH_LEAN | |
| 3876 if ((soap->omode & SOAP_IO_UDP)) | |
| 3877 sk = socket(AF_INET, SOCK_DGRAM, 0); | |
| 3878 else | |
| 3879 #endif | |
| 3880 sk = socket(AF_INET, SOCK_STREAM, 0); | |
| 3881 #endif | |
| 3882 if (!soap_valid_socket(sk)) | |
| 3883 { | |
| 3884 #ifdef WITH_IPV6 | |
| 3885 if (res->ai_next) | |
| 3886 { res = res->ai_next; | |
| 3887 goto again; | |
| 3888 } | |
| 3889 #endif | |
| 3890 soap->errnum = soap_socket_errno(sk); | |
| 3891 soap_set_sender_error(soap, tcp_error(soap), "socket failed in tcp_connect()", SOAP_TCP_ERROR); | |
| 3892 #ifdef WITH_IPV6 | |
| 3893 freeaddrinfo(ressave); | |
| 3894 #endif | |
| 3895 return SOAP_INVALID_SOCKET; | |
| 3896 } | |
| 3897 #ifdef SOCKET_CLOSE_ON_EXEC | |
| 3898 #ifdef WIN32 | |
| 3899 #ifndef UNDER_CE | |
| 3900 SetHandleInformation((HANDLE)sk, HANDLE_FLAG_INHERIT, 0); | |
| 3901 #endif | |
| 3902 #else | |
| 3903 fcntl(sk, F_SETFD, 1); | |
| 3904 #endif | |
| 3905 #endif | |
| 3906 #ifndef WITH_LEAN | |
| 3907 if (soap->connect_flags == SO_LINGER) | |
| 3908 { struct linger linger; | |
| 3909 memset((void*)&linger, 0, sizeof(linger)); | |
| 3910 linger.l_onoff = 1; | |
| 3911 linger.l_linger = soap->linger_time; | |
| 3912 if (setsockopt(sk, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger))) | |
| 3913 { soap->errnum = soap_socket_errno(sk); | |
| 3914 soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in tcp_connect()", SOAP_TCP_ERROR); | |
| 3915 soap->fclosesocket(soap, sk); | |
| 3916 #ifdef WITH_IPV6 | |
| 3917 freeaddrinfo(ressave); | |
| 3918 #endif | |
| 3919 return SOAP_INVALID_SOCKET; | |
| 3920 } | |
| 3921 } | |
| 3922 else if (soap->connect_flags && setsockopt(sk, SOL_SOCKET, soap->connect_flags, (char*)&set, sizeof(int))) | |
| 3923 { soap->errnum = soap_socket_errno(sk); | |
| 3924 soap_set_sender_error(soap, tcp_error(soap), "setsockopt failed in tcp_connect()", SOAP_TCP_ERROR); | |
| 3925 soap->fclosesocket(soap, sk); | |
| 3926 #ifdef WITH_IPV6 | |
| 3927 freeaddrinfo(ressave); | |
| 3928 #endif | |
| 3929 return SOAP_INVALID_SOCKET; | |
| 3930 } | |
| 3931 if ((soap->keep_alive || soap->tcp_keep_alive) && setsockopt(sk, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) | |
| 3932 { soap->errnum = soap_socket_errno(sk); | |
| 3933 soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in tcp_connect()", SOAP_TCP_ERROR); | |
| 3934 soap->fclosesocket(soap, sk); | |
| 3935 #ifdef WITH_IPV6 | |
| 3936 freeaddrinfo(ressave); | |
| 3937 #endif | |
| 3938 return SOAP_INVALID_SOCKET; | |
| 3939 } | |
| 3940 if (setsockopt(sk, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) | |
| 3941 { soap->errnum = soap_socket_errno(sk); | |
| 3942 soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in tcp_connect()", SOAP_TCP_ERROR); | |
| 3943 soap->fclosesocket(soap, sk); | |
| 3944 #ifdef WITH_IPV6 | |
| 3945 freeaddrinfo(ressave); | |
| 3946 #endif | |
| 3947 return SOAP_INVALID_SOCKET; | |
| 3948 } | |
| 3949 if (setsockopt(sk, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) | |
| 3950 { soap->errnum = soap_socket_errno(sk); | |
| 3951 soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in tcp_connect()", SOAP_TCP_ERROR); | |
| 3952 soap->fclosesocket(soap, sk); | |
| 3953 #ifdef WITH_IPV6 | |
| 3954 freeaddrinfo(ressave); | |
| 3955 #endif | |
| 3956 return SOAP_INVALID_SOCKET; | |
| 3957 } | |
| 3958 #ifdef TCP_KEEPIDLE | |
| 3959 if (soap->tcp_keep_idle && setsockopt((SOAP_SOCKET)sk, IPPROTO_TCP, TCP_KEEPIDLE, (char*)&(soap->tcp_keep_idle), sizeof(int))) | |
| 3960 { soap->errnum = soap_socket_errno(sk); | |
| 3961 soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPIDLE failed in tcp_connect()", SOAP_TCP_ERROR); | |
| 3962 soap->fclosesocket(soap, (SOAP_SOCKET)sk); | |
| 3963 #ifdef WITH_IPV6 | |
| 3964 freeaddrinfo(ressave); | |
| 3965 #endif | |
| 3966 return SOAP_INVALID_SOCKET; | |
| 3967 } | |
| 3968 #endif | |
| 3969 #ifdef TCP_KEEPINTVL | |
| 3970 if (soap->tcp_keep_intvl && setsockopt((SOAP_SOCKET)sk, IPPROTO_TCP, TCP_KEEPINTVL, (char*)&(soap->tcp_keep_intvl), sizeof(int))) | |
| 3971 { soap->errnum = soap_socket_errno(sk); | |
| 3972 soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPINTVL failed in tcp_connect()", SOAP_TCP_ERROR); | |
| 3973 soap->fclosesocket(soap, (SOAP_SOCKET)sk); | |
| 3974 #ifdef WITH_IPV6 | |
| 3975 freeaddrinfo(ressave); | |
| 3976 #endif | |
| 3977 return SOAP_INVALID_SOCKET; | |
| 3978 } | |
| 3979 #endif | |
| 3980 #ifdef TCP_KEEPCNT | |
| 3981 if (soap->tcp_keep_cnt && setsockopt((SOAP_SOCKET)sk, IPPROTO_TCP, TCP_KEEPCNT, (char*)&(soap->tcp_keep_cnt), sizeof(int))) | |
| 3982 { soap->errnum = soap_socket_errno(sk); | |
| 3983 soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPCNT failed in tcp_connect()", SOAP_TCP_ERROR); | |
| 3984 soap->fclosesocket(soap, (SOAP_SOCKET)sk); | |
| 3985 #ifdef WITH_IPV6 | |
| 3986 freeaddrinfo(ressave); | |
| 3987 #endif | |
| 3988 return SOAP_INVALID_SOCKET; | |
| 3989 } | |
| 3990 #endif | |
| 3991 #ifdef TCP_NODELAY | |
| 3992 if (!(soap->omode & SOAP_IO_UDP) && setsockopt(sk, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) | |
| 3993 { soap->errnum = soap_socket_errno(sk); | |
| 3994 soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in tcp_connect()", SOAP_TCP_ERROR); | |
| 3995 soap->fclosesocket(soap, sk); | |
| 3996 #ifdef WITH_IPV6 | |
| 3997 freeaddrinfo(ressave); | |
| 3998 #endif | |
| 3999 return SOAP_INVALID_SOCKET; | |
| 4000 } | |
| 4001 #endif | |
| 4002 #ifdef WITH_IPV6 | |
| 4003 if ((soap->omode & SOAP_IO_UDP) && soap->ipv6_multicast_if) | |
| 4004 { struct sockaddr_in6 *in6addr = (struct sockaddr_in6*)res->ai_addr; | |
| 4005 in6addr->sin6_scope_id = soap->ipv6_multicast_if; | |
| 4006 } | |
| 4007 #endif | |
| 4008 #ifdef IP_MULTICAST_TTL | |
| 4009 if ((soap->omode & SOAP_IO_UDP)) | |
| 4010 { if (soap->ipv4_multicast_ttl) | |
| 4011 { unsigned char ttl = soap->ipv4_multicast_ttl; | |
| 4012 if (setsockopt(sk, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ttl, sizeof(ttl))) | |
| 4013 { soap->errnum = soap_socket_errno(sk); | |
| 4014 soap_set_sender_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_TTL failed in tcp_connect()", SOAP_TCP_ERROR); | |
| 4015 soap->fclosesocket(soap, sk); | |
| 4016 return SOAP_INVALID_SOCKET; | |
| 4017 } | |
| 4018 } | |
| 4019 if ((soap->omode & SOAP_IO_UDP) && soap->ipv4_multicast_if && !soap->ipv6_multicast_if) | |
| 4020 { if (setsockopt(sk, IPPROTO_IP, IP_MULTICAST_IF, (char*)soap->ipv4_multicast_if, sizeof(struct in_addr))) | |
| 4021 #ifndef WINDOWS | |
| 4022 { soap->errnum = soap_socket_errno(sk); | |
| 4023 soap_set_sender_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR); | |
| 4024 soap->fclosesocket(soap, sk); | |
| 4025 return SOAP_INVALID_SOCKET; | |
| 4026 } | |
| 4027 #else | |
| 4028 #ifndef IP_MULTICAST_IF | |
| 4029 #define IP_MULTICAST_IF 2 | |
| 4030 #endif | |
| 4031 if (setsockopt(sk, IPPROTO_IP, IP_MULTICAST_IF, (char*)soap->ipv4_multicast_if, sizeof(struct in_addr))) | |
| 4032 { soap->errnum = soap_socket_errno(sk); | |
| 4033 soap_set_sender_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR); | |
| 4034 soap->fclosesocket(soap, sk); | |
| 4035 return SOAP_INVALID_SOCKET; | |
| 4036 } | |
| 4037 #endif | |
| 4038 } | |
| 4039 } | |
| 4040 #endif | |
| 4041 #endif | |
| 4042 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Opening socket=%d to host='%s' port=%d\n", sk, host, port)); | |
| 4043 #ifndef WITH_IPV6 | |
| 4044 soap->peerlen = sizeof(soap->peer); | |
| 4045 memset((void*)&soap->peer, 0, sizeof(soap->peer)); | |
| 4046 soap->peer.sin_family = AF_INET; | |
| 4047 soap->errmode = 2; | |
| 4048 if (soap->proxy_host) | |
| 4049 { if (soap->fresolve(soap, soap->proxy_host, &soap->peer.sin_addr)) | |
| 4050 { soap_set_sender_error(soap, tcp_error(soap), "get proxy host by name failed in tcp_connect()", SOAP_TCP_ERROR); | |
| 4051 soap->fclosesocket(soap, sk); | |
| 4052 return SOAP_INVALID_SOCKET; | |
| 4053 } | |
| 4054 soap->peer.sin_port = htons((short)soap->proxy_port); | |
| 4055 } | |
| 4056 else | |
| 4057 { if (soap->fresolve(soap, host, &soap->peer.sin_addr)) | |
| 4058 { soap_set_sender_error(soap, tcp_error(soap), "get host by name failed in tcp_connect()", SOAP_TCP_ERROR); | |
| 4059 soap->fclosesocket(soap, sk); | |
| 4060 return SOAP_INVALID_SOCKET; | |
| 4061 } | |
| 4062 soap->peer.sin_port = htons((short)port); | |
| 4063 } | |
| 4064 soap->errmode = 0; | |
| 4065 #ifndef WITH_LEAN | |
| 4066 if ((soap->omode & SOAP_IO_UDP)) | |
| 4067 return sk; | |
| 4068 #endif | |
| 4069 #else | |
| 4070 if ((soap->omode & SOAP_IO_UDP)) | |
| 4071 { memcpy(&soap->peer, res->ai_addr, res->ai_addrlen); | |
| 4072 soap->peerlen = res->ai_addrlen; | |
| 4073 freeaddrinfo(ressave); | |
| 4074 return sk; | |
| 4075 } | |
| 4076 #endif | |
| 4077 #ifndef WITH_LEAN | |
| 4078 if (soap->connect_timeout) | |
| 4079 SOAP_SOCKNONBLOCK(sk) | |
| 4080 else | |
| 4081 SOAP_SOCKBLOCK(sk) | |
| 4082 retries = 10; | |
| 4083 #endif | |
| 4084 for (;;) | |
| 4085 { | |
| 4086 #ifdef WITH_IPV6 | |
| 4087 if (connect(sk, res->ai_addr, (int)res->ai_addrlen)) | |
| 4088 #else | |
| 4089 if (connect(sk, (struct sockaddr*)&soap->peer, sizeof(soap->peer))) | |
| 4090 #endif | |
| 4091 { err = soap_socket_errno(sk); | |
| 4092 #ifndef WITH_LEAN | |
| 4093 if (err == SOAP_EADDRINUSE) | |
| 4094 { soap->fclosesocket(soap, sk); | |
| 4095 if (retries-- > 0) | |
| 4096 goto again; | |
| 4097 } | |
| 4098 else if (soap->connect_timeout && (err == SOAP_EINPROGRESS || err == SOAP_EAGAIN || err == SOAP_EWOULDBLOCK)) | |
| 4099 { | |
| 4100 SOAP_SOCKLEN_T k; | |
| 4101 for (;;) | |
| 4102 { register int r; | |
| 4103 r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND, soap->connect_timeout); | |
| 4104 if (r > 0) | |
| 4105 break; | |
| 4106 if (!r) | |
| 4107 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n")); | |
| 4108 soap_set_sender_error(soap, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR); | |
| 4109 soap->fclosesocket(soap, sk); | |
| 4110 #ifdef WITH_IPV6 | |
| 4111 freeaddrinfo(ressave); | |
| 4112 #endif | |
| 4113 return SOAP_INVALID_SOCKET; | |
| 4114 } | |
| 4115 r = soap->errnum = soap_socket_errno(sk); | |
| 4116 if (r != SOAP_EINTR) | |
| 4117 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); | |
| 4118 soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR); | |
| 4119 soap->fclosesocket(soap, sk); | |
| 4120 #ifdef WITH_IPV6 | |
| 4121 freeaddrinfo(ressave); | |
| 4122 #endif | |
| 4123 return SOAP_INVALID_SOCKET; | |
| 4124 } | |
| 4125 } | |
| 4126 k = (SOAP_SOCKLEN_T)sizeof(soap->errnum); | |
| 4127 if (!getsockopt(sk, SOL_SOCKET, SO_ERROR, (char*)&soap->errnum, &k) && !soap->errnum) /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */ | |
| 4128 break; | |
| 4129 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); | |
| 4130 if (!soap->errnum) | |
| 4131 soap->errnum = soap_socket_errno(sk); | |
| 4132 soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR); | |
| 4133 soap->fclosesocket(soap, sk); | |
| 4134 #ifdef WITH_IPV6 | |
| 4135 freeaddrinfo(ressave); | |
| 4136 #endif | |
| 4137 return SOAP_INVALID_SOCKET; | |
| 4138 } | |
| 4139 #endif | |
| 4140 #ifdef WITH_IPV6 | |
| 4141 if (res->ai_next) | |
| 4142 { res = res->ai_next; | |
| 4143 soap->fclosesocket(soap, sk); | |
| 4144 goto again; | |
| 4145 } | |
| 4146 #endif | |
| 4147 if (err && err != SOAP_EINTR) | |
| 4148 { soap->errnum = err; | |
| 4149 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); | |
| 4150 soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR); | |
| 4151 soap->fclosesocket(soap, sk); | |
| 4152 #ifdef WITH_IPV6 | |
| 4153 freeaddrinfo(ressave); | |
| 4154 #endif | |
| 4155 return SOAP_INVALID_SOCKET; | |
| 4156 } | |
| 4157 } | |
| 4158 else | |
| 4159 break; | |
| 4160 } | |
| 4161 #ifdef WITH_IPV6 | |
| 4162 soap->peerlen = 0; /* IPv6: already connected so use send() */ | |
| 4163 freeaddrinfo(ressave); | |
| 4164 #endif | |
| 4165 soap->socket = sk; | |
| 4166 soap->imode &= ~SOAP_ENC_SSL; | |
| 4167 soap->omode &= ~SOAP_ENC_SSL; | |
| 4168 if (!soap_tag_cmp(endpoint, "https:*")) | |
| 4169 { | |
| 4170 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) | |
| 4171 #ifdef WITH_OPENSSL | |
| 4172 BIO *bio; | |
| 4173 #endif | |
| 4174 int r; | |
| 4175 if (soap->proxy_host) | |
| 4176 { soap_mode m = soap->mode; /* preserve settings */ | |
| 4177 soap_mode om = soap->omode; /* make sure we only parse HTTP */ | |
| 4178 size_t n = soap->count; /* save the content length */ | |
| 4179 const char *userid, *passwd; | |
| 4180 int status = soap->status; /* save the current status/command */ | |
| 4181 short keep_alive = soap->keep_alive; /* save the KA status */ | |
| 4182 soap->omode &= ~SOAP_ENC; /* mask IO and ENC */ | |
| 4183 soap->omode |= SOAP_IO_BUFFER; | |
| 4184 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connecting to %s proxy server %s for destination endpoint %s\n", soap->proxy_http_version, soap->proxy_host, endpoint)); | |
| 4185 #ifdef WITH_NTLM | |
| 4186 if (soap->ntlm_challenge) | |
| 4187 { if (soap_ntlm_handshake(soap, SOAP_CONNECT, endpoint, host, port)) | |
| 4188 return soap->error; | |
| 4189 } | |
| 4190 #endif | |
| 4191 if (soap_begin_send(soap)) | |
| 4192 { soap->fclosesocket(soap, sk); | |
| 4193 return SOAP_INVALID_SOCKET; | |
| 4194 } | |
| 4195 soap->status = SOAP_CONNECT; | |
| 4196 soap->keep_alive = 1; | |
| 4197 if ((soap->error = soap->fpost(soap, endpoint, host, port, NULL, NULL, 0)) | |
| 4198 || soap_end_send_flush(soap)) | |
| 4199 { soap->fclosesocket(soap, sk); | |
| 4200 return SOAP_INVALID_SOCKET; | |
| 4201 } | |
| 4202 soap->keep_alive = keep_alive; | |
| 4203 soap->omode = om; | |
| 4204 om = soap->imode; | |
| 4205 soap->imode &= ~SOAP_ENC; /* mask IO and ENC */ | |
| 4206 userid = soap->userid; /* preserve */ | |
| 4207 passwd = soap->passwd; /* preserve */ | |
| 4208 if ((soap->error = soap->fparse(soap))) | |
| 4209 { soap->fclosesocket(soap, sk); | |
| 4210 return SOAP_INVALID_SOCKET; | |
| 4211 } | |
| 4212 soap->status = status; /* restore */ | |
| 4213 soap->userid = userid; /* restore */ | |
| 4214 soap->passwd = passwd; /* restore */ | |
| 4215 soap->imode = om; /* restore */ | |
| 4216 soap->count = n; /* restore */ | |
| 4217 if (soap_begin_send(soap)) | |
| 4218 { soap->fclosesocket(soap, sk); | |
| 4219 return SOAP_INVALID_SOCKET; | |
| 4220 } | |
| 4221 if (endpoint) | |
| 4222 { strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint)); /* restore */ | |
| 4223 soap->endpoint[sizeof(soap->endpoint) - 1] = '\0'; | |
| 4224 } | |
| 4225 soap->mode = m; | |
| 4226 } | |
| 4227 #ifdef WITH_OPENSSL | |
| 4228 soap->ssl_flags |= SOAP_SSL_CLIENT; | |
| 4229 if (!soap->ctx && (soap->error = soap->fsslauth(soap))) | |
| 4230 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL required, but no ctx set\n")); | |
| 4231 soap->fclosesocket(soap, sk); | |
| 4232 soap->error = SOAP_SSL_ERROR; | |
| 4233 return SOAP_INVALID_SOCKET; | |
| 4234 } | |
| 4235 if (!soap->ssl) | |
| 4236 { soap->ssl = SSL_new(soap->ctx); | |
| 4237 if (!soap->ssl) | |
| 4238 { soap->fclosesocket(soap, sk); | |
| 4239 soap->error = SOAP_SSL_ERROR; | |
| 4240 return SOAP_INVALID_SOCKET; | |
| 4241 } | |
| 4242 } | |
| 4243 else | |
| 4244 SSL_clear(soap->ssl); | |
| 4245 if (soap->session) | |
| 4246 { if (!strcmp(soap->session_host, host) && soap->session_port == port) | |
| 4247 SSL_set_session(soap->ssl, soap->session); | |
| 4248 SSL_SESSION_free(soap->session); | |
| 4249 soap->session = NULL; | |
| 4250 } | |
| 4251 soap->imode |= SOAP_ENC_SSL; | |
| 4252 soap->omode |= SOAP_ENC_SSL; | |
| 4253 bio = BIO_new_socket((int)sk, BIO_NOCLOSE); | |
| 4254 SSL_set_bio(soap->ssl, bio, bio); | |
| 4255 /* Connect timeout: set SSL sockets to non-blocking */ | |
| 4256 retries = 0; | |
| 4257 if (soap->connect_timeout) | |
| 4258 { SOAP_SOCKNONBLOCK(sk) | |
| 4259 retries = 10*soap->connect_timeout; | |
| 4260 } | |
| 4261 else | |
| 4262 SOAP_SOCKBLOCK(sk) | |
| 4263 if (retries <= 0) | |
| 4264 retries = 100; /* timeout: 10 sec retries, 100 times 0.1 sec */ | |
| 4265 /* Try connecting until success or timeout (when nonblocking) */ | |
| 4266 do | |
| 4267 { if ((r = SSL_connect(soap->ssl)) <= 0) | |
| 4268 { int err = SSL_get_error(soap->ssl, r); | |
| 4269 if (err == SSL_ERROR_WANT_CONNECT || err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) | |
| 4270 { register int s; | |
| 4271 if (err == SSL_ERROR_WANT_READ) | |
| 4272 s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000); | |
| 4273 else | |
| 4274 s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000); | |
| 4275 if (s < 0) | |
| 4276 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL_connect/select error in tcp_connect\n")); | |
| 4277 soap_set_sender_error(soap, soap_ssl_error(soap, r), "SSL_connect failed in tcp_connect()", SOAP_TCP_ERROR); | |
| 4278 soap->fclosesocket(soap, sk); | |
| 4279 return SOAP_INVALID_SOCKET; | |
| 4280 } | |
| 4281 if (s == 0 && retries-- <= 0) | |
| 4282 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL/TLS connect timeout\n")); | |
| 4283 soap_set_sender_error(soap, "Timeout", "SSL_connect failed in tcp_connect()", SOAP_TCP_ERROR); | |
| 4284 soap->fclosesocket(soap, sk); | |
| 4285 return SOAP_INVALID_SOCKET; | |
| 4286 } | |
| 4287 } | |
| 4288 else | |
| 4289 { soap_set_sender_error(soap, soap_ssl_error(soap, r), "SSL_connect error in tcp_connect()", SOAP_SSL_ERROR); | |
| 4290 soap->fclosesocket(soap, sk); | |
| 4291 return SOAP_INVALID_SOCKET; | |
| 4292 } | |
| 4293 } | |
| 4294 } while (!SSL_is_init_finished(soap->ssl)); | |
| 4295 /* Set SSL sockets to nonblocking */ | |
| 4296 SOAP_SOCKNONBLOCK(sk) | |
| 4297 /* Check server credentials when required */ | |
| 4298 if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION)) | |
| 4299 { int err; | |
| 4300 if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK) | |
| 4301 { 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); | |
| 4302 soap->fclosesocket(soap, sk); | |
| 4303 return SOAP_INVALID_SOCKET; | |
| 4304 } | |
| 4305 if (!(soap->ssl_flags & SOAP_SSL_SKIP_HOST_CHECK)) | |
| 4306 { X509_NAME *subj; | |
| 4307 STACK_OF(CONF_VALUE) *val = NULL; | |
| 4308 #if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) | |
| 4309 GENERAL_NAMES *names = NULL; | |
| 4310 #else | |
| 4311 int ext_count; | |
| 4312 #endif | |
| 4313 int ok = 0; | |
| 4314 X509 *peer = SSL_get_peer_certificate(soap->ssl); | |
| 4315 if (!peer) | |
| 4316 { soap_set_sender_error(soap, "SSL/TLS error", "No SSL/TLS certificate was presented by the peer in tcp_connect()", SOAP_SSL_ERROR); | |
| 4317 soap->fclosesocket(soap, sk); | |
| 4318 return SOAP_INVALID_SOCKET; | |
| 4319 } | |
| 4320 #if (OPENSSL_VERSION_NUMBER < 0x0090800fL) | |
| 4321 ext_count = X509_get_ext_count(peer); | |
| 4322 if (ext_count > 0) | |
| 4323 { int i; | |
| 4324 for (i = 0; i < ext_count; i++) | |
| 4325 { X509_EXTENSION *ext = X509_get_ext(peer, i); | |
| 4326 const char *ext_str = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext))); | |
| 4327 if (ext_str && !strcmp(ext_str, "subjectAltName")) | |
| 4328 { X509V3_EXT_METHOD *meth = (X509V3_EXT_METHOD*)X509V3_EXT_get(ext); | |
| 4329 unsigned char *data; | |
| 4330 if (!meth) | |
| 4331 break; | |
| 4332 data = ext->value->data; | |
| 4333 if (data) | |
| 4334 { | |
| 4335 #if (OPENSSL_VERSION_NUMBER > 0x00907000L) | |
| 4336 void *ext_data; | |
| 4337 if (meth->it) | |
| 4338 ext_data = ASN1_item_d2i(NULL, &data, ext->value->length, ASN1_ITEM_ptr(meth->it)); | |
| 4339 else | |
| 4340 { /* OpenSSL is not portable at this point (?): | |
| 4341 Some compilers appear to prefer | |
| 4342 meth->d2i(NULL, (const unsigned char**)&data, ... | |
| 4343 and others prefer | |
| 4344 meth->d2i(NULL, &data, ext->value->length); | |
| 4345 */ | |
| 4346 ext_data = meth->d2i(NULL, &data, ext->value->length); | |
| 4347 } | |
| 4348 if (ext_data) | |
| 4349 val = meth->i2v(meth, ext_data, NULL); | |
| 4350 else | |
| 4351 val = NULL; | |
| 4352 if (meth->it) | |
| 4353 ASN1_item_free((ASN1_VALUE*)ext_data, ASN1_ITEM_ptr(meth->it)); | |
| 4354 else | |
| 4355 meth->ext_free(ext_data); | |
| 4356 #else | |
| 4357 void *ext_data = meth->d2i(NULL, &data, ext->value->length); | |
| 4358 if (ext_data) | |
| 4359 val = meth->i2v(meth, ext_data, NULL); | |
| 4360 meth->ext_free(ext_data); | |
| 4361 #endif | |
| 4362 if (val) | |
| 4363 { int j; | |
| 4364 for (j = 0; j < sk_CONF_VALUE_num(val); j++) | |
| 4365 { CONF_VALUE *nval = sk_CONF_VALUE_value(val, j); | |
| 4366 if (nval && !strcmp(nval->name, "DNS") && !strcmp(nval->value, host)) | |
| 4367 { ok = 1; | |
| 4368 break; | |
| 4369 } | |
| 4370 } | |
| 4371 sk_CONF_VALUE_pop_free(val, X509V3_conf_free); | |
| 4372 } | |
| 4373 } | |
| 4374 } | |
| 4375 if (ok) | |
| 4376 break; | |
| 4377 } | |
| 4378 } | |
| 4379 #else | |
| 4380 names = (GENERAL_NAMES*)X509_get_ext_d2i(peer, NID_subject_alt_name, NULL, NULL); | |
| 4381 if (names) | |
| 4382 { val = i2v_GENERAL_NAMES(NULL, names, val); | |
| 4383 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free); | |
| 4384 } | |
| 4385 if (val) | |
| 4386 { int j; | |
| 4387 for (j = 0; j < sk_CONF_VALUE_num(val); j++) | |
| 4388 { CONF_VALUE *nval = sk_CONF_VALUE_value(val, j); | |
| 4389 if (nval && !strcmp(nval->name, "DNS") && !strcmp(nval->value, host)) | |
| 4390 { ok = 1; | |
| 4391 break; | |
| 4392 } | |
| 4393 } | |
| 4394 sk_CONF_VALUE_pop_free(val, X509V3_conf_free); | |
| 4395 } | |
| 4396 #endif | |
| 4397 if (!ok && (subj = X509_get_subject_name(peer))) | |
| 4398 { int i = -1; | |
| 4399 do | |
| 4400 { ASN1_STRING *name; | |
| 4401 i = X509_NAME_get_index_by_NID(subj, NID_commonName, i); | |
| 4402 if (i == -1) | |
| 4403 break; | |
| 4404 name = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subj, i)); | |
| 4405 if (name) | |
| 4406 { if (!soap_tag_cmp(host, (const char*)M_ASN1_STRING_data(name))) | |
| 4407 ok = 1; | |
| 4408 else | |
| 4409 { unsigned char *tmp = NULL; | |
| 4410 ASN1_STRING_to_UTF8(&tmp, name); | |
| 4411 if (tmp) | |
| 4412 { if (!soap_tag_cmp(host, (const char*)tmp)) | |
| 4413 ok = 1; | |
| 4414 else if (tmp[0] == '*') /* wildcard domain */ | |
| 4415 { const char *t = strchr(host, '.'); | |
| 4416 if (t && !soap_tag_cmp(t, (const char*)tmp+1)) | |
| 4417 ok = 1; | |
| 4418 } | |
| 4419 OPENSSL_free(tmp); | |
| 4420 } | |
| 4421 } | |
| 4422 } | |
| 4423 } while (!ok); | |
| 4424 } | |
| 4425 X509_free(peer); | |
| 4426 if (!ok) | |
| 4427 { soap_set_sender_error(soap, "SSL/TLS error", "SSL/TLS certificate host name mismatch in tcp_connect()", SOAP_SSL_ERROR); | |
| 4428 soap->fclosesocket(soap, sk); | |
| 4429 return SOAP_INVALID_SOCKET; | |
| 4430 } | |
| 4431 } | |
| 4432 } | |
| 4433 #endif | |
| 4434 #ifdef WITH_GNUTLS | |
| 4435 soap->ssl_flags |= SOAP_SSL_CLIENT; | |
| 4436 if (!soap->session && (soap->error = soap->fsslauth(soap))) | |
| 4437 { soap->fclosesocket(soap, sk); | |
| 4438 return SOAP_INVALID_SOCKET; | |
| 4439 } | |
| 4440 gnutls_transport_set_ptr(soap->session, (gnutls_transport_ptr_t)(long)sk); | |
| 4441 /* Set SSL sockets to non-blocking */ | |
| 4442 if (soap->connect_timeout) | |
| 4443 { SOAP_SOCKNONBLOCK(sk) | |
| 4444 retries = 10*soap->connect_timeout; | |
| 4445 } | |
| 4446 else | |
| 4447 SOAP_SOCKBLOCK(sk) | |
| 4448 if (retries <= 0) | |
| 4449 retries = 100; /* timeout: 10 sec retries, 100 times 0.1 sec */ | |
| 4450 while ((r = gnutls_handshake(soap->session))) | |
| 4451 { int s; | |
| 4452 /* GNUTLS repeat handhake when GNUTLS_E_AGAIN */ | |
| 4453 if (retries-- <= 0) | |
| 4454 break; | |
| 4455 if (r == GNUTLS_E_AGAIN || r == GNUTLS_E_INTERRUPTED) | |
| 4456 { if (!gnutls_record_get_direction(soap->session)) | |
| 4457 s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000); | |
| 4458 else | |
| 4459 s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000); | |
| 4460 if (s < 0) | |
| 4461 break; | |
| 4462 } | |
| 4463 else | |
| 4464 { soap->errnum = soap_socket_errno(sk); | |
| 4465 break; | |
| 4466 } | |
| 4467 } | |
| 4468 if (r) | |
| 4469 { soap_set_sender_error(soap, soap_ssl_error(soap, r), "SSL/TLS handshake failed", SOAP_SSL_ERROR); | |
| 4470 soap->fclosesocket(soap, sk); | |
| 4471 return SOAP_INVALID_SOCKET; | |
| 4472 } | |
| 4473 if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION)) | |
| 4474 { const char *err = ssl_verify(soap, host); | |
| 4475 if (err) | |
| 4476 { soap->fclosesocket(soap, sk); | |
| 4477 soap->error = soap_set_sender_error(soap, "SSL/TLS error", err, SOAP_SSL_ERROR); | |
| 4478 return SOAP_INVALID_SOCKET; | |
| 4479 } | |
| 4480 } | |
| 4481 #endif | |
| 4482 #else | |
| 4483 soap->fclosesocket(soap, sk); | |
| 4484 soap->error = SOAP_SSL_ERROR; | |
| 4485 return SOAP_INVALID_SOCKET; | |
| 4486 #endif | |
| 4487 } | |
| 4488 if (soap->recv_timeout || soap->send_timeout) | |
| 4489 SOAP_SOCKNONBLOCK(sk) | |
| 4490 else | |
| 4491 SOAP_SOCKBLOCK(sk) | |
| 4492 return sk; | |
| 4493 } | |
| 4494 #endif | |
| 4495 #endif | |
| 4496 | |
| 4497 /******************************************************************************/ | |
| 4498 #ifndef WITH_NOIO | |
| 4499 #ifndef PALM_1 | |
| 4500 static int | |
| 4501 tcp_select(struct soap *soap, SOAP_SOCKET sk, int flags, int timeout) | |
| 4502 { int r; | |
| 4503 struct timeval tv; | |
| 4504 fd_set fd[3], *rfd, *sfd, *efd; | |
| 4505 int retries = 0; | |
| 4506 int eintr = SOAP_MAXEINTR; | |
| 4507 soap->errnum = 0; | |
| 4508 #ifndef WIN32 | |
| 4509 #if !defined(FD_SETSIZE) || defined(__QNX__) || defined(QNX) | |
| 4510 /* no FD_SETSIZE or select() is not MT safe on some QNX: always poll */ | |
| 4511 if (1) | |
| 4512 #else | |
| 4513 /* if fd max set size exceeded, use poll() */ | |
| 4514 if ((int)sk >= (int)FD_SETSIZE) | |
| 4515 #endif | |
| 4516 #ifdef HAVE_POLL | |
| 4517 { struct pollfd pollfd; | |
| 4518 pollfd.fd = (int)sk; | |
| 4519 pollfd.events = 0; | |
| 4520 if (flags & SOAP_TCP_SELECT_RCV) | |
| 4521 pollfd.events |= POLLIN; | |
| 4522 if (flags & SOAP_TCP_SELECT_SND) | |
| 4523 pollfd.events |= POLLOUT; | |
| 4524 if (flags & SOAP_TCP_SELECT_ERR) | |
| 4525 pollfd.events |= POLLERR; | |
| 4526 if (timeout <= 0) | |
| 4527 timeout /= -1000; /* -usec -> ms */ | |
| 4528 else | |
| 4529 { retries = timeout - 1; | |
| 4530 timeout = 1000; | |
| 4531 } | |
| 4532 do | |
| 4533 { r = poll(&pollfd, 1, timeout); | |
| 4534 if (r < 0 && (soap->errnum = soap_socket_errno(sk)) == SOAP_EINTR && eintr--) | |
| 4535 continue; | |
| 4536 } while (r == 0 && retries--); | |
| 4537 if (r > 0) | |
| 4538 { r = 0; | |
| 4539 if ((flags & SOAP_TCP_SELECT_RCV) && (pollfd.revents & POLLIN)) | |
| 4540 r |= SOAP_TCP_SELECT_RCV; | |
| 4541 if ((flags & SOAP_TCP_SELECT_SND) && (pollfd.revents & POLLOUT)) | |
| 4542 r |= SOAP_TCP_SELECT_SND; | |
| 4543 if ((flags & SOAP_TCP_SELECT_ERR) && (pollfd.revents & POLLERR)) | |
| 4544 r |= SOAP_TCP_SELECT_ERR; | |
| 4545 } | |
| 4546 return r; | |
| 4547 } | |
| 4548 #else | |
| 4549 { soap->error = SOAP_FD_EXCEEDED; | |
| 4550 return -1; | |
| 4551 } | |
| 4552 #endif | |
| 4553 #endif | |
| 4554 if (timeout > 0) | |
| 4555 retries = timeout - 1; | |
| 4556 do | |
| 4557 { rfd = sfd = efd = NULL; | |
| 4558 if (flags & SOAP_TCP_SELECT_RCV) | |
| 4559 { rfd = &fd[0]; | |
| 4560 FD_ZERO(rfd); | |
| 4561 FD_SET(sk, rfd); | |
| 4562 } | |
| 4563 if (flags & SOAP_TCP_SELECT_SND) | |
| 4564 { sfd = &fd[1]; | |
| 4565 FD_ZERO(sfd); | |
| 4566 FD_SET(sk, sfd); | |
| 4567 } | |
| 4568 if (flags & SOAP_TCP_SELECT_ERR) | |
| 4569 { efd = &fd[2]; | |
| 4570 FD_ZERO(efd); | |
| 4571 FD_SET(sk, efd); | |
| 4572 } | |
| 4573 if (timeout <= 0) | |
| 4574 { tv.tv_sec = -timeout / 1000000; | |
| 4575 tv.tv_usec = -timeout % 1000000; | |
| 4576 } | |
| 4577 else | |
| 4578 { tv.tv_sec = 1; | |
| 4579 tv.tv_usec = 0; | |
| 4580 } | |
| 4581 r = select((int)sk + 1, rfd, sfd, efd, &tv); | |
| 4582 if (r < 0 && (soap->errnum = soap_socket_errno(sk)) == SOAP_EINTR && eintr--) | |
| 4583 continue; | |
| 4584 } while (r == 0 && retries--); | |
| 4585 if (r > 0) | |
| 4586 { r = 0; | |
| 4587 if ((flags & SOAP_TCP_SELECT_RCV) && FD_ISSET(sk, rfd)) | |
| 4588 r |= SOAP_TCP_SELECT_RCV; | |
| 4589 if ((flags & SOAP_TCP_SELECT_SND) && FD_ISSET(sk, sfd)) | |
| 4590 r |= SOAP_TCP_SELECT_SND; | |
| 4591 if ((flags & SOAP_TCP_SELECT_ERR) && FD_ISSET(sk, efd)) | |
| 4592 r |= SOAP_TCP_SELECT_ERR; | |
| 4593 } | |
| 4594 return r; | |
| 4595 } | |
| 4596 #endif | |
| 4597 #endif | |
| 4598 | |
| 4599 /******************************************************************************/ | |
| 4600 #ifndef WITH_NOIO | |
| 4601 #ifndef PALM_1 | |
| 4602 static SOAP_SOCKET | |
| 4603 tcp_accept(struct soap *soap, SOAP_SOCKET s, struct sockaddr *a, int *n) | |
| 4604 { SOAP_SOCKET sk; | |
| 4605 (void)soap; | |
| 4606 sk = accept(s, a, (SOAP_SOCKLEN_T*)n); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */ | |
| 4607 #ifdef SOCKET_CLOSE_ON_EXEC | |
| 4608 #ifdef WIN32 | |
| 4609 #ifndef UNDER_CE | |
| 4610 SetHandleInformation((HANDLE)sk, HANDLE_FLAG_INHERIT, 0); | |
| 4611 #endif | |
| 4612 #else | |
| 4613 fcntl(sk, F_SETFD, FD_CLOEXEC); | |
| 4614 #endif | |
| 4615 #endif | |
| 4616 return sk; | |
| 4617 } | |
| 4618 #endif | |
| 4619 #endif | |
| 4620 | |
| 4621 /******************************************************************************/ | |
| 4622 #ifndef WITH_NOIO | |
| 4623 #ifndef PALM_1 | |
| 4624 static int | |
| 4625 tcp_disconnect(struct soap *soap) | |
| 4626 { | |
| 4627 #ifdef WITH_OPENSSL | |
| 4628 if (soap->ssl) | |
| 4629 { int r, s = 0; | |
| 4630 if (soap->session) | |
| 4631 { SSL_SESSION_free(soap->session); | |
| 4632 soap->session = NULL; | |
| 4633 } | |
| 4634 if (*soap->host) | |
| 4635 { soap->session = SSL_get1_session(soap->ssl); | |
| 4636 if (soap->session) | |
| 4637 { strcpy(soap->session_host, soap->host); | |
| 4638 soap->session_port = soap->port; | |
| 4639 } | |
| 4640 } | |
| 4641 r = SSL_shutdown(soap->ssl); | |
| 4642 /* SSL shutdown does not work when reads are pending, non-blocking */ | |
| 4643 if (r == 0) | |
| 4644 { while (SSL_want_read(soap->ssl)) | |
| 4645 { if (SSL_read(soap->ssl, NULL, 0) | |
| 4646 || soap_socket_errno(soap->socket) != SOAP_EAGAIN) | |
| 4647 { r = SSL_shutdown(soap->ssl); | |
| 4648 break; | |
| 4649 } | |
| 4650 } | |
| 4651 } | |
| 4652 if (r == 0) | |
| 4653 { if (soap_valid_socket(soap->socket)) | |
| 4654 { if (!soap->fshutdownsocket(soap, soap->socket, SOAP_SHUT_WR)) | |
| 4655 { | |
| 4656 #if !defined(WITH_LEAN) && !defined(WIN32) | |
| 4657 /* | |
| 4658 wait up to 5 seconds for close_notify to be sent by peer (if peer not | |
| 4659 present, this avoids calling SSL_shutdown() which has a lengthy return | |
| 4660 timeout) | |
| 4661 */ | |
| 4662 r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, 5); | |
| 4663 if (r <= 0) | |
| 4664 { soap->errnum = 0; | |
| 4665 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connection lost...\n")); | |
| 4666 soap->fclosesocket(soap, soap->socket); | |
| 4667 soap->socket = SOAP_INVALID_SOCKET; | |
| 4668 ERR_remove_state(0); | |
| 4669 SSL_free(soap->ssl); | |
| 4670 soap->ssl = NULL; | |
| 4671 return SOAP_OK; | |
| 4672 } | |
| 4673 #else | |
| 4674 r = SSL_shutdown(soap->ssl); | |
| 4675 #endif | |
| 4676 } | |
| 4677 } | |
| 4678 } | |
| 4679 if (r != 1) | |
| 4680 { s = ERR_get_error(); | |
| 4681 if (s) | |
| 4682 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown failed: %d\n", SSL_get_error(soap->ssl, r))); | |
| 4683 if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP)) | |
| 4684 { soap->fclosesocket(soap, soap->socket); | |
| 4685 soap->socket = SOAP_INVALID_SOCKET; | |
| 4686 } | |
| 4687 } | |
| 4688 } | |
| 4689 SSL_free(soap->ssl); | |
| 4690 soap->ssl = NULL; | |
| 4691 if (s) | |
| 4692 return SOAP_SSL_ERROR; | |
| 4693 ERR_remove_state(0); | |
| 4694 } | |
| 4695 #endif | |
| 4696 #ifdef WITH_GNUTLS | |
| 4697 if (soap->session) | |
| 4698 { gnutls_bye(soap->session, GNUTLS_SHUT_RDWR); | |
| 4699 gnutls_deinit(soap->session); | |
| 4700 soap->session = NULL; | |
| 4701 } | |
| 4702 #endif | |
| 4703 if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP)) | |
| 4704 { soap->fshutdownsocket(soap, soap->socket, SOAP_SHUT_RDWR); | |
| 4705 soap->fclosesocket(soap, soap->socket); | |
| 4706 soap->socket = SOAP_INVALID_SOCKET; | |
| 4707 } | |
| 4708 return SOAP_OK; | |
| 4709 } | |
| 4710 #endif | |
| 4711 #endif | |
| 4712 | |
| 4713 /******************************************************************************/ | |
| 4714 #ifndef WITH_NOIO | |
| 4715 #ifndef PALM_1 | |
| 4716 static int | |
| 4717 tcp_closesocket(struct soap *soap, SOAP_SOCKET sk) | |
| 4718 { (void)soap; | |
| 4719 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Close socket=%d\n", (int)sk)); | |
| 4720 return soap_closesocket(sk); | |
| 4721 } | |
| 4722 #endif | |
| 4723 #endif | |
| 4724 | |
| 4725 /******************************************************************************/ | |
| 4726 #ifndef WITH_NOIO | |
| 4727 #ifndef PALM_1 | |
| 4728 static int | |
| 4729 tcp_shutdownsocket(struct soap *soap, SOAP_SOCKET sk, int how) | |
| 4730 { (void)soap; | |
| 4731 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown socket=%d how=%d\n", (int)sk, how)); | |
| 4732 return shutdown(sk, how); | |
| 4733 } | |
| 4734 #endif | |
| 4735 #endif | |
| 4736 | |
| 4737 /******************************************************************************/ | |
| 4738 #ifndef WITH_NOIO | |
| 4739 #ifndef PALM_1 | |
| 4740 SOAP_FMAC1 | |
| 4741 SOAP_SOCKET | |
| 4742 SOAP_FMAC2 | |
| 4743 soap_bind(struct soap *soap, const char *host, int port, int backlog) | |
| 4744 { | |
| 4745 #ifdef WITH_IPV6 | |
| 4746 struct addrinfo *addrinfo = NULL; | |
| 4747 struct addrinfo hints; | |
| 4748 struct addrinfo res; | |
| 4749 int err; | |
| 4750 #ifdef WITH_NO_IPV6_V6ONLY | |
| 4751 int unset = 0; | |
| 4752 #endif | |
| 4753 #endif | |
| 4754 #ifndef WITH_LEAN | |
| 4755 #ifndef WIN32 | |
| 4756 int len = SOAP_BUFLEN; | |
| 4757 #else | |
| 4758 int len = SOAP_BUFLEN + 1; /* speeds up windows xfer */ | |
| 4759 #endif | |
| 4760 int set = 1; | |
| 4761 #endif | |
| 4762 if (soap_valid_socket(soap->master)) | |
| 4763 { soap->fclosesocket(soap, soap->master); | |
| 4764 soap->master = SOAP_INVALID_SOCKET; | |
| 4765 } | |
| 4766 soap->socket = SOAP_INVALID_SOCKET; | |
| 4767 soap->errmode = 1; | |
| 4768 if (tcp_init(soap)) | |
| 4769 { soap_set_receiver_error(soap, tcp_error(soap), "TCP init failed in soap_bind()", SOAP_TCP_ERROR); | |
| 4770 return SOAP_INVALID_SOCKET; | |
| 4771 } | |
| 4772 #ifdef WITH_IPV6 | |
| 4773 memset((void*)&hints, 0, sizeof(hints)); | |
| 4774 hints.ai_family = PF_UNSPEC; | |
| 4775 #ifndef WITH_LEAN | |
| 4776 if ((soap->omode & SOAP_IO_UDP)) | |
| 4777 hints.ai_socktype = SOCK_DGRAM; | |
| 4778 else | |
| 4779 #endif | |
| 4780 hints.ai_socktype = SOCK_STREAM; | |
| 4781 hints.ai_flags = AI_PASSIVE; | |
| 4782 soap->errmode = 2; | |
| 4783 err = getaddrinfo(host, soap_int2s(soap, port), &hints, &addrinfo); | |
| 4784 if (err || !addrinfo) | |
| 4785 { soap_set_receiver_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in soap_bind()", SOAP_TCP_ERROR); | |
| 4786 return SOAP_INVALID_SOCKET; | |
| 4787 } | |
| 4788 res = *addrinfo; | |
| 4789 memcpy(&soap->peer, addrinfo->ai_addr, addrinfo->ai_addrlen); | |
| 4790 soap->peerlen = addrinfo->ai_addrlen; | |
| 4791 res.ai_addr = (struct sockaddr*)&soap->peer; | |
| 4792 res.ai_addrlen = soap->peerlen; | |
| 4793 freeaddrinfo(addrinfo); | |
| 4794 soap->master = (int)socket(res.ai_family, res.ai_socktype, res.ai_protocol); | |
| 4795 #else | |
| 4796 #ifndef WITH_LEAN | |
| 4797 if ((soap->omode & SOAP_IO_UDP)) | |
| 4798 soap->master = (int)socket(AF_INET, SOCK_DGRAM, 0); | |
| 4799 else | |
| 4800 #endif | |
| 4801 soap->master = (int)socket(AF_INET, SOCK_STREAM, 0); | |
| 4802 #endif | |
| 4803 soap->errmode = 0; | |
| 4804 if (!soap_valid_socket(soap->master)) | |
| 4805 { soap->errnum = soap_socket_errno(soap->master); | |
| 4806 soap_set_receiver_error(soap, tcp_error(soap), "socket failed in soap_bind()", SOAP_TCP_ERROR); | |
| 4807 return SOAP_INVALID_SOCKET; | |
| 4808 } | |
| 4809 soap->port = port; | |
| 4810 #ifndef WITH_LEAN | |
| 4811 if ((soap->omode & SOAP_IO_UDP)) | |
| 4812 soap->socket = soap->master; | |
| 4813 #endif | |
| 4814 #ifdef SOCKET_CLOSE_ON_EXEC | |
| 4815 #ifdef WIN32 | |
| 4816 #ifndef UNDER_CE | |
| 4817 SetHandleInformation((HANDLE)soap->master, HANDLE_FLAG_INHERIT, 0); | |
| 4818 #endif | |
| 4819 #else | |
| 4820 fcntl(soap->master, F_SETFD, 1); | |
| 4821 #endif | |
| 4822 #endif | |
| 4823 #ifndef WITH_LEAN | |
| 4824 if (soap->bind_flags && setsockopt(soap->master, SOL_SOCKET, soap->bind_flags, (char*)&set, sizeof(int))) | |
| 4825 { soap->errnum = soap_socket_errno(soap->master); | |
| 4826 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_bind()", SOAP_TCP_ERROR); | |
| 4827 return SOAP_INVALID_SOCKET; | |
| 4828 } | |
| 4829 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))) | |
| 4830 { soap->errnum = soap_socket_errno(soap->master); | |
| 4831 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_bind()", SOAP_TCP_ERROR); | |
| 4832 return SOAP_INVALID_SOCKET; | |
| 4833 } | |
| 4834 if (setsockopt(soap->master, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) | |
| 4835 { soap->errnum = soap_socket_errno(soap->master); | |
| 4836 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_bind()", SOAP_TCP_ERROR); | |
| 4837 return SOAP_INVALID_SOCKET; | |
| 4838 } | |
| 4839 if (setsockopt(soap->master, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) | |
| 4840 { soap->errnum = soap_socket_errno(soap->master); | |
| 4841 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_bind()", SOAP_TCP_ERROR); | |
| 4842 return SOAP_INVALID_SOCKET; | |
| 4843 } | |
| 4844 #ifdef TCP_NODELAY | |
| 4845 if (!(soap->omode & SOAP_IO_UDP) && setsockopt(soap->master, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) | |
| 4846 { soap->errnum = soap_socket_errno(soap->master); | |
| 4847 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_bind()", SOAP_TCP_ERROR); | |
| 4848 return SOAP_INVALID_SOCKET; | |
| 4849 } | |
| 4850 #endif | |
| 4851 #endif | |
| 4852 #ifdef WITH_IPV6 | |
| 4853 #ifdef WITH_IPV6_V6ONLY | |
| 4854 if (setsockopt(soap->master, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&set, sizeof(int))) | |
| 4855 { soap->errnum = soap_socket_errno(soap->master); | |
| 4856 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt set IPV6_V6ONLY failed in soap_bind()", SOAP_TCP_ERROR); | |
| 4857 return SOAP_INVALID_SOCKET; | |
| 4858 } | |
| 4859 #endif | |
| 4860 #ifdef WITH_NO_IPV6_V6ONLY | |
| 4861 if (setsockopt(soap->master, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&unset, sizeof(int))) | |
| 4862 { soap->errnum = soap_socket_errno(soap->master); | |
| 4863 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt unset IPV6_V6ONLY failed in soap_bind()", SOAP_TCP_ERROR); | |
| 4864 return SOAP_INVALID_SOCKET; | |
| 4865 } | |
| 4866 #endif | |
| 4867 soap->errmode = 0; | |
| 4868 if (bind(soap->master, res.ai_addr, (int)res.ai_addrlen)) | |
| 4869 { soap->errnum = soap_socket_errno(soap->master); | |
| 4870 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n")); | |
| 4871 soap_closesock(soap); | |
| 4872 soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR); | |
| 4873 return SOAP_INVALID_SOCKET; | |
| 4874 } | |
| 4875 #else | |
| 4876 soap->peerlen = sizeof(soap->peer); | |
| 4877 memset((void*)&soap->peer, 0, sizeof(soap->peer)); | |
| 4878 soap->peer.sin_family = AF_INET; | |
| 4879 soap->errmode = 2; | |
| 4880 if (host) | |
| 4881 { if (soap->fresolve(soap, host, &soap->peer.sin_addr)) | |
| 4882 { soap_set_receiver_error(soap, tcp_error(soap), "get host by name failed in soap_bind()", SOAP_TCP_ERROR); | |
| 4883 return SOAP_INVALID_SOCKET; | |
| 4884 } | |
| 4885 } | |
| 4886 else | |
| 4887 soap->peer.sin_addr.s_addr = htonl(INADDR_ANY); | |
| 4888 soap->peer.sin_port = htons((short)port); | |
| 4889 soap->errmode = 0; | |
| 4890 if (bind(soap->master, (struct sockaddr*)&soap->peer, (int)soap->peerlen)) | |
| 4891 { soap->errnum = soap_socket_errno(soap->master); | |
| 4892 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n")); | |
| 4893 soap_closesock(soap); | |
| 4894 soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR); | |
| 4895 return SOAP_INVALID_SOCKET; | |
| 4896 } | |
| 4897 #endif | |
| 4898 if (!(soap->omode & SOAP_IO_UDP) && listen(soap->master, backlog)) | |
| 4899 { soap->errnum = soap_socket_errno(soap->master); | |
| 4900 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n")); | |
| 4901 soap_closesock(soap); | |
| 4902 soap_set_receiver_error(soap, tcp_error(soap), "listen failed in soap_bind()", SOAP_TCP_ERROR); | |
| 4903 return SOAP_INVALID_SOCKET; | |
| 4904 } | |
| 4905 return soap->master; | |
| 4906 } | |
| 4907 #endif | |
| 4908 #endif | |
| 4909 | |
| 4910 /******************************************************************************/ | |
| 4911 #ifndef WITH_NOIO | |
| 4912 #ifndef PALM_1 | |
| 4913 SOAP_FMAC1 | |
| 4914 int | |
| 4915 SOAP_FMAC2 | |
| 4916 soap_poll(struct soap *soap) | |
| 4917 { | |
| 4918 #ifndef WITH_LEAN | |
| 4919 register int r; | |
| 4920 if (soap_valid_socket(soap->socket)) | |
| 4921 { r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_ALL, 0); | |
| 4922 if (r > 0 && (r & SOAP_TCP_SELECT_ERR)) | |
| 4923 r = -1; | |
| 4924 } | |
| 4925 else if (soap_valid_socket(soap->master)) | |
| 4926 r = tcp_select(soap, soap->master, SOAP_TCP_SELECT_SND, 0); | |
| 4927 else | |
| 4928 return SOAP_OK; /* OK when no socket! */ | |
| 4929 if (r > 0) | |
| 4930 { | |
| 4931 #ifdef WITH_OPENSSL | |
| 4932 if (soap->imode & SOAP_ENC_SSL) | |
| 4933 { | |
| 4934 if (soap_valid_socket(soap->socket) | |
| 4935 && (r & SOAP_TCP_SELECT_SND) | |
| 4936 && (!(r & SOAP_TCP_SELECT_RCV) | |
| 4937 || SSL_peek(soap->ssl, soap->tmpbuf, 1) > 0)) | |
| 4938 return SOAP_OK; | |
| 4939 } | |
| 4940 else | |
| 4941 #endif | |
| 4942 { int t; | |
| 4943 if (soap_valid_socket(soap->socket) | |
| 4944 && (r & SOAP_TCP_SELECT_SND) | |
| 4945 && (!(r & SOAP_TCP_SELECT_RCV) | |
| 4946 || recv(soap->socket, (char*)&t, 1, MSG_PEEK) > 0)) | |
| 4947 return SOAP_OK; | |
| 4948 } | |
| 4949 } | |
| 4950 else if (r < 0) | |
| 4951 { if ((soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) && soap_socket_errno(soap->master) != SOAP_EINTR) | |
| 4952 { soap_set_receiver_error(soap, tcp_error(soap), "select failed in soap_poll()", SOAP_TCP_ERROR); | |
| 4953 return soap->error = SOAP_TCP_ERROR; | |
| 4954 } | |
| 4955 } | |
| 4956 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Polling: other end down on socket=%d select=%d\n", soap->socket, r)); | |
| 4957 return SOAP_EOF; | |
| 4958 #else | |
| 4959 return SOAP_OK; | |
| 4960 #endif | |
| 4961 } | |
| 4962 #endif | |
| 4963 #endif | |
| 4964 | |
| 4965 /******************************************************************************/ | |
| 4966 #ifndef WITH_NOIO | |
| 4967 #ifndef PALM_1 | |
| 4968 SOAP_FMAC1 | |
| 4969 SOAP_SOCKET | |
| 4970 SOAP_FMAC2 | |
| 4971 soap_accept(struct soap *soap) | |
| 4972 { int n = (int)sizeof(soap->peer); | |
| 4973 register int err; | |
| 4974 #ifndef WITH_LEAN | |
| 4975 #ifndef WIN32 | |
| 4976 int len = SOAP_BUFLEN; | |
| 4977 #else | |
| 4978 int len = SOAP_BUFLEN + 1; /* speeds up windows xfer */ | |
| 4979 #endif | |
| 4980 int set = 1; | |
| 4981 #endif | |
| 4982 soap->error = SOAP_OK; | |
| 4983 memset((void*)&soap->peer, 0, sizeof(soap->peer)); | |
| 4984 soap->socket = SOAP_INVALID_SOCKET; | |
| 4985 soap->errmode = 0; | |
| 4986 soap->keep_alive = 0; | |
| 4987 if (!soap_valid_socket(soap->master)) | |
| 4988 { soap->errnum = 0; | |
| 4989 soap_set_receiver_error(soap, tcp_error(soap), "no master socket in soap_accept()", SOAP_TCP_ERROR); | |
| 4990 return SOAP_INVALID_SOCKET; | |
| 4991 } | |
| 4992 #ifndef WITH_LEAN | |
| 4993 if ((soap->omode & SOAP_IO_UDP)) | |
| 4994 return soap->socket = soap->master; | |
| 4995 #endif | |
| 4996 for (;;) | |
| 4997 { if (soap->accept_timeout || soap->send_timeout || soap->recv_timeout) | |
| 4998 { for (;;) | |
| 4999 { register int r; | |
| 5000 r = tcp_select(soap, soap->master, SOAP_TCP_SELECT_ALL, soap->accept_timeout ? soap->accept_timeout : 60); | |
| 5001 if (r > 0) | |
| 5002 break; | |
| 5003 if (!r && soap->accept_timeout) | |
| 5004 { soap_set_receiver_error(soap, "Timeout", "accept failed in soap_accept()", SOAP_TCP_ERROR); | |
| 5005 return SOAP_INVALID_SOCKET; | |
| 5006 } | |
| 5007 if (r < 0) | |
| 5008 { r = soap->errnum; | |
| 5009 if (r != SOAP_EINTR) | |
| 5010 { soap_closesock(soap); | |
| 5011 soap_set_sender_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR); | |
| 5012 return SOAP_INVALID_SOCKET; | |
| 5013 } | |
| 5014 } | |
| 5015 } | |
| 5016 } | |
| 5017 if (soap->accept_timeout) | |
| 5018 SOAP_SOCKNONBLOCK(soap->master) | |
| 5019 else | |
| 5020 SOAP_SOCKBLOCK(soap->master) | |
| 5021 soap->socket = soap->faccept(soap, soap->master, (struct sockaddr*)&soap->peer, &n); | |
| 5022 soap->peerlen = (size_t)n; | |
| 5023 if (soap_valid_socket(soap->socket)) | |
| 5024 { | |
| 5025 #ifdef WITH_IPV6 | |
| 5026 unsigned int ip1, ip2, ip3, ip4; | |
| 5027 char port[16]; | |
| 5028 getnameinfo((struct sockaddr*)&soap->peer, n, soap->host, sizeof(soap->host), port, 16, NI_NUMERICHOST | NI_NUMERICSERV); | |
| 5029 sscanf(soap->host, "%u.%u.%u.%u", &ip1, &ip2, &ip3, &ip4); | |
| 5030 soap->ip = (unsigned long)ip1 << 24 | (unsigned long)ip2 << 16 | (unsigned long)ip3 << 8 | (unsigned long)ip4; | |
| 5031 soap->port = soap_strtol(port, NULL, 10); | |
| 5032 #else | |
| 5033 soap->ip = ntohl(soap->peer.sin_addr.s_addr); | |
| 5034 #ifdef HAVE_SNPRINTF | |
| 5035 soap_snprintf(soap->host, sizeof(soap->host), "%u.%u.%u.%u", (int)(soap->ip>>24)&0xFF, (int)(soap->ip>>16)&0xFF, (int)(soap->ip>>8)&0xFF, (int)soap->ip&0xFF); | |
| 5036 #else | |
| 5037 sprintf(soap->host, "%u.%u.%u.%u", (int)(soap->ip>>24)&0xFF, (int)(soap->ip>>16)&0xFF, (int)(soap->ip>>8)&0xFF, (int)soap->ip&0xFF); | |
| 5038 #endif | |
| 5039 soap->port = (int)ntohs(soap->peer.sin_port); /* does not return port number on some systems */ | |
| 5040 #endif | |
| 5041 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket=%d at port=%d from IP='%s'\n", soap->socket, soap->port, soap->host)); | |
| 5042 #ifndef WITH_LEAN | |
| 5043 if (soap->accept_flags == SO_LINGER) | |
| 5044 { struct linger linger; | |
| 5045 memset((void*)&linger, 0, sizeof(linger)); | |
| 5046 linger.l_onoff = 1; | |
| 5047 linger.l_linger = soap->linger_time; | |
| 5048 if (setsockopt(soap->socket, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger))) | |
| 5049 { soap->errnum = soap_socket_errno(soap->socket); | |
| 5050 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in soap_accept()", SOAP_TCP_ERROR); | |
| 5051 soap_closesock(soap); | |
| 5052 return SOAP_INVALID_SOCKET; | |
| 5053 } | |
| 5054 } | |
| 5055 else if (soap->accept_flags && setsockopt(soap->socket, SOL_SOCKET, soap->accept_flags, (char*)&set, sizeof(int))) | |
| 5056 { soap->errnum = soap_socket_errno(soap->socket); | |
| 5057 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_accept()", SOAP_TCP_ERROR); | |
| 5058 soap_closesock(soap); | |
| 5059 return SOAP_INVALID_SOCKET; | |
| 5060 } | |
| 5061 if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt(soap->socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) | |
| 5062 { soap->errnum = soap_socket_errno(soap->socket); | |
| 5063 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_accept()", SOAP_TCP_ERROR); | |
| 5064 soap_closesock(soap); | |
| 5065 return SOAP_INVALID_SOCKET; | |
| 5066 } | |
| 5067 if (setsockopt(soap->socket, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) | |
| 5068 { soap->errnum = soap_socket_errno(soap->socket); | |
| 5069 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_accept()", SOAP_TCP_ERROR); | |
| 5070 soap_closesock(soap); | |
| 5071 return SOAP_INVALID_SOCKET; | |
| 5072 } | |
| 5073 if (setsockopt(soap->socket, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) | |
| 5074 { soap->errnum = soap_socket_errno(soap->socket); | |
| 5075 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_accept()", SOAP_TCP_ERROR); | |
| 5076 soap_closesock(soap); | |
| 5077 return SOAP_INVALID_SOCKET; | |
| 5078 } | |
| 5079 #ifdef TCP_NODELAY | |
| 5080 if (setsockopt(soap->socket, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) | |
| 5081 { soap->errnum = soap_socket_errno(soap->socket); | |
| 5082 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_accept()", SOAP_TCP_ERROR); | |
| 5083 soap_closesock(soap); | |
| 5084 return SOAP_INVALID_SOCKET; | |
| 5085 } | |
| 5086 #endif | |
| 5087 #endif | |
| 5088 soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0); | |
| 5089 if (soap->send_timeout || soap->recv_timeout) | |
| 5090 SOAP_SOCKNONBLOCK(soap->socket) | |
| 5091 else | |
| 5092 SOAP_SOCKBLOCK(soap->socket) | |
| 5093 return soap->socket; | |
| 5094 } | |
| 5095 err = soap_socket_errno(soap->socket); | |
| 5096 if (err != 0 && err != SOAP_EINTR && err != SOAP_EAGAIN && err != SOAP_EWOULDBLOCK) | |
| 5097 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept failed from %s\n", soap->host)); | |
| 5098 soap->errnum = err; | |
| 5099 soap_set_receiver_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR); | |
| 5100 soap_closesock(soap); | |
| 5101 return SOAP_INVALID_SOCKET; | |
| 5102 } | |
| 5103 } | |
| 5104 } | |
| 5105 #endif | |
| 5106 #endif | |
| 5107 | |
| 5108 /******************************************************************************/ | |
| 5109 #ifndef PALM_1 | |
| 5110 SOAP_FMAC1 | |
| 5111 int | |
| 5112 SOAP_FMAC2 | |
| 5113 soap_closesock(struct soap *soap) | |
| 5114 { register int status = soap->error; | |
| 5115 #ifndef WITH_LEANER | |
| 5116 if (status) /* close on error: attachment state is not to be trusted */ | |
| 5117 { soap->mime.first = NULL; | |
| 5118 soap->mime.last = NULL; | |
| 5119 soap->dime.first = NULL; | |
| 5120 soap->dime.last = NULL; | |
| 5121 } | |
| 5122 #endif | |
| 5123 if (soap->fdisconnect && (soap->error = soap->fdisconnect(soap))) | |
| 5124 return soap->error; | |
| 5125 if (status == SOAP_EOF || status == SOAP_TCP_ERROR || status == SOAP_SSL_ERROR || !soap->keep_alive) | |
| 5126 { if (soap->fclose && (soap->error = soap->fclose(soap))) | |
| 5127 return soap->error; | |
| 5128 soap->keep_alive = 0; | |
| 5129 } | |
| 5130 #ifdef WITH_ZLIB | |
| 5131 if (!(soap->mode & SOAP_MIME_POSTCHECK)) | |
| 5132 { if (soap->zlib_state == SOAP_ZLIB_DEFLATE) | |
| 5133 deflateEnd(soap->d_stream); | |
| 5134 else if (soap->zlib_state == SOAP_ZLIB_INFLATE) | |
| 5135 inflateEnd(soap->d_stream); | |
| 5136 soap->zlib_state = SOAP_ZLIB_NONE; | |
| 5137 } | |
| 5138 #endif | |
| 5139 return soap->error = status; | |
| 5140 } | |
| 5141 #endif | |
| 5142 | |
| 5143 /******************************************************************************/ | |
| 5144 #ifndef WITH_NOIO | |
| 5145 #ifndef PALM_1 | |
| 5146 SOAP_FMAC1 | |
| 5147 int | |
| 5148 SOAP_FMAC2 | |
| 5149 soap_force_closesock(struct soap *soap) | |
| 5150 { soap->keep_alive = 0; | |
| 5151 if (soap_valid_socket(soap->socket)) | |
| 5152 return soap_closesocket(soap->socket); | |
| 5153 return SOAP_OK; | |
| 5154 } | |
| 5155 #endif | |
| 5156 #endif | |
| 5157 | |
| 5158 /******************************************************************************/ | |
| 5159 #ifndef WITH_NOIO | |
| 5160 #ifndef PALM_2 | |
| 5161 SOAP_FMAC1 | |
| 5162 void | |
| 5163 SOAP_FMAC2 | |
| 5164 soap_cleanup(struct soap *soap) | |
| 5165 { soap_done(soap); | |
| 5166 #ifdef WIN32 | |
| 5167 if (!tcp_done) | |
| 5168 return; | |
| 5169 tcp_done = 0; | |
| 5170 WSACleanup(); | |
| 5171 #endif | |
| 5172 } | |
| 5173 #endif | |
| 5174 #endif | |
| 5175 | |
| 5176 /******************************************************************************/ | |
| 5177 #ifndef PALM_1 | |
| 5178 SOAP_FMAC1 | |
| 5179 void | |
| 5180 SOAP_FMAC2 | |
| 5181 soap_done(struct soap *soap) | |
| 5182 { | |
| 5183 #ifdef SOAP_DEBUG | |
| 5184 int i; | |
| 5185 #endif | |
| 5186 if (soap_check_state(soap)) | |
| 5187 return; | |
| 5188 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Done with context%s\n", soap->state == SOAP_COPY ? " copy" : "")); | |
| 5189 soap_free_temp(soap); | |
| 5190 while (soap->clist) | |
| 5191 { struct soap_clist *p = soap->clist->next; | |
| 5192 SOAP_FREE(soap, soap->clist); | |
| 5193 soap->clist = p; | |
| 5194 } | |
| 5195 if (soap->state == SOAP_INIT) | |
| 5196 soap->omode &= ~SOAP_IO_UDP; /* to force close the socket */ | |
| 5197 soap->keep_alive = 0; /* to force close the socket */ | |
| 5198 if (soap->master == soap->socket) /* do not close twice */ | |
| 5199 soap->master = SOAP_INVALID_SOCKET; | |
| 5200 soap_closesock(soap); | |
| 5201 #ifdef WITH_COOKIES | |
| 5202 soap_free_cookies(soap); | |
| 5203 #endif | |
| 5204 while (soap->plugins) | |
| 5205 { register struct soap_plugin *p = soap->plugins->next; | |
| 5206 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Removing plugin '%s'\n", soap->plugins->id)); | |
| 5207 if (soap->plugins->fcopy || soap->state == SOAP_INIT) | |
| 5208 soap->plugins->fdelete(soap, soap->plugins); | |
| 5209 SOAP_FREE(soap, soap->plugins); | |
| 5210 soap->plugins = p; | |
| 5211 } | |
| 5212 soap->fplugin = fplugin; | |
| 5213 soap->fmalloc = NULL; | |
| 5214 #ifndef WITH_NOHTTP | |
| 5215 soap->fpost = http_post; | |
| 5216 soap->fget = http_get; | |
| 5217 soap->fput = http_405; | |
| 5218 soap->fdel = http_405; | |
| 5219 soap->fopt = http_200; | |
| 5220 soap->fhead = http_200; | |
| 5221 soap->fform = NULL; | |
| 5222 soap->fposthdr = http_post_header; | |
| 5223 soap->fresponse = http_response; | |
| 5224 soap->fparse = http_parse; | |
| 5225 soap->fparsehdr = http_parse_header; | |
| 5226 #endif | |
| 5227 soap->fheader = NULL; | |
| 5228 #ifndef WITH_NOIO | |
| 5229 #ifndef WITH_IPV6 | |
| 5230 soap->fresolve = tcp_gethost; | |
| 5231 #else | |
| 5232 soap->fresolve = NULL; | |
| 5233 #endif | |
| 5234 soap->faccept = tcp_accept; | |
| 5235 soap->fopen = tcp_connect; | |
| 5236 soap->fclose = tcp_disconnect; | |
| 5237 soap->fclosesocket = tcp_closesocket; | |
| 5238 soap->fshutdownsocket = tcp_shutdownsocket; | |
| 5239 soap->fsend = fsend; | |
| 5240 soap->frecv = frecv; | |
| 5241 soap->fpoll = soap_poll; | |
| 5242 #else | |
| 5243 soap->fopen = NULL; | |
| 5244 soap->fclose = NULL; | |
| 5245 soap->fpoll = NULL; | |
| 5246 #endif | |
| 5247 #ifndef WITH_LEANER | |
| 5248 soap->feltbegin = NULL; | |
| 5249 soap->feltendin = NULL; | |
| 5250 soap->feltbegout = NULL; | |
| 5251 soap->feltendout = NULL; | |
| 5252 soap->fprepareinitsend = NULL; | |
| 5253 soap->fprepareinitrecv = NULL; | |
| 5254 soap->fpreparesend = NULL; | |
| 5255 soap->fpreparerecv = NULL; | |
| 5256 soap->fpreparefinalsend = NULL; | |
| 5257 soap->fpreparefinalrecv = NULL; | |
| 5258 soap->ffiltersend = NULL; | |
| 5259 soap->ffilterrecv = NULL; | |
| 5260 #endif | |
| 5261 soap->fseterror = NULL; | |
| 5262 soap->fignore = NULL; | |
| 5263 soap->fserveloop = NULL; | |
| 5264 #ifdef WITH_OPENSSL | |
| 5265 if (soap->session) | |
| 5266 { SSL_SESSION_free(soap->session); | |
| 5267 soap->session = NULL; | |
| 5268 } | |
| 5269 #endif | |
| 5270 if (soap->state == SOAP_INIT) | |
| 5271 { if (soap_valid_socket(soap->master)) | |
| 5272 { soap->fclosesocket(soap, soap->master); | |
| 5273 soap->master = SOAP_INVALID_SOCKET; | |
| 5274 } | |
| 5275 } | |
| 5276 #ifdef WITH_OPENSSL | |
| 5277 if (soap->ssl) | |
| 5278 { SSL_free(soap->ssl); | |
| 5279 soap->ssl = NULL; | |
| 5280 } | |
| 5281 if (soap->state == SOAP_INIT) | |
| 5282 { if (soap->ctx) | |
| 5283 { SSL_CTX_free(soap->ctx); | |
| 5284 soap->ctx = NULL; | |
| 5285 } | |
| 5286 } | |
| 5287 ERR_remove_state(0); | |
| 5288 #endif | |
| 5289 #ifdef WITH_GNUTLS | |
| 5290 if (soap->state == SOAP_INIT) | |
| 5291 { if (soap->xcred) | |
| 5292 { gnutls_certificate_free_credentials(soap->xcred); | |
| 5293 soap->xcred = NULL; | |
| 5294 } | |
| 5295 if (soap->acred) | |
| 5296 { gnutls_anon_free_client_credentials(soap->acred); | |
| 5297 soap->acred = NULL; | |
| 5298 } | |
| 5299 if (soap->cache) | |
| 5300 { gnutls_priority_deinit(soap->cache); | |
| 5301 soap->cache = NULL; | |
| 5302 } | |
| 5303 if (soap->dh_params) | |
| 5304 { gnutls_dh_params_deinit(soap->dh_params); | |
| 5305 soap->dh_params = NULL; | |
| 5306 } | |
| 5307 if (soap->rsa_params) | |
| 5308 { gnutls_rsa_params_deinit(soap->rsa_params); | |
| 5309 soap->rsa_params = NULL; | |
| 5310 } | |
| 5311 } | |
| 5312 if (soap->session) | |
| 5313 { gnutls_deinit(soap->session); | |
| 5314 soap->session = NULL; | |
| 5315 } | |
| 5316 #endif | |
| 5317 #ifdef WITH_C_LOCALE | |
| 5318 # ifdef WIN32 | |
| 5319 _free_locale(soap->c_locale); | |
| 5320 # else | |
| 5321 freelocale(soap->c_locale); | |
| 5322 # endif | |
| 5323 #endif | |
| 5324 #ifdef WITH_ZLIB | |
| 5325 if (soap->d_stream) | |
| 5326 { SOAP_FREE(soap, (void*)soap->d_stream); | |
| 5327 soap->d_stream = NULL; | |
| 5328 } | |
| 5329 if (soap->z_buf) | |
| 5330 { SOAP_FREE(soap, (void*)soap->z_buf); | |
| 5331 soap->z_buf = NULL; | |
| 5332 } | |
| 5333 #endif | |
| 5334 #ifdef SOAP_DEBUG | |
| 5335 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free logfiles\n")); | |
| 5336 for (i = 0; i < SOAP_MAXLOGS; i++) | |
| 5337 { if (soap->logfile[i]) | |
| 5338 { SOAP_FREE(soap, (void*)soap->logfile[i]); | |
| 5339 soap->logfile[i] = NULL; | |
| 5340 } | |
| 5341 soap_close_logfile(soap, i); | |
| 5342 } | |
| 5343 soap->state = SOAP_NONE; | |
| 5344 #endif | |
| 5345 #ifdef SOAP_MEM_DEBUG | |
| 5346 soap_free_mht(soap); | |
| 5347 #endif | |
| 5348 } | |
| 5349 #endif | |
| 5350 | |
| 5351 /******************************************************************************\ | |
| 5352 * | |
| 5353 * HTTP | |
| 5354 * | |
| 5355 \******************************************************************************/ | |
| 5356 | |
| 5357 /******************************************************************************/ | |
| 5358 #ifndef WITH_NOHTTP | |
| 5359 #ifndef PALM_1 | |
| 5360 static int | |
| 5361 http_parse(struct soap *soap) | |
| 5362 { char header[SOAP_HDRLEN], *s; | |
| 5363 unsigned short httpcmd = 0; | |
| 5364 int status = 0; | |
| 5365 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Waiting for HTTP request/response...\n")); | |
| 5366 *soap->endpoint = '\0'; | |
| 5367 #ifdef WITH_NTLM | |
| 5368 if (!soap->ntlm_challenge) | |
| 5369 #endif | |
| 5370 { soap->userid = NULL; | |
| 5371 soap->passwd = NULL; | |
| 5372 soap->authrealm = NULL; | |
| 5373 } | |
| 5374 #ifdef WITH_NTLM | |
| 5375 soap->ntlm_challenge = NULL; | |
| 5376 #endif | |
| 5377 soap->proxy_from = NULL; | |
| 5378 do | |
| 5379 { soap->length = 0; | |
| 5380 soap->http_content = NULL; | |
| 5381 soap->action = NULL; | |
| 5382 soap->status = 0; | |
| 5383 soap->body = 1; | |
| 5384 if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) | |
| 5385 { if (soap->error == SOAP_EOF) | |
| 5386 return SOAP_EOF; | |
| 5387 return soap->error = 414; | |
| 5388 } | |
| 5389 if ((s = strchr(soap->msgbuf, ' '))) | |
| 5390 { soap->status = (unsigned short)soap_strtoul(s, &s, 10); | |
| 5391 if (!soap_blank((soap_wchar)*s)) | |
| 5392 soap->status = 0; | |
| 5393 } | |
| 5394 else | |
| 5395 soap->status = 0; | |
| 5396 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP status: %s\n", soap->msgbuf)); | |
| 5397 for (;;) | |
| 5398 { if (soap_getline(soap, header, SOAP_HDRLEN)) | |
| 5399 { if (soap->error == SOAP_EOF) | |
| 5400 { soap->error = SOAP_OK; | |
| 5401 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "EOF in HTTP header, continue anyway\n")); | |
| 5402 break; | |
| 5403 } | |
| 5404 return soap->error; | |
| 5405 } | |
| 5406 if (!*header) | |
| 5407 break; | |
| 5408 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP header: %s\n", header)); | |
| 5409 s = strchr(header, ':'); | |
| 5410 if (s) | |
| 5411 { char *t; | |
| 5412 *s = '\0'; | |
| 5413 do s++; | |
| 5414 while (*s && *s <= 32); | |
| 5415 if (*s == '"') | |
| 5416 s++; | |
| 5417 t = s + strlen(s) - 1; | |
| 5418 while (t > s && *t <= 32) | |
| 5419 t--; | |
| 5420 if (t >= s && *t == '"') | |
| 5421 t--; | |
| 5422 t[1] = '\0'; | |
| 5423 if ((soap->error = soap->fparsehdr(soap, header, s))) | |
| 5424 { if (soap->error < SOAP_STOP) | |
| 5425 return soap->error; | |
| 5426 status = soap->error; | |
| 5427 soap->error = SOAP_OK; | |
| 5428 } | |
| 5429 } | |
| 5430 } | |
| 5431 } while (soap->status == 100); | |
| 5432 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Finished HTTP header parsing, status = %d\n", soap->status)); | |
| 5433 s = strstr(soap->msgbuf, "HTTP/"); | |
| 5434 if (s && s[7] != '1') | |
| 5435 { if (soap->keep_alive == 1) | |
| 5436 soap->keep_alive = 0; | |
| 5437 if (soap->status == 0 && (soap->omode & SOAP_IO) == SOAP_IO_CHUNK) /* soap->status == 0 for HTTP request */ | |
| 5438 soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE; /* HTTP 1.0 does not support chunked transfers */ | |
| 5439 } | |
| 5440 if (soap->keep_alive < 0) | |
| 5441 soap->keep_alive = 1; | |
| 5442 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Keep alive connection = %d\n", soap->keep_alive)); | |
| 5443 if (soap->status == 0) | |
| 5444 { size_t l = 0; | |
| 5445 if (s) | |
| 5446 { if (!strncmp(soap->msgbuf, "POST ", l = 5)) | |
| 5447 httpcmd = 1; | |
| 5448 else if (!strncmp(soap->msgbuf, "PUT ", l = 4)) | |
| 5449 httpcmd = 2; | |
| 5450 else if (!strncmp(soap->msgbuf, "GET ", l = 4)) | |
| 5451 httpcmd = 3; | |
| 5452 else if (!strncmp(soap->msgbuf, "DELETE ", l = 7)) | |
| 5453 httpcmd = 4; | |
| 5454 else if (!strncmp(soap->msgbuf, "OPTIONS ", l = 8)) | |
| 5455 httpcmd = 5; | |
| 5456 else if (!strncmp(soap->msgbuf, "HEAD ", l = 5)) | |
| 5457 httpcmd = 6; | |
| 5458 } | |
| 5459 if (s && httpcmd) | |
| 5460 { size_t m = strlen(soap->endpoint); | |
| 5461 size_t n = m + (s - soap->msgbuf) - l - 1; | |
| 5462 size_t k; | |
| 5463 if (n >= sizeof(soap->endpoint)) | |
| 5464 n = sizeof(soap->endpoint) - 1; | |
| 5465 if (m > n) | |
| 5466 m = n; | |
| 5467 k = n - m + 1; | |
| 5468 if (k > sizeof(soap->path)) | |
| 5469 k = sizeof(soap->path); | |
| 5470 strncpy(soap->path, soap->msgbuf + l, k); | |
| 5471 soap->path[k - 1] = '\0'; | |
| 5472 if (*soap->path && *soap->path != '/') | |
| 5473 *soap->endpoint = '\0'; | |
| 5474 strcat(soap->endpoint, soap->path); | |
| 5475 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Target endpoint='%s'\n", soap->endpoint)); | |
| 5476 if (httpcmd > 1) | |
| 5477 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP %s handler\n", soap->msgbuf)); | |
| 5478 switch (httpcmd) | |
| 5479 { case 2: soap->error = soap->fput(soap); break; | |
| 5480 case 3: soap->error = soap->fget(soap); break; | |
| 5481 case 4: soap->error = soap->fdel(soap); break; | |
| 5482 case 5: soap->error = soap->fopt(soap); break; | |
| 5483 case 6: soap->error = soap->fhead(soap); break; | |
| 5484 default: soap->error = 405; break; | |
| 5485 } | |
| 5486 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP handler return = %d\n", soap->error)); | |
| 5487 if (soap->error == SOAP_OK) | |
| 5488 soap->error = SOAP_STOP; /* prevents further processing */ | |
| 5489 return soap->error; | |
| 5490 } | |
| 5491 if (status) | |
| 5492 return soap->error = status; | |
| 5493 } | |
| 5494 else if (status) | |
| 5495 return soap->error = status; | |
| 5496 else if (s) | |
| 5497 return soap->error = 405; | |
| 5498 return SOAP_OK; | |
| 5499 } | |
| 5500 #if 0 | |
| 5501 if (soap->length > 0 || (soap->http_content && (!soap->keep_alive || soap->recv_timeout)) || (soap->imode & SOAP_IO) == SOAP_IO_CHUNK) | |
| 5502 #endif | |
| 5503 if (soap->body) | |
| 5504 { if ((soap->status >= 200 && soap->status <= 299) /* OK, Accepted, etc */ | |
| 5505 || soap->status == 400 /* Bad Request */ | |
| 5506 || soap->status == 500) /* Internal Server Error */ | |
| 5507 return SOAP_OK; | |
| 5508 /* force close afterwards in soap_closesock() */ | |
| 5509 soap->keep_alive = 0; | |
| 5510 #ifndef WITH_LEAN | |
| 5511 /* read HTTP body for error details */ | |
| 5512 s = soap_get_http_body(soap, NULL); | |
| 5513 if (s) | |
| 5514 return soap_set_receiver_error(soap, soap->msgbuf, s, soap->status); | |
| 5515 #endif | |
| 5516 } | |
| 5517 else if (soap->status >= 200 && soap->status <= 299) | |
| 5518 return soap->error = soap->status; | |
| 5519 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP error %d\n", soap->status)); | |
| 5520 return soap_set_receiver_error(soap, "HTTP Error", soap->msgbuf, soap->status); | |
| 5521 } | |
| 5522 #endif | |
| 5523 #endif | |
| 5524 | |
| 5525 /******************************************************************************/ | |
| 5526 #ifndef WITH_NOHTTP | |
| 5527 #ifndef PALM_1 | |
| 5528 static int | |
| 5529 http_parse_header(struct soap *soap, const char *key, const char *val) | |
| 5530 { if (!soap_tag_cmp(key, "Host")) | |
| 5531 { | |
| 5532 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) | |
| 5533 if (soap->imode & SOAP_ENC_SSL) | |
| 5534 strcpy(soap->endpoint, "https://"); | |
| 5535 else | |
| 5536 #endif | |
| 5537 strcpy(soap->endpoint, "http://"); | |
| 5538 strncat(soap->endpoint, val, sizeof(soap->endpoint) - 8); | |
| 5539 } | |
| 5540 #ifndef WITH_LEANER | |
| 5541 else if (!soap_tag_cmp(key, "Content-Type")) | |
| 5542 { const char *action; | |
| 5543 soap->http_content = soap_strdup(soap, val); | |
| 5544 if (soap_get_header_attribute(soap, val, "application/dime")) | |
| 5545 soap->imode |= SOAP_ENC_DIME; | |
| 5546 else if (soap_get_header_attribute(soap, val, "multipart/related") | |
| 5547 || soap_get_header_attribute(soap, val, "multipart/form-data")) | |
| 5548 { soap->mime.boundary = soap_strdup(soap, soap_get_header_attribute(soap, val, "boundary")); | |
| 5549 soap->mime.start = soap_strdup(soap, soap_get_header_attribute(soap, val, "start")); | |
| 5550 soap->imode |= SOAP_ENC_MIME; | |
| 5551 } | |
| 5552 action = soap_get_header_attribute(soap, val, "action"); | |
| 5553 if (action) | |
| 5554 { if (*action == '"') | |
| 5555 { soap->action = soap_strdup(soap, action + 1); | |
| 5556 if (*soap->action) | |
| 5557 soap->action[strlen(soap->action) - 1] = '\0'; | |
| 5558 } | |
| 5559 else | |
| 5560 soap->action = soap_strdup(soap, action); | |
| 5561 } | |
| 5562 } | |
| 5563 #endif | |
| 5564 else if (!soap_tag_cmp(key, "Content-Length")) | |
| 5565 { soap->length = soap_strtoul(val, NULL, 10); | |
| 5566 if (!soap->length) | |
| 5567 soap->body = 0; | |
| 5568 } | |
| 5569 else if (!soap_tag_cmp(key, "Content-Encoding")) | |
| 5570 { if (!soap_tag_cmp(val, "deflate")) | |
| 5571 #ifdef WITH_ZLIB | |
| 5572 soap->zlib_in = SOAP_ZLIB_DEFLATE; | |
| 5573 #else | |
| 5574 return SOAP_ZLIB_ERROR; | |
| 5575 #endif | |
| 5576 else if (!soap_tag_cmp(val, "gzip")) | |
| 5577 #ifdef WITH_GZIP | |
| 5578 soap->zlib_in = SOAP_ZLIB_GZIP; | |
| 5579 #else | |
| 5580 return SOAP_ZLIB_ERROR; | |
| 5581 #endif | |
| 5582 } | |
| 5583 #ifdef WITH_ZLIB | |
| 5584 else if (!soap_tag_cmp(key, "Accept-Encoding")) | |
| 5585 { | |
| 5586 #ifdef WITH_GZIP | |
| 5587 if (strchr(val, '*') || soap_get_header_attribute(soap, val, "gzip")) | |
| 5588 soap->zlib_out = SOAP_ZLIB_GZIP; | |
| 5589 else | |
| 5590 #endif | |
| 5591 if (strchr(val, '*') || soap_get_header_attribute(soap, val, "deflate")) | |
| 5592 soap->zlib_out = SOAP_ZLIB_DEFLATE; | |
| 5593 else | |
| 5594 soap->zlib_out = SOAP_ZLIB_NONE; | |
| 5595 } | |
| 5596 #endif | |
| 5597 else if (!soap_tag_cmp(key, "Transfer-Encoding")) | |
| 5598 { soap->imode &= ~SOAP_IO; | |
| 5599 if (!soap_tag_cmp(val, "chunked")) | |
| 5600 soap->imode |= SOAP_IO_CHUNK; | |
| 5601 } | |
| 5602 else if (!soap_tag_cmp(key, "Connection")) | |
| 5603 { if (!soap_tag_cmp(val, "keep-alive")) | |
| 5604 soap->keep_alive = -soap->keep_alive; | |
| 5605 else if (!soap_tag_cmp(val, "close")) | |
| 5606 soap->keep_alive = 0; | |
| 5607 } | |
| 5608 #ifndef WITH_LEAN | |
| 5609 else if (!soap_tag_cmp(key, "Authorization") || !soap_tag_cmp(key, "Proxy-Authorization")) | |
| 5610 { | |
| 5611 #ifdef WITH_NTLM | |
| 5612 if (!soap_tag_cmp(val, "NTLM*")) | |
| 5613 soap->ntlm_challenge = soap_strdup(soap, val + 4); | |
| 5614 else | |
| 5615 #endif | |
| 5616 if (!soap_tag_cmp(val, "Basic *")) | |
| 5617 { int n; | |
| 5618 char *s; | |
| 5619 soap_base642s(soap, val + 6, soap->tmpbuf, sizeof(soap->tmpbuf) - 1, &n); | |
| 5620 soap->tmpbuf[n] = '\0'; | |
| 5621 if ((s = strchr(soap->tmpbuf, ':'))) | |
| 5622 { *s = '\0'; | |
| 5623 soap->userid = soap_strdup(soap, soap->tmpbuf); | |
| 5624 soap->passwd = soap_strdup(soap, s + 1); | |
| 5625 } | |
| 5626 } | |
| 5627 } | |
| 5628 else if (!soap_tag_cmp(key, "WWW-Authenticate") || !soap_tag_cmp(key, "Proxy-Authenticate")) | |
| 5629 { | |
| 5630 #ifdef WITH_NTLM | |
| 5631 if (!soap_tag_cmp(val, "NTLM*")) | |
| 5632 soap->ntlm_challenge = soap_strdup(soap, val + 4); | |
| 5633 else | |
| 5634 #endif | |
| 5635 soap->authrealm = soap_strdup(soap, soap_get_header_attribute(soap, val + 6, "realm")); | |
| 5636 } | |
| 5637 else if (!soap_tag_cmp(key, "Expect")) | |
| 5638 { if (!soap_tag_cmp(val, "100-continue")) | |
| 5639 { if ((soap->error = soap->fposthdr(soap, "HTTP/1.1 100 Continue", NULL)) | |
| 5640 || (soap->error = soap->fposthdr(soap, NULL, NULL))) | |
| 5641 return soap->error; | |
| 5642 } | |
| 5643 } | |
| 5644 #endif | |
| 5645 else if (!soap_tag_cmp(key, "SOAPAction")) | |
| 5646 { if (*val == '"') | |
| 5647 { soap->action = soap_strdup(soap, val + 1); | |
| 5648 if (*soap->action) | |
| 5649 soap->action[strlen(soap->action) - 1] = '\0'; | |
| 5650 } | |
| 5651 else | |
| 5652 soap->action = soap_strdup(soap, val); | |
| 5653 } | |
| 5654 else if (!soap_tag_cmp(key, "Location")) | |
| 5655 { strncpy(soap->endpoint, val, sizeof(soap->endpoint)); | |
| 5656 soap->endpoint[sizeof(soap->endpoint) - 1] = '\0'; | |
| 5657 } | |
| 5658 else if (!soap_tag_cmp(key, "X-Forwarded-For")) | |
| 5659 { soap->proxy_from = soap_strdup(soap, val); | |
| 5660 } | |
| 5661 #ifdef WITH_COOKIES | |
| 5662 else if (!soap_tag_cmp(key, "Cookie") | |
| 5663 || !soap_tag_cmp(key, "Cookie2") | |
| 5664 || !soap_tag_cmp(key, "Set-Cookie") | |
| 5665 || !soap_tag_cmp(key, "Set-Cookie2")) | |
| 5666 { soap_getcookies(soap, val); | |
| 5667 } | |
| 5668 #endif | |
| 5669 return SOAP_OK; | |
| 5670 } | |
| 5671 #endif | |
| 5672 #endif | |
| 5673 | |
| 5674 /******************************************************************************/ | |
| 5675 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) | |
| 5676 #ifndef PALM_1 | |
| 5677 SOAP_FMAC1 | |
| 5678 const char* | |
| 5679 SOAP_FMAC2 | |
| 5680 soap_get_header_attribute(struct soap *soap, const char *line, const char *key) | |
| 5681 { register const char *s = line; | |
| 5682 if (s) | |
| 5683 { while (*s) | |
| 5684 { register short flag; | |
| 5685 s = soap_decode_key(soap->tmpbuf, sizeof(soap->tmpbuf), s); | |
| 5686 flag = soap_tag_cmp(soap->tmpbuf, key); | |
| 5687 s = soap_decode_val(soap->tmpbuf, sizeof(soap->tmpbuf), s); | |
| 5688 if (!flag) | |
| 5689 return soap->tmpbuf; | |
| 5690 } | |
| 5691 } | |
| 5692 return NULL; | |
| 5693 } | |
| 5694 #endif | |
| 5695 #endif | |
| 5696 | |
| 5697 /******************************************************************************/ | |
| 5698 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) | |
| 5699 #ifndef PALM_1 | |
| 5700 SOAP_FMAC1 | |
| 5701 const char* | |
| 5702 SOAP_FMAC2 | |
| 5703 soap_decode_key(char *buf, size_t len, const char *val) | |
| 5704 { return soap_decode(buf, len, val, "=,;"); | |
| 5705 } | |
| 5706 #endif | |
| 5707 #endif | |
| 5708 | |
| 5709 /******************************************************************************/ | |
| 5710 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) | |
| 5711 #ifndef PALM_1 | |
| 5712 SOAP_FMAC1 | |
| 5713 const char* | |
| 5714 SOAP_FMAC2 | |
| 5715 soap_decode_val(char *buf, size_t len, const char *val) | |
| 5716 { if (*val != '=') | |
| 5717 { *buf = '\0'; | |
| 5718 return val; | |
| 5719 } | |
| 5720 return soap_decode(buf, len, val + 1, ",;"); | |
| 5721 } | |
| 5722 #endif | |
| 5723 #endif | |
| 5724 | |
| 5725 /******************************************************************************/ | |
| 5726 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) | |
| 5727 #ifndef PALM_1 | |
| 5728 static const char* | |
| 5729 soap_decode(char *buf, size_t len, const char *val, const char *sep) | |
| 5730 { const char *s; | |
| 5731 char *t = buf; | |
| 5732 size_t i = len; | |
| 5733 for (s = val; *s; s++) | |
| 5734 if (*s != ' ' && *s != '\t' && !strchr(sep, *s)) | |
| 5735 break; | |
| 5736 if (len > 0) | |
| 5737 { if (*s == '"') | |
| 5738 { s++; | |
| 5739 while (*s && *s != '"' && --i) | |
| 5740 *t++ = *s++; | |
| 5741 } | |
| 5742 else | |
| 5743 { while (*s && !soap_blank((soap_wchar)*s) && !strchr(sep, *s) && --i) | |
| 5744 { if (*s == '%' && s[1] && s[2]) | |
| 5745 { *t++ = ((s[1] >= 'A' ? (s[1] & 0x7) + 9 : s[1] - '0') << 4) | |
| 5746 + (s[2] >= 'A' ? (s[2] & 0x7) + 9 : s[2] - '0'); | |
| 5747 s += 3; | |
| 5748 } | |
| 5749 else | |
| 5750 *t++ = *s++; | |
| 5751 } | |
| 5752 } | |
| 5753 buf[len - 1] = '\0'; /* appease */ | |
| 5754 } | |
| 5755 *t = '\0'; | |
| 5756 while (*s && !strchr(sep, *s)) | |
| 5757 s++; | |
| 5758 return s; | |
| 5759 } | |
| 5760 #endif | |
| 5761 #endif | |
| 5762 | |
| 5763 /******************************************************************************/ | |
| 5764 #ifndef WITH_NOHTTP | |
| 5765 #ifndef PALM_1 | |
| 5766 static const char* | |
| 5767 http_error(struct soap *soap, int status) | |
| 5768 { register const char *msg = SOAP_STR_EOS; | |
| 5769 (void)soap; | |
| 5770 #ifndef WITH_LEAN | |
| 5771 msg = soap_code_str(h_http_error_codes, status); | |
| 5772 if (!msg) | |
| 5773 msg = SOAP_STR_EOS; | |
| 5774 #endif | |
| 5775 return msg; | |
| 5776 } | |
| 5777 #endif | |
| 5778 #endif | |
| 5779 | |
| 5780 /******************************************************************************/ | |
| 5781 | |
| 5782 #ifndef WITH_NOHTTP | |
| 5783 #ifndef PALM_1 | |
| 5784 static int | |
| 5785 http_get(struct soap *soap) | |
| 5786 { (void)soap; | |
| 5787 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "HTTP GET request\n")); | |
| 5788 return SOAP_GET_METHOD; | |
| 5789 } | |
| 5790 #endif | |
| 5791 #endif | |
| 5792 | |
| 5793 /******************************************************************************/ | |
| 5794 #ifndef WITH_NOHTTP | |
| 5795 #ifndef PALM_1 | |
| 5796 static int | |
| 5797 http_405(struct soap *soap) | |
| 5798 { (void)soap; | |
| 5799 return 405; | |
| 5800 } | |
| 5801 #endif | |
| 5802 #endif | |
| 5803 | |
| 5804 /******************************************************************************/ | |
| 5805 #ifndef WITH_NOHTTP | |
| 5806 #ifndef PALM_1 | |
| 5807 static int | |
| 5808 http_200(struct soap *soap) | |
| 5809 { return soap_send_empty_response(soap, 200); | |
| 5810 } | |
| 5811 #endif | |
| 5812 #endif | |
| 5813 | |
| 5814 /******************************************************************************/ | |
| 5815 #ifndef WITH_NOHTTP | |
| 5816 #ifndef PALM_1 | |
| 5817 static int | |
| 5818 http_post(struct soap *soap, const char *endpoint, const char *host, int port, const char *path, const char *action, size_t count) | |
| 5819 { register const char *s; | |
| 5820 register int err; | |
| 5821 switch (soap->status) | |
| 5822 { case SOAP_GET: | |
| 5823 s = "GET"; | |
| 5824 break; | |
| 5825 case SOAP_PUT: | |
| 5826 s = "PUT"; | |
| 5827 break; | |
| 5828 case SOAP_DEL: | |
| 5829 s = "DELETE"; | |
| 5830 break; | |
| 5831 case SOAP_CONNECT: | |
| 5832 s = "CONNECT"; | |
| 5833 break; | |
| 5834 default: | |
| 5835 s = "POST"; | |
| 5836 } | |
| 5837 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "HTTP %s to %s\n", s, endpoint ? endpoint : "(null)")); | |
| 5838 #ifdef PALM | |
| 5839 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)) | |
| 5840 #else | |
| 5841 if (!endpoint || (soap_tag_cmp(endpoint, "http:*") && soap_tag_cmp(endpoint, "https:*") && strncmp(endpoint, "httpg:", 6))) | |
| 5842 #endif | |
| 5843 return SOAP_OK; | |
| 5844 if (strlen(endpoint) + strlen(soap->http_version) > sizeof(soap->tmpbuf) - 80 | |
| 5845 || strlen(host) + strlen(soap->http_version) > sizeof(soap->tmpbuf) - 80) | |
| 5846 return soap->error = SOAP_EOM; /* prevent overrun (note that 'host' and 'soap->host' are substrings of 'endpoint') */ | |
| 5847 if (soap->status == SOAP_CONNECT) | |
| 5848 { | |
| 5849 #ifdef HAVE_SNPRINTF | |
| 5850 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%s %s:%d HTTP/%s", s, soap->host, soap->port, soap->http_version); | |
| 5851 #else | |
| 5852 sprintf(soap->tmpbuf, "%s %s:%d HTTP/%s", s, soap->host, soap->port, soap->http_version); | |
| 5853 #endif | |
| 5854 } | |
| 5855 else if (soap->proxy_host && endpoint) | |
| 5856 { | |
| 5857 #ifdef HAVE_SNPRINTF | |
| 5858 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%s %s HTTP/%s", s, endpoint, soap->http_version); | |
| 5859 #else | |
| 5860 sprintf(soap->tmpbuf, "%s %s HTTP/%s", s, endpoint, soap->http_version); | |
| 5861 #endif | |
| 5862 } | |
| 5863 else | |
| 5864 { | |
| 5865 #ifdef HAVE_SNPRINTF | |
| 5866 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%s /%s HTTP/%s", s, (*path == '/' ? path + 1 : path), soap->http_version); | |
| 5867 #else | |
| 5868 sprintf(soap->tmpbuf, "%s /%s HTTP/%s", s, (*path == '/' ? path + 1 : path), soap->http_version); | |
| 5869 #endif | |
| 5870 } | |
| 5871 if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) | |
| 5872 return err; | |
| 5873 #ifdef WITH_OPENSSL | |
| 5874 if ((soap->ssl && port != 443) || (!soap->ssl && port != 80)) | |
| 5875 #else | |
| 5876 if (port != 80) | |
| 5877 #endif | |
| 5878 { | |
| 5879 #ifdef WITH_IPV6 | |
| 5880 if (*host != '[' && strchr(host, ':')) | |
| 5881 { | |
| 5882 #ifdef HAVE_SNPRINTF | |
| 5883 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "[%s]:%d", host, port); /* RFC 2732 */ | |
| 5884 #else | |
| 5885 sprintf(soap->tmpbuf, "[%s]:%d", host, port); /* RFC 2732 */ | |
| 5886 #endif | |
| 5887 } | |
| 5888 else | |
| 5889 #endif | |
| 5890 { | |
| 5891 #ifdef HAVE_SNPRINTF | |
| 5892 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%s:%d", host, port); | |
| 5893 #else | |
| 5894 sprintf(soap->tmpbuf, "%s:%d", host, port); | |
| 5895 #endif | |
| 5896 } | |
| 5897 } | |
| 5898 else | |
| 5899 { | |
| 5900 #ifdef WITH_IPV6 | |
| 5901 if (*host != '[' && strchr(host, ':')) | |
| 5902 { | |
| 5903 #ifdef HAVE_SNPRINTF | |
| 5904 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "[%s]", host); /* RFC 2732 */ | |
| 5905 #else | |
| 5906 sprintf(soap->tmpbuf, "[%s]", host); /* RFC 2732 */ | |
| 5907 #endif | |
| 5908 } | |
| 5909 else | |
| 5910 #endif | |
| 5911 strcpy(soap->tmpbuf, host); | |
| 5912 } | |
| 5913 if ((err = soap->fposthdr(soap, "Host", soap->tmpbuf))) | |
| 5914 return err; | |
| 5915 if ((err = soap->fposthdr(soap, "User-Agent", "gSOAP/2.8"))) | |
| 5916 return err; | |
| 5917 if ((err = soap_puthttphdr(soap, SOAP_OK, count))) | |
| 5918 return err; | |
| 5919 #ifdef WITH_ZLIB | |
| 5920 #ifdef WITH_GZIP | |
| 5921 if ((err = soap->fposthdr(soap, "Accept-Encoding", "gzip, deflate"))) | |
| 5922 #else | |
| 5923 if ((err = soap->fposthdr(soap, "Accept-Encoding", "deflate"))) | |
| 5924 #endif | |
| 5925 return err; | |
| 5926 #endif | |
| 5927 #ifndef WITH_LEAN | |
| 5928 #ifdef WITH_NTLM | |
| 5929 if (soap->ntlm_challenge && strlen(soap->ntlm_challenge) + 6 < sizeof(soap->tmpbuf)) | |
| 5930 { if (*soap->ntlm_challenge) | |
| 5931 { | |
| 5932 #ifdef HAVE_SNPRINTF | |
| 5933 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "NTLM %s", soap->ntlm_challenge); | |
| 5934 #else | |
| 5935 sprintf(soap->tmpbuf, "NTLM %s", soap->ntlm_challenge); | |
| 5936 #endif | |
| 5937 if (soap->proxy_host) | |
| 5938 { if ((err = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf))) | |
| 5939 return err; | |
| 5940 } | |
| 5941 else if ((err = soap->fposthdr(soap, "Authorization", soap->tmpbuf))) | |
| 5942 return err; | |
| 5943 } | |
| 5944 } | |
| 5945 else | |
| 5946 { | |
| 5947 #endif | |
| 5948 if (soap->userid && soap->passwd && strlen(soap->userid) + strlen(soap->passwd) < 761) | |
| 5949 { strcpy(soap->tmpbuf, "Basic "); | |
| 5950 #ifdef HAVE_SNPRINTF | |
| 5951 soap_snprintf(soap->tmpbuf + 262, sizeof(soap->tmpbuf) - 262, "%s:%s", soap->userid, soap->passwd); | |
| 5952 #else | |
| 5953 sprintf(soap->tmpbuf + 262, "%s:%s", soap->userid, soap->passwd); | |
| 5954 #endif | |
| 5955 soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262)); | |
| 5956 if ((err = soap->fposthdr(soap, "Authorization", soap->tmpbuf))) | |
| 5957 return err; | |
| 5958 } | |
| 5959 if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761) | |
| 5960 { strcpy(soap->tmpbuf, "Basic "); | |
| 5961 #ifdef HAVE_SNPRINTF | |
| 5962 soap_snprintf(soap->tmpbuf + 262, sizeof(soap->tmpbuf) - 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd); | |
| 5963 #else | |
| 5964 sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd); | |
| 5965 #endif | |
| 5966 soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262)); | |
| 5967 if ((err = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf))) | |
| 5968 return err; | |
| 5969 } | |
| 5970 #ifdef WITH_NTLM | |
| 5971 } | |
| 5972 #endif | |
| 5973 #endif | |
| 5974 #ifdef WITH_COOKIES | |
| 5975 #ifdef WITH_OPENSSL | |
| 5976 if (soap_putcookies(soap, host, path, soap->ssl != NULL)) | |
| 5977 return soap->error; | |
| 5978 #else | |
| 5979 if (soap_putcookies(soap, host, path, 0)) | |
| 5980 return soap->error; | |
| 5981 #endif | |
| 5982 #endif | |
| 5983 if (action && soap->status != SOAP_GET && soap->status != SOAP_DEL) | |
| 5984 { | |
| 5985 #ifdef HAVE_SNPRINTF | |
| 5986 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "\"%s\"", action); | |
| 5987 #else | |
| 5988 sprintf(soap->tmpbuf, "\"%s\"", strlen(action) < sizeof(soap->tmpbuf) - 3 ? action : SOAP_STR_EOS); | |
| 5989 #endif | |
| 5990 if ((err = soap->fposthdr(soap, "SOAPAction", soap->tmpbuf))) | |
| 5991 return err; | |
| 5992 } | |
| 5993 return soap->fposthdr(soap, NULL, NULL); | |
| 5994 } | |
| 5995 #endif | |
| 5996 #endif | |
| 5997 | |
| 5998 /******************************************************************************/ | |
| 5999 #ifndef WITH_NOHTTP | |
| 6000 #ifndef PALM_1 | |
| 6001 static int | |
| 6002 http_send_header(struct soap *soap, const char *s) | |
| 6003 { register const char *t; | |
| 6004 do | |
| 6005 { t = strchr(s, '\n'); /* disallow \n in HTTP headers */ | |
| 6006 if (!t) | |
| 6007 t = s + strlen(s); | |
| 6008 if (soap_send_raw(soap, s, t - s)) | |
| 6009 return soap->error; | |
| 6010 s = t + 1; | |
| 6011 } while (*t); | |
| 6012 return SOAP_OK; | |
| 6013 } | |
| 6014 #endif | |
| 6015 #endif | |
| 6016 | |
| 6017 /******************************************************************************/ | |
| 6018 #ifndef WITH_NOHTTP | |
| 6019 #ifndef PALM_1 | |
| 6020 static int | |
| 6021 http_post_header(struct soap *soap, const char *key, const char *val) | |
| 6022 { if (key) | |
| 6023 { if (http_send_header(soap, key)) | |
| 6024 return soap->error; | |
| 6025 if (val && (soap_send_raw(soap, ": ", 2) || http_send_header(soap, val))) | |
| 6026 return soap->error; | |
| 6027 } | |
| 6028 return soap_send_raw(soap, "\r\n", 2); | |
| 6029 } | |
| 6030 #endif | |
| 6031 #endif | |
| 6032 | |
| 6033 /******************************************************************************/ | |
| 6034 #ifndef WITH_NOHTTP | |
| 6035 #ifndef PALM_1 | |
| 6036 static int | |
| 6037 http_response(struct soap *soap, int status, size_t count) | |
| 6038 { register int err; | |
| 6039 char http[10]; | |
| 6040 int code = status; | |
| 6041 const char *line; | |
| 6042 #ifdef WMW_RPM_IO | |
| 6043 if (soap->rpmreqid) | |
| 6044 httpOutputEnable(soap->rpmreqid); | |
| 6045 #endif | |
| 6046 if (!soap->http_version || strlen(soap->http_version) > 4) | |
| 6047 return soap->error = SOAP_EOM; | |
| 6048 #ifdef WMW_RPM_IO | |
| 6049 if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */ | |
| 6050 #else | |
| 6051 if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application (socket) or CGI (stdin/out)? */ | |
| 6052 #endif | |
| 6053 { | |
| 6054 #ifdef HAVE_SNPRINTF | |
| 6055 soap_snprintf(http, sizeof(http), "HTTP/%s", soap->http_version); | |
| 6056 #else | |
| 6057 sprintf(http, "HTTP/%s", soap->http_version); | |
| 6058 #endif | |
| 6059 } | |
| 6060 else | |
| 6061 strcpy(http, "Status:"); | |
| 6062 if (!status || status == SOAP_HTML || status == SOAP_FILE) | |
| 6063 { if (count || ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK)) | |
| 6064 code = 200; | |
| 6065 else | |
| 6066 code = 202; | |
| 6067 } | |
| 6068 else if (status < 200 || status >= 600) | |
| 6069 { const char *s = *soap_faultcode(soap); | |
| 6070 if (status >= SOAP_GET_METHOD && status <= SOAP_HTTP_METHOD) | |
| 6071 code = 405; | |
| 6072 else if (soap->version == 2 && (!s || !strcmp(s, "SOAP-ENV:Sender"))) | |
| 6073 code = 400; | |
| 6074 else | |
| 6075 code = 500; | |
| 6076 } | |
| 6077 line = http_error(soap, code); | |
| 6078 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "HTTP Status = %d %s\n", code, line)); | |
| 6079 #ifdef HAVE_SNPRINTF | |
| 6080 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%s %d %s", http, code, line); | |
| 6081 #else | |
| 6082 sprintf(soap->tmpbuf, "%s %d %s", http, code, line); | |
| 6083 #endif | |
| 6084 if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) | |
| 6085 return err; | |
| 6086 #ifndef WITH_LEAN | |
| 6087 if (status == 401) | |
| 6088 { | |
| 6089 #ifdef HAVE_SNPRINTF | |
| 6090 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "Basic realm=\"%s\"", (soap->authrealm && strlen(soap->authrealm) < sizeof(soap->tmpbuf) - 14) ? soap->authrealm : "gSOAP Web Service"); | |
| 6091 #else | |
| 6092 sprintf(soap->tmpbuf, "Basic realm=\"%s\"", (soap->authrealm && strlen(soap->authrealm) < sizeof(soap->tmpbuf) - 14) ? soap->authrealm : "gSOAP Web Service"); | |
| 6093 #endif | |
| 6094 if ((err = soap->fposthdr(soap, "WWW-Authenticate", soap->tmpbuf))) | |
| 6095 return err; | |
| 6096 } | |
| 6097 else if ((status >= 301 && status <= 303) || status == 307) | |
| 6098 { if ((err = soap->fposthdr(soap, "Location", soap->endpoint))) | |
| 6099 return err; | |
| 6100 } | |
| 6101 #endif | |
| 6102 if ((err = soap->fposthdr(soap, "Server", "gSOAP/2.8")) | |
| 6103 || (err = soap_puthttphdr(soap, status, count))) | |
| 6104 return err; | |
| 6105 #ifdef WITH_COOKIES | |
| 6106 if (soap_putsetcookies(soap)) | |
| 6107 return soap->error; | |
| 6108 #endif | |
| 6109 return soap->fposthdr(soap, NULL, NULL); | |
| 6110 } | |
| 6111 #endif | |
| 6112 #endif | |
| 6113 | |
| 6114 /******************************************************************************/ | |
| 6115 #ifndef PALM_1 | |
| 6116 SOAP_FMAC1 | |
| 6117 int | |
| 6118 SOAP_FMAC2 | |
| 6119 soap_response(struct soap *soap, int status) | |
| 6120 { register size_t count; | |
| 6121 if (!(soap->omode & (SOAP_ENC_XML | SOAP_IO_STORE /* this tests for chunking too */)) | |
| 6122 && (status == SOAP_HTML || status == SOAP_FILE)) | |
| 6123 soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE; | |
| 6124 soap->status = status; | |
| 6125 count = soap_count_attachments(soap); | |
| 6126 if (soap_begin_send(soap)) | |
| 6127 return soap->error; | |
| 6128 #ifndef WITH_NOHTTP | |
| 6129 if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML)) | |
| 6130 { register int n = soap->mode; | |
| 6131 soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB); | |
| 6132 if ((n & SOAP_IO) != SOAP_IO_FLUSH) | |
| 6133 soap->mode |= SOAP_IO_BUFFER; | |
| 6134 if ((soap->error = soap->fresponse(soap, status, count))) | |
| 6135 return soap->error; | |
| 6136 #ifndef WITH_LEANER | |
| 6137 if ((n & SOAP_IO) == SOAP_IO_CHUNK) | |
| 6138 { if (soap_flush(soap)) | |
| 6139 return soap->error; | |
| 6140 } | |
| 6141 #endif | |
| 6142 soap->mode = n; | |
| 6143 } | |
| 6144 #endif | |
| 6145 return SOAP_OK; | |
| 6146 } | |
| 6147 #endif | |
| 6148 | |
| 6149 /******************************************************************************/ | |
| 6150 #ifndef PALM_1 | |
| 6151 SOAP_FMAC1 | |
| 6152 const char* | |
| 6153 SOAP_FMAC2 | |
| 6154 soap_url(struct soap *soap, const char *s, const char *t) | |
| 6155 { if (!t || (*t != '/' && *t != '?') || strlen(s) + strlen(t) >= sizeof(soap->msgbuf)) | |
| 6156 return s; | |
| 6157 strcpy(soap->msgbuf, s); | |
| 6158 strcat(soap->msgbuf, t); | |
| 6159 return soap->msgbuf; | |
| 6160 } | |
| 6161 #endif | |
| 6162 | |
| 6163 /******************************************************************************/ | |
| 6164 #ifndef PALM_1 | |
| 6165 SOAP_FMAC1 | |
| 6166 size_t | |
| 6167 SOAP_FMAC2 | |
| 6168 soap_encode_url(const char *s, char *t, size_t len) | |
| 6169 { register int c; | |
| 6170 register size_t n = len; | |
| 6171 while ((c = *s++) && --n > 0) | |
| 6172 { if (c > ' ' && c < 128 && !strchr("()<>@,;:\\\"/[]?={}#!$&'*+", c)) | |
| 6173 *t++ = c; | |
| 6174 else if (n > 2) | |
| 6175 { *t++ = '%'; | |
| 6176 *t++ = (c >> 4) + (c > 159 ? '7' : '0'); | |
| 6177 c &= 0xF; | |
| 6178 *t++ = c + (c > 9 ? '7' : '0'); | |
| 6179 n -= 2; | |
| 6180 } | |
| 6181 else | |
| 6182 break; | |
| 6183 } | |
| 6184 *t = '\0'; | |
| 6185 return len - n; | |
| 6186 } | |
| 6187 #endif | |
| 6188 | |
| 6189 /******************************************************************************/ | |
| 6190 #ifndef PALM_1 | |
| 6191 SOAP_FMAC1 | |
| 6192 const char* | |
| 6193 SOAP_FMAC2 | |
| 6194 soap_encode_url_string(struct soap *soap, const char *s) | |
| 6195 { if (s) | |
| 6196 { size_t n = 3*strlen(s)+1; | |
| 6197 char *t = (char*)soap_malloc(soap, n); | |
| 6198 if (t) | |
| 6199 { soap_encode_url(s, t, n); | |
| 6200 return t; | |
| 6201 } | |
| 6202 } | |
| 6203 return SOAP_STR_EOS; | |
| 6204 } | |
| 6205 #endif | |
| 6206 | |
| 6207 /******************************************************************************\ | |
| 6208 * | |
| 6209 * HTTP Cookies | |
| 6210 * | |
| 6211 \******************************************************************************/ | |
| 6212 | |
| 6213 #ifdef WITH_COOKIES | |
| 6214 /******************************************************************************/ | |
| 6215 SOAP_FMAC1 | |
| 6216 struct soap_cookie* | |
| 6217 SOAP_FMAC2 | |
| 6218 soap_cookie(struct soap *soap, const char *name, const char *domain, const char *path) | |
| 6219 { struct soap_cookie *p; | |
| 6220 if (!domain) | |
| 6221 domain = soap->cookie_domain; | |
| 6222 if (!path) | |
| 6223 path = soap->cookie_path; | |
| 6224 if (!path) | |
| 6225 path = SOAP_STR_EOS; | |
| 6226 else if (*path == '/') | |
| 6227 path++; | |
| 6228 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Search cookie='%s' domain='%s' path='%s'\n", name, domain ? domain : "(null)", path ? path : "(null)")); | |
| 6229 for (p = soap->cookies; p; p = p->next) | |
| 6230 { 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)); | |
| 6231 if (!strcmp(p->name, name) | |
| 6232 && p->domain | |
| 6233 && p->path | |
| 6234 && !strcmp(p->domain, domain) | |
| 6235 && (!*p->path || !strncmp(p->path, path, strlen(p->path)))) | |
| 6236 break; | |
| 6237 } | |
| 6238 return p; | |
| 6239 } | |
| 6240 | |
| 6241 /******************************************************************************/ | |
| 6242 SOAP_FMAC1 | |
| 6243 struct soap_cookie* | |
| 6244 SOAP_FMAC2 | |
| 6245 soap_set_cookie(struct soap *soap, const char *name, const char *value, const char *domain, const char *path) | |
| 6246 { struct soap_cookie **p, *q; | |
| 6247 int n; | |
| 6248 if (!domain) | |
| 6249 domain = soap->cookie_domain; | |
| 6250 if (!path) | |
| 6251 path = soap->cookie_path; | |
| 6252 if (!path) | |
| 6253 path = SOAP_STR_EOS; | |
| 6254 else if (*path == '/') | |
| 6255 path++; | |
| 6256 q = soap_cookie(soap, name, domain, path); | |
| 6257 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)")); | |
| 6258 if (!q) | |
| 6259 { if ((q = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie)))) | |
| 6260 { if ((q->name = (char*)SOAP_MALLOC(soap, strlen(name)+1))) | |
| 6261 strcpy(q->name, name); | |
| 6262 q->value = NULL; | |
| 6263 q->domain = NULL; | |
| 6264 q->path = NULL; | |
| 6265 q->expire = 0; | |
| 6266 q->maxage = -1; | |
| 6267 q->version = 1; | |
| 6268 q->secure = 0; | |
| 6269 q->modified = 0; | |
| 6270 for (p = &soap->cookies, n = soap->cookie_max; *p && n; p = &(*p)->next, n--) | |
| 6271 if (!strcmp((*p)->name, name) && (*p)->path && path && strcmp((*p)->path, path) < 0) | |
| 6272 break; | |
| 6273 if (n) | |
| 6274 { q->next = *p; | |
| 6275 *p = q; | |
| 6276 } | |
| 6277 else | |
| 6278 { SOAP_FREE(soap, q->name); | |
| 6279 SOAP_FREE(soap, q); | |
| 6280 q = NULL; | |
| 6281 } | |
| 6282 } | |
| 6283 } | |
| 6284 else | |
| 6285 q->modified = 1; | |
| 6286 if (q) | |
| 6287 { if (q->value) | |
| 6288 { if (!value || strcmp(value, q->value)) | |
| 6289 { SOAP_FREE(soap, q->value); | |
| 6290 q->value = NULL; | |
| 6291 } | |
| 6292 } | |
| 6293 if (value && *value && !q->value && (q->value = (char*)SOAP_MALLOC(soap, strlen(value)+1))) | |
| 6294 strcpy(q->value, value); | |
| 6295 if (q->domain) | |
| 6296 { if (!domain || strcmp(domain, q->domain)) | |
| 6297 { SOAP_FREE(soap, q->domain); | |
| 6298 q->domain = NULL; | |
| 6299 } | |
| 6300 } | |
| 6301 if (domain && !q->domain && (q->domain = (char*)SOAP_MALLOC(soap, strlen(domain)+1))) | |
| 6302 strcpy(q->domain, domain); | |
| 6303 if (q->path) | |
| 6304 { if (!path || strncmp(path, q->path, strlen(q->path))) | |
| 6305 { SOAP_FREE(soap, q->path); | |
| 6306 q->path = NULL; | |
| 6307 } | |
| 6308 } | |
| 6309 if (path && !q->path && (q->path = (char*)SOAP_MALLOC(soap, strlen(path)+1))) | |
| 6310 strcpy(q->path, path); | |
| 6311 q->session = 1; | |
| 6312 q->env = 0; | |
| 6313 } | |
| 6314 return q; | |
| 6315 } | |
| 6316 | |
| 6317 /******************************************************************************/ | |
| 6318 SOAP_FMAC1 | |
| 6319 void | |
| 6320 SOAP_FMAC2 | |
| 6321 soap_clr_cookie(struct soap *soap, const char *name, const char *domain, const char *path) | |
| 6322 { struct soap_cookie **p, *q; | |
| 6323 if (!domain) | |
| 6324 domain = soap->cookie_domain; | |
| 6325 if (!domain) | |
| 6326 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error in clear cookie='%s': cookie domain not set\n", name ? name : "(null)")); | |
| 6327 return; | |
| 6328 } | |
| 6329 if (!path) | |
| 6330 path = soap->cookie_path; | |
| 6331 if (!path) | |
| 6332 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error in clear cookie='%s': cookie path not set\n", name ? name : "(null)")); | |
| 6333 return; | |
| 6334 } | |
| 6335 if (*path == '/') | |
| 6336 path++; | |
| 6337 for (p = &soap->cookies, q = *p; q; q = *p) | |
| 6338 { if (!strcmp(q->name, name) && !strcmp(q->domain, domain) && !strncmp(q->path, path, strlen(q->path))) | |
| 6339 { if (q->value) | |
| 6340 SOAP_FREE(soap, q->value); | |
| 6341 if (q->domain) | |
| 6342 SOAP_FREE(soap, q->domain); | |
| 6343 if (q->path) | |
| 6344 SOAP_FREE(soap, q->path); | |
| 6345 *p = q->next; | |
| 6346 SOAP_FREE(soap, q); | |
| 6347 } | |
| 6348 else | |
| 6349 p = &q->next; | |
| 6350 } | |
| 6351 } | |
| 6352 | |
| 6353 /******************************************************************************/ | |
| 6354 SOAP_FMAC1 | |
| 6355 char * | |
| 6356 SOAP_FMAC2 | |
| 6357 soap_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path) | |
| 6358 { struct soap_cookie *p; | |
| 6359 if ((p = soap_cookie(soap, name, domain, path))) | |
| 6360 return p->value; | |
| 6361 return NULL; | |
| 6362 } | |
| 6363 | |
| 6364 /******************************************************************************/ | |
| 6365 SOAP_FMAC1 | |
| 6366 char * | |
| 6367 SOAP_FMAC2 | |
| 6368 soap_env_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path) | |
| 6369 { struct soap_cookie *p; | |
| 6370 if ((p = soap_cookie(soap, name, domain, path)) && p->env) | |
| 6371 return p->value; | |
| 6372 return NULL; | |
| 6373 } | |
| 6374 | |
| 6375 /******************************************************************************/ | |
| 6376 SOAP_FMAC1 | |
| 6377 time_t | |
| 6378 SOAP_FMAC2 | |
| 6379 soap_cookie_expire(struct soap *soap, const char *name, const char *domain, const char *path) | |
| 6380 { struct soap_cookie *p; | |
| 6381 if ((p = soap_cookie(soap, name, domain, path))) | |
| 6382 return p->expire; | |
| 6383 return -1; | |
| 6384 } | |
| 6385 | |
| 6386 /******************************************************************************/ | |
| 6387 SOAP_FMAC1 | |
| 6388 int | |
| 6389 SOAP_FMAC2 | |
| 6390 soap_set_cookie_expire(struct soap *soap, const char *name, long expire, const char *domain, const char *path) | |
| 6391 { struct soap_cookie *p; | |
| 6392 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set cookie expiration max-age=%ld: cookie='%s' domain='%s' path='%s'\n", expire, name, domain ? domain : "(null)", path ? path : "(null)")); | |
| 6393 if ((p = soap_cookie(soap, name, domain, path))) | |
| 6394 { p->maxage = expire; | |
| 6395 p->modified = 1; | |
| 6396 return SOAP_OK; | |
| 6397 } | |
| 6398 return SOAP_ERR; | |
| 6399 } | |
| 6400 | |
| 6401 /******************************************************************************/ | |
| 6402 SOAP_FMAC1 | |
| 6403 int | |
| 6404 SOAP_FMAC2 | |
| 6405 soap_set_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path) | |
| 6406 { struct soap_cookie *p; | |
| 6407 if ((p = soap_cookie(soap, name, domain, path))) | |
| 6408 { p->session = 1; | |
| 6409 p->modified = 1; | |
| 6410 return SOAP_OK; | |
| 6411 } | |
| 6412 return SOAP_ERR; | |
| 6413 } | |
| 6414 | |
| 6415 /******************************************************************************/ | |
| 6416 SOAP_FMAC1 | |
| 6417 int | |
| 6418 SOAP_FMAC2 | |
| 6419 soap_clr_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path) | |
| 6420 { struct soap_cookie *p; | |
| 6421 if ((p = soap_cookie(soap, name, domain, path))) | |
| 6422 { p->session = 0; | |
| 6423 p->modified = 1; | |
| 6424 return SOAP_OK; | |
| 6425 } | |
| 6426 return SOAP_ERR; | |
| 6427 } | |
| 6428 | |
| 6429 /******************************************************************************/ | |
| 6430 SOAP_FMAC1 | |
| 6431 int | |
| 6432 SOAP_FMAC2 | |
| 6433 soap_putsetcookies(struct soap *soap) | |
| 6434 { struct soap_cookie *p; | |
| 6435 char *s, tmp[4096]; | |
| 6436 const char *t; | |
| 6437 for (p = soap->cookies; p; p = p->next) | |
| 6438 { | |
| 6439 if (p->modified | |
| 6440 #ifdef WITH_OPENSSL | |
| 6441 || (!p->env && !soap->ssl == !p->secure) | |
| 6442 #endif | |
| 6443 ) | |
| 6444 { s = tmp; | |
| 6445 if (p->name) | |
| 6446 s += soap_encode_url(p->name, s, tmp-s+4064); | |
| 6447 if (p->value && *p->value) | |
| 6448 { *s++ = '='; | |
| 6449 s += soap_encode_url(p->value, s, tmp-s+4064); | |
| 6450 } | |
| 6451 if (p->domain && (int)strlen(p->domain) < tmp-s+4064) | |
| 6452 { strcpy(s, ";Domain="); | |
| 6453 strcat(s, p->domain); | |
| 6454 } | |
| 6455 else if (soap->cookie_domain && (int)strlen(soap->cookie_domain) < tmp-s+4064) | |
| 6456 { strcpy(s, ";Domain="); | |
| 6457 strcat(s, soap->cookie_domain); | |
| 6458 } | |
| 6459 strcat(s, ";Path=/"); | |
| 6460 s += strlen(s); | |
| 6461 if (p->path) | |
| 6462 t = p->path; | |
| 6463 else | |
| 6464 t = soap->cookie_path; | |
| 6465 if (t) | |
| 6466 { if (*t == '/') | |
| 6467 t++; | |
| 6468 if ((int)strlen(t) < tmp-s+4064) | |
| 6469 { if (strchr(t, '%')) /* already URL encoded? */ | |
| 6470 { strcpy(s, t); | |
| 6471 s += strlen(s); | |
| 6472 } | |
| 6473 else | |
| 6474 s += soap_encode_url(t, s, tmp-s+4064); | |
| 6475 } | |
| 6476 } | |
| 6477 if (p->version > 0 && s-tmp < 4060) | |
| 6478 { | |
| 6479 #ifdef HAVE_SNPRINTF | |
| 6480 soap_snprintf(s, 4096 - (s-tmp), ";Version=%u", p->version); | |
| 6481 #else | |
| 6482 sprintf(s, ";Version=%u", p->version); | |
| 6483 #endif | |
| 6484 s += strlen(s); | |
| 6485 } | |
| 6486 if (p->maxage >= 0 && s-tmp < 4060) | |
| 6487 { | |
| 6488 #ifdef HAVE_SNPRINTF | |
| 6489 soap_snprintf(s, 4096 - (s-tmp), ";Max-Age=%ld", p->maxage); | |
| 6490 #else | |
| 6491 sprintf(s, ";Max-Age=%ld", p->maxage); | |
| 6492 #endif | |
| 6493 s += strlen(s); | |
| 6494 } | |
| 6495 if (s-tmp < 4073 | |
| 6496 && (p->secure | |
| 6497 #ifdef WITH_OPENSSL | |
| 6498 || soap->ssl | |
| 6499 #endif | |
| 6500 )) | |
| 6501 strcpy(s, ";Secure"); | |
| 6502 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set-Cookie: %s\n", tmp)); | |
| 6503 if ((soap->error = soap->fposthdr(soap, "Set-Cookie", tmp))) | |
| 6504 return soap->error; | |
| 6505 } | |
| 6506 } | |
| 6507 return SOAP_OK; | |
| 6508 } | |
| 6509 | |
| 6510 /******************************************************************************/ | |
| 6511 SOAP_FMAC1 | |
| 6512 int | |
| 6513 SOAP_FMAC2 | |
| 6514 soap_putcookies(struct soap *soap, const char *domain, const char *path, int secure) | |
| 6515 { struct soap_cookie **p, *q; | |
| 6516 unsigned int version = 0; | |
| 6517 time_t now = time(NULL); | |
| 6518 char *s, tmp[4096]; | |
| 6519 if (!domain || !path) | |
| 6520 return SOAP_OK; | |
| 6521 s = tmp; | |
| 6522 p = &soap->cookies; | |
| 6523 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending cookies for domain='%s' path='%s'\n", domain, path)); | |
| 6524 if (*path == '/') | |
| 6525 path++; | |
| 6526 while ((q = *p)) | |
| 6527 { if (q->expire && now > q->expire) | |
| 6528 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie %s expired\n", q->name)); | |
| 6529 SOAP_FREE(soap, q->name); | |
| 6530 if (q->value) | |
| 6531 SOAP_FREE(soap, q->value); | |
| 6532 if (q->domain) | |
| 6533 SOAP_FREE(soap, q->domain); | |
| 6534 if (q->path) | |
| 6535 SOAP_FREE(soap, q->path); | |
| 6536 *p = q->next; | |
| 6537 SOAP_FREE(soap, q); | |
| 6538 } | |
| 6539 else | |
| 6540 { int flag; | |
| 6541 char *t = q->domain; | |
| 6542 size_t n = 0; | |
| 6543 if (!t) | |
| 6544 flag = 1; | |
| 6545 else | |
| 6546 { const char *r = strchr(t, ':'); | |
| 6547 if (r) | |
| 6548 n = r - t; | |
| 6549 else | |
| 6550 n = strlen(t); | |
| 6551 flag = !strncmp(t, domain, n); | |
| 6552 } | |
| 6553 /* domain-level cookies, cannot compile when WITH_NOIO set */ | |
| 6554 #ifndef WITH_NOIO | |
| 6555 if (!flag) | |
| 6556 { struct hostent *hostent = gethostbyname((char*)domain); | |
| 6557 if (hostent) | |
| 6558 { const char *r = strchr(hostent->h_name, '.'); | |
| 6559 if (!r) | |
| 6560 r = hostent->h_name; | |
| 6561 flag = !strncmp(t, r, n); | |
| 6562 } | |
| 6563 } | |
| 6564 #endif | |
| 6565 if (flag | |
| 6566 && (!q->path || !strncmp(q->path, path, strlen(q->path))) | |
| 6567 && (!q->secure || secure)) | |
| 6568 { size_t n = 12; | |
| 6569 if (q->name) | |
| 6570 n += 3*strlen(q->name); | |
| 6571 if (q->value && *q->value) | |
| 6572 n += 3*strlen(q->value) + 1; | |
| 6573 if (q->path && *q->path) | |
| 6574 n += strlen(q->path) + 9; | |
| 6575 if (q->domain) | |
| 6576 n += strlen(q->domain) + 11; | |
| 6577 if (tmp - s + n > sizeof(tmp)) | |
| 6578 { if (s == tmp) | |
| 6579 return SOAP_OK; /* HTTP header size overflow */ | |
| 6580 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie: %s\n", tmp)); | |
| 6581 if ((soap->error = soap->fposthdr(soap, "Cookie", tmp))) | |
| 6582 return soap->error; | |
| 6583 s = tmp; | |
| 6584 } | |
| 6585 else if (s != tmp) | |
| 6586 { strcat(s, " "); | |
| 6587 s++; | |
| 6588 } | |
| 6589 if (q->version != version && s-tmp < 4060) | |
| 6590 { | |
| 6591 #ifdef HAVE_SNPRINTF | |
| 6592 soap_snprintf(s, 4096 - (s-tmp), "$Version=%u;", q->version); | |
| 6593 #else | |
| 6594 sprintf(s, "$Version=%u;", q->version); | |
| 6595 #endif | |
| 6596 version = q->version; | |
| 6597 s += strlen(s); | |
| 6598 } | |
| 6599 if (q->name) | |
| 6600 s += soap_encode_url(q->name, s, tmp+sizeof(tmp)-s-16); | |
| 6601 if (q->value && *q->value) | |
| 6602 { *s++ = '='; | |
| 6603 s += soap_encode_url(q->value, s, tmp+sizeof(tmp)-s-16); | |
| 6604 } | |
| 6605 if (q->path && (s-tmp) + strlen(q->path) < 4060) | |
| 6606 { | |
| 6607 #ifdef HAVE_SNPRINTF | |
| 6608 soap_snprintf(s, 4096 - (s-tmp), ";$Path=\"/%s\"", (*q->path == '/' ? q->path + 1 : q->path)); | |
| 6609 #else | |
| 6610 sprintf(s, ";$Path=\"/%s\"", (*q->path == '/' ? q->path + 1 : q->path)); | |
| 6611 #endif | |
| 6612 s += strlen(s); | |
| 6613 } | |
| 6614 if (q->domain && (s-tmp) + strlen(q->domain) < 4060) | |
| 6615 { | |
| 6616 #ifdef HAVE_SNPRINTF | |
| 6617 soap_snprintf(s, 4096 - (s-tmp), ";$Domain=\"%s\"", q->domain); | |
| 6618 #else | |
| 6619 sprintf(s, ";$Domain=\"%s\"", q->domain); | |
| 6620 #endif | |
| 6621 s += strlen(s); | |
| 6622 } | |
| 6623 } | |
| 6624 p = &q->next; | |
| 6625 } | |
| 6626 } | |
| 6627 if (s != tmp) | |
| 6628 if ((soap->error = soap->fposthdr(soap, "Cookie", tmp))) | |
| 6629 return soap->error; | |
| 6630 return SOAP_OK; | |
| 6631 } | |
| 6632 | |
| 6633 /******************************************************************************/ | |
| 6634 SOAP_FMAC1 | |
| 6635 void | |
| 6636 SOAP_FMAC2 | |
| 6637 soap_getcookies(struct soap *soap, const char *val) | |
| 6638 { struct soap_cookie *p = NULL, *q; | |
| 6639 const char *s; | |
| 6640 char *t, tmp[4096]; /* cookie size is up to 4096 bytes [RFC2109] */ | |
| 6641 char *domain = NULL; | |
| 6642 char *path = NULL; | |
| 6643 unsigned int version = 0; | |
| 6644 time_t now = time(NULL); | |
| 6645 if (!val) | |
| 6646 return; | |
| 6647 s = val; | |
| 6648 while (*s) | |
| 6649 { s = soap_decode_key(tmp, sizeof(tmp), s); | |
| 6650 if (!soap_tag_cmp(tmp, "$Version")) | |
| 6651 { if ((s = soap_decode_val(tmp, sizeof(tmp), s))) | |
| 6652 { if (p) | |
| 6653 p->version = (int)soap_strtol(tmp, NULL, 10); | |
| 6654 else | |
| 6655 version = (int)soap_strtol(tmp, NULL, 10); | |
| 6656 } | |
| 6657 } | |
| 6658 else if (!soap_tag_cmp(tmp, "$Path")) | |
| 6659 { s = soap_decode_val(tmp, sizeof(tmp), s); | |
| 6660 if (*tmp) | |
| 6661 { if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) | |
| 6662 strcpy(t, tmp); | |
| 6663 } | |
| 6664 else | |
| 6665 t = NULL; | |
| 6666 if (p) | |
| 6667 { if (p->path) | |
| 6668 SOAP_FREE(soap, p->path); | |
| 6669 p->path = t; | |
| 6670 } | |
| 6671 else | |
| 6672 { if (path) | |
| 6673 SOAP_FREE(soap, path); | |
| 6674 path = t; | |
| 6675 } | |
| 6676 } | |
| 6677 else if (!soap_tag_cmp(tmp, "$Domain")) | |
| 6678 { s = soap_decode_val(tmp, sizeof(tmp), s); | |
| 6679 if (*tmp) | |
| 6680 { if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) | |
| 6681 strcpy(t, tmp); | |
| 6682 } | |
| 6683 else | |
| 6684 t = NULL; | |
| 6685 if (p) | |
| 6686 { if (p->domain) | |
| 6687 SOAP_FREE(soap, p->domain); | |
| 6688 p->domain = t; | |
| 6689 } | |
| 6690 else | |
| 6691 { if (domain) | |
| 6692 SOAP_FREE(soap, domain); | |
| 6693 domain = t; | |
| 6694 } | |
| 6695 } | |
| 6696 else if (p && !soap_tag_cmp(tmp, "Path")) | |
| 6697 { if (p->path) | |
| 6698 SOAP_FREE(soap, p->path); | |
| 6699 s = soap_decode_val(tmp, sizeof(tmp), s); | |
| 6700 if (*tmp) | |
| 6701 { if ((p->path = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) | |
| 6702 strcpy(p->path, tmp); | |
| 6703 } | |
| 6704 else | |
| 6705 p->path = NULL; | |
| 6706 } | |
| 6707 else if (p && !soap_tag_cmp(tmp, "Domain")) | |
| 6708 { if (p->domain) | |
| 6709 SOAP_FREE(soap, p->domain); | |
| 6710 s = soap_decode_val(tmp, sizeof(tmp), s); | |
| 6711 if (*tmp) | |
| 6712 { if ((p->domain = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) | |
| 6713 strcpy(p->domain, tmp); | |
| 6714 } | |
| 6715 else | |
| 6716 p->domain = NULL; | |
| 6717 } | |
| 6718 else if (p && !soap_tag_cmp(tmp, "Version")) | |
| 6719 { s = soap_decode_val(tmp, sizeof(tmp), s); | |
| 6720 p->version = (unsigned int)soap_strtoul(tmp, NULL, 10); | |
| 6721 } | |
| 6722 else if (p && !soap_tag_cmp(tmp, "Max-Age")) | |
| 6723 { s = soap_decode_val(tmp, sizeof(tmp), s); | |
| 6724 p->expire = now + soap_strtol(tmp, NULL, 10); | |
| 6725 } | |
| 6726 else if (p && !soap_tag_cmp(tmp, "Expires")) | |
| 6727 { struct tm T; | |
| 6728 char a[3]; | |
| 6729 static const char mns[] = "anebarprayunulugepctovec"; | |
| 6730 s = soap_decode_val(tmp, sizeof(tmp), s); | |
| 6731 if (strlen(tmp) > 20) | |
| 6732 { memset((void*)&T, 0, sizeof(T)); | |
| 6733 a[0] = tmp[4]; | |
| 6734 a[1] = tmp[5]; | |
| 6735 a[2] = '\0'; | |
| 6736 T.tm_mday = (int)soap_strtol(a, NULL, 10); | |
| 6737 a[0] = tmp[8]; | |
| 6738 a[1] = tmp[9]; | |
| 6739 T.tm_mon = (int)(strstr(mns, a) - mns) / 2; | |
| 6740 a[0] = tmp[11]; | |
| 6741 a[1] = tmp[12]; | |
| 6742 T.tm_year = 100 + (int)soap_strtol(a, NULL, 10); | |
| 6743 a[0] = tmp[13]; | |
| 6744 a[1] = tmp[14]; | |
| 6745 T.tm_hour = (int)soap_strtol(a, NULL, 10); | |
| 6746 a[0] = tmp[16]; | |
| 6747 a[1] = tmp[17]; | |
| 6748 T.tm_min = (int)soap_strtol(a, NULL, 10); | |
| 6749 a[0] = tmp[19]; | |
| 6750 a[1] = tmp[20]; | |
| 6751 T.tm_sec = (int)soap_strtol(a, NULL, 10); | |
| 6752 p->expire = soap_timegm(&T); | |
| 6753 } | |
| 6754 } | |
| 6755 else if (p && !soap_tag_cmp(tmp, "Secure")) | |
| 6756 p->secure = 1; | |
| 6757 else | |
| 6758 { if (p) | |
| 6759 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie='%s' value='%s' domain='%s' path='%s' expire=%ld secure=%d\n", p->name, p->value ? p->value : "(null)", p->domain ? p->domain : "(null)", p->path ? p->path : "(null)", p->expire, p->secure)); | |
| 6760 if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path))) | |
| 6761 { q->version = p->version; | |
| 6762 q->expire = p->expire; | |
| 6763 q->secure = p->secure; | |
| 6764 q->env = 1; | |
| 6765 } | |
| 6766 if (p->name) | |
| 6767 SOAP_FREE(soap, p->name); | |
| 6768 if (p->value) | |
| 6769 SOAP_FREE(soap, p->value); | |
| 6770 if (p->domain) | |
| 6771 SOAP_FREE(soap, p->domain); | |
| 6772 if (p->path) | |
| 6773 SOAP_FREE(soap, p->path); | |
| 6774 SOAP_FREE(soap, p); | |
| 6775 } | |
| 6776 if ((p = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie)))) | |
| 6777 { p->name = (char*)SOAP_MALLOC(soap, strlen(tmp)+1); | |
| 6778 strcpy(p->name, tmp); | |
| 6779 s = soap_decode_val(tmp, sizeof(tmp), s); | |
| 6780 if (*tmp) | |
| 6781 { p->value = (char*)SOAP_MALLOC(soap, strlen(tmp)+1); | |
| 6782 strcpy(p->value, tmp); | |
| 6783 } | |
| 6784 else | |
| 6785 p->value = NULL; | |
| 6786 if (domain) | |
| 6787 p->domain = domain; | |
| 6788 else if (*soap->host) | |
| 6789 { p->domain = (char*)SOAP_MALLOC(soap, strlen(soap->host)+1); | |
| 6790 strcpy(p->domain, soap->host); | |
| 6791 } | |
| 6792 else | |
| 6793 p->domain = NULL; | |
| 6794 if (path) | |
| 6795 p->path = path; | |
| 6796 else if (soap->path && *soap->path) | |
| 6797 { p->path = (char*)SOAP_MALLOC(soap, strlen(soap->path)+1); | |
| 6798 strcpy(p->path, soap->path); | |
| 6799 } | |
| 6800 else | |
| 6801 { p->path = (char*)SOAP_MALLOC(soap, 2); | |
| 6802 strcpy(p->path, "/"); | |
| 6803 } | |
| 6804 p->expire = 0; | |
| 6805 p->secure = 0; | |
| 6806 p->version = version; | |
| 6807 } | |
| 6808 } | |
| 6809 } | |
| 6810 if (p) | |
| 6811 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie='%s' value='%s' domain='%s' path='%s' expire=%ld secure=%d\n", p->name, p->value ? p->value : "(null)", p->domain ? p->domain : "(null)", p->path ? p->path : "(null)", p->expire, p->secure)); | |
| 6812 if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path))) | |
| 6813 { q->version = p->version; | |
| 6814 q->expire = p->expire; | |
| 6815 q->secure = p->secure; | |
| 6816 q->env = 1; | |
| 6817 } | |
| 6818 if (p->name) | |
| 6819 SOAP_FREE(soap, p->name); | |
| 6820 if (p->value) | |
| 6821 SOAP_FREE(soap, p->value); | |
| 6822 if (p->domain) | |
| 6823 SOAP_FREE(soap, p->domain); | |
| 6824 if (p->path) | |
| 6825 SOAP_FREE(soap, p->path); | |
| 6826 SOAP_FREE(soap, p); | |
| 6827 } | |
| 6828 if (domain) | |
| 6829 SOAP_FREE(soap, domain); | |
| 6830 if (path) | |
| 6831 SOAP_FREE(soap, path); | |
| 6832 } | |
| 6833 | |
| 6834 /******************************************************************************/ | |
| 6835 SOAP_FMAC1 | |
| 6836 int | |
| 6837 SOAP_FMAC2 | |
| 6838 soap_getenv_cookies(struct soap *soap) | |
| 6839 { struct soap_cookie *p; | |
| 6840 const char *s; | |
| 6841 char key[4096], val[4096]; /* cookie size is up to 4096 bytes [RFC2109] */ | |
| 6842 if (!(s = getenv("HTTP_COOKIE"))) | |
| 6843 return SOAP_ERR; | |
| 6844 do | |
| 6845 { s = soap_decode_key(key, sizeof(key), s); | |
| 6846 s = soap_decode_val(val, sizeof(val), s); | |
| 6847 p = soap_set_cookie(soap, key, val, NULL, NULL); | |
| 6848 if (p) | |
| 6849 p->env = 1; | |
| 6850 } while (*s); | |
| 6851 return SOAP_OK; | |
| 6852 } | |
| 6853 | |
| 6854 /******************************************************************************/ | |
| 6855 SOAP_FMAC1 | |
| 6856 struct soap_cookie* | |
| 6857 SOAP_FMAC2 | |
| 6858 soap_copy_cookies(struct soap *copy, const struct soap *soap) | |
| 6859 { struct soap_cookie *p, **q, *r; | |
| 6860 q = &r; | |
| 6861 for (p = soap->cookies; p; p = p->next) | |
| 6862 { if (!(*q = (struct soap_cookie*)SOAP_MALLOC(copy, sizeof(struct soap_cookie)))) | |
| 6863 return r; | |
| 6864 **q = *p; | |
| 6865 if (p->name) | |
| 6866 { if (((*q)->name = (char*)SOAP_MALLOC(copy, strlen(p->name)+1))) | |
| 6867 strcpy((*q)->name, p->name); | |
| 6868 } | |
| 6869 if (p->value) | |
| 6870 { if (((*q)->value = (char*)SOAP_MALLOC(copy, strlen(p->value)+1))) | |
| 6871 strcpy((*q)->value, p->value); | |
| 6872 } | |
| 6873 if (p->domain) | |
| 6874 { if (((*q)->domain = (char*)SOAP_MALLOC(copy, strlen(p->domain)+1))) | |
| 6875 strcpy((*q)->domain, p->domain); | |
| 6876 } | |
| 6877 if (p->path) | |
| 6878 { if (((*q)->path = (char*)SOAP_MALLOC(copy, strlen(p->path)+1))) | |
| 6879 strcpy((*q)->path, p->path); | |
| 6880 } | |
| 6881 q = &(*q)->next; | |
| 6882 } | |
| 6883 *q = NULL; | |
| 6884 return r; | |
| 6885 } | |
| 6886 | |
| 6887 /******************************************************************************/ | |
| 6888 SOAP_FMAC1 | |
| 6889 void | |
| 6890 SOAP_FMAC2 | |
| 6891 soap_free_cookies(struct soap *soap) | |
| 6892 { struct soap_cookie *p; | |
| 6893 for (p = soap->cookies; p; p = soap->cookies) | |
| 6894 { soap->cookies = p->next; | |
| 6895 SOAP_FREE(soap, p->name); | |
| 6896 if (p->value) | |
| 6897 SOAP_FREE(soap, p->value); | |
| 6898 if (p->domain) | |
| 6899 SOAP_FREE(soap, p->domain); | |
| 6900 if (p->path) | |
| 6901 SOAP_FREE(soap, p->path); | |
| 6902 SOAP_FREE(soap, p); | |
| 6903 } | |
| 6904 } | |
| 6905 | |
| 6906 /******************************************************************************/ | |
| 6907 #endif /* WITH_COOKIES */ | |
| 6908 | |
| 6909 /******************************************************************************/ | |
| 6910 #ifndef WITH_NOIDREF | |
| 6911 #ifndef PALM_2 | |
| 6912 SOAP_FMAC1 | |
| 6913 size_t | |
| 6914 SOAP_FMAC2 | |
| 6915 soap_hash(register const char *s) | |
| 6916 { register size_t h = 0; | |
| 6917 while (*s) | |
| 6918 h = 65599*h + *s++; | |
| 6919 return h % SOAP_IDHASH; | |
| 6920 } | |
| 6921 #endif | |
| 6922 #endif | |
| 6923 | |
| 6924 /******************************************************************************/ | |
| 6925 #ifndef WITH_NOIDREF | |
| 6926 #ifndef PALM_1 | |
| 6927 static void | |
| 6928 soap_init_pht(struct soap *soap) | |
| 6929 { register int i; | |
| 6930 soap->pblk = NULL; | |
| 6931 soap->pidx = 0; | |
| 6932 for (i = 0; i < (int)SOAP_PTRHASH; i++) | |
| 6933 soap->pht[i] = NULL; | |
| 6934 } | |
| 6935 #endif | |
| 6936 #endif | |
| 6937 | |
| 6938 /******************************************************************************/ | |
| 6939 #ifndef PALM_1 | |
| 6940 SOAP_FMAC1 | |
| 6941 struct soap* | |
| 6942 SOAP_FMAC2 | |
| 6943 soap_versioning(soap_new)(soap_mode imode, soap_mode omode) | |
| 6944 { struct soap *soap = (struct soap*)malloc(sizeof(struct soap)); | |
| 6945 if (soap) | |
| 6946 soap_versioning(soap_init)(soap, imode, omode); | |
| 6947 return soap; | |
| 6948 } | |
| 6949 #endif | |
| 6950 | |
| 6951 /******************************************************************************/ | |
| 6952 #ifndef PALM_1 | |
| 6953 SOAP_FMAC1 | |
| 6954 void | |
| 6955 SOAP_FMAC2 | |
| 6956 soap_free(struct soap *soap) | |
| 6957 { soap_done(soap); | |
| 6958 free(soap); | |
| 6959 } | |
| 6960 #endif | |
| 6961 | |
| 6962 /******************************************************************************/ | |
| 6963 #ifndef PALM_1 | |
| 6964 SOAP_FMAC1 | |
| 6965 void | |
| 6966 SOAP_FMAC2 | |
| 6967 soap_del(struct soap *soap) | |
| 6968 { free(soap); | |
| 6969 } | |
| 6970 #endif | |
| 6971 | |
| 6972 /******************************************************************************/ | |
| 6973 #ifndef WITH_NOIDREF | |
| 6974 #ifndef PALM_1 | |
| 6975 static void | |
| 6976 soap_free_pht(struct soap *soap) | |
| 6977 { register struct soap_pblk *pb, *next; | |
| 6978 register int i; | |
| 6979 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free pointer hashtable\n")); | |
| 6980 for (pb = soap->pblk; pb; pb = next) | |
| 6981 { next = pb->next; | |
| 6982 SOAP_FREE(soap, pb); | |
| 6983 } | |
| 6984 soap->pblk = NULL; | |
| 6985 soap->pidx = 0; | |
| 6986 for (i = 0; i < (int)SOAP_PTRHASH; i++) | |
| 6987 soap->pht[i] = NULL; | |
| 6988 } | |
| 6989 #endif | |
| 6990 #endif | |
| 6991 | |
| 6992 /******************************************************************************/ | |
| 6993 #ifndef WITH_NOIDREF | |
| 6994 #ifndef PALM_2 | |
| 6995 SOAP_FMAC1 | |
| 6996 int | |
| 6997 SOAP_FMAC2 | |
| 6998 soap_embed(struct soap *soap, const void *p, const struct soap_array *a, int n, const char *tag, int type) | |
| 6999 { register int i; | |
| 7000 struct soap_plist *pp; | |
| 7001 (void)soap; | |
| 7002 if (soap->version == 2) | |
| 7003 soap->encoding = 1; | |
| 7004 if (a) | |
| 7005 i = soap_array_pointer_lookup(soap, p, a, n, type, &pp); | |
| 7006 else | |
| 7007 i = soap_pointer_lookup(soap, p, type, &pp); | |
| 7008 if (i) | |
| 7009 { if (soap_is_embedded(soap, pp) | |
| 7010 || soap_is_single(soap, pp)) | |
| 7011 return 0; | |
| 7012 soap_set_embedded(soap, pp); | |
| 7013 } | |
| 7014 return i; | |
| 7015 } | |
| 7016 #endif | |
| 7017 #endif | |
| 7018 | |
| 7019 /******************************************************************************/ | |
| 7020 #ifndef WITH_NOIDREF | |
| 7021 #ifndef PALM_2 | |
| 7022 SOAP_FMAC1 | |
| 7023 int | |
| 7024 SOAP_FMAC2 | |
| 7025 soap_pointer_lookup(struct soap *soap, const void *p, int type, struct soap_plist **ppp) | |
| 7026 { register struct soap_plist *pp; | |
| 7027 *ppp = NULL; | |
| 7028 if (p) | |
| 7029 { for (pp = soap->pht[soap_hash_ptr(p)]; pp; pp = pp->next) | |
| 7030 { if (pp->ptr == p && pp->type == type) | |
| 7031 { *ppp = pp; | |
| 7032 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d id=%d\n", p, type, pp->id)); | |
| 7033 return pp->id; | |
| 7034 } | |
| 7035 } | |
| 7036 } | |
| 7037 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d: not found\n", p, type)); | |
| 7038 return 0; | |
| 7039 } | |
| 7040 #endif | |
| 7041 #endif | |
| 7042 | |
| 7043 /******************************************************************************/ | |
| 7044 #ifndef WITH_NOIDREF | |
| 7045 #ifndef PALM_2 | |
| 7046 SOAP_FMAC1 | |
| 7047 int | |
| 7048 SOAP_FMAC2 | |
| 7049 soap_pointer_enter(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp) | |
| 7050 { register size_t h; | |
| 7051 register struct soap_plist *pp; | |
| 7052 (void)n; | |
| 7053 if (!soap->pblk || soap->pidx >= SOAP_PTRBLK) | |
| 7054 { register struct soap_pblk *pb = (struct soap_pblk*)SOAP_MALLOC(soap, sizeof(struct soap_pblk)); | |
| 7055 if (!pb) | |
| 7056 { soap->error = SOAP_EOM; | |
| 7057 return 0; | |
| 7058 } | |
| 7059 pb->next = soap->pblk; | |
| 7060 soap->pblk = pb; | |
| 7061 soap->pidx = 0; | |
| 7062 } | |
| 7063 *ppp = pp = &soap->pblk->plist[soap->pidx++]; | |
| 7064 if (a) | |
| 7065 h = soap_hash_ptr(a->__ptr); | |
| 7066 else | |
| 7067 h = soap_hash_ptr(p); | |
| 7068 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)); | |
| 7069 pp->next = soap->pht[h]; | |
| 7070 pp->type = type; | |
| 7071 pp->mark1 = 0; | |
| 7072 pp->mark2 = 0; | |
| 7073 pp->ptr = p; | |
| 7074 pp->array = a; | |
| 7075 soap->pht[h] = pp; | |
| 7076 pp->id = ++soap->idnum; | |
| 7077 return pp->id; | |
| 7078 } | |
| 7079 #endif | |
| 7080 #endif | |
| 7081 | |
| 7082 /******************************************************************************/ | |
| 7083 #ifndef WITH_NOIDREF | |
| 7084 #ifndef PALM_2 | |
| 7085 SOAP_FMAC1 | |
| 7086 int | |
| 7087 SOAP_FMAC2 | |
| 7088 soap_array_pointer_lookup(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp) | |
| 7089 { register struct soap_plist *pp; | |
| 7090 *ppp = NULL; | |
| 7091 if (!p || !a->__ptr) | |
| 7092 return 0; | |
| 7093 for (pp = soap->pht[soap_hash_ptr(a->__ptr)]; pp; pp = pp->next) | |
| 7094 { if (pp->type == type && pp->array && pp->array->__ptr == a->__ptr) | |
| 7095 { register int i; | |
| 7096 for (i = 0; i < n; i++) | |
| 7097 if (((const int*)&pp->array->__size)[i] != ((const int*)&a->__size)[i]) | |
| 7098 break; | |
| 7099 if (i == n) | |
| 7100 { *ppp = pp; | |
| 7101 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d id=%d\n", a->__ptr, type, pp->id)); | |
| 7102 return pp->id; | |
| 7103 } | |
| 7104 } | |
| 7105 } | |
| 7106 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d: not found\n", a->__ptr, type)); | |
| 7107 return 0; | |
| 7108 } | |
| 7109 #endif | |
| 7110 #endif | |
| 7111 | |
| 7112 /******************************************************************************/ | |
| 7113 #ifndef PALM_1 | |
| 7114 SOAP_FMAC1 | |
| 7115 int | |
| 7116 SOAP_FMAC2 | |
| 7117 soap_begin_count(struct soap *soap) | |
| 7118 { soap_free_ns(soap); | |
| 7119 #ifndef WITH_LEANER | |
| 7120 if ((soap->mode & SOAP_ENC_DIME) || (soap->omode & SOAP_ENC_DIME)) | |
| 7121 soap->mode = soap->omode | SOAP_IO_LENGTH | SOAP_ENC_DIME; | |
| 7122 else | |
| 7123 #endif | |
| 7124 { soap->mode = soap->omode; | |
| 7125 if ((soap->mode & SOAP_IO_UDP)) | |
| 7126 soap->mode |= SOAP_ENC_XML; | |
| 7127 if ((soap->mode & SOAP_IO) == SOAP_IO_STORE | |
| 7128 || (((soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_ENC_XML)) | |
| 7129 #ifndef WITH_LEANER | |
| 7130 && !soap->fpreparesend | |
| 7131 #endif | |
| 7132 )) | |
| 7133 soap->mode &= ~SOAP_IO_LENGTH; | |
| 7134 else | |
| 7135 soap->mode |= SOAP_IO_LENGTH; | |
| 7136 } | |
| 7137 #ifdef WITH_ZLIB | |
| 7138 if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH) | |
| 7139 { if (!(soap->mode & SOAP_ENC_DIME)) | |
| 7140 soap->mode &= ~SOAP_IO_LENGTH; | |
| 7141 if (soap->mode & SOAP_ENC_XML) | |
| 7142 soap->mode |= SOAP_IO_BUFFER; | |
| 7143 else | |
| 7144 soap->mode |= SOAP_IO_STORE; | |
| 7145 } | |
| 7146 #endif | |
| 7147 #ifndef WITH_LEANER | |
| 7148 if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME)) | |
| 7149 soap->mode |= SOAP_ENC_MIME; | |
| 7150 else if (!(soap->mode & SOAP_ENC_MIME)) | |
| 7151 soap->mode &= ~SOAP_ENC_MTOM; | |
| 7152 if (soap->mode & SOAP_ENC_MIME) | |
| 7153 soap_select_mime_boundary(soap); | |
| 7154 soap->dime.list = soap->dime.last; /* keep track of last DIME attachment */ | |
| 7155 #endif | |
| 7156 soap->count = 0; | |
| 7157 soap->ns = 0; | |
| 7158 soap->null = 0; | |
| 7159 soap->position = 0; | |
| 7160 soap->mustUnderstand = 0; | |
| 7161 soap->encoding = 0; | |
| 7162 soap->part = SOAP_BEGIN; | |
| 7163 soap->event = 0; | |
| 7164 soap->evlev = 0; | |
| 7165 soap->idnum = 0; | |
| 7166 soap_clr_attr(soap); | |
| 7167 soap_set_local_namespaces(soap); | |
| 7168 #ifndef WITH_LEANER | |
| 7169 soap->dime.count = 0; /* count # of attachments */ | |
| 7170 soap->dime.size = 0; /* accumulate total size of attachments */ | |
| 7171 if (soap->fprepareinitsend && (soap->mode & SOAP_IO) != SOAP_IO_STORE && (soap->error = soap->fprepareinitsend(soap))) | |
| 7172 return soap->error; | |
| 7173 #endif | |
| 7174 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin count phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, (unsigned int)soap->mode, (unsigned long)soap->count)); | |
| 7175 return SOAP_OK; | |
| 7176 } | |
| 7177 #endif | |
| 7178 | |
| 7179 /******************************************************************************/ | |
| 7180 #ifndef PALM_1 | |
| 7181 SOAP_FMAC1 | |
| 7182 int | |
| 7183 SOAP_FMAC2 | |
| 7184 soap_end_count(struct soap *soap) | |
| 7185 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of count phase\n")); | |
| 7186 #ifndef WITH_LEANER | |
| 7187 if ((soap->mode & SOAP_IO_LENGTH)) | |
| 7188 { if (soap->fpreparefinalsend && (soap->error = soap->fpreparefinalsend(soap))) | |
| 7189 return soap->error; | |
| 7190 } | |
| 7191 #endif | |
| 7192 return SOAP_OK; | |
| 7193 } | |
| 7194 #endif | |
| 7195 | |
| 7196 /******************************************************************************/ | |
| 7197 #ifndef PALM_1 | |
| 7198 SOAP_FMAC1 | |
| 7199 int | |
| 7200 SOAP_FMAC2 | |
| 7201 soap_begin_send(struct soap *soap) | |
| 7202 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing for output to socket=%d/fd=%d\n", soap->socket, soap->sendfd)); | |
| 7203 soap_free_ns(soap); | |
| 7204 soap->error = SOAP_OK; | |
| 7205 soap->mode = soap->omode | (soap->mode & (SOAP_IO_LENGTH | SOAP_ENC_DIME)); | |
| 7206 #ifdef WITH_ZLIB | |
| 7207 if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH) | |
| 7208 { if (soap->mode & SOAP_ENC_XML) | |
| 7209 soap->mode |= SOAP_IO_BUFFER; | |
| 7210 else | |
| 7211 soap->mode |= SOAP_IO_STORE; | |
| 7212 } | |
| 7213 #endif | |
| 7214 #ifndef WITH_LEAN | |
| 7215 if ((soap->mode & SOAP_IO_UDP)) | |
| 7216 { soap->mode |= SOAP_ENC_XML; | |
| 7217 if (soap->count > SOAP_BUFLEN) | |
| 7218 return soap->error = SOAP_UDP_ERROR; | |
| 7219 } | |
| 7220 #endif | |
| 7221 if ((soap->mode & SOAP_IO) == SOAP_IO_FLUSH && soap_valid_socket(soap->socket)) | |
| 7222 { if (soap->count || (soap->mode & SOAP_IO_LENGTH) || (soap->mode & SOAP_ENC_XML)) | |
| 7223 soap->mode |= SOAP_IO_BUFFER; | |
| 7224 else | |
| 7225 soap->mode |= SOAP_IO_STORE; | |
| 7226 } | |
| 7227 soap->mode &= ~SOAP_IO_LENGTH; | |
| 7228 if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) | |
| 7229 if (soap_new_block(soap) == NULL) | |
| 7230 return soap->error; | |
| 7231 if (!(soap->mode & SOAP_IO_KEEPALIVE)) | |
| 7232 soap->keep_alive = 0; | |
| 7233 #ifndef WITH_LEANER | |
| 7234 if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME)) | |
| 7235 { soap->mode |= SOAP_ENC_MIME; | |
| 7236 soap->mode &= ~SOAP_ENC_DIME; | |
| 7237 } | |
| 7238 else if (!(soap->mode & SOAP_ENC_MIME)) | |
| 7239 soap->mode &= ~SOAP_ENC_MTOM; | |
| 7240 if (soap->mode & SOAP_ENC_MIME) | |
| 7241 soap_select_mime_boundary(soap); | |
| 7242 #ifdef WIN32 | |
| 7243 #ifndef UNDER_CE | |
| 7244 #ifndef WITH_FASTCGI | |
| 7245 if (!soap_valid_socket(soap->socket) && !soap->os) /* Set win32 stdout or soap->sendfd to BINARY, e.g. to support DIME */ | |
| 7246 #ifdef __BORLANDC__ | |
| 7247 setmode(soap->sendfd, _O_BINARY); | |
| 7248 #else | |
| 7249 _setmode(soap->sendfd, _O_BINARY); | |
| 7250 #endif | |
| 7251 #endif | |
| 7252 #endif | |
| 7253 #endif | |
| 7254 #endif | |
| 7255 if (soap->mode & SOAP_IO) | |
| 7256 { soap->bufidx = 0; | |
| 7257 soap->buflen = 0; | |
| 7258 } | |
| 7259 soap->chunksize = 0; | |
| 7260 soap->ns = 0; | |
| 7261 soap->null = 0; | |
| 7262 soap->position = 0; | |
| 7263 soap->mustUnderstand = 0; | |
| 7264 soap->encoding = 0; | |
| 7265 soap->idnum = 0; | |
| 7266 soap->level = 0; | |
| 7267 soap_clr_attr(soap); | |
| 7268 soap_set_local_namespaces(soap); | |
| 7269 #ifdef WITH_ZLIB | |
| 7270 soap->z_ratio_out = 1.0; | |
| 7271 if ((soap->mode & SOAP_ENC_ZLIB) && soap->zlib_state != SOAP_ZLIB_DEFLATE) | |
| 7272 { if (!soap->z_buf) | |
| 7273 soap->z_buf = (char*)SOAP_MALLOC(soap, SOAP_BUFLEN); | |
| 7274 soap->d_stream->next_out = (Byte*)soap->z_buf; | |
| 7275 soap->d_stream->avail_out = SOAP_BUFLEN; | |
| 7276 #ifdef WITH_GZIP | |
| 7277 if (soap->zlib_out != SOAP_ZLIB_DEFLATE) | |
| 7278 { memcpy(soap->z_buf, "\37\213\10\0\0\0\0\0\0\377", 10); | |
| 7279 soap->d_stream->next_out = (Byte*)soap->z_buf + 10; | |
| 7280 soap->d_stream->avail_out = SOAP_BUFLEN - 10; | |
| 7281 soap->z_crc = crc32(0L, NULL, 0); | |
| 7282 soap->zlib_out = SOAP_ZLIB_GZIP; | |
| 7283 if (soap->z_dict) | |
| 7284 *((Byte*)soap->z_buf + 2) = 0xff; | |
| 7285 if (deflateInit2(soap->d_stream, soap->z_level, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY) != Z_OK) | |
| 7286 return soap->error = SOAP_ZLIB_ERROR; | |
| 7287 } | |
| 7288 else | |
| 7289 #endif | |
| 7290 if (deflateInit(soap->d_stream, soap->z_level) != Z_OK) | |
| 7291 return soap->error = SOAP_ZLIB_ERROR; | |
| 7292 if (soap->z_dict) | |
| 7293 { if (deflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len) != Z_OK) | |
| 7294 return soap->error = SOAP_ZLIB_ERROR; | |
| 7295 } | |
| 7296 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflate initialized\n")); | |
| 7297 soap->zlib_state = SOAP_ZLIB_DEFLATE; | |
| 7298 } | |
| 7299 #endif | |
| 7300 #ifdef WITH_OPENSSL | |
| 7301 if (soap->ssl) | |
| 7302 ERR_clear_error(); | |
| 7303 #endif | |
| 7304 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin send phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count)); | |
| 7305 soap->part = SOAP_BEGIN; | |
| 7306 #ifndef WITH_LEANER | |
| 7307 if (soap->fprepareinitsend && (soap->mode & SOAP_IO) == SOAP_IO_STORE && (soap->error = soap->fprepareinitsend(soap))) | |
| 7308 return soap->error; | |
| 7309 #endif | |
| 7310 return SOAP_OK; | |
| 7311 } | |
| 7312 #endif | |
| 7313 | |
| 7314 /******************************************************************************/ | |
| 7315 #ifndef WITH_NOIDREF | |
| 7316 #ifndef PALM_2 | |
| 7317 SOAP_FMAC1 | |
| 7318 void | |
| 7319 SOAP_FMAC2 | |
| 7320 soap_embedded(struct soap *soap, const void *p, int t) | |
| 7321 { struct soap_plist *pp; | |
| 7322 if (soap_pointer_lookup(soap, p, t, &pp)) | |
| 7323 { pp->mark1 = 1; | |
| 7324 pp->mark2 = 1; | |
| 7325 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded %p type=%d mark set to 1\n", p, t)); | |
| 7326 } | |
| 7327 } | |
| 7328 #endif | |
| 7329 #endif | |
| 7330 | |
| 7331 /******************************************************************************/ | |
| 7332 #ifndef WITH_NOIDREF | |
| 7333 #ifndef PALM_2 | |
| 7334 SOAP_FMAC1 | |
| 7335 int | |
| 7336 SOAP_FMAC2 | |
| 7337 soap_reference(struct soap *soap, const void *p, int t) | |
| 7338 { struct soap_plist *pp; | |
| 7339 if (!p || (!soap->encodingStyle && !(soap->omode & (SOAP_ENC_DIME|SOAP_ENC_MIME|SOAP_ENC_MTOM|SOAP_XML_GRAPH))) || (soap->omode & SOAP_XML_TREE)) | |
| 7340 return 1; | |
| 7341 if (soap_pointer_lookup(soap, p, t, &pp)) | |
| 7342 { if (pp->mark1 == 0) | |
| 7343 { pp->mark1 = 2; | |
| 7344 pp->mark2 = 2; | |
| 7345 } | |
| 7346 } | |
| 7347 else if (!soap_pointer_enter(soap, p, NULL, 0, t, &pp)) | |
| 7348 return 1; | |
| 7349 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reference %p type=%d (%d %d)\n", p, t, (int)pp->mark1, (int)pp->mark2)); | |
| 7350 return pp->mark1; | |
| 7351 } | |
| 7352 #endif | |
| 7353 #endif | |
| 7354 | |
| 7355 /******************************************************************************/ | |
| 7356 #ifndef WITH_NOIDREF | |
| 7357 #ifndef PALM_2 | |
| 7358 SOAP_FMAC1 | |
| 7359 int | |
| 7360 SOAP_FMAC2 | |
| 7361 soap_array_reference(struct soap *soap, const void *p, const struct soap_array *a, int n, int t) | |
| 7362 { struct soap_plist *pp; | |
| 7363 if (!p || !a->__ptr || (!soap->encodingStyle && !(soap->omode & (SOAP_ENC_DIME|SOAP_ENC_MIME|SOAP_ENC_MTOM|SOAP_XML_GRAPH))) || (soap->omode & SOAP_XML_TREE)) | |
| 7364 return 1; | |
| 7365 if (soap_array_pointer_lookup(soap, p, a, n, t, &pp)) | |
| 7366 { if (pp->mark1 == 0) | |
| 7367 { pp->mark1 = 2; | |
| 7368 pp->mark2 = 2; | |
| 7369 } | |
| 7370 } | |
| 7371 else if (!soap_pointer_enter(soap, p, a, n, t, &pp)) | |
| 7372 return 1; | |
| 7373 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)); | |
| 7374 return pp->mark1; | |
| 7375 } | |
| 7376 #endif | |
| 7377 #endif | |
| 7378 | |
| 7379 /******************************************************************************/ | |
| 7380 #ifndef WITH_NOIDREF | |
| 7381 #ifndef PALM_2 | |
| 7382 SOAP_FMAC1 | |
| 7383 int | |
| 7384 SOAP_FMAC2 | |
| 7385 soap_embedded_id(struct soap *soap, int id, const void *p, int t) | |
| 7386 { struct soap_plist *pp = NULL; | |
| 7387 if (!id || (!soap->encodingStyle && !(soap->omode & SOAP_XML_GRAPH)) || (soap->omode & SOAP_XML_TREE)) | |
| 7388 return id; | |
| 7389 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id %p type=%d id=%d\n", p, t, id)); | |
| 7390 if (soap->version == 1 && soap->part != SOAP_IN_HEADER) | |
| 7391 { if (id < 0) | |
| 7392 { id = soap_pointer_lookup(soap, p, t, &pp); | |
| 7393 if (id) | |
| 7394 { if (soap->mode & SOAP_IO_LENGTH) | |
| 7395 pp->mark1 = 2; | |
| 7396 else | |
| 7397 pp->mark2 = 2; | |
| 7398 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id multiref id=%d %p type=%d = (%d %d)\n", id, p, t, (int)pp->mark1, (int)pp->mark2)); | |
| 7399 } | |
| 7400 return -1; | |
| 7401 } | |
| 7402 return id; | |
| 7403 } | |
| 7404 if (id < 0) | |
| 7405 id = soap_pointer_lookup(soap, p, t, &pp); | |
| 7406 else if (id && !soap_pointer_lookup(soap, p, t, &pp)) | |
| 7407 return 0; | |
| 7408 if (id && pp) | |
| 7409 { if (soap->mode & SOAP_IO_LENGTH) | |
| 7410 pp->mark1 = 1; | |
| 7411 else | |
| 7412 pp->mark2 = 1; | |
| 7413 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)); | |
| 7414 } | |
| 7415 return id; | |
| 7416 } | |
| 7417 #endif | |
| 7418 #endif | |
| 7419 | |
| 7420 /******************************************************************************/ | |
| 7421 #ifndef WITH_NOIDREF | |
| 7422 #ifndef PALM_2 | |
| 7423 SOAP_FMAC1 | |
| 7424 int | |
| 7425 SOAP_FMAC2 | |
| 7426 soap_is_embedded(struct soap *soap, struct soap_plist *pp) | |
| 7427 { if (!pp) | |
| 7428 return 0; | |
| 7429 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Is embedded? %d %d\n", (int)pp->mark1, (int)pp->mark2)); | |
| 7430 if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER) | |
| 7431 { if (soap->mode & SOAP_IO_LENGTH) | |
| 7432 return pp->mark1 != 0; | |
| 7433 return pp->mark2 != 0; | |
| 7434 } | |
| 7435 if (soap->mode & SOAP_IO_LENGTH) | |
| 7436 return pp->mark1 == 1; | |
| 7437 return pp->mark2 == 1; | |
| 7438 } | |
| 7439 #endif | |
| 7440 #endif | |
| 7441 | |
| 7442 /******************************************************************************/ | |
| 7443 #ifndef WITH_NOIDREF | |
| 7444 #ifndef PALM_2 | |
| 7445 SOAP_FMAC1 | |
| 7446 int | |
| 7447 SOAP_FMAC2 | |
| 7448 soap_is_single(struct soap *soap, struct soap_plist *pp) | |
| 7449 { if (soap->part == SOAP_IN_HEADER) | |
| 7450 return 1; | |
| 7451 if (!pp) | |
| 7452 return 0; | |
| 7453 if (soap->mode & SOAP_IO_LENGTH) | |
| 7454 return pp->mark1 == 0; | |
| 7455 return pp->mark2 == 0; | |
| 7456 } | |
| 7457 #endif | |
| 7458 #endif | |
| 7459 | |
| 7460 /******************************************************************************/ | |
| 7461 #ifndef WITH_NOIDREF | |
| 7462 #ifndef PALM_2 | |
| 7463 SOAP_FMAC1 | |
| 7464 void | |
| 7465 SOAP_FMAC2 | |
| 7466 soap_set_embedded(struct soap *soap, struct soap_plist *pp) | |
| 7467 { if (!pp) | |
| 7468 return; | |
| 7469 if (soap->mode & SOAP_IO_LENGTH) | |
| 7470 pp->mark1 = 1; | |
| 7471 else | |
| 7472 pp->mark2 = 1; | |
| 7473 } | |
| 7474 #endif | |
| 7475 #endif | |
| 7476 | |
| 7477 /******************************************************************************/ | |
| 7478 #ifndef WITH_LEANER | |
| 7479 #ifndef PALM_1 | |
| 7480 SOAP_FMAC1 | |
| 7481 int | |
| 7482 SOAP_FMAC2 | |
| 7483 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) | |
| 7484 { | |
| 7485 #ifndef WITH_NOIDREF | |
| 7486 struct soap_plist *pp; | |
| 7487 int i; | |
| 7488 if (!p || !a->__ptr || (!aid && !atype)) | |
| 7489 return soap_element_id(soap, tag, id, p, a, n, type, t); | |
| 7490 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)); | |
| 7491 i = soap_array_pointer_lookup(soap, p, a, n, t, &pp); | |
| 7492 if (!i) | |
| 7493 { i = soap_pointer_enter(soap, p, a, n, t, &pp); | |
| 7494 if (!i) | |
| 7495 { soap->error = SOAP_EOM; | |
| 7496 return -1; | |
| 7497 } | |
| 7498 } | |
| 7499 if (id <= 0) | |
| 7500 id = i; | |
| 7501 if (!aid) | |
| 7502 { | |
| 7503 #ifdef HAVE_SNPRINTF | |
| 7504 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), soap->dime_id_format, id); | |
| 7505 #else | |
| 7506 sprintf(soap->tmpbuf, soap->dime_id_format, id); | |
| 7507 #endif | |
| 7508 aid = soap_strdup(soap, soap->tmpbuf); | |
| 7509 } | |
| 7510 /* Add MTOM xop:Include element when necessary */ | |
| 7511 /* TODO: this code to be obsoleted with new import/xop.h conventions */ | |
| 7512 if ((soap->mode & SOAP_ENC_MTOM) && strcmp(tag, "xop:Include")) | |
| 7513 { if (soap_element_begin_out(soap, tag, 0, type) | |
| 7514 || soap_element_href(soap, "xop:Include", 0, "xmlns:xop=\"http://www.w3.org/2004/08/xop/include\" href", aid) | |
| 7515 || soap_element_end_out(soap, tag)) | |
| 7516 return soap->error; | |
| 7517 } | |
| 7518 else if (soap_element_href(soap, tag, 0, "href", aid)) | |
| 7519 return soap->error; | |
| 7520 if (soap->mode & SOAP_IO_LENGTH) | |
| 7521 { if (pp->mark1 != 3) | |
| 7522 { struct soap_multipart *content; | |
| 7523 if (soap->mode & SOAP_ENC_MTOM) | |
| 7524 content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, (char*)a->__ptr, a->__size); | |
| 7525 else | |
| 7526 content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, (char*)a->__ptr, a->__size); | |
| 7527 if (!content) | |
| 7528 { soap->error = SOAP_EOM; | |
| 7529 return -1; | |
| 7530 } | |
| 7531 if (!strncmp(aid, "cid:", 4)) /* RFC 2111 */ | |
| 7532 { if (soap->mode & SOAP_ENC_MTOM) | |
| 7533 { char *s = (char*)soap_malloc(soap, strlen(aid) - 1); | |
| 7534 if (s) | |
| 7535 { *s = '<'; | |
| 7536 strcpy(s + 1, aid + 4); | |
| 7537 strcat(s, ">"); | |
| 7538 content->id = s; | |
| 7539 } | |
| 7540 } | |
| 7541 else | |
| 7542 content->id = aid + 4; | |
| 7543 } | |
| 7544 else | |
| 7545 content->id = aid; | |
| 7546 content->type = atype; | |
| 7547 content->options = aoptions; | |
| 7548 content->encoding = SOAP_MIME_BINARY; | |
| 7549 pp->mark1 = 3; | |
| 7550 } | |
| 7551 } | |
| 7552 else | |
| 7553 pp->mark2 = 3; | |
| 7554 #endif | |
| 7555 return -1; | |
| 7556 } | |
| 7557 #endif | |
| 7558 #endif | |
| 7559 | |
| 7560 /******************************************************************************/ | |
| 7561 #ifndef WITH_NOIDREF | |
| 7562 #ifndef PALM_1 | |
| 7563 static void | |
| 7564 soap_init_iht(struct soap *soap) | |
| 7565 { register int i; | |
| 7566 for (i = 0; i < SOAP_IDHASH; i++) | |
| 7567 soap->iht[i] = NULL; | |
| 7568 } | |
| 7569 #endif | |
| 7570 #endif | |
| 7571 | |
| 7572 /******************************************************************************/ | |
| 7573 #ifndef WITH_NOIDREF | |
| 7574 #ifndef PALM_1 | |
| 7575 static void | |
| 7576 soap_free_iht(struct soap *soap) | |
| 7577 { register int i; | |
| 7578 register struct soap_ilist *ip = NULL, *p = NULL; | |
| 7579 register struct soap_flist *fp = NULL, *fq = NULL; | |
| 7580 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free ID hashtable\n")); | |
| 7581 for (i = 0; i < SOAP_IDHASH; i++) | |
| 7582 { for (ip = soap->iht[i]; ip; ip = p) | |
| 7583 { for (fp = ip->flist; fp; fp = fq) | |
| 7584 { fq = fp->next; | |
| 7585 SOAP_FREE(soap, fp); | |
| 7586 } | |
| 7587 p = ip->next; | |
| 7588 SOAP_FREE(soap, ip); | |
| 7589 } | |
| 7590 soap->iht[i] = NULL; | |
| 7591 } | |
| 7592 } | |
| 7593 #endif | |
| 7594 #endif | |
| 7595 | |
| 7596 /******************************************************************************/ | |
| 7597 #ifndef WITH_NOIDREF | |
| 7598 #ifndef PALM_2 | |
| 7599 SOAP_FMAC1 | |
| 7600 struct soap_ilist * | |
| 7601 SOAP_FMAC2 | |
| 7602 soap_lookup(struct soap *soap, const char *id) | |
| 7603 { register struct soap_ilist *ip = NULL; | |
| 7604 for (ip = soap->iht[soap_hash(id)]; ip; ip = ip->next) | |
| 7605 if (!strcmp(ip->id, id)) | |
| 7606 return ip; | |
| 7607 return NULL; | |
| 7608 } | |
| 7609 #endif | |
| 7610 #endif | |
| 7611 | |
| 7612 /******************************************************************************/ | |
| 7613 #ifndef WITH_NOIDREF | |
| 7614 #ifndef PALM_2 | |
| 7615 SOAP_FMAC1 | |
| 7616 struct soap_ilist * | |
| 7617 SOAP_FMAC2 | |
| 7618 soap_enter(struct soap *soap, const char *id) | |
| 7619 { register size_t h; | |
| 7620 register struct soap_ilist *ip; | |
| 7621 ip = (struct soap_ilist*)SOAP_MALLOC(soap, sizeof(struct soap_ilist) + strlen(id)); | |
| 7622 if (ip) | |
| 7623 { strcpy((char*)ip->id, id); | |
| 7624 h = soap_hash(id); /* h = (HASH(id) % SOAP_IDHASH) so soap->iht[h] is safe */ | |
| 7625 ip->next = soap->iht[h]; | |
| 7626 soap->iht[h] = ip; | |
| 7627 } | |
| 7628 return ip; | |
| 7629 } | |
| 7630 #endif | |
| 7631 #endif | |
| 7632 | |
| 7633 /******************************************************************************/ | |
| 7634 #ifndef PALM_2 | |
| 7635 SOAP_FMAC1 | |
| 7636 void* | |
| 7637 SOAP_FMAC2 | |
| 7638 soap_malloc(struct soap *soap, size_t n) | |
| 7639 { register char *p; | |
| 7640 if (!n) | |
| 7641 return (void*)SOAP_NON_NULL; | |
| 7642 if (!soap) | |
| 7643 return SOAP_MALLOC(soap, n); | |
| 7644 if (soap->fmalloc) | |
| 7645 p = (char*)soap->fmalloc(soap, n); | |
| 7646 else | |
| 7647 { n += sizeof(short); | |
| 7648 n += (-(long)n) & (sizeof(void*)-1); /* align at 4-, 8- or 16-byte boundary */ | |
| 7649 if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(void*) + sizeof(size_t)))) | |
| 7650 { soap->error = SOAP_EOM; | |
| 7651 return NULL; | |
| 7652 } | |
| 7653 /* set the canary to detect corruption */ | |
| 7654 *(unsigned short*)(p + n - sizeof(unsigned short)) = (unsigned short)SOAP_CANARY; | |
| 7655 /* keep chain of alloced cells for destruction */ | |
| 7656 *(void**)(p + n) = soap->alist; | |
| 7657 *(size_t*)(p + n + sizeof(void*)) = n; | |
| 7658 soap->alist = p + n; | |
| 7659 } | |
| 7660 soap->alloced = 1; | |
| 7661 return p; | |
| 7662 } | |
| 7663 #endif | |
| 7664 | |
| 7665 /******************************************************************************/ | |
| 7666 #ifdef SOAP_MEM_DEBUG | |
| 7667 static void | |
| 7668 soap_init_mht(struct soap *soap) | |
| 7669 { register int i; | |
| 7670 for (i = 0; i < (int)SOAP_PTRHASH; i++) | |
| 7671 soap->mht[i] = NULL; | |
| 7672 } | |
| 7673 #endif | |
| 7674 | |
| 7675 /******************************************************************************/ | |
| 7676 #ifdef SOAP_MEM_DEBUG | |
| 7677 static void | |
| 7678 soap_free_mht(struct soap *soap) | |
| 7679 { register int i; | |
| 7680 register struct soap_mlist *mp, *mq; | |
| 7681 for (i = 0; i < (int)SOAP_PTRHASH; i++) | |
| 7682 { for (mp = soap->mht[i]; mp; mp = mq) | |
| 7683 { mq = mp->next; | |
| 7684 if (mp->live) | |
| 7685 fprintf(stderr, "%s(%d): malloc() = %p not freed (memory leak or forgot to call soap_end()?)\n", mp->file, mp->line, mp->ptr); | |
| 7686 free(mp); | |
| 7687 } | |
| 7688 soap->mht[i] = NULL; | |
| 7689 } | |
| 7690 } | |
| 7691 #endif | |
| 7692 | |
| 7693 /******************************************************************************/ | |
| 7694 #ifdef SOAP_MEM_DEBUG | |
| 7695 SOAP_FMAC1 | |
| 7696 void* | |
| 7697 SOAP_FMAC2 | |
| 7698 soap_track_malloc(struct soap *soap, const char *file, int line, size_t size) | |
| 7699 { register void *p = malloc(size); | |
| 7700 if (soap) | |
| 7701 { register size_t h = soap_hash_ptr(p); | |
| 7702 register struct soap_mlist *mp = (struct soap_mlist*)malloc(sizeof(struct soap_mlist)); | |
| 7703 if (soap->fdebug[SOAP_INDEX_TEST]) | |
| 7704 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): malloc(%lu) = %p\n", file, line, (unsigned long)size, p)); | |
| 7705 } | |
| 7706 mp->next = soap->mht[h]; | |
| 7707 mp->ptr = p; | |
| 7708 mp->file = file; | |
| 7709 mp->line = line; | |
| 7710 mp->live = 1; | |
| 7711 soap->mht[h] = mp; | |
| 7712 } | |
| 7713 return p; | |
| 7714 } | |
| 7715 #endif | |
| 7716 | |
| 7717 /******************************************************************************/ | |
| 7718 #ifdef SOAP_MEM_DEBUG | |
| 7719 SOAP_FMAC1 | |
| 7720 void | |
| 7721 SOAP_FMAC2 | |
| 7722 soap_track_free(struct soap *soap, const char *file, int line, void *p) | |
| 7723 { register size_t h = soap_hash_ptr(p); | |
| 7724 register struct soap_mlist *mp; | |
| 7725 for (mp = soap->mht[h]; mp; mp = mp->next) | |
| 7726 if (mp->ptr == p) | |
| 7727 break; | |
| 7728 if (mp) | |
| 7729 { if (mp->live) | |
| 7730 { free(p); | |
| 7731 if (soap->fdebug[SOAP_INDEX_TEST]) | |
| 7732 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): free(%p)\n", file, line, p)); | |
| 7733 } | |
| 7734 mp->live = 0; | |
| 7735 } | |
| 7736 else | |
| 7737 fprintf(stderr, "%s(%d): free(%p) double free of pointer malloced at %s(%d)\n", file, line, p, mp->file, mp->line); | |
| 7738 } | |
| 7739 else | |
| 7740 fprintf(stderr, "%s(%d): free(%p) pointer not malloced\n", file, line, p); | |
| 7741 } | |
| 7742 #endif | |
| 7743 | |
| 7744 /******************************************************************************/ | |
| 7745 #ifdef SOAP_MEM_DEBUG | |
| 7746 static void | |
| 7747 soap_track_unlink(struct soap *soap, const void *p) | |
| 7748 { register size_t h = soap_hash_ptr(p); | |
| 7749 register struct soap_mlist *mp; | |
| 7750 for (mp = soap->mht[h]; mp; mp = mp->next) | |
| 7751 if (mp->ptr == p) | |
| 7752 break; | |
| 7753 if (mp) | |
| 7754 mp->live = 0; | |
| 7755 } | |
| 7756 #endif | |
| 7757 | |
| 7758 /******************************************************************************/ | |
| 7759 #ifndef PALM_2 | |
| 7760 SOAP_FMAC1 | |
| 7761 void | |
| 7762 SOAP_FMAC2 | |
| 7763 soap_dealloc(struct soap *soap, void *p) | |
| 7764 { if (soap_check_state(soap)) | |
| 7765 return; | |
| 7766 if (p) | |
| 7767 { register char **q; | |
| 7768 for (q = (char**)&soap->alist; *q; q = *(char***)q) | |
| 7769 { | |
| 7770 if (*(unsigned short*)(char*)(*q - sizeof(unsigned short)) != (unsigned short)SOAP_CANARY) | |
| 7771 { | |
| 7772 #ifdef SOAP_MEM_DEBUG | |
| 7773 fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n"); | |
| 7774 #endif | |
| 7775 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n")); | |
| 7776 DBGHEX(TEST, *q - 200, 200); | |
| 7777 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n")); | |
| 7778 soap->error = SOAP_MOE; | |
| 7779 return; | |
| 7780 } | |
| 7781 if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*)))) | |
| 7782 { *q = **(char***)q; | |
| 7783 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Freed data at %p\n", p)); | |
| 7784 SOAP_FREE(soap, p); | |
| 7785 return; | |
| 7786 } | |
| 7787 } | |
| 7788 soap_delete(soap, p); | |
| 7789 } | |
| 7790 else | |
| 7791 { register char *q; | |
| 7792 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free all soap_malloc() data\n")); | |
| 7793 while (soap->alist) | |
| 7794 { q = (char*)soap->alist; | |
| 7795 if (*(unsigned short*)(char*)(q - sizeof(unsigned short)) != (unsigned short)SOAP_CANARY) | |
| 7796 { | |
| 7797 #ifdef SOAP_MEM_DEBUG | |
| 7798 fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n"); | |
| 7799 #endif | |
| 7800 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n")); | |
| 7801 DBGHEX(TEST, q - 200, 200); | |
| 7802 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n")); | |
| 7803 soap->error = SOAP_MOE; | |
| 7804 return; | |
| 7805 } | |
| 7806 soap->alist = *(void**)q; | |
| 7807 q -= *(size_t*)(q + sizeof(void*)); | |
| 7808 SOAP_FREE(soap, q); | |
| 7809 } | |
| 7810 /* we must assume these were deallocated: */ | |
| 7811 soap->http_content = NULL; | |
| 7812 soap->action = NULL; | |
| 7813 soap->fault = NULL; | |
| 7814 soap->header = NULL; | |
| 7815 soap->userid = NULL; | |
| 7816 soap->passwd = NULL; | |
| 7817 soap->authrealm = NULL; | |
| 7818 #ifdef WITH_NTLM | |
| 7819 soap->ntlm_challenge = NULL; | |
| 7820 #endif | |
| 7821 #ifndef WITH_LEANER | |
| 7822 soap_clr_mime(soap); | |
| 7823 #endif | |
| 7824 } | |
| 7825 } | |
| 7826 #endif | |
| 7827 | |
| 7828 /******************************************************************************/ | |
| 7829 #ifndef PALM_2 | |
| 7830 SOAP_FMAC1 | |
| 7831 void | |
| 7832 SOAP_FMAC2 | |
| 7833 soap_delete(struct soap *soap, void *p) | |
| 7834 { register struct soap_clist **cp; | |
| 7835 if (soap_check_state(soap)) | |
| 7836 return; | |
| 7837 cp = &soap->clist; | |
| 7838 if (p) | |
| 7839 { while (*cp) | |
| 7840 { if (p == (*cp)->ptr) | |
| 7841 { register struct soap_clist *q = *cp; | |
| 7842 *cp = q->next; | |
| 7843 if (q->fdelete(q)) | |
| 7844 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: deletion callback failed for object type %d\n", q->ptr, q->type)); | |
| 7845 #ifdef SOAP_MEM_DEBUG | |
| 7846 fprintf(stderr, "new(object type = %d) = %p not freed: deletion callback failed\n", q->type, q->ptr); | |
| 7847 #endif | |
| 7848 } | |
| 7849 SOAP_FREE(soap, q); | |
| 7850 return; | |
| 7851 } | |
| 7852 cp = &(*cp)->next; | |
| 7853 } | |
| 7854 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: address not in list\n", p)); | |
| 7855 } | |
| 7856 else | |
| 7857 { while (*cp) | |
| 7858 { register struct soap_clist *q = *cp; | |
| 7859 *cp = q->next; | |
| 7860 if (q->fdelete(q)) | |
| 7861 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: deletion callback failed for object type %d\n", q->ptr, q->type)); | |
| 7862 #ifdef SOAP_MEM_DEBUG | |
| 7863 fprintf(stderr, "new(object type = %d) = %p not freed: deletion callback failed\n", q->type, q->ptr); | |
| 7864 #endif | |
| 7865 } | |
| 7866 SOAP_FREE(soap, q); | |
| 7867 } | |
| 7868 } | |
| 7869 soap->fault = NULL; /* this was possibly deallocated */ | |
| 7870 soap->header = NULL; /* this was possibly deallocated */ | |
| 7871 } | |
| 7872 #endif | |
| 7873 | |
| 7874 /******************************************************************************/ | |
| 7875 #ifndef PALM_2 | |
| 7876 SOAP_FMAC1 | |
| 7877 void | |
| 7878 SOAP_FMAC2 | |
| 7879 soap_delegate_deletion(struct soap *soap, struct soap *soap_to) | |
| 7880 { register struct soap_clist *cp; | |
| 7881 register char **q; | |
| 7882 #ifdef SOAP_MEM_DEBUG | |
| 7883 register void *p; | |
| 7884 register struct soap_mlist **mp, *mq; | |
| 7885 size_t h; | |
| 7886 #endif | |
| 7887 for (q = (char**)&soap->alist; *q; q = *(char***)q) | |
| 7888 { | |
| 7889 if (*(unsigned short*)(char*)(*q - sizeof(unsigned short)) != (unsigned short)SOAP_CANARY) | |
| 7890 { | |
| 7891 #ifdef SOAP_MEM_DEBUG | |
| 7892 fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n"); | |
| 7893 #endif | |
| 7894 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n")); | |
| 7895 DBGHEX(TEST, *q - 200, 200); | |
| 7896 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n")); | |
| 7897 soap->error = SOAP_MOE; | |
| 7898 return; | |
| 7899 } | |
| 7900 #ifdef SOAP_MEM_DEBUG | |
| 7901 p = (void*)(*q - *(size_t*)(*q + sizeof(void*))); | |
| 7902 h = soap_hash_ptr(p); | |
| 7903 for (mp = &soap->mht[h]; *mp; mp = &(*mp)->next) | |
| 7904 { if ((*mp)->ptr == p) | |
| 7905 { mq = *mp; | |
| 7906 *mp = mq->next; | |
| 7907 mq->next = soap_to->mht[h]; | |
| 7908 soap_to->mht[h] = mq; | |
| 7909 break; | |
| 7910 } | |
| 7911 } | |
| 7912 #endif | |
| 7913 } | |
| 7914 *q = (char*)soap_to->alist; | |
| 7915 soap_to->alist = soap->alist; | |
| 7916 soap->alist = NULL; | |
| 7917 #ifdef SOAP_MEM_DEBUG | |
| 7918 cp = soap->clist; | |
| 7919 while (cp) | |
| 7920 { h = soap_hash_ptr(cp); | |
| 7921 for (mp = &soap->mht[h]; *mp; mp = &(*mp)->next) | |
| 7922 { if ((*mp)->ptr == cp) | |
| 7923 { mq = *mp; | |
| 7924 *mp = mq->next; | |
| 7925 mq->next = soap_to->mht[h]; | |
| 7926 soap_to->mht[h] = mq; | |
| 7927 break; | |
| 7928 } | |
| 7929 } | |
| 7930 cp = cp->next; | |
| 7931 } | |
| 7932 #endif | |
| 7933 cp = soap_to->clist; | |
| 7934 if (cp) | |
| 7935 { while (cp->next) | |
| 7936 cp = cp->next; | |
| 7937 cp->next = soap->clist; | |
| 7938 } | |
| 7939 else | |
| 7940 soap_to->clist = soap->clist; | |
| 7941 soap->clist = NULL; | |
| 7942 } | |
| 7943 #endif | |
| 7944 | |
| 7945 /******************************************************************************/ | |
| 7946 #ifndef PALM_2 | |
| 7947 SOAP_FMAC1 | |
| 7948 struct soap_clist * | |
| 7949 SOAP_FMAC2 | |
| 7950 soap_link(struct soap *soap, void *p, int t, int n, int (*fdelete)(struct soap_clist*)) | |
| 7951 { register struct soap_clist *cp; | |
| 7952 if ((cp = (struct soap_clist*)SOAP_MALLOC(soap, sizeof(struct soap_clist)))) | |
| 7953 { cp->next = soap->clist; | |
| 7954 cp->type = t; | |
| 7955 cp->size = n; | |
| 7956 cp->ptr = p; | |
| 7957 cp->fdelete = fdelete; | |
| 7958 soap->clist = cp; | |
| 7959 } | |
| 7960 return cp; | |
| 7961 } | |
| 7962 #endif | |
| 7963 | |
| 7964 /******************************************************************************/ | |
| 7965 #ifndef PALM_2 | |
| 7966 SOAP_FMAC1 | |
| 7967 int | |
| 7968 SOAP_FMAC2 | |
| 7969 soap_unlink(struct soap *soap, const void *p) | |
| 7970 { register char **q; | |
| 7971 register struct soap_clist **cp; | |
| 7972 if (soap && p) | |
| 7973 { for (q = (char**)&soap->alist; *q; q = *(char***)q) | |
| 7974 { if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*)))) | |
| 7975 { *q = **(char***)q; | |
| 7976 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked data %p\n", p)); | |
| 7977 #ifdef SOAP_MEM_DEBUG | |
| 7978 soap_track_unlink(soap, p); | |
| 7979 #endif | |
| 7980 return SOAP_OK; /* found and removed from dealloc chain */ | |
| 7981 } | |
| 7982 } | |
| 7983 for (cp = &soap->clist; *cp; cp = &(*cp)->next) | |
| 7984 { if (p == (*cp)->ptr) | |
| 7985 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked class instance %p\n", p)); | |
| 7986 q = (char**)*cp; | |
| 7987 *cp = (*cp)->next; | |
| 7988 SOAP_FREE(soap, q); | |
| 7989 return SOAP_OK; /* found and removed from dealloc chain */ | |
| 7990 } | |
| 7991 } | |
| 7992 } | |
| 7993 return SOAP_ERR; | |
| 7994 } | |
| 7995 #endif | |
| 7996 | |
| 7997 /******************************************************************************/ | |
| 7998 #ifndef WITH_NOIDREF | |
| 7999 #ifndef PALM_2 | |
| 8000 SOAP_FMAC1 | |
| 8001 int | |
| 8002 SOAP_FMAC2 | |
| 8003 soap_lookup_type(struct soap *soap, const char *id) | |
| 8004 { register struct soap_ilist *ip; | |
| 8005 if (id && *id) | |
| 8006 { ip = soap_lookup(soap, id); | |
| 8007 if (ip) | |
| 8008 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup id='%s' type=%d\n", id, ip->type)); | |
| 8009 return ip->type; | |
| 8010 } | |
| 8011 } | |
| 8012 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "lookup type id='%s' NOT FOUND! Need to get it from xsi:type\n", id)); | |
| 8013 return 0; | |
| 8014 } | |
| 8015 #endif | |
| 8016 #endif | |
| 8017 | |
| 8018 /******************************************************************************/ | |
| 8019 #ifndef WITH_NOIDREF | |
| 8020 #ifndef PALM_2 | |
| 8021 SOAP_FMAC1 | |
| 8022 void* | |
| 8023 SOAP_FMAC2 | |
| 8024 soap_id_lookup(struct soap *soap, const char *id, void **p, int t, size_t n, unsigned int k) | |
| 8025 { struct soap_ilist *ip; | |
| 8026 void **q; | |
| 8027 if (!p || !id || !*id) | |
| 8028 return p; | |
| 8029 ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */ | |
| 8030 if (!ip) | |
| 8031 { if (!(ip = soap_enter(soap, id))) /* new hash table entry for string id */ | |
| 8032 return NULL; | |
| 8033 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding first href='%s' type=%d %p (%u bytes)\n", id, t, p, (unsigned int)n)); | |
| 8034 ip->type = t; | |
| 8035 ip->size = n; | |
| 8036 ip->link = p; | |
| 8037 ip->copy = NULL; | |
| 8038 ip->flist = NULL; | |
| 8039 ip->ptr = NULL; | |
| 8040 ip->level = k; | |
| 8041 *p = NULL; | |
| 8042 } | |
| 8043 else if (ip->ptr) | |
| 8044 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolved href='%s' type=%d location=%p (%u bytes)\n", id, t, ip->ptr, (unsigned int)n)); | |
| 8045 if (ip->type != t) | |
| 8046 { strcpy(soap->id, id); | |
| 8047 soap->error = SOAP_HREF; | |
| 8048 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility: href='%s' id-type=%d href-type=%d\n", id, ip->type, t)); | |
| 8049 return NULL; | |
| 8050 } | |
| 8051 while (ip->level < k) | |
| 8052 { q = (void**)soap_malloc(soap, sizeof(void*)); | |
| 8053 if (!q) | |
| 8054 return NULL; | |
| 8055 *p = (void*)q; | |
| 8056 p = q; | |
| 8057 k--; | |
| 8058 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); | |
| 8059 } | |
| 8060 *p = ip->ptr; | |
| 8061 } | |
| 8062 else if (ip->level > k) | |
| 8063 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving level %u pointers to href='%s'\n", ip->level, id)); | |
| 8064 while (ip->level > k) | |
| 8065 { void *s, **r = &ip->link; | |
| 8066 q = (void**)ip->link; | |
| 8067 while (q) | |
| 8068 { *r = (void*)soap_malloc(soap, sizeof(void*)); | |
| 8069 if (!*r) | |
| 8070 return NULL; | |
| 8071 s = *q; | |
| 8072 *q = *r; | |
| 8073 r = (void**)*r; | |
| 8074 q = (void**)s; | |
| 8075 } | |
| 8076 *r = NULL; | |
| 8077 ip->size = n; | |
| 8078 ip->copy = NULL; | |
| 8079 ip->level = ip->level - 1; | |
| 8080 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); | |
| 8081 } | |
| 8082 q = (void**)ip->link; | |
| 8083 ip->link = p; | |
| 8084 *p = (void*)q; | |
| 8085 } | |
| 8086 else | |
| 8087 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarded href='%s' type=%d location=%p (%u bytes)\n", id, t, p, (unsigned int)n)); | |
| 8088 while (ip->level < k) | |
| 8089 { q = (void**)soap_malloc(soap, sizeof(void*)); | |
| 8090 if (!q) | |
| 8091 return NULL; | |
| 8092 *p = q; | |
| 8093 p = q; | |
| 8094 k--; | |
| 8095 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); | |
| 8096 } | |
| 8097 q = (void**)ip->link; | |
| 8098 ip->link = p; | |
| 8099 *p = (void*)q; | |
| 8100 } | |
| 8101 return p; | |
| 8102 } | |
| 8103 #endif | |
| 8104 #endif | |
| 8105 | |
| 8106 /******************************************************************************/ | |
| 8107 #ifndef WITH_NOIDREF | |
| 8108 #ifndef PALM_2 | |
| 8109 SOAP_FMAC1 | |
| 8110 void* | |
| 8111 SOAP_FMAC2 | |
| 8112 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)) | |
| 8113 { struct soap_ilist *ip; | |
| 8114 if (!p || !href || !*href) | |
| 8115 return p; | |
| 8116 ip = soap_lookup(soap, href); /* lookup pointer to hash table entry for string id */ | |
| 8117 if (!ip) | |
| 8118 { if (!(ip = soap_enter(soap, href))) /* new hash table entry for string id */ | |
| 8119 return NULL; | |
| 8120 ip->type = st; | |
| 8121 ip->size = n; | |
| 8122 ip->link = NULL; | |
| 8123 ip->copy = NULL; | |
| 8124 ip->ptr = NULL; | |
| 8125 ip->level = 0; | |
| 8126 ip->flist = NULL; | |
| 8127 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)); | |
| 8128 } | |
| 8129 else if (ip->type != st || (ip->level == k && ip->size != n)) | |
| 8130 { 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)); | |
| 8131 strcpy(soap->id, href); | |
| 8132 soap->error = SOAP_HREF; | |
| 8133 return NULL; | |
| 8134 } | |
| 8135 if (fcopy || n < sizeof(void*) || *href != '#') | |
| 8136 { register struct soap_flist *fp = (struct soap_flist*)SOAP_MALLOC(soap, sizeof(struct soap_flist)); | |
| 8137 if (!fp) | |
| 8138 { soap->error = SOAP_EOM; | |
| 8139 return NULL; | |
| 8140 } | |
| 8141 fp->next = ip->flist; | |
| 8142 fp->type = tt; | |
| 8143 fp->ptr = p; | |
| 8144 fp->level = k; | |
| 8145 fp->len = len; | |
| 8146 if (fcopy) | |
| 8147 fp->fcopy = fcopy; | |
| 8148 else | |
| 8149 fp->fcopy = soap_fcopy; | |
| 8150 ip->flist = fp; | |
| 8151 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)); | |
| 8152 } | |
| 8153 else | |
| 8154 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding copying address %p for type=%d href='%s'\n", p, st, href)); | |
| 8155 *(void**)p = ip->copy; | |
| 8156 ip->copy = p; | |
| 8157 } | |
| 8158 return p; | |
| 8159 } | |
| 8160 #endif | |
| 8161 #endif | |
| 8162 | |
| 8163 /******************************************************************************/ | |
| 8164 #ifndef PALM_2 | |
| 8165 SOAP_FMAC1 | |
| 8166 void* | |
| 8167 SOAP_FMAC2 | |
| 8168 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*)) | |
| 8169 { | |
| 8170 #ifndef WITH_NOIDREF | |
| 8171 struct soap_ilist *ip; | |
| 8172 #endif | |
| 8173 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Enter id='%s' type=%d loc=%p size=%lu level=%u\n", id, t, p, (unsigned long)n, k)); | |
| 8174 soap->alloced = 0; | |
| 8175 if (!p) | |
| 8176 { if (finstantiate) | |
| 8177 p = finstantiate(soap, t, type, arrayType, &n); | |
| 8178 else | |
| 8179 p = soap_malloc(soap, n); | |
| 8180 if (p) | |
| 8181 soap->alloced = 1; | |
| 8182 } | |
| 8183 #ifndef WITH_NOIDREF | |
| 8184 if (!id || !*id) | |
| 8185 #endif | |
| 8186 return p; | |
| 8187 #ifndef WITH_NOIDREF | |
| 8188 ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */ | |
| 8189 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Lookup entry id='%s for location=%p'\n", id, p)); | |
| 8190 if (!ip) | |
| 8191 { if (!(ip = soap_enter(soap, id))) /* new hash table entry for string id */ | |
| 8192 return NULL; | |
| 8193 ip->type = t; | |
| 8194 ip->link = NULL; | |
| 8195 ip->copy = NULL; | |
| 8196 ip->flist = NULL; | |
| 8197 ip->size = n; | |
| 8198 ip->ptr = p; | |
| 8199 ip->level = k; | |
| 8200 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)); | |
| 8201 } | |
| 8202 else if ((ip->type != t || (ip->level == k && ip->size != n)) && (ip->copy || ip->flist)) | |
| 8203 { 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)); | |
| 8204 strcpy(soap->id, id); | |
| 8205 soap->error = SOAP_HREF; | |
| 8206 return NULL; | |
| 8207 } | |
| 8208 else if (ip->ptr) | |
| 8209 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Multiply defined id='%s'\n", id)); | |
| 8210 strcpy(soap->id, id); | |
| 8211 soap->error = SOAP_DUPLICATE_ID; | |
| 8212 return NULL; | |
| 8213 } | |
| 8214 else | |
| 8215 { ip->size = n; | |
| 8216 ip->ptr = p; | |
| 8217 ip->level = k; | |
| 8218 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)); | |
| 8219 } | |
| 8220 return ip->ptr; | |
| 8221 #endif | |
| 8222 } | |
| 8223 #endif | |
| 8224 | |
| 8225 /******************************************************************************/ | |
| 8226 #ifndef PALM_2 | |
| 8227 SOAP_FMAC1 | |
| 8228 void | |
| 8229 SOAP_FMAC2 | |
| 8230 soap_fcopy(struct soap *soap, int st, int tt, void *p, size_t len, const void *q, size_t n) | |
| 8231 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Copying data type=%d (target type=%d) %p -> %p (%lu bytes)\n", st, tt, q, p, (unsigned long)n)); | |
| 8232 memcpy(p, q, n); | |
| 8233 (void)soap; (void)st; (void)tt; (void)len; | |
| 8234 } | |
| 8235 #endif | |
| 8236 | |
| 8237 /******************************************************************************/ | |
| 8238 #ifndef PALM_1 | |
| 8239 SOAP_FMAC1 | |
| 8240 int | |
| 8241 SOAP_FMAC2 | |
| 8242 soap_end_send(struct soap *soap) | |
| 8243 { | |
| 8244 #ifndef WITH_LEANER | |
| 8245 int err; | |
| 8246 if (soap->dime.list) | |
| 8247 { /* SOAP body referenced attachments must appear first */ | |
| 8248 soap->dime.last->next = soap->dime.first; | |
| 8249 soap->dime.first = soap->dime.list->next; | |
| 8250 soap->dime.list->next = NULL; | |
| 8251 soap->dime.last = soap->dime.list; | |
| 8252 } | |
| 8253 if (!(err = soap_putdime(soap))) | |
| 8254 err = soap_putmime(soap); | |
| 8255 soap->mime.list = NULL; | |
| 8256 soap->mime.first = NULL; | |
| 8257 soap->mime.last = NULL; | |
| 8258 soap->dime.list = NULL; | |
| 8259 soap->dime.first = NULL; | |
| 8260 soap->dime.last = NULL; | |
| 8261 if (err) | |
| 8262 return err; | |
| 8263 #endif | |
| 8264 return soap_end_send_flush(soap); | |
| 8265 } | |
| 8266 #endif | |
| 8267 | |
| 8268 /******************************************************************************/ | |
| 8269 #ifndef PALM_1 | |
| 8270 SOAP_FMAC1 | |
| 8271 int | |
| 8272 SOAP_FMAC2 | |
| 8273 soap_end_send_flush(struct soap *soap) | |
| 8274 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End send mode=0x%x\n", soap->mode)); | |
| 8275 if (soap->mode & SOAP_IO) /* need to flush the remaining data in buffer */ | |
| 8276 { if (soap_flush(soap)) | |
| 8277 #ifdef WITH_ZLIB | |
| 8278 { if (soap->mode & SOAP_ENC_ZLIB && soap->zlib_state == SOAP_ZLIB_DEFLATE) | |
| 8279 { soap->zlib_state = SOAP_ZLIB_NONE; | |
| 8280 deflateEnd(soap->d_stream); | |
| 8281 } | |
| 8282 return soap->error; | |
| 8283 } | |
| 8284 #else | |
| 8285 return soap->error; | |
| 8286 #endif | |
| 8287 #ifdef WITH_ZLIB | |
| 8288 if (soap->mode & SOAP_ENC_ZLIB) | |
| 8289 { int r; | |
| 8290 soap->d_stream->avail_in = 0; | |
| 8291 do | |
| 8292 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating remainder\n")); | |
| 8293 r = deflate(soap->d_stream, Z_FINISH); | |
| 8294 if (soap->d_stream->avail_out != SOAP_BUFLEN) | |
| 8295 { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN - soap->d_stream->avail_out)) | |
| 8296 { soap->zlib_state = SOAP_ZLIB_NONE; | |
| 8297 deflateEnd(soap->d_stream); | |
| 8298 return soap->error; | |
| 8299 } | |
| 8300 soap->d_stream->next_out = (Byte*)soap->z_buf; | |
| 8301 soap->d_stream->avail_out = SOAP_BUFLEN; | |
| 8302 } | |
| 8303 } while (r == Z_OK); | |
| 8304 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflated total %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out)); | |
| 8305 soap->z_ratio_out = (float)soap->d_stream->total_out / (float)soap->d_stream->total_in; | |
| 8306 soap->mode &= ~SOAP_ENC_ZLIB; | |
| 8307 soap->zlib_state = SOAP_ZLIB_NONE; | |
| 8308 if (deflateEnd(soap->d_stream) != Z_OK || r != Z_STREAM_END) | |
| 8309 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to end deflate: %s\n", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS)); | |
| 8310 return soap->error = SOAP_ZLIB_ERROR; | |
| 8311 } | |
| 8312 #ifdef WITH_GZIP | |
| 8313 if (soap->zlib_out != SOAP_ZLIB_DEFLATE) | |
| 8314 { soap->z_buf[0] = soap->z_crc & 0xFF; | |
| 8315 soap->z_buf[1] = (soap->z_crc >> 8) & 0xFF; | |
| 8316 soap->z_buf[2] = (soap->z_crc >> 16) & 0xFF; | |
| 8317 soap->z_buf[3] = (soap->z_crc >> 24) & 0xFF; | |
| 8318 soap->z_buf[4] = soap->d_stream->total_in & 0xFF; | |
| 8319 soap->z_buf[5] = (soap->d_stream->total_in >> 8) & 0xFF; | |
| 8320 soap->z_buf[6] = (soap->d_stream->total_in >> 16) & 0xFF; | |
| 8321 soap->z_buf[7] = (soap->d_stream->total_in >> 24) & 0xFF; | |
| 8322 if (soap_flush_raw(soap, soap->z_buf, 8)) | |
| 8323 return soap->error; | |
| 8324 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip crc32=%lu\n", (unsigned long)soap->z_crc)); | |
| 8325 } | |
| 8326 #endif | |
| 8327 } | |
| 8328 #endif | |
| 8329 if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) | |
| 8330 { char *p; | |
| 8331 #ifndef WITH_NOHTTP | |
| 8332 if (!(soap->mode & SOAP_ENC_XML)) | |
| 8333 { soap->mode--; | |
| 8334 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending buffered message of length %u\n", (unsigned int)soap->blist->size)); | |
| 8335 if (soap->status >= SOAP_POST) | |
| 8336 soap->error = soap->fpost(soap, soap->endpoint, soap->host, soap->port, soap->path, soap->action, soap->blist->size); | |
| 8337 else if (soap->status != SOAP_STOP) | |
| 8338 soap->error = soap->fresponse(soap, soap->status, soap->blist->size); | |
| 8339 if (soap->error || soap_flush(soap)) | |
| 8340 return soap->error; | |
| 8341 soap->mode++; | |
| 8342 } | |
| 8343 #endif | |
| 8344 for (p = soap_first_block(soap, NULL); p; p = soap_next_block(soap, NULL)) | |
| 8345 { DBGMSG(SENT, p, soap_block_size(soap, NULL)); | |
| 8346 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Send %u bytes to socket=%d/fd=%d\n", (unsigned int)soap_block_size(soap, NULL), soap->socket, soap->sendfd)); | |
| 8347 if ((soap->error = soap->fsend(soap, p, soap_block_size(soap, NULL)))) | |
| 8348 { soap_end_block(soap, NULL); | |
| 8349 return soap->error; | |
| 8350 } | |
| 8351 } | |
| 8352 soap_end_block(soap, NULL); | |
| 8353 if (soap->fpreparefinalsend && (soap->error = soap->fpreparefinalsend(soap))) | |
| 8354 return soap->error; | |
| 8355 } | |
| 8356 #ifndef WITH_LEANER | |
| 8357 else if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) | |
| 8358 { DBGMSG(SENT, "\r\n0\r\n\r\n", 7); | |
| 8359 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Send 7 bytes to socket=%d/fd=%d\n", soap->socket, soap->sendfd)); | |
| 8360 if ((soap->error = soap->fsend(soap, "\r\n0\r\n\r\n", 7))) | |
| 8361 return soap->error; | |
| 8362 } | |
| 8363 #endif | |
| 8364 } | |
| 8365 #ifdef WITH_TCPFIN | |
| 8366 #ifdef WITH_OPENSSL | |
| 8367 if (!soap->ssl && soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP)) | |
| 8368 soap->fshutdownsocket(soap, soap->socket, SOAP_SHUT_WR); /* Send TCP FIN */ | |
| 8369 #else | |
| 8370 if (soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP)) | |
| 8371 soap->fshutdownsocket(soap, soap->socket, SOAP_SHUT_WR); /* Send TCP FIN */ | |
| 8372 #endif | |
| 8373 #endif | |
| 8374 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of send phase\n")); | |
| 8375 soap->omode &= ~SOAP_SEC_WSUID; | |
| 8376 soap->count = 0; | |
| 8377 soap->part = SOAP_END; | |
| 8378 return SOAP_OK; | |
| 8379 } | |
| 8380 #endif | |
| 8381 | |
| 8382 /******************************************************************************/ | |
| 8383 #ifndef PALM_1 | |
| 8384 SOAP_FMAC1 | |
| 8385 int | |
| 8386 SOAP_FMAC2 | |
| 8387 soap_end_recv(struct soap *soap) | |
| 8388 { soap->part = SOAP_END; | |
| 8389 #ifndef WITH_LEAN | |
| 8390 soap->wsuid = NULL; /* reset before next send */ | |
| 8391 soap->c14nexclude = NULL; /* reset before next send */ | |
| 8392 #endif | |
| 8393 #ifndef WITH_LEANER | |
| 8394 soap->ffilterrecv = NULL; | |
| 8395 if ((soap->mode & SOAP_ENC_DIME) && soap_getdime(soap)) | |
| 8396 { soap->dime.first = NULL; | |
| 8397 soap->dime.last = NULL; | |
| 8398 return soap->error; | |
| 8399 } | |
| 8400 soap->dime.list = soap->dime.first; | |
| 8401 soap->dime.first = NULL; | |
| 8402 soap->dime.last = NULL; | |
| 8403 /* Check if MIME attachments and mime-post-check flag is set, if so call soap_resolve() and return */ | |
| 8404 if (soap->mode & SOAP_ENC_MIME) | |
| 8405 { if (soap->mode & SOAP_MIME_POSTCHECK) | |
| 8406 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Post checking MIME attachments\n")); | |
| 8407 if (!soap->keep_alive) | |
| 8408 soap->keep_alive = -1; | |
| 8409 #ifndef WITH_NOIDREF | |
| 8410 soap_resolve(soap); | |
| 8411 #endif | |
| 8412 return SOAP_OK; | |
| 8413 } | |
| 8414 if (soap_getmime(soap)) | |
| 8415 return soap->error; | |
| 8416 } | |
| 8417 soap->mime.list = soap->mime.first; | |
| 8418 soap->mime.first = NULL; | |
| 8419 soap->mime.last = NULL; | |
| 8420 soap->mime.boundary = NULL; | |
| 8421 if (soap->xlist) | |
| 8422 { struct soap_multipart *content; | |
| 8423 for (content = soap->mime.list; content; content = content->next) | |
| 8424 soap_resolve_attachment(soap, content); | |
| 8425 } | |
| 8426 #endif | |
| 8427 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "End of receive message ok\n")); | |
| 8428 #ifdef WITH_ZLIB | |
| 8429 if (soap->mode & SOAP_ENC_ZLIB) | |
| 8430 { /* Make sure end of compressed content is reached */ | |
| 8431 while (soap->d_stream->next_out != Z_NULL) | |
| 8432 if ((int)soap_get1(soap) == EOF) | |
| 8433 break; | |
| 8434 soap->mode &= ~SOAP_ENC_ZLIB; | |
| 8435 memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN); | |
| 8436 soap->bufidx = (char*)soap->d_stream->next_in - soap->z_buf; | |
| 8437 soap->buflen = soap->z_buflen; | |
| 8438 soap->zlib_state = SOAP_ZLIB_NONE; | |
| 8439 if (inflateEnd(soap->d_stream) != Z_OK) | |
| 8440 return soap->error = SOAP_ZLIB_ERROR; | |
| 8441 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Inflate end ok\n")); | |
| 8442 #ifdef WITH_GZIP | |
| 8443 if (soap->zlib_in == SOAP_ZLIB_GZIP) | |
| 8444 { soap_wchar c; | |
| 8445 short i; | |
| 8446 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Inflate gzip crc check\n")); | |
| 8447 for (i = 0; i < 8; i++) | |
| 8448 { if ((int)(c = soap_get1(soap)) == EOF) | |
| 8449 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: unable to read crc value\n")); | |
| 8450 return soap->error = SOAP_ZLIB_ERROR; | |
| 8451 } | |
| 8452 soap->z_buf[i] = (char)c; | |
| 8453 } | |
| 8454 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))) | |
| 8455 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip inflate error: crc check failed, message corrupted? (crc32=%lu)\n", (unsigned long)soap->z_crc)); | |
| 8456 return soap->error = SOAP_ZLIB_ERROR; | |
| 8457 } | |
| 8458 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))) | |
| 8459 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip inflate error: incorrect message length\n")); | |
| 8460 return soap->error = SOAP_ZLIB_ERROR; | |
| 8461 } | |
| 8462 } | |
| 8463 soap->zlib_in = SOAP_ZLIB_NONE; | |
| 8464 #endif | |
| 8465 } | |
| 8466 #endif | |
| 8467 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) | |
| 8468 while (soap->ahead != EOF && !soap_recv_raw(soap)) | |
| 8469 ; | |
| 8470 #ifndef WITH_NOIDREF | |
| 8471 if (soap_resolve(soap)) | |
| 8472 return soap->error; | |
| 8473 #endif | |
| 8474 #ifndef WITH_LEANER | |
| 8475 if (soap->xlist) | |
| 8476 { if (soap->mode & SOAP_ENC_MTOM) | |
| 8477 return soap->error = SOAP_MIME_HREF; | |
| 8478 return soap->error = SOAP_DIME_HREF; | |
| 8479 } | |
| 8480 #endif | |
| 8481 soap_free_ns(soap); | |
| 8482 #ifndef WITH_LEANER | |
| 8483 if (soap->fpreparefinalrecv) | |
| 8484 return soap->error = soap->fpreparefinalrecv(soap); | |
| 8485 #endif | |
| 8486 return SOAP_OK; | |
| 8487 } | |
| 8488 #endif | |
| 8489 | |
| 8490 /******************************************************************************/ | |
| 8491 #ifndef PALM_1 | |
| 8492 SOAP_FMAC1 | |
| 8493 void | |
| 8494 SOAP_FMAC2 | |
| 8495 soap_free_temp(struct soap *soap) | |
| 8496 { register struct soap_attribute *tp, *tq; | |
| 8497 register struct Namespace *ns; | |
| 8498 soap_free_ns(soap); | |
| 8499 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free any remaining temp blocks\n")); | |
| 8500 while (soap->blist) | |
| 8501 soap_end_block(soap, NULL); | |
| 8502 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute storage\n")); | |
| 8503 for (tp = soap->attributes; tp; tp = tq) | |
| 8504 { tq = tp->next; | |
| 8505 if (tp->value) | |
| 8506 SOAP_FREE(soap, tp->value); | |
| 8507 SOAP_FREE(soap, tp); | |
| 8508 } | |
| 8509 soap->attributes = NULL; | |
| 8510 #ifdef WITH_FAST | |
| 8511 if (soap->labbuf) | |
| 8512 SOAP_FREE(soap, soap->labbuf); | |
| 8513 soap->labbuf = NULL; | |
| 8514 soap->lablen = 0; | |
| 8515 soap->labidx = 0; | |
| 8516 #endif | |
| 8517 ns = soap->local_namespaces; | |
| 8518 if (ns) | |
| 8519 { for (; ns->id; ns++) | |
| 8520 { if (ns->out) | |
| 8521 { SOAP_FREE(soap, ns->out); | |
| 8522 ns->out = NULL; | |
| 8523 } | |
| 8524 } | |
| 8525 SOAP_FREE(soap, soap->local_namespaces); | |
| 8526 soap->local_namespaces = NULL; | |
| 8527 } | |
| 8528 #ifndef WITH_LEANER | |
| 8529 while (soap->xlist) | |
| 8530 { struct soap_xlist *xp = soap->xlist->next; | |
| 8531 SOAP_FREE(soap, soap->xlist); | |
| 8532 soap->xlist = xp; | |
| 8533 } | |
| 8534 #endif | |
| 8535 #ifndef WITH_NOIDREF | |
| 8536 soap_free_pht(soap); | |
| 8537 soap_free_iht(soap); | |
| 8538 #endif | |
| 8539 } | |
| 8540 #endif | |
| 8541 | |
| 8542 /******************************************************************************/ | |
| 8543 #ifndef PALM_1 | |
| 8544 static void | |
| 8545 soap_free_ns(struct soap *soap) | |
| 8546 { register struct soap_nlist *np, *nq; | |
| 8547 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free namespace stack\n")); | |
| 8548 for (np = soap->nlist; np; np = nq) | |
| 8549 { nq = np->next; | |
| 8550 SOAP_FREE(soap, np); | |
| 8551 } | |
| 8552 soap->nlist = NULL; | |
| 8553 } | |
| 8554 #endif | |
| 8555 | |
| 8556 /******************************************************************************/ | |
| 8557 #ifndef PALM_1 | |
| 8558 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG) | |
| 8559 static void | |
| 8560 soap_init_logs(struct soap *soap) | |
| 8561 { int i; | |
| 8562 for (i = 0; i < SOAP_MAXLOGS; i++) | |
| 8563 { soap->logfile[i] = NULL; | |
| 8564 soap->fdebug[i] = NULL; | |
| 8565 } | |
| 8566 } | |
| 8567 #endif | |
| 8568 #endif | |
| 8569 | |
| 8570 /******************************************************************************/ | |
| 8571 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG) | |
| 8572 SOAP_FMAC1 | |
| 8573 void | |
| 8574 SOAP_FMAC2 | |
| 8575 soap_open_logfile(struct soap *soap, int i) | |
| 8576 { if (soap->logfile[i]) | |
| 8577 soap->fdebug[i] = fopen(soap->logfile[i], i < 2 ? "ab" : "a"); | |
| 8578 } | |
| 8579 #endif | |
| 8580 | |
| 8581 /******************************************************************************/ | |
| 8582 #ifdef SOAP_DEBUG | |
| 8583 static void | |
| 8584 soap_close_logfile(struct soap *soap, int i) | |
| 8585 { if (soap->fdebug[i]) | |
| 8586 { fclose(soap->fdebug[i]); | |
| 8587 soap->fdebug[i] = NULL; | |
| 8588 } | |
| 8589 } | |
| 8590 #endif | |
| 8591 | |
| 8592 /******************************************************************************/ | |
| 8593 #ifdef SOAP_DEBUG | |
| 8594 SOAP_FMAC1 | |
| 8595 void | |
| 8596 SOAP_FMAC2 | |
| 8597 soap_close_logfiles(struct soap *soap) | |
| 8598 { int i; | |
| 8599 for (i = 0; i < SOAP_MAXLOGS; i++) | |
| 8600 soap_close_logfile(soap, i); | |
| 8601 } | |
| 8602 #endif | |
| 8603 | |
| 8604 /******************************************************************************/ | |
| 8605 #ifdef SOAP_DEBUG | |
| 8606 static void | |
| 8607 soap_set_logfile(struct soap *soap, int i, const char *logfile) | |
| 8608 { const char *s; | |
| 8609 char *t = NULL; | |
| 8610 soap_close_logfile(soap, i); | |
| 8611 s = soap->logfile[i]; | |
| 8612 soap->logfile[i] = logfile; | |
| 8613 if (s) | |
| 8614 SOAP_FREE(soap, (void*)s); | |
| 8615 if (logfile) | |
| 8616 if ((t = (char*)SOAP_MALLOC(soap, strlen(logfile) + 1))) | |
| 8617 strcpy(t, logfile); | |
| 8618 soap->logfile[i] = t; | |
| 8619 } | |
| 8620 #endif | |
| 8621 | |
| 8622 /******************************************************************************/ | |
| 8623 SOAP_FMAC1 | |
| 8624 void | |
| 8625 SOAP_FMAC2 | |
| 8626 soap_set_recv_logfile(struct soap *soap, const char *logfile) | |
| 8627 { | |
| 8628 #ifdef SOAP_DEBUG | |
| 8629 soap_set_logfile(soap, SOAP_INDEX_RECV, logfile); | |
| 8630 #endif | |
| 8631 } | |
| 8632 | |
| 8633 /******************************************************************************/ | |
| 8634 SOAP_FMAC1 | |
| 8635 void | |
| 8636 SOAP_FMAC2 | |
| 8637 soap_set_sent_logfile(struct soap *soap, const char *logfile) | |
| 8638 { | |
| 8639 #ifdef SOAP_DEBUG | |
| 8640 soap_set_logfile(soap, SOAP_INDEX_SENT, logfile); | |
| 8641 #endif | |
| 8642 } | |
| 8643 | |
| 8644 /******************************************************************************/ | |
| 8645 SOAP_FMAC1 | |
| 8646 void | |
| 8647 SOAP_FMAC2 | |
| 8648 soap_set_test_logfile(struct soap *soap, const char *logfile) | |
| 8649 { | |
| 8650 #ifdef SOAP_DEBUG | |
| 8651 soap_set_logfile(soap, SOAP_INDEX_TEST, logfile); | |
| 8652 #endif | |
| 8653 } | |
| 8654 | |
| 8655 /******************************************************************************/ | |
| 8656 #ifndef PALM_1 | |
| 8657 SOAP_FMAC1 | |
| 8658 struct soap* | |
| 8659 SOAP_FMAC2 | |
| 8660 soap_copy(const struct soap *soap) | |
| 8661 { return soap_copy_context((struct soap*)malloc(sizeof(struct soap)), soap); | |
| 8662 } | |
| 8663 #endif | |
| 8664 | |
| 8665 /******************************************************************************/ | |
| 8666 #ifndef PALM_1 | |
| 8667 SOAP_FMAC1 | |
| 8668 struct soap* | |
| 8669 SOAP_FMAC2 | |
| 8670 soap_copy_context(struct soap *copy, const struct soap *soap) | |
| 8671 { if (copy == soap) | |
| 8672 return copy; | |
| 8673 if (soap_check_state(soap)) | |
| 8674 return NULL; | |
| 8675 if (copy) | |
| 8676 { register struct soap_plugin *p = NULL; | |
| 8677 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying context\n")); | |
| 8678 #ifdef __cplusplus | |
| 8679 *copy = *soap; | |
| 8680 #else | |
| 8681 memcpy(copy, soap, sizeof(struct soap)); | |
| 8682 #endif | |
| 8683 copy->state = SOAP_COPY; | |
| 8684 copy->error = SOAP_OK; | |
| 8685 copy->userid = NULL; | |
| 8686 copy->passwd = NULL; | |
| 8687 #ifdef WITH_NTLM | |
| 8688 copy->ntlm_challenge = NULL; | |
| 8689 #endif | |
| 8690 copy->nlist = NULL; | |
| 8691 copy->blist = NULL; | |
| 8692 copy->clist = NULL; | |
| 8693 copy->alist = NULL; | |
| 8694 copy->attributes = NULL; | |
| 8695 copy->labbuf = NULL; | |
| 8696 copy->lablen = 0; | |
| 8697 copy->labidx = 0; | |
| 8698 #ifdef SOAP_MEM_DEBUG | |
| 8699 soap_init_mht(copy); | |
| 8700 #endif | |
| 8701 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG) | |
| 8702 soap_init_logs(copy); | |
| 8703 #endif | |
| 8704 #ifdef SOAP_DEBUG | |
| 8705 soap_set_test_logfile(copy, soap->logfile[SOAP_INDEX_TEST]); | |
| 8706 soap_set_sent_logfile(copy, soap->logfile[SOAP_INDEX_SENT]); | |
| 8707 soap_set_recv_logfile(copy, soap->logfile[SOAP_INDEX_RECV]); | |
| 8708 #endif | |
| 8709 copy->namespaces = soap->local_namespaces; | |
| 8710 copy->local_namespaces = NULL; | |
| 8711 soap_set_local_namespaces(copy); /* copy content of soap->local_namespaces */ | |
| 8712 copy->namespaces = soap->namespaces; /* point to shared read-only namespaces table */ | |
| 8713 #ifdef WITH_C_LOCALE | |
| 8714 # ifdef WIN32 | |
| 8715 copy->c_locale = _create_locale(LC_ALL, "C"); | |
| 8716 # else | |
| 8717 copy->c_locale = duplocale(soap->c_locale); | |
| 8718 # endif | |
| 8719 #else | |
| 8720 copy->c_locale = NULL; | |
| 8721 #endif | |
| 8722 #ifdef WITH_OPENSSL | |
| 8723 copy->bio = NULL; | |
| 8724 copy->ssl = NULL; | |
| 8725 copy->session = NULL; | |
| 8726 #endif | |
| 8727 #ifdef WITH_GNUTLS | |
| 8728 copy->session = NULL; | |
| 8729 #endif | |
| 8730 #ifdef WITH_ZLIB | |
| 8731 copy->d_stream = (z_stream*)SOAP_MALLOC(copy, sizeof(z_stream)); | |
| 8732 copy->d_stream->zalloc = Z_NULL; | |
| 8733 copy->d_stream->zfree = Z_NULL; | |
| 8734 copy->d_stream->opaque = Z_NULL; | |
| 8735 copy->z_buf = NULL; | |
| 8736 #endif | |
| 8737 #ifndef WITH_NOIDREF | |
| 8738 soap_init_iht(copy); | |
| 8739 soap_init_pht(copy); | |
| 8740 #endif | |
| 8741 copy->header = NULL; | |
| 8742 copy->fault = NULL; | |
| 8743 copy->action = NULL; | |
| 8744 #ifndef WITH_LEAN | |
| 8745 #ifdef WITH_COOKIES | |
| 8746 copy->cookies = soap_copy_cookies(copy, soap); | |
| 8747 #else | |
| 8748 copy->cookies = NULL; | |
| 8749 #endif | |
| 8750 #endif | |
| 8751 copy->plugins = NULL; | |
| 8752 for (p = soap->plugins; p; p = p->next) | |
| 8753 { register struct soap_plugin *q = (struct soap_plugin*)SOAP_MALLOC(copy, sizeof(struct soap_plugin)); | |
| 8754 if (!q) | |
| 8755 return NULL; | |
| 8756 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying plugin '%s'\n", p->id)); | |
| 8757 *q = *p; | |
| 8758 if (p->fcopy && p->fcopy(copy, q, p)) | |
| 8759 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not copy plugin '%s'\n", p->id)); | |
| 8760 SOAP_FREE(copy, q); | |
| 8761 return NULL; | |
| 8762 } | |
| 8763 q->next = copy->plugins; | |
| 8764 copy->plugins = q; | |
| 8765 } | |
| 8766 } | |
| 8767 return copy; | |
| 8768 } | |
| 8769 #endif | |
| 8770 | |
| 8771 /******************************************************************************/ | |
| 8772 #ifndef PALM_1 | |
| 8773 SOAP_FMAC1 | |
| 8774 void | |
| 8775 SOAP_FMAC2 | |
| 8776 soap_copy_stream(struct soap *copy, struct soap *soap) | |
| 8777 { struct soap_attribute *tp = NULL, *tq; | |
| 8778 if (copy == soap) | |
| 8779 return; | |
| 8780 copy->header = soap->header; | |
| 8781 copy->mode = soap->mode; | |
| 8782 copy->imode = soap->imode; | |
| 8783 copy->omode = soap->omode; | |
| 8784 copy->master = soap->master; | |
| 8785 copy->socket = soap->socket; | |
| 8786 copy->sendsk = soap->sendsk; | |
| 8787 copy->recvsk = soap->recvsk; | |
| 8788 copy->recv_timeout = soap->recv_timeout; | |
| 8789 copy->send_timeout = soap->send_timeout; | |
| 8790 #if defined(__cplusplus) && !defined(WITH_LEAN) | |
| 8791 copy->os = soap->os; | |
| 8792 copy->is = soap->is; | |
| 8793 #endif | |
| 8794 copy->sendfd = soap->sendfd; | |
| 8795 copy->recvfd = soap->recvfd; | |
| 8796 copy->bufidx = soap->bufidx; | |
| 8797 copy->buflen = soap->buflen; | |
| 8798 copy->ahead = soap->ahead; | |
| 8799 copy->cdata = soap->cdata; | |
| 8800 copy->chunksize = soap->chunksize; | |
| 8801 copy->chunkbuflen = soap->chunkbuflen; | |
| 8802 copy->keep_alive = soap->keep_alive; | |
| 8803 copy->tcp_keep_alive = soap->tcp_keep_alive; | |
| 8804 copy->tcp_keep_idle = soap->tcp_keep_idle; | |
| 8805 copy->tcp_keep_intvl = soap->tcp_keep_intvl; | |
| 8806 copy->tcp_keep_cnt = soap->tcp_keep_cnt; | |
| 8807 copy->max_keep_alive = soap->max_keep_alive; | |
| 8808 #ifndef WITH_NOIO | |
| 8809 copy->peer = soap->peer; | |
| 8810 copy->peerlen = soap->peerlen; | |
| 8811 copy->ip = soap->ip; | |
| 8812 copy->port = soap->port; | |
| 8813 memcpy(copy->host, soap->host, sizeof(soap->host)); | |
| 8814 memcpy(copy->endpoint, soap->endpoint, sizeof(soap->endpoint)); | |
| 8815 #endif | |
| 8816 #ifdef WITH_OPENSSL | |
| 8817 copy->bio = soap->bio; | |
| 8818 copy->ctx = soap->ctx; | |
| 8819 copy->ssl = soap->ssl; | |
| 8820 #endif | |
| 8821 #ifdef WITH_GNUTLS | |
| 8822 copy->session = soap->session; | |
| 8823 #endif | |
| 8824 #ifdef WITH_ZLIB | |
| 8825 copy->zlib_state = soap->zlib_state; | |
| 8826 copy->zlib_in = soap->zlib_in; | |
| 8827 copy->zlib_out = soap->zlib_out; | |
| 8828 if (!copy->d_stream) | |
| 8829 copy->d_stream = (z_stream*)SOAP_MALLOC(copy, sizeof(z_stream)); | |
| 8830 if (copy->d_stream) | |
| 8831 memcpy(copy->d_stream, soap->d_stream, sizeof(z_stream)); | |
| 8832 copy->z_crc = soap->z_crc; | |
| 8833 copy->z_ratio_in = soap->z_ratio_in; | |
| 8834 copy->z_ratio_out = soap->z_ratio_out; | |
| 8835 copy->z_buf = NULL; | |
| 8836 copy->z_buflen = soap->z_buflen; | |
| 8837 copy->z_level = soap->z_level; | |
| 8838 if (soap->z_buf && soap->zlib_state != SOAP_ZLIB_NONE) | |
| 8839 { copy->z_buf = (char*)SOAP_MALLOC(copy, SOAP_BUFLEN); | |
| 8840 if (copy->z_buf) | |
| 8841 memcpy(copy->z_buf, soap->z_buf, SOAP_BUFLEN); | |
| 8842 } | |
| 8843 copy->z_dict = soap->z_dict; | |
| 8844 copy->z_dict_len = soap->z_dict_len; | |
| 8845 #endif | |
| 8846 memcpy(copy->buf, soap->buf, sizeof(soap->buf)); | |
| 8847 /* copy XML parser state */ | |
| 8848 soap_free_ns(copy); | |
| 8849 soap_set_local_namespaces(copy); | |
| 8850 copy->version = soap->version; | |
| 8851 if (soap->nlist && soap->local_namespaces) | |
| 8852 { register struct soap_nlist *np = NULL, *nq; | |
| 8853 /* copy reversed nlist */ | |
| 8854 for (nq = soap->nlist; nq; nq = nq->next) | |
| 8855 { register struct soap_nlist *nr = np; | |
| 8856 size_t n = sizeof(struct soap_nlist) + strlen(nq->id); | |
| 8857 np = (struct soap_nlist*)SOAP_MALLOC(copy, n); | |
| 8858 if (!np) | |
| 8859 break; | |
| 8860 memcpy(np, nq, n); | |
| 8861 np->next = nr; | |
| 8862 } | |
| 8863 while (np) | |
| 8864 { register const char *s = np->ns; | |
| 8865 copy->level = np->level; /* preserve element nesting level */ | |
| 8866 if (!s && np->index >= 0) | |
| 8867 { s = soap->local_namespaces[np->index].out; | |
| 8868 if (!s) | |
| 8869 s = soap->local_namespaces[np->index].ns; | |
| 8870 } | |
| 8871 if (s && soap_push_namespace(copy, np->id, s) == NULL) | |
| 8872 break; | |
| 8873 nq = np; | |
| 8874 np = np->next; | |
| 8875 SOAP_FREE(copy, nq); | |
| 8876 } | |
| 8877 } | |
| 8878 memcpy(copy->tag, soap->tag, sizeof(copy->tag)); | |
| 8879 memcpy(copy->id, soap->id, sizeof(copy->id)); | |
| 8880 memcpy(copy->href, soap->href, sizeof(copy->href)); | |
| 8881 memcpy(copy->type, soap->type, sizeof(copy->type)); | |
| 8882 copy->other = soap->other; | |
| 8883 copy->root = soap->root; | |
| 8884 copy->null = soap->null; | |
| 8885 copy->body = soap->body; | |
| 8886 copy->part = soap->part; | |
| 8887 copy->mustUnderstand = soap->mustUnderstand; | |
| 8888 copy->level = soap->level; | |
| 8889 copy->peeked = soap->peeked; | |
| 8890 /* copy attributes */ | |
| 8891 for (tq = soap->attributes; tq; tq = tq->next) | |
| 8892 { struct soap_attribute *tr = tp; | |
| 8893 size_t n = sizeof(struct soap_attribute) + strlen(tq->name); | |
| 8894 tp = (struct soap_attribute*)SOAP_MALLOC(copy, n); | |
| 8895 memcpy(tp, tq, n); | |
| 8896 if (tp->size) | |
| 8897 { tp->value = (char*)SOAP_MALLOC(copy, tp->size); | |
| 8898 if (tp->value) | |
| 8899 strcpy(tp->value, tq->value); | |
| 8900 } | |
| 8901 tp->ns = NULL; | |
| 8902 tp->next = tr; | |
| 8903 } | |
| 8904 copy->attributes = tp; | |
| 8905 } | |
| 8906 #endif | |
| 8907 | |
| 8908 /******************************************************************************/ | |
| 8909 #ifndef PALM_1 | |
| 8910 SOAP_FMAC1 | |
| 8911 void | |
| 8912 SOAP_FMAC2 | |
| 8913 soap_free_stream(struct soap *soap) | |
| 8914 { soap->socket = SOAP_INVALID_SOCKET; | |
| 8915 soap->sendsk = SOAP_INVALID_SOCKET; | |
| 8916 soap->recvsk = SOAP_INVALID_SOCKET; | |
| 8917 #ifdef WITH_OPENSSL | |
| 8918 soap->bio = NULL; | |
| 8919 soap->ctx = NULL; | |
| 8920 soap->ssl = NULL; | |
| 8921 #endif | |
| 8922 #ifdef WITH_GNUTLS | |
| 8923 soap->xcred = NULL; | |
| 8924 soap->acred = NULL; | |
| 8925 soap->cache = NULL; | |
| 8926 soap->session = NULL; | |
| 8927 soap->dh_params = NULL; | |
| 8928 soap->rsa_params = NULL; | |
| 8929 #endif | |
| 8930 #ifdef WITH_ZLIB | |
| 8931 if (soap->z_buf) | |
| 8932 SOAP_FREE(soap, soap->z_buf); | |
| 8933 soap->z_buf = NULL; | |
| 8934 #endif | |
| 8935 } | |
| 8936 #endif | |
| 8937 | |
| 8938 /******************************************************************************/ | |
| 8939 #ifndef PALM_1 | |
| 8940 SOAP_FMAC1 | |
| 8941 void | |
| 8942 SOAP_FMAC2 | |
| 8943 soap_initialize(struct soap *soap) | |
| 8944 { soap_versioning(soap_init)(soap, SOAP_IO_DEFAULT, SOAP_IO_DEFAULT); | |
| 8945 } | |
| 8946 #endif | |
| 8947 | |
| 8948 /******************************************************************************/ | |
| 8949 #ifndef PALM_1 | |
| 8950 SOAP_FMAC1 | |
| 8951 void | |
| 8952 SOAP_FMAC2 | |
| 8953 soap_versioning(soap_init)(struct soap *soap, soap_mode imode, soap_mode omode) | |
| 8954 { size_t i; | |
| 8955 soap->state = SOAP_INIT; | |
| 8956 #ifdef SOAP_MEM_DEBUG | |
| 8957 soap_init_mht(soap); | |
| 8958 #endif | |
| 8959 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG) | |
| 8960 soap_init_logs(soap); | |
| 8961 #endif | |
| 8962 #ifdef SOAP_DEBUG | |
| 8963 #ifdef TANDEM_NONSTOP | |
| 8964 soap_set_test_logfile(soap, "TESTLOG"); | |
| 8965 soap_set_sent_logfile(soap, "SENTLOG"); | |
| 8966 soap_set_recv_logfile(soap, "RECVLOG"); | |
| 8967 #else | |
| 8968 soap_set_test_logfile(soap, "TEST.log"); | |
| 8969 soap_set_sent_logfile(soap, "SENT.log"); | |
| 8970 soap_set_recv_logfile(soap, "RECV.log"); | |
| 8971 #endif | |
| 8972 #endif | |
| 8973 soap->version = 0; | |
| 8974 soap_mode(soap, imode); | |
| 8975 soap_imode(soap, imode); | |
| 8976 soap_omode(soap, omode); | |
| 8977 soap->plugins = NULL; | |
| 8978 soap->user = NULL; | |
| 8979 for (i = 0; i < sizeof(soap->data)/sizeof(*soap->data); i++) | |
| 8980 soap->data[i] = NULL; | |
| 8981 soap->userid = NULL; | |
| 8982 soap->passwd = NULL; | |
| 8983 soap->authrealm = NULL; | |
| 8984 #ifdef WITH_NTLM | |
| 8985 soap->ntlm_challenge = NULL; | |
| 8986 #endif | |
| 8987 #ifndef WITH_NOHTTP | |
| 8988 soap->fpost = http_post; | |
| 8989 soap->fget = http_get; | |
| 8990 soap->fput = http_405; | |
| 8991 soap->fdel = http_405; | |
| 8992 soap->fopt = http_200; | |
| 8993 soap->fhead = http_200; | |
| 8994 soap->fform = NULL; | |
| 8995 soap->fposthdr = http_post_header; | |
| 8996 soap->fresponse = http_response; | |
| 8997 soap->fparse = http_parse; | |
| 8998 soap->fparsehdr = http_parse_header; | |
| 8999 #endif | |
| 9000 soap->fheader = NULL; | |
| 9001 soap->fconnect = NULL; | |
| 9002 soap->fdisconnect = NULL; | |
| 9003 #ifndef WITH_NOIO | |
| 9004 soap->ipv6_multicast_if = 0; /* in_addr_t value */ | |
| 9005 soap->ipv4_multicast_if = NULL; /* points to struct in_addr or in_addr_t */ | |
| 9006 soap->ipv4_multicast_ttl = 0; /* 0: use default */ | |
| 9007 #ifndef WITH_IPV6 | |
| 9008 soap->fresolve = tcp_gethost; | |
| 9009 #else | |
| 9010 soap->fresolve = NULL; | |
| 9011 #endif | |
| 9012 soap->faccept = tcp_accept; | |
| 9013 soap->fopen = tcp_connect; | |
| 9014 soap->fclose = tcp_disconnect; | |
| 9015 soap->fclosesocket = tcp_closesocket; | |
| 9016 soap->fshutdownsocket = tcp_shutdownsocket; | |
| 9017 soap->fsend = fsend; | |
| 9018 soap->frecv = frecv; | |
| 9019 soap->fpoll = soap_poll; | |
| 9020 #else | |
| 9021 soap->fopen = NULL; | |
| 9022 soap->fclose = NULL; | |
| 9023 soap->fpoll = NULL; | |
| 9024 #endif | |
| 9025 soap->fseterror = NULL; | |
| 9026 soap->fignore = NULL; | |
| 9027 soap->fserveloop = NULL; | |
| 9028 soap->fplugin = fplugin; | |
| 9029 soap->fmalloc = NULL; | |
| 9030 #ifndef WITH_LEANER | |
| 9031 soap->feltbegin = NULL; | |
| 9032 soap->feltendin = NULL; | |
| 9033 soap->feltbegout = NULL; | |
| 9034 soap->feltendout = NULL; | |
| 9035 soap->fprepareinitsend = NULL; | |
| 9036 soap->fprepareinitrecv = NULL; | |
| 9037 soap->fpreparesend = NULL; | |
| 9038 soap->fpreparerecv = NULL; | |
| 9039 soap->fpreparefinalsend = NULL; | |
| 9040 soap->fpreparefinalrecv = NULL; | |
| 9041 soap->ffiltersend = NULL; | |
| 9042 soap->ffilterrecv = NULL; | |
| 9043 soap->fdimereadopen = NULL; | |
| 9044 soap->fdimewriteopen = NULL; | |
| 9045 soap->fdimereadclose = NULL; | |
| 9046 soap->fdimewriteclose = NULL; | |
| 9047 soap->fdimeread = NULL; | |
| 9048 soap->fdimewrite = NULL; | |
| 9049 soap->fmimereadopen = NULL; | |
| 9050 soap->fmimewriteopen = NULL; | |
| 9051 soap->fmimereadclose = NULL; | |
| 9052 soap->fmimewriteclose = NULL; | |
| 9053 soap->fmimeread = NULL; | |
| 9054 soap->fmimewrite = NULL; | |
| 9055 #endif | |
| 9056 soap->float_format = "%.9G"; /* Alternative: use "%G" */ | |
| 9057 soap->double_format = "%.17lG"; /* Alternative: use "%lG" */ | |
| 9058 soap->dime_id_format = "cid:id%d"; /* default DIME id format */ | |
| 9059 soap->http_version = "1.1"; | |
| 9060 soap->proxy_http_version = "1.0"; | |
| 9061 soap->http_content = NULL; | |
| 9062 soap->actor = NULL; | |
| 9063 soap->lang = "en"; | |
| 9064 soap->keep_alive = 0; | |
| 9065 soap->tcp_keep_alive = 0; | |
| 9066 soap->tcp_keep_idle = 0; | |
| 9067 soap->tcp_keep_intvl = 0; | |
| 9068 soap->tcp_keep_cnt = 0; | |
| 9069 soap->max_keep_alive = SOAP_MAXKEEPALIVE; | |
| 9070 soap->recv_timeout = 0; | |
| 9071 soap->send_timeout = 0; | |
| 9072 soap->connect_timeout = 0; | |
| 9073 soap->accept_timeout = 0; | |
| 9074 soap->socket_flags = 0; | |
| 9075 soap->connect_flags = 0; | |
| 9076 soap->bind_flags = 0; | |
| 9077 soap->accept_flags = 0; | |
| 9078 soap->linger_time = 0; | |
| 9079 soap->ip = 0; | |
| 9080 soap->labbuf = NULL; | |
| 9081 soap->lablen = 0; | |
| 9082 soap->labidx = 0; | |
| 9083 soap->encodingStyle = NULL; | |
| 9084 #ifndef WITH_NONAMESPACES | |
| 9085 soap->namespaces = namespaces; | |
| 9086 #else | |
| 9087 soap->namespaces = NULL; | |
| 9088 #endif | |
| 9089 soap->local_namespaces = NULL; | |
| 9090 soap->nlist = NULL; | |
| 9091 soap->blist = NULL; | |
| 9092 soap->clist = NULL; | |
| 9093 soap->alist = NULL; | |
| 9094 soap->attributes = NULL; | |
| 9095 soap->header = NULL; | |
| 9096 soap->fault = NULL; | |
| 9097 soap->master = SOAP_INVALID_SOCKET; | |
| 9098 soap->socket = SOAP_INVALID_SOCKET; | |
| 9099 soap->sendsk = SOAP_INVALID_SOCKET; | |
| 9100 soap->recvsk = SOAP_INVALID_SOCKET; | |
| 9101 soap->os = NULL; | |
| 9102 soap->is = NULL; | |
| 9103 #ifndef WITH_LEANER | |
| 9104 soap->dom = NULL; | |
| 9105 soap->dime.list = NULL; | |
| 9106 soap->dime.first = NULL; | |
| 9107 soap->dime.last = NULL; | |
| 9108 soap->mime.list = NULL; | |
| 9109 soap->mime.first = NULL; | |
| 9110 soap->mime.last = NULL; | |
| 9111 soap->mime.boundary = NULL; | |
| 9112 soap->mime.start = NULL; | |
| 9113 soap->xlist = NULL; | |
| 9114 #endif | |
| 9115 #ifndef UNDER_CE | |
| 9116 soap->recvfd = 0; | |
| 9117 soap->sendfd = 1; | |
| 9118 #else | |
| 9119 soap->recvfd = stdin; | |
| 9120 soap->sendfd = stdout; | |
| 9121 #endif | |
| 9122 soap->host[0] = '\0'; | |
| 9123 soap->port = 0; | |
| 9124 soap->action = NULL; | |
| 9125 soap->proxy_host = NULL; | |
| 9126 soap->proxy_port = 8080; | |
| 9127 soap->proxy_userid = NULL; | |
| 9128 soap->proxy_passwd = NULL; | |
| 9129 soap->prolog = NULL; | |
| 9130 #ifdef WITH_ZLIB | |
| 9131 soap->zlib_state = SOAP_ZLIB_NONE; | |
| 9132 soap->zlib_in = SOAP_ZLIB_NONE; | |
| 9133 soap->zlib_out = SOAP_ZLIB_NONE; | |
| 9134 soap->d_stream = (z_stream*)SOAP_MALLOC(soap, sizeof(z_stream)); | |
| 9135 soap->d_stream->zalloc = Z_NULL; | |
| 9136 soap->d_stream->zfree = Z_NULL; | |
| 9137 soap->d_stream->opaque = Z_NULL; | |
| 9138 soap->z_buf = NULL; | |
| 9139 soap->z_level = 6; | |
| 9140 soap->z_dict = NULL; | |
| 9141 soap->z_dict_len = 0; | |
| 9142 #endif | |
| 9143 #ifndef WITH_LEAN | |
| 9144 soap->wsuid = NULL; | |
| 9145 soap->c14nexclude = NULL; | |
| 9146 soap->cookies = NULL; | |
| 9147 soap->cookie_domain = NULL; | |
| 9148 soap->cookie_path = NULL; | |
| 9149 soap->cookie_max = 32; | |
| 9150 #endif | |
| 9151 #ifdef WMW_RPM_IO | |
| 9152 soap->rpmreqid = NULL; | |
| 9153 #endif | |
| 9154 #ifdef PALM | |
| 9155 palmNetLibOpen(); | |
| 9156 #endif | |
| 9157 #ifndef WITH_NOIDREF | |
| 9158 soap_init_iht(soap); | |
| 9159 soap_init_pht(soap); | |
| 9160 #endif | |
| 9161 #ifdef WITH_OPENSSL | |
| 9162 if (!soap_ssl_init_done) | |
| 9163 soap_ssl_init(); | |
| 9164 soap->fsslauth = ssl_auth_init; | |
| 9165 soap->fsslverify = ssl_verify_callback; | |
| 9166 soap->bio = NULL; | |
| 9167 soap->ssl = NULL; | |
| 9168 soap->ctx = NULL; | |
| 9169 soap->session = NULL; | |
| 9170 soap->ssl_flags = SOAP_SSL_DEFAULT; | |
| 9171 soap->keyfile = NULL; | |
| 9172 soap->keyid = NULL; | |
| 9173 soap->password = NULL; | |
| 9174 soap->cafile = NULL; | |
| 9175 soap->capath = NULL; | |
| 9176 soap->crlfile = NULL; | |
| 9177 soap->dhfile = NULL; | |
| 9178 soap->randfile = NULL; | |
| 9179 #endif | |
| 9180 #ifdef WITH_GNUTLS | |
| 9181 if (!soap_ssl_init_done) | |
| 9182 soap_ssl_init(); | |
| 9183 soap->fsslauth = ssl_auth_init; | |
| 9184 soap->fsslverify = NULL; | |
| 9185 soap->xcred = NULL; | |
| 9186 soap->acred = NULL; | |
| 9187 soap->cache = NULL; | |
| 9188 soap->session = NULL; | |
| 9189 soap->ssl_flags = SOAP_SSL_DEFAULT; | |
| 9190 soap->keyfile = NULL; | |
| 9191 soap->keyid = NULL; | |
| 9192 soap->password = NULL; | |
| 9193 soap->cafile = NULL; | |
| 9194 soap->capath = NULL; | |
| 9195 soap->crlfile = NULL; | |
| 9196 soap->dh_params = NULL; | |
| 9197 soap->rsa_params = NULL; | |
| 9198 #endif | |
| 9199 #ifdef WITH_C_LOCALE | |
| 9200 # ifdef WIN32 | |
| 9201 soap->c_locale = _create_locale(LC_ALL, "C"); | |
| 9202 # else | |
| 9203 soap->c_locale = newlocale(LC_ALL_MASK, "C", NULL); | |
| 9204 # endif | |
| 9205 #else | |
| 9206 soap->c_locale = NULL; | |
| 9207 #endif | |
| 9208 soap->buflen = 0; | |
| 9209 soap->bufidx = 0; | |
| 9210 #ifndef WITH_LEANER | |
| 9211 soap->dime.chunksize = 0; | |
| 9212 soap->dime.buflen = 0; | |
| 9213 #endif | |
| 9214 soap->null = 0; | |
| 9215 soap->position = 0; | |
| 9216 soap->encoding = 0; | |
| 9217 soap->mustUnderstand = 0; | |
| 9218 soap->ns = 0; | |
| 9219 soap->part = SOAP_END; | |
| 9220 soap->event = 0; | |
| 9221 soap->evlev = 0; | |
| 9222 soap->alloced = 0; | |
| 9223 soap->count = 0; | |
| 9224 soap->length = 0; | |
| 9225 soap->cdata = 0; | |
| 9226 soap->peeked = 0; | |
| 9227 soap->ahead = 0; | |
| 9228 soap->idnum = 0; | |
| 9229 soap->level = 0; | |
| 9230 soap->endpoint[0] = '\0'; | |
| 9231 soap->error = SOAP_OK; | |
| 9232 } | |
| 9233 #endif | |
| 9234 | |
| 9235 /******************************************************************************/ | |
| 9236 #ifndef PALM_2 | |
| 9237 SOAP_FMAC1 | |
| 9238 void | |
| 9239 SOAP_FMAC2 | |
| 9240 soap_begin(struct soap *soap) | |
| 9241 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reinitializing context\n")); | |
| 9242 if (!soap->keep_alive) | |
| 9243 { soap->buflen = 0; | |
| 9244 soap->bufidx = 0; | |
| 9245 } | |
| 9246 soap->null = 0; | |
| 9247 soap->position = 0; | |
| 9248 soap->encoding = 0; | |
| 9249 soap->mustUnderstand = 0; | |
| 9250 soap->mode = 0; | |
| 9251 soap->ns = 0; | |
| 9252 soap->part = SOAP_END; | |
| 9253 soap->event = 0; | |
| 9254 soap->evlev = 0; | |
| 9255 soap->alloced = 0; | |
| 9256 soap->count = 0; | |
| 9257 soap->length = 0; | |
| 9258 soap->cdata = 0; | |
| 9259 soap->error = SOAP_OK; | |
| 9260 soap->peeked = 0; | |
| 9261 soap->ahead = 0; | |
| 9262 soap->idnum = 0; | |
| 9263 soap->level = 0; | |
| 9264 soap->endpoint[0] = '\0'; | |
| 9265 soap->encodingStyle = SOAP_STR_EOS; | |
| 9266 #ifndef WITH_LEANER | |
| 9267 soap->dime.chunksize = 0; | |
| 9268 soap->dime.buflen = 0; | |
| 9269 #endif | |
| 9270 soap_free_temp(soap); | |
| 9271 } | |
| 9272 #endif | |
| 9273 | |
| 9274 /******************************************************************************/ | |
| 9275 #ifndef PALM_2 | |
| 9276 SOAP_FMAC1 | |
| 9277 void | |
| 9278 SOAP_FMAC2 | |
| 9279 soap_end(struct soap *soap) | |
| 9280 { if (soap_check_state(soap)) | |
| 9281 return; | |
| 9282 soap_free_temp(soap); | |
| 9283 soap_dealloc(soap, NULL); | |
| 9284 while (soap->clist) | |
| 9285 { register struct soap_clist *cp = soap->clist->next; | |
| 9286 SOAP_FREE(soap, soap->clist); | |
| 9287 soap->clist = cp; | |
| 9288 } | |
| 9289 soap_closesock(soap); | |
| 9290 #ifdef SOAP_DEBUG | |
| 9291 soap_close_logfiles(soap); | |
| 9292 #endif | |
| 9293 #ifdef PALM | |
| 9294 palmNetLibClose(); | |
| 9295 #endif | |
| 9296 } | |
| 9297 #endif | |
| 9298 | |
| 9299 /******************************************************************************/ | |
| 9300 #ifndef PALM_1 | |
| 9301 SOAP_FMAC1 | |
| 9302 void | |
| 9303 SOAP_FMAC2 | |
| 9304 soap_set_version(struct soap *soap, short version) | |
| 9305 { soap_set_local_namespaces(soap); | |
| 9306 if (soap->version != version) | |
| 9307 { if (version == 1) | |
| 9308 { soap->local_namespaces[0].ns = soap_env1; | |
| 9309 soap->local_namespaces[1].ns = soap_enc1; | |
| 9310 } | |
| 9311 else if (version == 2) | |
| 9312 { soap->local_namespaces[0].ns = soap_env2; | |
| 9313 soap->local_namespaces[1].ns = soap_enc2; | |
| 9314 } | |
| 9315 soap->version = version; | |
| 9316 } | |
| 9317 } | |
| 9318 #endif | |
| 9319 | |
| 9320 /******************************************************************************/ | |
| 9321 #ifndef PALM_1 | |
| 9322 SOAP_FMAC1 | |
| 9323 int | |
| 9324 SOAP_FMAC2 | |
| 9325 soap_set_namespaces(struct soap *soap, const struct Namespace *p) | |
| 9326 { register struct Namespace *ns = soap->local_namespaces; | |
| 9327 register struct soap_nlist *np, *nq, *nr; | |
| 9328 register unsigned int level = soap->level; | |
| 9329 soap->namespaces = p; | |
| 9330 soap->local_namespaces = NULL; | |
| 9331 soap_set_local_namespaces(soap); | |
| 9332 /* reverse the namespace list */ | |
| 9333 np = soap->nlist; | |
| 9334 soap->nlist = NULL; | |
| 9335 if (np) | |
| 9336 { nq = np->next; | |
| 9337 np->next = NULL; | |
| 9338 while (nq) | |
| 9339 { nr = nq->next; | |
| 9340 nq->next = np; | |
| 9341 np = nq; | |
| 9342 nq = nr; | |
| 9343 } | |
| 9344 } | |
| 9345 /* then push on new stack */ | |
| 9346 while (np) | |
| 9347 { register const char *s; | |
| 9348 soap->level = np->level; /* preserve element nesting level */ | |
| 9349 s = np->ns; | |
| 9350 if (!s && np->index >= 0 && ns) | |
| 9351 { s = ns[np->index].out; | |
| 9352 if (!s) | |
| 9353 s = ns[np->index].ns; | |
| 9354 } | |
| 9355 if (s && soap_push_namespace(soap, np->id, s) == NULL) | |
| 9356 return soap->error; | |
| 9357 nq = np; | |
| 9358 np = np->next; | |
| 9359 SOAP_FREE(soap, nq); | |
| 9360 } | |
| 9361 if (ns) | |
| 9362 { register int i; | |
| 9363 for (i = 0; ns[i].id; i++) | |
| 9364 { if (ns[i].out) | |
| 9365 { SOAP_FREE(soap, ns[i].out); | |
| 9366 ns[i].out = NULL; | |
| 9367 } | |
| 9368 } | |
| 9369 SOAP_FREE(soap, ns); | |
| 9370 } | |
| 9371 soap->level = level; /* restore level */ | |
| 9372 return SOAP_OK; | |
| 9373 } | |
| 9374 #endif | |
| 9375 | |
| 9376 /******************************************************************************/ | |
| 9377 #ifndef PALM_1 | |
| 9378 SOAP_FMAC1 | |
| 9379 void | |
| 9380 SOAP_FMAC2 | |
| 9381 soap_set_local_namespaces(struct soap *soap) | |
| 9382 { if (soap->namespaces && !soap->local_namespaces) | |
| 9383 { register const struct Namespace *ns1; | |
| 9384 register struct Namespace *ns2; | |
| 9385 register size_t n = 1; | |
| 9386 for (ns1 = soap->namespaces; ns1->id; ns1++) | |
| 9387 n++; | |
| 9388 n *= sizeof(struct Namespace); | |
| 9389 ns2 = (struct Namespace*)SOAP_MALLOC(soap, n); | |
| 9390 if (ns2) | |
| 9391 { memcpy(ns2, soap->namespaces, n); | |
| 9392 if (ns2[0].ns) | |
| 9393 { if (!strcmp(ns2[0].ns, soap_env1)) | |
| 9394 soap->version = 1; | |
| 9395 else if (!strcmp(ns2[0].ns, soap_env2)) | |
| 9396 soap->version = 2; | |
| 9397 } | |
| 9398 soap->local_namespaces = ns2; | |
| 9399 for (; ns2->id; ns2++) | |
| 9400 ns2->out = NULL; | |
| 9401 } | |
| 9402 } | |
| 9403 } | |
| 9404 #endif | |
| 9405 | |
| 9406 /******************************************************************************/ | |
| 9407 #ifndef WITH_LEAN | |
| 9408 #ifndef PALM_1 | |
| 9409 SOAP_FMAC1 | |
| 9410 const char * | |
| 9411 SOAP_FMAC2 | |
| 9412 soap_tagsearch(const char *big, const char *little) | |
| 9413 { if (little) | |
| 9414 { register size_t n = strlen(little); | |
| 9415 register const char *s = big; | |
| 9416 while (s) | |
| 9417 { register const char *t = s; | |
| 9418 register size_t i; | |
| 9419 for (i = 0; i < n; i++, t++) | |
| 9420 { if (*t != little[i]) | |
| 9421 break; | |
| 9422 } | |
| 9423 if (*t == '\0' || *t == ' ') | |
| 9424 { if (i == n || (i && little[i-1] == ':')) | |
| 9425 return s; | |
| 9426 } | |
| 9427 s = strchr(t, ' '); | |
| 9428 if (s) | |
| 9429 s++; | |
| 9430 } | |
| 9431 } | |
| 9432 return NULL; | |
| 9433 } | |
| 9434 #endif | |
| 9435 #endif | |
| 9436 | |
| 9437 /******************************************************************************/ | |
| 9438 #ifndef WITH_LEAN | |
| 9439 #ifndef PALM_1 | |
| 9440 SOAP_FMAC1 | |
| 9441 struct soap_nlist * | |
| 9442 SOAP_FMAC2 | |
| 9443 soap_lookup_ns(struct soap *soap, const char *tag, size_t n) | |
| 9444 { register struct soap_nlist *np; | |
| 9445 for (np = soap->nlist; np; np = np->next) | |
| 9446 { if (!strncmp(np->id, tag, n) && !np->id[n]) | |
| 9447 return np; | |
| 9448 } | |
| 9449 return NULL; | |
| 9450 } | |
| 9451 #endif | |
| 9452 #endif | |
| 9453 | |
| 9454 /******************************************************************************/ | |
| 9455 #ifndef WITH_LEAN | |
| 9456 static struct soap_nlist * | |
| 9457 soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized) | |
| 9458 { register struct soap_nlist *np; | |
| 9459 size_t n, k; | |
| 9460 if (soap_tagsearch(soap->c14nexclude, id)) | |
| 9461 return NULL; | |
| 9462 if (!utilized) | |
| 9463 { for (np = soap->nlist; np; np = np->next) | |
| 9464 { if (!strcmp(np->id, id) && (!np->ns || !strcmp(np->ns, ns))) | |
| 9465 break; | |
| 9466 } | |
| 9467 if (np) | |
| 9468 { if ((np->level < soap->level || !np->ns) && np->index == 1) | |
| 9469 utilized = 1; | |
| 9470 else | |
| 9471 return NULL; | |
| 9472 } | |
| 9473 } | |
| 9474 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Adding namespace binding (level=%u) '%s' '%s' utilized=%d\n", soap->level, id, ns ? ns : "(null)", utilized)); | |
| 9475 n = strlen(id); | |
| 9476 if (ns) | |
| 9477 k = strlen(ns); | |
| 9478 else | |
| 9479 k = 0; | |
| 9480 np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k + 1); | |
| 9481 if (!np) | |
| 9482 { soap->error = SOAP_EOM; | |
| 9483 return NULL; | |
| 9484 } | |
| 9485 np->next = soap->nlist; | |
| 9486 soap->nlist = np; | |
| 9487 strcpy((char*)np->id, id); | |
| 9488 if (ns) | |
| 9489 np->ns = strcpy((char*)np->id + n + 1, ns); | |
| 9490 else | |
| 9491 np->ns = NULL; | |
| 9492 np->level = soap->level; | |
| 9493 np->index = utilized; | |
| 9494 return np; | |
| 9495 } | |
| 9496 #endif | |
| 9497 | |
| 9498 /******************************************************************************/ | |
| 9499 #ifndef WITH_LEAN | |
| 9500 static void | |
| 9501 soap_utilize_ns(struct soap *soap, const char *tag) | |
| 9502 { register struct soap_nlist *np; | |
| 9503 size_t n = 0; | |
| 9504 const char *t = strchr(tag, ':'); | |
| 9505 if (t) | |
| 9506 { n = t - tag; | |
| 9507 if (n >= sizeof(soap->tmpbuf)) | |
| 9508 n = sizeof(soap->tmpbuf) - 1; | |
| 9509 } | |
| 9510 np = soap_lookup_ns(soap, tag, n); | |
| 9511 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Utilizing namespace of '%s'\n", tag)); | |
| 9512 if (np) | |
| 9513 { if (np->index <= 0) | |
| 9514 soap_push_ns(soap, np->id, np->ns, 1); | |
| 9515 } | |
| 9516 else if (strncmp(tag, "xml", 3)) | |
| 9517 { strncpy(soap->tmpbuf, tag, n); | |
| 9518 soap->tmpbuf[n] = '\0'; | |
| 9519 soap_push_ns(soap, soap->tmpbuf, NULL, 1); | |
| 9520 } | |
| 9521 } | |
| 9522 #endif | |
| 9523 | |
| 9524 /******************************************************************************/ | |
| 9525 #ifndef PALM_2 | |
| 9526 SOAP_FMAC1 | |
| 9527 int | |
| 9528 SOAP_FMAC2 | |
| 9529 soap_element(struct soap *soap, const char *tag, int id, const char *type) | |
| 9530 { | |
| 9531 #ifndef WITH_LEAN | |
| 9532 register const char *s; | |
| 9533 #endif | |
| 9534 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)); | |
| 9535 soap->level++; | |
| 9536 #ifdef WITH_DOM | |
| 9537 #ifndef WITH_LEAN | |
| 9538 if (soap->wsuid && soap_tagsearch(soap->wsuid, tag)) | |
| 9539 { size_t i; | |
| 9540 for (s = tag, i = 0; *s && i < sizeof(soap->tag) - 1; s++, i++) | |
| 9541 soap->tag[i] = *s == ':' ? '-' : *s; | |
| 9542 soap->tag[i] = '\0'; | |
| 9543 if (soap_set_attr(soap, "wsu:Id", soap->tag, 1)) | |
| 9544 return soap->error; | |
| 9545 } | |
| 9546 if ((soap->mode & SOAP_XML_CANONICAL) && !(soap->mode & SOAP_DOM_ASIS)) | |
| 9547 { if (soap->evlev >= soap->level) | |
| 9548 soap->evlev = 0; | |
| 9549 if (soap->event == SOAP_SEC_BEGIN && !soap->evlev) | |
| 9550 { register struct soap_nlist *np; | |
| 9551 /* non-nested wsu:Id found: clear xmlns, re-emit them for exc-c14n */ | |
| 9552 for (np = soap->nlist; np; np = np->next) | |
| 9553 { if (np->index == 2) | |
| 9554 { struct soap_nlist *np1 = soap_push_ns(soap, np->id, np->ns, 1); | |
| 9555 if (np1) | |
| 9556 np1->index = 0; | |
| 9557 } | |
| 9558 } | |
| 9559 soap->evlev = soap->level; | |
| 9560 } | |
| 9561 } | |
| 9562 #endif | |
| 9563 if (soap->mode & SOAP_XML_DOM) | |
| 9564 { register struct soap_dom_element *elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element)); | |
| 9565 if (!elt) | |
| 9566 return soap->error; | |
| 9567 elt->soap = soap; | |
| 9568 elt->next = NULL; | |
| 9569 elt->prnt = soap->dom; | |
| 9570 elt->name = soap_strdup(soap, tag); | |
| 9571 elt->elts = NULL; | |
| 9572 elt->atts = NULL; | |
| 9573 elt->nstr = NULL; | |
| 9574 elt->data = NULL; | |
| 9575 elt->wide = NULL; | |
| 9576 elt->node = NULL; | |
| 9577 elt->type = 0; | |
| 9578 elt->head = NULL; | |
| 9579 elt->tail = NULL; | |
| 9580 if (soap->dom) | |
| 9581 { struct soap_dom_element *p = soap->dom->elts; | |
| 9582 if (p) | |
| 9583 { while (p->next) | |
| 9584 p = p->next; | |
| 9585 p->next = elt; | |
| 9586 } | |
| 9587 else | |
| 9588 soap->dom->elts = elt; | |
| 9589 } | |
| 9590 soap->dom = elt; | |
| 9591 } | |
| 9592 else | |
| 9593 { | |
| 9594 #endif | |
| 9595 #ifndef WITH_LEAN | |
| 9596 if (!soap->ns) | |
| 9597 { if (!(soap->mode & SOAP_XML_CANONICAL) | |
| 9598 && soap_send(soap, soap->prolog ? soap->prolog : "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")) | |
| 9599 return soap->error; | |
| 9600 } | |
| 9601 else if (soap->mode & SOAP_XML_INDENT) | |
| 9602 { if (soap->ns == 1 && soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1)) | |
| 9603 return soap->error; | |
| 9604 soap->body = 1; | |
| 9605 } | |
| 9606 if ((soap->mode & SOAP_XML_DEFAULTNS) && (s = strchr(tag, ':'))) | |
| 9607 { struct Namespace *ns = soap->local_namespaces; | |
| 9608 size_t n = s - tag; | |
| 9609 if (soap_send_raw(soap, "<", 1) | |
| 9610 || soap_send(soap, s + 1)) | |
| 9611 return soap->error; | |
| 9612 if (soap->nlist && !strncmp(soap->nlist->id, tag, n) && !soap->nlist->id[n]) | |
| 9613 ns = NULL; | |
| 9614 for (; ns && ns->id; ns++) | |
| 9615 { if (*ns->id && (ns->out || ns->ns) && !strncmp(ns->id, tag, n) && !ns->id[n]) | |
| 9616 { soap_push_ns(soap, ns->id, ns->out ? ns->out : ns->ns, 0); | |
| 9617 if (soap_attribute(soap, "xmlns", ns->out ? ns->out : ns->ns)) | |
| 9618 return soap->error; | |
| 9619 break; | |
| 9620 } | |
| 9621 } | |
| 9622 } | |
| 9623 else | |
| 9624 #endif | |
| 9625 if (soap_send_raw(soap, "<", 1) | |
| 9626 || soap_send(soap, tag)) | |
| 9627 return soap->error; | |
| 9628 #ifdef WITH_DOM | |
| 9629 } | |
| 9630 #endif | |
| 9631 if (!soap->ns) | |
| 9632 { struct Namespace *ns = soap->local_namespaces; | |
| 9633 int k = -1; | |
| 9634 if (ns) | |
| 9635 { | |
| 9636 #ifndef WITH_LEAN | |
| 9637 if ((soap->mode & SOAP_XML_DEFAULTNS)) | |
| 9638 { if (soap->version) | |
| 9639 k = 4; /* first four required entries */ | |
| 9640 else if (!(soap->mode & SOAP_XML_NOTYPE) || (soap->mode & SOAP_XML_NIL)) | |
| 9641 { ns += 2; | |
| 9642 k = 2; /* next two entries */ | |
| 9643 } | |
| 9644 else | |
| 9645 k = 0; /* no entries */ | |
| 9646 } | |
| 9647 #endif | |
| 9648 while (k-- && ns->id) | |
| 9649 { if (*ns->id && (ns->out || ns->ns)) | |
| 9650 { | |
| 9651 #ifdef HAVE_SNPRINTF | |
| 9652 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "xmlns:%s", ns->id); | |
| 9653 #else | |
| 9654 sprintf(soap->tmpbuf, "xmlns:%s", ns->id); | |
| 9655 #endif | |
| 9656 if (soap_attribute(soap, soap->tmpbuf, ns->out ? ns->out : ns->ns)) | |
| 9657 return soap->error; | |
| 9658 } | |
| 9659 ns++; | |
| 9660 } | |
| 9661 } | |
| 9662 } | |
| 9663 soap->ns = 1; /* namespace table control: ns = 0 or 2 to start, then 1 to stop dumping the table */ | |
| 9664 #ifndef WITH_LEAN | |
| 9665 if (soap->mode & SOAP_XML_CANONICAL) | |
| 9666 soap_utilize_ns(soap, tag); | |
| 9667 #endif | |
| 9668 if (id > 0) | |
| 9669 { | |
| 9670 #ifdef HAVE_SNPRINTF | |
| 9671 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "_%d", id); | |
| 9672 #else | |
| 9673 sprintf(soap->tmpbuf, "_%d", id); | |
| 9674 #endif | |
| 9675 if (soap->version == 2) | |
| 9676 { if (soap_attribute(soap, "SOAP-ENC:id", soap->tmpbuf)) | |
| 9677 return soap->error; | |
| 9678 } | |
| 9679 else if (soap_attribute(soap, "id", soap->tmpbuf)) | |
| 9680 return soap->error; | |
| 9681 } | |
| 9682 if (type && *type && !(soap->mode & SOAP_XML_NOTYPE) && soap->part != SOAP_IN_HEADER) | |
| 9683 { const char *t = type; | |
| 9684 #ifndef WITH_LEAN | |
| 9685 if (soap->mode & SOAP_XML_DEFAULTNS) | |
| 9686 { t = strchr(type, ':'); | |
| 9687 if (t) | |
| 9688 t++; | |
| 9689 else | |
| 9690 t = type; | |
| 9691 } | |
| 9692 #endif | |
| 9693 if (soap->attributes ? soap_set_attr(soap, "xsi:type", t, 1) : soap_attribute(soap, "xsi:type", t)) | |
| 9694 return soap->error; | |
| 9695 #ifndef WITH_LEAN | |
| 9696 if (soap->mode & SOAP_XML_CANONICAL) | |
| 9697 soap_utilize_ns(soap, type); | |
| 9698 #endif | |
| 9699 } | |
| 9700 if (soap->null && soap->position > 0) | |
| 9701 { register int i; | |
| 9702 #ifdef HAVE_SNPRINTF | |
| 9703 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf) - 1, "[%d", soap->positions[0]); | |
| 9704 #else | |
| 9705 sprintf(soap->tmpbuf, "[%d", soap->positions[0]); | |
| 9706 #endif | |
| 9707 for (i = 1; i < soap->position; i++) | |
| 9708 { register size_t l = strlen(soap->tmpbuf); | |
| 9709 #ifdef HAVE_SNPRINTF | |
| 9710 soap_snprintf(soap->tmpbuf + l, sizeof(soap->tmpbuf)-l-1, ",%d", soap->positions[i]); | |
| 9711 #else | |
| 9712 if (l + 13 < sizeof(soap->tmpbuf)) | |
| 9713 sprintf(soap->tmpbuf + l, ",%d", soap->positions[i]); | |
| 9714 #endif | |
| 9715 } | |
| 9716 strcat(soap->tmpbuf, "]"); | |
| 9717 if (soap_attribute(soap, "SOAP-ENC:position", soap->tmpbuf)) | |
| 9718 return soap->error; | |
| 9719 } | |
| 9720 if (soap->mustUnderstand) | |
| 9721 { if (soap->actor && *soap->actor) | |
| 9722 { if (soap_attribute(soap, soap->version == 2 ? "SOAP-ENV:role" : "SOAP-ENV:actor", soap->actor)) | |
| 9723 return soap->error; | |
| 9724 } | |
| 9725 if (soap_attribute(soap, "SOAP-ENV:mustUnderstand", soap->version == 2 ? "true" : "1")) | |
| 9726 return soap->error; | |
| 9727 soap->mustUnderstand = 0; | |
| 9728 } | |
| 9729 if (soap->encoding) | |
| 9730 { if (soap->encodingStyle && soap->local_namespaces && soap->local_namespaces[0].id && soap->local_namespaces[1].id) | |
| 9731 { if (!*soap->encodingStyle) | |
| 9732 { if (soap->local_namespaces[1].out) | |
| 9733 soap->encodingStyle = soap->local_namespaces[1].out; | |
| 9734 else | |
| 9735 soap->encodingStyle = soap->local_namespaces[1].ns; | |
| 9736 } | |
| 9737 if (soap->encodingStyle && soap_attribute(soap, "SOAP-ENV:encodingStyle", soap->encodingStyle)) | |
| 9738 return soap->error; | |
| 9739 } | |
| 9740 else | |
| 9741 soap->encodingStyle = NULL; | |
| 9742 soap->encoding = 0; | |
| 9743 } | |
| 9744 soap->null = 0; | |
| 9745 soap->position = 0; | |
| 9746 if (soap->event == SOAP_SEC_BEGIN) | |
| 9747 soap->event = 0; | |
| 9748 return SOAP_OK; | |
| 9749 } | |
| 9750 #endif | |
| 9751 | |
| 9752 /******************************************************************************/ | |
| 9753 #ifndef PALM_2 | |
| 9754 SOAP_FMAC1 | |
| 9755 int | |
| 9756 SOAP_FMAC2 | |
| 9757 soap_element_begin_out(struct soap *soap, const char *tag, int id, const char *type) | |
| 9758 { if (*tag == '-') | |
| 9759 return SOAP_OK; | |
| 9760 if (soap_element(soap, tag, id, type)) | |
| 9761 return soap->error; | |
| 9762 #ifdef WITH_DOM | |
| 9763 if (soap_element_start_end_out(soap, NULL)) | |
| 9764 return soap->error; | |
| 9765 if (soap->feltbegout) | |
| 9766 return soap->error = soap->feltbegout(soap, tag); | |
| 9767 return SOAP_OK; | |
| 9768 #else | |
| 9769 return soap_element_start_end_out(soap, NULL); | |
| 9770 #endif | |
| 9771 } | |
| 9772 #endif | |
| 9773 | |
| 9774 /******************************************************************************/ | |
| 9775 #ifndef PALM_2 | |
| 9776 #ifndef HAVE_STRRCHR | |
| 9777 SOAP_FMAC1 | |
| 9778 char* | |
| 9779 SOAP_FMAC2 | |
| 9780 soap_strrchr(const char *s, int t) | |
| 9781 { register char *r = NULL; | |
| 9782 while (*s) | |
| 9783 if (*s++ == t) | |
| 9784 r = (char*)s - 1; | |
| 9785 return r; | |
| 9786 } | |
| 9787 #endif | |
| 9788 #endif | |
| 9789 | |
| 9790 /******************************************************************************/ | |
| 9791 #ifndef PALM_2 | |
| 9792 #ifndef HAVE_STRTOL | |
| 9793 SOAP_FMAC1 | |
| 9794 long | |
| 9795 SOAP_FMAC2 | |
| 9796 soap_strtol(const char *s, char **t, int b) | |
| 9797 { register long n = 0; | |
| 9798 register int c; | |
| 9799 while (*s > 0 && *s <= 32) | |
| 9800 s++; | |
| 9801 if (b == 10) | |
| 9802 { short neg = 0; | |
| 9803 if (*s == '-') | |
| 9804 { s++; | |
| 9805 neg = 1; | |
| 9806 } | |
| 9807 else if (*s == '+') | |
| 9808 s++; | |
| 9809 while ((c = *s) && c >= '0' && c <= '9') | |
| 9810 { if (n >= 214748364 && (n > 214748364 || c >= '8')) | |
| 9811 break; | |
| 9812 n *= 10; | |
| 9813 n += c - '0'; | |
| 9814 s++; | |
| 9815 } | |
| 9816 if (neg) | |
| 9817 n = -n; | |
| 9818 } | |
| 9819 else /* assume b == 16 and value is always positive */ | |
| 9820 { while ((c = *s)) | |
| 9821 { if (c >= '0' && c <= '9') | |
| 9822 c -= '0'; | |
| 9823 else if (c >= 'A' && c <= 'F') | |
| 9824 c -= 'A' - 10; | |
| 9825 else if (c >= 'a' && c <= 'f') | |
| 9826 c -= 'a' - 10; | |
| 9827 if (n > 0x07FFFFFF) | |
| 9828 break; | |
| 9829 n <<= 4; | |
| 9830 n += c; | |
| 9831 s++; | |
| 9832 } | |
| 9833 } | |
| 9834 if (t) | |
| 9835 *t = (char*)s; | |
| 9836 return n; | |
| 9837 } | |
| 9838 #endif | |
| 9839 #endif | |
| 9840 | |
| 9841 /******************************************************************************/ | |
| 9842 #ifndef PALM_2 | |
| 9843 #ifndef HAVE_STRTOUL | |
| 9844 SOAP_FMAC1 | |
| 9845 unsigned long | |
| 9846 SOAP_FMAC2 | |
| 9847 soap_strtoul(const char *s, char **t, int b) | |
| 9848 { unsigned long n = 0; | |
| 9849 register int c; | |
| 9850 while (*s > 0 && *s <= 32) | |
| 9851 s++; | |
| 9852 if (b == 10) | |
| 9853 { if (*s == '+') | |
| 9854 s++; | |
| 9855 while ((c = *s) && c >= '0' && c <= '9') | |
| 9856 { if (n >= 429496729 && (n > 429496729 || c >= '6')) | |
| 9857 break; | |
| 9858 n *= 10; | |
| 9859 n += c - '0'; | |
| 9860 s++; | |
| 9861 } | |
| 9862 } | |
| 9863 else /* b == 16 */ | |
| 9864 { while ((c = *s)) | |
| 9865 { if (c >= '0' && c <= '9') | |
| 9866 c -= '0'; | |
| 9867 else if (c >= 'A' && c <= 'F') | |
| 9868 c -= 'A' - 10; | |
| 9869 else if (c >= 'a' && c <= 'f') | |
| 9870 c -= 'a' - 10; | |
| 9871 if (n > 0x0FFFFFFF) | |
| 9872 break; | |
| 9873 n <<= 4; | |
| 9874 n += c; | |
| 9875 s++; | |
| 9876 } | |
| 9877 } | |
| 9878 if (t) | |
| 9879 *t = (char*)s; | |
| 9880 return n; | |
| 9881 } | |
| 9882 #endif | |
| 9883 #endif | |
| 9884 | |
| 9885 /******************************************************************************/ | |
| 9886 #ifndef PALM_1 | |
| 9887 SOAP_FMAC1 | |
| 9888 int | |
| 9889 SOAP_FMAC2 | |
| 9890 soap_array_begin_out(struct soap *soap, const char *tag, int id, const char *type, const char *offset) | |
| 9891 { if (!type || !*type) | |
| 9892 return soap_element_begin_out(soap, tag, id, NULL); | |
| 9893 if (soap_element(soap, tag, id, "SOAP-ENC:Array")) | |
| 9894 return soap->error; | |
| 9895 if (soap->version == 2) | |
| 9896 { const char *s; | |
| 9897 s = soap_strrchr(type, '['); | |
| 9898 if (s && (size_t)(s - type) < sizeof(soap->tmpbuf)) | |
| 9899 { strncpy(soap->tmpbuf, type, s - type); | |
| 9900 soap->tmpbuf[s - type] = '\0'; | |
| 9901 if (soap_attribute(soap, "SOAP-ENC:itemType", soap->tmpbuf)) | |
| 9902 return soap->error; | |
| 9903 s++; | |
| 9904 if (*s) | |
| 9905 { strncpy(soap->tmpbuf, s, sizeof(soap->tmpbuf)); | |
| 9906 soap->tmpbuf[sizeof(soap->tmpbuf) - 1] = '\0'; | |
| 9907 soap->tmpbuf[strlen(soap->tmpbuf) - 1] = '\0'; | |
| 9908 if (soap_attribute(soap, "SOAP-ENC:arraySize", soap->tmpbuf)) | |
| 9909 return soap->error; | |
| 9910 } | |
| 9911 } | |
| 9912 } | |
| 9913 else | |
| 9914 { if (offset && soap_attribute(soap, "SOAP-ENC:offset", offset)) | |
| 9915 return soap->error; | |
| 9916 if (soap_attribute(soap, "SOAP-ENC:arrayType", type)) | |
| 9917 return soap->error; | |
| 9918 } | |
| 9919 #ifndef WITH_LEAN | |
| 9920 if ((soap->mode & SOAP_XML_CANONICAL)) | |
| 9921 soap_utilize_ns(soap, type); | |
| 9922 #endif | |
| 9923 return soap_element_start_end_out(soap, NULL); | |
| 9924 } | |
| 9925 #endif | |
| 9926 | |
| 9927 /******************************************************************************/ | |
| 9928 #ifndef PALM_1 | |
| 9929 SOAP_FMAC1 | |
| 9930 int | |
| 9931 SOAP_FMAC2 | |
| 9932 soap_element_start_end_out(struct soap *soap, const char *tag) | |
| 9933 { register struct soap_attribute *tp; | |
| 9934 #ifndef WITH_LEAN | |
| 9935 if (soap->mode & SOAP_XML_CANONICAL) | |
| 9936 { struct soap_nlist *np; | |
| 9937 for (tp = soap->attributes; tp; tp = tp->next) | |
| 9938 { if (tp->visible && tp->name) | |
| 9939 soap_utilize_ns(soap, tp->name); | |
| 9940 } | |
| 9941 for (np = soap->nlist; np; np = np->next) | |
| 9942 { if (np->index == 1 && np->ns) | |
| 9943 { if (*(np->id)) | |
| 9944 { | |
| 9945 #ifdef HAVE_SNPRINTF | |
| 9946 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "xmlns:%s", np->id); | |
| 9947 #else | |
| 9948 sprintf(soap->tmpbuf, "xmlns:%s", np->id); | |
| 9949 #endif | |
| 9950 } | |
| 9951 else | |
| 9952 strcpy(soap->tmpbuf, "xmlns"); | |
| 9953 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enabling utilized binding (level=%u) %s='%s'\n", np->level, soap->tmpbuf, np->ns)); | |
| 9954 soap_set_attr(soap, soap->tmpbuf, np->ns, 1); | |
| 9955 np->index = 2; | |
| 9956 } | |
| 9957 } | |
| 9958 } | |
| 9959 #endif | |
| 9960 #ifdef WITH_DOM | |
| 9961 if ((soap->mode & SOAP_XML_DOM) && soap->dom) | |
| 9962 { register struct soap_dom_attribute **att; | |
| 9963 att = &soap->dom->atts; | |
| 9964 for (tp = soap->attributes; tp; tp = tp->next) | |
| 9965 { if (tp->visible) | |
| 9966 { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); | |
| 9967 if (!*att) | |
| 9968 return soap->error; | |
| 9969 (*att)->next = NULL; | |
| 9970 (*att)->nstr = NULL; | |
| 9971 (*att)->name = soap_strdup(soap, tp->name); | |
| 9972 (*att)->data = soap_strdup(soap, tp->value); | |
| 9973 (*att)->wide = NULL; | |
| 9974 (*att)->soap = soap; | |
| 9975 att = &(*att)->next; | |
| 9976 tp->visible = 0; | |
| 9977 } | |
| 9978 } | |
| 9979 return SOAP_OK; | |
| 9980 } | |
| 9981 #endif | |
| 9982 for (tp = soap->attributes; tp; tp = tp->next) | |
| 9983 { if (tp->visible) | |
| 9984 { | |
| 9985 #ifndef WITH_LEAN | |
| 9986 const char *s; | |
| 9987 if ((soap->mode & SOAP_XML_DEFAULTNS) && (s = strchr(tp->name, ':'))) | |
| 9988 { size_t n = s - tp->name; | |
| 9989 if (soap->nlist && !strncmp(soap->nlist->id, tp->name, n) && !soap->nlist->id[n]) | |
| 9990 s++; | |
| 9991 else | |
| 9992 s = tp->name; | |
| 9993 if (soap_send(soap, " ") || soap_send(soap, s)) | |
| 9994 return soap->error; | |
| 9995 } | |
| 9996 else | |
| 9997 #endif | |
| 9998 if (soap_send(soap, " ") || soap_send(soap, tp->name)) | |
| 9999 return soap->error; | |
| 10000 if (tp->visible == 2 && tp->value) | |
| 10001 if (soap_send_raw(soap, "=\"", 2) | |
| 10002 || soap_string_out(soap, tp->value, tp->flag) | |
| 10003 || soap_send_raw(soap, "\"", 1)) | |
| 10004 return soap->error; | |
| 10005 tp->visible = 0; | |
| 10006 } | |
| 10007 } | |
| 10008 if (tag) | |
| 10009 { | |
| 10010 #ifndef WITH_LEAN | |
| 10011 if (soap->mode & SOAP_XML_CANONICAL) | |
| 10012 { if (soap_send_raw(soap, ">", 1) | |
| 10013 || soap_element_end_out(soap, tag)) | |
| 10014 return soap->error; | |
| 10015 return SOAP_OK; | |
| 10016 } | |
| 10017 #endif | |
| 10018 soap->level--; /* decrement level just before /> */ | |
| 10019 return soap_send_raw(soap, "/>", 2); | |
| 10020 } | |
| 10021 return soap_send_raw(soap, ">", 1); | |
| 10022 } | |
| 10023 #endif | |
| 10024 | |
| 10025 /******************************************************************************/ | |
| 10026 #ifndef PALM_1 | |
| 10027 SOAP_FMAC1 | |
| 10028 int | |
| 10029 SOAP_FMAC2 | |
| 10030 soap_element_end_out(struct soap *soap, const char *tag) | |
| 10031 { | |
| 10032 #ifndef WITH_LEAN | |
| 10033 const char *s; | |
| 10034 #endif | |
| 10035 if (*tag == '-') | |
| 10036 return SOAP_OK; | |
| 10037 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element ending tag='%s'\n", tag)); | |
| 10038 #ifdef WITH_DOM | |
| 10039 if (soap->feltendout && (soap->error = soap->feltendout(soap, tag))) | |
| 10040 return soap->error; | |
| 10041 if ((soap->mode & SOAP_XML_DOM) && soap->dom) | |
| 10042 { if (soap->dom->prnt) | |
| 10043 soap->dom = soap->dom->prnt; | |
| 10044 return SOAP_OK; | |
| 10045 } | |
| 10046 #endif | |
| 10047 #ifndef WITH_LEAN | |
| 10048 if (soap->mode & SOAP_XML_CANONICAL) | |
| 10049 soap_pop_namespace(soap); | |
| 10050 if (soap->mode & SOAP_XML_INDENT) | |
| 10051 { if (!soap->body) | |
| 10052 { if (soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1)) | |
| 10053 return soap->error; | |
| 10054 } | |
| 10055 soap->body = 0; | |
| 10056 } | |
| 10057 if ((soap->mode & SOAP_XML_DEFAULTNS) && (s = strchr(tag, ':'))) | |
| 10058 { soap_pop_namespace(soap); | |
| 10059 tag = s + 1; | |
| 10060 } | |
| 10061 #endif | |
| 10062 if (soap_send_raw(soap, "</", 2) | |
| 10063 || soap_send(soap, tag)) | |
| 10064 return soap->error; | |
| 10065 soap->level--; /* decrement level just before > */ | |
| 10066 return soap_send_raw(soap, ">", 1); | |
| 10067 } | |
| 10068 #endif | |
| 10069 | |
| 10070 /******************************************************************************/ | |
| 10071 #ifndef PALM_1 | |
| 10072 SOAP_FMAC1 | |
| 10073 int | |
| 10074 SOAP_FMAC2 | |
| 10075 soap_element_ref(struct soap *soap, const char *tag, int id, int href) | |
| 10076 { register const char *s = "ref"; | |
| 10077 register int n = 1; | |
| 10078 if (soap->version == 1) | |
| 10079 { s = "href"; | |
| 10080 n = 0; | |
| 10081 } | |
| 10082 else if (soap->version == 2) | |
| 10083 s = "SOAP-ENC:ref"; | |
| 10084 #ifdef HAVE_SNPRINTF | |
| 10085 soap_snprintf(soap->href, sizeof(soap->href), "#_%d", href); | |
| 10086 #else | |
| 10087 sprintf(soap->href, "#_%d", href); | |
| 10088 #endif | |
| 10089 return soap_element_href(soap, tag, id, s, soap->href + n); | |
| 10090 } | |
| 10091 #endif | |
| 10092 | |
| 10093 /******************************************************************************/ | |
| 10094 #ifndef PALM_1 | |
| 10095 SOAP_FMAC1 | |
| 10096 int | |
| 10097 SOAP_FMAC2 | |
| 10098 soap_element_href(struct soap *soap, const char *tag, int id, const char *ref, const char *val) | |
| 10099 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element '%s' reference %s='%s'\n", tag, ref, val)); | |
| 10100 if (soap_element(soap, tag, id, NULL) | |
| 10101 || soap_attribute(soap, ref, val) | |
| 10102 || soap_element_start_end_out(soap, tag)) | |
| 10103 return soap->error; | |
| 10104 return SOAP_OK; | |
| 10105 } | |
| 10106 #endif | |
| 10107 | |
| 10108 /******************************************************************************/ | |
| 10109 #ifndef PALM_1 | |
| 10110 SOAP_FMAC1 | |
| 10111 int | |
| 10112 SOAP_FMAC2 | |
| 10113 soap_element_null(struct soap *soap, const char *tag, int id, const char *type) | |
| 10114 { struct soap_attribute *tp = NULL; | |
| 10115 for (tp = soap->attributes; tp; tp = tp->next) | |
| 10116 if (tp->visible) | |
| 10117 break; | |
| 10118 if (tp || (soap->version == 2 && soap->position > 0) || id > 0 || (soap->mode & SOAP_XML_NIL)) | |
| 10119 { if (soap_element(soap, tag, id, type) | |
| 10120 || (!tp && soap_attribute(soap, "xsi:nil", "true"))) | |
| 10121 return soap->error; | |
| 10122 return soap_element_start_end_out(soap, tag); | |
| 10123 } | |
| 10124 soap->null = 1; | |
| 10125 soap->position = 0; | |
| 10126 soap->mustUnderstand = 0; | |
| 10127 return SOAP_OK; | |
| 10128 } | |
| 10129 #endif | |
| 10130 | |
| 10131 /******************************************************************************/ | |
| 10132 #ifndef PALM_1 | |
| 10133 SOAP_FMAC1 | |
| 10134 int | |
| 10135 SOAP_FMAC2 | |
| 10136 soap_element_nil(struct soap *soap, const char *tag) | |
| 10137 { if (soap_element(soap, tag, -1, NULL) | |
| 10138 || ((soap->mode & SOAP_XML_NIL) && soap_attribute(soap, "xsi:nil", "true"))) | |
| 10139 return soap->error; | |
| 10140 return soap_element_start_end_out(soap, tag); | |
| 10141 } | |
| 10142 #endif | |
| 10143 | |
| 10144 /******************************************************************************/ | |
| 10145 #ifndef PALM_1 | |
| 10146 SOAP_FMAC1 | |
| 10147 int | |
| 10148 SOAP_FMAC2 | |
| 10149 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) | |
| 10150 { if (!p) | |
| 10151 { soap->error = soap_element_null(soap, tag, id, type); | |
| 10152 return -1; | |
| 10153 } | |
| 10154 #ifndef WITH_NOIDREF | |
| 10155 if ((!soap->encodingStyle && !(soap->omode & SOAP_XML_GRAPH)) || (soap->omode & SOAP_XML_TREE)) | |
| 10156 return 0; | |
| 10157 if (id < 0) | |
| 10158 { struct soap_plist *pp; | |
| 10159 if (a) | |
| 10160 id = soap_array_pointer_lookup(soap, p, a, n, t, &pp); | |
| 10161 else | |
| 10162 id = soap_pointer_lookup(soap, p, t, &pp); | |
| 10163 if (id) | |
| 10164 { if (soap_is_embedded(soap, pp)) | |
| 10165 { soap_element_ref(soap, tag, 0, id); | |
| 10166 return -1; | |
| 10167 } | |
| 10168 if (soap_is_single(soap, pp)) | |
| 10169 return 0; | |
| 10170 soap_set_embedded(soap, pp); | |
| 10171 } | |
| 10172 } | |
| 10173 return id; | |
| 10174 #else | |
| 10175 return 0; | |
| 10176 #endif | |
| 10177 } | |
| 10178 #endif | |
| 10179 | |
| 10180 /******************************************************************************/ | |
| 10181 #ifndef PALM_1 | |
| 10182 SOAP_FMAC1 | |
| 10183 int | |
| 10184 SOAP_FMAC2 | |
| 10185 soap_element_result(struct soap *soap, const char *tag) | |
| 10186 { if (soap->version == 2 && soap->encodingStyle) | |
| 10187 { if (soap_element(soap, "SOAP-RPC:result", 0, NULL) | |
| 10188 || soap_attribute(soap, "xmlns:SOAP-RPC", soap_rpc) | |
| 10189 || soap_element_start_end_out(soap, NULL) | |
| 10190 || soap_string_out(soap, tag, 0) | |
| 10191 || soap_element_end_out(soap, "SOAP-RPC:result")) | |
| 10192 return soap->error; | |
| 10193 } | |
| 10194 return SOAP_OK; | |
| 10195 } | |
| 10196 #endif | |
| 10197 | |
| 10198 /******************************************************************************/ | |
| 10199 #ifndef PALM_1 | |
| 10200 SOAP_FMAC1 | |
| 10201 void | |
| 10202 SOAP_FMAC2 | |
| 10203 soap_check_result(struct soap *soap, const char *tag) | |
| 10204 { if (soap->version == 2 && soap->encodingStyle) | |
| 10205 { soap_instring(soap, ":result", NULL, NULL, 0, 2, -1, -1); | |
| 10206 /* just ignore content for compliance reasons, but should compare tag to element's QName value? */ | |
| 10207 } | |
| 10208 (void)tag; | |
| 10209 } | |
| 10210 #endif | |
| 10211 | |
| 10212 /******************************************************************************/ | |
| 10213 #ifndef PALM_2 | |
| 10214 SOAP_FMAC1 | |
| 10215 int | |
| 10216 SOAP_FMAC2 | |
| 10217 soap_attribute(struct soap *soap, const char *name, const char *value) | |
| 10218 { | |
| 10219 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attribute '%s'='%s'\n", name, value)); | |
| 10220 #ifdef WITH_DOM | |
| 10221 if ((soap->mode & SOAP_XML_DOM) && !(soap->mode & SOAP_XML_CANONICAL) && soap->dom) | |
| 10222 { register struct soap_dom_attribute *a = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); | |
| 10223 if (!a) | |
| 10224 return soap->error; | |
| 10225 a->next = soap->dom->atts; | |
| 10226 a->nstr = NULL; | |
| 10227 a->name = soap_strdup(soap, name); | |
| 10228 a->data = soap_strdup(soap, value); | |
| 10229 a->wide = NULL; | |
| 10230 a->soap = soap; | |
| 10231 soap->dom->atts = a; | |
| 10232 return SOAP_OK; | |
| 10233 } | |
| 10234 #endif | |
| 10235 #ifndef WITH_LEAN | |
| 10236 if (soap->mode & SOAP_XML_CANONICAL) | |
| 10237 { /* push namespace */ | |
| 10238 if (!strncmp(name, "xmlns", 5) && (name[5] == ':' || name[5] == '\0')) | |
| 10239 soap_push_ns(soap, name + 5 + (name[5] == ':'), value, 0); | |
| 10240 else if (soap_set_attr(soap, name, value, 1)) | |
| 10241 return soap->error; | |
| 10242 } | |
| 10243 else | |
| 10244 #endif | |
| 10245 { if (soap_send(soap, " ") || soap_send(soap, name)) | |
| 10246 return soap->error; | |
| 10247 if (value) | |
| 10248 if (soap_send_raw(soap, "=\"", 2) | |
| 10249 || soap_string_out(soap, value, 1) | |
| 10250 || soap_send_raw(soap, "\"", 1)) | |
| 10251 return soap->error; | |
| 10252 } | |
| 10253 return SOAP_OK; | |
| 10254 } | |
| 10255 #endif | |
| 10256 | |
| 10257 /******************************************************************************/ | |
| 10258 #ifndef PALM_2 | |
| 10259 SOAP_FMAC1 | |
| 10260 int | |
| 10261 SOAP_FMAC2 | |
| 10262 soap_element_begin_in(struct soap *soap, const char *tag, int nillable, const char *type) | |
| 10263 { if (!soap_peek_element(soap)) | |
| 10264 { if (soap->other) | |
| 10265 return soap->error = SOAP_TAG_MISMATCH; | |
| 10266 if (tag && *tag == '-') | |
| 10267 return SOAP_OK; | |
| 10268 if (!(soap->error = soap_match_tag(soap, soap->tag, tag))) | |
| 10269 { soap->peeked = 0; | |
| 10270 if (type && *soap->type && soap_match_tag(soap, soap->type, type)) | |
| 10271 return soap->error = SOAP_TYPE; | |
| 10272 if (!nillable && soap->null && (soap->mode & SOAP_XML_STRICT)) | |
| 10273 return soap->error = SOAP_NULL; | |
| 10274 if (soap->body) | |
| 10275 soap->level++; | |
| 10276 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag ? tag : SOAP_STR_EOS )); | |
| 10277 soap->error = SOAP_OK; | |
| 10278 } | |
| 10279 } | |
| 10280 else if (soap->error == SOAP_NO_TAG && tag && *tag == '-') | |
| 10281 soap->error = SOAP_OK; | |
| 10282 return soap->error; | |
| 10283 } | |
| 10284 #endif | |
| 10285 | |
| 10286 /******************************************************************************/ | |
| 10287 #ifndef PALM_2 | |
| 10288 SOAP_FMAC1 | |
| 10289 int | |
| 10290 SOAP_FMAC2 | |
| 10291 soap_element_end_in(struct soap *soap, const char *tag) | |
| 10292 { register soap_wchar c; | |
| 10293 register char *s; | |
| 10294 register int n = 0; | |
| 10295 if (tag && *tag == '-') | |
| 10296 return SOAP_OK; | |
| 10297 if (soap->error == SOAP_NO_TAG) | |
| 10298 soap->error = SOAP_OK; | |
| 10299 #ifdef WITH_DOM | |
| 10300 /* this whitespace or mixed content is significant for DOM */ | |
| 10301 if ((soap->mode & SOAP_XML_DOM) && soap->dom) | |
| 10302 { if (!soap->peeked && !soap_string_in(soap, 3, -1, -1)) | |
| 10303 return soap->error; | |
| 10304 if (soap->dom->prnt) | |
| 10305 soap->dom = soap->dom->prnt; | |
| 10306 } | |
| 10307 #endif | |
| 10308 if (soap->peeked) | |
| 10309 { if (*soap->tag) | |
| 10310 n++; | |
| 10311 soap->peeked = 0; | |
| 10312 } | |
| 10313 do | |
| 10314 { while (((c = soap_get(soap)) != SOAP_TT)) | |
| 10315 { if ((int)c == EOF) | |
| 10316 return soap->error = SOAP_CHK_EOF; | |
| 10317 if (c == SOAP_LT) | |
| 10318 n++; | |
| 10319 else if (c == '/') | |
| 10320 { c = soap_get(soap); | |
| 10321 if (c == SOAP_GT) | |
| 10322 n--; | |
| 10323 else | |
| 10324 soap_unget(soap, c); | |
| 10325 } | |
| 10326 } | |
| 10327 } while (n--); | |
| 10328 s = soap->tag; | |
| 10329 n = sizeof(soap->tag); | |
| 10330 while (soap_notblank(c = soap_get(soap))) | |
| 10331 { if (--n > 0) | |
| 10332 *s++ = (char)c; | |
| 10333 } | |
| 10334 *s = '\0'; | |
| 10335 if ((int)c == EOF) | |
| 10336 return soap->error = SOAP_CHK_EOF; | |
| 10337 while (soap_blank(c)) | |
| 10338 c = soap_get(soap); | |
| 10339 if (c != SOAP_GT) | |
| 10340 return soap->error = SOAP_SYNTAX_ERROR; | |
| 10341 #ifndef WITH_LEAN | |
| 10342 #ifdef WITH_DOM | |
| 10343 if (soap->feltendin) | |
| 10344 { soap->level--; | |
| 10345 return soap->error = soap->feltendin(soap, soap->tag, tag); | |
| 10346 } | |
| 10347 #endif | |
| 10348 if (tag && (soap->mode & SOAP_XML_STRICT)) | |
| 10349 { soap_pop_namespace(soap); | |
| 10350 if (soap_match_tag(soap, soap->tag, tag)) | |
| 10351 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element tag '%s' does not match '%s'\n", soap->tag, tag ? tag : SOAP_STR_EOS)); | |
| 10352 return soap->error = SOAP_SYNTAX_ERROR; | |
| 10353 } | |
| 10354 } | |
| 10355 #endif | |
| 10356 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag ? tag : SOAP_STR_EOS)); | |
| 10357 soap->level--; | |
| 10358 return SOAP_OK; | |
| 10359 } | |
| 10360 #endif | |
| 10361 | |
| 10362 /******************************************************************************/ | |
| 10363 #ifndef PALM_2 | |
| 10364 SOAP_FMAC1 | |
| 10365 const char * | |
| 10366 SOAP_FMAC2 | |
| 10367 soap_attr_value(struct soap *soap, const char *name, int flag) | |
| 10368 { register struct soap_attribute *tp; | |
| 10369 if (*name == '-') | |
| 10370 return SOAP_STR_EOS; | |
| 10371 for (tp = soap->attributes; tp; tp = tp->next) | |
| 10372 { if (tp->visible && !soap_match_tag(soap, tp->name, name)) | |
| 10373 break; | |
| 10374 } | |
| 10375 if (tp) | |
| 10376 { if (flag == 2 && (soap->mode & SOAP_XML_STRICT)) | |
| 10377 soap->error = SOAP_PROHIBITED; | |
| 10378 else | |
| 10379 return tp->value; | |
| 10380 } | |
| 10381 else if (flag == 1 && (soap->mode & SOAP_XML_STRICT)) | |
| 10382 soap->error = SOAP_REQUIRED; | |
| 10383 else | |
| 10384 soap->error = SOAP_OK; | |
| 10385 return NULL; | |
| 10386 } | |
| 10387 #endif | |
| 10388 | |
| 10389 /******************************************************************************/ | |
| 10390 #ifndef PALM_2 | |
| 10391 SOAP_FMAC1 | |
| 10392 int | |
| 10393 SOAP_FMAC2 | |
| 10394 soap_set_attr(struct soap *soap, const char *name, const char *value, int flag) | |
| 10395 { register struct soap_attribute *tp; | |
| 10396 if (*name == '-') | |
| 10397 return SOAP_OK; | |
| 10398 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set attribute %s='%s'\n", name, value ? value : SOAP_STR_EOS)); | |
| 10399 for (tp = soap->attributes; tp; tp = tp->next) | |
| 10400 { if (!strcmp(tp->name, name)) | |
| 10401 break; | |
| 10402 } | |
| 10403 if (!tp) | |
| 10404 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute %s\n", name)); | |
| 10405 if (!(tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(name)))) | |
| 10406 return soap->error = SOAP_EOM; | |
| 10407 tp->ns = NULL; | |
| 10408 #ifndef WITH_LEAN | |
| 10409 if ((soap->mode & SOAP_XML_CANONICAL)) | |
| 10410 { struct soap_attribute **tpp = &soap->attributes; | |
| 10411 const char *s = strchr(name, ':'); | |
| 10412 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inserting attribute %s for c14n\n", name)); | |
| 10413 if (!strncmp(name, "xmlns", 5)) | |
| 10414 { for (; *tpp; tpp = &(*tpp)->next) | |
| 10415 if (strncmp((*tpp)->name, "xmlns", 5) || strcmp((*tpp)->name + 5, name + 5) > 0) | |
| 10416 break; | |
| 10417 } | |
| 10418 else if (!s) | |
| 10419 { for (; *tpp; tpp = &(*tpp)->next) | |
| 10420 if (strncmp((*tpp)->name, "xmlns", 5) && ((*tpp)->ns || strcmp((*tpp)->name, name) > 0)) | |
| 10421 break; | |
| 10422 } | |
| 10423 else | |
| 10424 { struct soap_nlist *np = soap_lookup_ns(soap, name, s - name); | |
| 10425 if (np) | |
| 10426 tp->ns = np->ns; | |
| 10427 else | |
| 10428 { struct soap_attribute *tq; | |
| 10429 for (tq = soap->attributes; tq; tq = tq->next) | |
| 10430 { if (!strncmp(tq->name, "xmlns:", 6) && !strncmp(tq->name + 6, name, s - name) && !tq->name[6 + s - name]) | |
| 10431 { tp->ns = tq->ns; | |
| 10432 break; | |
| 10433 } | |
| 10434 } | |
| 10435 } | |
| 10436 for (; *tpp; tpp = &(*tpp)->next) | |
| 10437 { int k; | |
| 10438 if (strncmp((*tpp)->name, "xmlns", 5) && (*tpp)->ns && tp->ns && ((k = strcmp((*tpp)->ns, tp->ns)) > 0 || (!k && strcmp((*tpp)->name, name) > 0))) | |
| 10439 break; | |
| 10440 } | |
| 10441 } | |
| 10442 tp->next = *tpp; | |
| 10443 *tpp = tp; | |
| 10444 } | |
| 10445 else | |
| 10446 #endif | |
| 10447 { tp->next = soap->attributes; | |
| 10448 soap->attributes = tp; | |
| 10449 } | |
| 10450 strcpy((char*)tp->name, name); | |
| 10451 tp->value = NULL; | |
| 10452 } | |
| 10453 else if (tp->visible) | |
| 10454 { return SOAP_OK; | |
| 10455 } | |
| 10456 else if (value && tp->value && tp->size <= strlen(value)) | |
| 10457 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute value of %s (free %p)\n", name, tp->value)); | |
| 10458 SOAP_FREE(soap, tp->value); | |
| 10459 tp->value = NULL; | |
| 10460 tp->ns = NULL; | |
| 10461 } | |
| 10462 if (value) | |
| 10463 { if (!tp->value) | |
| 10464 { tp->size = strlen(value) + 1; | |
| 10465 if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size))) | |
| 10466 return soap->error = SOAP_EOM; | |
| 10467 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute value for %s (%p)\n", tp->name, tp->value)); | |
| 10468 } | |
| 10469 strcpy(tp->value, value); | |
| 10470 if (!strncmp(tp->name, "xmlns:", 6)) | |
| 10471 tp->ns = tp->value; | |
| 10472 tp->visible = 2; | |
| 10473 tp->flag = (short)flag; | |
| 10474 #ifndef WITH_LEAN | |
| 10475 if (!strcmp(name, "wsu:Id")) | |
| 10476 { soap->event = SOAP_SEC_BEGIN; | |
| 10477 strncpy(soap->id, value, sizeof(soap->id)); | |
| 10478 soap->id[sizeof(soap->id) - 1] = '\0'; | |
| 10479 } | |
| 10480 #endif | |
| 10481 } | |
| 10482 else | |
| 10483 tp->visible = 1; | |
| 10484 return SOAP_OK; | |
| 10485 } | |
| 10486 #endif | |
| 10487 | |
| 10488 /******************************************************************************/ | |
| 10489 #ifndef PALM_2 | |
| 10490 SOAP_FMAC1 | |
| 10491 void | |
| 10492 SOAP_FMAC2 | |
| 10493 soap_clr_attr(struct soap *soap) | |
| 10494 { register struct soap_attribute *tp; | |
| 10495 #ifndef WITH_LEAN | |
| 10496 if ((soap->mode & SOAP_XML_CANONICAL)) | |
| 10497 { while (soap->attributes) | |
| 10498 { tp = soap->attributes->next; | |
| 10499 if (soap->attributes->value) | |
| 10500 SOAP_FREE(soap, soap->attributes->value); | |
| 10501 SOAP_FREE(soap, soap->attributes); | |
| 10502 soap->attributes = tp; | |
| 10503 } | |
| 10504 } | |
| 10505 else | |
| 10506 #endif | |
| 10507 { for (tp = soap->attributes; tp; tp = tp->next) | |
| 10508 tp->visible = 0; | |
| 10509 } | |
| 10510 } | |
| 10511 #endif | |
| 10512 | |
| 10513 /******************************************************************************/ | |
| 10514 #ifndef PALM_2 | |
| 10515 static int | |
| 10516 soap_getattrval(struct soap *soap, char *s, size_t n, soap_wchar d) | |
| 10517 { register size_t i; | |
| 10518 for (i = 0; i < n; i++) | |
| 10519 { register soap_wchar c = soap_get(soap); | |
| 10520 switch (c) | |
| 10521 { | |
| 10522 case SOAP_TT: | |
| 10523 *s++ = '<'; | |
| 10524 soap_unget(soap, '/'); | |
| 10525 break; | |
| 10526 case SOAP_LT: | |
| 10527 *s++ = '<'; | |
| 10528 break; | |
| 10529 case SOAP_GT: | |
| 10530 if (d == ' ') | |
| 10531 { soap_unget(soap, c); | |
| 10532 *s = '\0'; | |
| 10533 return SOAP_OK; | |
| 10534 } | |
| 10535 *s++ = '>'; | |
| 10536 break; | |
| 10537 case SOAP_QT: | |
| 10538 if (c == d) | |
| 10539 { *s = '\0'; | |
| 10540 return SOAP_OK; | |
| 10541 } | |
| 10542 *s++ = '"'; | |
| 10543 break; | |
| 10544 case SOAP_AP: | |
| 10545 if (c == d) | |
| 10546 { *s = '\0'; | |
| 10547 return SOAP_OK; | |
| 10548 } | |
| 10549 *s++ = '\''; | |
| 10550 break; | |
| 10551 case '\t': | |
| 10552 case '\n': | |
| 10553 case '\r': | |
| 10554 case ' ': | |
| 10555 case '/': | |
| 10556 if (d == ' ') | |
| 10557 { soap_unget(soap, c); | |
| 10558 *s = '\0'; | |
| 10559 return SOAP_OK; | |
| 10560 } | |
| 10561 default: | |
| 10562 if ((int)c == EOF) | |
| 10563 { *s = '\0'; | |
| 10564 return soap->error = SOAP_CHK_EOF; | |
| 10565 } | |
| 10566 *s++ = (char)c; | |
| 10567 } | |
| 10568 } | |
| 10569 return soap->error = SOAP_EOM; | |
| 10570 } | |
| 10571 #endif | |
| 10572 | |
| 10573 /******************************************************************************/ | |
| 10574 #ifdef WITH_FAST | |
| 10575 #ifndef PALM_2 | |
| 10576 SOAP_FMAC1 | |
| 10577 int | |
| 10578 SOAP_FMAC2 | |
| 10579 soap_store_lab(struct soap *soap, const char *s, size_t n) | |
| 10580 { soap->labidx = 0; | |
| 10581 return soap_append_lab(soap, s, n); | |
| 10582 } | |
| 10583 #endif | |
| 10584 #endif | |
| 10585 | |
| 10586 /******************************************************************************/ | |
| 10587 #ifdef WITH_FAST | |
| 10588 #ifndef PALM_2 | |
| 10589 SOAP_FMAC1 | |
| 10590 int | |
| 10591 SOAP_FMAC2 | |
| 10592 soap_append_lab(struct soap *soap, const char *s, size_t n) | |
| 10593 { if (soap->labidx + n >= soap->lablen) | |
| 10594 { register char *t = soap->labbuf; | |
| 10595 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enlarging look-aside buffer to append data, size=%lu\n", (unsigned long)soap->lablen)); | |
| 10596 if (soap->lablen == 0) | |
| 10597 soap->lablen = SOAP_LABLEN; | |
| 10598 while (soap->labidx + n >= soap->lablen) | |
| 10599 soap->lablen <<= 1; | |
| 10600 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New look-aside buffer size=%lu\n", (unsigned long)soap->lablen)); | |
| 10601 soap->labbuf = (char*)SOAP_MALLOC(soap, soap->lablen); | |
| 10602 if (!soap->labbuf) | |
| 10603 { if (t) | |
| 10604 SOAP_FREE(soap, t); | |
| 10605 return soap->error = SOAP_EOM; | |
| 10606 } | |
| 10607 if (t) | |
| 10608 { memcpy(soap->labbuf, t, soap->labidx); | |
| 10609 SOAP_FREE(soap, t); | |
| 10610 } | |
| 10611 } | |
| 10612 if (s) | |
| 10613 { memcpy(soap->labbuf + soap->labidx, s, n); | |
| 10614 soap->labidx += n; | |
| 10615 } | |
| 10616 return SOAP_OK; | |
| 10617 } | |
| 10618 #endif | |
| 10619 #endif | |
| 10620 | |
| 10621 /******************************************************************************/ | |
| 10622 #ifndef PALM_2 | |
| 10623 SOAP_FMAC1 | |
| 10624 int | |
| 10625 SOAP_FMAC2 | |
| 10626 soap_peek_element(struct soap *soap) | |
| 10627 { | |
| 10628 #ifdef WITH_DOM | |
| 10629 register struct soap_dom_attribute **att = NULL; | |
| 10630 register char *lead = NULL; | |
| 10631 #endif | |
| 10632 register struct soap_attribute *tp, *tq = NULL; | |
| 10633 register const char *t; | |
| 10634 register char *s; | |
| 10635 register soap_wchar c; | |
| 10636 register int i; | |
| 10637 if (soap->peeked) | |
| 10638 { if (!*soap->tag) | |
| 10639 return soap->error = SOAP_NO_TAG; | |
| 10640 return SOAP_OK; | |
| 10641 } | |
| 10642 soap->peeked = 1; | |
| 10643 soap->id[0] = '\0'; | |
| 10644 soap->href[0] = '\0'; | |
| 10645 soap->type[0] = '\0'; | |
| 10646 soap->arrayType[0] = '\0'; | |
| 10647 soap->arraySize[0] = '\0'; | |
| 10648 soap->arrayOffset[0] = '\0'; | |
| 10649 soap->other = 0; | |
| 10650 soap->root = -1; | |
| 10651 soap->position = 0; | |
| 10652 soap->null = 0; | |
| 10653 soap->mustUnderstand = 0; | |
| 10654 /* UTF-8 BOM? */ | |
| 10655 c = soap_getchar(soap); | |
| 10656 if (c == 0xEF && soap_get0(soap) == 0xBB) | |
| 10657 { c = soap_get1(soap); | |
| 10658 if ((c = soap_get1(soap)) == 0xBF) | |
| 10659 soap->mode &= ~SOAP_ENC_LATIN; | |
| 10660 else | |
| 10661 soap_unget(soap, (0x0F << 12) | (0xBB << 6) | (c & 0x3F)); /* UTF-8 */ | |
| 10662 } | |
| 10663 else if ((c == 0xFE && soap_get0(soap) == 0xFF) /* UTF-16 BE */ | |
| 10664 || (c == 0xFF && soap_get0(soap) == 0xFE)) /* UTF-16 LE */ | |
| 10665 return soap->error = SOAP_UTF_ERROR; | |
| 10666 else | |
| 10667 soap_unget(soap, c); | |
| 10668 c = soap_get(soap); | |
| 10669 #ifdef WITH_DOM | |
| 10670 /* whitespace leading to tag is not insignificant for DOM */ | |
| 10671 if (soap_blank(c)) | |
| 10672 { soap->labidx = 0; | |
| 10673 do | |
| 10674 { if (soap_append_lab(soap, NULL, 0)) | |
| 10675 return soap->error; | |
| 10676 s = soap->labbuf + soap->labidx; | |
| 10677 i = soap->lablen - soap->labidx; | |
| 10678 soap->labidx = soap->lablen; | |
| 10679 while (soap_blank(c) && i--) | |
| 10680 { *s++ = c; | |
| 10681 c = soap_get(soap); | |
| 10682 } | |
| 10683 } | |
| 10684 while (soap_blank(c)); | |
| 10685 *s = '\0'; | |
| 10686 lead = soap->labbuf; | |
| 10687 } | |
| 10688 #else | |
| 10689 /* skip space */ | |
| 10690 while (soap_blank(c)) | |
| 10691 c = soap_get(soap); | |
| 10692 #endif | |
| 10693 if (c != SOAP_LT) | |
| 10694 { *soap->tag = '\0'; | |
| 10695 if ((int)c == EOF) | |
| 10696 return soap->error = SOAP_CHK_EOF; | |
| 10697 soap_unget(soap, c); | |
| 10698 #ifdef WITH_DOM | |
| 10699 /* whitespace leading to end tag is significant for DOM */ | |
| 10700 if ((soap->mode & SOAP_XML_DOM) && soap->dom) | |
| 10701 { if (lead && *lead) | |
| 10702 soap->dom->tail = soap_strdup(soap, lead); | |
| 10703 else | |
| 10704 soap->dom->tail = (char*)SOAP_STR_EOS; | |
| 10705 } | |
| 10706 #endif | |
| 10707 return soap->error = SOAP_NO_TAG; | |
| 10708 } | |
| 10709 do c = soap_get1(soap); | |
| 10710 while (soap_blank(c)); | |
| 10711 s = soap->tag; | |
| 10712 i = sizeof(soap->tag); | |
| 10713 while (c != '>' && c != '/' && soap_notblank(c) && (int)c != EOF) | |
| 10714 { if (--i > 0) | |
| 10715 *s++ = (char)c; | |
| 10716 c = soap_get1(soap); | |
| 10717 } | |
| 10718 *s = '\0'; | |
| 10719 while (soap_blank(c)) | |
| 10720 c = soap_get1(soap); | |
| 10721 #ifdef WITH_DOM | |
| 10722 if (soap->mode & SOAP_XML_DOM) | |
| 10723 { register struct soap_dom_element *elt; | |
| 10724 elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element)); | |
| 10725 if (!elt) | |
| 10726 return soap->error; | |
| 10727 elt->next = NULL; | |
| 10728 elt->nstr = NULL; | |
| 10729 elt->name = soap_strdup(soap, soap->tag); | |
| 10730 elt->prnt = soap->dom; | |
| 10731 elt->elts = NULL; | |
| 10732 elt->atts = NULL; | |
| 10733 elt->data = NULL; | |
| 10734 elt->wide = NULL; | |
| 10735 elt->type = 0; | |
| 10736 elt->node = NULL; | |
| 10737 elt->head = soap_strdup(soap, lead); | |
| 10738 elt->tail = NULL; | |
| 10739 elt->soap = soap; | |
| 10740 if (soap->dom) | |
| 10741 { struct soap_dom_element *p = soap->dom->elts; | |
| 10742 if (p) | |
| 10743 { while (p->next) | |
| 10744 p = p->next; | |
| 10745 p->next = elt; | |
| 10746 } | |
| 10747 else | |
| 10748 soap->dom->elts = elt; | |
| 10749 } | |
| 10750 soap->dom = elt; | |
| 10751 att = &elt->atts; | |
| 10752 } | |
| 10753 #endif | |
| 10754 soap_pop_namespace(soap); | |
| 10755 for (tp = soap->attributes; tp; tp = tp->next) | |
| 10756 tp->visible = 0; | |
| 10757 while ((int)c != EOF && c != '>' && c != '/') | |
| 10758 { s = soap->tmpbuf; | |
| 10759 i = sizeof(soap->tmpbuf); | |
| 10760 while (c != '=' && c != '>' && c != '/' && soap_notblank(c) && (int)c != EOF) | |
| 10761 { if (--i > 0) | |
| 10762 *s++ = (char)c; | |
| 10763 c = soap_get1(soap); | |
| 10764 } | |
| 10765 *s = '\0'; | |
| 10766 if (i == sizeof(soap->tmpbuf)) | |
| 10767 return soap->error = SOAP_SYNTAX_ERROR; | |
| 10768 #ifdef WITH_DOM | |
| 10769 /* add attribute name to dom */ | |
| 10770 if (att) | |
| 10771 { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); | |
| 10772 if (!*att) | |
| 10773 return soap->error; | |
| 10774 (*att)->next = NULL; | |
| 10775 (*att)->nstr = NULL; | |
| 10776 (*att)->name = soap_strdup(soap, soap->tmpbuf); | |
| 10777 (*att)->data = NULL; | |
| 10778 (*att)->wide = NULL; | |
| 10779 (*att)->soap = soap; | |
| 10780 } | |
| 10781 #endif | |
| 10782 if (!strncmp(soap->tmpbuf, "xmlns", 5)) | |
| 10783 { if (soap->tmpbuf[5] == ':') | |
| 10784 t = soap->tmpbuf + 6; | |
| 10785 else if (soap->tmpbuf[5]) | |
| 10786 t = NULL; | |
| 10787 else | |
| 10788 t = SOAP_STR_EOS; | |
| 10789 } | |
| 10790 else | |
| 10791 t = NULL; | |
| 10792 tq = NULL; | |
| 10793 for (tp = soap->attributes; tp; tq = tp, tp = tp->next) | |
| 10794 { if (!SOAP_STRCMP(tp->name, soap->tmpbuf)) | |
| 10795 break; | |
| 10796 } | |
| 10797 if (!tp) | |
| 10798 { tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(soap->tmpbuf)); | |
| 10799 if (!tp) | |
| 10800 return soap->error = SOAP_EOM; | |
| 10801 strcpy((char*)tp->name, soap->tmpbuf); | |
| 10802 tp->value = NULL; | |
| 10803 tp->size = 0; | |
| 10804 tp->ns = NULL; | |
| 10805 /* if attribute name is qualified, append it to the end of the list */ | |
| 10806 if (tq && strchr(soap->tmpbuf, ':')) | |
| 10807 { tq->next = tp; | |
| 10808 tp->next = NULL; | |
| 10809 } | |
| 10810 else | |
| 10811 { tp->next = soap->attributes; | |
| 10812 soap->attributes = tp; | |
| 10813 } | |
| 10814 } | |
| 10815 while (soap_blank(c)) | |
| 10816 c = soap_get1(soap); | |
| 10817 if (c == '=') | |
| 10818 { do c = soap_getutf8(soap); | |
| 10819 while (soap_blank(c)); | |
| 10820 if (c != SOAP_QT && c != SOAP_AP) | |
| 10821 { soap_unget(soap, c); | |
| 10822 c = ' '; /* blank delimiter */ | |
| 10823 } | |
| 10824 if (soap_getattrval(soap, tp->value, tp->size, c)) | |
| 10825 { | |
| 10826 #ifdef WITH_FAST | |
| 10827 if (soap->error != SOAP_EOM) | |
| 10828 return soap->error; | |
| 10829 soap->error = SOAP_OK; | |
| 10830 if (soap_store_lab(soap, tp->value, tp->size)) | |
| 10831 return soap->error; | |
| 10832 if (tp->value) | |
| 10833 SOAP_FREE(soap, tp->value); | |
| 10834 tp->value = NULL; | |
| 10835 for (;;) | |
| 10836 { if (soap_getattrval(soap, soap->labbuf + soap->labidx, soap->lablen - soap->labidx, c)) | |
| 10837 { if (soap->error != SOAP_EOM) | |
| 10838 return soap->error; | |
| 10839 soap->error = SOAP_OK; | |
| 10840 soap->labidx = soap->lablen; | |
| 10841 if (soap_append_lab(soap, NULL, 0)) | |
| 10842 return soap->error; | |
| 10843 } | |
| 10844 else | |
| 10845 break; | |
| 10846 } | |
| 10847 if (soap->labidx) | |
| 10848 tp->size = soap->lablen; | |
| 10849 else | |
| 10850 { tp->size = strlen(soap->labbuf) + 1; | |
| 10851 if (tp->size < SOAP_LABLEN) | |
| 10852 tp->size = SOAP_LABLEN; | |
| 10853 } | |
| 10854 if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size))) | |
| 10855 return soap->error = SOAP_EOM; | |
| 10856 strcpy(tp->value, soap->labbuf); | |
| 10857 #else | |
| 10858 size_t n; | |
| 10859 if (soap->error != SOAP_EOM) | |
| 10860 return soap->error; | |
| 10861 soap->error = SOAP_OK; | |
| 10862 if (soap_new_block(soap) == NULL) | |
| 10863 return soap->error; | |
| 10864 for (;;) | |
| 10865 { if (!(s = (char*)soap_push_block(soap, NULL, SOAP_BLKLEN))) | |
| 10866 return soap->error; | |
| 10867 if (soap_getattrval(soap, s, SOAP_BLKLEN, c)) | |
| 10868 { if (soap->error != SOAP_EOM) | |
| 10869 return soap->error; | |
| 10870 soap->error = SOAP_OK; | |
| 10871 } | |
| 10872 else | |
| 10873 break; | |
| 10874 } | |
| 10875 n = tp->size + soap->blist->size; | |
| 10876 if (!(s = (char*)SOAP_MALLOC(soap, n))) | |
| 10877 return soap->error = SOAP_EOM; | |
| 10878 if (tp->value) | |
| 10879 { memcpy(s, tp->value, tp->size); | |
| 10880 SOAP_FREE(soap, tp->value); | |
| 10881 } | |
| 10882 soap_save_block(soap, NULL, s + tp->size, 0); | |
| 10883 tp->value = s; | |
| 10884 tp->size = n; | |
| 10885 #endif | |
| 10886 } | |
| 10887 do c = soap_get1(soap); | |
| 10888 while (soap_blank(c)); | |
| 10889 tp->visible = 2; /* seen this attribute w/ value */ | |
| 10890 #ifdef WITH_DOM | |
| 10891 if (att) | |
| 10892 (*att)->data = soap_strdup(soap, tp->value); | |
| 10893 #endif | |
| 10894 } | |
| 10895 else | |
| 10896 tp->visible = 1; /* seen this attribute w/o value */ | |
| 10897 #ifdef WITH_DOM | |
| 10898 if (att) | |
| 10899 att = &(*att)->next; | |
| 10900 #endif | |
| 10901 if (t && tp->value) | |
| 10902 { if (soap_push_namespace(soap, t, tp->value) == NULL) | |
| 10903 return soap->error; | |
| 10904 } | |
| 10905 } | |
| 10906 #ifdef WITH_DOM | |
| 10907 if (att) | |
| 10908 { soap->dom->nstr = soap_current_namespace(soap, soap->tag); | |
| 10909 for (att = &soap->dom->atts; *att; att = &(*att)->next) | |
| 10910 (*att)->nstr = soap_current_namespace(soap, (*att)->name); | |
| 10911 } | |
| 10912 #endif | |
| 10913 if ((int)c == EOF) | |
| 10914 return soap->error = SOAP_CHK_EOF; | |
| 10915 if (!(soap->body = (c != '/'))) | |
| 10916 do c = soap_get1(soap); | |
| 10917 while (soap_blank(c)); | |
| 10918 #ifdef WITH_DOM | |
| 10919 if (soap->mode & SOAP_XML_DOM) | |
| 10920 { if (!soap->body && soap->dom->prnt) | |
| 10921 soap->dom = soap->dom->prnt; | |
| 10922 } | |
| 10923 #endif | |
| 10924 for (tp = soap->attributes; tp; tp = tp->next) | |
| 10925 { if (tp->visible && tp->value) | |
| 10926 { | |
| 10927 #ifndef WITH_NOIDREF | |
| 10928 if (!strcmp(tp->name, "id")) | |
| 10929 { if ((soap->version > 0 && !(soap->imode & SOAP_XML_TREE)) | |
| 10930 || (soap->mode & SOAP_XML_GRAPH)) | |
| 10931 { *soap->id = '#'; | |
| 10932 strncpy(soap->id + 1, tp->value, sizeof(soap->id) - 2); | |
| 10933 soap->id[sizeof(soap->id) - 1] = '\0'; | |
| 10934 } | |
| 10935 } | |
| 10936 else if (!strcmp(tp->name, "href")) | |
| 10937 { if ((soap->version == 1 && !(soap->imode & SOAP_XML_TREE)) | |
| 10938 || (soap->mode & SOAP_XML_GRAPH) | |
| 10939 || (soap->mode & SOAP_ENC_MTOM) | |
| 10940 || (soap->mode & SOAP_ENC_DIME)) | |
| 10941 { strncpy(soap->href, tp->value, sizeof(soap->href) - 1); | |
| 10942 soap->href[sizeof(soap->href) - 1] = '\0'; | |
| 10943 } | |
| 10944 } | |
| 10945 else if (!strcmp(tp->name, "ref")) | |
| 10946 { if ((soap->version == 2 && !(soap->imode & SOAP_XML_TREE)) | |
| 10947 || (soap->mode & SOAP_XML_GRAPH)) | |
| 10948 { *soap->href = '#'; | |
| 10949 strncpy(soap->href + (*tp->value != '#'), tp->value, sizeof(soap->href) - 2); | |
| 10950 soap->href[sizeof(soap->href) - 1] = '\0'; | |
| 10951 } | |
| 10952 } | |
| 10953 else | |
| 10954 #endif | |
| 10955 if (!soap_match_tag(soap, tp->name, "xsi:type")) | |
| 10956 { strncpy(soap->type, tp->value, sizeof(soap->type) - 1); | |
| 10957 soap->type[sizeof(soap->type) - 1] = '\0'; | |
| 10958 } | |
| 10959 else if ((!soap_match_tag(soap, tp->name, "xsi:null") | |
| 10960 || !soap_match_tag(soap, tp->name, "xsi:nil")) | |
| 10961 && (!strcmp(tp->value, "1") | |
| 10962 || !strcmp(tp->value, "true"))) | |
| 10963 { soap->null = 1; | |
| 10964 } | |
| 10965 else if (soap->version == 1) | |
| 10966 { if (!soap_match_tag(soap, tp->name, "SOAP-ENC:arrayType")) | |
| 10967 { s = soap_strrchr(tp->value, '['); | |
| 10968 if (s && (size_t)(s - tp->value) < sizeof(soap->arrayType)) | |
| 10969 { strncpy(soap->arrayType, tp->value, s - tp->value); | |
| 10970 soap->arrayType[s - tp->value] = '\0'; | |
| 10971 strncpy(soap->arraySize, s, sizeof(soap->arraySize)); | |
| 10972 } | |
| 10973 else | |
| 10974 strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType)); | |
| 10975 soap->arraySize[sizeof(soap->arraySize) - 1] = '\0'; | |
| 10976 soap->arrayType[sizeof(soap->arrayType) - 1] = '\0'; | |
| 10977 } | |
| 10978 else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:offset")) | |
| 10979 strncpy(soap->arrayOffset, tp->value, sizeof(soap->arrayOffset)); | |
| 10980 else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:position")) | |
| 10981 soap->position = soap_getposition(tp->value, soap->positions); | |
| 10982 else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:root")) | |
| 10983 soap->root = ((!strcmp(tp->value, "1") || !strcmp(tp->value, "true"))); | |
| 10984 else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand") | |
| 10985 && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true"))) | |
| 10986 soap->mustUnderstand = 1; | |
| 10987 else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:actor")) | |
| 10988 { if ((!soap->actor || strcmp(soap->actor, tp->value)) | |
| 10989 && strcmp(tp->value, "http://schemas.xmlsoap.org/soap/actor/next")) | |
| 10990 soap->other = 1; | |
| 10991 } | |
| 10992 } | |
| 10993 else if (soap->version == 2) | |
| 10994 { | |
| 10995 #ifndef WITH_NOIDREF | |
| 10996 if (!soap_match_tag(soap, tp->name, "SOAP-ENC:id")) | |
| 10997 { *soap->id = '#'; | |
| 10998 strncpy(soap->id + 1, tp->value, sizeof(soap->id) - 2); | |
| 10999 soap->id[sizeof(soap->id) - 1] = '\0'; | |
| 11000 } | |
| 11001 else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:ref")) | |
| 11002 { *soap->href = '#'; | |
| 11003 strncpy(soap->href + (*tp->value != '#'), tp->value, sizeof(soap->href) - 2); | |
| 11004 soap->href[sizeof(soap->href) - 1] = '\0'; | |
| 11005 } | |
| 11006 else | |
| 11007 #endif | |
| 11008 if (!soap_match_tag(soap, tp->name, "SOAP-ENC:itemType")) | |
| 11009 strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1); | |
| 11010 else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:arraySize")) | |
| 11011 strncpy(soap->arraySize, tp->value, sizeof(soap->arraySize) - 1); | |
| 11012 else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand") | |
| 11013 && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true"))) | |
| 11014 soap->mustUnderstand = 1; | |
| 11015 else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:role")) | |
| 11016 { if ((!soap->actor || strcmp(soap->actor, tp->value)) | |
| 11017 && strcmp(tp->value, "http://www.w3.org/2003/05/soap-envelope/role/next")) | |
| 11018 soap->other = 1; | |
| 11019 } | |
| 11020 } | |
| 11021 else | |
| 11022 { if (!soap_match_tag(soap, tp->name, "wsdl:required") && !strcmp(tp->value, "true")) | |
| 11023 soap->mustUnderstand = 1; | |
| 11024 } | |
| 11025 } | |
| 11026 } | |
| 11027 #ifdef WITH_DOM | |
| 11028 if (soap->feltbegin) | |
| 11029 return soap->error = soap->feltbegin(soap, soap->tag); | |
| 11030 #endif | |
| 11031 return soap->error = SOAP_OK; | |
| 11032 } | |
| 11033 #endif | |
| 11034 | |
| 11035 /******************************************************************************/ | |
| 11036 #ifndef PALM_2 | |
| 11037 SOAP_FMAC1 | |
| 11038 void | |
| 11039 SOAP_FMAC2 | |
| 11040 soap_retry(struct soap *soap) | |
| 11041 { soap->error = SOAP_OK; | |
| 11042 soap_revert(soap); | |
| 11043 } | |
| 11044 #endif | |
| 11045 | |
| 11046 /******************************************************************************/ | |
| 11047 #ifndef PALM_2 | |
| 11048 SOAP_FMAC1 | |
| 11049 void | |
| 11050 SOAP_FMAC2 | |
| 11051 soap_revert(struct soap *soap) | |
| 11052 { if (!soap->peeked) | |
| 11053 { soap->peeked = 1; | |
| 11054 if (soap->body) | |
| 11055 soap->level--; | |
| 11056 } | |
| 11057 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reverting to last element '%s' (level=%u)\n", soap->tag, soap->level)); | |
| 11058 } | |
| 11059 #endif | |
| 11060 | |
| 11061 /******************************************************************************/ | |
| 11062 #ifndef PALM_2 | |
| 11063 SOAP_FMAC1 | |
| 11064 int | |
| 11065 SOAP_FMAC2 | |
| 11066 soap_string_out(struct soap *soap, const char *s, int flag) | |
| 11067 { register const char *t; | |
| 11068 register soap_wchar c; | |
| 11069 register soap_wchar mask = (soap_wchar)0xFFFFFF80UL; | |
| 11070 #ifdef WITH_DOM | |
| 11071 if ((soap->mode & SOAP_XML_DOM) && soap->dom) | |
| 11072 { soap->dom->data = soap_strdup(soap, s); | |
| 11073 return SOAP_OK; | |
| 11074 } | |
| 11075 #endif | |
| 11076 if (flag == 2 || soap->mode & SOAP_C_UTFSTRING) | |
| 11077 mask = 0; | |
| 11078 t = s; | |
| 11079 while ((c = *t++)) | |
| 11080 { switch (c) | |
| 11081 { | |
| 11082 case 0x09: | |
| 11083 if (flag) | |
| 11084 { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "	", 5)) | |
| 11085 return soap->error; | |
| 11086 s = t; | |
| 11087 } | |
| 11088 break; | |
| 11089 case 0x0A: | |
| 11090 if (flag || !(soap->mode & SOAP_XML_CANONICAL)) | |
| 11091 { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "
", 5)) | |
| 11092 return soap->error; | |
| 11093 s = t; | |
| 11094 } | |
| 11095 break; | |
| 11096 case 0x0D: | |
| 11097 if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "
", 5)) | |
| 11098 return soap->error; | |
| 11099 s = t; | |
| 11100 break; | |
| 11101 case '&': | |
| 11102 if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&", 5)) | |
| 11103 return soap->error; | |
| 11104 s = t; | |
| 11105 break; | |
| 11106 case '<': | |
| 11107 if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "<", 4)) | |
| 11108 return soap->error; | |
| 11109 s = t; | |
| 11110 break; | |
| 11111 case '>': | |
| 11112 if (!flag) | |
| 11113 { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, ">", 4)) | |
| 11114 return soap->error; | |
| 11115 s = t; | |
| 11116 } | |
| 11117 break; | |
| 11118 case '"': | |
| 11119 if (flag) | |
| 11120 { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, """, 6)) | |
| 11121 return soap->error; | |
| 11122 s = t; | |
| 11123 } | |
| 11124 break; | |
| 11125 default: | |
| 11126 #ifndef WITH_LEANER | |
| 11127 #ifdef HAVE_MBTOWC | |
| 11128 if (soap->mode & SOAP_C_MBSTRING) | |
| 11129 { wchar_t wc; | |
| 11130 register int m = mbtowc(&wc, t - 1, MB_CUR_MAX); | |
| 11131 if (m > 0 && !((soap_wchar)wc == c && m == 1 && c < 0x80)) | |
| 11132 { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned long)wc)) | |
| 11133 return soap->error; | |
| 11134 s = t += m - 1; | |
| 11135 continue; | |
| 11136 } | |
| 11137 } | |
| 11138 #endif | |
| 11139 #endif | |
| 11140 #ifndef WITH_NOSTRINGTOUTF8 | |
| 11141 if ((c & mask) || !(c & 0xFFFFFFE0UL)) | |
| 11142 { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned char)c)) | |
| 11143 return soap->error; | |
| 11144 s = t; | |
| 11145 } | |
| 11146 #endif | |
| 11147 } | |
| 11148 } | |
| 11149 return soap_send_raw(soap, s, t - s - 1); | |
| 11150 } | |
| 11151 #endif | |
| 11152 | |
| 11153 /******************************************************************************/ | |
| 11154 #ifndef PALM_2 | |
| 11155 SOAP_FMAC1 | |
| 11156 char * | |
| 11157 SOAP_FMAC2 | |
| 11158 soap_string_in(struct soap *soap, int flag, long minlen, long maxlen) | |
| 11159 { register char *s; | |
| 11160 char *t = NULL; | |
| 11161 register size_t i; | |
| 11162 register long l = 0; | |
| 11163 register int n = 0, f = 0, m = 0; | |
| 11164 register soap_wchar c; | |
| 11165 #if !defined(WITH_LEANER) && defined(HAVE_WCTOMB) | |
| 11166 char buf[MB_LEN_MAX > 8 ? MB_LEN_MAX : 8]; | |
| 11167 #else | |
| 11168 char buf[8]; | |
| 11169 #endif | |
| 11170 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading string content, flag=%d\n", flag)); | |
| 11171 if (soap->peeked && *soap->tag) | |
| 11172 { | |
| 11173 #ifndef WITH_LEAN | |
| 11174 struct soap_attribute *tp; | |
| 11175 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String content includes tag '%s' and attributes\n", soap->tag)); | |
| 11176 t = soap->tmpbuf; | |
| 11177 *t = '<'; | |
| 11178 strncpy(t + 1, soap->tag, sizeof(soap->tmpbuf) - 2); | |
| 11179 t[sizeof(soap->tmpbuf) - 1] = '\0'; | |
| 11180 t += strlen(t); | |
| 11181 for (tp = soap->attributes; tp; tp = tp->next) | |
| 11182 { if (tp->visible) | |
| 11183 { if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2) | |
| 11184 break; | |
| 11185 *t++ = ' '; | |
| 11186 strcpy(t, tp->name); | |
| 11187 t += strlen(t); | |
| 11188 if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2) | |
| 11189 break; /* too many or large attribute values */ | |
| 11190 if (tp->value) | |
| 11191 { *t++ = '='; | |
| 11192 *t++ = '"'; | |
| 11193 strcpy(t, tp->value); | |
| 11194 t += strlen(t); | |
| 11195 *t++ = '"'; | |
| 11196 } | |
| 11197 } | |
| 11198 } | |
| 11199 if (!soap->body) | |
| 11200 *t++ = '/'; | |
| 11201 *t++ = '>'; | |
| 11202 *t = '\0'; | |
| 11203 t = soap->tmpbuf; | |
| 11204 m = (int)strlen(soap->tmpbuf); | |
| 11205 #endif | |
| 11206 if (soap->body) | |
| 11207 n = 1; | |
| 11208 f = 1; | |
| 11209 soap->peeked = 0; | |
| 11210 } | |
| 11211 #ifdef WITH_CDATA | |
| 11212 if (!flag) | |
| 11213 { register int state = 0; | |
| 11214 #ifdef WITH_FAST | |
| 11215 soap->labidx = 0; /* use look-aside buffer */ | |
| 11216 #else | |
| 11217 if (soap_new_block(soap) == NULL) | |
| 11218 return NULL; | |
| 11219 #endif | |
| 11220 for (;;) | |
| 11221 { | |
| 11222 #ifdef WITH_FAST | |
| 11223 register size_t k; | |
| 11224 if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */ | |
| 11225 return NULL; | |
| 11226 s = soap->labbuf + soap->labidx; /* space to populate */ | |
| 11227 k = soap->lablen - soap->labidx; /* number of bytes available */ | |
| 11228 soap->labidx = soap->lablen; /* claim this space */ | |
| 11229 #else | |
| 11230 register size_t k = SOAP_BLKLEN; | |
| 11231 if (!(s = (char*)soap_push_block(soap, NULL, k))) | |
| 11232 return NULL; | |
| 11233 #endif | |
| 11234 for (i = 0; i < k; i++) | |
| 11235 { if (m > 0) | |
| 11236 { *s++ = *t++; /* copy multibyte characters */ | |
| 11237 m--; | |
| 11238 continue; | |
| 11239 } | |
| 11240 c = soap_getchar(soap); | |
| 11241 if ((int)c == EOF) | |
| 11242 goto end; | |
| 11243 if ((c >= 0x80 || c < SOAP_AP) && state != 1 && !(soap->mode & SOAP_ENC_LATIN)) | |
| 11244 { if ((c & 0x7FFFFFFF) >= 0x80) | |
| 11245 { soap_unget(soap, c); | |
| 11246 c = soap_getutf8(soap); | |
| 11247 } | |
| 11248 if ((c & 0x7FFFFFFF) >= 0x80 && (!flag || (soap->mode & SOAP_C_UTFSTRING))) | |
| 11249 { c &= 0x7FFFFFFF; | |
| 11250 t = buf; | |
| 11251 if (c < 0x0800) | |
| 11252 *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); | |
| 11253 else | |
| 11254 { if (c < 0x010000) | |
| 11255 *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); | |
| 11256 else | |
| 11257 { if (c < 0x200000) | |
| 11258 *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); | |
| 11259 else | |
| 11260 { if (c < 0x04000000) | |
| 11261 *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); | |
| 11262 else | |
| 11263 { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); | |
| 11264 *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); | |
| 11265 } | |
| 11266 *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); | |
| 11267 } | |
| 11268 *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); | |
| 11269 } | |
| 11270 *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); | |
| 11271 } | |
| 11272 *t++ = (char)(0x80 | (c & 0x3F)); | |
| 11273 m = (int)(t - buf) - 1; | |
| 11274 t = buf; | |
| 11275 *s++ = *t++; | |
| 11276 continue; | |
| 11277 } | |
| 11278 } | |
| 11279 switch (state) | |
| 11280 { case 1: | |
| 11281 if (c == ']') | |
| 11282 state = 4; | |
| 11283 *s++ = (char)c; | |
| 11284 continue; | |
| 11285 case 2: | |
| 11286 if (c == '-') | |
| 11287 state = 6; | |
| 11288 *s++ = (char)c; | |
| 11289 continue; | |
| 11290 case 3: | |
| 11291 if (c == '?') | |
| 11292 state = 8; | |
| 11293 *s++ = (char)c; | |
| 11294 continue; | |
| 11295 /* CDATA */ | |
| 11296 case 4: | |
| 11297 if (c == ']') | |
| 11298 state = 5; | |
| 11299 else | |
| 11300 state = 1; | |
| 11301 *s++ = (char)c; | |
| 11302 continue; | |
| 11303 case 5: | |
| 11304 if (c == '>') | |
| 11305 state = 0; | |
| 11306 else if (c != ']') | |
| 11307 state = 1; | |
| 11308 *s++ = (char)c; | |
| 11309 continue; | |
| 11310 /* comment */ | |
| 11311 case 6: | |
| 11312 if (c == '-') | |
| 11313 state = 7; | |
| 11314 else | |
| 11315 state = 2; | |
| 11316 *s++ = (char)c; | |
| 11317 continue; | |
| 11318 case 7: | |
| 11319 if (c == '>') | |
| 11320 state = 0; | |
| 11321 else if (c != '-') | |
| 11322 state = 2; | |
| 11323 *s++ = (char)c; | |
| 11324 continue; | |
| 11325 /* PI */ | |
| 11326 case 8: | |
| 11327 if (c == '>') | |
| 11328 state = 0; | |
| 11329 else if (c != '?') | |
| 11330 state = 3; | |
| 11331 *s++ = (char)c; | |
| 11332 continue; | |
| 11333 } | |
| 11334 switch (c) | |
| 11335 { | |
| 11336 case SOAP_TT: | |
| 11337 if (n == 0) | |
| 11338 goto end; | |
| 11339 n--; | |
| 11340 *s++ = '<'; | |
| 11341 t = (char*)"/"; | |
| 11342 m = 1; | |
| 11343 break; | |
| 11344 case SOAP_LT: | |
| 11345 if (f && n == 0) | |
| 11346 goto end; | |
| 11347 n++; | |
| 11348 *s++ = '<'; | |
| 11349 break; | |
| 11350 case SOAP_GT: | |
| 11351 *s++ = '>'; | |
| 11352 break; | |
| 11353 case SOAP_QT: | |
| 11354 *s++ = '"'; | |
| 11355 break; | |
| 11356 case SOAP_AP: | |
| 11357 *s++ = '\''; | |
| 11358 break; | |
| 11359 case '/': | |
| 11360 if (n > 0) | |
| 11361 { c = soap_getchar(soap); | |
| 11362 if (c == '>') | |
| 11363 n--; | |
| 11364 soap_unget(soap, c); | |
| 11365 } | |
| 11366 *s++ = '/'; | |
| 11367 break; | |
| 11368 case '<': | |
| 11369 c = soap_getchar(soap); | |
| 11370 if (c == '/') | |
| 11371 { if (n == 0) | |
| 11372 { c = SOAP_TT; | |
| 11373 goto end; | |
| 11374 } | |
| 11375 n--; | |
| 11376 } | |
| 11377 else if (c == '!') | |
| 11378 { c = soap_getchar(soap); | |
| 11379 if (c == '[') | |
| 11380 { do c = soap_getchar(soap); | |
| 11381 while ((int)c != EOF && c != '['); | |
| 11382 if ((int)c == EOF) | |
| 11383 goto end; | |
| 11384 t = (char*)"![CDATA["; | |
| 11385 m = 8; | |
| 11386 state = 1; | |
| 11387 } | |
| 11388 else if (c == '-') | |
| 11389 { if ((c = soap_getchar(soap)) == '-') | |
| 11390 state = 2; | |
| 11391 t = (char*)"!-"; | |
| 11392 m = 2; | |
| 11393 soap_unget(soap, c); | |
| 11394 } | |
| 11395 else | |
| 11396 { t = (char*)"!"; | |
| 11397 m = 1; | |
| 11398 soap_unget(soap, c); | |
| 11399 } | |
| 11400 *s++ = '<'; | |
| 11401 break; | |
| 11402 } | |
| 11403 else if (c == '?') | |
| 11404 state = 3; | |
| 11405 else if (f && n == 0) | |
| 11406 { soap_revget1(soap); | |
| 11407 c = '<'; | |
| 11408 goto end; | |
| 11409 } | |
| 11410 else | |
| 11411 n++; | |
| 11412 soap_unget(soap, c); | |
| 11413 *s++ = '<'; | |
| 11414 break; | |
| 11415 case '>': | |
| 11416 *s++ = '>'; | |
| 11417 break; | |
| 11418 case '"': | |
| 11419 *s++ = '"'; | |
| 11420 break; | |
| 11421 default: | |
| 11422 #ifndef WITH_LEANER | |
| 11423 #ifdef HAVE_WCTOMB | |
| 11424 if (soap->mode & SOAP_C_MBSTRING) | |
| 11425 { m = wctomb(buf, (wchar_t)(c & 0x7FFFFFFF)); | |
| 11426 if (m >= 1 && m <= (int)MB_CUR_MAX) | |
| 11427 { t = buf; | |
| 11428 *s++ = *t++; | |
| 11429 m--; | |
| 11430 } | |
| 11431 else | |
| 11432 { *s++ = SOAP_UNKNOWN_CHAR; | |
| 11433 m = 0; | |
| 11434 } | |
| 11435 } | |
| 11436 else | |
| 11437 #endif | |
| 11438 #endif | |
| 11439 *s++ = (char)(c & 0xFF); | |
| 11440 } | |
| 11441 l++; | |
| 11442 if (maxlen >= 0 && l > maxlen) | |
| 11443 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); | |
| 11444 soap->error = SOAP_LENGTH; | |
| 11445 return NULL; | |
| 11446 } | |
| 11447 } | |
| 11448 } | |
| 11449 } | |
| 11450 #endif | |
| 11451 #ifdef WITH_FAST | |
| 11452 soap->labidx = 0; /* use look-aside buffer */ | |
| 11453 #else | |
| 11454 if (soap_new_block(soap) == NULL) | |
| 11455 return NULL; | |
| 11456 #endif | |
| 11457 for (;;) | |
| 11458 { | |
| 11459 #ifdef WITH_FAST | |
| 11460 register size_t k; | |
| 11461 if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */ | |
| 11462 return NULL; | |
| 11463 s = soap->labbuf + soap->labidx; /* space to populate */ | |
| 11464 k = soap->lablen - soap->labidx; /* number of bytes available */ | |
| 11465 soap->labidx = soap->lablen; /* claim this space */ | |
| 11466 #else | |
| 11467 register size_t k = SOAP_BLKLEN; | |
| 11468 if (!(s = (char*)soap_push_block(soap, NULL, k))) | |
| 11469 return NULL; | |
| 11470 #endif | |
| 11471 for (i = 0; i < k; i++) | |
| 11472 { if (m > 0) | |
| 11473 { *s++ = *t++; /* copy multibyte characters */ | |
| 11474 m--; | |
| 11475 continue; | |
| 11476 } | |
| 11477 #ifndef WITH_CDATA | |
| 11478 if (!flag) | |
| 11479 c = soap_getchar(soap); | |
| 11480 else | |
| 11481 #endif | |
| 11482 if ((soap->mode & SOAP_C_UTFSTRING)) | |
| 11483 { if (((c = soap_get(soap)) & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP) | |
| 11484 { c &= 0x7FFFFFFF; | |
| 11485 t = buf; | |
| 11486 if (c < 0x0800) | |
| 11487 *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); | |
| 11488 else | |
| 11489 { if (c < 0x010000) | |
| 11490 *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); | |
| 11491 else | |
| 11492 { if (c < 0x200000) | |
| 11493 *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); | |
| 11494 else | |
| 11495 { if (c < 0x04000000) | |
| 11496 *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); | |
| 11497 else | |
| 11498 { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); | |
| 11499 *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); | |
| 11500 } | |
| 11501 *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); | |
| 11502 } | |
| 11503 *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); | |
| 11504 } | |
| 11505 *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); | |
| 11506 } | |
| 11507 *t++ = (char)(0x80 | (c & 0x3F)); | |
| 11508 m = (int)(t - buf) - 1; | |
| 11509 t = buf; | |
| 11510 *s++ = *t++; | |
| 11511 continue; | |
| 11512 } | |
| 11513 } | |
| 11514 else | |
| 11515 c = soap_getutf8(soap); | |
| 11516 switch (c) | |
| 11517 { | |
| 11518 case SOAP_TT: | |
| 11519 if (n == 0) | |
| 11520 goto end; | |
| 11521 n--; | |
| 11522 *s++ = '<'; | |
| 11523 t = (char*)"/"; | |
| 11524 m = 1; | |
| 11525 break; | |
| 11526 case SOAP_LT: | |
| 11527 if (f && n == 0) | |
| 11528 goto end; | |
| 11529 n++; | |
| 11530 *s++ = '<'; | |
| 11531 break; | |
| 11532 case SOAP_GT: | |
| 11533 *s++ = '>'; | |
| 11534 break; | |
| 11535 case SOAP_QT: | |
| 11536 *s++ = '"'; | |
| 11537 break; | |
| 11538 case SOAP_AP: | |
| 11539 *s++ = '\''; | |
| 11540 break; | |
| 11541 case '/': | |
| 11542 if (n > 0) | |
| 11543 { if (!flag) | |
| 11544 { c = soap_getchar(soap); | |
| 11545 if (c == '>') | |
| 11546 n--; | |
| 11547 } | |
| 11548 else | |
| 11549 { c = soap_get(soap); | |
| 11550 if (c == SOAP_GT) | |
| 11551 n--; | |
| 11552 } | |
| 11553 soap_unget(soap, c); | |
| 11554 } | |
| 11555 *s++ = '/'; | |
| 11556 break; | |
| 11557 case (soap_wchar)('<' | 0x80000000): | |
| 11558 if (flag) | |
| 11559 *s++ = '<'; | |
| 11560 else | |
| 11561 { *s++ = '&'; | |
| 11562 t = (char*)"lt;"; | |
| 11563 m = 3; | |
| 11564 } | |
| 11565 break; | |
| 11566 case (soap_wchar)('>' | 0x80000000): | |
| 11567 if (flag) | |
| 11568 *s++ = '>'; | |
| 11569 else | |
| 11570 { *s++ = '&'; | |
| 11571 t = (char*)"gt;"; | |
| 11572 m = 3; | |
| 11573 } | |
| 11574 break; | |
| 11575 case (soap_wchar)('&' | 0x80000000): | |
| 11576 if (flag) | |
| 11577 *s++ = '&'; | |
| 11578 else | |
| 11579 { *s++ = '&'; | |
| 11580 t = (char*)"amp;"; | |
| 11581 m = 4; | |
| 11582 } | |
| 11583 break; | |
| 11584 case (soap_wchar)('"' | 0x80000000): | |
| 11585 if (flag) | |
| 11586 *s++ = '"'; | |
| 11587 else | |
| 11588 { *s++ = '&'; | |
| 11589 t = (char*)"quot;"; | |
| 11590 m = 5; | |
| 11591 } | |
| 11592 break; | |
| 11593 case (soap_wchar)('\'' | 0x80000000): | |
| 11594 if (flag) | |
| 11595 *s++ = '\''; | |
| 11596 else | |
| 11597 { *s++ = '&'; | |
| 11598 t = (char*)"apos;"; | |
| 11599 m = 5; | |
| 11600 } | |
| 11601 break; | |
| 11602 default: | |
| 11603 if ((int)c == EOF) | |
| 11604 goto end; | |
| 11605 #ifndef WITH_CDATA | |
| 11606 if (c == '<' && !flag) | |
| 11607 { if (f && n == 0) | |
| 11608 goto end; | |
| 11609 c = soap_getchar(soap); | |
| 11610 soap_unget(soap, c); | |
| 11611 if (c == '/') | |
| 11612 { c = SOAP_TT; | |
| 11613 if (n == 0) | |
| 11614 goto end; | |
| 11615 n--; | |
| 11616 } | |
| 11617 else | |
| 11618 n++; | |
| 11619 *s++ = '<'; | |
| 11620 break; | |
| 11621 } | |
| 11622 else | |
| 11623 #endif | |
| 11624 #ifndef WITH_LEANER | |
| 11625 #ifdef HAVE_WCTOMB | |
| 11626 if (soap->mode & SOAP_C_MBSTRING) | |
| 11627 { m = wctomb(buf, (wchar_t)(c & 0x7FFFFFFF)); | |
| 11628 if (m >= 1 && m <= (int)MB_CUR_MAX) | |
| 11629 { t = buf; | |
| 11630 *s++ = *t++; | |
| 11631 m--; | |
| 11632 } | |
| 11633 else | |
| 11634 { *s++ = SOAP_UNKNOWN_CHAR; | |
| 11635 m = 0; | |
| 11636 } | |
| 11637 } | |
| 11638 else | |
| 11639 #endif | |
| 11640 #endif | |
| 11641 *s++ = (char)(c & 0xFF); | |
| 11642 } | |
| 11643 l++; | |
| 11644 if (maxlen >= 0 && l > maxlen) | |
| 11645 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); | |
| 11646 soap->error = SOAP_LENGTH; | |
| 11647 return NULL; | |
| 11648 } | |
| 11649 } | |
| 11650 } | |
| 11651 end: | |
| 11652 soap_unget(soap, c); | |
| 11653 *s = '\0'; | |
| 11654 #ifdef WITH_FAST | |
| 11655 t = soap_strdup(soap, soap->labbuf); | |
| 11656 #else | |
| 11657 soap_size_block(soap, NULL, i + 1); | |
| 11658 t = soap_save_block(soap, NULL, 0); | |
| 11659 #endif | |
| 11660 if (l < minlen) | |
| 11661 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen)); | |
| 11662 soap->error = SOAP_LENGTH; | |
| 11663 return NULL; | |
| 11664 } | |
| 11665 #ifdef WITH_DOM | |
| 11666 if ((soap->mode & SOAP_XML_DOM) && soap->dom) | |
| 11667 { if (flag == 3) | |
| 11668 soap->dom->tail = t; | |
| 11669 else | |
| 11670 soap->dom->data = t; | |
| 11671 } | |
| 11672 #endif | |
| 11673 if (flag == 2) | |
| 11674 if (soap_s2QName(soap, t, &t, minlen, maxlen)) | |
| 11675 return NULL; | |
| 11676 return t; | |
| 11677 } | |
| 11678 #endif | |
| 11679 | |
| 11680 /******************************************************************************/ | |
| 11681 #ifndef WITH_LEANER | |
| 11682 #ifndef PALM_2 | |
| 11683 SOAP_FMAC1 | |
| 11684 int | |
| 11685 SOAP_FMAC2 | |
| 11686 soap_wstring_out(struct soap *soap, const wchar_t *s, int flag) | |
| 11687 { const char *t; | |
| 11688 char tmp; | |
| 11689 register soap_wchar c; | |
| 11690 #ifdef WITH_DOM | |
| 11691 if ((soap->mode & SOAP_XML_DOM) && soap->dom) | |
| 11692 { wchar_t *r = (wchar_t*)s; | |
| 11693 int n = 1; | |
| 11694 while (*r++) | |
| 11695 n++; | |
| 11696 soap->dom->wide = r = (wchar_t*)soap_malloc(soap, n * sizeof(wchar_t)); | |
| 11697 while (n--) | |
| 11698 *r++ = *s++; | |
| 11699 return SOAP_OK; | |
| 11700 } | |
| 11701 #endif | |
| 11702 while ((c = *s++)) | |
| 11703 { switch (c) | |
| 11704 { | |
| 11705 case 0x09: | |
| 11706 if (flag) | |
| 11707 t = "	"; | |
| 11708 else | |
| 11709 t = "\t"; | |
| 11710 break; | |
| 11711 case 0x0A: | |
| 11712 if (flag || !(soap->mode & SOAP_XML_CANONICAL)) | |
| 11713 t = "
"; | |
| 11714 else | |
| 11715 t = "\n"; | |
| 11716 break; | |
| 11717 case 0x0D: | |
| 11718 t = "
"; | |
| 11719 break; | |
| 11720 case '&': | |
| 11721 t = "&"; | |
| 11722 break; | |
| 11723 case '<': | |
| 11724 t = "<"; | |
| 11725 break; | |
| 11726 case '>': | |
| 11727 if (flag) | |
| 11728 t = ">"; | |
| 11729 else | |
| 11730 t = ">"; | |
| 11731 break; | |
| 11732 case '"': | |
| 11733 if (flag) | |
| 11734 t = """; | |
| 11735 else | |
| 11736 t = "\""; | |
| 11737 break; | |
| 11738 default: | |
| 11739 if (c >= 0x20 && c < 0x80) | |
| 11740 { tmp = (char)c; | |
| 11741 if (soap_send_raw(soap, &tmp, 1)) | |
| 11742 return soap->error; | |
| 11743 } | |
| 11744 else | |
| 11745 { /* check for UTF16 encoding when wchar_t is too small to hold UCS */ | |
| 11746 if (sizeof(wchar_t) < 4 && (c & 0xFC00) == 0xD800) | |
| 11747 { register soap_wchar d = *s++; | |
| 11748 if ((d & 0xFC00) == 0xDC00) | |
| 11749 c = ((c - 0xD800) << 10) + (d - 0xDC00) + 0x10000; | |
| 11750 else | |
| 11751 c = 0xFFFD; /* Malformed */ | |
| 11752 } | |
| 11753 if (soap_pututf8(soap, (unsigned long)c)) | |
| 11754 return soap->error; | |
| 11755 } | |
| 11756 continue; | |
| 11757 } | |
| 11758 if (soap_send(soap, t)) | |
| 11759 return soap->error; | |
| 11760 } | |
| 11761 return SOAP_OK; | |
| 11762 } | |
| 11763 #endif | |
| 11764 #endif | |
| 11765 | |
| 11766 /******************************************************************************/ | |
| 11767 #ifndef WITH_LEANER | |
| 11768 #ifndef PALM_2 | |
| 11769 SOAP_FMAC1 | |
| 11770 wchar_t * | |
| 11771 SOAP_FMAC2 | |
| 11772 soap_wstring_in(struct soap *soap, int flag, long minlen, long maxlen) | |
| 11773 { wchar_t *s; | |
| 11774 register int i, n = 0, f = 0; | |
| 11775 register long l = 0; | |
| 11776 register soap_wchar c; | |
| 11777 char *t = NULL; | |
| 11778 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading wide string content\n")); | |
| 11779 if (soap->peeked) | |
| 11780 { if (*soap->tag) | |
| 11781 { | |
| 11782 #ifndef WITH_LEAN | |
| 11783 struct soap_attribute *tp; | |
| 11784 t = soap->tmpbuf; | |
| 11785 *t = '<'; | |
| 11786 strncpy(t + 1, soap->tag, sizeof(soap->tmpbuf) - 2); | |
| 11787 t[sizeof(soap->tmpbuf) - 1] = '\0'; | |
| 11788 t += strlen(t); | |
| 11789 for (tp = soap->attributes; tp; tp = tp->next) | |
| 11790 { if (tp->visible) | |
| 11791 { if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2) | |
| 11792 break; | |
| 11793 *t++ = ' '; | |
| 11794 strcpy(t, tp->name); | |
| 11795 t += strlen(t); | |
| 11796 if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2) | |
| 11797 break; | |
| 11798 if (tp->value) | |
| 11799 { *t++ = '='; | |
| 11800 *t++ = '"'; | |
| 11801 strcpy(t, tp->value); | |
| 11802 t += strlen(t); | |
| 11803 *t++ = '"'; | |
| 11804 } | |
| 11805 } | |
| 11806 } | |
| 11807 if (!soap->body) | |
| 11808 *t++ = '/'; | |
| 11809 *t++ = '>'; | |
| 11810 *t = '\0'; | |
| 11811 t = soap->tmpbuf; | |
| 11812 #endif | |
| 11813 if (soap->body) | |
| 11814 n = 1; | |
| 11815 f = 1; | |
| 11816 soap->peeked = 0; | |
| 11817 } | |
| 11818 } | |
| 11819 if (soap_new_block(soap) == NULL) | |
| 11820 return NULL; | |
| 11821 for (;;) | |
| 11822 { if (!(s = (wchar_t*)soap_push_block(soap, NULL, sizeof(wchar_t)*SOAP_BLKLEN))) | |
| 11823 return NULL; | |
| 11824 for (i = 0; i < SOAP_BLKLEN; i++) | |
| 11825 { if (t) | |
| 11826 { *s++ = (wchar_t)*t++; | |
| 11827 if (!*t) | |
| 11828 t = NULL; | |
| 11829 continue; | |
| 11830 } | |
| 11831 c = soap_getutf8(soap); | |
| 11832 switch (c) | |
| 11833 { | |
| 11834 case SOAP_TT: | |
| 11835 if (n == 0) | |
| 11836 goto end; | |
| 11837 n--; | |
| 11838 *s++ = '<'; | |
| 11839 soap_unget(soap, '/'); | |
| 11840 break; | |
| 11841 case SOAP_LT: | |
| 11842 if (f && n == 0) | |
| 11843 goto end; | |
| 11844 n++; | |
| 11845 *s++ = '<'; | |
| 11846 break; | |
| 11847 case SOAP_GT: | |
| 11848 *s++ = '>'; | |
| 11849 break; | |
| 11850 case SOAP_QT: | |
| 11851 *s++ = '"'; | |
| 11852 break; | |
| 11853 case SOAP_AP: | |
| 11854 *s++ = '\''; | |
| 11855 break; | |
| 11856 case '/': | |
| 11857 if (n > 0) | |
| 11858 { c = soap_getutf8(soap); | |
| 11859 if (c == SOAP_GT) | |
| 11860 n--; | |
| 11861 soap_unget(soap, c); | |
| 11862 } | |
| 11863 *s++ = '/'; | |
| 11864 break; | |
| 11865 case '<': | |
| 11866 if (flag) | |
| 11867 *s++ = (soap_wchar)'<'; | |
| 11868 else | |
| 11869 { *s++ = (soap_wchar)'&'; | |
| 11870 t = (char*)"lt;"; | |
| 11871 } | |
| 11872 break; | |
| 11873 case '>': | |
| 11874 if (flag) | |
| 11875 *s++ = (soap_wchar)'>'; | |
| 11876 else | |
| 11877 { *s++ = (soap_wchar)'&'; | |
| 11878 t = (char*)"gt;"; | |
| 11879 } | |
| 11880 break; | |
| 11881 case '"': | |
| 11882 if (flag) | |
| 11883 *s++ = (soap_wchar)'"'; | |
| 11884 else | |
| 11885 { *s++ = (soap_wchar)'&'; | |
| 11886 t = (char*)"quot;"; | |
| 11887 } | |
| 11888 break; | |
| 11889 default: | |
| 11890 if ((int)c == EOF) | |
| 11891 goto end; | |
| 11892 /* use UTF16 encoding when wchar_t is too small to hold UCS */ | |
| 11893 if (sizeof(wchar_t) < 4 && c > 0xFFFF) | |
| 11894 { register soap_wchar c1, c2; | |
| 11895 c1 = 0xD800 - (0x10000 >> 10) + (c >> 10); | |
| 11896 c2 = 0xDC00 + (c & 0x3FF); | |
| 11897 c = c1; | |
| 11898 soap_unget(soap, c2); | |
| 11899 } | |
| 11900 *s++ = (wchar_t)c & 0x7FFFFFFF; | |
| 11901 } | |
| 11902 l++; | |
| 11903 if (maxlen >= 0 && l > maxlen) | |
| 11904 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); | |
| 11905 soap->error = SOAP_LENGTH; | |
| 11906 return NULL; | |
| 11907 } | |
| 11908 } | |
| 11909 } | |
| 11910 end: | |
| 11911 soap_unget(soap, c); | |
| 11912 *s = '\0'; | |
| 11913 soap_size_block(soap, NULL, sizeof(wchar_t) * (i + 1)); | |
| 11914 if (l < minlen) | |
| 11915 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen)); | |
| 11916 soap->error = SOAP_LENGTH; | |
| 11917 return NULL; | |
| 11918 } | |
| 11919 s = (wchar_t*)soap_save_block(soap, NULL, NULL, 0); | |
| 11920 #ifdef WITH_DOM | |
| 11921 if ((soap->mode & SOAP_XML_DOM) && soap->dom) | |
| 11922 soap->dom->wide = s; | |
| 11923 #endif | |
| 11924 return s; | |
| 11925 } | |
| 11926 #endif | |
| 11927 #endif | |
| 11928 | |
| 11929 /******************************************************************************/ | |
| 11930 #ifndef PALM_2 | |
| 11931 SOAP_FMAC1 | |
| 11932 const char* | |
| 11933 SOAP_FMAC2 | |
| 11934 soap_int2s(struct soap *soap, int n) | |
| 11935 { return soap_long2s(soap, (long)n); | |
| 11936 } | |
| 11937 #endif | |
| 11938 | |
| 11939 /******************************************************************************/ | |
| 11940 #ifndef PALM_2 | |
| 11941 SOAP_FMAC1 | |
| 11942 int | |
| 11943 SOAP_FMAC2 | |
| 11944 soap_outint(struct soap *soap, const char *tag, int id, const int *p, const char *type, int n) | |
| 11945 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) | |
| 11946 || soap_string_out(soap, soap_long2s(soap, (long)*p), 0)) | |
| 11947 return soap->error; | |
| 11948 return soap_element_end_out(soap, tag); | |
| 11949 } | |
| 11950 #endif | |
| 11951 | |
| 11952 /******************************************************************************/ | |
| 11953 #ifndef PALM_2 | |
| 11954 SOAP_FMAC1 | |
| 11955 int | |
| 11956 SOAP_FMAC2 | |
| 11957 soap_s2int(struct soap *soap, const char *s, int *p) | |
| 11958 { if (s) | |
| 11959 { long n; | |
| 11960 char *r; | |
| 11961 #ifndef WITH_NOIO | |
| 11962 #ifndef WITH_LEAN | |
| 11963 soap_reset_errno; | |
| 11964 #endif | |
| 11965 #endif | |
| 11966 n = soap_strtol(s, &r, 10); | |
| 11967 if (s == r || *r | |
| 11968 #ifndef WITH_LEAN | |
| 11969 || n != (int)n | |
| 11970 #endif | |
| 11971 #ifndef WITH_NOIO | |
| 11972 #ifndef WITH_LEAN | |
| 11973 || soap_errno == SOAP_ERANGE | |
| 11974 #endif | |
| 11975 #endif | |
| 11976 ) | |
| 11977 soap->error = SOAP_TYPE; | |
| 11978 *p = (int)n; | |
| 11979 } | |
| 11980 return soap->error; | |
| 11981 } | |
| 11982 #endif | |
| 11983 | |
| 11984 /******************************************************************************/ | |
| 11985 #ifndef PALM_2 | |
| 11986 SOAP_FMAC1 | |
| 11987 int * | |
| 11988 SOAP_FMAC2 | |
| 11989 soap_inint(struct soap *soap, const char *tag, int *p, const char *type, int t) | |
| 11990 { if (soap_element_begin_in(soap, tag, 0, NULL)) | |
| 11991 return NULL; | |
| 11992 #ifndef WITH_LEAN | |
| 11993 if (*soap->type | |
| 11994 && soap_match_tag(soap, soap->type, type) | |
| 11995 && soap_match_tag(soap, soap->type, ":int") | |
| 11996 && soap_match_tag(soap, soap->type, ":short") | |
| 11997 && soap_match_tag(soap, soap->type, ":byte")) | |
| 11998 { soap->error = SOAP_TYPE; | |
| 11999 soap_revert(soap); | |
| 12000 return NULL; | |
| 12001 } | |
| 12002 #endif | |
| 12003 p = (int*)soap_id_enter(soap, soap->id, p, t, sizeof(int), 0, NULL, NULL, NULL); | |
| 12004 if (*soap->href) | |
| 12005 p = (int*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(int), 0, NULL); | |
| 12006 else if (p) | |
| 12007 { if (soap_s2int(soap, soap_value(soap), p)) | |
| 12008 return NULL; | |
| 12009 } | |
| 12010 if (soap->body && soap_element_end_in(soap, tag)) | |
| 12011 return NULL; | |
| 12012 return p; | |
| 12013 } | |
| 12014 #endif | |
| 12015 | |
| 12016 /******************************************************************************/ | |
| 12017 #ifndef PALM_2 | |
| 12018 SOAP_FMAC1 | |
| 12019 const char* | |
| 12020 SOAP_FMAC2 | |
| 12021 soap_long2s(struct soap *soap, long n) | |
| 12022 { | |
| 12023 #ifdef HAVE_SNPRINTF | |
| 12024 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%ld", n); | |
| 12025 #else | |
| 12026 sprintf(soap->tmpbuf, "%ld", n); | |
| 12027 #endif | |
| 12028 return soap->tmpbuf; | |
| 12029 } | |
| 12030 #endif | |
| 12031 | |
| 12032 /******************************************************************************/ | |
| 12033 #ifndef PALM_2 | |
| 12034 SOAP_FMAC1 | |
| 12035 int | |
| 12036 SOAP_FMAC2 | |
| 12037 soap_outlong(struct soap *soap, const char *tag, int id, const long *p, const char *type, int n) | |
| 12038 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) | |
| 12039 || soap_string_out(soap, soap_long2s(soap, *p), 0)) | |
| 12040 return soap->error; | |
| 12041 return soap_element_end_out(soap, tag); | |
| 12042 } | |
| 12043 #endif | |
| 12044 | |
| 12045 /******************************************************************************/ | |
| 12046 #ifndef PALM_2 | |
| 12047 SOAP_FMAC1 | |
| 12048 int | |
| 12049 SOAP_FMAC2 | |
| 12050 soap_s2long(struct soap *soap, const char *s, long *p) | |
| 12051 { if (s) | |
| 12052 { char *r; | |
| 12053 #ifndef WITH_NOIO | |
| 12054 #ifndef WITH_LEAN | |
| 12055 soap_reset_errno; | |
| 12056 #endif | |
| 12057 #endif | |
| 12058 *p = soap_strtol(s, &r, 10); | |
| 12059 if (s == r || *r | |
| 12060 #ifndef WITH_NOIO | |
| 12061 #ifndef WITH_LEAN | |
| 12062 || soap_errno == SOAP_ERANGE | |
| 12063 #endif | |
| 12064 #endif | |
| 12065 ) | |
| 12066 soap->error = SOAP_TYPE; | |
| 12067 } | |
| 12068 return soap->error; | |
| 12069 } | |
| 12070 #endif | |
| 12071 | |
| 12072 /******************************************************************************/ | |
| 12073 #ifndef PALM_2 | |
| 12074 SOAP_FMAC1 | |
| 12075 long * | |
| 12076 SOAP_FMAC2 | |
| 12077 soap_inlong(struct soap *soap, const char *tag, long *p, const char *type, int t) | |
| 12078 { if (soap_element_begin_in(soap, tag, 0, NULL)) | |
| 12079 return NULL; | |
| 12080 #ifndef WITH_LEAN | |
| 12081 if (*soap->type | |
| 12082 && soap_match_tag(soap, soap->type, type) | |
| 12083 && soap_match_tag(soap, soap->type, ":int") | |
| 12084 && soap_match_tag(soap, soap->type, ":short") | |
| 12085 && soap_match_tag(soap, soap->type, ":byte")) | |
| 12086 { soap->error = SOAP_TYPE; | |
| 12087 soap_revert(soap); | |
| 12088 return NULL; | |
| 12089 } | |
| 12090 #endif | |
| 12091 p = (long*)soap_id_enter(soap, soap->id, p, t, sizeof(long), 0, NULL, NULL, NULL); | |
| 12092 if (*soap->href) | |
| 12093 p = (long*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(long), 0, NULL); | |
| 12094 else if (p) | |
| 12095 { if (soap_s2long(soap, soap_value(soap), p)) | |
| 12096 return NULL; | |
| 12097 } | |
| 12098 if (soap->body && soap_element_end_in(soap, tag)) | |
| 12099 return NULL; | |
| 12100 return p; | |
| 12101 } | |
| 12102 #endif | |
| 12103 | |
| 12104 /******************************************************************************/ | |
| 12105 #ifndef WITH_LEAN | |
| 12106 SOAP_FMAC1 | |
| 12107 const char* | |
| 12108 SOAP_FMAC2 | |
| 12109 soap_LONG642s(struct soap *soap, LONG64 n) | |
| 12110 { | |
| 12111 #ifdef HAVE_SNPRINTF | |
| 12112 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), SOAP_LONG_FORMAT, n); | |
| 12113 #else | |
| 12114 sprintf(soap->tmpbuf, SOAP_LONG_FORMAT, n); | |
| 12115 #endif | |
| 12116 return soap->tmpbuf; | |
| 12117 } | |
| 12118 #endif | |
| 12119 | |
| 12120 /******************************************************************************/ | |
| 12121 #ifndef WITH_LEAN | |
| 12122 SOAP_FMAC1 | |
| 12123 int | |
| 12124 SOAP_FMAC2 | |
| 12125 soap_outLONG64(struct soap *soap, const char *tag, int id, const LONG64 *p, const char *type, int n) | |
| 12126 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) | |
| 12127 || soap_string_out(soap, soap_LONG642s(soap, *p), 0)) | |
| 12128 return soap->error; | |
| 12129 return soap_element_end_out(soap, tag); | |
| 12130 } | |
| 12131 #endif | |
| 12132 | |
| 12133 /******************************************************************************/ | |
| 12134 #ifndef WITH_LEAN | |
| 12135 SOAP_FMAC1 | |
| 12136 int | |
| 12137 SOAP_FMAC2 | |
| 12138 soap_s2LONG64(struct soap *soap, const char *s, LONG64 *p) | |
| 12139 { if (s) | |
| 12140 { | |
| 12141 #ifdef HAVE_STRTOLL | |
| 12142 char *r; | |
| 12143 #ifndef WITH_NOIO | |
| 12144 #ifndef WITH_LEAN | |
| 12145 soap_reset_errno; | |
| 12146 #endif | |
| 12147 #endif | |
| 12148 *p = soap_strtoll(s, &r, 10); | |
| 12149 if (s == r || *r | |
| 12150 #ifndef WITH_NOIO | |
| 12151 #ifndef WITH_LEAN | |
| 12152 || soap_errno == SOAP_ERANGE | |
| 12153 #endif | |
| 12154 #endif | |
| 12155 ) | |
| 12156 #else | |
| 12157 # ifdef HAVE_SSCANF | |
| 12158 if (sscanf(s, SOAP_LONG_FORMAT, p) != 1) | |
| 12159 # endif | |
| 12160 #endif | |
| 12161 soap->error = SOAP_TYPE; | |
| 12162 } | |
| 12163 return soap->error; | |
| 12164 } | |
| 12165 #endif | |
| 12166 | |
| 12167 /******************************************************************************/ | |
| 12168 #ifndef WITH_LEAN | |
| 12169 SOAP_FMAC1 | |
| 12170 LONG64 * | |
| 12171 SOAP_FMAC2 | |
| 12172 soap_inLONG64(struct soap *soap, const char *tag, LONG64 *p, const char *type, int t) | |
| 12173 { if (soap_element_begin_in(soap, tag, 0, NULL)) | |
| 12174 return NULL; | |
| 12175 #ifndef WITH_LEAN | |
| 12176 if (*soap->type | |
| 12177 && soap_match_tag(soap, soap->type, type) | |
| 12178 && soap_match_tag(soap, soap->type, ":integer") | |
| 12179 && soap_match_tag(soap, soap->type, ":positiveInteger") | |
| 12180 && soap_match_tag(soap, soap->type, ":negativeInteger") | |
| 12181 && soap_match_tag(soap, soap->type, ":nonPositiveInteger") | |
| 12182 && soap_match_tag(soap, soap->type, ":nonNegativeInteger") | |
| 12183 && soap_match_tag(soap, soap->type, ":long") | |
| 12184 && soap_match_tag(soap, soap->type, ":int") | |
| 12185 && soap_match_tag(soap, soap->type, ":short") | |
| 12186 && soap_match_tag(soap, soap->type, ":byte")) | |
| 12187 { soap->error = SOAP_TYPE; | |
| 12188 soap_revert(soap); | |
| 12189 return NULL; | |
| 12190 } | |
| 12191 #endif | |
| 12192 p = (LONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(LONG64), 0, NULL, NULL, NULL); | |
| 12193 if (*soap->href) | |
| 12194 p = (LONG64*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(LONG64), 0, NULL); | |
| 12195 else if (p) | |
| 12196 { if (soap_s2LONG64(soap, soap_value(soap), p)) | |
| 12197 return NULL; | |
| 12198 } | |
| 12199 if (soap->body && soap_element_end_in(soap, tag)) | |
| 12200 return NULL; | |
| 12201 return p; | |
| 12202 } | |
| 12203 #endif | |
| 12204 | |
| 12205 /******************************************************************************/ | |
| 12206 #ifndef PALM_2 | |
| 12207 SOAP_FMAC1 | |
| 12208 const char* | |
| 12209 SOAP_FMAC2 | |
| 12210 soap_byte2s(struct soap *soap, char n) | |
| 12211 { return soap_long2s(soap, (long)n); | |
| 12212 } | |
| 12213 #endif | |
| 12214 | |
| 12215 /******************************************************************************/ | |
| 12216 #ifndef PALM_2 | |
| 12217 SOAP_FMAC1 | |
| 12218 int | |
| 12219 SOAP_FMAC2 | |
| 12220 soap_outbyte(struct soap *soap, const char *tag, int id, const char *p, const char *type, int n) | |
| 12221 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) | |
| 12222 || soap_string_out(soap, soap_long2s(soap, (long)*p), 0)) | |
| 12223 return soap->error; | |
| 12224 return soap_element_end_out(soap, tag); | |
| 12225 } | |
| 12226 #endif | |
| 12227 | |
| 12228 /******************************************************************************/ | |
| 12229 #ifndef PALM_2 | |
| 12230 SOAP_FMAC1 | |
| 12231 int | |
| 12232 SOAP_FMAC2 | |
| 12233 soap_s2byte(struct soap *soap, const char *s, char *p) | |
| 12234 { if (s) | |
| 12235 { long n; | |
| 12236 char *r; | |
| 12237 n = soap_strtol(s, &r, 10); | |
| 12238 if (s == r || *r || n < -128 || n > 127) | |
| 12239 soap->error = SOAP_TYPE; | |
| 12240 *p = (char)n; | |
| 12241 } | |
| 12242 return soap->error; | |
| 12243 } | |
| 12244 #endif | |
| 12245 | |
| 12246 /******************************************************************************/ | |
| 12247 #ifndef PALM_2 | |
| 12248 SOAP_FMAC1 | |
| 12249 char * | |
| 12250 SOAP_FMAC2 | |
| 12251 soap_inbyte(struct soap *soap, const char *tag, char *p, const char *type, int t) | |
| 12252 { if (soap_element_begin_in(soap, tag, 0, NULL)) | |
| 12253 return NULL; | |
| 12254 #ifndef WITH_LEAN | |
| 12255 if (*soap->type | |
| 12256 && soap_match_tag(soap, soap->type, type) | |
| 12257 && soap_match_tag(soap, soap->type, ":byte")) | |
| 12258 { soap->error = SOAP_TYPE; | |
| 12259 soap_revert(soap); | |
| 12260 return NULL; | |
| 12261 } | |
| 12262 #endif | |
| 12263 p = (char*)soap_id_enter(soap, soap->id, p, t, sizeof(char), 0, NULL, NULL, NULL); | |
| 12264 if (*soap->href) | |
| 12265 p = (char*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(char), 0, NULL); | |
| 12266 else if (p) | |
| 12267 { if (soap_s2byte(soap, soap_value(soap), p)) | |
| 12268 return NULL; | |
| 12269 } | |
| 12270 if (soap->body && soap_element_end_in(soap, tag)) | |
| 12271 return NULL; | |
| 12272 return p; | |
| 12273 } | |
| 12274 #endif | |
| 12275 | |
| 12276 /******************************************************************************/ | |
| 12277 #ifndef PALM_2 | |
| 12278 SOAP_FMAC1 | |
| 12279 const char* | |
| 12280 SOAP_FMAC2 | |
| 12281 soap_short2s(struct soap *soap, short n) | |
| 12282 { return soap_long2s(soap, (long)n); | |
| 12283 } | |
| 12284 #endif | |
| 12285 | |
| 12286 /******************************************************************************/ | |
| 12287 #ifndef PALM_2 | |
| 12288 SOAP_FMAC1 | |
| 12289 int | |
| 12290 SOAP_FMAC2 | |
| 12291 soap_outshort(struct soap *soap, const char *tag, int id, const short *p, const char *type, int n) | |
| 12292 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) | |
| 12293 || soap_string_out(soap, soap_long2s(soap, (long)*p), 0)) | |
| 12294 return soap->error; | |
| 12295 return soap_element_end_out(soap, tag); | |
| 12296 } | |
| 12297 #endif | |
| 12298 | |
| 12299 /******************************************************************************/ | |
| 12300 #ifndef PALM_2 | |
| 12301 SOAP_FMAC1 | |
| 12302 int | |
| 12303 SOAP_FMAC2 | |
| 12304 soap_s2short(struct soap *soap, const char *s, short *p) | |
| 12305 { if (s) | |
| 12306 { long n; | |
| 12307 char *r; | |
| 12308 n = soap_strtol(s, &r, 10); | |
| 12309 if (s == r || *r || n < -32768 || n > 32767) | |
| 12310 soap->error = SOAP_TYPE; | |
| 12311 *p = (short)n; | |
| 12312 } | |
| 12313 return soap->error; | |
| 12314 } | |
| 12315 #endif | |
| 12316 | |
| 12317 /******************************************************************************/ | |
| 12318 #ifndef PALM_2 | |
| 12319 SOAP_FMAC1 | |
| 12320 short * | |
| 12321 SOAP_FMAC2 | |
| 12322 soap_inshort(struct soap *soap, const char *tag, short *p, const char *type, int t) | |
| 12323 { if (soap_element_begin_in(soap, tag, 0, NULL)) | |
| 12324 return NULL; | |
| 12325 #ifndef WITH_LEAN | |
| 12326 if (*soap->type | |
| 12327 && soap_match_tag(soap, soap->type, type) | |
| 12328 && soap_match_tag(soap, soap->type, ":short") | |
| 12329 && soap_match_tag(soap, soap->type, ":byte")) | |
| 12330 { soap->error = SOAP_TYPE; | |
| 12331 soap_revert(soap); | |
| 12332 return NULL; | |
| 12333 } | |
| 12334 #endif | |
| 12335 p = (short*)soap_id_enter(soap, soap->id, p, t, sizeof(short), 0, NULL, NULL, NULL); | |
| 12336 if (*soap->href) | |
| 12337 p = (short*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(short), 0, NULL); | |
| 12338 else if (p) | |
| 12339 { if (soap_s2short(soap, soap_value(soap), p)) | |
| 12340 return NULL; | |
| 12341 } | |
| 12342 if (soap->body && soap_element_end_in(soap, tag)) | |
| 12343 return NULL; | |
| 12344 return p; | |
| 12345 } | |
| 12346 #endif | |
| 12347 | |
| 12348 /******************************************************************************/ | |
| 12349 #ifndef PALM_2 | |
| 12350 SOAP_FMAC1 | |
| 12351 const char* | |
| 12352 SOAP_FMAC2 | |
| 12353 soap_float2s(struct soap *soap, float n) | |
| 12354 { char *s; | |
| 12355 if (soap_isnan((double)n)) | |
| 12356 return "NaN"; | |
| 12357 if (soap_ispinff(n)) | |
| 12358 return "INF"; | |
| 12359 if (soap_isninff(n)) | |
| 12360 return "-INF"; | |
| 12361 #if defined(HAVE_SPRINTF_L) | |
| 12362 # ifdef WIN32 | |
| 12363 _sprintf_s_l(soap->tmpbuf, _countof(soap->tmpbuf), soap->float_format, soap->c_locale, n); | |
| 12364 # else | |
| 12365 sprintf_l(soap->tmpbuf, soap->c_locale, soap->float_format, n); | |
| 12366 # endif | |
| 12367 #else | |
| 12368 # ifdef HAVE_SNPRINTF | |
| 12369 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), soap->float_format, n); | |
| 12370 # else | |
| 12371 sprintf(soap->tmpbuf, soap->float_format, n); | |
| 12372 # endif | |
| 12373 s = strchr(soap->tmpbuf, ','); /* convert decimal comma to DP */ | |
| 12374 if (s) | |
| 12375 *s = '.'; | |
| 12376 #endif | |
| 12377 return soap->tmpbuf; | |
| 12378 } | |
| 12379 #endif | |
| 12380 | |
| 12381 /******************************************************************************/ | |
| 12382 #ifndef PALM_2 | |
| 12383 SOAP_FMAC1 | |
| 12384 int | |
| 12385 SOAP_FMAC2 | |
| 12386 soap_outfloat(struct soap *soap, const char *tag, int id, const float *p, const char *type, int n) | |
| 12387 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) | |
| 12388 || soap_string_out(soap, soap_float2s(soap, *p), 0)) | |
| 12389 return soap->error; | |
| 12390 return soap_element_end_out(soap, tag); | |
| 12391 } | |
| 12392 #endif | |
| 12393 | |
| 12394 /******************************************************************************/ | |
| 12395 #ifndef PALM_2 | |
| 12396 SOAP_FMAC1 | |
| 12397 int | |
| 12398 SOAP_FMAC2 | |
| 12399 soap_s2float(struct soap *soap, const char *s, float *p) | |
| 12400 { if (s) | |
| 12401 { if (!*s) | |
| 12402 return soap->error = SOAP_TYPE; | |
| 12403 if (!soap_tag_cmp(s, "INF")) | |
| 12404 *p = FLT_PINFTY; | |
| 12405 else if (!soap_tag_cmp(s, "+INF")) | |
| 12406 *p = FLT_PINFTY; | |
| 12407 else if (!soap_tag_cmp(s, "-INF")) | |
| 12408 *p = FLT_NINFTY; | |
| 12409 else if (!soap_tag_cmp(s, "NaN")) | |
| 12410 *p = FLT_NAN; | |
| 12411 else | |
| 12412 { | |
| 12413 /* On some systems strtof requires -std=c99 or does not even link: so we try to use strtod first */ | |
| 12414 #if defined(HAVE_STRTOD_L) | |
| 12415 char *r; | |
| 12416 # ifdef WIN32 | |
| 12417 *p = (float)_strtod_l(s, &r, soap->c_locale); | |
| 12418 # else | |
| 12419 *p = (float)strtod_l(s, &r, soap->c_locale); | |
| 12420 # endif | |
| 12421 if (*r) | |
| 12422 #elif defined(HAVE_STRTOD) | |
| 12423 char *r; | |
| 12424 *p = (float)strtod(s, &r); | |
| 12425 if (*r) | |
| 12426 #elif defined(HAVE_STRTOF_L) | |
| 12427 char *r; | |
| 12428 *p = strtof_l((char*)s, &r, soap->c_locale); | |
| 12429 if (*r) | |
| 12430 #elif defined(HAVE_STRTOF) | |
| 12431 char *r; | |
| 12432 *p = strtof((char*)s, &r); | |
| 12433 if (*r) | |
| 12434 #endif | |
| 12435 { | |
| 12436 #if defined(HAVE_SSCANF_L) && !defined(HAVE_STRTOF_L) && !defined(HAVE_STRTOD_L) | |
| 12437 if (sscanf_l(s, soap->c_locale, "%f", p) != 1) | |
| 12438 soap->error = SOAP_TYPE; | |
| 12439 #elif defined(HAVE_SSCANF) | |
| 12440 if (sscanf(s, "%f", p) != 1) | |
| 12441 soap->error = SOAP_TYPE; | |
| 12442 #else | |
| 12443 soap->error = SOAP_TYPE; | |
| 12444 #endif | |
| 12445 } | |
| 12446 } | |
| 12447 } | |
| 12448 return soap->error; | |
| 12449 } | |
| 12450 #endif | |
| 12451 | |
| 12452 /******************************************************************************/ | |
| 12453 #ifndef WITH_LEAN | |
| 12454 static int soap_isnumeric(struct soap *soap, const char *type) | |
| 12455 { if (soap_match_tag(soap, soap->type, type) | |
| 12456 && soap_match_tag(soap, soap->type, ":float") | |
| 12457 && soap_match_tag(soap, soap->type, ":double") | |
| 12458 && soap_match_tag(soap, soap->type, ":decimal") | |
| 12459 && soap_match_tag(soap, soap->type, ":integer") | |
| 12460 && soap_match_tag(soap, soap->type, ":positiveInteger") | |
| 12461 && soap_match_tag(soap, soap->type, ":negativeInteger") | |
| 12462 && soap_match_tag(soap, soap->type, ":nonPositiveInteger") | |
| 12463 && soap_match_tag(soap, soap->type, ":nonNegativeInteger") | |
| 12464 && soap_match_tag(soap, soap->type, ":long") | |
| 12465 && soap_match_tag(soap, soap->type, ":int") | |
| 12466 && soap_match_tag(soap, soap->type, ":short") | |
| 12467 && soap_match_tag(soap, soap->type, ":byte") | |
| 12468 && soap_match_tag(soap, soap->type, ":unsignedLong") | |
| 12469 && soap_match_tag(soap, soap->type, ":unsignedInt") | |
| 12470 && soap_match_tag(soap, soap->type, ":unsignedShort") | |
| 12471 && soap_match_tag(soap, soap->type, ":unsignedByte")) | |
| 12472 { soap->error = SOAP_TYPE; | |
| 12473 soap_revert(soap); | |
| 12474 return SOAP_ERR; | |
| 12475 } | |
| 12476 return SOAP_OK; | |
| 12477 } | |
| 12478 #endif | |
| 12479 | |
| 12480 /******************************************************************************/ | |
| 12481 #ifndef PALM_2 | |
| 12482 SOAP_FMAC1 | |
| 12483 float * | |
| 12484 SOAP_FMAC2 | |
| 12485 soap_infloat(struct soap *soap, const char *tag, float *p, const char *type, int t) | |
| 12486 { if (soap_element_begin_in(soap, tag, 0, NULL)) | |
| 12487 return NULL; | |
| 12488 #ifndef WITH_LEAN | |
| 12489 if (*soap->type != '\0' && soap_isnumeric(soap, type)) | |
| 12490 return NULL; | |
| 12491 #endif | |
| 12492 p = (float*)soap_id_enter(soap, soap->id, p, t, sizeof(float), 0, NULL, NULL, NULL); | |
| 12493 if (*soap->href) | |
| 12494 p = (float*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(float), 0, NULL); | |
| 12495 else if (p) | |
| 12496 { if (soap_s2float(soap, soap_value(soap), p)) | |
| 12497 return NULL; | |
| 12498 } | |
| 12499 if (soap->body && soap_element_end_in(soap, tag)) | |
| 12500 return NULL; | |
| 12501 return p; | |
| 12502 } | |
| 12503 #endif | |
| 12504 | |
| 12505 /******************************************************************************/ | |
| 12506 #ifndef PALM_2 | |
| 12507 SOAP_FMAC1 | |
| 12508 const char* | |
| 12509 SOAP_FMAC2 | |
| 12510 soap_double2s(struct soap *soap, double n) | |
| 12511 { char *s; | |
| 12512 if (soap_isnan(n)) | |
| 12513 return "NaN"; | |
| 12514 if (soap_ispinfd(n)) | |
| 12515 return "INF"; | |
| 12516 if (soap_isninfd(n)) | |
| 12517 return "-INF"; | |
| 12518 #if defined(HAVE_SPRINTF_L) | |
| 12519 # ifdef WIN32 | |
| 12520 _sprintf_s_l(soap->tmpbuf, _countof(soap->tmpbuf), soap->double_format, soap->c_locale, n); | |
| 12521 # else | |
| 12522 sprintf_l(soap->tmpbuf, soap->c_locale, soap->double_format, n); | |
| 12523 # endif | |
| 12524 #else | |
| 12525 # ifdef HAVE_SNPRINTF | |
| 12526 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), soap->double_format, n); | |
| 12527 #else | |
| 12528 sprintf(soap->tmpbuf, soap->double_format, n); | |
| 12529 #endif | |
| 12530 s = strchr(soap->tmpbuf, ','); /* convert decimal comma to DP */ | |
| 12531 if (s) | |
| 12532 *s = '.'; | |
| 12533 #endif | |
| 12534 return soap->tmpbuf; | |
| 12535 } | |
| 12536 #endif | |
| 12537 | |
| 12538 /******************************************************************************/ | |
| 12539 #ifndef PALM_2 | |
| 12540 SOAP_FMAC1 | |
| 12541 int | |
| 12542 SOAP_FMAC2 | |
| 12543 soap_outdouble(struct soap *soap, const char *tag, int id, const double *p, const char *type, int n) | |
| 12544 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) | |
| 12545 || soap_string_out(soap, soap_double2s(soap, *p), 0)) | |
| 12546 return soap->error; | |
| 12547 return soap_element_end_out(soap, tag); | |
| 12548 } | |
| 12549 #endif | |
| 12550 | |
| 12551 /******************************************************************************/ | |
| 12552 #ifndef PALM_2 | |
| 12553 SOAP_FMAC1 | |
| 12554 int | |
| 12555 SOAP_FMAC2 | |
| 12556 soap_s2double(struct soap *soap, const char *s, double *p) | |
| 12557 { if (s) | |
| 12558 { if (!*s) | |
| 12559 return soap->error = SOAP_TYPE; | |
| 12560 if (!soap_tag_cmp(s, "INF")) | |
| 12561 *p = DBL_PINFTY; | |
| 12562 else if (!soap_tag_cmp(s, "+INF")) | |
| 12563 *p = DBL_PINFTY; | |
| 12564 else if (!soap_tag_cmp(s, "-INF")) | |
| 12565 *p = DBL_NINFTY; | |
| 12566 else if (!soap_tag_cmp(s, "NaN")) | |
| 12567 *p = DBL_NAN; | |
| 12568 else | |
| 12569 { | |
| 12570 #if defined(HAVE_STRTOD_L) | |
| 12571 char *r; | |
| 12572 # ifdef WIN32 | |
| 12573 *p = _strtod_l(s, &r, soap->c_locale); | |
| 12574 # else | |
| 12575 *p = strtod_l(s, &r, soap->c_locale); | |
| 12576 # endif | |
| 12577 if (*r) | |
| 12578 #elif defined(HAVE_STRTOD) | |
| 12579 char *r; | |
| 12580 *p = strtod(s, &r); | |
| 12581 if (*r) | |
| 12582 #endif | |
| 12583 { | |
| 12584 #if defined(HAVE_SSCANF_L) && !defined(HAVE_STRTOF_L) && !defined(HAVE_STRTOD_L) | |
| 12585 if (sscanf_l(s, soap->c_locale, "%lf", p) != 1) | |
| 12586 soap->error = SOAP_TYPE; | |
| 12587 #elif defined(HAVE_SSCANF) | |
| 12588 if (sscanf(s, "%lf", p) != 1) | |
| 12589 soap->error = SOAP_TYPE; | |
| 12590 #else | |
| 12591 soap->error = SOAP_TYPE; | |
| 12592 #endif | |
| 12593 } | |
| 12594 } | |
| 12595 } | |
| 12596 return soap->error; | |
| 12597 } | |
| 12598 #endif | |
| 12599 | |
| 12600 /******************************************************************************/ | |
| 12601 #ifndef PALM_2 | |
| 12602 SOAP_FMAC1 | |
| 12603 double * | |
| 12604 SOAP_FMAC2 | |
| 12605 soap_indouble(struct soap *soap, const char *tag, double *p, const char *type, int t) | |
| 12606 { if (soap_element_begin_in(soap, tag, 0, NULL)) | |
| 12607 return NULL; | |
| 12608 #ifndef WITH_LEAN | |
| 12609 if (*soap->type != '\0' && soap_isnumeric(soap, type)) | |
| 12610 return NULL; | |
| 12611 #endif | |
| 12612 p = (double*)soap_id_enter(soap, soap->id, p, t, sizeof(double), 0, NULL, NULL, NULL); | |
| 12613 if (*soap->href) | |
| 12614 p = (double*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(double), 0, NULL); | |
| 12615 else if (p) | |
| 12616 { if (soap_s2double(soap, soap_value(soap), p)) | |
| 12617 return NULL; | |
| 12618 } | |
| 12619 if (soap->body && soap_element_end_in(soap, tag)) | |
| 12620 return NULL; | |
| 12621 return p; | |
| 12622 } | |
| 12623 #endif | |
| 12624 | |
| 12625 /******************************************************************************/ | |
| 12626 #ifndef PALM_2 | |
| 12627 SOAP_FMAC1 | |
| 12628 const char* | |
| 12629 SOAP_FMAC2 | |
| 12630 soap_unsignedByte2s(struct soap *soap, unsigned char n) | |
| 12631 { return soap_unsignedLong2s(soap, (unsigned long)n); | |
| 12632 } | |
| 12633 #endif | |
| 12634 | |
| 12635 /******************************************************************************/ | |
| 12636 #ifndef PALM_2 | |
| 12637 SOAP_FMAC1 | |
| 12638 int | |
| 12639 SOAP_FMAC2 | |
| 12640 soap_outunsignedByte(struct soap *soap, const char *tag, int id, const unsigned char *p, const char *type, int n) | |
| 12641 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) | |
| 12642 || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0)) | |
| 12643 return soap->error; | |
| 12644 return soap_element_end_out(soap, tag); | |
| 12645 } | |
| 12646 #endif | |
| 12647 | |
| 12648 /******************************************************************************/ | |
| 12649 #ifndef PALM_2 | |
| 12650 SOAP_FMAC1 | |
| 12651 int | |
| 12652 SOAP_FMAC2 | |
| 12653 soap_s2unsignedByte(struct soap *soap, const char *s, unsigned char *p) | |
| 12654 { if (s) | |
| 12655 { unsigned long n; | |
| 12656 char *r; | |
| 12657 n = soap_strtoul(s, &r, 10); | |
| 12658 if (s == r || *r || n > 255) | |
| 12659 soap->error = SOAP_TYPE; | |
| 12660 *p = (unsigned char)n; | |
| 12661 } | |
| 12662 return soap->error; | |
| 12663 } | |
| 12664 #endif | |
| 12665 | |
| 12666 /******************************************************************************/ | |
| 12667 #ifndef PALM_2 | |
| 12668 SOAP_FMAC1 | |
| 12669 unsigned char * | |
| 12670 SOAP_FMAC2 | |
| 12671 soap_inunsignedByte(struct soap *soap, const char *tag, unsigned char *p, const char *type, int t) | |
| 12672 { if (soap_element_begin_in(soap, tag, 0, NULL)) | |
| 12673 return NULL; | |
| 12674 #ifndef WITH_LEAN | |
| 12675 if (*soap->type | |
| 12676 && soap_match_tag(soap, soap->type, type) | |
| 12677 && soap_match_tag(soap, soap->type, ":unsignedByte")) | |
| 12678 { soap->error = SOAP_TYPE; | |
| 12679 soap_revert(soap); | |
| 12680 return NULL; | |
| 12681 } | |
| 12682 #endif | |
| 12683 p = (unsigned char*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned char), 0, NULL, NULL, NULL); | |
| 12684 if (*soap->href) | |
| 12685 p = (unsigned char*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned char), 0, NULL); | |
| 12686 else if (p) | |
| 12687 { if (soap_s2unsignedByte(soap, soap_value(soap), p)) | |
| 12688 return NULL; | |
| 12689 } | |
| 12690 if (soap->body && soap_element_end_in(soap, tag)) | |
| 12691 return NULL; | |
| 12692 return p; | |
| 12693 } | |
| 12694 #endif | |
| 12695 | |
| 12696 /******************************************************************************/ | |
| 12697 #ifndef PALM_2 | |
| 12698 SOAP_FMAC1 | |
| 12699 const char* | |
| 12700 SOAP_FMAC2 | |
| 12701 soap_unsignedShort2s(struct soap *soap, unsigned short n) | |
| 12702 { return soap_unsignedLong2s(soap, (unsigned long)n); | |
| 12703 } | |
| 12704 #endif | |
| 12705 | |
| 12706 /******************************************************************************/ | |
| 12707 #ifndef PALM_2 | |
| 12708 SOAP_FMAC1 | |
| 12709 int | |
| 12710 SOAP_FMAC2 | |
| 12711 soap_outunsignedShort(struct soap *soap, const char *tag, int id, const unsigned short *p, const char *type, int n) | |
| 12712 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) | |
| 12713 || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0)) | |
| 12714 return soap->error; | |
| 12715 return soap_element_end_out(soap, tag); | |
| 12716 } | |
| 12717 #endif | |
| 12718 | |
| 12719 /******************************************************************************/ | |
| 12720 #ifndef PALM_2 | |
| 12721 SOAP_FMAC1 | |
| 12722 int | |
| 12723 SOAP_FMAC2 | |
| 12724 soap_s2unsignedShort(struct soap *soap, const char *s, unsigned short *p) | |
| 12725 { if (s) | |
| 12726 { unsigned long n; | |
| 12727 char *r; | |
| 12728 n = soap_strtoul(s, &r, 10); | |
| 12729 if (s == r || *r || n > 65535) | |
| 12730 soap->error = SOAP_TYPE; | |
| 12731 *p = (unsigned short)n; | |
| 12732 } | |
| 12733 return soap->error; | |
| 12734 } | |
| 12735 #endif | |
| 12736 | |
| 12737 /******************************************************************************/ | |
| 12738 #ifndef PALM_2 | |
| 12739 SOAP_FMAC1 | |
| 12740 unsigned short * | |
| 12741 SOAP_FMAC2 | |
| 12742 soap_inunsignedShort(struct soap *soap, const char *tag, unsigned short *p, const char *type, int t) | |
| 12743 { if (soap_element_begin_in(soap, tag, 0, NULL)) | |
| 12744 return NULL; | |
| 12745 #ifndef WITH_LEAN | |
| 12746 if (*soap->type | |
| 12747 && soap_match_tag(soap, soap->type, type) | |
| 12748 && soap_match_tag(soap, soap->type, ":unsignedShort") | |
| 12749 && soap_match_tag(soap, soap->type, ":unsignedByte")) | |
| 12750 { soap->error = SOAP_TYPE; | |
| 12751 soap_revert(soap); | |
| 12752 return NULL; | |
| 12753 } | |
| 12754 #endif | |
| 12755 p = (unsigned short*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned short), 0, NULL, NULL, NULL); | |
| 12756 if (*soap->href) | |
| 12757 p = (unsigned short*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned short), 0, NULL); | |
| 12758 else if (p) | |
| 12759 { if (soap_s2unsignedShort(soap, soap_value(soap), p)) | |
| 12760 return NULL; | |
| 12761 } | |
| 12762 if (soap->body && soap_element_end_in(soap, tag)) | |
| 12763 return NULL; | |
| 12764 return p; | |
| 12765 } | |
| 12766 #endif | |
| 12767 | |
| 12768 /******************************************************************************/ | |
| 12769 #ifndef PALM_2 | |
| 12770 SOAP_FMAC1 | |
| 12771 const char* | |
| 12772 SOAP_FMAC2 | |
| 12773 soap_unsignedInt2s(struct soap *soap, unsigned int n) | |
| 12774 { return soap_unsignedLong2s(soap, (unsigned long)n); | |
| 12775 } | |
| 12776 #endif | |
| 12777 | |
| 12778 /******************************************************************************/ | |
| 12779 #ifndef PALM_2 | |
| 12780 SOAP_FMAC1 | |
| 12781 int | |
| 12782 SOAP_FMAC2 | |
| 12783 soap_outunsignedInt(struct soap *soap, const char *tag, int id, const unsigned int *p, const char *type, int n) | |
| 12784 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) | |
| 12785 || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0)) | |
| 12786 return soap->error; | |
| 12787 return soap_element_end_out(soap, tag); | |
| 12788 } | |
| 12789 #endif | |
| 12790 | |
| 12791 /******************************************************************************/ | |
| 12792 #ifndef PALM_2 | |
| 12793 SOAP_FMAC1 | |
| 12794 int | |
| 12795 SOAP_FMAC2 | |
| 12796 soap_s2unsignedInt(struct soap *soap, const char *s, unsigned int *p) | |
| 12797 { if (s) | |
| 12798 { char *r; | |
| 12799 #ifndef WITH_NOIO | |
| 12800 #ifndef WITH_LEAN | |
| 12801 soap_reset_errno; | |
| 12802 #endif | |
| 12803 #endif | |
| 12804 *p = (unsigned int)soap_strtoul(s, &r, 10); | |
| 12805 if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r | |
| 12806 #ifndef WITH_NOIO | |
| 12807 #ifndef WITH_LEAN | |
| 12808 || soap_errno == SOAP_ERANGE | |
| 12809 #endif | |
| 12810 #endif | |
| 12811 ) | |
| 12812 soap->error = SOAP_TYPE; | |
| 12813 } | |
| 12814 return soap->error; | |
| 12815 } | |
| 12816 #endif | |
| 12817 | |
| 12818 /******************************************************************************/ | |
| 12819 #ifndef PALM_2 | |
| 12820 SOAP_FMAC1 | |
| 12821 unsigned int * | |
| 12822 SOAP_FMAC2 | |
| 12823 soap_inunsignedInt(struct soap *soap, const char *tag, unsigned int *p, const char *type, int t) | |
| 12824 { if (soap_element_begin_in(soap, tag, 0, NULL)) | |
| 12825 return NULL; | |
| 12826 #ifndef WITH_LEAN | |
| 12827 if (*soap->type | |
| 12828 && soap_match_tag(soap, soap->type, type) | |
| 12829 && soap_match_tag(soap, soap->type, ":unsignedInt") | |
| 12830 && soap_match_tag(soap, soap->type, ":unsignedShort") | |
| 12831 && soap_match_tag(soap, soap->type, ":unsignedByte")) | |
| 12832 { soap->error = SOAP_TYPE; | |
| 12833 soap_revert(soap); | |
| 12834 return NULL; | |
| 12835 } | |
| 12836 #endif | |
| 12837 p = (unsigned int*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned int), 0, NULL, NULL, NULL); | |
| 12838 if (*soap->href) | |
| 12839 p = (unsigned int*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned int), 0, NULL); | |
| 12840 else if (p) | |
| 12841 { if (soap_s2unsignedInt(soap, soap_value(soap), p)) | |
| 12842 return NULL; | |
| 12843 } | |
| 12844 if (soap->body && soap_element_end_in(soap, tag)) | |
| 12845 return NULL; | |
| 12846 return p; | |
| 12847 } | |
| 12848 #endif | |
| 12849 | |
| 12850 /******************************************************************************/ | |
| 12851 #ifndef PALM_2 | |
| 12852 SOAP_FMAC1 | |
| 12853 const char* | |
| 12854 SOAP_FMAC2 | |
| 12855 soap_unsignedLong2s(struct soap *soap, unsigned long n) | |
| 12856 { | |
| 12857 #ifdef HAVE_SNPRINTF | |
| 12858 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%lu", n); | |
| 12859 #else | |
| 12860 sprintf(soap->tmpbuf, "%lu", n); | |
| 12861 #endif | |
| 12862 return soap->tmpbuf; | |
| 12863 } | |
| 12864 #endif | |
| 12865 | |
| 12866 /******************************************************************************/ | |
| 12867 #ifndef PALM_2 | |
| 12868 SOAP_FMAC1 | |
| 12869 int | |
| 12870 SOAP_FMAC2 | |
| 12871 soap_outunsignedLong(struct soap *soap, const char *tag, int id, const unsigned long *p, const char *type, int n) | |
| 12872 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) | |
| 12873 || soap_string_out(soap, soap_unsignedLong2s(soap, *p), 0)) | |
| 12874 return soap->error; | |
| 12875 return soap_element_end_out(soap, tag); | |
| 12876 } | |
| 12877 #endif | |
| 12878 | |
| 12879 /******************************************************************************/ | |
| 12880 #ifndef PALM_2 | |
| 12881 SOAP_FMAC1 | |
| 12882 int | |
| 12883 SOAP_FMAC2 | |
| 12884 soap_s2unsignedLong(struct soap *soap, const char *s, unsigned long *p) | |
| 12885 { if (s) | |
| 12886 { char *r; | |
| 12887 #ifndef WITH_NOIO | |
| 12888 #ifndef WITH_LEAN | |
| 12889 soap_reset_errno; | |
| 12890 #endif | |
| 12891 #endif | |
| 12892 *p = soap_strtoul(s, &r, 10); | |
| 12893 if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r | |
| 12894 #ifndef WITH_NOIO | |
| 12895 #ifndef WITH_LEAN | |
| 12896 || soap_errno == SOAP_ERANGE | |
| 12897 #endif | |
| 12898 #endif | |
| 12899 ) | |
| 12900 soap->error = SOAP_TYPE; | |
| 12901 } | |
| 12902 return soap->error; | |
| 12903 } | |
| 12904 #endif | |
| 12905 | |
| 12906 /******************************************************************************/ | |
| 12907 #ifndef PALM_2 | |
| 12908 SOAP_FMAC1 | |
| 12909 unsigned long * | |
| 12910 SOAP_FMAC2 | |
| 12911 soap_inunsignedLong(struct soap *soap, const char *tag, unsigned long *p, const char *type, int t) | |
| 12912 { if (soap_element_begin_in(soap, tag, 0, NULL)) | |
| 12913 return NULL; | |
| 12914 #ifndef WITH_LEAN | |
| 12915 if (*soap->type | |
| 12916 && soap_match_tag(soap, soap->type, type) | |
| 12917 && soap_match_tag(soap, soap->type, ":unsignedInt") | |
| 12918 && soap_match_tag(soap, soap->type, ":unsignedShort") | |
| 12919 && soap_match_tag(soap, soap->type, ":unsignedByte")) | |
| 12920 { soap->error = SOAP_TYPE; | |
| 12921 soap_revert(soap); | |
| 12922 return NULL; | |
| 12923 } | |
| 12924 #endif | |
| 12925 p = (unsigned long*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned long), 0, NULL, NULL, NULL); | |
| 12926 if (*soap->href) | |
| 12927 p = (unsigned long*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned long), 0, NULL); | |
| 12928 else if (p) | |
| 12929 { if (soap_s2unsignedLong(soap, soap_value(soap), p)) | |
| 12930 return NULL; | |
| 12931 } | |
| 12932 if (soap->body && soap_element_end_in(soap, tag)) | |
| 12933 return NULL; | |
| 12934 return p; | |
| 12935 } | |
| 12936 #endif | |
| 12937 | |
| 12938 /******************************************************************************/ | |
| 12939 #ifndef WITH_LEAN | |
| 12940 SOAP_FMAC1 | |
| 12941 const char* | |
| 12942 SOAP_FMAC2 | |
| 12943 soap_ULONG642s(struct soap *soap, ULONG64 n) | |
| 12944 { | |
| 12945 #ifdef HAVE_SNPRINTF | |
| 12946 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), SOAP_ULONG_FORMAT, n); | |
| 12947 #else | |
| 12948 sprintf(soap->tmpbuf, SOAP_ULONG_FORMAT, n); | |
| 12949 #endif | |
| 12950 return soap->tmpbuf; | |
| 12951 } | |
| 12952 #endif | |
| 12953 | |
| 12954 /******************************************************************************/ | |
| 12955 #ifndef WITH_LEAN | |
| 12956 SOAP_FMAC1 | |
| 12957 int | |
| 12958 SOAP_FMAC2 | |
| 12959 soap_outULONG64(struct soap *soap, const char *tag, int id, const ULONG64 *p, const char *type, int n) | |
| 12960 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) | |
| 12961 || soap_string_out(soap, soap_ULONG642s(soap, *p), 0)) | |
| 12962 return soap->error; | |
| 12963 return soap_element_end_out(soap, tag); | |
| 12964 } | |
| 12965 #endif | |
| 12966 | |
| 12967 /******************************************************************************/ | |
| 12968 #ifndef WITH_LEAN | |
| 12969 SOAP_FMAC1 | |
| 12970 int | |
| 12971 SOAP_FMAC2 | |
| 12972 soap_s2ULONG64(struct soap *soap, const char *s, ULONG64 *p) | |
| 12973 { if (s) | |
| 12974 { | |
| 12975 #ifdef HAVE_STRTOULL | |
| 12976 char *r; | |
| 12977 #ifndef WITH_NOIO | |
| 12978 #ifndef WITH_LEAN | |
| 12979 soap_reset_errno; | |
| 12980 #endif | |
| 12981 #endif | |
| 12982 *p = soap_strtoull(s, &r, 10); | |
| 12983 if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r | |
| 12984 #ifndef WITH_NOIO | |
| 12985 #ifndef WITH_LEAN | |
| 12986 || soap_errno == SOAP_ERANGE | |
| 12987 #endif | |
| 12988 #endif | |
| 12989 ) | |
| 12990 #else | |
| 12991 #ifdef HAVE_SSCANF | |
| 12992 if (sscanf(s, SOAP_ULONG_FORMAT, p) != 1) | |
| 12993 #endif | |
| 12994 #endif | |
| 12995 soap->error = SOAP_TYPE; | |
| 12996 } | |
| 12997 return soap->error; | |
| 12998 } | |
| 12999 #endif | |
| 13000 | |
| 13001 /******************************************************************************/ | |
| 13002 #ifndef WITH_LEAN | |
| 13003 SOAP_FMAC1 | |
| 13004 ULONG64 * | |
| 13005 SOAP_FMAC2 | |
| 13006 soap_inULONG64(struct soap *soap, const char *tag, ULONG64 *p, const char *type, int t) | |
| 13007 { if (soap_element_begin_in(soap, tag, 0, NULL)) | |
| 13008 return NULL; | |
| 13009 if (*soap->type | |
| 13010 && soap_match_tag(soap, soap->type, type) | |
| 13011 && soap_match_tag(soap, soap->type, ":positiveInteger") | |
| 13012 && soap_match_tag(soap, soap->type, ":nonNegativeInteger") | |
| 13013 && soap_match_tag(soap, soap->type, ":unsignedLong") | |
| 13014 && soap_match_tag(soap, soap->type, ":unsignedInt") | |
| 13015 && soap_match_tag(soap, soap->type, ":unsignedShort") | |
| 13016 && soap_match_tag(soap, soap->type, ":unsignedByte")) | |
| 13017 { soap->error = SOAP_TYPE; | |
| 13018 soap_revert(soap); | |
| 13019 return NULL; | |
| 13020 } | |
| 13021 p = (ULONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(ULONG64), 0, NULL, NULL, NULL); | |
| 13022 if (*soap->href) | |
| 13023 p = (ULONG64*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(ULONG64), 0, NULL); | |
| 13024 else if (p) | |
| 13025 { if (soap_s2ULONG64(soap, soap_value(soap), p)) | |
| 13026 return NULL; | |
| 13027 } | |
| 13028 if (soap->body && soap_element_end_in(soap, tag)) | |
| 13029 return NULL; | |
| 13030 return p; | |
| 13031 } | |
| 13032 #endif | |
| 13033 | |
| 13034 /******************************************************************************/ | |
| 13035 #ifndef PALM_2 | |
| 13036 SOAP_FMAC1 | |
| 13037 int | |
| 13038 SOAP_FMAC2 | |
| 13039 soap_s2string(struct soap *soap, const char *s, char **t, long minlen, long maxlen) | |
| 13040 { if (s) | |
| 13041 { long l = (long)strlen(s); | |
| 13042 if ((maxlen >= 0 && l > maxlen) || l < minlen) | |
| 13043 return soap->error = SOAP_LENGTH; | |
| 13044 if (!(*t = soap_strdup(soap, s))) | |
| 13045 return soap->error = SOAP_EOM; | |
| 13046 if (!(soap->mode & (SOAP_ENC_LATIN | SOAP_C_UTFSTRING))) | |
| 13047 { char *r = *t; | |
| 13048 /* remove non-ASCII chars */ | |
| 13049 for (s = *t; *s; s++) | |
| 13050 if (!(*s & 0x80)) | |
| 13051 *r++ = *s; | |
| 13052 *r = '\0'; | |
| 13053 } | |
| 13054 } | |
| 13055 return soap->error; | |
| 13056 } | |
| 13057 #endif | |
| 13058 | |
| 13059 /******************************************************************************/ | |
| 13060 #ifndef PALM_2 | |
| 13061 SOAP_FMAC1 | |
| 13062 int | |
| 13063 SOAP_FMAC2 | |
| 13064 soap_s2QName(struct soap *soap, const char *s, char **t, long minlen, long maxlen) | |
| 13065 { if (s) | |
| 13066 { long l = (long)strlen(s); | |
| 13067 if ((maxlen >= 0 && l > maxlen) || l < minlen) | |
| 13068 return soap->error = SOAP_LENGTH; | |
| 13069 soap->labidx = 0; | |
| 13070 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Normalized namespace(s) of QNames '%s'", s)); | |
| 13071 /* convert (by prefix normalize prefix) all QNames in s */ | |
| 13072 for (;;) | |
| 13073 { size_t n; | |
| 13074 struct soap_nlist *np; | |
| 13075 register const char *p; | |
| 13076 /* skip blanks */ | |
| 13077 while (*s && soap_blank((soap_wchar)*s)) | |
| 13078 s++; | |
| 13079 if (!*s) | |
| 13080 break; | |
| 13081 /* find next QName */ | |
| 13082 n = 1; | |
| 13083 while (s[n] && !soap_blank((soap_wchar)s[n])) | |
| 13084 n++; | |
| 13085 np = soap->nlist; | |
| 13086 /* if there is no namespace stack, or prefix is "#" or "xml" then copy string */ | |
| 13087 if (!np || *s == '#' || !strncmp(s, "xml:", 4)) | |
| 13088 { soap_append_lab(soap, s, n); | |
| 13089 } | |
| 13090 else /* we normalize the QName by replacing its prefix */ | |
| 13091 { const char *q; | |
| 13092 for (p = s; *p && p < s + n; p++) | |
| 13093 if (*p == ':') | |
| 13094 break; | |
| 13095 if (*p == ':') | |
| 13096 { size_t k = p - s; | |
| 13097 while (np && (strncmp(np->id, s, k) || np->id[k])) | |
| 13098 np = np->next; | |
| 13099 p++; | |
| 13100 } | |
| 13101 else | |
| 13102 { while (np && *np->id) | |
| 13103 np = np->next; | |
| 13104 p = s; | |
| 13105 } | |
| 13106 /* replace prefix */ | |
| 13107 if (np) | |
| 13108 { if (np->index >= 0 && soap->local_namespaces && (q = soap->local_namespaces[np->index].id)) | |
| 13109 { size_t k = strlen(q); | |
| 13110 if (q[k-1] != '_') | |
| 13111 soap_append_lab(soap, q, k); | |
| 13112 else | |
| 13113 { soap_append_lab(soap, "\"", 1); | |
| 13114 soap_append_lab(soap, soap->local_namespaces[np->index].ns, strlen(soap->local_namespaces[np->index].ns)); | |
| 13115 soap_append_lab(soap, "\"", 1); | |
| 13116 } | |
| 13117 } | |
| 13118 else if (np->ns) | |
| 13119 { soap_append_lab(soap, "\"", 1); | |
| 13120 soap_append_lab(soap, np->ns, strlen(np->ns)); | |
| 13121 soap_append_lab(soap, "\"", 1); | |
| 13122 } | |
| 13123 else | |
| 13124 { 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)); | |
| 13125 return soap->error = SOAP_NAMESPACE; | |
| 13126 } | |
| 13127 } | |
| 13128 else if (s[n]) /* no namespace, part of string */ | |
| 13129 { soap_append_lab(soap, s, n); | |
| 13130 } | |
| 13131 else /* no namespace: assume "" namespace */ | |
| 13132 { soap_append_lab(soap, "\"\"", 2); | |
| 13133 } | |
| 13134 soap_append_lab(soap, ":", 1); | |
| 13135 soap_append_lab(soap, p, n - (p-s)); | |
| 13136 } | |
| 13137 /* advance to next and add spacing */ | |
| 13138 s += n; | |
| 13139 if (*s) | |
| 13140 soap_append_lab(soap, " ", 1); | |
| 13141 } | |
| 13142 soap_append_lab(soap, SOAP_STR_EOS, 1); | |
| 13143 *t = soap_strdup(soap, soap->labbuf); | |
| 13144 DBGLOG(TEST, SOAP_MESSAGE(fdebug, " into '%s'\n", *t)); | |
| 13145 } | |
| 13146 return soap->error; | |
| 13147 } | |
| 13148 #endif | |
| 13149 | |
| 13150 /******************************************************************************/ | |
| 13151 #ifndef PALM_2 | |
| 13152 SOAP_FMAC1 | |
| 13153 const char* | |
| 13154 SOAP_FMAC2 | |
| 13155 soap_QName2s(struct soap *soap, const char *s) | |
| 13156 { const char *t = NULL; | |
| 13157 if (s) | |
| 13158 { soap->labidx = 0; | |
| 13159 for (;;) | |
| 13160 { size_t n; | |
| 13161 /* skip blanks */ | |
| 13162 while (*s && soap_blank((soap_wchar)*s)) | |
| 13163 s++; | |
| 13164 if (!*s) | |
| 13165 break; | |
| 13166 /* find next QName */ | |
| 13167 n = 1; | |
| 13168 while (s[n] && !soap_blank((soap_wchar)s[n])) | |
| 13169 n++; | |
| 13170 /* normal prefix: pass string as is */ | |
| 13171 if (*s != '"') | |
| 13172 { | |
| 13173 #ifndef WITH_LEAN | |
| 13174 if ((soap->mode & SOAP_XML_CANONICAL)) | |
| 13175 soap_utilize_ns(soap, s); | |
| 13176 if ((soap->mode & SOAP_XML_DEFAULTNS)) | |
| 13177 { const char *r = strchr(s, ':'); | |
| 13178 if (r && soap->nlist && !strncmp(soap->nlist->id, s, r-s) && !soap->nlist->id[r-s]) | |
| 13179 { n -= r-s + 1; | |
| 13180 s = r + 1; | |
| 13181 } | |
| 13182 } | |
| 13183 #endif | |
| 13184 soap_append_lab(soap, s, n); | |
| 13185 } | |
| 13186 else /* URL-based string prefix */ | |
| 13187 { const char *q; | |
| 13188 s++; | |
| 13189 q = strchr(s, '"'); | |
| 13190 if (q) | |
| 13191 { struct Namespace *p = soap->local_namespaces; | |
| 13192 if (p) | |
| 13193 { for (; p->id; p++) | |
| 13194 { if (p->ns) | |
| 13195 if (!soap_tag_cmp(s, p->ns)) | |
| 13196 break; | |
| 13197 if (p->in) | |
| 13198 if (!soap_tag_cmp(s, p->in)) | |
| 13199 break; | |
| 13200 } | |
| 13201 } | |
| 13202 /* URL is in the namespace table? */ | |
| 13203 if (p && p->id) | |
| 13204 { const char *r = p->id; | |
| 13205 #ifndef WITH_LEAN | |
| 13206 if ((soap->mode & SOAP_XML_DEFAULTNS) && soap->nlist && !strcmp(soap->nlist->id, r)) | |
| 13207 q++; | |
| 13208 else | |
| 13209 #endif | |
| 13210 soap_append_lab(soap, r, strlen(r)); | |
| 13211 } | |
| 13212 else /* not in namespace table: create xmlns binding */ | |
| 13213 { char *r = soap_strdup(soap, s); | |
| 13214 r[q-s] = '\0'; | |
| 13215 #ifdef HAVE_SNPRINTF | |
| 13216 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "xmlns:_%d", soap->idnum++); | |
| 13217 #else | |
| 13218 sprintf(soap->tmpbuf, "xmlns:_%d", soap->idnum++); | |
| 13219 #endif | |
| 13220 soap_set_attr(soap, soap->tmpbuf, r, 1); | |
| 13221 soap_append_lab(soap, soap->tmpbuf + 6, strlen(soap->tmpbuf + 6)); | |
| 13222 } | |
| 13223 soap_append_lab(soap, q + 1, n - (q-s) - 1); | |
| 13224 } | |
| 13225 } | |
| 13226 /* advance to next and add spacing */ | |
| 13227 s += n; | |
| 13228 if (*s) | |
| 13229 soap_append_lab(soap, " ", 1); | |
| 13230 } | |
| 13231 soap_append_lab(soap, SOAP_STR_EOS, 1); | |
| 13232 t = soap_strdup(soap, soap->labbuf); | |
| 13233 } | |
| 13234 return t; | |
| 13235 } | |
| 13236 #endif | |
| 13237 | |
| 13238 /******************************************************************************/ | |
| 13239 #ifndef WITH_LEAN | |
| 13240 SOAP_FMAC1 | |
| 13241 int | |
| 13242 SOAP_FMAC2 | |
| 13243 soap_s2wchar(struct soap *soap, const char *s, wchar_t **t, long minlen, long maxlen) | |
| 13244 { if (s) | |
| 13245 { long l; | |
| 13246 wchar_t *r; | |
| 13247 *t = r = (wchar_t*)soap_malloc(soap, sizeof(wchar_t) * (strlen(s) + 1)); | |
| 13248 if (!r) | |
| 13249 return soap->error = SOAP_EOM; | |
| 13250 if (soap->mode & SOAP_ENC_LATIN) | |
| 13251 { while (*s) | |
| 13252 *r++ = (wchar_t)*s++; | |
| 13253 } | |
| 13254 else | |
| 13255 { /* Convert UTF8 to wchar */ | |
| 13256 while (*s) | |
| 13257 { register soap_wchar c, c1, c2, c3, c4; | |
| 13258 c = (unsigned char)*s++; | |
| 13259 if (c < 0x80) | |
| 13260 *r++ = (wchar_t)c; | |
| 13261 else | |
| 13262 { c1 = (soap_wchar)*s++ & 0x3F; | |
| 13263 if (c < 0xE0) | |
| 13264 *r++ = (wchar_t)(((soap_wchar)(c & 0x1F) << 6) | c1); | |
| 13265 else | |
| 13266 { c2 = (soap_wchar)*s++ & 0x3F; | |
| 13267 if (c < 0xF0) | |
| 13268 *r++ = (wchar_t)(((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2); | |
| 13269 else | |
| 13270 { c3 = (soap_wchar)*s++ & 0x3F; | |
| 13271 if (c < 0xF8) | |
| 13272 *r++ = (wchar_t)(((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3); | |
| 13273 else | |
| 13274 { c4 = (soap_wchar)*s++ & 0x3F; | |
| 13275 if (c < 0xFC) | |
| 13276 *r++ = (wchar_t)(((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4); | |
| 13277 else | |
| 13278 *r++ = (wchar_t)(((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(*s++ & 0x3F)); | |
| 13279 } | |
| 13280 } | |
| 13281 } | |
| 13282 } | |
| 13283 } | |
| 13284 } | |
| 13285 *r = L'\0'; | |
| 13286 l = (long)(r - *t); | |
| 13287 if ((maxlen >= 0 && l > maxlen) || l < minlen) | |
| 13288 return soap->error = SOAP_LENGTH; | |
| 13289 } | |
| 13290 return soap->error; | |
| 13291 } | |
| 13292 #endif | |
| 13293 | |
| 13294 /******************************************************************************/ | |
| 13295 #ifndef WITH_LEAN | |
| 13296 SOAP_FMAC1 | |
| 13297 const char* | |
| 13298 SOAP_FMAC2 | |
| 13299 soap_wchar2s(struct soap *soap, const wchar_t *s) | |
| 13300 { register soap_wchar c; | |
| 13301 register char *r, *t; | |
| 13302 const wchar_t *q = s; | |
| 13303 size_t n = 0; | |
| 13304 while ((c = *q++)) | |
| 13305 { if (c > 0 && c < 0x80) | |
| 13306 n++; | |
| 13307 else | |
| 13308 n += 6; | |
| 13309 } | |
| 13310 r = t = (char*)soap_malloc(soap, n + 1); | |
| 13311 if (r) | |
| 13312 { /* Convert wchar to UTF8 */ | |
| 13313 while ((c = *s++)) | |
| 13314 { if (c > 0 && c < 0x80) | |
| 13315 *t++ = (char)c; | |
| 13316 else | |
| 13317 { if (c < 0x0800) | |
| 13318 *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); | |
| 13319 else | |
| 13320 { if (c < 0x010000) | |
| 13321 *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); | |
| 13322 else | |
| 13323 { if (c < 0x200000) | |
| 13324 *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); | |
| 13325 else | |
| 13326 { if (c < 0x04000000) | |
| 13327 *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); | |
| 13328 else | |
| 13329 { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); | |
| 13330 *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); | |
| 13331 } | |
| 13332 *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); | |
| 13333 } | |
| 13334 *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); | |
| 13335 } | |
| 13336 *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); | |
| 13337 } | |
| 13338 *t++ = (char)(0x80 | (c & 0x3F)); | |
| 13339 } | |
| 13340 } | |
| 13341 *t = '\0'; | |
| 13342 } | |
| 13343 return r; | |
| 13344 } | |
| 13345 #endif | |
| 13346 | |
| 13347 /******************************************************************************/ | |
| 13348 #ifndef PALM_2 | |
| 13349 SOAP_FMAC1 | |
| 13350 int | |
| 13351 SOAP_FMAC2 | |
| 13352 soap_outstring(struct soap *soap, const char *tag, int id, char *const*p, const char *type, int n) | |
| 13353 { id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n); | |
| 13354 if (id < 0) | |
| 13355 return soap->error; | |
| 13356 if (!**p && (soap->mode & SOAP_C_NILSTRING)) | |
| 13357 return soap_element_null(soap, tag, id, type); | |
| 13358 if (soap_element_begin_out(soap, tag, id, type) | |
| 13359 || soap_string_out(soap, *p, 0) | |
| 13360 || soap_element_end_out(soap, tag)) | |
| 13361 return soap->error; | |
| 13362 return SOAP_OK; | |
| 13363 } | |
| 13364 #endif | |
| 13365 | |
| 13366 /******************************************************************************/ | |
| 13367 #ifndef PALM_2 | |
| 13368 SOAP_FMAC1 | |
| 13369 char ** | |
| 13370 SOAP_FMAC2 | |
| 13371 soap_instring(struct soap *soap, const char *tag, char **p, const char *type, int t, int flag, long minlen, long maxlen) | |
| 13372 { (void)type; | |
| 13373 if (soap_element_begin_in(soap, tag, 1, NULL)) | |
| 13374 { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG) | |
| 13375 return NULL; | |
| 13376 soap->error = SOAP_OK; | |
| 13377 } | |
| 13378 if (!p) | |
| 13379 { if (!(p = (char**)soap_malloc(soap, sizeof(char*)))) | |
| 13380 return NULL; | |
| 13381 } | |
| 13382 if (soap->null) | |
| 13383 *p = NULL; | |
| 13384 else if (soap->body) | |
| 13385 { *p = soap_string_in(soap, flag, minlen, maxlen); | |
| 13386 if (!*p || !(char*)soap_id_enter(soap, soap->id, *p, t, sizeof(char*), 0, NULL, NULL, NULL)) | |
| 13387 return NULL; | |
| 13388 if (!**p && tag && *tag == '-') | |
| 13389 { soap->error = SOAP_NO_TAG; | |
| 13390 return NULL; | |
| 13391 } | |
| 13392 } | |
| 13393 else if (tag && *tag == '-') | |
| 13394 { soap->error = SOAP_NO_TAG; | |
| 13395 return NULL; | |
| 13396 } | |
| 13397 else if (!*soap->href && minlen > 0) | |
| 13398 { soap->error = SOAP_LENGTH; | |
| 13399 return NULL; | |
| 13400 } | |
| 13401 else | |
| 13402 *p = soap_strdup(soap, SOAP_STR_EOS); | |
| 13403 if (*soap->href) | |
| 13404 p = (char**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(char**), 0); | |
| 13405 if (soap->body && soap_element_end_in(soap, tag)) | |
| 13406 return NULL; | |
| 13407 return p; | |
| 13408 } | |
| 13409 #endif | |
| 13410 | |
| 13411 /******************************************************************************/ | |
| 13412 #ifndef WITH_LEANER | |
| 13413 #ifndef PALM_2 | |
| 13414 SOAP_FMAC1 | |
| 13415 int | |
| 13416 SOAP_FMAC2 | |
| 13417 soap_outwstring(struct soap *soap, const char *tag, int id, wchar_t *const*p, const char *type, int n) | |
| 13418 { id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n); | |
| 13419 if (id < 0) | |
| 13420 return soap->error; | |
| 13421 if (!**p && (soap->mode & SOAP_C_NILSTRING)) | |
| 13422 return soap_element_null(soap, tag, id, type); | |
| 13423 if (soap_element_begin_out(soap, tag, id, type) | |
| 13424 || soap_wstring_out(soap, *p, 0) | |
| 13425 || soap_element_end_out(soap, tag)) | |
| 13426 return soap->error; | |
| 13427 return SOAP_OK; | |
| 13428 } | |
| 13429 #endif | |
| 13430 #endif | |
| 13431 | |
| 13432 /******************************************************************************/ | |
| 13433 #ifndef WITH_LEANER | |
| 13434 #ifndef PALM_2 | |
| 13435 SOAP_FMAC1 | |
| 13436 wchar_t ** | |
| 13437 SOAP_FMAC2 | |
| 13438 soap_inwstring(struct soap *soap, const char *tag, wchar_t **p, const char *type, int t, long minlen, long maxlen) | |
| 13439 { (void)type; | |
| 13440 if (soap_element_begin_in(soap, tag, 1, NULL)) | |
| 13441 { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG) | |
| 13442 return NULL; | |
| 13443 soap->error = SOAP_OK; | |
| 13444 } | |
| 13445 if (!p) | |
| 13446 { if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*)))) | |
| 13447 return NULL; | |
| 13448 } | |
| 13449 if (soap->body) | |
| 13450 { *p = soap_wstring_in(soap, 1, minlen, maxlen); | |
| 13451 if (!*p || !(wchar_t*)soap_id_enter(soap, soap->id, *p, t, sizeof(wchar_t*), 0, NULL, NULL, NULL)) | |
| 13452 return NULL; | |
| 13453 if (!**p && tag && *tag == '-') | |
| 13454 { soap->error = SOAP_NO_TAG; | |
| 13455 return NULL; | |
| 13456 } | |
| 13457 } | |
| 13458 else if (tag && *tag == '-') | |
| 13459 { soap->error = SOAP_NO_TAG; | |
| 13460 return NULL; | |
| 13461 } | |
| 13462 else if (soap->null) | |
| 13463 *p = NULL; | |
| 13464 else | |
| 13465 *p = soap_wstrdup(soap, (wchar_t*)SOAP_STR_EOS); | |
| 13466 if (*soap->href) | |
| 13467 p = (wchar_t**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(wchar_t**), 0); | |
| 13468 if (soap->body && soap_element_end_in(soap, tag)) | |
| 13469 return NULL; | |
| 13470 return p; | |
| 13471 } | |
| 13472 #endif | |
| 13473 #endif | |
| 13474 | |
| 13475 /******************************************************************************/ | |
| 13476 #ifndef WITH_LEAN | |
| 13477 SOAP_FMAC1 | |
| 13478 time_t | |
| 13479 SOAP_FMAC2 | |
| 13480 soap_timegm(struct tm *T) | |
| 13481 { | |
| 13482 #if defined(HAVE_TIMEGM) | |
| 13483 return timegm(T); | |
| 13484 #else | |
| 13485 time_t t, g, z; | |
| 13486 struct tm tm; | |
| 13487 t = mktime(T); | |
| 13488 if (t == (time_t)-1) | |
| 13489 return (time_t)-1; | |
| 13490 #ifdef HAVE_GMTIME_R | |
| 13491 gmtime_r(&t, &tm); | |
| 13492 #else | |
| 13493 tm = *gmtime(&t); | |
| 13494 #endif | |
| 13495 tm.tm_isdst = 0; | |
| 13496 g = mktime(&tm); | |
| 13497 if (g == (time_t)-1) | |
| 13498 return (time_t)-1; | |
| 13499 z = g - t; | |
| 13500 return t - z; | |
| 13501 #endif | |
| 13502 } | |
| 13503 #endif | |
| 13504 | |
| 13505 /******************************************************************************/ | |
| 13506 #ifndef WITH_LEAN | |
| 13507 SOAP_FMAC1 | |
| 13508 const char* | |
| 13509 SOAP_FMAC2 | |
| 13510 soap_dateTime2s(struct soap *soap, time_t n) | |
| 13511 { struct tm T, *pT = &T; | |
| 13512 #if defined(HAVE_GMTIME_R) | |
| 13513 if (gmtime_r(&n, pT)) | |
| 13514 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); | |
| 13515 #elif defined(HAVE_GMTIME) | |
| 13516 if ((pT = gmtime(&n))) | |
| 13517 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); | |
| 13518 #elif defined(HAVE_TM_GMTOFF) || defined(HAVE_STRUCT_TM_TM_GMTOFF) || defined(HAVE_STRUCT_TM___TM_GMTOFF) | |
| 13519 #if defined(HAVE_LOCALTIME_R) | |
| 13520 if (localtime_r(&n, pT)) | |
| 13521 { strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S%z", pT); | |
| 13522 memmove(soap->tmpbuf + 23, soap->tmpbuf + 22, 3); /* 2000-03-01T02:00:00+0300 */ | |
| 13523 soap->tmpbuf[22] = ':'; /* 2000-03-01T02:00:00+03:00 */ | |
| 13524 } | |
| 13525 #else | |
| 13526 if ((pT = localtime(&n))) | |
| 13527 { strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S%z", pT); | |
| 13528 memmove(soap->tmpbuf + 23, soap->tmpbuf + 22, 3); /* 2000-03-01T02:00:00+0300 */ | |
| 13529 soap->tmpbuf[22] = ':'; /* 2000-03-01T02:00:00+03:00 */ | |
| 13530 } | |
| 13531 #endif | |
| 13532 #elif defined(HAVE_GETTIMEOFDAY) | |
| 13533 struct timezone tz; | |
| 13534 memset((void*)&tz, 0, sizeof(tz)); | |
| 13535 #if defined(HAVE_LOCALTIME_R) | |
| 13536 if (localtime_r(&n, pT)) | |
| 13537 { struct timeval tv; | |
| 13538 gettimeofday(&tv, &tz); | |
| 13539 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); | |
| 13540 #ifdef HAVE_SNPRINTF | |
| 13541 soap_snprintf(soap->tmpbuf + strlen(soap->tmpbuf), sizeof(soap->tmpbuf) - strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60); | |
| 13542 #else | |
| 13543 sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60); | |
| 13544 #endif | |
| 13545 } | |
| 13546 #else | |
| 13547 if ((pT = localtime(&n))) | |
| 13548 { struct timeval tv; | |
| 13549 gettimeofday(&tv, &tz); | |
| 13550 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); | |
| 13551 #ifdef HAVE_SNPRINTF | |
| 13552 soap_snprintf(soap->tmpbuf + strlen(soap->tmpbuf), sizeof(soap->tmpbuf) - strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60); | |
| 13553 #else | |
| 13554 sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60); | |
| 13555 #endif | |
| 13556 } | |
| 13557 #endif | |
| 13558 #elif defined(HAVE_FTIME) | |
| 13559 struct timeb t; | |
| 13560 memset((void*)&t, 0, sizeof(t)); | |
| 13561 #if defined(HAVE_LOCALTIME_R) | |
| 13562 if (localtime_r(&n, pT)) | |
| 13563 { | |
| 13564 #ifdef __BORLANDC__ | |
| 13565 ::ftime(&t); | |
| 13566 #else | |
| 13567 ftime(&t); | |
| 13568 #endif | |
| 13569 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); | |
| 13570 #ifdef HAVE_SNPRINTF | |
| 13571 soap_snprintf(soap->tmpbuf + strlen(soap->tmpbuf), sizeof(soap->tmpbuf) - strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60); | |
| 13572 #else | |
| 13573 sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60); | |
| 13574 #endif | |
| 13575 } | |
| 13576 #else | |
| 13577 if ((pT = localtime(&n))) | |
| 13578 { | |
| 13579 #ifdef __BORLANDC__ | |
| 13580 ::ftime(&t); | |
| 13581 #else | |
| 13582 ftime(&t); | |
| 13583 #endif | |
| 13584 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); | |
| 13585 #ifdef HAVE_SNPRINTF | |
| 13586 soap_snprintf(soap->tmpbuf + strlen(soap->tmpbuf), sizeof(soap->tmpbuf) - strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60); | |
| 13587 #else | |
| 13588 sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60); | |
| 13589 #endif | |
| 13590 } | |
| 13591 #endif | |
| 13592 #elif defined(HAVE_LOCALTIME_R) | |
| 13593 if (localtime_r(&n, pT)) | |
| 13594 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); | |
| 13595 #else | |
| 13596 if ((pT = localtime(&n))) | |
| 13597 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); | |
| 13598 #endif | |
| 13599 else | |
| 13600 strcpy(soap->tmpbuf, "1969-12-31T23:59:59Z"); | |
| 13601 return soap->tmpbuf; | |
| 13602 } | |
| 13603 #endif | |
| 13604 | |
| 13605 /******************************************************************************/ | |
| 13606 #ifndef WITH_LEAN | |
| 13607 SOAP_FMAC1 | |
| 13608 int | |
| 13609 SOAP_FMAC2 | |
| 13610 soap_outdateTime(struct soap *soap, const char *tag, int id, const time_t *p, const char *type, int n) | |
| 13611 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) | |
| 13612 || soap_string_out(soap, soap_dateTime2s(soap, *p), 0)) | |
| 13613 return soap->error; | |
| 13614 return soap_element_end_out(soap, tag); | |
| 13615 } | |
| 13616 #endif | |
| 13617 | |
| 13618 /******************************************************************************/ | |
| 13619 #ifndef WITH_LEAN | |
| 13620 SOAP_FMAC1 | |
| 13621 int | |
| 13622 SOAP_FMAC2 | |
| 13623 soap_s2dateTime(struct soap *soap, const char *s, time_t *p) | |
| 13624 { if (s) | |
| 13625 { char zone[32]; | |
| 13626 struct tm T; | |
| 13627 const char *t; | |
| 13628 *zone = '\0'; | |
| 13629 memset((void*)&T, 0, sizeof(T)); | |
| 13630 if (strchr(s, '-')) | |
| 13631 t = "%d-%d-%dT%d:%d:%d%31s"; | |
| 13632 else if (strchr(s, ':')) | |
| 13633 t = "%4d%2d%2dT%d:%d:%d%31s"; | |
| 13634 else /* parse non-XSD-standard alternative ISO 8601 format */ | |
| 13635 t = "%4d%2d%2dT%2d%2d%2d%31s"; | |
| 13636 if (sscanf(s, t, &T.tm_year, &T.tm_mon, &T.tm_mday, &T.tm_hour, &T.tm_min, &T.tm_sec, zone) < 6) | |
| 13637 return soap->error = SOAP_TYPE; | |
| 13638 if (T.tm_year == 1) | |
| 13639 T.tm_year = 70; | |
| 13640 else | |
| 13641 T.tm_year -= 1900; | |
| 13642 T.tm_mon--; | |
| 13643 if (*zone == '.') | |
| 13644 { for (s = zone + 1; *s; s++) | |
| 13645 if (*s < '0' || *s > '9') | |
| 13646 break; | |
| 13647 } | |
| 13648 else | |
| 13649 s = zone; | |
| 13650 if (*s) | |
| 13651 { | |
| 13652 #ifndef WITH_NOZONE | |
| 13653 if (*s == '+' || *s == '-') | |
| 13654 { int h = 0, m = 0; | |
| 13655 if (s[3] == ':') | |
| 13656 { /* +hh:mm */ | |
| 13657 sscanf(s, "%d:%d", &h, &m); | |
| 13658 if (h < 0) | |
| 13659 m = -m; | |
| 13660 } | |
| 13661 else /* +hhmm */ | |
| 13662 { m = (int)soap_strtol(s, NULL, 10); | |
| 13663 h = m / 100; | |
| 13664 m = m % 100; | |
| 13665 } | |
| 13666 T.tm_min -= m; | |
| 13667 T.tm_hour -= h; | |
| 13668 /* put hour and min in range */ | |
| 13669 T.tm_hour += T.tm_min / 60; | |
| 13670 T.tm_min %= 60; | |
| 13671 if (T.tm_min < 0) | |
| 13672 { T.tm_min += 60; | |
| 13673 T.tm_hour--; | |
| 13674 } | |
| 13675 T.tm_mday += T.tm_hour / 24; | |
| 13676 T.tm_hour %= 24; | |
| 13677 if (T.tm_hour < 0) | |
| 13678 { T.tm_hour += 24; | |
| 13679 T.tm_mday--; | |
| 13680 } | |
| 13681 /* note: day of the month may be out of range, timegm() handles it */ | |
| 13682 } | |
| 13683 #endif | |
| 13684 *p = soap_timegm(&T); | |
| 13685 } | |
| 13686 else /* no UTC or timezone, so assume we got a localtime */ | |
| 13687 { T.tm_isdst = -1; | |
| 13688 *p = mktime(&T); | |
| 13689 } | |
| 13690 } | |
| 13691 return soap->error; | |
| 13692 } | |
| 13693 #endif | |
| 13694 | |
| 13695 /******************************************************************************/ | |
| 13696 #ifndef WITH_LEAN | |
| 13697 SOAP_FMAC1 | |
| 13698 time_t * | |
| 13699 SOAP_FMAC2 | |
| 13700 soap_indateTime(struct soap *soap, const char *tag, time_t *p, const char *type, int t) | |
| 13701 { if (soap_element_begin_in(soap, tag, 0, NULL)) | |
| 13702 return NULL; | |
| 13703 if (*soap->type | |
| 13704 && soap_match_tag(soap, soap->type, type) | |
| 13705 && soap_match_tag(soap, soap->type, ":dateTime")) | |
| 13706 { soap->error = SOAP_TYPE; | |
| 13707 soap_revert(soap); | |
| 13708 return NULL; | |
| 13709 } | |
| 13710 p = (time_t*)soap_id_enter(soap, soap->id, p, t, sizeof(time_t), 0, NULL, NULL, NULL); | |
| 13711 if (*soap->href) | |
| 13712 p = (time_t*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(time_t), 0, NULL); | |
| 13713 else if (p) | |
| 13714 { if (soap_s2dateTime(soap, soap_value(soap), p)) | |
| 13715 return NULL; | |
| 13716 } | |
| 13717 if (soap->body && soap_element_end_in(soap, tag)) | |
| 13718 return NULL; | |
| 13719 return p; | |
| 13720 } | |
| 13721 #endif | |
| 13722 | |
| 13723 /******************************************************************************/ | |
| 13724 #ifndef PALM_2 | |
| 13725 SOAP_FMAC1 | |
| 13726 int | |
| 13727 SOAP_FMAC2 | |
| 13728 soap_outliteral(struct soap *soap, const char *tag, char *const*p, const char *type) | |
| 13729 { int i; | |
| 13730 const char *t = NULL; | |
| 13731 if (tag && *tag != '-') | |
| 13732 { if (soap->local_namespaces && (t = strchr(tag, ':'))) | |
| 13733 { size_t n = t - tag; | |
| 13734 if (n >= sizeof(soap->tmpbuf)) | |
| 13735 n = sizeof(soap->tmpbuf) - 1; | |
| 13736 strncpy(soap->tmpbuf, tag, n); | |
| 13737 soap->tmpbuf[n] = '\0'; | |
| 13738 for (i = 0; soap->local_namespaces[i].id; i++) | |
| 13739 if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id)) | |
| 13740 break; | |
| 13741 t++; | |
| 13742 if (soap_element(soap, t, 0, type) | |
| 13743 || soap_attribute(soap, "xmlns", soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS) | |
| 13744 || soap_element_start_end_out(soap, NULL)) | |
| 13745 return soap->error; | |
| 13746 } | |
| 13747 else | |
| 13748 { t = tag; | |
| 13749 if (soap_element_begin_out(soap, t, 0, type)) | |
| 13750 return soap->error; | |
| 13751 } | |
| 13752 } | |
| 13753 if (p && *p) | |
| 13754 { if (soap_send(soap, *p)) /* send as-is */ | |
| 13755 return soap->error; | |
| 13756 } | |
| 13757 if (t) | |
| 13758 return soap_element_end_out(soap, t); | |
| 13759 return SOAP_OK; | |
| 13760 } | |
| 13761 #endif | |
| 13762 | |
| 13763 /******************************************************************************/ | |
| 13764 #ifndef PALM_2 | |
| 13765 SOAP_FMAC1 | |
| 13766 char ** | |
| 13767 SOAP_FMAC2 | |
| 13768 soap_inliteral(struct soap *soap, const char *tag, char **p) | |
| 13769 { if (soap_element_begin_in(soap, tag, 1, NULL)) | |
| 13770 { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT) | |
| 13771 return NULL; | |
| 13772 soap->error = SOAP_OK; | |
| 13773 } | |
| 13774 if (!p) | |
| 13775 { if (!(p = (char**)soap_malloc(soap, sizeof(char*)))) | |
| 13776 return NULL; | |
| 13777 } | |
| 13778 if (soap->body || (tag && *tag == '-')) | |
| 13779 { *p = soap_string_in(soap, 0, -1, -1); | |
| 13780 if (!*p) | |
| 13781 return NULL; | |
| 13782 if (!**p && tag && *tag == '-') | |
| 13783 { soap->error = SOAP_NO_TAG; | |
| 13784 return NULL; | |
| 13785 } | |
| 13786 } | |
| 13787 else if (soap->null) | |
| 13788 *p = NULL; | |
| 13789 else | |
| 13790 *p = soap_strdup(soap, SOAP_STR_EOS); | |
| 13791 if (soap->body && soap_element_end_in(soap, tag)) | |
| 13792 return NULL; | |
| 13793 return p; | |
| 13794 } | |
| 13795 #endif | |
| 13796 | |
| 13797 /******************************************************************************/ | |
| 13798 #ifndef WITH_LEANER | |
| 13799 #ifndef PALM_2 | |
| 13800 SOAP_FMAC1 | |
| 13801 int | |
| 13802 SOAP_FMAC2 | |
| 13803 soap_outwliteral(struct soap *soap, const char *tag, wchar_t *const*p, const char *type) | |
| 13804 { int i; | |
| 13805 const char *t = NULL; | |
| 13806 if (tag && *tag != '-') | |
| 13807 { if (soap->local_namespaces && (t = strchr(tag, ':'))) | |
| 13808 { size_t n = t - tag; | |
| 13809 if (n >= sizeof(soap->tmpbuf)) | |
| 13810 n = sizeof(soap->tmpbuf) - 1; | |
| 13811 strncpy(soap->tmpbuf, tag, n); | |
| 13812 soap->tmpbuf[n] = '\0'; | |
| 13813 for (i = 0; soap->local_namespaces[i].id; i++) | |
| 13814 if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id)) | |
| 13815 break; | |
| 13816 t++; | |
| 13817 if (soap_element(soap, t, 0, type) | |
| 13818 || soap_attribute(soap, "xmlns", soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS) | |
| 13819 || soap_element_start_end_out(soap, NULL)) | |
| 13820 return soap->error; | |
| 13821 } | |
| 13822 else | |
| 13823 { t = tag; | |
| 13824 if (soap_element_begin_out(soap, t, 0, type)) | |
| 13825 return soap->error; | |
| 13826 } | |
| 13827 } | |
| 13828 if (p) | |
| 13829 { wchar_t c; | |
| 13830 const wchar_t *s = *p; | |
| 13831 while ((c = *s++)) | |
| 13832 { if (soap_pututf8(soap, (unsigned long)c)) /* send as-is in UTF8 */ | |
| 13833 return soap->error; | |
| 13834 } | |
| 13835 } | |
| 13836 if (t) | |
| 13837 return soap_element_end_out(soap, t); | |
| 13838 return SOAP_OK; | |
| 13839 } | |
| 13840 #endif | |
| 13841 #endif | |
| 13842 | |
| 13843 /******************************************************************************/ | |
| 13844 #ifndef WITH_LEANER | |
| 13845 #ifndef PALM_2 | |
| 13846 SOAP_FMAC1 | |
| 13847 wchar_t ** | |
| 13848 SOAP_FMAC2 | |
| 13849 soap_inwliteral(struct soap *soap, const char *tag, wchar_t **p) | |
| 13850 { if (soap_element_begin_in(soap, tag, 1, NULL)) | |
| 13851 { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT) | |
| 13852 return NULL; | |
| 13853 soap->error = SOAP_OK; | |
| 13854 } | |
| 13855 if (!p) | |
| 13856 { if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*)))) | |
| 13857 return NULL; | |
| 13858 } | |
| 13859 if (soap->body) | |
| 13860 { *p = soap_wstring_in(soap, 0, -1, -1); | |
| 13861 if (!*p) | |
| 13862 return NULL; | |
| 13863 if (!**p && tag && *tag == '-') | |
| 13864 { soap->error = SOAP_NO_TAG; | |
| 13865 return NULL; | |
| 13866 } | |
| 13867 } | |
| 13868 else if (tag && *tag == '-') | |
| 13869 { soap->error = SOAP_NO_TAG; | |
| 13870 return NULL; | |
| 13871 } | |
| 13872 else if (soap->null) | |
| 13873 *p = NULL; | |
| 13874 else | |
| 13875 *p = soap_wstrdup(soap, (wchar_t*)SOAP_STR_EOS); | |
| 13876 if (soap->body && soap_element_end_in(soap, tag)) | |
| 13877 return NULL; | |
| 13878 return p; | |
| 13879 } | |
| 13880 #endif | |
| 13881 #endif | |
| 13882 | |
| 13883 /******************************************************************************/ | |
| 13884 #ifndef PALM_2 | |
| 13885 SOAP_FMAC1 | |
| 13886 const char * | |
| 13887 SOAP_FMAC2 | |
| 13888 soap_value(struct soap *soap) | |
| 13889 { register size_t i; | |
| 13890 register soap_wchar c = 0; | |
| 13891 register char *s = soap->tmpbuf; | |
| 13892 if (!soap->body) | |
| 13893 return SOAP_STR_EOS; | |
| 13894 do c = soap_get(soap); | |
| 13895 while (soap_blank(c)); | |
| 13896 for (i = 0; i < sizeof(soap->tmpbuf) - 1; i++) | |
| 13897 { if (c == SOAP_TT || c == SOAP_LT || (int)c == EOF) | |
| 13898 break; | |
| 13899 *s++ = (char)c; | |
| 13900 c = soap_get(soap); | |
| 13901 } | |
| 13902 for (s--; i > 0; i--, s--) | |
| 13903 { if (!soap_blank((soap_wchar)*s)) | |
| 13904 break; | |
| 13905 } | |
| 13906 s[1] = '\0'; | |
| 13907 soap->tmpbuf[sizeof(soap->tmpbuf) - 1] = '\0'; /* appease */ | |
| 13908 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element content value='%s'\n", soap->tmpbuf)); | |
| 13909 if (c == SOAP_TT || c == SOAP_LT || (int)c == EOF) | |
| 13910 soap_unget(soap, c); | |
| 13911 else if (soap->mode & SOAP_XML_STRICT) | |
| 13912 { soap->error = SOAP_LENGTH; | |
| 13913 return NULL; | |
| 13914 } | |
| 13915 #ifdef WITH_DOM | |
| 13916 if ((soap->mode & SOAP_XML_DOM) && soap->dom) | |
| 13917 soap->dom->data = soap_strdup(soap, soap->tmpbuf); | |
| 13918 #endif | |
| 13919 return soap->tmpbuf; /* return non-null pointer */ | |
| 13920 } | |
| 13921 #endif | |
| 13922 | |
| 13923 /******************************************************************************/ | |
| 13924 #if !defined(WITH_LEANER) || !defined(WITH_NOHTTP) | |
| 13925 #ifndef PALM_2 | |
| 13926 SOAP_FMAC1 | |
| 13927 int | |
| 13928 SOAP_FMAC2 | |
| 13929 soap_getline(struct soap *soap, char *s, int len) | |
| 13930 { int i = len; | |
| 13931 soap_wchar c = 0; | |
| 13932 for (;;) | |
| 13933 { while (--i > 0) | |
| 13934 { c = soap_getchar(soap); | |
| 13935 if (c == '\r' || c == '\n') | |
| 13936 break; | |
| 13937 if ((int)c == EOF) | |
| 13938 return soap->error = SOAP_CHK_EOF; | |
| 13939 *s++ = (char)c; | |
| 13940 } | |
| 13941 *s = '\0'; | |
| 13942 if (c != '\n') | |
| 13943 c = soap_getchar(soap); /* got \r or something else, now get \n */ | |
| 13944 if (c == '\n') | |
| 13945 { if (i + 1 == len) /* empty line: end of HTTP/MIME header */ | |
| 13946 break; | |
| 13947 c = soap_get0(soap); | |
| 13948 if (c != ' ' && c != '\t') /* HTTP line continuation? */ | |
| 13949 break; | |
| 13950 } | |
| 13951 else if ((int)c == EOF) | |
| 13952 return soap->error = SOAP_CHK_EOF; | |
| 13953 if (i <= 0) | |
| 13954 return soap->error = SOAP_HDR; | |
| 13955 } | |
| 13956 return SOAP_OK; | |
| 13957 } | |
| 13958 #endif | |
| 13959 #endif | |
| 13960 | |
| 13961 /******************************************************************************/ | |
| 13962 #ifndef PALM_1 | |
| 13963 static size_t | |
| 13964 soap_count_attachments(struct soap *soap) | |
| 13965 { | |
| 13966 #ifndef WITH_LEANER | |
| 13967 register struct soap_multipart *content; | |
| 13968 register size_t count = soap->count; | |
| 13969 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the message size with attachments, current count=%lu\n", (unsigned long)count)); | |
| 13970 if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) | |
| 13971 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of DIME attachments\n")); | |
| 13972 for (content = soap->dime.first; content; content = content->next) | |
| 13973 { count += 12 + ((content->size+3)&(~3)); | |
| 13974 if (content->id) | |
| 13975 count += ((strlen(content->id)+3)&(~3)); | |
| 13976 if (content->type) | |
| 13977 count += ((strlen(content->type)+3)&(~3)); | |
| 13978 if (content->options) | |
| 13979 count += ((((unsigned char)content->options[2] << 8) | ((unsigned char)content->options[3]))+7)&(~3); | |
| 13980 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of DIME attachment content is %lu bytes\n", (unsigned long)content->size)); | |
| 13981 } | |
| 13982 } | |
| 13983 if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary) | |
| 13984 { register size_t n = strlen(soap->mime.boundary); | |
| 13985 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of MIME attachments\n")); | |
| 13986 for (content = soap->mime.first; content; content = content->next) | |
| 13987 { register const char *s; | |
| 13988 /* count \r\n--boundary\r\n */ | |
| 13989 count += 6 + n; | |
| 13990 /* count Content-Type: ...\r\n */ | |
| 13991 if (content->type) | |
| 13992 count += 16 + strlen(content->type); | |
| 13993 /* count Content-Transfer-Encoding: ...\r\n */ | |
| 13994 s = soap_code_str(mime_codes, content->encoding); | |
| 13995 if (s) | |
| 13996 count += 29 + strlen(s); | |
| 13997 /* count Content-ID: ...\r\n */ | |
| 13998 if (content->id) | |
| 13999 count += 14 + strlen(content->id); | |
| 14000 /* count Content-Location: ...\r\n */ | |
| 14001 if (content->location) | |
| 14002 count += 20 + strlen(content->location); | |
| 14003 /* count Content-Description: ...\r\n */ | |
| 14004 if (content->description) | |
| 14005 count += 23 + strlen(content->description); | |
| 14006 /* count \r\n...content */ | |
| 14007 count += 2 + content->size; | |
| 14008 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of MIME attachment content is %lu bytes\n", (unsigned long)content->size)); | |
| 14009 } | |
| 14010 /* count \r\n--boundary-- */ | |
| 14011 count += 6 + n; | |
| 14012 } | |
| 14013 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New count=%lu\n", (unsigned long)count)); | |
| 14014 return count; | |
| 14015 #else | |
| 14016 return soap->count; | |
| 14017 #endif | |
| 14018 } | |
| 14019 #endif | |
| 14020 | |
| 14021 /******************************************************************************/ | |
| 14022 #ifndef WITH_LEANER | |
| 14023 #ifndef PALM_1 | |
| 14024 static int | |
| 14025 soap_putdimefield(struct soap *soap, const char *s, size_t n) | |
| 14026 { if (soap_send_raw(soap, s, n)) | |
| 14027 return soap->error; | |
| 14028 return soap_send_raw(soap, SOAP_STR_PADDING, -(long)n&3); | |
| 14029 } | |
| 14030 #endif | |
| 14031 #endif | |
| 14032 | |
| 14033 /******************************************************************************/ | |
| 14034 #ifndef WITH_LEANER | |
| 14035 #ifndef PALM_1 | |
| 14036 SOAP_FMAC1 | |
| 14037 char * | |
| 14038 SOAP_FMAC2 | |
| 14039 soap_dime_option(struct soap *soap, unsigned short optype, const char *option) | |
| 14040 { size_t n; | |
| 14041 char *s = NULL; | |
| 14042 if (option) | |
| 14043 { n = strlen(option); | |
| 14044 s = (char*)soap_malloc(soap, n + 5); | |
| 14045 if (s) | |
| 14046 { s[0] = (char)(optype >> 8); | |
| 14047 s[1] = (char)(optype & 0xFF); | |
| 14048 s[2] = (char)(n >> 8); | |
| 14049 s[3] = (char)(n & 0xFF); | |
| 14050 strcpy(s + 4, option); | |
| 14051 } | |
| 14052 } | |
| 14053 return s; | |
| 14054 } | |
| 14055 #endif | |
| 14056 #endif | |
| 14057 | |
| 14058 /******************************************************************************/ | |
| 14059 #ifndef WITH_LEANER | |
| 14060 #ifndef PALM_1 | |
| 14061 SOAP_FMAC1 | |
| 14062 int | |
| 14063 SOAP_FMAC2 | |
| 14064 soap_putdimehdr(struct soap *soap) | |
| 14065 { unsigned char tmp[12]; | |
| 14066 size_t optlen = 0, idlen = 0, typelen = 0; | |
| 14067 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Put DIME header id='%s'\n", soap->dime.id ? soap->dime.id : SOAP_STR_EOS)); | |
| 14068 if (soap->dime.options) | |
| 14069 optlen = (((unsigned char)soap->dime.options[2] << 8) | ((unsigned char)soap->dime.options[3])) + 4; | |
| 14070 if (soap->dime.id) | |
| 14071 { idlen = strlen(soap->dime.id); | |
| 14072 if (idlen > 0x0000FFFF) | |
| 14073 idlen = 0x0000FFFF; | |
| 14074 } | |
| 14075 if (soap->dime.type) | |
| 14076 { typelen = strlen(soap->dime.type); | |
| 14077 if (typelen > 0x0000FFFF) | |
| 14078 typelen = 0x0000FFFF; | |
| 14079 } | |
| 14080 tmp[0] = SOAP_DIME_VERSION | (soap->dime.flags & 0x7); | |
| 14081 tmp[1] = soap->dime.flags & 0xF0; | |
| 14082 tmp[2] = (char)(optlen >> 8); | |
| 14083 tmp[3] = (char)(optlen & 0xFF); | |
| 14084 tmp[4] = (char)(idlen >> 8); | |
| 14085 tmp[5] = (char)(idlen & 0xFF); | |
| 14086 tmp[6] = (char)(typelen >> 8); | |
| 14087 tmp[7] = (char)(typelen & 0xFF); | |
| 14088 tmp[8] = (char)(soap->dime.size >> 24); | |
| 14089 tmp[9] = (char)((soap->dime.size >> 16) & 0xFF); | |
| 14090 tmp[10] = (char)((soap->dime.size >> 8) & 0xFF); | |
| 14091 tmp[11] = (char)(soap->dime.size & 0xFF); | |
| 14092 if (soap_send_raw(soap, (char*)tmp, 12) | |
| 14093 || soap_putdimefield(soap, soap->dime.options, optlen) | |
| 14094 || soap_putdimefield(soap, soap->dime.id, idlen) | |
| 14095 || soap_putdimefield(soap, soap->dime.type, typelen)) | |
| 14096 return soap->error; | |
| 14097 return SOAP_OK; | |
| 14098 } | |
| 14099 #endif | |
| 14100 #endif | |
| 14101 | |
| 14102 /******************************************************************************/ | |
| 14103 #ifndef WITH_LEANER | |
| 14104 #ifndef PALM_1 | |
| 14105 SOAP_FMAC1 | |
| 14106 int | |
| 14107 SOAP_FMAC2 | |
| 14108 soap_putdime(struct soap *soap) | |
| 14109 { struct soap_multipart *content; | |
| 14110 if (!(soap->mode & SOAP_ENC_DIME)) | |
| 14111 return SOAP_OK; | |
| 14112 for (content = soap->dime.first; content; content = content->next) | |
| 14113 { void *handle; | |
| 14114 soap->dime.size = content->size; | |
| 14115 soap->dime.id = content->id; | |
| 14116 soap->dime.type = content->type; | |
| 14117 soap->dime.options = content->options; | |
| 14118 soap->dime.flags = SOAP_DIME_VERSION | SOAP_DIME_MEDIA; | |
| 14119 if (soap->fdimereadopen && ((handle = soap->fdimereadopen(soap, (void*)content->ptr, content->id, content->type, content->options)) || soap->error)) | |
| 14120 { size_t size = content->size; | |
| 14121 if (!handle) | |
| 14122 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadopen failed\n")); | |
| 14123 return soap->error; | |
| 14124 } | |
| 14125 if (!size && ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE)) | |
| 14126 { size_t chunksize = sizeof(soap->tmpbuf); | |
| 14127 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming DIME\n")); | |
| 14128 do | |
| 14129 { size = soap->fdimeread(soap, handle, soap->tmpbuf, chunksize); | |
| 14130 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread returned %lu bytes\n", (unsigned long)size)); | |
| 14131 if (size < chunksize) | |
| 14132 { soap->dime.flags &= ~SOAP_DIME_CF; | |
| 14133 if (!content->next) | |
| 14134 soap->dime.flags |= SOAP_DIME_ME; | |
| 14135 } | |
| 14136 else | |
| 14137 soap->dime.flags |= SOAP_DIME_CF; | |
| 14138 soap->dime.size = size; | |
| 14139 if (soap_putdimehdr(soap) | |
| 14140 || soap_putdimefield(soap, soap->tmpbuf, size)) | |
| 14141 break; | |
| 14142 if (soap->dime.id) | |
| 14143 { soap->dime.flags &= ~(SOAP_DIME_MB | SOAP_DIME_MEDIA); | |
| 14144 soap->dime.id = NULL; | |
| 14145 soap->dime.type = NULL; | |
| 14146 soap->dime.options = NULL; | |
| 14147 } | |
| 14148 } while (size >= chunksize); | |
| 14149 } | |
| 14150 else | |
| 14151 { if (!content->next) | |
| 14152 soap->dime.flags |= SOAP_DIME_ME; | |
| 14153 if (soap_putdimehdr(soap)) | |
| 14154 return soap->error; | |
| 14155 do | |
| 14156 { size_t bufsize; | |
| 14157 if (size < sizeof(soap->tmpbuf)) | |
| 14158 bufsize = size; | |
| 14159 else | |
| 14160 bufsize = sizeof(soap->tmpbuf); | |
| 14161 if (!(bufsize = soap->fdimeread(soap, handle, soap->tmpbuf, bufsize))) | |
| 14162 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size)); | |
| 14163 soap->error = SOAP_CHK_EOF; | |
| 14164 break; | |
| 14165 } | |
| 14166 if (soap_send_raw(soap, soap->tmpbuf, bufsize)) | |
| 14167 break; | |
| 14168 size -= bufsize; | |
| 14169 } while (size); | |
| 14170 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n")); | |
| 14171 soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3); | |
| 14172 } | |
| 14173 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n")); | |
| 14174 if (soap->fdimereadclose) | |
| 14175 soap->fdimereadclose(soap, handle); | |
| 14176 } | |
| 14177 else | |
| 14178 { if (!content->next) | |
| 14179 soap->dime.flags |= SOAP_DIME_ME; | |
| 14180 if (soap_putdimehdr(soap) | |
| 14181 || soap_putdimefield(soap, (char*)content->ptr, content->size)) | |
| 14182 return soap->error; | |
| 14183 } | |
| 14184 } | |
| 14185 return SOAP_OK; | |
| 14186 } | |
| 14187 #endif | |
| 14188 #endif | |
| 14189 | |
| 14190 /******************************************************************************/ | |
| 14191 #ifndef WITH_LEANER | |
| 14192 #ifndef PALM_1 | |
| 14193 static char * | |
| 14194 soap_getdimefield(struct soap *soap, size_t n) | |
| 14195 { register soap_wchar c; | |
| 14196 register size_t i; | |
| 14197 register char *s; | |
| 14198 register char *p = NULL; | |
| 14199 if (n) | |
| 14200 { p = (char*)soap_malloc(soap, n + 1); | |
| 14201 if (p) | |
| 14202 { s = p; | |
| 14203 for (i = n; i > 0; i--) | |
| 14204 { if ((int)(c = soap_get1(soap)) == EOF) | |
| 14205 { soap->error = SOAP_CHK_EOF; | |
| 14206 return NULL; | |
| 14207 } | |
| 14208 *s++ = (char)c; | |
| 14209 } | |
| 14210 *s = '\0'; | |
| 14211 if ((soap->error = soap_move(soap, (size_t)(-(long)n&3)))) | |
| 14212 return NULL; | |
| 14213 } | |
| 14214 else | |
| 14215 soap->error = SOAP_EOM; | |
| 14216 } | |
| 14217 return p; | |
| 14218 } | |
| 14219 #endif | |
| 14220 #endif | |
| 14221 | |
| 14222 /******************************************************************************/ | |
| 14223 #ifndef WITH_LEANER | |
| 14224 #ifndef PALM_1 | |
| 14225 SOAP_FMAC1 | |
| 14226 int | |
| 14227 SOAP_FMAC2 | |
| 14228 soap_getdimehdr(struct soap *soap) | |
| 14229 { register soap_wchar c; | |
| 14230 register char *s; | |
| 14231 register int i; | |
| 14232 unsigned char tmp[12]; | |
| 14233 size_t optlen, idlen, typelen; | |
| 14234 if (!(soap->mode & SOAP_ENC_DIME)) | |
| 14235 return soap->error = SOAP_DIME_END; | |
| 14236 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME header\n")); | |
| 14237 if (soap->dime.buflen || soap->dime.chunksize) | |
| 14238 { if (soap_move(soap, soap->dime.size - soap_tell(soap))) | |
| 14239 return soap->error = SOAP_CHK_EOF; | |
| 14240 soap_unget(soap, soap_getchar(soap)); /* skip padding and get hdr */ | |
| 14241 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... From chunked\n")); | |
| 14242 return SOAP_OK; | |
| 14243 } | |
| 14244 s = (char*)tmp; | |
| 14245 for (i = 12; i > 0; i--) | |
| 14246 { if ((int)(c = soap_getchar(soap)) == EOF) | |
| 14247 return soap->error = SOAP_CHK_EOF; | |
| 14248 *s++ = (char)c; | |
| 14249 } | |
| 14250 if ((tmp[0] & 0xF8) != SOAP_DIME_VERSION) | |
| 14251 return soap->error = SOAP_DIME_MISMATCH; | |
| 14252 soap->dime.flags = (tmp[0] & 0x7) | (tmp[1] & 0xF0); | |
| 14253 optlen = (tmp[2] << 8) | tmp[3]; | |
| 14254 idlen = (tmp[4] << 8) | tmp[5]; | |
| 14255 typelen = (tmp[6] << 8) | tmp[7]; | |
| 14256 soap->dime.size = ((size_t)tmp[8] << 24) | ((size_t)tmp[9] << 16) | ((size_t)tmp[10] << 8) | ((size_t)tmp[11]); | |
| 14257 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME size=%lu flags=0x%X\n", (unsigned long)soap->dime.size, soap->dime.flags)); | |
| 14258 if (!(soap->dime.options = soap_getdimefield(soap, optlen)) && soap->error) | |
| 14259 return soap->error; | |
| 14260 if (!(soap->dime.id = soap_getdimefield(soap, idlen)) && soap->error) | |
| 14261 return soap->error; | |
| 14262 if (!(soap->dime.type = soap_getdimefield(soap, typelen)) && soap->error) | |
| 14263 return soap->error; | |
| 14264 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)); | |
| 14265 if (soap->dime.flags & SOAP_DIME_ME) | |
| 14266 soap->mode &= ~SOAP_ENC_DIME; | |
| 14267 return SOAP_OK; | |
| 14268 } | |
| 14269 #endif | |
| 14270 #endif | |
| 14271 | |
| 14272 /******************************************************************************/ | |
| 14273 #ifndef WITH_LEANER | |
| 14274 #ifndef PALM_1 | |
| 14275 SOAP_FMAC1 | |
| 14276 int | |
| 14277 SOAP_FMAC2 | |
| 14278 soap_getdime(struct soap *soap) | |
| 14279 { while (soap->dime.flags & SOAP_DIME_CF) | |
| 14280 { if (soap_getdimehdr(soap)) | |
| 14281 return soap->error; | |
| 14282 if (soap_move(soap, soap->dime.size)) | |
| 14283 return soap->error = SOAP_EOF; | |
| 14284 } | |
| 14285 if (soap_move(soap, (size_t)(((soap->dime.size+3)&(~3)) - soap_tell(soap)))) | |
| 14286 return soap->error = SOAP_EOF; | |
| 14287 for (;;) | |
| 14288 { register struct soap_multipart *content; | |
| 14289 if (soap_getdimehdr(soap)) | |
| 14290 break; | |
| 14291 if (soap->fdimewriteopen && ((soap->dime.ptr = (char*)soap->fdimewriteopen(soap, soap->dime.id, soap->dime.type, soap->dime.options)) || soap->error)) | |
| 14292 { const char *id, *type, *options; | |
| 14293 size_t size, n; | |
| 14294 if (!soap->dime.ptr) | |
| 14295 return soap->error; | |
| 14296 id = soap->dime.id; | |
| 14297 type = soap->dime.type; | |
| 14298 options = soap->dime.options; | |
| 14299 for (;;) | |
| 14300 { size = soap->dime.size; | |
| 14301 for (;;) | |
| 14302 { n = soap->buflen - soap->bufidx; | |
| 14303 if (size < n) | |
| 14304 n = size; | |
| 14305 if ((soap->error = soap->fdimewrite(soap, (void*)soap->dime.ptr, soap->buf + soap->bufidx, n))) | |
| 14306 break; | |
| 14307 size -= n; | |
| 14308 if (!size) | |
| 14309 { soap->bufidx += n; | |
| 14310 break; | |
| 14311 } | |
| 14312 if (soap_recv(soap)) | |
| 14313 { soap->error = SOAP_EOF; | |
| 14314 goto end; | |
| 14315 } | |
| 14316 } | |
| 14317 if (soap_move(soap, (size_t)(-(long)soap->dime.size&3))) | |
| 14318 { soap->error = SOAP_EOF; | |
| 14319 break; | |
| 14320 } | |
| 14321 if (!(soap->dime.flags & SOAP_DIME_CF)) | |
| 14322 break; | |
| 14323 if (soap_getdimehdr(soap)) | |
| 14324 break; | |
| 14325 } | |
| 14326 end: | |
| 14327 if (soap->fdimewriteclose) | |
| 14328 soap->fdimewriteclose(soap, (void*)soap->dime.ptr); | |
| 14329 soap->dime.size = 0; | |
| 14330 soap->dime.id = id; | |
| 14331 soap->dime.type = type; | |
| 14332 soap->dime.options = options; | |
| 14333 } | |
| 14334 else if (soap->dime.flags & SOAP_DIME_CF) | |
| 14335 { const char *id, *type, *options; | |
| 14336 id = soap->dime.id; | |
| 14337 type = soap->dime.type; | |
| 14338 options = soap->dime.options; | |
| 14339 if (soap_new_block(soap) == NULL) | |
| 14340 return SOAP_EOM; | |
| 14341 for (;;) | |
| 14342 { register soap_wchar c; | |
| 14343 register size_t i; | |
| 14344 register char *s; | |
| 14345 if (soap->dime.size > SOAP_MAXDIMESIZE) | |
| 14346 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME size=%lu exceeds SOAP_MAXDIMESIZE=%lu\n", (unsigned long)soap->dime.size, (unsigned long)SOAP_MAXDIMESIZE)); | |
| 14347 return soap->error = SOAP_DIME_ERROR; | |
| 14348 } | |
| 14349 s = (char*)soap_push_block(soap, NULL, soap->dime.size); | |
| 14350 if (!s) | |
| 14351 return soap->error = SOAP_EOM; | |
| 14352 for (i = soap->dime.size; i > 0; i--) | |
| 14353 { if ((int)(c = soap_get1(soap)) == EOF) | |
| 14354 return soap->error = SOAP_EOF; | |
| 14355 *s++ = (char)c; | |
| 14356 } | |
| 14357 if (soap_move(soap, (size_t)(-(long)soap->dime.size&3))) | |
| 14358 return soap->error = SOAP_EOF; | |
| 14359 if (!(soap->dime.flags & SOAP_DIME_CF)) | |
| 14360 break; | |
| 14361 if (soap_getdimehdr(soap)) | |
| 14362 return soap->error; | |
| 14363 } | |
| 14364 soap->dime.size = soap->blist->size++; /* allocate one more byte in blist for the terminating '\0' */ | |
| 14365 if (!(soap->dime.ptr = soap_save_block(soap, NULL, NULL, 0))) | |
| 14366 return soap->error; | |
| 14367 soap->dime.ptr[soap->dime.size] = '\0'; /* make 0-terminated */ | |
| 14368 soap->dime.id = id; | |
| 14369 soap->dime.type = type; | |
| 14370 soap->dime.options = options; | |
| 14371 } | |
| 14372 else | |
| 14373 soap->dime.ptr = soap_getdimefield(soap, soap->dime.size); | |
| 14374 content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, soap->dime.ptr, soap->dime.size); | |
| 14375 if (!content) | |
| 14376 return soap->error = SOAP_EOM; | |
| 14377 content->id = soap->dime.id; | |
| 14378 content->type = soap->dime.type; | |
| 14379 content->options = soap->dime.options; | |
| 14380 if (soap->error) | |
| 14381 return soap->error; | |
| 14382 soap_resolve_attachment(soap, content); | |
| 14383 } | |
| 14384 if (soap->error != SOAP_DIME_END) | |
| 14385 return soap->error; | |
| 14386 return soap->error = SOAP_OK; | |
| 14387 } | |
| 14388 #endif | |
| 14389 #endif | |
| 14390 | |
| 14391 /******************************************************************************/ | |
| 14392 #ifndef WITH_LEANER | |
| 14393 #ifndef PALM_1 | |
| 14394 SOAP_FMAC1 | |
| 14395 int | |
| 14396 SOAP_FMAC2 | |
| 14397 soap_getmimehdr(struct soap *soap) | |
| 14398 { struct soap_multipart *content; | |
| 14399 do | |
| 14400 { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) | |
| 14401 return soap->error; | |
| 14402 } | |
| 14403 while (!*soap->msgbuf); | |
| 14404 if (soap->msgbuf[0] == '-' && soap->msgbuf[1] == '-') | |
| 14405 { char *s = soap->msgbuf + strlen(soap->msgbuf) - 1; | |
| 14406 /* remove white space */ | |
| 14407 while (soap_blank((soap_wchar)*s)) | |
| 14408 s--; | |
| 14409 s[1] = '\0'; | |
| 14410 if (soap->mime.boundary) | |
| 14411 { if (strcmp(soap->msgbuf + 2, soap->mime.boundary)) | |
| 14412 return soap->error = SOAP_MIME_ERROR; | |
| 14413 } | |
| 14414 else | |
| 14415 soap->mime.boundary = soap_strdup(soap, soap->msgbuf + 2); | |
| 14416 if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) | |
| 14417 return soap->error; | |
| 14418 } | |
| 14419 if (soap_set_mime_attachment(soap, NULL, 0, SOAP_MIME_NONE, NULL, NULL, NULL, NULL)) | |
| 14420 return soap->error = SOAP_EOM; | |
| 14421 content = soap->mime.last; | |
| 14422 for (;;) | |
| 14423 { register char *key = soap->msgbuf; | |
| 14424 register char *val; | |
| 14425 if (!*key) | |
| 14426 break; | |
| 14427 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "MIME header: %s\n", key)); | |
| 14428 val = strchr(soap->msgbuf, ':'); | |
| 14429 if (val) | |
| 14430 { *val = '\0'; | |
| 14431 do val++; | |
| 14432 while (*val && *val <= 32); | |
| 14433 if (!soap_tag_cmp(key, "Content-ID")) | |
| 14434 content->id = soap_strdup(soap, val); | |
| 14435 else if (!soap_tag_cmp(key, "Content-Location")) | |
| 14436 content->location = soap_strdup(soap, val); | |
| 14437 else if (!soap_tag_cmp(key, "Content-Disposition")) | |
| 14438 content->id = soap_strdup(soap, soap_get_header_attribute(soap, val, "name")); | |
| 14439 else if (!soap_tag_cmp(key, "Content-Type")) | |
| 14440 content->type = soap_strdup(soap, val); | |
| 14441 else if (!soap_tag_cmp(key, "Content-Description")) | |
| 14442 content->description = soap_strdup(soap, val); | |
| 14443 else if (!soap_tag_cmp(key, "Content-Transfer-Encoding")) | |
| 14444 content->encoding = (enum soap_mime_encoding)soap_code_int(mime_codes, val, (long)SOAP_MIME_NONE); | |
| 14445 } | |
| 14446 if (soap_getline(soap, key, sizeof(soap->msgbuf))) | |
| 14447 return soap->error; | |
| 14448 } | |
| 14449 return SOAP_OK; | |
| 14450 } | |
| 14451 #endif | |
| 14452 #endif | |
| 14453 | |
| 14454 /******************************************************************************/ | |
| 14455 #ifndef WITH_LEANER | |
| 14456 #ifndef PALM_1 | |
| 14457 SOAP_FMAC1 | |
| 14458 int | |
| 14459 SOAP_FMAC2 | |
| 14460 soap_getmime(struct soap *soap) | |
| 14461 { while (soap_get_mime_attachment(soap, NULL)) | |
| 14462 ; | |
| 14463 return soap->error; | |
| 14464 } | |
| 14465 #endif | |
| 14466 #endif | |
| 14467 | |
| 14468 /******************************************************************************/ | |
| 14469 #ifndef WITH_LEANER | |
| 14470 #ifndef PALM_1 | |
| 14471 SOAP_FMAC1 | |
| 14472 void | |
| 14473 SOAP_FMAC2 | |
| 14474 soap_post_check_mime_attachments(struct soap *soap) | |
| 14475 { soap->imode |= SOAP_MIME_POSTCHECK; | |
| 14476 } | |
| 14477 #endif | |
| 14478 #endif | |
| 14479 | |
| 14480 /******************************************************************************/ | |
| 14481 #ifndef WITH_LEANER | |
| 14482 #ifndef PALM_1 | |
| 14483 SOAP_FMAC1 | |
| 14484 int | |
| 14485 SOAP_FMAC2 | |
| 14486 soap_check_mime_attachments(struct soap *soap) | |
| 14487 { if (soap->mode & SOAP_MIME_POSTCHECK) | |
| 14488 return soap_get_mime_attachment(soap, NULL) != NULL; | |
| 14489 return SOAP_OK; | |
| 14490 } | |
| 14491 #endif | |
| 14492 #endif | |
| 14493 | |
| 14494 /******************************************************************************/ | |
| 14495 #ifndef WITH_LEANER | |
| 14496 #ifndef PALM_1 | |
| 14497 SOAP_FMAC1 | |
| 14498 struct soap_multipart * | |
| 14499 SOAP_FMAC2 | |
| 14500 soap_get_mime_attachment(struct soap *soap, void *handle) | |
| 14501 { register soap_wchar c = 0; | |
| 14502 register size_t i, m = 0; | |
| 14503 register char *s, *t = NULL; | |
| 14504 register struct soap_multipart *content; | |
| 14505 register short flag = 0; | |
| 14506 if (!(soap->mode & SOAP_ENC_MIME)) | |
| 14507 return NULL; | |
| 14508 content = soap->mime.last; | |
| 14509 if (!content) | |
| 14510 { if (soap_getmimehdr(soap)) | |
| 14511 return NULL; | |
| 14512 content = soap->mime.last; | |
| 14513 } | |
| 14514 else if (content != soap->mime.first) | |
| 14515 { if (soap->fmimewriteopen && ((content->ptr = (char*)soap->fmimewriteopen(soap, (void*)handle, content->id, content->type, content->description, content->encoding)) || soap->error)) | |
| 14516 { if (!content->ptr) | |
| 14517 return NULL; | |
| 14518 } | |
| 14519 } | |
| 14520 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)); | |
| 14521 if (!content->ptr && soap_new_block(soap) == NULL) | |
| 14522 { soap->error = SOAP_EOM; | |
| 14523 return NULL; | |
| 14524 } | |
| 14525 for (;;) | |
| 14526 { if (content->ptr) | |
| 14527 s = soap->tmpbuf; | |
| 14528 else if (!(s = (char*)soap_push_block(soap, NULL, sizeof(soap->tmpbuf)))) | |
| 14529 { soap->error = SOAP_EOM; | |
| 14530 return NULL; | |
| 14531 } | |
| 14532 for (i = 0; i < sizeof(soap->tmpbuf); i++) | |
| 14533 { if (m > 0) | |
| 14534 { *s++ = *t++; | |
| 14535 m--; | |
| 14536 } | |
| 14537 else | |
| 14538 { if (!flag) | |
| 14539 { c = soap_get1(soap); | |
| 14540 if ((int)c == EOF) | |
| 14541 { if (content->ptr && soap->fmimewriteclose) | |
| 14542 soap->fmimewriteclose(soap, (void*)content->ptr); | |
| 14543 soap->error = SOAP_CHK_EOF; | |
| 14544 return NULL; | |
| 14545 } | |
| 14546 } | |
| 14547 if (flag || c == '\r') | |
| 14548 { t = soap->msgbuf; | |
| 14549 memset(t, 0, sizeof(soap->msgbuf)); | |
| 14550 strcpy(t, "\n--"); | |
| 14551 if (soap->mime.boundary) | |
| 14552 strncat(t, soap->mime.boundary, sizeof(soap->msgbuf)-4); | |
| 14553 do c = soap_getchar(soap); | |
| 14554 while (c == *t++); | |
| 14555 if ((int)c == EOF) | |
| 14556 { if (content->ptr && soap->fmimewriteclose) | |
| 14557 soap->fmimewriteclose(soap, (void*)content->ptr); | |
| 14558 soap->error = SOAP_CHK_EOF; | |
| 14559 return NULL; | |
| 14560 } | |
| 14561 if (!*--t) | |
| 14562 goto end; | |
| 14563 *t = (char)c; | |
| 14564 flag = (c == '\r'); | |
| 14565 m = t - soap->msgbuf + 1 - flag; | |
| 14566 t = soap->msgbuf; | |
| 14567 c = '\r'; | |
| 14568 } | |
| 14569 *s++ = (char)c; | |
| 14570 } | |
| 14571 } | |
| 14572 if (content->ptr && soap->fmimewrite) | |
| 14573 { if ((soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i))) | |
| 14574 break; | |
| 14575 } | |
| 14576 } | |
| 14577 end: | |
| 14578 *s = '\0'; /* make 0-terminated */ | |
| 14579 if (content->ptr) | |
| 14580 { if (!soap->error && soap->fmimewrite) | |
| 14581 soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i); | |
| 14582 if (soap->fmimewriteclose) | |
| 14583 soap->fmimewriteclose(soap, (void*)content->ptr); | |
| 14584 if (soap->error) | |
| 14585 return NULL; | |
| 14586 } | |
| 14587 else | |
| 14588 { content->size = soap_size_block(soap, NULL, i+1) - 1; /* last block with '\0' */ | |
| 14589 content->ptr = soap_save_block(soap, NULL, NULL, 0); | |
| 14590 } | |
| 14591 soap_resolve_attachment(soap, content); | |
| 14592 if (c == '-' && soap_getchar(soap) == '-') | |
| 14593 { soap->mode &= ~SOAP_ENC_MIME; | |
| 14594 if ((soap->mode & SOAP_MIME_POSTCHECK) && soap_end_recv(soap)) | |
| 14595 { if (soap->keep_alive < 0) | |
| 14596 soap->keep_alive = 0; | |
| 14597 soap_closesock(soap); | |
| 14598 return NULL; | |
| 14599 } | |
| 14600 } | |
| 14601 else | |
| 14602 { while (c != '\r' && (int)c != EOF && soap_blank(c)) | |
| 14603 c = soap_getchar(soap); | |
| 14604 if (c != '\r' || soap_getchar(soap) != '\n') | |
| 14605 { soap->error = SOAP_MIME_ERROR; | |
| 14606 return NULL; | |
| 14607 } | |
| 14608 if (soap_getmimehdr(soap)) | |
| 14609 return NULL; | |
| 14610 } | |
| 14611 return content; | |
| 14612 } | |
| 14613 #endif | |
| 14614 #endif | |
| 14615 | |
| 14616 /******************************************************************************/ | |
| 14617 #ifndef WITH_LEANER | |
| 14618 #ifndef PALM_1 | |
| 14619 SOAP_FMAC1 | |
| 14620 int | |
| 14621 SOAP_FMAC2 | |
| 14622 soap_match_cid(struct soap *soap, const char *s, const char *t) | |
| 14623 { register size_t n; | |
| 14624 if (!s) | |
| 14625 return 1; | |
| 14626 if (!strcmp(s, t)) | |
| 14627 return 0; | |
| 14628 if (!strncmp(s, "cid:", 4)) | |
| 14629 s += 4; | |
| 14630 n = strlen(t); | |
| 14631 if (*t == '<') | |
| 14632 { t++; | |
| 14633 n -= 2; | |
| 14634 } | |
| 14635 if (!strncmp(s, t, n) && !s[n]) | |
| 14636 return 0; | |
| 14637 soap_decode(soap->tmpbuf, sizeof(soap->tmpbuf), s, SOAP_STR_EOS); | |
| 14638 if (!strncmp(soap->tmpbuf, t, n) && !soap->tmpbuf[n]) | |
| 14639 return 0; | |
| 14640 return 1; | |
| 14641 } | |
| 14642 #endif | |
| 14643 #endif | |
| 14644 | |
| 14645 /******************************************************************************/ | |
| 14646 #ifndef WITH_LEANER | |
| 14647 #ifndef PALM_1 | |
| 14648 static void | |
| 14649 soap_resolve_attachment(struct soap *soap, struct soap_multipart *content) | |
| 14650 { if (content->id) | |
| 14651 { register struct soap_xlist **xp = &soap->xlist; | |
| 14652 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving attachment data for id='%s'\n", content->id)); | |
| 14653 while (*xp) | |
| 14654 { register struct soap_xlist *xq = *xp; | |
| 14655 if (!soap_match_cid(soap, xq->id, content->id)) | |
| 14656 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Found matching attachment id='%s' for content id='%s'\n", xq->id, content->id)); | |
| 14657 *xp = xq->next; | |
| 14658 *xq->ptr = (unsigned char*)content->ptr; | |
| 14659 *xq->size = (int)content->size; | |
| 14660 *xq->type = (char*)content->type; | |
| 14661 if (content->options) | |
| 14662 *xq->options = (char*)content->options; | |
| 14663 else | |
| 14664 *xq->options = (char*)content->description; | |
| 14665 SOAP_FREE(soap, xq); | |
| 14666 } | |
| 14667 else | |
| 14668 xp = &(*xp)->next; | |
| 14669 } | |
| 14670 } | |
| 14671 } | |
| 14672 #endif | |
| 14673 #endif | |
| 14674 | |
| 14675 /******************************************************************************/ | |
| 14676 #ifndef WITH_LEANER | |
| 14677 #ifndef PALM_1 | |
| 14678 SOAP_FMAC1 | |
| 14679 int | |
| 14680 SOAP_FMAC2 | |
| 14681 soap_putmimehdr(struct soap *soap, struct soap_multipart *content) | |
| 14682 { const char *s; | |
| 14683 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "MIME attachment type='%s'\n", content->type ? content->type : SOAP_STR_EOS)); | |
| 14684 if (soap_send3(soap, "\r\n--", soap->mime.boundary, "\r\n")) | |
| 14685 return soap->error; | |
| 14686 if (content->type && soap_send3(soap, "Content-Type: ", content->type, "\r\n")) | |
| 14687 return soap->error; | |
| 14688 s = soap_code_str(mime_codes, content->encoding); | |
| 14689 if (s && soap_send3(soap, "Content-Transfer-Encoding: ", s, "\r\n")) | |
| 14690 return soap->error; | |
| 14691 if (content->id && soap_send3(soap, "Content-ID: ", content->id, "\r\n")) | |
| 14692 return soap->error; | |
| 14693 if (content->location && soap_send3(soap, "Content-Location: ", content->location, "\r\n")) | |
| 14694 return soap->error; | |
| 14695 if (content->description && soap_send3(soap, "Content-Description: ", content->description, "\r\n")) | |
| 14696 return soap->error; | |
| 14697 return soap_send_raw(soap, "\r\n", 2); | |
| 14698 } | |
| 14699 #endif | |
| 14700 #endif | |
| 14701 | |
| 14702 /******************************************************************************/ | |
| 14703 #ifndef WITH_LEANER | |
| 14704 #ifndef PALM_1 | |
| 14705 SOAP_FMAC1 | |
| 14706 int | |
| 14707 SOAP_FMAC2 | |
| 14708 soap_putmime(struct soap *soap) | |
| 14709 { struct soap_multipart *content; | |
| 14710 if (!(soap->mode & SOAP_ENC_MIME) || !soap->mime.boundary) | |
| 14711 return SOAP_OK; | |
| 14712 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending MIME attachments\n")); | |
| 14713 for (content = soap->mime.first; content; content = content->next) | |
| 14714 { void *handle; | |
| 14715 if (soap->fmimereadopen && ((handle = soap->fmimereadopen(soap, (void*)content->ptr, content->id, content->type, content->description)) || soap->error)) | |
| 14716 { size_t size = content->size; | |
| 14717 if (!handle) | |
| 14718 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimereadopen failed\n")); | |
| 14719 return soap->error; | |
| 14720 } | |
| 14721 if (soap_putmimehdr(soap, content)) | |
| 14722 return soap->error; | |
| 14723 if (!size) | |
| 14724 { if ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE) | |
| 14725 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming MIME\n")); | |
| 14726 do | |
| 14727 { size = soap->fmimeread(soap, handle, soap->tmpbuf, sizeof(soap->tmpbuf)); | |
| 14728 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread returned %lu bytes\n", (unsigned long)size)); | |
| 14729 if (soap_send_raw(soap, soap->tmpbuf, size)) | |
| 14730 break; | |
| 14731 } while (size); | |
| 14732 } | |
| 14733 else | |
| 14734 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error: cannot chunk streaming MIME (no HTTP chunking)\n")); | |
| 14735 } | |
| 14736 } | |
| 14737 else | |
| 14738 { do | |
| 14739 { size_t bufsize; | |
| 14740 if (size < sizeof(soap->tmpbuf)) | |
| 14741 bufsize = size; | |
| 14742 else | |
| 14743 bufsize = sizeof(soap->tmpbuf); | |
| 14744 if (!(bufsize = soap->fmimeread(soap, handle, soap->tmpbuf, bufsize))) | |
| 14745 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size)); | |
| 14746 soap->error = SOAP_EOF; | |
| 14747 break; | |
| 14748 } | |
| 14749 if (soap_send_raw(soap, soap->tmpbuf, bufsize)) | |
| 14750 break; | |
| 14751 size -= bufsize; | |
| 14752 } while (size); | |
| 14753 } | |
| 14754 if (soap->fmimereadclose) | |
| 14755 soap->fmimereadclose(soap, handle); | |
| 14756 } | |
| 14757 else | |
| 14758 { if (soap_putmimehdr(soap, content) | |
| 14759 || soap_send_raw(soap, content->ptr, content->size)) | |
| 14760 return soap->error; | |
| 14761 } | |
| 14762 } | |
| 14763 return soap_send3(soap, "\r\n--", soap->mime.boundary, "--"); | |
| 14764 } | |
| 14765 #endif | |
| 14766 #endif | |
| 14767 | |
| 14768 /******************************************************************************/ | |
| 14769 #ifndef WITH_LEANER | |
| 14770 #ifndef PALM_1 | |
| 14771 SOAP_FMAC1 | |
| 14772 void | |
| 14773 SOAP_FMAC2 | |
| 14774 soap_set_dime(struct soap *soap) | |
| 14775 { soap->omode |= SOAP_ENC_DIME; | |
| 14776 soap->dime.first = NULL; | |
| 14777 soap->dime.last = NULL; | |
| 14778 } | |
| 14779 #endif | |
| 14780 #endif | |
| 14781 | |
| 14782 /******************************************************************************/ | |
| 14783 #ifndef WITH_LEANER | |
| 14784 #ifndef PALM_1 | |
| 14785 SOAP_FMAC1 | |
| 14786 void | |
| 14787 SOAP_FMAC2 | |
| 14788 soap_set_mime(struct soap *soap, const char *boundary, const char *start) | |
| 14789 { soap->omode |= SOAP_ENC_MIME; | |
| 14790 soap->mime.first = NULL; | |
| 14791 soap->mime.last = NULL; | |
| 14792 soap->mime.boundary = soap_strdup(soap, boundary); | |
| 14793 soap->mime.start = soap_strdup(soap, start); | |
| 14794 } | |
| 14795 #endif | |
| 14796 #endif | |
| 14797 | |
| 14798 /******************************************************************************/ | |
| 14799 #ifndef WITH_LEANER | |
| 14800 #ifndef PALM_1 | |
| 14801 SOAP_FMAC1 | |
| 14802 void | |
| 14803 SOAP_FMAC2 | |
| 14804 soap_clr_dime(struct soap *soap) | |
| 14805 { soap->omode &= ~SOAP_ENC_DIME; | |
| 14806 soap->dime.first = NULL; | |
| 14807 soap->dime.last = NULL; | |
| 14808 } | |
| 14809 #endif | |
| 14810 #endif | |
| 14811 | |
| 14812 /******************************************************************************/ | |
| 14813 #ifndef WITH_LEANER | |
| 14814 #ifndef PALM_1 | |
| 14815 SOAP_FMAC1 | |
| 14816 void | |
| 14817 SOAP_FMAC2 | |
| 14818 soap_clr_mime(struct soap *soap) | |
| 14819 { soap->omode &= ~SOAP_ENC_MIME; | |
| 14820 soap->mime.first = NULL; | |
| 14821 soap->mime.last = NULL; | |
| 14822 soap->mime.boundary = NULL; | |
| 14823 soap->mime.start = NULL; | |
| 14824 } | |
| 14825 #endif | |
| 14826 #endif | |
| 14827 | |
| 14828 /******************************************************************************/ | |
| 14829 #ifndef WITH_LEANER | |
| 14830 #ifndef PALM_1 | |
| 14831 static struct soap_multipart* | |
| 14832 soap_new_multipart(struct soap *soap, struct soap_multipart **first, struct soap_multipart **last, char *ptr, size_t size) | |
| 14833 { struct soap_multipart *content; | |
| 14834 content = (struct soap_multipart*)soap_malloc(soap, sizeof(struct soap_multipart)); | |
| 14835 if (content) | |
| 14836 { content->next = NULL; | |
| 14837 content->ptr = ptr; | |
| 14838 content->size = size; | |
| 14839 content->id = NULL; | |
| 14840 content->type = NULL; | |
| 14841 content->options = NULL; | |
| 14842 content->encoding = SOAP_MIME_NONE; | |
| 14843 content->location = NULL; | |
| 14844 content->description = NULL; | |
| 14845 if (!*first) | |
| 14846 *first = content; | |
| 14847 if (*last) | |
| 14848 (*last)->next = content; | |
| 14849 *last = content; | |
| 14850 } | |
| 14851 return content; | |
| 14852 } | |
| 14853 #endif | |
| 14854 #endif | |
| 14855 | |
| 14856 /******************************************************************************/ | |
| 14857 #ifndef WITH_LEANER | |
| 14858 #ifndef PALM_1 | |
| 14859 SOAP_FMAC1 | |
| 14860 int | |
| 14861 SOAP_FMAC2 | |
| 14862 soap_set_dime_attachment(struct soap *soap, char *ptr, size_t size, const char *type, const char *id, unsigned short optype, const char *option) | |
| 14863 { struct soap_multipart *content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, ptr, size); | |
| 14864 if (!content) | |
| 14865 return SOAP_EOM; | |
| 14866 content->id = soap_strdup(soap, id); | |
| 14867 content->type = soap_strdup(soap, type); | |
| 14868 content->options = soap_dime_option(soap, optype, option); | |
| 14869 return SOAP_OK; | |
| 14870 } | |
| 14871 #endif | |
| 14872 #endif | |
| 14873 | |
| 14874 /******************************************************************************/ | |
| 14875 #ifndef WITH_LEANER | |
| 14876 #ifndef PALM_1 | |
| 14877 SOAP_FMAC1 | |
| 14878 int | |
| 14879 SOAP_FMAC2 | |
| 14880 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) | |
| 14881 { struct soap_multipart *content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, ptr, size); | |
| 14882 if (!content) | |
| 14883 return SOAP_EOM; | |
| 14884 content->id = soap_strdup(soap, id); | |
| 14885 content->type = soap_strdup(soap, type); | |
| 14886 content->encoding = encoding; | |
| 14887 content->location = soap_strdup(soap, location); | |
| 14888 content->description = soap_strdup(soap, description); | |
| 14889 return SOAP_OK; | |
| 14890 } | |
| 14891 #endif | |
| 14892 #endif | |
| 14893 | |
| 14894 /******************************************************************************/ | |
| 14895 #ifndef WITH_LEANER | |
| 14896 #ifndef PALM_1 | |
| 14897 SOAP_FMAC1 | |
| 14898 struct soap_multipart* | |
| 14899 SOAP_FMAC2 | |
| 14900 soap_next_multipart(struct soap_multipart *content) | |
| 14901 { if (content) | |
| 14902 return content->next; | |
| 14903 return NULL; | |
| 14904 } | |
| 14905 #endif | |
| 14906 #endif | |
| 14907 | |
| 14908 /******************************************************************************/ | |
| 14909 #ifndef WITH_LEANER | |
| 14910 #ifndef PALM_1 | |
| 14911 static void | |
| 14912 soap_select_mime_boundary(struct soap *soap) | |
| 14913 { while (!soap->mime.boundary || soap_valid_mime_boundary(soap)) | |
| 14914 { register char *s = soap->mime.boundary; | |
| 14915 register size_t n = 0; | |
| 14916 if (s) | |
| 14917 n = strlen(s); | |
| 14918 if (n < 16) | |
| 14919 { n = 64; | |
| 14920 s = soap->mime.boundary = (char*)soap_malloc(soap, n + 1); | |
| 14921 if (!s) | |
| 14922 return; | |
| 14923 } | |
| 14924 strcpy(s, "=="); | |
| 14925 s += 2; | |
| 14926 n -= 4; | |
| 14927 while (n) | |
| 14928 { *s++ = soap_base64o[soap_random & 0x3F]; | |
| 14929 n--; | |
| 14930 } | |
| 14931 strcpy(s, "=="); | |
| 14932 } | |
| 14933 if (!soap->mime.start) | |
| 14934 soap->mime.start = "<SOAP-ENV:Envelope>"; | |
| 14935 } | |
| 14936 #endif | |
| 14937 #endif | |
| 14938 | |
| 14939 /******************************************************************************/ | |
| 14940 #ifndef WITH_LEANER | |
| 14941 #ifndef PALM_1 | |
| 14942 static int | |
| 14943 soap_valid_mime_boundary(struct soap *soap) | |
| 14944 { register struct soap_multipart *content; | |
| 14945 register size_t k; | |
| 14946 if (soap->fmimeread) | |
| 14947 return SOAP_OK; | |
| 14948 k = strlen(soap->mime.boundary); | |
| 14949 for (content = soap->mime.first; content; content = content->next) | |
| 14950 { if (content->ptr && content->size >= k) | |
| 14951 { register const char *p = (const char*)content->ptr; | |
| 14952 register size_t i; | |
| 14953 for (i = 0; i < content->size - k; i++, p++) | |
| 14954 { if (!strncmp(p, soap->mime.boundary, k)) | |
| 14955 return SOAP_ERR; | |
| 14956 } | |
| 14957 } | |
| 14958 } | |
| 14959 return SOAP_OK; | |
| 14960 } | |
| 14961 #endif | |
| 14962 #endif | |
| 14963 | |
| 14964 /******************************************************************************/ | |
| 14965 #ifdef WITH_GZIP | |
| 14966 #ifndef PALM_1 | |
| 14967 static int | |
| 14968 soap_getgziphdr(struct soap *soap) | |
| 14969 { int i; | |
| 14970 soap_wchar c = 0, f = 0; | |
| 14971 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get gzip header\n")); | |
| 14972 for (i = 0; i < 9; i++) | |
| 14973 { if ((int)(c = soap_get1(soap) == EOF)) | |
| 14974 return soap->error = SOAP_ZLIB_ERROR; | |
| 14975 if (i == 1 && c == 8) | |
| 14976 soap->z_dict = 0; | |
| 14977 if (i == 2) | |
| 14978 f = c; | |
| 14979 } | |
| 14980 if (f & 0x04) /* FEXTRA */ | |
| 14981 { for (i = soap_get1(soap) | (soap_get1(soap) << 8); i; i--) | |
| 14982 { if ((int)soap_get1(soap) == EOF) | |
| 14983 return soap->error = SOAP_ZLIB_ERROR; | |
| 14984 } | |
| 14985 } | |
| 14986 if (f & 0x08) /* skip FNAME */ | |
| 14987 { do | |
| 14988 c = soap_get1(soap); | |
| 14989 while (c && (int)c != EOF); | |
| 14990 } | |
| 14991 if ((int)c != EOF && (f & 0x10)) /* skip FCOMMENT */ | |
| 14992 { do | |
| 14993 c = soap_get1(soap); | |
| 14994 while (c && (int)c != EOF); | |
| 14995 } | |
| 14996 if ((int)c != EOF && (f & 0x02)) /* skip FHCRC (CRC32 is used) */ | |
| 14997 { if ((int)(c = soap_get1(soap)) != EOF) | |
| 14998 c = soap_get1(soap); | |
| 14999 } | |
| 15000 if ((int)c == EOF) | |
| 15001 return soap->error = SOAP_ZLIB_ERROR; | |
| 15002 return SOAP_OK; | |
| 15003 } | |
| 15004 #endif | |
| 15005 #endif | |
| 15006 | |
| 15007 /******************************************************************************/ | |
| 15008 #ifndef PALM_1 | |
| 15009 SOAP_FMAC1 | |
| 15010 int | |
| 15011 SOAP_FMAC2 | |
| 15012 soap_begin_serve(struct soap *soap) | |
| 15013 { | |
| 15014 #ifdef WITH_FASTCGI | |
| 15015 if (FCGI_Accept() < 0) | |
| 15016 { soap->error = SOAP_EOF; | |
| 15017 return soap_send_fault(soap); | |
| 15018 } | |
| 15019 #endif | |
| 15020 soap_begin(soap); | |
| 15021 if (soap_begin_recv(soap) | |
| 15022 || soap_envelope_begin_in(soap) | |
| 15023 || soap_recv_header(soap) | |
| 15024 || soap_body_begin_in(soap)) | |
| 15025 { if (soap->error < SOAP_STOP) | |
| 15026 { | |
| 15027 #ifdef WITH_FASTCGI | |
| 15028 soap_send_fault(soap); | |
| 15029 #else | |
| 15030 return soap_send_fault(soap); | |
| 15031 #endif | |
| 15032 } | |
| 15033 return soap_closesock(soap); | |
| 15034 } | |
| 15035 return SOAP_OK; | |
| 15036 } | |
| 15037 #endif | |
| 15038 | |
| 15039 /******************************************************************************/ | |
| 15040 #ifndef PALM_1 | |
| 15041 SOAP_FMAC1 | |
| 15042 int | |
| 15043 SOAP_FMAC2 | |
| 15044 soap_begin_recv(struct soap *soap) | |
| 15045 { register soap_wchar c; | |
| 15046 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing for input from socket=%d/fd=%d\n", soap->socket, soap->recvfd)); | |
| 15047 soap->error = SOAP_OK; | |
| 15048 soap->filterstop = SOAP_OK; | |
| 15049 soap_free_temp(soap); | |
| 15050 soap_set_local_namespaces(soap); | |
| 15051 soap->version = 0; /* don't assume we're parsing SOAP content by default */ | |
| 15052 #ifndef WITH_NOIDREF | |
| 15053 soap_free_iht(soap); | |
| 15054 #endif | |
| 15055 if ((soap->imode & SOAP_IO) == SOAP_IO_CHUNK) | |
| 15056 soap->omode |= SOAP_IO_CHUNK; | |
| 15057 soap->imode &= ~(SOAP_IO | SOAP_ENC_MIME); | |
| 15058 soap->mode = soap->imode; | |
| 15059 if (!soap->keep_alive) | |
| 15060 { soap->buflen = 0; | |
| 15061 soap->bufidx = 0; | |
| 15062 } | |
| 15063 if (!(soap->mode & SOAP_IO_KEEPALIVE)) | |
| 15064 soap->keep_alive = 0; | |
| 15065 soap->ahead = 0; | |
| 15066 soap->peeked = 0; | |
| 15067 soap->level = 0; | |
| 15068 soap->part = SOAP_BEGIN; | |
| 15069 soap->alloced = 0; | |
| 15070 soap->body = 1; | |
| 15071 soap->count = 0; | |
| 15072 soap->length = 0; | |
| 15073 soap->cdata = 0; | |
| 15074 *soap->endpoint = '\0'; | |
| 15075 soap->action = NULL; | |
| 15076 soap->header = NULL; | |
| 15077 soap->fault = NULL; | |
| 15078 soap->status = 0; | |
| 15079 soap->fform = NULL; | |
| 15080 #ifndef WITH_LEANER | |
| 15081 soap->dom = NULL; | |
| 15082 soap->dime.chunksize = 0; | |
| 15083 soap->dime.buflen = 0; | |
| 15084 soap->dime.list = NULL; | |
| 15085 soap->dime.first = NULL; | |
| 15086 soap->dime.last = NULL; | |
| 15087 soap->mime.list = NULL; | |
| 15088 soap->mime.first = NULL; | |
| 15089 soap->mime.last = NULL; | |
| 15090 soap->mime.boundary = NULL; | |
| 15091 soap->mime.start = NULL; | |
| 15092 #endif | |
| 15093 #ifdef WIN32 | |
| 15094 #ifndef UNDER_CE | |
| 15095 #ifndef WITH_FASTCGI | |
| 15096 if (!soap_valid_socket(soap->socket) && !soap->is) /* Set win32 stdout or soap->sendfd to BINARY, e.g. to support DIME */ | |
| 15097 #ifdef __BORLANDC__ | |
| 15098 setmode(soap->recvfd, _O_BINARY); | |
| 15099 #else | |
| 15100 _setmode(soap->recvfd, _O_BINARY); | |
| 15101 #endif | |
| 15102 #endif | |
| 15103 #endif | |
| 15104 #endif | |
| 15105 #ifdef WITH_ZLIB | |
| 15106 soap->mode &= ~SOAP_ENC_ZLIB; | |
| 15107 soap->zlib_in = SOAP_ZLIB_NONE; | |
| 15108 soap->zlib_out = SOAP_ZLIB_NONE; | |
| 15109 soap->d_stream->next_in = Z_NULL; | |
| 15110 soap->d_stream->avail_in = 0; | |
| 15111 soap->d_stream->next_out = (Byte*)soap->buf; | |
| 15112 soap->d_stream->avail_out = SOAP_BUFLEN; | |
| 15113 soap->z_ratio_in = 1.0; | |
| 15114 #endif | |
| 15115 #ifdef WITH_OPENSSL | |
| 15116 if (soap->ssl) | |
| 15117 ERR_clear_error(); | |
| 15118 #endif | |
| 15119 #ifndef WITH_LEANER | |
| 15120 if (soap->fprepareinitrecv && (soap->error = soap->fprepareinitrecv(soap))) | |
| 15121 return soap->error; | |
| 15122 #endif | |
| 15123 c = soap_getchar(soap); | |
| 15124 #ifdef WITH_GZIP | |
| 15125 if (c == 0x1F) | |
| 15126 { if (soap_getgziphdr(soap)) | |
| 15127 return soap->error; | |
| 15128 if (inflateInit2(soap->d_stream, -MAX_WBITS) != Z_OK) | |
| 15129 return soap->error = SOAP_ZLIB_ERROR; | |
| 15130 if (soap->z_dict) | |
| 15131 { if (inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len) != Z_OK) | |
| 15132 return soap->error = SOAP_ZLIB_ERROR; | |
| 15133 } | |
| 15134 soap->zlib_state = SOAP_ZLIB_INFLATE; | |
| 15135 soap->mode |= SOAP_ENC_ZLIB; | |
| 15136 soap->zlib_in = SOAP_ZLIB_GZIP; | |
| 15137 soap->z_crc = crc32(0L, NULL, 0); | |
| 15138 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n")); | |
| 15139 if (!soap->z_buf) | |
| 15140 soap->z_buf = (char*)SOAP_MALLOC(soap, SOAP_BUFLEN); | |
| 15141 memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); | |
| 15142 /* should not chunk over plain transport, so why bother to check? */ | |
| 15143 /* if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) */ | |
| 15144 /* soap->z_buflen = soap->bufidx; */ | |
| 15145 /* else */ | |
| 15146 soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx); | |
| 15147 soap->d_stream->avail_in = (unsigned int)(soap->buflen - soap->bufidx); | |
| 15148 soap->z_buflen = soap->buflen; | |
| 15149 soap->buflen = soap->bufidx; | |
| 15150 c = ' '; | |
| 15151 } | |
| 15152 #endif | |
| 15153 while (soap_blank(c)) | |
| 15154 c = soap_getchar(soap); | |
| 15155 #ifndef WITH_LEANER | |
| 15156 if (c == '-' && soap_get0(soap) == '-') | |
| 15157 soap->mode |= SOAP_ENC_MIME; | |
| 15158 else if ((c & 0xFFFC) == (SOAP_DIME_VERSION | SOAP_DIME_MB) && (soap_get0(soap) & 0xFFF0) == 0x20) | |
| 15159 soap->mode |= SOAP_ENC_DIME; | |
| 15160 else | |
| 15161 #endif | |
| 15162 { /* skip BOM */ | |
| 15163 if (c == 0xEF && soap_get0(soap) == 0xBB) | |
| 15164 { c = soap_get1(soap); | |
| 15165 if ((c = soap_get1(soap)) == 0xBF) | |
| 15166 { soap->mode &= ~SOAP_ENC_LATIN; | |
| 15167 c = soap_getchar(soap); | |
| 15168 } | |
| 15169 else | |
| 15170 c = (0x0F << 12) | (0xBB << 6) | (c & 0x3F); /* UTF-8 */ | |
| 15171 } | |
| 15172 else if ((c == 0xFE && soap_get0(soap) == 0xFF) /* UTF-16 BE */ | |
| 15173 || (c == 0xFF && soap_get0(soap) == 0xFE)) /* UTF-16 LE */ | |
| 15174 return soap->error = SOAP_UTF_ERROR; | |
| 15175 /* skip space */ | |
| 15176 while (soap_blank(c)) | |
| 15177 c = soap_getchar(soap); | |
| 15178 } | |
| 15179 if ((int)c == EOF) | |
| 15180 return soap->error = SOAP_CHK_EOF; | |
| 15181 soap_unget(soap, c); | |
| 15182 #ifndef WITH_NOHTTP | |
| 15183 /* if not XML/MIME/DIME/ZLIB, assume HTTP method or status line */ | |
| 15184 if (((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) && !(soap->mode & (SOAP_ENC_MIME | SOAP_ENC_DIME | SOAP_ENC_ZLIB | SOAP_ENC_XML))) | |
| 15185 { soap_mode m = soap->imode; | |
| 15186 soap->mode &= ~SOAP_IO; | |
| 15187 soap->error = soap->fparse(soap); | |
| 15188 if (soap->error && soap->error < SOAP_STOP) | |
| 15189 { soap->keep_alive = 0; /* force close later */ | |
| 15190 return soap->error; | |
| 15191 } | |
| 15192 if (soap->error == SOAP_STOP) | |
| 15193 { if (soap->fform) | |
| 15194 { soap->error = soap->fform(soap); | |
| 15195 if (soap->error == SOAP_OK) | |
| 15196 soap->error = SOAP_STOP; /* prevents further processing */ | |
| 15197 } | |
| 15198 return soap->error; | |
| 15199 } | |
| 15200 soap->mode = soap->imode; /* if imode is changed, effectuate */ | |
| 15201 soap->imode = m; /* restore imode */ | |
| 15202 #ifdef WITH_ZLIB | |
| 15203 soap->mode &= ~SOAP_ENC_ZLIB; | |
| 15204 #endif | |
| 15205 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) | |
| 15206 { soap->chunkbuflen = soap->buflen; | |
| 15207 soap->buflen = soap->bufidx; | |
| 15208 soap->chunksize = 0; | |
| 15209 } | |
| 15210 /* Note: fparse should not use soap_unget to push back last char */ | |
| 15211 #if 0 | |
| 15212 if (soap->status > 200 && soap->length == 0 && !(soap->http_content && (!soap->keep_alive || soap->recv_timeout)) && (soap->imode & SOAP_IO) != SOAP_IO_CHUNK) | |
| 15213 #endif | |
| 15214 if (soap->status && !soap->body) | |
| 15215 return soap->error = soap->status; | |
| 15216 #ifdef WITH_ZLIB | |
| 15217 if (soap->zlib_in != SOAP_ZLIB_NONE) | |
| 15218 { | |
| 15219 #ifdef WITH_GZIP | |
| 15220 if (soap->zlib_in != SOAP_ZLIB_DEFLATE) | |
| 15221 { c = soap_get1(soap); | |
| 15222 if (c == (int)EOF) | |
| 15223 return soap->error = SOAP_EOF; | |
| 15224 if (c == 0x1F) | |
| 15225 { if (soap_getgziphdr(soap)) | |
| 15226 return soap->error; | |
| 15227 if (inflateInit2(soap->d_stream, -MAX_WBITS) != Z_OK) | |
| 15228 return soap->error = SOAP_ZLIB_ERROR; | |
| 15229 soap->z_crc = crc32(0L, NULL, 0); | |
| 15230 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n")); | |
| 15231 } | |
| 15232 else | |
| 15233 { soap_revget1(soap); | |
| 15234 if (inflateInit(soap->d_stream) != Z_OK) | |
| 15235 return soap->error = SOAP_ZLIB_ERROR; | |
| 15236 soap->zlib_in = SOAP_ZLIB_DEFLATE; | |
| 15237 } | |
| 15238 } | |
| 15239 else | |
| 15240 #endif | |
| 15241 if (inflateInit(soap->d_stream) != Z_OK) | |
| 15242 return soap->error = SOAP_ZLIB_ERROR; | |
| 15243 if (soap->z_dict) | |
| 15244 { if (inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len) != Z_OK) | |
| 15245 return soap->error = SOAP_ZLIB_ERROR; | |
| 15246 } | |
| 15247 soap->zlib_state = SOAP_ZLIB_INFLATE; | |
| 15248 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate initialized\n")); | |
| 15249 soap->mode |= SOAP_ENC_ZLIB; | |
| 15250 if (!soap->z_buf) | |
| 15251 soap->z_buf = (char*)SOAP_MALLOC(soap, SOAP_BUFLEN); | |
| 15252 memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); | |
| 15253 soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx); | |
| 15254 soap->d_stream->avail_in = (unsigned int)(soap->buflen - soap->bufidx); | |
| 15255 soap->z_buflen = soap->buflen; | |
| 15256 soap->buflen = soap->bufidx; | |
| 15257 } | |
| 15258 #endif | |
| 15259 #ifndef WITH_LEANER | |
| 15260 if (soap->fpreparerecv && (soap->mode & SOAP_IO) != SOAP_IO_CHUNK && soap->buflen > soap->bufidx) | |
| 15261 { int r; | |
| 15262 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Invoking fpreparerecv\n")); | |
| 15263 if ((r = soap->fpreparerecv(soap, soap->buf + soap->bufidx, soap->buflen - soap->bufidx))) | |
| 15264 return soap->error = r; | |
| 15265 } | |
| 15266 #endif | |
| 15267 if (soap_get0(soap) == (int)EOF) | |
| 15268 { if (soap->status == 0 || soap->status == 200) | |
| 15269 return soap->error = SOAP_NO_DATA; /* HTTP OK: always expect data */ | |
| 15270 return soap->error = soap->status; | |
| 15271 } | |
| 15272 if (soap->error) | |
| 15273 { if (soap->error == SOAP_FORM && soap->fform) | |
| 15274 { soap->error = soap->fform(soap); | |
| 15275 if (soap->error == SOAP_OK) | |
| 15276 soap->error = SOAP_STOP; /* prevents further processing */ | |
| 15277 } | |
| 15278 return soap->error; | |
| 15279 } | |
| 15280 } | |
| 15281 #endif | |
| 15282 #ifndef WITH_LEANER | |
| 15283 if (soap->mode & SOAP_ENC_MIME) | |
| 15284 { do /* skip preamble */ | |
| 15285 { if ((int)(c = soap_getchar(soap)) == EOF) | |
| 15286 return soap->error = SOAP_CHK_EOF; | |
| 15287 } while (c != '-' || soap_get0(soap) != '-'); | |
| 15288 soap_unget(soap, c); | |
| 15289 if (soap_getmimehdr(soap)) | |
| 15290 return soap->error; | |
| 15291 if (soap->mime.start) | |
| 15292 { do | |
| 15293 { if (!soap->mime.last->id) | |
| 15294 break; | |
| 15295 if (!soap_match_cid(soap, soap->mime.start, soap->mime.last->id)) | |
| 15296 break; | |
| 15297 } while (soap_get_mime_attachment(soap, NULL)); | |
| 15298 } | |
| 15299 if (soap_get_header_attribute(soap, soap->mime.first->type, "application/dime")) | |
| 15300 soap->mode |= SOAP_ENC_DIME; | |
| 15301 } | |
| 15302 if (soap->mode & SOAP_ENC_DIME) | |
| 15303 { if (soap_getdimehdr(soap)) | |
| 15304 return soap->error; | |
| 15305 if (soap->dime.flags & SOAP_DIME_CF) | |
| 15306 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked DIME SOAP message\n")); | |
| 15307 soap->dime.chunksize = soap->dime.size; | |
| 15308 if (soap->buflen - soap->bufidx >= soap->dime.chunksize) | |
| 15309 { soap->dime.buflen = soap->buflen; | |
| 15310 soap->buflen = soap->bufidx + soap->dime.chunksize; | |
| 15311 } | |
| 15312 else | |
| 15313 soap->dime.chunksize -= soap->buflen - soap->bufidx; | |
| 15314 } | |
| 15315 soap->count = soap->buflen - soap->bufidx; | |
| 15316 } | |
| 15317 #endif | |
| 15318 return SOAP_OK; | |
| 15319 } | |
| 15320 #endif | |
| 15321 | |
| 15322 /******************************************************************************/ | |
| 15323 #ifndef PALM_2 | |
| 15324 SOAP_FMAC1 | |
| 15325 int | |
| 15326 SOAP_FMAC2 | |
| 15327 soap_envelope_begin_out(struct soap *soap) | |
| 15328 { | |
| 15329 #ifndef WITH_LEANER | |
| 15330 size_t n = 0; | |
| 15331 if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && soap->mime.start && strlen(soap->mime.boundary) + strlen(soap->mime.start) < sizeof(soap->tmpbuf) - 80 ) | |
| 15332 { const char *s; | |
| 15333 if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) | |
| 15334 s = "application/dime"; | |
| 15335 else if (soap->version == 2) | |
| 15336 { if (soap->mode & SOAP_ENC_MTOM) | |
| 15337 s = "application/xop+xml; charset=utf-8; type=\"application/soap+xml\""; | |
| 15338 else | |
| 15339 s = "application/soap+xml; charset=utf-8"; | |
| 15340 } | |
| 15341 else if (soap->mode & SOAP_ENC_MTOM) | |
| 15342 s = "application/xop+xml; charset=utf-8; type=\"text/xml\""; | |
| 15343 else | |
| 15344 s = "text/xml; charset=utf-8"; | |
| 15345 #ifdef HAVE_SNPRINTF | |
| 15346 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "--%s\r\nContent-Type: %s\r\nContent-Transfer-Encoding: binary\r\nContent-ID: %s\r\n\r\n", soap->mime.boundary, s, soap->mime.start); | |
| 15347 #else | |
| 15348 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); | |
| 15349 #endif | |
| 15350 n = strlen(soap->tmpbuf); | |
| 15351 if (soap_send_raw(soap, soap->tmpbuf, n)) | |
| 15352 return soap->error; | |
| 15353 } | |
| 15354 if (soap->mode & SOAP_IO_LENGTH) | |
| 15355 soap->dime.size = soap->count; /* DIME in MIME correction */ | |
| 15356 if (!(soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME)) | |
| 15357 { if (soap_putdimehdr(soap)) | |
| 15358 return soap->error; | |
| 15359 } | |
| 15360 #endif | |
| 15361 if (soap->version == 0) | |
| 15362 return SOAP_OK; | |
| 15363 soap->part = SOAP_IN_ENVELOPE; | |
| 15364 return soap_element_begin_out(soap, "SOAP-ENV:Envelope", 0, NULL); | |
| 15365 } | |
| 15366 #endif | |
| 15367 | |
| 15368 /******************************************************************************/ | |
| 15369 #ifndef PALM_2 | |
| 15370 SOAP_FMAC1 | |
| 15371 int | |
| 15372 SOAP_FMAC2 | |
| 15373 soap_envelope_end_out(struct soap *soap) | |
| 15374 { if (soap->version == 0) | |
| 15375 return SOAP_OK; | |
| 15376 if (soap_element_end_out(soap, "SOAP-ENV:Envelope") | |
| 15377 || soap_send_raw(soap, "\r\n", 2)) /* 2.8: always emit \r\n */ | |
| 15378 return soap->error; | |
| 15379 #ifndef WITH_LEANER | |
| 15380 if ((soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) | |
| 15381 { soap->dime.size = soap->count - soap->dime.size; /* DIME in MIME correction */ | |
| 15382 #ifdef HAVE_SNPRINTF | |
| 15383 soap_snprintf(soap->id, sizeof(soap->id), soap->dime_id_format, 0); | |
| 15384 #else | |
| 15385 sprintf(soap->id, soap->dime_id_format, 0); | |
| 15386 #endif | |
| 15387 soap->dime.id = soap->id; | |
| 15388 if (soap->local_namespaces) | |
| 15389 { if (soap->local_namespaces[0].out) | |
| 15390 soap->dime.type = (char*)soap->local_namespaces[0].out; | |
| 15391 else | |
| 15392 soap->dime.type = (char*)soap->local_namespaces[0].ns; | |
| 15393 } | |
| 15394 soap->dime.options = NULL; | |
| 15395 soap->dime.flags = SOAP_DIME_MB | SOAP_DIME_ABSURI; | |
| 15396 if (!soap->dime.first) | |
| 15397 soap->dime.flags |= SOAP_DIME_ME; | |
| 15398 soap->count += 12 + ((strlen(soap->dime.id)+3)&(~3)) + (soap->dime.type ? ((strlen(soap->dime.type)+3)&(~3)) : 0); | |
| 15399 } | |
| 15400 if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) | |
| 15401 return soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3); | |
| 15402 #endif | |
| 15403 soap->part = SOAP_END_ENVELOPE; | |
| 15404 return SOAP_OK; | |
| 15405 } | |
| 15406 #endif | |
| 15407 | |
| 15408 /******************************************************************************/ | |
| 15409 #ifndef WITH_LEAN | |
| 15410 #ifndef PALM_1 | |
| 15411 SOAP_FMAC1 | |
| 15412 char* | |
| 15413 SOAP_FMAC2 | |
| 15414 soap_get_http_body(struct soap *soap, size_t *len) | |
| 15415 { if (len) | |
| 15416 *len = 0; | |
| 15417 #ifndef WITH_LEAN | |
| 15418 register size_t l = 0, n = 0; | |
| 15419 register char *s; | |
| 15420 /* get HTTP body length */ | |
| 15421 if (!(soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) != SOAP_IO_CHUNK) | |
| 15422 { n = soap->length; | |
| 15423 if (!n) | |
| 15424 return NULL; | |
| 15425 } | |
| 15426 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Parsing HTTP body (mode=0x%x,len=%lu)\n", soap->mode, (unsigned long)n)); | |
| 15427 #ifdef WITH_FAST | |
| 15428 soap->labidx = 0; /* use look-aside buffer */ | |
| 15429 #else | |
| 15430 if (soap_new_block(soap) == NULL) | |
| 15431 return NULL; | |
| 15432 #endif | |
| 15433 for (;;) | |
| 15434 { | |
| 15435 #ifdef WITH_FAST | |
| 15436 register size_t i, k; | |
| 15437 if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */ | |
| 15438 return NULL; | |
| 15439 s = soap->labbuf + soap->labidx; /* space to populate */ | |
| 15440 k = soap->lablen - soap->labidx; /* number of bytes available */ | |
| 15441 soap->labidx = soap->lablen; /* claim this space */ | |
| 15442 #else | |
| 15443 register size_t i, k = SOAP_BLKLEN; | |
| 15444 if (!(s = (char*)soap_push_block(soap, NULL, k))) | |
| 15445 return NULL; | |
| 15446 #endif | |
| 15447 for (i = 0; i < k; i++) | |
| 15448 { register soap_wchar c; | |
| 15449 l++; | |
| 15450 if (n > 0 && l > n) | |
| 15451 goto end; | |
| 15452 c = soap_get1(soap); | |
| 15453 if ((int)c == EOF) | |
| 15454 goto end; | |
| 15455 *s++ = (char)(c & 0xFF); | |
| 15456 } | |
| 15457 } | |
| 15458 end: | |
| 15459 *s = '\0'; | |
| 15460 if (len) | |
| 15461 *len = l - 1; /* len excludes terminating \0 */ | |
| 15462 #ifdef WITH_FAST | |
| 15463 if ((s = (char*)soap_malloc(soap, l))) | |
| 15464 memcpy(s, soap->labbuf, l); | |
| 15465 #else | |
| 15466 soap_size_block(soap, NULL, i+1); | |
| 15467 s = soap_save_block(soap, NULL, 0); | |
| 15468 #endif | |
| 15469 return s; | |
| 15470 #else | |
| 15471 return NULL; | |
| 15472 #endif | |
| 15473 } | |
| 15474 #endif | |
| 15475 #endif | |
| 15476 | |
| 15477 /******************************************************************************/ | |
| 15478 #ifndef PALM_1 | |
| 15479 SOAP_FMAC1 | |
| 15480 int | |
| 15481 SOAP_FMAC2 | |
| 15482 soap_envelope_begin_in(struct soap *soap) | |
| 15483 { register struct Namespace *p; | |
| 15484 soap->part = SOAP_IN_ENVELOPE; | |
| 15485 if (soap_element_begin_in(soap, "SOAP-ENV:Envelope", 0, NULL)) | |
| 15486 { if (soap->error == SOAP_TAG_MISMATCH) | |
| 15487 { if (!soap_element_begin_in(soap, "Envelope", 0, NULL)) | |
| 15488 soap->error = SOAP_VERSIONMISMATCH; | |
| 15489 else if (soap->status == 0 || (soap->status >= 200 && soap->status <= 299)) | |
| 15490 return SOAP_OK; /* allow non-SOAP XML content to be captured */ | |
| 15491 soap->error = soap->status; | |
| 15492 } | |
| 15493 else if (soap->status) | |
| 15494 soap->error = soap->status; | |
| 15495 return soap->error; | |
| 15496 } | |
| 15497 p = soap->local_namespaces; | |
| 15498 if (p) | |
| 15499 { const char *ns = p[0].out; | |
| 15500 if (!ns) | |
| 15501 ns = p[0].ns; | |
| 15502 if (!strcmp(ns, soap_env1)) | |
| 15503 { soap->version = 1; /* make sure we use SOAP 1.1 */ | |
| 15504 if (p[1].out) | |
| 15505 SOAP_FREE(soap, p[1].out); | |
| 15506 if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc1)))) | |
| 15507 strcpy(p[1].out, soap_enc1); | |
| 15508 } | |
| 15509 else if (!strcmp(ns, soap_env2)) | |
| 15510 { soap->version = 2; /* make sure we use SOAP 1.2 */ | |
| 15511 if (p[1].out) | |
| 15512 SOAP_FREE(soap, p[1].out); | |
| 15513 if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc2)))) | |
| 15514 strcpy(p[1].out, soap_enc2); | |
| 15515 } | |
| 15516 } | |
| 15517 return SOAP_OK; | |
| 15518 } | |
| 15519 #endif | |
| 15520 | |
| 15521 /******************************************************************************/ | |
| 15522 #ifndef PALM_1 | |
| 15523 SOAP_FMAC1 | |
| 15524 int | |
| 15525 SOAP_FMAC2 | |
| 15526 soap_envelope_end_in(struct soap *soap) | |
| 15527 { if (soap->version == 0) | |
| 15528 return SOAP_OK; | |
| 15529 soap->part = SOAP_END_ENVELOPE; | |
| 15530 return soap_element_end_in(soap, "SOAP-ENV:Envelope"); | |
| 15531 } | |
| 15532 #endif | |
| 15533 | |
| 15534 /******************************************************************************/ | |
| 15535 #ifndef PALM_2 | |
| 15536 SOAP_FMAC1 | |
| 15537 int | |
| 15538 SOAP_FMAC2 | |
| 15539 soap_body_begin_out(struct soap *soap) | |
| 15540 { if (soap->version == 1) | |
| 15541 soap->encoding = 1; | |
| 15542 #ifndef WITH_LEAN | |
| 15543 if ((soap->mode & SOAP_SEC_WSUID) && soap_set_attr(soap, "wsu:Id", "Body", 1)) | |
| 15544 return soap->error; | |
| 15545 #endif | |
| 15546 if (soap->version == 0) | |
| 15547 return SOAP_OK; | |
| 15548 soap->part = SOAP_IN_BODY; | |
| 15549 return soap_element_begin_out(soap, "SOAP-ENV:Body", 0, NULL); | |
| 15550 } | |
| 15551 #endif | |
| 15552 | |
| 15553 /******************************************************************************/ | |
| 15554 #ifndef PALM_2 | |
| 15555 SOAP_FMAC1 | |
| 15556 int | |
| 15557 SOAP_FMAC2 | |
| 15558 soap_body_end_out(struct soap *soap) | |
| 15559 { if (soap->version == 0) | |
| 15560 return SOAP_OK; | |
| 15561 if (soap_element_end_out(soap, "SOAP-ENV:Body")) | |
| 15562 return soap->error; | |
| 15563 soap->part = SOAP_END_BODY; | |
| 15564 return SOAP_OK; | |
| 15565 } | |
| 15566 #endif | |
| 15567 | |
| 15568 /******************************************************************************/ | |
| 15569 #ifndef PALM_2 | |
| 15570 SOAP_FMAC1 | |
| 15571 int | |
| 15572 SOAP_FMAC2 | |
| 15573 soap_body_begin_in(struct soap *soap) | |
| 15574 { if (soap->version == 0) | |
| 15575 return SOAP_OK; | |
| 15576 soap->part = SOAP_IN_BODY; | |
| 15577 if (soap_element_begin_in(soap, "SOAP-ENV:Body", 0, NULL)) | |
| 15578 return soap->error; | |
| 15579 if (!soap->body) | |
| 15580 soap->part = SOAP_NO_BODY; | |
| 15581 return SOAP_OK; | |
| 15582 } | |
| 15583 #endif | |
| 15584 | |
| 15585 /******************************************************************************/ | |
| 15586 #ifndef PALM_2 | |
| 15587 SOAP_FMAC1 | |
| 15588 int | |
| 15589 SOAP_FMAC2 | |
| 15590 soap_body_end_in(struct soap *soap) | |
| 15591 { if (soap->version == 0) | |
| 15592 return SOAP_OK; | |
| 15593 if (soap->part == SOAP_NO_BODY) | |
| 15594 return soap->error = SOAP_OK; | |
| 15595 soap->part = SOAP_END_BODY; | |
| 15596 return soap_element_end_in(soap, "SOAP-ENV:Body"); | |
| 15597 } | |
| 15598 #endif | |
| 15599 | |
| 15600 /******************************************************************************/ | |
| 15601 #ifndef PALM_2 | |
| 15602 SOAP_FMAC1 | |
| 15603 int | |
| 15604 SOAP_FMAC2 | |
| 15605 soap_recv_header(struct soap *soap) | |
| 15606 { if (soap_getheader(soap) && soap->error == SOAP_TAG_MISMATCH) | |
| 15607 soap->error = SOAP_OK; | |
| 15608 if (soap->error == SOAP_OK && soap->fheader) | |
| 15609 soap->error = soap->fheader(soap); | |
| 15610 return soap->error; | |
| 15611 } | |
| 15612 #endif | |
| 15613 | |
| 15614 /******************************************************************************/ | |
| 15615 #ifndef PALM_1 | |
| 15616 SOAP_FMAC1 | |
| 15617 void | |
| 15618 SOAP_FMAC2 | |
| 15619 soap_set_endpoint(struct soap *soap, const char *endpoint) | |
| 15620 { register const char *s; | |
| 15621 register size_t i, n; | |
| 15622 soap->endpoint[0] = '\0'; | |
| 15623 soap->host[0] = '\0'; | |
| 15624 soap->path[0] = '/'; | |
| 15625 soap->path[1] = '\0'; | |
| 15626 soap->port = 80; | |
| 15627 if (!endpoint || !*endpoint) | |
| 15628 return; | |
| 15629 #ifdef WITH_OPENSSL | |
| 15630 if (!soap_tag_cmp(endpoint, "https:*")) | |
| 15631 soap->port = 443; | |
| 15632 #endif | |
| 15633 strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint)); | |
| 15634 soap->endpoint[sizeof(soap->endpoint) - 1] = '\0'; | |
| 15635 s = strchr(endpoint, ':'); | |
| 15636 if (s && s[1] == '/' && s[2] == '/') | |
| 15637 s += 3; | |
| 15638 else | |
| 15639 s = endpoint; | |
| 15640 n = strlen(s); | |
| 15641 if (n >= sizeof(soap->host)) | |
| 15642 n = sizeof(soap->host) - 1; | |
| 15643 #ifdef WITH_IPV6 | |
| 15644 if (s[0] == '[') | |
| 15645 { s++; | |
| 15646 for (i = 0; i < n; i++) | |
| 15647 { if (s[i] == ']') | |
| 15648 { s++; | |
| 15649 --n; | |
| 15650 break; | |
| 15651 } | |
| 15652 soap->host[i] = s[i]; | |
| 15653 } | |
| 15654 } | |
| 15655 else | |
| 15656 { for (i = 0; i < n; i++) | |
| 15657 { soap->host[i] = s[i]; | |
| 15658 if (s[i] == '/' || s[i] == ':') | |
| 15659 break; | |
| 15660 } | |
| 15661 } | |
| 15662 #else | |
| 15663 for (i = 0; i < n; i++) | |
| 15664 { soap->host[i] = s[i]; | |
| 15665 if (s[i] == '/' || s[i] == ':') | |
| 15666 break; | |
| 15667 } | |
| 15668 #endif | |
| 15669 soap->host[i] = '\0'; | |
| 15670 if (s[i] == ':') | |
| 15671 { soap->port = (int)soap_strtol(s + i + 1, NULL, 10); | |
| 15672 for (i++; i < n; i++) | |
| 15673 if (s[i] == '/') | |
| 15674 break; | |
| 15675 } | |
| 15676 if (i < n && s[i]) | |
| 15677 { strncpy(soap->path, s + i, sizeof(soap->path)); | |
| 15678 soap->path[sizeof(soap->path) - 1] = '\0'; | |
| 15679 } | |
| 15680 } | |
| 15681 #endif | |
| 15682 | |
| 15683 /******************************************************************************/ | |
| 15684 #ifndef PALM_1 | |
| 15685 SOAP_FMAC1 | |
| 15686 int | |
| 15687 SOAP_FMAC2 | |
| 15688 soap_connect(struct soap *soap, const char *endpoint, const char *action) | |
| 15689 { return soap_connect_command(soap, SOAP_POST, endpoint, action); | |
| 15690 } | |
| 15691 #endif | |
| 15692 | |
| 15693 /******************************************************************************/ | |
| 15694 #ifndef PALM_1 | |
| 15695 SOAP_FMAC1 | |
| 15696 int | |
| 15697 SOAP_FMAC2 | |
| 15698 soap_connect_command(struct soap *soap, int http_command, const char *endpoints, const char *action) | |
| 15699 { char *endpoint; | |
| 15700 const char *s; | |
| 15701 if (endpoints && (s = strchr(endpoints, ' '))) | |
| 15702 { endpoint = (char*)SOAP_MALLOC(soap, strlen(endpoints) + 1); | |
| 15703 for (;;) | |
| 15704 { strncpy(endpoint, endpoints, s - endpoints); | |
| 15705 endpoint[s - endpoints] = '\0'; | |
| 15706 if (soap_try_connect_command(soap, http_command, endpoint, action) != SOAP_TCP_ERROR) | |
| 15707 break; | |
| 15708 if (!*s) | |
| 15709 break; | |
| 15710 soap->error = SOAP_OK; | |
| 15711 while (*s == ' ') | |
| 15712 s++; | |
| 15713 endpoints = s; | |
| 15714 s = strchr(endpoints, ' '); | |
| 15715 if (!s) | |
| 15716 s = endpoints + strlen(endpoints); | |
| 15717 } | |
| 15718 SOAP_FREE(soap, endpoint); | |
| 15719 } | |
| 15720 else | |
| 15721 soap_try_connect_command(soap, http_command, endpoints, action); | |
| 15722 return soap->error; | |
| 15723 } | |
| 15724 #endif | |
| 15725 | |
| 15726 /******************************************************************************/ | |
| 15727 #ifndef PALM_1 | |
| 15728 static int | |
| 15729 soap_try_connect_command(struct soap *soap, int http_command, const char *endpoint, const char *action) | |
| 15730 { char host[sizeof(soap->host)]; | |
| 15731 int port; | |
| 15732 size_t count; | |
| 15733 soap->error = SOAP_OK; | |
| 15734 strcpy(host, soap->host); /* save previous host name: if != then reconnect */ | |
| 15735 port = soap->port; /* save previous port to compare */ | |
| 15736 soap->status = http_command; | |
| 15737 soap_set_endpoint(soap, endpoint); | |
| 15738 #ifndef WITH_LEANER | |
| 15739 if (soap->fconnect) | |
| 15740 { if ((soap->error = soap->fconnect(soap, endpoint, soap->host, soap->port))) | |
| 15741 return soap->error; | |
| 15742 } | |
| 15743 else | |
| 15744 #endif | |
| 15745 soap->action = soap_strdup(soap, action); | |
| 15746 if (soap->fopen && *soap->host) | |
| 15747 { if (!soap->keep_alive || !soap_valid_socket(soap->socket) || strcmp(soap->host, host) || soap->port != port || !soap->fpoll || soap->fpoll(soap)) | |
| 15748 { soap->error = SOAP_OK; | |
| 15749 #ifndef WITH_LEAN | |
| 15750 if (!strncmp(endpoint, "soap.udp:", 9)) | |
| 15751 soap->omode |= SOAP_IO_UDP; | |
| 15752 else | |
| 15753 #endif | |
| 15754 { soap->keep_alive = 0; /* to force close */ | |
| 15755 soap->omode &= ~SOAP_IO_UDP; /* to force close */ | |
| 15756 } | |
| 15757 soap_closesock(soap); | |
| 15758 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)); | |
| 15759 if (!soap->keep_alive || !soap_valid_socket(soap->socket)) | |
| 15760 { soap->socket = soap->fopen(soap, endpoint, soap->host, soap->port); | |
| 15761 if (soap->error) | |
| 15762 return soap->error; | |
| 15763 soap->keep_alive = ((soap->omode & SOAP_IO_KEEPALIVE) != 0); | |
| 15764 } | |
| 15765 } | |
| 15766 } | |
| 15767 #ifdef WITH_NTLM | |
| 15768 if (soap_ntlm_handshake(soap, SOAP_GET, endpoint, soap->host, soap->port)) | |
| 15769 return soap->error; | |
| 15770 #endif | |
| 15771 count = soap_count_attachments(soap); | |
| 15772 if (soap_begin_send(soap)) | |
| 15773 return soap->error; | |
| 15774 if (http_command == SOAP_GET) | |
| 15775 { soap->mode &= ~SOAP_IO; | |
| 15776 soap->mode |= SOAP_IO_BUFFER; | |
| 15777 } | |
| 15778 #ifndef WITH_NOHTTP | |
| 15779 if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML) && endpoint) | |
| 15780 { unsigned int k = soap->mode; | |
| 15781 soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB); | |
| 15782 if ((k & SOAP_IO) != SOAP_IO_FLUSH) | |
| 15783 soap->mode |= SOAP_IO_BUFFER; | |
| 15784 if ((soap->error = soap->fpost(soap, endpoint, soap->host, soap->port, soap->path, action, count))) | |
| 15785 return soap->error; | |
| 15786 #ifndef WITH_LEANER | |
| 15787 if ((k & SOAP_IO) == SOAP_IO_CHUNK) | |
| 15788 { if (soap_flush(soap)) | |
| 15789 return soap->error; | |
| 15790 } | |
| 15791 #endif | |
| 15792 soap->mode = k; | |
| 15793 } | |
| 15794 if (http_command == SOAP_GET || http_command == SOAP_DEL) | |
| 15795 return soap_end_send_flush(soap); | |
| 15796 #endif | |
| 15797 return SOAP_OK; | |
| 15798 } | |
| 15799 #endif | |
| 15800 | |
| 15801 /******************************************************************************/ | |
| 15802 #ifdef WITH_NTLM | |
| 15803 #ifndef PALM_1 | |
| 15804 static int | |
| 15805 soap_ntlm_handshake(struct soap *soap, int command, const char *endpoint, const char *host, int port) | |
| 15806 { /* requires libntlm from http://www.nongnu.org/libntlm/ */ | |
| 15807 const char *userid = (soap->proxy_userid ? soap->proxy_userid : soap->userid); | |
| 15808 const char *passwd = (soap->proxy_passwd ? soap->proxy_passwd : soap->passwd); | |
| 15809 struct SOAP_ENV__Header *oldheader; | |
| 15810 if (soap->ntlm_challenge && userid && passwd && soap->authrealm) | |
| 15811 { tSmbNtlmAuthRequest req; | |
| 15812 tSmbNtlmAuthResponse res; | |
| 15813 tSmbNtlmAuthChallenge ch; | |
| 15814 short k = soap->keep_alive; | |
| 15815 size_t l = soap->length; | |
| 15816 size_t c = soap->count; | |
| 15817 soap_mode m = soap->mode, o = soap->omode; | |
| 15818 int s = soap->status; | |
| 15819 char *a = soap->action; | |
| 15820 short v = soap->version; | |
| 15821 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "NTLM '%s'\n", soap->ntlm_challenge)); | |
| 15822 if (!*soap->ntlm_challenge) | |
| 15823 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "NTLM S->C Type 1: received NTLM authentication challenge from server\n")); | |
| 15824 /* S -> C 401 Unauthorized | |
| 15825 WWW-Authenticate: NTLM | |
| 15826 */ | |
| 15827 buildSmbNtlmAuthRequest(&req, userid, soap->authrealm); | |
| 15828 soap->ntlm_challenge = soap_s2base64(soap, (unsigned char*)&req, NULL, SmbLength(&req)); | |
| 15829 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "NTLM C->S Type 2: sending NTLM authorization to server\nAuthorization: NTLM %s\n", soap->ntlm_challenge)); | |
| 15830 /* C -> S GET ... | |
| 15831 Authorization: NTLM TlRMTVNTUAABAAAAA7IAAAoACgApAAAACQAJACAAAABMSUdIVENJVFlVUlNBLU1JTk9S | |
| 15832 */ | |
| 15833 soap->omode = SOAP_IO_BUFFER; | |
| 15834 if (soap_begin_send(soap)) | |
| 15835 return soap->error; | |
| 15836 soap->keep_alive = 1; | |
| 15837 soap->status = command; | |
| 15838 if (soap->fpost(soap, endpoint, host, port, soap->path, soap->action, 0) | |
| 15839 || soap_end_send_flush(soap)) | |
| 15840 return soap->error; | |
| 15841 soap->mode = m; | |
| 15842 soap->keep_alive = k; | |
| 15843 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "NTLM S->C Type 2: waiting on server NTLM response\n")); | |
| 15844 oldheader = soap->header; | |
| 15845 if (soap_begin_recv(soap)) | |
| 15846 if (soap->error == SOAP_EOF) | |
| 15847 return soap->error; | |
| 15848 soap_end_recv(soap); | |
| 15849 soap->header = oldheader; | |
| 15850 soap->length = l; | |
| 15851 if (soap->status != 401 && soap->status != 407) | |
| 15852 return soap->error = SOAP_NTLM_ERROR; | |
| 15853 soap->error = SOAP_OK; | |
| 15854 } | |
| 15855 /* S -> C 401 Unauthorized | |
| 15856 WWW-Authenticate: NTLM TlRMTVNTUAACAAAAAAAAACgAAAABggAAU3J2Tm9uY2UAAAAAAAAAAA== | |
| 15857 */ | |
| 15858 soap_base642s(soap, soap->ntlm_challenge, (char*)&ch, sizeof(tSmbNtlmAuthChallenge), NULL); | |
| 15859 buildSmbNtlmAuthResponse(&ch, &res, userid, passwd); | |
| 15860 soap->ntlm_challenge = soap_s2base64(soap, (unsigned char*)&res, NULL, SmbLength(&res)); | |
| 15861 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "NTLM C->S Type 3: sending NTLM authorization to server\nAuthorization: NTLM %s\n", soap->ntlm_challenge)); | |
| 15862 /* C -> S GET ... | |
| 15863 Authorization: NTLM TlRMTVNTUAADAAAAGAAYAHIAAAAYABgAigAAABQAFABAAAAADAAMAFQAAAASABIAYAAAAAAAAACiAAAAAYIAAFUAUgBTAEEALQBNAEkATgBPAFIAWgBhAHAAaABvAGQATABJAEcASABUAEMASQBUAFkArYfKbe/jRoW5xDxHeoxC1gBmfWiS5+iX4OAN4xBKG/IFPwfH3agtPEia6YnhsADT | |
| 15864 */ | |
| 15865 soap->userid = NULL; | |
| 15866 soap->passwd = NULL; | |
| 15867 soap->proxy_userid = NULL; | |
| 15868 soap->proxy_passwd = NULL; | |
| 15869 soap->keep_alive = k; | |
| 15870 soap->length = l; | |
| 15871 soap->count = c; | |
| 15872 soap->mode = m; | |
| 15873 soap->omode = o; | |
| 15874 soap->status = s; | |
| 15875 soap->action = a; | |
| 15876 soap->version = v; | |
| 15877 } | |
| 15878 return SOAP_OK; | |
| 15879 } | |
| 15880 #endif | |
| 15881 #endif | |
| 15882 | |
| 15883 /******************************************************************************/ | |
| 15884 #ifndef WITH_LEAN | |
| 15885 SOAP_FMAC1 | |
| 15886 char* | |
| 15887 SOAP_FMAC2 | |
| 15888 soap_s2base64(struct soap *soap, const unsigned char *s, char *t, int n) | |
| 15889 { register int i; | |
| 15890 register unsigned long m; | |
| 15891 register char *p; | |
| 15892 if (!t) | |
| 15893 t = (char*)soap_malloc(soap, (n + 2) / 3 * 4 + 1); | |
| 15894 if (!t) | |
| 15895 return NULL; | |
| 15896 p = t; | |
| 15897 t[0] = '\0'; | |
| 15898 if (!s) | |
| 15899 return p; | |
| 15900 for (; n > 2; n -= 3, s += 3) | |
| 15901 { m = s[0]; | |
| 15902 m = (m << 8) | s[1]; | |
| 15903 m = (m << 8) | s[2]; | |
| 15904 for (i = 4; i > 0; m >>= 6) | |
| 15905 t[--i] = soap_base64o[m & 0x3F]; | |
| 15906 t += 4; | |
| 15907 } | |
| 15908 t[0] = '\0'; | |
| 15909 if (n > 0) /* 0 < n <= 2 implies that t[0..4] is allocated (base64 scaling formula) */ | |
| 15910 { m = 0; | |
| 15911 for (i = 0; i < n; i++) | |
| 15912 m = (m << 8) | *s++; | |
| 15913 for (; i < 3; i++) | |
| 15914 m <<= 8; | |
| 15915 for (i = 4; i > 0; m >>= 6) | |
| 15916 t[--i] = soap_base64o[m & 0x3F]; | |
| 15917 for (i = 3; i > n; i--) | |
| 15918 t[i] = '='; | |
| 15919 t[4] = '\0'; | |
| 15920 } | |
| 15921 return p; | |
| 15922 } | |
| 15923 #endif | |
| 15924 | |
| 15925 /******************************************************************************/ | |
| 15926 #ifndef WITH_LEAN | |
| 15927 SOAP_FMAC1 | |
| 15928 const char* | |
| 15929 SOAP_FMAC2 | |
| 15930 soap_base642s(struct soap *soap, const char *s, char *t, size_t l, int *n) | |
| 15931 { register size_t i, j; | |
| 15932 register soap_wchar c; | |
| 15933 register unsigned long m; | |
| 15934 register const char *p; | |
| 15935 if (!s || !*s) | |
| 15936 { if (n) | |
| 15937 *n = 0; | |
| 15938 if (soap->error) | |
| 15939 return NULL; | |
| 15940 return SOAP_NON_NULL; | |
| 15941 } | |
| 15942 if (!t) | |
| 15943 { l = (strlen(s) + 3) / 4 * 3 + 1; /* make sure enough space for \0 */ | |
| 15944 t = (char*)soap_malloc(soap, l); | |
| 15945 } | |
| 15946 if (!t) | |
| 15947 return NULL; | |
| 15948 p = t; | |
| 15949 if (n) | |
| 15950 *n = 0; | |
| 15951 for (i = 0; ; i += 3, l -= 3) | |
| 15952 { m = 0; | |
| 15953 j = 0; | |
| 15954 while (j < 4) | |
| 15955 { c = *s++; | |
| 15956 if (c == '=' || !c) | |
| 15957 { if (l >= j - 1) | |
| 15958 { switch (j) | |
| 15959 { case 2: | |
| 15960 *t++ = (char)((m >> 4) & 0xFF); | |
| 15961 i++; | |
| 15962 l--; | |
| 15963 break; | |
| 15964 case 3: | |
| 15965 *t++ = (char)((m >> 10) & 0xFF); | |
| 15966 *t++ = (char)((m >> 2) & 0xFF); | |
| 15967 i += 2; | |
| 15968 l -= 2; | |
| 15969 } | |
| 15970 } | |
| 15971 if (n) | |
| 15972 *n = (int)i; | |
| 15973 if (l) | |
| 15974 *t = '\0'; | |
| 15975 return p; | |
| 15976 } | |
| 15977 c -= '+'; | |
| 15978 if (c >= 0 && c <= 79) | |
| 15979 { int b = soap_base64i[c]; | |
| 15980 if (b >= 64) | |
| 15981 { soap->error = SOAP_TYPE; | |
| 15982 return NULL; | |
| 15983 } | |
| 15984 m = (m << 6) + b; | |
| 15985 j++; | |
| 15986 } | |
| 15987 else if (!soap_blank(c + '+')) | |
| 15988 { soap->error = SOAP_TYPE; | |
| 15989 return NULL; | |
| 15990 } | |
| 15991 } | |
| 15992 if (l < 3) | |
| 15993 { if (n) | |
| 15994 *n = (int)i; | |
| 15995 if (l) | |
| 15996 *t = '\0'; | |
| 15997 return p; | |
| 15998 } | |
| 15999 *t++ = (char)((m >> 16) & 0xFF); | |
| 16000 *t++ = (char)((m >> 8) & 0xFF); | |
| 16001 *t++ = (char)(m & 0xFF); | |
| 16002 } | |
| 16003 } | |
| 16004 #endif | |
| 16005 | |
| 16006 /******************************************************************************/ | |
| 16007 #ifndef WITH_LEAN | |
| 16008 SOAP_FMAC1 | |
| 16009 char* | |
| 16010 SOAP_FMAC2 | |
| 16011 soap_s2hex(struct soap *soap, const unsigned char *s, char *t, int n) | |
| 16012 { register char *p; | |
| 16013 if (!t) | |
| 16014 t = (char*)soap_malloc(soap, 2 * n + 1); | |
| 16015 if (!t) | |
| 16016 return NULL; | |
| 16017 p = t; | |
| 16018 t[0] = '\0'; | |
| 16019 if (s) | |
| 16020 { for (; n > 0; n--) | |
| 16021 { register int m = *s++; | |
| 16022 *t++ = (char)((m >> 4) + (m > 159 ? 'a' - 10 : '0')); | |
| 16023 m &= 0x0F; | |
| 16024 *t++ = (char)(m + (m > 9 ? 'a' - 10 : '0')); | |
| 16025 } | |
| 16026 } | |
| 16027 *t++ = '\0'; | |
| 16028 return p; | |
| 16029 } | |
| 16030 #endif | |
| 16031 | |
| 16032 /******************************************************************************/ | |
| 16033 #ifndef WITH_LEAN | |
| 16034 SOAP_FMAC1 | |
| 16035 const char* | |
| 16036 SOAP_FMAC2 | |
| 16037 soap_hex2s(struct soap *soap, const char *s, char *t, size_t l, int *n) | |
| 16038 { register const char *p; | |
| 16039 if (!s || !*s) | |
| 16040 { if (n) | |
| 16041 *n = 0; | |
| 16042 if (soap->error) | |
| 16043 return NULL; | |
| 16044 return SOAP_NON_NULL; | |
| 16045 } | |
| 16046 if (!t) | |
| 16047 { l = strlen(s) / 2 + 1; /* make sure enough space for \0 */ | |
| 16048 t = (char*)soap_malloc(soap, l); | |
| 16049 } | |
| 16050 if (!t) | |
| 16051 return NULL; | |
| 16052 p = t; | |
| 16053 while (l) | |
| 16054 { register int d1, d2; | |
| 16055 d1 = *s++; | |
| 16056 if (!d1) | |
| 16057 break; | |
| 16058 d2 = *s++; | |
| 16059 if (!d2) | |
| 16060 break; | |
| 16061 *t++ = (char)(((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0')); | |
| 16062 l--; | |
| 16063 } | |
| 16064 if (n) | |
| 16065 *n = (int)(t - p); | |
| 16066 if (l) | |
| 16067 *t = '\0'; | |
| 16068 return p; | |
| 16069 } | |
| 16070 #endif | |
| 16071 | |
| 16072 /******************************************************************************/ | |
| 16073 #ifndef WITH_NOHTTP | |
| 16074 #ifndef PALM_1 | |
| 16075 SOAP_FMAC1 | |
| 16076 int | |
| 16077 SOAP_FMAC2 | |
| 16078 soap_puthttphdr(struct soap *soap, int status, size_t count) | |
| 16079 { if (soap->status != SOAP_GET && soap->status != SOAP_DEL && soap->status != SOAP_CONNECT) | |
| 16080 { register const char *s = "text/xml; charset=utf-8"; | |
| 16081 register int err = SOAP_OK; | |
| 16082 #ifndef WITH_LEANER | |
| 16083 register const char *r = NULL; | |
| 16084 #endif | |
| 16085 if ((status == SOAP_FILE || soap->status == SOAP_PUT || soap->status == SOAP_POST_FILE) && soap->http_content && !strchr(s, 10) && !strchr(s, 13)) | |
| 16086 s = soap->http_content; | |
| 16087 else if (status == SOAP_HTML) | |
| 16088 s = "text/html; charset=utf-8"; | |
| 16089 else if (count || ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK)) | |
| 16090 { if (soap->version == 2) | |
| 16091 s = "application/soap+xml; charset=utf-8"; | |
| 16092 } | |
| 16093 #ifndef WITH_LEANER | |
| 16094 if (soap->mode & (SOAP_ENC_DIME | SOAP_ENC_MTOM)) | |
| 16095 { if (soap->mode & SOAP_ENC_MTOM) | |
| 16096 { if (soap->version == 2) | |
| 16097 r = "application/soap+xml"; | |
| 16098 else | |
| 16099 r = "text/xml"; | |
| 16100 s = "application/xop+xml"; | |
| 16101 } | |
| 16102 else | |
| 16103 s = "application/dime"; | |
| 16104 } | |
| 16105 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) | |
| 16106 { register const char *t; | |
| 16107 #ifdef HAVE_SNPRINTF | |
| 16108 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "multipart/related; charset=utf-8; boundary=\"%s\"; type=\"", soap->mime.boundary); | |
| 16109 #else | |
| 16110 sprintf(soap->tmpbuf, "multipart/related; charset=utf-8; boundary=\"%s\"; type=\"", soap->mime.boundary); | |
| 16111 #endif | |
| 16112 t = strchr(s, ';'); | |
| 16113 if (t) | |
| 16114 strncat(soap->tmpbuf, s, t - s); | |
| 16115 else | |
| 16116 strcat(soap->tmpbuf, s); | |
| 16117 if (soap->mime.start && strlen(soap->tmpbuf) + strlen(soap->mime.start) + 11 < sizeof(soap->tmpbuf)) | |
| 16118 { strcat(soap->tmpbuf, "\"; start=\""); | |
| 16119 strcat(soap->tmpbuf, soap->mime.start); | |
| 16120 } | |
| 16121 strcat(soap->tmpbuf, "\""); | |
| 16122 if (r && strlen(soap->tmpbuf) + strlen(r) + 15 < sizeof(soap->tmpbuf)) | |
| 16123 { strcat(soap->tmpbuf, "; start-info=\""); | |
| 16124 strcat(soap->tmpbuf, r); | |
| 16125 strcat(soap->tmpbuf, "\""); | |
| 16126 } | |
| 16127 } | |
| 16128 else | |
| 16129 strncpy(soap->tmpbuf, s, sizeof(soap->tmpbuf)); | |
| 16130 soap->tmpbuf[sizeof(soap->tmpbuf) - 1] = '\0'; | |
| 16131 s = soap->tmpbuf; | |
| 16132 if (status == SOAP_OK && soap->version == 2 && soap->action && strlen(soap->action) + strlen(s) < sizeof(soap->tmpbuf) - 80) | |
| 16133 { | |
| 16134 #ifdef HAVE_SNPRINTF | |
| 16135 size_t l = strlen(s); | |
| 16136 soap_snprintf(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, "; action=\"%s\"", soap->action); | |
| 16137 #else | |
| 16138 sprintf(soap->tmpbuf + strlen(s), "; action=\"%s\"", soap->action); | |
| 16139 #endif | |
| 16140 } | |
| 16141 #endif | |
| 16142 if ((err = soap->fposthdr(soap, "Content-Type", s))) | |
| 16143 return err; | |
| 16144 #ifdef WITH_ZLIB | |
| 16145 if ((soap->omode & SOAP_ENC_ZLIB)) | |
| 16146 { | |
| 16147 #ifdef WITH_GZIP | |
| 16148 err = soap->fposthdr(soap, "Content-Encoding", soap->zlib_out == SOAP_ZLIB_DEFLATE ? "deflate" : "gzip"); | |
| 16149 #else | |
| 16150 err = soap->fposthdr(soap, "Content-Encoding", "deflate"); | |
| 16151 #endif | |
| 16152 if (err) | |
| 16153 return err; | |
| 16154 } | |
| 16155 #endif | |
| 16156 #ifndef WITH_LEANER | |
| 16157 if ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK) | |
| 16158 err = soap->fposthdr(soap, "Transfer-Encoding", "chunked"); | |
| 16159 else | |
| 16160 #endif | |
| 16161 if (s) | |
| 16162 { | |
| 16163 #ifdef HAVE_SNPRINTF | |
| 16164 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%lu", (unsigned long)count); | |
| 16165 #else | |
| 16166 sprintf(soap->tmpbuf, "%lu", (unsigned long)count); | |
| 16167 #endif | |
| 16168 err = soap->fposthdr(soap, "Content-Length", soap->tmpbuf); | |
| 16169 } | |
| 16170 if (err) | |
| 16171 return err; | |
| 16172 } | |
| 16173 return soap->fposthdr(soap, "Connection", soap->keep_alive ? "keep-alive" : "close"); | |
| 16174 } | |
| 16175 #endif | |
| 16176 #endif | |
| 16177 | |
| 16178 /******************************************************************************/ | |
| 16179 #ifndef WITH_LEAN | |
| 16180 static const char* | |
| 16181 soap_set_validation_fault(struct soap *soap, const char *s, const char *t) | |
| 16182 { if (!t) | |
| 16183 t = SOAP_STR_EOS; | |
| 16184 if (*soap->tag) | |
| 16185 { | |
| 16186 #ifdef HAVE_SNPRINTF | |
| 16187 soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "Validation constraint violation: %s%s in element '%s'", s, t ? t : SOAP_STR_EOS, soap->tag); | |
| 16188 #else | |
| 16189 if (strlen(soap->tag) + strlen(t) < sizeof(soap->msgbuf) - 100) | |
| 16190 sprintf(soap->msgbuf, "Validation constraint violation: %s%s in element '%s'", s, t, soap->tag); | |
| 16191 else | |
| 16192 sprintf(soap->msgbuf, "Validation constraint violation: %s", s); | |
| 16193 #endif | |
| 16194 } | |
| 16195 else | |
| 16196 { | |
| 16197 #ifdef HAVE_SNPRINTF | |
| 16198 soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "Validation constraint violation: %s%s", s, t ? t : SOAP_STR_EOS); | |
| 16199 #else | |
| 16200 if (strlen(soap->tag) + strlen(t) < sizeof(soap->msgbuf) - 100) | |
| 16201 sprintf(soap->msgbuf, "Validation constraint violation: %s%s", s, t); | |
| 16202 else | |
| 16203 sprintf(soap->msgbuf, "Validation constraint violation: %s", s); | |
| 16204 #endif | |
| 16205 } | |
| 16206 return soap->msgbuf; | |
| 16207 } | |
| 16208 #endif | |
| 16209 | |
| 16210 /******************************************************************************/ | |
| 16211 #ifndef PALM_1 | |
| 16212 SOAP_FMAC1 | |
| 16213 void | |
| 16214 SOAP_FMAC2 | |
| 16215 soap_set_fault(struct soap *soap) | |
| 16216 { const char **c = soap_faultcode(soap); | |
| 16217 const char **s = soap_faultstring(soap); | |
| 16218 if (soap->fseterror) | |
| 16219 soap->fseterror(soap, c, s); | |
| 16220 if (!*c) | |
| 16221 { if (soap->version == 2) | |
| 16222 *c = "SOAP-ENV:Sender"; | |
| 16223 else | |
| 16224 *c = "SOAP-ENV:Client"; | |
| 16225 } | |
| 16226 if (*s) | |
| 16227 return; | |
| 16228 switch (soap->error) | |
| 16229 { | |
| 16230 #ifndef WITH_LEAN | |
| 16231 case SOAP_CLI_FAULT: | |
| 16232 *s = "Client fault"; | |
| 16233 break; | |
| 16234 case SOAP_SVR_FAULT: | |
| 16235 *s = "Server fault"; | |
| 16236 break; | |
| 16237 case SOAP_TAG_MISMATCH: | |
| 16238 *s = soap_set_validation_fault(soap, "tag name or namespace mismatch", NULL); | |
| 16239 break; | |
| 16240 case SOAP_TYPE: | |
| 16241 *s = soap_set_validation_fault(soap, "data type mismatch ", soap->type); | |
| 16242 break; | |
| 16243 case SOAP_SYNTAX_ERROR: | |
| 16244 *s = "Well-formedness violation"; | |
| 16245 break; | |
| 16246 case SOAP_NO_TAG: | |
| 16247 *s = "No tag: no XML root element or missing SOAP message body element"; | |
| 16248 break; | |
| 16249 case SOAP_MUSTUNDERSTAND: | |
| 16250 *c = "SOAP-ENV:MustUnderstand"; | |
| 16251 #ifdef HAVE_SNPRINTF | |
| 16252 soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "The data in element '%s' must be understood but cannot be handled", soap->tag); | |
| 16253 #else | |
| 16254 strncpy(soap->msgbuf, soap->tag, sizeof(soap->msgbuf)); | |
| 16255 soap->msgbuf[sizeof(soap->msgbuf) - 1] = '\0'; | |
| 16256 #endif | |
| 16257 *s = soap->msgbuf; | |
| 16258 break; | |
| 16259 case SOAP_VERSIONMISMATCH: | |
| 16260 *c = "SOAP-ENV:VersionMismatch"; | |
| 16261 *s = "Invalid SOAP message or SOAP version mismatch"; | |
| 16262 break; | |
| 16263 case SOAP_DATAENCODINGUNKNOWN: | |
| 16264 *c = "SOAP-ENV:DataEncodingUnknown"; | |
| 16265 *s = "Unsupported SOAP data encoding"; | |
| 16266 break; | |
| 16267 case SOAP_NAMESPACE: | |
| 16268 *s = soap_set_validation_fault(soap, "namespace error", NULL); | |
| 16269 break; | |
| 16270 case SOAP_USER_ERROR: | |
| 16271 *s = "User data error"; | |
| 16272 break; | |
| 16273 case SOAP_FATAL_ERROR: | |
| 16274 *s = "Fatal error"; | |
| 16275 break; | |
| 16276 case SOAP_NO_METHOD: | |
| 16277 #ifdef HAVE_SNPRINTF | |
| 16278 soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "Method '%s' not implemented: method name or namespace not recognized", soap->tag); | |
| 16279 #else | |
| 16280 sprintf(soap->msgbuf, "Method '%s' not implemented: method name or namespace not recognized", soap->tag); | |
| 16281 #endif | |
| 16282 *s = soap->msgbuf; | |
| 16283 break; | |
| 16284 case SOAP_NO_DATA: | |
| 16285 *s = "Data required for operation"; | |
| 16286 break; | |
| 16287 case SOAP_GET_METHOD: | |
| 16288 *s = "HTTP GET method not implemented"; | |
| 16289 break; | |
| 16290 case SOAP_PUT_METHOD: | |
| 16291 *s = "HTTP PUT method not implemented"; | |
| 16292 break; | |
| 16293 case SOAP_HTTP_METHOD: | |
| 16294 *s = "HTTP method not implemented"; | |
| 16295 break; | |
| 16296 case SOAP_EOM: | |
| 16297 *s = "Out of memory"; | |
| 16298 break; | |
| 16299 case SOAP_MOE: | |
| 16300 *s = "Memory overflow or memory corruption error"; | |
| 16301 break; | |
| 16302 case SOAP_HDR: | |
| 16303 *s = "Header line too long"; | |
| 16304 break; | |
| 16305 case SOAP_IOB: | |
| 16306 *s = "Array index out of bounds"; | |
| 16307 break; | |
| 16308 case SOAP_NULL: | |
| 16309 *s = soap_set_validation_fault(soap, "nil not allowed", NULL); | |
| 16310 break; | |
| 16311 case SOAP_DUPLICATE_ID: | |
| 16312 *s = soap_set_validation_fault(soap, "multiple elements (use the SOAP_XML_TREE flag) with duplicate id ", soap->id); | |
| 16313 if (soap->version == 2) | |
| 16314 *soap_faultsubcode(soap) = "SOAP-ENC:DuplicateID"; | |
| 16315 break; | |
| 16316 case SOAP_MISSING_ID: | |
| 16317 *s = soap_set_validation_fault(soap, "missing id for ref ", soap->id); | |
| 16318 if (soap->version == 2) | |
| 16319 *soap_faultsubcode(soap) = "SOAP-ENC:MissingID"; | |
| 16320 break; | |
| 16321 case SOAP_HREF: | |
| 16322 *s = soap_set_validation_fault(soap, "incompatible object type id-ref ", soap->id); | |
| 16323 break; | |
| 16324 case SOAP_FAULT: | |
| 16325 break; | |
| 16326 #ifndef WITH_NOIO | |
| 16327 case SOAP_UDP_ERROR: | |
| 16328 *s = "Message too large for UDP packet"; | |
| 16329 break; | |
| 16330 case SOAP_TCP_ERROR: | |
| 16331 *s = tcp_error(soap); | |
| 16332 break; | |
| 16333 #endif | |
| 16334 case SOAP_HTTP_ERROR: | |
| 16335 *s = "An HTTP processing error occurred"; | |
| 16336 break; | |
| 16337 case SOAP_NTLM_ERROR: | |
| 16338 *s = "An HTTP NTLM authentication error occurred"; | |
| 16339 break; | |
| 16340 case SOAP_SSL_ERROR: | |
| 16341 #ifdef WITH_OPENSSL | |
| 16342 *s = "SSL/TLS error"; | |
| 16343 #else | |
| 16344 *s = "OpenSSL not installed: recompile with -DWITH_OPENSSL"; | |
| 16345 #endif | |
| 16346 break; | |
| 16347 case SOAP_PLUGIN_ERROR: | |
| 16348 *s = "Plugin registry error"; | |
| 16349 break; | |
| 16350 case SOAP_DIME_ERROR: | |
| 16351 *s = "DIME format error or max DIME size exceeds SOAP_MAXDIMESIZE"; | |
| 16352 break; | |
| 16353 case SOAP_DIME_HREF: | |
| 16354 *s = "DIME href to missing attachment"; | |
| 16355 break; | |
| 16356 case SOAP_DIME_MISMATCH: | |
| 16357 *s = "DIME version/transmission error"; | |
| 16358 break; | |
| 16359 case SOAP_DIME_END: | |
| 16360 *s = "End of DIME error"; | |
| 16361 break; | |
| 16362 case SOAP_MIME_ERROR: | |
| 16363 *s = "MIME format error"; | |
| 16364 break; | |
| 16365 case SOAP_MIME_HREF: | |
| 16366 *s = "MIME href to missing attachment"; | |
| 16367 break; | |
| 16368 case SOAP_MIME_END: | |
| 16369 *s = "End of MIME error"; | |
| 16370 break; | |
| 16371 case SOAP_ZLIB_ERROR: | |
| 16372 #ifdef WITH_ZLIB | |
| 16373 #ifdef HAVE_SNPRINTF | |
| 16374 soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "Zlib/gzip error: '%s'", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS); | |
| 16375 #else | |
| 16376 sprintf(soap->msgbuf, "Zlib/gzip error: '%s'", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS); | |
| 16377 #endif | |
| 16378 *s = soap->msgbuf; | |
| 16379 #else | |
| 16380 *s = "Zlib/gzip not installed for (de)compression: recompile with -DWITH_GZIP"; | |
| 16381 #endif | |
| 16382 break; | |
| 16383 case SOAP_REQUIRED: | |
| 16384 *s = soap_set_validation_fault(soap, "missing required attribute", NULL); | |
| 16385 break; | |
| 16386 case SOAP_PROHIBITED: | |
| 16387 *s = soap_set_validation_fault(soap, "prohibited attribute present", NULL); | |
| 16388 break; | |
| 16389 case SOAP_OCCURS: | |
| 16390 *s = soap_set_validation_fault(soap, "occurrence violation", NULL); | |
| 16391 break; | |
| 16392 case SOAP_LENGTH: | |
| 16393 *s = soap_set_validation_fault(soap, "content range or length violation", NULL); | |
| 16394 break; | |
| 16395 case SOAP_FD_EXCEEDED: | |
| 16396 *s = "Maximum number of open connections was reached (no define HAVE_POLL): increase FD_SETSIZE"; | |
| 16397 break; | |
| 16398 case SOAP_UTF_ERROR: | |
| 16399 *s = "UTF content encoding error"; | |
| 16400 break; | |
| 16401 case SOAP_STOP: | |
| 16402 *s = "Stopped: no response sent or received (informative)"; | |
| 16403 break; | |
| 16404 #endif | |
| 16405 case SOAP_EOF: | |
| 16406 #ifndef WITH_NOIO | |
| 16407 *s = soap_strerror(soap); /* *s = soap->msgbuf */ | |
| 16408 #ifndef WITH_LEAN | |
| 16409 if (strlen(soap->msgbuf) + 25 < sizeof(soap->msgbuf)) | |
| 16410 { memmove(soap->msgbuf + 25, soap->msgbuf, strlen(soap->msgbuf) + 1); | |
| 16411 memcpy(soap->msgbuf, "End of file or no input: ", 25); | |
| 16412 } | |
| 16413 #endif | |
| 16414 break; | |
| 16415 #else | |
| 16416 *s = "End of file or no input"; | |
| 16417 break; | |
| 16418 #endif | |
| 16419 default: | |
| 16420 #ifndef WITH_NOHTTP | |
| 16421 #ifndef WITH_LEAN | |
| 16422 if (soap->error > 200 && soap->error < 600) | |
| 16423 { | |
| 16424 #ifdef HAVE_SNPRINTF | |
| 16425 soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "HTTP Error: %d %s", soap->error, http_error(soap, soap->error)); | |
| 16426 #else | |
| 16427 sprintf(soap->msgbuf, "HTTP Error: %d %s", soap->error, http_error(soap, soap->error)); | |
| 16428 #endif | |
| 16429 *s = soap->msgbuf; | |
| 16430 } | |
| 16431 else | |
| 16432 #endif | |
| 16433 #endif | |
| 16434 { | |
| 16435 #ifdef HAVE_SNPRINTF | |
| 16436 soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "Error %d", soap->error); | |
| 16437 #else | |
| 16438 sprintf(soap->msgbuf, "Error %d", soap->error); | |
| 16439 #endif | |
| 16440 *s = soap->msgbuf; | |
| 16441 } | |
| 16442 } | |
| 16443 } | |
| 16444 #endif | |
| 16445 | |
| 16446 /******************************************************************************/ | |
| 16447 #ifndef PALM_1 | |
| 16448 SOAP_FMAC1 | |
| 16449 int | |
| 16450 SOAP_FMAC2 | |
| 16451 soap_send_fault(struct soap *soap) | |
| 16452 { register int status = soap->error; | |
| 16453 if (status == SOAP_OK || status == SOAP_STOP) | |
| 16454 return soap_closesock(soap); | |
| 16455 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Sending back fault struct for error code %d\n", soap->error)); | |
| 16456 soap->keep_alive = 0; /* to terminate connection */ | |
| 16457 soap_set_fault(soap); | |
| 16458 if (soap->error < 200 && soap->error != SOAP_FAULT) | |
| 16459 soap->header = NULL; | |
| 16460 if (status != SOAP_EOF || (!soap->recv_timeout && !soap->send_timeout)) | |
| 16461 { register int r = 1; | |
| 16462 #ifndef WITH_NOIO | |
| 16463 if (soap->fpoll && soap->fpoll(soap)) | |
| 16464 r = 0; | |
| 16465 #ifndef WITH_LEAN | |
| 16466 else if (soap_valid_socket(soap->socket)) | |
| 16467 { r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_SND, 0); | |
| 16468 if (r > 0) | |
| 16469 { int t; | |
| 16470 if (!(r & SOAP_TCP_SELECT_SND) | |
| 16471 || ((r & SOAP_TCP_SELECT_RCV) | |
| 16472 && recv(soap->socket, (char*)&t, 1, MSG_PEEK) < 0)) | |
| 16473 r = 0; | |
| 16474 } | |
| 16475 } | |
| 16476 #endif | |
| 16477 #endif | |
| 16478 if (r > 0) | |
| 16479 { soap->error = SOAP_OK; | |
| 16480 soap->encodingStyle = NULL; /* no encodingStyle in Faults */ | |
| 16481 soap_serializeheader(soap); | |
| 16482 soap_serializefault(soap); | |
| 16483 soap_begin_count(soap); | |
| 16484 if (soap->mode & SOAP_IO_LENGTH) | |
| 16485 { soap_envelope_begin_out(soap); | |
| 16486 soap_putheader(soap); | |
| 16487 soap_body_begin_out(soap); | |
| 16488 soap_putfault(soap); | |
| 16489 soap_body_end_out(soap); | |
| 16490 soap_envelope_end_out(soap); | |
| 16491 } | |
| 16492 soap_end_count(soap); | |
| 16493 if (soap_response(soap, status) | |
| 16494 || soap_envelope_begin_out(soap) | |
| 16495 || soap_putheader(soap) | |
| 16496 || soap_body_begin_out(soap) | |
| 16497 || soap_putfault(soap) | |
| 16498 || soap_body_end_out(soap) | |
| 16499 || soap_envelope_end_out(soap)) | |
| 16500 return soap_closesock(soap); | |
| 16501 soap_end_send(soap); | |
| 16502 } | |
| 16503 } | |
| 16504 soap->error = status; | |
| 16505 return soap_closesock(soap); | |
| 16506 } | |
| 16507 #endif | |
| 16508 | |
| 16509 /******************************************************************************/ | |
| 16510 #ifndef PALM_1 | |
| 16511 SOAP_FMAC1 | |
| 16512 int | |
| 16513 SOAP_FMAC2 | |
| 16514 soap_recv_fault(struct soap *soap, int check) | |
| 16515 { register int status = soap->error; | |
| 16516 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Check if receiving SOAP Fault\n")); | |
| 16517 if (!check) | |
| 16518 { /* try getfault when no tag or tag mismatched at level 2, otherwise ret */ | |
| 16519 if (soap->error != SOAP_NO_TAG | |
| 16520 && (soap->error != SOAP_TAG_MISMATCH || soap->level != 2)) | |
| 16521 return soap->error; | |
| 16522 } | |
| 16523 else if (soap->version == 0) /* check == 1 but no SOAP: do not parse SOAP Fault */ | |
| 16524 return SOAP_OK; | |
| 16525 soap->error = SOAP_OK; | |
| 16526 if (soap_getfault(soap)) | |
| 16527 { /* check flag set: check if SOAP Fault is present, if not just return */ | |
| 16528 if (check && soap->error == SOAP_TAG_MISMATCH && soap->level == 2) | |
| 16529 return soap->error = SOAP_OK; | |
| 16530 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Error: soap_get_soapfault() failed at level %u tag '%s'\n", soap->level, soap->tag)); | |
| 16531 *soap_faultcode(soap) = (soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client"); | |
| 16532 soap->error = status; | |
| 16533 soap_set_fault(soap); | |
| 16534 } | |
| 16535 else | |
| 16536 { register const char *s = *soap_faultcode(soap); | |
| 16537 if (!soap_match_tag(soap, s, "SOAP-ENV:Server") || !soap_match_tag(soap, s, "SOAP-ENV:Receiver")) | |
| 16538 status = SOAP_SVR_FAULT; | |
| 16539 else if (!soap_match_tag(soap, s, "SOAP-ENV:Client") || !soap_match_tag(soap, s, "SOAP-ENV:Sender")) | |
| 16540 status = SOAP_CLI_FAULT; | |
| 16541 else if (!soap_match_tag(soap, s, "SOAP-ENV:MustUnderstand")) | |
| 16542 status = SOAP_MUSTUNDERSTAND; | |
| 16543 else if (!soap_match_tag(soap, s, "SOAP-ENV:VersionMismatch")) | |
| 16544 status = SOAP_VERSIONMISMATCH; | |
| 16545 else | |
| 16546 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Received SOAP Fault code %s\n", s)); | |
| 16547 status = SOAP_FAULT; | |
| 16548 } | |
| 16549 if (!soap_body_end_in(soap)) | |
| 16550 soap_envelope_end_in(soap); | |
| 16551 } | |
| 16552 soap_end_recv(soap); | |
| 16553 soap->error = status; | |
| 16554 return soap_closesock(soap); | |
| 16555 } | |
| 16556 #endif | |
| 16557 | |
| 16558 /******************************************************************************/ | |
| 16559 #ifndef WITH_NOHTTP | |
| 16560 #ifndef PALM_1 | |
| 16561 SOAP_FMAC1 | |
| 16562 int | |
| 16563 SOAP_FMAC2 | |
| 16564 soap_send_empty_response(struct soap *soap, int httpstatuscode) | |
| 16565 { register soap_mode m = soap->omode; | |
| 16566 if (!(m & SOAP_IO_UDP)) | |
| 16567 { soap->count = 0; | |
| 16568 if ((m & SOAP_IO) == SOAP_IO_CHUNK) | |
| 16569 soap->omode = (m & ~SOAP_IO) | SOAP_IO_BUFFER; | |
| 16570 soap_response(soap, httpstatuscode); | |
| 16571 soap_end_send(soap); /* force end of sends */ | |
| 16572 soap->error = SOAP_STOP; /* stops the server (from returning a response) */ | |
| 16573 soap->omode = m; | |
| 16574 } | |
| 16575 return soap_closesock(soap); | |
| 16576 } | |
| 16577 #endif | |
| 16578 #endif | |
| 16579 | |
| 16580 /******************************************************************************/ | |
| 16581 #ifndef WITH_NOHTTP | |
| 16582 #ifndef PALM_1 | |
| 16583 SOAP_FMAC1 | |
| 16584 int | |
| 16585 SOAP_FMAC2 | |
| 16586 soap_recv_empty_response(struct soap *soap) | |
| 16587 { if (!(soap->omode & SOAP_IO_UDP)) | |
| 16588 { if (!soap_begin_recv(soap)) | |
| 16589 { | |
| 16590 #ifndef WITH_LEAN | |
| 16591 if (soap->body) | |
| 16592 soap_get_http_body(soap, NULL); /* read (empty?) HTTP body and discard */ | |
| 16593 #endif | |
| 16594 soap_end_recv(soap); | |
| 16595 } | |
| 16596 else if (soap->error == SOAP_NO_DATA || soap->error == 202) | |
| 16597 soap->error = SOAP_OK; | |
| 16598 } | |
| 16599 return soap_closesock(soap); | |
| 16600 } | |
| 16601 #endif | |
| 16602 #endif | |
| 16603 | |
| 16604 /******************************************************************************/ | |
| 16605 #ifndef WITH_NOIO | |
| 16606 #ifndef PALM_1 | |
| 16607 static const char* | |
| 16608 soap_strerror(struct soap *soap) | |
| 16609 { register int err = soap->errnum; | |
| 16610 *soap->msgbuf = '\0'; | |
| 16611 if (err) | |
| 16612 { | |
| 16613 #ifndef WIN32 | |
| 16614 # ifdef HAVE_STRERROR_R | |
| 16615 # ifdef _GNU_SOURCE | |
| 16616 return strerror_r(err, soap->msgbuf, sizeof(soap->msgbuf)); /* GNU-specific */ | |
| 16617 # else | |
| 16618 strerror_r(err, soap->msgbuf, sizeof(soap->msgbuf)); /* XSI-compliant */ | |
| 16619 # endif | |
| 16620 # else | |
| 16621 return strerror(err); | |
| 16622 # endif | |
| 16623 #else | |
| 16624 #ifndef UNDER_CE | |
| 16625 DWORD len; | |
| 16626 *soap->msgbuf = '\0'; | |
| 16627 len = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)soap->msgbuf, (DWORD)sizeof(soap->msgbuf), NULL); | |
| 16628 #else | |
| 16629 DWORD i, len; | |
| 16630 *soap->msgbuf = '\0'; | |
| 16631 len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, 0, (LPTSTR)soap->msgbuf, (DWORD)(sizeof(soap->msgbuf)/sizeof(TCHAR)), NULL); | |
| 16632 for (i = 0; i <= len; i++) | |
| 16633 { if (((TCHAR*)soap->msgbuf)[i] < 0x80) | |
| 16634 soap->msgbuf[i] = (char)((TCHAR*)soap->msgbuf)[i]; | |
| 16635 else | |
| 16636 soap->msgbuf[i] = '?'; | |
| 16637 } | |
| 16638 #endif | |
| 16639 #endif | |
| 16640 } | |
| 16641 else | |
| 16642 { char *s = soap->msgbuf; | |
| 16643 #ifndef WITH_LEAN | |
| 16644 int rt = soap->recv_timeout, st = soap->send_timeout; | |
| 16645 int ru = ' ', su = ' '; | |
| 16646 #endif | |
| 16647 strcpy(s, "Operation interrupted or timed out"); | |
| 16648 #ifndef WITH_LEAN | |
| 16649 if (rt < 0) | |
| 16650 { rt = -rt; | |
| 16651 ru = 'u'; | |
| 16652 } | |
| 16653 if (st < 0) | |
| 16654 { st = -st; | |
| 16655 su = 'u'; | |
| 16656 } | |
| 16657 if (rt) | |
| 16658 { | |
| 16659 #ifdef HAVE_SNPRINTF | |
| 16660 size_t l = strlen(s); | |
| 16661 soap_snprintf(s + l, sizeof(soap->msgbuf) - l, " (%d%cs recv delay)", rt, ru); | |
| 16662 #else | |
| 16663 sprintf(s + strlen(s), " (%d%cs recv delay)", rt, ru); | |
| 16664 #endif | |
| 16665 } | |
| 16666 if (st) | |
| 16667 { | |
| 16668 #ifdef HAVE_SNPRINTF | |
| 16669 size_t l = strlen(s); | |
| 16670 soap_snprintf(s + l, sizeof(soap->msgbuf) - l, " (%d%cs send delay)", st, su); | |
| 16671 #else | |
| 16672 sprintf(s + strlen(s), " (%d%cs send delay)", st, su); | |
| 16673 #endif | |
| 16674 } | |
| 16675 #endif | |
| 16676 } | |
| 16677 return soap->msgbuf; | |
| 16678 } | |
| 16679 #endif | |
| 16680 #endif | |
| 16681 | |
| 16682 /******************************************************************************/ | |
| 16683 #ifndef PALM_2 | |
| 16684 static int | |
| 16685 soap_set_error(struct soap *soap, const char *faultcode, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML, int soaperror) | |
| 16686 { *soap_faultcode(soap) = faultcode; | |
| 16687 if (faultsubcodeQName) | |
| 16688 *soap_faultsubcode(soap) = faultsubcodeQName; | |
| 16689 *soap_faultstring(soap) = faultstring; | |
| 16690 if (faultdetailXML && *faultdetailXML) | |
| 16691 { register const char **s = soap_faultdetail(soap); | |
| 16692 if (s) | |
| 16693 *s = faultdetailXML; | |
| 16694 } | |
| 16695 return soap->error = soaperror; | |
| 16696 } | |
| 16697 #endif | |
| 16698 | |
| 16699 /******************************************************************************/ | |
| 16700 #ifndef PALM_2 | |
| 16701 SOAP_FMAC1 | |
| 16702 int | |
| 16703 SOAP_FMAC2 | |
| 16704 soap_set_sender_error(struct soap *soap, const char *faultstring, const char *faultdetailXML, int soaperror) | |
| 16705 { return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", NULL, faultstring, faultdetailXML, soaperror); | |
| 16706 } | |
| 16707 #endif | |
| 16708 | |
| 16709 /******************************************************************************/ | |
| 16710 #ifndef PALM_2 | |
| 16711 SOAP_FMAC1 | |
| 16712 int | |
| 16713 SOAP_FMAC2 | |
| 16714 soap_set_receiver_error(struct soap *soap, const char *faultstring, const char *faultdetailXML, int soaperror) | |
| 16715 { return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", NULL, faultstring, faultdetailXML, soaperror); | |
| 16716 } | |
| 16717 #endif | |
| 16718 | |
| 16719 /******************************************************************************/ | |
| 16720 #ifndef PALM_2 | |
| 16721 static int | |
| 16722 soap_copy_fault(struct soap *soap, const char *faultcode, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML) | |
| 16723 { char *r = NULL, *s = NULL, *t = NULL; | |
| 16724 if (faultsubcodeQName) | |
| 16725 r = soap_strdup(soap, faultsubcodeQName); | |
| 16726 if (faultstring) | |
| 16727 s = soap_strdup(soap, faultstring); | |
| 16728 if (faultdetailXML) | |
| 16729 t = soap_strdup(soap, faultdetailXML); | |
| 16730 return soap_set_error(soap, faultcode, r, s, t, SOAP_FAULT); | |
| 16731 } | |
| 16732 #endif | |
| 16733 | |
| 16734 /******************************************************************************/ | |
| 16735 #ifndef PALM_2 | |
| 16736 SOAP_FMAC1 | |
| 16737 int | |
| 16738 SOAP_FMAC2 | |
| 16739 soap_sender_fault(struct soap *soap, const char *faultstring, const char *faultdetailXML) | |
| 16740 { return soap_sender_fault_subcode(soap, NULL, faultstring, faultdetailXML); | |
| 16741 } | |
| 16742 #endif | |
| 16743 | |
| 16744 /******************************************************************************/ | |
| 16745 #ifndef PALM_2 | |
| 16746 SOAP_FMAC1 | |
| 16747 int | |
| 16748 SOAP_FMAC2 | |
| 16749 soap_sender_fault_subcode(struct soap *soap, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML) | |
| 16750 { return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", faultsubcodeQName, faultstring, faultdetailXML); | |
| 16751 } | |
| 16752 #endif | |
| 16753 | |
| 16754 /******************************************************************************/ | |
| 16755 #ifndef PALM_2 | |
| 16756 SOAP_FMAC1 | |
| 16757 int | |
| 16758 SOAP_FMAC2 | |
| 16759 soap_receiver_fault(struct soap *soap, const char *faultstring, const char *faultdetailXML) | |
| 16760 { return soap_receiver_fault_subcode(soap, NULL, faultstring, faultdetailXML); | |
| 16761 } | |
| 16762 #endif | |
| 16763 | |
| 16764 /******************************************************************************/ | |
| 16765 #ifndef PALM_2 | |
| 16766 SOAP_FMAC1 | |
| 16767 int | |
| 16768 SOAP_FMAC2 | |
| 16769 soap_receiver_fault_subcode(struct soap *soap, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML) | |
| 16770 { return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", faultsubcodeQName, faultstring, faultdetailXML); | |
| 16771 } | |
| 16772 #endif | |
| 16773 | |
| 16774 /******************************************************************************/ | |
| 16775 #ifndef PALM_2 | |
| 16776 #ifndef WITH_NOSTDLIB | |
| 16777 SOAP_FMAC1 | |
| 16778 void | |
| 16779 SOAP_FMAC2 | |
| 16780 soap_print_fault(struct soap *soap, FILE *fd) | |
| 16781 { if (soap_check_state(soap)) | |
| 16782 fprintf(fd, "Error: soap struct state not initialized\n"); | |
| 16783 else if (soap->error) | |
| 16784 { const char **c, *v = NULL, *s, *d; | |
| 16785 c = soap_faultcode(soap); | |
| 16786 if (!*c) | |
| 16787 soap_set_fault(soap); | |
| 16788 if (soap->version == 2) | |
| 16789 v = soap_check_faultsubcode(soap); | |
| 16790 s = *soap_faultstring(soap); | |
| 16791 d = soap_check_faultdetail(soap); | |
| 16792 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]"); | |
| 16793 } | |
| 16794 } | |
| 16795 #endif | |
| 16796 #endif | |
| 16797 | |
| 16798 /******************************************************************************/ | |
| 16799 #ifdef __cplusplus | |
| 16800 #ifndef WITH_LEAN | |
| 16801 #ifndef WITH_NOSTDLIB | |
| 16802 #ifndef WITH_COMPAT | |
| 16803 SOAP_FMAC1 | |
| 16804 void | |
| 16805 SOAP_FMAC2 | |
| 16806 soap_stream_fault(struct soap *soap, std::ostream& os) | |
| 16807 { if (soap_check_state(soap)) | |
| 16808 os << "Error: soap struct state not initialized\n"; | |
| 16809 else if (soap->error) | |
| 16810 { const char **c, *v = NULL, *s, *d; | |
| 16811 c = soap_faultcode(soap); | |
| 16812 if (!*c) | |
| 16813 soap_set_fault(soap); | |
| 16814 if (soap->version == 2) | |
| 16815 v = soap_check_faultsubcode(soap); | |
| 16816 s = *soap_faultstring(soap); | |
| 16817 d = soap_check_faultdetail(soap); | |
| 16818 os << (soap->version ? "SOAP 1." : "Error ") | |
| 16819 << (soap->version ? (int)soap->version : soap->error) | |
| 16820 << " fault: " << *c | |
| 16821 << "[" << (v ? v : "no subcode") << "]" | |
| 16822 << std::endl | |
| 16823 << "\"" << (s ? s : "[no reason]") << "\"" | |
| 16824 << std::endl | |
| 16825 << "Detail: " << (d ? d : "[no detail]") | |
| 16826 << std::endl; | |
| 16827 } | |
| 16828 } | |
| 16829 #endif | |
| 16830 #endif | |
| 16831 #endif | |
| 16832 #endif | |
| 16833 | |
| 16834 /******************************************************************************/ | |
| 16835 #ifndef WITH_LEAN | |
| 16836 #ifndef WITH_NOSTDLIB | |
| 16837 SOAP_FMAC1 | |
| 16838 char* | |
| 16839 SOAP_FMAC2 | |
| 16840 soap_sprint_fault(struct soap *soap, char *buf, size_t len) | |
| 16841 { if (soap_check_state(soap)) | |
| 16842 { strncpy(buf, "Error: soap struct not initialized", len); | |
| 16843 buf[len - 1] = '\0'; | |
| 16844 } | |
| 16845 else if (soap->error) | |
| 16846 { const char **c, *v = NULL, *s, *d; | |
| 16847 c = soap_faultcode(soap); | |
| 16848 if (!*c) | |
| 16849 soap_set_fault(soap); | |
| 16850 if (soap->version == 2) | |
| 16851 v = *soap_faultsubcode(soap); | |
| 16852 s = *soap_faultstring(soap); | |
| 16853 d = soap_check_faultdetail(soap); | |
| 16854 #ifdef HAVE_SNPRINTF | |
| 16855 soap_snprintf(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 : "[no detail]"); | |
| 16856 #else | |
| 16857 if (len > 40 + (v ? strlen(v) : 0) + (s ? strlen(s) : 0) + (d ? strlen(d) : 0)) | |
| 16858 sprintf(buf, "%s%d fault: %s [%s]\n\"%s\"\nDetail: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, *c, v ? v : "no subcode", s ? s : "[no reason]", d ? d : "[no detail]"); | |
| 16859 else if (len > 40) | |
| 16860 sprintf(buf, "%s%d fault: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, *c); | |
| 16861 else | |
| 16862 buf[0] = '\0'; | |
| 16863 #endif | |
| 16864 } | |
| 16865 return buf; | |
| 16866 } | |
| 16867 #endif | |
| 16868 #endif | |
| 16869 | |
| 16870 /******************************************************************************/ | |
| 16871 #ifndef PALM_1 | |
| 16872 #ifndef WITH_NOSTDLIB | |
| 16873 SOAP_FMAC1 | |
| 16874 void | |
| 16875 SOAP_FMAC2 | |
| 16876 soap_print_fault_location(struct soap *soap, FILE *fd) | |
| 16877 { | |
| 16878 #ifndef WITH_LEAN | |
| 16879 int i, j, c1, c2; | |
| 16880 if (soap->error && soap->error != SOAP_STOP && soap->bufidx <= soap->buflen && soap->buflen > 0 && soap->buflen <= SOAP_BUFLEN) | |
| 16881 { i = (int)soap->bufidx - 1; | |
| 16882 if (i <= 0) | |
| 16883 i = 0; | |
| 16884 c1 = soap->buf[i]; | |
| 16885 soap->buf[i] = '\0'; | |
| 16886 if ((int)soap->buflen >= i + 1024) | |
| 16887 j = i + 1023; | |
| 16888 else | |
| 16889 j = (int)soap->buflen - 1; | |
| 16890 c2 = soap->buf[j]; | |
| 16891 soap->buf[j] = '\0'; | |
| 16892 fprintf(fd, "%s%c\n<!-- ** HERE ** -->\n", soap->buf, c1); | |
| 16893 if (soap->bufidx < soap->buflen) | |
| 16894 fprintf(fd, "%s\n", soap->buf + soap->bufidx); | |
| 16895 soap->buf[i] = (char)c1; | |
| 16896 soap->buf[j] = (char)c2; | |
| 16897 } | |
| 16898 #endif | |
| 16899 } | |
| 16900 #endif | |
| 16901 #endif | |
| 16902 | |
| 16903 /******************************************************************************/ | |
| 16904 #ifndef PALM_1 | |
| 16905 SOAP_FMAC1 | |
| 16906 int | |
| 16907 SOAP_FMAC2 | |
| 16908 soap_register_plugin_arg(struct soap *soap, int (*fcreate)(struct soap*, struct soap_plugin*, void*), void *arg) | |
| 16909 { register struct soap_plugin *p; | |
| 16910 register int r; | |
| 16911 if (!(p = (struct soap_plugin*)SOAP_MALLOC(soap, sizeof(struct soap_plugin)))) | |
| 16912 return soap->error = SOAP_EOM; | |
| 16913 p->id = NULL; | |
| 16914 p->data = NULL; | |
| 16915 p->fcopy = NULL; | |
| 16916 p->fdelete = NULL; | |
| 16917 r = fcreate(soap, p, arg); | |
| 16918 if (!r && p->fdelete) | |
| 16919 { p->next = soap->plugins; | |
| 16920 soap->plugins = p; | |
| 16921 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Registered '%s' plugin\n", p->id)); | |
| 16922 return SOAP_OK; | |
| 16923 } | |
| 16924 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not register plugin '%s': plugin returned error %d (or fdelete callback not set)\n", p->id ? p->id : "?", r)); | |
| 16925 SOAP_FREE(soap, p); | |
| 16926 return r; | |
| 16927 } | |
| 16928 #endif | |
| 16929 | |
| 16930 /******************************************************************************/ | |
| 16931 #ifndef PALM_1 | |
| 16932 static void * | |
| 16933 fplugin(struct soap *soap, const char *id) | |
| 16934 { register struct soap_plugin *p; | |
| 16935 for (p = soap->plugins; p; p = p->next) | |
| 16936 if (p->id == id || !strcmp(p->id, id)) | |
| 16937 return p->data; | |
| 16938 return NULL; | |
| 16939 } | |
| 16940 #endif | |
| 16941 | |
| 16942 /******************************************************************************/ | |
| 16943 #ifndef PALM_2 | |
| 16944 SOAP_FMAC1 | |
| 16945 void * | |
| 16946 SOAP_FMAC2 | |
| 16947 soap_lookup_plugin(struct soap *soap, const char *id) | |
| 16948 { return soap->fplugin(soap, id); | |
| 16949 } | |
| 16950 #endif | |
| 16951 | |
| 16952 /******************************************************************************/ | |
| 16953 #ifdef __cplusplus | |
| 16954 } | |
| 16955 #endif | |
| 16956 | |
| 16957 /******************************************************************************\ | |
| 16958 * | |
| 16959 * C++ soap struct methods | |
| 16960 * | |
| 16961 \******************************************************************************/ | |
| 16962 | |
| 16963 #ifdef __cplusplus | |
| 16964 soap::soap() | |
| 16965 { soap_init(this); | |
| 16966 } | |
| 16967 #endif | |
| 16968 | |
| 16969 /******************************************************************************/ | |
| 16970 #ifdef __cplusplus | |
| 16971 soap::soap(soap_mode m) | |
| 16972 { soap_init1(this, m); | |
| 16973 } | |
| 16974 #endif | |
| 16975 | |
| 16976 /******************************************************************************/ | |
| 16977 #ifdef __cplusplus | |
| 16978 soap::soap(soap_mode im, soap_mode om) | |
| 16979 { soap_init2(this, im, om); | |
| 16980 } | |
| 16981 #endif | |
| 16982 | |
| 16983 /******************************************************************************/ | |
| 16984 #ifdef __cplusplus | |
| 16985 soap::soap(const struct soap& soap) | |
| 16986 { soap_copy_context(this, &soap); | |
| 16987 } | |
| 16988 #endif | |
| 16989 | |
| 16990 /******************************************************************************/ | |
| 16991 #ifdef __cplusplus | |
| 16992 soap::~soap() | |
| 16993 { soap_destroy(this); | |
| 16994 soap_end(this); | |
| 16995 soap_done(this); | |
| 16996 } | |
| 16997 #endif | |
| 16998 | |
| 16999 /******************************************************************************/ |
