00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 #ifdef AS400
00067 # pragma convert(819)
00068 #endif
00069
00070 #include "stdsoap2.h"
00071
00072 #ifdef __BORLANDC__
00073 # pragma warn -8060
00074 #else
00075 # ifdef WIN32
00076 # ifdef UNDER_CE
00077 # pragma comment(lib, "ws2.lib")
00078 # else
00079 # pragma comment(lib, "ws2_32.lib")
00080 # endif
00081 # pragma warning(disable : 4996)
00082 # endif
00083 #endif
00084
00085 #ifdef __cplusplus
00086 SOAP_SOURCE_STAMP("@(#) stdsoap2.cpp ver 2.8.3 2011-06-24 00:00:00 GMT")
00087 extern "C" {
00088 #else
00089 SOAP_SOURCE_STAMP("@(#) stdsoap2.c ver 2.8.3 2011-06-24 00:00:00 GMT")
00090 #endif
00091
00092
00093 #ifndef SOAP_UNKNOWN_CHAR
00094 #define SOAP_UNKNOWN_CHAR (127)
00095 #endif
00096
00097
00098 #define SOAP_LT (soap_wchar)(-2)
00099 #define SOAP_TT (soap_wchar)(-3)
00100 #define SOAP_GT (soap_wchar)(-4)
00101 #define SOAP_QT (soap_wchar)(-5)
00102 #define SOAP_AP (soap_wchar)(-6)
00103
00104 #define soap_blank(c) ((c) >= 0 && (c) <= 32)
00105 #define soap_notblank(c) ((c) > 32)
00106
00107 #if defined(WIN32) && !defined(UNDER_CE)
00108 #define soap_hash_ptr(p) ((PtrToUlong(p) >> 3) & (SOAP_PTRHASH - 1))
00109 #else
00110 #define soap_hash_ptr(p) ((size_t)(((unsigned long)(p) >> 3) & (SOAP_PTRHASH-1)))
00111 #endif
00112
00113 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
00114 static void soap_init_logs(struct soap*);
00115 #endif
00116 #ifdef SOAP_DEBUG
00117 static void soap_close_logfile(struct soap*, int);
00118 static void soap_set_logfile(struct soap*, int, const char*);
00119 #endif
00120
00121 #ifdef SOAP_MEM_DEBUG
00122 static void soap_init_mht(struct soap*);
00123 static void soap_free_mht(struct soap*);
00124 static void soap_track_unlink(struct soap*, const void*);
00125 #endif
00126
00127 #ifndef PALM_2
00128 static int soap_set_error(struct soap*, const char*, const char*, const char*, const char*, int);
00129 static int soap_copy_fault(struct soap*, const char*, const char*, const char*, const char*);
00130 static int soap_getattrval(struct soap*, char*, size_t, soap_wchar);
00131 #endif
00132
00133 #ifndef PALM_1
00134 static void soap_free_ns(struct soap *soap);
00135 static soap_wchar soap_char(struct soap*);
00136 static soap_wchar soap_get_pi(struct soap*);
00137 static int soap_isxdigit(int);
00138 static void *fplugin(struct soap*, const char*);
00139 static size_t soap_count_attachments(struct soap *soap);
00140 static int soap_try_connect_command(struct soap*, int http_command, const char *endpoint, const char *action);
00141 #ifndef WITH_NOIDREF
00142 static void soap_update_ptrs(struct soap*, char*, char*, char*, char*);
00143 static int soap_has_copies(struct soap*, const char*, const char*);
00144 static void soap_init_iht(struct soap*);
00145 static void soap_free_iht(struct soap*);
00146 static void soap_init_pht(struct soap*);
00147 static void soap_free_pht(struct soap*);
00148 #endif
00149 #endif
00150
00151 #ifndef WITH_LEAN
00152 static const char *soap_set_validation_fault(struct soap*, const char*, const char*);
00153 static int soap_isnumeric(struct soap*, const char*);
00154 static struct soap_nlist *soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized);
00155 static void soap_utilize_ns(struct soap *soap, const char *tag, size_t n);
00156 #endif
00157
00158 #ifndef WITH_LEANER
00159 #ifndef PALM_1
00160 static struct soap_multipart *soap_new_multipart(struct soap*, struct soap_multipart**, struct soap_multipart**, char*, size_t);
00161 static int soap_putdimefield(struct soap*, const char*, size_t);
00162 static char *soap_getdimefield(struct soap*, size_t);
00163 static void soap_select_mime_boundary(struct soap*);
00164 static int soap_valid_mime_boundary(struct soap*);
00165 static void soap_resolve_attachment(struct soap*, struct soap_multipart*);
00166 #endif
00167 #endif
00168
00169 #ifdef WITH_GZIP
00170 static int soap_getgziphdr(struct soap*);
00171 #endif
00172
00173 #ifdef WITH_OPENSSL
00174 # ifndef SOAP_SSL_RSA_BITS
00175 # define SOAP_SSL_RSA_BITS 2048
00176 # endif
00177 static int soap_ssl_init_done = 0;
00178 static int ssl_auth_init(struct soap*);
00179 static int ssl_verify_callback(int, X509_STORE_CTX*);
00180 static int ssl_verify_callback_allow_expired_certificate(int, X509_STORE_CTX*);
00181 static int ssl_password(char*, int, int, void *);
00182 #endif
00183
00184 #ifdef WITH_GNUTLS
00185 # ifndef SOAP_SSL_RSA_BITS
00186 # define SOAP_SSL_RSA_BITS 2048
00187 # endif
00188 static int soap_ssl_init_done = 0;
00189 static const char *ssl_verify(struct soap *soap, const char *host);
00190 # if defined(HAVE_PTHREAD_H)
00191 # include <pthread.h>
00192
00193 GCRY_THREAD_OPTION_PTHREAD_IMPL;
00194 # elif defined(HAVE_PTH_H)
00195 #include <pth.h>
00196
00197 GCRY_THREAD_OPTION_PTH_IMPL;
00198 # endif
00199 #endif
00200
00201 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
00202 #ifndef PALM_1
00203 static const char *soap_decode(char*, size_t, const char*, const char*);
00204 #endif
00205 #endif
00206
00207 #ifndef WITH_NOHTTP
00208 #ifndef PALM_1
00209 static soap_wchar soap_getchunkchar(struct soap*);
00210 static const char *http_error(struct soap*, int);
00211 static int http_put(struct soap*);
00212 static int http_get(struct soap*);
00213 static int http_405(struct soap*);
00214 static int http_post(struct soap*, const char*, const char*, int, const char*, const char*, size_t);
00215 static int http_send_header(struct soap*, const char*);
00216 static int http_post_header(struct soap*, const char*, const char*);
00217 static int http_response(struct soap*, int, size_t);
00218 static int http_parse(struct soap*);
00219 static int http_parse_header(struct soap*, const char*, const char*);
00220 #endif
00221 #endif
00222
00223 #ifndef WITH_NOIO
00224
00225 #ifndef PALM_1
00226 static int fsend(struct soap*, const char*, size_t);
00227 static size_t frecv(struct soap*, char*, size_t);
00228 static int tcp_init(struct soap*);
00229 static const char *tcp_error(struct soap*);
00230 #ifndef WITH_IPV6
00231 static int tcp_gethost(struct soap*, const char *addr, struct in_addr *inaddr);
00232 #endif
00233 static SOAP_SOCKET tcp_connect(struct soap*, const char *endpoint, const char *host, int port);
00234 static SOAP_SOCKET tcp_accept(struct soap*, SOAP_SOCKET, struct sockaddr*, int*);
00235 static int tcp_select(struct soap*, SOAP_SOCKET, int, int);
00236 static int tcp_disconnect(struct soap*);
00237 static int tcp_closesocket(struct soap*, SOAP_SOCKET);
00238 static int tcp_shutdownsocket(struct soap*, SOAP_SOCKET, int);
00239 static const char *soap_strerror(struct soap*);
00240 #endif
00241
00242 #define SOAP_TCP_SELECT_RCV 0x1
00243 #define SOAP_TCP_SELECT_SND 0x2
00244 #define SOAP_TCP_SELECT_ERR 0x4
00245 #define SOAP_TCP_SELECT_ALL 0x7
00246
00247 #if defined(WIN32)
00248 #define SOAP_SOCKBLOCK(fd) \
00249 { u_long blocking = 0; \
00250 ioctlsocket(fd, FIONBIO, &blocking); \
00251 }
00252 #define SOAP_SOCKNONBLOCK(fd) \
00253 { u_long nonblocking = 1; \
00254 ioctlsocket(fd, FIONBIO, &nonblocking); \
00255 }
00256 #elif defined(VXWORKS)
00257 #define SOAP_SOCKBLOCK(fd) \
00258 { u_long blocking = 0; \
00259 ioctl(fd, FIONBIO, (int)(&blocking)); \
00260 }
00261 #define SOAP_SOCKNONBLOCK(fd) \
00262 { u_long nonblocking = 1; \
00263 ioctl(fd, FIONBIO, (int)(&nonblocking)); \
00264 }
00265 #elif defined(__VMS)
00266 #define SOAP_SOCKBLOCK(fd) \
00267 { int blocking = 0; \
00268 ioctl(fd, FIONBIO, &blocking); \
00269 }
00270 #define SOAP_SOCKNONBLOCK(fd) \
00271 { int nonblocking = 1; \
00272 ioctl(fd, FIONBIO, &nonblocking); \
00273 }
00274 #elif defined(PALM)
00275 #define SOAP_SOCKBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)&~O_NONBLOCK);
00276 #define SOAP_SOCKNONBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)|O_NONBLOCK);
00277 #elif defined(SYMBIAN)
00278 #define SOAP_SOCKBLOCK(fd) \
00279 { long blocking = 0; \
00280 ioctl(fd, 0, &blocking); \
00281 }
00282 #define SOAP_SOCKNONBLOCK(fd) \
00283 { long nonblocking = 1; \
00284 ioctl(fd, 0, &nonblocking); \
00285 }
00286 #else
00287 #define SOAP_SOCKBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)&~O_NONBLOCK);
00288 #define SOAP_SOCKNONBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)|O_NONBLOCK);
00289 #endif
00290
00291 #endif
00292
00293 #if defined(PALM) && !defined(PALM_2)
00294 unsigned short errno;
00295 #endif
00296
00297 #ifndef PALM_1
00298 static const char soap_env1[42] = "http://schemas.xmlsoap.org/soap/envelope/";
00299 static const char soap_enc1[42] = "http://schemas.xmlsoap.org/soap/encoding/";
00300 static const char soap_env2[40] = "http://www.w3.org/2003/05/soap-envelope";
00301 static const char soap_enc2[40] = "http://www.w3.org/2003/05/soap-encoding";
00302 static const char soap_rpc[35] = "http://www.w3.org/2003/05/soap-rpc";
00303 #endif
00304
00305 #ifndef PALM_1
00306 const union soap_double_nan soap_double_nan = {{0xFFFFFFFF, 0xFFFFFFFF}};
00307 const char soap_base64o[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00308 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";
00309 #endif
00310
00311 #ifndef WITH_LEAN
00312 static const char soap_indent[11] = "\n\t\t\t\t\t\t\t\t\t";
00313
00314
00315
00316 #endif
00317
00318 #ifndef SOAP_CANARY
00319 # define SOAP_CANARY (0xC0DE)
00320 #endif
00321
00322 static const char soap_padding[4] = "\0\0\0";
00323 #define SOAP_STR_PADDING (soap_padding)
00324 #define SOAP_STR_EOS (soap_padding)
00325 #define SOAP_NON_NULL (soap_padding)
00326
00327 #ifndef WITH_LEAN
00328 static const struct soap_code_map html_entity_codes[] =
00329 { { 160, "nbsp" },
00330 { 161, "iexcl" },
00331 { 162, "cent" },
00332 { 163, "pound" },
00333 { 164, "curren" },
00334 { 165, "yen" },
00335 { 166, "brvbar" },
00336 { 167, "sect" },
00337 { 168, "uml" },
00338 { 169, "copy" },
00339 { 170, "ordf" },
00340 { 171, "laquo" },
00341 { 172, "not" },
00342 { 173, "shy" },
00343 { 174, "reg" },
00344 { 175, "macr" },
00345 { 176, "deg" },
00346 { 177, "plusmn" },
00347 { 178, "sup2" },
00348 { 179, "sup3" },
00349 { 180, "acute" },
00350 { 181, "micro" },
00351 { 182, "para" },
00352 { 183, "middot" },
00353 { 184, "cedil" },
00354 { 185, "sup1" },
00355 { 186, "ordm" },
00356 { 187, "raquo" },
00357 { 188, "frac14" },
00358 { 189, "frac12" },
00359 { 190, "frac34" },
00360 { 191, "iquest" },
00361 { 192, "Agrave" },
00362 { 193, "Aacute" },
00363 { 194, "Acirc" },
00364 { 195, "Atilde" },
00365 { 196, "Auml" },
00366 { 197, "Aring" },
00367 { 198, "AElig" },
00368 { 199, "Ccedil" },
00369 { 200, "Egrave" },
00370 { 201, "Eacute" },
00371 { 202, "Ecirc" },
00372 { 203, "Euml" },
00373 { 204, "Igrave" },
00374 { 205, "Iacute" },
00375 { 206, "Icirc" },
00376 { 207, "Iuml" },
00377 { 208, "ETH" },
00378 { 209, "Ntilde" },
00379 { 210, "Ograve" },
00380 { 211, "Oacute" },
00381 { 212, "Ocirc" },
00382 { 213, "Otilde" },
00383 { 214, "Ouml" },
00384 { 215, "times" },
00385 { 216, "Oslash" },
00386 { 217, "Ugrave" },
00387 { 218, "Uacute" },
00388 { 219, "Ucirc" },
00389 { 220, "Uuml" },
00390 { 221, "Yacute" },
00391 { 222, "THORN" },
00392 { 223, "szlig" },
00393 { 224, "agrave" },
00394 { 225, "aacute" },
00395 { 226, "acirc" },
00396 { 227, "atilde" },
00397 { 228, "auml" },
00398 { 229, "aring" },
00399 { 230, "aelig" },
00400 { 231, "ccedil" },
00401 { 232, "egrave" },
00402 { 233, "eacute" },
00403 { 234, "ecirc" },
00404 { 235, "euml" },
00405 { 236, "igrave" },
00406 { 237, "iacute" },
00407 { 238, "icirc" },
00408 { 239, "iuml" },
00409 { 240, "eth" },
00410 { 241, "ntilde" },
00411 { 242, "ograve" },
00412 { 243, "oacute" },
00413 { 244, "ocirc" },
00414 { 245, "otilde" },
00415 { 246, "ouml" },
00416 { 247, "divide" },
00417 { 248, "oslash" },
00418 { 249, "ugrave" },
00419 { 250, "uacute" },
00420 { 251, "ucirc" },
00421 { 252, "uuml" },
00422 { 253, "yacute" },
00423 { 254, "thorn" },
00424 { 255, "yuml" },
00425 { 0, NULL }
00426 };
00427 #endif
00428
00429 #ifndef WITH_NOIO
00430 #ifndef WITH_LEAN
00431 static const struct soap_code_map h_error_codes[] =
00432 {
00433 #ifdef HOST_NOT_FOUND
00434 { HOST_NOT_FOUND, "Host not found" },
00435 #endif
00436 #ifdef TRY_AGAIN
00437 { TRY_AGAIN, "Try Again" },
00438 #endif
00439 #ifdef NO_RECOVERY
00440 { NO_RECOVERY, "No Recovery" },
00441 #endif
00442 #ifdef NO_DATA
00443 { NO_DATA, "No Data" },
00444 #endif
00445 #ifdef NO_ADDRESS
00446 { NO_ADDRESS, "No Address" },
00447 #endif
00448 { 0, NULL }
00449 };
00450 #endif
00451 #endif
00452
00453 #ifndef WITH_NOHTTP
00454 #ifndef WITH_LEAN
00455 static const struct soap_code_map h_http_error_codes[] =
00456 { { 200, "OK" },
00457 { 201, "Created" },
00458 { 202, "Accepted" },
00459 { 203, "Non-Authoritative Information" },
00460 { 204, "No Content" },
00461 { 205, "Reset Content" },
00462 { 206, "Partial Content" },
00463 { 300, "Multiple Choices" },
00464 { 301, "Moved Permanently" },
00465 { 302, "Found" },
00466 { 303, "See Other" },
00467 { 304, "Not Modified" },
00468 { 305, "Use Proxy" },
00469 { 307, "Temporary Redirect" },
00470 { 400, "Bad Request" },
00471 { 401, "Unauthorized" },
00472 { 402, "Payment Required" },
00473 { 403, "Forbidden" },
00474 { 404, "Not Found" },
00475 { 405, "Method Not Allowed" },
00476 { 406, "Not Acceptable" },
00477 { 407, "Proxy Authentication Required" },
00478 { 408, "Request Time-out" },
00479 { 409, "Conflict" },
00480 { 410, "Gone" },
00481 { 411, "Length Required" },
00482 { 412, "Precondition Failed" },
00483 { 413, "Request Entity Too Large" },
00484 { 414, "Request-URI Too Large" },
00485 { 415, "Unsupported Media Type" },
00486 { 416, "Requested range not satisfiable" },
00487 { 417, "Expectation Failed" },
00488 { 500, "Internal Server Error" },
00489 { 501, "Not Implemented" },
00490 { 502, "Bad Gateway" },
00491 { 503, "Service Unavailable" },
00492 { 504, "Gateway Time-out" },
00493 { 505, "HTTP Version not supported" },
00494 { 0, NULL }
00495 };
00496 #endif
00497 #endif
00498
00499 #ifdef WITH_OPENSSL
00500 static const struct soap_code_map h_ssl_error_codes[] =
00501 {
00502 #define _SSL_ERROR(e) { e, #e }
00503 _SSL_ERROR(SSL_ERROR_SSL),
00504 _SSL_ERROR(SSL_ERROR_ZERO_RETURN),
00505 _SSL_ERROR(SSL_ERROR_WANT_READ),
00506 _SSL_ERROR(SSL_ERROR_WANT_WRITE),
00507 _SSL_ERROR(SSL_ERROR_WANT_CONNECT),
00508 _SSL_ERROR(SSL_ERROR_WANT_X509_LOOKUP),
00509 _SSL_ERROR(SSL_ERROR_SYSCALL),
00510 { 0, NULL }
00511 };
00512 #endif
00513
00514 #ifndef WITH_LEANER
00515 static const struct soap_code_map mime_codes[] =
00516 { { SOAP_MIME_7BIT, "7bit" },
00517 { SOAP_MIME_8BIT, "8bit" },
00518 { SOAP_MIME_BINARY, "binary" },
00519 { SOAP_MIME_QUOTED_PRINTABLE, "quoted-printable" },
00520 { SOAP_MIME_BASE64, "base64" },
00521 { SOAP_MIME_IETF_TOKEN, "ietf-token" },
00522 { SOAP_MIME_X_TOKEN, "x-token" },
00523 { 0, NULL }
00524 };
00525 #endif
00526
00527 #ifdef WIN32
00528 static int tcp_done = 0;
00529 #endif
00530
00531 #if defined(HP_UX) && defined(HAVE_GETHOSTBYNAME_R)
00532 extern int h_errno;
00533 #endif
00534
00535
00536 #ifndef WITH_NOIO
00537 #ifndef PALM_1
00538 static int
00539 fsend(struct soap *soap, const char *s, size_t n)
00540 { register int nwritten, err;
00541 #if defined(__cplusplus) && !defined(WITH_LEAN) && !defined(WITH_COMPAT)
00542 if (soap->os)
00543 { soap->os->write(s, (std::streamsize)n);
00544 if (soap->os->good())
00545 return SOAP_OK;
00546 soap->errnum = 0;
00547 return SOAP_EOF;
00548 }
00549 #endif
00550 while (n)
00551 { if (soap_valid_socket(soap->socket))
00552 {
00553 if (soap->send_timeout)
00554 { for (;;)
00555 { register int r;
00556 #ifdef WITH_OPENSSL
00557 if (soap->ssl)
00558 r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_ALL, soap->send_timeout);
00559 else
00560 #endif
00561 #ifdef WITH_GNUTLS
00562 if (soap->session)
00563 r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_ALL, soap->send_timeout);
00564 else
00565 #endif
00566 r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->send_timeout);
00567 if (r > 0)
00568 break;
00569 if (!r)
00570 return SOAP_EOF;
00571 err = soap->errnum;
00572 if (!err)
00573 return soap->error;
00574 if (err != SOAP_EINTR && err != SOAP_EAGAIN && err != SOAP_EWOULDBLOCK)
00575 return SOAP_EOF;
00576 }
00577 }
00578 #ifdef WITH_OPENSSL
00579 if (soap->ssl)
00580 nwritten = SSL_write(soap->ssl, s, (int)n);
00581 else if (soap->bio)
00582 nwritten = BIO_write(soap->bio, s, (int)n);
00583 else
00584 #endif
00585 #ifdef WITH_GNUTLS
00586 if (soap->session)
00587 nwritten = gnutls_record_send(soap->session, s, n);
00588 else
00589 #endif
00590 #ifndef WITH_LEAN
00591 if ((soap->omode & SOAP_IO_UDP))
00592 { if (soap->peerlen)
00593 nwritten = sendto(soap->socket, (char*)s, (SOAP_WINSOCKINT)n, soap->socket_flags, (struct sockaddr*)&soap->peer, (SOAP_WINSOCKINT)soap->peerlen);
00594 else
00595 nwritten = send(soap->socket, s, (SOAP_WINSOCKINT)n, soap->socket_flags);
00596
00597
00598 if (nwritten < 0)
00599 { int udp_repeat;
00600 int udp_delay;
00601 if ((soap->connect_flags & SO_BROADCAST))
00602 udp_repeat = 3;
00603 else
00604 udp_repeat = 1;
00605 udp_delay = ((unsigned int)soap_random % 201) + 50;
00606 do
00607 { tcp_select(soap, soap->socket, SOAP_TCP_SELECT_ERR, -1000 * udp_delay);
00608 if (soap->peerlen)
00609 nwritten = sendto(soap->socket, (char*)s, (SOAP_WINSOCKINT)n, soap->socket_flags, (struct sockaddr*)&soap->peer, (SOAP_WINSOCKINT)soap->peerlen);
00610 else
00611 nwritten = send(soap->socket, s, (SOAP_WINSOCKINT)n, soap->socket_flags);
00612 udp_delay <<= 1;
00613 if (udp_delay > 500)
00614 udp_delay = 500;
00615 }
00616 while (nwritten < 0 && --udp_repeat > 0);
00617 }
00618 }
00619 else
00620 #endif
00621 #if !defined(PALM) && !defined(AS400)
00622 nwritten = send(soap->socket, s, (int)n, soap->socket_flags);
00623 #else
00624 nwritten = send(soap->socket, (void*)s, n, soap->socket_flags);
00625 #endif
00626 if (nwritten <= 0)
00627 {
00628 register int r = 0;
00629 err = soap_socket_errno(soap->socket);
00630 #ifdef WITH_OPENSSL
00631 if (soap->ssl && (r = SSL_get_error(soap->ssl, nwritten)) != SSL_ERROR_NONE && r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE)
00632 { soap->errnum = err;
00633 return SOAP_EOF;
00634 }
00635 #endif
00636 #ifdef WITH_GNUTLS
00637 if (soap->session)
00638 { if (nwritten == GNUTLS_E_INTERRUPTED)
00639 err = SOAP_EINTR;
00640 else if (nwritten == GNUTLS_E_AGAIN)
00641 err = SOAP_EAGAIN;
00642 }
00643 #endif
00644 if (err == SOAP_EWOULDBLOCK || err == SOAP_EAGAIN)
00645 {
00646 #if defined(WITH_OPENSSL)
00647 if (soap->ssl && r == SSL_ERROR_WANT_READ)
00648 r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->send_timeout ? soap->send_timeout : -10000);
00649 else
00650 #elif defined(WITH_GNUTLS)
00651 if (soap->session && !gnutls_record_get_direction(soap->session))
00652 r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->send_timeout ? soap->send_timeout : -10000);
00653 else
00654 #endif
00655 r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->send_timeout ? soap->send_timeout : -10000);
00656 if (!r && soap->send_timeout)
00657 return SOAP_EOF;
00658 if (r < 0 && soap->errnum != SOAP_EINTR)
00659 return SOAP_EOF;
00660 }
00661 else if (err && err != SOAP_EINTR)
00662 { soap->errnum = err;
00663 return SOAP_EOF;
00664 }
00665 nwritten = 0;
00666 }
00667 }
00668 else
00669 {
00670 #ifdef WITH_FASTCGI
00671 nwritten = fwrite((void*)s, 1, n, stdout);
00672 fflush(stdout);
00673 #else
00674 #ifdef UNDER_CE
00675 nwritten = fwrite(s, 1, n, soap->sendfd);
00676 #else
00677 #ifdef VXWORKS
00678 #ifdef WMW_RPM_IO
00679 if (soap->rpmreqid)
00680 nwritten = (httpBlockPut(soap->rpmreqid, (char*)s, n) == 0) ? n : -1;
00681 else
00682 #endif
00683 nwritten = fwrite(s, sizeof(char), n, fdopen(soap->sendfd, "w"));
00684 #else
00685 #ifdef WIN32
00686 nwritten = _write(soap->sendfd, s, (unsigned int)n);
00687 #else
00688 nwritten = write(soap->sendfd, s, (unsigned int)n);
00689 #endif
00690 #endif
00691 #endif
00692 #endif
00693 if (nwritten <= 0)
00694 {
00695 #ifndef WITH_FASTCGI
00696 err = soap_errno;
00697 #else
00698 err = EOF;
00699 #endif
00700 if (err && err != SOAP_EINTR && err != SOAP_EWOULDBLOCK && err != SOAP_EAGAIN)
00701 { soap->errnum = err;
00702 return SOAP_EOF;
00703 }
00704 nwritten = 0;
00705 }
00706 }
00707 n -= nwritten;
00708 s += nwritten;
00709 }
00710 return SOAP_OK;
00711 }
00712 #endif
00713 #endif
00714
00715
00716 #ifndef PALM_1
00717 SOAP_FMAC1
00718 int
00719 SOAP_FMAC2
00720 soap_send_raw(struct soap *soap, const char *s, size_t n)
00721 { if (!n)
00722 return SOAP_OK;
00723 #ifndef WITH_LEANER
00724 if (soap->fpreparesend && (soap->mode & SOAP_IO) != SOAP_IO_STORE && (soap->mode & SOAP_IO_LENGTH) && (soap->error = soap->fpreparesend(soap, s, n)))
00725 return soap->error;
00726 if (soap->ffiltersend && (soap->error = soap->ffiltersend(soap, &s, &n)))
00727 return soap->error;
00728 #endif
00729 if (soap->mode & SOAP_IO_LENGTH)
00730 soap->count += n;
00731 else if (soap->mode & SOAP_IO)
00732 { register size_t i = SOAP_BUFLEN - soap->bufidx;
00733 while (n >= i)
00734 { memcpy(soap->buf + soap->bufidx, s, i);
00735 soap->bufidx = SOAP_BUFLEN;
00736 if (soap_flush(soap))
00737 return soap->error;
00738 s += i;
00739 n -= i;
00740 i = SOAP_BUFLEN;
00741 }
00742 memcpy(soap->buf + soap->bufidx, s, n);
00743 soap->bufidx += n;
00744 }
00745 else
00746 return soap_flush_raw(soap, s, n);
00747 return SOAP_OK;
00748 }
00749 #endif
00750
00751
00752 #ifndef PALM_1
00753 SOAP_FMAC1
00754 int
00755 SOAP_FMAC2
00756 soap_flush(struct soap *soap)
00757 { register size_t n = soap->bufidx;
00758 if (n)
00759 {
00760 #ifndef WITH_LEANER
00761 if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
00762 { register int r;
00763 if (soap->fpreparesend && (r = soap->fpreparesend(soap, soap->buf, n)))
00764 return soap->error = r;
00765 }
00766 #endif
00767 soap->bufidx = 0;
00768 #ifdef WITH_ZLIB
00769 if (soap->mode & SOAP_ENC_ZLIB)
00770 { soap->d_stream->next_in = (Byte*)soap->buf;
00771 soap->d_stream->avail_in = (unsigned int)n;
00772 #ifdef WITH_GZIP
00773 soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)n);
00774 #endif
00775 do
00776 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating %u bytes\n", soap->d_stream->avail_in));
00777 if (deflate(soap->d_stream, Z_NO_FLUSH) != Z_OK)
00778 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to deflate: %s\n", soap->d_stream->msg?soap->d_stream->msg:SOAP_STR_EOS));
00779 return soap->error = SOAP_ZLIB_ERROR;
00780 }
00781 if (!soap->d_stream->avail_out)
00782 { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN))
00783 return soap->error;
00784 soap->d_stream->next_out = (Byte*)soap->z_buf;
00785 soap->d_stream->avail_out = SOAP_BUFLEN;
00786 }
00787 } while (soap->d_stream->avail_in);
00788 }
00789 else
00790 #endif
00791 return soap_flush_raw(soap, soap->buf, n);
00792 }
00793 return SOAP_OK;
00794 }
00795 #endif
00796
00797
00798 #ifndef PALM_1
00799 SOAP_FMAC1
00800 int
00801 SOAP_FMAC2
00802 soap_flush_raw(struct soap *soap, const char *s, size_t n)
00803 { if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
00804 { register char *t;
00805 if (!(t = (char*)soap_push_block(soap, NULL, n)))
00806 return soap->error = SOAP_EOM;
00807 memcpy(t, s, n);
00808 return SOAP_OK;
00809 }
00810 #ifndef WITH_LEANER
00811 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
00812 { char t[16];
00813 sprintf(t, "\r\n%lX\r\n" + (soap->chunksize ? 0 : 2), (unsigned long)n);
00814 DBGMSG(SENT, t, strlen(t));
00815 if ((soap->error = soap->fsend(soap, t, strlen(t))))
00816 return soap->error;
00817 soap->chunksize += n;
00818 }
00819 DBGMSG(SENT, s, n);
00820 #endif
00821 return soap->error = soap->fsend(soap, s, n);
00822 }
00823 #endif
00824
00825
00826 #ifndef PALM_1
00827 SOAP_FMAC1
00828 int
00829 SOAP_FMAC2
00830 soap_send(struct soap *soap, const char *s)
00831 { if (s)
00832 return soap_send_raw(soap, s, strlen(s));
00833 return SOAP_OK;
00834 }
00835 #endif
00836
00837
00838 #ifndef WITH_LEANER
00839 #ifndef PALM_1
00840 SOAP_FMAC1
00841 int
00842 SOAP_FMAC2
00843 soap_send2(struct soap *soap, const char *s1, const char *s2)
00844 { if (soap_send(soap, s1))
00845 return soap->error;
00846 return soap_send(soap, s2);
00847 }
00848 #endif
00849 #endif
00850
00851
00852 #ifndef WITH_LEANER
00853 #ifndef PALM_1
00854 SOAP_FMAC1
00855 int
00856 SOAP_FMAC2
00857 soap_send3(struct soap *soap, const char *s1, const char *s2, const char *s3)
00858 { if (soap_send(soap, s1)
00859 || soap_send(soap, s2))
00860 return soap->error;
00861 return soap_send(soap, s3);
00862 }
00863 #endif
00864 #endif
00865
00866
00867 #ifndef WITH_NOIO
00868 #ifndef PALM_1
00869 static size_t
00870 frecv(struct soap *soap, char *s, size_t n)
00871 { register int r;
00872 register int retries = 100;
00873 soap->errnum = 0;
00874 #if defined(__cplusplus) && !defined(WITH_LEAN) && !defined(WITH_COMPAT)
00875 if (soap->is)
00876 { if (soap->is->good())
00877 return soap->is->read(s, (std::streamsize)n).gcount();
00878 return 0;
00879 }
00880 #endif
00881 if (soap_valid_socket(soap->socket))
00882 { for (;;)
00883 {
00884 #ifdef WITH_OPENSSL
00885 register int err = 0;
00886 #endif
00887 #ifdef WITH_OPENSSL
00888 if (soap->recv_timeout && !soap->ssl)
00889 #else
00890 if (soap->recv_timeout)
00891 #endif
00892 { for (;;)
00893 { r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->recv_timeout);
00894 if (r > 0)
00895 break;
00896 if (!r)
00897 return 0;
00898 r = soap->errnum;
00899 if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
00900 return 0;
00901 }
00902 }
00903 #ifdef WITH_OPENSSL
00904 if (soap->ssl)
00905 { r = SSL_read(soap->ssl, s, (int)n);
00906 if (r > 0)
00907 return (size_t)r;
00908 err = SSL_get_error(soap->ssl, r);
00909 if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
00910 return 0;
00911 }
00912 else if (soap->bio)
00913 { r = BIO_read(soap->bio, s, (int)n);
00914 if (r > 0)
00915 return (size_t)r;
00916 return 0;
00917 }
00918 else
00919 #endif
00920 #ifdef WITH_GNUTLS
00921 if (soap->session)
00922 { r = (int)gnutls_record_recv(soap->session, s, n);
00923 if (r >= 0)
00924 return (size_t)r;
00925 }
00926 else
00927 #endif
00928 {
00929 #ifndef WITH_LEAN
00930 if ((soap->omode & SOAP_IO_UDP))
00931 { SOAP_SOCKLEN_T k = (SOAP_SOCKLEN_T)sizeof(soap->peer);
00932 memset((void*)&soap->peer, 0, sizeof(soap->peer));
00933 r = recvfrom(soap->socket, s, (SOAP_WINSOCKINT)n, soap->socket_flags, (struct sockaddr*)&soap->peer, &k);
00934 soap->peerlen = (size_t)k;
00935 #ifndef WITH_IPV6
00936 soap->ip = ntohl(soap->peer.sin_addr.s_addr);
00937 #endif
00938 }
00939 else
00940 #endif
00941 r = recv(soap->socket, s, (int)n, soap->socket_flags);
00942 #ifdef PALM
00943
00944 #endif
00945 if (r >= 0)
00946 return (size_t)r;
00947 r = soap_socket_errno(soap->socket);
00948 if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
00949 { soap->errnum = r;
00950 return 0;
00951 }
00952 }
00953 #if defined(WITH_OPENSSL)
00954 if (soap->ssl && err == SSL_ERROR_WANT_WRITE)
00955 r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5);
00956 else
00957 #elif defined(WITH_GNUTLS)
00958 if (soap->session && gnutls_record_get_direction(soap->session))
00959 r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5);
00960 else
00961 #endif
00962 r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5);
00963 if (!r && soap->recv_timeout)
00964 return 0;
00965 if (r < 0)
00966 { r = soap->errnum;
00967 if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
00968 return 0;
00969 }
00970 if (retries-- <= 0)
00971 return 0;
00972 #ifdef PALM
00973 r = soap_socket_errno(soap->socket);
00974 if (r != SOAP_EINTR && retries-- <= 0)
00975 { soap->errnum = r;
00976 return 0;
00977 }
00978 #endif
00979 }
00980 }
00981 #ifdef WITH_FASTCGI
00982 return fread(s, 1, n, stdin);
00983 #else
00984 #ifdef UNDER_CE
00985 return fread(s, 1, n, soap->recvfd);
00986 #else
00987 #ifdef WMW_RPM_IO
00988 if (soap->rpmreqid)
00989 r = httpBlockRead(soap->rpmreqid, s, n);
00990 else
00991 #endif
00992 #ifdef WIN32
00993 r = _read(soap->recvfd, s, (unsigned int)n);
00994 #else
00995 r = read(soap->recvfd, s, (unsigned int)n);
00996 #endif
00997 if (r >= 0)
00998 return (size_t)r;
00999 soap->errnum = soap_errno;
01000 return 0;
01001 #endif
01002 #endif
01003 }
01004 #endif
01005 #endif
01006
01007
01008 #ifndef WITH_NOHTTP
01009 #ifndef PALM_1
01010 static soap_wchar
01011 soap_getchunkchar(struct soap *soap)
01012 { if (soap->bufidx < soap->buflen)
01013 return soap->buf[soap->bufidx++];
01014 soap->bufidx = 0;
01015 soap->buflen = soap->chunkbuflen = soap->frecv(soap, soap->buf, SOAP_BUFLEN);
01016 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket=%d/fd=%d\n", (unsigned int)soap->buflen, soap->socket, soap->recvfd));
01017 DBGMSG(RECV, soap->buf, soap->buflen);
01018 if (soap->buflen)
01019 return soap->buf[soap->bufidx++];
01020 return EOF;
01021 }
01022 #endif
01023 #endif
01024
01025
01026 #ifndef PALM_1
01027 static int
01028 soap_isxdigit(int c)
01029 { return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
01030 }
01031 #endif
01032
01033
01034 #ifndef PALM_1
01035 SOAP_FMAC1
01036 int
01037 SOAP_FMAC2
01038 soap_recv_raw(struct soap *soap)
01039 { register size_t ret;
01040 #if !defined(WITH_LEANER) || defined(WITH_ZLIB)
01041 register int r;
01042 #endif
01043 #ifdef WITH_ZLIB
01044 if (soap->mode & SOAP_ENC_ZLIB)
01045 { if (soap->d_stream->next_out == Z_NULL)
01046 { soap->bufidx = soap->buflen = 0;
01047 return EOF;
01048 }
01049 if (soap->d_stream->avail_in || !soap->d_stream->avail_out)
01050 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflating\n"));
01051 soap->d_stream->next_out = (Byte*)soap->buf;
01052 soap->d_stream->avail_out = SOAP_BUFLEN;
01053 r = inflate(soap->d_stream, Z_NO_FLUSH);
01054 if (r == Z_NEED_DICT && soap->z_dict)
01055 r = inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len);
01056 if (r == Z_OK || r == Z_STREAM_END)
01057 { soap->bufidx = 0;
01058 ret = soap->buflen = SOAP_BUFLEN - soap->d_stream->avail_out;
01059 if (soap->zlib_in == SOAP_ZLIB_GZIP)
01060 soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)ret);
01061 if (r == Z_STREAM_END)
01062 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out));
01063 soap->z_ratio_in = (float)soap->d_stream->total_in / (float)soap->d_stream->total_out;
01064 soap->d_stream->next_out = Z_NULL;
01065 }
01066 if (ret)
01067 { soap->count += ret;
01068 DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- decompressed ----\n"));
01069 DBGMSG(RECV, soap->buf, ret);
01070 DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n----\n"));
01071 #ifndef WITH_LEANER
01072 if (soap->fpreparerecv && (r = soap->fpreparerecv(soap, soap->buf, ret)))
01073 return soap->error = r;
01074 #endif
01075 return SOAP_OK;
01076 }
01077 }
01078 else if (r != Z_BUF_ERROR)
01079 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate error: %s\n", soap->d_stream->msg?soap->d_stream->msg:SOAP_STR_EOS));
01080 soap->d_stream->next_out = Z_NULL;
01081 soap->error = SOAP_ZLIB_ERROR;
01082 return EOF;
01083 }
01084 }
01085 zlib_again:
01086 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK && !soap->chunksize)
01087 { memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN);
01088 soap->buflen = soap->z_buflen;
01089 }
01090 DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- compressed ----\n"));
01091 }
01092 #endif
01093 #ifndef WITH_NOHTTP
01094 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
01095 { for (;;)
01096 { register soap_wchar c;
01097 char *t, tmp[17];
01098 if (soap->chunksize)
01099 { soap->buflen = ret = soap->frecv(soap, soap->buf, soap->chunksize > SOAP_BUFLEN ? SOAP_BUFLEN : soap->chunksize);
01100 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk: read %u bytes\n", (unsigned int)ret));
01101 DBGMSG(RECV, soap->buf, ret);
01102 soap->bufidx = 0;
01103 soap->chunksize -= ret;
01104 break;
01105 }
01106 t = tmp;
01107 if (!soap->chunkbuflen)
01108 { soap->chunkbuflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN);
01109 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes (chunked) from socket %d\n", (unsigned int)ret, soap->socket));
01110 DBGMSG(RECV, soap->buf, ret);
01111 soap->bufidx = 0;
01112 if (!ret)
01113 return soap->ahead = EOF;
01114 }
01115 else
01116 soap->bufidx = soap->buflen;
01117 soap->buflen = soap->chunkbuflen;
01118 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk size (idx=%u len=%u)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen));
01119 while (!soap_isxdigit((int)(c = soap_getchunkchar(soap))))
01120 { if ((int)c == EOF)
01121 return soap->ahead = EOF;
01122 }
01123 do
01124 *t++ = (char)c;
01125 while (soap_isxdigit((int)(c = soap_getchunkchar(soap))) && (size_t)(t - tmp) < sizeof(tmp)-1);
01126 while ((int)c != EOF && c != '\n')
01127 c = soap_getchunkchar(soap);
01128 if ((int)c == EOF)
01129 return soap->ahead = EOF;
01130 *t = '\0';
01131 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunk size = %s (hex)\n", tmp));
01132 soap->chunksize = (size_t)soap_strtoul(tmp, &t, 16);
01133 if (!soap->chunksize)
01134 { soap->bufidx = soap->buflen = soap->chunkbuflen = 0;
01135 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of chunked message\n"));
01136 while ((int)c != EOF && c != '\n')
01137 c = soap_getchunkchar(soap);
01138 ret = 0;
01139 soap->ahead = EOF;
01140 break;
01141 }
01142 soap->buflen = soap->bufidx + soap->chunksize;
01143 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving buf len to idx=%u len=%u (%s)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen, tmp));
01144 if (soap->buflen > soap->chunkbuflen)
01145 { soap->buflen = soap->chunkbuflen;
01146 soap->chunksize -= soap->buflen - soap->bufidx;
01147 soap->chunkbuflen = 0;
01148 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Passed end of buffer for chunked HTTP (%u bytes left)\n", (unsigned int)(soap->buflen - soap->bufidx)));
01149 }
01150 else if (soap->chunkbuflen)
01151 soap->chunksize = 0;
01152 ret = soap->buflen - soap->bufidx;
01153 if (ret)
01154 break;
01155 }
01156 }
01157 else
01158 #endif
01159 { soap->bufidx = 0;
01160 soap->buflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN);
01161 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket=%d/fd=%d\n", (unsigned int)ret, soap->socket, soap->recvfd));
01162 DBGMSG(RECV, soap->buf, ret);
01163 }
01164 #ifdef WITH_ZLIB
01165 if (soap->mode & SOAP_ENC_ZLIB)
01166 { memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN);
01167 soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx);
01168 soap->d_stream->avail_in = (unsigned int)ret;
01169 soap->d_stream->next_out = (Byte*)soap->buf;
01170 soap->d_stream->avail_out = SOAP_BUFLEN;
01171 r = inflate(soap->d_stream, Z_NO_FLUSH);
01172 if (r == Z_NEED_DICT && soap->z_dict)
01173 r = inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len);
01174 if (r == Z_OK || r == Z_STREAM_END)
01175 { soap->bufidx = 0;
01176 soap->z_buflen = soap->buflen;
01177 soap->buflen = SOAP_BUFLEN - soap->d_stream->avail_out;
01178 if (soap->zlib_in == SOAP_ZLIB_GZIP)
01179 soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen);
01180 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %u bytes\n", (unsigned int)soap->buflen));
01181 if (ret && !soap->buflen && r != Z_STREAM_END)
01182 goto zlib_again;
01183 ret = soap->buflen;
01184 if (r == Z_STREAM_END)
01185 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated total %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out));
01186 soap->z_ratio_in = (float)soap->d_stream->total_in / (float)soap->d_stream->total_out;
01187 soap->d_stream->next_out = Z_NULL;
01188 }
01189 DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- decompressed ----\n"));
01190 DBGMSG(RECV, soap->buf, ret);
01191 #ifndef WITH_LEANER
01192 if (soap->fpreparerecv && (r = soap->fpreparerecv(soap, soap->buf, ret)))
01193 return soap->error = r;
01194 #endif
01195 }
01196 else
01197 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to inflate: (%d) %s\n", r, soap->d_stream->msg?soap->d_stream->msg:SOAP_STR_EOS));
01198 soap->d_stream->next_out = Z_NULL;
01199 soap->error = SOAP_ZLIB_ERROR;
01200 return EOF;
01201 }
01202 }
01203 #endif
01204 #ifndef WITH_LEANER
01205 if (soap->fpreparerecv
01206 #ifdef WITH_ZLIB
01207 && soap->zlib_in == SOAP_ZLIB_NONE
01208 #endif
01209 && (r = soap->fpreparerecv(soap, soap->buf + soap->bufidx, ret)))
01210 return soap->error = r;
01211 #endif
01212 soap->count += ret;
01213 return !ret;
01214 }
01215 #endif
01216
01217
01218 #ifndef PALM_1
01219 SOAP_FMAC1
01220 int
01221 SOAP_FMAC2
01222 soap_recv(struct soap *soap)
01223 {
01224 #ifndef WITH_LEANER
01225 if (soap->mode & SOAP_ENC_DIME)
01226 { if (soap->dime.buflen)
01227 { char *s;
01228 int i;
01229 unsigned char tmp[12];
01230 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME hdr for chunked DIME is in buffer\n"));
01231 soap->count += soap->dime.buflen - soap->buflen;
01232 soap->buflen = soap->dime.buflen;
01233 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Skip padding (%ld bytes)\n", -(long)soap->dime.size&3));
01234 for (i = -(long)soap->dime.size&3; i > 0; i--)
01235 { soap->bufidx++;
01236 if (soap->bufidx >= soap->buflen)
01237 if (soap_recv_raw(soap))
01238 return EOF;
01239 }
01240 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME hdr for next chunk\n"));
01241 s = (char*)tmp;
01242 for (i = 12; i > 0; i--)
01243 { *s++ = soap->buf[soap->bufidx++];
01244 if (soap->bufidx >= soap->buflen)
01245 if (soap_recv_raw(soap))
01246 return EOF;
01247 }
01248 soap->dime.flags = tmp[0] & 0x7;
01249 soap->dime.size = ((size_t)tmp[8] << 24) | ((size_t)tmp[9] << 16) | ((size_t)tmp[10] << 8) | ((size_t)tmp[11]);
01250 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME chunk (%u bytes)\n", (unsigned int)soap->dime.size));
01251 if (soap->dime.flags & SOAP_DIME_CF)
01252 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "More chunking\n"));
01253 soap->dime.chunksize = soap->dime.size;
01254 if (soap->buflen - soap->bufidx >= soap->dime.size)
01255 { soap->dime.buflen = soap->buflen;
01256 soap->buflen = soap->bufidx + soap->dime.chunksize;
01257 }
01258 else
01259 soap->dime.chunksize -= soap->buflen - soap->bufidx;
01260 }
01261 else
01262 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Last chunk\n"));
01263 soap->dime.buflen = 0;
01264 soap->dime.chunksize = 0;
01265 }
01266 soap->count = soap->buflen - soap->bufidx;
01267 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%u bytes remaining\n", (unsigned int)soap->count));
01268 return SOAP_OK;
01269 }
01270 if (soap->dime.chunksize)
01271 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get next DIME hdr for chunked DIME (%u bytes chunk)\n", (unsigned int)soap->dime.chunksize));
01272 if (soap_recv_raw(soap))
01273 return EOF;
01274 if (soap->buflen - soap->bufidx >= soap->dime.chunksize)
01275 { soap->dime.buflen = soap->buflen;
01276 soap->count -= soap->buflen - soap->bufidx - soap->dime.chunksize;
01277 soap->buflen = soap->bufidx + soap->dime.chunksize;
01278 }
01279 else
01280 soap->dime.chunksize -= soap->buflen - soap->bufidx;
01281 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%lu bytes remaining, count=%lu\n", (unsigned long)(soap->buflen-soap->bufidx), (unsigned long)soap->count));
01282 return SOAP_OK;
01283 }
01284 }
01285 while (soap->ffilterrecv)
01286 { int err = soap->filterstop;
01287 if (err)
01288 soap->bufidx = soap->buflen = 0;
01289 else
01290 err = soap_recv_raw(soap);
01291 if ((soap->error = soap->ffilterrecv(soap, soap->buf, &soap->buflen, sizeof(soap->buf))))
01292 return soap->error;
01293 if (soap->buflen)
01294 { soap->filterstop = err;
01295 return SOAP_OK;
01296 }
01297 if (err)
01298 return err;
01299 }
01300 #endif
01301 return soap_recv_raw(soap);
01302 }
01303 #endif
01304
01305
01306 #ifndef PALM_1
01307 SOAP_FMAC1
01308 soap_wchar
01309 SOAP_FMAC2
01310 soap_getchar(struct soap *soap)
01311 { register soap_wchar c;
01312 c = soap->ahead;
01313 if (c)
01314 { if (c != EOF)
01315 soap->ahead = 0;
01316 return c;
01317 }
01318 return soap_get1(soap);
01319 }
01320 #endif
01321
01322
01323 #ifndef PALM_1
01324 SOAP_FMAC1
01325 const struct soap_code_map*
01326 SOAP_FMAC2
01327 soap_code(const struct soap_code_map *code_map, const char *str)
01328 { if (code_map && str)
01329 { while (code_map->string)
01330 { if (!strcmp(str, code_map->string))
01331 return code_map;
01332 code_map++;
01333 }
01334 }
01335 return NULL;
01336 }
01337 #endif
01338
01339
01340 #ifndef PALM_1
01341 SOAP_FMAC1
01342 long
01343 SOAP_FMAC2
01344 soap_code_int(const struct soap_code_map *code_map, const char *str, long other)
01345 { if (code_map)
01346 { while (code_map->string)
01347 { if (!soap_tag_cmp(str, code_map->string))
01348 return code_map->code;
01349 code_map++;
01350 }
01351 }
01352 return other;
01353 }
01354 #endif
01355
01356
01357 #ifndef PALM_1
01358 SOAP_FMAC1
01359 const char*
01360 SOAP_FMAC2
01361 soap_code_str(const struct soap_code_map *code_map, long code)
01362 { if (!code_map)
01363 return NULL;
01364 while (code_map->code != code && code_map->string)
01365 code_map++;
01366 return code_map->string;
01367 }
01368 #endif
01369
01370
01371 #ifndef PALM_1
01372 SOAP_FMAC1
01373 long
01374 SOAP_FMAC2
01375 soap_code_bits(const struct soap_code_map *code_map, const char *str)
01376 { register long bits = 0;
01377 if (code_map)
01378 { while (str && *str)
01379 { const struct soap_code_map *p;
01380 for (p = code_map; p->string; p++)
01381 { register size_t n = strlen(p->string);
01382 if (!strncmp(p->string, str, n) && soap_blank((soap_wchar)str[n]))
01383 { bits |= p->code;
01384 str += n;
01385 while (*str > 0 && *str <= 32)
01386 str++;
01387 break;
01388 }
01389 }
01390 if (!p->string)
01391 return 0;
01392 }
01393 }
01394 return bits;
01395 }
01396 #endif
01397
01398
01399 #ifndef PALM_1
01400 SOAP_FMAC1
01401 const char*
01402 SOAP_FMAC2
01403 soap_code_list(struct soap *soap, const struct soap_code_map *code_map, long code)
01404 { register char *t = soap->tmpbuf;
01405 if (code_map)
01406 { while (code_map->string)
01407 { if (code_map->code & code)
01408 { register const char *s = code_map->string;
01409 if (t != soap->tmpbuf)
01410 *t++ = ' ';
01411 while (*s && t < soap->tmpbuf + sizeof(soap->tmpbuf) - 1)
01412 *t++ = *s++;
01413 if (t == soap->tmpbuf + sizeof(soap->tmpbuf) - 1)
01414 break;
01415 }
01416 code_map++;
01417 }
01418 }
01419 *t = '\0';
01420 return soap->tmpbuf;
01421 }
01422 #endif
01423
01424
01425 #ifndef PALM_1
01426 static soap_wchar
01427 soap_char(struct soap *soap)
01428 { char tmp[8];
01429 register int i;
01430 register soap_wchar c;
01431 register char *s = tmp;
01432 for (i = 0; i < 7; i++)
01433 { c = soap_get1(soap);
01434 if (c == ';' || (int)c == EOF)
01435 break;
01436 *s++ = (char)c;
01437 }
01438 *s = '\0';
01439 if (*tmp == '#')
01440 { if (tmp[1] == 'x' || tmp[1] == 'X')
01441 return (soap_wchar)soap_strtol(tmp + 2, NULL, 16);
01442 return (soap_wchar)soap_strtol(tmp + 1, NULL, 10);
01443 }
01444 if (!strcmp(tmp, "lt"))
01445 return '<';
01446 if (!strcmp(tmp, "gt"))
01447 return '>';
01448 if (!strcmp(tmp, "amp"))
01449 return '&';
01450 if (!strcmp(tmp, "quot"))
01451 return '"';
01452 if (!strcmp(tmp, "apos"))
01453 return '\'';
01454 #ifndef WITH_LEAN
01455 return (soap_wchar)soap_code_int(html_entity_codes, tmp, SOAP_UNKNOWN_CHAR);
01456 #else
01457 return SOAP_UNKNOWN_CHAR;
01458 #endif
01459 }
01460 #endif
01461
01462
01463 #ifdef WITH_LEAN
01464 #ifndef PALM_1
01465 soap_wchar
01466 soap_get0(struct soap *soap)
01467 { if (soap->bufidx >= soap->buflen && soap_recv(soap))
01468 return EOF;
01469 return (unsigned char)soap->buf[soap->bufidx];
01470 }
01471 #endif
01472 #endif
01473
01474
01475 #ifdef WITH_LEAN
01476 #ifndef PALM_1
01477 soap_wchar
01478 soap_get1(struct soap *soap)
01479 { if (soap->bufidx >= soap->buflen && soap_recv(soap))
01480 return EOF;
01481 return (unsigned char)soap->buf[soap->bufidx++];
01482 }
01483 #endif
01484 #endif
01485
01486
01487 #ifndef PALM_1
01488 SOAP_FMAC1
01489 soap_wchar
01490 SOAP_FMAC2
01491 soap_get(struct soap *soap)
01492 { register soap_wchar c;
01493 c = soap->ahead;
01494 if (c)
01495 { if ((int)c != EOF)
01496 soap->ahead = 0;
01497 }
01498 else
01499 c = soap_get1(soap);
01500 while ((int)c != EOF)
01501 { if (soap->cdata)
01502 { if (c == ']')
01503 { c = soap_get1(soap);
01504 if (c == ']')
01505 { c = soap_get0(soap);
01506 if (c == '>')
01507 { soap->cdata = 0;
01508 soap_get1(soap);
01509 c = soap_get1(soap);
01510 }
01511 else
01512 { soap_unget(soap, ']');
01513 return ']';
01514 }
01515 }
01516 else
01517 { soap_revget1(soap);
01518 return ']';
01519 }
01520 }
01521 else
01522 return c;
01523 }
01524 switch (c)
01525 { case '<':
01526 do c = soap_get1(soap);
01527 while (soap_blank(c));
01528 if (c == '!' || c == '?' || c == '%')
01529 { register int k = 1;
01530 if (c == '!')
01531 { c = soap_get1(soap);
01532 if (c == '[')
01533 { do c = soap_get1(soap);
01534 while ((int)c != EOF && c != '[');
01535 if ((int)c == EOF)
01536 break;
01537 soap->cdata = 1;
01538 c = soap_get1(soap);
01539 continue;
01540 }
01541 if (c == '-' && (c = soap_get1(soap)) == '-')
01542 { do
01543 { c = soap_get1(soap);
01544 if (c == '-' && (c = soap_get1(soap)) == '-')
01545 break;
01546 } while ((int)c != EOF);
01547 }
01548 }
01549 else if (c == '?')
01550 c = soap_get_pi(soap);
01551 while ((int)c != EOF)
01552 { if (c == '<')
01553 k++;
01554 else if (c == '>')
01555 { if (--k <= 0)
01556 break;
01557 }
01558 c = soap_get1(soap);
01559 }
01560 if ((int)c == EOF)
01561 break;
01562 c = soap_get1(soap);
01563 continue;
01564 }
01565 if (c == '/')
01566 return SOAP_TT;
01567 soap_revget1(soap);
01568 return SOAP_LT;
01569 case '>':
01570 return SOAP_GT;
01571 case '"':
01572 return SOAP_QT;
01573 case '\'':
01574 return SOAP_AP;
01575 case '&':
01576 return soap_char(soap) | 0x80000000;
01577 }
01578 break;
01579 }
01580 return c;
01581 }
01582 #endif
01583
01584
01585 #ifndef PALM_1
01586 static soap_wchar
01587 soap_get_pi(struct soap *soap)
01588 { char buf[64];
01589 register char *s = buf;
01590 register int i = sizeof(buf);
01591 register soap_wchar c = soap_getchar(soap);
01592
01593
01594 while ((int)c != EOF && c != '?')
01595 { if (--i > 0)
01596 { if (soap_blank(c))
01597 c = ' ';
01598 *s++ = (char)c;
01599 }
01600 c = soap_getchar(soap);
01601 }
01602 *s = '\0';
01603 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "XML PI <?%s?>\n", buf));
01604 if (!strncmp(buf, "xml ", 4))
01605 { s = strstr(buf, " encoding=");
01606 if (s && s[10])
01607 { if (!soap_tag_cmp(s + 11, "iso-8859-1*")
01608 || !soap_tag_cmp(s + 11, "latin1*"))
01609 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to latin1 encoding\n"));
01610 soap->mode |= SOAP_ENC_LATIN;
01611 }
01612 else if (!soap_tag_cmp(s + 11, "utf-8*"))
01613 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to utf-8 encoding\n"));
01614 soap->mode &= ~SOAP_ENC_LATIN;
01615 }
01616 }
01617 }
01618 if ((int)c != EOF)
01619 c = soap_getchar(soap);
01620 return c;
01621 }
01622 #endif
01623
01624
01625 #ifndef WITH_LEANER
01626 #ifndef PALM_1
01627 SOAP_FMAC1
01628 int
01629 SOAP_FMAC2
01630 soap_move(struct soap *soap, long n)
01631 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving %ld bytes forward\n", (long)n));
01632 for (; n > 0; n--)
01633 if ((int)soap_getchar(soap) == EOF)
01634 return SOAP_EOF;
01635 return SOAP_OK;
01636 }
01637 #endif
01638 #endif
01639
01640
01641 #ifndef WITH_LEANER
01642 #ifndef PALM_1
01643 SOAP_FMAC1
01644 size_t
01645 SOAP_FMAC2
01646 soap_tell(struct soap *soap)
01647 { return soap->count - soap->buflen + soap->bufidx - (soap->ahead != 0);
01648 }
01649 #endif
01650 #endif
01651
01652
01653 #ifndef PALM_1
01654 SOAP_FMAC1
01655 int
01656 SOAP_FMAC2
01657 soap_pututf8(struct soap *soap, register unsigned long c)
01658 { char tmp[16];
01659 if (c < 0x80 && c > 0)
01660 { *tmp = (char)c;
01661 return soap_send_raw(soap, tmp, 1);
01662 }
01663 #ifndef WITH_LEAN
01664 if (c >= 0x80)
01665 { register char *t = tmp;
01666 if (c < 0x0800)
01667 *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
01668 else
01669 { if (c < 0x010000)
01670 *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
01671 else
01672 { if (c < 0x200000)
01673 *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
01674 else
01675 { if (c < 0x04000000)
01676 *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
01677 else
01678 { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
01679 *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
01680 }
01681 *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
01682 }
01683 *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
01684 }
01685 *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
01686 }
01687 *t++ = (char)(0x80 | (c & 0x3F));
01688 *t = '\0';
01689 }
01690 #else
01691 sprintf(tmp, "&#%lu;", c);
01692 #endif
01693 return soap_send(soap, tmp);
01694 }
01695 #endif
01696
01697
01698 #ifndef PALM_1
01699 SOAP_FMAC1
01700 soap_wchar
01701 SOAP_FMAC2
01702 soap_getutf8(struct soap *soap)
01703 { register soap_wchar c, c1, c2, c3, c4;
01704 c = soap->ahead;
01705 if (c > 0x7F)
01706 { soap->ahead = 0;
01707 return c;
01708 }
01709 c = soap_get(soap);
01710 if (c < 0x80 || (soap->mode & SOAP_ENC_LATIN))
01711 return c;
01712 c1 = soap_get1(soap);
01713 if (c1 < 0x80)
01714 { soap_revget1(soap);
01715 return c;
01716 }
01717 c1 &= 0x3F;
01718 if (c < 0xE0)
01719 return ((soap_wchar)(c & 0x1F) << 6) | c1;
01720 c2 = (soap_wchar)soap_get1(soap) & 0x3F;
01721 if (c < 0xF0)
01722 return ((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2;
01723 c3 = (soap_wchar)soap_get1(soap) & 0x3F;
01724 if (c < 0xF8)
01725 return ((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3;
01726 c4 = (soap_wchar)soap_get1(soap) & 0x3F;
01727 if (c < 0xFC)
01728 return ((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4;
01729 return ((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(soap_get1(soap) & 0x3F);
01730 }
01731 #endif
01732
01733
01734 #ifndef PALM_1
01735 SOAP_FMAC1
01736 int
01737 SOAP_FMAC2
01738 soap_puthex(struct soap *soap, const unsigned char *s, int n)
01739 { char d[2];
01740 register int i;
01741 #ifdef WITH_DOM
01742 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
01743 { if (!(soap->dom->data = soap_s2hex(soap, s, NULL, n)))
01744 return soap->error;
01745 return SOAP_OK;
01746 }
01747 #endif
01748 for (i = 0; i < n; i++)
01749 { register int m = *s++;
01750 d[0] = (char)((m >> 4) + (m > 159 ? '7' : '0'));
01751 m &= 0x0F;
01752 d[1] = (char)(m + (m > 9 ? '7' : '0'));
01753 if (soap_send_raw(soap, d, 2))
01754 return soap->error;
01755 }
01756 return SOAP_OK;
01757 }
01758 #endif
01759
01760
01761 #ifndef PALM_1
01762 SOAP_FMAC1
01763 unsigned char*
01764 SOAP_FMAC2
01765 soap_gethex(struct soap *soap, int *n)
01766 {
01767 #ifdef WITH_DOM
01768 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
01769 { soap->dom->data = soap_string_in(soap, 0, -1, -1);
01770 return (unsigned char*)soap_hex2s(soap, soap->dom->data, NULL, 0, n);
01771 }
01772 #endif
01773 #ifdef WITH_FAST
01774 soap->labidx = 0;
01775 for (;;)
01776 { register char *s;
01777 register size_t i, k;
01778 if (soap_append_lab(soap, NULL, 0))
01779 return NULL;
01780 s = soap->labbuf + soap->labidx;
01781 k = soap->lablen - soap->labidx;
01782 soap->labidx = soap->lablen;
01783 for (i = 0; i < k; i++)
01784 { register char d1, d2;
01785 register soap_wchar c;
01786 c = soap_get(soap);
01787 if (soap_isxdigit(c))
01788 { d1 = (char)c;
01789 c = soap_get(soap);
01790 if (soap_isxdigit(c))
01791 d2 = (char)c;
01792 else
01793 { soap->error = SOAP_TYPE;
01794 return NULL;
01795 }
01796 }
01797 else
01798 { unsigned char *p;
01799 soap_unget(soap, c);
01800 if (n)
01801 *n = (int)(soap->lablen + i - k);
01802 p = (unsigned char*)soap_malloc(soap, soap->lablen + i - k);
01803 if (p)
01804 memcpy(p, soap->labbuf, soap->lablen + i - k);
01805 return p;
01806 }
01807 *s++ = (char)(((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'));
01808 }
01809 }
01810 #else
01811 if (soap_new_block(soap) == NULL)
01812 return NULL;
01813 for (;;)
01814 { register int i;
01815 register char *s = (char*)soap_push_block(soap, NULL, SOAP_BLKLEN);
01816 if (!s)
01817 { soap_end_block(soap, NULL);
01818 return NULL;
01819 }
01820 for (i = 0; i < SOAP_BLKLEN; i++)
01821 { register char d1, d2;
01822 register soap_wchar c = soap_get(soap);
01823 if (soap_isxdigit(c))
01824 { d1 = (char)c;
01825 c = soap_get(soap);
01826 if (soap_isxdigit(c))
01827 d2 = (char)c;
01828 else
01829 { soap_end_block(soap, NULL);
01830 soap->error = SOAP_TYPE;
01831 return NULL;
01832 }
01833 }
01834 else
01835 { unsigned char *p;
01836 soap_unget(soap, c);
01837 if (n)
01838 *n = (int)soap_size_block(soap, NULL, i);
01839 p = (unsigned char*)soap_save_block(soap, NULL, 0);
01840 return p;
01841 }
01842 *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0');
01843 }
01844 }
01845 #endif
01846 }
01847 #endif
01848
01849
01850 #ifndef PALM_1
01851 SOAP_FMAC1
01852 int
01853 SOAP_FMAC2
01854 soap_putbase64(struct soap *soap, const unsigned char *s, int n)
01855 { register int i;
01856 register unsigned long m;
01857 char d[4];
01858 if (!s)
01859 return SOAP_OK;
01860 #ifdef WITH_DOM
01861 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
01862 { if (!(soap->dom->data = soap_s2base64(soap, s, NULL, n)))
01863 return soap->error;
01864 return SOAP_OK;
01865 }
01866 #endif
01867 for (; n > 2; n -= 3, s += 3)
01868 { m = s[0];
01869 m = (m << 8) | s[1];
01870 m = (m << 8) | s[2];
01871 for (i = 4; i > 0; m >>= 6)
01872 d[--i] = soap_base64o[m & 0x3F];
01873 if (soap_send_raw(soap, d, 4))
01874 return soap->error;
01875 }
01876 if (n > 0)
01877 { m = 0;
01878 for (i = 0; i < n; i++)
01879 m = (m << 8) | *s++;
01880 for (; i < 3; i++)
01881 m <<= 8;
01882 for (i++; i > 0; m >>= 6)
01883 d[--i] = soap_base64o[m & 0x3F];
01884 for (i = 3; i > n; i--)
01885 d[i] = '=';
01886 if (soap_send_raw(soap, d, 4))
01887 return soap->error;
01888 }
01889 return SOAP_OK;
01890 }
01891 #endif
01892
01893
01894 #ifndef PALM_1
01895 SOAP_FMAC1
01896 unsigned char*
01897 SOAP_FMAC2
01898 soap_getbase64(struct soap *soap, int *n, int malloc_flag)
01899 {
01900 #ifdef WITH_DOM
01901 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
01902 { soap->dom->data = soap_string_in(soap, 0, -1, -1);
01903 return (unsigned char*)soap_base642s(soap, soap->dom->data, NULL, 0, n);
01904 }
01905 #endif
01906 #ifdef WITH_FAST
01907 soap->labidx = 0;
01908 for (;;)
01909 { register size_t i, k;
01910 register char *s;
01911 if (soap_append_lab(soap, NULL, 2))
01912 return NULL;
01913 s = soap->labbuf + soap->labidx;
01914 k = soap->lablen - soap->labidx;
01915 soap->labidx = 3 * (soap->lablen / 3);
01916 if (!s)
01917 return NULL;
01918 if (k > 2)
01919 { for (i = 0; i < k - 2; i += 3)
01920 { register unsigned long m = 0;
01921 register int j = 0;
01922 do
01923 { register soap_wchar c = soap_get(soap);
01924 if (c == '=' || c < 0)
01925 { unsigned char *p;
01926 switch (j)
01927 { case 2:
01928 *s++ = (char)((m >> 4) & 0xFF);
01929 i++;
01930 break;
01931 case 3:
01932 *s++ = (char)((m >> 10) & 0xFF);
01933 *s++ = (char)((m >> 2) & 0xFF);
01934 i += 2;
01935 }
01936 if (n)
01937 *n = (int)(soap->lablen + i - k);
01938 p = (unsigned char*)soap_malloc(soap, soap->lablen + i - k);
01939 if (p)
01940 memcpy(p, soap->labbuf, soap->lablen + i - k);
01941 if (c >= 0)
01942 { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT)
01943 ;
01944 }
01945 soap_unget(soap, c);
01946 return p;
01947 }
01948 c -= '+';
01949 if (c >= 0 && c <= 79)
01950 { register int b = soap_base64i[c];
01951 if (b >= 64)
01952 { soap->error = SOAP_TYPE;
01953 return NULL;
01954 }
01955 m = (m << 6) + b;
01956 j++;
01957 }
01958 else if (!soap_blank(c + '+'))
01959 { soap->error = SOAP_TYPE;
01960 return NULL;
01961 }
01962 } while (j < 4);
01963 *s++ = (char)((m >> 16) & 0xFF);
01964 *s++ = (char)((m >> 8) & 0xFF);
01965 *s++ = (char)(m & 0xFF);
01966 }
01967 }
01968 }
01969 #else
01970 if (soap_new_block(soap) == NULL)
01971 return NULL;
01972 for (;;)
01973 { register int i;
01974 register char *s = (char*)soap_push_block(soap, NULL, 3 * SOAP_BLKLEN);
01975 if (!s)
01976 { soap_end_block(soap, NULL);
01977 return NULL;
01978 }
01979 for (i = 0; i < SOAP_BLKLEN; i++)
01980 { register unsigned long m = 0;
01981 register int j = 0;
01982 do
01983 { register soap_wchar c = soap_get(soap);
01984 if (c == '=' || c < 0)
01985 { unsigned char *p;
01986 i *= 3;
01987 switch (j)
01988 { case 2:
01989 *s++ = (char)((m >> 4) & 0xFF);
01990 i++;
01991 break;
01992 case 3:
01993 *s++ = (char)((m >> 10) & 0xFF);
01994 *s++ = (char)((m >> 2) & 0xFF);
01995 i += 2;
01996 }
01997 if (n)
01998 *n = (int)soap_size_block(soap, NULL, i);
01999 p = (unsigned char*)soap_save_block(soap, NULL, 0);
02000 if (c >= 0)
02001 { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT)
02002 ;
02003 }
02004 soap_unget(soap, c);
02005 return p;
02006 }
02007 c -= '+';
02008 if (c >= 0 && c <= 79)
02009 { int b = soap_base64i[c];
02010 if (b >= 64)
02011 { soap->error = SOAP_TYPE;
02012 return NULL;
02013 }
02014 m = (m << 6) + b;
02015 j++;
02016 }
02017 else if (!soap_blank(c))
02018 { soap->error = SOAP_TYPE;
02019 return NULL;
02020 }
02021 } while (j < 4);
02022 *s++ = (char)((m >> 16) & 0xFF);
02023 *s++ = (char)((m >> 8) & 0xFF);
02024 *s++ = (char)(m & 0xFF);
02025 }
02026 }
02027 #endif
02028 }
02029 #endif
02030
02031
02032 #ifndef WITH_LEANER
02033 #ifndef PALM_1
02034 SOAP_FMAC1
02035 int
02036 SOAP_FMAC2
02037 soap_xop_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options)
02038 {
02039
02040 int body = soap->body;
02041 if (!soap_peek_element(soap))
02042 { if (!soap_element_begin_in(soap, "xop:Include", 0, NULL))
02043 { if (soap_dime_forward(soap, ptr, size, id, type, options))
02044 return soap->error;
02045 }
02046 if (soap->body && soap_element_end_in(soap, NULL))
02047 return soap->error;
02048 }
02049 soap->body = body;
02050 return SOAP_OK;
02051 }
02052 #endif
02053 #endif
02054
02055
02056 #ifndef WITH_LEANER
02057 #ifndef PALM_1
02058 SOAP_FMAC1
02059 int
02060 SOAP_FMAC2
02061 soap_dime_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options)
02062 { struct soap_xlist *xp;
02063 *ptr = NULL;
02064 *size = 0;
02065 *id = NULL;
02066 *type = NULL;
02067 *options = NULL;
02068 if (!*soap->href)
02069 return SOAP_OK;
02070 *id = soap_strdup(soap, soap->href);
02071 xp = (struct soap_xlist*)SOAP_MALLOC(soap, sizeof(struct soap_xlist));
02072 if (!xp)
02073 return soap->error = SOAP_EOM;
02074 xp->next = soap->xlist;
02075 xp->ptr = ptr;
02076 xp->size = size;
02077 xp->id = *id;
02078 xp->type = type;
02079 xp->options = options;
02080 soap->xlist = xp;
02081 return SOAP_OK;
02082 }
02083 #endif
02084 #endif
02085
02086
02087 #ifndef PALM_1
02088 SOAP_FMAC1
02089 char *
02090 SOAP_FMAC2
02091 soap_strdup(struct soap *soap, const char *s)
02092 { char *t = NULL;
02093 if (s && (t = (char*)soap_malloc(soap, strlen(s) + 1)))
02094 strcpy(t, s);
02095 return t;
02096 }
02097 #endif
02098
02099
02100 #ifndef PALM_1
02101 SOAP_FMAC1
02102 wchar_t *
02103 SOAP_FMAC2
02104 soap_wstrdup(struct soap *soap, const wchar_t *s)
02105 { wchar_t *t = NULL;
02106 if (s)
02107 { size_t n = 0;
02108 while (s[n])
02109 n++;
02110 if ((t = (wchar_t*)soap_malloc(soap, sizeof(wchar_t)*(n+1))))
02111 memcpy(t, s, sizeof(wchar_t)*(n+1));
02112 }
02113 return t;
02114 }
02115 #endif
02116
02117
02118 #ifndef PALM_1
02119 SOAP_FMAC1
02120 struct soap_blist*
02121 SOAP_FMAC2
02122 soap_new_block(struct soap *soap)
02123 { struct soap_blist *p;
02124 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New block sequence (prev=%p)\n", soap->blist));
02125 if (!(p = (struct soap_blist*)SOAP_MALLOC(soap, sizeof(struct soap_blist))))
02126 { soap->error = SOAP_EOM;
02127 return NULL;
02128 }
02129 p->next = soap->blist;
02130 p->ptr = NULL;
02131 p->size = 0;
02132 soap->blist = p;
02133 return p;
02134 }
02135 #endif
02136
02137
02138 #ifndef PALM_1
02139 SOAP_FMAC1
02140 void*
02141 SOAP_FMAC2
02142 soap_push_block(struct soap *soap, struct soap_blist *b, size_t n)
02143 { char *p;
02144 if (!b)
02145 b = soap->blist;
02146 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push block of %u bytes (%u bytes total)\n", (unsigned int)n, (unsigned int)b->size + (unsigned int)n));
02147 if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(char*) + sizeof(size_t))))
02148 { soap->error = SOAP_EOM;
02149 return NULL;
02150 }
02151 *(char**)p = b->ptr;
02152 *(size_t*)(p + sizeof(char*)) = n;
02153 b->ptr = p;
02154 b->size += n;
02155 return p + sizeof(char*) + sizeof(size_t);
02156 }
02157 #endif
02158
02159
02160 #ifndef PALM_1
02161 SOAP_FMAC1
02162 void
02163 SOAP_FMAC2
02164 soap_pop_block(struct soap *soap, struct soap_blist *b)
02165 { char *p;
02166 if (!b)
02167 b = soap->blist;
02168 if (!b->ptr)
02169 return;
02170 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop block\n"));
02171 p = b->ptr;
02172 b->size -= *(size_t*)(p + sizeof(char*));
02173 b->ptr = *(char**)p;
02174 SOAP_FREE(soap, p);
02175 }
02176 #endif
02177
02178
02179 #ifndef WITH_NOIDREF
02180 #ifndef PALM_1
02181 static void
02182 soap_update_ptrs(struct soap *soap, char *start, char *end, char *p1, char *p2)
02183 { int i;
02184 register struct soap_ilist *ip = NULL;
02185 register struct soap_flist *fp = NULL;
02186 #ifndef WITH_LEANER
02187 register struct soap_xlist *xp = NULL;
02188 #endif
02189 register void *p, **q;
02190 for (i = 0; i < SOAP_IDHASH; i++)
02191 { for (ip = soap->iht[i]; ip; ip = ip->next)
02192 { if (ip->ptr && (char*)ip->ptr >= start && (char*)ip->ptr < end)
02193 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", ip->id, ip->ptr, (char*)ip->ptr + (p1-p2)));
02194 ip->ptr = (char*)ip->ptr + (p1-p2);
02195 }
02196 for (q = &ip->link; q; q = (void**)p)
02197 { p = *q;
02198 if (p && (char*)p >= start && (char*)p < end)
02199 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Link update id='%s' %p\n", ip->id, p));
02200 *q = (char*)p + (p1-p2);
02201 }
02202 }
02203 for (q = &ip->copy; q; q = (void**)p)
02204 { p = *q;
02205 if (p && (char*)p >= start && (char*)p < end)
02206 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy chain update id='%s' %p\n", ip->id, p));
02207 *q = (char*)p + (p1-p2);
02208 }
02209 }
02210 for (fp = ip->flist; fp; fp = fp->next)
02211 { if ((char*)fp->ptr >= start && (char*)fp->ptr < end)
02212 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy list update id='%s' %p\n", ip->id, fp));
02213 fp->ptr = (char*)fp->ptr + (p1-p2);
02214 }
02215 }
02216 }
02217 }
02218 #ifndef WITH_LEANER
02219 for (xp = soap->xlist; xp; xp = xp->next)
02220 { if (xp->ptr && (char*)xp->ptr >= start && (char*)xp->ptr < end)
02221 { 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)));
02222 xp->ptr = (unsigned char**)((char*)xp->ptr + (p1-p2));
02223 xp->size = (int*)((char*)xp->size + (p1-p2));
02224 xp->type = (char**)((char*)xp->type + (p1-p2));
02225 xp->options = (char**)((char*)xp->options + (p1-p2));
02226 }
02227 }
02228 #endif
02229 }
02230 #endif
02231 #endif
02232
02233
02234 #ifndef WITH_NOIDREF
02235 #ifndef PALM_1
02236 static int
02237 soap_has_copies(struct soap *soap, register const char *start, register const char *end)
02238 { register int i;
02239 register struct soap_ilist *ip = NULL;
02240 register struct soap_flist *fp = NULL;
02241 register const char *p;
02242 for (i = 0; i < SOAP_IDHASH; i++)
02243 { for (ip = soap->iht[i]; ip; ip = ip->next)
02244 { for (p = (const char*)ip->copy; p; p = *(const char**)p)
02245 if (p >= start && p < end)
02246 return SOAP_ERR;
02247 for (fp = ip->flist; fp; fp = fp->next)
02248 if ((const char*)fp->ptr >= start && (const char*)fp->ptr < end)
02249 return SOAP_ERR;
02250 }
02251 }
02252 return SOAP_OK;
02253 }
02254 #endif
02255 #endif
02256
02257
02258 #ifndef WITH_NOIDREF
02259 #ifndef PALM_1
02260 SOAP_FMAC1
02261 int
02262 SOAP_FMAC2
02263 soap_resolve(struct soap *soap)
02264 { register int i;
02265 register struct soap_ilist *ip = NULL;
02266 register struct soap_flist *fp = NULL;
02267 short flag;
02268 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data\n"));
02269 for (i = 0; i < SOAP_IDHASH; i++)
02270 { for (ip = soap->iht[i]; ip; ip = ip->next)
02271 { if (ip->ptr)
02272 { register void *p, **q, *r;
02273 q = (void**)ip->link;
02274 ip->link = NULL;
02275 r = ip->ptr;
02276 DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing link chain to resolve id='%s'\n", ip->id));
02277 while (q)
02278 { p = *q;
02279 *q = r;
02280 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "... link %p -> %p\n", q, r));
02281 q = (void**)p;
02282 }
02283 }
02284 else if (*ip->id == '#')
02285 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Missing data for id='%s'\n", ip->id));
02286 strcpy(soap->id, ip->id + 1);
02287 return soap->error = SOAP_MISSING_ID;
02288 }
02289 }
02290 }
02291 do
02292 { flag = 0;
02293 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution phase\n"));
02294 for (i = 0; i < SOAP_IDHASH; i++)
02295 { for (ip = soap->iht[i]; ip; ip = ip->next)
02296 { if (ip->ptr && !soap_has_copies(soap, (const char*)ip->ptr, (const char*)ip->ptr + ip->size))
02297 { if (ip->copy)
02298 { register void *p, **q = (void**)ip->copy;
02299 DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing copy chain to resolve id='%s'\n", ip->id));
02300 ip->copy = NULL;
02301 do
02302 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... copy %p -> %p (%u bytes)\n", ip->ptr, q, (unsigned int)ip->size));
02303 p = *q;
02304 memcpy(q, ip->ptr, ip->size);
02305 q = (void**)p;
02306 } while (q);
02307 flag = 1;
02308 }
02309 for (fp = ip->flist; fp; fp = ip->flist)
02310 { register unsigned int k = fp->level;
02311 register void *p = ip->ptr;
02312 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));
02313 while (ip->level < k)
02314 { register void **q = (void**)soap_malloc(soap, sizeof(void*));
02315 if (!q)
02316 return soap->error;
02317 *q = p;
02318 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level, new location=%p holds=%p...\n", q, *q));
02319 p = (void*)q;
02320 k--;
02321 }
02322 if (fp->fcopy)
02323 fp->fcopy(soap, ip->type, fp->type, fp->ptr, fp->len, p, ip->size);
02324 else
02325 soap_fcopy(soap, ip->type, fp->type, fp->ptr, fp->len, p, ip->size);
02326 ip->flist = fp->next;
02327 SOAP_FREE(soap, fp);
02328 flag = 1;
02329 }
02330 }
02331 }
02332 }
02333 } while (flag);
02334 #ifdef SOAP_DEBUG
02335 for (i = 0; i < SOAP_IDHASH; i++)
02336 { for (ip = soap->iht[i]; ip; ip = ip->next)
02337 { if (ip->copy || ip->flist)
02338 { 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));
02339 }
02340 }
02341 }
02342 #endif
02343 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution done\n"));
02344 return SOAP_OK;
02345 }
02346 #endif
02347 #endif
02348
02349
02350 #ifndef PALM_1
02351 SOAP_FMAC1
02352 size_t
02353 SOAP_FMAC2
02354 soap_size_block(struct soap *soap, struct soap_blist *b, size_t n)
02355 { if (!b)
02356 b = soap->blist;
02357 if (b->ptr)
02358 { b->size -= *(size_t*)(b->ptr + sizeof(char*)) - n;
02359 *(size_t*)(b->ptr + sizeof(char*)) = n;
02360 }
02361 return b->size;
02362 }
02363 #endif
02364
02365
02366 #ifndef PALM_1
02367 SOAP_FMAC1
02368 char*
02369 SOAP_FMAC2
02370 soap_first_block(struct soap *soap, struct soap_blist *b)
02371 { char *p, *q, *r;
02372 if (!b)
02373 b = soap->blist;
02374 p = b->ptr;
02375 if (!p)
02376 return NULL;
02377 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "First block\n"));
02378 r = NULL;
02379 do
02380 { q = *(char**)p;
02381 *(char**)p = r;
02382 r = p;
02383 p = q;
02384 } while (p);
02385 b->ptr = r;
02386 return r + sizeof(char*) + sizeof(size_t);
02387 }
02388 #endif
02389
02390
02391 #ifndef PALM_1
02392 SOAP_FMAC1
02393 char*
02394 SOAP_FMAC2
02395 soap_next_block(struct soap *soap, struct soap_blist *b)
02396 { char *p;
02397 if (!b)
02398 b = soap->blist;
02399 p = b->ptr;
02400 if (p)
02401 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Next block\n"));
02402 b->ptr = *(char**)p;
02403 SOAP_FREE(soap, p);
02404 if (b->ptr)
02405 return b->ptr + sizeof(char*) + sizeof(size_t);
02406 }
02407 return NULL;
02408 }
02409 #endif
02410
02411
02412 #ifndef PALM_1
02413 SOAP_FMAC1
02414 size_t
02415 SOAP_FMAC2
02416 soap_block_size(struct soap *soap, struct soap_blist *b)
02417 { if (!b)
02418 b = soap->blist;
02419 return *(size_t*)(b->ptr + sizeof(char*));
02420 }
02421 #endif
02422
02423
02424 #ifndef PALM_1
02425 SOAP_FMAC1
02426 void
02427 SOAP_FMAC2
02428 soap_end_block(struct soap *soap, struct soap_blist *b)
02429 { char *p, *q;
02430 if (!b)
02431 b = soap->blist;
02432 if (b)
02433 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of block sequence, free all remaining blocks\n"));
02434 for (p = b->ptr; p; p = q)
02435 { q = *(char**)p;
02436 SOAP_FREE(soap, p);
02437 }
02438 if (soap->blist == b)
02439 soap->blist = b->next;
02440 else
02441 { struct soap_blist *bp;
02442 for (bp = soap->blist; bp; bp = bp->next)
02443 { if (bp->next == b)
02444 { bp->next = b->next;
02445 break;
02446 }
02447 }
02448 }
02449 SOAP_FREE(soap, b);
02450 }
02451 DBGLOG(TEST, if (soap->blist) SOAP_MESSAGE(fdebug, "Restore previous block sequence\n"));
02452 }
02453 #endif
02454
02455
02456 #ifndef PALM_1
02457 SOAP_FMAC1
02458 char*
02459 SOAP_FMAC2
02460 soap_save_block(struct soap *soap, struct soap_blist *b, char *p, int flag)
02461 { register size_t n;
02462 register char *q, *s;
02463 if (!b)
02464 b = soap->blist;
02465 if (b->size)
02466 { if (!p)
02467 p = (char*)soap_malloc(soap, b->size);
02468 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));
02469 if (p)
02470 { for (s = p, q = soap_first_block(soap, b); q; q = soap_next_block(soap, b))
02471 { n = soap_block_size(soap, b);
02472 #ifndef WITH_NOIDREF
02473 if (flag)
02474 soap_update_ptrs(soap, q, q + n, s, q);
02475 #endif
02476 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy %u bytes from %p to %p\n", (unsigned int)n, q, s));
02477 memcpy(s, q, n);
02478 s += n;
02479 }
02480 }
02481 else
02482 soap->error = SOAP_EOM;
02483 }
02484 soap_end_block(soap, b);
02485 return p;
02486 }
02487 #endif
02488
02489
02490 #ifndef PALM_2
02491 SOAP_FMAC1
02492 char *
02493 SOAP_FMAC2
02494 soap_putsize(struct soap *soap, const char *type, int size)
02495 { return soap_putsizes(soap, type, &size, 1);
02496 }
02497 #endif
02498
02499
02500 #ifndef PALM_2
02501 SOAP_FMAC1
02502 char *
02503 SOAP_FMAC2
02504 soap_putsizes(struct soap *soap, const char *type, const int *size, int dim)
02505 { return soap_putsizesoffsets(soap, type, size, NULL, dim);
02506 }
02507 #endif
02508
02509
02510 #ifndef PALM_2
02511 SOAP_FMAC1
02512 char *
02513 SOAP_FMAC2
02514 soap_putsizesoffsets(struct soap *soap, const char *type, const int *size, const int *offset, int dim)
02515 { int i;
02516 if (!type)
02517 return NULL;
02518 if (soap->version == 2)
02519 { sprintf(soap->type, "%s[%d", type, size[0]);
02520 for (i = 1; i < dim; i++)
02521 sprintf(soap->type + strlen(soap->type), " %d", size[i]);
02522 }
02523 else
02524 { if (offset)
02525 { sprintf(soap->type, "%s[%d", type, size[0] + offset[0]);
02526 for (i = 1; i < dim; i++)
02527 sprintf(soap->type + strlen(soap->type), ",%d", size[i] + offset[i]);
02528 }
02529 else
02530 { sprintf(soap->type, "%s[%d", type, size[0]);
02531 for (i = 1; i < dim; i++)
02532 sprintf(soap->type + strlen(soap->type), ",%d", size[i]);
02533 }
02534 strcat(soap->type, "]");
02535 }
02536 return soap->type;
02537 }
02538 #endif
02539
02540
02541 #ifndef PALM_2
02542 SOAP_FMAC1
02543 char *
02544 SOAP_FMAC2
02545 soap_putoffset(struct soap *soap, int offset)
02546 { return soap_putoffsets(soap, &offset, 1);
02547 }
02548 #endif
02549
02550
02551 #ifndef PALM_2
02552 SOAP_FMAC1
02553 char *
02554 SOAP_FMAC2
02555 soap_putoffsets(struct soap *soap, const int *offset, int dim)
02556 { register int i;
02557 sprintf(soap->arrayOffset, "[%d", offset[0]);
02558 for (i = 1; i < dim; i++)
02559 sprintf(soap->arrayOffset + strlen(soap->arrayOffset), ",%d", offset[i]);
02560 strcat(soap->arrayOffset, "]");
02561 return soap->arrayOffset;
02562 }
02563 #endif
02564
02565
02566 #ifndef PALM_2
02567 SOAP_FMAC1
02568 int
02569 SOAP_FMAC2
02570 soap_size(const int *size, int dim)
02571 { register int i, n = size[0];
02572 for (i = 1; i < dim; i++)
02573 n *= size[i];
02574 return n;
02575 }
02576 #endif
02577
02578
02579 #ifndef PALM_2
02580 SOAP_FMAC1
02581 int
02582 SOAP_FMAC2
02583 soap_getoffsets(const char *attr, const int *size, int *offset, int dim)
02584 { register int i, j = 0;
02585 if (offset)
02586 for (i = 0; i < dim && attr && *attr; i++)
02587 { attr++;
02588 j *= size[i];
02589 j += offset[i] = (int)soap_strtol(attr, NULL, 10);
02590 attr = strchr(attr, ',');
02591 }
02592 else
02593 for (i = 0; i < dim && attr && *attr; i++)
02594 { attr++;
02595 j *= size[i];
02596 j += (int)soap_strtol(attr, NULL, 10);
02597 attr = strchr(attr, ',');
02598 }
02599 return j;
02600 }
02601 #endif
02602
02603
02604 #ifndef PALM_2
02605 SOAP_FMAC1
02606 int
02607 SOAP_FMAC2
02608 soap_getsize(const char *attr1, const char *attr2, int *j)
02609 { register int n, k;
02610 char *s;
02611 *j = 0;
02612 if (!*attr1)
02613 return -1;
02614 if (*attr1 == '[')
02615 attr1++;
02616 n = 1;
02617 for (;;)
02618 { k = (int)soap_strtol(attr1, &s, 10);
02619 n *= k;
02620 if (k < 0 || n > SOAP_MAXARRAYSIZE || s == attr1)
02621 return -1;
02622 attr1 = strchr(s, ',');
02623 if (!attr1)
02624 attr1 = strchr(s, ' ');
02625 if (attr2 && *attr2)
02626 { attr2++;
02627 *j *= k;
02628 k = (int)soap_strtol(attr2, &s, 10);
02629 *j += k;
02630 if (k < 0)
02631 return -1;
02632 attr2 = s;
02633 }
02634 if (!attr1)
02635 break;
02636 attr1++;
02637 }
02638 return n - *j;
02639 }
02640 #endif
02641
02642
02643 #ifndef PALM_2
02644 SOAP_FMAC1
02645 int
02646 SOAP_FMAC2
02647 soap_getsizes(const char *attr, int *size, int dim)
02648 { register int i, k, n;
02649 if (!*attr)
02650 return -1;
02651 i = (int)strlen(attr);
02652 n = 1;
02653 do
02654 { for (i = i-1; i >= 0; i--)
02655 if (attr[i] == '[' || attr[i] == ',' || attr[i] == ' ')
02656 break;
02657 k = (int)soap_strtol(attr + i + 1, NULL, 10);
02658 n *= size[--dim] = k;
02659 if (k < 0 || n > SOAP_MAXARRAYSIZE)
02660 return -1;
02661 } while (i >= 0 && attr[i] != '[');
02662 return n;
02663 }
02664 #endif
02665
02666
02667 #ifndef PALM_2
02668 SOAP_FMAC1
02669 int
02670 SOAP_FMAC2
02671 soap_getposition(const char *attr, int *pos)
02672 { register int i, n;
02673 if (!*attr)
02674 return -1;
02675 n = 0;
02676 i = 1;
02677 do
02678 { pos[n++] = (int)soap_strtol(attr + i, NULL, 10);
02679 while (attr[i] && attr[i] != ',' && attr[i] != ']')
02680 i++;
02681 if (attr[i] == ',')
02682 i++;
02683 } while (n < SOAP_MAXDIMS && attr[i] && attr[i] != ']');
02684 return n;
02685 }
02686 #endif
02687
02688
02689 #ifndef PALM_2
02690 SOAP_FMAC1
02691 struct soap_nlist *
02692 SOAP_FMAC2
02693 soap_push_namespace(struct soap *soap, const char *id, const char *ns)
02694 { register struct soap_nlist *np;
02695 register struct Namespace *p;
02696 register short i = -1;
02697 register size_t n, k;
02698 n = strlen(id);
02699 k = strlen(ns) + 1;
02700 p = soap->local_namespaces;
02701 if (p)
02702 { for (i = 0; p->id; p++, i++)
02703 { if (p->ns && !strcmp(ns, p->ns))
02704 { if (p->out)
02705 { SOAP_FREE(soap, p->out);
02706 p->out = NULL;
02707 }
02708 break;
02709 }
02710 if (p->out)
02711 { if (!strcmp(ns, p->out))
02712 break;
02713 }
02714 else if (p->in)
02715 { if (!soap_tag_cmp(ns, p->in))
02716 { if ((p->out = (char*)SOAP_MALLOC(soap, k)))
02717 strcpy(p->out, ns);
02718 break;
02719 }
02720 }
02721 }
02722 if (!p || !p->id)
02723 i = -1;
02724 }
02725 if (i >= 0)
02726 k = 0;
02727 np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k);
02728 if (!np)
02729 { soap->error = SOAP_EOM;
02730 return NULL;
02731 }
02732 np->next = soap->nlist;
02733 soap->nlist = np;
02734 np->level = soap->level;
02735 np->index = i;
02736 strcpy(np->id, id);
02737 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push namespace binding (level=%u) '%s' '%s'\n", soap->level, id, ns));
02738 if (i < 0)
02739 { np->ns = strcpy(np->id + n + 1, ns);
02740 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push NOT OK: no match found for '%s' in namespace mapping table (added to stack anyway)\n", ns));
02741 }
02742 else
02743 { np->ns = NULL;
02744 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push OK ('%s' matches '%s' in namespace table)\n", id, p->id));
02745 }
02746 return np;
02747 }
02748 #endif
02749
02750
02751 #ifndef PALM_2
02752 SOAP_FMAC1
02753 void
02754 SOAP_FMAC2
02755 soap_pop_namespace(struct soap *soap)
02756 { register struct soap_nlist *np, *nq;
02757 for (np = soap->nlist; np && np->level >= soap->level; np = nq)
02758 { nq = np->next;
02759 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop namespace binding (level=%u) '%s'\n", soap->level, np->id));
02760 SOAP_FREE(soap, np);
02761 }
02762 soap->nlist = np;
02763 }
02764 #endif
02765
02766
02767 #ifndef PALM_2
02768 SOAP_FMAC1
02769 int
02770 SOAP_FMAC2
02771 soap_match_namespace(struct soap *soap, const char *id1, const char *id2, size_t n1, size_t n2)
02772 { register struct soap_nlist *np = soap->nlist;
02773 const char *s;
02774 while (np && (strncmp(np->id, id1, n1) || np->id[n1]))
02775 np = np->next;
02776 if (np)
02777 { if (!(soap->mode & SOAP_XML_IGNORENS))
02778 if (np->index < 0
02779 || ((s = soap->local_namespaces[np->index].id) && (strncmp(s, id2, n2) || (s[n2] && s[n2] != '_'))))
02780 return SOAP_NAMESPACE;
02781 return SOAP_OK;
02782 }
02783 if (n1 == 0)
02784 return (soap->mode & SOAP_XML_IGNORENS) ? SOAP_OK : SOAP_NAMESPACE;
02785 if ((n1 == 3 && n1 == n2 && !strncmp(id1, "xml", 3) && !strncmp(id1, id2, 3))
02786 || (soap->mode & SOAP_XML_IGNORENS))
02787 return SOAP_OK;
02788 return soap->error = SOAP_SYNTAX_ERROR;
02789 }
02790 #endif
02791
02792
02793 #ifndef PALM_2
02794 SOAP_FMAC1
02795 const char*
02796 SOAP_FMAC2
02797 soap_current_namespace(struct soap *soap, const char *tag)
02798 { register struct soap_nlist *np;
02799 register const char *s;
02800 if (!tag || !strncmp(tag, "xml", 3))
02801 return NULL;
02802 np = soap->nlist;
02803 if (!(s = strchr(tag, ':')))
02804 { while (np && *np->id)
02805 np = np->next;
02806 }
02807 else
02808 { while (np && (strncmp(np->id, tag, s - tag) || np->id[s - tag]))
02809 np = np->next;
02810 if (!np)
02811 soap->error = SOAP_NAMESPACE;
02812 }
02813 if (np)
02814 { if (np->index >= 0)
02815 return soap->namespaces[np->index].ns;
02816 if (np->ns)
02817 return soap_strdup(soap, np->ns);
02818 }
02819 return NULL;
02820 }
02821 #endif
02822
02823
02824 #ifndef PALM_2
02825 SOAP_FMAC1
02826 int
02827 SOAP_FMAC2
02828 soap_tag_cmp(const char *s, const char *t)
02829 { for (;;)
02830 { register int c1 = *s;
02831 register int c2 = *t;
02832 if (!c1 || c1 == '"')
02833 break;
02834 if (c2 != '-')
02835 { if (c1 != c2)
02836 { if (c1 >= 'A' && c1 <= 'Z')
02837 c1 += 'a' - 'A';
02838 if (c2 >= 'A' && c2 <= 'Z')
02839 c2 += 'a' - 'A';
02840 }
02841 if (c1 != c2)
02842 { if (c2 != '*')
02843 return 1;
02844 c2 = *++t;
02845 if (!c2)
02846 return 0;
02847 if (c2 >= 'A' && c2 <= 'Z')
02848 c2 += 'a' - 'A';
02849 for (;;)
02850 { c1 = *s;
02851 if (!c1 || c1 == '"')
02852 break;
02853 if (c1 >= 'A' && c1 <= 'Z')
02854 c1 += 'a' - 'A';
02855 if (c1 == c2 && !soap_tag_cmp(s + 1, t + 1))
02856 return 0;
02857 s++;
02858 }
02859 break;
02860 }
02861 }
02862 s++;
02863 t++;
02864 }
02865 if (*t == '*' && !t[1])
02866 return 0;
02867 return *t;
02868 }
02869 #endif
02870
02871
02872 #ifndef PALM_2
02873 SOAP_FMAC1
02874 int
02875 SOAP_FMAC2
02876 soap_match_tag(struct soap *soap, const char *tag1, const char *tag2)
02877 { register const char *s, *t;
02878 register int err;
02879 if (!tag1 || !tag2 || !*tag2)
02880 return SOAP_OK;
02881 s = strchr(tag1, ':');
02882 t = strchr(tag2, ':');
02883 if (t)
02884 { if (s)
02885 { if (t[1] && SOAP_STRCMP(s + 1, t + 1))
02886 return SOAP_TAG_MISMATCH;
02887 if (t != tag2 && (err = soap_match_namespace(soap, tag1, tag2, s - tag1, t - tag2)))
02888 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2));
02889 if (err == SOAP_NAMESPACE)
02890 return SOAP_TAG_MISMATCH;
02891 return err;
02892 }
02893 }
02894 else if (SOAP_STRCMP(tag1, t + 1))
02895 { return SOAP_TAG_MISMATCH;
02896 }
02897 else if (t != tag2 && (err = soap_match_namespace(soap, tag1, tag2, 0, t - tag2)))
02898 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2));
02899 if (err == SOAP_NAMESPACE)
02900 return SOAP_TAG_MISMATCH;
02901 return err;
02902 }
02903 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags and (default) namespaces match: '%s' '%s'\n", tag1, tag2));
02904 return SOAP_OK;
02905 }
02906 if (s)
02907 { if (SOAP_STRCMP(s + 1, tag2))
02908 return SOAP_TAG_MISMATCH;
02909 }
02910 else if (SOAP_STRCMP(tag1, tag2))
02911 return SOAP_TAG_MISMATCH;
02912 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags match: '%s' '%s'\n", tag1, tag2));
02913 return SOAP_OK;
02914 }
02915 #endif
02916
02917
02918 #ifndef PALM_2
02919 SOAP_FMAC1
02920 int
02921 SOAP_FMAC2
02922 soap_match_array(struct soap *soap, const char *type)
02923 { if (*soap->arrayType)
02924 if (soap_match_tag(soap, soap->arrayType, type)
02925 && soap_match_tag(soap, soap->arrayType, "xsd:anyType")
02926 && soap_match_tag(soap, soap->arrayType, "xsd:ur-type")
02927 )
02928 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array type mismatch: '%s' '%s'\n", soap->arrayType, type));
02929 return SOAP_TAG_MISMATCH;
02930 }
02931 return SOAP_OK;
02932 }
02933 #endif
02934
02935
02936
02937
02938
02939
02940
02941
02942 #ifdef WITH_OPENSSL
02943 #ifndef PALM_2
02944 SOAP_FMAC1
02945 int
02946 SOAP_FMAC2
02947 soap_rand()
02948 { unsigned char buf[4];
02949 if (!soap_ssl_init_done)
02950 soap_ssl_init();
02951 RAND_pseudo_bytes(buf, 4);
02952 return *(int*)buf;
02953 }
02954 #endif
02955 #endif
02956
02957
02958 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
02959 #ifndef PALM_2
02960 SOAP_FMAC1
02961 int
02962 SOAP_FMAC2
02963 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)
02964 { int err;
02965 soap->keyfile = keyfile;
02966 soap->password = password;
02967 soap->cafile = cafile;
02968 soap->capath = capath;
02969 soap->crlfile = NULL;
02970 #ifdef WITH_OPENSSL
02971 soap->dhfile = dhfile;
02972 soap->randfile = randfile;
02973 #endif
02974 soap->ssl_flags = flags | (dhfile == NULL ? SOAP_SSL_RSA : 0);
02975 #ifdef WITH_GNUTLS
02976 if (dhfile)
02977 { char *s;
02978 int n = (int)soap_strtoul(dhfile, &s, 10);
02979 if (!soap->dh_params)
02980 gnutls_dh_params_init(&soap->dh_params);
02981
02982 if (n >= 512 && s && *s == '\0')
02983 gnutls_dh_params_generate2(soap->dh_params, (unsigned int)n);
02984 else
02985 { unsigned int dparams_len;
02986 unsigned char dparams_buf[1024];
02987 FILE *fd = fopen(dhfile, "r");
02988 if (!fd)
02989 return soap_set_receiver_error(soap, "SSL/TLS error", "Invalid DH file", SOAP_SSL_ERROR);
02990 dparams_len = (unsigned int)fread(dparams_buf, 1, sizeof(dparams_buf), fd);
02991 fclose(fd);
02992 gnutls_datum_t dparams = { dparams_buf, dparams_len };
02993 if (gnutls_dh_params_import_pkcs3(soap->dh_params, &dparams, GNUTLS_X509_FMT_PEM))
02994 return soap_set_receiver_error(soap, "SSL/TLS error", "Invalid DH file", SOAP_SSL_ERROR);
02995 }
02996 }
02997 else
02998 { if (!soap->rsa_params)
02999 gnutls_rsa_params_init(&soap->rsa_params);
03000 gnutls_rsa_params_generate2(soap->rsa_params, SOAP_SSL_RSA_BITS);
03001 }
03002 if (soap->session)
03003 { gnutls_deinit(soap->session);
03004 soap->session = NULL;
03005 }
03006 if (soap->xcred)
03007 { gnutls_certificate_free_credentials(soap->xcred);
03008 soap->xcred = NULL;
03009 }
03010 #endif
03011 err = soap->fsslauth(soap);
03012 #ifdef WITH_OPENSSL
03013 if (!err)
03014 { if (sid)
03015 SSL_CTX_set_session_id_context(soap->ctx, (unsigned char*)sid, (unsigned int)strlen(sid));
03016 else
03017 SSL_CTX_set_session_cache_mode(soap->ctx, SSL_SESS_CACHE_OFF);
03018 }
03019 #endif
03020 return err;
03021 }
03022 #endif
03023 #endif
03024
03025
03026 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
03027 #ifndef PALM_2
03028 SOAP_FMAC1
03029 int
03030 SOAP_FMAC2
03031 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)
03032 { soap->keyfile = keyfile;
03033 soap->password = password;
03034 soap->cafile = cafile;
03035 soap->capath = capath;
03036 soap->ssl_flags = SOAP_SSL_CLIENT | flags;
03037 #ifdef WITH_OPENSSL
03038 soap->dhfile = NULL;
03039 soap->randfile = randfile;
03040 soap->fsslverify = (flags & SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE) == 0 ? ssl_verify_callback : ssl_verify_callback_allow_expired_certificate;
03041 #endif
03042 #ifdef WITH_GNUTLS
03043 if (soap->session)
03044 { gnutls_deinit(soap->session);
03045 soap->session = NULL;
03046 }
03047 if (soap->xcred)
03048 { gnutls_certificate_free_credentials(soap->xcred);
03049 soap->xcred = NULL;
03050 }
03051 #endif
03052 return soap->fsslauth(soap);
03053 }
03054 #endif
03055 #endif
03056
03057
03058 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
03059 #ifndef PALM_2
03060 SOAP_FMAC1
03061 void
03062 SOAP_FMAC2
03063 soap_ssl_init()
03064 {
03065 if (!soap_ssl_init_done)
03066 { soap_ssl_init_done = 1;
03067 #ifdef WITH_OPENSSL
03068 SSL_library_init();
03069 OpenSSL_add_all_algorithms();
03070 #ifndef WITH_LEAN
03071 SSL_load_error_strings();
03072 #endif
03073 if (!RAND_load_file("/dev/urandom", 1024))
03074 { char buf[1024];
03075 RAND_seed(buf, sizeof(buf));
03076 while (!RAND_status())
03077 { int r = rand();
03078 RAND_seed(&r, sizeof(int));
03079 }
03080 }
03081 #endif
03082 #ifdef WITH_GNUTLS
03083 # if defined(HAVE_PTHREAD_H)
03084 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
03085 # elif defined(HAVE_PTH_H)
03086 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth);
03087 # endif
03088 gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM, 0);
03089 gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
03090 gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
03091 gnutls_global_init();
03092 #endif
03093 }
03094 }
03095 #endif
03096 #endif
03097
03098
03099 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
03100 #ifndef PALM_1
03101 SOAP_FMAC1
03102 const char *
03103 SOAP_FMAC2
03104 soap_ssl_error(struct soap *soap, int ret)
03105 {
03106 #ifdef WITH_OPENSSL
03107 int err = SSL_get_error(soap->ssl, ret);
03108 const char *msg = soap_code_str(h_ssl_error_codes, err);
03109 if (msg)
03110 strcpy(soap->msgbuf, msg);
03111 else
03112 return ERR_error_string(err, soap->msgbuf);
03113 if (ERR_peek_error())
03114 { unsigned long r;
03115 strcat(soap->msgbuf, "\n");
03116 while ((r = ERR_get_error()))
03117 ERR_error_string_n(r, soap->msgbuf + strlen(soap->msgbuf), sizeof(soap->msgbuf) - strlen(soap->msgbuf));
03118 }
03119 else
03120 { switch (ret)
03121 { case 0:
03122 strcpy(soap->msgbuf, "EOF was observed that violates the protocol. The client probably provided invalid authentication information.");
03123 break;
03124 case -1:
03125 sprintf(soap->msgbuf, "Error observed by underlying BIO: %s", strerror(errno));
03126 break;
03127 }
03128 }
03129 return soap->msgbuf;
03130 #endif
03131 #ifdef WITH_GNUTLS
03132 return gnutls_strerror(ret);
03133 #endif
03134 }
03135 #endif
03136 #endif
03137
03138
03139 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
03140 #ifndef PALM_1
03141 static int
03142 ssl_auth_init(struct soap *soap)
03143 {
03144 #ifdef WITH_OPENSSL
03145 long flags;
03146 int mode;
03147 if (!soap_ssl_init_done)
03148 soap_ssl_init();
03149 ERR_clear_error();
03150 if (!soap->ctx)
03151 { if (!(soap->ctx = SSL_CTX_new(SSLv23_method())))
03152 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't setup context", SOAP_SSL_ERROR);
03153
03154 #if 0
03155 SSL_CTX_set_mode(soap->ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY);
03156 #endif
03157 }
03158 if (soap->randfile)
03159 { if (!RAND_load_file(soap->randfile, -1))
03160 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't load randomness", SOAP_SSL_ERROR);
03161 }
03162 if (soap->cafile || soap->capath)
03163 { if (!SSL_CTX_load_verify_locations(soap->ctx, soap->cafile, soap->capath))
03164 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CA file", SOAP_SSL_ERROR);
03165 if (soap->cafile && (soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
03166 SSL_CTX_set_client_CA_list(soap->ctx, SSL_load_client_CA_file(soap->cafile));
03167 }
03168 if (!(soap->ssl_flags & SOAP_SSL_NO_DEFAULT_CA_PATH))
03169 { if (!SSL_CTX_set_default_verify_paths(soap->ctx))
03170 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read default CA file and/or directory", SOAP_SSL_ERROR);
03171 }
03172
03173 if (soap->keyfile)
03174 { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile))
03175 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read certificate key file", SOAP_SSL_ERROR);
03176 if (soap->password)
03177 { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password);
03178 SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password);
03179 }
03180 if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM))
03181 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read key file", SOAP_SSL_ERROR);
03182 }
03183
03184 #if 0
03185 if (soap->password)
03186 { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password);
03187 SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password);
03188 }
03189 if (!soap->cafile || !SSL_CTX_use_certificate_chain_file(soap->ctx, soap->cafile))
03190 { if (soap->keyfile)
03191 { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile))
03192 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read certificate or key file", SOAP_SSL_ERROR);
03193 if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM))
03194 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read key file", SOAP_SSL_ERROR);
03195 }
03196 }
03197 #endif
03198 if ((soap->ssl_flags & SOAP_SSL_RSA))
03199 { RSA *rsa = RSA_generate_key(SOAP_SSL_RSA_BITS, RSA_F4, NULL, NULL);
03200 if (!SSL_CTX_set_tmp_rsa(soap->ctx, rsa))
03201 { if (rsa)
03202 RSA_free(rsa);
03203 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't set RSA key", SOAP_SSL_ERROR);
03204 }
03205 RSA_free(rsa);
03206 }
03207 else if (soap->dhfile)
03208 { DH *dh = 0;
03209 char *s;
03210 int n = (int)soap_strtoul(soap->dhfile, &s, 10);
03211
03212 if (n >= 512 && s && *s == '\0')
03213 dh = DH_generate_parameters(n, 2, NULL, NULL);
03214 else
03215 { BIO *bio;
03216 bio = BIO_new_file(soap->dhfile, "r");
03217 if (!bio)
03218 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read DH file", SOAP_SSL_ERROR);
03219 dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
03220 BIO_free(bio);
03221 }
03222 if (!dh || DH_check(dh, &n) != 1 || SSL_CTX_set_tmp_dh(soap->ctx, dh) < 0)
03223 { if (dh)
03224 DH_free(dh);
03225 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't set DH parameters", SOAP_SSL_ERROR);
03226 }
03227 DH_free(dh);
03228 }
03229 flags = (SSL_OP_ALL | SSL_OP_NO_SSLv2);
03230 if ((soap->ssl_flags & SOAP_SSLv3))
03231 flags |= SSL_OP_NO_TLSv1;
03232 if ((soap->ssl_flags & SOAP_TLSv1))
03233 flags |= SSL_OP_NO_SSLv3;
03234 #ifdef SSL_OP_NO_TICKET
03235
03236
03237 flags |= SSL_OP_NO_TICKET;
03238 #endif
03239 SSL_CTX_set_options(soap->ctx, flags);
03240 if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
03241 mode = (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
03242 else if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION))
03243 mode = SSL_VERIFY_PEER;
03244 else
03245 mode = SSL_VERIFY_NONE;
03246 SSL_CTX_set_verify(soap->ctx, mode, soap->fsslverify);
03247 #if (OPENSSL_VERSION_NUMBER < 0x00905100L)
03248 SSL_CTX_set_verify_depth(soap->ctx, 1);
03249 #else
03250 SSL_CTX_set_verify_depth(soap->ctx, 9);
03251 #endif
03252 #endif
03253 #ifdef WITH_GNUTLS
03254 int ret;
03255 if (!soap_ssl_init_done)
03256 soap_ssl_init();
03257 if (!soap->xcred)
03258 { gnutls_certificate_allocate_credentials(&soap->xcred);
03259 if (soap->cafile)
03260 { if (gnutls_certificate_set_x509_trust_file(soap->xcred, soap->cafile, GNUTLS_X509_FMT_PEM) < 0)
03261 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CA file", SOAP_SSL_ERROR);
03262 }
03263 if (soap->crlfile)
03264 { if (gnutls_certificate_set_x509_crl_file(soap->xcred, soap->crlfile, GNUTLS_X509_FMT_PEM) < 0)
03265 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CRL file", SOAP_SSL_ERROR);
03266 }
03267 if (soap->keyfile)
03268 { if (gnutls_certificate_set_x509_key_file(soap->xcred, soap->keyfile, soap->keyfile, GNUTLS_X509_FMT_PEM) < 0)
03269 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read key file", SOAP_SSL_ERROR);
03270 }
03271 }
03272 if ((soap->ssl_flags & SOAP_SSL_CLIENT))
03273 { gnutls_init(&soap->session, GNUTLS_CLIENT);
03274 if (soap->cafile || soap->crlfile || soap->keyfile)
03275 { ret = gnutls_priority_set_direct(soap->session, "PERFORMANCE", NULL);
03276 if (ret < 0)
03277 return soap_set_receiver_error(soap, soap_ssl_error(soap, ret), "SSL/TLS set priority error", SOAP_SSL_ERROR);
03278 gnutls_credentials_set(soap->session, GNUTLS_CRD_CERTIFICATE, soap->xcred);
03279 }
03280 else
03281 { if (!soap->acred)
03282 gnutls_anon_allocate_client_credentials(&soap->acred);
03283 gnutls_init(&soap->session, GNUTLS_CLIENT);
03284 gnutls_priority_set_direct(soap->session, "PERFORMANCE:+ANON-DH:!ARCFOUR-128", NULL);
03285 gnutls_credentials_set(soap->session, GNUTLS_CRD_ANON, soap->acred);
03286 }
03287 }
03288 else
03289 { if (!soap->keyfile)
03290 return soap_set_receiver_error(soap, "SSL/TLS error", "No key file: anonymous server authentication not supported in this release", SOAP_SSL_ERROR);
03291 if ((soap->ssl_flags & SOAP_SSL_RSA) && soap->rsa_params)
03292 gnutls_certificate_set_rsa_export_params(soap->xcred, soap->rsa_params);
03293 else if (soap->dh_params)
03294 gnutls_certificate_set_dh_params(soap->xcred, soap->dh_params);
03295 if (!soap->cache)
03296 gnutls_priority_init(&soap->cache, "NORMAL", NULL);
03297 gnutls_init(&soap->session, GNUTLS_SERVER);
03298 gnutls_priority_set(soap->session, soap->cache);
03299 gnutls_credentials_set(soap->session, GNUTLS_CRD_CERTIFICATE, soap->xcred);
03300 if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
03301 gnutls_certificate_server_set_request(soap->session, GNUTLS_CERT_REQUEST);
03302 gnutls_session_enable_compatibility_mode(soap->session);
03303 if ((soap->ssl_flags & SOAP_TLSv1))
03304 { int protocol_priority[] = { GNUTLS_TLS1_0, 0 };
03305 if (gnutls_protocol_set_priority(soap->session, protocol_priority) != GNUTLS_E_SUCCESS)
03306 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't set TLS v1.0 protocol", SOAP_SSL_ERROR);
03307 }
03308 }
03309 #endif
03310 return SOAP_OK;
03311 }
03312 #endif
03313 #endif
03314
03315
03316 #ifdef WITH_OPENSSL
03317 #ifndef PALM_1
03318 static int
03319 ssl_password(char *buf, int num, int rwflag, void *userdata)
03320 { if (num < (int)strlen((char*)userdata) + 1)
03321 return 0;
03322 return (int)strlen(strcpy(buf, (char*)userdata));
03323 }
03324 #endif
03325 #endif
03326
03327
03328 #ifdef WITH_OPENSSL
03329 #ifndef PALM_1
03330 static int
03331 ssl_verify_callback(int ok, X509_STORE_CTX *store)
03332 {
03333 #ifdef SOAP_DEBUG
03334 if (!ok)
03335 { char buf[1024];
03336 X509 *cert = X509_STORE_CTX_get_current_cert(store);
03337 fprintf(stderr, "SSL verify error or warning with certificate at depth %d: %s\n", X509_STORE_CTX_get_error_depth(store), X509_verify_cert_error_string(X509_STORE_CTX_get_error(store)));
03338 X509_NAME_oneline(X509_get_issuer_name(cert), buf, sizeof(buf));
03339 fprintf(stderr, "certificate issuer %s\n", buf);
03340 X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf));
03341 fprintf(stderr, "certificate subject %s\n", buf);
03342 }
03343 #endif
03344
03345 return ok;
03346 }
03347 #endif
03348 #endif
03349
03350
03351 #ifdef WITH_OPENSSL
03352 #ifndef PALM_1
03353 static int
03354 ssl_verify_callback_allow_expired_certificate(int ok, X509_STORE_CTX *store)
03355 { ok = ssl_verify_callback(ok, store);
03356 if (ok == 0 && X509_STORE_CTX_get_error(store) == X509_V_ERR_CERT_HAS_EXPIRED)
03357 {
03358 #ifdef SOAP_DEBUG
03359 fprintf(stderr, "ignoring certificate expiration\n");
03360 #endif
03361 X509_STORE_CTX_set_error(store, X509_V_OK);
03362 ok = 1;
03363 }
03364
03365 return ok;
03366 }
03367 #endif
03368 #endif
03369
03370
03371 #ifdef WITH_GNUTLS
03372 static const char *
03373 ssl_verify(struct soap *soap, const char *host)
03374 { unsigned int status;
03375 const char *err = NULL;
03376 int r = gnutls_certificate_verify_peers2(soap->session, &status);
03377 if (r < 0)
03378 err = "Certificate verify error";
03379 else if ((status & GNUTLS_CERT_INVALID))
03380 err = "The certificate is not trusted";
03381 else if ((status & GNUTLS_CERT_SIGNER_NOT_FOUND))
03382 err = "The certificate hasn't got a known issuer";
03383 else if ((status & GNUTLS_CERT_REVOKED))
03384 err = "The certificate has been revoked";
03385 else if (gnutls_certificate_type_get(soap->session) == GNUTLS_CRT_X509)
03386 { gnutls_x509_crt_t cert;
03387 const gnutls_datum_t *cert_list;
03388 unsigned int cert_list_size;
03389 if (gnutls_x509_crt_init(&cert) < 0)
03390 err = "Could not get X509 certificates";
03391 else if ((cert_list = gnutls_certificate_get_peers(soap->session, &cert_list_size)) == NULL)
03392 err = "Could not get X509 certificates";
03393 else if (gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0)
03394 err = "Error parsing X509 certificate";
03395 else if (!(soap->ssl_flags & SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE) && gnutls_x509_crt_get_expiration_time(cert) < time(NULL))
03396 err = "The certificate has expired";
03397 else if (!(soap->ssl_flags & SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE) && gnutls_x509_crt_get_activation_time(cert) > time(NULL))
03398 err = "The certificate is not yet activated";
03399 else if (host && !(soap->ssl_flags & SOAP_SSL_SKIP_HOST_CHECK))
03400 { if (!gnutls_x509_crt_check_hostname(cert, host))
03401 err = "Certificate host name mismatch";
03402 }
03403 gnutls_x509_crt_deinit(cert);
03404 }
03405 return err;
03406 }
03407 #endif
03408
03409
03410 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
03411 #ifndef WITH_NOIO
03412 #ifndef PALM_1
03413 SOAP_FMAC1
03414 int
03415 SOAP_FMAC2
03416 soap_ssl_accept(struct soap *soap)
03417 { SOAP_SOCKET fd = soap->socket;
03418 #ifdef WITH_OPENSSL
03419 BIO *bio;
03420 int retries, r, s;
03421 if (!soap_valid_socket(fd))
03422 return soap_set_receiver_error(soap, "SSL/TLS error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR);
03423 soap->ssl_flags &= ~SOAP_SSL_CLIENT;
03424 if (!soap->ctx && (soap->error = soap->fsslauth(soap)))
03425 return soap->error;
03426 if (!soap->ssl)
03427 { soap->ssl = SSL_new(soap->ctx);
03428 if (!soap->ssl)
03429 return soap_set_receiver_error(soap, "SSL/TLS error", "SSL_new() failed in soap_ssl_accept()", SOAP_SSL_ERROR);
03430 }
03431 else
03432 SSL_clear(soap->ssl);
03433 bio = BIO_new_socket((int)fd, BIO_NOCLOSE);
03434 SSL_set_bio(soap->ssl, bio, bio);
03435
03436 retries = 0;
03437 if (soap->accept_timeout)
03438 { SOAP_SOCKNONBLOCK(fd)
03439 retries = 10*soap->accept_timeout;
03440 }
03441 if (retries <= 0)
03442 retries = 100;
03443 while ((r = SSL_accept(soap->ssl)) <= 0)
03444 { int err;
03445 if (retries-- <= 0)
03446 break;
03447 err = SSL_get_error(soap->ssl, r);
03448 if (err == SSL_ERROR_WANT_ACCEPT || err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
03449 { if (err == SSL_ERROR_WANT_READ)
03450 s = tcp_select(soap, fd, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000);
03451 else
03452 s = tcp_select(soap, fd, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000);
03453 if (s < 0 && soap->errnum != SOAP_EINTR)
03454 break;
03455 }
03456 else
03457 { soap->errnum = soap_socket_errno(fd);
03458 break;
03459 }
03460 }
03461 if (r <= 0)
03462 { soap_set_receiver_error(soap, soap_ssl_error(soap, r), "SSL_accept() failed in soap_ssl_accept()", SOAP_SSL_ERROR);
03463 soap_closesock(soap);
03464 return SOAP_SSL_ERROR;
03465 }
03466 if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
03467 { X509 *peer;
03468 int err;
03469 if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK)
03470 { soap_closesock(soap);
03471 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);
03472 }
03473 peer = SSL_get_peer_certificate(soap->ssl);
03474 if (!peer)
03475 { soap_closesock(soap);
03476 return soap_set_sender_error(soap, "SSL/TLS error", "No SSL certificate was presented by the peer in soap_ssl_accept()", SOAP_SSL_ERROR);
03477 }
03478 X509_free(peer);
03479 }
03480 #endif
03481 #ifdef WITH_GNUTLS
03482 int retries = 0, r;
03483 if (!soap_valid_socket(fd))
03484 return soap_set_receiver_error(soap, "SSL/TLS error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR);
03485 soap->ssl_flags &= ~SOAP_SSL_CLIENT;
03486 if (!soap->session && (soap->error = soap->fsslauth(soap)))
03487 { soap_closesock(soap);
03488 return soap->error;
03489 }
03490 gnutls_transport_set_ptr(soap->session, (gnutls_transport_ptr_t)(long)fd);
03491
03492 if (soap->accept_timeout)
03493 { SOAP_SOCKNONBLOCK(fd)
03494 retries = 10*soap->accept_timeout;
03495 }
03496 if (retries <= 0)
03497 retries = 100;
03498 while ((r = gnutls_handshake(soap->session)))
03499 { int s;
03500
03501 if (retries-- <= 0)
03502 break;
03503 if (r == GNUTLS_E_AGAIN || r == GNUTLS_E_INTERRUPTED)
03504 { if (!gnutls_record_get_direction(soap->session))
03505 s = tcp_select(soap, fd, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000);
03506 else
03507 s = tcp_select(soap, fd, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000);
03508 if (s < 0 && soap->errnum != SOAP_EINTR)
03509 break;
03510 }
03511 else
03512 { soap->errnum = soap_socket_errno(fd);
03513 break;
03514 }
03515 }
03516 if (r)
03517 { soap_closesock(soap);
03518 return soap_set_receiver_error(soap, soap_ssl_error(soap, r), "SSL/TLS handshake failed", SOAP_SSL_ERROR);
03519 }
03520 if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
03521 { const char *err = ssl_verify(soap, NULL);
03522 if (err)
03523 { soap_closesock(soap);
03524 return soap_set_receiver_error(soap, "SSL/TLS error", err, SOAP_SSL_ERROR);
03525 }
03526 }
03527 #endif
03528 if (soap->recv_timeout || soap->send_timeout)
03529 SOAP_SOCKNONBLOCK(fd)
03530 else
03531 SOAP_SOCKBLOCK(fd)
03532 soap->imode |= SOAP_ENC_SSL;
03533 soap->omode |= SOAP_ENC_SSL;
03534 return SOAP_OK;
03535 }
03536 #endif
03537 #endif
03538 #endif
03539
03540
03541
03542
03543
03544
03545
03546
03547 #ifndef WITH_NOIO
03548 #ifndef PALM_1
03549 static int
03550 tcp_init(struct soap *soap)
03551 { soap->errmode = 1;
03552 #ifdef WIN32
03553 if (tcp_done)
03554 return 0;
03555 else
03556 { WSADATA w;
03557 if (WSAStartup(MAKEWORD(1, 1), &w))
03558 return -1;
03559 tcp_done = 1;
03560 }
03561 #endif
03562 return 0;
03563 }
03564 #endif
03565 #endif
03566
03567
03568 #ifndef WITH_NOIO
03569 #ifndef PALM_1
03570 static const char*
03571 tcp_error(struct soap *soap)
03572 { register const char *msg = NULL;
03573 switch (soap->errmode)
03574 { case 0:
03575 msg = soap_strerror(soap);
03576 break;
03577 case 1:
03578 msg = "WSAStartup failed";
03579 break;
03580 case 2:
03581 {
03582 #ifndef WITH_LEAN
03583 msg = soap_code_str(h_error_codes, soap->errnum);
03584 if (!msg)
03585 #endif
03586 { sprintf(soap->msgbuf, "TCP/UDP IP error %d", soap->errnum);
03587 msg = soap->msgbuf;
03588 }
03589 }
03590 }
03591 return msg;
03592 }
03593 #endif
03594 #endif
03595
03596
03597 #ifndef WITH_IPV6
03598 #ifndef WITH_NOIO
03599 #ifndef PALM_1
03600 static int
03601 tcp_gethost(struct soap *soap, const char *addr, struct in_addr *inaddr)
03602 { soap_int32 iadd = -1;
03603 struct hostent hostent, *host = &hostent;
03604 #ifdef VXWORKS
03605 int hostint;
03606
03607 iadd = inet_addr((char*)addr);
03608 #else
03609 #if defined(_AIX43) || ((defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R))
03610 struct hostent_data ht_data;
03611 #endif
03612 #ifdef AS400
03613 iadd = inet_addr((void*)addr);
03614 #else
03615 iadd = inet_addr(addr);
03616 #endif
03617 #endif
03618 if (iadd != -1)
03619 { memcpy(inaddr, &iadd, sizeof(iadd));
03620 return SOAP_OK;
03621 }
03622 #if defined(__GLIBC__) || (defined(HAVE_GETHOSTBYNAME_R) && (defined(FREEBSD) || defined(__FreeBSD__)))
03623 if (gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &host, &soap->errnum) < 0)
03624 host = NULL;
03625 #elif defined(_AIX43) || ((defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R))
03626 memset((void*)&ht_data, 0, sizeof(ht_data));
03627 if (gethostbyname_r(addr, &hostent, &ht_data) < 0)
03628 { host = NULL;
03629 soap->errnum = h_errno;
03630 }
03631 #elif defined(HAVE_GETHOSTBYNAME_R)
03632 host = gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &soap->errnum);
03633 #elif defined(VXWORKS)
03634
03635
03636
03637 hostint = hostGetByName((char*)addr);
03638 if (hostint == ERROR)
03639 { host = NULL;
03640 soap->errnum = soap_errno;
03641 }
03642 #else
03643 #ifdef AS400
03644 if (!(host = gethostbyname((void*)addr)))
03645 soap->errnum = h_errno;
03646 #else
03647 if (!(host = gethostbyname(addr)))
03648 soap->errnum = h_errno;
03649 #endif
03650 #endif
03651 if (!host)
03652 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Host name not found\n"));
03653 return SOAP_ERR;
03654 }
03655 #ifdef VXWORKS
03656 inaddr->s_addr = hostint;
03657 #else
03658 memcpy(inaddr, host->h_addr, host->h_length);
03659 #endif
03660 return SOAP_OK;
03661 }
03662 #endif
03663 #endif
03664 #endif
03665
03666
03667 #ifndef WITH_NOIO
03668 #ifndef PALM_1
03669 static SOAP_SOCKET
03670 tcp_connect(struct soap *soap, const char *endpoint, const char *host, int port)
03671 {
03672 #ifdef WITH_IPV6
03673 struct addrinfo hints, *res, *ressave;
03674 #endif
03675 SOAP_SOCKET fd;
03676 int err = 0;
03677 #ifndef WITH_LEAN
03678 #ifndef WIN32
03679 int len = SOAP_BUFLEN;
03680 #else
03681 int len = SOAP_BUFLEN + 1;
03682 #endif
03683 int set = 1;
03684 #endif
03685 #if !defined(WITH_LEAN) || defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
03686 int retries;
03687 #endif
03688 if (soap_valid_socket(soap->socket))
03689 soap->fclosesocket(soap, soap->socket);
03690 soap->socket = SOAP_INVALID_SOCKET;
03691 if (tcp_init(soap))
03692 { soap->errnum = 0;
03693 soap_set_sender_error(soap, tcp_error(soap), "TCP init failed in tcp_connect()", SOAP_TCP_ERROR);
03694 return SOAP_INVALID_SOCKET;
03695 }
03696 soap->errmode = 0;
03697 #ifdef WITH_IPV6
03698 memset((void*)&hints, 0, sizeof(hints));
03699 hints.ai_family = PF_UNSPEC;
03700 #ifndef WITH_LEAN
03701 if ((soap->omode & SOAP_IO_UDP))
03702 hints.ai_socktype = SOCK_DGRAM;
03703 else
03704 #endif
03705 hints.ai_socktype = SOCK_STREAM;
03706 soap->errmode = 2;
03707 if (soap->proxy_host)
03708 err = getaddrinfo(soap->proxy_host, soap_int2s(soap, soap->proxy_port), &hints, &res);
03709 else
03710 err = getaddrinfo(host, soap_int2s(soap, port), &hints, &res);
03711 if (err)
03712 { soap_set_sender_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in tcp_connect()", SOAP_TCP_ERROR);
03713 return SOAP_INVALID_SOCKET;
03714 }
03715 ressave = res;
03716 again:
03717 fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
03718 soap->errmode = 0;
03719 #else
03720 #ifndef WITH_LEAN
03721 again:
03722 #endif
03723 #ifndef WITH_LEAN
03724 if ((soap->omode & SOAP_IO_UDP))
03725 fd = socket(AF_INET, SOCK_DGRAM, 0);
03726 else
03727 #endif
03728 fd = socket(AF_INET, SOCK_STREAM, 0);
03729 #endif
03730 if (!soap_valid_socket(fd))
03731 {
03732 #ifdef WITH_IPV6
03733 if (res->ai_next)
03734 { res = res->ai_next;
03735 goto again;
03736 }
03737 #endif
03738 soap->errnum = soap_socket_errno(fd);
03739 soap_set_sender_error(soap, tcp_error(soap), "socket failed in tcp_connect()", SOAP_TCP_ERROR);
03740 #ifdef WITH_IPV6
03741 freeaddrinfo(ressave);
03742 #endif
03743 return SOAP_INVALID_SOCKET;
03744 }
03745 #ifdef SOCKET_CLOSE_ON_EXEC
03746 #ifdef WIN32
03747 #ifndef UNDER_CE
03748 SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0);
03749 #endif
03750 #else
03751 fcntl(fd, F_SETFD, 1);
03752 #endif
03753 #endif
03754 #ifndef WITH_LEAN
03755 if (soap->connect_flags == SO_LINGER)
03756 { struct linger linger;
03757 memset((void*)&linger, 0, sizeof(linger));
03758 linger.l_onoff = 1;
03759 linger.l_linger = soap->linger_time;
03760 if (setsockopt(fd, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger)))
03761 { soap->errnum = soap_socket_errno(fd);
03762 soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in tcp_connect()", SOAP_TCP_ERROR);
03763 soap->fclosesocket(soap, fd);
03764 #ifdef WITH_IPV6
03765 freeaddrinfo(ressave);
03766 #endif
03767 return SOAP_INVALID_SOCKET;
03768 }
03769 }
03770 else if (soap->connect_flags && setsockopt(fd, SOL_SOCKET, soap->connect_flags, (char*)&set, sizeof(int)))
03771 { soap->errnum = soap_socket_errno(fd);
03772 soap_set_sender_error(soap, tcp_error(soap), "setsockopt failed in tcp_connect()", SOAP_TCP_ERROR);
03773 soap->fclosesocket(soap, fd);
03774 #ifdef WITH_IPV6
03775 freeaddrinfo(ressave);
03776 #endif
03777 return SOAP_INVALID_SOCKET;
03778 }
03779 if ((soap->keep_alive || soap->tcp_keep_alive) && setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
03780 { soap->errnum = soap_socket_errno(fd);
03781 soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in tcp_connect()", SOAP_TCP_ERROR);
03782 soap->fclosesocket(soap, fd);
03783 #ifdef WITH_IPV6
03784 freeaddrinfo(ressave);
03785 #endif
03786 return SOAP_INVALID_SOCKET;
03787 }
03788 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
03789 { soap->errnum = soap_socket_errno(fd);
03790 soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in tcp_connect()", SOAP_TCP_ERROR);
03791 soap->fclosesocket(soap, fd);
03792 #ifdef WITH_IPV6
03793 freeaddrinfo(ressave);
03794 #endif
03795 return SOAP_INVALID_SOCKET;
03796 }
03797 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
03798 { soap->errnum = soap_socket_errno(fd);
03799 soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in tcp_connect()", SOAP_TCP_ERROR);
03800 soap->fclosesocket(soap, fd);
03801 #ifdef WITH_IPV6
03802 freeaddrinfo(ressave);
03803 #endif
03804 return SOAP_INVALID_SOCKET;
03805 }
03806 #ifdef TCP_KEEPIDLE
03807 if (soap->tcp_keep_idle && setsockopt((SOAP_SOCKET)fd, IPPROTO_TCP, TCP_KEEPIDLE, (char*)&(soap->tcp_keep_idle), sizeof(int)))
03808 { soap->errnum = soap_socket_errno(fd);
03809 soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPIDLE failed in tcp_connect()", SOAP_TCP_ERROR);
03810 soap->fclosesocket(soap, (SOAP_SOCKET)fd);
03811 #ifdef WITH_IPV6
03812 freeaddrinfo(ressave);
03813 #endif
03814 return SOAP_INVALID_SOCKET;
03815 }
03816 #endif
03817 #ifdef TCP_KEEPINTVL
03818 if (soap->tcp_keep_intvl && setsockopt((SOAP_SOCKET)fd, IPPROTO_TCP, TCP_KEEPINTVL, (char*)&(soap->tcp_keep_intvl), sizeof(int)))
03819 { soap->errnum = soap_socket_errno(fd);
03820 soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPINTVL failed in tcp_connect()", SOAP_TCP_ERROR);
03821 soap->fclosesocket(soap, (SOAP_SOCKET)fd);
03822 #ifdef WITH_IPV6
03823 freeaddrinfo(ressave);
03824 #endif
03825 return SOAP_INVALID_SOCKET;
03826 }
03827 #endif
03828 #ifdef TCP_KEEPCNT
03829 if (soap->tcp_keep_cnt && setsockopt((SOAP_SOCKET)fd, IPPROTO_TCP, TCP_KEEPCNT, (char*)&(soap->tcp_keep_cnt), sizeof(int)))
03830 { soap->errnum = soap_socket_errno(fd);
03831 soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPCNT failed in tcp_connect()", SOAP_TCP_ERROR);
03832 soap->fclosesocket(soap, (SOAP_SOCKET)fd);
03833 #ifdef WITH_IPV6
03834 freeaddrinfo(ressave);
03835 #endif
03836 return SOAP_INVALID_SOCKET;
03837 }
03838 #endif
03839 #ifdef TCP_NODELAY
03840 if (!(soap->omode & SOAP_IO_UDP) && setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
03841 { soap->errnum = soap_socket_errno(fd);
03842 soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in tcp_connect()", SOAP_TCP_ERROR);
03843 soap->fclosesocket(soap, fd);
03844 #ifdef WITH_IPV6
03845 freeaddrinfo(ressave);
03846 #endif
03847 return SOAP_INVALID_SOCKET;
03848 }
03849 #endif
03850 #ifdef WITH_IPV6
03851 if ((soap->omode & SOAP_IO_UDP) && soap->ipv6_multicast_if)
03852 { struct sockaddr_in6 *in6addr = (struct sockaddr_in6*)res->ai_addr;
03853 in6addr->sin6_scope_id = soap->ipv6_multicast_if;
03854 }
03855 #endif
03856 #ifdef IP_MULTICAST_TTL
03857 if ((soap->omode & SOAP_IO_UDP))
03858 { if (soap->ipv4_multicast_ttl)
03859 { unsigned char ttl = soap->ipv4_multicast_ttl;
03860 if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ttl, sizeof(ttl)))
03861 { soap->errnum = soap_socket_errno(fd);
03862 soap_set_sender_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_TTL failed in tcp_connect()", SOAP_TCP_ERROR);
03863 soap->fclosesocket(soap, fd);
03864 return SOAP_INVALID_SOCKET;
03865 }
03866 }
03867 if ((soap->omode & SOAP_IO_UDP) && soap->ipv4_multicast_if && !soap->ipv6_multicast_if)
03868 { if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, (char*)soap->ipv4_multicast_if, sizeof(struct in_addr)))
03869 #ifndef WINDOWS
03870 { soap->errnum = soap_socket_errno(fd);
03871 soap_set_sender_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR);
03872 soap->fclosesocket(soap, fd);
03873 return SOAP_INVALID_SOCKET;
03874 }
03875 #else
03876 #ifndef IP_MULTICAST_IF
03877 #define IP_MULTICAST_IF 2
03878 #endif
03879 if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, (char*)soap->ipv4_multicast_if, sizeof(struct in_addr)))
03880 { soap->errnum = soap_socket_errno(fd);
03881 soap_set_sender_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR);
03882 soap->fclosesocket(soap, fd);
03883 return SOAP_INVALID_SOCKET;
03884 }
03885 #endif
03886 }
03887 }
03888 #endif
03889 #endif
03890 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Opening socket %d to host='%s' port=%d\n", fd, host, port));
03891 #ifndef WITH_IPV6
03892 soap->peerlen = sizeof(soap->peer);
03893 memset((void*)&soap->peer, 0, sizeof(soap->peer));
03894 soap->peer.sin_family = AF_INET;
03895 soap->errmode = 2;
03896 if (soap->proxy_host)
03897 { if (soap->fresolve(soap, soap->proxy_host, &soap->peer.sin_addr))
03898 { soap_set_sender_error(soap, tcp_error(soap), "get proxy host by name failed in tcp_connect()", SOAP_TCP_ERROR);
03899 soap->fclosesocket(soap, fd);
03900 return SOAP_INVALID_SOCKET;
03901 }
03902 soap->peer.sin_port = htons((short)soap->proxy_port);
03903 }
03904 else
03905 { if (soap->fresolve(soap, host, &soap->peer.sin_addr))
03906 { soap_set_sender_error(soap, tcp_error(soap), "get host by name failed in tcp_connect()", SOAP_TCP_ERROR);
03907 soap->fclosesocket(soap, fd);
03908 return SOAP_INVALID_SOCKET;
03909 }
03910 soap->peer.sin_port = htons((short)port);
03911 }
03912 soap->errmode = 0;
03913 #ifndef WITH_LEAN
03914 if ((soap->omode & SOAP_IO_UDP))
03915 return fd;
03916 #endif
03917 #else
03918 if ((soap->omode & SOAP_IO_UDP))
03919 { memcpy(&soap->peer, res->ai_addr, res->ai_addrlen);
03920 soap->peerlen = res->ai_addrlen;
03921 freeaddrinfo(ressave);
03922 return fd;
03923 }
03924 #endif
03925 #ifndef WITH_LEAN
03926 if (soap->connect_timeout)
03927 SOAP_SOCKNONBLOCK(fd)
03928 else
03929 SOAP_SOCKBLOCK(fd)
03930 retries = 10;
03931 #endif
03932 for (;;)
03933 {
03934 #ifdef WITH_IPV6
03935 if (connect(fd, res->ai_addr, (int)res->ai_addrlen))
03936 #else
03937 if (connect(fd, (struct sockaddr*)&soap->peer, sizeof(soap->peer)))
03938 #endif
03939 { err = soap_socket_errno(fd);
03940 #ifndef WITH_LEAN
03941 if (err == SOAP_EADDRINUSE)
03942 { soap->fclosesocket(soap, fd);
03943 if (retries-- > 0)
03944 goto again;
03945 }
03946 else if (soap->connect_timeout && (err == SOAP_EINPROGRESS || err == SOAP_EAGAIN || err == SOAP_EWOULDBLOCK))
03947 {
03948 SOAP_SOCKLEN_T k;
03949 for (;;)
03950 { register int r;
03951 r = tcp_select(soap, fd, SOAP_TCP_SELECT_SND, soap->connect_timeout);
03952 if (r > 0)
03953 break;
03954 if (!r)
03955 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n"));
03956 soap_set_sender_error(soap, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR);
03957 soap->fclosesocket(soap, fd);
03958 #ifdef WITH_IPV6
03959 freeaddrinfo(ressave);
03960 #endif
03961 return SOAP_INVALID_SOCKET;
03962 }
03963 r = soap->errnum;
03964 if (r != SOAP_EINTR)
03965 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
03966 soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
03967 soap->fclosesocket(soap, fd);
03968 #ifdef WITH_IPV6
03969 freeaddrinfo(ressave);
03970 #endif
03971 return SOAP_INVALID_SOCKET;
03972 }
03973 }
03974 k = (SOAP_SOCKLEN_T)sizeof(soap->errnum);
03975 if (!getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*)&soap->errnum, &k) && !soap->errnum)
03976 break;
03977 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
03978 if (!soap->errnum)
03979 soap->errnum = soap_socket_errno(fd);
03980 soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
03981 soap->fclosesocket(soap, fd);
03982 #ifdef WITH_IPV6
03983 freeaddrinfo(ressave);
03984 #endif
03985 return SOAP_INVALID_SOCKET;
03986 }
03987 #endif
03988 #ifdef WITH_IPV6
03989 if (res->ai_next)
03990 { res = res->ai_next;
03991 soap->fclosesocket(soap, fd);
03992 goto again;
03993 }
03994 #endif
03995 if (err && err != SOAP_EINTR)
03996 { soap->errnum = err;
03997 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
03998 soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
03999 soap->fclosesocket(soap, fd);
04000 #ifdef WITH_IPV6
04001 freeaddrinfo(ressave);
04002 #endif
04003 return SOAP_INVALID_SOCKET;
04004 }
04005 }
04006 else
04007 break;
04008 }
04009 #ifdef WITH_IPV6
04010 soap->peerlen = 0;
04011 freeaddrinfo(ressave);
04012 #endif
04013 soap->socket = fd;
04014 soap->imode &= ~SOAP_ENC_SSL;
04015 soap->omode &= ~SOAP_ENC_SSL;
04016 if (!soap_tag_cmp(endpoint, "https:*"))
04017 {
04018 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
04019 #ifdef WITH_OPENSSL
04020 BIO *bio;
04021 #endif
04022 int r;
04023 if (soap->proxy_host)
04024 { soap_mode m = soap->mode;
04025 soap_mode om = soap->omode;
04026 size_t n = soap->count;
04027 const char *userid, *passwd;
04028 soap->omode &= ~SOAP_ENC;
04029 soap->omode |= SOAP_IO_BUFFER;
04030 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connecting to %s proxy server\n", soap->proxy_http_version));
04031 sprintf(soap->tmpbuf, "CONNECT %s:%d HTTP/%s", host, port, soap->proxy_http_version);
04032 if (soap_begin_send(soap)
04033 || (soap->error = soap->fposthdr(soap, soap->tmpbuf, NULL)))
04034 { soap->fclosesocket(soap, fd);
04035 return SOAP_INVALID_SOCKET;
04036 }
04037 #ifndef WITH_LEAN
04038 if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761)
04039 { sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd);
04040 strcpy(soap->tmpbuf, "Basic ");
04041 soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262));
04042 if ((soap->error = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf)))
04043 { soap->fclosesocket(soap, fd);
04044 return soap->error;
04045 }
04046 }
04047 #endif
04048 if ((soap->error = soap->fposthdr(soap, NULL, NULL))
04049 || soap_flush(soap))
04050 { soap->fclosesocket(soap, fd);
04051 return SOAP_INVALID_SOCKET;
04052 }
04053 soap->omode = om;
04054 om = soap->imode;
04055 soap->imode &= ~SOAP_ENC;
04056 userid = soap->userid;
04057 passwd = soap->passwd;
04058 if ((soap->error = soap->fparse(soap)))
04059 { soap->fclosesocket(soap, fd);
04060 return SOAP_INVALID_SOCKET;
04061 }
04062 soap->userid = userid;
04063 soap->passwd = passwd;
04064 soap->imode = om;
04065 soap->count = n;
04066 if (soap_begin_send(soap))
04067 { soap->fclosesocket(soap, fd);
04068 return SOAP_INVALID_SOCKET;
04069 }
04070 if (endpoint)
04071 strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint)-1);
04072 soap->mode = m;
04073 }
04074 #ifdef WITH_OPENSSL
04075 soap->ssl_flags |= SOAP_SSL_CLIENT;
04076 if (!soap->ctx && (soap->error = soap->fsslauth(soap)))
04077 { soap->fclosesocket(soap, fd);
04078 return SOAP_INVALID_SOCKET;
04079 }
04080 if (!soap->ssl)
04081 { soap->ssl = SSL_new(soap->ctx);
04082 if (!soap->ssl)
04083 { soap->fclosesocket(soap, fd);
04084 soap->error = SOAP_SSL_ERROR;
04085 return SOAP_INVALID_SOCKET;
04086 }
04087 }
04088 else
04089 SSL_clear(soap->ssl);
04090 if (soap->session)
04091 { if (!strcmp(soap->session_host, host) && soap->session_port == port)
04092 SSL_set_session(soap->ssl, soap->session);
04093 SSL_SESSION_free(soap->session);
04094 soap->session = NULL;
04095 }
04096 soap->imode |= SOAP_ENC_SSL;
04097 soap->omode |= SOAP_ENC_SSL;
04098 bio = BIO_new_socket((int)fd, BIO_NOCLOSE);
04099 SSL_set_bio(soap->ssl, bio, bio);
04100
04101 retries = 0;
04102 if (soap->connect_timeout)
04103 { SOAP_SOCKNONBLOCK(fd)
04104 retries = 10*soap->connect_timeout;
04105 }
04106 else
04107 SOAP_SOCKBLOCK(fd)
04108 if (retries <= 0)
04109 retries = 100;
04110
04111 do
04112 { if ((r = SSL_connect(soap->ssl)) <= 0)
04113 { int err = SSL_get_error(soap->ssl, r);
04114 if (err == SSL_ERROR_WANT_CONNECT || err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
04115 { register int s;
04116 if (err == SSL_ERROR_WANT_READ)
04117 s = tcp_select(soap, fd, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000);
04118 else
04119 s = tcp_select(soap, fd, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000);
04120 if (s < 0 && soap->errnum != SOAP_EINTR)
04121 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL_connect/select error in tcp_connect\n"));
04122 soap_set_sender_error(soap, soap_ssl_error(soap, r), "SSL_connect failed in tcp_connect()", SOAP_TCP_ERROR);
04123 soap->fclosesocket(soap, fd);
04124 return SOAP_INVALID_SOCKET;
04125 }
04126 if (s == 0 && retries-- <= 0)
04127 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL/TLS connect timeout\n"));
04128 soap_set_sender_error(soap, "Timeout", "SSL_connect failed in tcp_connect()", SOAP_TCP_ERROR);
04129 soap->fclosesocket(soap, fd);
04130 return SOAP_INVALID_SOCKET;
04131 }
04132 }
04133 else
04134 { soap_set_sender_error(soap, soap_ssl_error(soap, r), "SSL_connect error in tcp_connect()", SOAP_SSL_ERROR);
04135 soap->fclosesocket(soap, fd);
04136 return SOAP_INVALID_SOCKET;
04137 }
04138 }
04139 } while (!SSL_is_init_finished(soap->ssl));
04140
04141 SOAP_SOCKNONBLOCK(fd)
04142
04143 if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION))
04144 { int err;
04145 if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK)
04146 { 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);
04147 soap->fclosesocket(soap, fd);
04148 return SOAP_INVALID_SOCKET;
04149 }
04150 if (!(soap->ssl_flags & SOAP_SSL_SKIP_HOST_CHECK))
04151 { X509_NAME *subj;
04152 int ext_count;
04153 int ok = 0;
04154 X509 *peer;
04155 peer = SSL_get_peer_certificate(soap->ssl);
04156 if (!peer)
04157 { soap_set_sender_error(soap, "SSL/TLS error", "No SSL/TLS certificate was presented by the peer in tcp_connect()", SOAP_SSL_ERROR);
04158 soap->fclosesocket(soap, fd);
04159 return SOAP_INVALID_SOCKET;
04160 }
04161 ext_count = X509_get_ext_count(peer);
04162 if (ext_count > 0)
04163 { int i;
04164 for (i = 0; i < ext_count; i++)
04165 { X509_EXTENSION *ext = X509_get_ext(peer, i);
04166 const char *ext_str = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));
04167 if (ext_str && !strcmp(ext_str, "subjectAltName"))
04168 { X509V3_EXT_METHOD *meth = (X509V3_EXT_METHOD*)X509V3_EXT_get(ext);
04169 void *ext_data;
04170 #if (OPENSSL_VERSION_NUMBER >= 0x0090800fL)
04171 const unsigned char *data;
04172 #else
04173 unsigned char *data;
04174 #endif
04175 STACK_OF(CONF_VALUE) *val;
04176 int j;
04177 if (!meth)
04178 break;
04179 data = ext->value->data;
04180 #if (OPENSSL_VERSION_NUMBER > 0x00907000L)
04181 if (meth->it)
04182 ext_data = ASN1_item_d2i(NULL, &data, ext->value->length, ASN1_ITEM_ptr(meth->it));
04183 else
04184 {
04185
04186
04187
04188
04189
04190 ext_data = meth->d2i(NULL, &data, ext->value->length);
04191 }
04192 #else
04193 ext_data = meth->d2i(NULL, &data, ext->value->length);
04194 #endif
04195 if (ext_data)
04196 { val = meth->i2v(meth, ext_data, NULL);
04197 if (val)
04198 { for (j = 0; j < sk_CONF_VALUE_num(val); j++)
04199 { CONF_VALUE *nval = sk_CONF_VALUE_value(val, j);
04200 if (nval && !strcmp(nval->name, "DNS") && !strcmp(nval->value, host))
04201 { ok = 1;
04202 break;
04203 }
04204 }
04205 sk_CONF_VALUE_pop_free(val, X509V3_conf_free);
04206 }
04207 #if (OPENSSL_VERSION_NUMBER > 0x00907000L)
04208 if (meth->it)
04209 ASN1_item_free((ASN1_VALUE*)ext_data, ASN1_ITEM_ptr(meth->it));
04210 else
04211 meth->ext_free(ext_data);
04212 #else
04213 meth->ext_free(ext_data);
04214 #endif
04215 }
04216 }
04217 if (ok)
04218 break;
04219 }
04220 }
04221 if (!ok && (subj = X509_get_subject_name(peer)))
04222 { int i = -1;
04223 do
04224 { ASN1_STRING *name;
04225 i = X509_NAME_get_index_by_NID(subj, NID_commonName, i);
04226 if (i == -1)
04227 break;
04228 name = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subj, i));
04229 if (name)
04230 { if (!soap_tag_cmp(host, (const char*)M_ASN1_STRING_data(name)))
04231 ok = 1;
04232 else
04233 { unsigned char *tmp = NULL;
04234 ASN1_STRING_to_UTF8(&tmp, name);
04235 if (tmp)
04236 { if (!soap_tag_cmp(host, (const char*)tmp))
04237 ok = 1;
04238 else if (tmp[0] == '*')
04239 { const char *t = strchr(host, '.');
04240 if (t && !soap_tag_cmp(t, (const char*)tmp+1))
04241 ok = 1;
04242 }
04243 OPENSSL_free(tmp);
04244 }
04245 }
04246 }
04247 } while (!ok);
04248 }
04249 X509_free(peer);
04250 if (!ok)
04251 { soap_set_sender_error(soap, "SSL/TLS error", "SSL/TLS certificate host name mismatch in tcp_connect()", SOAP_SSL_ERROR);
04252 soap->fclosesocket(soap, fd);
04253 return SOAP_INVALID_SOCKET;
04254 }
04255 }
04256 }
04257 #endif
04258 #ifdef WITH_GNUTLS
04259 soap->ssl_flags |= SOAP_SSL_CLIENT;
04260 if (!soap->session && (soap->error = soap->fsslauth(soap)))
04261 { soap->fclosesocket(soap, fd);
04262 return SOAP_INVALID_SOCKET;
04263 }
04264 gnutls_transport_set_ptr(soap->session, (gnutls_transport_ptr_t)(long)fd);
04265
04266 if (soap->connect_timeout)
04267 { SOAP_SOCKNONBLOCK(fd)
04268 retries = 10*soap->connect_timeout;
04269 }
04270 else
04271 SOAP_SOCKBLOCK(fd)
04272 if (retries <= 0)
04273 retries = 100;
04274 while ((r = gnutls_handshake(soap->session)))
04275 { int s;
04276
04277 if (retries-- <= 0)
04278 break;
04279 if (r == GNUTLS_E_AGAIN || r == GNUTLS_E_INTERRUPTED)
04280 { if (!gnutls_record_get_direction(soap->session))
04281 s = tcp_select(soap, fd, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000);
04282 else
04283 s = tcp_select(soap, fd, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000);
04284 if (s < 0 && soap->errnum != SOAP_EINTR)
04285 break;
04286 }
04287 else
04288 { soap->errnum = soap_socket_errno(fd);
04289 break;
04290 }
04291 }
04292 if (r)
04293 { soap_set_sender_error(soap, soap_ssl_error(soap, r), "SSL/TLS handshake failed", SOAP_SSL_ERROR);
04294 soap->fclosesocket(soap, fd);
04295 return SOAP_INVALID_SOCKET;
04296 }
04297 if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION))
04298 { const char *err = ssl_verify(soap, host);
04299 if (err)
04300 { soap->fclosesocket(soap, fd);
04301 soap->error = soap_set_sender_error(soap, "SSL/TLS error", err, SOAP_SSL_ERROR);
04302 return SOAP_INVALID_SOCKET;
04303 }
04304 }
04305 #endif
04306 #else
04307 soap->fclosesocket(soap, fd);
04308 soap->error = SOAP_SSL_ERROR;
04309 return SOAP_INVALID_SOCKET;
04310 #endif
04311 }
04312 if (soap->recv_timeout || soap->send_timeout)
04313 SOAP_SOCKNONBLOCK(fd)
04314 else
04315 SOAP_SOCKBLOCK(fd)
04316 return fd;
04317 }
04318 #endif
04319 #endif
04320
04321
04322 #ifndef WITH_NOIO
04323 #ifndef PALM_1
04324 static int
04325 tcp_select(struct soap *soap, SOAP_SOCKET s, int flags, int timeout)
04326 { register int r;
04327 struct timeval tv;
04328 fd_set fd[3], *rfd, *sfd, *efd;
04329 soap->errnum = 0;
04330 #ifndef WIN32
04331 #if !defined(FD_SETSIZE) || defined(__QNX__) || defined(QNX)
04332
04333 if (1)
04334 #else
04335
04336 if ((int)s >= (int)FD_SETSIZE)
04337 #endif
04338 #ifdef HAVE_POLL
04339 { struct pollfd pollfd;
04340 int retries = 0;
04341 pollfd.fd = (int)s;
04342 pollfd.events = 0;
04343 if (flags & SOAP_TCP_SELECT_RCV)
04344 pollfd.events |= POLLIN;
04345 if (flags & SOAP_TCP_SELECT_SND)
04346 pollfd.events |= POLLOUT;
04347 if (flags & SOAP_TCP_SELECT_ERR)
04348 pollfd.events |= POLLERR;
04349 if (timeout < 0)
04350 timeout /= -1000;
04351 else if (timeout <= 1000000)
04352 timeout *= 1000;
04353 else
04354 { retries = timeout / 1000000;
04355 timeout = 1000000000;
04356 }
04357 do r = poll(&pollfd, 1, timeout);
04358 while (r == 0 && retries--);
04359 if (r > 0)
04360 { r = 0;
04361 if ((flags & SOAP_TCP_SELECT_RCV) && (pollfd.revents & POLLIN))
04362 r |= SOAP_TCP_SELECT_RCV;
04363 if ((flags & SOAP_TCP_SELECT_SND) && (pollfd.revents & POLLOUT))
04364 r |= SOAP_TCP_SELECT_SND;
04365 if ((flags & SOAP_TCP_SELECT_ERR) && (pollfd.revents & POLLERR))
04366 r |= SOAP_TCP_SELECT_ERR;
04367 }
04368 else if (r < 0)
04369 soap->errnum = soap_socket_errno(s);
04370 return r;
04371 }
04372 #else
04373 { soap->error = SOAP_FD_EXCEEDED;
04374 return -1;
04375 }
04376 #endif
04377 #endif
04378 rfd = sfd = efd = NULL;
04379 if (flags & SOAP_TCP_SELECT_RCV)
04380 { rfd = &fd[0];
04381 FD_ZERO(rfd);
04382 FD_SET(s, rfd);
04383 }
04384 if (flags & SOAP_TCP_SELECT_SND)
04385 { sfd = &fd[1];
04386 FD_ZERO(sfd);
04387 FD_SET(s, sfd);
04388 }
04389 if (flags & SOAP_TCP_SELECT_ERR)
04390 { efd = &fd[2];
04391 FD_ZERO(efd);
04392 FD_SET(s, efd);
04393 }
04394 if (timeout >= 0)
04395 { tv.tv_sec = timeout;
04396 tv.tv_usec = 0;
04397 }
04398 else
04399 { tv.tv_sec = -timeout / 1000000;
04400 tv.tv_usec = -timeout % 1000000;
04401 }
04402 r = select((int)s + 1, rfd, sfd, efd, &tv);
04403 if (r > 0)
04404 { r = 0;
04405 if ((flags & SOAP_TCP_SELECT_RCV) && FD_ISSET(s, rfd))
04406 r |= SOAP_TCP_SELECT_RCV;
04407 if ((flags & SOAP_TCP_SELECT_SND) && FD_ISSET(s, sfd))
04408 r |= SOAP_TCP_SELECT_SND;
04409 if ((flags & SOAP_TCP_SELECT_ERR) && FD_ISSET(s, efd))
04410 r |= SOAP_TCP_SELECT_ERR;
04411 }
04412 else if (r < 0)
04413 soap->errnum = soap_socket_errno(s);
04414 return r;
04415 }
04416 #endif
04417 #endif
04418
04419
04420 #ifndef WITH_NOIO
04421 #ifndef PALM_1
04422 static SOAP_SOCKET
04423 tcp_accept(struct soap *soap, SOAP_SOCKET s, struct sockaddr *a, int *n)
04424 { SOAP_SOCKET fd;
04425 fd = accept(s, a, (SOAP_SOCKLEN_T*)n);
04426 #ifdef SOCKET_CLOSE_ON_EXEC
04427 #ifdef WIN32
04428 #ifndef UNDER_CE
04429 SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0);
04430 #endif
04431 #else
04432 fcntl(fd, F_SETFD, FD_CLOEXEC);
04433 #endif
04434 #endif
04435 return fd;
04436 }
04437 #endif
04438 #endif
04439
04440
04441 #ifndef WITH_NOIO
04442 #ifndef PALM_1
04443 static int
04444 tcp_disconnect(struct soap *soap)
04445 {
04446 #ifdef WITH_OPENSSL
04447 if (soap->ssl)
04448 { int r, s = 0;
04449 if (soap->session)
04450 { SSL_SESSION_free(soap->session);
04451 soap->session = NULL;
04452 }
04453 if (*soap->host)
04454 { soap->session = SSL_get1_session(soap->ssl);
04455 if (soap->session)
04456 { strcpy(soap->session_host, soap->host);
04457 soap->session_port = soap->port;
04458 }
04459 }
04460 r = SSL_shutdown(soap->ssl);
04461
04462 if (r == 0)
04463 { while (SSL_want_read(soap->ssl))
04464 { if (SSL_read(soap->ssl, NULL, 0)
04465 || soap_socket_errno(soap->socket) != SOAP_EAGAIN)
04466 { r = SSL_shutdown(soap->ssl);
04467 break;
04468 }
04469 }
04470 }
04471 if (r == 0)
04472 { if (soap_valid_socket(soap->socket))
04473 { if (!soap->fshutdownsocket(soap, soap->socket, SOAP_SHUT_WR))
04474 {
04475 #if !defined(WITH_LEAN) && !defined(WIN32)
04476
04477
04478
04479
04480
04481 r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, 5);
04482 if (r <= 0 && soap->errnum != SOAP_EINTR)
04483 { soap->errnum = 0;
04484 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connection lost...\n"));
04485 soap->fclosesocket(soap, soap->socket);
04486 soap->socket = SOAP_INVALID_SOCKET;
04487 ERR_remove_state(0);
04488 SSL_free(soap->ssl);
04489 soap->ssl = NULL;
04490 return SOAP_OK;
04491 }
04492 #else
04493 r = SSL_shutdown(soap->ssl);
04494 #endif
04495 }
04496 }
04497 }
04498 if (r != 1)
04499 { s = ERR_get_error();
04500 if (s)
04501 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown failed: %d\n", SSL_get_error(soap->ssl, r)));
04502 if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP))
04503 { soap->fclosesocket(soap, soap->socket);
04504 soap->socket = SOAP_INVALID_SOCKET;
04505 }
04506 }
04507 }
04508 SSL_free(soap->ssl);
04509 soap->ssl = NULL;
04510 if (s)
04511 return SOAP_SSL_ERROR;
04512 ERR_remove_state(0);
04513 }
04514 #endif
04515 #ifdef WITH_GNUTLS
04516 if (soap->session)
04517 { gnutls_bye(soap->session, GNUTLS_SHUT_RDWR);
04518 gnutls_deinit(soap->session);
04519 soap->session = NULL;
04520 }
04521 #endif
04522 if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP))
04523 { soap->fshutdownsocket(soap, soap->socket, SOAP_SHUT_RDWR);
04524 soap->fclosesocket(soap, soap->socket);
04525 soap->socket = SOAP_INVALID_SOCKET;
04526 }
04527 return SOAP_OK;
04528 }
04529 #endif
04530 #endif
04531
04532
04533 #ifndef WITH_NOIO
04534 #ifndef PALM_1
04535 static int
04536 tcp_closesocket(struct soap *soap, SOAP_SOCKET fd)
04537 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Close socket %d\n", (int)fd));
04538 return soap_closesocket(fd);
04539 }
04540 #endif
04541 #endif
04542
04543
04544 #ifndef WITH_NOIO
04545 #ifndef PALM_1
04546 static int
04547 tcp_shutdownsocket(struct soap *soap, SOAP_SOCKET fd, int how)
04548 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown socket %d how=%d\n", (int)fd, how));
04549 return shutdown(fd, how);
04550 }
04551 #endif
04552 #endif
04553
04554
04555 #ifndef WITH_NOIO
04556 #ifndef PALM_1
04557 SOAP_FMAC1
04558 SOAP_SOCKET
04559 SOAP_FMAC2
04560 soap_bind(struct soap *soap, const char *host, int port, int backlog)
04561 {
04562 #ifdef WITH_IPV6
04563 struct addrinfo *addrinfo = NULL;
04564 struct addrinfo hints;
04565 struct addrinfo res;
04566 int err;
04567 #ifdef WITH_NO_IPV6_V6ONLY
04568 int unset = 0;
04569 #endif
04570 #endif
04571 #ifndef WITH_LEAN
04572 #ifndef WITH_WIN32
04573 int len = SOAP_BUFLEN;
04574 #else
04575 int len = SOAP_BUFLEN + 1;
04576 #endif
04577 int set = 1;
04578 #endif
04579 if (soap_valid_socket(soap->master))
04580 { soap->fclosesocket(soap, soap->master);
04581 soap->master = SOAP_INVALID_SOCKET;
04582 }
04583 soap->socket = SOAP_INVALID_SOCKET;
04584 soap->errmode = 1;
04585 if (tcp_init(soap))
04586 { soap_set_receiver_error(soap, tcp_error(soap), "TCP init failed in soap_bind()", SOAP_TCP_ERROR);
04587 return SOAP_INVALID_SOCKET;
04588 }
04589 #ifdef WITH_IPV6
04590 memset((void*)&hints, 0, sizeof(hints));
04591 hints.ai_family = PF_UNSPEC;
04592 #ifndef WITH_LEAN
04593 if ((soap->omode & SOAP_IO_UDP))
04594 hints.ai_socktype = SOCK_DGRAM;
04595 else
04596 #endif
04597 hints.ai_socktype = SOCK_STREAM;
04598 hints.ai_flags = AI_PASSIVE;
04599 soap->errmode = 2;
04600 err = getaddrinfo(host, soap_int2s(soap, port), &hints, &addrinfo);
04601 if (err || !addrinfo)
04602 { soap_set_receiver_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in soap_bind()", SOAP_TCP_ERROR);
04603 return SOAP_INVALID_SOCKET;
04604 }
04605 res = *addrinfo;
04606 memcpy(&soap->peer, addrinfo->ai_addr, addrinfo->ai_addrlen);
04607 soap->peerlen = addrinfo->ai_addrlen;
04608 res.ai_addr = (struct sockaddr*)&soap->peer;
04609 res.ai_addrlen = soap->peerlen;
04610 freeaddrinfo(addrinfo);
04611 soap->master = (int)socket(res.ai_family, res.ai_socktype, res.ai_protocol);
04612 #else
04613 #ifndef WITH_LEAN
04614 if ((soap->omode & SOAP_IO_UDP))
04615 soap->master = (int)socket(AF_INET, SOCK_DGRAM, 0);
04616 else
04617 #endif
04618 soap->master = (int)socket(AF_INET, SOCK_STREAM, 0);
04619 #endif
04620 soap->errmode = 0;
04621 if (!soap_valid_socket(soap->master))
04622 { soap->errnum = soap_socket_errno(soap->master);
04623 soap_set_receiver_error(soap, tcp_error(soap), "socket failed in soap_bind()", SOAP_TCP_ERROR);
04624 return SOAP_INVALID_SOCKET;
04625 }
04626 #ifndef WITH_LEAN
04627 if ((soap->omode & SOAP_IO_UDP))
04628 soap->socket = soap->master;
04629 #endif
04630 #ifdef SOCKET_CLOSE_ON_EXEC
04631 #ifdef WIN32
04632 #ifndef UNDER_CE
04633 SetHandleInformation((HANDLE)soap->master, HANDLE_FLAG_INHERIT, 0);
04634 #endif
04635 #else
04636 fcntl(soap->master, F_SETFD, 1);
04637 #endif
04638 #endif
04639 #ifndef WITH_LEAN
04640 if (soap->bind_flags && setsockopt(soap->master, SOL_SOCKET, soap->bind_flags, (char*)&set, sizeof(int)))
04641 { soap->errnum = soap_socket_errno(soap->master);
04642 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_bind()", SOAP_TCP_ERROR);
04643 return SOAP_INVALID_SOCKET;
04644 }
04645 if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt(soap->master, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
04646 { soap->errnum = soap_socket_errno(soap->master);
04647 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_bind()", SOAP_TCP_ERROR);
04648 return SOAP_INVALID_SOCKET;
04649 }
04650 if (setsockopt(soap->master, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
04651 { soap->errnum = soap_socket_errno(soap->master);
04652 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_bind()", SOAP_TCP_ERROR);
04653 return SOAP_INVALID_SOCKET;
04654 }
04655 if (setsockopt(soap->master, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
04656 { soap->errnum = soap_socket_errno(soap->master);
04657 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_bind()", SOAP_TCP_ERROR);
04658 return SOAP_INVALID_SOCKET;
04659 }
04660 #ifdef TCP_NODELAY
04661 if (!(soap->omode & SOAP_IO_UDP) && setsockopt(soap->master, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
04662 { soap->errnum = soap_socket_errno(soap->master);
04663 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_bind()", SOAP_TCP_ERROR);
04664 return SOAP_INVALID_SOCKET;
04665 }
04666 #endif
04667 #endif
04668 #ifdef WITH_IPV6
04669 #ifdef WITH_IPV6_V6ONLY
04670 if (setsockopt(soap->master, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&set, sizeof(int)))
04671 { soap->errnum = soap_socket_errno(soap->master);
04672 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt IPV6_V6ONLY failed in soap_bind()", SOAP_TCP_ERROR);
04673 return SOAP_INVALID_SOCKET;
04674 }
04675 #endif
04676 #ifdef WITH_NO_IPV6_V6ONLY
04677 if (setsockopt(soap->master, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&unset, sizeof(int)))
04678 { soap->errnum = soap_socket_errno(soap->master);
04679 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt IPV6_V6ONLY failed in soap_bind()", SOAP_TCP_ERROR);
04680 return SOAP_INVALID_SOCKET;
04681 }
04682 #endif
04683 soap->errmode = 0;
04684 if (bind(soap->master, res.ai_addr, (int)res.ai_addrlen))
04685 { soap->errnum = soap_socket_errno(soap->master);
04686 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
04687 soap_closesock(soap);
04688 soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR);
04689 return SOAP_INVALID_SOCKET;
04690 }
04691 #else
04692 soap->peerlen = sizeof(soap->peer);
04693 memset((void*)&soap->peer, 0, sizeof(soap->peer));
04694 soap->peer.sin_family = AF_INET;
04695 soap->errmode = 2;
04696 if (host)
04697 { if (soap->fresolve(soap, host, &soap->peer.sin_addr))
04698 { soap_set_receiver_error(soap, tcp_error(soap), "get host by name failed in soap_bind()", SOAP_TCP_ERROR);
04699 return SOAP_INVALID_SOCKET;
04700 }
04701 }
04702 else
04703 soap->peer.sin_addr.s_addr = htonl(INADDR_ANY);
04704 soap->peer.sin_port = htons((short)port);
04705 soap->errmode = 0;
04706 if (bind(soap->master, (struct sockaddr*)&soap->peer, (int)soap->peerlen))
04707 { soap->errnum = soap_socket_errno(soap->master);
04708 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
04709 soap_closesock(soap);
04710 soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR);
04711 return SOAP_INVALID_SOCKET;
04712 }
04713 #endif
04714 if (!(soap->omode & SOAP_IO_UDP) && listen(soap->master, backlog))
04715 { soap->errnum = soap_socket_errno(soap->master);
04716 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
04717 soap_closesock(soap);
04718 soap_set_receiver_error(soap, tcp_error(soap), "listen failed in soap_bind()", SOAP_TCP_ERROR);
04719 return SOAP_INVALID_SOCKET;
04720 }
04721 return soap->master;
04722 }
04723 #endif
04724 #endif
04725
04726
04727 #ifndef WITH_NOIO
04728 #ifndef PALM_1
04729 SOAP_FMAC1
04730 int
04731 SOAP_FMAC2
04732 soap_poll(struct soap *soap)
04733 {
04734 #ifndef WITH_LEAN
04735 register int r;
04736 if (soap_valid_socket(soap->socket))
04737 { r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_ALL, 0);
04738 if (r > 0 && (r & SOAP_TCP_SELECT_ERR))
04739 r = -1;
04740 }
04741 else if (soap_valid_socket(soap->master))
04742 r = tcp_select(soap, soap->master, SOAP_TCP_SELECT_SND, 0);
04743 else
04744 return SOAP_OK;
04745 if (r > 0)
04746 {
04747 #ifdef WITH_OPENSSL
04748 if (soap->imode & SOAP_ENC_SSL)
04749 {
04750 if (soap_valid_socket(soap->socket)
04751 && (r & SOAP_TCP_SELECT_SND)
04752 && (!(r & SOAP_TCP_SELECT_RCV)
04753 || SSL_peek(soap->ssl, soap->tmpbuf, 1) > 0))
04754 return SOAP_OK;
04755 }
04756 else
04757 #endif
04758 if (soap_valid_socket(soap->socket)
04759 && (r & SOAP_TCP_SELECT_SND)
04760 && (!(r & SOAP_TCP_SELECT_RCV)
04761 || recv(soap->socket, soap->tmpbuf, 1, MSG_PEEK) > 0))
04762 return SOAP_OK;
04763 }
04764 else if (r < 0)
04765 { if ((soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) && soap_socket_errno(soap->master) != SOAP_EINTR)
04766 { soap_set_receiver_error(soap, tcp_error(soap), "select failed in soap_poll()", SOAP_TCP_ERROR);
04767 return soap->error = SOAP_TCP_ERROR;
04768 }
04769 }
04770 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Polling: other end down on socket=%d select=%d\n", soap->socket, r));
04771 return SOAP_EOF;
04772 #else
04773 return SOAP_OK;
04774 #endif
04775 }
04776 #endif
04777 #endif
04778
04779
04780 #ifndef WITH_NOIO
04781 #ifndef PALM_1
04782 SOAP_FMAC1
04783 SOAP_SOCKET
04784 SOAP_FMAC2
04785 soap_accept(struct soap *soap)
04786 { int n = (int)sizeof(soap->peer);
04787 #ifndef WITH_LEAN
04788 #ifndef WITH_WIN32
04789 int len = SOAP_BUFLEN;
04790 #else
04791 int len = SOAP_BUFLEN + 1;
04792 #endif
04793 int set = 1;
04794 #endif
04795 soap->error = SOAP_OK;
04796 #ifndef WITH_LEAN
04797 if ((soap->omode & SOAP_IO_UDP))
04798 return soap->socket = soap->master;
04799 #endif
04800 memset((void*)&soap->peer, 0, sizeof(soap->peer));
04801 soap->socket = SOAP_INVALID_SOCKET;
04802 soap->errmode = 0;
04803 soap->keep_alive = 0;
04804 if (soap_valid_socket(soap->master))
04805 { register int err;
04806 for (;;)
04807 { if (soap->accept_timeout || soap->send_timeout || soap->recv_timeout)
04808 { for (;;)
04809 { register int r;
04810 r = tcp_select(soap, soap->master, SOAP_TCP_SELECT_ALL, soap->accept_timeout ? soap->accept_timeout : 60);
04811 if (r > 0)
04812 break;
04813 if (!r && soap->accept_timeout)
04814 { soap_set_receiver_error(soap, "Timeout", "accept failed in soap_accept()", SOAP_TCP_ERROR);
04815 return SOAP_INVALID_SOCKET;
04816 }
04817 if (r < 0)
04818 { r = soap->errnum;
04819 if (r != SOAP_EINTR)
04820 { soap_closesock(soap);
04821 soap_set_sender_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR);
04822 return SOAP_INVALID_SOCKET;
04823 }
04824 }
04825 }
04826 }
04827 if (soap->accept_timeout)
04828 SOAP_SOCKNONBLOCK(soap->master)
04829 else
04830 SOAP_SOCKBLOCK(soap->master)
04831 soap->socket = soap->faccept(soap, soap->master, (struct sockaddr*)&soap->peer, &n);
04832 soap->peerlen = (size_t)n;
04833 if (soap_valid_socket(soap->socket))
04834 {
04835 #ifdef WITH_IPV6
04836
04837 getnameinfo((struct sockaddr*)&soap->peer, n, soap->host, sizeof(soap->host), NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV);
04838 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket %d from %s\n", soap->socket, soap->host));
04839 soap->ip = 0;
04840 soap->port = 0;
04841 #else
04842 soap->ip = ntohl(soap->peer.sin_addr.s_addr);
04843 soap->port = (int)ntohs(soap->peer.sin_port);
04844 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket %d at port %d from IP %d.%d.%d.%d\n", soap->socket, soap->port, (int)(soap->ip>>24)&0xFF, (int)(soap->ip>>16)&0xFF, (int)(soap->ip>>8)&0xFF, (int)soap->ip&0xFF));
04845 #endif
04846 #ifndef WITH_LEAN
04847 if (soap->accept_flags == SO_LINGER)
04848 { struct linger linger;
04849 memset((void*)&linger, 0, sizeof(linger));
04850 linger.l_onoff = 1;
04851 linger.l_linger = soap->linger_time;
04852 if (setsockopt(soap->socket, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger)))
04853 { soap->errnum = soap_socket_errno(soap->socket);
04854 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in soap_accept()", SOAP_TCP_ERROR);
04855 soap_closesock(soap);
04856 return SOAP_INVALID_SOCKET;
04857 }
04858 }
04859 else if (soap->accept_flags && setsockopt(soap->socket, SOL_SOCKET, soap->accept_flags, (char*)&set, sizeof(int)))
04860 { soap->errnum = soap_socket_errno(soap->socket);
04861 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_accept()", SOAP_TCP_ERROR);
04862 soap_closesock(soap);
04863 return SOAP_INVALID_SOCKET;
04864 }
04865 if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt(soap->socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
04866 { soap->errnum = soap_socket_errno(soap->socket);
04867 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_accept()", SOAP_TCP_ERROR);
04868 soap_closesock(soap);
04869 return SOAP_INVALID_SOCKET;
04870 }
04871 if (setsockopt(soap->socket, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
04872 { soap->errnum = soap_socket_errno(soap->socket);
04873 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_accept()", SOAP_TCP_ERROR);
04874 soap_closesock(soap);
04875 return SOAP_INVALID_SOCKET;
04876 }
04877 if (setsockopt(soap->socket, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
04878 { soap->errnum = soap_socket_errno(soap->socket);
04879 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_accept()", SOAP_TCP_ERROR);
04880 soap_closesock(soap);
04881 return SOAP_INVALID_SOCKET;
04882 }
04883 #ifdef TCP_NODELAY
04884 if (!(soap->omode & SOAP_IO_UDP) && setsockopt(soap->socket, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
04885 { soap->errnum = soap_socket_errno(soap->socket);
04886 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_accept()", SOAP_TCP_ERROR);
04887 soap_closesock(soap);
04888 return SOAP_INVALID_SOCKET;
04889 }
04890 #endif
04891 #endif
04892 soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0);
04893 if (soap->send_timeout || soap->recv_timeout)
04894 SOAP_SOCKNONBLOCK(soap->socket)
04895 else
04896 SOAP_SOCKBLOCK(soap->socket)
04897 return soap->socket;
04898 }
04899 err = soap_socket_errno(soap->socket);
04900 if (err != 0 && err != SOAP_EINTR && err != SOAP_EAGAIN && err != SOAP_EWOULDBLOCK)
04901 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept failed from %s\n", soap->host));
04902 soap->errnum = err;
04903 soap_set_receiver_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR);
04904 soap_closesock(soap);
04905 return SOAP_INVALID_SOCKET;
04906 }
04907 }
04908 }
04909 else
04910 { soap->errnum = 0;
04911 soap_set_receiver_error(soap, tcp_error(soap), "no master socket in soap_accept()", SOAP_TCP_ERROR);
04912 return SOAP_INVALID_SOCKET;
04913 }
04914 }
04915 #endif
04916 #endif
04917
04918
04919 #ifndef PALM_1
04920 SOAP_FMAC1
04921 int
04922 SOAP_FMAC2
04923 soap_closesock(struct soap *soap)
04924 { register int status = soap->error;
04925 #ifndef WITH_LEANER
04926 if (status)
04927 { soap->mime.first = NULL;
04928 soap->mime.last = NULL;
04929 soap->dime.first = NULL;
04930 soap->dime.last = NULL;
04931 }
04932 #endif
04933 if (soap->fdisconnect && (soap->error = soap->fdisconnect(soap)))
04934 return soap->error;
04935 if (status == SOAP_EOF || status == SOAP_TCP_ERROR || status == SOAP_SSL_ERROR || !soap->keep_alive)
04936 { if (soap->fclose && (soap->error = soap->fclose(soap)))
04937 return soap->error;
04938 soap->keep_alive = 0;
04939 }
04940 #ifdef WITH_ZLIB
04941 if (soap->zlib_state == SOAP_ZLIB_DEFLATE)
04942 deflateEnd(soap->d_stream);
04943 else if (soap->zlib_state == SOAP_ZLIB_INFLATE)
04944 inflateEnd(soap->d_stream);
04945 soap->zlib_state = SOAP_ZLIB_NONE;
04946 #endif
04947 return soap->error = status;
04948 }
04949 #endif
04950
04951
04952 #ifndef WITH_NOIO
04953 #ifndef PALM_2
04954 SOAP_FMAC1
04955 void
04956 SOAP_FMAC2
04957 soap_cleanup(struct soap *soap)
04958 { soap_done(soap);
04959 #ifdef WIN32
04960 if (!tcp_done)
04961 return;
04962 tcp_done = 0;
04963 WSACleanup();
04964 #endif
04965 }
04966 #endif
04967 #endif
04968
04969
04970 #ifndef PALM_1
04971 SOAP_FMAC1
04972 void
04973 SOAP_FMAC2
04974 soap_done(struct soap *soap)
04975 {
04976 #ifdef SOAP_DEBUG
04977 int i;
04978 #endif
04979 if (soap_check_state(soap))
04980 return;
04981 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Done with context\n"));
04982 soap_free_temp(soap);
04983 while (soap->clist)
04984 { struct soap_clist *p = soap->clist->next;
04985 SOAP_FREE(soap, soap->clist);
04986 soap->clist = p;
04987 }
04988 if (soap->state == SOAP_INIT)
04989 soap->omode &= ~SOAP_IO_UDP;
04990 soap->keep_alive = 0;
04991 soap_closesock(soap);
04992 #ifdef WITH_COOKIES
04993 soap_free_cookies(soap);
04994 #endif
04995 while (soap->plugins)
04996 { register struct soap_plugin *p = soap->plugins->next;
04997 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Removing plugin '%s'\n", soap->plugins->id));
04998 if (soap->plugins->fcopy || soap->state == SOAP_INIT)
04999 soap->plugins->fdelete(soap, soap->plugins);
05000 SOAP_FREE(soap, soap->plugins);
05001 soap->plugins = p;
05002 }
05003 soap->fplugin = fplugin;
05004 soap->fmalloc = NULL;
05005 #ifndef WITH_NOHTTP
05006 soap->fpost = http_post;
05007 soap->fput = http_put;
05008 soap->fget = http_get;
05009 soap->fdel = http_405;
05010 soap->fopt = http_405;
05011 soap->fhead = http_405;
05012 soap->fform = NULL;
05013 soap->fposthdr = http_post_header;
05014 soap->fresponse = http_response;
05015 soap->fparse = http_parse;
05016 soap->fparsehdr = http_parse_header;
05017 #endif
05018 soap->fheader = NULL;
05019 #ifndef WITH_NOIO
05020 #ifndef WITH_IPV6
05021 soap->fresolve = tcp_gethost;
05022 #else
05023 soap->fresolve = NULL;
05024 #endif
05025 soap->faccept = tcp_accept;
05026 soap->fopen = tcp_connect;
05027 soap->fclose = tcp_disconnect;
05028 soap->fclosesocket = tcp_closesocket;
05029 soap->fshutdownsocket = tcp_shutdownsocket;
05030 soap->fsend = fsend;
05031 soap->frecv = frecv;
05032 soap->fpoll = soap_poll;
05033 #else
05034 soap->fopen = NULL;
05035 soap->fclose = NULL;
05036 soap->fpoll = NULL;
05037 #endif
05038 #ifndef WITH_LEANER
05039 soap->feltbegin = NULL;
05040 soap->feltendin = NULL;
05041 soap->feltbegout = NULL;
05042 soap->feltendout = NULL;
05043 soap->fprepareinitsend = NULL;
05044 soap->fprepareinitrecv = NULL;
05045 soap->fpreparesend = NULL;
05046 soap->fpreparerecv = NULL;
05047 soap->fpreparefinalsend = NULL;
05048 soap->fpreparefinalrecv = NULL;
05049 soap->ffiltersend = NULL;
05050 soap->ffilterrecv = NULL;
05051 #endif
05052 soap->fseterror = NULL;
05053 soap->fignore = NULL;
05054 soap->fserveloop = NULL;
05055 #ifdef WITH_OPENSSL
05056 if (soap->session)
05057 { SSL_SESSION_free(soap->session);
05058 soap->session = NULL;
05059 }
05060 #endif
05061 if (soap->state == SOAP_INIT)
05062 { if (soap_valid_socket(soap->master))
05063 { soap->fclosesocket(soap, soap->master);
05064 soap->master = SOAP_INVALID_SOCKET;
05065 }
05066 }
05067 #ifdef WITH_OPENSSL
05068 if (soap->ssl)
05069 { SSL_free(soap->ssl);
05070 soap->ssl = NULL;
05071 }
05072 if (soap->state == SOAP_INIT)
05073 { if (soap->ctx)
05074 { SSL_CTX_free(soap->ctx);
05075 soap->ctx = NULL;
05076 }
05077 }
05078 ERR_remove_state(0);
05079 #endif
05080 #ifdef WITH_GNUTLS
05081 if (soap->state == SOAP_INIT)
05082 { if (soap->xcred)
05083 { gnutls_certificate_free_credentials(soap->xcred);
05084 soap->xcred = NULL;
05085 }
05086 if (soap->acred)
05087 { gnutls_anon_free_client_credentials(soap->acred);
05088 soap->acred = NULL;
05089 }
05090 if (soap->cache)
05091 { gnutls_priority_deinit(soap->cache);
05092 soap->cache = NULL;
05093 }
05094 if (soap->dh_params)
05095 { gnutls_dh_params_deinit(soap->dh_params);
05096 soap->dh_params = NULL;
05097 }
05098 if (soap->rsa_params)
05099 { gnutls_rsa_params_deinit(soap->rsa_params);
05100 soap->rsa_params = NULL;
05101 }
05102 }
05103 if (soap->session)
05104 { gnutls_deinit(soap->session);
05105 soap->session = NULL;
05106 }
05107 #endif
05108 #ifdef WITH_C_LOCALE
05109 freelocale(soap->c_locale);
05110 #endif
05111 #ifdef WITH_ZLIB
05112 if (soap->d_stream)
05113 { SOAP_FREE(soap, (void*)soap->d_stream);
05114 soap->d_stream = NULL;
05115 }
05116 if (soap->z_buf)
05117 { SOAP_FREE(soap, (void*)soap->z_buf);
05118 soap->z_buf = NULL;
05119 }
05120 #endif
05121 #ifdef SOAP_DEBUG
05122 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free logfiles\n"));
05123 for (i = 0; i < SOAP_MAXLOGS; i++)
05124 { if (soap->logfile[i])
05125 { SOAP_FREE(soap, (void*)soap->logfile[i]);
05126 soap->logfile[i] = NULL;
05127 }
05128 soap_close_logfile(soap, i);
05129 }
05130 soap->state = SOAP_NONE;
05131 #endif
05132 #ifdef SOAP_MEM_DEBUG
05133 soap_free_mht(soap);
05134 #endif
05135 }
05136 #endif
05137
05138
05139
05140
05141
05142
05143
05144
05145 #ifndef WITH_NOHTTP
05146 #ifndef PALM_1
05147 int
05148 http_parse(struct soap *soap)
05149 { char header[SOAP_HDRLEN], *s;
05150 unsigned short httpcmd = 0, status = 0;
05151 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Waiting for HTTP request/response...\n"));
05152 *soap->endpoint = '\0';
05153 soap->length = 0;
05154 soap->userid = NULL;
05155 soap->passwd = NULL;
05156 soap->action = NULL;
05157 soap->authrealm = NULL;
05158 soap->proxy_from = NULL;
05159 soap->http_content = NULL;
05160 soap->status = 0;
05161 do
05162 { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
05163 { if (soap->error == SOAP_EOF)
05164 return SOAP_EOF;
05165 return soap->error = 414;
05166 }
05167 if ((s = strchr(soap->msgbuf, ' ')))
05168 { soap->status = (unsigned short)soap_strtoul(s, &s, 10);
05169 if (!soap_blank((soap_wchar)*s))
05170 soap->status = 0;
05171 }
05172 else
05173 soap->status = 0;
05174 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP status: %s\n", soap->msgbuf));
05175 for (;;)
05176 { if (soap_getline(soap, header, SOAP_HDRLEN))
05177 { if (soap->error == SOAP_EOF)
05178 { soap->error = SOAP_OK;
05179 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "EOF in HTTP header, continue anyway\n"));
05180 break;
05181 }
05182 return soap->error;
05183 }
05184 if (!*header)
05185 break;
05186 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP header: %s\n", header));
05187 s = strchr(header, ':');
05188 if (s)
05189 { char *t;
05190 *s = '\0';
05191 do s++;
05192 while (*s && *s <= 32);
05193 if (*s == '"')
05194 s++;
05195 t = s + strlen(s) - 1;
05196 while (t > s && *t <= 32)
05197 t--;
05198 if (t >= s && *t == '"')
05199 t--;
05200 t[1] = '\0';
05201 if ((soap->error = soap->fparsehdr(soap, header, s)))
05202 { if (soap->error < SOAP_STOP)
05203 return soap->error;
05204 status = soap->error;
05205 soap->error = SOAP_OK;
05206 }
05207 }
05208 }
05209 } while (soap->status == 100);
05210 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Finished HTTP header parsing, status = %d\n", soap->status));
05211 s = strstr(soap->msgbuf, "HTTP/");
05212 if (s && s[7] != '1')
05213 { if (soap->keep_alive == 1)
05214 soap->keep_alive = 0;
05215 if (soap->status == 0 && (soap->omode & SOAP_IO) == SOAP_IO_CHUNK)
05216 { soap->imode |= SOAP_IO_CHUNK;
05217 soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE;
05218 }
05219 }
05220 if (soap->keep_alive < 0)
05221 soap->keep_alive = 1;
05222 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Keep alive connection = %d\n", soap->keep_alive));
05223 if (soap->status == 0)
05224 { size_t l = 0;
05225 if (s)
05226 { if (!strncmp(soap->msgbuf, "POST ", l = 5))
05227 httpcmd = 1;
05228 else if (!strncmp(soap->msgbuf, "PUT ", l = 4))
05229 httpcmd = 2;
05230 else if (!strncmp(soap->msgbuf, "GET ", l = 4))
05231 httpcmd = 3;
05232 else if (!strncmp(soap->msgbuf, "DELETE ", l = 7))
05233 httpcmd = 4;
05234 else if (!strncmp(soap->msgbuf, "OPTIONS ", l = 8))
05235 httpcmd = 5;
05236 else if (!strncmp(soap->msgbuf, "HEAD ", l = 5))
05237 httpcmd = 6;
05238 }
05239 if (s && httpcmd)
05240 { size_t m = strlen(soap->endpoint);
05241 size_t n = m + (s - soap->msgbuf) - l - 1;
05242 if (m > n)
05243 m = n;
05244 if (n >= sizeof(soap->endpoint))
05245 n = sizeof(soap->endpoint) - 1;
05246 strncpy(soap->path, soap->msgbuf + l, n - m);
05247 soap->path[n - m] = '\0';
05248 strcat(soap->endpoint, soap->path);
05249 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Target endpoint='%s'\n", soap->endpoint));
05250 if (httpcmd > 1)
05251 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP %s handler\n", soap->msgbuf));
05252 switch (httpcmd)
05253 { case 2: soap->error = soap->fput(soap); break;
05254 case 3: soap->error = soap->fget(soap); break;
05255 case 4: soap->error = soap->fdel(soap); break;
05256 case 5: soap->error = soap->fopt(soap); break;
05257 case 6: soap->error = soap->fhead(soap); break;
05258 default: soap->error = 405; break;
05259 }
05260 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP handler return = %d\n", soap->error));
05261 if (soap->error == SOAP_OK)
05262 soap->error = SOAP_STOP;
05263 return soap->error;
05264 }
05265 if (status)
05266 return soap->error = status;
05267 }
05268 else if (status)
05269 return soap->error = status;
05270 else if (s)
05271 return soap->error = 405;
05272 }
05273
05274 if (soap->status == 0 || soap->status == 200)
05275 return SOAP_OK;
05276
05277
05278
05279
05280 if (soap->length > 0 || (soap->http_content && soap->recv_timeout) || (soap->imode & SOAP_IO) == SOAP_IO_CHUNK)
05281 { if ((soap->status > 200 && soap->status <= 299)
05282 || soap->status == 400
05283 || soap->status == 500)
05284 return SOAP_OK;
05285
05286 soap->keep_alive = 0;
05287 #ifndef WITH_LEAN
05288
05289 s = soap_get_http_body(soap);
05290 if (s)
05291 return soap_set_receiver_error(soap, soap->msgbuf, s, soap->status);
05292 #endif
05293 }
05294 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP error %d\n", soap->status));
05295 return soap_set_receiver_error(soap, "HTTP Error", soap->msgbuf, soap->status);
05296 }
05297 #endif
05298 #endif
05299
05300
05301 #ifndef WITH_NOHTTP
05302 #ifndef PALM_1
05303 static int
05304 http_parse_header(struct soap *soap, const char *key, const char *val)
05305 { if (!soap_tag_cmp(key, "Host"))
05306 {
05307 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
05308 if (soap->imode & SOAP_ENC_SSL)
05309 strcpy(soap->endpoint, "https://");
05310 else
05311 #endif
05312 strcpy(soap->endpoint, "http://");
05313 strncat(soap->endpoint, val, sizeof(soap->endpoint) - 8);
05314 soap->endpoint[sizeof(soap->endpoint) - 1] = '\0';
05315 }
05316 #ifndef WITH_LEANER
05317 else if (!soap_tag_cmp(key, "Content-Type"))
05318 { const char *action;
05319 soap->http_content = soap_strdup(soap, val);
05320 if (soap_get_header_attribute(soap, val, "application/dime"))
05321 soap->imode |= SOAP_ENC_DIME;
05322 else if (soap_get_header_attribute(soap, val, "multipart/related")
05323 || soap_get_header_attribute(soap, val, "multipart/form-data"))
05324 { soap->mime.boundary = soap_strdup(soap, soap_get_header_attribute(soap, val, "boundary"));
05325 soap->mime.start = soap_strdup(soap, soap_get_header_attribute(soap, val, "start"));
05326 soap->imode |= SOAP_ENC_MIME;
05327 }
05328 action = soap_get_header_attribute(soap, val, "action");
05329 if (action)
05330 { if (*action == '"')
05331 { soap->action = soap_strdup(soap, action + 1);
05332 soap->action[strlen(soap->action) - 1] = '\0';
05333 }
05334 else
05335 soap->action = soap_strdup(soap, action);
05336 }
05337 }
05338 #endif
05339 else if (!soap_tag_cmp(key, "Content-Length"))
05340 { soap->length = soap_strtoul(val, NULL, 10);
05341 }
05342 else if (!soap_tag_cmp(key, "Content-Encoding"))
05343 { if (!soap_tag_cmp(val, "deflate"))
05344 #ifdef WITH_ZLIB
05345 soap->zlib_in = SOAP_ZLIB_DEFLATE;
05346 #else
05347 return SOAP_ZLIB_ERROR;
05348 #endif
05349 else if (!soap_tag_cmp(val, "gzip"))
05350 #ifdef WITH_GZIP
05351 soap->zlib_in = SOAP_ZLIB_GZIP;
05352 #else
05353 return SOAP_ZLIB_ERROR;
05354 #endif
05355 }
05356 #ifdef WITH_ZLIB
05357 else if (!soap_tag_cmp(key, "Accept-Encoding"))
05358 {
05359 #ifdef WITH_GZIP
05360 if (strchr(val, '*') || soap_get_header_attribute(soap, val, "gzip"))
05361 soap->zlib_out = SOAP_ZLIB_GZIP;
05362 else
05363 #endif
05364 if (strchr(val, '*') || soap_get_header_attribute(soap, val, "deflate"))
05365 soap->zlib_out = SOAP_ZLIB_DEFLATE;
05366 else
05367 soap->zlib_out = SOAP_ZLIB_NONE;
05368 }
05369 #endif
05370 else if (!soap_tag_cmp(key, "Transfer-Encoding"))
05371 { soap->imode &= ~SOAP_IO;
05372 if (!soap_tag_cmp(val, "chunked"))
05373 soap->imode |= SOAP_IO_CHUNK;
05374 }
05375 else if (!soap_tag_cmp(key, "Connection"))
05376 { if (!soap_tag_cmp(val, "keep-alive"))
05377 soap->keep_alive = -soap->keep_alive;
05378 else if (!soap_tag_cmp(val, "close"))
05379 soap->keep_alive = 0;
05380 }
05381 #ifndef WITH_LEAN
05382 else if (!soap_tag_cmp(key, "Authorization"))
05383 { if (!soap_tag_cmp(val, "Basic *"))
05384 { int n;
05385 char *s;
05386 soap_base642s(soap, val + 6, soap->tmpbuf, sizeof(soap->tmpbuf) - 1, &n);
05387 soap->tmpbuf[n] = '\0';
05388 if ((s = strchr(soap->tmpbuf, ':')))
05389 { *s = '\0';
05390 soap->userid = soap_strdup(soap, soap->tmpbuf);
05391 soap->passwd = soap_strdup(soap, s + 1);
05392 }
05393 }
05394 }
05395 else if (!soap_tag_cmp(key, "WWW-Authenticate"))
05396 { soap->authrealm = soap_strdup(soap, soap_get_header_attribute(soap, val + 6, "realm"));
05397 }
05398 else if (!soap_tag_cmp(key, "Expect"))
05399 { if (!soap_tag_cmp(val, "100-continue"))
05400 { if ((soap->error = soap->fposthdr(soap, "HTTP/1.1 100 Continue", NULL))
05401 || (soap->error = soap->fposthdr(soap, NULL, NULL)))
05402 return soap->error;
05403 }
05404 }
05405 #endif
05406 else if (!soap_tag_cmp(key, "SOAPAction"))
05407 { if (*val == '"')
05408 { soap->action = soap_strdup(soap, val + 1);
05409 soap->action[strlen(soap->action) - 1] = '\0';
05410 }
05411 else
05412 soap->action = soap_strdup(soap, val);
05413 }
05414 else if (!soap_tag_cmp(key, "Location"))
05415 { strncpy(soap->endpoint, val, sizeof(soap->endpoint));
05416 soap->endpoint[sizeof(soap->endpoint) - 1] = '\0';
05417 }
05418 else if (!soap_tag_cmp(key, "X-Forwarded-For"))
05419 { soap->proxy_from = soap_strdup(soap, val);
05420 }
05421 #ifdef WITH_COOKIES
05422 else if (!soap_tag_cmp(key, "Cookie")
05423 || !soap_tag_cmp(key, "Cookie2")
05424 || !soap_tag_cmp(key, "Set-Cookie")
05425 || !soap_tag_cmp(key, "Set-Cookie2"))
05426 { soap_getcookies(soap, val);
05427 }
05428 #endif
05429 return SOAP_OK;
05430 }
05431 #endif
05432 #endif
05433
05434
05435 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
05436 #ifndef PALM_1
05437 SOAP_FMAC1
05438 const char*
05439 SOAP_FMAC2
05440 soap_get_header_attribute(struct soap *soap, const char *line, const char *key)
05441 { register const char *s = line;
05442 if (s)
05443 { while (*s)
05444 { register short flag;
05445 s = soap_decode_key(soap->tmpbuf, sizeof(soap->tmpbuf), s);
05446 flag = soap_tag_cmp(soap->tmpbuf, key);
05447 s = soap_decode_val(soap->tmpbuf, sizeof(soap->tmpbuf), s);
05448 if (!flag)
05449 return soap->tmpbuf;
05450 }
05451 }
05452 return NULL;
05453 }
05454 #endif
05455 #endif
05456
05457
05458 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
05459 #ifndef PALM_1
05460 SOAP_FMAC1
05461 const char*
05462 SOAP_FMAC2
05463 soap_decode_key(char *buf, size_t len, const char *val)
05464 { return soap_decode(buf, len, val, "=,;");
05465 }
05466 #endif
05467 #endif
05468
05469
05470 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
05471 #ifndef PALM_1
05472 SOAP_FMAC1
05473 const char*
05474 SOAP_FMAC2
05475 soap_decode_val(char *buf, size_t len, const char *val)
05476 { if (*val != '=')
05477 { *buf = '\0';
05478 return val;
05479 }
05480 return soap_decode(buf, len, val + 1, ",;");
05481 }
05482 #endif
05483 #endif
05484
05485
05486 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
05487 #ifndef PALM_1
05488 static const char*
05489 soap_decode(char *buf, size_t len, const char *val, const char *sep)
05490 { const char *s;
05491 char *t = buf;
05492 for (s = val; *s; s++)
05493 if (*s != ' ' && *s != '\t' && !strchr(sep, *s))
05494 break;
05495 if (*s == '"')
05496 { s++;
05497 while (*s && *s != '"' && --len)
05498 *t++ = *s++;
05499 }
05500 else
05501 { while (*s && !soap_blank((soap_wchar)*s) && !strchr(sep, *s) && --len)
05502 { if (*s == '%')
05503 { *t++ = ((s[1] >= 'A' ? (s[1] & 0x7) + 9 : s[1] - '0') << 4)
05504 + (s[2] >= 'A' ? (s[2] & 0x7) + 9 : s[2] - '0');
05505 s += 3;
05506 }
05507 else
05508 *t++ = *s++;
05509 }
05510 }
05511 *t = '\0';
05512 while (*s && !strchr(sep, *s))
05513 s++;
05514 return s;
05515 }
05516 #endif
05517 #endif
05518
05519
05520 #ifndef WITH_NOHTTP
05521 #ifndef PALM_1
05522 static const char*
05523 http_error(struct soap *soap, int status)
05524 { register const char *msg = SOAP_STR_EOS;
05525 #ifndef WITH_LEAN
05526 msg = soap_code_str(h_http_error_codes, status);
05527 if (!msg)
05528 msg = SOAP_STR_EOS;
05529 #endif
05530 return msg;
05531 }
05532 #endif
05533 #endif
05534
05535
05536 #ifndef WITH_NOHTTP
05537 #ifndef PALM_1
05538 static int
05539 http_put(struct soap *soap)
05540 { return http_parse(soap);
05541 }
05542 #endif
05543 #endif
05544
05545
05546 #ifndef WITH_NOHTTP
05547 #ifndef PALM_1
05548 static int
05549 http_get(struct soap *soap)
05550 { return SOAP_GET_METHOD;
05551 }
05552 #endif
05553 #endif
05554
05555
05556 #ifndef WITH_NOHTTP
05557 #ifndef PALM_1
05558 static int
05559 http_405(struct soap *soap)
05560 { return 405;
05561 }
05562 #endif
05563 #endif
05564
05565
05566 #ifndef WITH_NOHTTP
05567 #ifndef PALM_1
05568 static int
05569 http_post(struct soap *soap, const char *endpoint, const char *host, int port, const char *path, const char *action, size_t count)
05570 { register const char *s;
05571 register int err;
05572 if (soap->status == SOAP_GET)
05573 s = "GET";
05574 else
05575 s = "POST";
05576 #ifdef PALM
05577 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))
05578 #else
05579 if (!endpoint || (soap_tag_cmp(endpoint, "http:*") && soap_tag_cmp(endpoint, "https:*") && strncmp(endpoint, "httpg:", 6)))
05580 #endif
05581 return SOAP_OK;
05582 if (strlen(endpoint) + strlen(soap->http_version) > sizeof(soap->tmpbuf) - 80)
05583 return soap->error = SOAP_EOM;
05584 if (soap->proxy_host && soap_tag_cmp(endpoint, "https:*"))
05585 sprintf(soap->tmpbuf, "%s %s HTTP/%s", s, endpoint, soap->http_version);
05586 else
05587 sprintf(soap->tmpbuf, "%s /%s HTTP/%s", s, (*path == '/' ? path + 1 : path), soap->http_version);
05588 if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
05589 return err;
05590 #ifdef WITH_OPENSSL
05591 if ((soap->ssl && soap->port != 443) || (!soap->ssl && soap->port != 80))
05592 sprintf(soap->tmpbuf, "%s:%d", host, port);
05593 else
05594 strcpy(soap->tmpbuf, host);
05595 #else
05596 if (port != 80)
05597 sprintf(soap->tmpbuf, "%s:%d", host, port);
05598 else
05599 strcpy(soap->tmpbuf, host);
05600 #endif
05601 if ((err = soap->fposthdr(soap, "Host", soap->tmpbuf)))
05602 return err;
05603 if ((err = soap->fposthdr(soap, "User-Agent", "gSOAP/2.8")))
05604 return err;
05605 if ((err = soap_puthttphdr(soap, SOAP_OK, count)))
05606 return err;
05607 #ifdef WITH_ZLIB
05608 #ifdef WITH_GZIP
05609 if ((err = soap->fposthdr(soap, "Accept-Encoding", "gzip, deflate")))
05610 #else
05611 if ((err = soap->fposthdr(soap, "Accept-Encoding", "deflate")))
05612 #endif
05613 return err;
05614 #endif
05615 #ifndef WITH_LEAN
05616 if (soap->userid && soap->passwd && strlen(soap->userid) + strlen(soap->passwd) < 761)
05617 { sprintf(soap->tmpbuf + 262, "%s:%s", soap->userid, soap->passwd);
05618 strcpy(soap->tmpbuf, "Basic ");
05619 soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262));
05620 if ((err = soap->fposthdr(soap, "Authorization", soap->tmpbuf)))
05621 return err;
05622 }
05623 if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761)
05624 { sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd);
05625 strcpy(soap->tmpbuf, "Basic ");
05626 soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262));
05627 if ((err = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf)))
05628 return err;
05629 }
05630 #endif
05631 #ifdef WITH_COOKIES
05632 #ifdef WITH_OPENSSL
05633 if (soap_putcookies(soap, host, path, soap->ssl != NULL))
05634 return soap->error;
05635 #else
05636 if (soap_putcookies(soap, host, path, 0))
05637 return soap->error;
05638 #endif
05639 #endif
05640 if (soap->status != SOAP_GET && soap->version == 1)
05641 { sprintf(soap->tmpbuf, "\"%s\"", action && strlen(action) < sizeof(soap->tmpbuf) - 3 ? action : SOAP_STR_EOS);
05642 if ((err = soap->fposthdr(soap, "SOAPAction", soap->tmpbuf)))
05643 return err;
05644 }
05645 return soap->fposthdr(soap, NULL, NULL);
05646 }
05647 #endif
05648 #endif
05649
05650
05651 #ifndef WITH_NOHTTP
05652 #ifndef PALM_1
05653 static int
05654 http_send_header(struct soap *soap, const char *s)
05655 { register const char *t;
05656 do
05657 { t = strchr(s, '\n');
05658 if (!t)
05659 t = s + strlen(s);
05660 if (soap_send_raw(soap, s, t - s))
05661 return soap->error;
05662 s = t + 1;
05663 } while (*t);
05664 return SOAP_OK;
05665 }
05666 #endif
05667 #endif
05668
05669
05670 #ifndef WITH_NOHTTP
05671 #ifndef PALM_1
05672 static int
05673 http_post_header(struct soap *soap, const char *key, const char *val)
05674 { if (key)
05675 { if (http_send_header(soap, key))
05676 return soap->error;
05677 if (val && (soap_send_raw(soap, ": ", 2) || http_send_header(soap, val)))
05678 return soap->error;
05679 }
05680 return soap_send_raw(soap, "\r\n", 2);
05681 }
05682 #endif
05683 #endif
05684
05685
05686 #ifndef WITH_NOHTTP
05687 #ifndef PALM_1
05688 static int
05689 http_response(struct soap *soap, int status, size_t count)
05690 { register int err;
05691 #ifdef WMW_RPM_IO
05692 if (soap->rpmreqid)
05693 httpOutputEnable(soap->rpmreqid);
05694 #endif
05695 if (strlen(soap->http_version) > 4)
05696 return soap->error = SOAP_EOM;
05697 if (!status || status == SOAP_HTML || status == SOAP_FILE)
05698 { const char *s;
05699 if (count || ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK))
05700 s = "200 OK";
05701 else
05702 s = "202 ACCEPTED";
05703 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Status = %s\n", s));
05704 #ifdef WMW_RPM_IO
05705 if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket))
05706 #else
05707 if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket))
05708 #endif
05709 { sprintf(soap->tmpbuf, "HTTP/%s %s", soap->http_version, s);
05710 if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
05711 return err;
05712 }
05713 else if ((err = soap->fposthdr(soap, "Status", s)))
05714 return err;
05715 }
05716 else if (status >= 200 && status < 600)
05717 { sprintf(soap->tmpbuf, "HTTP/%s %d %s", soap->http_version, status, http_error(soap, status));
05718 if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
05719 return err;
05720 #ifndef WITH_LEAN
05721 if (status == 401)
05722 { sprintf(soap->tmpbuf, "Basic realm=\"%s\"", (soap->authrealm && strlen(soap->authrealm) < sizeof(soap->tmpbuf) - 14) ? soap->authrealm : "gSOAP Web Service");
05723 if ((err = soap->fposthdr(soap, "WWW-Authenticate", soap->tmpbuf)))
05724 return err;
05725 }
05726 else if ((status >= 301 && status <= 303) || status == 307)
05727 { if ((err = soap->fposthdr(soap, "Location", soap->endpoint)))
05728 return err;
05729 }
05730 #endif
05731 }
05732 else
05733 { const char *s = *soap_faultcode(soap);
05734 if (status >= SOAP_GET_METHOD && status <= SOAP_HTTP_METHOD)
05735 s = "405 Method Not Allowed";
05736 else if (soap->version == 2 && (!s || !strcmp(s, "SOAP-ENV:Sender")))
05737 s = "400 Bad Request";
05738 else
05739 s = "500 Internal Server Error";
05740 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error %s (status=%d)\n", s, status));
05741 #ifdef WMW_RPM_IO
05742 if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket))
05743 #else
05744 if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket))
05745 #endif
05746 { sprintf(soap->tmpbuf, "HTTP/%s %s", soap->http_version, s);
05747 if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
05748 return err;
05749 }
05750 else if ((err = soap->fposthdr(soap, "Status", s)))
05751 return err;
05752 }
05753 if ((err = soap->fposthdr(soap, "Server", "gSOAP/2.8"))
05754 || (err = soap_puthttphdr(soap, status, count)))
05755 return err;
05756 #ifdef WITH_COOKIES
05757 if (soap_putsetcookies(soap))
05758 return soap->error;
05759 #endif
05760 return soap->fposthdr(soap, NULL, NULL);
05761 }
05762 #endif
05763 #endif
05764
05765
05766 #ifndef PALM_1
05767 SOAP_FMAC1
05768 int
05769 SOAP_FMAC2
05770 soap_response(struct soap *soap, int status)
05771 { register size_t count;
05772 if (!(soap->omode & (SOAP_ENC_XML | SOAP_IO_STORE ))
05773 && (status == SOAP_HTML || status == SOAP_FILE))
05774 soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE;
05775 soap->status = status;
05776 count = soap_count_attachments(soap);
05777 if (soap_begin_send(soap))
05778 return soap->error;
05779 #ifndef WITH_NOHTTP
05780 if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML))
05781 { register int n = soap->mode;
05782 soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB);
05783 if ((n & SOAP_IO) != SOAP_IO_FLUSH)
05784 soap->mode |= SOAP_IO_BUFFER;
05785 if ((soap->error = soap->fresponse(soap, status, count)))
05786 return soap->error;
05787 #ifndef WITH_LEANER
05788 if ((n & SOAP_IO) == SOAP_IO_CHUNK)
05789 { if (soap_flush(soap))
05790 return soap->error;
05791 }
05792 #endif
05793 soap->mode = n;
05794 }
05795 #endif
05796 return SOAP_OK;
05797 }
05798 #endif
05799
05800
05801
05802
05803
05804
05805
05806 #ifdef WITH_COOKIES
05807
05808 SOAP_FMAC1
05809 size_t
05810 SOAP_FMAC2
05811 soap_encode_cookie(const char *s, char *t, size_t len)
05812 { register int c;
05813 register size_t n = len;
05814 while ((c = *s++) && --n > 0)
05815 { if (c > ' ' && c < 128 && !strchr("()<>@,;:\\\"/[]?={}#!$&'*+", c))
05816 *t++ = c;
05817 else if (n > 2)
05818 { *t++ = '%';
05819 *t++ = (c >> 4) + (c > 159 ? '7' : '0');
05820 c &= 0xF;
05821 *t++ = c + (c > 9 ? '7' : '0');
05822 n -= 2;
05823 }
05824 else
05825 break;
05826 }
05827 *t = '\0';
05828 return len - n;
05829 }
05830
05831
05832 SOAP_FMAC1
05833 struct soap_cookie*
05834 SOAP_FMAC2
05835 soap_cookie(struct soap *soap, const char *name, const char *domain, const char *path)
05836 { struct soap_cookie *p;
05837 if (!domain)
05838 domain = soap->cookie_domain;
05839 if (!path)
05840 path = soap->cookie_path;
05841 if (!path)
05842 path = SOAP_STR_EOS;
05843 else if (*path == '/')
05844 path++;
05845 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Search cookie %s domain=%s path=%s\n", name, domain?domain:"(null)", path?path:"(null)"));
05846 for (p = soap->cookies; p; p = p->next)
05847 { 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));
05848 if (!strcmp(p->name, name)
05849 && p->domain
05850 && p->path
05851 && !strcmp(p->domain, domain)
05852 && (!*p->path || !strncmp(p->path, path, strlen(p->path))))
05853 break;
05854 }
05855 return p;
05856 }
05857
05858
05859 SOAP_FMAC1
05860 struct soap_cookie*
05861 SOAP_FMAC2
05862 soap_set_cookie(struct soap *soap, const char *name, const char *value, const char *domain, const char *path)
05863 { struct soap_cookie **p, *q;
05864 int n;
05865 if (!domain)
05866 domain = soap->cookie_domain;
05867 if (!path)
05868 path = soap->cookie_path;
05869 if (!path)
05870 path = SOAP_STR_EOS;
05871 else if (*path == '/')
05872 path++;
05873 q = soap_cookie(soap, name, domain, path);
05874 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)"));
05875 if (!q)
05876 { if ((q = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie))))
05877 { if ((q->name = (char*)SOAP_MALLOC(soap, strlen(name)+1)))
05878 strcpy(q->name, name);
05879 q->value = NULL;
05880 q->domain = NULL;
05881 q->path = NULL;
05882 q->expire = 0;
05883 q->maxage = -1;
05884 q->version = 1;
05885 q->secure = 0;
05886 q->modified = 0;
05887 for (p = &soap->cookies, n = soap->cookie_max; *p && n; p = &(*p)->next, n--)
05888 if (!strcmp((*p)->name, name) && (*p)->path && path && strcmp((*p)->path, path) < 0)
05889 break;
05890 if (n)
05891 { q->next = *p;
05892 *p = q;
05893 }
05894 else
05895 { SOAP_FREE(soap, q->name);
05896 SOAP_FREE(soap, q);
05897 q = NULL;
05898 }
05899 }
05900 }
05901 else
05902 q->modified = 1;
05903 if (q)
05904 { if (q->value)
05905 { if (!value || strcmp(value, q->value))
05906 { SOAP_FREE(soap, q->value);
05907 q->value = NULL;
05908 }
05909 }
05910 if (value && *value && !q->value && (q->value = (char*)SOAP_MALLOC(soap, strlen(value)+1)))
05911 strcpy(q->value, value);
05912 if (q->domain)
05913 { if (!domain || strcmp(domain, q->domain))
05914 { SOAP_FREE(soap, q->domain);
05915 q->domain = NULL;
05916 }
05917 }
05918 if (domain && !q->domain && (q->domain = (char*)SOAP_MALLOC(soap, strlen(domain)+1)))
05919 strcpy(q->domain, domain);
05920 if (q->path)
05921 { if (!path || strncmp(path, q->path, strlen(q->path)))
05922 { SOAP_FREE(soap, q->path);
05923 q->path = NULL;
05924 }
05925 }
05926 if (path && !q->path && (q->path = (char*)SOAP_MALLOC(soap, strlen(path)+1)))
05927 strcpy(q->path, path);
05928 q->session = 1;
05929 q->env = 0;
05930 }
05931 return q;
05932 }
05933
05934
05935 SOAP_FMAC1
05936 void
05937 SOAP_FMAC2
05938 soap_clr_cookie(struct soap *soap, const char *name, const char *domain, const char *path)
05939 { struct soap_cookie **p, *q;
05940 if (!domain)
05941 domain = soap->cookie_domain;
05942 if (!domain)
05943 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error in clear cookie %s: cookie domain not set\n", name?name:"(null)"));
05944 return;
05945 }
05946 if (!path)
05947 path = soap->cookie_path;
05948 if (!path)
05949 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error in clear cookie %s: cookie path not set\n", name?name:"(null)"));
05950 return;
05951 }
05952 if (*path == '/')
05953 path++;
05954 for (p = &soap->cookies, q = *p; q; q = *p)
05955 { if (!strcmp(q->name, name) && !strcmp(q->domain, domain) && !strncmp(q->path, path, strlen(q->path)))
05956 { if (q->value)
05957 SOAP_FREE(soap, q->value);
05958 if (q->domain)
05959 SOAP_FREE(soap, q->domain);
05960 if (q->path)
05961 SOAP_FREE(soap, q->path);
05962 *p = q->next;
05963 SOAP_FREE(soap, q);
05964 }
05965 else
05966 p = &q->next;
05967 }
05968 }
05969
05970
05971 SOAP_FMAC1
05972 char *
05973 SOAP_FMAC2
05974 soap_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path)
05975 { struct soap_cookie *p;
05976 if ((p = soap_cookie(soap, name, domain, path)))
05977 return p->value;
05978 return NULL;
05979 }
05980
05981
05982 SOAP_FMAC1
05983 char *
05984 SOAP_FMAC2
05985 soap_env_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path)
05986 { struct soap_cookie *p;
05987 if ((p = soap_cookie(soap, name, domain, path)) && p->env)
05988 return p->value;
05989 return NULL;
05990 }
05991
05992
05993 SOAP_FMAC1
05994 time_t
05995 SOAP_FMAC2
05996 soap_cookie_expire(struct soap *soap, const char *name, const char *domain, const char *path)
05997 { struct soap_cookie *p;
05998 if ((p = soap_cookie(soap, name, domain, path)))
05999 return p->expire;
06000 return -1;
06001 }
06002
06003
06004 SOAP_FMAC1
06005 int
06006 SOAP_FMAC2
06007 soap_set_cookie_expire(struct soap *soap, const char *name, long expire, const char *domain, const char *path)
06008 { struct soap_cookie *p;
06009 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set cookie expiration max-age %ld: %s domain=%s path=%s\n", expire, name, domain?domain:"(null)", path?path:"(null)"));
06010 if ((p = soap_cookie(soap, name, domain, path)))
06011 { p->maxage = expire;
06012 p->modified = 1;
06013 return SOAP_OK;
06014 }
06015 return SOAP_ERR;
06016 }
06017
06018
06019 SOAP_FMAC1
06020 int
06021 SOAP_FMAC2
06022 soap_set_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path)
06023 { struct soap_cookie *p;
06024 if ((p = soap_cookie(soap, name, domain, path)))
06025 { p->session = 1;
06026 p->modified = 1;
06027 return SOAP_OK;
06028 }
06029 return SOAP_ERR;
06030 }
06031
06032
06033 SOAP_FMAC1
06034 int
06035 SOAP_FMAC2
06036 soap_clr_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path)
06037 { struct soap_cookie *p;
06038 if ((p = soap_cookie(soap, name, domain, path)))
06039 { p->session = 0;
06040 p->modified = 1;
06041 return SOAP_OK;
06042 }
06043 return SOAP_ERR;
06044 }
06045
06046
06047 SOAP_FMAC1
06048 int
06049 SOAP_FMAC2
06050 soap_putsetcookies(struct soap *soap)
06051 { struct soap_cookie *p;
06052 char *s, tmp[4096];
06053 const char *t;
06054 for (p = soap->cookies; p; p = p->next)
06055 {
06056 if (p->modified
06057 #ifdef WITH_OPENSSL
06058 || (!p->env && !soap->ssl == !p->secure)
06059 #endif
06060 )
06061 { s = tmp;
06062 if (p->name)
06063 s += soap_encode_cookie(p->name, s, tmp-s+4064);
06064 if (p->value && *p->value)
06065 { *s++ = '=';
06066 s += soap_encode_cookie(p->value, s, tmp-s+4064);
06067 }
06068 if (p->domain && (int)strlen(p->domain) < tmp-s+4064)
06069 { strcpy(s, ";Domain=");
06070 strcat(s, p->domain);
06071 }
06072 else if (soap->cookie_domain && (int)strlen(soap->cookie_domain) < tmp-s+4064)
06073 { strcpy(s, ";Domain=");
06074 strcat(s, soap->cookie_domain);
06075 }
06076 strcat(s, ";Path=/");
06077 s += strlen(s);
06078 if (p->path)
06079 t = p->path;
06080 else
06081 t = soap->cookie_path;
06082 if (t)
06083 { if (*t == '/')
06084 t++;
06085 if ((int)strlen(t) < tmp-s+4064)
06086 { if (strchr(t, '%'))
06087 { strcpy(s, t);
06088 s += strlen(s);
06089 }
06090 else
06091 s += soap_encode_cookie(t, s, tmp-s+4064);
06092 }
06093 }
06094 if (p->version > 0 && s-tmp < 4060)
06095 { sprintf(s, ";Version=%u", p->version);
06096 s += strlen(s);
06097 }
06098 if (p->maxage >= 0 && s-tmp < 4060)
06099 { sprintf(s, ";Max-Age=%ld", p->maxage);
06100 s += strlen(s);
06101 }
06102 if (s-tmp < 4073
06103 && (p->secure
06104 #ifdef WITH_OPENSSL
06105 || soap->ssl
06106 #endif
06107 ))
06108 strcpy(s, ";Secure");
06109 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set-Cookie: %s\n", tmp));
06110 if ((soap->error = soap->fposthdr(soap, "Set-Cookie", tmp)))
06111 return soap->error;
06112 }
06113 }
06114 return SOAP_OK;
06115 }
06116
06117
06118 SOAP_FMAC1
06119 int
06120 SOAP_FMAC2
06121 soap_putcookies(struct soap *soap, const char *domain, const char *path, int secure)
06122 { struct soap_cookie **p, *q;
06123 unsigned int version = 0;
06124 time_t now = time(NULL);
06125 char *s, tmp[4096];
06126 p = &soap->cookies;
06127 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending cookies for domain=%s path=%s\n", domain, path));
06128 if (*path == '/')
06129 path++;
06130 while ((q = *p))
06131 { if (q->expire && now > q->expire)
06132 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie %s expired\n", q->name));
06133 SOAP_FREE(soap, q->name);
06134 if (q->value)
06135 SOAP_FREE(soap, q->value);
06136 if (q->domain)
06137 SOAP_FREE(soap, q->domain);
06138 if (q->path)
06139 SOAP_FREE(soap, q->path);
06140 *p = q->next;
06141 SOAP_FREE(soap, q);
06142 }
06143 else
06144 { int flag;
06145 char *t = q->domain;
06146 size_t n = 0;
06147 if (!t)
06148 flag = 1;
06149 else
06150 { const char *r = strchr(t, ':');
06151 if (r)
06152 n = r - t;
06153 else
06154 n = strlen(t);
06155 flag = !strncmp(t, domain, n);
06156 }
06157
06158 #ifndef WITH_NOIO
06159 if (!flag)
06160 { struct hostent *hostent = gethostbyname((char*)domain);
06161 if (hostent)
06162 { const char *r = strchr(hostent->h_name, '.');
06163 if (!r)
06164 r = hostent->h_name;
06165 flag = !strncmp(t, r, n);
06166 }
06167 }
06168 #endif
06169 if (flag
06170 && (!q->path || !strncmp(q->path, path, strlen(q->path)))
06171 && (!q->secure || secure))
06172 { s = tmp;
06173 if (q->version != version)
06174 { sprintf(s, "$Version=%u;", q->version);
06175 version = q->version;
06176 }
06177 if (q->name)
06178 s += soap_encode_cookie(q->name, s, tmp-s+4080);
06179 if (q->value && *q->value)
06180 { *s++ = '=';
06181 s += soap_encode_cookie(q->value, s, tmp-s+4080);
06182 }
06183 if (q->path && *q->path && (int)strlen(q->path) < tmp-s+4080)
06184 { sprintf(s, ";$Path=\"/%s\"", (*q->path == '/' ? q->path + 1 : q->path));
06185 s += strlen(s);
06186 }
06187 if (q->domain && (int)strlen(q->domain) < tmp-s+4080)
06188 sprintf(s, ";$Domain=\"%s\"", q->domain);
06189 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie: %s\n", tmp));
06190 if ((soap->error = soap->fposthdr(soap, "Cookie", tmp)))
06191 return soap->error;
06192 }
06193 p = &q->next;
06194 }
06195 }
06196 return SOAP_OK;
06197 }
06198
06199
06200 SOAP_FMAC1
06201 void
06202 SOAP_FMAC2
06203 soap_getcookies(struct soap *soap, const char *val)
06204 { struct soap_cookie *p = NULL, *q;
06205 const char *s;
06206 char *t, tmp[4096];
06207 char *domain = NULL;
06208 char *path = NULL;
06209 unsigned int version = 0;
06210 time_t now = time(NULL);
06211 if (!val)
06212 return;
06213 s = val;
06214 while (*s)
06215 { s = soap_decode_key(tmp, sizeof(tmp), s);
06216 if (!soap_tag_cmp(tmp, "$Version"))
06217 { if ((s = soap_decode_val(tmp, sizeof(tmp), s)))
06218 { if (p)
06219 p->version = (int)soap_strtol(tmp, NULL, 10);
06220 else
06221 version = (int)soap_strtol(tmp, NULL, 10);
06222 }
06223 }
06224 else if (!soap_tag_cmp(tmp, "$Path"))
06225 { s = soap_decode_val(tmp, sizeof(tmp), s);
06226 if (*tmp)
06227 { if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1)))
06228 strcpy(t, tmp);
06229 }
06230 else
06231 t = NULL;
06232 if (p)
06233 { if (p->path)
06234 SOAP_FREE(soap, p->path);
06235 p->path = t;
06236 }
06237 else
06238 { if (path)
06239 SOAP_FREE(soap, path);
06240 path = t;
06241 }
06242 }
06243 else if (!soap_tag_cmp(tmp, "$Domain"))
06244 { s = soap_decode_val(tmp, sizeof(tmp), s);
06245 if (*tmp)
06246 { if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1)))
06247 strcpy(t, tmp);
06248 }
06249 else
06250 t = NULL;
06251 if (p)
06252 { if (p->domain)
06253 SOAP_FREE(soap, p->domain);
06254 p->domain = t;
06255 }
06256 else
06257 { if (domain)
06258 SOAP_FREE(soap, domain);
06259 domain = t;
06260 }
06261 }
06262 else if (p && !soap_tag_cmp(tmp, "Path"))
06263 { if (p->path)
06264 SOAP_FREE(soap, p->path);
06265 s = soap_decode_val(tmp, sizeof(tmp), s);
06266 if (*tmp)
06267 { if ((p->path = (char*)SOAP_MALLOC(soap, strlen(tmp)+1)))
06268 strcpy(p->path, tmp);
06269 }
06270 else
06271 p->path = NULL;
06272 }
06273 else if (p && !soap_tag_cmp(tmp, "Domain"))
06274 { if (p->domain)
06275 SOAP_FREE(soap, p->domain);
06276 s = soap_decode_val(tmp, sizeof(tmp), s);
06277 if (*tmp)
06278 { if ((p->domain = (char*)SOAP_MALLOC(soap, strlen(tmp)+1)))
06279 strcpy(p->domain, tmp);
06280 }
06281 else
06282 p->domain = NULL;
06283 }
06284 else if (p && !soap_tag_cmp(tmp, "Version"))
06285 { s = soap_decode_val(tmp, sizeof(tmp), s);
06286 p->version = (unsigned int)soap_strtoul(tmp, NULL, 10);
06287 }
06288 else if (p && !soap_tag_cmp(tmp, "Max-Age"))
06289 { s = soap_decode_val(tmp, sizeof(tmp), s);
06290 p->expire = now + soap_strtol(tmp, NULL, 10);
06291 }
06292 else if (p && !soap_tag_cmp(tmp, "Expires"))
06293 { struct tm T;
06294 char a[3];
06295 static const char mns[] = "anebarprayunulugepctovec";
06296 s = soap_decode_val(tmp, sizeof(tmp), s);
06297 if (strlen(tmp) > 20)
06298 { memset((void*)&T, 0, sizeof(T));
06299 a[0] = tmp[4];
06300 a[1] = tmp[5];
06301 a[2] = '\0';
06302 T.tm_mday = (int)soap_strtol(a, NULL, 10);
06303 a[0] = tmp[8];
06304 a[1] = tmp[9];
06305 T.tm_mon = (int)(strstr(mns, a) - mns) / 2;
06306 a[0] = tmp[11];
06307 a[1] = tmp[12];
06308 T.tm_year = 100 + (int)soap_strtol(a, NULL, 10);
06309 a[0] = tmp[13];
06310 a[1] = tmp[14];
06311 T.tm_hour = (int)soap_strtol(a, NULL, 10);
06312 a[0] = tmp[16];
06313 a[1] = tmp[17];
06314 T.tm_min = (int)soap_strtol(a, NULL, 10);
06315 a[0] = tmp[19];
06316 a[1] = tmp[20];
06317 T.tm_sec = (int)soap_strtol(a, NULL, 10);
06318 p->expire = soap_timegm(&T);
06319 }
06320 }
06321 else if (p && !soap_tag_cmp(tmp, "Secure"))
06322 p->secure = 1;
06323 else
06324 { if (p)
06325 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie %s=%s domain=%s path=%s expire=%ld secure=%d\n", p->name, p->value?p->value:"(null)", p->domain?p->domain:"(null)", p->path?p->path:"(null)", p->expire, p->secure));
06326 if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path)))
06327 { q->version = p->version;
06328 q->expire = p->expire;
06329 q->secure = p->secure;
06330 q->env = 1;
06331 }
06332 if (p->name)
06333 SOAP_FREE(soap, p->name);
06334 if (p->value)
06335 SOAP_FREE(soap, p->value);
06336 if (p->domain)
06337 SOAP_FREE(soap, p->domain);
06338 if (p->path)
06339 SOAP_FREE(soap, p->path);
06340 SOAP_FREE(soap, p);
06341 }
06342 if ((p = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie))))
06343 { p->name = (char*)SOAP_MALLOC(soap, strlen(tmp)+1);
06344 strcpy(p->name, tmp);
06345 s = soap_decode_val(tmp, sizeof(tmp), s);
06346 if (*tmp)
06347 { p->value = (char*)SOAP_MALLOC(soap, strlen(tmp)+1);
06348 strcpy(p->value, tmp);
06349 }
06350 else
06351 p->value = NULL;
06352 if (domain)
06353 p->domain = domain;
06354 else if (*soap->host)
06355 { p->domain = (char*)SOAP_MALLOC(soap, strlen(soap->host)+1);
06356 strcpy(p->domain, soap->host);
06357 }
06358 else
06359 p->domain = NULL;
06360 if (path)
06361 p->path = path;
06362 else if (soap->path && *soap->path)
06363 { p->path = (char*)SOAP_MALLOC(soap, strlen(soap->path)+1);
06364 strcpy(p->path, soap->path);
06365 }
06366 else
06367 { p->path = (char*)SOAP_MALLOC(soap, 2);
06368 strcpy(p->path, "/");
06369 }
06370 p->expire = 0;
06371 p->secure = 0;
06372 p->version = version;
06373 }
06374 }
06375 }
06376 if (p)
06377 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie %s=%s domain=%s path=%s expire=%ld secure=%d\n", p->name, p->value?p->value:"(null)", p->domain?p->domain:"(null)", p->path?p->path:"(null)", p->expire, p->secure));
06378 if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path)))
06379 { q->version = p->version;
06380 q->expire = p->expire;
06381 q->secure = p->secure;
06382 q->env = 1;
06383 }
06384 if (p->name)
06385 SOAP_FREE(soap, p->name);
06386 if (p->value)
06387 SOAP_FREE(soap, p->value);
06388 if (p->domain)
06389 SOAP_FREE(soap, p->domain);
06390 if (p->path)
06391 SOAP_FREE(soap, p->path);
06392 SOAP_FREE(soap, p);
06393 }
06394 if (domain)
06395 SOAP_FREE(soap, domain);
06396 if (path)
06397 SOAP_FREE(soap, path);
06398 }
06399
06400
06401 SOAP_FMAC1
06402 int
06403 SOAP_FMAC2
06404 soap_getenv_cookies(struct soap *soap)
06405 { struct soap_cookie *p;
06406 const char *s;
06407 char key[4096], val[4096];
06408 if (!(s = getenv("HTTP_COOKIE")))
06409 return SOAP_ERR;
06410 do
06411 { s = soap_decode_key(key, sizeof(key), s);
06412 s = soap_decode_val(val, sizeof(val), s);
06413 p = soap_set_cookie(soap, key, val, NULL, NULL);
06414 if (p)
06415 p->env = 1;
06416 } while (*s);
06417 return SOAP_OK;
06418 }
06419
06420
06421 SOAP_FMAC1
06422 struct soap_cookie*
06423 SOAP_FMAC2
06424 soap_copy_cookies(struct soap *copy, const struct soap *soap)
06425 { struct soap_cookie *p, **q, *r;
06426 q = &r;
06427 for (p = soap->cookies; p; p = p->next)
06428 { if (!(*q = (struct soap_cookie*)SOAP_MALLOC(copy, sizeof(struct soap_cookie))))
06429 return r;
06430 **q = *p;
06431 if (p->name)
06432 { if (((*q)->name = (char*)SOAP_MALLOC(copy, strlen(p->name)+1)))
06433 strcpy((*q)->name, p->name);
06434 }
06435 if (p->value)
06436 { if (((*q)->value = (char*)SOAP_MALLOC(copy, strlen(p->value)+1)))
06437 strcpy((*q)->value, p->value);
06438 }
06439 if (p->domain)
06440 { if (((*q)->domain = (char*)SOAP_MALLOC(copy, strlen(p->domain)+1)))
06441 strcpy((*q)->domain, p->domain);
06442 }
06443 if (p->path)
06444 { if (((*q)->path = (char*)SOAP_MALLOC(copy, strlen(p->path)+1)))
06445 strcpy((*q)->path, p->path);
06446 }
06447 q = &(*q)->next;
06448 }
06449 *q = NULL;
06450 return r;
06451 }
06452
06453
06454 SOAP_FMAC1
06455 void
06456 SOAP_FMAC2
06457 soap_free_cookies(struct soap *soap)
06458 { struct soap_cookie *p;
06459 for (p = soap->cookies; p; p = soap->cookies)
06460 { soap->cookies = p->next;
06461 SOAP_FREE(soap, p->name);
06462 if (p->value)
06463 SOAP_FREE(soap, p->value);
06464 if (p->domain)
06465 SOAP_FREE(soap, p->domain);
06466 if (p->path)
06467 SOAP_FREE(soap, p->path);
06468 SOAP_FREE(soap, p);
06469 }
06470 }
06471
06472
06473 #endif
06474
06475
06476 #ifndef WITH_NOIDREF
06477 #ifndef PALM_2
06478 SOAP_FMAC1
06479 size_t
06480 SOAP_FMAC2
06481 soap_hash(register const char *s)
06482 { register size_t h = 0;
06483 while (*s)
06484 h = 65599*h + *s++;
06485 return h % SOAP_IDHASH;
06486 }
06487 #endif
06488 #endif
06489
06490
06491 #ifndef WITH_NOIDREF
06492 #ifndef PALM_1
06493 static void
06494 soap_init_pht(struct soap *soap)
06495 { register int i;
06496 soap->pblk = NULL;
06497 soap->pidx = 0;
06498 for (i = 0; i < (int)SOAP_PTRHASH; i++)
06499 soap->pht[i] = NULL;
06500 }
06501 #endif
06502 #endif
06503
06504
06505 #ifndef PALM_1
06506 SOAP_FMAC1
06507 struct soap*
06508 SOAP_FMAC2
06509 soap_new1(soap_mode mode)
06510 { return soap_new2(mode, mode);
06511 }
06512 #endif
06513
06514
06515 #ifndef PALM_1
06516 SOAP_FMAC1
06517 struct soap*
06518 SOAP_FMAC2
06519 soap_new()
06520 { return soap_new2(SOAP_IO_DEFAULT, SOAP_IO_DEFAULT);
06521 }
06522 #endif
06523
06524
06525 #ifndef PALM_1
06526 SOAP_FMAC1
06527 struct soap*
06528 SOAP_FMAC2
06529 soap_new2(soap_mode imode, soap_mode omode)
06530 { struct soap *soap = (struct soap*)malloc(sizeof(struct soap));
06531 if (soap)
06532 soap_init2(soap, imode, omode);
06533 return soap;
06534 }
06535 #endif
06536
06537
06538 #ifndef PALM_1
06539 SOAP_FMAC1
06540 void
06541 SOAP_FMAC2
06542 soap_free(struct soap *soap)
06543 { soap_done(soap);
06544 free(soap);
06545 }
06546 #endif
06547
06548
06549 #ifndef PALM_1
06550 SOAP_FMAC1
06551 void
06552 SOAP_FMAC2
06553 soap_del(struct soap *soap)
06554 { free(soap);
06555 }
06556 #endif
06557
06558
06559 #ifndef WITH_NOIDREF
06560 #ifndef PALM_1
06561 static void
06562 soap_free_pht(struct soap *soap)
06563 { register struct soap_pblk *pb, *next;
06564 register int i;
06565 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free pointer hashtable\n"));
06566 for (pb = soap->pblk; pb; pb = next)
06567 { next = pb->next;
06568 SOAP_FREE(soap, pb);
06569 }
06570 soap->pblk = NULL;
06571 soap->pidx = 0;
06572 for (i = 0; i < (int)SOAP_PTRHASH; i++)
06573 soap->pht[i] = NULL;
06574 }
06575 #endif
06576 #endif
06577
06578
06579 #ifndef WITH_NOIDREF
06580 #ifndef PALM_2
06581 SOAP_FMAC1
06582 int
06583 SOAP_FMAC2
06584 soap_embed(struct soap *soap, const void *p, const struct soap_array *a, int n, const char *tag, int type)
06585 { register int i;
06586 struct soap_plist *pp;
06587 if (soap->version == 2)
06588 soap->encoding = 1;
06589 if (a)
06590 i = soap_array_pointer_lookup(soap, p, a, n, type, &pp);
06591 else
06592 i = soap_pointer_lookup(soap, p, type, &pp);
06593 if (i)
06594 { if (soap_is_embedded(soap, pp)
06595 || soap_is_single(soap, pp))
06596 return 0;
06597 soap_set_embedded(soap, pp);
06598 }
06599 return i;
06600 }
06601 #endif
06602 #endif
06603
06604
06605 #ifndef WITH_NOIDREF
06606 #ifndef PALM_2
06607 SOAP_FMAC1
06608 int
06609 SOAP_FMAC2
06610 soap_pointer_lookup(struct soap *soap, const void *p, int type, struct soap_plist **ppp)
06611 { register struct soap_plist *pp;
06612 *ppp = NULL;
06613 if (p)
06614 { for (pp = soap->pht[soap_hash_ptr(p)]; pp; pp = pp->next)
06615 { if (pp->ptr == p && pp->type == type)
06616 { *ppp = pp;
06617 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d id=%d\n", p, type, pp->id));
06618 return pp->id;
06619 }
06620 }
06621 }
06622 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d: not found\n", p, type));
06623 return 0;
06624 }
06625 #endif
06626 #endif
06627
06628
06629 #ifndef WITH_NOIDREF
06630 #ifndef PALM_2
06631 SOAP_FMAC1
06632 int
06633 SOAP_FMAC2
06634 soap_pointer_enter(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp)
06635 { register size_t h;
06636 register struct soap_plist *pp;
06637 if (!soap->pblk || soap->pidx >= SOAP_PTRBLK)
06638 { register struct soap_pblk *pb = (struct soap_pblk*)SOAP_MALLOC(soap, sizeof(struct soap_pblk));
06639 if (!pb)
06640 { soap->error = SOAP_EOM;
06641 return 0;
06642 }
06643 pb->next = soap->pblk;
06644 soap->pblk = pb;
06645 soap->pidx = 0;
06646 }
06647 *ppp = pp = &soap->pblk->plist[soap->pidx++];
06648 if (a)
06649 h = soap_hash_ptr(a->__ptr);
06650 else
06651 h = soap_hash_ptr(p);
06652 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));
06653 pp->next = soap->pht[h];
06654 pp->type = type;
06655 pp->mark1 = 0;
06656 pp->mark2 = 0;
06657 pp->ptr = p;
06658 pp->array = a;
06659 soap->pht[h] = pp;
06660 pp->id = ++soap->idnum;
06661 return pp->id;
06662 }
06663 #endif
06664 #endif
06665
06666
06667 #ifndef WITH_NOIDREF
06668 #ifndef PALM_2
06669 SOAP_FMAC1
06670 int
06671 SOAP_FMAC2
06672 soap_array_pointer_lookup(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp)
06673 { register struct soap_plist *pp;
06674 *ppp = NULL;
06675 if (!p || !a->__ptr)
06676 return 0;
06677 for (pp = soap->pht[soap_hash_ptr(a->__ptr)]; pp; pp = pp->next)
06678 { if (pp->type == type && pp->array && pp->array->__ptr == a->__ptr)
06679 { register int i;
06680 for (i = 0; i < n; i++)
06681 if (((const int*)&pp->array->__size)[i] != ((const int*)&a->__size)[i])
06682 break;
06683 if (i == n)
06684 { *ppp = pp;
06685 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d id=%d\n", a->__ptr, type, pp->id));
06686 return pp->id;
06687 }
06688 }
06689 }
06690 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d: not found\n", a->__ptr, type));
06691 return 0;
06692 }
06693 #endif
06694 #endif
06695
06696
06697 #ifndef PALM_1
06698 SOAP_FMAC1
06699 int
06700 SOAP_FMAC2
06701 soap_begin_count(struct soap *soap)
06702 { soap_free_ns(soap);
06703 #ifndef WITH_LEANER
06704 if ((soap->mode & SOAP_ENC_DIME) || (soap->omode & SOAP_ENC_DIME))
06705 soap->mode = soap->omode | SOAP_IO_LENGTH | SOAP_ENC_DIME;
06706 else
06707 #endif
06708 { soap->mode = soap->omode;
06709 if ((soap->mode & SOAP_IO_UDP))
06710 soap->mode |= SOAP_ENC_XML;
06711 if ((soap->mode & SOAP_IO) == SOAP_IO_STORE
06712 || (((soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_ENC_XML))
06713 #ifndef WITH_LEANER
06714 && !soap->fpreparesend
06715 #endif
06716 ))
06717 soap->mode &= ~SOAP_IO_LENGTH;
06718 else
06719 soap->mode |= SOAP_IO_LENGTH;
06720 }
06721 #ifdef WITH_ZLIB
06722 if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH)
06723 { if (!(soap->mode & SOAP_ENC_DIME))
06724 soap->mode &= ~SOAP_IO_LENGTH;
06725 if (soap->mode & SOAP_ENC_XML)
06726 soap->mode |= SOAP_IO_BUFFER;
06727 else
06728 soap->mode |= SOAP_IO_STORE;
06729 }
06730 #endif
06731 if (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH))
06732 soap->mode |= SOAP_XML_TREE;
06733 #ifndef WITH_LEANER
06734 if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME))
06735 soap->mode |= SOAP_ENC_MIME;
06736 else if (!(soap->mode & SOAP_ENC_MIME))
06737 soap->mode &= ~SOAP_ENC_MTOM;
06738 if (soap->mode & SOAP_ENC_MIME)
06739 soap_select_mime_boundary(soap);
06740 soap->dime.list = soap->dime.last;
06741 #endif
06742 soap->count = 0;
06743 soap->ns = 0;
06744 soap->null = 0;
06745 soap->position = 0;
06746 soap->mustUnderstand = 0;
06747 soap->encoding = 0;
06748 soap->part = SOAP_BEGIN;
06749 soap->event = 0;
06750 soap->idnum = 0;
06751 soap_clr_attr(soap);
06752 soap_set_local_namespaces(soap);
06753 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));
06754 #ifndef WITH_LEANER
06755 soap->dime.count = 0;
06756 soap->dime.size = 0;
06757 if (soap->fprepareinitsend && (soap->mode & SOAP_IO) != SOAP_IO_STORE && (soap->error = soap->fprepareinitsend(soap)))
06758 return soap->error;
06759 #endif
06760 return SOAP_OK;
06761 }
06762 #endif
06763
06764
06765 #ifndef PALM_1
06766 SOAP_FMAC1
06767 int
06768 SOAP_FMAC2
06769 soap_end_count(struct soap *soap)
06770 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of count phase\n"));
06771 #ifndef WITH_LEANER
06772 if ((soap->mode & SOAP_IO_LENGTH))
06773 { if (soap->fpreparefinalsend && (soap->error = soap->fpreparefinalsend(soap)))
06774 return soap->error;
06775 }
06776 #endif
06777 return SOAP_OK;
06778 }
06779 #endif
06780
06781
06782 #ifndef PALM_1
06783 SOAP_FMAC1
06784 int
06785 SOAP_FMAC2
06786 soap_begin_send(struct soap *soap)
06787 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing for output\n"));
06788 soap_free_ns(soap);
06789 soap->error = SOAP_OK;
06790 soap->mode = soap->omode | (soap->mode & (SOAP_IO_LENGTH | SOAP_ENC_DIME));
06791 #ifdef WITH_ZLIB
06792 if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH)
06793 { if (soap->mode & SOAP_ENC_XML)
06794 soap->mode |= SOAP_IO_BUFFER;
06795 else
06796 soap->mode |= SOAP_IO_STORE;
06797 }
06798 #endif
06799 #ifndef WITH_LEAN
06800 if ((soap->mode & SOAP_IO_UDP))
06801 { soap->mode |= SOAP_ENC_XML;
06802 if (soap->count > SOAP_BUFLEN)
06803 return soap->error = SOAP_UDP_ERROR;
06804 }
06805 #endif
06806 if ((soap->mode & SOAP_IO) == SOAP_IO_FLUSH && soap_valid_socket(soap->socket))
06807 { if (soap->count || (soap->mode & SOAP_IO_LENGTH) || (soap->mode & SOAP_ENC_XML))
06808 soap->mode |= SOAP_IO_BUFFER;
06809 else
06810 soap->mode |= SOAP_IO_STORE;
06811 }
06812 soap->mode &= ~SOAP_IO_LENGTH;
06813 if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
06814 if (soap_new_block(soap) == NULL)
06815 return soap->error;
06816 if (!(soap->mode & SOAP_IO_KEEPALIVE))
06817 soap->keep_alive = 0;
06818 if (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH))
06819 soap->mode |= SOAP_XML_TREE;
06820 #ifndef WITH_LEANER
06821 if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME))
06822 { soap->mode |= SOAP_ENC_MIME;
06823 soap->mode &= ~SOAP_ENC_DIME;
06824 }
06825 else if (!(soap->mode & SOAP_ENC_MIME))
06826 soap->mode &= ~SOAP_ENC_MTOM;
06827 if (soap->mode & SOAP_ENC_MIME)
06828 soap_select_mime_boundary(soap);
06829 #ifdef WIN32
06830 #ifndef UNDER_CE
06831 #ifndef WITH_FASTCGI
06832 if (!soap_valid_socket(soap->socket))
06833 #ifdef __BORLANDC__
06834 setmode(soap->sendfd, _O_BINARY);
06835 #else
06836 _setmode(soap->sendfd, _O_BINARY);
06837 #endif
06838 #endif
06839 #endif
06840 #endif
06841 #endif
06842 if (soap->mode & SOAP_IO)
06843 { soap->bufidx = 0;
06844 soap->buflen = 0;
06845 }
06846 soap->chunksize = 0;
06847 soap->ns = 0;
06848 soap->null = 0;
06849 soap->position = 0;
06850 soap->mustUnderstand = 0;
06851 soap->encoding = 0;
06852 soap->idnum = 0;
06853 soap->level = 0;
06854 soap_clr_attr(soap);
06855 soap_set_local_namespaces(soap);
06856 #ifdef WITH_ZLIB
06857 soap->z_ratio_out = 1.0;
06858 if ((soap->mode & SOAP_ENC_ZLIB) && soap->zlib_state != SOAP_ZLIB_DEFLATE)
06859 { if (!soap->z_buf)
06860 soap->z_buf = (char*)SOAP_MALLOC(soap, SOAP_BUFLEN);
06861 soap->d_stream->next_out = (Byte*)soap->z_buf;
06862 soap->d_stream->avail_out = SOAP_BUFLEN;
06863 #ifdef WITH_GZIP
06864 if (soap->zlib_out != SOAP_ZLIB_DEFLATE)
06865 { memcpy(soap->z_buf, "\37\213\10\0\0\0\0\0\0\377", 10);
06866 soap->d_stream->next_out = (Byte*)soap->z_buf + 10;
06867 soap->d_stream->avail_out = SOAP_BUFLEN - 10;
06868 soap->z_crc = crc32(0L, NULL, 0);
06869 soap->zlib_out = SOAP_ZLIB_GZIP;
06870 if (soap->z_dict)
06871 *((Byte*)soap->z_buf + 2) = 0xff;
06872 if (deflateInit2(soap->d_stream, soap->z_level, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY) != Z_OK)
06873 return soap->error = SOAP_ZLIB_ERROR;
06874 }
06875 else
06876 #endif
06877 if (deflateInit(soap->d_stream, soap->z_level) != Z_OK)
06878 return soap->error = SOAP_ZLIB_ERROR;
06879 if (soap->z_dict)
06880 { if (deflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len) != Z_OK)
06881 return soap->error = SOAP_ZLIB_ERROR;
06882 }
06883 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflate initialized\n"));
06884 soap->zlib_state = SOAP_ZLIB_DEFLATE;
06885 }
06886 #endif
06887 #ifdef WITH_OPENSSL
06888 if (soap->ssl)
06889 ERR_clear_error();
06890 #endif
06891 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin send phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count));
06892 soap->part = SOAP_BEGIN;
06893 #ifndef WITH_LEANER
06894 if (soap->fprepareinitsend && (soap->mode & SOAP_IO) == SOAP_IO_STORE && (soap->error = soap->fprepareinitsend(soap)))
06895 return soap->error;
06896 #endif
06897 return SOAP_OK;
06898 }
06899 #endif
06900
06901
06902 #ifndef WITH_NOIDREF
06903 #ifndef PALM_2
06904 SOAP_FMAC1
06905 void
06906 SOAP_FMAC2
06907 soap_embedded(struct soap *soap, const void *p, int t)
06908 { struct soap_plist *pp;
06909 if (soap_pointer_lookup(soap, p, t, &pp))
06910 { pp->mark1 = 1;
06911 pp->mark2 = 1;
06912 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded %p type=%d mark set to 1\n", p, t));
06913 }
06914 }
06915 #endif
06916 #endif
06917
06918
06919 #ifndef WITH_NOIDREF
06920 #ifndef PALM_2
06921 SOAP_FMAC1
06922 int
06923 SOAP_FMAC2
06924 soap_reference(struct soap *soap, const void *p, int t)
06925 { struct soap_plist *pp;
06926 if (!p || (soap->mode & SOAP_XML_TREE))
06927 return 1;
06928 if (soap_pointer_lookup(soap, p, t, &pp))
06929 { if (pp->mark1 == 0)
06930 { pp->mark1 = 2;
06931 pp->mark2 = 2;
06932 }
06933 }
06934 else if (soap_pointer_enter(soap, p, NULL, 0, t, &pp))
06935 { pp->mark1 = 0;
06936 pp->mark2 = 0;
06937 }
06938 else
06939 return 1;
06940 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reference %p type=%d (%d %d)\n", p, t, (int)pp->mark1, (int)pp->mark2));
06941 return pp->mark1;
06942 }
06943 #endif
06944 #endif
06945
06946
06947 #ifndef WITH_NOIDREF
06948 #ifndef PALM_2
06949 SOAP_FMAC1
06950 int
06951 SOAP_FMAC2
06952 soap_array_reference(struct soap *soap, const void *p, const struct soap_array *a, int n, int t)
06953 { register int i;
06954 struct soap_plist *pp;
06955 if (!p || !a->__ptr)
06956 return 1;
06957 i = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
06958 if (i)
06959 { if (pp->mark1 == 0)
06960 { pp->mark1 = 2;
06961 pp->mark2 = 2;
06962 }
06963 }
06964 else if (!soap_pointer_enter(soap, p, a, n, t, &pp))
06965 return 1;
06966 else
06967 { pp->mark1 = 0;
06968 pp->mark2 = 0;
06969 }
06970 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));
06971 return pp->mark1;
06972 }
06973 #endif
06974 #endif
06975
06976
06977 #ifndef WITH_NOIDREF
06978 #ifndef PALM_2
06979 SOAP_FMAC1
06980 int
06981 SOAP_FMAC2
06982 soap_embedded_id(struct soap *soap, int id, const void *p, int t)
06983 { struct soap_plist *pp = NULL;
06984 if (soap->mode & SOAP_XML_TREE)
06985 return id;
06986 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id %p type=%d id=%d\n", p, t, id));
06987 if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER)
06988 { if (id < 0)
06989 { id = soap_pointer_lookup(soap, p, t, &pp);
06990 if (id)
06991 { if (soap->mode & SOAP_IO_LENGTH)
06992 pp->mark1 = 2;
06993 else
06994 pp->mark2 = 2;
06995 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));
06996 }
06997 return -1;
06998 }
06999 return id;
07000 }
07001 if (id < 0)
07002 id = soap_pointer_lookup(soap, p, t, &pp);
07003 else if (id && !soap_pointer_lookup(soap, p, t, &pp))
07004 return 0;
07005 if (id && pp)
07006 { if (soap->mode & SOAP_IO_LENGTH)
07007 pp->mark1 = 1;
07008 else
07009 pp->mark2 = 1;
07010 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));
07011 }
07012 return id;
07013 }
07014 #endif
07015 #endif
07016
07017
07018 #ifndef WITH_NOIDREF
07019 #ifndef PALM_2
07020 SOAP_FMAC1
07021 int
07022 SOAP_FMAC2
07023 soap_is_embedded(struct soap *soap, struct soap_plist *pp)
07024 { if (!pp)
07025 return 0;
07026 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Is embedded? %d %d\n", (int)pp->mark1, (int)pp->mark2));
07027 if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER)
07028 { if (soap->mode & SOAP_IO_LENGTH)
07029 return pp->mark1 != 0;
07030 return pp->mark2 != 0;
07031 }
07032 if (soap->mode & SOAP_IO_LENGTH)
07033 return pp->mark1 == 1;
07034 return pp->mark2 == 1;
07035 }
07036 #endif
07037 #endif
07038
07039
07040 #ifndef WITH_NOIDREF
07041 #ifndef PALM_2
07042 SOAP_FMAC1
07043 int
07044 SOAP_FMAC2
07045 soap_is_single(struct soap *soap, struct soap_plist *pp)
07046 { if (soap->part == SOAP_IN_HEADER)
07047 return 1;
07048 if (!pp)
07049 return 0;
07050 if (soap->mode & SOAP_IO_LENGTH)
07051 return pp->mark1 == 0;
07052 return pp->mark2 == 0;
07053 }
07054 #endif
07055 #endif
07056
07057
07058 #ifndef WITH_NOIDREF
07059 #ifndef PALM_2
07060 SOAP_FMAC1
07061 void
07062 SOAP_FMAC2
07063 soap_set_embedded(struct soap *soap, struct soap_plist *pp)
07064 { if (!pp)
07065 return;
07066 if (soap->mode & SOAP_IO_LENGTH)
07067 pp->mark1 = 1;
07068 else
07069 pp->mark2 = 1;
07070 }
07071 #endif
07072 #endif
07073
07074
07075 #ifndef WITH_LEANER
07076 #ifndef PALM_1
07077 SOAP_FMAC1
07078 int
07079 SOAP_FMAC2
07080 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)
07081 {
07082 #ifndef WITH_NOIDREF
07083 struct soap_plist *pp;
07084 int i;
07085 if (!p || !a->__ptr || (!aid && !atype))
07086 return soap_element_id(soap, tag, id, p, a, n, type, t);
07087 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));
07088 i = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
07089 if (!i)
07090 { i = soap_pointer_enter(soap, p, a, n, t, &pp);
07091 if (!i)
07092 { soap->error = SOAP_EOM;
07093 return -1;
07094 }
07095 }
07096 if (id <= 0)
07097 id = i;
07098 if (!aid)
07099 { sprintf(soap->tmpbuf, soap->dime_id_format, id);
07100 aid = soap_strdup(soap, soap->tmpbuf);
07101 }
07102
07103
07104 if ((soap->mode & SOAP_ENC_MTOM) && strcmp(tag, "xop:Include"))
07105 { if (soap_element_begin_out(soap, tag, 0, type)
07106 || soap_element_href(soap, "xop:Include", 0, "xmlns:xop=\"http://www.w3.org/2004/08/xop/include\" href", aid)
07107 || soap_element_end_out(soap, tag))
07108 return soap->error;
07109 }
07110 else if (soap_element_href(soap, tag, 0, "href", aid))
07111 return soap->error;
07112 if (soap->mode & SOAP_IO_LENGTH)
07113 { if (pp->mark1 != 3)
07114 { struct soap_multipart *content;
07115 if (soap->mode & SOAP_ENC_MTOM)
07116 content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, (char*)a->__ptr, a->__size);
07117 else
07118 content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, (char*)a->__ptr, a->__size);
07119 if (!content)
07120 { soap->error = SOAP_EOM;
07121 return -1;
07122 }
07123 if (!strncmp(aid, "cid:", 4))
07124 { if (soap->mode & SOAP_ENC_MTOM)
07125 { char *s = (char*)soap_malloc(soap, strlen(aid) - 1);
07126 if (s)
07127 { *s = '<';
07128 strcpy(s + 1, aid + 4);
07129 strcat(s, ">");
07130 content->id = s;
07131 }
07132 }
07133 else
07134 content->id = aid + 4;
07135 }
07136 else
07137 content->id = aid;
07138 content->type = atype;
07139 content->options = aoptions;
07140 content->encoding = SOAP_MIME_BINARY;
07141 pp->mark1 = 3;
07142 }
07143 }
07144 else
07145 pp->mark2 = 3;
07146 #endif
07147 return -1;
07148 }
07149 #endif
07150 #endif
07151
07152
07153 #ifndef WITH_NOIDREF
07154 #ifndef PALM_1
07155 static void
07156 soap_init_iht(struct soap *soap)
07157 { register int i;
07158 for (i = 0; i < SOAP_IDHASH; i++)
07159 soap->iht[i] = NULL;
07160 }
07161 #endif
07162 #endif
07163
07164
07165 #ifndef WITH_NOIDREF
07166 #ifndef PALM_1
07167 static void
07168 soap_free_iht(struct soap *soap)
07169 { register int i;
07170 register struct soap_ilist *ip = NULL, *p = NULL;
07171 register struct soap_flist *fp = NULL, *fq = NULL;
07172 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free ID hashtable\n"));
07173 for (i = 0; i < SOAP_IDHASH; i++)
07174 { for (ip = soap->iht[i]; ip; ip = p)
07175 { for (fp = ip->flist; fp; fp = fq)
07176 { fq = fp->next;
07177 SOAP_FREE(soap, fp);
07178 }
07179 p = ip->next;
07180 SOAP_FREE(soap, ip);
07181 }
07182 soap->iht[i] = NULL;
07183 }
07184 }
07185 #endif
07186 #endif
07187
07188
07189 #ifndef WITH_NOIDREF
07190 #ifndef PALM_2
07191 SOAP_FMAC1
07192 struct soap_ilist *
07193 SOAP_FMAC2
07194 soap_lookup(struct soap *soap, const char *id)
07195 { register struct soap_ilist *ip = NULL;
07196 for (ip = soap->iht[soap_hash(id)]; ip; ip = ip->next)
07197 if (!strcmp(ip->id, id))
07198 return ip;
07199 return NULL;
07200 }
07201 #endif
07202 #endif
07203
07204
07205 #ifndef WITH_NOIDREF
07206 #ifndef PALM_2
07207 SOAP_FMAC1
07208 struct soap_ilist *
07209 SOAP_FMAC2
07210 soap_enter(struct soap *soap, const char *id)
07211 { register size_t h;
07212 register struct soap_ilist *ip;
07213 ip = (struct soap_ilist*)SOAP_MALLOC(soap, sizeof(struct soap_ilist) + strlen(id));
07214 if (ip)
07215 { h = soap_hash(id);
07216 strcpy(ip->id, id);
07217 ip->next = soap->iht[h];
07218 soap->iht[h] = ip;
07219 }
07220 return ip;
07221 }
07222 #endif
07223 #endif
07224
07225
07226 #ifndef PALM_2
07227 SOAP_FMAC1
07228 void*
07229 SOAP_FMAC2
07230 soap_malloc(struct soap *soap, size_t n)
07231 { register char *p;
07232 if (!n)
07233 return (void*)SOAP_NON_NULL;
07234 if (!soap)
07235 return SOAP_MALLOC(soap, n);
07236 if (soap->fmalloc)
07237 p = (char*)soap->fmalloc(soap, n);
07238 else
07239 { n += sizeof(short);
07240 n += (-(long)n) & (sizeof(void*)-1);
07241 if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(void*) + sizeof(size_t))))
07242 { soap->error = SOAP_EOM;
07243 return NULL;
07244 }
07245
07246 *(unsigned short*)(p + n - sizeof(unsigned short)) = (unsigned short)SOAP_CANARY;
07247
07248 *(void**)(p + n) = soap->alist;
07249 *(size_t*)(p + n + sizeof(void*)) = n;
07250 soap->alist = p + n;
07251 }
07252 soap->alloced = 1;
07253 return p;
07254 }
07255 #endif
07256
07257
07258 #ifdef SOAP_MEM_DEBUG
07259 static void
07260 soap_init_mht(struct soap *soap)
07261 { register int i;
07262 for (i = 0; i < (int)SOAP_PTRHASH; i++)
07263 soap->mht[i] = NULL;
07264 }
07265 #endif
07266
07267
07268 #ifdef SOAP_MEM_DEBUG
07269 static void
07270 soap_free_mht(struct soap *soap)
07271 { register int i;
07272 register struct soap_mlist *mp, *mq;
07273 for (i = 0; i < (int)SOAP_PTRHASH; i++)
07274 { for (mp = soap->mht[i]; mp; mp = mq)
07275 { mq = mp->next;
07276 if (mp->live)
07277 fprintf(stderr, "%s(%d): malloc() = %p not freed (memory leak or forgot to call soap_end()?)\n", mp->file, mp->line, mp->ptr);
07278 free(mp);
07279 }
07280 soap->mht[i] = NULL;
07281 }
07282 }
07283 #endif
07284
07285
07286 #ifdef SOAP_MEM_DEBUG
07287 SOAP_FMAC1
07288 void*
07289 SOAP_FMAC2
07290 soap_track_malloc(struct soap *soap, const char *file, int line, size_t size)
07291 { register void *p = malloc(size);
07292 if (soap)
07293 { register size_t h = soap_hash_ptr(p);
07294 register struct soap_mlist *mp = (struct soap_mlist*)malloc(sizeof(struct soap_mlist));
07295 if (soap->fdebug[SOAP_INDEX_TEST])
07296 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): malloc(%lu) = %p\n", file, line, (unsigned long)size, p));
07297 }
07298 mp->next = soap->mht[h];
07299 mp->ptr = p;
07300 mp->file = file;
07301 mp->line = line;
07302 mp->live = 1;
07303 soap->mht[h] = mp;
07304 }
07305 return p;
07306 }
07307 #endif
07308
07309
07310 #ifdef SOAP_MEM_DEBUG
07311 SOAP_FMAC1
07312 void
07313 SOAP_FMAC2
07314 soap_track_free(struct soap *soap, const char *file, int line, void *p)
07315 { register size_t h = soap_hash_ptr(p);
07316 register struct soap_mlist *mp;
07317 for (mp = soap->mht[h]; mp; mp = mp->next)
07318 if (mp->ptr == p)
07319 break;
07320 if (mp)
07321 { if (mp->live)
07322 { free(p);
07323 if (soap->fdebug[SOAP_INDEX_TEST])
07324 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): free(%p)\n", file, line, p));
07325 }
07326 mp->live = 0;
07327 }
07328 else
07329 fprintf(stderr, "%s(%d): free(%p) double free of pointer malloced at %s(%d)\n", file, line, p, mp->file, mp->line);
07330 }
07331 else
07332 fprintf(stderr, "%s(%d): free(%p) pointer not malloced\n", file, line, p);
07333 }
07334 #endif
07335
07336
07337 #ifdef SOAP_MEM_DEBUG
07338 static void
07339 soap_track_unlink(struct soap *soap, const void *p)
07340 { register size_t h = soap_hash_ptr(p);
07341 register struct soap_mlist *mp;
07342 for (mp = soap->mht[h]; mp; mp = mp->next)
07343 if (mp->ptr == p)
07344 break;
07345 if (mp)
07346 mp->live = 0;
07347 }
07348 #endif
07349
07350
07351 #ifndef PALM_2
07352 SOAP_FMAC1
07353 void
07354 SOAP_FMAC2
07355 soap_dealloc(struct soap *soap, void *p)
07356 { if (soap_check_state(soap))
07357 return;
07358 if (p)
07359 { register char **q;
07360 for (q = (char**)&soap->alist; *q; q = *(char***)q)
07361 {
07362 if (*(unsigned short*)(char*)(*q - sizeof(unsigned short)) != (unsigned short)SOAP_CANARY)
07363 {
07364 #ifdef SOAP_MEM_DEBUG
07365 fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n");
07366 #endif
07367 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n"));
07368 DBGHEX(TEST, *q - 200, 200);
07369 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n"));
07370 soap->error = SOAP_MOE;
07371 return;
07372 }
07373 if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*))))
07374 { *q = **(char***)q;
07375 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Freed data at %p\n", p));
07376 SOAP_FREE(soap, p);
07377 return;
07378 }
07379 }
07380 soap_delete(soap, p);
07381 }
07382 else
07383 { register char *q;
07384 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free all soap_malloc() data\n"));
07385 while (soap->alist)
07386 { q = (char*)soap->alist;
07387 if (*(unsigned short*)(char*)(q - sizeof(unsigned short)) != (unsigned short)SOAP_CANARY)
07388 {
07389 #ifdef SOAP_MEM_DEBUG
07390 fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n");
07391 #endif
07392 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n"));
07393 DBGHEX(TEST, q - 200, 200);
07394 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n"));
07395 soap->error = SOAP_MOE;
07396 return;
07397 }
07398 soap->alist = *(void**)q;
07399 q -= *(size_t*)(q + sizeof(void*));
07400 SOAP_FREE(soap, q);
07401 }
07402
07403 soap->action = NULL;
07404 soap->fault = NULL;
07405 soap->header = NULL;
07406 soap->userid = NULL;
07407 soap->passwd = NULL;
07408 soap->authrealm = NULL;
07409 soap->http_content = NULL;
07410 #ifndef WITH_LEANER
07411 soap_clr_mime(soap);
07412 #endif
07413 }
07414 }
07415 #endif
07416
07417
07418 #ifndef PALM_2
07419 SOAP_FMAC1
07420 void
07421 SOAP_FMAC2
07422 soap_delete(struct soap *soap, void *p)
07423 { register struct soap_clist **cp;
07424 if (soap_check_state(soap))
07425 return;
07426 cp = &soap->clist;
07427 if (p)
07428 { while (*cp)
07429 { if (p == (*cp)->ptr)
07430 { register struct soap_clist *q = *cp;
07431 *cp = q->next;
07432 if (q->fdelete(q))
07433 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: deletion callback failed for object type %d\n", q->ptr, q->type));
07434 #ifdef SOAP_MEM_DEBUG
07435 fprintf(stderr, "new(object type = %d) = %p not freed: deletion callback failed\n", q->type, q->ptr);
07436 #endif
07437 }
07438 SOAP_FREE(soap, q);
07439 return;
07440 }
07441 cp = &(*cp)->next;
07442 }
07443 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: address not in list\n", p));
07444 }
07445 else
07446 { while (*cp)
07447 { register struct soap_clist *q = *cp;
07448 *cp = q->next;
07449 if (q->fdelete(q))
07450 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: deletion callback failed for object type %d\n", q->ptr, q->type));
07451 #ifdef SOAP_MEM_DEBUG
07452 fprintf(stderr, "new(object type = %d) = %p not freed: deletion callback failed\n", q->type, q->ptr);
07453 #endif
07454 }
07455 SOAP_FREE(soap, q);
07456 }
07457 }
07458 soap->fault = NULL;
07459 soap->header = NULL;
07460 }
07461 #endif
07462
07463
07464 #ifndef PALM_2
07465 SOAP_FMAC1
07466 void
07467 SOAP_FMAC2
07468 soap_delegate_deletion(struct soap *soap, struct soap *soap_to)
07469 { register struct soap_clist *cp;
07470 register char **q;
07471 #ifdef SOAP_MEM_DEBUG
07472 register void *p;
07473 register struct soap_mlist **mp, *mq;
07474 size_t h;
07475 #endif
07476 for (q = (char**)&soap->alist; *q; q = *(char***)q)
07477 {
07478 if (*(unsigned short*)(char*)(*q - sizeof(unsigned short)) != (unsigned short)SOAP_CANARY)
07479 {
07480 #ifdef SOAP_MEM_DEBUG
07481 fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n");
07482 #endif
07483 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n"));
07484 DBGHEX(TEST, *q - 200, 200);
07485 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n"));
07486 soap->error = SOAP_MOE;
07487 return;
07488 }
07489 #ifdef SOAP_MEM_DEBUG
07490 p = (void*)(*q - *(size_t*)(*q + sizeof(void*)));
07491 h = soap_hash_ptr(p);
07492 for (mp = &soap->mht[h]; *mp; mp = &(*mp)->next)
07493 { if ((*mp)->ptr == p)
07494 { mq = *mp;
07495 *mp = mq->next;
07496 mq->next = soap_to->mht[h];
07497 soap_to->mht[h] = mq;
07498 break;
07499 }
07500 }
07501 #endif
07502 }
07503 *q = (char*)soap_to->alist;
07504 soap_to->alist = soap->alist;
07505 soap->alist = NULL;
07506 cp = soap_to->clist;
07507 if (cp)
07508 { while (cp->next)
07509 cp = cp->next;
07510 cp->next = soap->clist;
07511 }
07512 else
07513 soap_to->clist = soap->clist;
07514 soap->clist = NULL;
07515 }
07516 #endif
07517
07518
07519 #ifndef PALM_2
07520 SOAP_FMAC1
07521 struct soap_clist *
07522 SOAP_FMAC2
07523 soap_link(struct soap *soap, void *p, int t, int n, int (*fdelete)(struct soap_clist*))
07524 { register struct soap_clist *cp;
07525 if ((cp = (struct soap_clist*)SOAP_MALLOC(soap, sizeof(struct soap_clist))))
07526 { cp->next = soap->clist;
07527 cp->type = t;
07528 cp->size = n;
07529 cp->ptr = p;
07530 cp->fdelete = fdelete;
07531 soap->clist = cp;
07532 }
07533 return cp;
07534 }
07535 #endif
07536
07537
07538 #ifndef PALM_2
07539 SOAP_FMAC1
07540 void
07541 SOAP_FMAC2
07542 soap_unlink(struct soap *soap, const void *p)
07543 { register char **q;
07544 register struct soap_clist **cp;
07545 if (!soap || !p)
07546 return;
07547 for (q = (char**)&soap->alist; *q; q = *(char***)q)
07548 { if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*))))
07549 { *q = **(char***)q;
07550 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked data %p\n", p));
07551 #ifdef SOAP_MEM_DEBUG
07552 soap_track_unlink(soap, p);
07553 #endif
07554 return;
07555 }
07556 }
07557 for (cp = &soap->clist; *cp; cp = &(*cp)->next)
07558 { if (p == (*cp)->ptr)
07559 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked class instance %p\n", p));
07560 q = (char**)*cp;
07561 *cp = (*cp)->next;
07562 SOAP_FREE(soap, q);
07563 return;
07564 }
07565 }
07566 }
07567 #endif
07568
07569
07570 #ifndef WITH_NOIDREF
07571 #ifndef PALM_2
07572 SOAP_FMAC1
07573 int
07574 SOAP_FMAC2
07575 soap_lookup_type(struct soap *soap, const char *id)
07576 { register struct soap_ilist *ip;
07577 if (id && *id)
07578 { ip = soap_lookup(soap, id);
07579 if (ip)
07580 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup id='%s' type=%d\n", id, ip->type));
07581 return ip->type;
07582 }
07583 }
07584 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "lookup type id='%s' NOT FOUND! Need to get it from xsi:type\n", id));
07585 return 0;
07586 }
07587 #endif
07588 #endif
07589
07590
07591 #ifndef WITH_NOIDREF
07592 #ifndef PALM_2
07593 SOAP_FMAC1
07594 void*
07595 SOAP_FMAC2
07596 soap_id_lookup(struct soap *soap, const char *id, void **p, int t, size_t n, unsigned int k)
07597 { struct soap_ilist *ip;
07598 void **q;
07599 if (!p || !id || !*id)
07600 return p;
07601 ip = soap_lookup(soap, id);
07602 if (!ip)
07603 { if (!(ip = soap_enter(soap, id)))
07604 return NULL;
07605 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding first href='%s' type=%d %p (%u bytes)\n", id, t, p, (unsigned int)n));
07606 ip->type = t;
07607 ip->size = n;
07608 ip->link = p;
07609 ip->copy = NULL;
07610 ip->flist = NULL;
07611 ip->ptr = NULL;
07612 ip->level = k;
07613 *p = NULL;
07614 }
07615 else if (ip->ptr)
07616 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolved href='%s' type=%d location=%p (%u bytes)\n", id, t, ip->ptr, (unsigned int)n));
07617 if (ip->type != t)
07618 { strcpy(soap->id, id);
07619 soap->error = SOAP_HREF;
07620 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility: href='%s' id-type=%d href-type=%d\n", id, ip->type, t));
07621 return NULL;
07622 }
07623 while (ip->level < k)
07624 { q = (void**)soap_malloc(soap, sizeof(void*));
07625 if (!q)
07626 return NULL;
07627 *p = (void*)q;
07628 p = q;
07629 k--;
07630 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n"));
07631 }
07632 *p = ip->ptr;
07633 }
07634 else if (ip->level > k)
07635 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving level %u pointers to href='%s'\n", ip->level, id));
07636 while (ip->level > k)
07637 { void *s, **r = &ip->link;
07638 q = (void**)ip->link;
07639 while (q)
07640 { *r = (void*)soap_malloc(soap, sizeof(void*));
07641 if (!*r)
07642 return NULL;
07643 s = *q;
07644 *q = *r;
07645 r = (void**)*r;
07646 q = (void**)s;
07647 }
07648 *r = NULL;
07649 ip->size = n;
07650 ip->copy = NULL;
07651 ip->level = ip->level - 1;
07652 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n"));
07653 }
07654 q = (void**)ip->link;
07655 ip->link = p;
07656 *p = (void*)q;
07657 }
07658 else
07659 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarded href='%s' type=%d location=%p (%u bytes)\n", id, t, p, (unsigned int)n));
07660 while (ip->level < k)
07661 { q = (void**)soap_malloc(soap, sizeof(void*));
07662 if (!q)
07663 return NULL;
07664 *p = q;
07665 p = q;
07666 k--;
07667 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n"));
07668 }
07669 q = (void**)ip->link;
07670 ip->link = p;
07671 *p = (void*)q;
07672 }
07673 return p;
07674 }
07675 #endif
07676 #endif
07677
07678
07679 #ifndef WITH_NOIDREF
07680 #ifndef PALM_2
07681 SOAP_FMAC1
07682 void*
07683 SOAP_FMAC2
07684 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))
07685 { struct soap_ilist *ip;
07686 if (!p || !href || !*href)
07687 return p;
07688 ip = soap_lookup(soap, href);
07689 if (!ip)
07690 { if (!(ip = soap_enter(soap, href)))
07691 return NULL;
07692 ip->type = st;
07693 ip->size = n;
07694 ip->link = NULL;
07695 ip->copy = NULL;
07696 ip->ptr = NULL;
07697 ip->level = 0;
07698 ip->flist = NULL;
07699 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));
07700 }
07701 else if (ip->type != st || (ip->level == k && ip->size != n))
07702 { 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));
07703 strcpy(soap->id, href);
07704 soap->error = SOAP_HREF;
07705 return NULL;
07706 }
07707 if (fcopy || n < sizeof(void*) || *href != '#')
07708 { register struct soap_flist *fp = (struct soap_flist*)SOAP_MALLOC(soap, sizeof(struct soap_flist));
07709 if (!fp)
07710 { soap->error = SOAP_EOM;
07711 return NULL;
07712 }
07713 fp->next = ip->flist;
07714 fp->type = tt;
07715 fp->ptr = p;
07716 fp->level = k;
07717 fp->len = len;
07718 if (fcopy)
07719 fp->fcopy = fcopy;
07720 else
07721 fp->fcopy = soap_fcopy;
07722 ip->flist = fp;
07723 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));
07724 }
07725 else
07726 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding copying address %p for type=%d href='%s'\n", p, st, href));
07727 *(void**)p = ip->copy;
07728 ip->copy = p;
07729 }
07730 return p;
07731 }
07732 #endif
07733 #endif
07734
07735
07736 #ifndef PALM_2
07737 SOAP_FMAC1
07738 void*
07739 SOAP_FMAC2
07740 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*))
07741 {
07742 #ifndef WITH_NOIDREF
07743 struct soap_ilist *ip;
07744 #endif
07745 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Enter id='%s' type=%d loc=%p size=%lu level=%u\n", id, t, p, (unsigned long)n, k));
07746 soap->alloced = 0;
07747 if (!p)
07748 { if (finstantiate)
07749 p = finstantiate(soap, t, type, arrayType, &n);
07750 else
07751 p = soap_malloc(soap, n);
07752 if (p)
07753 soap->alloced = 1;
07754 }
07755 #ifndef WITH_NOIDREF
07756 if (!id || !*id)
07757 #endif
07758 return p;
07759 #ifndef WITH_NOIDREF
07760 ip = soap_lookup(soap, id);
07761 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Lookup entry id='%s for location=%p'\n", id, p));
07762 if (!ip)
07763 { if (!(ip = soap_enter(soap, id)))
07764 return NULL;
07765 ip->type = t;
07766 ip->link = NULL;
07767 ip->copy = NULL;
07768 ip->flist = NULL;
07769 ip->size = n;
07770 ip->ptr = p;
07771 ip->level = k;
07772 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));
07773 }
07774 else if ((ip->type != t || (ip->level == k && ip->size != n)) && (ip->copy || ip->flist))
07775 { 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));
07776 strcpy(soap->id, id);
07777 soap->error = SOAP_HREF;
07778 return NULL;
07779 }
07780 else if (ip->ptr)
07781 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Multiply defined id='%s'\n", id));
07782 strcpy(soap->id, id);
07783 soap->error = SOAP_DUPLICATE_ID;
07784 return NULL;
07785 }
07786 else
07787 { ip->size = n;
07788 ip->ptr = p;
07789 ip->level = k;
07790 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));
07791 }
07792 return ip->ptr;
07793 #endif
07794 }
07795 #endif
07796
07797
07798 #ifndef PALM_2
07799 SOAP_FMAC1
07800 void
07801 SOAP_FMAC2
07802 soap_fcopy(struct soap *soap, int st, int tt, void *p, size_t len, const void *q, size_t n)
07803 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Copying data type=%d (target type=%d) %p -> %p (%lu bytes)\n", st, tt, q, p, (unsigned long)n));
07804 memcpy(p, q, n);
07805 }
07806 #endif
07807
07808
07809 #ifndef PALM_1
07810 SOAP_FMAC1
07811 int
07812 SOAP_FMAC2
07813 soap_end_send(struct soap *soap)
07814 {
07815 #ifndef WITH_LEANER
07816 int err;
07817 if (soap->dime.list)
07818 {
07819 soap->dime.last->next = soap->dime.first;
07820 soap->dime.first = soap->dime.list->next;
07821 soap->dime.list->next = NULL;
07822 soap->dime.last = soap->dime.list;
07823 }
07824 if (!(err = soap_putdime(soap)))
07825 err = soap_putmime(soap);
07826 soap->mime.list = NULL;
07827 soap->mime.first = NULL;
07828 soap->mime.last = NULL;
07829 soap->dime.list = NULL;
07830 soap->dime.first = NULL;
07831 soap->dime.last = NULL;
07832 if (err)
07833 return err;
07834 #endif
07835 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End send mode=0x%x\n", soap->mode));
07836 if (soap->mode & SOAP_IO)
07837 { if (soap_flush(soap))
07838 #ifdef WITH_ZLIB
07839 { if (soap->mode & SOAP_ENC_ZLIB && soap->zlib_state == SOAP_ZLIB_DEFLATE)
07840 { soap->zlib_state = SOAP_ZLIB_NONE;
07841 deflateEnd(soap->d_stream);
07842 }
07843 return soap->error;
07844 }
07845 #else
07846 return soap->error;
07847 #endif
07848 #ifdef WITH_ZLIB
07849 if (soap->mode & SOAP_ENC_ZLIB)
07850 { int r;
07851 soap->d_stream->avail_in = 0;
07852 do
07853 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating remainder\n"));
07854 r = deflate(soap->d_stream, Z_FINISH);
07855 if (soap->d_stream->avail_out != SOAP_BUFLEN)
07856 { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN - soap->d_stream->avail_out))
07857 { soap->zlib_state = SOAP_ZLIB_NONE;
07858 deflateEnd(soap->d_stream);
07859 return soap->error;
07860 }
07861 soap->d_stream->next_out = (Byte*)soap->z_buf;
07862 soap->d_stream->avail_out = SOAP_BUFLEN;
07863 }
07864 } while (r == Z_OK);
07865 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflated total %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out));
07866 soap->z_ratio_out = (float)soap->d_stream->total_out / (float)soap->d_stream->total_in;
07867 soap->mode &= ~SOAP_ENC_ZLIB;
07868 soap->zlib_state = SOAP_ZLIB_NONE;
07869 if (deflateEnd(soap->d_stream) != Z_OK || r != Z_STREAM_END)
07870 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to end deflate: %s\n", soap->d_stream->msg?soap->d_stream->msg:SOAP_STR_EOS));
07871 return soap->error = SOAP_ZLIB_ERROR;
07872 }
07873 #ifdef WITH_GZIP
07874 if (soap->zlib_out != SOAP_ZLIB_DEFLATE)
07875 { soap->z_buf[0] = soap->z_crc & 0xFF;
07876 soap->z_buf[1] = (soap->z_crc >> 8) & 0xFF;
07877 soap->z_buf[2] = (soap->z_crc >> 16) & 0xFF;
07878 soap->z_buf[3] = (soap->z_crc >> 24) & 0xFF;
07879 soap->z_buf[4] = soap->d_stream->total_in & 0xFF;
07880 soap->z_buf[5] = (soap->d_stream->total_in >> 8) & 0xFF;
07881 soap->z_buf[6] = (soap->d_stream->total_in >> 16) & 0xFF;
07882 soap->z_buf[7] = (soap->d_stream->total_in >> 24) & 0xFF;
07883 if (soap_flush_raw(soap, soap->z_buf, 8))
07884 return soap->error;
07885 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip crc32=%lu\n", (unsigned long)soap->z_crc));
07886 }
07887 #endif
07888 }
07889 #endif
07890 if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
07891 { char *p;
07892 #ifndef WITH_NOHTTP
07893 if (!(soap->mode & SOAP_ENC_XML))
07894 { soap->mode--;
07895 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending buffered message of length %u\n", (unsigned int)soap->blist->size));
07896 if (soap->status >= SOAP_POST)
07897 soap->error = soap->fpost(soap, soap->endpoint, soap->host, soap->port, soap->path, soap->action, soap->blist->size);
07898 else if (soap->status != SOAP_STOP)
07899 soap->error = soap->fresponse(soap, soap->status, soap->blist->size);
07900 if (soap->error || soap_flush(soap))
07901 return soap->error;
07902 soap->mode++;
07903 }
07904 #endif
07905 for (p = soap_first_block(soap, NULL); p; p = soap_next_block(soap, NULL))
07906 { DBGMSG(SENT, p, soap_block_size(soap, NULL));
07907 if ((soap->error = soap->fsend(soap, p, soap_block_size(soap, NULL))))
07908 { soap_end_block(soap, NULL);
07909 return soap->error;
07910 }
07911 }
07912 soap_end_block(soap, NULL);
07913 }
07914 #ifndef WITH_LEANER
07915 else if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
07916 { DBGMSG(SENT, "\r\n0\r\n\r\n", 7);
07917 if ((soap->error = soap->fsend(soap, "\r\n0\r\n\r\n", 7)))
07918 return soap->error;
07919 }
07920 #endif
07921 }
07922 #ifdef WITH_TCPFIN
07923 #ifdef WITH_OPENSSL
07924 if (!soap->ssl && soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP))
07925 soap->fshutdownsocket(soap, soap->socket, SOAP_SHUT_WR);
07926 #else
07927 if (soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP))
07928 soap->fshutdownsocket(soap, soap->socket, SOAP_SHUT_WR);
07929 #endif
07930 #endif
07931 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of send phase\n"));
07932 soap->omode &= ~SOAP_SEC_WSUID;
07933 soap->count = 0;
07934 soap->part = SOAP_END;
07935 return SOAP_OK;
07936 }
07937 #endif
07938
07939
07940 #ifndef PALM_1
07941 SOAP_FMAC1
07942 int
07943 SOAP_FMAC2
07944 soap_end_recv(struct soap *soap)
07945 { soap->part = SOAP_END;
07946 #ifndef WITH_LEAN
07947 soap->wsuid = NULL;
07948 soap->c14nexclude = NULL;
07949 #endif
07950 #ifndef WITH_LEANER
07951 soap->ffilterrecv = NULL;
07952 if ((soap->mode & SOAP_ENC_DIME) && soap_getdime(soap))
07953 { soap->dime.first = NULL;
07954 soap->dime.last = NULL;
07955 return soap->error;
07956 }
07957 soap->dime.list = soap->dime.first;
07958 soap->dime.first = NULL;
07959 soap->dime.last = NULL;
07960
07961 if (soap->mode & SOAP_ENC_MIME)
07962 { if (soap->mode & SOAP_MIME_POSTCHECK)
07963 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Post checking MIME attachments\n"));
07964 if (!soap->keep_alive)
07965 soap->keep_alive = -1;
07966 #ifndef WITH_NOIDREF
07967 soap_resolve(soap);
07968 #endif
07969 return SOAP_OK;
07970 }
07971 if (soap_getmime(soap))
07972 return soap->error;
07973 }
07974 soap->mime.list = soap->mime.first;
07975 soap->mime.first = NULL;
07976 soap->mime.last = NULL;
07977 soap->mime.boundary = NULL;
07978 if (soap->xlist)
07979 { struct soap_multipart *content;
07980 for (content = soap->mime.list; content; content = content->next)
07981 soap_resolve_attachment(soap, content);
07982 }
07983 #endif
07984 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "End of receive message ok\n"));
07985 #ifdef WITH_ZLIB
07986 if (soap->mode & SOAP_ENC_ZLIB)
07987 {
07988 while (soap->d_stream->next_out != Z_NULL)
07989 if ((int)soap_get1(soap) == EOF)
07990 break;
07991 soap->mode &= ~SOAP_ENC_ZLIB;
07992 memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN);
07993 soap->bufidx = (char*)soap->d_stream->next_in - soap->z_buf;
07994 soap->buflen = soap->z_buflen;
07995 soap->zlib_state = SOAP_ZLIB_NONE;
07996 if (inflateEnd(soap->d_stream) != Z_OK)
07997 return soap->error = SOAP_ZLIB_ERROR;
07998 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Inflate end ok\n"));
07999 #ifdef WITH_GZIP
08000 if (soap->zlib_in == SOAP_ZLIB_GZIP)
08001 { soap_wchar c;
08002 short i;
08003 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Inflate gzip crc check\n"));
08004 for (i = 0; i < 8; i++)
08005 { if ((int)(c = soap_get1(soap)) == EOF)
08006 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: unable to read crc value\n"));
08007 return soap->error = SOAP_EOF;
08008 }
08009 soap->z_buf[i] = (char)c;
08010 }
08011 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)))
08012 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip inflate error: crc check failed, message corrupted? (crc32=%lu)\n", (unsigned long)soap->z_crc));
08013 return soap->error = SOAP_ZLIB_ERROR;
08014 }
08015 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)))
08016 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip inflate error: incorrect message length\n"));
08017 return soap->error = SOAP_ZLIB_ERROR;
08018 }
08019 }
08020 soap->zlib_in = SOAP_ZLIB_NONE;
08021 #endif
08022 }
08023 #endif
08024 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
08025 while (soap->ahead != EOF && !soap_recv_raw(soap))
08026 ;
08027 #ifndef WITH_NOIDREF
08028 if (soap_resolve(soap))
08029 return soap->error;
08030 #endif
08031 #ifndef WITH_LEANER
08032 if (soap->xlist)
08033 { if (soap->mode & SOAP_ENC_MTOM)
08034 return soap->error = SOAP_MIME_HREF;
08035 return soap->error = SOAP_DIME_HREF;
08036 }
08037 #endif
08038 soap_free_ns(soap);
08039 #ifndef WITH_LEANER
08040 if (soap->fpreparefinalrecv)
08041 return soap->error = soap->fpreparefinalrecv(soap);
08042 #endif
08043 return SOAP_OK;
08044 }
08045 #endif
08046
08047
08048 #ifndef PALM_1
08049 SOAP_FMAC1
08050 void
08051 SOAP_FMAC2
08052 soap_free_temp(struct soap *soap)
08053 { register struct soap_attribute *tp, *tq;
08054 register struct Namespace *ns;
08055 soap_free_ns(soap);
08056 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free any remaining temp blocks\n"));
08057 while (soap->blist)
08058 soap_end_block(soap, NULL);
08059 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute storage\n"));
08060 for (tp = soap->attributes; tp; tp = tq)
08061 { tq = tp->next;
08062 if (tp->value)
08063 SOAP_FREE(soap, tp->value);
08064 SOAP_FREE(soap, tp);
08065 }
08066 soap->attributes = NULL;
08067 #ifdef WITH_FAST
08068 if (soap->labbuf)
08069 SOAP_FREE(soap, soap->labbuf);
08070 soap->labbuf = NULL;
08071 soap->lablen = 0;
08072 soap->labidx = 0;
08073 #endif
08074 ns = soap->local_namespaces;
08075 if (ns)
08076 { for (; ns->id; ns++)
08077 { if (ns->out)
08078 { if (soap->encodingStyle == ns->out)
08079 soap->encodingStyle = SOAP_STR_EOS;
08080 SOAP_FREE(soap, ns->out);
08081 ns->out = NULL;
08082 }
08083 if (soap->encodingStyle == ns->ns)
08084 soap->encodingStyle = SOAP_STR_EOS;
08085 }
08086 SOAP_FREE(soap, soap->local_namespaces);
08087 soap->local_namespaces = NULL;
08088 }
08089 #ifndef WITH_LEANER
08090 while (soap->xlist)
08091 { struct soap_xlist *xp = soap->xlist->next;
08092 SOAP_FREE(soap, soap->xlist);
08093 soap->xlist = xp;
08094 }
08095 #endif
08096 #ifndef WITH_NOIDREF
08097 soap_free_pht(soap);
08098 soap_free_iht(soap);
08099 #endif
08100 }
08101 #endif
08102
08103
08104 #ifndef PALM_1
08105 static void
08106 soap_free_ns(struct soap *soap)
08107 { register struct soap_nlist *np, *nq;
08108 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free namespace stack\n"));
08109 for (np = soap->nlist; np; np = nq)
08110 { nq = np->next;
08111 SOAP_FREE(soap, np);
08112 }
08113 soap->nlist = NULL;
08114 }
08115 #endif
08116
08117
08118 #ifndef PALM_1
08119 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
08120 static void
08121 soap_init_logs(struct soap *soap)
08122 { int i;
08123 for (i = 0; i < SOAP_MAXLOGS; i++)
08124 { soap->logfile[i] = NULL;
08125 soap->fdebug[i] = NULL;
08126 }
08127 }
08128 #endif
08129 #endif
08130
08131
08132 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
08133 SOAP_FMAC1
08134 void
08135 SOAP_FMAC2
08136 soap_open_logfile(struct soap *soap, int i)
08137 { if (soap->logfile[i])
08138 soap->fdebug[i] = fopen(soap->logfile[i], i < 2 ? "ab" : "a");
08139 }
08140 #endif
08141
08142
08143 #ifdef SOAP_DEBUG
08144 static void
08145 soap_close_logfile(struct soap *soap, int i)
08146 { if (soap->fdebug[i])
08147 { fclose(soap->fdebug[i]);
08148 soap->fdebug[i] = NULL;
08149 }
08150 }
08151 #endif
08152
08153
08154 #ifdef SOAP_DEBUG
08155 SOAP_FMAC1
08156 void
08157 SOAP_FMAC2
08158 soap_close_logfiles(struct soap *soap)
08159 { int i;
08160 for (i = 0; i < SOAP_MAXLOGS; i++)
08161 soap_close_logfile(soap, i);
08162 }
08163 #endif
08164
08165
08166 #ifdef SOAP_DEBUG
08167 static void
08168 soap_set_logfile(struct soap *soap, int i, const char *logfile)
08169 { const char *s;
08170 char *t = NULL;
08171 soap_close_logfile(soap, i);
08172 s = soap->logfile[i];
08173 soap->logfile[i] = logfile;
08174 if (s)
08175 SOAP_FREE(soap, (void*)s);
08176 if (logfile)
08177 if ((t = (char*)SOAP_MALLOC(soap, strlen(logfile) + 1)))
08178 strcpy(t, logfile);
08179 soap->logfile[i] = t;
08180 }
08181 #endif
08182
08183
08184 #ifdef SOAP_DEBUG
08185 SOAP_FMAC1
08186 void
08187 SOAP_FMAC2
08188 soap_set_recv_logfile(struct soap *soap, const char *logfile)
08189 { soap_set_logfile(soap, SOAP_INDEX_RECV, logfile);
08190 }
08191 #endif
08192
08193
08194 #ifdef SOAP_DEBUG
08195 SOAP_FMAC1
08196 void
08197 SOAP_FMAC2
08198 soap_set_sent_logfile(struct soap *soap, const char *logfile)
08199 { soap_set_logfile(soap, SOAP_INDEX_SENT, logfile);
08200 }
08201 #endif
08202
08203
08204 #ifdef SOAP_DEBUG
08205 SOAP_FMAC1
08206 void
08207 SOAP_FMAC2
08208 soap_set_test_logfile(struct soap *soap, const char *logfile)
08209 { soap_set_logfile(soap, SOAP_INDEX_TEST, logfile);
08210 }
08211 #endif
08212
08213
08214 #ifndef PALM_1
08215 SOAP_FMAC1
08216 struct soap*
08217 SOAP_FMAC2
08218 soap_copy(const struct soap *soap)
08219 { return soap_copy_context((struct soap*)malloc(sizeof(struct soap)), soap);
08220 }
08221 #endif
08222
08223
08224 #ifndef PALM_1
08225 SOAP_FMAC1
08226 struct soap*
08227 SOAP_FMAC2
08228 soap_copy_context(struct soap *copy, const struct soap *soap)
08229 { if (copy == soap)
08230 return copy;
08231 if (soap_check_state(soap))
08232 return NULL;
08233 if (copy)
08234 { register struct soap_plugin *p = NULL;
08235 #ifdef __cplusplus
08236 *copy = *soap;
08237 #else
08238 memcpy(copy, soap, sizeof(struct soap));
08239 #endif
08240 copy->state = SOAP_COPY;
08241 copy->error = SOAP_OK;
08242 copy->userid = NULL;
08243 copy->passwd = NULL;
08244 copy->nlist = NULL;
08245 copy->blist = NULL;
08246 copy->clist = NULL;
08247 copy->alist = NULL;
08248 copy->attributes = NULL;
08249 copy->labbuf = NULL;
08250 copy->lablen = 0;
08251 copy->labidx = 0;
08252 #ifdef SOAP_MEM_DEBUG
08253 soap_init_mht(copy);
08254 #endif
08255 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
08256 soap_init_logs(copy);
08257 #endif
08258 #ifdef SOAP_DEBUG
08259 soap_set_test_logfile(copy, soap->logfile[SOAP_INDEX_TEST]);
08260 soap_set_sent_logfile(copy, soap->logfile[SOAP_INDEX_SENT]);
08261 soap_set_recv_logfile(copy, soap->logfile[SOAP_INDEX_RECV]);
08262 #endif
08263 copy->local_namespaces = NULL;
08264 soap_set_namespaces(copy, soap->local_namespaces);
08265 #ifdef WITH_C_LOCALE
08266 copy->c_locale = duplocale(soap->c_locale);
08267 #else
08268 copy->c_locale = NULL;
08269 #endif
08270 #ifdef WITH_OPENSSL
08271 copy->bio = NULL;
08272 copy->ssl = NULL;
08273 copy->session = NULL;
08274 #endif
08275 #ifdef WITH_GNUTLS
08276 copy->session = NULL;
08277 #endif
08278 #ifdef WITH_ZLIB
08279 copy->d_stream = (z_stream*)SOAP_MALLOC(copy, sizeof(z_stream));
08280 copy->d_stream->zalloc = Z_NULL;
08281 copy->d_stream->zfree = Z_NULL;
08282 copy->d_stream->opaque = Z_NULL;
08283 copy->z_buf = NULL;
08284 #endif
08285 #ifndef WITH_NOIDREF
08286 soap_init_iht(copy);
08287 soap_init_pht(copy);
08288 #endif
08289 copy->header = NULL;
08290 copy->fault = NULL;
08291 copy->action = NULL;
08292 #ifndef WITH_LEAN
08293 #ifdef WITH_COOKIES
08294 copy->cookies = soap_copy_cookies(copy, soap);
08295 #else
08296 copy->cookies = NULL;
08297 #endif
08298 #endif
08299 copy->plugins = NULL;
08300 for (p = soap->plugins; p; p = p->next)
08301 { register struct soap_plugin *q = (struct soap_plugin*)SOAP_MALLOC(copy, sizeof(struct soap_plugin));
08302 if (!q)
08303 return NULL;
08304 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying plugin '%s'\n", p->id));
08305 *q = *p;
08306 if (p->fcopy && p->fcopy(copy, q, p))
08307 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not copy plugin '%s'\n", p->id));
08308 SOAP_FREE(copy, q);
08309 return NULL;
08310 }
08311 q->next = copy->plugins;
08312 copy->plugins = q;
08313 }
08314 }
08315 return copy;
08316 }
08317 #endif
08318
08319
08320 #ifndef PALM_1
08321 SOAP_FMAC1
08322 void
08323 SOAP_FMAC2
08324 soap_copy_stream(struct soap *copy, struct soap *soap)
08325 { struct soap_attribute *tp = NULL, *tq;
08326 if (copy == soap)
08327 return;
08328 copy->mode = soap->mode;
08329 copy->imode = soap->imode;
08330 copy->omode = soap->omode;
08331 copy->socket = soap->socket;
08332 copy->recv_timeout = soap->recv_timeout;
08333 copy->send_timeout = soap->send_timeout;
08334 #if defined(__cplusplus) && !defined(WITH_LEAN)
08335 copy->os = soap->os;
08336 copy->is = soap->is;
08337 #endif
08338 copy->sendfd = soap->sendfd;
08339 copy->recvfd = soap->recvfd;
08340 copy->bufidx = soap->bufidx;
08341 copy->buflen = soap->buflen;
08342 copy->ahead = soap->ahead;
08343 copy->cdata = soap->cdata;
08344 copy->chunksize = soap->chunksize;
08345 copy->chunkbuflen = soap->chunkbuflen;
08346 copy->keep_alive = soap->keep_alive;
08347 copy->tcp_keep_alive = soap->tcp_keep_alive;
08348 copy->tcp_keep_idle = soap->tcp_keep_idle;
08349 copy->tcp_keep_intvl = soap->tcp_keep_intvl;
08350 copy->tcp_keep_cnt = soap->tcp_keep_cnt;
08351 copy->max_keep_alive = soap->max_keep_alive;
08352 #ifndef WITH_NOIO
08353 copy->peer = soap->peer;
08354 copy->peerlen = soap->peerlen;
08355 #endif
08356 #ifdef WITH_OPENSSL
08357 copy->bio = NULL;
08358 copy->ctx = NULL;
08359 copy->ssl = NULL;
08360 if (soap->ssl)
08361 copy->ssl = SSL_dup(soap->ssl);
08362 #endif
08363 #ifdef WITH_GNUTLS
08364 copy->session = soap->session;
08365 #endif
08366 #ifdef WITH_ZLIB
08367 copy->zlib_state = soap->zlib_state;
08368 copy->zlib_in = soap->zlib_in;
08369 copy->zlib_out = soap->zlib_out;
08370 copy->d_stream = (z_stream*)SOAP_MALLOC(copy, sizeof(z_stream));
08371 memcpy(copy->d_stream, soap->d_stream, sizeof(z_stream));
08372 copy->z_crc = soap->z_crc;
08373 copy->z_ratio_in = soap->z_ratio_in;
08374 copy->z_ratio_out = soap->z_ratio_out;
08375 copy->z_buf = NULL;
08376 copy->z_buflen = soap->z_buflen;
08377 copy->z_level = soap->z_level;
08378 if (soap->z_buf && soap->zlib_state != SOAP_ZLIB_NONE)
08379 { copy->z_buf = (char*)SOAP_MALLOC(copy, SOAP_BUFLEN);
08380 memcpy(copy->z_buf, soap->z_buf, sizeof(soap->z_buf));
08381 }
08382 copy->z_dict = soap->z_dict;
08383 copy->z_dict_len = soap->z_dict_len;
08384 #endif
08385 memcpy(copy->buf, soap->buf, sizeof(soap->buf));
08386
08387 soap_free_ns(copy);
08388 soap_set_local_namespaces(copy);
08389 if (soap->nlist && soap->local_namespaces)
08390 { register struct soap_nlist *np = NULL, *nq;
08391
08392 for (nq = soap->nlist; nq; nq = nq->next)
08393 { register struct soap_nlist *nr = np;
08394 size_t n = sizeof(struct soap_nlist) + strlen(nq->id);
08395 np = (struct soap_nlist*)SOAP_MALLOC(copy, n);
08396 if (!np)
08397 break;
08398 memcpy(np, nq, n);
08399 np->next = nr;
08400 }
08401 while (np)
08402 { register const char *s = np->ns;
08403 copy->level = np->level;
08404 if (!s && np->index >= 0)
08405 { s = soap->local_namespaces[np->index].out;
08406 if (!s)
08407 s = soap->local_namespaces[np->index].ns;
08408 }
08409 if (s && soap_push_namespace(copy, np->id, s) == NULL)
08410 break;
08411 nq = np;
08412 np = np->next;
08413 SOAP_FREE(copy, nq);
08414 }
08415 }
08416 copy->level = soap->level;
08417 copy->body = soap->body;
08418 copy->peeked = soap->peeked;
08419 memcpy(copy->tag, soap->tag, sizeof(copy->tag));
08420
08421 for (tq = soap->attributes; tq; tq = tq->next)
08422 { struct soap_attribute *tr = tp;
08423 size_t n = sizeof(struct soap_attribute) + strlen(tq->name);
08424 tp = (struct soap_attribute*)SOAP_MALLOC(copy, n);
08425 memcpy(tp, tq, n);
08426 if (tp->size)
08427 { tp->value = (char*)SOAP_MALLOC(copy, tp->size);
08428 if (tp->value)
08429 strcpy(tp->value, tq->value);
08430 }
08431 tp->ns = NULL;
08432 tp->next = tr;
08433 }
08434 copy->attributes = tp;
08435 }
08436 #endif
08437
08438
08439 #ifndef PALM_1
08440 SOAP_FMAC1
08441 void
08442 SOAP_FMAC2
08443 soap_free_stream(struct soap *soap)
08444 { soap->socket = SOAP_INVALID_SOCKET;
08445 #ifdef WITH_OPENSSL
08446 soap->bio = NULL;
08447 if (soap->ssl)
08448 SSL_free(soap->ssl);
08449 soap->ssl = NULL;
08450 #endif
08451 #ifdef WITH_GNUTLS
08452 soap->xcred = NULL;
08453 soap->acred = NULL;
08454 soap->cache = NULL;
08455 soap->session = NULL;
08456 soap->dh_params = NULL;
08457 soap->rsa_params = NULL;
08458 #endif
08459 #ifdef WITH_ZLIB
08460 if (soap->d_stream)
08461 SOAP_FREE(soap, soap->d_stream);
08462 soap->d_stream = NULL;
08463 if (soap->z_buf)
08464 SOAP_FREE(soap, soap->z_buf);
08465 soap->z_buf = NULL;
08466 #endif
08467 }
08468 #endif
08469
08470
08471 #ifndef PALM_1
08472 SOAP_FMAC1
08473 void
08474 SOAP_FMAC2
08475 soap_init(struct soap *soap)
08476 { size_t i;
08477 soap->state = SOAP_INIT;
08478 #ifdef SOAP_MEM_DEBUG
08479 soap_init_mht(soap);
08480 #endif
08481 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
08482 soap_init_logs(soap);
08483 #endif
08484 #ifdef SOAP_DEBUG
08485 #ifdef TANDEM
08486 soap_set_test_logfile(soap, "TESTLOG");
08487 soap_set_sent_logfile(soap, "SENTLOG");
08488 soap_set_recv_logfile(soap, "RECVLOG");
08489 #else
08490 soap_set_test_logfile(soap, "TEST.log");
08491 soap_set_sent_logfile(soap, "SENT.log");
08492 soap_set_recv_logfile(soap, "RECV.log");
08493 #endif
08494 #endif
08495 soap->version = 0;
08496 soap_imode(soap, SOAP_IO_DEFAULT);
08497 soap_omode(soap, SOAP_IO_DEFAULT);
08498 soap->plugins = NULL;
08499 soap->user = NULL;
08500 for (i = 0; i < sizeof(soap->data)/sizeof(*soap->data); i++)
08501 soap->data[i] = NULL;
08502 soap->userid = NULL;
08503 soap->passwd = NULL;
08504 #ifndef WITH_NOHTTP
08505 soap->fpost = http_post;
08506 soap->fput = http_put;
08507 soap->fget = http_get;
08508 soap->fdel = http_405;
08509 soap->fopt = http_405;
08510 soap->fhead = http_405;
08511 soap->fform = NULL;
08512 soap->fposthdr = http_post_header;
08513 soap->fresponse = http_response;
08514 soap->fparse = http_parse;
08515 soap->fparsehdr = http_parse_header;
08516 #endif
08517 soap->fheader = NULL;
08518 soap->fconnect = NULL;
08519 soap->fdisconnect = NULL;
08520 #ifndef WITH_NOIO
08521 soap->ipv6_multicast_if = 0;
08522 soap->ipv4_multicast_if = NULL;
08523 soap->ipv4_multicast_ttl = 0;
08524 #ifndef WITH_IPV6
08525 soap->fresolve = tcp_gethost;
08526 #else
08527 soap->fresolve = NULL;
08528 #endif
08529 soap->faccept = tcp_accept;
08530 soap->fopen = tcp_connect;
08531 soap->fclose = tcp_disconnect;
08532 soap->fclosesocket = tcp_closesocket;
08533 soap->fshutdownsocket = tcp_shutdownsocket;
08534 soap->fsend = fsend;
08535 soap->frecv = frecv;
08536 soap->fpoll = soap_poll;
08537 #else
08538 soap->fopen = NULL;
08539 soap->fclose = NULL;
08540 soap->fpoll = NULL;
08541 #endif
08542 soap->fseterror = NULL;
08543 soap->fignore = NULL;
08544 soap->fserveloop = NULL;
08545 soap->fplugin = fplugin;
08546 soap->fmalloc = NULL;
08547 #ifndef WITH_LEANER
08548 soap->feltbegin = NULL;
08549 soap->feltendin = NULL;
08550 soap->feltbegout = NULL;
08551 soap->feltendout = NULL;
08552 soap->fprepareinitsend = NULL;
08553 soap->fprepareinitrecv = NULL;
08554 soap->fpreparesend = NULL;
08555 soap->fpreparerecv = NULL;
08556 soap->fpreparefinalsend = NULL;
08557 soap->fpreparefinalrecv = NULL;
08558 soap->ffiltersend = NULL;
08559 soap->ffilterrecv = NULL;
08560 soap->fdimereadopen = NULL;
08561 soap->fdimewriteopen = NULL;
08562 soap->fdimereadclose = NULL;
08563 soap->fdimewriteclose = NULL;
08564 soap->fdimeread = NULL;
08565 soap->fdimewrite = NULL;
08566 soap->fmimereadopen = NULL;
08567 soap->fmimewriteopen = NULL;
08568 soap->fmimereadclose = NULL;
08569 soap->fmimewriteclose = NULL;
08570 soap->fmimeread = NULL;
08571 soap->fmimewrite = NULL;
08572 #endif
08573 soap->float_format = "%.9G";
08574 soap->double_format = "%.17lG";
08575 soap->dime_id_format = "cid:id%d";
08576 soap->http_version = "1.1";
08577 soap->proxy_http_version = "1.0";
08578 soap->http_content = NULL;
08579 soap->actor = NULL;
08580 soap->lang = "en";
08581 soap->keep_alive = 0;
08582 soap->tcp_keep_alive = 0;
08583 soap->tcp_keep_idle = 0;
08584 soap->tcp_keep_intvl = 0;
08585 soap->tcp_keep_cnt = 0;
08586 soap->max_keep_alive = SOAP_MAXKEEPALIVE;
08587 soap->recv_timeout = 0;
08588 soap->send_timeout = 0;
08589 soap->connect_timeout = 0;
08590 soap->accept_timeout = 0;
08591 soap->socket_flags = 0;
08592 soap->connect_flags = 0;
08593 soap->bind_flags = 0;
08594 soap->accept_flags = 0;
08595 soap->linger_time = 0;
08596 soap->ip = 0;
08597 soap->labbuf = NULL;
08598 soap->lablen = 0;
08599 soap->labidx = 0;
08600 soap->encodingStyle = SOAP_STR_EOS;
08601 #ifndef WITH_NONAMESPACES
08602 soap->namespaces = namespaces;
08603 #else
08604 soap->namespaces = NULL;
08605 #endif
08606 soap->local_namespaces = NULL;
08607 soap->nlist = NULL;
08608 soap->blist = NULL;
08609 soap->clist = NULL;
08610 soap->alist = NULL;
08611 soap->attributes = NULL;
08612 soap->header = NULL;
08613 soap->fault = NULL;
08614 soap->master = SOAP_INVALID_SOCKET;
08615 soap->socket = SOAP_INVALID_SOCKET;
08616 soap->os = NULL;
08617 soap->is = NULL;
08618 #ifndef WITH_LEANER
08619 soap->dom = NULL;
08620 soap->dime.list = NULL;
08621 soap->dime.first = NULL;
08622 soap->dime.last = NULL;
08623 soap->mime.list = NULL;
08624 soap->mime.first = NULL;
08625 soap->mime.last = NULL;
08626 soap->mime.boundary = NULL;
08627 soap->mime.start = NULL;
08628 soap->xlist = NULL;
08629 #endif
08630 #ifndef UNDER_CE
08631 soap->recvfd = 0;
08632 soap->sendfd = 1;
08633 #else
08634 soap->recvfd = stdin;
08635 soap->sendfd = stdout;
08636 #endif
08637 soap->host[0] = '\0';
08638 soap->port = 0;
08639 soap->action = NULL;
08640 soap->proxy_host = NULL;
08641 soap->proxy_port = 8080;
08642 soap->proxy_userid = NULL;
08643 soap->proxy_passwd = NULL;
08644 soap->authrealm = NULL;
08645 soap->prolog = NULL;
08646 #ifdef WITH_ZLIB
08647 soap->zlib_state = SOAP_ZLIB_NONE;
08648 soap->zlib_in = SOAP_ZLIB_NONE;
08649 soap->zlib_out = SOAP_ZLIB_NONE;
08650 soap->d_stream = (z_stream*)SOAP_MALLOC(soap, sizeof(z_stream));
08651 soap->d_stream->zalloc = Z_NULL;
08652 soap->d_stream->zfree = Z_NULL;
08653 soap->d_stream->opaque = Z_NULL;
08654 soap->z_buf = NULL;
08655 soap->z_level = 6;
08656 soap->z_dict = NULL;
08657 soap->z_dict_len = 0;
08658 #endif
08659 #ifndef WITH_LEAN
08660 soap->wsuid = NULL;
08661 soap->c14nexclude = NULL;
08662 soap->cookies = NULL;
08663 soap->cookie_domain = NULL;
08664 soap->cookie_path = NULL;
08665 soap->cookie_max = 32;
08666 #endif
08667 #ifdef WMW_RPM_IO
08668 soap->rpmreqid = NULL;
08669 #endif
08670 #ifdef PALM
08671 palmNetLibOpen();
08672 #endif
08673 #ifndef WITH_NOIDREF
08674 soap_init_iht(soap);
08675 soap_init_pht(soap);
08676 #endif
08677 #ifdef WITH_OPENSSL
08678 if (!soap_ssl_init_done)
08679 soap_ssl_init();
08680 soap->fsslauth = ssl_auth_init;
08681 soap->fsslverify = ssl_verify_callback;
08682 soap->bio = NULL;
08683 soap->ssl = NULL;
08684 soap->ctx = NULL;
08685 soap->session = NULL;
08686 soap->ssl_flags = SOAP_SSL_DEFAULT;
08687 soap->keyfile = NULL;
08688 soap->password = NULL;
08689 soap->cafile = NULL;
08690 soap->capath = NULL;
08691 soap->crlfile = NULL;
08692 soap->dhfile = NULL;
08693 soap->randfile = NULL;
08694 #endif
08695 #ifdef WITH_GNUTLS
08696 if (!soap_ssl_init_done)
08697 soap_ssl_init();
08698 soap->fsslauth = ssl_auth_init;
08699 soap->fsslverify = NULL;
08700 soap->xcred = NULL;
08701 soap->acred = NULL;
08702 soap->cache = NULL;
08703 soap->session = NULL;
08704 soap->ssl_flags = SOAP_SSL_DEFAULT;
08705 soap->keyfile = NULL;
08706 soap->password = NULL;
08707 soap->cafile = NULL;
08708 soap->capath = NULL;
08709 soap->crlfile = NULL;
08710 soap->dh_params = NULL;
08711 soap->rsa_params = NULL;
08712 #endif
08713 #ifdef WITH_C_LOCALE
08714 soap->c_locale = newlocale(LC_ALL_MASK, "C", NULL);
08715 #else
08716 soap->c_locale = NULL;
08717 #endif
08718 soap->buflen = 0;
08719 soap->bufidx = 0;
08720 #ifndef WITH_LEANER
08721 soap->dime.chunksize = 0;
08722 soap->dime.buflen = 0;
08723 #endif
08724 soap->null = 0;
08725 soap->position = 0;
08726 soap->encoding = 0;
08727 soap->mustUnderstand = 0;
08728 soap->ns = 0;
08729 soap->part = SOAP_END;
08730 soap->event = 0;
08731 soap->alloced = 0;
08732 soap->count = 0;
08733 soap->length = 0;
08734 soap->cdata = 0;
08735 soap->peeked = 0;
08736 soap->ahead = 0;
08737 soap->idnum = 0;
08738 soap->level = 0;
08739 soap->endpoint[0] = '\0';
08740 soap->error = SOAP_OK;
08741 }
08742 #endif
08743
08744
08745 #ifndef PALM_1
08746 SOAP_FMAC1
08747 void
08748 SOAP_FMAC2
08749 soap_init1(struct soap *soap, soap_mode mode)
08750 { soap_init2(soap, mode, mode);
08751 }
08752 #endif
08753
08754
08755 #ifndef PALM_1
08756 SOAP_FMAC1
08757 void
08758 SOAP_FMAC2
08759 soap_init2(struct soap *soap, soap_mode imode, soap_mode omode)
08760 { soap_init(soap);
08761 soap_imode(soap, imode);
08762 soap_omode(soap, omode);
08763 }
08764 #endif
08765
08766
08767 #ifndef PALM_2
08768 SOAP_FMAC1
08769 void
08770 SOAP_FMAC2
08771 soap_begin(struct soap *soap)
08772 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reinitializing context\n"));
08773 if (!soap->keep_alive)
08774 { soap->buflen = 0;
08775 soap->bufidx = 0;
08776 }
08777 soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0);
08778 soap->null = 0;
08779 soap->position = 0;
08780 soap->encoding = 0;
08781 soap->mustUnderstand = 0;
08782 soap->mode = 0;
08783 soap->ns = 0;
08784 soap->part = SOAP_END;
08785 soap->event = 0;
08786 soap->alloced = 0;
08787 soap->count = 0;
08788 soap->length = 0;
08789 soap->cdata = 0;
08790 soap->error = SOAP_OK;
08791 soap->peeked = 0;
08792 soap->ahead = 0;
08793 soap->idnum = 0;
08794 soap->level = 0;
08795 soap->endpoint[0] = '\0';
08796 #ifndef WITH_LEANER
08797 soap->dime.chunksize = 0;
08798 soap->dime.buflen = 0;
08799 #endif
08800 soap_free_temp(soap);
08801 }
08802 #endif
08803
08804
08805 #ifndef PALM_2
08806 SOAP_FMAC1
08807 void
08808 SOAP_FMAC2
08809 soap_end(struct soap *soap)
08810 { if (soap_check_state(soap))
08811 return;
08812 soap_free_temp(soap);
08813 soap_dealloc(soap, NULL);
08814 while (soap->clist)
08815 { register struct soap_clist *cp = soap->clist->next;
08816 SOAP_FREE(soap, soap->clist);
08817 soap->clist = cp;
08818 }
08819 soap_closesock(soap);
08820 #ifdef SOAP_DEBUG
08821 soap_close_logfiles(soap);
08822 #endif
08823 #ifdef PALM
08824 palmNetLibClose();
08825 #endif
08826 }
08827 #endif
08828
08829
08830 #ifndef PALM_1
08831 SOAP_FMAC1
08832 int
08833 SOAP_FMAC2
08834 soap_set_namespaces(struct soap *soap, const struct Namespace *p)
08835 { register struct Namespace *ns = soap->local_namespaces;
08836 register struct soap_nlist *np, *nq, *nr;
08837 register unsigned int level = soap->level;
08838 soap->namespaces = p;
08839 soap->local_namespaces = NULL;
08840 soap_set_local_namespaces(soap);
08841
08842 np = soap->nlist;
08843 soap->nlist = NULL;
08844 if (np)
08845 { nq = np->next;
08846 np->next = NULL;
08847 while (nq)
08848 { nr = nq->next;
08849 nq->next = np;
08850 np = nq;
08851 nq = nr;
08852 }
08853 }
08854
08855 while (np)
08856 { register const char *s;
08857 soap->level = np->level;
08858 s = np->ns;
08859 if (!s && np->index >= 0 && ns)
08860 { s = ns[np->index].out;
08861 if (!s)
08862 s = ns[np->index].ns;
08863 }
08864 if (s && soap_push_namespace(soap, np->id, s) == NULL)
08865 return soap->error;
08866 nq = np;
08867 np = np->next;
08868 SOAP_FREE(soap, nq);
08869 }
08870 if (ns)
08871 { register int i;
08872 for (i = 0; ns[i].id; i++)
08873 { if (ns[i].out)
08874 { SOAP_FREE(soap, ns[i].out);
08875 ns[i].out = NULL;
08876 }
08877 }
08878 SOAP_FREE(soap, ns);
08879 }
08880 soap->level = level;
08881 return SOAP_OK;
08882 }
08883 #endif
08884
08885
08886 #ifndef PALM_1
08887 SOAP_FMAC1
08888 void
08889 SOAP_FMAC2
08890 soap_set_local_namespaces(struct soap *soap)
08891 { if (soap->namespaces && !soap->local_namespaces)
08892 { register const struct Namespace *ns1;
08893 register struct Namespace *ns2;
08894 register size_t n = 1;
08895 for (ns1 = soap->namespaces; ns1->id; ns1++)
08896 n++;
08897 n *= sizeof(struct Namespace);
08898 ns2 = (struct Namespace*)SOAP_MALLOC(soap, n);
08899 if (ns2)
08900 { memcpy(ns2, soap->namespaces, n);
08901 if (ns2[0].ns)
08902 { if (!strcmp(ns2[0].ns, soap_env1))
08903 soap->version = 1;
08904 else
08905 soap->version = 2;
08906 }
08907 soap->local_namespaces = ns2;
08908 }
08909 }
08910 }
08911 #endif
08912
08913
08914 #ifndef WITH_LEAN
08915 #ifndef PALM_1
08916 SOAP_FMAC1
08917 const char *
08918 SOAP_FMAC2
08919 soap_tagsearch(const char *big, const char *little)
08920 { if (little)
08921 { register size_t n = strlen(little);
08922 register const char *s = big;
08923 while (s)
08924 { register const char *t = s;
08925 register size_t i;
08926 for (i = 0; i < n; i++, t++)
08927 { if (*t != little[i])
08928 break;
08929 }
08930 if (*t == '\0' || *t == ' ')
08931 { if (i == n || (i && little[i-1] == ':'))
08932 return s;
08933 }
08934 s = strchr(t, ' ');
08935 if (s)
08936 s++;
08937 }
08938 }
08939 return NULL;
08940 }
08941 #endif
08942 #endif
08943
08944
08945 #ifndef WITH_LEAN
08946 #ifndef PALM_1
08947 SOAP_FMAC1
08948 struct soap_nlist *
08949 SOAP_FMAC2
08950 soap_lookup_ns(struct soap *soap, const char *tag, size_t n)
08951 { register struct soap_nlist *np;
08952 for (np = soap->nlist; np; np = np->next)
08953 { if (!strncmp(np->id, tag, n) && !np->id[n])
08954 return np;
08955 }
08956 return NULL;
08957 }
08958 #endif
08959 #endif
08960
08961
08962 #ifndef WITH_LEAN
08963 static struct soap_nlist *
08964 soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized)
08965 { register struct soap_nlist *np;
08966 size_t n, k;
08967 if (soap_tagsearch(soap->c14nexclude, id))
08968 return NULL;
08969 if (!utilized)
08970 { for (np = soap->nlist; np; np = np->next)
08971 { if (!strcmp(np->id, id) && (!np->ns || !strcmp(np->ns, ns)))
08972 break;
08973 }
08974 if (np)
08975 { if ((np->level < soap->level || !np->ns) && np->index == 1)
08976 utilized = 1;
08977 else
08978 return NULL;
08979 }
08980 }
08981 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Adding namespace binding (level=%u) '%s' '%s' utilized=%d\n", soap->level, id, ns?ns:"(null)", utilized));
08982 n = strlen(id);
08983 if (ns)
08984 k = strlen(ns);
08985 else
08986 k = 0;
08987 np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k + 1);
08988 if (!np)
08989 { soap->error = SOAP_EOM;
08990 return NULL;
08991 }
08992 np->next = soap->nlist;
08993 soap->nlist = np;
08994 strcpy(np->id, id);
08995 if (ns)
08996 np->ns = strcpy(np->id + n + 1, ns);
08997 else
08998 np->ns = NULL;
08999 np->level = soap->level;
09000 np->index = utilized;
09001 return np;
09002 }
09003 #endif
09004
09005
09006 #ifndef WITH_LEAN
09007 static void
09008 soap_utilize_ns(struct soap *soap, const char *tag, size_t n)
09009 { register struct soap_nlist *np = soap_lookup_ns(soap, tag, n);
09010 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Utilizing namespace of '%s'\n", tag));
09011 if (np)
09012 { if (np->index == 0)
09013 soap_push_ns(soap, np->id, np->ns, 1);
09014 }
09015 else if (strncmp(tag, "xml", 3))
09016 { strncpy(soap->tmpbuf, tag, n);
09017 soap->tmpbuf[n] = '\0';
09018 soap_push_ns(soap, soap->tmpbuf, NULL, 1);
09019 }
09020 }
09021 #endif
09022
09023
09024 #ifndef PALM_2
09025 SOAP_FMAC1
09026 int
09027 SOAP_FMAC2
09028 soap_element(struct soap *soap, const char *tag, int id, const char *type)
09029 {
09030 #ifndef WITH_LEAN
09031 register const char *s;
09032 #endif
09033 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element begin tag='%s' id='%d' type='%s'\n", tag, id, type?type:SOAP_STR_EOS));
09034 #ifdef WITH_DOM
09035 #ifndef WITH_LEAN
09036 if (soap->wsuid && soap_tagsearch(soap->wsuid, tag))
09037 { size_t i;
09038 for (s = tag, i = 0; *s && i < sizeof(soap->tag) - 1; s++, i++)
09039 soap->tag[i] = *s == ':' ? '-' : *s;
09040 soap->tag[i] = '\0';
09041 if (soap_set_attr(soap, "wsu:Id", soap->tag, 1))
09042 return soap->error;
09043 }
09044 if (soap->event == SOAP_SEC_BEGIN && (soap->mode & SOAP_XML_CANONICAL) && !(soap->mode & SOAP_DOM_ASIS))
09045 { register struct soap_nlist *np;
09046
09047 for (np = soap->nlist; np; np = np->next)
09048 { if (np->index == 2)
09049 np->index = 0;
09050 }
09051 }
09052 #endif
09053 if (soap->mode & SOAP_XML_DOM)
09054 { register struct soap_dom_element *elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element));
09055 if (!elt)
09056 return soap->error;
09057 elt->soap = soap;
09058 elt->next = NULL;
09059 elt->prnt = soap->dom;
09060 elt->name = soap_strdup(soap, tag);
09061 elt->elts = NULL;
09062 elt->atts = NULL;
09063 elt->nstr = NULL;
09064 elt->data = NULL;
09065 elt->wide = NULL;
09066 elt->node = NULL;
09067 elt->type = 0;
09068 elt->head = NULL;
09069 elt->tail = NULL;
09070 if (soap->dom)
09071 { struct soap_dom_element *p = soap->dom->elts;
09072 if (p)
09073 { while (p->next)
09074 p = p->next;
09075 p->next = elt;
09076 }
09077 else
09078 soap->dom->elts = elt;
09079 }
09080 soap->dom = elt;
09081 }
09082 else
09083 {
09084 #endif
09085 soap->level++;
09086 #ifndef WITH_LEAN
09087 if (!soap->ns)
09088 { if (!(soap->mode & SOAP_XML_CANONICAL)
09089 && soap_send(soap, soap->prolog ? soap->prolog : "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"))
09090 return soap->error;
09091 }
09092 else if (soap->mode & SOAP_XML_INDENT)
09093 { if (soap->ns == 1 && soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1))
09094 return soap->error;
09095 soap->body = 1;
09096 }
09097 if ((soap->mode & SOAP_XML_DEFAULTNS) && (s = strchr(tag, ':')))
09098 { struct Namespace *ns = soap->local_namespaces;
09099 size_t n = s - tag;
09100 if (soap_send_raw(soap, "<", 1)
09101 || soap_send(soap, s + 1))
09102 return soap->error;
09103 if (soap->nlist && !strncmp(soap->nlist->id, tag, n) && !soap->nlist->id[n])
09104 ns = NULL;
09105 for (; ns && ns->id; ns++)
09106 { if (*ns->id && (ns->out || ns->ns) && !strncmp(ns->id, tag, n) && !ns->id[n])
09107 { soap_push_ns(soap, ns->id, ns->out ? ns->out : ns->ns, 0);
09108 if (soap_attribute(soap, "xmlns", ns->out ? ns->out : ns->ns))
09109 return soap->error;
09110 break;
09111 }
09112 }
09113 }
09114 else
09115 #endif
09116 if (soap_send_raw(soap, "<", 1)
09117 || soap_send(soap, tag))
09118 return soap->error;
09119 #ifdef WITH_DOM
09120 }
09121 #endif
09122 if (!soap->ns)
09123 { struct Namespace *ns;
09124 int k = -1;
09125 #ifndef WITH_LEAN
09126 if ((soap->mode & SOAP_XML_DEFAULTNS))
09127 k = 4;
09128 #endif
09129 for (ns = soap->local_namespaces; ns && ns->id && k; ns++, k--)
09130 { if (*ns->id && (ns->out || ns->ns))
09131 { sprintf(soap->tmpbuf, "xmlns:%s", ns->id);
09132 if (soap_attribute(soap, soap->tmpbuf, ns->out ? ns->out : ns->ns))
09133 return soap->error;
09134 }
09135 }
09136 }
09137 soap->ns = 1;
09138 #ifndef WITH_LEAN
09139 if (soap->mode & SOAP_XML_CANONICAL)
09140 { const char *t = strchr(tag, ':');
09141 if (t)
09142 soap_utilize_ns(soap, tag, t - tag);
09143 }
09144 #endif
09145 if (id > 0)
09146 { sprintf(soap->tmpbuf, "_%d", id);
09147 if (soap_attribute(soap, "id", soap->tmpbuf))
09148 return soap->error;
09149 }
09150 if (type && *type && soap->part != SOAP_IN_HEADER)
09151 { if (soap->attributes ? soap_set_attr(soap, "xsi:type", type, 1) : soap_attribute(soap, "xsi:type", type))
09152 return soap->error;
09153 #ifndef WITH_LEAN
09154 if (soap->mode & SOAP_XML_CANONICAL)
09155 { const char *t = strchr(type, ':');
09156 if (t)
09157 soap_utilize_ns(soap, type, t - type);
09158 }
09159 #endif
09160 }
09161 if (soap->null && soap->position > 0)
09162 { register int i;
09163 sprintf(soap->tmpbuf, "[%d", soap->positions[0]);
09164 for (i = 1; i < soap->position; i++)
09165 sprintf(soap->tmpbuf + strlen(soap->tmpbuf), ",%d", soap->positions[i]);
09166 strcat(soap->tmpbuf, "]");
09167 if (soap_attribute(soap, "SOAP-ENC:position", soap->tmpbuf))
09168 return soap->error;
09169 }
09170 if (soap->mustUnderstand)
09171 { if (soap->actor && *soap->actor)
09172 { if (soap_attribute(soap, soap->version == 2 ? "SOAP-ENV:role" : "SOAP-ENV:actor", soap->actor))
09173 return soap->error;
09174 }
09175 if (soap_attribute(soap, "SOAP-ENV:mustUnderstand", soap->version == 2 ? "true" : "1"))
09176 return soap->error;
09177 soap->mustUnderstand = 0;
09178 }
09179 if (soap->encoding)
09180 { if (soap->encodingStyle && soap->local_namespaces)
09181 { if (!*soap->encodingStyle)
09182 { if (soap->local_namespaces[1].out)
09183 soap->encodingStyle = soap->local_namespaces[1].out;
09184 else
09185 soap->encodingStyle = soap->local_namespaces[1].ns;
09186 }
09187 if (soap->encodingStyle && soap_attribute(soap, "SOAP-ENV:encodingStyle", soap->encodingStyle))
09188 return soap->error;
09189 }
09190 soap->encoding = 0;
09191 }
09192 soap->null = 0;
09193 soap->position = 0;
09194 if (soap->event == SOAP_SEC_BEGIN && (soap->mode & SOAP_XML_CANONICAL))
09195 soap->event = SOAP_SEC_SIGN;
09196 return SOAP_OK;
09197 }
09198 #endif
09199
09200
09201 #ifndef PALM_2
09202 SOAP_FMAC1
09203 int
09204 SOAP_FMAC2
09205 soap_element_begin_out(struct soap *soap, const char *tag, int id, const char *type)
09206 { if (*tag == '-')
09207 return SOAP_OK;
09208 if (soap_element(soap, tag, id, type))
09209 return soap->error;
09210 #ifdef WITH_DOM
09211 if (soap_element_start_end_out(soap, NULL))
09212 return soap->error;
09213 if (soap->feltbegout)
09214 return soap->error = soap->feltbegout(soap, tag);
09215 return SOAP_OK;
09216 #else
09217 return soap_element_start_end_out(soap, NULL);
09218 #endif
09219 }
09220 #endif
09221
09222
09223 #ifndef PALM_2
09224 #ifndef HAVE_STRRCHR
09225 SOAP_FMAC1
09226 char*
09227 SOAP_FMAC2
09228 soap_strrchr(const char *s, int t)
09229 { register char *r = NULL;
09230 while (*s)
09231 if (*s++ == t)
09232 r = (char*)s - 1;
09233 return r;
09234 }
09235 #endif
09236 #endif
09237
09238
09239 #ifndef PALM_2
09240 #ifndef HAVE_STRTOL
09241 SOAP_FMAC1
09242 long
09243 SOAP_FMAC2
09244 soap_strtol(const char *s, char **t, int b)
09245 { register long n = 0;
09246 register int c;
09247 while (*s > 0 && *s <= 32)
09248 s++;
09249 if (b == 10)
09250 { short neg = 0;
09251 if (*s == '-')
09252 { s++;
09253 neg = 1;
09254 }
09255 else if (*s == '+')
09256 s++;
09257 while ((c = *s) && c >= '0' && c <= '9')
09258 { if (n >= 214748364 && (n > 214748364 || c >= '8'))
09259 break;
09260 n *= 10;
09261 n += c - '0';
09262 s++;
09263 }
09264 if (neg)
09265 n = -n;
09266 }
09267 else
09268 { while ((c = *s))
09269 { if (c >= '0' && c <= '9')
09270 c -= '0';
09271 else if (c >= 'A' && c <= 'F')
09272 c -= 'A' - 10;
09273 else if (c >= 'a' && c <= 'f')
09274 c -= 'a' - 10;
09275 if (n > 0x07FFFFFF)
09276 break;
09277 n <<= 4;
09278 n += c;
09279 s++;
09280 }
09281 }
09282 if (t)
09283 *t = (char*)s;
09284 return n;
09285 }
09286 #endif
09287 #endif
09288
09289
09290 #ifndef PALM_2
09291 #ifndef HAVE_STRTOUL
09292 SOAP_FMAC1
09293 unsigned long
09294 SOAP_FMAC2
09295 soap_strtoul(const char *s, char **t, int b)
09296 { unsigned long n = 0;
09297 register int c;
09298 while (*s > 0 && *s <= 32)
09299 s++;
09300 if (b == 10)
09301 { if (*s == '+')
09302 s++;
09303 while ((c = *s) && c >= '0' && c <= '9')
09304 { if (n >= 429496729 && (n > 429496729 || c >= '6'))
09305 break;
09306 n *= 10;
09307 n += c - '0';
09308 s++;
09309 }
09310 }
09311 else
09312 { while ((c = *s))
09313 { if (c >= '0' && c <= '9')
09314 c -= '0';
09315 else if (c >= 'A' && c <= 'F')
09316 c -= 'A' - 10;
09317 else if (c >= 'a' && c <= 'f')
09318 c -= 'a' - 10;
09319 if (n > 0x0FFFFFFF)
09320 break;
09321 n <<= 4;
09322 n += c;
09323 s++;
09324 }
09325 }
09326 if (t)
09327 *t = (char*)s;
09328 return n;
09329 }
09330 #endif
09331 #endif
09332
09333
09334 #ifndef PALM_1
09335 SOAP_FMAC1
09336 int
09337 SOAP_FMAC2
09338 soap_array_begin_out(struct soap *soap, const char *tag, int id, const char *type, const char *offset)
09339 { if (!type || !*type)
09340 return soap_element_begin_out(soap, tag, id, NULL);
09341 if (soap_element(soap, tag, id, "SOAP-ENC:Array"))
09342 return soap->error;
09343 if (soap->version == 2)
09344 { const char *s;
09345 s = soap_strrchr(type, '[');
09346 if ((size_t)(s - type) < sizeof(soap->tmpbuf))
09347 { strncpy(soap->tmpbuf, type, s - type);
09348 soap->tmpbuf[s - type] = '\0';
09349 if (soap_attribute(soap, "SOAP-ENC:itemType", soap->tmpbuf))
09350 return soap->error;
09351 if (s && (soap_attribute(soap, "SOAP-ENC:arraySize", s + 1)))
09352 return soap->error;
09353 }
09354 }
09355 else
09356 { if (offset && soap_attribute(soap, "SOAP-ENC:offset", offset))
09357 return soap->error;
09358 if (soap_attribute(soap, "SOAP-ENC:arrayType", type))
09359 return soap->error;
09360 }
09361 #ifndef WITH_LEAN
09362 if ((soap->mode & SOAP_XML_CANONICAL))
09363 { const char *s = strchr(type, ':');
09364 if (s)
09365 soap_utilize_ns(soap, type, s - type);
09366 }
09367 #endif
09368 return soap_element_start_end_out(soap, NULL);
09369 }
09370 #endif
09371
09372
09373 #ifndef PALM_1
09374 SOAP_FMAC1
09375 int
09376 SOAP_FMAC2
09377 soap_element_start_end_out(struct soap *soap, const char *tag)
09378 { register struct soap_attribute *tp;
09379 #ifndef WITH_LEAN
09380 if (soap->mode & SOAP_XML_CANONICAL)
09381 { struct soap_nlist *np;
09382 for (tp = soap->attributes; tp; tp = tp->next)
09383 { if (tp->visible && tp->name)
09384 { const char *s = strchr(tp->name, ':');
09385 if (s)
09386 soap_utilize_ns(soap, tp->name, s - tp->name);
09387 }
09388 }
09389 for (np = soap->nlist; np; np = np->next)
09390 { if (np->index == 1 && np->ns)
09391 { sprintf(soap->tmpbuf, "xmlns:%s", np->id);
09392 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enabling utilized binding (level=%u) %s='%s'\n", np->level, soap->tmpbuf, np->ns));
09393 soap_set_attr(soap, soap->tmpbuf, np->ns, 1);
09394 np->index = 2;
09395 }
09396 }
09397 }
09398 #endif
09399 #ifdef WITH_DOM
09400 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
09401 { register struct soap_dom_attribute **att;
09402 att = &soap->dom->atts;
09403 for (tp = soap->attributes; tp; tp = tp->next)
09404 { if (tp->visible)
09405 { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
09406 if (!*att)
09407 return soap->error;
09408 (*att)->next = NULL;
09409 (*att)->nstr = NULL;
09410 (*att)->name = soap_strdup(soap, tp->name);
09411 (*att)->data = soap_strdup(soap, tp->value);
09412 (*att)->wide = NULL;
09413 (*att)->soap = soap;
09414 att = &(*att)->next;
09415 tp->visible = 0;
09416 }
09417 }
09418 return SOAP_OK;
09419 }
09420 #endif
09421 for (tp = soap->attributes; tp; tp = tp->next)
09422 { if (tp->visible)
09423 {
09424 #ifndef WITH_LEAN
09425 const char *s;
09426 if ((soap->mode & SOAP_XML_DEFAULTNS) && (s = strchr(tp->name, ':')))
09427 { size_t n = s - tp->name;
09428 if (soap->nlist && !strncmp(soap->nlist->id, tp->name, n) && !soap->nlist->id[n])
09429 s++;
09430 else
09431 s = tp->name;
09432 if (soap_send(soap, " ") || soap_send(soap, s))
09433 return soap->error;
09434 }
09435 else
09436 #endif
09437 if (soap_send(soap, " ") || soap_send(soap, tp->name))
09438 return soap->error;
09439 if (tp->visible == 2 && tp->value)
09440 if (soap_send_raw(soap, "=\"", 2)
09441 || soap_string_out(soap, tp->value, tp->flag)
09442 || soap_send_raw(soap, "\"", 1))
09443 return soap->error;
09444 tp->visible = 0;
09445 }
09446 }
09447 if (tag)
09448 {
09449 #ifndef WITH_LEAN
09450 if (soap->mode & SOAP_XML_CANONICAL)
09451 { if (soap_send_raw(soap, ">", 1)
09452 || soap_element_end_out(soap, tag))
09453 return soap->error;
09454 return SOAP_OK;
09455 }
09456 #endif
09457 soap->level--;
09458 return soap_send_raw(soap, "/>", 2);
09459 }
09460 return soap_send_raw(soap, ">", 1);
09461 }
09462 #endif
09463
09464
09465 #ifndef PALM_1
09466 SOAP_FMAC1
09467 int
09468 SOAP_FMAC2
09469 soap_element_end_out(struct soap *soap, const char *tag)
09470 {
09471 #ifndef WITH_LEAN
09472 const char *s;
09473 #endif
09474 if (*tag == '-')
09475 return SOAP_OK;
09476 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element ending tag='%s'\n", tag));
09477 #ifdef WITH_DOM
09478 if (soap->feltendout && (soap->error = soap->feltendout(soap, tag)))
09479 return soap->error;
09480 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
09481 { if (soap->dom->prnt)
09482 soap->dom = soap->dom->prnt;
09483 return SOAP_OK;
09484 }
09485 #endif
09486 #ifndef WITH_LEAN
09487 if (soap->mode & SOAP_XML_CANONICAL)
09488 soap_pop_namespace(soap);
09489 if (soap->mode & SOAP_XML_INDENT)
09490 { if (!soap->body)
09491 { if (soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1))
09492 return soap->error;
09493 }
09494 soap->body = 0;
09495 }
09496 if ((soap->mode & SOAP_XML_DEFAULTNS) && (s = strchr(tag, ':')))
09497 { soap_pop_namespace(soap);
09498 tag = s + 1;
09499 }
09500 #endif
09501 if (soap_send_raw(soap, "</", 2)
09502 || soap_send(soap, tag))
09503 return soap->error;
09504 soap->level--;
09505 return soap_send_raw(soap, ">", 1);
09506 }
09507 #endif
09508
09509
09510 #ifndef PALM_1
09511 SOAP_FMAC1
09512 int
09513 SOAP_FMAC2
09514 soap_element_ref(struct soap *soap, const char *tag, int id, int href)
09515 { register int n = 0;
09516 const char *s = "href";
09517 if (soap->version == 2)
09518 { s = "SOAP-ENC:ref";
09519 n = 1;
09520 }
09521 sprintf(soap->href, "#_%d", href);
09522 return soap_element_href(soap, tag, id, s, soap->href + n);
09523 }
09524 #endif
09525
09526
09527 #ifndef PALM_1
09528 SOAP_FMAC1
09529 int
09530 SOAP_FMAC2
09531 soap_element_href(struct soap *soap, const char *tag, int id, const char *ref, const char *val)
09532 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element '%s' reference %s='%s'\n", tag, ref, val));
09533 if (soap_element(soap, tag, id, NULL)
09534 || soap_attribute(soap, ref, val)
09535 || soap_element_start_end_out(soap, tag))
09536 return soap->error;
09537 return SOAP_OK;
09538 }
09539 #endif
09540
09541
09542 #ifndef PALM_1
09543 SOAP_FMAC1
09544 int
09545 SOAP_FMAC2
09546 soap_element_null(struct soap *soap, const char *tag, int id, const char *type)
09547 { struct soap_attribute *tp = NULL;
09548 for (tp = soap->attributes; tp; tp = tp->next)
09549 if (tp->visible)
09550 break;
09551 if (tp || (soap->version == 2 && soap->position > 0) || id > 0 || (soap->mode & SOAP_XML_NIL))
09552 { if (soap_element(soap, tag, id, type)
09553 || (!tp && soap_attribute(soap, "xsi:nil", "true")))
09554 return soap->error;
09555 return soap_element_start_end_out(soap, tag);
09556 }
09557 soap->null = 1;
09558 soap->position = 0;
09559 soap->mustUnderstand = 0;
09560 return SOAP_OK;
09561 }
09562 #endif
09563
09564
09565 #ifndef PALM_1
09566 SOAP_FMAC1
09567 int
09568 SOAP_FMAC2
09569 soap_element_nil(struct soap *soap, const char *tag)
09570 { if (soap_element(soap, tag, -1, NULL)
09571 || soap_attribute(soap, "xsi:nil", "true"))
09572 return soap->error;
09573 return soap_element_start_end_out(soap, tag);
09574 }
09575 #endif
09576
09577
09578 #ifndef PALM_1
09579 SOAP_FMAC1
09580 int
09581 SOAP_FMAC2
09582 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)
09583 { if (!p)
09584 { soap_element_null(soap, tag, id, type);
09585 return -1;
09586 }
09587 #ifndef WITH_NOIDREF
09588 if (soap->mode & SOAP_XML_TREE)
09589 return 0;
09590 if (id < 0)
09591 { struct soap_plist *pp;
09592 if (a)
09593 id = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
09594 else
09595 id = soap_pointer_lookup(soap, p, t, &pp);
09596 if (id)
09597 { if (soap_is_embedded(soap, pp))
09598 { soap_element_ref(soap, tag, 0, id);
09599 return -1;
09600 }
09601 if (soap_is_single(soap, pp))
09602 return 0;
09603 soap_set_embedded(soap, pp);
09604 }
09605 }
09606 return id;
09607 #else
09608 return 0;
09609 #endif
09610 }
09611 #endif
09612
09613
09614 #ifndef PALM_1
09615 SOAP_FMAC1
09616 int
09617 SOAP_FMAC2
09618 soap_element_result(struct soap *soap, const char *tag)
09619 { if (soap->version == 2 && soap->encodingStyle)
09620 { if (soap_element(soap, "SOAP-RPC:result", 0, NULL)
09621 || soap_attribute(soap, "xmlns:SOAP-RPC", soap_rpc)
09622 || soap_element_start_end_out(soap, NULL)
09623 || soap_string_out(soap, tag, 0)
09624 || soap_element_end_out(soap, "SOAP-RPC:result"))
09625 return soap->error;
09626 }
09627 return SOAP_OK;
09628 }
09629 #endif
09630
09631
09632 #ifndef PALM_1
09633 SOAP_FMAC1
09634 void
09635 SOAP_FMAC2
09636 soap_check_result(struct soap *soap, const char *tag)
09637 { if (soap->version == 2 && soap->encodingStyle)
09638 { soap_instring(soap, ":result", NULL, NULL, 0, 2, -1, -1);
09639
09640 }
09641 }
09642 #endif
09643
09644
09645 #ifndef PALM_2
09646 SOAP_FMAC1
09647 int
09648 SOAP_FMAC2
09649 soap_attribute(struct soap *soap, const char *name, const char *value)
09650 {
09651 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attribute '%s'='%s'\n", name, value));
09652 #ifdef WITH_DOM
09653 if ((soap->mode & SOAP_XML_DOM) && !(soap->mode & SOAP_XML_CANONICAL) && soap->dom)
09654 { register struct soap_dom_attribute *a = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
09655 if (!a)
09656 return soap->error;
09657 a->next = soap->dom->atts;
09658 a->nstr = NULL;
09659 a->name = soap_strdup(soap, name);
09660 a->data = soap_strdup(soap, value);
09661 a->wide = NULL;
09662 a->soap = soap;
09663 soap->dom->atts = a;
09664 return SOAP_OK;
09665 }
09666 #endif
09667 #ifndef WITH_LEAN
09668 if (soap->mode & SOAP_XML_CANONICAL)
09669 {
09670
09671
09672
09673
09674
09675
09676
09677 if (!strncmp(name, "xmlns:", 6))
09678 soap_push_ns(soap, name + 6, value, 0);
09679 else if (soap_set_attr(soap, name, value, 1))
09680 return soap->error;
09681 }
09682 else
09683 #endif
09684 { if (soap_send(soap, " ") || soap_send(soap, name))
09685 return soap->error;
09686 if (value)
09687 if (soap_send_raw(soap, "=\"", 2)
09688 || soap_string_out(soap, value, 1)
09689 || soap_send_raw(soap, "\"", 1))
09690 return soap->error;
09691 }
09692 return SOAP_OK;
09693 }
09694 #endif
09695
09696
09697 #ifndef PALM_2
09698 SOAP_FMAC1
09699 int
09700 SOAP_FMAC2
09701 soap_element_begin_in(struct soap *soap, const char *tag, int nillable, const char *type)
09702 { if (!soap_peek_element(soap))
09703 { if (soap->other)
09704 return soap->error = SOAP_TAG_MISMATCH;
09705 if (tag && *tag == '-')
09706 return SOAP_OK;
09707 if (!(soap->error = soap_match_tag(soap, soap->tag, tag)))
09708 { soap->peeked = 0;
09709 if (type && *soap->type && soap_match_tag(soap, soap->type, type))
09710 return soap->error = SOAP_TYPE;
09711 if (!nillable && soap->null && (soap->mode & SOAP_XML_STRICT))
09712 return soap->error = SOAP_NULL;
09713 if (soap->body)
09714 soap->level++;
09715 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:SOAP_STR_EOS ));
09716 }
09717 }
09718 else if (soap->error == SOAP_NO_TAG && tag && *tag == '-')
09719 soap->error = SOAP_OK;
09720 return soap->error;
09721 }
09722 #endif
09723
09724
09725 #ifndef PALM_2
09726 SOAP_FMAC1
09727 int
09728 SOAP_FMAC2
09729 soap_element_end_in(struct soap *soap, const char *tag)
09730 { register soap_wchar c;
09731 register char *s;
09732 register int n = 0;
09733 if (tag && *tag == '-')
09734 return SOAP_OK;
09735 if (soap->error == SOAP_NO_TAG)
09736 soap->error = SOAP_OK;
09737 #ifdef WITH_DOM
09738
09739 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
09740 { if (!soap->peeked && !soap_string_in(soap, 3, -1, -1))
09741 return soap->error;
09742 if (soap->dom->prnt)
09743 soap->dom = soap->dom->prnt;
09744 }
09745 #endif
09746 if (soap->peeked)
09747 { if (*soap->tag)
09748 n++;
09749 soap->peeked = 0;
09750 }
09751 do
09752 { while (((c = soap_get(soap)) != SOAP_TT))
09753 { if ((int)c == EOF)
09754 return soap->error = SOAP_EOF;
09755 if (c == SOAP_LT)
09756 n++;
09757 else if (c == '/')
09758 { c = soap_get(soap);
09759 if (c == SOAP_GT)
09760 n--;
09761 else
09762 soap_unget(soap, c);
09763 }
09764 }
09765 } while (n--);
09766 s = soap->tag;
09767 n = sizeof(soap->tag);
09768 while (soap_notblank(c = soap_get(soap)))
09769 { if (--n > 0)
09770 *s++ = (char)c;
09771 }
09772 *s = '\0';
09773 if ((int)c == EOF)
09774 return soap->error = SOAP_EOF;
09775 while (soap_blank(c))
09776 c = soap_get(soap);
09777 if (c != SOAP_GT)
09778 return soap->error = SOAP_SYNTAX_ERROR;
09779 #ifndef WITH_LEAN
09780 #ifdef WITH_DOM
09781 if (soap->feltendin)
09782 { soap->level--;
09783 return soap->error = soap->feltendin(soap, soap->tag, tag);
09784 }
09785 #endif
09786 if (tag && (soap->mode & SOAP_XML_STRICT))
09787 { soap_pop_namespace(soap);
09788 if (soap_match_tag(soap, soap->tag, tag))
09789 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element tag '%s' does not match '%s'\n", soap->tag, tag?tag:SOAP_STR_EOS));
09790 return soap->error = SOAP_SYNTAX_ERROR;
09791 }
09792 }
09793 #endif
09794 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:SOAP_STR_EOS));
09795 soap->level--;
09796 return SOAP_OK;
09797 }
09798 #endif
09799
09800
09801 #ifndef PALM_2
09802 SOAP_FMAC1
09803 const char *
09804 SOAP_FMAC2
09805 soap_attr_value(struct soap *soap, const char *name, int flag)
09806 { register struct soap_attribute *tp;
09807 if (*name == '-')
09808 return SOAP_STR_EOS;
09809 for (tp = soap->attributes; tp; tp = tp->next)
09810 { if (tp->visible && !soap_match_tag(soap, tp->name, name))
09811 break;
09812 }
09813 if (tp)
09814 { if (flag == 2 && (soap->mode & SOAP_XML_STRICT))
09815 soap->error = SOAP_PROHIBITED;
09816 else
09817 return tp->value;
09818 }
09819 else if (flag == 1 && (soap->mode & SOAP_XML_STRICT))
09820 soap->error = SOAP_REQUIRED;
09821 else
09822 soap->error = SOAP_OK;
09823 return NULL;
09824 }
09825 #endif
09826
09827
09828 #ifndef PALM_2
09829 SOAP_FMAC1
09830 int
09831 SOAP_FMAC2
09832 soap_set_attr(struct soap *soap, const char *name, const char *value, int flag)
09833 { register struct soap_attribute *tp;
09834 if (*name == '-')
09835 return SOAP_OK;
09836 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set attribute %s='%s'\n", name, value?value:SOAP_STR_EOS));
09837 for (tp = soap->attributes; tp; tp = tp->next)
09838 { if (!strcmp(tp->name, name))
09839 break;
09840 }
09841 if (!tp)
09842 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute %s\n", name));
09843 if (!(tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(name))))
09844 return soap->error = SOAP_EOM;
09845 tp->ns = NULL;
09846 #ifndef WITH_LEAN
09847 if ((soap->mode & SOAP_XML_CANONICAL))
09848 { struct soap_attribute **tpp = &soap->attributes;
09849 const char *s = strchr(name, ':');
09850 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inserting attribute %s for c14n\n", name))
09851 if (!strncmp(name, "xmlns", 5))
09852 { for (; *tpp; tpp = &(*tpp)->next)
09853 if (strncmp((*tpp)->name, "xmlns", 5) || strcmp((*tpp)->name + 5, name + 5) > 0)
09854 break;
09855 }
09856 else if (!s)
09857 { for (; *tpp; tpp = &(*tpp)->next)
09858 if (strncmp((*tpp)->name, "xmlns", 5) && ((*tpp)->ns || strcmp((*tpp)->name, name) > 0))
09859 break;
09860 }
09861 else
09862 { struct soap_nlist *np = soap_lookup_ns(soap, name, s - name);
09863 if (np)
09864 tp->ns = np->ns;
09865 else
09866 { struct soap_attribute *tq;
09867 for (tq = soap->attributes; tq; tq = tq->next)
09868 { if (!strncmp(tq->name, "xmlns:", 6) && !strncmp(tq->name + 6, name, s - name) && !tq->name[6 + s - name])
09869 { tp->ns = tq->ns;
09870 break;
09871 }
09872 }
09873 }
09874 for (; *tpp; tpp = &(*tpp)->next)
09875 { int k;
09876 if (strncmp((*tpp)->name, "xmlns", 5) && (*tpp)->ns && tp->ns && ((k = strcmp((*tpp)->ns, tp->ns)) > 0 || (!k && strcmp((*tpp)->name, name) > 0)))
09877 break;
09878 }
09879 }
09880 tp->next = *tpp;
09881 *tpp = tp;
09882 }
09883 else
09884 #endif
09885 { tp->next = soap->attributes;
09886 soap->attributes = tp;
09887 }
09888 strcpy(tp->name, name);
09889 tp->value = NULL;
09890 }
09891 else if (tp->visible)
09892 { return SOAP_OK;
09893 }
09894 else if (value && tp->value && tp->size <= strlen(value))
09895 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute value of %s (free %p)\n", name, tp->value));
09896 SOAP_FREE(soap, tp->value);
09897 tp->value = NULL;
09898 tp->ns = NULL;
09899 }
09900 if (value)
09901 { if (!tp->value)
09902 { tp->size = strlen(value) + 1;
09903 if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size)))
09904 return soap->error = SOAP_EOM;
09905 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute value for %s (%p)\n", tp->name, tp->value));
09906 }
09907 strcpy(tp->value, value);
09908 if (!strncmp(tp->name, "xmlns:", 6))
09909 tp->ns = tp->value;
09910 tp->visible = 2;
09911 tp->flag = flag;
09912 #ifndef WITH_LEAN
09913 if (soap->event != SOAP_SEC_SIGN && !strcmp(name, "wsu:Id"))
09914 { soap->event = SOAP_SEC_BEGIN;
09915 strncpy(soap->id, value, sizeof(soap->id));
09916 soap->id[sizeof(soap->id)-1] = '\0';
09917 }
09918 #endif
09919 }
09920 else
09921 tp->visible = 1;
09922 return SOAP_OK;
09923 }
09924 #endif
09925
09926
09927 #ifndef PALM_2
09928 SOAP_FMAC1
09929 void
09930 SOAP_FMAC2
09931 soap_clr_attr(struct soap *soap)
09932 { register struct soap_attribute *tp;
09933 #ifndef WITH_LEAN
09934 if ((soap->mode & SOAP_XML_CANONICAL))
09935 { while (soap->attributes)
09936 { tp = soap->attributes->next;
09937 if (soap->attributes->value)
09938 SOAP_FREE(soap, soap->attributes->value);
09939 SOAP_FREE(soap, soap->attributes);
09940 soap->attributes = tp;
09941 }
09942 }
09943 else
09944 #endif
09945 { for (tp = soap->attributes; tp; tp = tp->next)
09946 tp->visible = 0;
09947 }
09948 }
09949 #endif
09950
09951
09952 #ifndef PALM_2
09953 static int
09954 soap_getattrval(struct soap *soap, char *s, size_t n, soap_wchar d)
09955 { register size_t i;
09956 for (i = 0; i < n; i++)
09957 { register soap_wchar c = soap_get(soap);
09958 switch (c)
09959 {
09960 case SOAP_TT:
09961 *s++ = '<';
09962 soap_unget(soap, '/');
09963 break;
09964 case SOAP_LT:
09965 *s++ = '<';
09966 break;
09967 case SOAP_GT:
09968 if (d == ' ')
09969 { soap_unget(soap, c);
09970 *s = '\0';
09971 return SOAP_OK;
09972 }
09973 *s++ = '>';
09974 break;
09975 case SOAP_QT:
09976 if (c == d)
09977 { *s = '\0';
09978 return SOAP_OK;
09979 }
09980 *s++ = '"';
09981 break;
09982 case SOAP_AP:
09983 if (c == d)
09984 { *s = '\0';
09985 return SOAP_OK;
09986 }
09987 *s++ = '\'';
09988 break;
09989 case '\t':
09990 case '\n':
09991 case '\r':
09992 case ' ':
09993 case '/':
09994 if (d == ' ')
09995 { soap_unget(soap, c);
09996 *s = '\0';
09997 return SOAP_OK;
09998 }
09999 default:
10000 if ((int)c == EOF)
10001 return soap->error = SOAP_EOF;
10002 *s++ = (char)c;
10003 }
10004 }
10005 return soap->error = SOAP_EOM;
10006 }
10007 #endif
10008
10009
10010 #ifdef WITH_FAST
10011 #ifndef PALM_2
10012 SOAP_FMAC1
10013 int
10014 SOAP_FMAC2
10015 soap_store_lab(struct soap *soap, const char *s, size_t n)
10016 { soap->labidx = 0;
10017 return soap_append_lab(soap, s, n);
10018 }
10019 #endif
10020 #endif
10021
10022
10023 #ifdef WITH_FAST
10024 #ifndef PALM_2
10025 SOAP_FMAC1
10026 int
10027 SOAP_FMAC2
10028 soap_append_lab(struct soap *soap, const char *s, size_t n)
10029 { if (soap->labidx + n >= soap->lablen)
10030 { register char *t = soap->labbuf;
10031 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enlarging look-aside buffer to append data, old size=%lu", (unsigned long)soap->lablen));
10032 if (soap->lablen == 0)
10033 soap->lablen = SOAP_LABLEN;
10034 while (soap->labidx + n >= soap->lablen)
10035 soap->lablen <<= 1;
10036 DBGLOG(TEST, SOAP_MESSAGE(fdebug, ", new size=%lu\n", (unsigned long)soap->lablen));
10037 soap->labbuf = (char*)SOAP_MALLOC(soap, soap->lablen);
10038 if (!soap->labbuf)
10039 { if (t)
10040 SOAP_FREE(soap, t);
10041 return soap->error = SOAP_EOM;
10042 }
10043 if (t)
10044 { memcpy(soap->labbuf, t, soap->labidx);
10045 SOAP_FREE(soap, t);
10046 }
10047 }
10048 if (s)
10049 { memcpy(soap->labbuf + soap->labidx, s, n);
10050 soap->labidx += n;
10051 }
10052 return SOAP_OK;
10053 }
10054 #endif
10055 #endif
10056
10057
10058 #ifndef PALM_2
10059 SOAP_FMAC1
10060 int
10061 SOAP_FMAC2
10062 soap_peek_element(struct soap *soap)
10063 {
10064 #ifdef WITH_DOM
10065 register struct soap_dom_attribute **att = NULL;
10066 register char *lead = NULL;
10067 #endif
10068 register struct soap_attribute *tp, *tq = NULL;
10069 register const char *t;
10070 register char *s;
10071 register soap_wchar c;
10072 register int i;
10073 if (soap->peeked)
10074 { if (!*soap->tag)
10075 return soap->error = SOAP_NO_TAG;
10076 return SOAP_OK;
10077 }
10078 soap->peeked = 1;
10079 soap->id[0] = '\0';
10080 soap->href[0] = '\0';
10081 soap->type[0] = '\0';
10082 soap->arrayType[0] = '\0';
10083 soap->arraySize[0] = '\0';
10084 soap->arrayOffset[0] = '\0';
10085 soap->other = 0;
10086 soap->root = -1;
10087 soap->position = 0;
10088 soap->null = 0;
10089 soap->mustUnderstand = 0;
10090
10091 if ((c = soap_getchar(soap)) == 0xEF && (c = soap_get1(soap)) == 0xBB && (c = soap_get1(soap)) == 0xBF)
10092 soap->mode &= ~SOAP_ENC_LATIN;
10093 else
10094 {
10095 if ((c == 0xFE && soap_get0(soap) == 0xFF)
10096 || (c == 0xFF && soap_get0(soap) == 0xFE))
10097 return soap->error = SOAP_UTF_ERROR;
10098 soap_unget(soap, c);
10099 }
10100 c = soap_get(soap);
10101 #ifdef WITH_DOM
10102
10103 if (soap_blank(c))
10104 { soap->labidx = 0;
10105 do
10106 { if (soap_append_lab(soap, NULL, 0))
10107 return soap->error;
10108 s = soap->labbuf + soap->labidx;
10109 i = soap->lablen - soap->labidx;
10110 soap->labidx = soap->lablen;
10111 while (soap_blank(c) && i--)
10112 { *s++ = c;
10113 c = soap_get(soap);
10114 }
10115 }
10116 while (soap_blank(c));
10117 *s = '\0';
10118 lead = soap->labbuf;
10119 }
10120 #else
10121
10122 while (soap_blank(c))
10123 c = soap_get(soap);
10124 #endif
10125 if (c != SOAP_LT)
10126 { *soap->tag = '\0';
10127 if ((int)c == EOF)
10128 return soap->error = SOAP_EOF;
10129 soap_unget(soap, c > 0 ? c | 0x80000000 : c);
10130 #ifdef WITH_DOM
10131
10132 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
10133 { if (lead && *lead)
10134 soap->dom->tail = soap_strdup(soap, lead);
10135 else
10136 soap->dom->tail = (char*)SOAP_STR_EOS;
10137 }
10138 #endif
10139 return soap->error = SOAP_NO_TAG;
10140 }
10141 s = soap->tag;
10142 do c = soap_get1(soap);
10143 while (soap_blank(c));
10144 i = sizeof(soap->tag);
10145 while (c != '>' && c != '/' && soap_notblank(c) && (int)c != EOF)
10146 { if (--i > 0)
10147 *s++ = (char)c;
10148 c = soap_get1(soap);
10149 }
10150 while (soap_blank(c))
10151 c = soap_get1(soap);
10152 *s = '\0';
10153 #ifdef WITH_DOM
10154 if (soap->mode & SOAP_XML_DOM)
10155 { register struct soap_dom_element *elt;
10156 elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element));
10157 if (!elt)
10158 return soap->error;
10159 elt->next = NULL;
10160 elt->nstr = NULL;
10161 elt->name = soap_strdup(soap, soap->tag);
10162 elt->prnt = soap->dom;
10163 elt->elts = NULL;
10164 elt->atts = NULL;
10165 elt->data = NULL;
10166 elt->wide = NULL;
10167 elt->type = 0;
10168 elt->node = NULL;
10169 elt->head = soap_strdup(soap, lead);
10170 elt->tail = NULL;
10171 elt->soap = soap;
10172 if (soap->dom)
10173 { struct soap_dom_element *p = soap->dom->elts;
10174 if (p)
10175 { while (p->next)
10176 p = p->next;
10177 p->next = elt;
10178 }
10179 else
10180 soap->dom->elts = elt;
10181 }
10182 soap->dom = elt;
10183 att = &elt->atts;
10184 }
10185 #endif
10186 soap_pop_namespace(soap);
10187 for (tp = soap->attributes; tp; tp = tp->next)
10188 tp->visible = 0;
10189 while ((int)c != EOF && c != '>' && c != '/')
10190 { s = soap->tmpbuf;
10191 i = sizeof(soap->tmpbuf);
10192 while (c != '=' && c != '>' && c != '/' && soap_notblank(c) && (int)c != EOF)
10193 { if (--i > 0)
10194 *s++ = (char)c;
10195 c = soap_get1(soap);
10196 }
10197 *s = '\0';
10198 if (i == sizeof(soap->tmpbuf))
10199 return soap->error = SOAP_SYNTAX_ERROR;
10200 #ifdef WITH_DOM
10201
10202 if (att)
10203 { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
10204 if (!*att)
10205 return soap->error;
10206 (*att)->next = NULL;
10207 (*att)->nstr = NULL;
10208 (*att)->name = soap_strdup(soap, soap->tmpbuf);
10209 (*att)->data = NULL;
10210 (*att)->wide = NULL;
10211 (*att)->soap = soap;
10212 }
10213 #endif
10214 if (!strncmp(soap->tmpbuf, "xmlns", 5))
10215 { if (soap->tmpbuf[5] == ':')
10216 t = soap->tmpbuf + 6;
10217 else if (soap->tmpbuf[5])
10218 t = NULL;
10219 else
10220 t = SOAP_STR_EOS;
10221 }
10222 else
10223 t = NULL;
10224 tq = NULL;
10225 for (tp = soap->attributes; tp; tq = tp, tp = tp->next)
10226 { if (!SOAP_STRCMP(tp->name, soap->tmpbuf))
10227 break;
10228 }
10229 if (!tp)
10230 { tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(soap->tmpbuf));
10231 if (!tp)
10232 return soap->error = SOAP_EOM;
10233 strcpy(tp->name, soap->tmpbuf);
10234 tp->value = NULL;
10235 tp->size = 0;
10236 tp->ns = NULL;
10237
10238 if (tq && strchr(soap->tmpbuf, ':'))
10239 { tq->next = tp;
10240 tp->next = NULL;
10241 }
10242 else
10243 { tp->next = soap->attributes;
10244 soap->attributes = tp;
10245 }
10246 }
10247 while (soap_blank(c))
10248 c = soap_get1(soap);
10249 if (c == '=')
10250 { do c = soap_getutf8(soap);
10251 while (soap_blank(c));
10252 if (c != SOAP_QT && c != SOAP_AP)
10253 { soap_unget(soap, c);
10254 c = ' ';
10255 }
10256 if (soap_getattrval(soap, tp->value, tp->size, c))
10257 {
10258 #ifdef WITH_FAST
10259 if (soap->error != SOAP_EOM)
10260 return soap->error;
10261 soap->error = SOAP_OK;
10262 if (soap_store_lab(soap, tp->value, tp->size))
10263 return soap->error;
10264 if (tp->value)
10265 SOAP_FREE(soap, tp->value);
10266 for (;;)
10267 { if (soap_getattrval(soap, soap->labbuf + soap->labidx, soap->lablen - soap->labidx, c))
10268 { if (soap->error != SOAP_EOM)
10269 return soap->error;
10270 soap->error = SOAP_OK;
10271 soap->labidx = soap->lablen;
10272 if (soap_append_lab(soap, NULL, 0))
10273 return soap->error;
10274 }
10275 else
10276 break;
10277 }
10278 if (soap->labidx)
10279 tp->size = soap->lablen;
10280 else
10281 { tp->size = strlen(soap->labbuf) + 1;
10282 if (tp->size < SOAP_LABLEN)
10283 tp->size = SOAP_LABLEN;
10284 }
10285 if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size)))
10286 return soap->error = SOAP_EOM;
10287 strcpy(tp->value, soap->labbuf);
10288 #else
10289 size_t n;
10290 if (soap->error != SOAP_EOM)
10291 return soap->error;
10292 soap->error = SOAP_OK;
10293 if (soap_new_block(soap) == NULL)
10294 return soap->error;
10295 for (;;)
10296 { if (!(s = (char*)soap_push_block(soap, NULL, SOAP_BLKLEN)))
10297 return soap->error;
10298 if (soap_getattrval(soap, s, SOAP_BLKLEN, c))
10299 { if (soap->error != SOAP_EOM)
10300 return soap->error;
10301 soap->error = SOAP_OK;
10302 }
10303 else
10304 break;
10305 }
10306 n = tp->size + soap->blist->size;
10307 if (!(s = (char*)SOAP_MALLOC(soap, n)))
10308 return soap->error = SOAP_EOM;
10309 if (tp->value)
10310 { memcpy(s, tp->value, tp->size);
10311 SOAP_FREE(soap, tp->value);
10312 }
10313 soap_save_block(soap, NULL, s + tp->size, 0);
10314 tp->value = s;
10315 tp->size = n;
10316 #endif
10317 }
10318 do c = soap_get1(soap);
10319 while (soap_blank(c));
10320 tp->visible = 2;
10321 #ifdef WITH_DOM
10322 if (att)
10323 (*att)->data = soap_strdup(soap, tp->value);
10324 #endif
10325 }
10326 else
10327 tp->visible = 1;
10328 #ifdef WITH_DOM
10329 if (att)
10330 att = &(*att)->next;
10331 #endif
10332 if (t && tp->value)
10333 { if (soap_push_namespace(soap, t, tp->value) == NULL)
10334 return soap->error;
10335 }
10336 }
10337 #ifdef WITH_DOM
10338 if (att)
10339 { soap->dom->nstr = soap_current_namespace(soap, soap->tag);
10340 for (att = &soap->dom->atts; *att; att = &(*att)->next)
10341 (*att)->nstr = soap_current_namespace(soap, (*att)->name);
10342 }
10343 #endif
10344 if ((int)c == EOF)
10345 return soap->error = SOAP_EOF;
10346 if (!(soap->body = (c != '/')))
10347 do c = soap_get1(soap);
10348 while (soap_blank(c));
10349 #ifdef WITH_DOM
10350 if (soap->mode & SOAP_XML_DOM)
10351 { if (!soap->body && soap->dom->prnt)
10352 soap->dom = soap->dom->prnt;
10353 }
10354 if (soap->feltbegin)
10355 return soap->error = soap->feltbegin(soap, soap->tag);
10356 #endif
10357 for (tp = soap->attributes; tp; tp = tp->next)
10358 { if (tp->visible && tp->value)
10359 {
10360 #ifndef WITH_NOIDREF
10361 if (!strcmp(tp->name, "id"))
10362 { if ((soap->version > 0 && !(soap->mode & SOAP_XML_TREE))
10363 || (soap->mode & SOAP_XML_GRAPH))
10364 { *soap->id = '#';
10365 strncpy(soap->id + 1, tp->value, sizeof(soap->id) - 2);
10366 soap->id[sizeof(soap->id)-1] = '\0';
10367 }
10368 }
10369 else if (!strcmp(tp->name, "href"))
10370 { if (soap->version == 1
10371 || (soap->mode & SOAP_XML_GRAPH)
10372 || (soap->mode & SOAP_ENC_MTOM)
10373 || (soap->mode & SOAP_ENC_DIME))
10374 { strncpy(soap->href, tp->value, sizeof(soap->href) - 1);
10375 soap->href[sizeof(soap->href)-1] = '\0';
10376 }
10377 }
10378 else
10379 #endif
10380 if (!soap_match_tag(soap, tp->name, "xsi:type"))
10381 { strncpy(soap->type, tp->value, sizeof(soap->type) - 1);
10382 soap->type[sizeof(soap->type)-1] = '\0';
10383 }
10384 else if ((!soap_match_tag(soap, tp->name, "xsi:null")
10385 || !soap_match_tag(soap, tp->name, "xsi:nil"))
10386 && (!strcmp(tp->value, "1")
10387 || !strcmp(tp->value, "true")))
10388 { soap->null = 1;
10389 }
10390 else if (soap->version == 1)
10391 { if (!soap_match_tag(soap, tp->name, "SOAP-ENC:arrayType"))
10392 { s = soap_strrchr(tp->value, '[');
10393 if (s && (size_t)(s - tp->value) < sizeof(soap->arrayType))
10394 { strncpy(soap->arrayType, tp->value, s - tp->value);
10395 soap->arrayType[s - tp->value] = '\0';
10396 strncpy(soap->arraySize, s, sizeof(soap->arraySize) - 1);
10397 }
10398 else
10399 strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1);
10400 soap->arraySize[sizeof(soap->arrayType)-1] = '\0';
10401 soap->arrayType[sizeof(soap->arrayType)-1] = '\0';
10402 }
10403 else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:offset"))
10404 strncpy(soap->arrayOffset, tp->value, sizeof(soap->arrayOffset));
10405 else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:position"))
10406 soap->position = soap_getposition(tp->value, soap->positions);
10407 else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:root"))
10408 soap->root = ((!strcmp(tp->value, "1") || !strcmp(tp->value, "true")));
10409 else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand")
10410 && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true")))
10411 soap->mustUnderstand = 1;
10412 else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:actor"))
10413 { if ((!soap->actor || strcmp(soap->actor, tp->value))
10414 && strcmp(tp->value, "http://schemas.xmlsoap.org/soap/actor/next"))
10415 soap->other = 1;
10416 }
10417 }
10418 else if (soap->version == 2)
10419 {
10420 #ifndef WITH_NOIDREF
10421 if (!strcmp(tp->name, "ref")
10422 || !soap_match_tag(soap, tp->name, "SOAP-ENC:ref"))
10423 { *soap->href = '#';
10424 strncpy(soap->href + 1, tp->value, sizeof(soap->href) - 2);
10425 soap->href[sizeof(soap->href)-1] = '\0';
10426 }
10427 else
10428 #endif
10429 if (!soap_match_tag(soap, tp->name, "SOAP-ENC:itemType"))
10430 strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1);
10431 else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:arraySize"))
10432 strncpy(soap->arraySize, tp->value, sizeof(soap->arraySize) - 1);
10433 else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand")
10434 && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true")))
10435 soap->mustUnderstand = 1;
10436 else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:role"))
10437 { if ((!soap->actor || strcmp(soap->actor, tp->value))
10438 && strcmp(tp->value, "http://www.w3.org/2003/05/soap-envelope/role/next"))
10439 soap->other = 1;
10440 }
10441 }
10442 else
10443 { if (!soap_match_tag(soap, tp->name, "wsdl:required") && !strcmp(tp->value, "true"))
10444 soap->mustUnderstand = 1;
10445 }
10446 }
10447 }
10448 return soap->error = SOAP_OK;
10449 }
10450 #endif
10451
10452
10453 #ifndef PALM_2
10454 SOAP_FMAC1
10455 void
10456 SOAP_FMAC2
10457 soap_retry(struct soap *soap)
10458 { soap->error = SOAP_OK;
10459 soap_revert(soap);
10460 }
10461 #endif
10462
10463
10464 #ifndef PALM_2
10465 SOAP_FMAC1
10466 void
10467 SOAP_FMAC2
10468 soap_revert(struct soap *soap)
10469 { if (!soap->peeked)
10470 { soap->peeked = 1;
10471 if (soap->body)
10472 soap->level--;
10473 }
10474 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reverting to last element '%s' (level=%u)\n", soap->tag, soap->level));
10475 }
10476 #endif
10477
10478
10479 #ifndef PALM_2
10480 SOAP_FMAC1
10481 int
10482 SOAP_FMAC2
10483 soap_string_out(struct soap *soap, const char *s, int flag)
10484 { register const char *t;
10485 register soap_wchar c;
10486 register soap_wchar mask = (soap_wchar)0xFFFFFF80UL;
10487 #ifdef WITH_DOM
10488 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
10489 { soap->dom->data = soap_strdup(soap, s);
10490 return SOAP_OK;
10491 }
10492 #endif
10493 if (flag == 2 || soap->mode & SOAP_C_UTFSTRING)
10494 mask = 0;
10495 t = s;
10496 while ((c = *t++))
10497 { switch (c)
10498 {
10499 case 0x09:
10500 if (flag)
10501 { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "	", 5))
10502 return soap->error;
10503 s = t;
10504 }
10505 break;
10506 case 0x0A:
10507 if (flag || !(soap->mode & SOAP_XML_CANONICAL))
10508 { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "
", 5))
10509 return soap->error;
10510 s = t;
10511 }
10512 break;
10513 case 0x0D:
10514 if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "
", 5))
10515 return soap->error;
10516 s = t;
10517 break;
10518 case '&':
10519 if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&", 5))
10520 return soap->error;
10521 s = t;
10522 break;
10523 case '<':
10524 if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "<", 4))
10525 return soap->error;
10526 s = t;
10527 break;
10528 case '>':
10529 if (!flag)
10530 { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, ">", 4))
10531 return soap->error;
10532 s = t;
10533 }
10534 break;
10535 case '"':
10536 if (flag)
10537 { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, """, 6))
10538 return soap->error;
10539 s = t;
10540 }
10541 break;
10542 default:
10543 #ifndef WITH_LEANER
10544 #ifdef HAVE_MBTOWC
10545 if (soap->mode & SOAP_C_MBSTRING)
10546 { wchar_t wc;
10547 register int m = mbtowc(&wc, t - 1, MB_CUR_MAX);
10548 if (m > 0 && !((soap_wchar)wc == c && m == 1 && c < 0x80))
10549 { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, wc))
10550 return soap->error;
10551 s = t += m - 1;
10552 continue;
10553 }
10554 }
10555 #endif
10556 #endif
10557 #ifndef WITH_NOSTRINGTOUTF8
10558 if ((c & mask) || !(c & 0xFFFFFFE0UL))
10559 { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned char)c))
10560 return soap->error;
10561 s = t;
10562 }
10563 #endif
10564 }
10565 }
10566 return soap_send_raw(soap, s, t - s - 1);
10567 }
10568 #endif
10569
10570
10571 #ifndef PALM_2
10572 SOAP_FMAC1
10573 char *
10574 SOAP_FMAC2
10575 soap_string_in(struct soap *soap, int flag, long minlen, long maxlen)
10576 { register char *s;
10577 char *t = NULL;
10578 register size_t i;
10579 register long l = 0;
10580 register int n = 0, f = 0, m = 0;
10581 register soap_wchar c;
10582 #if !defined(WITH_LEANER) && defined(HAVE_WCTOMB)
10583 char buf[MB_LEN_MAX > 8 ? MB_LEN_MAX : 8];
10584 #else
10585 char buf[8];
10586 #endif
10587 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading string content, flag=%d\n", flag));
10588 if (soap->peeked && *soap->tag)
10589 {
10590 #ifndef WITH_LEAN
10591 struct soap_attribute *tp;
10592 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String content includes tag '%s' and attributes\n", soap->tag));
10593 t = soap->tmpbuf;
10594 *t = '<';
10595 t[sizeof(soap->tmpbuf)-1] = '\0';
10596 strncpy(t + 1, soap->tag, sizeof(soap->tmpbuf) - 2);
10597 t += strlen(t);
10598 for (tp = soap->attributes; tp; tp = tp->next)
10599 { if (tp->visible)
10600 { if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2)
10601 break;
10602 *t++ = ' ';
10603 strcpy(t, tp->name);
10604 t += strlen(t);
10605 if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2)
10606 break;
10607 if (tp->value)
10608 { *t++ = '=';
10609 *t++ = '"';
10610 strcpy(t, tp->value);
10611 t += strlen(t);
10612 *t++ = '"';
10613 }
10614 }
10615 }
10616 if (!soap->body)
10617 *t++ = '/';
10618 *t++ = '>';
10619 *t = '\0';
10620 t = soap->tmpbuf;
10621 m = (int)strlen(soap->tmpbuf);
10622 #endif
10623 if (soap->body)
10624 n = 1;
10625 f = 1;
10626 soap->peeked = 0;
10627 }
10628 #ifdef WITH_CDATA
10629 if (!flag)
10630 { register int state = 0;
10631 #ifdef WITH_FAST
10632 soap->labidx = 0;
10633 #else
10634 if (soap_new_block(soap) == NULL)
10635 return NULL;
10636 #endif
10637 for (;;)
10638 {
10639 #ifdef WITH_FAST
10640 register size_t k;
10641 if (soap_append_lab(soap, NULL, 0))
10642 return NULL;
10643 s = soap->labbuf + soap->labidx;
10644 k = soap->lablen - soap->labidx;
10645 soap->labidx = soap->lablen;
10646 #else
10647 register size_t k = SOAP_BLKLEN;
10648 if (!(s = (char*)soap_push_block(soap, NULL, k)))
10649 return NULL;
10650 #endif
10651 for (i = 0; i < k; i++)
10652 { if (m > 0)
10653 { *s++ = *t++;
10654 m--;
10655 continue;
10656 }
10657 c = soap_getchar(soap);
10658 if ((int)c == EOF)
10659 goto end;
10660 if ((c >= 0x80 || c < SOAP_AP) && state != 1 && !(soap->mode & SOAP_ENC_LATIN))
10661 { if (c >= 0x80)
10662 { soap_unget(soap, c);
10663 c = soap_getutf8(soap);
10664 }
10665 if (soap->mode & SOAP_C_UTFSTRING)
10666 { c &= 0x7FFFFFFF;
10667 t = buf;
10668 if (c < 0x0800)
10669 *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
10670 else
10671 { if (c < 0x010000)
10672 *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
10673 else
10674 { if (c < 0x200000)
10675 *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
10676 else
10677 { if (c < 0x04000000)
10678 *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
10679 else
10680 { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
10681 *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
10682 }
10683 *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
10684 }
10685 *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
10686 }
10687 *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
10688 }
10689 *t++ = (char)(0x80 | (c & 0x3F));
10690 m = (int)(t - buf) - 1;
10691 t = buf;
10692 *s++ = *t++;
10693 continue;
10694 }
10695 }
10696 switch (state)
10697 { case 1:
10698 if (c == ']')
10699 state = 4;
10700 *s++ = c;
10701 continue;
10702 case 2:
10703 if (c == '-')
10704 state = 6;
10705 *s++ = c;
10706 continue;
10707 case 3:
10708 if (c == '?')
10709 state = 8;
10710 *s++ = c;
10711 continue;
10712
10713 case 4:
10714 if (c == ']')
10715 state = 5;
10716 else
10717 state = 1;
10718 *s++ = c;
10719 continue;
10720 case 5:
10721 if (c == '>')
10722 state = 0;
10723 else
10724 state = 1;
10725 *s++ = c;
10726 continue;
10727
10728 case 6:
10729 if (c == '-')
10730 state = 7;
10731 else
10732 state = 2;
10733 *s++ = c;
10734 continue;
10735 case 7:
10736 if (c == '>')
10737 state = 0;
10738 else
10739 state = 2;
10740 *s++ = c;
10741 continue;
10742
10743 case 8:
10744 if (c == '>')
10745 state = 0;
10746 else
10747 state = 3;
10748 *s++ = c;
10749 continue;
10750 }
10751 switch (c)
10752 {
10753 case SOAP_TT:
10754 if (n == 0)
10755 goto end;
10756 n--;
10757 *s++ = '<';
10758 t = (char*)"/";
10759 m = 1;
10760 break;
10761 case SOAP_LT:
10762 if (f && n == 0)
10763 goto end;
10764 n++;
10765 *s++ = '<';
10766 break;
10767 case SOAP_GT:
10768 *s++ = '>';
10769 break;
10770 case SOAP_QT:
10771 *s++ = '"';
10772 break;
10773 case SOAP_AP:
10774 *s++ = '\'';
10775 break;
10776 case '/':
10777 if (n > 0)
10778 { c = soap_getchar(soap);
10779 if (c == '>')
10780 n--;
10781 soap_unget(soap, c);
10782 }
10783 *s++ = '/';
10784 break;
10785 case '<':
10786 c = soap_getchar(soap);
10787 if (c == '/')
10788 { if (n == 0)
10789 { c = SOAP_TT;
10790 goto end;
10791 }
10792 n--;
10793 }
10794 else if (c == '!')
10795 { c = soap_getchar(soap);
10796 if (c == '[')
10797 { do c = soap_getchar(soap);
10798 while ((int)c != EOF && c != '[');
10799 if ((int)c == EOF)
10800 goto end;
10801 t = (char*)"![CDATA[";
10802 m = 8;
10803 state = 1;
10804 }
10805 else if (c == '-')
10806 { if ((c = soap_getchar(soap)) == '-')
10807 state = 2;
10808 t = (char*)"!-";
10809 m = 2;
10810 soap_unget(soap, c);
10811 }
10812 else
10813 { t = (char*)"!";
10814 m = 1;
10815 soap_unget(soap, c);
10816 }
10817 *s++ = '<';
10818 break;
10819 }
10820 else if (c == '?')
10821 state = 3;
10822 else if (f && n == 0)
10823 { soap_revget1(soap);
10824 c = '<';
10825 goto end;
10826 }
10827 else
10828 n++;
10829 soap_unget(soap, c);
10830 *s++ = '<';
10831 break;
10832 case '>':
10833 *s++ = '>';
10834 break;
10835 case '"':
10836 *s++ = '"';
10837 break;
10838 default:
10839 #ifndef WITH_LEANER
10840 #ifdef HAVE_WCTOMB
10841 if (soap->mode & SOAP_C_MBSTRING)
10842 { m = wctomb(buf, c & 0x7FFFFFFF);
10843 if (m >= 1 && m <= (int)MB_CUR_MAX)
10844 { t = buf;
10845 *s++ = *t++;
10846 m--;
10847 }
10848 else
10849 { *s++ = SOAP_UNKNOWN_CHAR;
10850 m = 0;
10851 }
10852 }
10853 else
10854 #endif
10855 #endif
10856 *s++ = (char)(c & 0xFF);
10857 }
10858 l++;
10859 if (maxlen >= 0 && l > maxlen)
10860 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
10861 soap->error = SOAP_LENGTH;
10862 return NULL;
10863 }
10864 }
10865 }
10866 }
10867 #endif
10868 #ifdef WITH_FAST
10869 soap->labidx = 0;
10870 #else
10871 if (soap_new_block(soap) == NULL)
10872 return NULL;
10873 #endif
10874 for (;;)
10875 {
10876 #ifdef WITH_FAST
10877 register size_t k;
10878 if (soap_append_lab(soap, NULL, 0))
10879 return NULL;
10880 s = soap->labbuf + soap->labidx;
10881 k = soap->lablen - soap->labidx;
10882 soap->labidx = soap->lablen;
10883 #else
10884 register size_t k = SOAP_BLKLEN;
10885 if (!(s = (char*)soap_push_block(soap, NULL, k)))
10886 return NULL;
10887 #endif
10888 for (i = 0; i < k; i++)
10889 { if (m > 0)
10890 { *s++ = *t++;
10891 m--;
10892 continue;
10893 }
10894 if (soap->mode & SOAP_C_UTFSTRING)
10895 { if (((c = soap_get(soap)) & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP)
10896 { c &= 0x7FFFFFFF;
10897 t = buf;
10898 if (c < 0x0800)
10899 *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
10900 else
10901 { if (c < 0x010000)
10902 *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
10903 else
10904 { if (c < 0x200000)
10905 *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
10906 else
10907 { if (c < 0x04000000)
10908 *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
10909 else
10910 { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
10911 *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
10912 }
10913 *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
10914 }
10915 *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
10916 }
10917 *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
10918 }
10919 *t++ = (char)(0x80 | (c & 0x3F));
10920 m = (int)(t - buf) - 1;
10921 t = buf;
10922 *s++ = *t++;
10923 continue;
10924 }
10925 }
10926 else
10927 c = soap_getutf8(soap);
10928 switch (c)
10929 {
10930 case SOAP_TT:
10931 if (n == 0)
10932 goto end;
10933 n--;
10934 *s++ = '<';
10935 t = (char*)"/";
10936 m = 1;
10937 break;
10938 case SOAP_LT:
10939 if (f && n == 0)
10940 goto end;
10941 n++;
10942 *s++ = '<';
10943 break;
10944 case SOAP_GT:
10945 *s++ = '>';
10946 break;
10947 case SOAP_QT:
10948 *s++ = '"';
10949 break;
10950 case SOAP_AP:
10951 *s++ = '\'';
10952 break;
10953 case '/':
10954 if (n > 0)
10955 { c = soap_get(soap);
10956 if (c == SOAP_GT)
10957 n--;
10958 soap_unget(soap, c);
10959 }
10960 *s++ = '/';
10961 break;
10962 case (soap_wchar)('<' | 0x80000000):
10963 if (flag)
10964 *s++ = '<';
10965 else
10966 { *s++ = '&';
10967 t = (char*)"lt;";
10968 m = 3;
10969 }
10970 break;
10971 case (soap_wchar)('>' | 0x80000000):
10972 if (flag)
10973 *s++ = '>';
10974 else
10975 { *s++ = '&';
10976 t = (char*)"gt;";
10977 m = 3;
10978 }
10979 break;
10980 case (soap_wchar)('&' | 0x80000000):
10981 if (flag)
10982 *s++ = '&';
10983 else
10984 { *s++ = '&';
10985 t = (char*)"amp;";
10986 m = 4;
10987 }
10988 break;
10989 case (soap_wchar)('"' | 0x80000000):
10990 if (flag)
10991 *s++ = '"';
10992 else
10993 { *s++ = '&';
10994 t = (char*)"quot;";
10995 m = 5;
10996 }
10997 break;
10998 case (soap_wchar)('\'' | 0x80000000):
10999 if (flag)
11000 *s++ = '\'';
11001 else
11002 { *s++ = '&';
11003 t = (char*)"apos;";
11004 m = 5;
11005 }
11006 break;
11007 default:
11008 if ((int)c == EOF)
11009 goto end;
11010 #ifndef WITH_LEANER
11011 #ifdef HAVE_WCTOMB
11012 if (soap->mode & SOAP_C_MBSTRING)
11013 { m = wctomb(buf, c & 0x7FFFFFFF);
11014 if (m >= 1 && m <= (int)MB_CUR_MAX)
11015 { t = buf;
11016 *s++ = *t++;
11017 m--;
11018 }
11019 else
11020 { *s++ = SOAP_UNKNOWN_CHAR;
11021 m = 0;
11022 }
11023 }
11024 else
11025 #endif
11026 #endif
11027 *s++ = (char)(c & 0xFF);
11028 }
11029 l++;
11030 if (maxlen >= 0 && l > maxlen)
11031 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
11032 soap->error = SOAP_LENGTH;
11033 return NULL;
11034 }
11035 }
11036 }
11037 end:
11038 soap_unget(soap, c);
11039 *s = '\0';
11040 #ifdef WITH_FAST
11041 t = soap_strdup(soap, soap->labbuf);
11042 #else
11043 soap_size_block(soap, NULL, i+1);
11044 t = soap_save_block(soap, NULL, 0);
11045 #endif
11046 if (l < minlen)
11047 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen));
11048 soap->error = SOAP_LENGTH;
11049 return NULL;
11050 }
11051 #ifdef WITH_DOM
11052 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
11053 { if (flag == 3)
11054 soap->dom->tail = t;
11055 else
11056 soap->dom->data = t;
11057 }
11058 #endif
11059 if (flag == 2)
11060 if (soap_s2QName(soap, t, &t, minlen, maxlen))
11061 return NULL;
11062 return t;
11063 }
11064 #endif
11065
11066
11067 #ifndef WITH_LEANER
11068 #ifndef PALM_2
11069 SOAP_FMAC1
11070 int
11071 SOAP_FMAC2
11072 soap_wstring_out(struct soap *soap, const wchar_t *s, int flag)
11073 { const char *t;
11074 char tmp;
11075 register soap_wchar c;
11076 #ifdef WITH_DOM
11077 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
11078 { wchar_t *r = (wchar_t*)s;
11079 int n = 1;
11080 while (*r++)
11081 n++;
11082 soap->dom->wide = r = (wchar_t*)soap_malloc(soap, n * sizeof(wchar_t));
11083 while (n--)
11084 *r++ = *s++;
11085 return SOAP_OK;
11086 }
11087 #endif
11088 while ((c = *s++))
11089 { switch (c)
11090 {
11091 case 0x09:
11092 if (flag)
11093 t = "	";
11094 else
11095 t = "\t";
11096 break;
11097 case 0x0A:
11098 if (flag || !(soap->mode & SOAP_XML_CANONICAL))
11099 t = "
";
11100 else
11101 t = "\n";
11102 break;
11103 case 0x0D:
11104 t = "
";
11105 break;
11106 case '&':
11107 t = "&";
11108 break;
11109 case '<':
11110 t = "<";
11111 break;
11112 case '>':
11113 if (flag)
11114 t = ">";
11115 else
11116 t = ">";
11117 break;
11118 case '"':
11119 if (flag)
11120 t = """;
11121 else
11122 t = "\"";
11123 break;
11124 default:
11125 if (c >= 0x20 && c < 0x80)
11126 { tmp = (char)c;
11127 if (soap_send_raw(soap, &tmp, 1))
11128 return soap->error;
11129 }
11130 else
11131 { if (sizeof(wchar_t) < 4 && (c & 0xD800) == 0xD800)
11132 {
11133 if ((*s & 0xD800) == 0xD800)
11134 c = (c << 10) + *s++ + 0x10000 - (0xD800 << 10) - 0xDC00;
11135 else
11136 c = 0xFFFD;
11137 }
11138 if (soap_pututf8(soap, (unsigned long)c))
11139 return soap->error;
11140 }
11141 continue;
11142 }
11143 if (soap_send(soap, t))
11144 return soap->error;
11145 }
11146 return SOAP_OK;
11147 }
11148 #endif
11149 #endif
11150
11151
11152 #ifndef WITH_LEANER
11153 #ifndef PALM_2
11154 SOAP_FMAC1
11155 wchar_t *
11156 SOAP_FMAC2
11157 soap_wstring_in(struct soap *soap, int flag, long minlen, long maxlen)
11158 { wchar_t *s;
11159 register int i, n = 0, f = 0;
11160 register long l = 0;
11161 register soap_wchar c;
11162 char *t = NULL;
11163 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading wide string content\n"));
11164 if (soap->peeked)
11165 { if (*soap->tag)
11166 {
11167 #ifndef WITH_LEAN
11168 struct soap_attribute *tp;
11169 t = soap->tmpbuf;
11170 *t = '<';
11171 t[sizeof(soap->tmpbuf)-1] = '\0';
11172 strncpy(t + 1, soap->tag, sizeof(soap->tmpbuf) - 2);
11173 t += strlen(t);
11174 for (tp = soap->attributes; tp; tp = tp->next)
11175 { if (tp->visible)
11176 { if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2)
11177 break;
11178 *t++ = ' ';
11179 strcpy(t, tp->name);
11180 t += strlen(t);
11181 if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2)
11182 break;
11183 if (tp->value)
11184 { *t++ = '=';
11185 *t++ = '"';
11186 strcpy(t, tp->value);
11187 t += strlen(t);
11188 *t++ = '"';
11189 }
11190 }
11191 }
11192 if (!soap->body)
11193 *t++ = '/';
11194 *t++ = '>';
11195 *t = '\0';
11196 t = soap->tmpbuf;
11197 #endif
11198 if (soap->body)
11199 n = 1;
11200 f = 1;
11201 soap->peeked = 0;
11202 }
11203 }
11204 if (soap_new_block(soap) == NULL)
11205 return NULL;
11206 for (;;)
11207 { if (!(s = (wchar_t*)soap_push_block(soap, NULL, sizeof(wchar_t)*SOAP_BLKLEN)))
11208 return NULL;
11209 for (i = 0; i < SOAP_BLKLEN; i++)
11210 { if (t)
11211 { *s++ = (wchar_t)*t++;
11212 if (!*t)
11213 t = NULL;
11214 continue;
11215 }
11216 c = soap_getutf8(soap);
11217 switch (c)
11218 {
11219 case SOAP_TT:
11220 if (n == 0)
11221 goto end;
11222 n--;
11223 *s++ = '<';
11224 soap_unget(soap, '/');
11225 break;
11226 case SOAP_LT:
11227 if (f && n == 0)
11228 goto end;
11229 n++;
11230 *s++ = '<';
11231 break;
11232 case SOAP_GT:
11233 *s++ = '>';
11234 break;
11235 case SOAP_QT:
11236 *s++ = '"';
11237 break;
11238 case SOAP_AP:
11239 *s++ = '\'';
11240 break;
11241 case '/':
11242 if (n > 0)
11243 { c = soap_getutf8(soap);
11244 if (c == SOAP_GT)
11245 n--;
11246 soap_unget(soap, c);
11247 }
11248 *s++ = '/';
11249 break;
11250 case '<':
11251 if (flag)
11252 *s++ = (soap_wchar)'<';
11253 else
11254 { *s++ = (soap_wchar)'&';
11255 t = (char*)"lt;";
11256 }
11257 break;
11258 case '>':
11259 if (flag)
11260 *s++ = (soap_wchar)'>';
11261 else
11262 { *s++ = (soap_wchar)'&';
11263 t = (char*)"gt;";
11264 }
11265 break;
11266 case '"':
11267 if (flag)
11268 *s++ = (soap_wchar)'"';
11269 else
11270 { *s++ = (soap_wchar)'&';
11271 t = (char*)"quot;";
11272 }
11273 break;
11274 default:
11275 if ((int)c == EOF)
11276 goto end;
11277 if (sizeof(wchar_t) < 4 && c > 0xFFFF)
11278 { wchar_t c1, c2;
11279
11280 c1 = 0xD800 - (0x10000 >> 10) + (c >> 10);
11281 c2 = 0xDC00 + (c & 0x3FF);
11282 c = c1;
11283 soap_unget(soap, c2);
11284 }
11285 *s++ = (wchar_t)c & 0x7FFFFFFF;
11286 }
11287 l++;
11288 if (maxlen >= 0 && l > maxlen)
11289 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
11290 soap->error = SOAP_LENGTH;
11291 return NULL;
11292 }
11293 }
11294 }
11295 end:
11296 soap_unget(soap, c);
11297 *s = '\0';
11298 soap_size_block(soap, NULL, sizeof(wchar_t) * (i + 1));
11299 if (l < minlen)
11300 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen));
11301 soap->error = SOAP_LENGTH;
11302 return NULL;
11303 }
11304 s = (wchar_t*)soap_save_block(soap, NULL, NULL, 0);
11305 #ifdef WITH_DOM
11306 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
11307 soap->dom->wide = s;
11308 #endif
11309 return s;
11310 }
11311 #endif
11312 #endif
11313
11314
11315 #ifndef PALM_2
11316 SOAP_FMAC1
11317 const char*
11318 SOAP_FMAC2
11319 soap_int2s(struct soap *soap, int n)
11320 { return soap_long2s(soap, (long)n);
11321 }
11322 #endif
11323
11324
11325 #ifndef PALM_2
11326 SOAP_FMAC1
11327 int
11328 SOAP_FMAC2
11329 soap_outint(struct soap *soap, const char *tag, int id, const int *p, const char *type, int n)
11330 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
11331 || soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
11332 return soap->error;
11333 return soap_element_end_out(soap, tag);
11334 }
11335 #endif
11336
11337
11338 #ifndef PALM_2
11339 SOAP_FMAC1
11340 int
11341 SOAP_FMAC2
11342 soap_s2int(struct soap *soap, const char *s, int *p)
11343 { if (s)
11344 { long n;
11345 char *r;
11346 #ifndef WITH_NOIO
11347 #ifndef WITH_LEAN
11348 soap_reset_errno;
11349 #endif
11350 #endif
11351 n = soap_strtol(s, &r, 10);
11352 if (s == r || *r
11353 #ifndef WITH_LEAN
11354 || n != (int)n
11355 #endif
11356 #ifndef WITH_NOIO
11357 #ifndef WITH_LEAN
11358 || soap_errno == SOAP_ERANGE
11359 #endif
11360 #endif
11361 )
11362 soap->error = SOAP_TYPE;
11363 *p = (int)n;
11364 }
11365 return soap->error;
11366 }
11367 #endif
11368
11369
11370 #ifndef PALM_2
11371 SOAP_FMAC1
11372 int *
11373 SOAP_FMAC2
11374 soap_inint(struct soap *soap, const char *tag, int *p, const char *type, int t)
11375 { if (soap_element_begin_in(soap, tag, 0, NULL))
11376 return NULL;
11377 #ifndef WITH_LEAN
11378 if (*soap->type
11379 && soap_match_tag(soap, soap->type, type)
11380 && soap_match_tag(soap, soap->type, ":int")
11381 && soap_match_tag(soap, soap->type, ":short")
11382 && soap_match_tag(soap, soap->type, ":byte"))
11383 { soap->error = SOAP_TYPE;
11384 soap_revert(soap);
11385 return NULL;
11386 }
11387 #endif
11388 p = (int*)soap_id_enter(soap, soap->id, p, t, sizeof(int), 0, NULL, NULL, NULL);
11389 if (*soap->href)
11390 p = (int*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(int), 0, NULL);
11391 else if (p)
11392 { if (soap_s2int(soap, soap_value(soap), p))
11393 return NULL;
11394 }
11395 if (soap->body && soap_element_end_in(soap, tag))
11396 return NULL;
11397 return p;
11398 }
11399 #endif
11400
11401
11402 #ifndef PALM_2
11403 SOAP_FMAC1
11404 const char*
11405 SOAP_FMAC2
11406 soap_long2s(struct soap *soap, long n)
11407 { sprintf(soap->tmpbuf, "%ld", n);
11408 return soap->tmpbuf;
11409 }
11410 #endif
11411
11412
11413 #ifndef PALM_2
11414 SOAP_FMAC1
11415 int
11416 SOAP_FMAC2
11417 soap_outlong(struct soap *soap, const char *tag, int id, const long *p, const char *type, int n)
11418 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
11419 || soap_string_out(soap, soap_long2s(soap, *p), 0))
11420 return soap->error;
11421 return soap_element_end_out(soap, tag);
11422 }
11423 #endif
11424
11425
11426 #ifndef PALM_2
11427 SOAP_FMAC1
11428 int
11429 SOAP_FMAC2
11430 soap_s2long(struct soap *soap, const char *s, long *p)
11431 { if (s)
11432 { char *r;
11433 #ifndef WITH_NOIO
11434 #ifndef WITH_LEAN
11435 soap_reset_errno;
11436 #endif
11437 #endif
11438 *p = soap_strtol(s, &r, 10);
11439 if (s == r || *r
11440 #ifndef WITH_NOIO
11441 #ifndef WITH_LEAN
11442 || soap_errno == SOAP_ERANGE
11443 #endif
11444 #endif
11445 )
11446 soap->error = SOAP_TYPE;
11447 }
11448 return soap->error;
11449 }
11450 #endif
11451
11452
11453 #ifndef PALM_2
11454 SOAP_FMAC1
11455 long *
11456 SOAP_FMAC2
11457 soap_inlong(struct soap *soap, const char *tag, long *p, const char *type, int t)
11458 { if (soap_element_begin_in(soap, tag, 0, NULL))
11459 return NULL;
11460 #ifndef WITH_LEAN
11461 if (*soap->type
11462 && soap_match_tag(soap, soap->type, type)
11463 && soap_match_tag(soap, soap->type, ":int")
11464 && soap_match_tag(soap, soap->type, ":short")
11465 && soap_match_tag(soap, soap->type, ":byte"))
11466 { soap->error = SOAP_TYPE;
11467 soap_revert(soap);
11468 return NULL;
11469 }
11470 #endif
11471 p = (long*)soap_id_enter(soap, soap->id, p, t, sizeof(long), 0, NULL, NULL, NULL);
11472 if (*soap->href)
11473 p = (long*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(long), 0, NULL);
11474 else if (p)
11475 { if (soap_s2long(soap, soap_value(soap), p))
11476 return NULL;
11477 }
11478 if (soap->body && soap_element_end_in(soap, tag))
11479 return NULL;
11480 return p;
11481 }
11482 #endif
11483
11484
11485 #ifndef WITH_LEAN
11486 SOAP_FMAC1
11487 const char*
11488 SOAP_FMAC2
11489 soap_LONG642s(struct soap *soap, LONG64 n)
11490 { sprintf(soap->tmpbuf, SOAP_LONG_FORMAT, n);
11491 return soap->tmpbuf;
11492 }
11493 #endif
11494
11495
11496 #ifndef WITH_LEAN
11497 SOAP_FMAC1
11498 int
11499 SOAP_FMAC2
11500 soap_outLONG64(struct soap *soap, const char *tag, int id, const LONG64 *p, const char *type, int n)
11501 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
11502 || soap_string_out(soap, soap_LONG642s(soap, *p), 0))
11503 return soap->error;
11504 return soap_element_end_out(soap, tag);
11505 }
11506 #endif
11507
11508
11509 #ifndef WITH_LEAN
11510 SOAP_FMAC1
11511 int
11512 SOAP_FMAC2
11513 soap_s2LONG64(struct soap *soap, const char *s, LONG64 *p)
11514 { if (s)
11515 {
11516 #ifdef HAVE_STRTOLL
11517 char *r;
11518 #ifndef WITH_NOIO
11519 #ifndef WITH_LEAN
11520 soap_reset_errno;
11521 #endif
11522 #endif
11523 *p = strtoll(s, &r, 10);
11524 if (s == r || *r
11525 #ifndef WITH_NOIO
11526 #ifndef WITH_LEAN
11527 || soap_errno == SOAP_ERANGE
11528 #endif
11529 #endif
11530 )
11531 #else
11532 # ifdef HAVE_SSCANF
11533 if (sscanf(s, SOAP_LONG_FORMAT, p) != 1)
11534 # endif
11535 #endif
11536 soap->error = SOAP_TYPE;
11537 }
11538 return soap->error;
11539 }
11540 #endif
11541
11542
11543 #ifndef WITH_LEAN
11544 SOAP_FMAC1
11545 LONG64 *
11546 SOAP_FMAC2
11547 soap_inLONG64(struct soap *soap, const char *tag, LONG64 *p, const char *type, int t)
11548 { if (soap_element_begin_in(soap, tag, 0, NULL))
11549 return NULL;
11550 #ifndef WITH_LEAN
11551 if (*soap->type
11552 && soap_match_tag(soap, soap->type, type)
11553 && soap_match_tag(soap, soap->type, ":integer")
11554 && soap_match_tag(soap, soap->type, ":positiveInteger")
11555 && soap_match_tag(soap, soap->type, ":negativeInteger")
11556 && soap_match_tag(soap, soap->type, ":nonPositiveInteger")
11557 && soap_match_tag(soap, soap->type, ":nonNegativeInteger")
11558 && soap_match_tag(soap, soap->type, ":long")
11559 && soap_match_tag(soap, soap->type, ":int")
11560 && soap_match_tag(soap, soap->type, ":short")
11561 && soap_match_tag(soap, soap->type, ":byte"))
11562 { soap->error = SOAP_TYPE;
11563 soap_revert(soap);
11564 return NULL;
11565 }
11566 #endif
11567 p = (LONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(LONG64), 0, NULL, NULL, NULL);
11568 if (*soap->href)
11569 p = (LONG64*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(LONG64), 0, NULL);
11570 else if (p)
11571 { if (soap_s2LONG64(soap, soap_value(soap), p))
11572 return NULL;
11573 }
11574 if (soap->body && soap_element_end_in(soap, tag))
11575 return NULL;
11576 return p;
11577 }
11578 #endif
11579
11580
11581 #ifndef PALM_2
11582 SOAP_FMAC1
11583 const char*
11584 SOAP_FMAC2
11585 soap_byte2s(struct soap *soap, char n)
11586 { return soap_long2s(soap, (long)n);
11587 }
11588 #endif
11589
11590
11591 #ifndef PALM_2
11592 SOAP_FMAC1
11593 int
11594 SOAP_FMAC2
11595 soap_outbyte(struct soap *soap, const char *tag, int id, const char *p, const char *type, int n)
11596 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
11597 || soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
11598 return soap->error;
11599 return soap_element_end_out(soap, tag);
11600 }
11601 #endif
11602
11603
11604 #ifndef PALM_2
11605 SOAP_FMAC1
11606 int
11607 SOAP_FMAC2
11608 soap_s2byte(struct soap *soap, const char *s, char *p)
11609 { if (s)
11610 { long n;
11611 char *r;
11612 n = soap_strtol(s, &r, 10);
11613 if (s == r || *r || n < -128 || n > 127)
11614 soap->error = SOAP_TYPE;
11615 *p = (char)n;
11616 }
11617 return soap->error;
11618 }
11619 #endif
11620
11621
11622 #ifndef PALM_2
11623 SOAP_FMAC1
11624 char *
11625 SOAP_FMAC2
11626 soap_inbyte(struct soap *soap, const char *tag, char *p, const char *type, int t)
11627 { if (soap_element_begin_in(soap, tag, 0, NULL))
11628 return NULL;
11629 #ifndef WITH_LEAN
11630 if (*soap->type
11631 && soap_match_tag(soap, soap->type, type)
11632 && soap_match_tag(soap, soap->type, ":byte"))
11633 { soap->error = SOAP_TYPE;
11634 soap_revert(soap);
11635 return NULL;
11636 }
11637 #endif
11638 p = (char*)soap_id_enter(soap, soap->id, p, t, sizeof(char), 0, NULL, NULL, NULL);
11639 if (*soap->href)
11640 p = (char*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(char), 0, NULL);
11641 else if (p)
11642 { if (soap_s2byte(soap, soap_value(soap), p))
11643 return NULL;
11644 }
11645 if (soap->body && soap_element_end_in(soap, tag))
11646 return NULL;
11647 return p;
11648 }
11649 #endif
11650
11651
11652 #ifndef PALM_2
11653 SOAP_FMAC1
11654 const char*
11655 SOAP_FMAC2
11656 soap_short2s(struct soap *soap, short n)
11657 { return soap_long2s(soap, (long)n);
11658 }
11659 #endif
11660
11661
11662 #ifndef PALM_2
11663 SOAP_FMAC1
11664 int
11665 SOAP_FMAC2
11666 soap_outshort(struct soap *soap, const char *tag, int id, const short *p, const char *type, int n)
11667 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
11668 || soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
11669 return soap->error;
11670 return soap_element_end_out(soap, tag);
11671 }
11672 #endif
11673
11674
11675 #ifndef PALM_2
11676 SOAP_FMAC1
11677 int
11678 SOAP_FMAC2
11679 soap_s2short(struct soap *soap, const char *s, short *p)
11680 { if (s)
11681 { long n;
11682 char *r;
11683 n = soap_strtol(s, &r, 10);
11684 if (s == r || *r || n < -32768 || n > 32767)
11685 soap->error = SOAP_TYPE;
11686 *p = (short)n;
11687 }
11688 return soap->error;
11689 }
11690 #endif
11691
11692
11693 #ifndef PALM_2
11694 SOAP_FMAC1
11695 short *
11696 SOAP_FMAC2
11697 soap_inshort(struct soap *soap, const char *tag, short *p, const char *type, int t)
11698 { if (soap_element_begin_in(soap, tag, 0, NULL))
11699 return NULL;
11700 #ifndef WITH_LEAN
11701 if (*soap->type
11702 && soap_match_tag(soap, soap->type, type)
11703 && soap_match_tag(soap, soap->type, ":short")
11704 && soap_match_tag(soap, soap->type, ":byte"))
11705 { soap->error = SOAP_TYPE;
11706 soap_revert(soap);
11707 return NULL;
11708 }
11709 #endif
11710 p = (short*)soap_id_enter(soap, soap->id, p, t, sizeof(short), 0, NULL, NULL, NULL);
11711 if (*soap->href)
11712 p = (short*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(short), 0, NULL);
11713 else if (p)
11714 { if (soap_s2short(soap, soap_value(soap), p))
11715 return NULL;
11716 }
11717 if (soap->body && soap_element_end_in(soap, tag))
11718 return NULL;
11719 return p;
11720 }
11721 #endif
11722
11723
11724 #ifndef PALM_2
11725 SOAP_FMAC1
11726 const char*
11727 SOAP_FMAC2
11728 soap_float2s(struct soap *soap, float n)
11729 { char *s;
11730 if (soap_isnan((double)n))
11731 return "NaN";
11732 if (soap_ispinff(n))
11733 return "INF";
11734 if (soap_isninff(n))
11735 return "-INF";
11736 s = soap->tmpbuf;
11737 #if defined(HAVE_SPRINTF_L)
11738 sprintf_l(s, soap->c_locale, soap->float_format, n);
11739 #else
11740 sprintf(s, soap->float_format, n);
11741 s = strchr(s, ',');
11742 if (s)
11743 *s = '.';
11744 #endif
11745 return soap->tmpbuf;
11746 }
11747 #endif
11748
11749
11750 #ifndef PALM_2
11751 SOAP_FMAC1
11752 int
11753 SOAP_FMAC2
11754 soap_outfloat(struct soap *soap, const char *tag, int id, const float *p, const char *type, int n)
11755 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
11756 || soap_string_out(soap, soap_float2s(soap, *p), 0))
11757 return soap->error;
11758 return soap_element_end_out(soap, tag);
11759 }
11760 #endif
11761
11762
11763 #ifndef PALM_2
11764 SOAP_FMAC1
11765 int
11766 SOAP_FMAC2
11767 soap_s2float(struct soap *soap, const char *s, float *p)
11768 { if (s)
11769 { if (!*s)
11770 return soap->error = SOAP_TYPE;
11771 if (!soap_tag_cmp(s, "INF"))
11772 *p = FLT_PINFTY;
11773 else if (!soap_tag_cmp(s, "+INF"))
11774 *p = FLT_PINFTY;
11775 else if (!soap_tag_cmp(s, "-INF"))
11776 *p = FLT_NINFTY;
11777 else if (!soap_tag_cmp(s, "NaN"))
11778 *p = FLT_NAN;
11779 else
11780 {
11781
11782 #if defined(HAVE_STRTOD_L)
11783 char *r;
11784 *p = (float)strtod_l(s, &r, soap->c_locale);
11785 if (*r)
11786 #elif defined(HAVE_STRTOD)
11787 char *r;
11788 *p = (float)strtod(s, &r);
11789 if (*r)
11790 #elif defined(HAVE_STRTOF_L)
11791 char *r;
11792 *p = strtof_l((char*)s, &r, soap->c_locale);
11793 if (*r)
11794 #elif defined(HAVE_STRTOF)
11795 char *r;
11796 *p = strtof((char*)s, &r);
11797 if (*r)
11798 #endif
11799 {
11800 #if defined(HAVE_SSCANF_L) && !defined(HAVE_STRTOF_L) && !defined(HAVE_STRTOD_L)
11801 if (sscanf_l(s, soap->c_locale, "%g", p) != 1)
11802 soap->error = SOAP_TYPE;
11803 #elif defined(HAVE_SSCANF)
11804 if (sscanf(s, "%g", p) != 1)
11805 soap->error = SOAP_TYPE;
11806 #else
11807 soap->error = SOAP_TYPE;
11808 #endif
11809 }
11810 }
11811 }
11812 return soap->error;
11813 }
11814 #endif
11815
11816
11817 #ifndef WITH_LEAN
11818 static int soap_isnumeric(struct soap *soap, const char *type)
11819 { if (soap_match_tag(soap, soap->type, type)
11820 && soap_match_tag(soap, soap->type, ":float")
11821 && soap_match_tag(soap, soap->type, ":double")
11822 && soap_match_tag(soap, soap->type, ":decimal")
11823 && soap_match_tag(soap, soap->type, ":integer")
11824 && soap_match_tag(soap, soap->type, ":positiveInteger")
11825 && soap_match_tag(soap, soap->type, ":negativeInteger")
11826 && soap_match_tag(soap, soap->type, ":nonPositiveInteger")
11827 && soap_match_tag(soap, soap->type, ":nonNegativeInteger")
11828 && soap_match_tag(soap, soap->type, ":long")
11829 && soap_match_tag(soap, soap->type, ":int")
11830 && soap_match_tag(soap, soap->type, ":short")
11831 && soap_match_tag(soap, soap->type, ":byte")
11832 && soap_match_tag(soap, soap->type, ":unsignedLong")
11833 && soap_match_tag(soap, soap->type, ":unsignedInt")
11834 && soap_match_tag(soap, soap->type, ":unsignedShort")
11835 && soap_match_tag(soap, soap->type, ":unsignedByte"))
11836 { soap->error = SOAP_TYPE;
11837 soap_revert(soap);
11838 return SOAP_ERR;
11839 }
11840 return SOAP_OK;
11841 }
11842 #endif
11843
11844
11845 #ifndef PALM_2
11846 SOAP_FMAC1
11847 float *
11848 SOAP_FMAC2
11849 soap_infloat(struct soap *soap, const char *tag, float *p, const char *type, int t)
11850 { if (soap_element_begin_in(soap, tag, 0, NULL))
11851 return NULL;
11852 #ifndef WITH_LEAN
11853 if (*soap->type != '\0' && soap_isnumeric(soap, type))
11854 return NULL;
11855 #endif
11856 p = (float*)soap_id_enter(soap, soap->id, p, t, sizeof(float), 0, NULL, NULL, NULL);
11857 if (*soap->href)
11858 p = (float*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(float), 0, NULL);
11859 else if (p)
11860 { if (soap_s2float(soap, soap_value(soap), p))
11861 return NULL;
11862 }
11863 if (soap->body && soap_element_end_in(soap, tag))
11864 return NULL;
11865 return p;
11866 }
11867 #endif
11868
11869
11870 #ifndef PALM_2
11871 SOAP_FMAC1
11872 const char*
11873 SOAP_FMAC2
11874 soap_double2s(struct soap *soap, double n)
11875 { char *s;
11876 if (soap_isnan(n))
11877 return "NaN";
11878 if (soap_ispinfd(n))
11879 return "INF";
11880 if (soap_isninfd(n))
11881 return "-INF";
11882 s = soap->tmpbuf;
11883 #if defined(HAVE_SPRINTF_L)
11884 sprintf_l(s, soap->c_locale, soap->double_format, n);
11885 #else
11886 sprintf(s, soap->double_format, n);
11887 s = strchr(s, ',');
11888 if (s)
11889 *s = '.';
11890 #endif
11891 return soap->tmpbuf;
11892 }
11893 #endif
11894
11895
11896 #ifndef PALM_2
11897 SOAP_FMAC1
11898 int
11899 SOAP_FMAC2
11900 soap_outdouble(struct soap *soap, const char *tag, int id, const double *p, const char *type, int n)
11901 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
11902 || soap_string_out(soap, soap_double2s(soap, *p), 0))
11903 return soap->error;
11904 return soap_element_end_out(soap, tag);
11905 }
11906 #endif
11907
11908
11909 #ifndef PALM_2
11910 SOAP_FMAC1
11911 int
11912 SOAP_FMAC2
11913 soap_s2double(struct soap *soap, const char *s, double *p)
11914 { if (s)
11915 { if (!*s)
11916 return soap->error = SOAP_TYPE;
11917 if (!soap_tag_cmp(s, "INF"))
11918 *p = DBL_PINFTY;
11919 else if (!soap_tag_cmp(s, "+INF"))
11920 *p = DBL_PINFTY;
11921 else if (!soap_tag_cmp(s, "-INF"))
11922 *p = DBL_NINFTY;
11923 else if (!soap_tag_cmp(s, "NaN"))
11924 *p = DBL_NAN;
11925 else
11926 {
11927 #if defined(HAVE_STRTOD_L)
11928 char *r;
11929 *p = strtod_l(s, &r, soap->c_locale);
11930 if (*r)
11931 #elif defined(HAVE_STRTOD)
11932 char *r;
11933 *p = strtod(s, &r);
11934 if (*r)
11935 #endif
11936 {
11937 #if defined(HAVE_SSCANF_L) && !defined(HAVE_STRTOF_L) && !defined(HAVE_STRTOD_L)
11938 if (sscanf_l(s, soap->c_locale, "%lg", p) != 1)
11939 soap->error = SOAP_TYPE;
11940 #elif defined(HAVE_SSCANF)
11941 if (sscanf(s, "%lg", p) != 1)
11942 soap->error = SOAP_TYPE;
11943 #else
11944 soap->error = SOAP_TYPE;
11945 #endif
11946 }
11947 }
11948 }
11949 return soap->error;
11950 }
11951 #endif
11952
11953
11954 #ifndef PALM_2
11955 SOAP_FMAC1
11956 double *
11957 SOAP_FMAC2
11958 soap_indouble(struct soap *soap, const char *tag, double *p, const char *type, int t)
11959 { if (soap_element_begin_in(soap, tag, 0, NULL))
11960 return NULL;
11961 #ifndef WITH_LEAN
11962 if (*soap->type != '\0' && soap_isnumeric(soap, type))
11963 return NULL;
11964 #endif
11965 p = (double*)soap_id_enter(soap, soap->id, p, t, sizeof(double), 0, NULL, NULL, NULL);
11966 if (*soap->href)
11967 p = (double*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(double), 0, NULL);
11968 else if (p)
11969 { if (soap_s2double(soap, soap_value(soap), p))
11970 return NULL;
11971 }
11972 if (soap->body && soap_element_end_in(soap, tag))
11973 return NULL;
11974 return p;
11975 }
11976 #endif
11977
11978
11979 #ifndef PALM_2
11980 SOAP_FMAC1
11981 const char*
11982 SOAP_FMAC2
11983 soap_unsignedByte2s(struct soap *soap, unsigned char n)
11984 { return soap_unsignedLong2s(soap, (unsigned long)n);
11985 }
11986 #endif
11987
11988
11989 #ifndef PALM_2
11990 SOAP_FMAC1
11991 int
11992 SOAP_FMAC2
11993 soap_outunsignedByte(struct soap *soap, const char *tag, int id, const unsigned char *p, const char *type, int n)
11994 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
11995 || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0))
11996 return soap->error;
11997 return soap_element_end_out(soap, tag);
11998 }
11999 #endif
12000
12001
12002 #ifndef PALM_2
12003 SOAP_FMAC1
12004 int
12005 SOAP_FMAC2
12006 soap_s2unsignedByte(struct soap *soap, const char *s, unsigned char *p)
12007 { if (s)
12008 { unsigned long n;
12009 char *r;
12010 n = soap_strtoul(s, &r, 10);
12011 if (s == r || *r || n > 255)
12012 soap->error = SOAP_TYPE;
12013 *p = (unsigned char)n;
12014 }
12015 return soap->error;
12016 }
12017 #endif
12018
12019
12020 #ifndef PALM_2
12021 SOAP_FMAC1
12022 unsigned char *
12023 SOAP_FMAC2
12024 soap_inunsignedByte(struct soap *soap, const char *tag, unsigned char *p, const char *type, int t)
12025 { if (soap_element_begin_in(soap, tag, 0, NULL))
12026 return NULL;
12027 #ifndef WITH_LEAN
12028 if (*soap->type
12029 && soap_match_tag(soap, soap->type, type)
12030 && soap_match_tag(soap, soap->type, ":unsignedByte"))
12031 { soap->error = SOAP_TYPE;
12032 soap_revert(soap);
12033 return NULL;
12034 }
12035 #endif
12036 p = (unsigned char*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned char), 0, NULL, NULL, NULL);
12037 if (*soap->href)
12038 p = (unsigned char*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned char), 0, NULL);
12039 else if (p)
12040 { if (soap_s2unsignedByte(soap, soap_value(soap), p))
12041 return NULL;
12042 }
12043 if (soap->body && soap_element_end_in(soap, tag))
12044 return NULL;
12045 return p;
12046 }
12047 #endif
12048
12049
12050 #ifndef PALM_2
12051 SOAP_FMAC1
12052 const char*
12053 SOAP_FMAC2
12054 soap_unsignedShort2s(struct soap *soap, unsigned short n)
12055 { return soap_unsignedLong2s(soap, (unsigned long)n);
12056 }
12057 #endif
12058
12059
12060 #ifndef PALM_2
12061 SOAP_FMAC1
12062 int
12063 SOAP_FMAC2
12064 soap_outunsignedShort(struct soap *soap, const char *tag, int id, const unsigned short *p, const char *type, int n)
12065 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
12066 || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0))
12067 return soap->error;
12068 return soap_element_end_out(soap, tag);
12069 }
12070 #endif
12071
12072
12073 #ifndef PALM_2
12074 SOAP_FMAC1
12075 int
12076 SOAP_FMAC2
12077 soap_s2unsignedShort(struct soap *soap, const char *s, unsigned short *p)
12078 { if (s)
12079 { unsigned long n;
12080 char *r;
12081 n = soap_strtoul(s, &r, 10);
12082 if (s == r || *r || n > 65535)
12083 soap->error = SOAP_TYPE;
12084 *p = (unsigned short)n;
12085 }
12086 return soap->error;
12087 }
12088 #endif
12089
12090
12091 #ifndef PALM_2
12092 SOAP_FMAC1
12093 unsigned short *
12094 SOAP_FMAC2
12095 soap_inunsignedShort(struct soap *soap, const char *tag, unsigned short *p, const char *type, int t)
12096 { if (soap_element_begin_in(soap, tag, 0, NULL))
12097 return NULL;
12098 #ifndef WITH_LEAN
12099 if (*soap->type
12100 && soap_match_tag(soap, soap->type, type)
12101 && soap_match_tag(soap, soap->type, ":unsignedShort")
12102 && soap_match_tag(soap, soap->type, ":unsignedByte"))
12103 { soap->error = SOAP_TYPE;
12104 soap_revert(soap);
12105 return NULL;
12106 }
12107 #endif
12108 p = (unsigned short*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned short), 0, NULL, NULL, NULL);
12109 if (*soap->href)
12110 p = (unsigned short*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned short), 0, NULL);
12111 else if (p)
12112 { if (soap_s2unsignedShort(soap, soap_value(soap), p))
12113 return NULL;
12114 }
12115 if (soap->body && soap_element_end_in(soap, tag))
12116 return NULL;
12117 return p;
12118 }
12119 #endif
12120
12121
12122 #ifndef PALM_2
12123 SOAP_FMAC1
12124 const char*
12125 SOAP_FMAC2
12126 soap_unsignedInt2s(struct soap *soap, unsigned int n)
12127 { return soap_unsignedLong2s(soap, (unsigned long)n);
12128 }
12129 #endif
12130
12131
12132 #ifndef PALM_2
12133 SOAP_FMAC1
12134 int
12135 SOAP_FMAC2
12136 soap_outunsignedInt(struct soap *soap, const char *tag, int id, const unsigned int *p, const char *type, int n)
12137 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
12138 || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0))
12139 return soap->error;
12140 return soap_element_end_out(soap, tag);
12141 }
12142 #endif
12143
12144
12145 #ifndef PALM_2
12146 SOAP_FMAC1
12147 int
12148 SOAP_FMAC2
12149 soap_s2unsignedInt(struct soap *soap, const char *s, unsigned int *p)
12150 { if (s)
12151 { char *r;
12152 #ifndef WITH_NOIO
12153 #ifndef WITH_LEAN
12154 soap_reset_errno;
12155 #endif
12156 #endif
12157 *p = (unsigned int)soap_strtoul(s, &r, 10);
12158 if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
12159 #ifndef WITH_NOIO
12160 #ifndef WITH_LEAN
12161 || soap_errno == SOAP_ERANGE
12162 #endif
12163 #endif
12164 )
12165 soap->error = SOAP_TYPE;
12166 }
12167 return soap->error;
12168 }
12169 #endif
12170
12171
12172 #ifndef PALM_2
12173 SOAP_FMAC1
12174 unsigned int *
12175 SOAP_FMAC2
12176 soap_inunsignedInt(struct soap *soap, const char *tag, unsigned int *p, const char *type, int t)
12177 { if (soap_element_begin_in(soap, tag, 0, NULL))
12178 return NULL;
12179 #ifndef WITH_LEAN
12180 if (*soap->type
12181 && soap_match_tag(soap, soap->type, type)
12182 && soap_match_tag(soap, soap->type, ":unsignedInt")
12183 && soap_match_tag(soap, soap->type, ":unsignedShort")
12184 && soap_match_tag(soap, soap->type, ":unsignedByte"))
12185 { soap->error = SOAP_TYPE;
12186 soap_revert(soap);
12187 return NULL;
12188 }
12189 #endif
12190 p = (unsigned int*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned int), 0, NULL, NULL, NULL);
12191 if (*soap->href)
12192 p = (unsigned int*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned int), 0, NULL);
12193 else if (p)
12194 { if (soap_s2unsignedInt(soap, soap_value(soap), p))
12195 return NULL;
12196 }
12197 if (soap->body && soap_element_end_in(soap, tag))
12198 return NULL;
12199 return p;
12200 }
12201 #endif
12202
12203
12204 #ifndef PALM_2
12205 SOAP_FMAC1
12206 const char*
12207 SOAP_FMAC2
12208 soap_unsignedLong2s(struct soap *soap, unsigned long n)
12209 { sprintf(soap->tmpbuf, "%lu", n);
12210 return soap->tmpbuf;
12211 }
12212 #endif
12213
12214
12215 #ifndef PALM_2
12216 SOAP_FMAC1
12217 int
12218 SOAP_FMAC2
12219 soap_outunsignedLong(struct soap *soap, const char *tag, int id, const unsigned long *p, const char *type, int n)
12220 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
12221 || soap_string_out(soap, soap_unsignedLong2s(soap, *p), 0))
12222 return soap->error;
12223 return soap_element_end_out(soap, tag);
12224 }
12225 #endif
12226
12227
12228 #ifndef PALM_2
12229 SOAP_FMAC1
12230 int
12231 SOAP_FMAC2
12232 soap_s2unsignedLong(struct soap *soap, const char *s, unsigned long *p)
12233 { if (s)
12234 { char *r;
12235 #ifndef WITH_NOIO
12236 #ifndef WITH_LEAN
12237 soap_reset_errno;
12238 #endif
12239 #endif
12240 *p = soap_strtoul(s, &r, 10);
12241 if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
12242 #ifndef WITH_NOIO
12243 #ifndef WITH_LEAN
12244 || soap_errno == SOAP_ERANGE
12245 #endif
12246 #endif
12247 )
12248 soap->error = SOAP_TYPE;
12249 }
12250 return soap->error;
12251 }
12252 #endif
12253
12254
12255 #ifndef PALM_2
12256 SOAP_FMAC1
12257 unsigned long *
12258 SOAP_FMAC2
12259 soap_inunsignedLong(struct soap *soap, const char *tag, unsigned long *p, const char *type, int t)
12260 { if (soap_element_begin_in(soap, tag, 0, NULL))
12261 return NULL;
12262 #ifndef WITH_LEAN
12263 if (*soap->type
12264 && soap_match_tag(soap, soap->type, type)
12265 && soap_match_tag(soap, soap->type, ":unsignedInt")
12266 && soap_match_tag(soap, soap->type, ":unsignedShort")
12267 && soap_match_tag(soap, soap->type, ":unsignedByte"))
12268 { soap->error = SOAP_TYPE;
12269 soap_revert(soap);
12270 return NULL;
12271 }
12272 #endif
12273 p = (unsigned long*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned long), 0, NULL, NULL, NULL);
12274 if (*soap->href)
12275 p = (unsigned long*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned long), 0, NULL);
12276 else if (p)
12277 { if (soap_s2unsignedLong(soap, soap_value(soap), p))
12278 return NULL;
12279 }
12280 if (soap->body && soap_element_end_in(soap, tag))
12281 return NULL;
12282 return p;
12283 }
12284 #endif
12285
12286
12287 #ifndef WITH_LEAN
12288 SOAP_FMAC1
12289 const char*
12290 SOAP_FMAC2
12291 soap_ULONG642s(struct soap *soap, ULONG64 n)
12292 { sprintf(soap->tmpbuf, SOAP_ULONG_FORMAT, n);
12293 return soap->tmpbuf;
12294 }
12295 #endif
12296
12297
12298 #ifndef WITH_LEAN
12299 SOAP_FMAC1
12300 int
12301 SOAP_FMAC2
12302 soap_outULONG64(struct soap *soap, const char *tag, int id, const ULONG64 *p, const char *type, int n)
12303 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
12304 || soap_string_out(soap, soap_ULONG642s(soap, *p), 0))
12305 return soap->error;
12306 return soap_element_end_out(soap, tag);
12307 }
12308 #endif
12309
12310
12311 #ifndef WITH_LEAN
12312 SOAP_FMAC1
12313 int
12314 SOAP_FMAC2
12315 soap_s2ULONG64(struct soap *soap, const char *s, ULONG64 *p)
12316 { if (s)
12317 {
12318 #ifdef HAVE_STRTOULL
12319 char *r;
12320 #ifndef WITH_NOIO
12321 #ifndef WITH_LEAN
12322 soap_reset_errno;
12323 #endif
12324 #endif
12325 *p = strtoull(s, &r, 10);
12326 if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
12327 #ifndef WITH_NOIO
12328 #ifndef WITH_LEAN
12329 || soap_errno == SOAP_ERANGE
12330 #endif
12331 #endif
12332 )
12333 #else
12334 #ifdef HAVE_SSCANF
12335 if (sscanf(s, SOAP_ULONG_FORMAT, p) != 1)
12336 #endif
12337 #endif
12338 soap->error = SOAP_TYPE;
12339 }
12340 return soap->error;
12341 }
12342 #endif
12343
12344
12345 #ifndef WITH_LEAN
12346 SOAP_FMAC1
12347 ULONG64 *
12348 SOAP_FMAC2
12349 soap_inULONG64(struct soap *soap, const char *tag, ULONG64 *p, const char *type, int t)
12350 { if (soap_element_begin_in(soap, tag, 0, NULL))
12351 return NULL;
12352 if (*soap->type
12353 && soap_match_tag(soap, soap->type, type)
12354 && soap_match_tag(soap, soap->type, ":positiveInteger")
12355 && soap_match_tag(soap, soap->type, ":nonNegativeInteger")
12356 && soap_match_tag(soap, soap->type, ":unsignedLong")
12357 && soap_match_tag(soap, soap->type, ":unsignedInt")
12358 && soap_match_tag(soap, soap->type, ":unsignedShort")
12359 && soap_match_tag(soap, soap->type, ":unsignedByte"))
12360 { soap->error = SOAP_TYPE;
12361 soap_revert(soap);
12362 return NULL;
12363 }
12364 p = (ULONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(ULONG64), 0, NULL, NULL, NULL);
12365 if (*soap->href)
12366 p = (ULONG64*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(ULONG64), 0, NULL);
12367 else if (p)
12368 { if (soap_s2ULONG64(soap, soap_value(soap), p))
12369 return NULL;
12370 }
12371 if (soap->body && soap_element_end_in(soap, tag))
12372 return NULL;
12373 return p;
12374 }
12375 #endif
12376
12377
12378 #ifndef PALM_2
12379 SOAP_FMAC1
12380 int
12381 SOAP_FMAC2
12382 soap_s2string(struct soap *soap, const char *s, char **t, long minlen, long maxlen)
12383 { if (s)
12384 { long l = (long)strlen(s);
12385 if ((maxlen >= 0 && l > maxlen) || l < minlen)
12386 return soap->error = SOAP_LENGTH;
12387 if (!(*t = soap_strdup(soap, s)))
12388 return soap->error = SOAP_EOM;
12389 if (!(soap->mode & (SOAP_ENC_LATIN | SOAP_C_UTFSTRING)))
12390 { char *r = *t;
12391
12392 for (s = *t; *s; s++)
12393 if (!(*s & 0x80))
12394 *r++ = *s;
12395 *r = '\0';
12396 }
12397 }
12398 return soap->error;
12399 }
12400 #endif
12401
12402
12403 #ifndef PALM_2
12404 SOAP_FMAC1
12405 int
12406 SOAP_FMAC2
12407 soap_s2QName(struct soap *soap, const char *s, char **t, long minlen, long maxlen)
12408 { if (s)
12409 { long l = (long)strlen(s);
12410 if ((maxlen >= 0 && l > maxlen) || l < minlen)
12411 return soap->error = SOAP_LENGTH;
12412 soap->labidx = 0;
12413 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Normalized namespace(s) of QNames '%s'", s));
12414
12415 for (;;)
12416 { size_t n;
12417 struct soap_nlist *np;
12418 register const char *p;
12419
12420 while (*s && soap_blank((soap_wchar)*s))
12421 s++;
12422 if (!*s)
12423 break;
12424
12425 n = 1;
12426 while (s[n] && !soap_blank(s[n]))
12427 n++;
12428 np = soap->nlist;
12429
12430 if (!np || !strncmp(s, "xml:", 4))
12431 { soap_append_lab(soap, s, n);
12432 }
12433 else
12434 { const char *q;
12435 for (p = s; *p && p < s + n; p++)
12436 if (*p == ':')
12437 break;
12438 if (*p == ':')
12439 { size_t k = p - s;
12440 while (np && (strncmp(np->id, s, k) || np->id[k]))
12441 np = np->next;
12442 p++;
12443 }
12444 else
12445 { while (np && *np->id)
12446 np = np->next;
12447 p = s;
12448 }
12449
12450 if (np)
12451 { if (np->index >= 0 && soap->local_namespaces && (q = soap->local_namespaces[np->index].id))
12452 { size_t k = strlen(q);
12453 if (q[k-1] != '_')
12454 soap_append_lab(soap, q, k);
12455 else
12456 { soap_append_lab(soap, "\"", 1);
12457 soap_append_lab(soap, soap->local_namespaces[np->index].ns, strlen(soap->local_namespaces[np->index].ns));
12458 soap_append_lab(soap, "\"", 1);
12459 }
12460 }
12461 else if (np->ns)
12462 { soap_append_lab(soap, "\"", 1);
12463 soap_append_lab(soap, np->ns, strlen(np->ns));
12464 soap_append_lab(soap, "\"", 1);
12465 }
12466 else
12467 { 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));
12468 return soap->error = SOAP_NAMESPACE;
12469 }
12470 }
12471 else if (s[n])
12472 { soap_append_lab(soap, s, n);
12473 }
12474 else
12475 { soap_append_lab(soap, "\"\"", 2);
12476 }
12477 soap_append_lab(soap, ":", 1);
12478 soap_append_lab(soap, p, n - (p-s));
12479 }
12480
12481 s += n;
12482 if (*s)
12483 soap_append_lab(soap, " ", 1);
12484 }
12485 soap_append_lab(soap, SOAP_STR_EOS, 1);
12486 *t = soap_strdup(soap, soap->labbuf);
12487 DBGLOG(TEST, SOAP_MESSAGE(fdebug, " into '%s'\n", *t));
12488 }
12489 return soap->error;
12490 }
12491 #endif
12492
12493
12494 #ifndef PALM_2
12495 SOAP_FMAC1
12496 const char*
12497 SOAP_FMAC2
12498 soap_QName2s(struct soap *soap, const char *s)
12499 { const char *t = NULL;
12500 if (s)
12501 { soap->labidx = 0;
12502 for (;;)
12503 { size_t n;
12504
12505 while (*s && soap_blank((soap_wchar)*s))
12506 s++;
12507 if (!*s)
12508 break;
12509
12510 n = 1;
12511 while (s[n] && !soap_blank((soap_wchar)s[n]))
12512 n++;
12513
12514 if (*s != '"')
12515 { soap_append_lab(soap, s, n);
12516 #ifndef WITH_LEAN
12517 if ((soap->mode & SOAP_XML_CANONICAL))
12518 { const char *r = strchr(s, ':');
12519 if (r)
12520 soap_utilize_ns(soap, s, r - s);
12521 }
12522 #endif
12523 }
12524 else
12525 { const char *q;
12526 s++;
12527 q = strchr(s, '"');
12528 if (q)
12529 { struct Namespace *p = soap->local_namespaces;
12530 if (p)
12531 { for (; p->id; p++)
12532 { if (p->ns)
12533 if (!soap_tag_cmp(s, p->ns))
12534 break;
12535 if (p->in)
12536 if (!soap_tag_cmp(s, p->in))
12537 break;
12538 }
12539 }
12540
12541 if (p && p->id)
12542 { soap_append_lab(soap, p->id, strlen(p->id));
12543 }
12544 else
12545 { char *r = soap_strdup(soap, s);
12546 r[q-s] = '\0';
12547 sprintf(soap->tmpbuf, "xmlns:_%d", soap->idnum++);
12548 soap_set_attr(soap, soap->tmpbuf, r, 1);
12549 soap_append_lab(soap, soap->tmpbuf + 6, strlen(soap->tmpbuf + 6));
12550 }
12551 soap_append_lab(soap, q + 1, n - (q-s) - 1);
12552 }
12553 }
12554
12555 s += n;
12556 if (*s)
12557 soap_append_lab(soap, " ", 1);
12558 }
12559 soap_append_lab(soap, SOAP_STR_EOS, 1);
12560 t = soap_strdup(soap, soap->labbuf);
12561 }
12562 return t;
12563 }
12564 #endif
12565
12566
12567 #ifndef WITH_LEAN
12568 SOAP_FMAC1
12569 int
12570 SOAP_FMAC2
12571 soap_s2wchar(struct soap *soap, const char *s, wchar_t **t, long minlen, long maxlen)
12572 { if (s)
12573 { long l;
12574 wchar_t *r;
12575 *t = r = (wchar_t*)soap_malloc(soap, sizeof(wchar_t) * (strlen(s) + 1));
12576 if (!r)
12577 return soap->error = SOAP_EOM;
12578 if (soap->mode & SOAP_ENC_LATIN)
12579 { while (*s)
12580 *r++ = (wchar_t)*s++;
12581 }
12582 else
12583 {
12584 while (*s)
12585 { register soap_wchar c, c1, c2, c3, c4;
12586 c = (unsigned char)*s++;
12587 if (c < 0x80)
12588 *r++ = (wchar_t)c;
12589 else
12590 { c1 = (soap_wchar)*s++ & 0x3F;
12591 if (c < 0xE0)
12592 *r++ = (wchar_t)(((soap_wchar)(c & 0x1F) << 6) | c1);
12593 else
12594 { c2 = (soap_wchar)*s++ & 0x3F;
12595 if (c < 0xF0)
12596 *r++ = (wchar_t)(((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2);
12597 else
12598 { c3 = (soap_wchar)*s++ & 0x3F;
12599 if (c < 0xF8)
12600 *r++ = (wchar_t)(((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3);
12601 else
12602 { c4 = (soap_wchar)*s++ & 0x3F;
12603 if (c < 0xFC)
12604 *r++ = (wchar_t)(((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4);
12605 else
12606 *r++ = (wchar_t)(((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(*s++ & 0x3F));
12607 }
12608 }
12609 }
12610 }
12611 }
12612 }
12613 *r = L'\0';
12614 l = (long)(r - *t);
12615 if ((maxlen >= 0 && l > maxlen) || l < minlen)
12616 return soap->error = SOAP_LENGTH;
12617 }
12618 return soap->error;
12619 }
12620 #endif
12621
12622
12623 #ifndef WITH_LEAN
12624 SOAP_FMAC1
12625 const char*
12626 SOAP_FMAC2
12627 soap_wchar2s(struct soap *soap, const wchar_t *s)
12628 { register soap_wchar c;
12629 register char *r, *t;
12630 const wchar_t *q = s;
12631 size_t n = 0;
12632 while ((c = *q++))
12633 { if (c > 0 && c < 0x80)
12634 n++;
12635 else
12636 n += 6;
12637 }
12638 r = t = (char*)soap_malloc(soap, n + 1);
12639 if (r)
12640 {
12641 while ((c = *s++))
12642 { if (c > 0 && c < 0x80)
12643 *t++ = (char)c;
12644 else
12645 { if (c < 0x0800)
12646 *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
12647 else
12648 { if (c < 0x010000)
12649 *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
12650 else
12651 { if (c < 0x200000)
12652 *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
12653 else
12654 { if (c < 0x04000000)
12655 *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
12656 else
12657 { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
12658 *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
12659 }
12660 *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
12661 }
12662 *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
12663 }
12664 *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
12665 }
12666 *t++ = (char)(0x80 | (c & 0x3F));
12667 }
12668 }
12669 *t = '\0';
12670 }
12671 return r;
12672 }
12673 #endif
12674
12675
12676 #ifndef PALM_2
12677 SOAP_FMAC1
12678 int
12679 SOAP_FMAC2
12680 soap_outstring(struct soap *soap, const char *tag, int id, char *const*p, const char *type, int n)
12681 { id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n);
12682 if (id < 0)
12683 return soap->error;
12684 if (!**p && (soap->mode & SOAP_C_NILSTRING))
12685 return soap_element_null(soap, tag, id, type);
12686 if (soap_element_begin_out(soap, tag, id, type)
12687 || soap_string_out(soap, *p, 0)
12688 || soap_element_end_out(soap, tag))
12689 return soap->error;
12690 return SOAP_OK;
12691 }
12692 #endif
12693
12694
12695 #ifndef PALM_2
12696 SOAP_FMAC1
12697 char **
12698 SOAP_FMAC2
12699 soap_instring(struct soap *soap, const char *tag, char **p, const char *type, int t, int flag, long minlen, long maxlen)
12700 { if (soap_element_begin_in(soap, tag, 1, NULL))
12701 { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG)
12702 return NULL;
12703 soap->error = SOAP_OK;
12704 }
12705 if (!p)
12706 { if (!(p = (char**)soap_malloc(soap, sizeof(char*))))
12707 return NULL;
12708 }
12709 if (soap->null)
12710 *p = NULL;
12711 else if (soap->body)
12712 { *p = soap_string_in(soap, flag, minlen, maxlen);
12713 if (!*p || !(char*)soap_id_enter(soap, soap->id, *p, t, sizeof(char*), 0, NULL, NULL, NULL))
12714 return NULL;
12715 if (!**p && tag && *tag == '-')
12716 { soap->error = SOAP_NO_TAG;
12717 return NULL;
12718 }
12719 }
12720 else if (tag && *tag == '-')
12721 { soap->error = SOAP_NO_TAG;
12722 return NULL;
12723 }
12724 else if (!*soap->href && minlen > 0)
12725 { soap->error = SOAP_LENGTH;
12726 return NULL;
12727 }
12728 else
12729 *p = soap_strdup(soap, SOAP_STR_EOS);
12730 if (*soap->href)
12731 p = (char**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(char**), 0);
12732 if (soap->body && soap_element_end_in(soap, tag))
12733 return NULL;
12734 return p;
12735 }
12736 #endif
12737
12738
12739 #ifndef WITH_LEANER
12740 #ifndef PALM_2
12741 SOAP_FMAC1
12742 int
12743 SOAP_FMAC2
12744 soap_outwstring(struct soap *soap, const char *tag, int id, wchar_t *const*p, const char *type, int n)
12745 { id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n);
12746 if (id < 0)
12747 return soap->error;
12748 if (!**p && (soap->mode & SOAP_C_NILSTRING))
12749 return soap_element_null(soap, tag, id, type);
12750 if (soap_element_begin_out(soap, tag, id, type)
12751 || soap_wstring_out(soap, *p, 0)
12752 || soap_element_end_out(soap, tag))
12753 return soap->error;
12754 return SOAP_OK;
12755 }
12756 #endif
12757 #endif
12758
12759
12760 #ifndef WITH_LEANER
12761 #ifndef PALM_2
12762 SOAP_FMAC1
12763 wchar_t **
12764 SOAP_FMAC2
12765 soap_inwstring(struct soap *soap, const char *tag, wchar_t **p, const char *type, int t, long minlen, long maxlen)
12766 { if (soap_element_begin_in(soap, tag, 1, NULL))
12767 { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG)
12768 return NULL;
12769 soap->error = SOAP_OK;
12770 }
12771 if (!p)
12772 { if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*))))
12773 return NULL;
12774 }
12775 if (soap->body)
12776 { *p = soap_wstring_in(soap, 1, minlen, maxlen);
12777 if (!*p || !(wchar_t*)soap_id_enter(soap, soap->id, *p, t, sizeof(wchar_t*), 0, NULL, NULL, NULL))
12778 return NULL;
12779 if (!**p && tag && *tag == '-')
12780 { soap->error = SOAP_NO_TAG;
12781 return NULL;
12782 }
12783 }
12784 else if (tag && *tag == '-')
12785 { soap->error = SOAP_NO_TAG;
12786 return NULL;
12787 }
12788 else if (soap->null)
12789 *p = NULL;
12790 else
12791 *p = soap_wstrdup(soap, (wchar_t*)SOAP_STR_EOS);
12792 if (*soap->href)
12793 p = (wchar_t**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(wchar_t**), 0);
12794 if (soap->body && soap_element_end_in(soap, tag))
12795 return NULL;
12796 return p;
12797 }
12798 #endif
12799 #endif
12800
12801
12802 #ifndef WITH_LEAN
12803 SOAP_FMAC1
12804 time_t
12805 SOAP_FMAC2
12806 soap_timegm(struct tm *T)
12807 {
12808 #if defined(HAVE_TIMEGM)
12809 return timegm(T);
12810 #else
12811 time_t t, g, z;
12812 struct tm tm;
12813 t = mktime(T);
12814 if (t == (time_t)-1)
12815 return (time_t)-1;
12816 #ifdef HAVE_GMTIME_R
12817 gmtime_r(&t, &tm);
12818 #else
12819 tm = *gmtime(&t);
12820 #endif
12821 tm.tm_isdst = 0;
12822 g = mktime(&tm);
12823 if (g == (time_t)-1)
12824 return (time_t)-1;
12825 z = g - t;
12826 return t - z;
12827 #endif
12828 }
12829 #endif
12830
12831
12832 #ifndef WITH_LEAN
12833 SOAP_FMAC1
12834 const char*
12835 SOAP_FMAC2
12836 soap_dateTime2s(struct soap *soap, time_t n)
12837 { struct tm T, *pT = &T;
12838 #if defined(HAVE_GMTIME_R)
12839 if (gmtime_r(&n, pT))
12840 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT);
12841 #elif defined(HAVE_GMTIME)
12842 if ((pT = gmtime(&n)))
12843 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT);
12844 #elif defined(HAVE_GETTIMEOFDAY)
12845 struct timezone tz;
12846 memset((void*)&tz, 0, sizeof(tz));
12847 #if defined(HAVE_LOCALTIME_R)
12848 if (localtime_r(&n, pT))
12849 { struct timeval tv;
12850 gettimeofday(&tv, &tz);
12851 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
12852 sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60);
12853 }
12854 #else
12855 if ((pT = localtime(&n)))
12856 { struct timeval tv;
12857 gettimeofday(&tv, &tz);
12858 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
12859 sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60);
12860 }
12861 #endif
12862 #elif defined(HAVE_FTIME)
12863 struct timeb t;
12864 memset((void*)&t, 0, sizeof(t));
12865 #if defined(HAVE_LOCALTIME_R)
12866 if (localtime_r(&n, pT))
12867 {
12868 #ifdef __BORLANDC__
12869 ::ftime(&t);
12870 #else
12871 ftime(&t);
12872 #endif
12873 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
12874 sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60);
12875 }
12876 #else
12877 if ((pT = localtime(&n)))
12878 {
12879 #ifdef __BORLANDC__
12880 ::ftime(&t);
12881 #else
12882 ftime(&t);
12883 #endif
12884 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
12885 sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60);
12886 }
12887 #endif
12888 #elif defined(HAVE_LOCALTIME_R)
12889 if (localtime_r(&n, pT))
12890 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
12891 #else
12892 if ((pT = localtime(&n)))
12893 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
12894 #endif
12895 else
12896 strcpy(soap->tmpbuf, "1969-12-31T23:59:59Z");
12897 return soap->tmpbuf;
12898 }
12899 #endif
12900
12901
12902 #ifndef WITH_LEAN
12903 SOAP_FMAC1
12904 int
12905 SOAP_FMAC2
12906 soap_outdateTime(struct soap *soap, const char *tag, int id, const time_t *p, const char *type, int n)
12907 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
12908 || soap_string_out(soap, soap_dateTime2s(soap, *p), 0))
12909 return soap->error;
12910 return soap_element_end_out(soap, tag);
12911 }
12912 #endif
12913
12914
12915 #ifndef WITH_LEAN
12916 SOAP_FMAC1
12917 int
12918 SOAP_FMAC2
12919 soap_s2dateTime(struct soap *soap, const char *s, time_t *p)
12920 { if (s)
12921 { char zone[32];
12922 struct tm T;
12923 const char *t;
12924 *zone = '\0';
12925 memset((void*)&T, 0, sizeof(T));
12926 if (strchr(s, '-'))
12927 t = "%d-%d-%dT%d:%d:%d%31s";
12928 else if (strchr(s, ':'))
12929 t = "%4d%2d%2dT%d:%d:%d%31s";
12930 else
12931 t = "%4d%2d%2dT%2d%2d%2d%31s";
12932 if (sscanf(s, t, &T.tm_year, &T.tm_mon, &T.tm_mday, &T.tm_hour, &T.tm_min, &T.tm_sec, zone) < 6)
12933 return soap->error = SOAP_TYPE;
12934 if (T.tm_year == 1)
12935 T.tm_year = 70;
12936 else
12937 T.tm_year -= 1900;
12938 T.tm_mon--;
12939 if (*zone == '.')
12940 { for (s = zone + 1; *s; s++)
12941 if (*s < '0' || *s > '9')
12942 break;
12943 }
12944 else
12945 s = zone;
12946 if (*s)
12947 {
12948 #ifndef WITH_NOZONE
12949 if (*s == '+' || *s == '-')
12950 { int h = 0, m = 0;
12951 if (s[3] == ':')
12952 {
12953 sscanf(s, "%d:%d", &h, &m);
12954 if (h < 0)
12955 m = -m;
12956 }
12957 else
12958 { m = (int)soap_strtol(s, NULL, 10);
12959 h = m / 100;
12960 m = m % 100;
12961 }
12962 T.tm_min -= m;
12963 T.tm_hour -= h;
12964
12965 T.tm_hour += T.tm_min / 60;
12966 T.tm_min %= 60;
12967 if (T.tm_min < 0)
12968 { T.tm_min += 60;
12969 T.tm_hour--;
12970 }
12971 T.tm_mday += T.tm_hour / 24;
12972 T.tm_hour %= 24;
12973 if (T.tm_hour < 0)
12974 { T.tm_hour += 24;
12975 T.tm_mday--;
12976 }
12977
12978 }
12979 #endif
12980 *p = soap_timegm(&T);
12981 }
12982 else
12983 { T.tm_isdst = -1;
12984 *p = mktime(&T);
12985 }
12986 }
12987 return soap->error;
12988 }
12989 #endif
12990
12991
12992 #ifndef WITH_LEAN
12993 SOAP_FMAC1
12994 time_t *
12995 SOAP_FMAC2
12996 soap_indateTime(struct soap *soap, const char *tag, time_t *p, const char *type, int t)
12997 { if (soap_element_begin_in(soap, tag, 0, NULL))
12998 return NULL;
12999 if (*soap->type
13000 && soap_match_tag(soap, soap->type, type)
13001 && soap_match_tag(soap, soap->type, ":dateTime"))
13002 { soap->error = SOAP_TYPE;
13003 soap_revert(soap);
13004 return NULL;
13005 }
13006 p = (time_t*)soap_id_enter(soap, soap->id, p, t, sizeof(time_t), 0, NULL, NULL, NULL);
13007 if (*soap->href)
13008 p = (time_t*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(time_t), 0, NULL);
13009 else if (p)
13010 { if (soap_s2dateTime(soap, soap_value(soap), p))
13011 return NULL;
13012 }
13013 if (soap->body && soap_element_end_in(soap, tag))
13014 return NULL;
13015 return p;
13016 }
13017 #endif
13018
13019
13020 #ifndef PALM_2
13021 SOAP_FMAC1
13022 int
13023 SOAP_FMAC2
13024 soap_outliteral(struct soap *soap, const char *tag, char *const*p, const char *type)
13025 { int i;
13026 const char *t = NULL;
13027 if (tag && *tag != '-')
13028 { if (soap->local_namespaces && (t = strchr(tag, ':')))
13029 { strncpy(soap->tmpbuf, tag, t-tag);
13030 soap->tmpbuf[t-tag] = '\0';
13031 for (i = 0; soap->local_namespaces[i].id; i++)
13032 if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id))
13033 break;
13034 t++;
13035 if (soap_element(soap, t, 0, type)
13036 || soap_attribute(soap, "xmlns", soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS)
13037 || soap_element_start_end_out(soap, NULL))
13038 return soap->error;
13039 }
13040 else
13041 { t = tag;
13042 if (soap_element_begin_out(soap, t, 0, type))
13043 return soap->error;
13044 }
13045 }
13046 if (p && *p)
13047 { if (soap_send(soap, *p))
13048 return soap->error;
13049 }
13050 if (t)
13051 return soap_element_end_out(soap, t);
13052 return SOAP_OK;
13053 }
13054 #endif
13055
13056
13057 #ifndef PALM_2
13058 SOAP_FMAC1
13059 char **
13060 SOAP_FMAC2
13061 soap_inliteral(struct soap *soap, const char *tag, char **p)
13062 { if (soap_element_begin_in(soap, tag, 1, NULL))
13063 { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT)
13064 return NULL;
13065 soap->error = SOAP_OK;
13066 }
13067 if (!p)
13068 { if (!(p = (char**)soap_malloc(soap, sizeof(char*))))
13069 return NULL;
13070 }
13071 if (soap->body || (tag && *tag == '-'))
13072 { *p = soap_string_in(soap, 0, -1, -1);
13073 if (!*p)
13074 return NULL;
13075 if (!**p && tag && *tag == '-')
13076 { soap->error = SOAP_NO_TAG;
13077 return NULL;
13078 }
13079 }
13080 else if (soap->null)
13081 *p = NULL;
13082 else
13083 *p = soap_strdup(soap, SOAP_STR_EOS);
13084 if (soap->body && soap_element_end_in(soap, tag))
13085 return NULL;
13086 return p;
13087 }
13088 #endif
13089
13090
13091 #ifndef WITH_LEANER
13092 #ifndef PALM_2
13093 SOAP_FMAC1
13094 int
13095 SOAP_FMAC2
13096 soap_outwliteral(struct soap *soap, const char *tag, wchar_t *const*p, const char *type)
13097 { int i;
13098 const char *t = NULL;
13099 if (tag && *tag != '-')
13100 { if (soap->local_namespaces && (t = strchr(tag, ':')))
13101 { strncpy(soap->tmpbuf, tag, t-tag);
13102 soap->tmpbuf[t-tag] = '\0';
13103 for (i = 0; soap->local_namespaces[i].id; i++)
13104 if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id))
13105 break;
13106 t++;
13107 if (soap_element(soap, t, 0, type)
13108 || soap_attribute(soap, "xmlns", soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS)
13109 || soap_element_start_end_out(soap, NULL))
13110 return soap->error;
13111 }
13112 else
13113 { t = tag;
13114 if (soap_element_begin_out(soap, t, 0, type))
13115 return soap->error;
13116 }
13117 if (soap_send(soap, soap->tmpbuf))
13118 return soap->error;
13119 }
13120 if (p)
13121 { wchar_t c;
13122 const wchar_t *s = *p;
13123 while ((c = *s++))
13124 { if (soap_pututf8(soap, (unsigned long)c))
13125 return soap->error;
13126 }
13127 }
13128 if (t)
13129 return soap_element_end_out(soap, t);
13130 return SOAP_OK;
13131 }
13132 #endif
13133 #endif
13134
13135
13136 #ifndef WITH_LEANER
13137 #ifndef PALM_2
13138 SOAP_FMAC1
13139 wchar_t **
13140 SOAP_FMAC2
13141 soap_inwliteral(struct soap *soap, const char *tag, wchar_t **p)
13142 { if (soap_element_begin_in(soap, tag, 1, NULL))
13143 { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT)
13144 return NULL;
13145 soap->error = SOAP_OK;
13146 }
13147 if (!p)
13148 { if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*))))
13149 return NULL;
13150 }
13151 if (soap->body)
13152 { *p = soap_wstring_in(soap, 0, -1, -1);
13153 if (!*p)
13154 return NULL;
13155 if (!**p && tag && *tag == '-')
13156 { soap->error = SOAP_NO_TAG;
13157 return NULL;
13158 }
13159 }
13160 else if (tag && *tag == '-')
13161 { soap->error = SOAP_NO_TAG;
13162 return NULL;
13163 }
13164 else if (soap->null)
13165 *p = NULL;
13166 else
13167 *p = soap_wstrdup(soap, (wchar_t*)SOAP_STR_EOS);
13168 if (soap->body && soap_element_end_in(soap, tag))
13169 return NULL;
13170 return p;
13171 }
13172 #endif
13173 #endif
13174
13175
13176 #ifndef PALM_2
13177 SOAP_FMAC1
13178 const char *
13179 SOAP_FMAC2
13180 soap_value(struct soap *soap)
13181 { register size_t i;
13182 register soap_wchar c = 0;
13183 register char *s = soap->tmpbuf;
13184 if (!soap->body)
13185 return SOAP_STR_EOS;
13186 do c = soap_get(soap);
13187 while (soap_blank(c));
13188 for (i = 0; i < sizeof(soap->tmpbuf) - 1; i++)
13189 { if (c == SOAP_TT || c == SOAP_LT || (int)c == EOF)
13190 break;
13191 *s++ = (char)c;
13192 c = soap_get(soap);
13193 }
13194 for (s--; i > 0; i--, s--)
13195 { if (!soap_blank((soap_wchar)*s))
13196 break;
13197 }
13198 s[1] = '\0';
13199 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element content value='%s'\n", soap->tmpbuf));
13200 if (c == SOAP_TT || c == SOAP_LT || (int)c == EOF)
13201 soap_unget(soap, c);
13202 else if (soap->mode & SOAP_XML_STRICT)
13203 { soap->error = SOAP_LENGTH;
13204 return NULL;
13205 }
13206 #ifdef WITH_DOM
13207 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
13208 soap->dom->data = soap_strdup(soap, soap->tmpbuf);
13209 #endif
13210 return soap->tmpbuf;
13211 }
13212 #endif
13213
13214
13215 #if !defined(WITH_LEANER) || !defined(WITH_NOHTTP)
13216 #ifndef PALM_2
13217 SOAP_FMAC1
13218 int
13219 SOAP_FMAC2
13220 soap_getline(struct soap *soap, char *s, int len)
13221 { int i = len;
13222 soap_wchar c = 0;
13223 for (;;)
13224 { while (--i > 0)
13225 { c = soap_getchar(soap);
13226 if (c == '\r' || c == '\n')
13227 break;
13228 if ((int)c == EOF)
13229 return soap->error = SOAP_EOF;
13230 *s++ = (char)c;
13231 }
13232 if (c != '\n')
13233 c = soap_getchar(soap);
13234 if (c == '\n')
13235 { *s = '\0';
13236 if (i+1 == len)
13237 break;
13238 c = soap_get0(soap);
13239 if (c != ' ' && c != '\t')
13240 break;
13241 }
13242 else if ((int)c == EOF)
13243 return soap->error = SOAP_EOF;
13244 if (i < 0)
13245 return soap->error = SOAP_HDR;
13246 }
13247 return SOAP_OK;
13248 }
13249 #endif
13250 #endif
13251
13252
13253 #ifndef PALM_1
13254 static size_t
13255 soap_count_attachments(struct soap *soap)
13256 {
13257 #ifndef WITH_LEANER
13258 register struct soap_multipart *content;
13259 register size_t count = soap->count;
13260 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the message size with attachments, current count=%lu\n", (unsigned long)count));
13261 if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
13262 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of DIME attachments\n"));
13263 for (content = soap->dime.first; content; content = content->next)
13264 { count += 12 + ((content->size+3)&(~3));
13265 if (content->id)
13266 count += ((strlen(content->id)+3)&(~3));
13267 if (content->type)
13268 count += ((strlen(content->type)+3)&(~3));
13269 if (content->options)
13270 count += ((((unsigned char)content->options[2] << 8) | ((unsigned char)content->options[3]))+7)&(~3);
13271 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of DIME attachment content is %lu bytes\n", (unsigned long)content->size));
13272 }
13273 }
13274 if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary)
13275 { register size_t n = strlen(soap->mime.boundary);
13276 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of MIME attachments\n"));
13277 for (content = soap->mime.first; content; content = content->next)
13278 { register const char *s;
13279
13280 count += 6 + n;
13281
13282 if (content->type)
13283 count += 16 + strlen(content->type);
13284
13285 s = soap_code_str(mime_codes, content->encoding);
13286 if (s)
13287 count += 29 + strlen(s);
13288
13289 if (content->id)
13290 count += 14 + strlen(content->id);
13291
13292 if (content->location)
13293 count += 20 + strlen(content->location);
13294
13295 if (content->description)
13296 count += 23 + strlen(content->description);
13297
13298 count += 2 + content->size;
13299 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of MIME attachment content is %lu bytes\n", (unsigned long)content->size));
13300 }
13301
13302 count += 6 + n;
13303 }
13304 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New count is %lu bytes\n", (unsigned long)count));
13305 return count;
13306 #else
13307 return soap->count;
13308 #endif
13309 }
13310 #endif
13311
13312
13313 #ifndef WITH_LEANER
13314 #ifndef PALM_1
13315 static int
13316 soap_putdimefield(struct soap *soap, const char *s, size_t n)
13317 { if (soap_send_raw(soap, s, n))
13318 return soap->error;
13319 return soap_send_raw(soap, SOAP_STR_PADDING, -(long)n&3);
13320 }
13321 #endif
13322 #endif
13323
13324
13325 #ifndef WITH_LEANER
13326 #ifndef PALM_1
13327 SOAP_FMAC1
13328 char *
13329 SOAP_FMAC2
13330 soap_dime_option(struct soap *soap, unsigned short optype, const char *option)
13331 { size_t n;
13332 char *s = NULL;
13333 if (option)
13334 { n = strlen(option);
13335 s = (char*)soap_malloc(soap, n + 5);
13336 if (s)
13337 { s[0] = (char)(optype >> 8);
13338 s[1] = (char)(optype & 0xFF);
13339 s[2] = (char)(n >> 8);
13340 s[3] = (char)(n & 0xFF);
13341 strcpy(s + 4, option);
13342 }
13343 }
13344 return s;
13345 }
13346 #endif
13347 #endif
13348
13349
13350 #ifndef WITH_LEANER
13351 #ifndef PALM_1
13352 SOAP_FMAC1
13353 int
13354 SOAP_FMAC2
13355 soap_putdimehdr(struct soap *soap)
13356 { unsigned char tmp[12];
13357 size_t optlen = 0, idlen = 0, typelen = 0;
13358 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Put DIME header id='%s'\n", soap->dime.id?soap->dime.id:SOAP_STR_EOS));
13359 if (soap->dime.options)
13360 optlen = (((unsigned char)soap->dime.options[2] << 8) | ((unsigned char)soap->dime.options[3])) + 4;
13361 if (soap->dime.id)
13362 { idlen = strlen(soap->dime.id);
13363 if (idlen > 0x0000FFFF)
13364 idlen = 0x0000FFFF;
13365 }
13366 if (soap->dime.type)
13367 { typelen = strlen(soap->dime.type);
13368 if (typelen > 0x0000FFFF)
13369 typelen = 0x0000FFFF;
13370 }
13371 tmp[0] = SOAP_DIME_VERSION | (soap->dime.flags & 0x7);
13372 tmp[1] = soap->dime.flags & 0xF0;
13373 tmp[2] = (char)(optlen >> 8);
13374 tmp[3] = (char)(optlen & 0xFF);
13375 tmp[4] = (char)(idlen >> 8);
13376 tmp[5] = (char)(idlen & 0xFF);
13377 tmp[6] = (char)(typelen >> 8);
13378 tmp[7] = (char)(typelen & 0xFF);
13379 tmp[8] = (char)(soap->dime.size >> 24);
13380 tmp[9] = (char)((soap->dime.size >> 16) & 0xFF);
13381 tmp[10] = (char)((soap->dime.size >> 8) & 0xFF);
13382 tmp[11] = (char)(soap->dime.size & 0xFF);
13383 if (soap_send_raw(soap, (char*)tmp, 12)
13384 || soap_putdimefield(soap, soap->dime.options, optlen)
13385 || soap_putdimefield(soap, soap->dime.id, idlen)
13386 || soap_putdimefield(soap, soap->dime.type, typelen))
13387 return soap->error;
13388 return SOAP_OK;
13389 }
13390 #endif
13391 #endif
13392
13393
13394 #ifndef WITH_LEANER
13395 #ifndef PALM_1
13396 SOAP_FMAC1
13397 int
13398 SOAP_FMAC2
13399 soap_putdime(struct soap *soap)
13400 { struct soap_multipart *content;
13401 if (!(soap->mode & SOAP_ENC_DIME))
13402 return SOAP_OK;
13403 for (content = soap->dime.first; content; content = content->next)
13404 { void *handle;
13405 soap->dime.size = content->size;
13406 soap->dime.id = content->id;
13407 soap->dime.type = content->type;
13408 soap->dime.options = content->options;
13409 soap->dime.flags = SOAP_DIME_VERSION | SOAP_DIME_MEDIA;
13410 if (soap->fdimereadopen && ((handle = soap->fdimereadopen(soap, (void*)content->ptr, content->id, content->type, content->options)) || soap->error))
13411 { size_t size = content->size;
13412 if (!handle)
13413 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadopen failed\n"));
13414 return soap->error;
13415 }
13416 if (!size && ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE))
13417 { size_t chunksize = sizeof(soap->tmpbuf);
13418 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming DIME\n"));
13419 do
13420 { size = soap->fdimeread(soap, handle, soap->tmpbuf, chunksize);
13421 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread returned %lu bytes\n", (unsigned long)size));
13422 if (size < chunksize)
13423 { soap->dime.flags &= ~SOAP_DIME_CF;
13424 if (!content->next)
13425 soap->dime.flags |= SOAP_DIME_ME;
13426 }
13427 else
13428 soap->dime.flags |= SOAP_DIME_CF;
13429 soap->dime.size = size;
13430 if (soap_putdimehdr(soap)
13431 || soap_putdimefield(soap, soap->tmpbuf, size))
13432 break;
13433 if (soap->dime.id)
13434 { soap->dime.flags &= ~(SOAP_DIME_MB | SOAP_DIME_MEDIA);
13435 soap->dime.id = NULL;
13436 soap->dime.type = NULL;
13437 soap->dime.options = NULL;
13438 }
13439 } while (size >= chunksize);
13440 }
13441 else
13442 { if (!content->next)
13443 soap->dime.flags |= SOAP_DIME_ME;
13444 if (soap_putdimehdr(soap))
13445 return soap->error;
13446 do
13447 { size_t bufsize;
13448 if (size < sizeof(soap->tmpbuf))
13449 bufsize = size;
13450 else
13451 bufsize = sizeof(soap->tmpbuf);
13452 if (!(bufsize = soap->fdimeread(soap, handle, soap->tmpbuf, bufsize)))
13453 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size));
13454 soap->error = SOAP_EOF;
13455 break;
13456 }
13457 if (soap_send_raw(soap, soap->tmpbuf, bufsize))
13458 break;
13459 size -= bufsize;
13460 } while (size);
13461 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n"));
13462 soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3);
13463 }
13464 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n"));
13465 if (soap->fdimereadclose)
13466 soap->fdimereadclose(soap, handle);
13467 }
13468 else
13469 { if (!content->next)
13470 soap->dime.flags |= SOAP_DIME_ME;
13471 if (soap_putdimehdr(soap)
13472 || soap_putdimefield(soap, (char*)content->ptr, content->size))
13473 return soap->error;
13474 }
13475 }
13476 return SOAP_OK;
13477 }
13478 #endif
13479 #endif
13480
13481
13482 #ifndef WITH_LEANER
13483 #ifndef PALM_1
13484 static char *
13485 soap_getdimefield(struct soap *soap, size_t n)
13486 { register soap_wchar c;
13487 register size_t i;
13488 register char *s;
13489 register char *p = NULL;
13490 if (n)
13491 { p = (char*)soap_malloc(soap, n + 1);
13492 if (p)
13493 { s = p;
13494 for (i = n; i > 0; i--)
13495 { if ((int)(c = soap_get1(soap)) == EOF)
13496 { soap->error = SOAP_EOF;
13497 return NULL;
13498 }
13499 *s++ = (char)c;
13500 }
13501 *s = '\0';
13502 if ((soap->error = soap_move(soap, -(long)n&3)))
13503 return NULL;
13504 }
13505 else
13506 soap->error = SOAP_EOM;
13507 }
13508 return p;
13509 }
13510 #endif
13511 #endif
13512
13513
13514 #ifndef WITH_LEANER
13515 #ifndef PALM_1
13516 SOAP_FMAC1
13517 int
13518 SOAP_FMAC2
13519 soap_getdimehdr(struct soap *soap)
13520 { register soap_wchar c;
13521 register char *s;
13522 register int i;
13523 unsigned char tmp[12];
13524 size_t optlen, idlen, typelen;
13525 if (!(soap->mode & SOAP_ENC_DIME))
13526 return soap->error = SOAP_DIME_END;
13527 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME header\n"));
13528 if (soap->dime.buflen || soap->dime.chunksize)
13529 { if (soap_move(soap, (long)(soap->dime.size - soap_tell(soap))))
13530 return soap->error = SOAP_EOF;
13531 soap_unget(soap, soap_getchar(soap));
13532 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... From chunked\n"));
13533 return SOAP_OK;
13534 }
13535 s = (char*)tmp;
13536 for (i = 12; i > 0; i--)
13537 { if ((int)(c = soap_getchar(soap)) == EOF)
13538 return soap->error = SOAP_EOF;
13539 *s++ = (char)c;
13540 }
13541 if ((tmp[0] & 0xF8) != SOAP_DIME_VERSION)
13542 return soap->error = SOAP_DIME_MISMATCH;
13543 soap->dime.flags = (tmp[0] & 0x7) | (tmp[1] & 0xF0);
13544 optlen = (tmp[2] << 8) | tmp[3];
13545 idlen = (tmp[4] << 8) | tmp[5];
13546 typelen = (tmp[6] << 8) | tmp[7];
13547 soap->dime.size = (tmp[8] << 24) | (tmp[9] << 16) | (tmp[10] << 8) | tmp[11];
13548 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME size=%lu flags=0x%X\n", (unsigned long)soap->dime.size, soap->dime.flags));
13549 if (!(soap->dime.options = soap_getdimefield(soap, optlen)) && soap->error)
13550 return soap->error;
13551 if (!(soap->dime.id = soap_getdimefield(soap, idlen)) && soap->error)
13552 return soap->error;
13553 if (!(soap->dime.type = soap_getdimefield(soap, typelen)) && soap->error)
13554 return soap->error;
13555 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));
13556 if (soap->dime.flags & SOAP_DIME_ME)
13557 soap->mode &= ~SOAP_ENC_DIME;
13558 return SOAP_OK;
13559 }
13560 #endif
13561 #endif
13562
13563
13564 #ifndef WITH_LEANER
13565 #ifndef PALM_1
13566 SOAP_FMAC1
13567 int
13568 SOAP_FMAC2
13569 soap_getdime(struct soap *soap)
13570 { while (soap->dime.flags & SOAP_DIME_CF)
13571 { if (soap_getdimehdr(soap))
13572 return soap->error;
13573 if (soap_move(soap, (long)soap->dime.size))
13574 return soap->error = SOAP_EOF;
13575 }
13576 if (soap_move(soap, (long)(((soap->dime.size+3)&(~3))-soap_tell(soap))))
13577 return soap->error = SOAP_EOF;
13578 for (;;)
13579 { register struct soap_multipart *content;
13580 if (soap_getdimehdr(soap))
13581 break;
13582 if (soap->fdimewriteopen && ((soap->dime.ptr = (char*)soap->fdimewriteopen(soap, soap->dime.id, soap->dime.type, soap->dime.options)) || soap->error))
13583 { const char *id, *type, *options;
13584 size_t size, n;
13585 if (!soap->dime.ptr)
13586 return soap->error;
13587 id = soap->dime.id;
13588 type = soap->dime.type;
13589 options = soap->dime.options;
13590 for (;;)
13591 { size = soap->dime.size;
13592 for (;;)
13593 { n = soap->buflen - soap->bufidx;
13594 if (size < n)
13595 n = size;
13596 if ((soap->error = soap->fdimewrite(soap, (void*)soap->dime.ptr, soap->buf + soap->bufidx, n)))
13597 break;
13598 size -= n;
13599 if (!size)
13600 { soap->bufidx += n;
13601 break;
13602 }
13603 if (soap_recv(soap))
13604 { soap->error = SOAP_EOF;
13605 goto end;
13606 }
13607 }
13608 if (soap_move(soap, -(long)soap->dime.size&3))
13609 { soap->error = SOAP_EOF;
13610 break;
13611 }
13612 if (!(soap->dime.flags & SOAP_DIME_CF))
13613 break;
13614 if (soap_getdimehdr(soap))
13615 break;
13616 }
13617 end:
13618 if (soap->fdimewriteclose)
13619 soap->fdimewriteclose(soap, (void*)soap->dime.ptr);
13620 soap->dime.size = 0;
13621 soap->dime.id = id;
13622 soap->dime.type = type;
13623 soap->dime.options = options;
13624 }
13625 else if (soap->dime.flags & SOAP_DIME_CF)
13626 { const char *id, *type, *options;
13627 id = soap->dime.id;
13628 type = soap->dime.type;
13629 options = soap->dime.options;
13630 if (soap_new_block(soap) == NULL)
13631 return SOAP_EOM;
13632 for (;;)
13633 { register soap_wchar c;
13634 register size_t i;
13635 register char *s;
13636 s = (char*)soap_push_block(soap, NULL, soap->dime.size);
13637 if (!s)
13638 return soap->error = SOAP_EOM;
13639 for (i = soap->dime.size; i > 0; i--)
13640 { if ((int)(c = soap_get1(soap)) == EOF)
13641 return soap->error = SOAP_EOF;
13642 *s++ = (char)c;
13643 }
13644 if (soap_move(soap, -(long)soap->dime.size&3))
13645 return soap->error = SOAP_EOF;
13646 if (!(soap->dime.flags & SOAP_DIME_CF))
13647 break;
13648 if (soap_getdimehdr(soap))
13649 return soap->error;
13650 }
13651 soap->dime.size = soap->blist->size++;
13652 if (!(soap->dime.ptr = soap_save_block(soap, NULL, NULL, 0)))
13653 return soap->error;
13654 soap->dime.ptr[soap->dime.size] = '\0';
13655 soap->dime.id = id;
13656 soap->dime.type = type;
13657 soap->dime.options = options;
13658 }
13659 else
13660 soap->dime.ptr = soap_getdimefield(soap, soap->dime.size);
13661 content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, soap->dime.ptr, soap->dime.size);
13662 if (!content)
13663 return soap->error = SOAP_EOM;
13664 content->id = soap->dime.id;
13665 content->type = soap->dime.type;
13666 content->options = soap->dime.options;
13667 if (soap->error)
13668 return soap->error;
13669 soap_resolve_attachment(soap, content);
13670 }
13671 if (soap->error != SOAP_DIME_END)
13672 return soap->error;
13673 return soap->error = SOAP_OK;
13674 }
13675 #endif
13676 #endif
13677
13678
13679 #ifndef WITH_LEANER
13680 #ifndef PALM_1
13681 SOAP_FMAC1
13682 int
13683 SOAP_FMAC2
13684 soap_getmimehdr(struct soap *soap)
13685 { struct soap_multipart *content;
13686 do
13687 { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
13688 return soap->error;
13689 }
13690 while (!*soap->msgbuf);
13691 if (soap->msgbuf[0] == '-' && soap->msgbuf[1] == '-')
13692 { char *s = soap->msgbuf + strlen(soap->msgbuf) - 1;
13693
13694 while (soap_blank((soap_wchar)*s))
13695 s--;
13696 s[1] = '\0';
13697 if (soap->mime.boundary)
13698 { if (strcmp(soap->msgbuf + 2, soap->mime.boundary))
13699 return soap->error = SOAP_MIME_ERROR;
13700 }
13701 else
13702 soap->mime.boundary = soap_strdup(soap, soap->msgbuf + 2);
13703 if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
13704 return soap->error;
13705 }
13706 if (soap_set_mime_attachment(soap, NULL, 0, SOAP_MIME_NONE, NULL, NULL, NULL, NULL))
13707 return soap->error = SOAP_EOM;
13708 content = soap->mime.last;
13709 for (;;)
13710 { register char *key = soap->msgbuf;
13711 register char *val;
13712 if (!*key)
13713 break;
13714 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "MIME header: %s\n", key));
13715 val = strchr(soap->msgbuf, ':');
13716 if (val)
13717 { *val = '\0';
13718 do val++;
13719 while (*val && *val <= 32);
13720 if (!soap_tag_cmp(key, "Content-ID"))
13721 content->id = soap_strdup(soap, val);
13722 else if (!soap_tag_cmp(key, "Content-Location"))
13723 content->location = soap_strdup(soap, val);
13724 else if (!soap_tag_cmp(key, "Content-Disposition"))
13725 content->id = soap_strdup(soap, soap_get_header_attribute(soap, val, "name"));
13726 else if (!soap_tag_cmp(key, "Content-Type"))
13727 content->type = soap_strdup(soap, val);
13728 else if (!soap_tag_cmp(key, "Content-Description"))
13729 content->description = soap_strdup(soap, val);
13730 else if (!soap_tag_cmp(key, "Content-Transfer-Encoding"))
13731 content->encoding = (enum soap_mime_encoding)soap_code_int(mime_codes, val, (long)SOAP_MIME_NONE);
13732 }
13733 if (soap_getline(soap, key, sizeof(soap->msgbuf)))
13734 return soap->error;
13735 }
13736 return SOAP_OK;
13737 }
13738 #endif
13739 #endif
13740
13741
13742 #ifndef WITH_LEANER
13743 #ifndef PALM_1
13744 SOAP_FMAC1
13745 int
13746 SOAP_FMAC2
13747 soap_getmime(struct soap *soap)
13748 { while (soap_get_mime_attachment(soap, NULL))
13749 ;
13750 return soap->error;
13751 }
13752 #endif
13753 #endif
13754
13755
13756 #ifndef WITH_LEANER
13757 #ifndef PALM_1
13758 SOAP_FMAC1
13759 void
13760 SOAP_FMAC2
13761 soap_post_check_mime_attachments(struct soap *soap)
13762 { soap->imode |= SOAP_MIME_POSTCHECK;
13763 }
13764 #endif
13765 #endif
13766
13767
13768 #ifndef WITH_LEANER
13769 #ifndef PALM_1
13770 SOAP_FMAC1
13771 int
13772 SOAP_FMAC2
13773 soap_check_mime_attachments(struct soap *soap)
13774 { if (soap->mode & SOAP_MIME_POSTCHECK)
13775 return soap_get_mime_attachment(soap, NULL) != NULL;
13776 return SOAP_OK;
13777 }
13778 #endif
13779 #endif
13780
13781
13782 #ifndef WITH_LEANER
13783 #ifndef PALM_1
13784 SOAP_FMAC1
13785 struct soap_multipart *
13786 SOAP_FMAC2
13787 soap_get_mime_attachment(struct soap *soap, void *handle)
13788 { register soap_wchar c = 0;
13789 register size_t i, m = 0;
13790 register char *s, *t = NULL;
13791 register struct soap_multipart *content;
13792 register short flag = 0;
13793 if (!(soap->mode & SOAP_ENC_MIME))
13794 return NULL;
13795 content = soap->mime.last;
13796 if (!content)
13797 { if (soap_getmimehdr(soap))
13798 return NULL;
13799 content = soap->mime.last;
13800 }
13801 else if (content != soap->mime.first)
13802 { if (soap->fmimewriteopen && ((content->ptr = (char*)soap->fmimewriteopen(soap, (void*)handle, content->id, content->type, content->description, content->encoding)) || soap->error))
13803 { if (!content->ptr)
13804 return NULL;
13805 }
13806 }
13807 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));
13808 if (!content->ptr && soap_new_block(soap) == NULL)
13809 { soap->error = SOAP_EOM;
13810 return NULL;
13811 }
13812 for (;;)
13813 { if (content->ptr)
13814 s = soap->tmpbuf;
13815 else if (!(s = (char*)soap_push_block(soap, NULL, sizeof(soap->tmpbuf))))
13816 { soap->error = SOAP_EOM;
13817 return NULL;
13818 }
13819 for (i = 0; i < sizeof(soap->tmpbuf); i++)
13820 { if (m > 0)
13821 { *s++ = *t++;
13822 m--;
13823 }
13824 else
13825 { if (!flag)
13826 { c = soap_get1(soap);
13827 if ((int)c == EOF)
13828 { soap->error = SOAP_EOF;
13829 return NULL;
13830 }
13831 }
13832 if (flag || c == '\r')
13833 { t = soap->msgbuf;
13834 memset(t, 0, sizeof(soap->msgbuf));
13835 strcpy(t, "\n--");
13836 if (soap->mime.boundary)
13837 strncat(t, soap->mime.boundary, sizeof(soap->msgbuf)-4);
13838 do c = soap_getchar(soap);
13839 while (c == *t++);
13840 if ((int)c == EOF)
13841 { soap->error = SOAP_EOF;
13842 return NULL;
13843 }
13844 if (!*--t)
13845 goto end;
13846 *t = (char)c;
13847 flag = (c == '\r');
13848 m = t - soap->msgbuf + 1 - flag;
13849 t = soap->msgbuf;
13850 c = '\r';
13851 }
13852 *s++ = (char)c;
13853 }
13854 }
13855 if (content->ptr && soap->fmimewrite)
13856 { if ((soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i)))
13857 break;
13858 }
13859 }
13860 end:
13861 *s = '\0';
13862 if (content->ptr)
13863 { if (!soap->error && soap->fmimewrite)
13864 soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i);
13865 if (soap->fmimewriteclose)
13866 soap->fmimewriteclose(soap, (void*)content->ptr);
13867 if (soap->error)
13868 return NULL;
13869 }
13870 else
13871 { content->size = soap_size_block(soap, NULL, i+1)-1;
13872 content->ptr = soap_save_block(soap, NULL, NULL, 0);
13873 }
13874 soap_resolve_attachment(soap, content);
13875 if (c == '-' && soap_getchar(soap) == '-')
13876 { soap->mode &= ~SOAP_ENC_MIME;
13877 if ((soap->mode & SOAP_MIME_POSTCHECK) && soap_end_recv(soap))
13878 { if (soap->keep_alive < 0)
13879 soap->keep_alive = 0;
13880 soap_closesock(soap);
13881 return NULL;
13882 }
13883 }
13884 else
13885 { while (c != '\r' && (int)c != EOF && soap_blank(c))
13886 c = soap_getchar(soap);
13887 if (c != '\r' || soap_getchar(soap) != '\n')
13888 { soap->error = SOAP_MIME_ERROR;
13889 return NULL;
13890 }
13891 if (soap_getmimehdr(soap))
13892 return NULL;
13893 }
13894 return content;
13895 }
13896 #endif
13897 #endif
13898
13899
13900 #ifndef WITH_LEANER
13901 #ifndef PALM_1
13902 SOAP_FMAC1
13903 int
13904 SOAP_FMAC2
13905 soap_match_cid(struct soap *soap, const char *s, const char *t)
13906 { register size_t n;
13907 if (!s)
13908 return 1;
13909 if (!strcmp(s, t))
13910 return 0;
13911 if (!strncmp(s, "cid:", 4))
13912 s += 4;
13913 n = strlen(t);
13914 if (*t == '<')
13915 { t++;
13916 n -= 2;
13917 }
13918 if (!strncmp(s, t, n) && !s[n])
13919 return 0;
13920 soap_decode(soap->tmpbuf, sizeof(soap->tmpbuf), s, SOAP_STR_EOS);
13921 if (!strncmp(soap->tmpbuf, t, n) && !soap->tmpbuf[n])
13922 return 0;
13923 return 1;
13924 }
13925 #endif
13926 #endif
13927
13928
13929 #ifndef WITH_LEANER
13930 #ifndef PALM_1
13931 static void
13932 soap_resolve_attachment(struct soap *soap, struct soap_multipart *content)
13933 { if (content->id)
13934 { register struct soap_xlist **xp = &soap->xlist;
13935 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving attachment data for id=%s\n", content->id));
13936 while (*xp)
13937 { register struct soap_xlist *xq = *xp;
13938 if (!soap_match_cid(soap, xq->id, content->id))
13939 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Found matching attachment %s for content id=%s\n", xq->id, content->id));
13940 *xp = xq->next;
13941 *xq->ptr = (unsigned char*)content->ptr;
13942 *xq->size = (int)content->size;
13943 *xq->type = (char*)content->type;
13944 if (content->options)
13945 *xq->options = (char*)content->options;
13946 else
13947 *xq->options = (char*)content->description;
13948 SOAP_FREE(soap, xq);
13949 }
13950 else
13951 xp = &(*xp)->next;
13952 }
13953 }
13954 }
13955 #endif
13956 #endif
13957
13958
13959 #ifndef WITH_LEANER
13960 #ifndef PALM_1
13961 SOAP_FMAC1
13962 int
13963 SOAP_FMAC2
13964 soap_putmimehdr(struct soap *soap, struct soap_multipart *content)
13965 { const char *s;
13966 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "MIME attachment type=%s\n", content->type?content->type:SOAP_STR_EOS));
13967 if (soap_send3(soap, "\r\n--", soap->mime.boundary, "\r\n"))
13968 return soap->error;
13969 if (content->type && soap_send3(soap, "Content-Type: ", content->type, "\r\n"))
13970 return soap->error;
13971 s = soap_code_str(mime_codes, content->encoding);
13972 if (s && soap_send3(soap, "Content-Transfer-Encoding: ", s, "\r\n"))
13973 return soap->error;
13974 if (content->id && soap_send3(soap, "Content-ID: ", content->id, "\r\n"))
13975 return soap->error;
13976 if (content->location && soap_send3(soap, "Content-Location: ", content->location, "\r\n"))
13977 return soap->error;
13978 if (content->description && soap_send3(soap, "Content-Description: ", content->description, "\r\n"))
13979 return soap->error;
13980 return soap_send_raw(soap, "\r\n", 2);
13981 }
13982 #endif
13983 #endif
13984
13985
13986 #ifndef WITH_LEANER
13987 #ifndef PALM_1
13988 SOAP_FMAC1
13989 int
13990 SOAP_FMAC2
13991 soap_putmime(struct soap *soap)
13992 { struct soap_multipart *content;
13993 if (!(soap->mode & SOAP_ENC_MIME) || !soap->mime.boundary)
13994 return SOAP_OK;
13995 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending MIME attachments\n"));
13996 for (content = soap->mime.first; content; content = content->next)
13997 { void *handle;
13998 if (soap->fmimereadopen && ((handle = soap->fmimereadopen(soap, (void*)content->ptr, content->id, content->type, content->description)) || soap->error))
13999 { size_t size = content->size;
14000 if (!handle)
14001 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimereadopen failed\n"));
14002 return soap->error;
14003 }
14004 if (soap_putmimehdr(soap, content))
14005 return soap->error;
14006 if (!size)
14007 { if ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE)
14008 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming MIME\n"));
14009 do
14010 { size = soap->fmimeread(soap, handle, soap->tmpbuf, sizeof(soap->tmpbuf));
14011 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread returned %lu bytes\n", (unsigned long)size));
14012 if (soap_send_raw(soap, soap->tmpbuf, size))
14013 break;
14014 } while (size);
14015 }
14016 else
14017 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error: cannot chunk streaming MIME (no HTTP chunking)\n"));
14018 }
14019 }
14020 else
14021 { do
14022 { size_t bufsize;
14023 if (size < sizeof(soap->tmpbuf))
14024 bufsize = size;
14025 else
14026 bufsize = sizeof(soap->tmpbuf);
14027 if (!(bufsize = soap->fmimeread(soap, handle, soap->tmpbuf, bufsize)))
14028 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size));
14029 soap->error = SOAP_EOF;
14030 break;
14031 }
14032 if (soap_send_raw(soap, soap->tmpbuf, bufsize))
14033 break;
14034 size -= bufsize;
14035 } while (size);
14036 }
14037 if (soap->fmimereadclose)
14038 soap->fmimereadclose(soap, handle);
14039 }
14040 else
14041 { if (soap_putmimehdr(soap, content)
14042 || soap_send_raw(soap, content->ptr, content->size))
14043 return soap->error;
14044 }
14045 }
14046 return soap_send3(soap, "\r\n--", soap->mime.boundary, "--");
14047 }
14048 #endif
14049 #endif
14050
14051
14052 #ifndef WITH_LEANER
14053 #ifndef PALM_1
14054 SOAP_FMAC1
14055 void
14056 SOAP_FMAC2
14057 soap_set_dime(struct soap *soap)
14058 { soap->omode |= SOAP_ENC_DIME;
14059 soap->dime.first = NULL;
14060 soap->dime.last = NULL;
14061 }
14062 #endif
14063 #endif
14064
14065
14066 #ifndef WITH_LEANER
14067 #ifndef PALM_1
14068 SOAP_FMAC1
14069 void
14070 SOAP_FMAC2
14071 soap_set_mime(struct soap *soap, const char *boundary, const char *start)
14072 { soap->omode |= SOAP_ENC_MIME;
14073 soap->mime.first = NULL;
14074 soap->mime.last = NULL;
14075 soap->mime.boundary = soap_strdup(soap, boundary);
14076 soap->mime.start = soap_strdup(soap, start);
14077 }
14078 #endif
14079 #endif
14080
14081
14082 #ifndef WITH_LEANER
14083 #ifndef PALM_1
14084 SOAP_FMAC1
14085 void
14086 SOAP_FMAC2
14087 soap_clr_dime(struct soap *soap)
14088 { soap->omode &= ~SOAP_ENC_DIME;
14089 soap->dime.first = NULL;
14090 soap->dime.last = NULL;
14091 }
14092 #endif
14093 #endif
14094
14095
14096 #ifndef WITH_LEANER
14097 #ifndef PALM_1
14098 SOAP_FMAC1
14099 void
14100 SOAP_FMAC2
14101 soap_clr_mime(struct soap *soap)
14102 { soap->omode &= ~SOAP_ENC_MIME;
14103 soap->mime.first = NULL;
14104 soap->mime.last = NULL;
14105 soap->mime.boundary = NULL;
14106 soap->mime.start = NULL;
14107 }
14108 #endif
14109 #endif
14110
14111
14112 #ifndef WITH_LEANER
14113 #ifndef PALM_1
14114 static struct soap_multipart*
14115 soap_new_multipart(struct soap *soap, struct soap_multipart **first, struct soap_multipart **last, char *ptr, size_t size)
14116 { struct soap_multipart *content;
14117 content = (struct soap_multipart*)soap_malloc(soap, sizeof(struct soap_multipart));
14118 if (content)
14119 { content->next = NULL;
14120 content->ptr = ptr;
14121 content->size = size;
14122 content->id = NULL;
14123 content->type = NULL;
14124 content->options = NULL;
14125 content->encoding = SOAP_MIME_NONE;
14126 content->location = NULL;
14127 content->description = NULL;
14128 if (!*first)
14129 *first = content;
14130 if (*last)
14131 (*last)->next = content;
14132 *last = content;
14133 }
14134 return content;
14135 }
14136 #endif
14137 #endif
14138
14139
14140 #ifndef WITH_LEANER
14141 #ifndef PALM_1
14142 SOAP_FMAC1
14143 int
14144 SOAP_FMAC2
14145 soap_set_dime_attachment(struct soap *soap, char *ptr, size_t size, const char *type, const char *id, unsigned short optype, const char *option)
14146 { struct soap_multipart *content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, ptr, size);
14147 if (!content)
14148 return SOAP_EOM;
14149 content->id = soap_strdup(soap, id);
14150 content->type = soap_strdup(soap, type);
14151 content->options = soap_dime_option(soap, optype, option);
14152 return SOAP_OK;
14153 }
14154 #endif
14155 #endif
14156
14157
14158 #ifndef WITH_LEANER
14159 #ifndef PALM_1
14160 SOAP_FMAC1
14161 int
14162 SOAP_FMAC2
14163 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)
14164 { struct soap_multipart *content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, ptr, size);
14165 if (!content)
14166 return SOAP_EOM;
14167 content->id = soap_strdup(soap, id);
14168 content->type = soap_strdup(soap, type);
14169 content->encoding = encoding;
14170 content->location = soap_strdup(soap, location);
14171 content->description = soap_strdup(soap, description);
14172 return SOAP_OK;
14173 }
14174 #endif
14175 #endif
14176
14177
14178 #ifndef WITH_LEANER
14179 #ifndef PALM_1
14180 SOAP_FMAC1
14181 struct soap_multipart*
14182 SOAP_FMAC2
14183 soap_next_multipart(struct soap_multipart *content)
14184 { if (content)
14185 return content->next;
14186 return NULL;
14187 }
14188 #endif
14189 #endif
14190
14191
14192 #ifndef WITH_LEANER
14193 #ifndef PALM_1
14194 static void
14195 soap_select_mime_boundary(struct soap *soap)
14196 { while (!soap->mime.boundary || soap_valid_mime_boundary(soap))
14197 { register char *s = soap->mime.boundary;
14198 register size_t n = 0;
14199 if (s)
14200 n = strlen(s);
14201 if (n < 16)
14202 { n = 64;
14203 s = soap->mime.boundary = (char*)soap_malloc(soap, n + 1);
14204 if (!s)
14205 return;
14206 }
14207 strcpy(s, "==");
14208 s += 2;
14209 n -= 4;
14210 while (n)
14211 { *s++ = soap_base64o[soap_random & 0x3F];
14212 n--;
14213 }
14214 strcpy(s, "==");
14215 }
14216 if (!soap->mime.start)
14217 soap->mime.start = "<SOAP-ENV:Envelope>";
14218 }
14219 #endif
14220 #endif
14221
14222
14223 #ifndef WITH_LEANER
14224 #ifndef PALM_1
14225 static int
14226 soap_valid_mime_boundary(struct soap *soap)
14227 { register struct soap_multipart *content;
14228 register size_t k;
14229 if (soap->fmimeread)
14230 return SOAP_OK;
14231 k = strlen(soap->mime.boundary);
14232 for (content = soap->mime.first; content; content = content->next)
14233 { if (content->ptr && content->size >= k)
14234 { register const char *p = (const char*)content->ptr;
14235 register size_t i;
14236 for (i = 0; i < content->size - k; i++, p++)
14237 { if (!strncmp(p, soap->mime.boundary, k))
14238 return SOAP_ERR;
14239 }
14240 }
14241 }
14242 return SOAP_OK;
14243 }
14244 #endif
14245 #endif
14246
14247
14248 #ifdef WITH_GZIP
14249 #ifndef PALM_1
14250 static int
14251 soap_getgziphdr(struct soap *soap)
14252 { int i;
14253 soap_wchar c = 0, f = 0;
14254 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get gzip header\n"));
14255 for (i = 0; i < 9; i++)
14256 { if ((int)(c = soap_get1(soap) == EOF))
14257 return soap->error = SOAP_EOF;
14258 if (i == 1 && c == 8)
14259 soap->z_dict = 0;
14260 if (i == 2)
14261 f = c;
14262 }
14263 if (f & 0x04)
14264 { for (i = soap_get1(soap) | (soap_get1(soap) << 8); i; i--)
14265 { if ((int)soap_get1(soap) == EOF)
14266 return soap->error = SOAP_EOF;
14267 }
14268 }
14269 if (f & 0x08)
14270 { do
14271 c = soap_get1(soap);
14272 while (c && (int)c != EOF);
14273 }
14274 if ((int)c != EOF && (f & 0x10))
14275 { do
14276 c = soap_get1(soap);
14277 while (c && (int)c != EOF);
14278 }
14279 if ((int)c != EOF && (f & 0x02))
14280 { if ((int)(c = soap_get1(soap)) != EOF)
14281 c = soap_get1(soap);
14282 }
14283 if ((int)c == EOF)
14284 return soap->error = SOAP_EOF;
14285 return SOAP_OK;
14286 }
14287 #endif
14288 #endif
14289
14290
14291 #ifndef PALM_1
14292 SOAP_FMAC1
14293 int
14294 SOAP_FMAC2
14295 soap_begin_serve(struct soap *soap)
14296 {
14297 #ifdef WITH_FASTCGI
14298 if (FCGI_Accept() < 0)
14299 { soap->error = SOAP_EOF;
14300 return soap_send_fault(soap);
14301 }
14302 #endif
14303 soap_begin(soap);
14304 if (soap_begin_recv(soap))
14305 { if (soap->error < SOAP_STOP)
14306 {
14307 #ifdef WITH_FASTCGI
14308 soap_send_fault(soap);
14309 #else
14310 return soap_send_fault(soap);
14311 #endif
14312 }
14313 return soap_closesock(soap);
14314 }
14315 if (soap_envelope_begin_in(soap)
14316 || soap_recv_header(soap)
14317 || soap_body_begin_in(soap))
14318 return soap->error;
14319 return SOAP_OK;
14320 }
14321 #endif
14322
14323
14324 #ifndef PALM_1
14325 SOAP_FMAC1
14326 int
14327 SOAP_FMAC2
14328 soap_begin_recv(struct soap *soap)
14329 { soap_wchar c;
14330 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing for input\n"));
14331 soap->error = SOAP_OK;
14332 soap->filterstop = SOAP_OK;
14333 soap_free_temp(soap);
14334 soap_set_local_namespaces(soap);
14335 soap->version = 0;
14336 #ifndef WITH_NOIDREF
14337 soap_free_iht(soap);
14338 #endif
14339 if ((soap->imode & SOAP_IO) == SOAP_IO_CHUNK)
14340 soap->omode |= SOAP_IO_CHUNK;
14341 soap->imode &= ~(SOAP_IO | SOAP_ENC_MIME);
14342 soap->mode = soap->imode;
14343 if (!soap->keep_alive)
14344 { soap->buflen = 0;
14345 soap->bufidx = 0;
14346 }
14347 if (!(soap->mode & SOAP_IO_KEEPALIVE))
14348 soap->keep_alive = 0;
14349 soap->ahead = 0;
14350 soap->peeked = 0;
14351 soap->level = 0;
14352 soap->part = SOAP_BEGIN;
14353 soap->alloced = 0;
14354 soap->count = 0;
14355 soap->length = 0;
14356 soap->cdata = 0;
14357 *soap->endpoint = '\0';
14358 soap->action = NULL;
14359 soap->header = NULL;
14360 soap->fault = NULL;
14361 soap->status = 0;
14362 #ifndef WITH_LEANER
14363 soap->dom = NULL;
14364 soap->dime.chunksize = 0;
14365 soap->dime.buflen = 0;
14366 soap->dime.list = NULL;
14367 soap->dime.first = NULL;
14368 soap->dime.last = NULL;
14369 soap->mime.list = NULL;
14370 soap->mime.first = NULL;
14371 soap->mime.last = NULL;
14372 soap->mime.boundary = NULL;
14373 soap->mime.start = NULL;
14374 #endif
14375 #ifdef WIN32
14376 #ifndef UNDER_CE
14377 #ifndef WITH_FASTCGI
14378 if (!soap_valid_socket(soap->socket))
14379 #ifdef __BORLANDC__
14380 setmode(soap->recvfd, _O_BINARY);
14381 #else
14382 _setmode(soap->recvfd, _O_BINARY);
14383 #endif
14384 #endif
14385 #endif
14386 #endif
14387 #ifdef WITH_ZLIB
14388 soap->mode &= ~SOAP_ENC_ZLIB;
14389 soap->zlib_in = SOAP_ZLIB_NONE;
14390 soap->zlib_out = SOAP_ZLIB_NONE;
14391 soap->d_stream->next_in = Z_NULL;
14392 soap->d_stream->avail_in = 0;
14393 soap->d_stream->next_out = (Byte*)soap->buf;
14394 soap->d_stream->avail_out = SOAP_BUFLEN;
14395 soap->z_ratio_in = 1.0;
14396 #endif
14397 #ifdef WITH_OPENSSL
14398 if (soap->ssl)
14399 ERR_clear_error();
14400 #endif
14401 #ifndef WITH_LEANER
14402 if (soap->fprepareinitrecv && (soap->error = soap->fprepareinitrecv(soap)))
14403 return soap->error;
14404 #endif
14405 c = soap_getchar(soap);
14406 #ifdef WITH_GZIP
14407 if (c == 0x1F)
14408 { if (soap_getgziphdr(soap))
14409 return soap->error;
14410 if (inflateInit2(soap->d_stream, -MAX_WBITS) != Z_OK)
14411 return soap->error = SOAP_ZLIB_ERROR;
14412 if (soap->z_dict)
14413 { if (inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len) != Z_OK)
14414 return soap->error = SOAP_ZLIB_ERROR;
14415 }
14416 soap->zlib_state = SOAP_ZLIB_INFLATE;
14417 soap->mode |= SOAP_ENC_ZLIB;
14418 soap->zlib_in = SOAP_ZLIB_GZIP;
14419 soap->z_crc = crc32(0L, NULL, 0);
14420 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n"));
14421 if (!soap->z_buf)
14422 soap->z_buf = (char*)SOAP_MALLOC(soap, SOAP_BUFLEN);
14423 memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN);
14424
14425
14426
14427
14428 soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx);
14429 soap->d_stream->avail_in = (unsigned int)(soap->buflen - soap->bufidx);
14430 soap->z_buflen = soap->buflen;
14431 soap->buflen = soap->bufidx;
14432 c = ' ';
14433 }
14434 #endif
14435 while (soap_blank(c))
14436 c = soap_getchar(soap);
14437 #ifndef WITH_LEANER
14438 if (c == '-' && soap_get0(soap) == '-')
14439 soap->mode |= SOAP_ENC_MIME;
14440 else if ((c & 0xFFFC) == (SOAP_DIME_VERSION | SOAP_DIME_MB) && (soap_get0(soap) & 0xFFF0) == 0x20)
14441 soap->mode |= SOAP_ENC_DIME;
14442 else
14443 #endif
14444 {
14445 if (c == 0xEF && (c = soap_get1(soap)) == 0xBB && (c = soap_get1(soap)) == 0xBF)
14446 { soap->mode &= ~SOAP_ENC_LATIN;
14447 c = soap_getchar(soap);
14448 }
14449 else
14450 {
14451 if ((c == 0xFE && soap_get1(soap) == 0xFF)
14452 || (c == 0xFF && soap_get1(soap) == 0xFE))
14453 return soap->error = SOAP_UTF_ERROR;
14454 }
14455
14456 while (soap_blank(c))
14457 c = soap_getchar(soap);
14458 }
14459 if ((int)c == EOF)
14460 return soap->error = SOAP_EOF;
14461 soap_unget(soap, c);
14462 #ifndef WITH_NOHTTP
14463
14464 if (c != '<' && !(soap->mode & (SOAP_ENC_MIME | SOAP_ENC_DIME | SOAP_ENC_ZLIB)))
14465 { soap_mode m = soap->imode;
14466 soap->mode &= ~SOAP_IO;
14467 soap->error = soap->fparse(soap);
14468 if (soap->error && soap->error < SOAP_STOP)
14469 { soap->keep_alive = 0;
14470 return soap->error;
14471 }
14472 if (soap->error == SOAP_STOP)
14473 return soap->error;
14474 soap->mode = soap->imode;
14475 soap->imode = m;
14476 #ifdef WITH_ZLIB
14477 soap->mode &= ~SOAP_ENC_ZLIB;
14478 #endif
14479 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
14480 { soap->chunkbuflen = soap->buflen;
14481 soap->buflen = soap->bufidx;
14482 soap->chunksize = 0;
14483 }
14484
14485 if (soap_get0(soap) == (int)EOF)
14486 { if (soap->status == 200)
14487 return soap->error = SOAP_NO_DATA;
14488 return soap->error = soap->status;
14489 }
14490 #ifdef WITH_ZLIB
14491 if (soap->zlib_in != SOAP_ZLIB_NONE)
14492 {
14493 #ifdef WITH_GZIP
14494 if (soap->zlib_in != SOAP_ZLIB_DEFLATE)
14495 { c = soap_get1(soap);
14496 if (c == 0x1F)
14497 { if (soap_getgziphdr(soap))
14498 return soap->error;
14499 if (inflateInit2(soap->d_stream, -MAX_WBITS) != Z_OK)
14500 return soap->error = SOAP_ZLIB_ERROR;
14501 soap->z_crc = crc32(0L, NULL, 0);
14502 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n"));
14503 }
14504 else
14505 { soap_revget1(soap);
14506 if (inflateInit(soap->d_stream) != Z_OK)
14507 return soap->error = SOAP_ZLIB_ERROR;
14508 soap->zlib_in = SOAP_ZLIB_DEFLATE;
14509 }
14510 }
14511 else
14512 #endif
14513 if (inflateInit(soap->d_stream) != Z_OK)
14514 return soap->error = SOAP_ZLIB_ERROR;
14515 if (soap->z_dict)
14516 { if (inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len) != Z_OK)
14517 return soap->error = SOAP_ZLIB_ERROR;
14518 }
14519 soap->zlib_state = SOAP_ZLIB_INFLATE;
14520 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate initialized\n"));
14521 soap->mode |= SOAP_ENC_ZLIB;
14522 if (!soap->z_buf)
14523 soap->z_buf = (char*)SOAP_MALLOC(soap, SOAP_BUFLEN);
14524 memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN);
14525 soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx);
14526 soap->d_stream->avail_in = (unsigned int)(soap->buflen - soap->bufidx);
14527 soap->z_buflen = soap->buflen;
14528 soap->buflen = soap->bufidx;
14529 }
14530 #endif
14531 #ifndef WITH_LEANER
14532 if (soap->fpreparerecv && (soap->mode & SOAP_IO) != SOAP_IO_CHUNK && soap->buflen > soap->bufidx)
14533 { int r;
14534 if ((r = soap->fpreparerecv(soap, soap->buf + soap->bufidx, soap->buflen - soap->bufidx)))
14535 return soap->error = r;
14536 }
14537 #endif
14538 if (soap->error)
14539 { if (soap->error == SOAP_FORM && soap->fform)
14540 { soap->error = soap->fform(soap);
14541 if (soap->error == SOAP_OK)
14542 soap->error = SOAP_STOP;
14543 }
14544 return soap->error;
14545 }
14546 }
14547 #endif
14548 #ifndef WITH_LEANER
14549 if (soap->mode & SOAP_ENC_MIME)
14550 { do
14551 { if ((int)(c = soap_getchar(soap)) == EOF)
14552 return soap->error = SOAP_EOF;
14553 } while (c != '-' || soap_get0(soap) != '-');
14554 soap_unget(soap, c);
14555 if (soap_getmimehdr(soap))
14556 return soap->error;
14557 if (soap->mime.start)
14558 { do
14559 { if (!soap->mime.last->id)
14560 break;
14561 if (!soap_match_cid(soap, soap->mime.start, soap->mime.last->id))
14562 break;
14563 } while (soap_get_mime_attachment(soap, NULL));
14564 }
14565 if (soap_get_header_attribute(soap, soap->mime.first->type, "application/dime"))
14566 soap->mode |= SOAP_ENC_DIME;
14567 }
14568 if (soap->mode & SOAP_ENC_DIME)
14569 { if (soap_getdimehdr(soap))
14570 return soap->error;
14571 if (soap->dime.flags & SOAP_DIME_CF)
14572 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked DIME SOAP message\n"));
14573 soap->dime.chunksize = soap->dime.size;
14574 if (soap->buflen - soap->bufidx >= soap->dime.chunksize)
14575 { soap->dime.buflen = soap->buflen;
14576 soap->buflen = soap->bufidx + soap->dime.chunksize;
14577 }
14578 else
14579 soap->dime.chunksize -= soap->buflen - soap->bufidx;
14580 }
14581 soap->count = soap->buflen - soap->bufidx;
14582 }
14583 #endif
14584 return SOAP_OK;
14585 }
14586 #endif
14587
14588
14589 #ifndef PALM_2
14590 SOAP_FMAC1
14591 int
14592 SOAP_FMAC2
14593 soap_envelope_begin_out(struct soap *soap)
14594 {
14595 #ifndef WITH_LEANER
14596 size_t n = 0;
14597 if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && soap->mime.start && strlen(soap->mime.boundary) + strlen(soap->mime.start) < sizeof(soap->tmpbuf) - 80 )
14598 { const char *s;
14599 if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
14600 s = "application/dime";
14601 else if (soap->version == 2)
14602 { if (soap->mode & SOAP_ENC_MTOM)
14603 s = "application/xop+xml; charset=utf-8; type=\"application/soap+xml\"";
14604 else
14605 s = "application/soap+xml; charset=utf-8";
14606 }
14607 else if (soap->mode & SOAP_ENC_MTOM)
14608 s = "application/xop+xml; charset=utf-8; type=\"text/xml\"";
14609 else
14610 s = "text/xml; charset=utf-8";
14611 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);
14612 n = strlen(soap->tmpbuf);
14613 if (soap_send_raw(soap, soap->tmpbuf, n))
14614 return soap->error;
14615 }
14616 if (soap->mode & SOAP_IO_LENGTH)
14617 soap->dime.size = soap->count;
14618 if (!(soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME))
14619 { if (soap_putdimehdr(soap))
14620 return soap->error;
14621 }
14622 #endif
14623 soap->part = SOAP_IN_ENVELOPE;
14624 return soap_element_begin_out(soap, "SOAP-ENV:Envelope", 0, NULL);
14625 }
14626 #endif
14627
14628
14629 #ifndef PALM_2
14630 SOAP_FMAC1
14631 int
14632 SOAP_FMAC2
14633 soap_envelope_end_out(struct soap *soap)
14634 { if (soap_element_end_out(soap, "SOAP-ENV:Envelope") || soap_send_raw(soap, "\r\n", 2))
14635 return soap->error;
14636 #ifndef WITH_LEANER
14637 if ((soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
14638 { soap->dime.size = soap->count - soap->dime.size;
14639 sprintf(soap->id, soap->dime_id_format, 0);
14640 soap->dime.id = soap->id;
14641 if (soap->local_namespaces)
14642 { if (soap->local_namespaces[0].out)
14643 soap->dime.type = (char*)soap->local_namespaces[0].out;
14644 else
14645 soap->dime.type = (char*)soap->local_namespaces[0].ns;
14646 }
14647 soap->dime.options = NULL;
14648 soap->dime.flags = SOAP_DIME_MB | SOAP_DIME_ABSURI;
14649 if (!soap->dime.first)
14650 soap->dime.flags |= SOAP_DIME_ME;
14651 soap->count += 12 + ((strlen(soap->dime.id)+3)&(~3)) + (soap->dime.type ? ((strlen(soap->dime.type)+3)&(~3)) : 0);
14652 }
14653 if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
14654 return soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3);
14655 #endif
14656 soap->part = SOAP_END_ENVELOPE;
14657 return SOAP_OK;
14658 }
14659 #endif
14660
14661
14662 #ifndef WITH_LEAN
14663 #ifndef PALM_1
14664 SOAP_FMAC1
14665 char*
14666 SOAP_FMAC2
14667 soap_get_http_body(struct soap *soap)
14668 {
14669 #ifndef WITH_LEAN
14670 register size_t l = 0, n = 0;
14671 register char *s;
14672
14673 if (!(soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) != SOAP_IO_CHUNK)
14674 { n = soap->length;
14675 if (!n)
14676 return NULL;
14677 }
14678 #ifdef WITH_FAST
14679 soap->labidx = 0;
14680 #else
14681 if (soap_new_block(soap) == NULL)
14682 return NULL;
14683 #endif
14684 for (;;)
14685 {
14686 #ifdef WITH_FAST
14687 register size_t i, k;
14688 if (soap_append_lab(soap, NULL, 0))
14689 return NULL;
14690 s = soap->labbuf + soap->labidx;
14691 k = soap->lablen - soap->labidx;
14692 soap->labidx = soap->lablen;
14693 #else
14694 register size_t i, k = SOAP_BLKLEN;
14695 if (!(s = (char*)soap_push_block(soap, NULL, k)))
14696 return NULL;
14697 #endif
14698 for (i = 0; i < k; i++)
14699 { register soap_wchar c;
14700 l++;
14701 if (n > 0 && l > n)
14702 goto end;
14703 c = soap_getchar(soap);
14704 if ((int)c == EOF)
14705 goto end;
14706 *s++ = (char)(c & 0xFF);
14707 }
14708 }
14709 end:
14710 *s = '\0';
14711 #ifdef WITH_FAST
14712 s = soap_strdup(soap, soap->labbuf);
14713 #else
14714 soap_size_block(soap, NULL, i+1);
14715 s = soap_save_block(soap, NULL, 0);
14716 #endif
14717 return s;
14718 #else
14719 return NULL;
14720 #endif
14721 }
14722 #endif
14723 #endif
14724
14725
14726 #ifndef PALM_1
14727 SOAP_FMAC1
14728 int
14729 SOAP_FMAC2
14730 soap_envelope_begin_in(struct soap *soap)
14731 { register struct Namespace *p;
14732 soap->part = SOAP_IN_ENVELOPE;
14733 if (soap_element_begin_in(soap, "SOAP-ENV:Envelope", 0, NULL))
14734 { if (soap->error == SOAP_TAG_MISMATCH
14735 && !soap_element_begin_in(soap, "Envelope", 0, NULL))
14736 soap->error = SOAP_VERSIONMISMATCH;
14737 else if (soap->status)
14738 soap->error = soap->status;
14739 return soap->error;
14740 }
14741 p = soap->local_namespaces;
14742 if (p)
14743 { const char *ns = p[0].out;
14744 if (!ns)
14745 ns = p[0].ns;
14746 if (!strcmp(ns, soap_env1))
14747 { soap->version = 1;
14748 if (p[1].out)
14749 SOAP_FREE(soap, p[1].out);
14750 if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc1))))
14751 strcpy(p[1].out, soap_enc1);
14752 }
14753 else if (!strcmp(ns, soap_env2))
14754 { soap->version = 2;
14755 if (p[1].out)
14756 SOAP_FREE(soap, p[1].out);
14757 if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc2))))
14758 strcpy(p[1].out, soap_enc2);
14759 }
14760 }
14761 return SOAP_OK;
14762 }
14763 #endif
14764
14765
14766 #ifndef PALM_1
14767 SOAP_FMAC1
14768 int
14769 SOAP_FMAC2
14770 soap_envelope_end_in(struct soap *soap)
14771 { soap->part = SOAP_END_ENVELOPE;
14772 return soap_element_end_in(soap, "SOAP-ENV:Envelope");
14773 }
14774 #endif
14775
14776
14777 #ifndef PALM_2
14778 SOAP_FMAC1
14779 int
14780 SOAP_FMAC2
14781 soap_body_begin_out(struct soap *soap)
14782 { soap->part = SOAP_IN_BODY;
14783 if (soap->version == 1)
14784 soap->encoding = 1;
14785 #ifndef WITH_LEAN
14786 if ((soap->mode & SOAP_SEC_WSUID) && soap_set_attr(soap, "wsu:Id", "Body", 1))
14787 return soap->error;
14788 #endif
14789 return soap_element_begin_out(soap, "SOAP-ENV:Body", 0, NULL);
14790 }
14791 #endif
14792
14793
14794 #ifndef PALM_2
14795 SOAP_FMAC1
14796 int
14797 SOAP_FMAC2
14798 soap_body_end_out(struct soap *soap)
14799 { if (soap_element_end_out(soap, "SOAP-ENV:Body"))
14800 return soap->error;
14801 soap->part = SOAP_END_BODY;
14802 return SOAP_OK;
14803 }
14804 #endif
14805
14806
14807 #ifndef PALM_2
14808 SOAP_FMAC1
14809 int
14810 SOAP_FMAC2
14811 soap_body_begin_in(struct soap *soap)
14812 { soap->part = SOAP_IN_BODY;
14813 if (soap_element_begin_in(soap, "SOAP-ENV:Body", 0, NULL))
14814 return soap->error;
14815 if (!soap->body)
14816 soap->part = SOAP_NO_BODY;
14817 return SOAP_OK;
14818 }
14819 #endif
14820
14821
14822 #ifndef PALM_2
14823 SOAP_FMAC1
14824 int
14825 SOAP_FMAC2
14826 soap_body_end_in(struct soap *soap)
14827 { if (soap->part == SOAP_NO_BODY)
14828 return soap->error = SOAP_OK;
14829 soap->part = SOAP_END_BODY;
14830 return soap_element_end_in(soap, "SOAP-ENV:Body");
14831 }
14832 #endif
14833
14834
14835 #ifndef PALM_2
14836 SOAP_FMAC1
14837 int
14838 SOAP_FMAC2
14839 soap_recv_header(struct soap *soap)
14840 { if (soap_getheader(soap) && soap->error == SOAP_TAG_MISMATCH)
14841 soap->error = SOAP_OK;
14842 if (soap->error == SOAP_OK && soap->fheader)
14843 soap->error = soap->fheader(soap);
14844 return soap->error;
14845 }
14846 #endif
14847
14848
14849 #ifndef PALM_1
14850 SOAP_FMAC1
14851 void
14852 SOAP_FMAC2
14853 soap_set_endpoint(struct soap *soap, const char *endpoint)
14854 { register const char *s;
14855 register size_t i, n;
14856 soap->endpoint[0] = '\0';
14857 soap->host[0] = '\0';
14858 soap->path[0] = '/';
14859 soap->path[1] = '\0';
14860 soap->port = 80;
14861 if (!endpoint || !*endpoint)
14862 return;
14863 #ifdef WITH_OPENSSL
14864 if (!soap_tag_cmp(endpoint, "https:*"))
14865 soap->port = 443;
14866 #endif
14867 strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint) - 1);
14868 soap->endpoint[sizeof(soap->endpoint) - 1] = '\0';
14869 s = strchr(endpoint, ':');
14870 if (s && s[1] == '/' && s[2] == '/')
14871 s += 3;
14872 else
14873 s = endpoint;
14874 n = strlen(s);
14875 if (n >= sizeof(soap->host))
14876 n = sizeof(soap->host) - 1;
14877 #ifdef WITH_IPV6
14878 if (s[0] == '[')
14879 { s++;
14880 for (i = 0; i < n; i++)
14881 { if (s[i] == ']')
14882 { s++;
14883 --n;
14884 break;
14885 }
14886 soap->host[i] = s[i];
14887 }
14888 }
14889 else
14890 { for (i = 0; i < n; i++)
14891 { soap->host[i] = s[i];
14892 if (s[i] == '/' || s[i] == ':')
14893 break;
14894 }
14895 }
14896 #else
14897 for (i = 0; i < n; i++)
14898 { soap->host[i] = s[i];
14899 if (s[i] == '/' || s[i] == ':')
14900 break;
14901 }
14902 #endif
14903 soap->host[i] = '\0';
14904 if (s[i] == ':')
14905 { soap->port = (int)soap_strtol(s + i + 1, NULL, 10);
14906 for (i++; i < n; i++)
14907 if (s[i] == '/')
14908 break;
14909 }
14910 if (i < n && s[i])
14911 { strncpy(soap->path, s + i, sizeof(soap->path));
14912 soap->path[sizeof(soap->path) - 1] = '\0';
14913 }
14914 }
14915 #endif
14916
14917
14918 #ifndef PALM_1
14919 SOAP_FMAC1
14920 int
14921 SOAP_FMAC2
14922 soap_connect(struct soap *soap, const char *endpoint, const char *action)
14923 { return soap_connect_command(soap, SOAP_POST, endpoint, action);
14924 }
14925 #endif
14926
14927
14928 #ifndef PALM_1
14929 SOAP_FMAC1
14930 int
14931 SOAP_FMAC2
14932 soap_connect_command(struct soap *soap, int http_command, const char *endpoints, const char *action)
14933 { char *endpoint;
14934 const char *s;
14935 if (endpoints && (s = strchr(endpoints, ' ')))
14936 { endpoint = (char*)SOAP_MALLOC(soap, strlen(endpoints) + 1);
14937 for (;;)
14938 { strncpy(endpoint, endpoints, s - endpoints);
14939 endpoint[s - endpoints] = '\0';
14940 if (soap_try_connect_command(soap, http_command, endpoint, action) != SOAP_TCP_ERROR)
14941 break;
14942 if (!*s)
14943 break;
14944 soap->error = SOAP_OK;
14945 while (*s == ' ')
14946 s++;
14947 endpoints = s;
14948 s = strchr(endpoints, ' ');
14949 if (!s)
14950 s = endpoints + strlen(endpoints);
14951 }
14952 SOAP_FREE(soap, endpoint);
14953 }
14954 else
14955 soap_try_connect_command(soap, http_command, endpoints, action);
14956 return soap->error;
14957 }
14958 #endif
14959
14960
14961 #ifndef PALM_1
14962 static int
14963 soap_try_connect_command(struct soap *soap, int http_command, const char *endpoint, const char *action)
14964 { char host[sizeof(soap->host)];
14965 int port;
14966 size_t count;
14967 soap->error = SOAP_OK;
14968 strcpy(host, soap->host);
14969 port = soap->port;
14970 soap->status = http_command;
14971 soap_set_endpoint(soap, endpoint);
14972 #ifndef WITH_LEANER
14973 if (soap->fconnect)
14974 { if ((soap->error = soap->fconnect(soap, endpoint, soap->host, soap->port)))
14975 return soap->error;
14976 }
14977 else
14978 #endif
14979 soap->action = soap_strdup(soap, action);
14980 if (soap->fopen && *soap->host)
14981 { if (!soap->keep_alive || !soap_valid_socket(soap->socket) || strcmp(soap->host, host) || soap->port != port || !soap->fpoll || soap->fpoll(soap))
14982 { soap->error = SOAP_OK;
14983 soap->keep_alive = 0;
14984 soap->omode &= ~SOAP_IO_UDP;
14985 soap_closesock(soap);
14986 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Connect/reconnect to host='%s' path='%s' port=%d\n", soap->host, soap->path, soap->port));
14987 #ifndef WITH_LEAN
14988 if (!strncmp(endpoint, "soap.udp:", 9))
14989 soap->omode |= SOAP_IO_UDP;
14990 #endif
14991 soap->socket = soap->fopen(soap, endpoint, soap->host, soap->port);
14992 if (soap->error)
14993 return soap->error;
14994 soap->keep_alive = ((soap->omode & SOAP_IO_KEEPALIVE) != 0);
14995 }
14996 }
14997 count = soap_count_attachments(soap);
14998 if (soap_begin_send(soap))
14999 return soap->error;
15000 if (http_command == SOAP_GET)
15001 { soap->mode &= ~SOAP_IO;
15002 soap->mode |= SOAP_IO_BUFFER;
15003 }
15004 #ifndef WITH_NOHTTP
15005 if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML) && endpoint)
15006 { unsigned int k = soap->mode;
15007 soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB);
15008 if ((k & SOAP_IO) != SOAP_IO_FLUSH)
15009 soap->mode |= SOAP_IO_BUFFER;
15010 if ((soap->error = soap->fpost(soap, endpoint, soap->host, soap->port, soap->path, action, count)))
15011 return soap->error;
15012 #ifndef WITH_LEANER
15013 if ((k & SOAP_IO) == SOAP_IO_CHUNK)
15014 { if (soap_flush(soap))
15015 return soap->error;
15016 }
15017 #endif
15018 soap->mode = k;
15019 }
15020 if (http_command == SOAP_GET)
15021 return soap_end_send(soap);
15022 #endif
15023 return SOAP_OK;
15024 }
15025 #endif
15026
15027
15028 #ifndef WITH_LEAN
15029 SOAP_FMAC1
15030 char*
15031 SOAP_FMAC2
15032 soap_s2base64(struct soap *soap, const unsigned char *s, char *t, int n)
15033 { register int i;
15034 register unsigned long m;
15035 register char *p;
15036 if (!t)
15037 t = (char*)soap_malloc(soap, (n + 2) / 3 * 4 + 1);
15038 if (!t)
15039 return NULL;
15040 p = t;
15041 t[0] = '\0';
15042 if (!s)
15043 return p;
15044 for (; n > 2; n -= 3, s += 3)
15045 { m = s[0];
15046 m = (m << 8) | s[1];
15047 m = (m << 8) | s[2];
15048 for (i = 4; i > 0; m >>= 6)
15049 t[--i] = soap_base64o[m & 0x3F];
15050 t += 4;
15051 }
15052 t[0] = '\0';
15053 if (n > 0)
15054 { m = 0;
15055 for (i = 0; i < n; i++)
15056 m = (m << 8) | *s++;
15057 for (; i < 3; i++)
15058 m <<= 8;
15059 for (i++; i > 0; m >>= 6)
15060 t[--i] = soap_base64o[m & 0x3F];
15061 for (i = 3; i > n; i--)
15062 t[i] = '=';
15063 t[4] = '\0';
15064 }
15065 return p;
15066 }
15067 #endif
15068
15069
15070 #ifndef WITH_LEAN
15071 SOAP_FMAC1
15072 const char*
15073 SOAP_FMAC2
15074 soap_base642s(struct soap *soap, const char *s, char *t, size_t l, int *n)
15075 { register int i, j, c;
15076 register unsigned long m;
15077 register const char *p;
15078 if (!s || !*s)
15079 { if (n)
15080 *n = 0;
15081 if (soap->error)
15082 return NULL;
15083 return SOAP_NON_NULL;
15084 }
15085 if (!t)
15086 { l = (strlen(s) + 3) / 4 * 3;
15087 t = (char*)soap_malloc(soap, l);
15088 }
15089 if (!t)
15090 return NULL;
15091 p = t;
15092 if (n)
15093 *n = 0;
15094 for (;;)
15095 { for (i = 0; i < SOAP_BLKLEN; i++)
15096 { m = 0;
15097 j = 0;
15098 while (j < 4)
15099 { c = *s++;
15100 if (c == '=' || !c)
15101 { i *= 3;
15102 switch (j)
15103 { case 2:
15104 *t++ = (char)((m >> 4) & 0xFF);
15105 i++;
15106 break;
15107 case 3:
15108 *t++ = (char)((m >> 10) & 0xFF);
15109 *t++ = (char)((m >> 2) & 0xFF);
15110 i += 2;
15111 }
15112 if (n)
15113 *n += i;
15114 return p;
15115 }
15116 c -= '+';
15117 if (c >= 0 && c <= 79)
15118 { int b = soap_base64i[c];
15119 if (b >= 64)
15120 { soap->error = SOAP_TYPE;
15121 return NULL;
15122 }
15123 m = (m << 6) + b;
15124 j++;
15125 }
15126 else if (!soap_blank(c + '+'))
15127 { soap->error = SOAP_TYPE;
15128 return NULL;
15129 }
15130 }
15131 *t++ = (char)((m >> 16) & 0xFF);
15132 *t++ = (char)((m >> 8) & 0xFF);
15133 *t++ = (char)(m & 0xFF);
15134 if (l < 3)
15135 { if (n)
15136 *n += i;
15137 return p;
15138 }
15139 l -= 3;
15140 }
15141 if (n)
15142 *n += 3 * SOAP_BLKLEN;
15143 }
15144 }
15145 #endif
15146
15147
15148 #ifndef WITH_LEAN
15149 SOAP_FMAC1
15150 char*
15151 SOAP_FMAC2
15152 soap_s2hex(struct soap *soap, const unsigned char *s, char *t, int n)
15153 { register char *p;
15154 if (!t)
15155 t = (char*)soap_malloc(soap, 2 * n + 1);
15156 if (!t)
15157 return NULL;
15158 p = t;
15159 t[0] = '\0';
15160 if (s)
15161 { for (; n > 0; n--)
15162 { register int m = *s++;
15163 *t++ = (char)((m >> 4) + (m > 159 ? 'a' - 10 : '0'));
15164 m &= 0x0F;
15165 *t++ = (char)(m + (m > 9 ? 'a' - 10 : '0'));
15166 }
15167 }
15168 *t++ = '\0';
15169 return p;
15170 }
15171 #endif
15172
15173
15174 #ifndef WITH_LEAN
15175 SOAP_FMAC1
15176 const char*
15177 SOAP_FMAC2
15178 soap_hex2s(struct soap *soap, const char *s, char *t, size_t l, int *n)
15179 { register const char *p;
15180 if (!s || !*s)
15181 { if (n)
15182 *n = 0;
15183 if (soap->error)
15184 return NULL;
15185 return SOAP_NON_NULL;
15186 }
15187 if (!t)
15188 { l = strlen(s) / 2;
15189 t = (char*)soap_malloc(soap, l);
15190 }
15191 if (!t)
15192 return NULL;
15193 p = t;
15194 while (l)
15195 { register int d1, d2;
15196 d1 = *s++;
15197 if (!d1)
15198 break;
15199 d2 = *s++;
15200 if (!d2)
15201 break;
15202 *t++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0');
15203 l--;
15204 }
15205 if (n)
15206 *n = (int)(t - p);
15207 return p;
15208 }
15209 #endif
15210
15211
15212 #ifndef WITH_NOHTTP
15213 #ifndef PALM_1
15214 SOAP_FMAC1
15215 int
15216 SOAP_FMAC2
15217 soap_puthttphdr(struct soap *soap, int status, size_t count)
15218 { if (soap->status != SOAP_GET)
15219 { register const char *s = "text/xml; charset=utf-8";
15220 register int err = SOAP_OK;
15221 #ifndef WITH_LEANER
15222 register const char *r = NULL;
15223 #endif
15224 if ((status == SOAP_FILE || soap->status == SOAP_POST_FILE) && soap->http_content)
15225 s = soap->http_content;
15226 else if (status == SOAP_HTML)
15227 s = "text/html; charset=utf-8";
15228 else if (count || ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK))
15229 { if (soap->version == 2)
15230 s = "application/soap+xml; charset=utf-8";
15231 }
15232 #ifndef WITH_LEANER
15233 if (soap->mode & (SOAP_ENC_DIME | SOAP_ENC_MTOM))
15234 { if (soap->mode & SOAP_ENC_MTOM)
15235 { if (soap->version == 2)
15236 r = "application/soap+xml";
15237 else
15238 r = "text/xml";
15239 s = "application/xop+xml";
15240 }
15241 else
15242 s = "application/dime";
15243 }
15244 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)
15245 { register const char *t = strchr(s, ';');
15246 sprintf(soap->tmpbuf, "multipart/related; charset=utf-8; boundary=\"%s\"; type=\"", soap->mime.boundary);
15247 if (t)
15248 { strncat(soap->tmpbuf, s, t - s);
15249 soap->tmpbuf[sizeof(soap->tmpbuf)-1] = '\0';
15250 }
15251 else
15252 strcat(soap->tmpbuf, s);
15253 if (soap->mime.start)
15254 { strcat(soap->tmpbuf, "\"; start=\"");
15255 strcat(soap->tmpbuf, soap->mime.start);
15256 }
15257 strcat(soap->tmpbuf, "\"");
15258 if (r)
15259 { strcat(soap->tmpbuf, "; start-info=\"");
15260 strcat(soap->tmpbuf, r);
15261 strcat(soap->tmpbuf, "\"");
15262 }
15263 s = soap->tmpbuf;
15264 }
15265 if (status == SOAP_OK && soap->version == 2 && soap->action && strlen(soap->action) < sizeof(soap->tmpbuf) - 80)
15266 { sprintf(soap->tmpbuf, "%s; action=\"%s\"", s, soap->action);
15267 s = soap->tmpbuf;
15268 }
15269 #endif
15270 if (s && (err = soap->fposthdr(soap, "Content-Type", s)))
15271 return err;
15272 #ifdef WITH_ZLIB
15273 if ((soap->omode & SOAP_ENC_ZLIB))
15274 {
15275 #ifdef WITH_GZIP
15276 err = soap->fposthdr(soap, "Content-Encoding", soap->zlib_out == SOAP_ZLIB_DEFLATE ? "deflate" : "gzip");
15277 #else
15278 err = soap->fposthdr(soap, "Content-Encoding", "deflate");
15279 #endif
15280 if (err)
15281 return err;
15282 }
15283 #endif
15284 #ifndef WITH_LEANER
15285 if ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK)
15286 err = soap->fposthdr(soap, "Transfer-Encoding", "chunked");
15287 else
15288 #endif
15289 if (s)
15290 { sprintf(soap->tmpbuf, "%lu", (unsigned long)count);
15291 err = soap->fposthdr(soap, "Content-Length", soap->tmpbuf);
15292 }
15293 if (err)
15294 return err;
15295 }
15296 return soap->fposthdr(soap, "Connection", soap->keep_alive ? "keep-alive" : "close");
15297 }
15298 #endif
15299 #endif
15300
15301
15302 #ifndef WITH_LEAN
15303 static const char*
15304 soap_set_validation_fault(struct soap *soap, const char *s, const char *t)
15305 { if (*soap->tag)
15306 sprintf(soap->msgbuf, "Validation constraint violation: %s%s in element '%s'", s, t?t:SOAP_STR_EOS, soap->tag);
15307 else
15308 sprintf(soap->msgbuf, "Validation constraint violation: %s%s", s, t?t:SOAP_STR_EOS);
15309 return soap->msgbuf;
15310 }
15311 #endif
15312
15313
15314 #ifndef PALM_1
15315 SOAP_FMAC1
15316 void
15317 SOAP_FMAC2
15318 soap_set_fault(struct soap *soap)
15319 { const char **c = soap_faultcode(soap);
15320 const char **s = soap_faultstring(soap);
15321 if (soap->fseterror)
15322 soap->fseterror(soap, c, s);
15323 if (!*c)
15324 { if (soap->version == 2)
15325 *c = "SOAP-ENV:Sender";
15326 else
15327 *c = "SOAP-ENV:Client";
15328 }
15329 if (*s)
15330 return;
15331 switch (soap->error)
15332 {
15333 #ifndef WITH_LEAN
15334 case SOAP_CLI_FAULT:
15335 *s = "Client fault";
15336 break;
15337 case SOAP_SVR_FAULT:
15338 *s = "Server fault";
15339 break;
15340 case SOAP_TAG_MISMATCH:
15341 *s = soap_set_validation_fault(soap, "tag name or namespace mismatch", NULL);
15342 break;
15343 case SOAP_TYPE:
15344 *s = soap_set_validation_fault(soap, "data type mismatch ", soap->type);
15345 break;
15346 case SOAP_SYNTAX_ERROR:
15347 *s = "Well-formedness violation";
15348 break;
15349 case SOAP_NO_TAG:
15350 *s = "No XML root element";
15351 break;
15352 case SOAP_MUSTUNDERSTAND:
15353 *c = "SOAP-ENV:MustUnderstand";
15354 sprintf(soap->msgbuf, "The data in element '%s' must be understood but cannot be handled", soap->tag);
15355 *s = soap->msgbuf;
15356 break;
15357 case SOAP_VERSIONMISMATCH:
15358 *c = "SOAP-ENV:VersionMismatch";
15359 *s = "Invalid SOAP message or SOAP version mismatch";
15360 break;
15361 case SOAP_DATAENCODINGUNKNOWN:
15362 *c = "SOAP-ENV:DataEncodingUnknown";
15363 *s = "Unsupported SOAP data encoding";
15364 break;
15365 case SOAP_NAMESPACE:
15366 *s = soap_set_validation_fault(soap, "namespace error", NULL);
15367 break;
15368 case SOAP_USER_ERROR:
15369 *s = "User data error";
15370 break;
15371 case SOAP_FATAL_ERROR:
15372 *s = "Fatal error";
15373 break;
15374 case SOAP_NO_METHOD:
15375 sprintf(soap->msgbuf, "Method '%s' not implemented: method name or namespace not recognized", soap->tag);
15376 *s = soap->msgbuf;
15377 break;
15378 case SOAP_NO_DATA:
15379 *s = "Data required for operation";
15380 break;
15381 case SOAP_GET_METHOD:
15382 *s = "HTTP GET method not implemented";
15383 break;
15384 case SOAP_PUT_METHOD:
15385 *s = "HTTP PUT method not implemented";
15386 break;
15387 case SOAP_HTTP_METHOD:
15388 *s = "HTTP method not implemented";
15389 break;
15390 case SOAP_EOM:
15391 *s = "Out of memory";
15392 break;
15393 case SOAP_MOE:
15394 *s = "Memory overflow or memory corruption error";
15395 break;
15396 case SOAP_HDR:
15397 *s = "Header line too long";
15398 break;
15399 case SOAP_IOB:
15400 *s = "Array index out of bounds";
15401 break;
15402 case SOAP_NULL:
15403 *s = soap_set_validation_fault(soap, "nil not allowed", NULL);
15404 break;
15405 case SOAP_DUPLICATE_ID:
15406 *s = soap_set_validation_fault(soap, "multiple definitions of id ", soap->id);
15407 if (soap->version == 2)
15408 *soap_faultsubcode(soap) = "SOAP-ENC:DuplicateID";
15409 break;
15410 case SOAP_MISSING_ID:
15411 *s = soap_set_validation_fault(soap, "missing id for ref ", soap->id);
15412 if (soap->version == 2)
15413 *soap_faultsubcode(soap) = "SOAP-ENC:MissingID";
15414 break;
15415 case SOAP_HREF:
15416 *s = soap_set_validation_fault(soap, "incompatible object type ref/id pair ", soap->id);
15417 break;
15418 case SOAP_FAULT:
15419 break;
15420 #ifndef WITH_NOIO
15421 case SOAP_UDP_ERROR:
15422 *s = "Message too large for UDP packet";
15423 break;
15424 case SOAP_TCP_ERROR:
15425 *s = tcp_error(soap);
15426 break;
15427 #endif
15428 case SOAP_HTTP_ERROR:
15429 *s = "An HTTP processing error occurred";
15430 break;
15431 case SOAP_SSL_ERROR:
15432 #ifdef WITH_OPENSSL
15433 *s = "SSL/TLS error";
15434 #else
15435 *s = "OpenSSL not installed: recompile with -DWITH_OPENSSL";
15436 #endif
15437 break;
15438 case SOAP_PLUGIN_ERROR:
15439 *s = "Plugin registry error";
15440 break;
15441 case SOAP_DIME_ERROR:
15442 *s = "DIME format error";
15443 break;
15444 case SOAP_DIME_HREF:
15445 *s = "DIME href to missing attachment";
15446 break;
15447 case SOAP_DIME_MISMATCH:
15448 *s = "DIME version/transmission error";
15449 break;
15450 case SOAP_DIME_END:
15451 *s = "End of DIME error";
15452 break;
15453 case SOAP_MIME_ERROR:
15454 *s = "MIME format error";
15455 break;
15456 case SOAP_MIME_HREF:
15457 *s = "MIME href to missing attachment";
15458 break;
15459 case SOAP_MIME_END:
15460 *s = "End of MIME error";
15461 break;
15462 case SOAP_ZLIB_ERROR:
15463 #ifdef WITH_ZLIB
15464 sprintf(soap->msgbuf, "Zlib/gzip error: '%s'", soap->d_stream->msg?soap->d_stream->msg:SOAP_STR_EOS);
15465 *s = soap->msgbuf;
15466 #else
15467 *s = "Zlib/gzip not installed for (de)compression: recompile with -DWITH_GZIP";
15468 #endif
15469 break;
15470 case SOAP_REQUIRED:
15471 *s = soap_set_validation_fault(soap, "missing required attribute", NULL);
15472 break;
15473 case SOAP_PROHIBITED:
15474 *s = soap_set_validation_fault(soap, "prohibited attribute present", NULL);
15475 break;
15476 case SOAP_OCCURS:
15477 *s = soap_set_validation_fault(soap, "occurrence violation", NULL);
15478 break;
15479 case SOAP_LENGTH:
15480 *s = soap_set_validation_fault(soap, "content range or length violation", NULL);
15481 break;
15482 case SOAP_FD_EXCEEDED:
15483 *s = "Maximum number of open connections was reached (no define HAVE_POLL): increase FD_SETSIZE";
15484 break;
15485 case SOAP_UTF_ERROR:
15486 *s = "UTF content encoding error";
15487 break;
15488 case SOAP_STOP:
15489 *s = "Stopped: no response to be sent or received (informative)";
15490 break;
15491 #endif
15492 case SOAP_EOF:
15493 #ifndef WITH_NOIO
15494 strcpy(soap->msgbuf, soap_strerror(soap));
15495 #ifndef WITH_LEAN
15496 if (strlen(soap->msgbuf) + 25 < sizeof(soap->msgbuf))
15497 { memmove(soap->msgbuf + 25, soap->msgbuf, strlen(soap->msgbuf) + 1);
15498 memcpy(soap->msgbuf, "End of file or no input: ", 25);
15499 }
15500 #endif
15501 *s = soap->msgbuf;
15502 break;
15503 #else
15504 *s = "End of file or no input";
15505 break;
15506 #endif
15507 default:
15508 #ifndef WITH_NOHTTP
15509 #ifndef WITH_LEAN
15510 if (soap->error > 200 && soap->error < 600)
15511 { sprintf(soap->msgbuf, "HTTP Error: %d %s", soap->error, http_error(soap, soap->error));
15512 *s = soap->msgbuf;
15513 }
15514 else
15515 #endif
15516 #endif
15517 { sprintf(soap->msgbuf, "Error %d", soap->error);
15518 *s = soap->msgbuf;
15519 }
15520 }
15521 }
15522 #endif
15523
15524
15525 #ifndef PALM_1
15526 SOAP_FMAC1
15527 int
15528 SOAP_FMAC2
15529 soap_send_fault(struct soap *soap)
15530 { register int status = soap->error;
15531 if (status == SOAP_STOP)
15532 return soap_closesock(soap);
15533 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Sending back fault struct for error code %d\n", soap->error));
15534 soap->keep_alive = 0;
15535 soap_set_fault(soap);
15536 if (soap->error < 200 && soap->error != SOAP_FAULT)
15537 soap->header = NULL;
15538 if (status != SOAP_EOF || (!soap->recv_timeout && !soap->send_timeout))
15539 { int r = 1;
15540 #ifndef WITH_NOIO
15541 if (soap->fpoll && soap->fpoll(soap))
15542 r = 0;
15543 #ifndef WITH_LEAN
15544 else if (soap_valid_socket(soap->socket))
15545 { r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_SND, 0);
15546 if (r > 0)
15547 { if (!(r & SOAP_TCP_SELECT_SND)
15548 || ((r & SOAP_TCP_SELECT_RCV)
15549 && recv(soap->socket, soap->tmpbuf, 1, MSG_PEEK) < 0))
15550 r = 0;
15551 }
15552 }
15553 #endif
15554 #endif
15555 if (r > 0)
15556 { soap->error = SOAP_OK;
15557 soap_serializeheader(soap);
15558 soap_serializefault(soap);
15559 soap_begin_count(soap);
15560 if (soap->mode & SOAP_IO_LENGTH)
15561 { soap_envelope_begin_out(soap);
15562 soap_putheader(soap);
15563 soap_body_begin_out(soap);
15564 soap_putfault(soap);
15565 soap_body_end_out(soap);
15566 soap_envelope_end_out(soap);
15567 }
15568 soap_end_count(soap);
15569 if (soap_response(soap, status)
15570 || soap_envelope_begin_out(soap)
15571 || soap_putheader(soap)
15572 || soap_body_begin_out(soap)
15573 || soap_putfault(soap)
15574 || soap_body_end_out(soap)
15575 || soap_envelope_end_out(soap))
15576 return soap_closesock(soap);
15577 soap_end_send(soap);
15578 }
15579 }
15580 soap->error = status;
15581 return soap_closesock(soap);
15582 }
15583 #endif
15584
15585
15586 #ifndef PALM_1
15587 SOAP_FMAC1
15588 int
15589 SOAP_FMAC2
15590 soap_recv_fault(struct soap *soap, int check)
15591 { register int status = soap->error;
15592 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Check if receiving SOAP Fault\n"));
15593 if (!check)
15594 {
15595 if (soap->error != SOAP_NO_TAG
15596 && (soap->error != SOAP_TAG_MISMATCH || soap->level != 2))
15597 return soap->error;
15598 }
15599 soap->error = SOAP_OK;
15600 if (soap_getfault(soap))
15601 {
15602 if (check && soap->error == SOAP_TAG_MISMATCH && soap->level == 2)
15603 return soap->error = SOAP_OK;
15604 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Error: soap_get_soapfault() failed at level %u tag '%s'\n", soap->level, soap->tag));
15605 *soap_faultcode(soap) = (soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client");
15606 soap->error = status;
15607 soap_set_fault(soap);
15608 }
15609 else
15610 { register const char *s = *soap_faultcode(soap);
15611 if (!soap_match_tag(soap, s, "SOAP-ENV:Server") || !soap_match_tag(soap, s, "SOAP-ENV:Receiver"))
15612 status = SOAP_SVR_FAULT;
15613 else if (!soap_match_tag(soap, s, "SOAP-ENV:Client") || !soap_match_tag(soap, s, "SOAP-ENV:Sender"))
15614 status = SOAP_CLI_FAULT;
15615 else if (!soap_match_tag(soap, s, "SOAP-ENV:MustUnderstand"))
15616 status = SOAP_MUSTUNDERSTAND;
15617 else if (!soap_match_tag(soap, s, "SOAP-ENV:VersionMismatch"))
15618 status = SOAP_VERSIONMISMATCH;
15619 else
15620 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Received SOAP Fault code %s\n", s));
15621 status = SOAP_FAULT;
15622 }
15623 if (!soap_body_end_in(soap))
15624 soap_envelope_end_in(soap);
15625 }
15626 soap_end_recv(soap);
15627 soap->error = status;
15628 return soap_closesock(soap);
15629 }
15630 #endif
15631
15632
15633 #ifndef WITH_NOHTTP
15634 #ifndef PALM_1
15635 SOAP_FMAC1
15636 int
15637 SOAP_FMAC2
15638 soap_send_empty_response(struct soap *soap, int httpstatuscode)
15639 { register soap_mode m = soap->omode;
15640 soap->count = 0;
15641 if ((m & SOAP_IO) == SOAP_IO_CHUNK)
15642 soap->omode = (m & ~SOAP_IO) | SOAP_IO_BUFFER;
15643 if (!soap_response(soap, httpstatuscode) && !soap_end_send(soap))
15644 soap->error = SOAP_STOP;
15645 soap->omode = m;
15646 return soap_closesock(soap);
15647 }
15648 #endif
15649 #endif
15650
15651
15652 #ifndef WITH_NOHTTP
15653 #ifndef PALM_1
15654 SOAP_FMAC1
15655 int
15656 SOAP_FMAC2
15657 soap_recv_empty_response(struct soap *soap)
15658 { if (!soap_begin_recv(soap))
15659 soap_end_recv(soap);
15660 else if (soap->error == SOAP_NO_DATA || soap->error == 202)
15661 soap->error = SOAP_OK;
15662 return soap_closesock(soap);
15663 }
15664 #endif
15665 #endif
15666
15667
15668 #ifndef WITH_NOIO
15669 #ifndef PALM_1
15670 static const char*
15671 soap_strerror(struct soap *soap)
15672 { register int err = soap->errnum;
15673 if (err)
15674 {
15675 #ifndef WIN32
15676 # ifdef HAVE_STRERROR_R
15677 strerror_r(err, soap->msgbuf, sizeof(soap->msgbuf));
15678 # else
15679 return strerror(err);
15680 # endif
15681 #else
15682 #ifndef UNDER_CE
15683 DWORD len;
15684 *soap->msgbuf = '\0';
15685 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);
15686 #else
15687 DWORD i, len;
15688 *soap->msgbuf = '\0';
15689 len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, 0, (LPTSTR)soap->msgbuf, (DWORD)(sizeof(soap->msgbuf)/sizeof(TCHAR)), NULL);
15690 for (i = 0; i <= len; i++)
15691 { if (((TCHAR*)soap->msgbuf)[i] < 0x80)
15692 soap->msgbuf[i] = (char)((TCHAR*)soap->msgbuf)[i];
15693 else
15694 soap->msgbuf[i] = '?';
15695 }
15696 #endif
15697 #endif
15698 }
15699 else
15700 { char *s = soap->msgbuf;
15701 #ifndef WITH_LEAN
15702 int rt = soap->recv_timeout, st = soap->send_timeout;
15703 int ru = ' ', su = ' ';
15704 #endif
15705 strcpy(s, "Operation interrupted or timed out");
15706 #ifndef WITH_LEAN
15707 if (rt < 0)
15708 { rt = -rt;
15709 ru = 'u';
15710 }
15711 if (st < 0)
15712 { st = -st;
15713 su = 'u';
15714 }
15715 if (rt)
15716 sprintf(s + strlen(s), " (%d%cs receive delay)", rt, ru);
15717 if (st)
15718 sprintf(s + strlen(s), " (%d%cs send delay)", st, su);
15719 #endif
15720 }
15721 return soap->msgbuf;
15722 }
15723 #endif
15724 #endif
15725
15726
15727 #ifndef PALM_2
15728 static int
15729 soap_set_error(struct soap *soap, const char *faultcode, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML, int soaperror)
15730 { *soap_faultcode(soap) = faultcode;
15731 if (faultsubcodeQName)
15732 *soap_faultsubcode(soap) = faultsubcodeQName;
15733 *soap_faultstring(soap) = faultstring;
15734 if (faultdetailXML && *faultdetailXML)
15735 { register const char **s = soap_faultdetail(soap);
15736 if (s)
15737 *s = faultdetailXML;
15738 }
15739 return soap->error = soaperror;
15740 }
15741 #endif
15742
15743
15744 #ifndef PALM_2
15745 SOAP_FMAC1
15746 int
15747 SOAP_FMAC2
15748 soap_set_sender_error(struct soap *soap, const char *faultstring, const char *faultdetailXML, int soaperror)
15749 { return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", NULL, faultstring, faultdetailXML, soaperror);
15750 }
15751 #endif
15752
15753
15754 #ifndef PALM_2
15755 SOAP_FMAC1
15756 int
15757 SOAP_FMAC2
15758 soap_set_receiver_error(struct soap *soap, const char *faultstring, const char *faultdetailXML, int soaperror)
15759 { return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", NULL, faultstring, faultdetailXML, soaperror);
15760 }
15761 #endif
15762
15763
15764 #ifndef PALM_2
15765 static int
15766 soap_copy_fault(struct soap *soap, const char *faultcode, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML)
15767 { char *r = NULL, *s = NULL, *t = NULL;
15768 if (faultsubcodeQName)
15769 r = soap_strdup(soap, faultsubcodeQName);
15770 if (faultstring)
15771 s = soap_strdup(soap, faultstring);
15772 if (faultdetailXML)
15773 t = soap_strdup(soap, faultdetailXML);
15774 return soap_set_error(soap, faultcode, r, s, t, SOAP_FAULT);
15775 }
15776 #endif
15777
15778
15779 #ifndef PALM_2
15780 SOAP_FMAC1
15781 int
15782 SOAP_FMAC2
15783 soap_sender_fault(struct soap *soap, const char *faultstring, const char *faultdetailXML)
15784 { return soap_sender_fault_subcode(soap, NULL, faultstring, faultdetailXML);
15785 }
15786 #endif
15787
15788
15789 #ifndef PALM_2
15790 SOAP_FMAC1
15791 int
15792 SOAP_FMAC2
15793 soap_sender_fault_subcode(struct soap *soap, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML)
15794 { return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", faultsubcodeQName, faultstring, faultdetailXML);
15795 }
15796 #endif
15797
15798
15799 #ifndef PALM_2
15800 SOAP_FMAC1
15801 int
15802 SOAP_FMAC2
15803 soap_receiver_fault(struct soap *soap, const char *faultstring, const char *faultdetailXML)
15804 { return soap_receiver_fault_subcode(soap, NULL, faultstring, faultdetailXML);
15805 }
15806 #endif
15807
15808
15809 #ifndef PALM_2
15810 SOAP_FMAC1
15811 int
15812 SOAP_FMAC2
15813 soap_receiver_fault_subcode(struct soap *soap, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML)
15814 { return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", faultsubcodeQName, faultstring, faultdetailXML);
15815 }
15816 #endif
15817
15818
15819 #ifndef PALM_2
15820 #ifndef WITH_NOSTDLIB
15821 SOAP_FMAC1
15822 void
15823 SOAP_FMAC2
15824 soap_print_fault(struct soap *soap, FILE *fd)
15825 { if (soap_check_state(soap))
15826 fprintf(fd, "Error: soap struct state not initialized\n");
15827 else if (soap->error)
15828 { const char *c, *v = NULL, *s, **d;
15829 d = soap_faultcode(soap);
15830 if (!*d)
15831 soap_set_fault(soap);
15832 c = *d;
15833 if (soap->version == 2)
15834 v = *soap_faultsubcode(soap);
15835 s = *soap_faultstring(soap);
15836 d = soap_faultdetail(soap);
15837 fprintf(fd, "%s%d fault: %s [%s]\n\"%s\"\nDetail: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, c, v ? v : "no subcode", s ? s : "[no reason]", d && *d ? *d : "[no detail]");
15838 }
15839 }
15840 #endif
15841 #endif
15842
15843
15844 #ifdef __cplusplus
15845 #ifndef WITH_LEAN
15846 #ifndef WITH_NOSTDLIB
15847 SOAP_FMAC1
15848 void
15849 SOAP_FMAC2
15850 soap_stream_fault(struct soap *soap, std::ostream& os)
15851 { if (soap_check_state(soap))
15852 os << "Error: soap struct state not initialized\n";
15853 else if (soap->error)
15854 { const char *c, *v = NULL, *s, **d;
15855 d = soap_faultcode(soap);
15856 if (!*d)
15857 soap_set_fault(soap);
15858 c = *d;
15859 if (soap->version == 2)
15860 v = *soap_faultsubcode(soap);
15861 s = *soap_faultstring(soap);
15862 d = soap_faultdetail(soap);
15863 os << (soap->version ? "SOAP 1." : "Error ")
15864 << (soap->version ? (int)soap->version : soap->error)
15865 << " fault: " << c
15866 << "[" << (v ? v : "no subcode") << "]"
15867 << std::endl
15868 << "\"" << (s ? s : "[no reason]") << "\""
15869 << std::endl
15870 << "Detail: " << (d && *d ? *d : "[no detail]")
15871 << std::endl;
15872 }
15873 }
15874 #endif
15875 #endif
15876 #endif
15877
15878
15879 #ifndef WITH_LEAN
15880 #ifndef WITH_NOSTDLIB
15881 SOAP_FMAC1
15882 char*
15883 SOAP_FMAC2
15884 soap_sprint_fault(struct soap *soap, char *buf, size_t len)
15885 { if (soap_check_state(soap))
15886 strncpy(buf, "Error: soap struct not initialized", len);
15887 else if (soap->error)
15888 { const char *c, *v = NULL, *s, **d;
15889 d = soap_faultcode(soap);
15890 if (!*d)
15891 soap_set_fault(soap);
15892 c = *d;
15893 if (soap->version == 2)
15894 v = *soap_faultsubcode(soap);
15895 s = *soap_faultstring(soap);
15896 d = soap_faultdetail(soap);
15897 #ifdef HAVE_SNPRINTF
15898 # ifdef WIN32
15899 _snprintf
15900 # else
15901 snprintf
15902 # endif
15903 (buf, len, "%s%d fault: %s [%s]\n\"%s\"\nDetail: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, c, v ? v : "no subcode", s ? s : "[no reason]", d && *d ? *d : "[no detail]");
15904 #else
15905 if (len > 40 + (v ? strlen(v) : 0) + (s ? strlen(s) : 0) + (d && *d ? strlen(*d) : 0))
15906 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 ? *d : "[no detail]");
15907 else if (len > 40)
15908 sprintf(buf, "%s%d fault: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, c);
15909 else
15910 buf[0] = '\0';
15911 #endif
15912 }
15913 return buf;
15914 }
15915 #endif
15916 #endif
15917
15918
15919 #ifndef PALM_1
15920 #ifndef WITH_NOSTDLIB
15921 SOAP_FMAC1
15922 void
15923 SOAP_FMAC2
15924 soap_print_fault_location(struct soap *soap, FILE *fd)
15925 {
15926 #ifndef WITH_LEAN
15927 int i, j, c1, c2;
15928 if (soap->error && soap->error != SOAP_STOP && soap->bufidx <= soap->buflen && soap->buflen > 0 && soap->buflen <= SOAP_BUFLEN)
15929 { i = (int)soap->bufidx - 1;
15930 if (i <= 0)
15931 i = 0;
15932 c1 = soap->buf[i];
15933 soap->buf[i] = '\0';
15934 if ((int)soap->buflen >= i + 1024)
15935 j = i + 1023;
15936 else
15937 j = (int)soap->buflen - 1;
15938 c2 = soap->buf[j];
15939 soap->buf[j] = '\0';
15940 fprintf(fd, "%s%c\n<!-- ** HERE ** -->\n", soap->buf, c1);
15941 if (soap->bufidx < soap->buflen)
15942 fprintf(fd, "%s\n", soap->buf + soap->bufidx);
15943 soap->buf[i] = c1;
15944 soap->buf[j] = c2;
15945 }
15946 #endif
15947 }
15948 #endif
15949 #endif
15950
15951
15952 #ifndef PALM_1
15953 SOAP_FMAC1
15954 int
15955 SOAP_FMAC2
15956 soap_register_plugin_arg(struct soap *soap, int (*fcreate)(struct soap*, struct soap_plugin*, void*), void *arg)
15957 { register struct soap_plugin *p;
15958 register int r;
15959 if (!(p = (struct soap_plugin*)SOAP_MALLOC(soap, sizeof(struct soap_plugin))))
15960 return soap->error = SOAP_EOM;
15961 p->id = NULL;
15962 p->data = NULL;
15963 p->fcopy = NULL;
15964 p->fdelete = NULL;
15965 r = fcreate(soap, p, arg);
15966 if (!r && p->fdelete)
15967 { p->next = soap->plugins;
15968 soap->plugins = p;
15969 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Registered '%s' plugin\n", p->id));
15970 return SOAP_OK;
15971 }
15972 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));
15973 SOAP_FREE(soap, p);
15974 return r;
15975 }
15976 #endif
15977
15978
15979 #ifndef PALM_1
15980 static void *
15981 fplugin(struct soap *soap, const char *id)
15982 { register struct soap_plugin *p;
15983 for (p = soap->plugins; p; p = p->next)
15984 if (p->id == id || !strcmp(p->id, id))
15985 return p->data;
15986 return NULL;
15987 }
15988 #endif
15989
15990
15991 #ifndef PALM_2
15992 SOAP_FMAC1
15993 void *
15994 SOAP_FMAC2
15995 soap_lookup_plugin(struct soap *soap, const char *id)
15996 { return soap->fplugin(soap, id);
15997 }
15998 #endif
15999
16000
16001 #ifdef __cplusplus
16002 }
16003 #endif
16004
16005
16006
16007
16008
16009
16010
16011 #ifdef __cplusplus
16012 soap::soap()
16013 { soap_init(this);
16014 }
16015 #endif
16016
16017
16018 #ifdef __cplusplus
16019 soap::soap(soap_mode m)
16020 { soap_init1(this, m);
16021 }
16022 #endif
16023
16024
16025 #ifdef __cplusplus
16026 soap::soap(soap_mode im, soap_mode om)
16027 { soap_init2(this, im, om);
16028 }
16029 #endif
16030
16031
16032 #ifdef __cplusplus
16033 soap::soap(const struct soap& soap)
16034 { soap_copy_context(this, &soap);
16035 }
16036 #endif
16037
16038
16039 #ifdef __cplusplus
16040 soap::~soap()
16041 { soap_destroy(this);
16042 soap_end(this);
16043 soap_done(this);
16044 }
16045 #endif
16046
16047