998 obsolete DMA driver interfaces should be removed
[unleashed.git] / usr / src / lib / libkmsagent / common / SOAP / stdsoap2.cpp
blob725f64b08b7045767364bb019e4d6301162cc62f
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
26 stdsoap2.c[pp] 2.7.17
28 gSOAP runtime engine
30 gSOAP XML Web services tools
31 Copyright (C) 2000-2010, Robert van Engelen, Genivia Inc., All Rights Reserved.
32 This part of the software is released under ONE of the following licenses:
33 GPL, or the gSOAP public license, or Genivia's license for commercial use.
34 --------------------------------------------------------------------------------
35 Contributors:
37 Oracle, Inc. - additions are noted in the code commented with
38 "Oracle customization"
39 - customization of the SSL accept timeout
40 - work around for SSL_Sleep reporting closed connection
41 - Function ssl_auth_init was static, but is now exported for external override
42 - redirection of gSoap debug logs when debug builds enabled
43 - added SSL_CTX_set_cipher_list call to restrict the cipher suite to RSA-2048/AES
44 TLS_RSA_WITH_AES_256_CBC_SHA is defined in RFC 3268
45 also see http://www.openssl.org/docs/apps/ciphers.html
46 - Added SSL_OP_NO_SSLv3 to force use of TLS
47 - bug fix: added call to close socket handle in various places noted in the code,
48 since the caller overwrites soap->socket with the return value
49 - compile warning cleanup
52 Wind River Systems Inc., for the following additions under gSOAP public license:
53 - vxWorks compatible
54 --------------------------------------------------------------------------------
55 gSOAP public license.
57 The contents of this file are subject to the gSOAP Public License Version 1.3
58 (the "License"); you may not use this file except in compliance with the
59 License. You may obtain a copy of the License at
60 http://www.cs.fsu.edu/~engelen/soaplicense.html
61 Software distributed under the License is distributed on an "AS IS" basis,
62 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
63 for the specific language governing rights and limitations under the License.
65 The Initial Developer of the Original Code is Robert A. van Engelen.
66 Copyright (C) 2000-2010, Robert van Engelen, Genivia Inc., All Rights Reserved.
67 --------------------------------------------------------------------------------
68 GPL license.
70 This program is free software; you can redistribute it and/or modify it under
71 the terms of the GNU General Public License as published by the Free Software
72 Foundation; either version 2 of the License, or (at your option) any later
73 version.
75 This program is distributed in the hope that it will be useful, but WITHOUT ANY
76 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
77 PARTICULAR PURPOSE. See the GNU General Public License for more details.
79 You should have received a copy of the GNU General Public License along with
80 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
81 Place, Suite 330, Boston, MA 02111-1307 USA
83 Author contact information:
84 engelen@genivia.com / engelen@acm.org
86 This program is released under the GPL with the additional exemption that
87 compiling, linking, and/or using OpenSSL is allowed.
88 --------------------------------------------------------------------------------
89 A commercial use license is available from Genivia, Inc., contact@genivia.com
90 --------------------------------------------------------------------------------
92 Installation note:
94 Win32 build needs winsock.dll (Visual C++ "wsock32.lib")
95 To do this in Visual C++ 6.0, go to "Project", "settings", select the "Link"
96 tab (the project file needs to be selected in the file view) and add
97 "wsock32.lib" to the "Object/library modules" entry
99 On Mac OS X with gcc (GCC) 3.1 20020420 (prerelease) you MUST compile with
100 -fstack_check when using -O2 because gcc 3.1 has a bug that smashes the stack
101 when locally allocated data exceeds 64K.
105 #ifdef AS400
106 # pragma convert(819) /* EBCDIC to ASCII */
107 #endif
109 #include "stdsoap2.h"
112 Oracle customization for OpenSSL 0.9.8 removal of deprecated function usage: RSA_generate_key
114 #ifdef WITH_OPENSSL
115 #ifdef OPENSSL_NO_DEPRECATED
116 #include <openssl/rsa.h>
117 #include <openssl/bn.h>
118 #include <openssl/dh.h>
119 #endif
120 #endif
122 #ifdef SOAP_MEM_DEBUG
123 #ifndef WIN32
124 #include <ucontext.h> /* Oracle customization (for printstack(3C)) */
125 #endif
126 #endif
128 #ifdef __BORLANDC__
129 # pragma warn -8060
130 #else
131 # ifdef WIN32
132 # ifdef UNDER_CE
133 # pragma comment(lib, "winsock.lib")
134 # else
135 # pragma comment(lib, "wsock32.lib")
136 # endif
137 # pragma warning(disable : 4996) /* disable deprecation warnings */
138 # endif
139 #endif
141 #ifdef __cplusplus
142 SOAP_SOURCE_STAMP("@(#) stdsoap2.cpp ver 2.7.17 2010-05-10 00:00:00 GMT")
143 extern "C" {
144 #else
145 SOAP_SOURCE_STAMP("@(#) stdsoap2.c ver 2.7.17 2010-05-10 00:00:00 GMT")
146 #endif
148 /* 8bit character representing unknown/nonrepresentable character data (e.g. not supported by current locale with multibyte support enabled) */
149 #ifndef SOAP_UNKNOWN_CHAR
150 #define SOAP_UNKNOWN_CHAR (127)
151 #endif
153 /* EOF=-1 */
154 #define SOAP_LT (soap_wchar)(-2) /* XML character '<' */
155 #define SOAP_TT (soap_wchar)(-3) /* XML character '</' */
156 #define SOAP_GT (soap_wchar)(-4) /* XML character '>' */
157 #define SOAP_QT (soap_wchar)(-5) /* XML character '"' */
158 #define SOAP_AP (soap_wchar)(-6) /* XML character ''' */
160 #define soap_blank(c) ((c) >= 0 && (c) <= 32)
161 #define soap_notblank(c) ((c) > 32)
163 #if defined(WIN32) && !defined(UNDER_CE)
164 #define soap_hash_ptr(p) ((PtrToUlong(p) >> 3) & (SOAP_PTRHASH - 1))
165 #else
166 #define soap_hash_ptr(p) ((size_t)(((unsigned long)(p) >> 3) & (SOAP_PTRHASH-1)))
167 #endif
169 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
170 static void soap_init_logs(struct soap*);
171 #endif
172 #ifdef SOAP_DEBUG
173 static void soap_close_logfile(struct soap*, int);
174 static void soap_set_logfile(struct soap*, int, const char*);
175 #endif
177 #ifdef SOAP_MEM_DEBUG
178 static void soap_init_mht(struct soap*);
179 static void soap_free_mht(struct soap*);
180 static void soap_track_unlink(struct soap*, const void*);
181 #endif
183 #ifndef PALM_2
184 static int soap_set_error(struct soap*, const char*, const char*, const char*, const char*, int);
185 static int soap_copy_fault(struct soap*, const char*, const char*, const char*, const char*);
186 static int soap_getattrval(struct soap*, char*, size_t, soap_wchar);
187 #endif
189 #ifndef PALM_1
190 static void soap_free_ns(struct soap *soap);
191 static soap_wchar soap_char(struct soap*);
192 static soap_wchar soap_get_pi(struct soap*);
193 static int soap_isxdigit(int);
194 static void *fplugin(struct soap*, const char*);
195 static char *soap_get_http_body(struct soap*);
196 static size_t soap_count_attachments(struct soap *soap);
197 static int soap_try_connect_command(struct soap*, int http_command, const char *endpoint, const char *action);
198 #ifndef WITH_NOIDREF
199 static void soap_update_ptrs(struct soap*, char*, char*, char*, char*);
200 static int soap_has_copies(struct soap*, const char*, const char*);
201 static void soap_init_iht(struct soap*);
202 static void soap_free_iht(struct soap*);
203 static void soap_init_pht(struct soap*);
204 static void soap_free_pht(struct soap*);
205 #endif
206 #endif
208 #ifndef WITH_LEAN
209 static const char *soap_set_validation_fault(struct soap*, const char*, const char*);
210 static int soap_isnumeric(struct soap*, const char*);
211 static struct soap_nlist *soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized);
212 static void soap_utilize_ns(struct soap *soap, const char *tag, size_t n);
213 #endif
215 #ifndef WITH_LEANER
216 #ifndef PALM_1
217 static struct soap_multipart *soap_new_multipart(struct soap*, struct soap_multipart**, struct soap_multipart**, char*, size_t);
218 static int soap_putdimefield(struct soap*, const char*, size_t);
219 static char *soap_getdimefield(struct soap*, size_t);
220 static void soap_select_mime_boundary(struct soap*);
221 static int soap_valid_mime_boundary(struct soap*);
222 static void soap_resolve_attachment(struct soap*, struct soap_multipart*);
223 #endif
224 #endif
226 #ifdef WITH_GZIP
227 static int soap_getgziphdr(struct soap*);
228 #endif
230 #ifdef WITH_OPENSSL
231 int soap_ssl_init_done = 0;
234 // Oracle customization
236 // Function ssl_auth_init was static, but is now exported for external override
238 static int ssl_auth_init(struct soap*);
240 int ssl_auth_init(struct soap*);
241 static int ssl_verify_callback(int, X509_STORE_CTX*);
242 static int ssl_verify_callback_allow_expired_certificate(int, X509_STORE_CTX*);
243 static int ssl_password(char*, int, int, void *);
244 #endif
246 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
247 #ifndef PALM_1
248 static const char *soap_decode(char*, size_t, const char*, const char*);
249 #endif
250 #endif
252 #ifndef WITH_NOHTTP
253 #ifndef PALM_1
254 static soap_wchar soap_getchunkchar(struct soap*);
255 static const char *http_error(struct soap*, int);
256 static int http_get(struct soap*);
257 static int http_405(struct soap*);
258 static int http_post(struct soap*, const char*, const char*, int, const char*, const char*, size_t);
259 static int http_send_header(struct soap*, const char*);
260 static int http_post_header(struct soap*, const char*, const char*);
261 static int http_response(struct soap*, int, size_t);
262 static int http_parse(struct soap*);
263 static int http_parse_header(struct soap*, const char*, const char*);
264 #endif
265 #endif
267 #ifndef WITH_NOIO
269 #ifndef PALM_1
270 static int fsend(struct soap*, const char*, size_t);
271 static size_t frecv(struct soap*, char*, size_t);
272 static int tcp_init(struct soap*);
273 static const char *tcp_error(struct soap*);
274 #ifndef WITH_IPV6
275 static int tcp_gethost(struct soap*, const char *addr, struct in_addr *inaddr);
276 #endif
277 static SOAP_SOCKET tcp_connect(struct soap*, const char *endpoint, const char *host, int port);
278 static SOAP_SOCKET tcp_accept(struct soap*, SOAP_SOCKET, struct sockaddr*, int*);
279 static int tcp_select(struct soap*, SOAP_SOCKET, int, int);
280 static int tcp_disconnect(struct soap*);
281 static int tcp_closesocket(struct soap*, SOAP_SOCKET);
282 static int tcp_shutdownsocket(struct soap*, SOAP_SOCKET, int);
283 static const char *soap_strerror(struct soap*);
284 #endif
286 #define SOAP_TCP_SELECT_RCV 0x1
287 #define SOAP_TCP_SELECT_SND 0x2
288 #define SOAP_TCP_SELECT_ERR 0x4
289 #define SOAP_TCP_SELECT_ALL 0x7
291 #if defined(WIN32)
292 #define SOAP_SOCKBLOCK(fd) \
293 { u_long blocking = 0; \
294 ioctlsocket(fd, FIONBIO, &blocking); \
296 #define SOAP_SOCKNONBLOCK(fd) \
297 { u_long nonblocking = 1; \
298 ioctlsocket(fd, FIONBIO, &nonblocking); \
300 #elif defined(VXWORKS)
301 #define SOAP_SOCKBLOCK(fd) \
302 { u_long blocking = 0; \
303 ioctl(fd, FIONBIO, (int)(&blocking)); \
305 #define SOAP_SOCKNONBLOCK(fd) \
306 { u_long nonblocking = 1; \
307 ioctl(fd, FIONBIO, (int)(&nonblocking)); \
309 #elif defined(PALM)
310 #define SOAP_SOCKBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)&~O_NONBLOCK);
311 #define SOAP_SOCKNONBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)|O_NONBLOCK);
312 #elif defined(SYMBIAN)
313 #define SOAP_SOCKBLOCK(fd) \
314 { long blocking = 0; \
315 ioctl(fd, 0/*FIONBIO*/, &blocking); \
317 #define SOAP_SOCKNONBLOCK(fd) \
318 { long nonblocking = 1; \
319 ioctl(fd, 0/*FIONBIO*/, &nonblocking); \
321 #else
322 #define SOAP_SOCKBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)&~O_NONBLOCK);
323 #define SOAP_SOCKNONBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)|O_NONBLOCK);
324 #endif
326 #endif
328 #if defined(PALM) && !defined(PALM_2)
329 unsigned short errno;
330 #endif
332 #ifndef PALM_1
333 static const char soap_env1[42] = "http://schemas.xmlsoap.org/soap/envelope/";
334 static const char soap_enc1[42] = "http://schemas.xmlsoap.org/soap/encoding/";
335 static const char soap_env2[40] = "http://www.w3.org/2003/05/soap-envelope";
336 static const char soap_enc2[40] = "http://www.w3.org/2003/05/soap-encoding";
337 static const char soap_rpc[35] = "http://www.w3.org/2003/05/soap-rpc";
338 #endif
340 #ifndef PALM_1
341 const struct soap_double_nan soap_double_nan = {0xFFFFFFFF, 0xFFFFFFFF};
342 static const char soap_base64o[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
343 static const char soap_base64i[81] = "\76XXX\77\64\65\66\67\70\71\72\73\74\75XXXXXXX\00\01\02\03\04\05\06\07\10\11\12\13\14\15\16\17\20\21\22\23\24\25\26\27\30\31XXXXXX\32\33\34\35\36\37\40\41\42\43\44\45\46\47\50\51\52\53\54\55\56\57\60\61\62\63";
344 #endif
346 #ifndef WITH_LEAN
347 static const char soap_indent[11] = "\n\t\t\t\t\t\t\t\t\t";
348 /* Alternative indentation form for SOAP_XML_INDENT:
349 static const char soap_indent[21] = "\n ";
351 #endif
353 #ifndef SOAP_CANARY
354 # define SOAP_CANARY (0xC0DE)
355 #endif
357 static const char soap_padding[4] = "\0\0\0";
358 #define SOAP_STR_PADDING (soap_padding)
359 #define SOAP_STR_EOS (soap_padding)
360 #define SOAP_NON_NULL (soap_padding)
362 #ifndef WITH_LEAN
363 static const struct soap_code_map html_entity_codes[] = /* entities for XHTML parsing */
364 { { 160, "nbsp" },
365 { 161, "iexcl" },
366 { 162, "cent" },
367 { 163, "pound" },
368 { 164, "curren" },
369 { 165, "yen" },
370 { 166, "brvbar" },
371 { 167, "sect" },
372 { 168, "uml" },
373 { 169, "copy" },
374 { 170, "ordf" },
375 { 171, "laquo" },
376 { 172, "not" },
377 { 173, "shy" },
378 { 174, "reg" },
379 { 175, "macr" },
380 { 176, "deg" },
381 { 177, "plusmn" },
382 { 178, "sup2" },
383 { 179, "sup3" },
384 { 180, "acute" },
385 { 181, "micro" },
386 { 182, "para" },
387 { 183, "middot" },
388 { 184, "cedil" },
389 { 185, "sup1" },
390 { 186, "ordm" },
391 { 187, "raquo" },
392 { 188, "frac14" },
393 { 189, "frac12" },
394 { 190, "frac34" },
395 { 191, "iquest" },
396 { 192, "Agrave" },
397 { 193, "Aacute" },
398 { 194, "Acirc" },
399 { 195, "Atilde" },
400 { 196, "Auml" },
401 { 197, "Aring" },
402 { 198, "AElig" },
403 { 199, "Ccedil" },
404 { 200, "Egrave" },
405 { 201, "Eacute" },
406 { 202, "Ecirc" },
407 { 203, "Euml" },
408 { 204, "Igrave" },
409 { 205, "Iacute" },
410 { 206, "Icirc" },
411 { 207, "Iuml" },
412 { 208, "ETH" },
413 { 209, "Ntilde" },
414 { 210, "Ograve" },
415 { 211, "Oacute" },
416 { 212, "Ocirc" },
417 { 213, "Otilde" },
418 { 214, "Ouml" },
419 { 215, "times" },
420 { 216, "Oslash" },
421 { 217, "Ugrave" },
422 { 218, "Uacute" },
423 { 219, "Ucirc" },
424 { 220, "Uuml" },
425 { 221, "Yacute" },
426 { 222, "THORN" },
427 { 223, "szlig" },
428 { 224, "agrave" },
429 { 225, "aacute" },
430 { 226, "acirc" },
431 { 227, "atilde" },
432 { 228, "auml" },
433 { 229, "aring" },
434 { 230, "aelig" },
435 { 231, "ccedil" },
436 { 232, "egrave" },
437 { 233, "eacute" },
438 { 234, "ecirc" },
439 { 235, "euml" },
440 { 236, "igrave" },
441 { 237, "iacute" },
442 { 238, "icirc" },
443 { 239, "iuml" },
444 { 240, "eth" },
445 { 241, "ntilde" },
446 { 242, "ograve" },
447 { 243, "oacute" },
448 { 244, "ocirc" },
449 { 245, "otilde" },
450 { 246, "ouml" },
451 { 247, "divide" },
452 { 248, "oslash" },
453 { 249, "ugrave" },
454 { 250, "uacute" },
455 { 251, "ucirc" },
456 { 252, "uuml" },
457 { 253, "yacute" },
458 { 254, "thorn" },
459 { 255, "yuml" },
460 { 0, NULL }
462 #endif
464 #ifndef WITH_NOIO
465 #ifndef WITH_LEAN
466 static const struct soap_code_map h_error_codes[] =
468 #ifdef HOST_NOT_FOUND
469 { HOST_NOT_FOUND, "Host not found" },
470 #endif
471 #ifdef TRY_AGAIN
472 { TRY_AGAIN, "Try Again" },
473 #endif
474 #ifdef NO_RECOVERY
475 { NO_RECOVERY, "No Recovery" },
476 #endif
477 #ifdef NO_DATA
478 { NO_DATA, "No Data" },
479 #endif
480 #ifdef NO_ADDRESS
481 { NO_ADDRESS, "No Address" },
482 #endif
483 { 0, NULL }
485 #endif
486 #endif
488 #ifndef WITH_NOHTTP
489 #ifndef WITH_LEAN
490 static const struct soap_code_map h_http_error_codes[] =
491 { { 200, "OK" },
492 { 201, "Created" },
493 { 202, "Accepted" },
494 { 203, "Non-Authoritative Information" },
495 { 204, "No Content" },
496 { 205, "Reset Content" },
497 { 206, "Partial Content" },
498 { 300, "Multiple Choices" },
499 { 301, "Moved Permanently" },
500 { 302, "Found" },
501 { 303, "See Other" },
502 { 304, "Not Modified" },
503 { 305, "Use Proxy" },
504 { 307, "Temporary Redirect" },
505 { 400, "Bad Request" },
506 { 401, "Unauthorized" },
507 { 402, "Payment Required" },
508 { 403, "Forbidden" },
509 { 404, "Not Found" },
510 { 405, "Method Not Allowed" },
511 { 406, "Not Acceptable" },
512 { 407, "Proxy Authentication Required" },
513 { 408, "Request Time-out" },
514 { 409, "Conflict" },
515 { 410, "Gone" },
516 { 411, "Length Required" },
517 { 412, "Precondition Failed" },
518 { 413, "Request Entity Too Large" },
519 { 414, "Request-URI Too Large" },
520 { 415, "Unsupported Media Type" },
521 { 416, "Requested range not satisfiable" },
522 { 417, "Expectation Failed" },
523 { 500, "Internal Server Error" },
524 { 501, "Not Implemented" },
525 { 502, "Bad Gateway" },
526 { 503, "Service Unavailable" },
527 { 504, "Gateway Time-out" },
528 { 505, "HTTP Version not supported" },
529 { 0, NULL }
531 #endif
532 #endif
534 #ifdef WITH_OPENSSL
535 static const struct soap_code_map h_ssl_error_codes[] =
537 #define _SSL_ERROR(e) { e, #e }
538 _SSL_ERROR(SSL_ERROR_SSL),
539 _SSL_ERROR(SSL_ERROR_ZERO_RETURN),
540 _SSL_ERROR(SSL_ERROR_WANT_READ),
541 _SSL_ERROR(SSL_ERROR_WANT_WRITE),
542 _SSL_ERROR(SSL_ERROR_WANT_CONNECT),
543 _SSL_ERROR(SSL_ERROR_WANT_X509_LOOKUP),
544 _SSL_ERROR(SSL_ERROR_SYSCALL),
545 { 0, NULL }
547 #endif
549 #ifndef WITH_LEANER
550 static const struct soap_code_map mime_codes[] =
551 { { SOAP_MIME_7BIT, "7bit" },
552 { SOAP_MIME_8BIT, "8bit" },
553 { SOAP_MIME_BINARY, "binary" },
554 { SOAP_MIME_QUOTED_PRINTABLE, "quoted-printable" },
555 { SOAP_MIME_BASE64, "base64" },
556 { SOAP_MIME_IETF_TOKEN, "ietf-token" },
557 { SOAP_MIME_X_TOKEN, "x-token" },
558 { 0, NULL }
560 #endif
562 #ifdef WIN32
563 static int tcp_done = 0;
564 #endif
566 #if defined(HP_UX) && defined(HAVE_GETHOSTBYNAME_R)
567 extern int h_errno;
568 #endif
570 /******************************************************************************/
571 #ifndef WITH_NOIO
572 #ifndef PALM_1
573 static int
574 fsend(struct soap *soap, const char *s, size_t n)
575 { register int nwritten, err;
576 #if defined(__cplusplus) && !defined(WITH_LEAN) && !defined(WITH_COMPAT)
577 if (soap->os)
578 { soap->os->write(s, (std::streamsize)n);
579 if (soap->os->good())
580 return SOAP_OK;
581 soap->errnum = 0;
582 return SOAP_EOF;
584 #endif
585 while (n)
586 { if (soap_valid_socket(soap->socket))
588 if (soap->send_timeout)
589 { for (;;)
590 { register int r;
591 #ifdef WITH_OPENSSL
592 if (soap->ssl)
593 r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_ALL, soap->send_timeout);
594 else
595 #endif
596 r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->send_timeout);
597 if (r > 0)
598 break;
599 if (!r)
600 return SOAP_EOF;
601 err = soap->errnum;
602 if (!err)
603 return soap->error;
604 if (err != SOAP_EINTR && err != SOAP_EAGAIN && err != SOAP_EWOULDBLOCK)
605 return SOAP_EOF;
608 #ifdef WITH_OPENSSL
609 if (soap->ssl)
610 nwritten = SSL_write(soap->ssl, s, (int)n);
611 else if (soap->bio)
612 nwritten = BIO_write(soap->bio, s, (int)n);
613 else
614 #endif
615 #ifndef WITH_LEAN
616 if ((soap->omode & SOAP_IO_UDP))
617 { if (soap->peerlen)
618 nwritten = sendto(soap->socket, (char*)s, (SOAP_WINSOCKINT)n, soap->socket_flags, (struct sockaddr*)&soap->peer, (SOAP_WINSOCKINT)soap->peerlen);
619 else
620 nwritten = send(soap->socket, s, (SOAP_WINSOCKINT)n, soap->socket_flags);
621 /* retry and back-off algorithm */
622 /* TODO: this is not very clear from specs so verify and limit conditions under which we should loop (e.g. ENOBUFS) */
623 if (nwritten < 0)
624 { int udp_repeat;
625 int udp_delay;
626 if ((soap->connect_flags & SO_BROADCAST))
627 udp_repeat = 3; /* SOAP-over-UDP MULTICAST_UDP_REPEAT - 1 */
628 else
629 udp_repeat = 1; /* SOAP-over-UDP UNICAST_UDP_REPEAT - 1 */
630 udp_delay = (soap_random % 201) + 50; /* UDP_MIN_DELAY .. UDP_MAX_DELAY */
632 { tcp_select(soap, soap->socket, SOAP_TCP_SELECT_ERR, -1000 * udp_delay);
633 if (soap->peerlen)
634 nwritten = sendto(soap->socket, (char*)s, (SOAP_WINSOCKINT)n, soap->socket_flags, (struct sockaddr*)&soap->peer, (SOAP_WINSOCKINT)soap->peerlen);
635 else
636 nwritten = send(soap->socket, s, (SOAP_WINSOCKINT)n, soap->socket_flags);
637 udp_delay <<= 1;
638 if (udp_delay > 500) /* UDP_UPPER_DELAY */
639 udp_delay = 500;
641 while (nwritten < 0 && --udp_repeat > 0);
644 else
645 #endif
646 #if !defined(PALM) && !defined(AS400)
647 nwritten = send(soap->socket, s, (int)n, soap->socket_flags);
648 #else
649 nwritten = send(soap->socket, (void*)s, n, soap->socket_flags);
650 #endif
651 if (nwritten <= 0)
653 register int r = 0;
654 err = soap_socket_errno(soap->socket);
655 #ifdef WITH_OPENSSL
656 if (soap->ssl && (r = SSL_get_error(soap->ssl, nwritten)) != SSL_ERROR_NONE && r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE)
657 { soap->errnum = err;
658 return SOAP_EOF;
660 #endif
661 if (err == SOAP_EWOULDBLOCK || err == SOAP_EAGAIN)
663 #ifdef WITH_OPENSSL
664 if (soap->ssl && r == SSL_ERROR_WANT_READ)
665 r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->send_timeout ? soap->send_timeout : -10000);
666 else
667 r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->send_timeout ? soap->send_timeout : -10000);
668 #else
669 r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->send_timeout ? soap->send_timeout : -10000);
670 #endif
671 if (!r && soap->send_timeout)
672 return SOAP_EOF;
673 if (r < 0 && soap->errnum != SOAP_EINTR)
674 return SOAP_EOF;
676 else if (err && err != SOAP_EINTR)
677 { soap->errnum = err;
678 return SOAP_EOF;
680 nwritten = 0; /* and call write() again */
683 else
685 #ifdef WITH_FASTCGI
686 nwritten = fwrite((void*)s, 1, n, stdout);
687 fflush(stdout);
688 #else
689 #ifdef UNDER_CE
690 nwritten = fwrite(s, 1, n, soap->sendfd);
691 #else
692 #ifdef VXWORKS
693 #ifdef WMW_RPM_IO
694 if (soap->rpmreqid)
695 nwritten = (httpBlockPut(soap->rpmreqid, (char*)s, n) == 0) ? n : -1;
696 else
697 #endif
698 nwritten = fwrite(s, sizeof(char), n, fdopen(soap->sendfd, "w"));
699 #else
700 #ifdef WIN32
701 nwritten = _write(soap->sendfd, s, (unsigned int)n);
702 #else
703 nwritten = write(soap->sendfd, s, (unsigned int)n);
704 #endif
705 #endif
706 #endif
707 #endif
708 if (nwritten <= 0)
710 #ifndef WITH_FASTCGI
711 err = soap_errno;
712 #else
713 err = EOF;
714 #endif
715 if (err && err != SOAP_EINTR && err != SOAP_EWOULDBLOCK && err != SOAP_EAGAIN)
716 { soap->errnum = err;
717 return SOAP_EOF;
719 nwritten = 0; /* and call write() again */
722 n -= nwritten;
723 s += nwritten;
725 return SOAP_OK;
727 #endif
728 #endif
730 /******************************************************************************/
731 #ifndef PALM_1
732 SOAP_FMAC1
734 SOAP_FMAC2
735 soap_send_raw(struct soap *soap, const char *s, size_t n)
736 { if (!n)
737 return SOAP_OK;
738 if (soap->mode & SOAP_IO_LENGTH)
739 { soap->count += n;
740 #ifndef WITH_LEANER
741 if (soap->fpreparesend && (soap->mode & SOAP_IO) != SOAP_IO_STORE)
742 return soap->error = soap->fpreparesend(soap, s, n);
743 #endif
744 return SOAP_OK;
746 if (soap->mode & SOAP_IO)
747 { register size_t i = SOAP_BUFLEN - soap->bufidx;
748 while (n >= i)
749 { memcpy(soap->buf + soap->bufidx, s, i);
750 soap->bufidx = SOAP_BUFLEN;
751 if (soap_flush(soap))
752 return soap->error;
753 s += i;
754 n -= i;
755 i = SOAP_BUFLEN;
757 memcpy(soap->buf + soap->bufidx, s, n);
758 soap->bufidx += n;
759 return SOAP_OK;
761 return soap_flush_raw(soap, s, n);
763 #endif
765 /******************************************************************************/
766 #ifndef PALM_1
767 SOAP_FMAC1
769 SOAP_FMAC2
770 soap_flush(struct soap *soap)
771 { register size_t n = soap->bufidx;
772 if (n)
774 #ifndef WITH_LEANER
775 if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
776 { register int r;
777 if (soap->fpreparesend && (r = soap->fpreparesend(soap, soap->buf, n)))
778 return soap->error = r;
780 #endif
781 soap->bufidx = 0;
782 #ifdef WITH_ZLIB
783 if (soap->mode & SOAP_ENC_ZLIB)
784 { soap->d_stream->next_in = (Byte*)soap->buf;
785 soap->d_stream->avail_in = (unsigned int)n;
786 #ifdef WITH_GZIP
787 soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)n);
788 #endif
790 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating %u bytes\n", soap->d_stream->avail_in));
791 if (deflate(soap->d_stream, Z_NO_FLUSH) != Z_OK)
792 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to deflate: %s\n", soap->d_stream->msg?soap->d_stream->msg:SOAP_STR_EOS));
793 return soap->error = SOAP_ZLIB_ERROR;
795 if (!soap->d_stream->avail_out)
796 { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN))
797 return soap->error;
798 soap->d_stream->next_out = (Byte*)soap->z_buf;
799 soap->d_stream->avail_out = SOAP_BUFLEN;
801 } while (soap->d_stream->avail_in);
803 else
804 #endif
805 return soap_flush_raw(soap, soap->buf, n);
807 return SOAP_OK;
809 #endif
811 /******************************************************************************/
812 #ifndef PALM_1
813 SOAP_FMAC1
815 SOAP_FMAC2
816 soap_flush_raw(struct soap *soap, const char *s, size_t n)
817 { if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
818 { register char *t;
819 if (!(t = (char*)soap_push_block(soap, NULL, n)))
820 return soap->error = SOAP_EOM;
821 memcpy(t, s, n);
822 return SOAP_OK;
824 #ifndef WITH_LEANER
825 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
826 { char t[16];
827 sprintf(t, "\r\n%lX\r\n" + (soap->chunksize ? 0 : 2), (unsigned long)n);
828 DBGMSG(SENT, t, strlen(t));
829 if ((soap->error = soap->fsend(soap, t, strlen(t))))
830 return soap->error;
831 soap->chunksize += n;
833 DBGMSG(SENT, s, n);
834 #endif
835 return soap->error = soap->fsend(soap, s, n);
837 #endif
839 /******************************************************************************/
840 #ifndef PALM_1
841 SOAP_FMAC1
843 SOAP_FMAC2
844 soap_send(struct soap *soap, const char *s)
845 { if (s)
846 return soap_send_raw(soap, s, strlen(s));
847 return SOAP_OK;
849 #endif
851 /******************************************************************************/
852 #ifndef WITH_LEANER
853 #ifndef PALM_1
854 SOAP_FMAC1
856 SOAP_FMAC2
857 soap_send2(struct soap *soap, const char *s1, const char *s2)
858 { if (soap_send(soap, s1))
859 return soap->error;
860 return soap_send(soap, s2);
862 #endif
863 #endif
865 /******************************************************************************/
866 #ifndef WITH_LEANER
867 #ifndef PALM_1
868 SOAP_FMAC1
870 SOAP_FMAC2
871 soap_send3(struct soap *soap, const char *s1, const char *s2, const char *s3)
872 { if (soap_send(soap, s1)
873 || soap_send(soap, s2))
874 return soap->error;
875 return soap_send(soap, s3);
877 #endif
878 #endif
880 /******************************************************************************/
881 #ifndef WITH_NOIO
882 #ifndef PALM_1
883 static size_t
884 frecv(struct soap *soap, char *s, size_t n)
885 { register int r;
886 register int retries = 100; /* max 100 retries with non-blocking sockets */
887 soap->errnum = 0;
888 #if defined(__cplusplus) && !defined(WITH_LEAN) && !defined(WITH_COMPAT)
889 if (soap->is)
890 { if (soap->is->good())
891 return soap->is->read(s, (std::streamsize)n).gcount();
892 return 0;
894 #endif
895 if (soap_valid_socket(soap->socket))
896 { for (;;)
898 #ifdef WITH_OPENSSL
899 register int err = 0;
900 #endif
901 #ifdef WITH_OPENSSL
902 if (soap->recv_timeout && !soap->ssl) /* SSL: sockets are nonblocking */
903 #else
904 if (soap->recv_timeout)
905 #endif
906 { for (;;)
907 { r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->recv_timeout);
908 if (r > 0)
909 break;
910 if (!r)
911 return 0;
912 r = soap->errnum;
913 if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
914 return 0;
917 #ifdef WITH_OPENSSL
918 if (soap->ssl)
919 { r = SSL_read(soap->ssl, s, (int)n);
920 if (r > 0)
921 return (size_t)r;
922 err = SSL_get_error(soap->ssl, r);
923 if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
924 return 0;
926 else if (soap->bio)
927 { r = BIO_read(soap->bio, s, (int)n);
928 if (r > 0)
929 return (size_t)r;
930 return 0;
932 else
933 #endif
935 #ifndef WITH_LEAN
936 if ((soap->omode & SOAP_IO_UDP))
937 { SOAP_SOCKLEN_T k = (SOAP_SOCKLEN_T)sizeof(soap->peer);
938 memset((void*)&soap->peer, 0, sizeof(soap->peer));
939 r = recvfrom(soap->socket, s, (SOAP_WINSOCKINT)n, soap->socket_flags, (struct sockaddr*)&soap->peer, &k); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
940 soap->peerlen = (size_t)k;
941 #ifndef WITH_IPV6
942 soap->ip = ntohl(soap->peer.sin_addr.s_addr);
943 #endif
945 else
946 #endif
947 r = recv(soap->socket, s, (int)n, soap->socket_flags);
948 #ifdef PALM
949 /* CycleSyncDisplay(curStatusMsg); */
950 #endif
951 if (r >= 0)
952 return (size_t)r;
953 r = soap_socket_errno(soap->socket);
954 if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
955 { soap->errnum = r;
956 return 0;
959 #ifdef WITH_OPENSSL
960 if (soap->ssl && err == SSL_ERROR_WANT_WRITE)
961 r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5);
962 else
963 r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5);
964 #else
965 r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5);
966 #endif
967 if (!r && soap->recv_timeout)
968 return 0;
969 if (r < 0)
970 { r = soap->errnum;
971 if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
972 return 0;
974 if (retries-- <= 0)
975 return 0;
976 #ifdef PALM
977 r = soap_socket_errno(soap->socket);
978 if (r != SOAP_EINTR && retries-- <= 0)
979 { soap->errnum = r;
980 return 0;
982 #endif
985 #ifdef WITH_FASTCGI
986 return fread(s, 1, n, stdin);
987 #else
988 #ifdef UNDER_CE
989 return fread(s, 1, n, soap->recvfd);
990 #else
991 #ifdef WMW_RPM_IO
992 if (soap->rpmreqid)
993 r = httpBlockRead(soap->rpmreqid, s, n);
994 else
995 #endif
996 #ifdef WIN32
997 r = _read(soap->recvfd, s, (unsigned int)n);
998 #else
999 r = read(soap->recvfd, s, (unsigned int)n);
1000 #endif
1001 if (r >= 0)
1002 return (size_t)r;
1003 soap->errnum = soap_errno;
1004 return 0;
1005 #endif
1006 #endif
1008 #endif
1009 #endif
1011 /******************************************************************************/
1012 #ifndef WITH_NOHTTP
1013 #ifndef PALM_1
1014 static soap_wchar
1015 soap_getchunkchar(struct soap *soap)
1016 { if (soap->bufidx < soap->buflen)
1017 return soap->buf[soap->bufidx++];
1018 soap->bufidx = 0;
1019 soap->buflen = soap->chunkbuflen = soap->frecv(soap, soap->buf, SOAP_BUFLEN);
1020 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket %d\n", (unsigned int)soap->buflen, soap->socket));
1021 DBGMSG(RECV, soap->buf, soap->buflen);
1022 if (soap->buflen)
1023 return soap->buf[soap->bufidx++];
1024 return EOF;
1026 #endif
1027 #endif
1029 /******************************************************************************/
1030 #ifndef PALM_1
1031 static int
1032 soap_isxdigit(int c)
1033 { return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
1035 #endif
1037 /******************************************************************************/
1038 #ifndef PALM_1
1039 SOAP_FMAC1
1041 SOAP_FMAC2
1042 soap_recv_raw(struct soap *soap)
1043 { register size_t ret;
1044 #if !defined(WITH_LEANER) || defined(WITH_ZLIB)
1045 register int r;
1046 #endif
1047 #ifdef WITH_ZLIB
1048 if (soap->mode & SOAP_ENC_ZLIB)
1049 { if (soap->d_stream->next_out == Z_NULL)
1050 return EOF;
1051 if (soap->d_stream->avail_in || !soap->d_stream->avail_out)
1052 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflating\n"));
1053 soap->d_stream->next_out = (Byte*)soap->buf;
1054 soap->d_stream->avail_out = SOAP_BUFLEN;
1055 r = inflate(soap->d_stream, Z_NO_FLUSH);
1056 if (r == Z_NEED_DICT && soap->z_dict)
1057 r = inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len);
1058 if (r == Z_OK || r == Z_STREAM_END)
1059 { soap->bufidx = 0;
1060 ret = soap->buflen = SOAP_BUFLEN - soap->d_stream->avail_out;
1061 if (soap->zlib_in == SOAP_ZLIB_GZIP)
1062 soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)ret);
1063 if (r == Z_STREAM_END)
1064 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out));
1065 soap->z_ratio_in = (float)soap->d_stream->total_in / (float)soap->d_stream->total_out;
1066 soap->d_stream->next_out = Z_NULL;
1068 if (ret)
1069 { soap->count += ret;
1070 DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- decompressed ----\n"));
1071 DBGMSG(RECV, soap->buf, ret);
1072 DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n----\n"));
1073 #ifndef WITH_LEANER
1074 if (soap->fpreparerecv && (r = soap->fpreparerecv(soap, soap->buf, ret)))
1075 return soap->error = r;
1076 #endif
1077 return SOAP_OK;
1080 else if (r != Z_BUF_ERROR)
1081 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate error: %s\n", soap->d_stream->msg?soap->d_stream->msg:SOAP_STR_EOS));
1082 soap->d_stream->next_out = Z_NULL;
1083 soap->error = SOAP_ZLIB_ERROR;
1084 return EOF;
1087 zlib_again:
1088 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK && !soap->chunksize)
1089 { memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN);
1090 soap->buflen = soap->z_buflen;
1092 DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- compressed ----\n"));
1094 #endif
1095 #ifndef WITH_NOHTTP
1096 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) /* read HTTP chunked transfer */
1097 { for (;;)
1098 { register soap_wchar c;
1099 char *t, tmp[8];
1100 if (soap->chunksize)
1101 { soap->buflen = ret = soap->frecv(soap, soap->buf, soap->chunksize > SOAP_BUFLEN ? SOAP_BUFLEN : soap->chunksize);
1102 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk: read %u bytes\n", (unsigned int)ret));
1103 DBGMSG(RECV, soap->buf, ret);
1104 soap->bufidx = 0;
1105 soap->chunksize -= ret;
1106 break;
1108 t = tmp;
1109 if (!soap->chunkbuflen)
1110 { soap->chunkbuflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN);
1111 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes (chunked) from socket %d\n", (unsigned int)ret, soap->socket));
1112 DBGMSG(RECV, soap->buf, ret);
1113 soap->bufidx = 0;
1114 if (!ret)
1115 return soap->ahead = EOF;
1117 else
1118 soap->bufidx = soap->buflen;
1119 soap->buflen = soap->chunkbuflen;
1120 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk size (idx=%u len=%u)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen));
1121 while (!soap_isxdigit((int)(c = soap_getchunkchar(soap))))
1122 { if ((int)c == EOF)
1123 return soap->ahead = EOF;
1126 *t++ = (char)c;
1127 while (soap_isxdigit((int)(c = soap_getchunkchar(soap))) && t - tmp < 7);
1128 while ((int)c != EOF && c != '\n')
1129 c = soap_getchunkchar(soap);
1130 if ((int)c == EOF)
1131 return soap->ahead = EOF;
1132 *t = '\0';
1133 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunk size = %s (hex)\n", tmp));
1134 soap->chunksize = soap_strtoul(tmp, &t, 16);
1135 if (!soap->chunksize)
1136 { soap->chunkbuflen = 0;
1137 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of chunked message\n"));
1138 while ((int)c != EOF && c != '\n')
1139 c = soap_getchunkchar(soap);
1140 ret = 0;
1141 soap->ahead = EOF;
1142 break;
1144 soap->buflen = soap->bufidx + soap->chunksize;
1145 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving buf len to idx=%u len=%u (%s)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen, tmp));
1146 if (soap->buflen > soap->chunkbuflen)
1147 { soap->buflen = soap->chunkbuflen;
1148 soap->chunksize -= soap->buflen - soap->bufidx;
1149 soap->chunkbuflen = 0;
1150 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Passed end of buffer for chunked HTTP (%u bytes left)\n", (unsigned int)(soap->buflen - soap->bufidx)));
1152 else if (soap->chunkbuflen)
1153 soap->chunksize = 0;
1154 ret = soap->buflen - soap->bufidx;
1155 if (ret)
1156 break;
1159 else
1160 #endif
1161 { soap->bufidx = 0;
1162 soap->buflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN);
1163 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket %d\n", (unsigned int)ret, soap->socket));
1164 DBGMSG(RECV, soap->buf, ret);
1166 #ifdef WITH_ZLIB
1167 if (soap->mode & SOAP_ENC_ZLIB)
1168 { memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN);
1169 soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx);
1170 soap->d_stream->avail_in = (unsigned int)ret;
1171 soap->d_stream->next_out = (Byte*)soap->buf;
1172 soap->d_stream->avail_out = SOAP_BUFLEN;
1173 r = inflate(soap->d_stream, Z_NO_FLUSH);
1174 if (r == Z_NEED_DICT && soap->z_dict)
1175 r = inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len);
1176 if (r == Z_OK || r == Z_STREAM_END)
1177 { soap->bufidx = 0;
1178 soap->z_buflen = soap->buflen;
1179 soap->buflen = SOAP_BUFLEN - soap->d_stream->avail_out;
1180 if (soap->zlib_in == SOAP_ZLIB_GZIP)
1181 soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen);
1182 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %u bytes\n", (unsigned int)soap->buflen));
1183 if (ret && !soap->buflen && r != Z_STREAM_END)
1184 goto zlib_again;
1185 ret = soap->buflen;
1186 if (r == Z_STREAM_END)
1187 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated total %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out));
1188 soap->z_ratio_in = (float)soap->d_stream->total_in / (float)soap->d_stream->total_out;
1189 soap->d_stream->next_out = Z_NULL;
1191 DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- decompressed ----\n"));
1192 DBGMSG(RECV, soap->buf, ret);
1193 #ifndef WITH_LEANER
1194 if (soap->fpreparerecv && (r = soap->fpreparerecv(soap, soap->buf, ret)))
1195 return soap->error = r;
1196 #endif
1198 else
1199 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to inflate: (%d) %s\n", r, soap->d_stream->msg?soap->d_stream->msg:SOAP_STR_EOS));
1200 soap->d_stream->next_out = Z_NULL;
1201 soap->error = SOAP_ZLIB_ERROR;
1202 return EOF;
1205 #endif
1206 #ifndef WITH_LEANER
1207 if (soap->fpreparerecv
1208 #ifdef WITH_ZLIB
1209 && soap->zlib_in == SOAP_ZLIB_NONE
1210 #endif
1211 && (r = soap->fpreparerecv(soap, soap->buf + soap->bufidx, ret)))
1212 return soap->error = r;
1213 #endif
1214 soap->count += ret;
1215 return !ret;
1217 #endif
1219 /******************************************************************************/
1220 #ifndef PALM_1
1221 SOAP_FMAC1
1223 SOAP_FMAC2
1224 soap_recv(struct soap *soap)
1226 #ifndef WITH_LEANER
1227 if (soap->mode & SOAP_ENC_DIME)
1228 { if (soap->dime.buflen)
1229 { char *s;
1230 int i;
1231 unsigned char tmp[12];
1232 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME hdr for chunked DIME is in buffer\n"));
1233 soap->count += soap->dime.buflen - soap->buflen;
1234 soap->buflen = soap->dime.buflen;
1235 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Skip padding (%ld bytes)\n", -(long)soap->dime.size&3));
1236 for (i = -(long)soap->dime.size&3; i > 0; i--)
1237 { soap->bufidx++;
1238 if (soap->bufidx >= soap->buflen)
1239 if (soap_recv_raw(soap))
1240 return EOF;
1242 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME hdr for next chunk\n"));
1243 s = (char*)tmp;
1244 for (i = 12; i > 0; i--)
1245 { *s++ = soap->buf[soap->bufidx++];
1246 if (soap->bufidx >= soap->buflen)
1247 if (soap_recv_raw(soap))
1248 return EOF;
1250 soap->dime.flags = tmp[0] & 0x7;
1251 soap->dime.size = ((size_t)tmp[8] << 24) | ((size_t)tmp[9] << 16) | ((size_t)tmp[10] << 8) | ((size_t)tmp[11]);
1252 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME chunk (%u bytes)\n", (unsigned int)soap->dime.size));
1253 if (soap->dime.flags & SOAP_DIME_CF)
1254 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "More chunking\n"));
1255 soap->dime.chunksize = soap->dime.size;
1256 if (soap->buflen - soap->bufidx >= soap->dime.size)
1257 { soap->dime.buflen = soap->buflen;
1258 soap->buflen = soap->bufidx + soap->dime.chunksize;
1260 else
1261 soap->dime.chunksize -= soap->buflen - soap->bufidx;
1263 else
1264 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Last chunk\n"));
1265 soap->dime.buflen = 0;
1266 soap->dime.chunksize = 0;
1268 soap->count = soap->buflen - soap->bufidx;
1269 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%u bytes remaining\n", (unsigned int)soap->count));
1270 return SOAP_OK;
1272 if (soap->dime.chunksize)
1273 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get next DIME hdr for chunked DIME (%u bytes chunk)\n", (unsigned int)soap->dime.chunksize));
1274 if (soap_recv_raw(soap))
1275 return EOF;
1276 if (soap->buflen - soap->bufidx >= soap->dime.chunksize)
1277 { soap->dime.buflen = soap->buflen;
1278 soap->count -= soap->buflen - soap->bufidx - soap->dime.chunksize;
1279 soap->buflen = soap->bufidx + soap->dime.chunksize;
1281 else
1282 soap->dime.chunksize -= soap->buflen - soap->bufidx;
1283 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%lu bytes remaining, count=%u\n", (unsigned long)(soap->buflen-soap->bufidx), (unsigned int)soap->count));
1284 return SOAP_OK;
1287 #endif
1288 return soap_recv_raw(soap);
1290 #endif
1292 /******************************************************************************/
1293 #ifndef PALM_1
1294 SOAP_FMAC1
1295 soap_wchar
1296 SOAP_FMAC2
1297 soap_getchar(struct soap *soap)
1298 { register soap_wchar c;
1299 c = soap->ahead;
1300 if (c)
1301 { if (c != EOF)
1302 soap->ahead = 0;
1303 return c;
1305 return soap_get1(soap);
1307 #endif
1309 /******************************************************************************/
1310 #ifndef PALM_1
1311 SOAP_FMAC1
1312 const struct soap_code_map*
1313 SOAP_FMAC2
1314 soap_code(const struct soap_code_map *code_map, const char *str)
1315 { if (code_map && str)
1316 { while (code_map->string)
1317 { if (!strcmp(str, code_map->string)) /* case sensitive */
1318 return code_map;
1319 code_map++;
1322 return NULL;
1324 #endif
1326 /******************************************************************************/
1327 #ifndef PALM_1
1328 SOAP_FMAC1
1329 long
1330 SOAP_FMAC2
1331 soap_code_int(const struct soap_code_map *code_map, const char *str, long other)
1332 { if (code_map)
1333 { while (code_map->string)
1334 { if (!soap_tag_cmp(str, code_map->string)) /* case insensitive */
1335 return code_map->code;
1336 code_map++;
1339 return other;
1341 #endif
1343 /******************************************************************************/
1344 #ifndef PALM_1
1345 SOAP_FMAC1
1346 const char*
1347 SOAP_FMAC2
1348 soap_code_str(const struct soap_code_map *code_map, long code)
1349 { if (!code_map)
1350 return NULL;
1351 while (code_map->code != code && code_map->string)
1352 code_map++;
1353 return code_map->string;
1355 #endif
1357 /******************************************************************************/
1358 #ifndef PALM_1
1359 SOAP_FMAC1
1360 long
1361 SOAP_FMAC2
1362 soap_code_bits(const struct soap_code_map *code_map, const char *str)
1363 { register long bits = 0;
1364 if (code_map)
1365 { while (str && *str)
1366 { const struct soap_code_map *p;
1367 for (p = code_map; p->string; p++)
1368 { register size_t n = strlen(p->string);
1369 if (!strncmp(p->string, str, n) && soap_blank(str[n]))
1370 { bits |= p->code;
1371 str += n;
1372 while (*str > 0 && *str <= 32)
1373 str++;
1374 break;
1377 if (!p->string)
1378 return 0;
1381 return bits;
1383 #endif
1385 /******************************************************************************/
1386 #ifndef PALM_1
1387 SOAP_FMAC1
1388 const char*
1389 SOAP_FMAC2
1390 soap_code_list(struct soap *soap, const struct soap_code_map *code_map, long code)
1391 { register char *t = soap->tmpbuf;
1392 if (code_map)
1393 { while (code_map->string)
1394 { if (code_map->code & code)
1395 { register const char *s = code_map->string;
1396 if (t != soap->tmpbuf)
1397 *t++ = ' ';
1398 while (*s && t < soap->tmpbuf + sizeof(soap->tmpbuf) - 1)
1399 *t++ = *s++;
1400 if (t == soap->tmpbuf + sizeof(soap->tmpbuf) - 1)
1401 break;
1403 code_map++;
1406 *t = '\0';
1407 return soap->tmpbuf;
1409 #endif
1411 /******************************************************************************/
1412 #ifndef PALM_1
1413 static soap_wchar
1414 soap_char(struct soap *soap)
1415 { char tmp[8];
1416 register int i;
1417 register soap_wchar c;
1418 register char *s = tmp;
1419 for (i = 0; i < 7; i++)
1420 { c = soap_get1(soap);
1421 if (c == ';' || (int)c == EOF)
1422 break;
1423 *s++ = (char)c;
1425 *s = '\0';
1426 if (*tmp == '#')
1427 { if (tmp[1] == 'x' || tmp[1] == 'X')
1428 return (soap_wchar)soap_strtol(tmp + 2, NULL, 16);
1429 return (soap_wchar)soap_strtol(tmp + 1, NULL, 10);
1431 if (!strcmp(tmp, "lt"))
1432 return '<';
1433 if (!strcmp(tmp, "gt"))
1434 return '>';
1435 if (!strcmp(tmp, "amp"))
1436 return '&';
1437 if (!strcmp(tmp, "quot"))
1438 return '"';
1439 if (!strcmp(tmp, "apos"))
1440 return '\'';
1441 #ifndef WITH_LEAN
1442 return (soap_wchar)soap_code_int(html_entity_codes, tmp, SOAP_UNKNOWN_CHAR);
1443 #else
1444 return SOAP_UNKNOWN_CHAR; /* use this to represent unknown code */
1445 #endif
1447 #endif
1449 /******************************************************************************/
1450 #ifdef WITH_LEAN
1451 #ifndef PALM_1
1452 soap_wchar
1453 soap_get0(struct soap *soap)
1454 { if (soap->bufidx >= soap->buflen && soap_recv(soap))
1455 return EOF;
1456 return (unsigned char)soap->buf[soap->bufidx];
1458 #endif
1459 #endif
1461 /******************************************************************************/
1462 #ifdef WITH_LEAN
1463 #ifndef PALM_1
1464 soap_wchar
1465 soap_get1(struct soap *soap)
1466 { if (soap->bufidx >= soap->buflen && soap_recv(soap))
1467 return EOF;
1468 return (unsigned char)soap->buf[soap->bufidx++];
1470 #endif
1471 #endif
1473 /******************************************************************************/
1474 #ifndef PALM_1
1475 SOAP_FMAC1
1476 soap_wchar
1477 SOAP_FMAC2
1478 soap_get(struct soap *soap)
1479 { register soap_wchar c;
1480 c = soap->ahead;
1481 if (c)
1482 { if ((int)c != EOF)
1483 soap->ahead = 0;
1485 else
1486 c = soap_get1(soap);
1487 while ((int)c != EOF)
1488 { if (soap->cdata)
1489 { if (c == ']')
1490 { c = soap_get1(soap);
1491 if (c == ']')
1492 { c = soap_get0(soap);
1493 if (c == '>')
1494 { soap->cdata = 0;
1495 soap_get1(soap);
1496 c = soap_get1(soap);
1498 else
1499 { soap_unget(soap, ']');
1500 return ']';
1503 else
1504 { soap_revget1(soap);
1505 return ']';
1508 else
1509 return c;
1511 switch (c)
1512 { case '<':
1513 do c = soap_get1(soap);
1514 while (soap_blank(c));
1515 if (c == '!' || c == '?' || c == '%')
1516 { register int k = 1;
1517 if (c == '!')
1518 { c = soap_get1(soap);
1519 if (c == '[')
1520 { do c = soap_get1(soap);
1521 while ((int)c != EOF && c != '[');
1522 if ((int)c == EOF)
1523 break;
1524 soap->cdata = 1;
1525 c = soap_get1(soap);
1526 continue;
1528 if (c == '-' && (c = soap_get1(soap)) == '-')
1529 { do
1530 { c = soap_get1(soap);
1531 if (c == '-' && (c = soap_get1(soap)) == '-')
1532 break;
1533 } while ((int)c != EOF);
1536 else if (c == '?')
1537 c = soap_get_pi(soap);
1538 while ((int)c != EOF)
1539 { if (c == '<')
1540 k++;
1541 else if (c == '>')
1542 { if (--k <= 0)
1543 break;
1545 c = soap_get1(soap);
1547 if ((int)c == EOF)
1548 break;
1549 c = soap_get1(soap);
1550 continue;
1552 if (c == '/')
1553 return SOAP_TT;
1554 soap_revget1(soap);
1555 return SOAP_LT;
1556 case '>':
1557 return SOAP_GT;
1558 case '"':
1559 return SOAP_QT;
1560 case '\'':
1561 return SOAP_AP;
1562 case '&':
1563 return soap_char(soap) | 0x80000000;
1565 break;
1567 return c;
1569 #endif
1571 /******************************************************************************/
1572 #ifndef PALM_1
1573 static soap_wchar
1574 soap_get_pi(struct soap *soap)
1575 { char buf[64];
1576 register char *s = buf;
1577 register int i = sizeof(buf);
1578 register soap_wchar c = soap_getchar(soap);
1579 /* This is a quick way to parse XML PI and we could use a callback instead to
1580 * enable applications to intercept processing instructions */
1581 while ((int)c != EOF && c != '?')
1582 { if (--i > 0)
1583 { if (soap_blank(c))
1584 c = ' ';
1585 *s++ = (char)c;
1587 c = soap_getchar(soap);
1589 *s = '\0';
1590 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "XML PI <?%s?>\n", buf));
1591 if (!strncmp(buf, "xml ", 4))
1592 { s = strstr(buf, " encoding=");
1593 if (s && s[10])
1594 { if (!soap_tag_cmp(s + 11, "iso-8859-1*")
1595 || !soap_tag_cmp(s + 11, "latin1*"))
1596 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to latin1 encoding\n"));
1597 soap->mode |= SOAP_ENC_LATIN;
1599 else if (!soap_tag_cmp(s + 11, "utf-8*"))
1600 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to utf-8 encoding\n"));
1601 soap->mode &= ~SOAP_ENC_LATIN;
1605 if ((int)c != EOF)
1606 c = soap_getchar(soap);
1607 return c;
1609 #endif
1611 /******************************************************************************/
1612 #ifndef WITH_LEANER
1613 #ifndef PALM_1
1614 SOAP_FMAC1
1616 SOAP_FMAC2
1617 soap_move(struct soap *soap, long n)
1618 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving %ld bytes forward\n", (long)n));
1619 for (; n > 0; n--)
1620 if ((int)soap_getchar(soap) == EOF)
1621 return SOAP_EOF;
1622 return SOAP_OK;
1624 #endif
1625 #endif
1627 /******************************************************************************/
1628 #ifndef WITH_LEANER
1629 #ifndef PALM_1
1630 SOAP_FMAC1
1631 size_t
1632 SOAP_FMAC2
1633 soap_tell(struct soap *soap)
1634 { return soap->count - soap->buflen + soap->bufidx - (soap->ahead != 0);
1636 #endif
1637 #endif
1639 /******************************************************************************/
1640 #ifndef PALM_1
1641 SOAP_FMAC1
1643 SOAP_FMAC2
1644 soap_pututf8(struct soap *soap, register unsigned long c)
1645 { char tmp[16];
1646 if (c < 0x80 && c > 0)
1647 { *tmp = (char)c;
1648 return soap_send_raw(soap, tmp, 1);
1650 #ifndef WITH_LEAN
1651 if (c >= 0x80)
1652 { register char *t = tmp;
1653 if (c < 0x0800)
1654 *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
1655 else
1656 { if (c < 0x010000)
1657 *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
1658 else
1659 { if (c < 0x200000)
1660 *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
1661 else
1662 { if (c < 0x04000000)
1663 *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
1664 else
1665 { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
1666 *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
1668 *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
1670 *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
1672 *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
1674 *t++ = (char)(0x80 | (c & 0x3F));
1675 *t = '\0';
1677 #else
1678 sprintf(tmp, "&#%lu;", c);
1679 #endif
1680 return soap_send(soap, tmp);
1682 #endif
1684 /******************************************************************************/
1685 #ifndef PALM_1
1686 SOAP_FMAC1
1687 soap_wchar
1688 SOAP_FMAC2
1689 soap_getutf8(struct soap *soap)
1690 { register soap_wchar c, c1, c2, c3, c4;
1691 c = soap->ahead;
1692 if (c > 0x7F)
1693 { soap->ahead = 0;
1694 return c;
1696 c = soap_get(soap);
1697 if (c < 0x80 || (soap->mode & SOAP_ENC_LATIN))
1698 return c;
1699 c1 = soap_get1(soap);
1700 if (c1 < 0x80)
1701 { soap_revget1(soap); /* doesn't look like this is UTF8 */
1702 return c;
1704 c1 &= 0x3F;
1705 if (c < 0xE0)
1706 return ((soap_wchar)(c & 0x1F) << 6) | c1;
1707 c2 = (soap_wchar)soap_get1(soap) & 0x3F;
1708 if (c < 0xF0)
1709 return ((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2;
1710 c3 = (soap_wchar)soap_get1(soap) & 0x3F;
1711 if (c < 0xF8)
1712 return ((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3;
1713 c4 = (soap_wchar)soap_get1(soap) & 0x3F;
1714 if (c < 0xFC)
1715 return ((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4;
1716 return ((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(soap_get1(soap) & 0x3F);
1718 #endif
1720 /******************************************************************************/
1721 #ifndef PALM_1
1722 SOAP_FMAC1
1724 SOAP_FMAC2
1725 soap_puthex(struct soap *soap, const unsigned char *s, int n)
1726 { char d[2];
1727 register int i;
1728 #ifdef WITH_DOM
1729 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
1730 { if (!(soap->dom->data = soap_s2hex(soap, s, NULL, n)))
1731 return soap->error;
1732 return SOAP_OK;
1734 #endif
1735 for (i = 0; i < n; i++)
1736 { register int m = *s++;
1737 d[0] = (char)((m >> 4) + (m > 159 ? '7' : '0'));
1738 m &= 0x0F;
1739 d[1] = (char)(m + (m > 9 ? '7' : '0'));
1740 if (soap_send_raw(soap, d, 2))
1741 return soap->error;
1743 return SOAP_OK;
1745 #endif
1747 /******************************************************************************/
1748 #ifndef PALM_1
1749 SOAP_FMAC1
1750 unsigned char*
1751 SOAP_FMAC2
1752 soap_gethex(struct soap *soap, int *n)
1754 #ifdef WITH_DOM
1755 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
1756 { soap->dom->data = soap_string_in(soap, 0, -1, -1);
1757 return (unsigned char*)soap_hex2s(soap, soap->dom->data, NULL, 0, n);
1759 #endif
1760 #ifdef WITH_FAST
1761 soap->labidx = 0;
1762 for (;;)
1763 { register char *s;
1764 register size_t i, k;
1765 if (soap_append_lab(soap, NULL, 0))
1766 return NULL;
1767 s = soap->labbuf + soap->labidx;
1768 k = soap->lablen - soap->labidx;
1769 soap->labidx = soap->lablen;
1770 for (i = 0; i < k; i++)
1771 { register char d1, d2;
1772 register soap_wchar c;
1773 c = soap_get(soap);
1774 if (soap_isxdigit(c))
1775 { d1 = (char)c;
1776 c = soap_get(soap);
1777 if (soap_isxdigit(c))
1778 d2 = (char)c;
1779 else
1780 { soap->error = SOAP_TYPE;
1781 return NULL;
1784 else
1785 { unsigned char *p;
1786 soap_unget(soap, c);
1787 if (n)
1788 *n = (int)(soap->lablen + i - k);
1789 p = (unsigned char*)soap_malloc(soap, soap->lablen + i - k);
1790 if (p)
1791 memcpy(p, soap->labbuf, soap->lablen + i - k);
1792 return p;
1794 *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0');
1797 #else
1798 if (soap_new_block(soap) == NULL)
1799 return NULL;
1800 for (;;)
1801 { register int i;
1802 register char *s = (char*)soap_push_block(soap, NULL, SOAP_BLKLEN);
1803 if (!s)
1804 { soap_end_block(soap, NULL);
1805 return NULL;
1807 for (i = 0; i < SOAP_BLKLEN; i++)
1808 { register char d1, d2;
1809 register soap_wchar c = soap_get(soap);
1810 if (soap_isxdigit(c))
1811 { d1 = (char)c;
1812 c = soap_get(soap);
1813 if (soap_isxdigit(c))
1814 d2 = (char)c;
1815 else
1816 { soap_end_block(soap, NULL);
1817 soap->error = SOAP_TYPE;
1818 return NULL;
1821 else
1822 { unsigned char *p;
1823 soap_unget(soap, c);
1824 if (n)
1825 *n = (int)soap_size_block(soap, NULL, i);
1826 p = (unsigned char*)soap_save_block(soap, NULL, 0);
1827 return p;
1829 *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0');
1832 #endif
1834 #endif
1836 /******************************************************************************/
1837 #ifndef PALM_1
1838 SOAP_FMAC1
1840 SOAP_FMAC2
1841 soap_putbase64(struct soap *soap, const unsigned char *s, int n)
1842 { register int i;
1843 register unsigned long m;
1844 char d[4];
1845 if (!s)
1846 return SOAP_OK;
1847 #ifdef WITH_DOM
1848 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
1849 { if (!(soap->dom->data = soap_s2base64(soap, s, NULL, n)))
1850 return soap->error;
1851 return SOAP_OK;
1853 #endif
1854 for (; n > 2; n -= 3, s += 3)
1855 { m = s[0];
1856 m = (m << 8) | s[1];
1857 m = (m << 8) | s[2];
1858 for (i = 4; i > 0; m >>= 6)
1859 d[--i] = soap_base64o[m & 0x3F];
1860 if (soap_send_raw(soap, d, 4))
1861 return soap->error;
1863 if (n > 0)
1864 { m = 0;
1865 for (i = 0; i < n; i++)
1866 m = (m << 8) | *s++;
1867 for (; i < 3; i++)
1868 m <<= 8;
1869 for (i++; i > 0; m >>= 6)
1870 d[--i] = soap_base64o[m & 0x3F];
1871 for (i = 3; i > n; i--)
1872 d[i] = '=';
1873 if (soap_send_raw(soap, d, 4))
1874 return soap->error;
1876 return SOAP_OK;
1878 #endif
1880 /******************************************************************************/
1881 #ifndef PALM_1
1882 SOAP_FMAC1
1883 unsigned char*
1884 SOAP_FMAC2
1885 soap_getbase64(struct soap *soap, int *n, int malloc_flag)
1887 #ifdef WITH_DOM
1888 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
1889 { soap->dom->data = soap_string_in(soap, 0, -1, -1);
1890 return (unsigned char*)soap_base642s(soap, soap->dom->data, NULL, 0, n);
1892 #endif
1893 #ifdef WITH_FAST
1894 soap->labidx = 0;
1895 for (;;)
1896 { register size_t i, k;
1897 register char *s;
1898 if (soap_append_lab(soap, NULL, 2))
1899 return NULL;
1900 s = soap->labbuf + soap->labidx;
1901 k = soap->lablen - soap->labidx;
1902 soap->labidx = 3 * (soap->lablen / 3);
1903 if (!s)
1904 return NULL;
1905 if (k > 2)
1906 { for (i = 0; i < k - 2; i += 3)
1907 { register unsigned long m = 0;
1908 register int j = 0;
1910 { register soap_wchar c = soap_get(soap);
1911 if (c == '=' || c < 0)
1912 { unsigned char *p;
1913 switch (j)
1914 { case 2:
1915 *s++ = (char)((m >> 4) & 0xFF);
1916 i++;
1917 break;
1918 case 3:
1919 *s++ = (char)((m >> 10) & 0xFF);
1920 *s++ = (char)((m >> 2) & 0xFF);
1921 i += 2;
1923 if (n)
1924 *n = (int)(soap->lablen + i - k);
1925 p = (unsigned char*)soap_malloc(soap, soap->lablen + i - k);
1926 if (p)
1927 memcpy(p, soap->labbuf, soap->lablen + i - k);
1928 if (c >= 0)
1929 { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT)
1932 soap_unget(soap, c);
1933 return p;
1935 c -= '+';
1936 if (c >= 0 && c <= 79)
1937 { register int b = soap_base64i[c];
1938 if (b >= 64)
1939 { soap->error = SOAP_TYPE;
1940 return NULL;
1942 m = (m << 6) + b;
1943 j++;
1945 else if (!soap_blank(c + '+'))
1946 { soap->error = SOAP_TYPE;
1947 return NULL;
1949 } while (j < 4);
1950 *s++ = (char)((m >> 16) & 0xFF);
1951 *s++ = (char)((m >> 8) & 0xFF);
1952 *s++ = (char)(m & 0xFF);
1956 #else
1957 if (soap_new_block(soap) == NULL)
1958 return NULL;
1959 for (;;)
1960 { register int i;
1961 register char *s = (char*)soap_push_block(soap, NULL, 3 * SOAP_BLKLEN); /* must be multiple of 3 */
1962 if (!s)
1963 { soap_end_block(soap, NULL);
1964 return NULL;
1966 for (i = 0; i < SOAP_BLKLEN; i++)
1967 { register unsigned long m = 0;
1968 register int j = 0;
1970 { register soap_wchar c = soap_get(soap);
1971 if (c == '=' || c < 0)
1972 { unsigned char *p;
1973 i *= 3;
1974 switch (j)
1975 { case 2:
1976 *s++ = (char)((m >> 4) & 0xFF);
1977 i++;
1978 break;
1979 case 3:
1980 *s++ = (char)((m >> 10) & 0xFF);
1981 *s++ = (char)((m >> 2) & 0xFF);
1982 i += 2;
1984 if (n)
1985 *n = (int)soap_size_block(soap, NULL, i);
1986 p = (unsigned char*)soap_save_block(soap, NULL, 0);
1987 if (c >= 0)
1988 { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT)
1991 soap_unget(soap, c);
1992 return p;
1994 c -= '+';
1995 if (c >= 0 && c <= 79)
1996 { int b = soap_base64i[c];
1997 if (b >= 64)
1998 { soap->error = SOAP_TYPE;
1999 return NULL;
2001 m = (m << 6) + b;
2002 j++;
2004 else if (!soap_blank(c))
2005 { soap->error = SOAP_TYPE;
2006 return NULL;
2008 } while (j < 4);
2009 *s++ = (char)((m >> 16) & 0xFF);
2010 *s++ = (char)((m >> 8) & 0xFF);
2011 *s++ = (char)(m & 0xFF);
2014 #endif
2016 #endif
2018 /******************************************************************************/
2019 #ifndef WITH_LEANER
2020 #ifndef PALM_1
2021 SOAP_FMAC1
2023 SOAP_FMAC2
2024 soap_xop_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options)
2025 { /* Check MTOM xop:Include element (within hex/base64Binary) */
2026 /* TODO: this code to be obsoleted with new import/xop.h conventions */
2027 int body = soap->body; /* should save type too? */
2028 if (!soap_peek_element(soap))
2029 { if (!soap_element_begin_in(soap, "xop:Include", 0, NULL) && *soap->href)
2030 { if (soap_dime_forward(soap, ptr, size, id, type, options))
2031 return soap->error;
2033 if (soap->body && soap_element_end_in(soap, NULL))
2034 return soap->error;
2036 soap->body = body;
2037 return SOAP_OK;
2039 #endif
2040 #endif
2042 /******************************************************************************/
2043 #ifndef WITH_LEANER
2044 #ifndef PALM_1
2045 SOAP_FMAC1
2047 SOAP_FMAC2
2048 soap_dime_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options)
2049 { struct soap_xlist *xp;
2050 *ptr = NULL;
2051 *size = 0;
2052 *id = NULL;
2053 *type = NULL;
2054 *options = NULL;
2055 if (!*soap->href)
2056 return SOAP_OK;
2057 *id = soap_strdup(soap, soap->href);
2058 xp = (struct soap_xlist*)SOAP_MALLOC(soap, sizeof(struct soap_xlist));
2059 if (!xp)
2060 return soap->error = SOAP_EOM;
2061 xp->next = soap->xlist;
2062 xp->ptr = ptr;
2063 xp->size = size;
2064 xp->id = *id;
2065 xp->type = type;
2066 xp->options = options;
2067 soap->xlist = xp;
2068 return SOAP_OK;
2070 #endif
2071 #endif
2073 /******************************************************************************/
2074 #ifndef PALM_1
2075 SOAP_FMAC1
2076 char *
2077 SOAP_FMAC2
2078 soap_strdup(struct soap *soap, const char *s)
2079 { char *t = NULL;
2080 if (s && (t = (char*)soap_malloc(soap, strlen(s) + 1)))
2081 strcpy(t, s);
2082 return t;
2084 #endif
2086 /******************************************************************************/
2087 #ifndef PALM_1
2088 SOAP_FMAC1
2089 wchar_t *
2090 SOAP_FMAC2
2091 soap_wstrdup(struct soap *soap, const wchar_t *s)
2092 { wchar_t *t = NULL;
2093 if (s)
2094 { size_t n = 0;
2095 while (s[n])
2096 n++;
2097 if ((t = (wchar_t*)soap_malloc(soap, sizeof(wchar_t)*(n+1))))
2098 memcpy(t, s, sizeof(wchar_t)*(n+1));
2100 return t;
2102 #endif
2104 /******************************************************************************/
2105 #ifndef PALM_1
2106 SOAP_FMAC1
2107 struct soap_blist*
2108 SOAP_FMAC2
2109 soap_new_block(struct soap *soap)
2110 { struct soap_blist *p;
2111 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New block sequence (prev=%p)\n", soap->blist));
2112 if (!(p = (struct soap_blist*)SOAP_MALLOC(soap, sizeof(struct soap_blist))))
2113 { soap->error = SOAP_EOM;
2114 return NULL;
2116 p->next = soap->blist;
2117 p->ptr = NULL;
2118 p->size = 0;
2119 soap->blist = p;
2120 return p;
2122 #endif
2124 /******************************************************************************/
2125 #ifndef PALM_1
2126 SOAP_FMAC1
2127 void*
2128 SOAP_FMAC2
2129 soap_push_block(struct soap *soap, struct soap_blist *b, size_t n)
2130 { char *p;
2131 if (!b)
2132 b = soap->blist;
2133 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push block of %u bytes (%u bytes total)\n", (unsigned int)n, (unsigned int)b->size + (unsigned int)n));
2134 if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(char*) + sizeof(size_t))))
2135 { soap->error = SOAP_EOM;
2136 return NULL;
2138 *(char**)p = b->ptr;
2139 *(size_t*)(p + sizeof(char*)) = n;
2140 b->ptr = p;
2141 b->size += n;
2142 return p + sizeof(char*) + sizeof(size_t);
2144 #endif
2146 /******************************************************************************/
2147 #ifndef PALM_1
2148 SOAP_FMAC1
2149 void
2150 SOAP_FMAC2
2151 soap_pop_block(struct soap *soap, struct soap_blist *b)
2152 { char *p;
2153 if (!b)
2154 b = soap->blist;
2155 if (!b->ptr)
2156 return;
2157 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop block\n"));
2158 p = b->ptr;
2159 b->size -= *(size_t*)(p + sizeof(char*));
2160 b->ptr = *(char**)p;
2161 SOAP_FREE(soap, p);
2163 #endif
2165 /******************************************************************************/
2166 #ifndef WITH_NOIDREF
2167 #ifndef PALM_1
2168 static void
2169 soap_update_ptrs(struct soap *soap, char *start, char *end, char *p1, char *p2)
2170 { int i;
2171 register struct soap_ilist *ip = NULL;
2172 register struct soap_flist *fp = NULL;
2173 #ifndef WITH_LEANER
2174 register struct soap_xlist *xp = NULL;
2175 #endif
2176 register void *p, **q;
2177 for (i = 0; i < SOAP_IDHASH; i++)
2178 { for (ip = soap->iht[i]; ip; ip = ip->next)
2179 { if (ip->ptr && (char*)ip->ptr >= start && (char*)ip->ptr < end)
2180 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", ip->id, ip->ptr, (char*)ip->ptr + (p1-p2)));
2181 ip->ptr = (char*)ip->ptr + (p1-p2);
2183 for (q = &ip->link; q; q = (void**)p)
2184 { p = *q;
2185 if (p && (char*)p >= start && (char*)p < end)
2186 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Link update id='%s' %p\n", ip->id, p));
2187 *q = (char*)p + (p1-p2);
2190 for (q = &ip->copy; q; q = (void**)p)
2191 { p = *q;
2192 if (p && (char*)p >= start && (char*)p < end)
2193 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy chain update id='%s' %p\n", ip->id, p));
2194 *q = (char*)p + (p1-p2);
2197 for (fp = ip->flist; fp; fp = fp->next)
2198 { if ((char*)fp->ptr >= start && (char*)fp->ptr < end)
2199 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy list update id='%s' %p\n", ip->id, fp));
2200 fp->ptr = (char*)fp->ptr + (p1-p2);
2205 #ifndef WITH_LEANER
2206 for (xp = soap->xlist; xp; xp = xp->next)
2207 { if (xp->ptr && (char*)xp->ptr >= start && (char*)xp->ptr < end)
2208 { 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)));
2209 xp->ptr = (unsigned char**)((char*)xp->ptr + (p1-p2));
2210 xp->size = (int*)((char*)xp->size + (p1-p2));
2211 xp->type = (char**)((char*)xp->type + (p1-p2));
2212 xp->options = (char**)((char*)xp->options + (p1-p2));
2215 #endif
2217 #endif
2218 #endif
2220 /******************************************************************************/
2221 #ifndef WITH_NOIDREF
2222 #ifndef PALM_1
2223 static int
2224 soap_has_copies(struct soap *soap, register const char *start, register const char *end)
2225 { register int i;
2226 register struct soap_ilist *ip = NULL;
2227 register struct soap_flist *fp = NULL;
2228 register const char *p;
2229 for (i = 0; i < SOAP_IDHASH; i++)
2230 { for (ip = soap->iht[i]; ip; ip = ip->next)
2231 { for (p = (const char*)ip->copy; p; p = *(const char**)p)
2232 if (p >= start && p < end)
2233 return SOAP_ERR;
2234 for (fp = ip->flist; fp; fp = fp->next)
2235 if ((const char*)fp->ptr >= start && (const char*)fp->ptr < end)
2236 return SOAP_ERR;
2239 return SOAP_OK;
2241 #endif
2242 #endif
2244 /******************************************************************************/
2245 #ifndef WITH_NOIDREF
2246 #ifndef PALM_1
2247 SOAP_FMAC1
2249 SOAP_FMAC2
2250 soap_resolve(struct soap *soap)
2251 { register int i;
2252 register struct soap_ilist *ip = NULL;
2253 register struct soap_flist *fp = NULL;
2254 short flag;
2255 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data\n"));
2256 for (i = 0; i < SOAP_IDHASH; i++)
2257 { for (ip = soap->iht[i]; ip; ip = ip->next)
2258 { if (ip->ptr)
2259 { register void *p, **q, *r;
2260 q = (void**)ip->link;
2261 ip->link = NULL;
2262 r = ip->ptr;
2263 DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing link chain to resolve id='%s'\n", ip->id));
2264 while (q)
2265 { p = *q;
2266 *q = r;
2267 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "... link %p -> %p\n", q, r));
2268 q = (void**)p;
2271 else if (*ip->id == '#')
2272 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Missing data for id='%s'\n", ip->id));
2273 /* Oracle customization */
2274 strncpy(soap->id, ip->id + 1, sizeof(soap->id) - 1);
2275 soap->id[sizeof(soap->id) - 1] = '\0';
2276 return soap->error = SOAP_MISSING_ID;
2281 { flag = 0;
2282 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution phase\n"));
2283 for (i = 0; i < SOAP_IDHASH; i++)
2284 { for (ip = soap->iht[i]; ip; ip = ip->next)
2285 { if (ip->ptr && !soap_has_copies(soap, (const char*)ip->ptr, (const char*)ip->ptr + ip->size))
2286 { if (ip->copy)
2287 { register void *p, **q = (void**)ip->copy;
2288 DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing copy chain to resolve id='%s'\n", ip->id));
2289 ip->copy = NULL;
2291 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... copy %p -> %p (%u bytes)\n", ip->ptr, q, (unsigned int)ip->size));
2292 p = *q;
2293 memcpy(q, ip->ptr, ip->size);
2294 q = (void**)p;
2295 } while (q);
2296 flag = 1;
2298 for (fp = ip->flist; fp; fp = ip->flist)
2299 { register unsigned int k = fp->level;
2300 register void *p = ip->ptr;
2301 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));
2302 while (ip->level < k)
2303 { register void **q = (void**)soap_malloc(soap, sizeof(void*));
2304 if (!q)
2305 return soap->error;
2306 *q = p;
2307 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level, new location=%p holds=%p...\n", q, *q));
2308 p = (void*)q;
2309 k--;
2311 if (fp->fcopy)
2312 fp->fcopy(soap, ip->type, fp->type, fp->ptr, fp->len, p, ip->size);
2313 else
2314 soap_fcopy(soap, ip->type, fp->type, fp->ptr, fp->len, p, ip->size);
2315 ip->flist = fp->next;
2316 SOAP_FREE(soap, fp);
2317 flag = 1;
2322 } while (flag);
2323 #ifdef SOAP_DEBUG
2324 for (i = 0; i < SOAP_IDHASH; i++)
2325 { for (ip = soap->iht[i]; ip; ip = ip->next)
2326 { if (ip->copy || ip->flist)
2327 { 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));
2331 #endif
2332 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution done\n"));
2333 return SOAP_OK;
2335 #endif
2336 #endif
2338 /******************************************************************************/
2339 #ifndef PALM_1
2340 SOAP_FMAC1
2341 size_t
2342 SOAP_FMAC2
2343 soap_size_block(struct soap *soap, struct soap_blist *b, size_t n)
2344 { if (!b)
2345 b = soap->blist;
2346 if (b->ptr)
2347 { b->size -= *(size_t*)(b->ptr + sizeof(char*)) - n;
2348 *(size_t*)(b->ptr + sizeof(char*)) = n;
2350 return b->size;
2352 #endif
2354 /******************************************************************************/
2355 #ifndef PALM_1
2356 SOAP_FMAC1
2357 char*
2358 SOAP_FMAC2
2359 soap_first_block(struct soap *soap, struct soap_blist *b)
2360 { char *p, *q, *r;
2361 if (!b)
2362 b = soap->blist;
2363 p = b->ptr;
2364 if (!p)
2365 return NULL;
2366 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "First block\n"));
2367 r = NULL;
2369 { q = *(char**)p;
2370 *(char**)p = r;
2371 r = p;
2372 p = q;
2373 } while (p);
2374 b->ptr = r;
2375 return r + sizeof(char*) + sizeof(size_t);
2377 #endif
2379 /******************************************************************************/
2380 #ifndef PALM_1
2381 SOAP_FMAC1
2382 char*
2383 SOAP_FMAC2
2384 soap_next_block(struct soap *soap, struct soap_blist *b)
2385 { char *p;
2386 if (!b)
2387 b = soap->blist;
2388 p = b->ptr;
2389 if (p)
2390 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Next block\n"));
2391 b->ptr = *(char**)p;
2392 SOAP_FREE(soap, p);
2393 if (b->ptr)
2394 return b->ptr + sizeof(char*) + sizeof(size_t);
2396 return NULL;
2398 #endif
2400 /******************************************************************************/
2401 #ifndef PALM_1
2402 SOAP_FMAC1
2403 size_t
2404 SOAP_FMAC2
2405 soap_block_size(struct soap *soap, struct soap_blist *b)
2406 { if (!b)
2407 b = soap->blist;
2408 return *(size_t*)(b->ptr + sizeof(char*));
2410 #endif
2412 /******************************************************************************/
2413 #ifndef PALM_1
2414 SOAP_FMAC1
2415 void
2416 SOAP_FMAC2
2417 soap_end_block(struct soap *soap, struct soap_blist *b)
2418 { char *p, *q;
2419 if (!b)
2420 b = soap->blist;
2421 if (b)
2422 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of block sequence, free all remaining blocks\n"));
2423 for (p = b->ptr; p; p = q)
2424 { q = *(char**)p;
2425 SOAP_FREE(soap, p);
2427 if (soap->blist == b)
2428 soap->blist = b->next;
2429 else
2430 { struct soap_blist *bp;
2431 for (bp = soap->blist; bp; bp = bp->next)
2432 { if (bp->next == b)
2433 { bp->next = b->next;
2434 break;
2438 SOAP_FREE(soap, b);
2440 DBGLOG(TEST, if (soap->blist) SOAP_MESSAGE(fdebug, "Restore previous block sequence\n"));
2442 #endif
2444 /******************************************************************************/
2445 #ifndef PALM_1
2446 SOAP_FMAC1
2447 char*
2448 SOAP_FMAC2
2449 soap_save_block(struct soap *soap, struct soap_blist *b, char *p, int flag)
2450 { register size_t n;
2451 register char *q, *s;
2452 if (!b)
2453 b = soap->blist;
2454 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));
2455 if (b->size)
2456 { if (!p)
2457 p = (char*)soap_malloc(soap, b->size);
2458 if (p)
2459 { for (s = p, q = soap_first_block(soap, b); q; q = soap_next_block(soap, b))
2460 { n = soap_block_size(soap, b);
2461 #ifndef WITH_NOIDREF
2462 if (flag)
2463 soap_update_ptrs(soap, q, q + n, s, q);
2464 #endif
2465 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy %u bytes from %p to %p\n", (unsigned int)n, q, s));
2466 memcpy(s, q, n);
2467 s += n;
2470 else
2471 soap->error = SOAP_EOM;
2473 soap_end_block(soap, b);
2474 return p;
2476 #endif
2478 /******************************************************************************/
2479 #ifndef PALM_2
2480 SOAP_FMAC1
2481 char *
2482 SOAP_FMAC2
2483 soap_putsize(struct soap *soap, const char *type, int size)
2484 { return soap_putsizes(soap, type, &size, 1);
2486 #endif
2488 /******************************************************************************/
2489 #ifndef PALM_2
2490 SOAP_FMAC1
2491 char *
2492 SOAP_FMAC2
2493 soap_putsizes(struct soap *soap, const char *type, const int *size, int dim)
2494 { return soap_putsizesoffsets(soap, type, size, NULL, dim);
2496 #endif
2498 /******************************************************************************/
2499 #ifndef PALM_2
2500 SOAP_FMAC1
2501 char *
2502 SOAP_FMAC2
2503 soap_putsizesoffsets(struct soap *soap, const char *type, const int *size, const int *offset, int dim)
2504 { int i;
2505 if (!type)
2506 return NULL;
2507 if (soap->version == 2)
2508 { sprintf(soap->type, "%s[%d", type, size[0]);
2509 for (i = 1; i < dim; i++)
2510 sprintf(soap->type + strlen(soap->type), " %d", size[i]);
2512 else
2513 { if (offset)
2514 { sprintf(soap->type, "%s[%d", type, size[0] + offset[0]);
2515 for (i = 1; i < dim; i++)
2516 sprintf(soap->type + strlen(soap->type), ",%d", size[i] + offset[i]);
2518 else
2519 { sprintf(soap->type, "%s[%d", type, size[0]);
2520 for (i = 1; i < dim; i++)
2521 sprintf(soap->type + strlen(soap->type), ",%d", size[i]);
2523 strcat(soap->type, "]");
2525 return soap->type;
2527 #endif
2529 /******************************************************************************/
2530 #ifndef PALM_2
2531 SOAP_FMAC1
2532 char *
2533 SOAP_FMAC2
2534 soap_putoffset(struct soap *soap, int offset)
2535 { return soap_putoffsets(soap, &offset, 1);
2537 #endif
2539 /******************************************************************************/
2540 #ifndef PALM_2
2541 SOAP_FMAC1
2542 char *
2543 SOAP_FMAC2
2544 soap_putoffsets(struct soap *soap, const int *offset, int dim)
2545 { register int i;
2546 sprintf(soap->arrayOffset, "[%d", offset[0]);
2547 for (i = 1; i < dim; i++)
2548 sprintf(soap->arrayOffset + strlen(soap->arrayOffset), ",%d", offset[i]);
2549 strcat(soap->arrayOffset, "]");
2550 return soap->arrayOffset;
2552 #endif
2554 /******************************************************************************/
2555 #ifndef PALM_2
2556 SOAP_FMAC1
2558 SOAP_FMAC2
2559 soap_size(const int *size, int dim)
2560 { register int i, n = size[0];
2561 for (i = 1; i < dim; i++)
2562 n *= size[i];
2563 return n;
2565 #endif
2567 /******************************************************************************/
2568 #ifndef PALM_2
2569 SOAP_FMAC1
2571 SOAP_FMAC2
2572 soap_getoffsets(const char *attr, const int *size, int *offset, int dim)
2573 { register int i, j = 0;
2574 if (offset)
2575 for (i = 0; i < dim && attr && *attr; i++)
2576 { attr++;
2577 j *= size[i];
2578 j += offset[i] = (int)soap_strtol(attr, NULL, 10);
2579 attr = strchr(attr, ',');
2581 else
2582 for (i = 0; i < dim && attr && *attr; i++)
2583 { attr++;
2584 j *= size[i];
2585 j += (int)soap_strtol(attr, NULL, 10);
2586 attr = strchr(attr, ',');
2588 return j;
2590 #endif
2592 /******************************************************************************/
2593 #ifndef PALM_2
2594 SOAP_FMAC1
2596 SOAP_FMAC2
2597 soap_getsize(const char *attr1, const char *attr2, int *j)
2598 { register int n, k;
2599 char *s;
2600 *j = 0;
2601 if (!*attr1)
2602 return -1;
2603 if (*attr1 == '[')
2604 attr1++;
2605 n = 1;
2606 for (;;)
2607 { k = (int)soap_strtol(attr1, &s, 10);
2608 n *= k;
2609 if (k < 0 || n > SOAP_MAXARRAYSIZE || s == attr1)
2610 return -1;
2611 attr1 = strchr(s, ',');
2612 if (!attr1)
2613 attr1 = strchr(s, ' ');
2614 if (attr2 && *attr2)
2615 { attr2++;
2616 *j *= k;
2617 k = (int)soap_strtol(attr2, &s, 10);
2618 *j += k;
2619 if (k < 0)
2620 return -1;
2621 attr2 = s;
2623 if (!attr1)
2624 break;
2625 attr1++;
2627 return n - *j;
2629 #endif
2631 /******************************************************************************/
2632 #ifndef PALM_2
2633 SOAP_FMAC1
2635 SOAP_FMAC2
2636 soap_getsizes(const char *attr, int *size, int dim)
2637 { register int i, k, n;
2638 if (!*attr)
2639 return -1;
2640 i = (int)strlen(attr);
2641 n = 1;
2643 { for (i = i-1; i >= 0; i--)
2644 if (attr[i] == '[' || attr[i] == ',' || attr[i] == ' ')
2645 break;
2646 k = (int)soap_strtol(attr + i + 1, NULL, 10);
2647 n *= size[--dim] = k;
2648 if (k < 0 || n > SOAP_MAXARRAYSIZE)
2649 return -1;
2650 } while (i >= 0 && attr[i] != '[');
2651 return n;
2653 #endif
2655 /******************************************************************************/
2656 #ifndef PALM_2
2657 SOAP_FMAC1
2659 SOAP_FMAC2
2660 soap_getposition(const char *attr, int *pos)
2661 { register int i, n;
2662 if (!*attr)
2663 return -1;
2664 n = 0;
2665 i = 1;
2667 { pos[n++] = (int)soap_strtol(attr + i, NULL, 10);
2668 while (attr[i] && attr[i] != ',' && attr[i] != ']')
2669 i++;
2670 if (attr[i] == ',')
2671 i++;
2672 } while (n < SOAP_MAXDIMS && attr[i] && attr[i] != ']');
2673 return n;
2675 #endif
2677 /******************************************************************************/
2678 #ifndef PALM_2
2679 SOAP_FMAC1
2680 struct soap_nlist *
2681 SOAP_FMAC2
2682 soap_push_namespace(struct soap *soap, const char *id, const char *ns)
2683 { register struct soap_nlist *np;
2684 register struct Namespace *p;
2685 register short i = -1;
2686 register size_t n, k;
2687 n = strlen(id);
2688 k = strlen(ns) + 1;
2689 p = soap->local_namespaces;
2690 if (p)
2691 { for (i = 0; p->id; p++, i++)
2692 { if (p->ns && !strcmp(ns, p->ns))
2693 { if (p->out)
2694 { SOAP_FREE(soap, p->out);
2695 p->out = NULL;
2697 break;
2699 if (p->out)
2700 { if (!strcmp(ns, p->out))
2701 break;
2703 else if (p->in)
2704 { if (!soap_tag_cmp(ns, p->in))
2705 { if ((p->out = (char*)SOAP_MALLOC(soap, k)))
2706 strcpy(p->out, ns);
2707 break;
2711 if (!p || !p->id)
2712 i = -1;
2714 if (i >= 0)
2715 k = 0;
2716 np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k);
2717 if (!np)
2718 { soap->error = SOAP_EOM;
2719 return NULL;
2721 np->next = soap->nlist;
2722 soap->nlist = np;
2723 np->level = soap->level;
2724 np->index = i;
2725 strcpy(np->id, id);
2726 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push namespace binding (level=%u) '%s' '%s'\n", soap->level, id, ns));
2727 if (i < 0)
2728 { np->ns = strcpy(np->id + n + 1, ns);
2729 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push NOT OK: no match found for '%s' in namespace mapping table (added to stack anyway)\n", ns));
2731 else
2732 { np->ns = NULL;
2733 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push OK ('%s' matches '%s' in namespace table)\n", id, p->id));
2735 return np;
2737 #endif
2739 /******************************************************************************/
2740 #ifndef PALM_2
2741 SOAP_FMAC1
2742 void
2743 SOAP_FMAC2
2744 soap_pop_namespace(struct soap *soap)
2745 { register struct soap_nlist *np, *nq;
2746 for (np = soap->nlist; np && np->level >= soap->level; np = nq)
2747 { nq = np->next;
2748 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop namespace binding (level=%u) '%s'\n", soap->level, np->id));
2749 SOAP_FREE(soap, np);
2751 soap->nlist = np;
2753 #endif
2755 /******************************************************************************/
2756 #ifndef PALM_2
2757 SOAP_FMAC1
2759 SOAP_FMAC2
2760 soap_match_namespace(struct soap *soap, const char *id1, const char *id2, size_t n1, size_t n2)
2761 { register struct soap_nlist *np = soap->nlist;
2762 while (np && (strncmp(np->id, id1, n1) || np->id[n1]))
2763 np = np->next;
2764 if (np)
2765 { if (!(soap->mode & SOAP_XML_IGNORENS))
2766 if (np->index < 0
2767 || (soap->local_namespaces[np->index].id
2768 && (strncmp(soap->local_namespaces[np->index].id, id2, n2)
2769 || soap->local_namespaces[np->index].id[n2])))
2770 return SOAP_NAMESPACE;
2771 return SOAP_OK;
2773 if (n1 == 0)
2774 return SOAP_NAMESPACE;
2775 if ((n1 == 3 && n1 == n2 && !strncmp(id1, "xml", 3) && !strncmp(id1, id2, 3))
2776 || (soap->mode & SOAP_XML_IGNORENS))
2777 return SOAP_OK;
2778 return soap->error = SOAP_SYNTAX_ERROR;
2780 #endif
2782 /******************************************************************************/
2783 #ifndef PALM_2
2784 SOAP_FMAC1
2785 const char*
2786 SOAP_FMAC2
2787 soap_current_namespace(struct soap *soap, const char *tag)
2788 { register struct soap_nlist *np;
2789 register const char *s;
2790 if (!tag || !strncmp(tag, "xml", 3))
2791 return NULL;
2792 np = soap->nlist;
2793 if (!(s = strchr(tag, ':')))
2794 { while (np && *np->id) /* find default namespace, if present */
2795 np = np->next;
2797 else
2798 { while (np && (strncmp(np->id, tag, s - tag) || np->id[s - tag]))
2799 np = np->next;
2800 if (!np)
2801 soap->error = SOAP_NAMESPACE;
2803 if (np)
2804 { if (np->index >= 0)
2805 return soap->namespaces[np->index].ns;
2806 if (np->ns)
2807 return soap_strdup(soap, np->ns);
2809 return NULL;
2811 #endif
2813 /******************************************************************************/
2814 #ifndef PALM_2
2815 SOAP_FMAC1
2817 SOAP_FMAC2
2818 soap_tag_cmp(const char *s, const char *t)
2819 { for (;;)
2820 { register int c1 = *s;
2821 register int c2 = *t;
2822 if (!c1 || c1 == '"')
2823 break;
2824 if (c2 != '-')
2825 { if (c1 != c2)
2826 { if (c1 >= 'A' && c1 <= 'Z')
2827 c1 += 'a' - 'A';
2828 if (c2 >= 'A' && c2 <= 'Z')
2829 c2 += 'a' - 'A';
2831 if (c1 != c2)
2832 { if (c2 != '*')
2833 return 1;
2834 c2 = *++t;
2835 if (!c2)
2836 return 0;
2837 if (c2 >= 'A' && c2 <= 'Z')
2838 c2 += 'a' - 'A';
2839 for (;;)
2840 { c1 = *s;
2841 if (!c1 || c1 == '"')
2842 break;
2843 if (c1 >= 'A' && c1 <= 'Z')
2844 c1 += 'a' - 'A';
2845 if (c1 == c2 && !soap_tag_cmp(s + 1, t + 1))
2846 return 0;
2847 s++;
2849 break;
2852 s++;
2853 t++;
2855 if (*t == '*' && !t[1])
2856 return 0;
2857 return *t;
2859 #endif
2861 /******************************************************************************/
2862 #ifndef PALM_2
2863 SOAP_FMAC1
2865 SOAP_FMAC2
2866 soap_match_tag(struct soap *soap, const char *tag1, const char *tag2)
2867 { register const char *s, *t;
2868 register int err;
2869 if (!tag1 || !tag2 || !*tag2)
2870 return SOAP_OK;
2871 s = strchr(tag1, ':');
2872 t = strchr(tag2, ':');
2873 if (t)
2874 { if (s)
2875 { if (t[1] && SOAP_STRCMP(s + 1, t + 1))
2876 return SOAP_TAG_MISMATCH;
2877 if (t != tag2 && (err = soap_match_namespace(soap, tag1, tag2, s - tag1, t - tag2)))
2878 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2));
2879 if (err == SOAP_NAMESPACE)
2880 return SOAP_TAG_MISMATCH;
2881 return err;
2884 else if (SOAP_STRCMP(tag1, t + 1))
2885 { return SOAP_TAG_MISMATCH;
2887 else if (t != tag2 && (err = soap_match_namespace(soap, tag1, tag2, 0, t - tag2)))
2888 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2));
2889 if (err == SOAP_NAMESPACE)
2890 return SOAP_TAG_MISMATCH;
2891 return err;
2893 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags and (default) namespaces match: '%s' '%s'\n", tag1, tag2));
2894 return SOAP_OK;
2896 if (s)
2897 { if (SOAP_STRCMP(s + 1, tag2))
2898 return SOAP_TAG_MISMATCH;
2900 else if (SOAP_STRCMP(tag1, tag2))
2901 return SOAP_TAG_MISMATCH;
2902 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags match: '%s' '%s'\n", tag1, tag2));
2903 return SOAP_OK;
2905 #endif
2907 /******************************************************************************/
2908 #ifndef PALM_2
2909 SOAP_FMAC1
2911 SOAP_FMAC2
2912 soap_match_array(struct soap *soap, const char *type)
2913 { if (*soap->arrayType)
2914 if (soap_match_tag(soap, soap->arrayType, type)
2915 && soap_match_tag(soap, soap->arrayType, "xsd:anyType")
2916 && soap_match_tag(soap, soap->arrayType, "xsd:ur-type")
2918 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array type mismatch: '%s' '%s'\n", soap->arrayType, type));
2919 return SOAP_TAG_MISMATCH;
2921 return SOAP_OK;
2923 #endif
2925 /******************************************************************************\
2927 * SSL/TLS
2929 \******************************************************************************/
2931 /******************************************************************************/
2932 #ifdef WITH_OPENSSL
2933 #ifndef PALM_2
2934 SOAP_FMAC1
2936 SOAP_FMAC2
2937 soap_rand()
2938 { unsigned char buf[4];
2939 if (!soap_ssl_init_done)
2940 soap_ssl_init();
2941 RAND_pseudo_bytes(buf, 4);
2942 return *(int*)buf;
2944 #endif
2945 #endif
2947 /******************************************************************************/
2948 #ifdef WITH_OPENSSL
2949 #ifndef PALM_2
2950 SOAP_FMAC1
2952 SOAP_FMAC2
2953 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)
2954 { int err;
2955 soap->keyfile = keyfile;
2956 soap->password = password;
2957 soap->cafile = cafile;
2958 soap->capath = capath;
2959 soap->crlfile = NULL;
2960 soap->dhfile = dhfile;
2961 soap->randfile = randfile;
2962 soap->ssl_flags = flags | (dhfile == NULL ? SOAP_SSL_RSA : 0);
2963 if (!(err = soap->fsslauth(soap)))
2964 { if (sid)
2965 SSL_CTX_set_session_id_context(soap->ctx, (unsigned char*)sid, (unsigned int)strlen(sid));
2966 else
2967 SSL_CTX_set_session_cache_mode(soap->ctx, SSL_SESS_CACHE_OFF);
2969 return err;
2971 #endif
2972 #endif
2974 /******************************************************************************/
2975 #ifdef WITH_OPENSSL
2976 #ifndef PALM_2
2977 SOAP_FMAC1
2979 SOAP_FMAC2
2980 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)
2981 { soap->keyfile = keyfile;
2982 soap->password = password;
2983 soap->cafile = cafile;
2984 soap->capath = capath;
2985 soap->dhfile = NULL;
2986 soap->ssl_flags = flags;
2987 soap->randfile = randfile;
2988 soap->fsslverify = (flags & SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE) == 0 ? ssl_verify_callback : ssl_verify_callback_allow_expired_certificate;
2989 return soap->fsslauth(soap);
2991 #endif
2992 #endif
2994 /******************************************************************************/
2995 #ifdef WITH_OPENSSL
2996 #ifndef PALM_2
2997 SOAP_FMAC1
2998 void
2999 SOAP_FMAC2
3000 soap_ssl_init()
3001 { /* Note: for MT systems, the main program MUST call soap_ssl_init() before any threads are started */
3002 if (!soap_ssl_init_done)
3003 { soap_ssl_init_done = 1;
3004 SSL_library_init();
3005 #ifndef WITH_LEAN
3006 SSL_load_error_strings();
3007 #endif
3008 if (!RAND_load_file("/dev/urandom", 1024))
3009 { char buf[1024];
3010 RAND_seed(buf, sizeof(buf));
3011 while (!RAND_status())
3012 { int r = rand();
3013 RAND_seed(&r, sizeof(int));
3018 #endif
3019 #endif
3021 /******************************************************************************/
3022 #ifdef WITH_OPENSSL
3023 #ifndef PALM_1
3024 SOAP_FMAC1
3025 const char *
3026 SOAP_FMAC2
3027 soap_ssl_error(struct soap *soap, int ret)
3028 { int err = SSL_get_error(soap->ssl, ret);
3029 const char *msg = soap_code_str(h_ssl_error_codes, err);
3030 size_t msgbufsize = sizeof(soap->msgbuf);
3031 if (msg)
3032 { /* Oracle customization */
3033 strncpy(soap->msgbuf, msg, msgbufsize - 1);
3034 soap->msgbuf[msgbufsize - 1] = '\0';
3036 else
3037 return ERR_error_string(err, soap->msgbuf);
3038 if (ERR_peek_error())
3039 { unsigned long r;
3040 /* Oracle customization */
3041 if (strlen(soap->msgbuf) < (msgbufsize-1))
3042 strcat(soap->msgbuf, "\n");
3043 else
3044 soap->msgbuf[msgbufsize - 2] = '\n';
3045 while ((r = ERR_get_error()))
3046 ERR_error_string_n(r, soap->msgbuf + strlen(soap->msgbuf), sizeof(soap->msgbuf) - strlen(soap->msgbuf));
3048 else
3049 { switch (ret)
3050 { case 0:
3052 /* Oracle customization -- display SSL error code and string at the end */
3053 int myerrno = errno;
3054 unsigned long ec = ERR_get_error();
3055 sprintf(soap->msgbuf,
3056 "EOF was observed that violates the protocol. The client probably provided invalid authentication information. SSL error code is %s. ",
3057 msg);
3058 if (ec != 0)
3060 /* display the next error string in the error queue */
3061 ERR_error_string_n(ec, soap->msgbuf + strlen(soap->msgbuf),
3062 sizeof(soap->msgbuf) - strlen(soap->msgbuf));
3063 if (sizeof(soap->msgbuf) - strlen(soap->msgbuf) > 2)
3065 strcat(soap->msgbuf, ". ");
3068 if (myerrno != 0)
3070 /* display system error too */
3071 char *mystrerror = strerror(myerrno);
3072 if (strlen(mystrerror)
3073 < (sizeof(soap->msgbuf) - strlen(soap->msgbuf)))
3075 strncat(soap->msgbuf + strlen(soap->msgbuf), mystrerror,
3076 strlen(mystrerror));
3078 else
3080 strncat(soap->msgbuf + strlen(soap->msgbuf), mystrerror,
3081 (sizeof(soap->msgbuf) - strlen(soap->msgbuf)));
3083 soap->msgbuf[sizeof(soap->msgbuf) - 1] = '\0';
3086 break;
3087 case -1:
3088 sprintf(soap->msgbuf, "Error observed by underlying BIO: %s", strerror(errno));
3089 break;
3092 return soap->msgbuf;
3094 #endif
3095 #endif
3097 /******************************************************************************/
3098 #ifdef WITH_OPENSSL
3099 #ifndef PALM_1
3100 static int
3101 ssl_password(char *buf, int num, int rwflag, void *userdata)
3102 { if (num < (int)strlen((char*)userdata) + 1)
3103 return 0;
3104 return (int)strlen(strcpy(buf, (char*)userdata));
3106 #endif
3107 #endif
3109 /******************************************************************************/
3110 #ifdef WITH_OPENSSL
3111 #ifndef PALM_1
3113 static int
3116 ssl_auth_init(struct soap *soap)
3117 { long flags;
3118 int mode;
3119 if (!soap_ssl_init_done)
3120 soap_ssl_init();
3121 ERR_clear_error();
3122 if (!soap->ctx)
3123 { if (!(soap->ctx = SSL_CTX_new(SSLv23_method())))
3124 return soap_set_receiver_error(soap, "SSL error", "Can't setup context", SOAP_SSL_ERROR);
3125 /* The following alters the behavior of SSL read/write: */
3126 #if 0
3127 SSL_CTX_set_mode(soap->ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY);
3128 #endif
3131 // Oracle customization
3133 // added SSL_CTX_set_cipher_list call to restrict the cipher suite to RSA-2048/AES
3134 // TLS_RSA_WITH_AES_256_CBC_SHA is defined in RFC 3268
3135 // also see http://www.openssl.org/docs/apps/ciphers.html
3137 if (!SSL_CTX_set_cipher_list(soap->ctx, "AES256-SHA"))
3138 return soap_set_receiver_error(soap, "SSL error", "Cannot set cipher suite", SOAP_SSL_ERROR);
3139 if (soap->randfile)
3140 { if (!RAND_load_file(soap->randfile, -1))
3141 return soap_set_receiver_error(soap, "SSL error", "Can't load randomness", SOAP_SSL_ERROR);
3143 if (soap->cafile || soap->capath)
3144 { if (!SSL_CTX_load_verify_locations(soap->ctx, soap->cafile, soap->capath))
3145 return soap_set_receiver_error(soap, "SSL error", "Can't read CA file and directory", SOAP_SSL_ERROR);
3146 if (soap->cafile && (soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
3147 SSL_CTX_set_client_CA_list(soap->ctx, SSL_load_client_CA_file(soap->cafile));
3149 if (!(soap->ssl_flags & SOAP_SSL_NO_DEFAULT_CA_PATH))
3150 { if (!SSL_CTX_set_default_verify_paths(soap->ctx))
3151 return soap_set_receiver_error(soap, "SSL error", "Can't read default CA file and/or directory", SOAP_SSL_ERROR);
3153 /* This code assumes a typical scenario, see alternative code below */
3154 if (soap->keyfile)
3155 { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile))
3156 return soap_set_receiver_error(soap, "SSL error", "Can't read certificate key file", SOAP_SSL_ERROR);
3157 if (soap->password)
3158 { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password);
3159 SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password);
3161 if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM))
3162 return soap_set_receiver_error(soap, "SSL error", "Can't read key file", SOAP_SSL_ERROR);
3164 /* Suggested alternative approach to check the key file for certs (cafile=NULL):*/
3165 #if 0
3166 if (soap->password)
3167 { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password);
3168 SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password);
3170 if (!soap->cafile || !SSL_CTX_use_certificate_chain_file(soap->ctx, soap->cafile))
3171 { if (soap->keyfile)
3172 { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile))
3173 return soap_set_receiver_error(soap, "SSL error", "Can't read certificate or key file", SOAP_SSL_ERROR);
3174 if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM))
3175 return soap_set_receiver_error(soap, "SSL error", "Can't read key file", SOAP_SSL_ERROR);
3178 #endif
3179 if ((soap->ssl_flags & SOAP_SSL_RSA))
3182 Oracle customization for OpenSSL 0.9.8 removal of deprecated function usage: RSA_generate_key
3184 #ifdef OPENSSL_NO_DEPRECATED
3185 RSA *rsa = RSA_new();
3186 if (!rsa)
3188 return soap_set_receiver_error(soap, "SSL error", "Can't allocate RSA struct", SOAP_SSL_ERROR);
3191 BIGNUM *e = BN_new();
3192 if (!e)
3194 RSA_free(rsa);
3195 return soap_set_receiver_error(soap, "SSL error", "Can't allocate BIGNUM", SOAP_SSL_ERROR);
3197 if (!BN_set_word(e, RSA_F4 ))
3199 RSA_free(rsa);
3200 BN_free(e);
3201 return soap_set_receiver_error(soap, "SSL error", "Can't set BIGNUM value", SOAP_SSL_ERROR);
3204 #if OPENSSL_VERSION_NUMBER > 0x00908000L
3205 if (!RSA_generate_key_ex(rsa, 1024, e, NULL))
3206 #else
3207 if (( rsa = RSA_generate_key(1024, RSA_F4, NULL, NULL)) == NULL )
3208 #endif
3210 RSA_free(rsa);
3211 BN_free(e);
3212 return soap_set_receiver_error(soap, "SSL error", "Can't set RSA key", SOAP_SSL_ERROR);
3215 #else
3216 RSA *rsa = RSA_generate_key(1024, RSA_F4, NULL, NULL);
3217 #endif
3218 if (!SSL_CTX_set_tmp_rsa(soap->ctx, rsa))
3219 { if (rsa)
3220 RSA_free(rsa);
3222 Oracle customization for OpenSSL 0.9.8 removal of deprecated function usage: RSA_generate_key
3224 #ifdef OPENSSL_NO_DEPRECATED
3225 BN_free(e);
3226 #endif
3227 return soap_set_receiver_error(soap, "SSL error", "Can't set RSA key", SOAP_SSL_ERROR);
3229 RSA_free(rsa);
3231 Oracle customization for OpenSSL 0.9.8 removal of deprecated function usage: RSA_generate_key
3233 #ifdef OPENSSL_NO_DEPRECATED
3234 BN_free(e);
3235 #endif
3237 else if (soap->dhfile)
3239 DH *dh = 0;
3240 #ifdef OPENSSL_NO_DEPRECATED
3241 DH dhrec;
3242 #endif
3243 char *s;
3244 int n = (int)soap_strtoul(soap->dhfile, &s, 10);
3245 /* if dhfile is numeric, treat it as a key length to generate DH params which can take a while */
3246 if (n >= 512 && s && *s == '\0') {
3247 #if !defined(OPENSSL_NO_DEPRECATED) || OPENSSL_VERSION_NUMBER < 0x00908000L
3248 dh = DH_generate_parameters(n, 2/*or 5*/, NULL, NULL);
3249 #else
3250 if (DH_generate_parameters_ex(&dhrec, n, 2/*or 5*/, NULL) == 0)
3251 dh = &dhrec;
3252 else
3253 return soap_set_receiver_error(soap, "SSL error", "Can't compute DH params", SOAP_SSL_ERROR);
3254 #endif
3256 else
3257 { BIO *bio;
3258 bio = BIO_new_file(soap->dhfile, "r");
3259 if (!bio)
3260 return soap_set_receiver_error(soap, "SSL error", "Can't read DH file", SOAP_SSL_ERROR);
3261 dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
3262 BIO_free(bio);
3264 if (!dh || DH_check(dh, &n) != 1 || SSL_CTX_set_tmp_dh(soap->ctx, dh) < 0)
3266 #ifndef OPENSSL_NO_DEPRECATED
3267 if (dh)
3268 DH_free(dh);
3269 #endif
3270 return soap_set_receiver_error(soap, "SSL error", "Can't set DH parameters", SOAP_SSL_ERROR);
3272 #ifndef OPENSSL_NO_DEPRECATED
3273 DH_free(dh);
3274 #endif
3278 // Oracle customization
3280 // Added SSL_OP_NO_SSLv3 to force use of TLS
3281 // Added SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG to prevent forced downgrade
3282 // of security level
3284 flags = ((SSL_OP_ALL & ~SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG) | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
3286 flags = (SSL_OP_ALL | SSL_OP_NO_SSLv2);
3287 if ((soap->ssl_flags & SOAP_SSLv3))
3288 flags |= SSL_OP_NO_TLSv1;
3289 if ((soap->ssl_flags & SOAP_TLSv1))
3290 flags |= SSL_OP_NO_SSLv3;
3291 #ifdef SSL_OP_NO_TICKET
3292 /* TLS extension is enabled by default in OPENSSL v0.9.8k
3293 Disable it by adding SSL_OP_NO_TICKET */
3294 flags |= SSL_OP_NO_TICKET;
3295 #endif
3296 SSL_CTX_set_options(soap->ctx, flags);
3297 if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
3298 mode = (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
3299 else if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION))
3300 mode = SSL_VERIFY_PEER;
3301 else
3302 mode = SSL_VERIFY_NONE;
3303 SSL_CTX_set_verify(soap->ctx, mode, soap->fsslverify);
3304 #if (OPENSSL_VERSION_NUMBER < 0x00905100L)
3305 SSL_CTX_set_verify_depth(soap->ctx, 1);
3306 #else
3307 SSL_CTX_set_verify_depth(soap->ctx, 9);
3308 #endif
3309 return SOAP_OK;
3311 #endif
3312 #endif
3314 /******************************************************************************/
3315 #ifdef WITH_OPENSSL
3316 #ifndef PALM_1
3317 static int
3318 ssl_verify_callback(int ok, X509_STORE_CTX *store)
3320 #ifdef SOAP_DEBUG
3321 if (!ok)
3322 { char data[256];
3323 X509 *cert = X509_STORE_CTX_get_current_cert(store);
3324 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)));
3325 X509_NAME_oneline(X509_get_issuer_name(cert), data, sizeof(data));
3326 fprintf(stderr, "certificate issuer %s\n", data);
3327 X509_NAME_oneline(X509_get_subject_name(cert), data, sizeof(data));
3328 fprintf(stderr, "certificate subject %s\n", data);
3330 #endif
3331 /* Note: return 1 to continue, but unsafe progress will be terminated by SSL */
3332 return ok;
3334 #endif
3335 #endif
3337 /******************************************************************************/
3338 #ifdef WITH_OPENSSL
3339 #ifndef PALM_1
3340 static int
3341 ssl_verify_callback_allow_expired_certificate(int ok, X509_STORE_CTX *store)
3342 { ok = ssl_verify_callback(ok, store);
3343 if (ok == 0 && X509_STORE_CTX_get_error(store) == X509_V_ERR_CERT_HAS_EXPIRED)
3345 #ifdef SOAP_DEBUG
3346 fprintf(stderr, "ignoring certificate expiration\n");
3347 #endif
3348 X509_STORE_CTX_set_error(store, X509_V_OK);
3349 ok = 1;
3351 /* Note: return 1 to continue, but unsafe progress will be terminated by SSL */
3352 return ok;
3354 #endif
3355 #endif
3357 /******************************************************************************/
3358 #ifdef WITH_OPENSSL
3359 #ifndef WITH_NOIO
3360 #ifndef PALM_1
3361 SOAP_FMAC1
3363 SOAP_FMAC2
3364 soap_ssl_accept(struct soap *soap)
3365 { BIO *bio;
3366 int retries, r, s;
3367 if (!soap_valid_socket(soap->socket))
3368 return soap_set_receiver_error(soap, "SSL error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR);
3369 if (!soap->ctx && (soap->error = soap->fsslauth(soap)))
3370 return SOAP_SSL_ERROR;
3371 if (!soap->ssl)
3372 { soap->ssl = SSL_new(soap->ctx);
3373 if (!soap->ssl)
3374 return soap_set_receiver_error(soap, "SSL error", "SSL_new() failed in soap_ssl_accept()", SOAP_SSL_ERROR);
3376 else
3377 SSL_clear(soap->ssl);
3378 soap->imode |= SOAP_ENC_SSL;
3379 soap->omode |= SOAP_ENC_SSL;
3380 /* Set SSL sockets to non-blocking */
3381 SOAP_SOCKNONBLOCK(soap->socket)
3382 bio = BIO_new_socket((int)soap->socket, BIO_NOCLOSE);
3383 SSL_set_bio(soap->ssl, bio, bio);
3384 retries = 100; /* SSL_accept timeout: 10 sec retries, 100 times 0.1 sec */
3385 #if defined(WITH_OPENSSL) && defined(KMS_SERVER)
3386 /* Oracle customization for Ultra 2 KMS Server */
3387 if (soap->ssl_accept_timeout > 0 )
3389 retries = 10 * soap->ssl_accept_timeout;
3391 #endif
3393 while ((r = SSL_accept(soap->ssl)) <= 0)
3394 { int err = SSL_get_error(soap->ssl, r);
3395 if (err == SSL_ERROR_WANT_ACCEPT || err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
3396 { if (err == SSL_ERROR_WANT_READ)
3397 s = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000);
3398 else
3399 s = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000);
3400 if (s < 0 && soap->errnum != SOAP_EINTR)
3401 break;
3403 else
3404 { soap->errnum = soap_socket_errno(soap->socket);
3405 break;
3407 if (retries-- <= 0)
3408 break;
3410 if (r <= 0)
3411 { soap_set_receiver_error(soap, soap_ssl_error(soap, r), "SSL_accept() failed in soap_ssl_accept()", SOAP_SSL_ERROR);
3412 soap_closesock(soap);
3413 return SOAP_SSL_ERROR;
3415 if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
3416 { X509 *peer;
3417 int err;
3418 if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK)
3419 { soap_closesock(soap);
3420 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);
3422 peer = SSL_get_peer_certificate(soap->ssl);
3423 if (!peer)
3424 { soap_closesock(soap);
3425 return soap_set_sender_error(soap, "SSL error", "No SSL certificate was presented by the peer in soap_ssl_accept()", SOAP_SSL_ERROR);
3427 X509_free(peer);
3429 return SOAP_OK;
3431 #endif
3432 #endif
3433 #endif
3435 /******************************************************************************\
3437 * TCP/UDP [SSL/TLS] IPv4 and IPv6
3439 \******************************************************************************/
3441 /******************************************************************************/
3442 #ifndef WITH_NOIO
3443 #ifndef PALM_1
3444 static int
3445 tcp_init(struct soap *soap)
3446 { soap->errmode = 1;
3447 #ifdef WIN32
3448 if (tcp_done)
3449 return 0;
3450 else
3451 { WSADATA w;
3452 if (WSAStartup(MAKEWORD(1, 1), &w))
3453 return -1;
3454 tcp_done = 1;
3456 #endif
3457 return 0;
3459 #endif
3460 #endif
3462 /******************************************************************************/
3463 #ifndef WITH_NOIO
3464 #ifndef PALM_1
3465 static const char*
3466 tcp_error(struct soap *soap)
3467 { register const char *msg = NULL;
3468 switch (soap->errmode)
3469 { case 0:
3470 msg = soap_strerror(soap);
3471 break;
3472 case 1:
3473 msg = "WSAStartup failed";
3474 break;
3475 case 2:
3477 #ifndef WITH_LEAN
3478 msg = soap_code_str(h_error_codes, soap->errnum);
3479 if (!msg)
3480 #endif
3481 { sprintf(soap->msgbuf, "TCP/UDP IP error %d", soap->errnum);
3482 msg = soap->msgbuf;
3486 return msg;
3488 #endif
3489 #endif
3491 /******************************************************************************/
3492 #ifndef WITH_IPV6
3493 #ifndef WITH_NOIO
3494 #ifndef PALM_1
3495 static int
3496 tcp_gethost(struct soap *soap, const char *addr, struct in_addr *inaddr)
3497 { soap_int32 iadd = -1;
3498 struct hostent hostent, *host = &hostent;
3499 #ifdef VXWORKS
3500 int hostint;
3501 /* inet_addr(), and hostGetByName() expect "char *"; addr is a "const char *". */
3502 iadd = inet_addr((char*)addr);
3503 #else
3504 #if defined(_AIX43) || ((defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R))
3505 struct hostent_data ht_data;
3506 #endif
3507 #ifdef AS400
3508 iadd = inet_addr((void*)addr);
3509 #else
3510 iadd = inet_addr(addr);
3511 #endif
3512 #endif
3513 if (iadd != -1)
3514 { memcpy(inaddr, &iadd, sizeof(iadd));
3515 return SOAP_OK;
3517 #if defined(__GLIBC__) || (defined(HAVE_GETHOSTBYNAME_R) && (defined(FREEBSD) || defined(__FreeBSD__)))
3518 if (gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &host, &soap->errnum) < 0)
3519 host = NULL;
3520 #elif defined(_AIX43) || ((defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R))
3521 memset((void*)&ht_data, 0, sizeof(ht_data));
3522 if (gethostbyname_r(addr, &hostent, &ht_data) < 0)
3523 { host = NULL;
3524 soap->errnum = h_errno;
3526 #elif defined(HAVE_GETHOSTBYNAME_R)
3527 host = gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &soap->errnum);
3528 #elif defined(VXWORKS)
3529 /* If the DNS resolver library resolvLib has been configured in the vxWorks
3530 * image, a query for the host IP address is sent to the DNS server, if the
3531 * name was not found in the local host table. */
3532 hostint = hostGetByName((char*)addr);
3533 if (hostint == ERROR)
3534 { host = NULL;
3535 soap->errnum = soap_errno;
3537 #else
3538 #ifdef AS400
3539 if (!(host = gethostbyname((void*)addr)))
3540 soap->errnum = h_errno;
3541 #else
3542 if (!(host = gethostbyname(addr)))
3543 soap->errnum = h_errno;
3544 #endif
3545 #endif
3546 if (!host)
3547 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Host name not found\n"));
3548 return SOAP_ERR;
3550 #ifdef VXWORKS
3551 inaddr->s_addr = hostint;
3552 #else
3553 memcpy(inaddr, host->h_addr, host->h_length);
3554 #endif
3555 return SOAP_OK;
3557 #endif
3558 #endif
3559 #endif
3561 /******************************************************************************/
3562 #ifndef WITH_NOIO
3563 #ifndef PALM_1
3564 static SOAP_SOCKET
3565 tcp_connect(struct soap *soap, const char *endpoint, const char *host, int port)
3567 #ifdef WITH_IPV6
3568 struct addrinfo hints, *res, *ressave;
3569 #endif
3570 SOAP_SOCKET fd;
3571 int err = 0;
3572 #ifndef WITH_LEAN
3573 int len = SOAP_BUFLEN;
3574 int set = 1;
3575 #endif
3576 #if !defined(WITH_LEAN) || defined(WITH_OPENSSL)
3577 int retries;
3578 #endif
3579 if (soap_valid_socket(soap->socket))
3580 soap->fclosesocket(soap, soap->socket);
3581 soap->socket = SOAP_INVALID_SOCKET;
3582 if (tcp_init(soap))
3583 { soap->errnum = 0;
3584 soap_set_sender_error(soap, tcp_error(soap), "TCP init failed in tcp_connect()", SOAP_TCP_ERROR);
3585 return SOAP_INVALID_SOCKET;
3587 soap->errmode = 0;
3588 #ifdef WITH_IPV6
3589 memset((void*)&hints, 0, sizeof(hints));
3590 hints.ai_family = PF_UNSPEC;
3591 #ifndef WITH_LEAN
3592 if ((soap->omode & SOAP_IO_UDP))
3593 hints.ai_socktype = SOCK_DGRAM;
3594 else
3595 #endif
3596 hints.ai_socktype = SOCK_STREAM;
3597 soap->errmode = 2;
3598 res = NULL;
3599 if (soap->proxy_host)
3600 err = getaddrinfo(soap->proxy_host, soap_int2s(soap, soap->proxy_port), &hints, &res);
3601 else
3602 err = getaddrinfo(host, soap_int2s(soap, port), &hints, &res);
3603 /* Oracle customization: check err before using res */
3604 if (err || (res==NULL))
3605 { soap_set_sender_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in tcp_connect()", SOAP_TCP_ERROR);
3606 if (res)
3608 freeaddrinfo(res);
3610 return SOAP_INVALID_SOCKET;
3612 ressave = res;
3613 again:
3614 fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
3615 soap->errmode = 0;
3616 #else
3617 #ifndef WITH_LEAN
3618 again:
3619 #endif
3620 #ifndef WITH_LEAN
3621 if ((soap->omode & SOAP_IO_UDP))
3622 fd = socket(AF_INET, SOCK_DGRAM, 0);
3623 else
3624 #endif
3625 fd = socket(AF_INET, SOCK_STREAM, 0);
3626 #endif
3627 if (!soap_valid_socket(fd))
3629 #ifdef WITH_IPV6
3630 if (res->ai_next)
3631 { res = res->ai_next;
3632 goto again;
3634 #endif
3635 soap->errnum = soap_socket_errno(fd);
3636 soap_set_sender_error(soap, tcp_error(soap), "socket failed in tcp_connect()", SOAP_TCP_ERROR);
3637 #ifdef WITH_IPV6
3638 freeaddrinfo(ressave);
3639 #endif
3640 return SOAP_INVALID_SOCKET;
3642 #ifdef SOCKET_CLOSE_ON_EXEC
3643 #ifdef WIN32
3644 #ifndef UNDER_CE
3645 SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0);
3646 #endif
3647 #else
3648 fcntl(fd, F_SETFD, 1);
3649 #endif
3650 #endif
3651 #ifndef WITH_LEAN
3652 if (soap->connect_flags == SO_LINGER)
3653 { struct linger linger;
3654 memset((void*)&linger, 0, sizeof(linger));
3655 linger.l_onoff = 1;
3656 linger.l_linger = soap->linger_time;
3657 if (setsockopt(fd, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger)))
3658 { soap->errnum = soap_socket_errno(fd);
3659 soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in tcp_connect()", SOAP_TCP_ERROR);
3660 soap->fclosesocket(soap, fd);
3661 #ifdef WITH_IPV6
3662 freeaddrinfo(ressave);
3663 #endif
3664 return SOAP_INVALID_SOCKET;
3667 else if (soap->connect_flags && setsockopt(fd, SOL_SOCKET, soap->connect_flags, (char*)&set, sizeof(int)))
3668 { soap->errnum = soap_socket_errno(fd);
3669 soap_set_sender_error(soap, tcp_error(soap), "setsockopt failed in tcp_connect()", SOAP_TCP_ERROR);
3670 soap->fclosesocket(soap, fd);
3671 #ifdef WITH_IPV6
3672 freeaddrinfo(ressave);
3673 #endif
3674 return SOAP_INVALID_SOCKET;
3676 if ((soap->keep_alive || soap->tcp_keep_alive) && setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
3677 { soap->errnum = soap_socket_errno(fd);
3678 soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in tcp_connect()", SOAP_TCP_ERROR);
3679 soap->fclosesocket(soap, fd);
3680 #ifdef WITH_IPV6
3681 freeaddrinfo(ressave);
3682 #endif
3683 return SOAP_INVALID_SOCKET;
3685 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
3686 { soap->errnum = soap_socket_errno(fd);
3687 soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in tcp_connect()", SOAP_TCP_ERROR);
3688 soap->fclosesocket(soap, fd);
3689 #ifdef WITH_IPV6
3690 freeaddrinfo(ressave);
3691 #endif
3692 return SOAP_INVALID_SOCKET;
3694 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
3695 { soap->errnum = soap_socket_errno(fd);
3696 soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in tcp_connect()", SOAP_TCP_ERROR);
3697 soap->fclosesocket(soap, fd);
3698 #ifdef WITH_IPV6
3699 freeaddrinfo(ressave);
3700 #endif
3701 return SOAP_INVALID_SOCKET;
3703 #ifdef TCP_KEEPIDLE
3704 if (soap->tcp_keep_idle && setsockopt((SOAP_SOCKET)fd, IPPROTO_TCP, TCP_KEEPIDLE, (char*)&(soap->tcp_keep_idle), sizeof(int)))
3705 { soap->errnum = soap_socket_errno(fd);
3706 soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPIDLE failed in tcp_connect()", SOAP_TCP_ERROR);
3707 soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3708 #ifdef WITH_IPV6
3709 freeaddrinfo(ressave);
3710 #endif
3711 return SOAP_INVALID_SOCKET;
3713 #endif
3714 #ifdef TCP_KEEPINTVL
3715 if (soap->tcp_keep_intvl && setsockopt((SOAP_SOCKET)fd, IPPROTO_TCP, TCP_KEEPINTVL, (char*)&(soap->tcp_keep_intvl), sizeof(int)))
3716 { soap->errnum = soap_socket_errno(fd);
3717 soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPINTVL failed in tcp_connect()", SOAP_TCP_ERROR);
3718 soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3719 #ifdef WITH_IPV6
3720 freeaddrinfo(ressave);
3721 #endif
3722 return SOAP_INVALID_SOCKET;
3724 #endif
3725 #ifdef TCP_KEEPCNT
3726 if (soap->tcp_keep_cnt && setsockopt((SOAP_SOCKET)fd, IPPROTO_TCP, TCP_KEEPCNT, (char*)&(soap->tcp_keep_cnt), sizeof(int)))
3727 { soap->errnum = soap_socket_errno(fd);
3728 soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPCNT failed in tcp_connect()", SOAP_TCP_ERROR);
3729 soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3730 #ifdef WITH_IPV6
3731 freeaddrinfo(ressave);
3732 #endif
3733 return SOAP_INVALID_SOCKET;
3735 #endif
3736 #ifdef TCP_NODELAY
3737 if (!(soap->omode & SOAP_IO_UDP) && setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
3738 { soap->errnum = soap_socket_errno(fd);
3739 soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in tcp_connect()", SOAP_TCP_ERROR);
3740 soap->fclosesocket(soap, fd);
3741 #ifdef WITH_IPV6
3742 freeaddrinfo(ressave);
3743 #endif
3744 return SOAP_INVALID_SOCKET;
3746 #endif
3747 #ifdef WITH_IPV6
3748 if ((soap->omode & SOAP_IO_UDP) && soap->ipv6_multicast_if)
3749 { struct sockaddr_in6 *in6addr = (struct sockaddr_in6*)res->ai_addr;
3750 in6addr->sin6_scope_id = soap->ipv6_multicast_if;
3752 #endif
3753 #ifdef IP_MULTICAST_TTL
3754 if ((soap->omode & SOAP_IO_UDP) && soap->ipv4_multicast_if && !soap->ipv6_multicast_if)
3755 { if (soap->ipv4_multicast_ttl > 0)
3756 { char ttl = (char)(soap->ipv4_multicast_ttl);
3757 if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ttl, sizeof(ttl)))
3758 { soap->errnum = soap_socket_errno(fd);
3759 soap_set_sender_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_TTL failed in tcp_connect()", SOAP_TCP_ERROR);
3760 soap->fclosesocket(soap, fd);
3761 return SOAP_INVALID_SOCKET;
3764 #ifndef WINDOWS
3765 if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, (char*)soap->ipv4_multicast_if, sizeof(struct in_addr)))
3766 { soap->errnum = soap_socket_errno(fd);
3767 soap_set_sender_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR);
3768 soap->fclosesocket(soap, fd);
3769 return SOAP_INVALID_SOCKET;
3771 #else
3772 #ifndef IP_MULTICAST_IF
3773 #define IP_MULTICAST_IF 2
3774 #endif
3775 if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, (char*)soap->ipv4_multicast_if, sizeof(struct in_addr)))
3776 { soap->errnum = soap_socket_errno(fd);
3777 soap_set_sender_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR);
3778 soap->fclosesocket(soap, fd);
3779 return SOAP_INVALID_SOCKET;
3781 #endif
3783 #endif
3784 #endif
3785 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Opening socket %d to host='%s' port=%d\n", fd, host, port));
3786 #ifndef WITH_IPV6
3787 soap->peerlen = sizeof(soap->peer);
3788 memset((void*)&soap->peer, 0, sizeof(soap->peer));
3789 soap->peer.sin_family = AF_INET;
3790 soap->errmode = 2;
3791 if (soap->proxy_host)
3792 { if (soap->fresolve(soap, soap->proxy_host, &soap->peer.sin_addr))
3793 { soap_set_sender_error(soap, tcp_error(soap), "get proxy host by name failed in tcp_connect()", SOAP_TCP_ERROR);
3794 soap->fclosesocket(soap, fd);
3795 return SOAP_INVALID_SOCKET;
3797 soap->peer.sin_port = htons((short)soap->proxy_port);
3799 else
3800 { if (soap->fresolve(soap, host, &soap->peer.sin_addr))
3801 { soap_set_sender_error(soap, tcp_error(soap), "get host by name failed in tcp_connect()", SOAP_TCP_ERROR);
3802 soap->fclosesocket(soap, fd);
3803 return SOAP_INVALID_SOCKET;
3805 soap->peer.sin_port = htons((short)port);
3807 soap->errmode = 0;
3808 #ifndef WITH_LEAN
3809 if ((soap->omode & SOAP_IO_UDP))
3810 return fd;
3811 #endif
3812 #else
3813 if ((soap->omode & SOAP_IO_UDP))
3814 { memcpy(&soap->peer, res->ai_addr, res->ai_addrlen);
3815 soap->peerlen = res->ai_addrlen;
3816 freeaddrinfo(ressave);
3817 return fd;
3819 #endif
3820 #ifndef WITH_LEAN
3821 if (soap->connect_timeout)
3822 SOAP_SOCKNONBLOCK(fd)
3823 else
3824 SOAP_SOCKBLOCK(fd)
3825 retries = 10;
3826 #endif
3827 for (;;)
3829 #ifdef WITH_IPV6
3830 if (connect(fd, res->ai_addr, (int)res->ai_addrlen))
3831 #else
3832 if (connect(fd, (struct sockaddr*)&soap->peer, sizeof(soap->peer)))
3833 #endif
3834 { err = soap_socket_errno(fd);
3835 #ifndef WITH_LEAN
3836 if (err == SOAP_EADDRINUSE)
3837 { soap->fclosesocket(soap, fd);
3838 if (retries-- > 0)
3839 goto again;
3841 else if (soap->connect_timeout && (err == SOAP_EINPROGRESS || err == SOAP_EAGAIN || err == SOAP_EWOULDBLOCK))
3843 SOAP_SOCKLEN_T k;
3844 for (;;)
3845 { register int r;
3846 r = tcp_select(soap, fd, SOAP_TCP_SELECT_SND, soap->connect_timeout);
3847 if (r > 0)
3848 break;
3849 if (!r)
3850 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n"));
3851 soap_set_sender_error(soap, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR);
3852 soap->fclosesocket(soap, fd);
3853 soap->socket = SOAP_INVALID_SOCKET; /* Oracle customization */
3854 #ifdef WITH_IPV6
3855 freeaddrinfo(ressave);
3856 #endif
3857 return SOAP_INVALID_SOCKET;
3859 r = soap->errnum;
3860 if (r != SOAP_EINTR)
3861 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
3862 soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
3863 soap->fclosesocket(soap, fd);
3864 soap->socket = SOAP_INVALID_SOCKET; /* Oracle customization */
3865 #ifdef WITH_IPV6
3866 freeaddrinfo(ressave);
3867 #endif
3868 return SOAP_INVALID_SOCKET;
3871 k = (SOAP_SOCKLEN_T)sizeof(soap->errnum);
3872 if (!getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*)&soap->errnum, &k) && !soap->errnum) /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
3873 break;
3874 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
3875 if (!soap->errnum)
3876 soap->errnum = soap_socket_errno(fd);
3877 soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
3878 soap->fclosesocket(soap, fd);
3879 #ifdef WITH_IPV6
3880 freeaddrinfo(ressave);
3881 #endif
3882 return SOAP_INVALID_SOCKET;
3884 #endif
3885 #ifdef WITH_IPV6
3886 if (res->ai_next)
3887 { res = res->ai_next;
3888 soap->fclosesocket(soap, fd);
3889 goto again;
3891 #endif
3892 if (err && err != SOAP_EINTR)
3893 { soap->errnum = err;
3894 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
3895 soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
3896 soap->fclosesocket(soap, fd);
3897 #ifdef WITH_IPV6
3898 freeaddrinfo(ressave);
3899 #endif
3900 return SOAP_INVALID_SOCKET;
3903 else
3904 break;
3906 #ifdef WITH_IPV6
3907 soap->peerlen = 0; /* IPv6: already connected so use send() */
3908 freeaddrinfo(ressave);
3909 #endif
3910 if (soap->recv_timeout || soap->send_timeout)
3911 SOAP_SOCKNONBLOCK(fd)
3912 else
3913 SOAP_SOCKBLOCK(fd)
3914 soap->socket = fd;
3915 soap->imode &= ~SOAP_ENC_SSL;
3916 soap->omode &= ~SOAP_ENC_SSL;
3917 if (!soap_tag_cmp(endpoint, "https:*"))
3919 #ifdef WITH_OPENSSL
3920 BIO *bio;
3921 int r;
3922 if (soap->proxy_host)
3923 { soap_mode m = soap->mode; /* preserve settings */
3924 soap_mode om = soap->omode; /* make sure we only parse HTTP */
3925 size_t n = soap->count; /* save the content length */
3926 const char *userid, *passwd;
3927 soap->omode &= ~SOAP_ENC; /* mask IO and ENC */
3928 soap->omode |= SOAP_IO_BUFFER;
3929 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connecting to %s proxy server\n", soap->proxy_http_version));
3930 sprintf(soap->tmpbuf, "CONNECT %s:%d HTTP/%s", host, port, soap->proxy_http_version);
3931 if (soap_begin_send(soap)
3932 || (soap->error = soap->fposthdr(soap, soap->tmpbuf, NULL)))
3933 { soap->fclosesocket(soap, fd);
3934 soap->socket = SOAP_INVALID_SOCKET; /* Oracle customization */
3935 return SOAP_INVALID_SOCKET;
3937 #ifndef WITH_LEAN
3938 if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761)
3939 { sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd);
3940 strcpy(soap->tmpbuf, "Basic ");
3941 soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262));
3942 if ((soap->error = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf)))
3943 { soap->fclosesocket(soap, fd);
3944 soap->socket = SOAP_INVALID_SOCKET; /* Oracle customization */
3946 // Oracle customization
3947 // TODO: returning soap->error may also be a bug
3949 return soap->error;
3952 #endif
3953 if ((soap->error = soap->fposthdr(soap, NULL, NULL))
3954 || soap_flush(soap))
3955 { soap->fclosesocket(soap, fd);
3956 soap->socket = SOAP_INVALID_SOCKET; /* Oracle customization */
3957 return SOAP_INVALID_SOCKET;
3959 soap->omode = om;
3960 om = soap->imode;
3961 soap->imode &= ~SOAP_ENC; /* mask IO and ENC */
3962 userid = soap->userid; /* preserve */
3963 passwd = soap->passwd; /* preserve */
3964 if ((soap->error = soap->fparse(soap)))
3965 { soap->fclosesocket(soap, fd);
3966 soap->socket = SOAP_INVALID_SOCKET; /* Oracle customization */
3967 return SOAP_INVALID_SOCKET;
3969 soap->userid = userid; /* restore */
3970 soap->passwd = passwd; /* restore */
3971 soap->imode = om; /* restore */
3972 soap->count = n; /* restore */
3973 if (soap_begin_send(soap))
3974 { soap->fclosesocket(soap, fd);
3975 return SOAP_INVALID_SOCKET;
3977 if (endpoint)
3978 strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint)-1); /* restore */
3979 soap->mode = m;
3981 if (!soap->ctx && (soap->error = soap->fsslauth(soap)))
3982 { soap_set_sender_error(soap, "SSL error", "SSL authentication failed in tcp_connect(): check password, key file, and ca file.", SOAP_SSL_ERROR);
3983 soap->fclosesocket(soap, fd);
3984 soap->socket = SOAP_INVALID_SOCKET; /* Oracle customization */
3985 return SOAP_INVALID_SOCKET;
3987 if (!soap->ssl)
3988 { soap->ssl = SSL_new(soap->ctx);
3989 if (!soap->ssl)
3990 { soap->fclosesocket(soap, fd);
3991 soap->socket = SOAP_INVALID_SOCKET; /* Oracle customization */
3992 soap->error = SOAP_SSL_ERROR;
3993 return SOAP_INVALID_SOCKET;
3996 else
3997 SSL_clear(soap->ssl);
3998 if (soap->session)
3999 { if (!strcmp(soap->session_host, host) && soap->session_port == port)
4000 SSL_set_session(soap->ssl, soap->session);
4001 SSL_SESSION_free(soap->session);
4002 soap->session = NULL;
4004 soap->imode |= SOAP_ENC_SSL;
4005 soap->omode |= SOAP_ENC_SSL;
4006 bio = BIO_new_socket((int)fd, BIO_NOCLOSE);
4007 SSL_set_bio(soap->ssl, bio, bio);
4008 retries = 0;
4009 #ifndef WITH_LEAN
4010 /* Connect timeout: set SSL sockets to non-blocking */
4011 if (soap->connect_timeout)
4012 { SOAP_SOCKNONBLOCK(fd)
4013 retries = 10*soap->connect_timeout;
4015 else
4016 SOAP_SOCKBLOCK(fd)
4017 #endif
4019 // Oracle customization
4021 // Clear error queue of any errors remaining from a previous operation
4022 ERR_clear_error();
4024 if (retries <= 0)
4025 retries = 100; /* SSL connect timeout: 10 sec retries, 100 x 0.1 sec */
4026 /* Try connecting until success or timeout (when nonblocking) */
4028 { if ((r = SSL_connect(soap->ssl)) <= 0)
4029 { int err = SSL_get_error(soap->ssl, r);
4030 if (err == SSL_ERROR_WANT_CONNECT || err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
4031 { register int s;
4032 if (err == SSL_ERROR_WANT_READ)
4033 s = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000);
4034 else
4035 s = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000);
4036 if (s < 0 && soap->errnum != SOAP_EINTR)
4037 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL_connect/select error in tcp_connect\n"));
4038 soap_set_sender_error(soap, soap_ssl_error(soap, r), "SSL_connect failed in tcp_connect()", SOAP_TCP_ERROR);
4039 soap->fclosesocket(soap, fd);
4040 soap->socket = SOAP_INVALID_SOCKET; /* Oracle customization */
4041 return SOAP_INVALID_SOCKET;
4043 if (s == 0 && retries-- <= 0)
4044 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL connect timeout\n"));
4045 soap_set_sender_error(soap, "Timeout", "SSL connect failed in tcp_connect()", SOAP_TCP_ERROR);
4046 soap->fclosesocket(soap, fd);
4047 soap->socket = SOAP_INVALID_SOCKET; /* Oracle customization */
4048 return SOAP_INVALID_SOCKET;
4051 else
4052 { soap_set_sender_error(soap, soap_ssl_error(soap, r), "SSL_connect error in tcp_connect()", SOAP_SSL_ERROR);
4053 soap->fclosesocket(soap, fd);
4054 soap->socket = SOAP_INVALID_SOCKET; /* Oracle customization */
4055 return SOAP_INVALID_SOCKET;
4058 } while (!SSL_is_init_finished(soap->ssl));
4059 /* Set SSL sockets to nonblocking */
4060 SOAP_SOCKNONBLOCK(fd)
4061 /* Check server credentials when required */
4062 if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION))
4063 { int err;
4064 if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK)
4065 { soap_set_sender_error(soap, X509_verify_cert_error_string(err), "SSL certificate presented by peer cannot be verified in tcp_connect()", SOAP_SSL_ERROR);
4066 soap->fclosesocket(soap, fd);
4067 soap->socket = SOAP_INVALID_SOCKET; /* Oracle customization */
4068 return SOAP_INVALID_SOCKET;
4070 if (!(soap->ssl_flags & SOAP_SSL_SKIP_HOST_CHECK))
4071 { /* Oracle customization: X509_NAME *subj; */
4072 int ext_count;
4073 int ok = 0;
4074 X509 *peer;
4075 peer = SSL_get_peer_certificate(soap->ssl);
4076 if (!peer)
4077 { soap_set_sender_error(soap, "SSL error", "No SSL certificate was presented by the peer in tcp_connect()", SOAP_SSL_ERROR);
4078 soap->fclosesocket(soap, fd);
4079 soap->socket = SOAP_INVALID_SOCKET; /* Oracle customization */
4080 return SOAP_INVALID_SOCKET;
4082 ext_count = X509_get_ext_count(peer);
4083 if (ext_count > 0)
4084 { int i;
4085 for (i = 0; i < ext_count; i++)
4086 { X509_EXTENSION *ext = X509_get_ext(peer, i);
4087 const char *ext_str = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));
4088 if (ext_str && !strcmp(ext_str, "subjectAltName"))
4089 { X509V3_EXT_METHOD *meth = (X509V3_EXT_METHOD*)X509V3_EXT_get(ext);
4090 void *ext_data;
4091 #if (OPENSSL_VERSION_NUMBER >= 0x0090800fL)
4092 const unsigned char *data;
4093 #else
4094 unsigned char *data;
4095 #endif
4096 STACK_OF(CONF_VALUE) *val;
4097 int j;
4098 if (!meth)
4099 break;
4100 data = ext->value->data;
4101 #if (OPENSSL_VERSION_NUMBER > 0x00907000L)
4102 if (meth->it)
4103 ext_data = ASN1_item_d2i(NULL, &data, ext->value->length, ASN1_ITEM_ptr(meth->it));
4104 else
4105 { /* OpenSSL not perfectly portable at this point (?):
4106 Some compilers appear to prefer
4107 meth->d2i(NULL, (const unsigned char**)&data, ...
4108 and others prefer
4109 meth->d2i(NULL, &data, ext->value->length);
4111 ext_data = meth->d2i(NULL, &data, ext->value->length);
4113 #else
4114 ext_data = meth->d2i(NULL, &data, ext->value->length);
4115 #endif
4116 if (ext_data)
4117 { val = meth->i2v(meth, ext_data, NULL);
4118 if (val)
4119 { for (j = 0; j < sk_CONF_VALUE_num(val); j++)
4120 { CONF_VALUE *nval = sk_CONF_VALUE_value(val, j);
4121 if (nval && !strcmp(nval->name, "DNS") && !strcmp(nval->value, host))
4122 { ok = 1;
4123 break;
4126 sk_CONF_VALUE_pop_free(val, X509V3_conf_free);
4128 #if (OPENSSL_VERSION_NUMBER > 0x00907000L)
4129 if (meth->it)
4130 ASN1_item_free((ASN1_VALUE*)ext_data, ASN1_ITEM_ptr(meth->it));
4131 else
4132 meth->ext_free(ext_data);
4133 #else
4134 meth->ext_free(ext_data);
4135 #endif
4138 if (ok)
4139 break;
4143 // Oracle customization
4145 // the certificate subject name is an entity name, not a DNS name
4148 if (!ok && (subj = X509_get_subject_name(peer)))
4149 { int i = -1;
4151 { ASN1_STRING *name;
4152 i = X509_NAME_get_index_by_NID(subj, NID_commonName, i);
4153 if (i == -1)
4154 break;
4155 name = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subj, i));
4156 if (name)
4157 { if (!soap_tag_cmp(host, (const char*)M_ASN1_STRING_data(name)))
4158 ok = 1;
4159 else
4160 { unsigned char *tmp = NULL;
4161 ASN1_STRING_to_UTF8(&tmp, name);
4162 if (tmp)
4163 { if (!soap_tag_cmp(host, (const char*)tmp))
4164 ok = 1;
4165 OPENSSL_free(tmp);
4169 } while (!ok);
4172 X509_free(peer);
4174 if (!ok)
4175 { soap_set_sender_error(soap, "SSL error", "SSL certificate host name mismatch in tcp_connect()", SOAP_SSL_ERROR);
4176 soap->fclosesocket(soap, fd);
4177 return SOAP_INVALID_SOCKET;
4182 #ifdef SOAP_DEBUG
4184 // Oracle customization for debug
4186 if ( SSL_session_reused( soap->ssl ) == 1)
4188 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL session reused\n"));
4190 else
4192 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL session negotiated\n"));
4194 #endif
4195 #else
4196 soap->fclosesocket(soap, fd);
4197 soap->socket = SOAP_INVALID_SOCKET; /* Oracle customization */
4198 soap->error = SOAP_SSL_ERROR;
4199 return SOAP_INVALID_SOCKET;
4200 #endif
4202 return fd;
4204 #endif
4205 #endif
4207 /******************************************************************************/
4208 #ifndef WITH_NOIO
4209 #ifndef PALM_1
4210 static int
4211 tcp_select(struct soap *soap, SOAP_SOCKET s, int flags, int timeout)
4212 { register int r;
4213 struct timeval tv;
4214 fd_set fd[3], *rfd, *sfd, *efd;
4215 soap->errnum = 0;
4216 #ifndef WIN32
4217 /* if fd max set size exceeded, use poll() when available */
4218 #if defined(__QNX__) || defined(QNX) /* select() is not MT safe on some QNX */
4219 if (1)
4220 #else
4221 if ((int)s >= (int)FD_SETSIZE)
4222 #endif
4223 #ifdef HAVE_POLL
4224 { struct pollfd pollfd;
4225 int retries = 0;
4226 pollfd.fd = (int)s;
4227 pollfd.events = 0;
4228 if (flags & SOAP_TCP_SELECT_RCV)
4229 pollfd.events |= POLLIN;
4230 if (flags & SOAP_TCP_SELECT_SND)
4231 pollfd.events |= POLLOUT;
4232 if (flags & SOAP_TCP_SELECT_ERR)
4233 pollfd.events |= POLLERR;
4234 if (timeout < 0)
4235 timeout /= -1000; /* -usec -> ms */
4236 else if (timeout <= 1000000) /* avoid overflow */
4237 timeout *= 1000; /* sec -> ms */
4238 else
4239 { retries = timeout / 1000000;
4240 timeout = 1000000000;
4242 do r = poll(&pollfd, 1, timeout);
4243 while (r == 0 && retries--);
4244 if (r > 0)
4245 { r = 0;
4246 if ((flags & SOAP_TCP_SELECT_RCV) && (pollfd.revents & POLLIN))
4247 r |= SOAP_TCP_SELECT_RCV;
4248 if ((flags & SOAP_TCP_SELECT_SND) && (pollfd.revents & POLLOUT))
4249 r |= SOAP_TCP_SELECT_SND;
4250 if ((flags & SOAP_TCP_SELECT_ERR) && (pollfd.revents & POLLERR))
4251 r |= SOAP_TCP_SELECT_ERR;
4253 else if (r < 0)
4254 soap->errnum = soap_socket_errno(s);
4255 return r;
4257 #else
4258 { soap->error = SOAP_FD_EXCEEDED;
4259 return -1;
4261 #endif
4262 #endif
4263 rfd = sfd = efd = NULL;
4264 if (flags & SOAP_TCP_SELECT_RCV)
4265 { rfd = &fd[0];
4266 FD_ZERO(rfd);
4267 FD_SET(s, rfd);
4269 if (flags & SOAP_TCP_SELECT_SND)
4270 { sfd = &fd[1];
4271 FD_ZERO(sfd);
4272 FD_SET(s, sfd);
4274 if (flags & SOAP_TCP_SELECT_ERR)
4275 { efd = &fd[2];
4276 FD_ZERO(efd);
4277 FD_SET(s, efd);
4279 if (timeout >= 0)
4280 { tv.tv_sec = timeout;
4281 tv.tv_usec = 0;
4283 else
4284 { tv.tv_sec = -timeout / 1000000;
4285 tv.tv_usec = -timeout % 1000000;
4287 r = select((int)s + 1, rfd, sfd, efd, &tv);
4288 if (r > 0)
4289 { r = 0;
4290 if ((flags & SOAP_TCP_SELECT_RCV) && FD_ISSET(s, rfd))
4291 r |= SOAP_TCP_SELECT_RCV;
4292 if ((flags & SOAP_TCP_SELECT_SND) && FD_ISSET(s, sfd))
4293 r |= SOAP_TCP_SELECT_SND;
4294 if ((flags & SOAP_TCP_SELECT_ERR) && FD_ISSET(s, efd))
4295 r |= SOAP_TCP_SELECT_ERR;
4297 else if (r < 0)
4298 soap->errnum = soap_socket_errno(s);
4299 return r;
4301 #endif
4302 #endif
4304 /******************************************************************************/
4305 #ifndef WITH_NOIO
4306 #ifndef PALM_1
4307 static SOAP_SOCKET
4308 tcp_accept(struct soap *soap, SOAP_SOCKET s, struct sockaddr *a, int *n)
4309 { SOAP_SOCKET fd;
4310 fd = accept(s, a, (SOAP_SOCKLEN_T*)n); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
4311 #ifdef SOCKET_CLOSE_ON_EXEC
4312 #ifdef WIN32
4313 #ifndef UNDER_CE
4314 SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0);
4315 #endif
4316 #else
4317 fcntl(fd, F_SETFD, FD_CLOEXEC);
4318 #endif
4319 #endif
4320 return fd;
4322 #endif
4323 #endif
4325 /******************************************************************************/
4326 #ifndef WITH_NOIO
4327 #ifndef PALM_1
4328 static int
4329 tcp_disconnect(struct soap *soap)
4331 #ifdef WITH_OPENSSL
4332 if (soap->ssl)
4333 { int r, s = 0;
4334 if (soap->session)
4335 { SSL_SESSION_free(soap->session);
4336 soap->session = NULL;
4338 if (*soap->host)
4339 { soap->session = SSL_get1_session(soap->ssl);
4340 if (soap->session)
4341 { strcpy(soap->session_host, soap->host);
4342 soap->session_port = soap->port;
4345 r = SSL_shutdown(soap->ssl);
4346 /* SSL shutdown does not work when reads are pending */
4347 while (SSL_want_read(soap->ssl))
4348 { SSL_read(soap->ssl, NULL, 0);
4349 if (soap_socket_errno(soap->socket) != SOAP_EAGAIN)
4350 { r = SSL_shutdown(soap->ssl);
4351 break;
4354 if (r == 0)
4355 { if (soap_valid_socket(soap->socket))
4356 { if (!soap->fshutdownsocket(soap, soap->socket, 1))
4358 #ifndef WITH_LEAN
4360 wait up to 10 seconds for close_notify to be sent by peer (if peer not
4361 present, this avoids calling SSL_shutdown() which has a lengthy return
4362 timeout)
4364 r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, 10);
4365 if (r <= 0 && soap->errnum != SOAP_EINTR)
4366 { soap->errnum = 0;
4367 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connection lost...\n"));
4368 soap->fclosesocket(soap, soap->socket);
4369 soap->socket = SOAP_INVALID_SOCKET;
4370 ERR_remove_state(0);
4371 return SOAP_OK;
4373 #else
4374 r = SSL_shutdown(soap->ssl);
4375 #endif
4379 if (r != 1)
4380 { s = ERR_get_error();
4381 if (s)
4382 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown failed: %d\n", SSL_get_error(soap->ssl, r)));
4383 if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP))
4384 { soap->fclosesocket(soap, soap->socket);
4385 soap->socket = SOAP_INVALID_SOCKET;
4389 SSL_free(soap->ssl);
4390 soap->ssl = NULL;
4391 if (s)
4392 return SOAP_SSL_ERROR;
4393 ERR_remove_state(0);
4395 #endif
4396 if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP))
4397 { soap->fshutdownsocket(soap, soap->socket, 2);
4398 soap->fclosesocket(soap, soap->socket);
4399 soap->socket = SOAP_INVALID_SOCKET;
4401 return SOAP_OK;
4403 #endif
4404 #endif
4406 /******************************************************************************/
4407 #ifndef WITH_NOIO
4408 #ifndef PALM_1
4409 static int
4410 tcp_closesocket(struct soap *soap, SOAP_SOCKET fd)
4411 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Close socket %d\n", (int)fd));
4412 return soap_closesocket(fd);
4414 #endif
4415 #endif
4417 /******************************************************************************/
4418 #ifndef WITH_NOIO
4419 #ifndef PALM_1
4420 static int
4421 tcp_shutdownsocket(struct soap *soap, SOAP_SOCKET fd, int how)
4422 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown socket %d how=%d\n", (int)fd, how));
4423 return shutdown(fd, how);
4425 #endif
4426 #endif
4428 /******************************************************************************/
4429 #ifndef WITH_NOIO
4430 #ifndef PALM_1
4431 SOAP_FMAC1
4432 SOAP_SOCKET
4433 SOAP_FMAC2
4434 soap_bind(struct soap *soap, const char *host, int port, int backlog)
4436 #ifdef WITH_IPV6
4437 struct addrinfo *addrinfo = NULL;
4438 struct addrinfo hints;
4439 struct addrinfo res;
4440 int err;
4441 #ifdef IPV6_V6ONLY
4442 int unset = 0;
4443 #ifdef SOL_IP
4444 int level = SOL_IP;
4445 #else
4446 int level = IPPROTO_IPV6;
4447 #endif
4448 #endif
4449 #endif
4450 #ifndef WITH_LEAN
4451 int len = SOAP_BUFLEN;
4452 int set = 1;
4453 #endif
4454 if (soap_valid_socket(soap->master))
4455 { soap->fclosesocket(soap, soap->master);
4456 soap->master = SOAP_INVALID_SOCKET;
4458 soap->socket = SOAP_INVALID_SOCKET;
4459 soap->errmode = 1;
4460 if (tcp_init(soap))
4461 { soap_set_receiver_error(soap, tcp_error(soap), "TCP init failed in soap_bind()", SOAP_TCP_ERROR);
4462 return SOAP_INVALID_SOCKET;
4464 #ifdef WITH_IPV6
4465 memset((void*)&hints, 0, sizeof(hints));
4466 hints.ai_family = PF_UNSPEC;
4467 #ifndef WITH_LEAN
4468 if ((soap->omode & SOAP_IO_UDP))
4469 hints.ai_socktype = SOCK_DGRAM;
4470 else
4471 #endif
4472 hints.ai_socktype = SOCK_STREAM;
4473 hints.ai_flags = AI_PASSIVE;
4474 soap->errmode = 2;
4475 /* Oracle customization: check err before using addrinfo */
4476 err = getaddrinfo(host, soap_int2s(soap, port), &hints, &addrinfo);
4477 if (err || !addrinfo)
4478 { soap_set_receiver_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in soap_bind()", SOAP_TCP_ERROR);
4479 if (addrinfo)
4481 freeaddrinfo(addrinfo);
4483 return SOAP_INVALID_SOCKET;
4485 res = *addrinfo;
4486 memcpy(&soap->peer, addrinfo->ai_addr, addrinfo->ai_addrlen);
4487 soap->peerlen = addrinfo->ai_addrlen;
4488 res.ai_addr = (struct sockaddr*)&soap->peer;
4489 res.ai_addrlen = soap->peerlen;
4490 freeaddrinfo(addrinfo);
4491 soap->master = (int)socket(res.ai_family, res.ai_socktype, res.ai_protocol);
4492 #else
4493 #ifndef WITH_LEAN
4494 if ((soap->omode & SOAP_IO_UDP))
4495 soap->master = (int)socket(AF_INET, SOCK_DGRAM, 0);
4496 else
4497 #endif
4498 soap->master = (int)socket(AF_INET, SOCK_STREAM, 0);
4499 #endif
4500 soap->errmode = 0;
4501 if (!soap_valid_socket(soap->master))
4502 { soap->errnum = soap_socket_errno(soap->master);
4503 soap_set_receiver_error(soap, tcp_error(soap), "socket failed in soap_bind()", SOAP_TCP_ERROR);
4504 return SOAP_INVALID_SOCKET;
4506 #ifndef WITH_LEAN
4507 if ((soap->omode & SOAP_IO_UDP))
4508 soap->socket = soap->master;
4509 #endif
4510 #ifdef SOCKET_CLOSE_ON_EXEC
4511 #ifdef WIN32
4512 #ifndef UNDER_CE
4513 SetHandleInformation((HANDLE)soap->master, HANDLE_FLAG_INHERIT, 0);
4514 #endif
4515 #else
4516 fcntl(soap->master, F_SETFD, 1);
4517 #endif
4518 #endif
4519 #ifndef WITH_LEAN
4520 if (soap->bind_flags && setsockopt(soap->master, SOL_SOCKET, soap->bind_flags, (char*)&set, sizeof(int)))
4521 { soap->errnum = soap_socket_errno(soap->master);
4522 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_bind()", SOAP_TCP_ERROR);
4523 return SOAP_INVALID_SOCKET;
4525 if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt(soap->master, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
4526 { soap->errnum = soap_socket_errno(soap->master);
4527 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_bind()", SOAP_TCP_ERROR);
4528 return SOAP_INVALID_SOCKET;
4530 if (setsockopt(soap->master, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
4531 { soap->errnum = soap_socket_errno(soap->master);
4532 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_bind()", SOAP_TCP_ERROR);
4533 return SOAP_INVALID_SOCKET;
4535 if (setsockopt(soap->master, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
4536 { soap->errnum = soap_socket_errno(soap->master);
4537 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_bind()", SOAP_TCP_ERROR);
4538 return SOAP_INVALID_SOCKET;
4540 #ifdef TCP_NODELAY
4541 if (!(soap->omode & SOAP_IO_UDP) && setsockopt(soap->master, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
4542 { soap->errnum = soap_socket_errno(soap->master);
4543 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_bind()", SOAP_TCP_ERROR);
4544 return SOAP_INVALID_SOCKET;
4546 #endif
4547 #endif
4548 #ifdef WITH_IPV6
4549 #ifdef IPV6_V6ONLY
4550 if (setsockopt(soap->master, level, IPV6_V6ONLY, (char*)&unset, sizeof(int)))
4551 { soap->errnum = soap_socket_errno(soap->master);
4552 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt IPV6_V6ONLY failed in soap_bind()", SOAP_TCP_ERROR);
4553 return SOAP_INVALID_SOCKET;
4555 #endif
4556 soap->errmode = 0;
4557 if (bind(soap->master, res.ai_addr, (int)res.ai_addrlen))
4558 { soap->errnum = soap_socket_errno(soap->master);
4559 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
4560 soap_closesock(soap);
4561 soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR);
4562 return SOAP_INVALID_SOCKET;
4564 #else
4565 soap->peerlen = sizeof(soap->peer);
4566 memset((void*)&soap->peer, 0, sizeof(soap->peer));
4567 soap->peer.sin_family = AF_INET;
4568 soap->errmode = 2;
4569 if (host)
4570 { if (soap->fresolve(soap, host, &soap->peer.sin_addr))
4571 { soap_set_receiver_error(soap, tcp_error(soap), "get host by name failed in soap_bind()", SOAP_TCP_ERROR);
4572 return SOAP_INVALID_SOCKET;
4575 else
4576 soap->peer.sin_addr.s_addr = htonl(INADDR_ANY);
4577 soap->peer.sin_port = htons((short)port);
4578 soap->errmode = 0;
4579 if (bind(soap->master, (struct sockaddr*)&soap->peer, (int)soap->peerlen))
4580 { soap->errnum = soap_socket_errno(soap->master);
4581 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
4582 soap_closesock(soap);
4583 soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR);
4584 return SOAP_INVALID_SOCKET;
4586 #endif
4587 if (!(soap->omode & SOAP_IO_UDP) && listen(soap->master, backlog))
4588 { soap->errnum = soap_socket_errno(soap->master);
4589 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
4590 soap_closesock(soap);
4591 soap_set_receiver_error(soap, tcp_error(soap), "listen failed in soap_bind()", SOAP_TCP_ERROR);
4592 return SOAP_INVALID_SOCKET;
4594 return soap->master;
4596 #endif
4597 #endif
4599 /******************************************************************************/
4600 #ifndef WITH_NOIO
4601 #ifndef PALM_1
4602 SOAP_FMAC1
4604 SOAP_FMAC2
4605 soap_poll(struct soap *soap)
4607 #ifndef WITH_LEAN
4608 register int r;
4609 if (soap_valid_socket(soap->socket))
4610 { r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_ALL, 0);
4611 if (r > 0 && (r & SOAP_TCP_SELECT_ERR))
4612 r = -1;
4614 else if (soap_valid_socket(soap->master))
4615 r = tcp_select(soap, soap->master, SOAP_TCP_SELECT_SND, 0);
4616 else
4617 return SOAP_OK;
4618 if (r > 0)
4620 #ifdef WITH_OPENSSL
4621 if (soap->imode & SOAP_ENC_SSL)
4623 if (soap_valid_socket(soap->socket)
4624 && (r & SOAP_TCP_SELECT_SND)
4625 && (!(r & SOAP_TCP_SELECT_RCV)
4626 || SSL_peek(soap->ssl, soap->tmpbuf, 1) > 0))
4627 return SOAP_OK;
4629 else
4630 #endif
4631 if (soap_valid_socket(soap->socket)
4632 && (r & SOAP_TCP_SELECT_SND)
4633 && (!(r & SOAP_TCP_SELECT_RCV)
4634 || recv(soap->socket, soap->tmpbuf, 1, MSG_PEEK) > 0))
4635 return SOAP_OK;
4637 else if (r < 0)
4638 { if ((soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) && soap_socket_errno(soap->master) != SOAP_EINTR)
4639 { soap_set_receiver_error(soap, tcp_error(soap), "select failed in soap_poll()", SOAP_TCP_ERROR);
4640 return soap->error = SOAP_TCP_ERROR;
4643 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Polling: other end down on socket=%d select=%d\n", soap->socket, r));
4644 return SOAP_EOF;
4645 #else
4646 return SOAP_OK;
4647 #endif
4649 #endif
4650 #endif
4652 /******************************************************************************/
4653 #ifndef WITH_NOIO
4654 #ifndef PALM_1
4655 SOAP_FMAC1
4656 SOAP_SOCKET
4657 SOAP_FMAC2
4658 soap_accept(struct soap *soap)
4659 { int n = (int)sizeof(soap->peer);
4660 #ifndef WITH_LEAN
4661 int len = SOAP_BUFLEN;
4662 int set = 1;
4663 #endif
4664 soap->error = SOAP_OK;
4665 #ifndef WITH_LEAN
4666 if ((soap->omode & SOAP_IO_UDP))
4667 return soap->socket = soap->master;
4668 #endif
4669 memset((void*)&soap->peer, 0, sizeof(soap->peer));
4670 soap->socket = SOAP_INVALID_SOCKET;
4671 soap->errmode = 0;
4672 soap->keep_alive = 0;
4673 if (soap_valid_socket(soap->master))
4674 { register int err;
4675 for (;;)
4676 { if (soap->accept_timeout || soap->send_timeout || soap->recv_timeout)
4677 { for (;;)
4678 { register int r;
4679 r = tcp_select(soap, soap->master, SOAP_TCP_SELECT_ALL, soap->accept_timeout ? soap->accept_timeout : 60);
4680 if (r > 0)
4681 break;
4682 if (!r && soap->accept_timeout)
4683 { soap_set_receiver_error(soap, "Timeout", "accept failed in soap_accept()", SOAP_TCP_ERROR);
4684 return SOAP_INVALID_SOCKET;
4686 if (r < 0)
4687 { r = soap->errnum;
4688 if (r != SOAP_EINTR)
4689 { soap_closesock(soap);
4690 soap_set_sender_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR);
4691 return SOAP_INVALID_SOCKET;
4696 if (soap->accept_timeout || soap->send_timeout || soap->recv_timeout)
4697 SOAP_SOCKNONBLOCK(soap->master)
4698 else
4699 SOAP_SOCKBLOCK(soap->master)
4700 soap->socket = soap->faccept(soap, soap->master, (struct sockaddr*)&soap->peer, &n);
4701 soap->peerlen = (size_t)n;
4702 if (soap_valid_socket(soap->socket))
4704 #ifdef WITH_IPV6
4705 /* Use soap->host to store the numeric form of the remote host */
4706 getnameinfo((struct sockaddr*)&soap->peer, n, soap->host, sizeof(soap->host), NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV);
4707 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket %d from %s\n", soap->socket, soap->host));
4709 // Oracle customization
4711 // bug fix: save off the remote host
4712 strcpy(soap->session_host, soap->host);
4713 soap->ip = 0; /* info stored in soap->peer and soap->host */
4714 soap->port = 0; /* info stored in soap->peer and soap->host */
4715 #else
4716 soap->ip = ntohl(soap->peer.sin_addr.s_addr);
4717 soap->port = (int)ntohs(soap->peer.sin_port); /* does not return port number on some systems */
4718 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));
4719 #endif
4720 #ifndef WITH_LEAN
4721 if (soap->accept_flags == SO_LINGER)
4722 { struct linger linger;
4723 memset((void*)&linger, 0, sizeof(linger));
4724 linger.l_onoff = 1;
4725 linger.l_linger = soap->linger_time;
4726 if (setsockopt(soap->socket, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger)))
4727 { soap->errnum = soap_socket_errno(soap->socket);
4728 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in soap_accept()", SOAP_TCP_ERROR);
4729 soap_closesock(soap);
4730 return SOAP_INVALID_SOCKET;
4733 else if (soap->accept_flags && setsockopt(soap->socket, SOL_SOCKET, soap->accept_flags, (char*)&set, sizeof(int)))
4734 { soap->errnum = soap_socket_errno(soap->socket);
4735 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_accept()", SOAP_TCP_ERROR);
4736 soap_closesock(soap);
4737 return SOAP_INVALID_SOCKET;
4739 if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt(soap->socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
4740 { soap->errnum = soap_socket_errno(soap->socket);
4741 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_accept()", SOAP_TCP_ERROR);
4742 soap_closesock(soap);
4743 return SOAP_INVALID_SOCKET;
4745 if (setsockopt(soap->socket, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
4746 { soap->errnum = soap_socket_errno(soap->socket);
4747 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_accept()", SOAP_TCP_ERROR);
4748 soap_closesock(soap);
4749 return SOAP_INVALID_SOCKET;
4751 if (setsockopt(soap->socket, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
4752 { soap->errnum = soap_socket_errno(soap->socket);
4753 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_accept()", SOAP_TCP_ERROR);
4754 soap_closesock(soap);
4755 return SOAP_INVALID_SOCKET;
4757 #ifdef TCP_NODELAY
4758 if (!(soap->omode & SOAP_IO_UDP) && setsockopt(soap->socket, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
4759 { soap->errnum = soap_socket_errno(soap->socket);
4760 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_accept()", SOAP_TCP_ERROR);
4761 soap_closesock(soap);
4762 return SOAP_INVALID_SOCKET;
4764 #endif
4765 #endif
4766 soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0);
4767 return soap->socket;
4769 err = soap_socket_errno(soap->socket);
4770 if (err != 0 && err != SOAP_EINTR && err != SOAP_EAGAIN && err != SOAP_EWOULDBLOCK)
4771 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept failed from %s\n", soap->host));
4772 soap->errnum = err;
4773 soap_set_receiver_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR);
4774 soap_closesock(soap);
4775 return SOAP_INVALID_SOCKET;
4779 else
4780 { soap->errnum = 0;
4781 soap_set_receiver_error(soap, tcp_error(soap), "no master socket in soap_accept()", SOAP_TCP_ERROR);
4782 return SOAP_INVALID_SOCKET;
4785 #endif
4786 #endif
4788 /******************************************************************************/
4789 #ifndef PALM_1
4790 SOAP_FMAC1
4792 SOAP_FMAC2
4793 soap_closesock(struct soap *soap)
4794 { register int status = soap->error;
4795 #ifndef WITH_LEANER
4796 soap->mime.first = NULL;
4797 soap->mime.last = NULL;
4798 soap->dime.first = NULL;
4799 soap->dime.last = NULL;
4800 #endif
4801 if (soap->fdisconnect && (soap->error = soap->fdisconnect(soap)))
4802 return soap->error;
4803 if (status == SOAP_EOF || status == SOAP_TCP_ERROR || status == SOAP_SSL_ERROR || !soap->keep_alive)
4804 { if (soap->fclose && (soap->error = soap->fclose(soap)))
4805 return soap->error;
4806 soap->keep_alive = 0;
4808 #ifdef WITH_ZLIB
4809 if (soap->zlib_state == SOAP_ZLIB_DEFLATE)
4810 deflateEnd(soap->d_stream);
4811 else if (soap->zlib_state == SOAP_ZLIB_INFLATE)
4812 inflateEnd(soap->d_stream);
4813 soap->zlib_state = SOAP_ZLIB_NONE;
4814 #endif
4815 return soap->error = status;
4817 #endif
4819 /******************************************************************************/
4820 #ifndef WITH_NOIO
4821 #ifndef PALM_2
4822 SOAP_FMAC1
4823 void
4824 SOAP_FMAC2
4825 soap_cleanup(struct soap *soap)
4826 { soap_done(soap);
4827 #ifdef WIN32
4828 if (!tcp_done)
4829 return;
4830 tcp_done = 0;
4831 WSACleanup();
4832 #endif
4834 #endif
4835 #endif
4837 /******************************************************************************/
4838 #ifndef PALM_1
4839 SOAP_FMAC1
4840 void
4841 SOAP_FMAC2
4842 soap_done(struct soap *soap)
4844 #ifdef SOAP_DEBUG
4845 int i;
4846 #endif
4847 if (soap_check_state(soap))
4848 return;
4849 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Done with context\n"));
4850 soap_free_temp(soap);
4851 while (soap->clist)
4852 { struct soap_clist *p = soap->clist->next;
4853 SOAP_FREE(soap, soap->clist);
4854 soap->clist = p;
4856 if (soap->state == SOAP_INIT)
4857 soap->omode &= ~SOAP_IO_UDP; /* to force close the socket */
4858 soap->keep_alive = 0; /* to force close the socket */
4859 soap_closesock(soap);
4860 #ifdef WITH_COOKIES
4861 soap_free_cookies(soap);
4862 #endif
4863 while (soap->plugins)
4864 { register struct soap_plugin *p = soap->plugins->next;
4865 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Removing plugin '%s'\n", soap->plugins->id));
4866 if (soap->plugins->fcopy || soap->state == SOAP_INIT)
4867 soap->plugins->fdelete(soap, soap->plugins);
4868 SOAP_FREE(soap, soap->plugins);
4869 soap->plugins = p;
4871 soap->fplugin = fplugin;
4872 soap->fmalloc = NULL;
4873 #ifndef WITH_NOHTTP
4874 soap->fpost = http_post;
4875 soap->fget = http_get;
4876 soap->fput = http_405;
4877 soap->fdel = http_405;
4878 soap->fhead = http_405;
4879 soap->fform = NULL;
4880 soap->fposthdr = http_post_header;
4881 soap->fresponse = http_response;
4882 soap->fparse = http_parse;
4883 soap->fparsehdr = http_parse_header;
4884 #endif
4885 soap->fheader = NULL;
4886 #ifndef WITH_NOIO
4887 #ifndef WITH_IPV6
4888 soap->fresolve = tcp_gethost;
4889 #else
4890 soap->fresolve = NULL;
4891 #endif
4892 soap->faccept = tcp_accept;
4893 soap->fopen = tcp_connect;
4894 soap->fclose = tcp_disconnect;
4895 soap->fclosesocket = tcp_closesocket;
4896 soap->fshutdownsocket = tcp_shutdownsocket;
4897 soap->fsend = fsend;
4898 soap->frecv = frecv;
4899 soap->fpoll = soap_poll;
4900 #else
4901 soap->fopen = NULL;
4902 soap->fclose = NULL;
4903 soap->fpoll = NULL;
4904 #endif
4905 #ifndef WITH_LEANER
4906 soap->fprepareinitsend = NULL;
4907 soap->fprepareinitrecv = NULL;
4908 soap->fpreparesend = NULL;
4909 soap->fpreparerecv = NULL;
4910 soap->fpreparefinalsend = NULL;
4911 soap->fpreparefinalrecv = NULL;
4912 #endif
4913 soap->fseterror = NULL;
4914 soap->fignore = NULL;
4915 soap->fserveloop = NULL;
4916 #ifdef WITH_OPENSSL
4917 if (soap->session)
4918 { SSL_SESSION_free(soap->session);
4919 soap->session = NULL;
4921 #endif
4922 if (soap->state == SOAP_INIT)
4923 { if (soap_valid_socket(soap->master))
4924 { soap->fclosesocket(soap, soap->master);
4925 soap->master = SOAP_INVALID_SOCKET;
4928 #ifdef WITH_OPENSSL
4929 if (soap->ssl)
4930 { SSL_free(soap->ssl);
4931 soap->ssl = NULL;
4933 if (soap->state == SOAP_INIT)
4934 { if (soap->ctx)
4935 { SSL_CTX_free(soap->ctx);
4936 soap->ctx = NULL;
4939 #endif
4940 #ifdef WITH_OPENSSL
4941 ERR_remove_state(0);
4942 #endif
4943 #ifdef WITH_C_LOCALE
4944 freelocale(soap->c_locale);
4945 #endif
4946 #ifdef WITH_ZLIB
4947 if (soap->d_stream)
4948 { SOAP_FREE(soap, (void*)soap->d_stream);
4949 soap->d_stream = NULL;
4951 if (soap->z_buf)
4952 { SOAP_FREE(soap, (void*)soap->z_buf);
4953 soap->z_buf = NULL;
4955 #endif
4956 #ifdef SOAP_DEBUG
4957 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free logfiles\n"));
4958 for (i = 0; i < SOAP_MAXLOGS; i++)
4959 { if (soap->logfile[i])
4960 { SOAP_FREE(soap, (void*)soap->logfile[i]);
4961 soap->logfile[i] = NULL;
4963 soap_close_logfile(soap, i);
4965 soap->state = SOAP_NONE;
4966 #endif
4967 #ifdef SOAP_MEM_DEBUG
4968 soap_free_mht(soap);
4969 #endif
4971 #endif
4973 /******************************************************************************\
4975 * HTTP
4977 \******************************************************************************/
4979 /******************************************************************************/
4980 #ifndef WITH_NOHTTP
4981 #ifndef PALM_1
4982 static int
4983 http_parse(struct soap *soap)
4984 { char header[SOAP_HDRLEN], *s;
4985 unsigned short httpcmd = 0, status = 0;
4986 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Waiting for HTTP request/response...\n"));
4987 *soap->endpoint = '\0';
4988 soap->length = 0;
4989 soap->userid = NULL;
4990 soap->passwd = NULL;
4991 soap->action = NULL;
4992 soap->authrealm = NULL;
4993 soap->proxy_from = NULL;
4994 soap->http_content = NULL;
4995 soap->status = 0;
4997 { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
4998 { if (soap->error == SOAP_EOF)
4999 return SOAP_EOF;
5000 return soap->error = 414;
5002 if ((s = strchr(soap->msgbuf, ' ')))
5003 { soap->status = (unsigned short)soap_strtoul(s, &s, 10);
5004 if (!soap_blank(*s))
5005 soap->status = 0;
5007 else
5008 soap->status = 0;
5009 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP status: %s\n", soap->msgbuf));
5010 for (;;)
5011 { if (soap_getline(soap, header, SOAP_HDRLEN))
5012 { if (soap->error == SOAP_EOF)
5013 { soap->error = SOAP_OK;
5014 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "EOF in HTTP header, continue anyway\n"));
5015 break;
5017 return soap->error;
5019 if (!*header)
5020 break;
5021 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP header: %s\n", header));
5022 s = strchr(header, ':');
5023 if (s)
5024 { char *t;
5025 *s = '\0';
5026 do s++;
5027 while (*s && *s <= 32);
5028 if (*s == '"')
5029 s++;
5030 t = s + strlen(s) - 1;
5031 while (t > s && *t <= 32)
5032 t--;
5033 if (t >= s && *t == '"')
5034 t--;
5035 t[1] = '\0';
5036 if ((soap->error = soap->fparsehdr(soap, header, s)))
5037 { if (soap->error < SOAP_STOP)
5038 return soap->error;
5039 status = soap->error;
5040 soap->error = SOAP_OK;
5044 } while (soap->status == 100);
5045 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Finished HTTP header parsing, status = %d\n", soap->status));
5046 s = strstr(soap->msgbuf, "HTTP/");
5047 if (s && s[7] != '1')
5048 { if (soap->keep_alive == 1)
5049 soap->keep_alive = 0;
5050 if (soap->status == 0 && (soap->omode & SOAP_IO) == SOAP_IO_CHUNK) /* soap->status == 0 for HTTP request */
5051 { soap->imode |= SOAP_IO_CHUNK;
5052 soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE;
5055 if (soap->keep_alive < 0)
5056 soap->keep_alive = 1;
5057 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Keep alive connection = %d\n", soap->keep_alive));
5058 if (soap->status == 0)
5059 { size_t l = 0;
5060 if (s)
5061 { if (!strncmp(soap->msgbuf, "POST ", l = 5))
5062 httpcmd = 1;
5063 else if (!strncmp(soap->msgbuf, "GET ", l = 4))
5064 httpcmd = 2;
5065 else if (!strncmp(soap->msgbuf, "PUT ", l = 4))
5066 httpcmd = 3;
5067 else if (!strncmp(soap->msgbuf, "DELETE ", l = 7))
5068 httpcmd = 4;
5069 else if (!strncmp(soap->msgbuf, "HEAD ", l = 5))
5070 httpcmd = 5;
5072 if (s && httpcmd)
5073 { size_t m = strlen(soap->endpoint);
5074 size_t n = m + (s - soap->msgbuf) - l - 1;
5075 if (m > n)
5076 m = n;
5077 if (n >= sizeof(soap->endpoint))
5078 n = sizeof(soap->endpoint) - 1;
5079 strncpy(soap->path, soap->msgbuf + l, n - m);
5080 soap->path[n - m] = '\0';
5081 strcat(soap->endpoint, soap->path);
5082 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Target endpoint='%s'\n", soap->endpoint));
5083 if (httpcmd > 1)
5084 { switch (httpcmd)
5085 { case 2: soap->error = soap->fget(soap); break;
5086 case 3: soap->error = soap->fput(soap); break;
5087 case 4: soap->error = soap->fdel(soap); break;
5088 case 5: soap->error = soap->fhead(soap); break;
5089 default: soap->error = 405; break;
5091 if (soap->error == SOAP_OK)
5092 soap->error = SOAP_STOP; /* prevents further processing */
5093 return soap->error;
5095 if (status)
5096 return soap->error = status;
5098 else if (status)
5099 return soap->error = status;
5100 else if (s)
5101 return soap->error = 405;
5103 /* Status OK (HTTP 200) */
5104 if (soap->status == 0 || soap->status == 200)
5105 return SOAP_OK;
5106 /* Status 201 (Created), 202 (Accepted), ... and HTTP 400 and 500 errors
5107 may not have a body. When content length, content type, or chunking is
5108 used assume there is a message to parse, either XML or HTTP.
5109 This version allows parsing of content when length=0:
5110 if (soap->length > 0 || soap->http_content || (soap->imode & SOAP_IO) == SOAP_IO_CHUNK)
5112 if (soap->length > 0 || (soap->imode & SOAP_IO) == SOAP_IO_CHUNK)
5113 { if (((soap->status > 200 && soap->status <= 299) || soap->status == 400 || soap->status == 500))
5114 return SOAP_OK;
5115 /* force close afterwards in soap_closesock() */
5116 soap->keep_alive = 0;
5117 /* read HTTP body for error details */
5118 s = soap_get_http_body(soap);
5119 if (s)
5120 return soap_set_receiver_error(soap, soap->msgbuf, s, soap->status);
5122 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP error %d\n", soap->status));
5123 return soap_set_receiver_error(soap, "HTTP Error", soap->msgbuf, soap->status);
5125 #endif
5126 #endif
5128 /******************************************************************************/
5129 #ifndef WITH_NOHTTP
5130 #ifndef PALM_1
5131 static int
5132 http_parse_header(struct soap *soap, const char *key, const char *val)
5133 { if (!soap_tag_cmp(key, "Host"))
5135 #ifdef WITH_OPENSSL
5136 if (soap->imode & SOAP_ENC_SSL)
5137 strcpy(soap->endpoint, "https://");
5138 else
5139 #endif
5140 strcpy(soap->endpoint, "http://");
5141 strncat(soap->endpoint, val, sizeof(soap->endpoint) - 8);
5142 soap->endpoint[sizeof(soap->endpoint) - 1] = '\0';
5144 #ifndef WITH_LEANER
5145 else if (!soap_tag_cmp(key, "Content-Type"))
5146 { const char *action;
5147 soap->http_content = soap_strdup(soap, val);
5148 if (soap_get_header_attribute(soap, val, "application/dime"))
5149 soap->imode |= SOAP_ENC_DIME;
5150 else if (soap_get_header_attribute(soap, val, "multipart/related")
5151 || soap_get_header_attribute(soap, val, "multipart/form-data"))
5152 { soap->mime.boundary = soap_strdup(soap, soap_get_header_attribute(soap, val, "boundary"));
5153 soap->mime.start = soap_strdup(soap, soap_get_header_attribute(soap, val, "start"));
5154 soap->imode |= SOAP_ENC_MIME;
5156 action = soap_get_header_attribute(soap, val, "action");
5157 if (action)
5158 { if (*action == '"')
5159 { soap->action = soap_strdup(soap, action + 1);
5160 soap->action[strlen(soap->action) - 1] = '\0';
5162 else
5163 soap->action = soap_strdup(soap, action);
5166 #endif
5167 else if (!soap_tag_cmp(key, "Content-Length"))
5168 { soap->length = soap_strtoul(val, NULL, 10);
5170 else if (!soap_tag_cmp(key, "Content-Encoding"))
5171 { if (!soap_tag_cmp(val, "deflate"))
5172 #ifdef WITH_ZLIB
5173 soap->zlib_in = SOAP_ZLIB_DEFLATE;
5174 #else
5175 return SOAP_ZLIB_ERROR;
5176 #endif
5177 else if (!soap_tag_cmp(val, "gzip"))
5178 #ifdef WITH_GZIP
5179 soap->zlib_in = SOAP_ZLIB_GZIP;
5180 #else
5181 return SOAP_ZLIB_ERROR;
5182 #endif
5184 #ifdef WITH_ZLIB
5185 else if (!soap_tag_cmp(key, "Accept-Encoding"))
5187 #ifdef WITH_GZIP
5188 if (strchr(val, '*') || soap_get_header_attribute(soap, val, "gzip"))
5189 soap->zlib_out = SOAP_ZLIB_GZIP;
5190 else
5191 #endif
5192 if (strchr(val, '*') || soap_get_header_attribute(soap, val, "deflate"))
5193 soap->zlib_out = SOAP_ZLIB_DEFLATE;
5194 else
5195 soap->zlib_out = SOAP_ZLIB_NONE;
5197 #endif
5198 else if (!soap_tag_cmp(key, "Transfer-Encoding"))
5199 { soap->imode &= ~SOAP_IO;
5200 if (!soap_tag_cmp(val, "chunked"))
5201 soap->imode |= SOAP_IO_CHUNK;
5203 else if (!soap_tag_cmp(key, "Connection"))
5204 { if (!soap_tag_cmp(val, "keep-alive"))
5205 soap->keep_alive = -soap->keep_alive;
5206 else if (!soap_tag_cmp(val, "close"))
5207 soap->keep_alive = 0;
5209 #ifndef WITH_LEAN
5210 else if (!soap_tag_cmp(key, "Authorization"))
5211 { if (!soap_tag_cmp(val, "Basic *"))
5212 { int n;
5213 char *s;
5214 soap_base642s(soap, val + 6, soap->tmpbuf, sizeof(soap->tmpbuf) - 1, &n);
5215 soap->tmpbuf[n] = '\0';
5216 if ((s = strchr(soap->tmpbuf, ':')))
5217 { *s = '\0';
5218 soap->userid = soap_strdup(soap, soap->tmpbuf);
5219 soap->passwd = soap_strdup(soap, s + 1);
5223 else if (!soap_tag_cmp(key, "WWW-Authenticate"))
5224 { soap->authrealm = soap_strdup(soap, soap_get_header_attribute(soap, val + 6, "realm"));
5226 else if (!soap_tag_cmp(key, "Expect"))
5227 { if (!soap_tag_cmp(val, "100-continue"))
5228 { if ((soap->error = soap->fposthdr(soap, "HTTP/1.1 100 Continue", NULL))
5229 || (soap->error = soap->fposthdr(soap, NULL, NULL)))
5230 return soap->error;
5233 #endif
5234 else if (!soap_tag_cmp(key, "SOAPAction"))
5235 { if (*val == '"')
5236 { soap->action = soap_strdup(soap, val + 1);
5237 soap->action[strlen(soap->action) - 1] = '\0';
5239 else
5240 soap->action = soap_strdup(soap, val);
5242 else if (!soap_tag_cmp(key, "Location"))
5243 { strncpy(soap->endpoint, val, sizeof(soap->endpoint));
5244 soap->endpoint[sizeof(soap->endpoint) - 1] = '\0';
5246 else if (!soap_tag_cmp(key, "X-Forwarded-For"))
5247 { soap->proxy_from = soap_strdup(soap, val);
5249 #ifdef WITH_COOKIES
5250 else if (!soap_tag_cmp(key, "Cookie")
5251 || !soap_tag_cmp(key, "Cookie2")
5252 || !soap_tag_cmp(key, "Set-Cookie")
5253 || !soap_tag_cmp(key, "Set-Cookie2"))
5254 { soap_getcookies(soap, val);
5256 #endif
5257 return SOAP_OK;
5259 #endif
5260 #endif
5262 /******************************************************************************/
5263 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
5264 #ifndef PALM_1
5265 SOAP_FMAC1
5266 const char*
5267 SOAP_FMAC2
5268 soap_get_header_attribute(struct soap *soap, const char *line, const char *key)
5269 { register const char *s = line;
5270 if (s)
5271 { while (*s)
5272 { register short flag;
5273 s = soap_decode_key(soap->tmpbuf, sizeof(soap->tmpbuf), s);
5274 flag = soap_tag_cmp(soap->tmpbuf, key);
5275 s = soap_decode_val(soap->tmpbuf, sizeof(soap->tmpbuf), s);
5276 if (!flag)
5277 return soap->tmpbuf;
5280 return NULL;
5282 #endif
5283 #endif
5285 /******************************************************************************/
5286 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
5287 #ifndef PALM_1
5288 SOAP_FMAC1
5289 const char*
5290 SOAP_FMAC2
5291 soap_decode_key(char *buf, size_t len, const char *val)
5292 { return soap_decode(buf, len, val, "=,;");
5294 #endif
5295 #endif
5297 /******************************************************************************/
5298 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
5299 #ifndef PALM_1
5300 SOAP_FMAC1
5301 const char*
5302 SOAP_FMAC2
5303 soap_decode_val(char *buf, size_t len, const char *val)
5304 { if (*val != '=')
5305 { *buf = '\0';
5306 return val;
5308 return soap_decode(buf, len, val + 1, ",;");
5310 #endif
5311 #endif
5313 /******************************************************************************/
5314 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
5315 #ifndef PALM_1
5316 static const char*
5317 soap_decode(char *buf, size_t len, const char *val, const char *sep)
5318 { const char *s;
5319 char *t = buf;
5320 for (s = val; *s; s++)
5321 if (*s != ' ' && *s != '\t' && !strchr(sep, *s))
5322 break;
5323 if (*s == '"')
5324 { s++;
5325 while (*s && *s != '"' && --len)
5326 *t++ = *s++;
5328 else
5329 { while (*s && !soap_blank(*s) && !strchr(sep, *s) && --len)
5330 { if (*s == '%')
5331 { *t++ = ((s[1] >= 'A' ? (s[1] & 0x7) + 9 : s[1] - '0') << 4)
5332 + (s[2] >= 'A' ? (s[2] & 0x7) + 9 : s[2] - '0');
5333 s += 3;
5335 else
5336 *t++ = *s++;
5339 *t = '\0';
5340 while (*s && !strchr(sep, *s))
5341 s++;
5342 return s;
5344 #endif
5345 #endif
5347 /******************************************************************************/
5348 #ifndef WITH_NOHTTP
5349 #ifndef PALM_1
5350 static const char*
5351 http_error(struct soap *soap, int status)
5352 { register const char *msg = SOAP_STR_EOS;
5353 #ifndef WITH_LEAN
5354 msg = soap_code_str(h_http_error_codes, status);
5355 if (!msg)
5356 msg = SOAP_STR_EOS;
5357 #endif
5358 return msg;
5360 #endif
5361 #endif
5363 /******************************************************************************/
5364 #ifndef WITH_NOHTTP
5365 #ifndef PALM_1
5366 static int
5367 http_get(struct soap *soap)
5368 { return SOAP_GET_METHOD;
5370 #endif
5371 #endif
5373 /******************************************************************************/
5374 #ifndef WITH_NOHTTP
5375 #ifndef PALM_1
5376 static int
5377 http_405(struct soap *soap)
5378 { return 405;
5380 #endif
5381 #endif
5383 /******************************************************************************/
5384 #ifndef WITH_NOHTTP
5385 #ifndef PALM_1
5386 static int
5387 http_post(struct soap *soap, const char *endpoint, const char *host, int port, const char *path, const char *action, size_t count)
5388 { register const char *s;
5389 register int err;
5390 if (soap->status == SOAP_GET)
5391 s = "GET";
5392 else
5393 s = "POST";
5394 #ifdef PALM
5395 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))
5396 #else
5397 if (!endpoint || (soap_tag_cmp(endpoint, "http:*") && soap_tag_cmp(endpoint, "https:*") && strncmp(endpoint, "httpg:", 6)))
5398 #endif
5399 return SOAP_OK;
5400 if (strlen(endpoint) + strlen(soap->http_version) > sizeof(soap->tmpbuf) - 80)
5401 return soap->error = SOAP_EOM;
5402 if (soap->proxy_host && soap_tag_cmp(endpoint, "https:*"))
5403 sprintf(soap->tmpbuf, "%s %s HTTP/%s", s, endpoint, soap->http_version);
5404 else
5405 sprintf(soap->tmpbuf, "%s /%s HTTP/%s", s, (*path == '/' ? path + 1 : path), soap->http_version);
5406 if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
5407 return err;
5408 #ifdef WITH_OPENSSL
5409 if ((soap->ssl && soap->port != 443) || (!soap->ssl && soap->port != 80))
5410 sprintf(soap->tmpbuf, "%s:%d", host, port);
5411 else
5412 strcpy(soap->tmpbuf, host);
5413 #else
5414 if (port != 80)
5415 sprintf(soap->tmpbuf, "%s:%d", host, port);
5416 else
5417 { /* Oracle customization */
5418 strncpy(soap->tmpbuf, host, sizeof(soap->tmpbuf) - 1);
5419 soap->tmpbuf[sizeof(soap->tmpbuf) - 1] = '\0';
5421 #endif
5422 // Oracle customization
5423 if ((err = soap->fposthdr(soap, "Host", soap->tmpbuf))
5424 || (err = soap->fposthdr(soap, "User-Agent", "SunKMS gSOAP/2.7.17"))
5425 || (err = soap_puthttphdr(soap, SOAP_OK, count)))
5426 return err;
5427 #ifdef WITH_ZLIB
5428 #ifdef WITH_GZIP
5429 if ((err = soap->fposthdr(soap, "Accept-Encoding", "gzip, deflate")))
5430 #else
5431 if ((err = soap->fposthdr(soap, "Accept-Encoding", "deflate")))
5432 #endif
5433 return err;
5434 #endif
5435 #ifndef WITH_LEAN
5436 if (soap->userid && soap->passwd && strlen(soap->userid) + strlen(soap->passwd) < 761)
5437 { sprintf(soap->tmpbuf + 262, "%s:%s", soap->userid, soap->passwd);
5438 strcpy(soap->tmpbuf, "Basic ");
5439 soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262));
5440 if ((err = soap->fposthdr(soap, "Authorization", soap->tmpbuf)))
5441 return err;
5443 if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761)
5444 { sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd);
5445 strcpy(soap->tmpbuf, "Basic ");
5446 soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262));
5447 if ((err = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf)))
5448 return err;
5450 #endif
5451 #ifdef WITH_COOKIES
5452 #ifdef WITH_OPENSSL
5453 if (soap_putcookies(soap, host, path, soap->ssl != NULL))
5454 return soap->error;
5455 #else
5456 if (soap_putcookies(soap, host, path, 0))
5457 return soap->error;
5458 #endif
5459 #endif
5460 if (soap->status != SOAP_GET && (soap->version == 1 || (action && *action)))
5461 { sprintf(soap->tmpbuf, "\"%s\"", action && strlen(action) < sizeof(soap->tmpbuf) - 3 ? action : SOAP_STR_EOS);
5462 if ((err = soap->fposthdr(soap, "SOAPAction", soap->tmpbuf)))
5463 return err;
5465 return soap->fposthdr(soap, NULL, NULL);
5467 #endif
5468 #endif
5470 /******************************************************************************/
5471 #ifndef WITH_NOHTTP
5472 #ifndef PALM_1
5473 static int
5474 http_send_header(struct soap *soap, const char *s)
5475 { register const char *t;
5477 { t = strchr(s, '\n'); /* disallow \n in HTTP headers */
5478 if (!t)
5479 t = s + strlen(s);
5480 if (soap_send_raw(soap, s, t - s))
5481 return soap->error;
5482 s = t + 1;
5483 } while (*t);
5484 return SOAP_OK;
5486 #endif
5487 #endif
5489 /******************************************************************************/
5490 #ifndef WITH_NOHTTP
5491 #ifndef PALM_1
5492 static int
5493 http_post_header(struct soap *soap, const char *key, const char *val)
5494 { if (key)
5495 { if (http_send_header(soap, key))
5496 return soap->error;
5497 if (val && (soap_send_raw(soap, ": ", 2) || http_send_header(soap, val)))
5498 return soap->error;
5500 return soap_send_raw(soap, "\r\n", 2);
5502 #endif
5503 #endif
5505 /******************************************************************************/
5506 #ifndef WITH_NOHTTP
5507 #ifndef PALM_1
5508 static int
5509 http_response(struct soap *soap, int status, size_t count)
5510 { register int err;
5511 #ifdef WMW_RPM_IO
5512 if (soap->rpmreqid)
5513 httpOutputEnable(soap->rpmreqid);
5514 #endif
5515 if (strlen(soap->http_version) > 4)
5516 return soap->error = SOAP_EOM;
5517 if (!status || status == SOAP_HTML || status == SOAP_FILE)
5518 { const char *s;
5519 if (count || ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK))
5520 s = "200 OK";
5521 else
5522 s = "202 ACCEPTED";
5523 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Status = %s\n", s));
5524 #ifdef WMW_RPM_IO
5525 if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */
5526 #else
5527 if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application (socket) or CGI (stdin/out)? */
5528 #endif
5529 { sprintf(soap->tmpbuf, "HTTP/%s %s", soap->http_version, s);
5530 if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
5531 return err;
5533 else if ((err = soap->fposthdr(soap, "Status", s))) /* CGI header */
5534 return err;
5536 else if (status >= 200 && status < 600)
5537 { sprintf(soap->tmpbuf, "HTTP/%s %d %s", soap->http_version, status, http_error(soap, status));
5538 if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
5539 return err;
5540 #ifndef WITH_LEAN
5541 if (status == 401)
5542 { sprintf(soap->tmpbuf, "Basic realm=\"%s\"", (soap->authrealm && strlen(soap->authrealm) < sizeof(soap->tmpbuf) - 14) ? soap->authrealm : "gSOAP Web Service");
5543 if ((err = soap->fposthdr(soap, "WWW-Authenticate", soap->tmpbuf)))
5544 return err;
5546 else if ((status >= 301 && status <= 303) || status == 307)
5547 { if ((err = soap->fposthdr(soap, "Location", soap->endpoint)))
5548 return err;
5550 #endif
5552 else
5553 { const char *s = *soap_faultcode(soap);
5554 if (status >= SOAP_GET_METHOD && status <= SOAP_HTTP_METHOD)
5555 s = "405 Method Not Allowed";
5556 else if (soap->version == 2 && (!s || !strcmp(s, "SOAP-ENV:Sender")))
5557 s = "400 Bad Request";
5558 else
5559 s = "500 Internal Server Error";
5560 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error %s (status=%d)\n", s, status));
5561 #ifdef WMW_RPM_IO
5562 if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */
5563 #else
5564 if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application */
5565 #endif
5566 { sprintf(soap->tmpbuf, "HTTP/%s %s", soap->http_version, s);
5567 if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
5568 return err;
5570 else if ((err = soap->fposthdr(soap, "Status", s))) /* CGI */
5571 return err;
5573 if ((err = soap->fposthdr(soap, "Server", "gSOAP/2.7"))
5574 || (err = soap_puthttphdr(soap, status, count)))
5575 return err;
5576 #ifdef WITH_COOKIES
5577 if (soap_putsetcookies(soap))
5578 return soap->error;
5579 #endif
5580 return soap->fposthdr(soap, NULL, NULL);
5582 #endif
5583 #endif
5585 /******************************************************************************/
5586 #ifndef PALM_1
5587 SOAP_FMAC1
5589 SOAP_FMAC2
5590 soap_response(struct soap *soap, int status)
5591 { register size_t count;
5592 if (!(soap->omode & (SOAP_ENC_XML | SOAP_IO_STORE /* this tests for chunking too */))
5593 && (status == SOAP_HTML || status == SOAP_FILE))
5594 soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE;
5595 soap->status = status;
5596 count = soap_count_attachments(soap);
5597 if (soap_begin_send(soap))
5598 return soap->error;
5599 #ifndef WITH_NOHTTP
5600 if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML))
5601 { register int n = soap->mode;
5602 soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB);
5603 if ((n & SOAP_IO) != SOAP_IO_FLUSH)
5604 soap->mode |= SOAP_IO_BUFFER;
5605 if ((soap->error = soap->fresponse(soap, status, count)))
5606 return soap->error;
5607 #ifndef WITH_LEANER
5608 if ((n & SOAP_IO) == SOAP_IO_CHUNK)
5609 { if (soap_flush(soap))
5610 return soap->error;
5612 #endif
5613 soap->mode = n;
5615 #endif
5616 return SOAP_OK;
5618 #endif
5620 /******************************************************************************\
5622 * HTTP Cookies
5624 \******************************************************************************/
5626 #ifdef WITH_COOKIES
5627 /******************************************************************************/
5628 SOAP_FMAC1
5629 size_t
5630 SOAP_FMAC2
5631 soap_encode_cookie(const char *s, char *t, size_t len)
5632 { register int c;
5633 register size_t n = len;
5634 while ((c = *s++) && --n > 0)
5635 { if (c > ' ' && c < 128 && !strchr("()<>@,;:\\\"/[]?={}#!$&'*+", c))
5636 *t++ = c;
5637 else if (n > 2)
5638 { *t++ = '%';
5639 *t++ = (c >> 4) + (c > 159 ? '7' : '0');
5640 c &= 0xF;
5641 *t++ = c + (c > 9 ? '7' : '0');
5642 n -= 2;
5644 else
5645 break;
5647 *t = '\0';
5648 return len - n;
5651 /******************************************************************************/
5652 SOAP_FMAC1
5653 struct soap_cookie*
5654 SOAP_FMAC2
5655 soap_cookie(struct soap *soap, const char *name, const char *domain, const char *path)
5656 { struct soap_cookie *p;
5657 if (!domain)
5658 domain = soap->cookie_domain;
5659 if (!path)
5660 path = soap->cookie_path;
5661 if (!path)
5662 path = SOAP_STR_EOS;
5663 else if (*path == '/')
5664 path++;
5665 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Search cookie %s domain=%s path=%s\n", name, domain?domain:"(null)", path?path:"(null)"));
5666 for (p = soap->cookies; p; p = p->next)
5667 { 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));
5668 if (!strcmp(p->name, name)
5669 && p->domain
5670 && p->path
5671 && !strcmp(p->domain, domain)
5672 && (!*p->path || !strncmp(p->path, path, strlen(p->path))))
5673 break;
5675 return p;
5678 /******************************************************************************/
5679 SOAP_FMAC1
5680 struct soap_cookie*
5681 SOAP_FMAC2
5682 soap_set_cookie(struct soap *soap, const char *name, const char *value, const char *domain, const char *path)
5683 { struct soap_cookie **p, *q;
5684 int n;
5685 if (!domain)
5686 domain = soap->cookie_domain;
5687 if (!path)
5688 path = soap->cookie_path;
5689 if (!path)
5690 path = SOAP_STR_EOS;
5691 else if (*path == '/')
5692 path++;
5693 q = soap_cookie(soap, name, domain, path);
5694 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)"));
5695 if (!q)
5696 { if ((q = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie))))
5697 { if ((q->name = (char*)SOAP_MALLOC(soap, strlen(name)+1)))
5698 strcpy(q->name, name);
5699 q->value = NULL;
5700 q->domain = NULL;
5701 q->path = NULL;
5702 q->expire = 0;
5703 q->maxage = -1;
5704 q->version = 1;
5705 q->secure = 0;
5706 q->modified = 0;
5707 for (p = &soap->cookies, n = soap->cookie_max; *p && n; p = &(*p)->next, n--)
5708 if (!strcmp((*p)->name, name) && (*p)->path && path && strcmp((*p)->path, path) < 0)
5709 break;
5710 if (n)
5711 { q->next = *p;
5712 *p = q;
5714 else
5715 { SOAP_FREE(soap, q->name);
5716 SOAP_FREE(soap, q);
5717 q = NULL;
5721 else
5722 q->modified = 1;
5723 if (q)
5724 { if (q->value)
5725 { if (!value || strcmp(value, q->value))
5726 { SOAP_FREE(soap, q->value);
5727 q->value = NULL;
5730 if (value && *value && !q->value && (q->value = (char*)SOAP_MALLOC(soap, strlen(value)+1)))
5731 strcpy(q->value, value);
5732 if (q->domain)
5733 { if (!domain || strcmp(domain, q->domain))
5734 { SOAP_FREE(soap, q->domain);
5735 q->domain = NULL;
5738 if (domain && !q->domain && (q->domain = (char*)SOAP_MALLOC(soap, strlen(domain)+1)))
5739 strcpy(q->domain, domain);
5740 if (q->path)
5741 { if (!path || strncmp(path, q->path, strlen(q->path)))
5742 { SOAP_FREE(soap, q->path);
5743 q->path = NULL;
5746 if (path && !q->path && (q->path = (char*)SOAP_MALLOC(soap, strlen(path)+1)))
5747 strcpy(q->path, path);
5748 q->session = 1;
5749 q->env = 0;
5751 return q;
5754 /******************************************************************************/
5755 SOAP_FMAC1
5756 void
5757 SOAP_FMAC2
5758 soap_clr_cookie(struct soap *soap, const char *name, const char *domain, const char *path)
5759 { struct soap_cookie **p, *q;
5760 if (!domain)
5761 domain = soap->cookie_domain;
5762 if (!domain)
5763 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error in clear cookie %s: cookie domain not set\n", name?name:"(null)"));
5764 return;
5766 if (!path)
5767 path = soap->cookie_path;
5768 if (!path)
5769 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error in clear cookie %s: cookie path not set\n", name?name:"(null)"));
5770 return;
5772 if (*path == '/')
5773 path++;
5774 for (p = &soap->cookies, q = *p; q; q = *p)
5775 { if (!strcmp(q->name, name) && !strcmp(q->domain, domain) && !strncmp(q->path, path, strlen(q->path)))
5776 { if (q->value)
5777 SOAP_FREE(soap, q->value);
5778 if (q->domain)
5779 SOAP_FREE(soap, q->domain);
5780 if (q->path)
5781 SOAP_FREE(soap, q->path);
5782 *p = q->next;
5783 SOAP_FREE(soap, q);
5785 else
5786 p = &q->next;
5790 /******************************************************************************/
5791 SOAP_FMAC1
5792 char *
5793 SOAP_FMAC2
5794 soap_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path)
5795 { struct soap_cookie *p;
5796 if ((p = soap_cookie(soap, name, domain, path)))
5797 return p->value;
5798 return NULL;
5801 /******************************************************************************/
5802 SOAP_FMAC1
5803 char *
5804 SOAP_FMAC2
5805 soap_env_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path)
5806 { struct soap_cookie *p;
5807 if ((p = soap_cookie(soap, name, domain, path)) && p->env)
5808 return p->value;
5809 return NULL;
5812 /******************************************************************************/
5813 SOAP_FMAC1
5814 time_t
5815 SOAP_FMAC2
5816 soap_cookie_expire(struct soap *soap, const char *name, const char *domain, const char *path)
5817 { struct soap_cookie *p;
5818 if ((p = soap_cookie(soap, name, domain, path)))
5819 return p->expire;
5820 return -1;
5823 /******************************************************************************/
5824 SOAP_FMAC1
5826 SOAP_FMAC2
5827 soap_set_cookie_expire(struct soap *soap, const char *name, long expire, const char *domain, const char *path)
5828 { struct soap_cookie *p;
5829 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)"));
5830 if ((p = soap_cookie(soap, name, domain, path)))
5831 { p->maxage = expire;
5832 p->modified = 1;
5833 return SOAP_OK;
5835 return SOAP_ERR;
5838 /******************************************************************************/
5839 SOAP_FMAC1
5841 SOAP_FMAC2
5842 soap_set_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path)
5843 { struct soap_cookie *p;
5844 if ((p = soap_cookie(soap, name, domain, path)))
5845 { p->session = 1;
5846 p->modified = 1;
5847 return SOAP_OK;
5849 return SOAP_ERR;
5852 /******************************************************************************/
5853 SOAP_FMAC1
5855 SOAP_FMAC2
5856 soap_clr_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path)
5857 { struct soap_cookie *p;
5858 if ((p = soap_cookie(soap, name, domain, path)))
5859 { p->session = 0;
5860 p->modified = 1;
5861 return SOAP_OK;
5863 return SOAP_ERR;
5866 /******************************************************************************/
5867 SOAP_FMAC1
5869 SOAP_FMAC2
5870 soap_putsetcookies(struct soap *soap)
5871 { struct soap_cookie *p;
5872 char *s, tmp[4096];
5873 const char *t;
5874 for (p = soap->cookies; p; p = p->next)
5876 if (p->modified
5877 #ifdef WITH_OPENSSL
5878 || (!p->env && !soap->ssl == !p->secure)
5879 #endif
5881 { s = tmp;
5882 if (p->name)
5883 s += soap_encode_cookie(p->name, s, tmp-s+4064);
5884 if (p->value && *p->value)
5885 { *s++ = '=';
5886 s += soap_encode_cookie(p->value, s, tmp-s+4064);
5888 if (p->domain && (int)strlen(p->domain) < tmp-s+4064)
5889 { strcpy(s, ";Domain=");
5890 strcat(s, p->domain);
5892 else if (soap->cookie_domain && (int)strlen(soap->cookie_domain) < tmp-s+4064)
5893 { strcpy(s, ";Domain=");
5894 strcat(s, soap->cookie_domain);
5896 strcat(s, ";Path=/");
5897 s += strlen(s);
5898 if (p->path)
5899 t = p->path;
5900 else
5901 t = soap->cookie_path;
5902 if (t)
5903 { if (*t == '/')
5904 t++;
5905 if ((int)strlen(t) < tmp-s+4064)
5906 { if (strchr(t, '%')) /* already URL encoded? */
5907 { strcpy(s, t);
5908 s += strlen(s);
5910 else
5911 s += soap_encode_cookie(t, s, tmp-s+4064);
5914 if (p->version > 0 && s-tmp < 4060)
5915 { sprintf(s, ";Version=%u", p->version);
5916 s += strlen(s);
5918 if (p->maxage >= 0 && s-tmp < 4060)
5919 { sprintf(s, ";Max-Age=%ld", p->maxage);
5920 s += strlen(s);
5922 if (s-tmp < 4073
5923 && (p->secure
5924 #ifdef WITH_OPENSSL
5925 || soap->ssl
5926 #endif
5928 strcpy(s, ";Secure");
5929 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set-Cookie: %s\n", tmp));
5930 if ((soap->error = soap->fposthdr(soap, "Set-Cookie", tmp)))
5931 return soap->error;
5934 return SOAP_OK;
5937 /******************************************************************************/
5938 SOAP_FMAC1
5940 SOAP_FMAC2
5941 soap_putcookies(struct soap *soap, const char *domain, const char *path, int secure)
5942 { struct soap_cookie **p, *q;
5943 unsigned int version = 0;
5944 time_t now = time(NULL);
5945 char *s, tmp[4096];
5946 p = &soap->cookies;
5947 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending cookies for domain=%s path=%s\n", domain, path));
5948 if (*path == '/')
5949 path++;
5950 while ((q = *p))
5951 { if (q->expire && now > q->expire)
5952 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie %s expired\n", q->name));
5953 SOAP_FREE(soap, q->name);
5954 if (q->value)
5955 SOAP_FREE(soap, q->value);
5956 if (q->domain)
5957 SOAP_FREE(soap, q->domain);
5958 if (q->path)
5959 SOAP_FREE(soap, q->path);
5960 *p = q->next;
5961 SOAP_FREE(soap, q);
5963 else
5964 { int flag;
5965 char *t = q->domain;
5966 size_t n = 0;
5967 if (!t)
5968 flag = 1;
5969 else
5970 { const char *r = strchr(t, ':');
5971 if (r)
5972 n = r - t;
5973 else
5974 n = strlen(t);
5975 flag = !strncmp(t, domain, n);
5977 /* domain-level cookies, cannot compile when WITH_NOIO set */
5978 #ifndef WITH_NOIO
5979 if (!flag)
5980 { struct hostent *hostent = gethostbyname((char*)domain);
5981 if (hostent)
5982 { const char *r = strchr(hostent->h_name, '.');
5983 if (!r)
5984 r = hostent->h_name;
5985 flag = !strncmp(t, r, n);
5988 #endif
5989 if (flag
5990 && (!q->path || !strncmp(q->path, path, strlen(q->path)))
5991 && (!q->secure || secure))
5992 { s = tmp;
5993 if (q->version != version)
5994 { sprintf(s, "$Version=%u;", q->version);
5995 version = q->version;
5997 if (q->name)
5998 s += soap_encode_cookie(q->name, s, tmp-s+4080);
5999 if (q->value && *q->value)
6000 { *s++ = '=';
6001 s += soap_encode_cookie(q->value, s, tmp-s+4080);
6003 if (q->path && *q->path && (int)strlen(q->path) < tmp-s+4080)
6004 { sprintf(s, ";$Path=\"/%s\"", (*q->path == '/' ? q->path + 1 : q->path));
6005 s += strlen(s);
6007 if (q->domain && (int)strlen(q->domain) < tmp-s+4080)
6008 sprintf(s, ";$Domain=\"%s\"", q->domain);
6009 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie: %s\n", tmp));
6010 if ((soap->error = soap->fposthdr(soap, "Cookie", tmp)))
6011 return soap->error;
6013 p = &q->next;
6016 return SOAP_OK;
6019 /******************************************************************************/
6020 SOAP_FMAC1
6021 void
6022 SOAP_FMAC2
6023 soap_getcookies(struct soap *soap, const char *val)
6024 { struct soap_cookie *p = NULL, *q;
6025 const char *s;
6026 char *t, tmp[4096]; /* cookie size is up to 4096 bytes [RFC2109] */
6027 char *domain = NULL;
6028 char *path = NULL;
6029 unsigned int version = 0;
6030 time_t now = time(NULL);
6031 if (!val)
6032 return;
6033 s = val;
6034 while (*s)
6035 { s = soap_decode_key(tmp, sizeof(tmp), s);
6036 if (!soap_tag_cmp(tmp, "$Version"))
6037 { if ((s = soap_decode_val(tmp, sizeof(tmp), s)))
6038 { if (p)
6039 p->version = (int)soap_strtol(tmp, NULL, 10);
6040 else
6041 version = (int)soap_strtol(tmp, NULL, 10);
6044 else if (!soap_tag_cmp(tmp, "$Path"))
6045 { s = soap_decode_val(tmp, sizeof(tmp), s);
6046 if (*tmp)
6047 { if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1)))
6048 strcpy(t, tmp);
6050 else
6051 t = NULL;
6052 if (p)
6053 { if (p->path)
6054 SOAP_FREE(soap, p->path);
6055 p->path = t;
6057 else
6058 { if (path)
6059 SOAP_FREE(soap, path);
6060 path = t;
6063 else if (!soap_tag_cmp(tmp, "$Domain"))
6064 { s = soap_decode_val(tmp, sizeof(tmp), s);
6065 if (*tmp)
6066 { if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1)))
6067 strcpy(t, tmp);
6069 else
6070 t = NULL;
6071 if (p)
6072 { if (p->domain)
6073 SOAP_FREE(soap, p->domain);
6074 p->domain = t;
6076 else
6077 { if (domain)
6078 SOAP_FREE(soap, domain);
6079 domain = t;
6082 else if (p && !soap_tag_cmp(tmp, "Path"))
6083 { if (p->path)
6084 SOAP_FREE(soap, p->path);
6085 s = soap_decode_val(tmp, sizeof(tmp), s);
6086 if (*tmp)
6087 { if ((p->path = (char*)SOAP_MALLOC(soap, strlen(tmp)+1)))
6088 strcpy(p->path, tmp);
6090 else
6091 p->path = NULL;
6093 else if (p && !soap_tag_cmp(tmp, "Domain"))
6094 { if (p->domain)
6095 SOAP_FREE(soap, p->domain);
6096 s = soap_decode_val(tmp, sizeof(tmp), s);
6097 if (*tmp)
6098 { if ((p->domain = (char*)SOAP_MALLOC(soap, strlen(tmp)+1)))
6099 strcpy(p->domain, tmp);
6101 else
6102 p->domain = NULL;
6104 else if (p && !soap_tag_cmp(tmp, "Version"))
6105 { s = soap_decode_val(tmp, sizeof(tmp), s);
6106 p->version = (unsigned int)soap_strtoul(tmp, NULL, 10);
6108 else if (p && !soap_tag_cmp(tmp, "Max-Age"))
6109 { s = soap_decode_val(tmp, sizeof(tmp), s);
6110 p->expire = now + soap_strtol(tmp, NULL, 10);
6112 else if (p && !soap_tag_cmp(tmp, "Expires"))
6113 { struct tm T;
6114 char a[3];
6115 static const char mns[] = "anebarprayunulugepctovec";
6116 s = soap_decode_val(tmp, sizeof(tmp), s);
6117 if (strlen(tmp) > 20)
6118 { memset((void*)&T, 0, sizeof(T));
6119 a[0] = tmp[4];
6120 a[1] = tmp[5];
6121 a[2] = '\0';
6122 T.tm_mday = (int)soap_strtol(a, NULL, 10);
6123 a[0] = tmp[8];
6124 a[1] = tmp[9];
6125 T.tm_mon = (int)(strstr(mns, a) - mns) / 2;
6126 a[0] = tmp[11];
6127 a[1] = tmp[12];
6128 T.tm_year = 100 + (int)soap_strtol(a, NULL, 10);
6129 a[0] = tmp[13];
6130 a[1] = tmp[14];
6131 T.tm_hour = (int)soap_strtol(a, NULL, 10);
6132 a[0] = tmp[16];
6133 a[1] = tmp[17];
6134 T.tm_min = (int)soap_strtol(a, NULL, 10);
6135 a[0] = tmp[19];
6136 a[1] = tmp[20];
6137 T.tm_sec = (int)soap_strtol(a, NULL, 10);
6138 p->expire = soap_timegm(&T);
6141 else if (p && !soap_tag_cmp(tmp, "Secure"))
6142 p->secure = 1;
6143 else
6144 { if (p)
6145 { 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));
6146 if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path)))
6147 { q->version = p->version;
6148 q->expire = p->expire;
6149 q->secure = p->secure;
6150 q->env = 1;
6152 if (p->name)
6153 SOAP_FREE(soap, p->name);
6154 if (p->value)
6155 SOAP_FREE(soap, p->value);
6156 if (p->domain)
6157 SOAP_FREE(soap, p->domain);
6158 if (p->path)
6159 SOAP_FREE(soap, p->path);
6160 SOAP_FREE(soap, p);
6162 if ((p = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie))))
6163 { p->name = (char*)SOAP_MALLOC(soap, strlen(tmp)+1);
6164 strcpy(p->name, tmp);
6165 s = soap_decode_val(tmp, sizeof(tmp), s);
6166 if (*tmp)
6167 { p->value = (char*)SOAP_MALLOC(soap, strlen(tmp)+1);
6168 strcpy(p->value, tmp);
6170 else
6171 p->value = NULL;
6172 if (domain)
6173 p->domain = domain;
6174 else if (*soap->host)
6175 { p->domain = (char*)SOAP_MALLOC(soap, strlen(soap->host)+1);
6176 strcpy(p->domain, soap->host);
6178 else
6179 p->domain = NULL;
6180 if (path)
6181 p->path = path;
6182 else if (soap->path && *soap->path)
6183 { p->path = (char*)SOAP_MALLOC(soap, strlen(soap->path)+1);
6184 strcpy(p->path, soap->path);
6186 else
6187 { p->path = (char*)SOAP_MALLOC(soap, 2);
6188 strcpy(p->path, "/");
6190 p->expire = 0;
6191 p->secure = 0;
6192 p->version = version;
6196 if (p)
6197 { 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));
6198 if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path)))
6199 { q->version = p->version;
6200 q->expire = p->expire;
6201 q->secure = p->secure;
6202 q->env = 1;
6204 if (p->name)
6205 SOAP_FREE(soap, p->name);
6206 if (p->value)
6207 SOAP_FREE(soap, p->value);
6208 if (p->domain)
6209 SOAP_FREE(soap, p->domain);
6210 if (p->path)
6211 SOAP_FREE(soap, p->path);
6212 SOAP_FREE(soap, p);
6214 if (domain)
6215 SOAP_FREE(soap, domain);
6216 if (path)
6217 SOAP_FREE(soap, path);
6220 /******************************************************************************/
6221 SOAP_FMAC1
6223 SOAP_FMAC2
6224 soap_getenv_cookies(struct soap *soap)
6225 { struct soap_cookie *p;
6226 const char *s;
6227 char key[4096], val[4096]; /* cookie size is up to 4096 bytes [RFC2109] */
6228 if (!(s = getenv("HTTP_COOKIE")))
6229 return SOAP_ERR;
6231 { s = soap_decode_key(key, sizeof(key), s);
6232 s = soap_decode_val(val, sizeof(val), s);
6233 p = soap_set_cookie(soap, key, val, NULL, NULL);
6234 if (p)
6235 p->env = 1;
6236 } while (*s);
6237 return SOAP_OK;
6240 /******************************************************************************/
6241 SOAP_FMAC1
6242 struct soap_cookie*
6243 SOAP_FMAC2
6244 soap_copy_cookies(struct soap *copy, const struct soap *soap)
6245 { struct soap_cookie *p, **q, *r;
6246 q = &r;
6247 for (p = soap->cookies; p; p = p->next)
6248 { if (!(*q = (struct soap_cookie*)SOAP_MALLOC(copy, sizeof(struct soap_cookie))))
6249 return r;
6250 **q = *p;
6251 if (p->name)
6252 { if (((*q)->name = (char*)SOAP_MALLOC(copy, strlen(p->name)+1)))
6253 strcpy((*q)->name, p->name);
6255 if (p->value)
6256 { if (((*q)->value = (char*)SOAP_MALLOC(copy, strlen(p->value)+1)))
6257 strcpy((*q)->value, p->value);
6259 if (p->domain)
6260 { if (((*q)->domain = (char*)SOAP_MALLOC(copy, strlen(p->domain)+1)))
6261 strcpy((*q)->domain, p->domain);
6263 if (p->path)
6264 { if (((*q)->path = (char*)SOAP_MALLOC(copy, strlen(p->path)+1)))
6265 strcpy((*q)->path, p->path);
6267 q = &(*q)->next;
6269 *q = NULL;
6270 return r;
6273 /******************************************************************************/
6274 SOAP_FMAC1
6275 void
6276 SOAP_FMAC2
6277 soap_free_cookies(struct soap *soap)
6278 { struct soap_cookie *p;
6279 for (p = soap->cookies; p; p = soap->cookies)
6280 { soap->cookies = p->next;
6281 SOAP_FREE(soap, p->name);
6282 if (p->value)
6283 SOAP_FREE(soap, p->value);
6284 if (p->domain)
6285 SOAP_FREE(soap, p->domain);
6286 if (p->path)
6287 SOAP_FREE(soap, p->path);
6288 SOAP_FREE(soap, p);
6292 /******************************************************************************/
6293 #endif /* WITH_COOKIES */
6295 /******************************************************************************/
6296 #ifndef WITH_NOIDREF
6297 #ifndef PALM_2
6298 SOAP_FMAC1
6299 size_t
6300 SOAP_FMAC2
6301 soap_hash(register const char *s)
6302 { register size_t h = 0;
6303 while (*s)
6304 h = 65599*h + *s++;
6305 return h % SOAP_IDHASH;
6307 #endif
6308 #endif
6310 /******************************************************************************/
6311 #ifndef WITH_NOIDREF
6312 #ifndef PALM_1
6313 static void
6314 soap_init_pht(struct soap *soap)
6315 { register int i;
6316 soap->pblk = NULL;
6317 soap->pidx = 0;
6318 for (i = 0; i < (int)SOAP_PTRHASH; i++)
6319 soap->pht[i] = NULL;
6321 #endif
6322 #endif
6324 /******************************************************************************/
6325 #ifndef PALM_1
6326 SOAP_FMAC1
6327 struct soap*
6328 SOAP_FMAC2
6329 soap_new1(soap_mode mode)
6330 { return soap_new2(mode, mode);
6332 #endif
6334 /******************************************************************************/
6335 #ifndef PALM_1
6336 SOAP_FMAC1
6337 struct soap*
6338 SOAP_FMAC2
6339 soap_new()
6340 { return soap_new2(SOAP_IO_DEFAULT, SOAP_IO_DEFAULT);
6342 #endif
6344 /******************************************************************************/
6345 #ifndef PALM_1
6346 SOAP_FMAC1
6347 struct soap*
6348 SOAP_FMAC2
6349 soap_new2(soap_mode imode, soap_mode omode)
6350 { struct soap *soap = (struct soap*)malloc(sizeof(struct soap));
6351 if (soap)
6352 soap_init2(soap, imode, omode);
6353 return soap;
6355 #endif
6357 /******************************************************************************/
6358 #ifndef PALM_1
6359 SOAP_FMAC1
6360 void
6361 SOAP_FMAC2
6362 soap_free(struct soap *soap)
6363 { soap_done(soap);
6364 free(soap);
6366 #endif
6368 /******************************************************************************/
6369 #ifndef PALM_1
6370 SOAP_FMAC1
6371 void
6372 SOAP_FMAC2
6373 soap_del(struct soap *soap)
6374 { free(soap);
6376 #endif
6378 /******************************************************************************/
6379 #ifndef WITH_NOIDREF
6380 #ifndef PALM_1
6381 static void
6382 soap_free_pht(struct soap *soap)
6383 { register struct soap_pblk *pb, *next;
6384 register int i;
6385 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free pointer hashtable\n"));
6386 for (pb = soap->pblk; pb; pb = next)
6387 { next = pb->next;
6388 SOAP_FREE(soap, pb);
6390 soap->pblk = NULL;
6391 soap->pidx = 0;
6392 for (i = 0; i < (int)SOAP_PTRHASH; i++)
6393 soap->pht[i] = NULL;
6395 #endif
6396 #endif
6398 /******************************************************************************/
6399 #ifndef WITH_NOIDREF
6400 #ifndef PALM_2
6401 SOAP_FMAC1
6403 SOAP_FMAC2
6404 soap_embed(struct soap *soap, const void *p, const struct soap_array *a, int n, const char *tag, int type)
6405 { register int i;
6406 struct soap_plist *pp;
6407 if (soap->version == 2)
6408 soap->encoding = 1;
6409 if (a)
6410 i = soap_array_pointer_lookup(soap, p, a, n, type, &pp);
6411 else
6412 i = soap_pointer_lookup(soap, p, type, &pp);
6413 if (i)
6414 { if (soap_is_embedded(soap, pp)
6415 || soap_is_single(soap, pp))
6416 return 0;
6417 soap_set_embedded(soap, pp);
6419 return i;
6421 #endif
6422 #endif
6424 /******************************************************************************/
6425 #ifndef WITH_NOIDREF
6426 #ifndef PALM_2
6427 SOAP_FMAC1
6429 SOAP_FMAC2
6430 soap_pointer_lookup(struct soap *soap, const void *p, int type, struct soap_plist **ppp)
6431 { register struct soap_plist *pp;
6432 *ppp = NULL;
6433 if (p)
6434 { for (pp = soap->pht[soap_hash_ptr(p)]; pp; pp = pp->next)
6435 { if (pp->ptr == p && pp->type == type)
6436 { *ppp = pp;
6437 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d id=%d\n", p, type, pp->id));
6438 return pp->id;
6442 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d: not found\n", p, type));
6443 return 0;
6445 #endif
6446 #endif
6448 /******************************************************************************/
6449 #ifndef WITH_NOIDREF
6450 #ifndef PALM_2
6451 SOAP_FMAC1
6453 SOAP_FMAC2
6454 soap_pointer_enter(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp)
6455 { register size_t h;
6456 register struct soap_plist *pp;
6457 if (!soap->pblk || soap->pidx >= SOAP_PTRBLK)
6458 { register struct soap_pblk *pb = (struct soap_pblk*)SOAP_MALLOC(soap, sizeof(struct soap_pblk));
6459 if (!pb)
6460 { soap->error = SOAP_EOM;
6461 return 0;
6463 pb->next = soap->pblk;
6464 soap->pblk = pb;
6465 soap->pidx = 0;
6467 *ppp = pp = &soap->pblk->plist[soap->pidx++];
6468 if (a)
6469 h = soap_hash_ptr(a->__ptr);
6470 else
6471 h = soap_hash_ptr(p);
6472 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));
6473 pp->next = soap->pht[h];
6474 pp->type = type;
6475 pp->mark1 = 0;
6476 pp->mark2 = 0;
6477 pp->ptr = p;
6478 pp->array = a;
6479 soap->pht[h] = pp;
6480 pp->id = ++soap->idnum;
6481 return pp->id;
6483 #endif
6484 #endif
6486 /******************************************************************************/
6487 #ifndef WITH_NOIDREF
6488 #ifndef PALM_2
6489 SOAP_FMAC1
6491 SOAP_FMAC2
6492 soap_array_pointer_lookup(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp)
6493 { register struct soap_plist *pp;
6494 *ppp = NULL;
6495 if (!p || !a->__ptr)
6496 return 0;
6497 for (pp = soap->pht[soap_hash_ptr(a->__ptr)]; pp; pp = pp->next)
6498 { if (pp->type == type && pp->array && pp->array->__ptr == a->__ptr)
6499 { register int i;
6500 for (i = 0; i < n; i++)
6501 if (((const int*)&pp->array->__size)[i] != ((const int*)&a->__size)[i])
6502 break;
6503 if (i == n)
6504 { *ppp = pp;
6505 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d id=%d\n", a->__ptr, type, pp->id));
6506 return pp->id;
6510 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d: not found\n", a->__ptr, type));
6511 return 0;
6513 #endif
6514 #endif
6516 /******************************************************************************/
6517 #ifndef PALM_1
6518 SOAP_FMAC1
6520 SOAP_FMAC2
6521 soap_begin_count(struct soap *soap)
6522 { soap_free_ns(soap);
6523 #ifndef WITH_LEANER
6524 if ((soap->mode & SOAP_ENC_DIME) || (soap->omode & SOAP_ENC_DIME))
6525 soap->mode = soap->omode | SOAP_IO_LENGTH | SOAP_ENC_DIME;
6526 else
6527 #endif
6528 { soap->mode = soap->omode;
6529 if ((soap->mode & SOAP_IO_UDP))
6530 soap->mode |= SOAP_ENC_XML;
6531 if ((soap->mode & SOAP_IO) == SOAP_IO_STORE
6532 || (((soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_ENC_XML))
6533 #ifndef WITH_LEANER
6534 && !soap->fpreparesend
6535 #endif
6537 soap->mode &= ~SOAP_IO_LENGTH;
6538 else
6539 soap->mode |= SOAP_IO_LENGTH;
6541 #ifdef WITH_ZLIB
6542 if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH)
6543 { if (!(soap->mode & SOAP_ENC_DIME))
6544 soap->mode &= ~SOAP_IO_LENGTH;
6545 if (soap->mode & SOAP_ENC_XML)
6546 soap->mode |= SOAP_IO_BUFFER;
6547 else
6548 soap->mode |= SOAP_IO_STORE;
6550 #endif
6551 if (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH))
6552 soap->mode |= SOAP_XML_TREE;
6553 #ifndef WITH_LEANER
6554 if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME))
6555 soap->mode |= SOAP_ENC_MIME;
6556 else if (!(soap->mode & SOAP_ENC_MIME))
6557 soap->mode &= ~SOAP_ENC_MTOM;
6558 if (soap->mode & SOAP_ENC_MIME)
6559 soap_select_mime_boundary(soap);
6560 soap->dime.list = soap->dime.last; /* keep track of last DIME attachment */
6561 #endif
6562 soap->count = 0;
6563 soap->ns = 0;
6564 soap->null = 0;
6565 soap->position = 0;
6566 soap->mustUnderstand = 0;
6567 soap->encoding = 0;
6568 soap->part = SOAP_BEGIN;
6569 soap->idnum = 0;
6570 soap_clr_attr(soap);
6571 soap_set_local_namespaces(soap);
6572 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));
6573 #ifndef WITH_LEANER
6574 soap->dime.count = 0; /* count # of attachments */
6575 soap->dime.size = 0; /* accumulate total size of attachments */
6576 if (soap->fprepareinitsend && (soap->mode & SOAP_IO) != SOAP_IO_STORE)
6577 return soap->error = soap->fprepareinitsend(soap);
6578 #endif
6579 return SOAP_OK;
6581 #endif
6583 /******************************************************************************/
6584 #ifndef PALM_1
6585 SOAP_FMAC1
6587 SOAP_FMAC2
6588 soap_end_count(struct soap *soap)
6589 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of count phase\n"));
6590 #ifndef WITH_LEANER
6591 if (soap->fpreparefinalsend && (soap->mode & SOAP_IO_LENGTH))
6592 return soap->error = soap->fpreparefinalsend(soap);
6593 #endif
6594 return SOAP_OK;
6596 #endif
6598 /******************************************************************************/
6599 #ifndef PALM_1
6600 SOAP_FMAC1
6602 SOAP_FMAC2
6603 soap_begin_send(struct soap *soap)
6604 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing for output\n"));
6605 soap_free_ns(soap);
6606 soap->error = SOAP_OK;
6607 soap->mode = soap->omode | (soap->mode & (SOAP_IO_LENGTH | SOAP_ENC_DIME));
6608 #ifdef WITH_ZLIB
6609 if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH)
6610 { if (soap->mode & SOAP_ENC_XML)
6611 soap->mode |= SOAP_IO_BUFFER;
6612 else
6613 soap->mode |= SOAP_IO_STORE;
6615 #endif
6616 #ifndef WITH_LEAN
6617 if ((soap->mode & SOAP_IO_UDP))
6618 { soap->mode |= SOAP_ENC_XML;
6619 if (soap->count > SOAP_BUFLEN)
6620 return soap->error = SOAP_UDP_ERROR;
6622 #endif
6623 if ((soap->mode & SOAP_IO) == SOAP_IO_FLUSH && soap_valid_socket(soap->socket))
6624 { if (soap->count || (soap->mode & SOAP_IO_LENGTH) || (soap->mode & SOAP_ENC_XML))
6625 soap->mode |= SOAP_IO_BUFFER;
6626 else
6627 soap->mode |= SOAP_IO_STORE;
6629 soap->mode &= ~SOAP_IO_LENGTH;
6630 if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
6631 if (soap_new_block(soap) == NULL)
6632 return soap->error;
6633 if (!(soap->mode & SOAP_IO_KEEPALIVE))
6634 soap->keep_alive = 0;
6635 if (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH))
6636 soap->mode |= SOAP_XML_TREE;
6637 #ifndef WITH_LEANER
6638 if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME))
6639 { soap->mode |= SOAP_ENC_MIME;
6640 soap->mode &= ~SOAP_ENC_DIME;
6642 else if (!(soap->mode & SOAP_ENC_MIME))
6643 soap->mode &= ~SOAP_ENC_MTOM;
6644 if (soap->mode & SOAP_ENC_MIME)
6645 soap_select_mime_boundary(soap);
6646 #ifdef WIN32
6647 #ifndef UNDER_CE
6648 #ifndef WITH_FASTCGI
6649 if (!soap_valid_socket(soap->socket)) /* Set win32 stdout or soap->sendfd to BINARY, e.g. to support DIME */
6650 #ifdef __BORLANDC__
6651 setmode(soap->sendfd, _O_BINARY);
6652 #else
6653 _setmode(soap->sendfd, _O_BINARY);
6654 #endif
6655 #endif
6656 #endif
6657 #endif
6658 #endif
6659 if (soap->mode & SOAP_IO)
6660 { soap->bufidx = 0;
6661 soap->buflen = 0;
6663 soap->chunksize = 0;
6664 soap->ns = 0;
6665 soap->null = 0;
6666 soap->position = 0;
6667 soap->mustUnderstand = 0;
6668 soap->encoding = 0;
6669 soap->idnum = 0;
6670 soap->level = 0;
6671 soap_clr_attr(soap);
6672 soap_set_local_namespaces(soap);
6673 #ifdef WITH_ZLIB
6674 soap->z_ratio_out = 1.0;
6675 if ((soap->mode & SOAP_ENC_ZLIB) && soap->zlib_state != SOAP_ZLIB_DEFLATE)
6676 { if (!soap->z_buf)
6677 soap->z_buf = (char*)SOAP_MALLOC(soap, SOAP_BUFLEN);
6678 soap->d_stream->next_out = (Byte*)soap->z_buf;
6679 soap->d_stream->avail_out = SOAP_BUFLEN;
6680 #ifdef WITH_GZIP
6681 if (soap->zlib_out != SOAP_ZLIB_DEFLATE)
6682 { memcpy(soap->z_buf, "\37\213\10\0\0\0\0\0\0\377", 10);
6683 soap->d_stream->next_out = (Byte*)soap->z_buf + 10;
6684 soap->d_stream->avail_out = SOAP_BUFLEN - 10;
6685 soap->z_crc = crc32(0L, NULL, 0);
6686 soap->zlib_out = SOAP_ZLIB_GZIP;
6687 if (soap->z_dict)
6688 *((Byte*)soap->z_buf + 2) = 0xff;
6689 if (deflateInit2(soap->d_stream, soap->z_level, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY) != Z_OK)
6690 return soap->error = SOAP_ZLIB_ERROR;
6692 else
6693 #endif
6694 if (deflateInit(soap->d_stream, soap->z_level) != Z_OK)
6695 return soap->error = SOAP_ZLIB_ERROR;
6696 if (soap->z_dict)
6697 { if (deflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len) != Z_OK)
6698 return soap->error = SOAP_ZLIB_ERROR;
6700 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflate initialized\n"));
6701 soap->zlib_state = SOAP_ZLIB_DEFLATE;
6703 #endif
6704 #ifdef WITH_OPENSSL
6705 if (soap->ssl)
6706 ERR_clear_error();
6707 #endif
6708 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin send phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count));
6709 soap->part = SOAP_BEGIN;
6710 #ifndef WITH_LEANER
6711 if (soap->fprepareinitsend && (soap->mode & SOAP_IO) == SOAP_IO_STORE)
6712 soap->fprepareinitsend(soap);
6713 #endif
6714 return SOAP_OK;
6716 #endif
6718 /******************************************************************************/
6719 #ifndef WITH_NOIDREF
6720 #ifndef PALM_2
6721 SOAP_FMAC1
6722 void
6723 SOAP_FMAC2
6724 soap_embedded(struct soap *soap, const void *p, int t)
6725 { struct soap_plist *pp;
6726 if (soap_pointer_lookup(soap, p, t, &pp))
6727 { pp->mark1 = 1;
6728 pp->mark2 = 1;
6729 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded %p type=%d mark set to 1\n", p, t));
6732 #endif
6733 #endif
6735 /******************************************************************************/
6736 #ifndef WITH_NOIDREF
6737 #ifndef PALM_2
6738 SOAP_FMAC1
6740 SOAP_FMAC2
6741 soap_reference(struct soap *soap, const void *p, int t)
6742 { struct soap_plist *pp;
6743 if (!p || (soap->mode & SOAP_XML_TREE))
6744 return 1;
6745 if (soap_pointer_lookup(soap, p, t, &pp))
6746 { if (pp->mark1 == 0)
6747 { pp->mark1 = 2;
6748 pp->mark2 = 2;
6751 else if (soap_pointer_enter(soap, p, NULL, 0, t, &pp))
6752 { pp->mark1 = 0;
6753 pp->mark2 = 0;
6755 else
6756 return 1;
6757 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reference %p type=%d (%d %d)\n", p, t, (int)pp->mark1, (int)pp->mark2));
6758 return pp->mark1;
6760 #endif
6761 #endif
6763 /******************************************************************************/
6764 #ifndef WITH_NOIDREF
6765 #ifndef PALM_2
6766 SOAP_FMAC1
6768 SOAP_FMAC2
6769 soap_array_reference(struct soap *soap, const void *p, const struct soap_array *a, int n, int t)
6770 { register int i;
6771 struct soap_plist *pp;
6772 if (!p || !a->__ptr)
6773 return 1;
6774 i = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
6775 if (i)
6776 { if (pp->mark1 == 0)
6777 { pp->mark1 = 2;
6778 pp->mark2 = 2;
6781 else if (!soap_pointer_enter(soap, p, a, n, t, &pp))
6782 return 1;
6783 else
6784 { pp->mark1 = 0;
6785 pp->mark2 = 0;
6787 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));
6788 return pp->mark1;
6790 #endif
6791 #endif
6793 /******************************************************************************/
6794 #ifndef WITH_NOIDREF
6795 #ifndef PALM_2
6796 SOAP_FMAC1
6798 SOAP_FMAC2
6799 soap_embedded_id(struct soap *soap, int id, const void *p, int t)
6800 { struct soap_plist *pp = NULL;
6801 if (soap->mode & SOAP_XML_TREE)
6802 return id;
6803 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id %p type=%d id=%d\n", p, t, id));
6804 if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER)
6805 { if (id < 0)
6806 { id = soap_pointer_lookup(soap, p, t, &pp);
6807 if (id)
6808 { if (soap->mode & SOAP_IO_LENGTH)
6809 pp->mark1 = 2;
6810 else
6811 pp->mark2 = 2;
6812 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));
6814 return -1;
6816 return id;
6818 if (id < 0)
6819 id = soap_pointer_lookup(soap, p, t, &pp);
6820 else if (id && !soap_pointer_lookup(soap, p, t, &pp))
6821 return 0;
6822 if (id && pp)
6823 { if (soap->mode & SOAP_IO_LENGTH)
6824 pp->mark1 = 1;
6825 else
6826 pp->mark2 = 1;
6827 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));
6829 return id;
6831 #endif
6832 #endif
6834 /******************************************************************************/
6835 #ifndef WITH_NOIDREF
6836 #ifndef PALM_2
6837 SOAP_FMAC1
6839 SOAP_FMAC2
6840 soap_is_embedded(struct soap *soap, struct soap_plist *pp)
6841 { if (!pp)
6842 return 0;
6843 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Is embedded? %d %d\n", (int)pp->mark1, (int)pp->mark2));
6844 if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER)
6845 { if (soap->mode & SOAP_IO_LENGTH)
6846 return pp->mark1 != 0;
6847 return pp->mark2 != 0;
6849 if (soap->mode & SOAP_IO_LENGTH)
6850 return pp->mark1 == 1;
6851 return pp->mark2 == 1;
6853 #endif
6854 #endif
6856 /******************************************************************************/
6857 #ifndef WITH_NOIDREF
6858 #ifndef PALM_2
6859 SOAP_FMAC1
6861 SOAP_FMAC2
6862 soap_is_single(struct soap *soap, struct soap_plist *pp)
6863 { if (soap->part == SOAP_IN_HEADER)
6864 return 1;
6865 if (!pp)
6866 return 0;
6867 if (soap->mode & SOAP_IO_LENGTH)
6868 return pp->mark1 == 0;
6869 return pp->mark2 == 0;
6871 #endif
6872 #endif
6874 /******************************************************************************/
6875 #ifndef WITH_NOIDREF
6876 #ifndef PALM_2
6877 SOAP_FMAC1
6878 void
6879 SOAP_FMAC2
6880 soap_set_embedded(struct soap *soap, struct soap_plist *pp)
6881 { if (!pp)
6882 return;
6883 if (soap->mode & SOAP_IO_LENGTH)
6884 pp->mark1 = 1;
6885 else
6886 pp->mark2 = 1;
6888 #endif
6889 #endif
6891 /******************************************************************************/
6892 #ifndef WITH_LEANER
6893 #ifndef PALM_1
6894 SOAP_FMAC1
6896 SOAP_FMAC2
6897 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)
6899 #ifndef WITH_NOIDREF
6900 struct soap_plist *pp = NULL; /* Oracle customization */
6901 int i;
6902 if (!p || !a->__ptr || (!aid && !atype))
6903 return soap_element_id(soap, tag, id, p, a, n, type, t);
6904 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));
6905 i = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
6906 if (!i)
6907 { i = soap_pointer_enter(soap, p, a, n, t, &pp);
6908 if (!i)
6909 { soap->error = SOAP_EOM;
6910 return -1;
6913 if (id <= 0)
6914 id = i;
6915 if (!aid)
6916 { sprintf(soap->tmpbuf, soap->dime_id_format, id);
6917 aid = soap_strdup(soap, soap->tmpbuf);
6919 /* Add MTOM xop:Include element when necessary */
6920 /* TODO: this code to be obsoleted with new import/xop.h conventions */
6921 if ((soap->mode & SOAP_ENC_MTOM) && strcmp(tag, "xop:Include"))
6922 { if (soap_element_begin_out(soap, tag, 0, type)
6923 || soap_element_href(soap, "xop:Include", 0, "xmlns:xop=\"http://www.w3.org/2004/08/xop/include\" href", aid)
6924 || soap_element_end_out(soap, tag))
6925 return soap->error;
6927 else if (soap_element_href(soap, tag, 0, "href", aid))
6928 return soap->error;
6929 if (soap->mode & SOAP_IO_LENGTH)
6930 { if (pp && (pp->mark1 != 3)) /* Oracle customization */
6931 { struct soap_multipart *content;
6932 if (soap->mode & SOAP_ENC_MTOM)
6933 content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, (char*)a->__ptr, a->__size);
6934 else
6935 content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, (char*)a->__ptr, a->__size);
6936 if (!content)
6937 { soap->error = SOAP_EOM;
6938 return -1;
6940 if (!strncmp(aid, "cid:", 4)) /* RFC 2111 */
6941 { if (soap->mode & SOAP_ENC_MTOM)
6942 { char *s = (char*)soap_malloc(soap, strlen(aid) - 1);
6943 if (s)
6944 { *s = '<';
6945 strcpy(s + 1, aid + 4);
6946 strcat(s, ">");
6947 content->id = s;
6950 else
6951 content->id = aid + 4;
6953 else
6954 content->id = aid;
6955 content->type = atype;
6956 content->options = aoptions;
6957 content->encoding = SOAP_MIME_BINARY;
6958 pp->mark1 = 3;
6961 else if (pp) /* Oracle customization */
6962 pp->mark2 = 3;
6963 #endif
6964 return -1;
6966 #endif
6967 #endif
6969 /******************************************************************************/
6970 #ifndef WITH_NOIDREF
6971 #ifndef PALM_1
6972 static void
6973 soap_init_iht(struct soap *soap)
6974 { register int i;
6975 for (i = 0; i < SOAP_IDHASH; i++)
6976 soap->iht[i] = NULL;
6978 #endif
6979 #endif
6981 /******************************************************************************/
6982 #ifndef WITH_NOIDREF
6983 #ifndef PALM_1
6984 static void
6985 soap_free_iht(struct soap *soap)
6986 { register int i;
6987 register struct soap_ilist *ip = NULL, *p = NULL;
6988 register struct soap_flist *fp = NULL, *fq = NULL;
6989 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free ID hashtable\n"));
6990 for (i = 0; i < SOAP_IDHASH; i++)
6991 { for (ip = soap->iht[i]; ip; ip = p)
6992 { for (fp = ip->flist; fp; fp = fq)
6993 { fq = fp->next;
6994 SOAP_FREE(soap, fp);
6996 p = ip->next;
6997 SOAP_FREE(soap, ip);
6999 soap->iht[i] = NULL;
7002 #endif
7003 #endif
7005 /******************************************************************************/
7006 #ifndef WITH_NOIDREF
7007 #ifndef PALM_2
7008 SOAP_FMAC1
7009 struct soap_ilist *
7010 SOAP_FMAC2
7011 soap_lookup(struct soap *soap, const char *id)
7012 { register struct soap_ilist *ip = NULL;
7013 for (ip = soap->iht[soap_hash(id)]; ip; ip = ip->next)
7014 if (!strcmp(ip->id, id))
7015 return ip;
7016 return NULL;
7018 #endif
7019 #endif
7021 /******************************************************************************/
7022 #ifndef WITH_NOIDREF
7023 #ifndef PALM_2
7024 SOAP_FMAC1
7025 struct soap_ilist *
7026 SOAP_FMAC2
7027 soap_enter(struct soap *soap, const char *id)
7028 { register size_t h;
7029 register struct soap_ilist *ip;
7030 ip = (struct soap_ilist*)SOAP_MALLOC(soap, sizeof(struct soap_ilist) + strlen(id));
7031 if (ip)
7032 { h = soap_hash(id);
7033 strcpy(ip->id, id);
7034 ip->next = soap->iht[h];
7035 soap->iht[h] = ip;
7037 return ip;
7039 #endif
7040 #endif
7042 /******************************************************************************/
7043 #ifndef PALM_2
7044 SOAP_FMAC1
7045 void*
7046 SOAP_FMAC2
7047 soap_malloc(struct soap *soap, size_t n)
7048 { register char *p;
7049 if (!n)
7050 return (void*)SOAP_NON_NULL;
7051 if (!soap)
7052 return SOAP_MALLOC(soap, n);
7053 if (soap->fmalloc)
7054 p = (char*)soap->fmalloc(soap, n);
7055 else
7056 { n += sizeof(short);
7057 n += (-(long)n) & (sizeof(void*)-1); /* align at 4-, 8- or 16-byte boundary */
7058 if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(void*) + sizeof(size_t))))
7059 { soap->error = SOAP_EOM;
7060 return NULL;
7062 /* set the canary to detect corruption */
7063 *(unsigned short*)(p + n - sizeof(unsigned short)) = (unsigned short)SOAP_CANARY;
7064 /* keep chain of alloced cells for destruction */
7065 *(void**)(p + n) = soap->alist;
7066 *(size_t*)(p + n + sizeof(void*)) = n;
7067 soap->alist = p + n;
7069 soap->alloced = 1;
7070 return p;
7072 #endif
7074 /******************************************************************************/
7075 #ifdef SOAP_MEM_DEBUG
7076 static void
7077 soap_init_mht(struct soap *soap)
7078 { register int i;
7079 for (i = 0; i < (int)SOAP_PTRHASH; i++)
7080 soap->mht[i] = NULL;
7082 #endif
7084 /******************************************************************************/
7085 #ifdef SOAP_MEM_DEBUG
7086 static void
7087 soap_free_mht(struct soap *soap)
7088 { register int i;
7089 register struct soap_mlist *mp, *mq;
7090 for (i = 0; i < (int)SOAP_PTRHASH; i++)
7091 { for (mp = soap->mht[i]; mp; mp = mq)
7092 { mq = mp->next;
7093 if (mp->live)
7095 fprintf(stderr, "%s(%d): malloc() = %p not freed (memory leak or forgot to call soap_end()?)\n", mp->file, mp->line, mp->ptr);
7096 #ifndef WIN32
7097 (void) printstack( 2 ); /* Oracle customization */
7098 #endif
7100 free(mp);
7102 soap->mht[i] = NULL;
7105 #endif
7107 /******************************************************************************/
7108 #ifdef SOAP_MEM_DEBUG
7109 SOAP_FMAC1
7110 void*
7111 SOAP_FMAC2
7112 soap_track_malloc(struct soap *soap, const char *file, int line, size_t size)
7113 { register void *p = malloc(size);
7114 if (soap)
7115 { register size_t h = soap_hash_ptr(p);
7116 register struct soap_mlist *mp = (struct soap_mlist*)malloc(sizeof(struct soap_mlist));
7117 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): malloc(%lu) = %p\n", file, line, (unsigned long)size, p));
7118 mp->next = soap->mht[h];
7119 mp->ptr = p;
7120 mp->file = file;
7121 mp->line = line;
7122 mp->live = 1;
7123 soap->mht[h] = mp;
7125 return p;
7127 #endif
7129 /******************************************************************************/
7130 #ifdef SOAP_MEM_DEBUG
7131 SOAP_FMAC1
7132 void
7133 SOAP_FMAC2
7134 soap_track_free(struct soap *soap, const char *file, int line, void *p)
7135 { register size_t h = soap_hash_ptr(p);
7136 register struct soap_mlist *mp;
7137 for (mp = soap->mht[h]; mp; mp = mp->next)
7138 if (mp->ptr == p)
7139 break;
7140 if (mp)
7141 { if (mp->live)
7142 { free(p);
7143 if (soap->fdebug[SOAP_INDEX_TEST])
7144 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): free(%p)\n", file, line, p));
7146 mp->live = 0;
7148 else
7149 fprintf(stderr, "%s(%d): free(%p) double free of pointer malloced at %s(%d)\n", file, line, p, mp->file, mp->line);
7151 else
7152 fprintf(stderr, "%s(%d): free(%p) pointer not malloced\n", file, line, p);
7154 #endif
7156 /******************************************************************************/
7157 #ifdef SOAP_MEM_DEBUG
7158 static void
7159 soap_track_unlink(struct soap *soap, const void *p)
7160 { register size_t h = soap_hash_ptr(p);
7161 register struct soap_mlist *mp;
7162 for (mp = soap->mht[h]; mp; mp = mp->next)
7163 if (mp->ptr == p)
7164 break;
7165 if (mp)
7166 mp->live = 0;
7168 #endif
7170 /******************************************************************************/
7171 #ifndef PALM_2
7172 SOAP_FMAC1
7173 void
7174 SOAP_FMAC2
7175 soap_dealloc(struct soap *soap, void *p)
7176 { if (soap_check_state(soap))
7177 return;
7178 if (p)
7179 { register char **q;
7180 for (q = (char**)&soap->alist; *q; q = *(char***)q)
7182 if (*(unsigned short*)(char*)(*q - sizeof(unsigned short)) != (unsigned short)SOAP_CANARY)
7184 #ifdef SOAP_MEM_DEBUG
7185 fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n");
7186 #endif
7187 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n"));
7188 DBGHEX(TEST, *q - 200, 200);
7189 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n"));
7190 soap->error = SOAP_MOE;
7191 return;
7193 if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*))))
7194 { *q = **(char***)q;
7195 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Freed data at %p\n", p));
7196 SOAP_FREE(soap, p);
7197 return;
7200 soap_delete(soap, p);
7202 else
7203 { register char *q;
7204 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free all soap_malloc() data\n"));
7205 while (soap->alist)
7206 { q = (char*)soap->alist;
7207 if (*(unsigned short*)(char*)(q - sizeof(unsigned short)) != (unsigned short)SOAP_CANARY)
7209 #ifdef SOAP_MEM_DEBUG
7210 fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n");
7211 #endif
7212 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n"));
7213 DBGHEX(TEST, q - 200, 200);
7214 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n"));
7215 soap->error = SOAP_MOE;
7216 return;
7218 soap->alist = *(void**)q;
7219 q -= *(size_t*)(q + sizeof(void*));
7220 SOAP_FREE(soap, q);
7222 /* we must assume these were deallocated: */
7223 soap->action = NULL;
7224 soap->fault = NULL;
7225 soap->header = NULL;
7226 soap->userid = NULL;
7227 soap->passwd = NULL;
7228 soap->authrealm = NULL;
7229 soap->http_content = NULL;
7230 #ifndef WITH_LEANER
7231 soap_clr_mime(soap);
7232 #endif
7235 #endif
7237 /******************************************************************************/
7238 #ifndef PALM_2
7239 SOAP_FMAC1
7240 void
7241 SOAP_FMAC2
7242 soap_delete(struct soap *soap, void *p)
7243 { register struct soap_clist **cp;
7244 if (soap_check_state(soap))
7245 return;
7246 cp = &soap->clist;
7247 if (p)
7248 { while (*cp)
7249 { if (p == (*cp)->ptr)
7250 { register struct soap_clist *q = *cp;
7251 *cp = q->next;
7252 if (q->fdelete(q))
7253 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: deletion callback failed for object type %d\n", q->ptr, q->type));
7254 #ifdef SOAP_MEM_DEBUG
7255 fprintf(stderr, "new(object type = %d) = %p not freed: deletion callback failed\n", q->type, q->ptr);
7256 #endif
7258 SOAP_FREE(soap, q);
7259 return;
7261 cp = &(*cp)->next;
7263 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: address not in list\n", p));
7265 else
7266 { while (*cp)
7267 { register struct soap_clist *q = *cp;
7268 *cp = q->next;
7269 if (q->fdelete(q))
7270 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: deletion callback failed for object type %d\n", q->ptr, q->type));
7271 #ifdef SOAP_MEM_DEBUG
7272 fprintf(stderr, "new(object type = %d) = %p not freed: deletion callback failed\n", q->type, q->ptr);
7273 #endif
7275 SOAP_FREE(soap, q);
7278 soap->fault = NULL; /* this was possibly deallocated */
7279 soap->header = NULL; /* this was possibly deallocated */
7281 #endif
7283 /******************************************************************************/
7284 #ifndef PALM_2
7285 SOAP_FMAC1
7286 void
7287 SOAP_FMAC2
7288 soap_delegate_deletion(struct soap *soap, struct soap *soap_to)
7289 { register struct soap_clist *cp;
7290 register char **q;
7291 #ifdef SOAP_MEM_DEBUG
7292 register void *p;
7293 register struct soap_mlist **mp, *mq;
7294 size_t h;
7295 #endif
7296 for (q = (char**)&soap->alist; *q; q = *(char***)q)
7298 if (*(unsigned short*)(char*)(*q - sizeof(unsigned short)) != (unsigned short)SOAP_CANARY)
7300 #ifdef SOAP_MEM_DEBUG
7301 fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n");
7302 #endif
7303 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n"));
7304 DBGHEX(TEST, *q - 200, 200);
7305 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n"));
7306 soap->error = SOAP_MOE;
7307 return;
7309 #ifdef SOAP_MEM_DEBUG
7310 p = (void*)(*q - *(size_t*)(*q + sizeof(void*)));
7311 h = soap_hash_ptr(p);
7312 for (mp = &soap->mht[h]; *mp; mp = &(*mp)->next)
7313 { if ((*mp)->ptr == p)
7314 { mq = *mp;
7315 *mp = mq->next;
7316 mq->next = soap_to->mht[h];
7317 soap_to->mht[h] = mq;
7318 break;
7321 #endif
7323 *q = (char*)soap_to->alist;
7324 soap_to->alist = soap->alist;
7325 soap->alist = NULL;
7326 cp = soap_to->clist;
7327 if (cp)
7328 { while (cp->next)
7329 cp = cp->next;
7330 cp->next = soap->clist;
7332 else
7333 soap_to->clist = soap->clist;
7334 soap->clist = NULL;
7336 #endif
7338 /******************************************************************************/
7339 #ifndef PALM_2
7340 SOAP_FMAC1
7341 struct soap_clist *
7342 SOAP_FMAC2
7343 soap_link(struct soap *soap, void *p, int t, int n, int (*fdelete)(struct soap_clist*))
7344 { register struct soap_clist *cp;
7345 if ((cp = (struct soap_clist*)SOAP_MALLOC(soap, sizeof(struct soap_clist))))
7346 { cp->next = soap->clist;
7347 cp->type = t;
7348 cp->size = n;
7349 cp->ptr = p;
7350 cp->fdelete = fdelete;
7351 soap->clist = cp;
7353 return cp;
7355 #endif
7357 /******************************************************************************/
7358 #ifndef PALM_2
7359 SOAP_FMAC1
7360 void
7361 SOAP_FMAC2
7362 soap_unlink(struct soap *soap, const void *p)
7363 { register char **q;
7364 register struct soap_clist **cp;
7365 if (!soap || !p)
7366 return;
7367 for (q = (char**)&soap->alist; *q; q = *(char***)q)
7368 { if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*))))
7369 { *q = **(char***)q;
7370 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked data %p\n", p));
7371 #ifdef SOAP_MEM_DEBUG
7372 soap_track_unlink(soap, p);
7373 #endif
7374 return;
7377 for (cp = &soap->clist; *cp; cp = &(*cp)->next)
7378 { if (p == (*cp)->ptr)
7379 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked class instance %p\n", p));
7380 q = (char**)*cp;
7381 *cp = (*cp)->next;
7382 SOAP_FREE(soap, q);
7383 return;
7387 #endif
7389 /******************************************************************************/
7390 #ifndef WITH_NOIDREF
7391 #ifndef PALM_2
7392 SOAP_FMAC1
7394 SOAP_FMAC2
7395 soap_lookup_type(struct soap *soap, const char *id)
7396 { register struct soap_ilist *ip;
7397 if (id && *id)
7398 { ip = soap_lookup(soap, id);
7399 if (ip)
7400 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup id='%s' type=%d\n", id, ip->type));
7401 return ip->type;
7404 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "lookup type id='%s' NOT FOUND! Need to get it from xsi:type\n", id));
7405 return 0;
7407 #endif
7408 #endif
7410 /******************************************************************************/
7411 #ifndef WITH_NOIDREF
7412 #ifndef PALM_2
7413 SOAP_FMAC1
7414 void*
7415 SOAP_FMAC2
7416 soap_id_lookup(struct soap *soap, const char *id, void **p, int t, size_t n, unsigned int k)
7417 { struct soap_ilist *ip;
7418 void **q;
7419 if (!p || !id || !*id)
7420 return p;
7421 ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */
7422 if (!ip)
7423 { if (!(ip = soap_enter(soap, id))) /* new hash table entry for string id */
7424 return NULL;
7425 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding first href='%s' type=%d %p (%u bytes)\n", id, t, p, (unsigned int)n));
7426 ip->type = t;
7427 ip->size = n;
7428 ip->link = p;
7429 ip->copy = NULL;
7430 ip->flist = NULL;
7431 ip->ptr = NULL;
7432 ip->level = k;
7433 *p = NULL;
7435 else if (ip->ptr)
7436 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolved href='%s' type=%d location=%p (%u bytes)\n", id, t, ip->ptr, (unsigned int)n));
7437 if (ip->type != t)
7439 /* Oracle customization */
7440 strncpy(soap->id, id, sizeof(soap->id) - 1);
7441 soap->id[sizeof(soap->id) - 1] = '\0';
7442 soap->error = SOAP_HREF;
7443 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility: href='%s' id-type=%d href-type=%d\n", id, ip->type, t));
7444 return NULL;
7446 while (ip->level < k)
7447 { q = (void**)soap_malloc(soap, sizeof(void*));
7448 if (!q)
7449 return NULL;
7450 *p = (void*)q;
7451 p = q;
7452 k--;
7453 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n"));
7455 *p = ip->ptr;
7457 else if (ip->level > k)
7458 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving level %u pointers to href='%s'\n", ip->level, id));
7459 while (ip->level > k)
7460 { void *s, **r = &ip->link;
7461 q = (void**)ip->link;
7462 while (q)
7463 { *r = (void*)soap_malloc(soap, sizeof(void*));
7464 if (!*r)
7465 return NULL;
7466 s = *q;
7467 *q = *r;
7468 r = (void**)*r;
7469 q = (void**)s;
7471 *r = NULL;
7472 ip->size = n;
7473 ip->copy = NULL;
7474 ip->level = ip->level - 1;
7475 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n"));
7477 q = (void**)ip->link;
7478 ip->link = p;
7479 *p = (void*)q;
7481 else
7482 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarded href='%s' type=%d location=%p (%u bytes)\n", id, t, p, (unsigned int)n));
7483 while (ip->level < k)
7484 { q = (void**)soap_malloc(soap, sizeof(void*));
7485 if (!q)
7486 return NULL;
7487 *p = q;
7488 p = q;
7489 k--;
7490 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n"));
7492 q = (void**)ip->link;
7493 ip->link = p;
7494 *p = (void*)q;
7496 return p;
7498 #endif
7499 #endif
7501 /******************************************************************************/
7502 #ifndef WITH_NOIDREF
7503 #ifndef PALM_2
7504 SOAP_FMAC1
7505 void*
7506 SOAP_FMAC2
7507 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))
7508 { struct soap_ilist *ip;
7509 if (!p || !href || !*href)
7510 return p;
7511 ip = soap_lookup(soap, href); /* lookup pointer to hash table entry for string id */
7512 if (!ip)
7513 { if (!(ip = soap_enter(soap, href))) /* new hash table entry for string id */
7514 return NULL;
7515 ip->type = st;
7516 ip->size = n;
7517 ip->link = NULL;
7518 ip->copy = NULL;
7519 ip->ptr = NULL;
7520 ip->level = 0;
7521 ip->flist = NULL;
7522 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));
7524 else if (ip->type != st || (ip->level == k && ip->size != n))
7525 { 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));
7526 /* Oracle customization */
7527 strncpy(soap->id, href, sizeof(soap->id) - 1);
7528 soap->id[sizeof(soap->id) - 1] = '\0';
7529 soap->error = SOAP_HREF;
7530 return NULL;
7532 if (fcopy || n < sizeof(void*) || *href != '#')
7533 { register struct soap_flist *fp = (struct soap_flist*)SOAP_MALLOC(soap, sizeof(struct soap_flist));
7534 if (!fp)
7535 { soap->error = SOAP_EOM;
7536 return NULL;
7538 fp->next = ip->flist;
7539 fp->type = tt;
7540 fp->ptr = p;
7541 fp->level = k;
7542 fp->len = len;
7543 if (fcopy)
7544 fp->fcopy = fcopy;
7545 else
7546 fp->fcopy = soap_fcopy;
7547 ip->flist = fp;
7548 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));
7550 else
7551 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding copying address %p for type=%d href='%s'\n", p, st, href));
7552 *(void**)p = ip->copy;
7553 ip->copy = p;
7555 return p;
7557 #endif
7558 #endif
7560 /******************************************************************************/
7561 #ifndef PALM_2
7562 SOAP_FMAC1
7563 void*
7564 SOAP_FMAC2
7565 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*))
7567 #ifndef WITH_NOIDREF
7568 struct soap_ilist *ip;
7569 #endif
7570 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Enter id='%s' type=%d loc=%p size=%lu level=%u\n", id, t, p, (unsigned long)n, k));
7571 soap->alloced = 0;
7572 if (!p)
7573 { if (finstantiate)
7574 p = finstantiate(soap, t, type, arrayType, &n);
7575 else
7576 p = soap_malloc(soap, n);
7577 if (p)
7578 soap->alloced = 1;
7580 #ifndef WITH_NOIDREF
7581 if (!id || !*id)
7582 #endif
7583 return p;
7584 #ifndef WITH_NOIDREF
7585 ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */
7586 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Lookup entry id='%s for location=%p'\n", id, p));
7587 if (!ip)
7588 { if (!(ip = soap_enter(soap, id))) /* new hash table entry for string id */
7589 return NULL;
7590 ip->type = t;
7591 ip->link = NULL;
7592 ip->copy = NULL;
7593 ip->flist = NULL;
7594 ip->size = n;
7595 ip->ptr = p;
7596 ip->level = k;
7597 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));
7599 else if ((ip->type != t || (ip->level == k && ip->size != n)) && (ip->copy || ip->flist))
7600 { 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));
7601 /* Oracle customization */
7602 strncpy(soap->id, id, sizeof(soap->id) - 1);
7603 soap->id[sizeof(soap->id) - 1] = '\0';
7604 soap->error = SOAP_HREF;
7605 return NULL;
7607 else if (ip->ptr)
7608 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Multiply defined id='%s'\n", id));
7609 /* Oracle customization */
7610 strncpy(soap->id, id, sizeof(soap->id) - 1);
7611 soap->id[sizeof(soap->id) - 1] = '\0';
7612 soap->error = SOAP_DUPLICATE_ID;
7613 return NULL;
7615 else
7616 { ip->size = n;
7617 ip->ptr = p;
7618 ip->level = k;
7619 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));
7621 return ip->ptr;
7622 #endif
7624 #endif
7626 /******************************************************************************/
7627 #ifndef PALM_2
7628 SOAP_FMAC1
7629 void
7630 SOAP_FMAC2
7631 soap_fcopy(struct soap *soap, int st, int tt, void *p, size_t len, const void *q, size_t n)
7632 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Copying data type=%d (target type=%d) %p -> %p (%lu bytes)\n", st, tt, q, p, (unsigned long)n));
7633 memcpy(p, q, n);
7635 #endif
7637 /******************************************************************************/
7638 #ifndef PALM_1
7639 SOAP_FMAC1
7641 SOAP_FMAC2
7642 soap_end_send(struct soap *soap)
7644 #ifndef WITH_LEANER
7645 int err;
7646 if (soap->dime.list)
7647 { /* SOAP body referenced attachments must appear first */
7648 soap->dime.last->next = soap->dime.first;
7649 soap->dime.first = soap->dime.list->next;
7650 soap->dime.list->next = NULL;
7651 soap->dime.last = soap->dime.list;
7653 if (!(err = soap_putdime(soap)))
7654 err = soap_putmime(soap);
7655 soap->mime.list = NULL;
7656 soap->mime.first = NULL;
7657 soap->mime.last = NULL;
7658 soap->dime.list = NULL;
7659 soap->dime.first = NULL;
7660 soap->dime.last = NULL;
7661 if (err)
7662 return err;
7663 #endif
7664 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End send\n"));
7665 if (soap->mode & SOAP_IO) /* need to flush the remaining data in buffer */
7666 { if (soap_flush(soap))
7667 #ifdef WITH_ZLIB
7668 { if (soap->mode & SOAP_ENC_ZLIB && soap->zlib_state == SOAP_ZLIB_DEFLATE)
7669 { soap->zlib_state = SOAP_ZLIB_NONE;
7670 deflateEnd(soap->d_stream);
7672 return soap->error;
7674 #else
7675 return soap->error;
7676 #endif
7677 #ifdef WITH_ZLIB
7678 if (soap->mode & SOAP_ENC_ZLIB)
7679 { int r;
7680 soap->d_stream->avail_in = 0;
7682 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating remainder\n"));
7683 r = deflate(soap->d_stream, Z_FINISH);
7684 if (soap->d_stream->avail_out != SOAP_BUFLEN)
7685 { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN - soap->d_stream->avail_out))
7686 { soap->zlib_state = SOAP_ZLIB_NONE;
7687 deflateEnd(soap->d_stream);
7688 return soap->error;
7690 soap->d_stream->next_out = (Byte*)soap->z_buf;
7691 soap->d_stream->avail_out = SOAP_BUFLEN;
7693 } while (r == Z_OK);
7694 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflated total %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out));
7695 soap->z_ratio_out = (float)soap->d_stream->total_out / (float)soap->d_stream->total_in;
7696 soap->mode &= ~SOAP_ENC_ZLIB;
7697 soap->zlib_state = SOAP_ZLIB_NONE;
7698 if (deflateEnd(soap->d_stream) != Z_OK || r != Z_STREAM_END)
7699 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to end deflate: %s\n", soap->d_stream->msg?soap->d_stream->msg:SOAP_STR_EOS));
7700 return soap->error = SOAP_ZLIB_ERROR;
7702 #ifdef WITH_GZIP
7703 if (soap->zlib_out != SOAP_ZLIB_DEFLATE)
7704 { soap->z_buf[0] = soap->z_crc & 0xFF;
7705 soap->z_buf[1] = (soap->z_crc >> 8) & 0xFF;
7706 soap->z_buf[2] = (soap->z_crc >> 16) & 0xFF;
7707 soap->z_buf[3] = (soap->z_crc >> 24) & 0xFF;
7708 soap->z_buf[4] = soap->d_stream->total_in & 0xFF;
7709 soap->z_buf[5] = (soap->d_stream->total_in >> 8) & 0xFF;
7710 soap->z_buf[6] = (soap->d_stream->total_in >> 16) & 0xFF;
7711 soap->z_buf[7] = (soap->d_stream->total_in >> 24) & 0xFF;
7712 if (soap_flush_raw(soap, soap->z_buf, 8))
7713 return soap->error;
7714 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip crc32=%lu\n", (unsigned long)soap->z_crc));
7716 #endif
7718 #endif
7719 if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
7720 { char *p;
7721 #ifndef WITH_NOHTTP
7722 if (!(soap->mode & SOAP_ENC_XML))
7723 { soap->mode--;
7724 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending buffered message of length %u\n", (unsigned int)soap->blist->size));
7725 if (soap->status >= SOAP_POST)
7726 soap->error = soap->fpost(soap, soap->endpoint, soap->host, soap->port, soap->path, soap->action, soap->blist->size);
7727 else if (soap->status != SOAP_STOP)
7728 soap->error = soap->fresponse(soap, soap->status, soap->blist->size);
7729 if (soap->error || soap_flush(soap))
7730 return soap->error;
7731 soap->mode++;
7733 #endif
7734 for (p = soap_first_block(soap, NULL); p; p = soap_next_block(soap, NULL))
7735 { DBGMSG(SENT, p, soap_block_size(soap, NULL));
7736 if ((soap->error = soap->fsend(soap, p, soap_block_size(soap, NULL))))
7737 { soap_end_block(soap, NULL);
7738 return soap->error;
7741 soap_end_block(soap, NULL);
7743 #ifndef WITH_LEANER
7744 else if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
7745 { DBGMSG(SENT, "\r\n0\r\n\r\n", 7);
7746 if ((soap->error = soap->fsend(soap, "\r\n0\r\n\r\n", 7)))
7747 return soap->error;
7749 #endif
7751 #ifdef WITH_TCPFIN
7752 #ifdef WITH_OPENSSL
7753 if (!soap->ssl && soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP))
7754 soap->fshutdownsocket(soap, soap->socket, 1); /* Send TCP FIN */
7755 #else
7756 if (soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP))
7757 soap->fshutdownsocket(soap, soap->socket, 1); /* Send TCP FIN */
7758 #endif
7759 #endif
7760 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of send phase\n"));
7761 soap->omode &= ~SOAP_XML_SEC;
7762 soap->count = 0;
7763 soap->part = SOAP_END;
7764 return SOAP_OK;
7766 #endif
7768 /******************************************************************************/
7769 #ifndef PALM_1
7770 SOAP_FMAC1
7772 SOAP_FMAC2
7773 soap_end_recv(struct soap *soap)
7774 { soap->part = SOAP_END;
7775 #ifndef WITH_LEAN
7776 soap->wsuid = NULL; /* reset before next send */
7777 soap->c14nexclude = NULL; /* reset before next send */
7778 #endif
7779 #ifndef WITH_LEANER
7780 if ((soap->mode & SOAP_ENC_DIME) && soap_getdime(soap))
7781 { soap->dime.first = NULL;
7782 soap->dime.last = NULL;
7783 return soap->error;
7785 soap->dime.list = soap->dime.first;
7786 soap->dime.first = NULL;
7787 soap->dime.last = NULL;
7788 /* Check if MIME attachments and mime-post-check flag is set, if set call soap_resolve() and return */
7789 if (soap->mode & SOAP_ENC_MIME)
7791 #ifndef WITH_NOIDREF
7792 if (soap->mode & SOAP_MIME_POSTCHECK)
7793 { soap_resolve(soap);
7794 return SOAP_OK;
7796 #endif
7797 if (soap_getmime(soap))
7798 return soap->error;
7800 soap->mime.list = soap->mime.first;
7801 soap->mime.first = NULL;
7802 soap->mime.last = NULL;
7803 soap->mime.boundary = NULL;
7804 if (soap->xlist)
7805 { struct soap_multipart *content;
7806 for (content = soap->mime.list; content; content = content->next)
7807 soap_resolve_attachment(soap, content);
7809 #endif
7810 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "End of receive message ok\n"));
7811 #ifdef WITH_ZLIB
7812 if (soap->mode & SOAP_ENC_ZLIB)
7813 { /* Make sure end of compressed content is reached */
7814 while (soap->d_stream->next_out != Z_NULL)
7815 if ((int)soap_get1(soap) == EOF)
7816 break;
7817 soap->mode &= ~SOAP_ENC_ZLIB;
7818 memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN);
7819 soap->bufidx = (char*)soap->d_stream->next_in - soap->z_buf;
7820 soap->buflen = soap->z_buflen;
7821 soap->zlib_state = SOAP_ZLIB_NONE;
7822 if (inflateEnd(soap->d_stream) != Z_OK)
7823 return soap->error = SOAP_ZLIB_ERROR;
7824 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Inflate end ok\n"));
7825 #ifdef WITH_GZIP
7826 if (soap->zlib_in == SOAP_ZLIB_GZIP)
7827 { soap_wchar c;
7828 short i;
7829 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Inflate gzip crc check\n"));
7830 for (i = 0; i < 8; i++)
7831 { if ((int)(c = soap_get1(soap)) == EOF)
7832 return soap->error = SOAP_EOF;
7833 soap->z_buf[i] = (char)c;
7835 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)))
7836 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: crc check failed, message corrupted? (crc32=%lu)\n", (unsigned long)soap->z_crc));
7837 return soap->error = SOAP_ZLIB_ERROR;
7839 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)))
7840 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: incorrect message length\n"));
7841 return soap->error = SOAP_ZLIB_ERROR;
7844 soap->zlib_in = SOAP_ZLIB_NONE;
7845 #endif
7847 #endif
7848 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
7849 while ((int)soap_getchar(soap) != EOF) /* advance to last chunk */
7851 #ifndef WITH_NOIDREF
7852 if (soap_resolve(soap))
7853 return soap->error;
7854 #endif
7855 #ifndef WITH_LEANER
7856 if (soap->xlist)
7857 { if (soap->mode & SOAP_ENC_MTOM)
7858 return soap->error = SOAP_MIME_HREF;
7859 return soap->error = SOAP_DIME_HREF;
7861 #endif
7862 soap_free_ns(soap);
7863 #ifndef WITH_LEANER
7864 if (soap->fpreparefinalrecv)
7865 return soap->error = soap->fpreparefinalrecv(soap);
7866 #endif
7867 return SOAP_OK;
7869 #endif
7871 /******************************************************************************/
7872 #ifndef PALM_1
7873 SOAP_FMAC1
7874 void
7875 SOAP_FMAC2
7876 soap_free_temp(struct soap *soap)
7877 { register struct soap_attribute *tp, *tq;
7878 register struct Namespace *ns;
7879 soap_free_ns(soap);
7880 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free any remaining temp blocks\n"));
7881 while (soap->blist)
7882 soap_end_block(soap, NULL);
7883 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute storage\n"));
7884 for (tp = soap->attributes; tp; tp = tq)
7885 { tq = tp->next;
7886 if (tp->value)
7887 SOAP_FREE(soap, tp->value);
7888 SOAP_FREE(soap, tp);
7890 soap->attributes = NULL;
7891 #ifdef WITH_FAST
7892 if (soap->labbuf)
7893 SOAP_FREE(soap, soap->labbuf);
7894 soap->labbuf = NULL;
7895 soap->lablen = 0;
7896 soap->labidx = 0;
7897 #endif
7898 ns = soap->local_namespaces;
7899 if (ns)
7900 { for (; ns->id; ns++)
7901 { if (ns->out)
7902 { if (soap->encodingStyle == ns->out)
7903 soap->encodingStyle = SOAP_STR_EOS;
7904 SOAP_FREE(soap, ns->out);
7905 ns->out = NULL;
7907 if (soap->encodingStyle == ns->ns)
7908 soap->encodingStyle = SOAP_STR_EOS;
7910 SOAP_FREE(soap, soap->local_namespaces);
7911 soap->local_namespaces = NULL;
7913 #ifndef WITH_LEANER
7914 while (soap->xlist)
7915 { struct soap_xlist *xp = soap->xlist->next;
7916 SOAP_FREE(soap, soap->xlist);
7917 soap->xlist = xp;
7919 #endif
7920 #ifndef WITH_NOIDREF
7921 soap_free_pht(soap);
7922 soap_free_iht(soap);
7923 #endif
7925 #endif
7927 /******************************************************************************/
7928 #ifndef PALM_1
7929 static void
7930 soap_free_ns(struct soap *soap)
7931 { register struct soap_nlist *np, *nq;
7932 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free namespace stack\n"));
7933 for (np = soap->nlist; np; np = nq)
7934 { nq = np->next;
7935 SOAP_FREE(soap, np);
7937 soap->nlist = NULL;
7939 #endif
7941 /******************************************************************************/
7942 #ifndef PALM_1
7943 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
7944 static void
7945 soap_init_logs(struct soap *soap)
7946 { int i;
7947 for (i = 0; i < SOAP_MAXLOGS; i++)
7948 { soap->logfile[i] = NULL;
7949 soap->fdebug[i] = NULL;
7952 #endif
7953 #endif
7955 /******************************************************************************/
7956 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
7957 SOAP_FMAC1
7958 void
7959 SOAP_FMAC2
7960 soap_open_logfile(struct soap *soap, int i)
7961 { if (soap->logfile[i])
7962 soap->fdebug[i] = fopen(soap->logfile[i], i < 2 ? "ab" : "a");
7964 #endif
7966 /******************************************************************************/
7967 #ifdef SOAP_DEBUG
7968 static void
7969 soap_close_logfile(struct soap *soap, int i)
7970 { if (soap->fdebug[i])
7971 { fclose(soap->fdebug[i]);
7972 soap->fdebug[i] = NULL;
7975 #endif
7977 /******************************************************************************/
7978 #ifdef SOAP_DEBUG
7979 SOAP_FMAC1
7980 void
7981 SOAP_FMAC2
7982 soap_close_logfiles(struct soap *soap)
7983 { int i;
7984 for (i = 0; i < SOAP_MAXLOGS; i++)
7985 soap_close_logfile(soap, i);
7987 #endif
7989 /******************************************************************************/
7990 #ifdef SOAP_DEBUG
7991 static void
7992 soap_set_logfile(struct soap *soap, int i, const char *logfile)
7993 { const char *s;
7994 char *t = NULL;
7995 soap_close_logfile(soap, i);
7996 s = soap->logfile[i];
7997 soap->logfile[i] = logfile;
7998 if (s)
7999 SOAP_FREE(soap, (void*)s);
8000 if (logfile)
8001 if ((t = (char*)SOAP_MALLOC(soap, strlen(logfile) + 1)))
8002 strcpy(t, logfile);
8003 soap->logfile[i] = t;
8005 #endif
8007 /******************************************************************************/
8008 #ifdef SOAP_DEBUG
8009 SOAP_FMAC1
8010 void
8011 SOAP_FMAC2
8012 soap_set_recv_logfile(struct soap *soap, const char *logfile)
8013 { soap_set_logfile(soap, SOAP_INDEX_RECV, logfile);
8015 #endif
8017 /******************************************************************************/
8018 #ifdef SOAP_DEBUG
8019 SOAP_FMAC1
8020 void
8021 SOAP_FMAC2
8022 soap_set_sent_logfile(struct soap *soap, const char *logfile)
8023 { soap_set_logfile(soap, SOAP_INDEX_SENT, logfile);
8025 #endif
8027 /******************************************************************************/
8028 #ifdef SOAP_DEBUG
8029 SOAP_FMAC1
8030 void
8031 SOAP_FMAC2
8032 soap_set_test_logfile(struct soap *soap, const char *logfile)
8033 { soap_set_logfile(soap, SOAP_INDEX_TEST, logfile);
8035 #endif
8037 /******************************************************************************/
8038 #ifndef PALM_1
8039 SOAP_FMAC1
8040 struct soap*
8041 SOAP_FMAC2
8042 soap_copy(const struct soap *soap)
8043 { return soap_copy_context((struct soap*)malloc(sizeof(struct soap)), soap);
8045 #endif
8047 /******************************************************************************/
8048 #ifndef PALM_1
8049 SOAP_FMAC1
8050 struct soap*
8051 SOAP_FMAC2
8052 soap_copy_context(struct soap *copy, const struct soap *soap)
8053 { if (soap_check_state(soap))
8054 return NULL;
8055 if (copy)
8056 { register struct soap_plugin *p = NULL;
8057 #ifdef __cplusplus
8058 *copy = *soap;
8059 #else
8060 memcpy(copy, soap, sizeof(struct soap));
8061 #endif
8062 copy->state = SOAP_COPY;
8063 copy->error = SOAP_OK;
8064 copy->userid = NULL;
8065 copy->passwd = NULL;
8066 copy->nlist = NULL;
8067 copy->blist = NULL;
8068 copy->clist = NULL;
8069 copy->alist = NULL;
8070 copy->attributes = NULL;
8071 copy->labbuf = NULL;
8072 copy->lablen = 0;
8073 copy->labidx = 0;
8074 #ifdef SOAP_MEM_DEBUG
8075 soap_init_mht(copy);
8076 #endif
8077 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
8078 soap_init_logs(copy);
8079 #endif
8080 #ifdef SOAP_DEBUG
8081 soap_set_test_logfile(copy, soap->logfile[SOAP_INDEX_TEST]);
8082 soap_set_sent_logfile(copy, soap->logfile[SOAP_INDEX_SENT]);
8083 soap_set_recv_logfile(copy, soap->logfile[SOAP_INDEX_RECV]);
8084 #endif
8085 #ifdef WITH_C_LOCALE
8086 copy->c_locale = duplocale(soap->c_locale);
8087 #else
8088 copy->c_locale = NULL;
8089 #endif
8090 #ifdef WITH_OPENSSL
8091 copy->bio = NULL;
8092 copy->ssl = NULL;
8093 copy->session = NULL;
8094 #endif
8095 #ifdef WITH_ZLIB
8096 copy->d_stream = (z_stream*)SOAP_MALLOC(copy, sizeof(z_stream));
8097 copy->d_stream->zalloc = Z_NULL;
8098 copy->d_stream->zfree = Z_NULL;
8099 copy->d_stream->opaque = Z_NULL;
8100 copy->z_buf = NULL;
8101 #endif
8102 copy->local_namespaces = NULL;
8103 #ifndef WITH_NOIDREF
8104 soap_init_iht(copy);
8105 soap_init_pht(copy);
8106 #endif
8107 copy->header = NULL;
8108 copy->fault = NULL;
8109 copy->action = NULL;
8110 #ifndef WITH_LEAN
8111 #ifdef WITH_COOKIES
8112 copy->cookies = soap_copy_cookies(copy, soap);
8113 #else
8114 copy->cookies = NULL;
8115 #endif
8116 #endif
8117 copy->plugins = NULL;
8118 for (p = soap->plugins; p; p = p->next)
8119 { register struct soap_plugin *q = (struct soap_plugin*)SOAP_MALLOC(copy, sizeof(struct soap_plugin));
8120 if (!q)
8121 return NULL;
8122 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying plugin '%s'\n", p->id));
8123 *q = *p;
8124 if (p->fcopy && p->fcopy(copy, q, p))
8125 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not copy plugin '%s'\n", p->id));
8126 SOAP_FREE(copy, q);
8127 return NULL;
8129 q->next = copy->plugins;
8130 copy->plugins = q;
8133 return copy;
8135 #endif
8137 /******************************************************************************/
8138 #ifndef PALM_1
8139 SOAP_FMAC1
8140 void
8141 SOAP_FMAC2
8142 soap_copy_stream(struct soap *copy, struct soap *soap)
8143 { copy->mode = soap->mode;
8144 copy->imode = soap->imode;
8145 copy->omode = soap->omode;
8146 copy->socket = soap->socket;
8147 copy->recv_timeout = soap->recv_timeout;
8148 copy->send_timeout = soap->send_timeout;
8149 #if defined(__cplusplus) && !defined(WITH_LEAN)
8150 copy->os = soap->os;
8151 copy->is = soap->is;
8152 #endif
8153 copy->sendfd = soap->sendfd;
8154 copy->recvfd = soap->recvfd;
8155 copy->bufidx = soap->bufidx;
8156 copy->buflen = soap->buflen;
8157 copy->ahead = soap->ahead;
8158 copy->cdata = soap->cdata;
8159 copy->chunksize = soap->chunksize;
8160 copy->chunkbuflen = soap->chunkbuflen;
8161 copy->keep_alive = soap->keep_alive;
8162 copy->tcp_keep_alive = soap->tcp_keep_alive;
8163 copy->tcp_keep_idle = soap->tcp_keep_idle;
8164 copy->tcp_keep_intvl = soap->tcp_keep_intvl;
8165 copy->tcp_keep_cnt = soap->tcp_keep_cnt;
8166 copy->max_keep_alive = soap->max_keep_alive;
8167 #ifndef WITH_NOIO
8168 copy->peer = soap->peer;
8169 copy->peerlen = soap->peerlen;
8170 #endif
8171 #ifdef WITH_OPENSSL
8172 copy->bio = soap->bio;
8173 copy->ssl = soap->ssl;
8174 copy->ctx = soap->ctx;
8175 #endif
8176 #ifdef WITH_ZLIB
8177 copy->zlib_state = soap->zlib_state;
8178 copy->zlib_in = soap->zlib_in;
8179 copy->zlib_out = soap->zlib_out;
8180 copy->d_stream = (z_stream*)SOAP_MALLOC(copy, sizeof(z_stream));
8181 memcpy(copy->d_stream, soap->d_stream, sizeof(z_stream));
8182 copy->z_crc = soap->z_crc;
8183 copy->z_ratio_in = soap->z_ratio_in;
8184 copy->z_ratio_out = soap->z_ratio_out;
8185 copy->z_buf = NULL;
8186 copy->z_buflen = soap->z_buflen;
8187 copy->z_level = soap->z_level;
8188 if (soap->z_buf && soap->zlib_state != SOAP_ZLIB_NONE)
8189 { copy->z_buf = (char*)SOAP_MALLOC(copy, SOAP_BUFLEN);
8190 memcpy(copy->z_buf, soap->z_buf, sizeof(soap->z_buf));
8192 copy->z_dict = soap->z_dict;
8193 copy->z_dict_len = soap->z_dict_len;
8194 #endif
8195 memcpy(copy->buf, soap->buf, sizeof(soap->buf));
8197 #endif
8199 /******************************************************************************/
8200 #ifndef PALM_1
8201 SOAP_FMAC1
8202 void
8203 SOAP_FMAC2
8204 soap_free_stream(struct soap *soap)
8205 { soap->socket = SOAP_INVALID_SOCKET;
8206 #ifdef WITH_OPENSSL
8207 soap->bio = NULL;
8208 soap->ssl = NULL;
8209 #endif
8210 #ifdef WITH_ZLIB
8211 if (soap->d_stream)
8212 SOAP_FREE(soap, soap->d_stream);
8213 soap->d_stream = NULL;
8214 if (soap->z_buf)
8215 SOAP_FREE(soap, soap->z_buf);
8216 soap->z_buf = NULL;
8217 #endif
8219 #endif
8221 /******************************************************************************/
8222 #ifndef PALM_1
8223 SOAP_FMAC1
8224 void
8225 SOAP_FMAC2
8226 soap_init(struct soap *soap)
8227 { soap->state = SOAP_INIT;
8228 #ifdef SOAP_MEM_DEBUG
8229 soap_init_mht(soap);
8230 #endif
8231 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
8232 soap_init_logs(soap);
8233 #endif
8234 #ifdef SOAP_DEBUG
8236 Oracle customization for KMS server debug
8238 #ifdef SOAP_DEBUG_SERVER
8239 soap_set_test_logfile(soap, "/var/log/SUNWkms2/TEST.log");
8240 soap_set_sent_logfile(soap, "/var/log/SUNWkms2/SENT.log");
8241 soap_set_recv_logfile(soap, "/var/log/SUNWkms2/RECV.log");
8242 #else
8243 soap_set_test_logfile(soap, "TEST.log");
8244 soap_set_sent_logfile(soap, "SENT.log");
8245 soap_set_recv_logfile(soap, "RECV.log");
8246 #endif
8247 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing context\n"));
8248 #endif
8249 soap->version = 0;
8250 soap_imode(soap, SOAP_IO_DEFAULT);
8251 soap_omode(soap, SOAP_IO_DEFAULT);
8252 soap->plugins = NULL;
8253 soap->user = NULL;
8254 soap->userid = NULL;
8255 soap->passwd = NULL;
8256 #ifndef WITH_NOHTTP
8257 soap->fpost = http_post;
8258 soap->fget = http_get;
8259 soap->fput = http_405;
8260 soap->fdel = http_405;
8261 soap->fhead = http_405;
8262 soap->fform = NULL;
8263 soap->fposthdr = http_post_header;
8264 soap->fresponse = http_response;
8265 soap->fparse = http_parse;
8266 soap->fparsehdr = http_parse_header;
8267 #endif
8268 soap->fheader = NULL;
8269 soap->fconnect = NULL;
8270 soap->fdisconnect = NULL;
8271 #ifndef WITH_NOIO
8272 soap->ipv6_multicast_if = 0;
8273 soap->ipv4_multicast_if = NULL;
8274 #ifndef WITH_IPV6
8275 soap->fresolve = tcp_gethost;
8276 #else
8277 soap->fresolve = NULL;
8278 #endif
8279 soap->faccept = tcp_accept;
8280 soap->fopen = tcp_connect;
8281 soap->fclose = tcp_disconnect;
8282 soap->fclosesocket = tcp_closesocket;
8283 soap->fshutdownsocket = tcp_shutdownsocket;
8284 soap->fsend = fsend;
8285 soap->frecv = frecv;
8286 soap->fpoll = soap_poll;
8287 #else
8288 soap->fopen = NULL;
8289 soap->fclose = NULL;
8290 soap->fpoll = NULL;
8291 #endif
8292 soap->fseterror = NULL;
8293 soap->fignore = NULL;
8294 soap->fserveloop = NULL;
8295 soap->fplugin = fplugin;
8296 soap->fmalloc = NULL;
8297 #ifndef WITH_LEANER
8298 soap->fprepareinitsend = NULL;
8299 soap->fprepareinitrecv = NULL;
8300 soap->fpreparesend = NULL;
8301 soap->fpreparerecv = NULL;
8302 soap->fpreparefinalsend = NULL;
8303 soap->fpreparefinalrecv = NULL;
8304 soap->fdimereadopen = NULL;
8305 soap->fdimewriteopen = NULL;
8306 soap->fdimereadclose = NULL;
8307 soap->fdimewriteclose = NULL;
8308 soap->fdimeread = NULL;
8309 soap->fdimewrite = NULL;
8310 soap->fmimereadopen = NULL;
8311 soap->fmimewriteopen = NULL;
8312 soap->fmimereadclose = NULL;
8313 soap->fmimewriteclose = NULL;
8314 soap->fmimeread = NULL;
8315 soap->fmimewrite = NULL;
8316 #endif
8317 soap->float_format = "%.9G"; /* Alternative: use "%G" */
8318 soap->double_format = "%.17lG"; /* Alternative: use "%lG" */
8319 soap->dime_id_format = "cid:id%d"; /* default DIME id format */
8320 soap->http_version = "1.1";
8321 soap->proxy_http_version = "1.0";
8322 soap->http_content = NULL;
8323 soap->actor = NULL;
8324 soap->lang = "en";
8325 soap->keep_alive = 0;
8326 soap->tcp_keep_alive = 0;
8327 soap->tcp_keep_idle = 0;
8328 soap->tcp_keep_intvl = 0;
8329 soap->tcp_keep_cnt = 0;
8330 soap->max_keep_alive = SOAP_MAXKEEPALIVE;
8331 soap->recv_timeout = 0;
8332 soap->send_timeout = 0;
8333 soap->connect_timeout = 0;
8334 soap->accept_timeout = 0;
8335 #if defined(WITH_OPENSSL) && defined(KMS_SERVER)
8336 /* Oracle customization for Ultra 2 KMS Server */
8337 soap->ssl_accept_timeout = 0;
8338 #endif
8339 soap->socket_flags = 0;
8340 soap->connect_flags = 0;
8341 soap->bind_flags = 0;
8342 soap->accept_flags = 0;
8343 soap->linger_time = 0;
8344 soap->ip = 0;
8345 soap->labbuf = NULL;
8346 soap->lablen = 0;
8347 soap->labidx = 0;
8348 soap->encodingStyle = SOAP_STR_EOS;
8349 #ifndef WITH_NONAMESPACES
8350 soap->namespaces = namespaces;
8351 #else
8352 soap->namespaces = NULL;
8353 #endif
8354 soap->local_namespaces = NULL;
8355 soap->nlist = NULL;
8356 soap->blist = NULL;
8357 soap->clist = NULL;
8358 soap->alist = NULL;
8359 soap->attributes = NULL;
8360 soap->header = NULL;
8361 soap->fault = NULL;
8362 soap->master = SOAP_INVALID_SOCKET;
8363 soap->socket = SOAP_INVALID_SOCKET;
8364 soap->os = NULL;
8365 soap->is = NULL;
8366 #ifndef WITH_LEANER
8367 soap->dom = NULL;
8368 soap->dime.list = NULL;
8369 soap->dime.first = NULL;
8370 soap->dime.last = NULL;
8371 soap->mime.list = NULL;
8372 soap->mime.first = NULL;
8373 soap->mime.last = NULL;
8374 soap->mime.boundary = NULL;
8375 soap->mime.start = NULL;
8376 soap->xlist = NULL;
8377 #endif
8378 #ifndef UNDER_CE
8379 soap->recvfd = 0;
8380 soap->sendfd = 1;
8381 #else
8382 soap->recvfd = stdin;
8383 soap->sendfd = stdout;
8384 #endif
8385 soap->host[0] = '\0';
8386 soap->session_host[0] = '\0'; /* Oracle customization */
8387 soap->session_port = 0; /* Oracle customization */
8388 soap->port = 0;
8389 soap->action = NULL;
8390 soap->proxy_host = NULL;
8391 soap->proxy_port = 8080;
8392 soap->proxy_userid = NULL;
8393 soap->proxy_passwd = NULL;
8394 soap->authrealm = NULL;
8395 soap->prolog = NULL;
8396 #ifdef WITH_ZLIB
8397 soap->zlib_state = SOAP_ZLIB_NONE;
8398 soap->zlib_in = SOAP_ZLIB_NONE;
8399 soap->zlib_out = SOAP_ZLIB_NONE;
8400 soap->d_stream = (z_stream*)SOAP_MALLOC(soap, sizeof(z_stream));
8401 soap->d_stream->zalloc = Z_NULL;
8402 soap->d_stream->zfree = Z_NULL;
8403 soap->d_stream->opaque = Z_NULL;
8404 soap->z_buf = NULL;
8405 soap->z_level = 6;
8406 soap->z_dict = NULL;
8407 soap->z_dict_len = 0;
8408 #endif
8409 #ifndef WITH_LEAN
8410 soap->wsuid = NULL;
8411 soap->c14nexclude = NULL;
8412 soap->cookies = NULL;
8413 soap->cookie_domain = NULL;
8414 soap->cookie_path = NULL;
8415 soap->cookie_max = 32;
8416 #endif
8417 #ifdef WMW_RPM_IO
8418 soap->rpmreqid = NULL;
8419 #endif
8420 #ifdef PALM
8421 palmNetLibOpen();
8422 #endif
8423 #ifndef WITH_NOIDREF
8424 soap_init_iht(soap);
8425 soap_init_pht(soap);
8426 #endif
8427 #ifdef WITH_OPENSSL
8428 if (!soap_ssl_init_done)
8429 soap_ssl_init();
8430 soap->fsslauth = ssl_auth_init;
8431 soap->fsslverify = ssl_verify_callback;
8432 soap->bio = NULL;
8433 soap->ssl = NULL;
8434 soap->ctx = NULL;
8435 soap->ssl_flags = SOAP_SSL_DEFAULT;
8436 soap->keyfile = NULL;
8437 soap->password = NULL;
8438 soap->dhfile = NULL;
8439 soap->cafile = NULL;
8440 soap->capath = NULL;
8441 soap->crlfile = NULL;
8442 soap->randfile = NULL;
8443 soap->session = NULL;
8444 #endif
8445 #ifdef WITH_C_LOCALE
8446 soap->c_locale = newlocale(LC_ALL_MASK, "C", NULL);
8447 #else
8448 soap->c_locale = NULL;
8449 #endif
8450 soap->buflen = 0;
8451 soap->bufidx = 0;
8452 #ifndef WITH_LEANER
8453 soap->dime.chunksize = 0;
8454 soap->dime.buflen = 0;
8455 #endif
8456 soap->null = 0;
8457 soap->position = 0;
8458 soap->encoding = 0;
8459 soap->mustUnderstand = 0;
8460 soap->ns = 0;
8461 soap->part = SOAP_END;
8462 soap->alloced = 0;
8463 soap->count = 0;
8464 soap->length = 0;
8465 soap->cdata = 0;
8466 soap->peeked = 0;
8467 soap->ahead = 0;
8468 soap->idnum = 0;
8469 soap->level = 0;
8470 soap->endpoint[0] = '\0';
8471 soap->error = SOAP_OK;
8473 #endif
8475 /******************************************************************************/
8476 #ifndef PALM_1
8477 SOAP_FMAC1
8478 void
8479 SOAP_FMAC2
8480 soap_init1(struct soap *soap, soap_mode mode)
8481 { soap_init2(soap, mode, mode);
8483 #endif
8485 /******************************************************************************/
8486 #ifndef PALM_1
8487 SOAP_FMAC1
8488 void
8489 SOAP_FMAC2
8490 soap_init2(struct soap *soap, soap_mode imode, soap_mode omode)
8491 { soap_init(soap);
8492 soap_imode(soap, imode);
8493 soap_omode(soap, omode);
8495 #endif
8497 /******************************************************************************/
8498 #ifndef PALM_2
8499 SOAP_FMAC1
8500 void
8501 SOAP_FMAC2
8502 soap_begin(struct soap *soap)
8503 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reinitializing context\n"));
8504 if (!soap->keep_alive)
8505 { soap->buflen = 0;
8506 soap->bufidx = 0;
8508 soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0);
8509 soap->null = 0;
8510 soap->position = 0;
8511 soap->encoding = 0;
8512 soap->mustUnderstand = 0;
8513 soap->mode = 0;
8514 soap->ns = 0;
8515 soap->part = SOAP_END;
8516 soap->alloced = 0;
8517 soap->count = 0;
8518 soap->length = 0;
8519 soap->cdata = 0;
8520 soap->error = SOAP_OK;
8521 soap->peeked = 0;
8522 soap->ahead = 0;
8523 soap->idnum = 0;
8524 soap->level = 0;
8525 soap->endpoint[0] = '\0';
8526 #ifndef WITH_LEANER
8527 soap->dime.chunksize = 0;
8528 soap->dime.buflen = 0;
8529 #endif
8530 soap_free_temp(soap);
8532 #endif
8534 /******************************************************************************/
8535 #ifndef PALM_2
8536 SOAP_FMAC1
8537 void
8538 SOAP_FMAC2
8539 soap_end(struct soap *soap)
8540 { if (soap_check_state(soap))
8541 return;
8542 soap_free_temp(soap);
8543 soap_dealloc(soap, NULL);
8544 while (soap->clist)
8545 { register struct soap_clist *cp = soap->clist->next;
8546 SOAP_FREE(soap, soap->clist);
8547 soap->clist = cp;
8549 soap_closesock(soap);
8550 #ifdef SOAP_DEBUG
8551 soap_close_logfiles(soap);
8552 #endif
8553 #ifdef PALM
8554 palmNetLibClose();
8555 #endif
8557 #endif
8559 /******************************************************************************/
8560 #ifndef PALM_1
8561 SOAP_FMAC1
8563 SOAP_FMAC2
8564 soap_set_namespaces(struct soap *soap, const struct Namespace *p)
8565 { register struct Namespace *ns = soap->local_namespaces;
8566 register struct soap_nlist *np, *nq, *nr;
8567 register unsigned int level = soap->level;
8568 soap->namespaces = p;
8569 soap->local_namespaces = NULL;
8570 soap_set_local_namespaces(soap);
8571 /* reverse the namespace list */
8572 np = soap->nlist;
8573 soap->nlist = NULL;
8574 if (np)
8575 { nq = np->next;
8576 np->next = NULL;
8577 while (nq)
8578 { nr = nq->next;
8579 nq->next = np;
8580 np = nq;
8581 nq = nr;
8584 /* then push on new stack */
8585 while (np)
8586 { register const char *s;
8587 soap->level = np->level; /* preserve element nesting level */
8588 s = np->ns;
8589 if (!s && np->index >= 0 && ns)
8590 { s = ns[np->index].out;
8591 if (!s)
8592 s = ns[np->index].ns;
8594 if (s && soap_push_namespace(soap, np->id, s) == NULL)
8595 return soap->error;
8596 nq = np;
8597 np = np->next;
8598 SOAP_FREE(soap, nq);
8600 if (ns)
8601 { register int i;
8602 for (i = 0; ns[i].id; i++)
8603 { if (ns[i].out)
8604 { SOAP_FREE(soap, ns[i].out);
8605 ns[i].out = NULL;
8608 SOAP_FREE(soap, ns);
8610 soap->level = level; /* restore level */
8611 return SOAP_OK;
8613 #endif
8615 /******************************************************************************/
8616 #ifndef PALM_1
8617 SOAP_FMAC1
8618 void
8619 SOAP_FMAC2
8620 soap_set_local_namespaces(struct soap *soap)
8621 { if (soap->namespaces && !soap->local_namespaces)
8622 { register const struct Namespace *ns1;
8623 register struct Namespace *ns2;
8624 register size_t n = 1;
8625 for (ns1 = soap->namespaces; ns1->id; ns1++)
8626 n++;
8627 n *= sizeof(struct Namespace);
8628 ns2 = (struct Namespace*)SOAP_MALLOC(soap, n);
8629 if (ns2)
8630 { memcpy(ns2, soap->namespaces, n);
8631 if (ns2[0].ns)
8632 { if (!strcmp(ns2[0].ns, soap_env1))
8633 soap->version = 1;
8634 else
8635 soap->version = 2;
8637 soap->local_namespaces = ns2;
8641 #endif
8643 /******************************************************************************/
8644 #ifndef WITH_LEAN
8645 #ifndef PALM_1
8646 SOAP_FMAC1
8647 const char *
8648 SOAP_FMAC2
8649 soap_tagsearch(const char *big, const char *little)
8650 { if (little)
8651 { register size_t n = strlen(little);
8652 register const char *s = big;
8653 while (s)
8654 { register const char *t = s;
8655 register size_t i;
8656 for (i = 0; i < n; i++, t++)
8657 { if (*t != little[i])
8658 break;
8660 if (*t == '\0' || *t == ' ')
8661 { if (i == n || (i && little[i-1] == ':'))
8662 return s;
8664 s = strchr(t, ' ');
8665 if (s)
8666 s++;
8669 return NULL;
8671 #endif
8672 #endif
8674 /******************************************************************************/
8675 #ifndef WITH_LEAN
8676 #ifndef PALM_1
8677 SOAP_FMAC1
8678 struct soap_nlist *
8679 SOAP_FMAC2
8680 soap_lookup_ns(struct soap *soap, const char *tag, size_t n)
8681 { register struct soap_nlist *np;
8682 for (np = soap->nlist; np; np = np->next)
8683 { if (!strncmp(np->id, tag, n) && !np->id[n])
8684 return np;
8686 return NULL;
8688 #endif
8689 #endif
8691 /******************************************************************************/
8692 #ifndef WITH_LEAN
8693 static struct soap_nlist *
8694 soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized)
8695 { register struct soap_nlist *np;
8696 size_t n, k;
8697 if (soap_tagsearch(soap->c14nexclude, id))
8698 return NULL;
8699 if (!utilized)
8700 { for (np = soap->nlist; np; np = np->next)
8701 { if (!strcmp(np->id, id) && (!np->ns || !strcmp(np->ns, ns)))
8702 break;
8704 if (np)
8705 { if ((np->level < soap->level || !np->ns) && np->index == 1)
8706 utilized = 1;
8707 else
8708 return NULL;
8711 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Adding namespace binding (level=%u) '%s' '%s' utilized=%d\n", soap->level, id, ns?ns:"(null)", utilized));
8712 n = strlen(id);
8713 if (ns)
8714 k = strlen(ns);
8715 else
8716 k = 0;
8717 np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k + 1);
8718 if (!np)
8719 { soap->error = SOAP_EOM;
8720 return NULL;
8722 np->next = soap->nlist;
8723 soap->nlist = np;
8724 strcpy(np->id, id);
8725 if (ns)
8726 np->ns = strcpy(np->id + n + 1, ns);
8727 else
8728 np->ns = NULL;
8729 np->level = soap->level;
8730 np->index = utilized;
8731 return np;
8733 #endif
8735 /******************************************************************************/
8736 #ifndef WITH_LEAN
8737 static void
8738 soap_utilize_ns(struct soap *soap, const char *tag, size_t n)
8739 { register struct soap_nlist *np = soap_lookup_ns(soap, tag, n);
8740 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Utilizing namespace of '%s'\n", tag));
8741 if (np)
8742 { if (np->index == 0)
8743 soap_push_ns(soap, np->id, np->ns, 1);
8745 else if (strncmp(tag, "xml", 3))
8746 { strncpy(soap->tmpbuf, tag, n);
8747 soap->tmpbuf[n] = '\0';
8748 soap_push_ns(soap, soap->tmpbuf, NULL, 1);
8751 #endif
8753 /******************************************************************************/
8754 #ifndef PALM_2
8755 SOAP_FMAC1
8757 SOAP_FMAC2
8758 soap_element(struct soap *soap, const char *tag, int id, const char *type)
8760 #ifndef WITH_LEAN
8761 register const char *s;
8762 #endif
8763 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element begin tag='%s' id='%d' type='%s'\n", tag, id, type?type:SOAP_STR_EOS));
8764 #ifdef WITH_DOM
8765 #ifndef WITH_LEAN
8766 if (soap->wsuid && soap_tagsearch(soap->wsuid, tag))
8767 { int i;
8768 for (s = tag, i = 0; *s && i < sizeof(soap->tag); s++, i++)
8769 soap->tag[i] = *s == ':' ? '-' : *s;
8770 soap->tag[sizeof(soap->tag) - 1] = '\0';
8771 if (soap_set_attr(soap, "wsu:Id", soap->tag, 1))
8772 return soap->error;
8774 #endif
8775 if (soap->part == SOAP_BEGIN_SECURITY && (soap->mode & SOAP_XML_CANONICAL) && !(soap->mode & SOAP_DOM_ASIS))
8776 { register struct soap_nlist *np;
8777 /* wsu:Id found: clear xmlns renderings, so re-emit them for exc-c14n */
8778 for (np = soap->nlist; np; np = np->next)
8779 { if (np->index == 2)
8780 np->index = 0;
8783 if (soap->mode & SOAP_XML_DOM)
8784 { register struct soap_dom_element *elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element));
8785 if (!elt)
8786 return soap->error;
8787 elt->soap = soap;
8788 elt->next = NULL;
8789 elt->prnt = soap->dom;
8790 elt->name = soap_strdup(soap, tag);
8791 elt->elts = NULL;
8792 elt->atts = NULL;
8793 elt->nstr = NULL;
8794 elt->data = NULL;
8795 elt->wide = NULL;
8796 elt->node = NULL;
8797 elt->type = 0;
8798 elt->head = NULL;
8799 elt->tail = NULL;
8800 if (soap->dom)
8801 { struct soap_dom_element *p = soap->dom->elts;
8802 if (p)
8803 { while (p->next)
8804 p = p->next;
8805 p->next = elt;
8807 else
8808 soap->dom->elts = elt;
8810 soap->dom = elt;
8812 else
8814 #endif
8815 soap->level++;
8816 #ifndef WITH_LEAN
8817 if (!soap->ns)
8818 { if (!(soap->mode & SOAP_XML_CANONICAL)
8819 && soap_send(soap, soap->prolog ? soap->prolog : "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"))
8820 return soap->error;
8822 else if (soap->mode & SOAP_XML_INDENT)
8823 { if (soap->ns == 1 && soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1))
8824 return soap->error;
8825 soap->body = 1;
8827 if ((soap->mode & SOAP_XML_DEFAULTNS) && (s = strchr(tag, ':')))
8828 { struct Namespace *ns = soap->local_namespaces;
8829 size_t n = s - tag;
8830 if (soap_send_raw(soap, "<", 1)
8831 || soap_send(soap, s + 1))
8832 return soap->error;
8833 if (soap->nlist && !strncmp(soap->nlist->id, tag, n) && !soap->nlist->id[n])
8834 ns = NULL;
8835 for (; ns && ns->id; ns++)
8836 { if (*ns->id && (ns->out || ns->ns) && !strncmp(ns->id, tag, n) && !ns->id[n])
8837 { soap_push_ns(soap, ns->id, ns->out ? ns->out : ns->ns, 0);
8838 if (soap_attribute(soap, "xmlns", ns->out ? ns->out : ns->ns))
8839 return soap->error;
8840 break;
8844 else
8845 #endif
8846 if (soap_send_raw(soap, "<", 1)
8847 || soap_send(soap, tag))
8848 return soap->error;
8849 #ifdef WITH_DOM
8851 #endif
8852 if (!soap->ns)
8853 { struct Namespace *ns;
8854 int k = -1;
8855 #ifndef WITH_LEAN
8856 if ((soap->mode & SOAP_XML_DEFAULTNS))
8857 k = 4; /* only produce the first four required entries */
8858 #endif
8859 for (ns = soap->local_namespaces; ns && ns->id && k; ns++, k--)
8860 { if (*ns->id && (ns->out || ns->ns))
8861 { sprintf(soap->tmpbuf, "xmlns:%s", ns->id);
8862 if (soap_attribute(soap, soap->tmpbuf, ns->out ? ns->out : ns->ns))
8863 return soap->error;
8867 soap->ns = 1; /* namespace table control: ns = 0 or 2 to start, then 1 to stop dumping the table */
8868 #ifndef WITH_LEAN
8869 if (soap->mode & SOAP_XML_CANONICAL)
8870 { const char *t = strchr(tag, ':');
8871 if (t)
8872 soap_utilize_ns(soap, tag, t - tag);
8874 #endif
8875 if (id > 0)
8876 { sprintf(soap->tmpbuf, "_%d", id);
8877 if (soap_attribute(soap, "id", soap->tmpbuf))
8878 return soap->error;
8880 if (type && *type && (!(soap->mode & SOAP_XML_SEC) || soap->part == SOAP_IN_BODY))
8881 { if (soap_attribute(soap, "xsi:type", type))
8882 return soap->error;
8883 #ifndef WITH_LEAN
8884 if (soap->mode & SOAP_XML_CANONICAL)
8885 { const char *t = strchr(type, ':');
8886 if (t)
8887 soap_utilize_ns(soap, type, t - type);
8889 #endif
8891 if (soap->null && soap->position > 0)
8892 { register int i;
8893 sprintf(soap->tmpbuf, "[%d", soap->positions[0]);
8894 for (i = 1; i < soap->position; i++)
8895 sprintf(soap->tmpbuf + strlen(soap->tmpbuf), ",%d", soap->positions[i]);
8896 strcat(soap->tmpbuf, "]");
8897 if (soap_attribute(soap, "SOAP-ENC:position", soap->tmpbuf))
8898 return soap->error;
8900 if (soap->mustUnderstand)
8901 { if (soap->actor && *soap->actor)
8902 { if (soap_attribute(soap, soap->version == 2 ? "SOAP-ENV:role" : "SOAP-ENV:actor", soap->actor))
8903 return soap->error;
8905 if (soap_attribute(soap, "SOAP-ENV:mustUnderstand", soap->version == 2 ? "true" : "1"))
8906 return soap->error;
8907 soap->mustUnderstand = 0;
8909 if (soap->encoding)
8910 { if (soap->encodingStyle && soap->local_namespaces)
8911 { if (!*soap->encodingStyle)
8912 { if (soap->local_namespaces[1].out)
8913 soap->encodingStyle = soap->local_namespaces[1].out;
8914 else
8915 soap->encodingStyle = soap->local_namespaces[1].ns;
8917 if (soap->encodingStyle && soap_attribute(soap, "SOAP-ENV:encodingStyle", soap->encodingStyle))
8918 return soap->error;
8920 soap->encoding = 0;
8922 soap->null = 0;
8923 soap->position = 0;
8924 if (soap->part == SOAP_BEGIN_SECURITY && (soap->mode & SOAP_XML_CANONICAL))
8925 soap->part = SOAP_IN_SECURITY;
8926 return SOAP_OK;
8928 #endif
8930 /******************************************************************************/
8931 #ifndef PALM_2
8932 SOAP_FMAC1
8934 SOAP_FMAC2
8935 soap_element_begin_out(struct soap *soap, const char *tag, int id, const char *type)
8936 { if (*tag == '-')
8937 return SOAP_OK;
8938 if (soap_element(soap, tag, id, type))
8939 return soap->error;
8940 return soap_element_start_end_out(soap, NULL);
8942 #endif
8944 /******************************************************************************/
8945 #ifndef PALM_2
8946 #ifndef HAVE_STRRCHR
8947 SOAP_FMAC1
8948 char*
8949 SOAP_FMAC2
8950 soap_strrchr(const char *s, int t)
8951 { register char *r = NULL;
8952 while (*s)
8953 if (*s++ == t)
8954 r = (char*)s - 1;
8955 return r;
8957 #endif
8958 #endif
8960 /******************************************************************************/
8961 #ifndef PALM_2
8962 #ifndef HAVE_STRTOL
8963 SOAP_FMAC1
8964 long
8965 SOAP_FMAC2
8966 soap_strtol(const char *s, char **t, int b)
8967 { register long n = 0;
8968 register int c;
8969 while (*s > 0 && *s <= 32)
8970 s++;
8971 if (b == 10)
8972 { short neg = 0;
8973 if (*s == '-')
8974 { s++;
8975 neg = 1;
8977 else if (*s == '+')
8978 s++;
8979 while ((c = *s) && c >= '0' && c <= '9')
8980 { if (n >= 214748364 && (n > 214748364 || c >= '8'))
8981 break;
8982 n *= 10;
8983 n += c - '0';
8984 s++;
8986 if (neg)
8987 n = -n;
8989 else /* assume b == 16 and value is always positive */
8990 { while ((c = *s))
8991 { if (c >= '0' && c <= '9')
8992 c -= '0';
8993 else if (c >= 'A' && c <= 'F')
8994 c -= 'A' - 10;
8995 else if (c >= 'a' && c <= 'f')
8996 c -= 'a' - 10;
8997 if (n > 0x07FFFFFF)
8998 break;
8999 n <<= 4;
9000 n += c;
9001 s++;
9004 if (t)
9005 *t = (char*)s;
9006 return n;
9008 #endif
9009 #endif
9011 /******************************************************************************/
9012 #ifndef PALM_2
9013 #ifndef HAVE_STRTOUL
9014 SOAP_FMAC1
9015 unsigned long
9016 SOAP_FMAC2
9017 soap_strtoul(const char *s, char **t, int b)
9018 { unsigned long n = 0;
9019 register int c;
9020 while (*s > 0 && *s <= 32)
9021 s++;
9022 if (b == 10)
9023 { if (*s == '+')
9024 s++;
9025 while ((c = *s) && c >= '0' && c <= '9')
9026 { if (n >= 429496729 && (n > 429496729 || c >= '6'))
9027 break;
9028 n *= 10;
9029 n += c - '0';
9030 s++;
9033 else /* b == 16 */
9034 { while ((c = *s))
9035 { if (c >= '0' && c <= '9')
9036 c -= '0';
9037 else if (c >= 'A' && c <= 'F')
9038 c -= 'A' - 10;
9039 else if (c >= 'a' && c <= 'f')
9040 c -= 'a' - 10;
9041 if (n > 0x0FFFFFFF)
9042 break;
9043 n <<= 4;
9044 n += c;
9045 s++;
9048 if (t)
9049 *t = (char*)s;
9050 return n;
9052 #endif
9053 #endif
9055 /******************************************************************************/
9056 #ifndef PALM_1
9057 SOAP_FMAC1
9059 SOAP_FMAC2
9060 soap_array_begin_out(struct soap *soap, const char *tag, int id, const char *type, const char *offset)
9061 { if (!type || !*type)
9062 return soap_element_begin_out(soap, tag, id, NULL);
9063 if (soap_element(soap, tag, id, "SOAP-ENC:Array"))
9064 return soap->error;
9065 if (soap->version == 2)
9066 { const char *s;
9067 s = soap_strrchr(type, '[');
9068 if ((size_t)(s - type) < sizeof(soap->tmpbuf))
9069 { strncpy(soap->tmpbuf, type, s - type);
9070 soap->tmpbuf[s - type] = '\0';
9071 if (soap_attribute(soap, "SOAP-ENC:itemType", soap->tmpbuf))
9072 return soap->error;
9073 if (s && (soap_attribute(soap, "SOAP-ENC:arraySize", s + 1)))
9074 return soap->error;
9077 else
9078 { if (offset && soap_attribute(soap, "SOAP-ENC:offset", offset))
9079 return soap->error;
9080 if (soap_attribute(soap, "SOAP-ENC:arrayType", type))
9081 return soap->error;
9083 #ifndef WITH_LEAN
9084 if ((soap->mode & SOAP_XML_CANONICAL))
9085 { const char *s = strchr(type, ':');
9086 if (s)
9087 soap_utilize_ns(soap, type, s - type);
9089 #endif
9090 return soap_element_start_end_out(soap, NULL);
9092 #endif
9094 /******************************************************************************/
9095 #ifndef PALM_1
9096 SOAP_FMAC1
9098 SOAP_FMAC2
9099 soap_element_start_end_out(struct soap *soap, const char *tag)
9100 { register struct soap_attribute *tp;
9101 #ifndef WITH_LEAN
9102 if (soap->mode & SOAP_XML_CANONICAL)
9103 { struct soap_nlist *np;
9104 for (tp = soap->attributes; tp; tp = tp->next)
9105 { if (tp->visible && tp->name)
9106 { const char *s = strchr(tp->name, ':');
9107 if (s)
9108 soap_utilize_ns(soap, tp->name, s - tp->name);
9111 for (np = soap->nlist; np; np = np->next)
9112 { if (np->index == 1 && np->ns)
9113 { sprintf(soap->tmpbuf, "xmlns:%s", np->id);
9114 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enabling utilized binding (level=%u) %s='%s'\n", np->level, soap->tmpbuf, np->ns));
9115 soap_set_attr(soap, soap->tmpbuf, np->ns, 1);
9116 np->index = 2;
9120 #endif
9121 #ifdef WITH_DOM
9122 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
9123 { register struct soap_dom_attribute **att;
9124 att = &soap->dom->atts;
9125 for (tp = soap->attributes; tp; tp = tp->next)
9126 { if (tp->visible)
9127 { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
9128 if (!*att)
9129 return soap->error;
9130 (*att)->next = NULL;
9131 (*att)->nstr = NULL;
9132 (*att)->name = soap_strdup(soap, tp->name);
9133 (*att)->data = soap_strdup(soap, tp->value);
9134 (*att)->wide = NULL;
9135 (*att)->soap = soap;
9136 att = &(*att)->next;
9137 tp->visible = 0;
9140 return SOAP_OK;
9142 #endif
9143 for (tp = soap->attributes; tp; tp = tp->next)
9144 { if (tp->visible)
9146 #ifndef WITH_LEAN
9147 const char *s;
9148 if ((soap->mode & SOAP_XML_DEFAULTNS) && (s = strchr(tp->name, ':')))
9149 { size_t n = s - tp->name;
9150 if (soap->nlist && !strncmp(soap->nlist->id, tp->name, n) && !soap->nlist->id[n])
9151 s++;
9152 else
9153 s = tp->name;
9154 if (soap_send(soap, " ") || soap_send(soap, s))
9155 return soap->error;
9157 else
9158 #endif
9159 if (soap_send(soap, " ") || soap_send(soap, tp->name))
9160 return soap->error;
9161 if (tp->visible == 2 && tp->value)
9162 if (soap_send_raw(soap, "=\"", 2)
9163 || soap_string_out(soap, tp->value, tp->flag)
9164 || soap_send_raw(soap, "\"", 1))
9165 return soap->error;
9166 tp->visible = 0;
9169 if (tag)
9171 #ifndef WITH_LEAN
9172 if (soap->mode & SOAP_XML_CANONICAL)
9173 { if (soap_send_raw(soap, ">", 1)
9174 || soap_element_end_out(soap, tag))
9175 return soap->error;
9176 return SOAP_OK;
9178 #endif
9179 soap->level--; /* decrement level just before /> */
9180 if (soap_send_raw(soap, "/>", 2))
9181 return soap->error;
9182 return SOAP_OK;
9184 return soap_send_raw(soap, ">", 1);
9186 #endif
9188 /******************************************************************************/
9189 #ifndef PALM_1
9190 SOAP_FMAC1
9192 SOAP_FMAC2
9193 soap_element_end_out(struct soap *soap, const char *tag)
9195 #ifndef WITH_LEAN
9196 const char *s;
9197 #endif
9198 if (*tag == '-')
9199 return SOAP_OK;
9200 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element ending tag='%s'\n", tag));
9201 #ifdef WITH_DOM
9202 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
9203 { if (soap->dom->prnt)
9204 soap->dom = soap->dom->prnt;
9205 return SOAP_OK;
9207 #endif
9208 #ifndef WITH_LEAN
9209 if (soap->mode & SOAP_XML_CANONICAL)
9210 soap_pop_namespace(soap);
9211 if (soap->mode & SOAP_XML_INDENT)
9212 { if (!soap->body)
9213 { if (soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1))
9214 return soap->error;
9216 soap->body = 0;
9218 if ((soap->mode & SOAP_XML_DEFAULTNS) && (s = strchr(tag, ':')))
9219 { soap_pop_namespace(soap);
9220 tag = s + 1;
9222 #endif
9223 if (soap_send_raw(soap, "</", 2)
9224 || soap_send(soap, tag))
9225 return soap->error;
9226 soap->level--; /* decrement level just before > */
9227 return soap_send_raw(soap, ">", 1);
9229 #endif
9231 /******************************************************************************/
9232 #ifndef PALM_1
9233 SOAP_FMAC1
9235 SOAP_FMAC2
9236 soap_element_ref(struct soap *soap, const char *tag, int id, int href)
9237 { register int n = 0;
9238 const char *s = "href";
9239 if (soap->version == 2)
9240 { s = "SOAP-ENC:ref";
9241 n = 1;
9243 sprintf(soap->href, "#_%d", href);
9244 return soap_element_href(soap, tag, id, s, soap->href + n);
9246 #endif
9248 /******************************************************************************/
9249 #ifndef PALM_1
9250 SOAP_FMAC1
9252 SOAP_FMAC2
9253 soap_element_href(struct soap *soap, const char *tag, int id, const char *ref, const char *val)
9254 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element '%s' reference %s='%s'\n", tag, ref, val));
9255 if (soap_element(soap, tag, id, NULL)
9256 || soap_attribute(soap, ref, val)
9257 || soap_element_start_end_out(soap, tag))
9258 return soap->error;
9259 return SOAP_OK;
9261 #endif
9263 /******************************************************************************/
9264 #ifndef PALM_1
9265 SOAP_FMAC1
9267 SOAP_FMAC2
9268 soap_element_null(struct soap *soap, const char *tag, int id, const char *type)
9269 { struct soap_attribute *tp;
9270 for (tp = soap->attributes; tp; tp = tp->next)
9271 if (tp->visible)
9272 break;
9273 if (tp || (soap->version == 2 && soap->position > 0) || id > 0 || (soap->mode & SOAP_XML_NIL))
9274 { if (soap_element(soap, tag, id, type))
9275 return soap->error;
9276 if (!tp && soap_attribute(soap, "xsi:nil", "true"))
9277 return soap->error;
9278 return soap_element_start_end_out(soap, tag);
9280 soap->null = 1;
9281 soap->position = 0;
9282 soap->mustUnderstand = 0;
9283 return SOAP_OK;
9285 #endif
9287 /******************************************************************************/
9288 #ifndef PALM_1
9289 SOAP_FMAC1
9291 SOAP_FMAC2
9292 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)
9293 { if (!p)
9294 { soap_element_null(soap, tag, id, type);
9295 return -1;
9297 #ifndef WITH_NOIDREF
9298 if (soap->mode & SOAP_XML_TREE)
9299 return 0;
9300 if (id < 0)
9301 { struct soap_plist *pp;
9302 if (a)
9303 id = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
9304 else
9305 id = soap_pointer_lookup(soap, p, t, &pp);
9306 if (id)
9307 { if (soap_is_embedded(soap, pp))
9308 { soap_element_ref(soap, tag, 0, id);
9309 return -1;
9311 if (soap_is_single(soap, pp))
9312 return 0;
9313 soap_set_embedded(soap, pp);
9316 return id;
9317 #else
9318 return 0;
9319 #endif
9321 #endif
9323 /******************************************************************************/
9324 #ifndef PALM_1
9325 SOAP_FMAC1
9327 SOAP_FMAC2
9328 soap_element_result(struct soap *soap, const char *tag)
9329 { if (soap->version == 2 && soap->encodingStyle)
9330 { if (soap_element(soap, "SOAP-RPC:result", 0, NULL)
9331 || soap_attribute(soap, "xmlns:SOAP-RPC", soap_rpc)
9332 || soap_element_start_end_out(soap, NULL)
9333 || soap_string_out(soap, tag, 0)
9334 || soap_element_end_out(soap, "SOAP-RPC:result"))
9335 return soap->error;
9337 return SOAP_OK;
9339 #endif
9341 /******************************************************************************/
9342 #ifndef PALM_1
9343 SOAP_FMAC1
9344 void
9345 SOAP_FMAC2
9346 soap_check_result(struct soap *soap, const char *tag)
9347 { if (soap->version == 2 && soap->encodingStyle)
9348 { soap_instring(soap, ":result", NULL, NULL, 0, 2, -1, -1);
9349 /* just ignore content for compliance reasons, but should compare tag to element's QName value? */
9352 #endif
9354 /******************************************************************************/
9355 #ifndef PALM_2
9356 SOAP_FMAC1
9358 SOAP_FMAC2
9359 soap_attribute(struct soap *soap, const char *name, const char *value)
9361 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attribute '%s'='%s'\n", name, value));
9362 #ifdef WITH_DOM
9363 if ((soap->mode & SOAP_XML_DOM) && !(soap->mode & SOAP_XML_CANONICAL) && soap->dom)
9364 { register struct soap_dom_attribute *a = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
9365 if (!a)
9366 return soap->error;
9367 a->next = soap->dom->atts;
9368 a->nstr = NULL;
9369 a->name = soap_strdup(soap, name);
9370 a->data = soap_strdup(soap, value);
9371 a->wide = NULL;
9372 a->soap = soap;
9373 soap->dom->atts = a;
9374 return SOAP_OK;
9376 #endif
9377 #ifndef WITH_LEAN
9378 if (soap->mode & SOAP_XML_CANONICAL)
9379 { /* TODO: consider using this code to handle default namespace bindings
9380 if (!strncmp(name, "xmlns", 5) && (name[5] == ':' || name[5] == '\0'))
9381 { if (name[5] == ':')
9382 soap_push_ns(soap, name + 6, value, 0);
9383 else
9384 soap_push_ns(soap, "", value, 0);
9387 if (!strncmp(name, "xmlns:", 6))
9388 soap_push_ns(soap, name + 6, value, 0);
9389 else if (soap_set_attr(soap, name, value, 1))
9390 return soap->error;
9392 else
9393 #endif
9394 { if (soap_send(soap, " ") || soap_send(soap, name))
9395 return soap->error;
9396 if (value)
9397 if (soap_send_raw(soap, "=\"", 2)
9398 || soap_string_out(soap, value, 1)
9399 || soap_send_raw(soap, "\"", 1))
9400 return soap->error;
9402 return SOAP_OK;
9404 #endif
9406 /******************************************************************************/
9407 #ifndef PALM_2
9408 SOAP_FMAC1
9410 SOAP_FMAC2
9411 soap_element_begin_in(struct soap *soap, const char *tag, int nillable, const char *type)
9412 { if (!soap_peek_element(soap))
9413 { if (soap->other)
9414 return soap->error = SOAP_TAG_MISMATCH;
9415 if (tag && *tag == '-')
9416 return SOAP_OK;
9417 if (!(soap->error = soap_match_tag(soap, soap->tag, tag)))
9418 { soap->peeked = 0;
9419 if (type && *soap->type && soap_match_tag(soap, soap->type, type))
9420 return soap->error = SOAP_TYPE;
9421 if (!nillable && soap->null && (soap->mode & SOAP_XML_STRICT))
9422 return soap->error = SOAP_NULL;
9423 if (soap->body)
9424 soap->level++;
9425 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:SOAP_STR_EOS ));
9428 else if (soap->error == SOAP_NO_TAG && tag && *tag == '-')
9429 soap->error = SOAP_OK;
9430 return soap->error;
9432 #endif
9434 /******************************************************************************/
9435 #ifndef PALM_2
9436 SOAP_FMAC1
9438 SOAP_FMAC2
9439 soap_element_end_in(struct soap *soap, const char *tag)
9440 { register soap_wchar c;
9441 register char *s;
9442 register int n = 0;
9443 if (tag && *tag == '-')
9444 return SOAP_OK;
9445 if (soap->error == SOAP_NO_TAG)
9446 soap->error = SOAP_OK;
9447 #ifdef WITH_DOM
9448 /* this whitespace or mixed content is not insignificant for DOM */
9449 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
9450 { if (!soap->peeked && !soap_string_in(soap, 3, -1, -1))
9451 return soap->error;
9452 if (soap->dom->prnt)
9453 soap->dom = soap->dom->prnt;
9455 #endif
9456 if (soap->peeked)
9457 { if (*soap->tag)
9458 n++;
9459 soap->peeked = 0;
9462 { while (((c = soap_get(soap)) != SOAP_TT))
9463 { if ((int)c == EOF)
9464 return soap->error = SOAP_EOF;
9465 if (c == SOAP_LT)
9466 n++;
9467 else if (c == '/')
9468 { c = soap_get(soap);
9469 if (c == SOAP_GT)
9470 n--;
9471 else
9472 soap_unget(soap, c);
9475 } while (n--);
9476 s = soap->tag;
9477 n = sizeof(soap->tag);
9478 while (soap_notblank(c = soap_get(soap)))
9479 { if (--n > 0)
9480 *s++ = (char)c;
9482 *s = '\0';
9483 if ((int)c == EOF)
9484 return soap->error = SOAP_EOF;
9485 while (soap_blank(c))
9486 c = soap_get(soap);
9487 if (c != SOAP_GT)
9488 return soap->error = SOAP_SYNTAX_ERROR;
9489 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:SOAP_STR_EOS));
9490 #ifndef WITH_LEAN
9491 if (tag && (soap->mode & SOAP_XML_STRICT))
9492 { soap_pop_namespace(soap);
9493 if (soap_match_tag(soap, soap->tag, tag))
9494 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element tag name does not match\n"));
9495 return soap->error = SOAP_SYNTAX_ERROR;
9498 #endif
9499 soap->level--;
9500 return SOAP_OK;
9502 #endif
9504 /******************************************************************************/
9505 #ifndef PALM_2
9506 SOAP_FMAC1
9507 const char *
9508 SOAP_FMAC2
9509 soap_attr_value(struct soap *soap, const char *name, int flag)
9510 { register struct soap_attribute *tp;
9511 if (*name == '-')
9512 return SOAP_STR_EOS;
9513 for (tp = soap->attributes; tp; tp = tp->next)
9514 { if (tp->visible && !soap_match_tag(soap, tp->name, name))
9515 break;
9517 if (tp)
9518 { if (flag == 2 && (soap->mode & SOAP_XML_STRICT))
9519 soap->error = SOAP_PROHIBITED;
9520 else
9521 return tp->value;
9523 else if (flag == 1 && (soap->mode & SOAP_XML_STRICT))
9524 soap->error = SOAP_REQUIRED;
9525 else
9526 soap->error = SOAP_OK;
9527 return NULL;
9529 #endif
9531 /******************************************************************************/
9532 #ifndef PALM_2
9533 SOAP_FMAC1
9535 SOAP_FMAC2
9536 soap_set_attr(struct soap *soap, const char *name, const char *value, int flag)
9537 { register struct soap_attribute *tp;
9538 if (*name == '-')
9539 return SOAP_OK;
9540 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set attribute %s='%s'\n", name, value?value:SOAP_STR_EOS));
9541 for (tp = soap->attributes; tp; tp = tp->next)
9542 { if (!strcmp(tp->name, name))
9543 break;
9545 if (!tp)
9546 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute %s\n", name));
9547 if (!(tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(name))))
9548 return soap->error = SOAP_EOM;
9549 tp->ns = NULL;
9550 #ifndef WITH_LEAN
9551 if ((soap->mode & SOAP_XML_CANONICAL))
9552 { struct soap_attribute **tpp = &soap->attributes;
9553 const char *s = strchr(name, ':');
9554 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inserting attribute %s for c14n\n", name))
9555 if (!strncmp(name, "xmlns", 5))
9556 { for (; *tpp; tpp = &(*tpp)->next)
9557 if (strncmp((*tpp)->name, "xmlns", 5) || strcmp((*tpp)->name + 5, name + 5) > 0)
9558 break;
9560 else if (!s)
9561 { for (; *tpp; tpp = &(*tpp)->next)
9562 if (strncmp((*tpp)->name, "xmlns", 5) && ((*tpp)->ns || strcmp((*tpp)->name, name) > 0))
9563 break;
9565 else
9566 { int k;
9567 for (; *tpp; tpp = &(*tpp)->next)
9568 { if (!strncmp((*tpp)->name, "xmlns:", 6) && !strncmp((*tpp)->name + 6, name, s - name) && !(*tpp)->name[6 + s - name])
9569 { if (!tp->ns)
9570 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Canonicalization: prefix %s=%p (%s)\n", name, (*tpp)->ns, (*tpp)->ns));
9571 tp->ns = (*tpp)->ns;
9574 else if (strncmp((*tpp)->name, "xmlns", 5) && (*tpp)->ns && tp->ns && ((k = strcmp((*tpp)->ns, tp->ns)) > 0 || (!k && strcmp((*tpp)->name, name) > 0)))
9575 break;
9578 tp->next = *tpp;
9579 *tpp = tp;
9581 else
9582 #endif
9583 { tp->next = soap->attributes;
9584 soap->attributes = tp;
9586 strcpy(tp->name, name);
9587 tp->value = NULL;
9589 else if (tp->visible)
9590 { return SOAP_OK;
9592 else if (value && tp->value && tp->size <= strlen(value))
9593 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute value of %s (free %p)\n", name, tp->value));
9594 SOAP_FREE(soap, tp->value);
9595 tp->value = NULL;
9596 tp->ns = NULL;
9598 if (value)
9599 { if (!tp->value)
9600 { tp->size = strlen(value) + 1;
9601 if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size)))
9602 return soap->error = SOAP_EOM;
9603 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute value for %s (%p)\n", tp->name, tp->value));
9605 strcpy(tp->value, value);
9606 if (!strncmp(tp->name, "xmlns:", 6))
9607 tp->ns = tp->value;
9608 tp->visible = 2;
9609 tp->flag = flag;
9610 #ifndef WITH_LEAN
9611 if (soap->part != SOAP_IN_SECURITY && !strcmp(name, "wsu:Id"))
9612 { soap->part = SOAP_BEGIN_SECURITY;
9613 strncpy(soap->id, value, sizeof(soap->id));
9614 soap->id[sizeof(soap->id)-1] = '\0';
9616 #endif
9618 else
9619 tp->visible = 1;
9620 return SOAP_OK;
9622 #endif
9624 /******************************************************************************/
9625 #ifndef PALM_2
9626 SOAP_FMAC1
9627 void
9628 SOAP_FMAC2
9629 soap_clr_attr(struct soap *soap)
9630 { register struct soap_attribute *tp;
9631 #ifndef WITH_LEAN
9632 if ((soap->mode & SOAP_XML_CANONICAL))
9633 { while (soap->attributes)
9634 { tp = soap->attributes->next;
9635 if (soap->attributes->value)
9636 SOAP_FREE(soap, soap->attributes->value);
9637 SOAP_FREE(soap, soap->attributes);
9638 soap->attributes = tp;
9641 else
9642 #endif
9643 { for (tp = soap->attributes; tp; tp = tp->next)
9644 tp->visible = 0;
9647 #endif
9649 /******************************************************************************/
9650 #ifndef PALM_2
9651 static int
9652 soap_getattrval(struct soap *soap, char *s, size_t n, soap_wchar d)
9653 { register size_t i;
9654 for (i = 0; i < n; i++)
9655 { register soap_wchar c = soap_get(soap);
9656 switch (c)
9658 case SOAP_TT:
9659 *s++ = '<';
9660 soap_unget(soap, '/');
9661 break;
9662 case SOAP_LT:
9663 *s++ = '<';
9664 break;
9665 case SOAP_GT:
9666 if (d == ' ')
9667 { soap_unget(soap, c);
9668 *s = '\0';
9669 return SOAP_OK;
9671 *s++ = '>';
9672 break;
9673 case SOAP_QT:
9674 if (c == d)
9675 { *s = '\0';
9676 return SOAP_OK;
9678 *s++ = '"';
9679 break;
9680 case SOAP_AP:
9681 if (c == d)
9682 { *s = '\0';
9683 return SOAP_OK;
9685 *s++ = '\'';
9686 break;
9687 case '\t':
9688 case '\n':
9689 case '\r':
9690 case ' ':
9691 case '/':
9692 if (d == ' ')
9693 { soap_unget(soap, c);
9694 *s = '\0';
9695 return SOAP_OK;
9697 default:
9698 if ((int)c == EOF)
9699 return soap->error = SOAP_EOF;
9700 *s++ = (char)c;
9703 return soap->error = SOAP_EOM;
9705 #endif
9707 /******************************************************************************/
9708 #ifdef WITH_FAST
9709 #ifndef PALM_2
9710 SOAP_FMAC1
9712 SOAP_FMAC2
9713 soap_store_lab(struct soap *soap, const char *s, size_t n)
9714 { soap->labidx = 0;
9715 return soap_append_lab(soap, s, n);
9717 #endif
9718 #endif
9720 /******************************************************************************/
9721 #ifdef WITH_FAST
9722 #ifndef PALM_2
9723 SOAP_FMAC1
9725 SOAP_FMAC2
9726 soap_append_lab(struct soap *soap, const char *s, size_t n)
9727 { if (soap->labidx + n >= soap->lablen)
9728 { register char *t = soap->labbuf;
9729 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enlarging look-aside buffer to append data, old size=%lu", (unsigned long)soap->lablen));
9730 if (soap->lablen == 0)
9731 soap->lablen = SOAP_LABLEN;
9732 while (soap->labidx + n >= soap->lablen)
9733 soap->lablen <<= 1;
9734 DBGLOG(TEST, SOAP_MESSAGE(fdebug, ", new size=%lu\n", (unsigned long)soap->lablen));
9735 soap->labbuf = (char*)SOAP_MALLOC(soap, soap->lablen);
9736 if (!soap->labbuf)
9737 { if (t)
9738 SOAP_FREE(soap, t);
9739 return soap->error = SOAP_EOM;
9741 if (t)
9742 { memcpy(soap->labbuf, t, soap->labidx);
9743 SOAP_FREE(soap, t);
9746 if (s)
9747 { memcpy(soap->labbuf + soap->labidx, s, n);
9748 soap->labidx += n;
9750 return SOAP_OK;
9752 #endif
9753 #endif
9755 /******************************************************************************/
9756 #ifndef PALM_2
9757 SOAP_FMAC1
9759 SOAP_FMAC2
9760 soap_peek_element(struct soap *soap)
9762 #ifdef WITH_DOM
9763 register struct soap_dom_attribute **att = NULL;
9764 register char *lead = NULL;
9765 #endif
9766 register struct soap_attribute *tp, *tq = NULL;
9767 register const char *t;
9768 register char *s;
9769 register soap_wchar c;
9770 register int i;
9771 if (soap->peeked)
9772 { if (!*soap->tag)
9773 return soap->error = SOAP_NO_TAG;
9774 return SOAP_OK;
9776 soap->peeked = 1;
9777 soap->id[0] = '\0';
9778 soap->href[0] = '\0';
9779 soap->type[0] = '\0';
9780 soap->arrayType[0] = '\0';
9781 soap->arraySize[0] = '\0';
9782 soap->arrayOffset[0] = '\0';
9783 soap->other = 0;
9784 soap->root = -1;
9785 soap->position = 0;
9786 soap->null = 0;
9787 soap->mustUnderstand = 0;
9788 /* skip BOM */
9789 if ((c = soap_getchar(soap)) != 0xEF || (c = soap_get1(soap)) != 0xBB || (c = soap_get1(soap)) != 0xBF)
9790 soap_unget(soap, c);
9791 c = soap_get(soap);
9792 #ifdef WITH_DOM
9793 /* whitespace leading to start tag is not insignificant for DOM */
9794 if (soap_blank(c))
9795 { soap->labidx = 0;
9797 { if (soap_append_lab(soap, NULL, 0))
9798 return soap->error;
9799 s = soap->labbuf + soap->labidx;
9800 i = soap->lablen - soap->labidx;
9801 soap->labidx = soap->lablen;
9802 while (soap_blank(c) && i--)
9803 { *s++ = c;
9804 c = soap_get(soap);
9807 while (soap_blank(c));
9808 *s = '\0';
9809 if (*soap->labbuf)
9810 lead = soap->labbuf;
9812 #else
9813 /* skip space */
9814 while (soap_blank(c))
9815 c = soap_get(soap);
9816 #endif
9817 if (c != SOAP_LT)
9818 { *soap->tag = '\0';
9819 if ((int)c == EOF)
9820 return soap->error = SOAP_EOF;
9821 soap_unget(soap, c);
9822 #ifdef WITH_DOM
9823 /* whitespace leading to end tag is not insignificant for DOM */
9824 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
9825 soap->dom->tail = soap_strdup(soap, lead);
9826 #endif
9827 return soap->error = SOAP_NO_TAG;
9829 s = soap->tag;
9830 do c = soap_get1(soap);
9831 while (soap_blank(c));
9832 i = sizeof(soap->tag);
9833 while (c != '>' && c != '/' && soap_notblank(c) && (int)c != EOF)
9834 { if (--i > 0)
9835 *s++ = (char)c;
9836 c = soap_get1(soap);
9838 while (soap_blank(c))
9839 c = soap_get1(soap);
9840 *s = '\0';
9841 #ifdef WITH_DOM
9842 if (soap->mode & SOAP_XML_DOM)
9843 { register struct soap_dom_element *elt;
9844 elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element));
9845 if (!elt)
9846 return soap->error;
9847 elt->next = NULL;
9848 elt->nstr = NULL;
9849 elt->name = soap_strdup(soap, soap->tag);
9850 elt->prnt = soap->dom;
9851 elt->elts = NULL;
9852 elt->atts = NULL;
9853 elt->data = NULL;
9854 elt->wide = NULL;
9855 elt->type = 0;
9856 elt->node = NULL;
9857 elt->head = soap_strdup(soap, lead);
9858 elt->tail = NULL;
9859 elt->soap = soap;
9860 if (soap->dom)
9861 { struct soap_dom_element *p = soap->dom->elts;
9862 if (p)
9863 { while (p->next)
9864 p = p->next;
9865 p->next = elt;
9867 else
9868 soap->dom->elts = elt;
9870 soap->dom = elt;
9871 att = &elt->atts;
9873 #endif
9874 soap_pop_namespace(soap);
9875 for (tp = soap->attributes; tp; tp = tp->next)
9876 tp->visible = 0;
9877 while ((int)c != EOF && c != '>' && c != '/')
9878 { s = soap->tmpbuf;
9879 i = sizeof(soap->tmpbuf);
9880 while (c != '=' && c != '>' && c != '/' && soap_notblank(c) && (int)c != EOF)
9881 { if (--i > 0)
9882 *s++ = (char)c;
9883 c = soap_get1(soap);
9885 *s = '\0';
9886 if (i == sizeof(soap->tmpbuf))
9887 return soap->error = SOAP_SYNTAX_ERROR;
9888 #ifdef WITH_DOM
9889 /* add attribute name to dom */
9890 if (att)
9891 { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
9892 if (!*att)
9893 return soap->error;
9894 (*att)->next = NULL;
9895 (*att)->nstr = NULL;
9896 (*att)->name = soap_strdup(soap, soap->tmpbuf);
9897 (*att)->data = NULL;
9898 (*att)->wide = NULL;
9899 (*att)->soap = soap;
9901 #endif
9902 if (!strncmp(soap->tmpbuf, "xmlns", 5))
9903 { if (soap->tmpbuf[5] == ':')
9904 t = soap->tmpbuf + 6;
9905 else if (soap->tmpbuf[5])
9906 t = NULL;
9907 else
9908 t = SOAP_STR_EOS;
9910 else
9911 t = NULL;
9912 tq = NULL;
9913 for (tp = soap->attributes; tp; tq = tp, tp = tp->next)
9914 { if (!SOAP_STRCMP(tp->name, soap->tmpbuf))
9915 break;
9917 if (!tp)
9918 { tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(soap->tmpbuf));
9919 if (!tp)
9920 return soap->error = SOAP_EOM;
9921 strcpy(tp->name, soap->tmpbuf);
9922 tp->value = NULL;
9923 tp->size = 0;
9924 /* if attribute name is qualified, append it to the end of the list */
9925 if (tq && strchr(soap->tmpbuf, ':'))
9926 { tq->next = tp;
9927 tp->next = NULL;
9929 else
9930 { tp->next = soap->attributes;
9931 soap->attributes = tp;
9934 while (soap_blank(c))
9935 c = soap_get1(soap);
9936 if (c == '=')
9937 { do c = soap_getutf8(soap);
9938 while (soap_blank(c));
9939 if (c != SOAP_QT && c != SOAP_AP)
9940 { soap_unget(soap, c);
9941 c = ' '; /* blank delimiter */
9943 if (soap_getattrval(soap, tp->value, tp->size, c))
9945 #ifdef WITH_FAST
9946 if (soap->error != SOAP_EOM)
9947 return soap->error;
9948 soap->error = SOAP_OK;
9949 if (soap_store_lab(soap, tp->value, tp->size))
9950 return soap->error;
9951 if (tp->value)
9952 SOAP_FREE(soap, tp->value);
9953 for (;;)
9954 { if (soap_getattrval(soap, soap->labbuf + soap->labidx, soap->lablen - soap->labidx, c))
9955 { if (soap->error != SOAP_EOM)
9956 return soap->error;
9957 soap->error = SOAP_OK;
9958 soap->labidx = soap->lablen;
9959 if (soap_append_lab(soap, NULL, 0))
9960 return soap->error;
9962 else
9963 break;
9965 if (soap->labidx)
9966 tp->size = soap->lablen;
9967 else
9968 { tp->size = strlen(soap->labbuf) + 1;
9969 if (tp->size < SOAP_LABLEN)
9970 tp->size = SOAP_LABLEN;
9972 if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size)))
9973 return soap->error = SOAP_EOM;
9974 strcpy(tp->value, soap->labbuf);
9975 #else
9976 size_t n;
9977 if (soap->error != SOAP_EOM)
9978 return soap->error;
9979 soap->error = SOAP_OK;
9980 if (soap_new_block(soap) == NULL)
9981 return soap->error;
9982 for (;;)
9983 { if (!(s = (char*)soap_push_block(soap, NULL, SOAP_BLKLEN)))
9984 return soap->error;
9985 if (soap_getattrval(soap, s, SOAP_BLKLEN, c))
9986 { if (soap->error != SOAP_EOM)
9987 return soap->error;
9988 soap->error = SOAP_OK;
9990 else
9991 break;
9993 n = tp->size + soap->blist->size;
9994 if (!(s = (char*)SOAP_MALLOC(soap, n)))
9995 return soap->error = SOAP_EOM;
9996 if (tp->value)
9997 { memcpy(s, tp->value, tp->size);
9998 SOAP_FREE(soap, tp->value);
10000 soap_save_block(soap, NULL, s + tp->size, 0);
10001 tp->value = s;
10002 tp->size = n;
10003 #endif
10005 do c = soap_get1(soap);
10006 while (soap_blank(c));
10007 tp->visible = 2; /* seen this attribute w/ value */
10008 #ifdef WITH_DOM
10009 if (att)
10010 (*att)->data = soap_strdup(soap, tp->value);
10011 #endif
10013 else
10014 tp->visible = 1; /* seen this attribute w/o value */
10015 #ifdef WITH_DOM
10016 if (att)
10017 att = &(*att)->next;
10018 #endif
10019 if (t && tp->value)
10020 { if (soap_push_namespace(soap, t, tp->value) == NULL)
10021 return soap->error;
10024 #ifdef WITH_DOM
10025 if (att)
10026 { soap->dom->nstr = soap_current_namespace(soap, soap->tag);
10027 for (att = &soap->dom->atts; *att; att = &(*att)->next)
10028 (*att)->nstr = soap_current_namespace(soap, (*att)->name);
10030 #endif
10031 if ((int)c == EOF)
10032 return soap->error = SOAP_EOF;
10033 if (!(soap->body = (c != '/')))
10034 do c = soap_get1(soap);
10035 while (soap_blank(c));
10036 #ifdef WITH_DOM
10037 if (soap->mode & SOAP_XML_DOM)
10038 { if (!soap->body && soap->dom->prnt)
10039 soap->dom = soap->dom->prnt;
10041 #endif
10042 for (tp = soap->attributes; tp; tp = tp->next)
10043 { if (tp->visible && tp->value)
10045 #ifndef WITH_NOIDREF
10046 if (!strcmp(tp->name, "id"))
10047 { if ((soap->version > 0 && !(soap->mode & SOAP_XML_TREE))
10048 || (soap->mode & SOAP_XML_GRAPH))
10049 { *soap->id = '#';
10050 strncpy(soap->id + 1, tp->value, sizeof(soap->id) - 2);
10051 soap->id[sizeof(soap->id)-1] = '\0';
10054 else if (!strcmp(tp->name, "href"))
10055 { if (soap->version == 1
10056 || (soap->mode & SOAP_XML_GRAPH)
10057 || (soap->mode & SOAP_ENC_MTOM)
10058 || (soap->mode & SOAP_ENC_DIME))
10059 { strncpy(soap->href, tp->value, sizeof(soap->href) - 1);
10060 soap->href[sizeof(soap->href)-1] = '\0';
10063 else
10064 #endif
10065 if (!soap_match_tag(soap, tp->name, "xsi:type"))
10066 { strncpy(soap->type, tp->value, sizeof(soap->type) - 1);
10067 soap->type[sizeof(soap->type)-1] = '\0';
10069 else if ((!soap_match_tag(soap, tp->name, "xsi:null")
10070 || !soap_match_tag(soap, tp->name, "xsi:nil"))
10071 && (!strcmp(tp->value, "1")
10072 || !strcmp(tp->value, "true")))
10073 { soap->null = 1;
10075 else if (soap->version == 1)
10076 { if (!soap_match_tag(soap, tp->name, "SOAP-ENC:arrayType"))
10077 { s = soap_strrchr(tp->value, '[');
10078 if (s && (size_t)(s - tp->value) < sizeof(soap->arrayType))
10079 { strncpy(soap->arrayType, tp->value, s - tp->value);
10080 soap->arrayType[s - tp->value] = '\0';
10081 strncpy(soap->arraySize, s, sizeof(soap->arraySize) - 1);
10083 else
10084 strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1);
10085 soap->arraySize[sizeof(soap->arrayType)-1] = '\0';
10086 soap->arrayType[sizeof(soap->arrayType)-1] = '\0';
10088 else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:offset"))
10089 strncpy(soap->arrayOffset, tp->value, sizeof(soap->arrayOffset));
10090 else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:position"))
10091 soap->position = soap_getposition(tp->value, soap->positions);
10092 else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:root"))
10093 soap->root = ((!strcmp(tp->value, "1") || !strcmp(tp->value, "true")));
10094 else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand")
10095 && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true")))
10096 soap->mustUnderstand = 1;
10097 else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:actor"))
10098 { if ((!soap->actor || strcmp(soap->actor, tp->value))
10099 && strcmp(tp->value, "http://schemas.xmlsoap.org/soap/actor/next"))
10100 soap->other = 1;
10103 else if (soap->version == 2)
10105 #ifndef WITH_NOIDREF
10106 if (!strcmp(tp->name, "ref")
10107 || !soap_match_tag(soap, tp->name, "SOAP-ENC:ref"))
10108 { *soap->href = '#';
10109 strncpy(soap->href + 1, tp->value, sizeof(soap->href) - 2);
10110 soap->href[sizeof(soap->href)-1] = '\0';
10112 else
10113 #endif
10114 if (!soap_match_tag(soap, tp->name, "SOAP-ENC:itemType"))
10115 strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1);
10116 else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:arraySize"))
10117 strncpy(soap->arraySize, tp->value, sizeof(soap->arraySize) - 1);
10118 else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand")
10119 && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true")))
10120 soap->mustUnderstand = 1;
10121 else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:role"))
10122 { if ((!soap->actor || strcmp(soap->actor, tp->value))
10123 && strcmp(tp->value, "http://www.w3.org/2003/05/soap-envelope/role/next"))
10124 soap->other = 1;
10127 else
10128 { if (!soap_match_tag(soap, tp->name, "wsdl:required") && !strcmp(tp->value, "true"))
10129 soap->mustUnderstand = 1;
10133 return soap->error = SOAP_OK;
10135 #endif
10137 /******************************************************************************/
10138 #ifndef PALM_2
10139 SOAP_FMAC1
10140 void
10141 SOAP_FMAC2
10142 soap_retry(struct soap *soap)
10143 { soap->error = SOAP_OK;
10144 soap_revert(soap);
10146 #endif
10148 /******************************************************************************/
10149 #ifndef PALM_2
10150 SOAP_FMAC1
10151 void
10152 SOAP_FMAC2
10153 soap_revert(struct soap *soap)
10154 { if (!soap->peeked)
10155 { soap->peeked = 1;
10156 if (soap->body)
10157 soap->level--;
10159 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reverting last element (level=%u)\n", soap->level));
10161 #endif
10163 /******************************************************************************/
10164 #ifndef PALM_2
10165 SOAP_FMAC1
10167 SOAP_FMAC2
10168 soap_string_out(struct soap *soap, const char *s, int flag)
10169 { register const char *t;
10170 register soap_wchar c;
10171 register soap_wchar mask = (soap_wchar)0xFFFFFF80UL;
10172 #ifdef WITH_DOM
10173 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
10174 { soap->dom->data = soap_strdup(soap, s);
10175 return SOAP_OK;
10177 #endif
10178 if (flag == 2 || soap->mode & SOAP_C_UTFSTRING)
10179 mask = 0;
10180 t = s;
10181 while ((c = *t++))
10182 { switch (c)
10184 case 0x09:
10185 if (flag)
10186 { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&#x9;", 5))
10187 return soap->error;
10188 s = t;
10190 break;
10191 case 0x0A:
10192 if (flag || !(soap->mode & SOAP_XML_CANONICAL))
10193 { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&#xA;", 5))
10194 return soap->error;
10195 s = t;
10197 break;
10198 case 0x0D:
10199 if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&#xD;", 5))
10200 return soap->error;
10201 s = t;
10202 break;
10203 case '&':
10204 if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&amp;", 5))
10205 return soap->error;
10206 s = t;
10207 break;
10208 case '<':
10209 if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&lt;", 4))
10210 return soap->error;
10211 s = t;
10212 break;
10213 case '>':
10214 if (!flag)
10215 { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&gt;", 4))
10216 return soap->error;
10217 s = t;
10219 break;
10220 case '"':
10221 if (flag)
10222 { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&quot;", 6))
10223 return soap->error;
10224 s = t;
10226 break;
10227 default:
10228 #ifndef WITH_LEANER
10229 #ifdef HAVE_MBTOWC
10230 if (soap->mode & SOAP_C_MBSTRING)
10231 { wchar_t wc;
10232 register int m = mbtowc(&wc, t - 1, MB_CUR_MAX);
10233 if (m > 0 && wc != c)
10234 { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, wc))
10235 return soap->error;
10236 s = t += m - 1;
10237 continue;
10240 #endif
10241 #endif
10242 #ifndef WITH_NOSTRINGTOUTF8
10243 if ((c & mask) || !(c & 0xFFFFFFE0UL))
10244 { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned char)c))
10245 return soap->error;
10246 s = t;
10248 #endif
10251 return soap_send_raw(soap, s, t - s - 1);
10253 #endif
10255 /******************************************************************************/
10256 #ifndef PALM_2
10257 SOAP_FMAC1
10258 char *
10259 SOAP_FMAC2
10260 soap_string_in(struct soap *soap, int flag, long minlen, long maxlen)
10261 { register char *s;
10262 char *t = NULL;
10263 register size_t i;
10264 register long l = 0;
10265 register int n = 0, f = 0, m = 0;
10266 register soap_wchar c;
10267 #if !defined(WITH_LEANER) && defined(HAVE_WCTOMB)
10268 char buf[MB_LEN_MAX > 8 ? MB_LEN_MAX : 8];
10269 #else
10270 char buf[8];
10271 #endif
10272 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading string content, flag=%d\n", flag));
10273 if (soap->peeked && *soap->tag)
10275 #ifndef WITH_LEAN
10276 struct soap_attribute *tp;
10277 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String content includes tag '%s' and attributes\n", soap->tag));
10278 t = soap->tmpbuf;
10279 *t = '<';
10280 t[sizeof(soap->tmpbuf)-1] = '\0';
10281 strncpy(t + 1, soap->tag, sizeof(soap->tmpbuf) - 2);
10282 t += strlen(t);
10283 for (tp = soap->attributes; tp; tp = tp->next)
10284 { if (tp->visible)
10285 { if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2)
10286 break;
10287 *t++ = ' ';
10288 strcpy(t, tp->name);
10289 t += strlen(t);
10290 if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2)
10291 break; /* too many or large attribute values */
10292 if (tp->value)
10293 { *t++ = '=';
10294 *t++ = '"';
10295 strcpy(t, tp->value);
10296 t += strlen(t);
10297 *t++ = '"';
10301 if (!soap->body)
10302 *t++ = '/';
10303 *t++ = '>';
10304 *t = '\0';
10305 t = soap->tmpbuf;
10306 m = (int)strlen(soap->tmpbuf);
10307 #endif
10308 if (soap->body)
10309 n = 1;
10310 f = 1;
10311 soap->peeked = 0;
10313 #ifdef WITH_CDATA
10314 if (!flag)
10315 { register int state = 0;
10316 #ifdef WITH_FAST
10317 soap->labidx = 0; /* use look-aside buffer */
10318 #else
10319 if (soap_new_block(soap) == NULL)
10320 return NULL;
10321 #endif
10322 for (;;)
10324 #ifdef WITH_FAST
10325 register size_t k;
10326 if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */
10327 return NULL;
10328 s = soap->labbuf + soap->labidx; /* space to populate */
10329 k = soap->lablen - soap->labidx; /* number of bytes available */
10330 soap->labidx = soap->lablen; /* claim this space */
10331 #else
10332 register size_t k = SOAP_BLKLEN;
10333 if (!(s = (char*)soap_push_block(soap, NULL, k)))
10334 return NULL;
10335 #endif
10336 for (i = 0; i < k; i++)
10337 { if (m > 0)
10338 { *s++ = *t++; /* copy multibyte characters */
10339 m--;
10340 continue;
10342 c = soap_getchar(soap);
10343 if ((int)c == EOF)
10344 goto end;
10345 if (c >= 0x80 && state != 1 && !(soap->mode & SOAP_ENC_LATIN))
10346 { soap_unget(soap, c);
10347 c = soap_getutf8(soap);
10348 if (soap->mode & SOAP_C_UTFSTRING)
10349 { c &= 0x7FFFFFFF;
10350 t = buf;
10351 if (c < 0x0800)
10352 *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
10353 else
10354 { if (c < 0x010000)
10355 *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
10356 else
10357 { if (c < 0x200000)
10358 *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
10359 else
10360 { if (c < 0x04000000)
10361 *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
10362 else
10363 { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
10364 *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
10366 *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
10368 *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
10370 *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
10372 *t++ = (char)(0x80 | (c & 0x3F));
10373 m = (int)(t - buf) - 1;
10374 t = buf;
10375 *s++ = *t++;
10376 continue;
10379 switch (state)
10380 { case 1:
10381 if (c == ']')
10382 state = 4;
10383 *s++ = c;
10384 continue;
10385 case 2:
10386 if (c == '-')
10387 state = 6;
10388 *s++ = c;
10389 continue;
10390 case 3:
10391 if (c == '?')
10392 state = 8;
10393 *s++ = c;
10394 continue;
10395 /* CDATA */
10396 case 4:
10397 if (c == ']')
10398 state = 5;
10399 else
10400 state = 1;
10401 *s++ = c;
10402 continue;
10403 case 5:
10404 if (c == '>')
10405 state = 0;
10406 else
10407 state = 1;
10408 *s++ = c;
10409 continue;
10410 /* comment */
10411 case 6:
10412 if (c == '-')
10413 state = 7;
10414 else
10415 state = 2;
10416 *s++ = c;
10417 continue;
10418 case 7:
10419 if (c == '>')
10420 state = 0;
10421 else
10422 state = 2;
10423 *s++ = c;
10424 continue;
10425 /* PI */
10426 case 8:
10427 if (c == '>')
10428 state = 0;
10429 else
10430 state = 3;
10431 *s++ = c;
10432 continue;
10434 switch (c)
10436 case SOAP_TT:
10437 if (n == 0)
10438 goto end;
10439 n--;
10440 *s++ = '<';
10441 t = (char*)"/";
10442 m = 1;
10443 break;
10444 case SOAP_LT:
10445 if (f && n == 0)
10446 goto end;
10447 n++;
10448 *s++ = '<';
10449 break;
10450 case '/':
10451 if (n > 0)
10452 { c = soap_getchar(soap);
10453 if (c == '>')
10454 n--;
10455 soap_unget(soap, c);
10457 *s++ = '/';
10458 break;
10459 case '<':
10460 c = soap_getchar(soap);
10461 if (c == '/')
10462 { if (n == 0)
10463 { c = SOAP_TT;
10464 goto end;
10466 n--;
10468 else if (c == '!')
10469 { c = soap_getchar(soap);
10470 if (c == '[')
10471 { do c = soap_getchar(soap);
10472 while ((int)c != EOF && c != '[');
10473 if ((int)c == EOF)
10474 goto end;
10475 t = (char*)"![CDATA[";
10476 m = 8;
10477 state = 1;
10479 else if (c == '-')
10480 { if ((c = soap_getchar(soap)) == '-')
10481 state = 2;
10482 t = (char*)"!-";
10483 m = 2;
10484 soap_unget(soap, c);
10486 else
10487 { t = (char*)"!";
10488 m = 1;
10489 soap_unget(soap, c);
10491 *s++ = '<';
10492 break;
10494 else if (c == '?')
10495 state = 3;
10496 else if (f && n == 0)
10497 { soap_revget1(soap);
10498 c = '<';
10499 goto end;
10501 else
10502 n++;
10503 soap_unget(soap, c);
10504 *s++ = '<';
10505 break;
10506 case '>':
10507 *s++ = '>';
10508 break;
10509 case '"':
10510 *s++ = '"';
10511 break;
10512 default:
10513 #ifndef WITH_LEANER
10514 #ifdef HAVE_WCTOMB
10515 if (soap->mode & SOAP_C_MBSTRING)
10516 { m = wctomb(buf, c & 0x7FFFFFFF);
10517 if (m >= 1 && m <= (int)MB_CUR_MAX)
10518 { t = buf;
10519 *s++ = *t++;
10520 m--;
10522 else
10523 { *s++ = SOAP_UNKNOWN_CHAR;
10524 m = 0;
10527 else
10528 #endif
10529 #endif
10530 *s++ = (char)(c & 0xFF);
10532 l++;
10533 if (maxlen >= 0 && l > maxlen)
10534 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
10535 soap->error = SOAP_LENGTH;
10536 return NULL;
10541 #endif
10542 #ifdef WITH_FAST
10543 soap->labidx = 0; /* use look-aside buffer */
10544 #else
10545 if (soap_new_block(soap) == NULL)
10546 return NULL;
10547 #endif
10548 for (;;)
10550 #ifdef WITH_FAST
10551 register size_t k;
10552 if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */
10553 return NULL;
10554 s = soap->labbuf + soap->labidx; /* space to populate */
10555 k = soap->lablen - soap->labidx; /* number of bytes available */
10556 soap->labidx = soap->lablen; /* claim this space */
10557 #else
10558 register size_t k = SOAP_BLKLEN;
10559 if (!(s = (char*)soap_push_block(soap, NULL, k)))
10560 return NULL;
10561 #endif
10562 for (i = 0; i < k; i++)
10563 { if (m > 0)
10564 { *s++ = *t++; /* copy multibyte characters */
10565 m--;
10566 continue;
10568 if (soap->mode & SOAP_C_UTFSTRING)
10569 { if (((c = soap_get(soap)) & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP)
10570 { c &= 0x7FFFFFFF;
10571 t = buf;
10572 if (c < 0x0800)
10573 *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
10574 else
10575 { if (c < 0x010000)
10576 *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
10577 else
10578 { if (c < 0x200000)
10579 *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
10580 else
10581 { if (c < 0x04000000)
10582 *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
10583 else
10584 { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
10585 *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
10587 *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
10589 *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
10591 *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
10593 *t++ = (char)(0x80 | (c & 0x3F));
10594 m = (int)(t - buf) - 1;
10595 t = buf;
10596 *s++ = *t++;
10597 continue;
10600 else
10601 c = soap_getutf8(soap);
10602 switch (c)
10604 case SOAP_TT:
10605 if (n == 0)
10606 goto end;
10607 n--;
10608 *s++ = '<';
10609 t = (char*)"/";
10610 m = 1;
10611 break;
10612 case SOAP_LT:
10613 if (f && n == 0)
10614 goto end;
10615 n++;
10616 *s++ = '<';
10617 break;
10618 case SOAP_GT:
10619 *s++ = '>';
10620 break;
10621 case SOAP_QT:
10622 *s++ = '"';
10623 break;
10624 case SOAP_AP:
10625 *s++ = '\'';
10626 break;
10627 case '/':
10628 if (n > 0)
10629 { c = soap_get(soap);
10630 if (c == SOAP_GT)
10631 n--;
10632 soap_unget(soap, c);
10634 *s++ = '/';
10635 break;
10636 case (soap_wchar)('<' | 0x80000000):
10637 if (flag)
10638 *s++ = '<';
10639 else
10640 { *s++ = '&';
10641 t = (char*)"lt;";
10642 m = 3;
10644 break;
10645 case (soap_wchar)('>' | 0x80000000):
10646 if (flag)
10647 *s++ = '>';
10648 else
10649 { *s++ = '&';
10650 t = (char*)"gt;";
10651 m = 3;
10653 break;
10654 case (soap_wchar)('&' | 0x80000000):
10655 if (flag)
10656 *s++ = '&';
10657 else
10658 { *s++ = '&';
10659 t = (char*)"amp;";
10660 m = 4;
10662 break;
10663 case (soap_wchar)('"' | 0x80000000):
10664 if (flag)
10665 *s++ = '"';
10666 else
10667 { *s++ = '&';
10668 t = (char*)"quot;";
10669 m = 5;
10671 break;
10672 case (soap_wchar)('\'' | 0x80000000):
10673 if (flag)
10674 *s++ = '\'';
10675 else
10676 { *s++ = '&';
10677 t = (char*)"apos;";
10678 m = 5;
10680 break;
10681 default:
10682 if ((int)c == EOF)
10683 goto end;
10684 #ifndef WITH_LEANER
10685 #ifdef HAVE_WCTOMB
10686 if (soap->mode & SOAP_C_MBSTRING)
10687 { m = wctomb(buf, c & 0x7FFFFFFF);
10688 if (m >= 1 && m <= (int)MB_CUR_MAX)
10689 { t = buf;
10690 *s++ = *t++;
10691 m--;
10693 else
10694 { *s++ = SOAP_UNKNOWN_CHAR;
10695 m = 0;
10698 else
10699 #endif
10700 #endif
10701 *s++ = (char)(c & 0xFF);
10703 l++;
10704 if (maxlen >= 0 && l > maxlen)
10705 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
10706 soap->error = SOAP_LENGTH;
10707 return NULL;
10711 end:
10712 soap_unget(soap, c);
10713 *s = '\0';
10714 #ifdef WITH_FAST
10715 t = soap_strdup(soap, soap->labbuf);
10716 #else
10717 soap_size_block(soap, NULL, i+1);
10718 t = soap_save_block(soap, NULL, 0);
10719 #endif
10720 if (l < minlen)
10721 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen));
10722 soap->error = SOAP_LENGTH;
10723 return NULL;
10725 #ifdef WITH_DOM
10726 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
10727 { if (flag == 3)
10728 soap->dom->tail = t;
10729 else
10730 soap->dom->data = t;
10732 #endif
10733 if (flag == 2)
10734 if (soap_s2QName(soap, t, &t, minlen, maxlen))
10735 return NULL;
10736 return t;
10738 #endif
10740 /******************************************************************************/
10741 #ifndef WITH_LEANER
10742 #ifndef PALM_2
10743 SOAP_FMAC1
10745 SOAP_FMAC2
10746 soap_wstring_out(struct soap *soap, const wchar_t *s, int flag)
10747 { const char *t;
10748 char tmp;
10749 register soap_wchar c;
10750 #ifdef WITH_DOM
10751 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
10752 { wchar_t *r = (wchar_t*)s;
10753 int n = 1;
10754 while (*r++)
10755 n++;
10756 soap->dom->wide = r = (wchar_t*)soap_malloc(soap, n * sizeof(wchar_t));
10757 while (n--)
10758 *r++ = *s++;
10759 return SOAP_OK;
10761 #endif
10762 while ((c = *s++))
10763 { switch (c)
10765 case 0x09:
10766 if (flag)
10767 t = "&#x9;";
10768 else
10769 t = "\t";
10770 break;
10771 case 0x0A:
10772 if (flag || !(soap->mode & SOAP_XML_CANONICAL))
10773 t = "&#xA;";
10774 else
10775 t = "\n";
10776 break;
10777 case 0x0D:
10778 t = "&#xD;";
10779 break;
10780 case '&':
10781 t = "&amp;";
10782 break;
10783 case '<':
10784 t = "&lt;";
10785 break;
10786 case '>':
10787 if (flag)
10788 t = ">";
10789 else
10790 t = "&gt;";
10791 break;
10792 case '"':
10793 if (flag)
10794 t = "&quot;";
10795 else
10796 t = "\"";
10797 break;
10798 default:
10799 if (c >= 0x20 && c < 0x80)
10800 { tmp = (char)c;
10801 if (soap_send_raw(soap, &tmp, 1))
10802 return soap->error;
10804 else if (soap_pututf8(soap, (unsigned long)c))
10805 return soap->error;
10806 continue;
10808 if (soap_send(soap, t))
10809 return soap->error;
10811 return SOAP_OK;
10813 #endif
10814 #endif
10816 /******************************************************************************/
10817 #ifndef WITH_LEANER
10818 #ifndef PALM_2
10819 SOAP_FMAC1
10820 wchar_t *
10821 SOAP_FMAC2
10822 soap_wstring_in(struct soap *soap, int flag, long minlen, long maxlen)
10823 { wchar_t *s;
10824 register int i, n = 0, f = 0;
10825 register long l = 0;
10826 register soap_wchar c;
10827 char *t = NULL;
10828 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading wide string content\n"));
10829 if (soap->peeked)
10830 { if (*soap->tag)
10832 #ifndef WITH_LEAN
10833 struct soap_attribute *tp;
10834 t = soap->tmpbuf;
10835 *t = '<';
10836 t[sizeof(soap->tmpbuf)-1] = '\0';
10837 strncpy(t + 1, soap->tag, sizeof(soap->tmpbuf) - 2);
10838 t += strlen(t);
10839 for (tp = soap->attributes; tp; tp = tp->next)
10840 { if (tp->visible)
10841 { if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2)
10842 break;
10843 *t++ = ' ';
10844 strcpy(t, tp->name);
10845 t += strlen(t);
10846 if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2)
10847 break;
10848 if (tp->value)
10849 { *t++ = '=';
10850 *t++ = '"';
10851 strcpy(t, tp->value);
10852 t += strlen(t);
10853 *t++ = '"';
10857 if (!soap->body)
10858 *t++ = '/';
10859 *t++ = '>';
10860 *t = '\0';
10861 t = soap->tmpbuf;
10862 #endif
10863 if (soap->body)
10864 n = 1;
10865 f = 1;
10866 soap->peeked = 0;
10869 if (soap_new_block(soap) == NULL)
10870 return NULL;
10871 for (;;)
10872 { if (!(s = (wchar_t*)soap_push_block(soap, NULL, sizeof(wchar_t)*SOAP_BLKLEN)))
10873 return NULL;
10874 for (i = 0; i < SOAP_BLKLEN; i++)
10875 { if (t)
10876 { *s++ = (wchar_t)*t++;
10877 if (!*t)
10878 t = NULL;
10879 continue;
10881 c = soap_getutf8(soap);
10882 switch (c)
10884 case SOAP_TT:
10885 if (n == 0)
10886 goto end;
10887 n--;
10888 *s++ = '<';
10889 soap_unget(soap, '/');
10890 break;
10891 case SOAP_LT:
10892 if (f && n == 0)
10893 goto end;
10894 n++;
10895 *s++ = '<';
10896 break;
10897 case SOAP_GT:
10898 *s++ = '>';
10899 break;
10900 case SOAP_QT:
10901 *s++ = '"';
10902 break;
10903 case SOAP_AP:
10904 *s++ = '\'';
10905 break;
10906 case '/':
10907 if (n > 0)
10908 { c = soap_getutf8(soap);
10909 if (c == SOAP_GT)
10910 n--;
10911 soap_unget(soap, c);
10913 *s++ = '/';
10914 break;
10915 case '<':
10916 if (flag)
10917 *s++ = (soap_wchar)'<';
10918 else
10919 { *s++ = (soap_wchar)'&';
10920 t = (char*)"lt;";
10922 break;
10923 case '>':
10924 if (flag)
10925 *s++ = (soap_wchar)'>';
10926 else
10927 { *s++ = (soap_wchar)'&';
10928 t = (char*)"gt;";
10930 break;
10931 case '"':
10932 if (flag)
10933 *s++ = (soap_wchar)'"';
10934 else
10935 { *s++ = (soap_wchar)'&';
10936 t = (char*)"quot;";
10938 break;
10939 default:
10940 if ((int)c == EOF)
10941 goto end;
10942 *s++ = (wchar_t)c & 0x7FFFFFFF;
10944 l++;
10945 if (maxlen >= 0 && l > maxlen)
10946 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
10947 soap->error = SOAP_LENGTH;
10948 return NULL;
10952 end:
10953 soap_unget(soap, c);
10954 *s = '\0';
10955 soap_size_block(soap, NULL, sizeof(wchar_t) * (i + 1));
10956 if (l < minlen)
10957 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen));
10958 soap->error = SOAP_LENGTH;
10959 return NULL;
10961 s = (wchar_t*)soap_save_block(soap, NULL, NULL, 0);
10962 #ifdef WITH_DOM
10963 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
10964 soap->dom->wide = s;
10965 #endif
10966 return s;
10968 #endif
10969 #endif
10971 /******************************************************************************/
10972 #ifndef PALM_2
10973 SOAP_FMAC1
10974 const char*
10975 SOAP_FMAC2
10976 soap_int2s(struct soap *soap, int n)
10977 { return soap_long2s(soap, (long)n);
10979 #endif
10981 /******************************************************************************/
10982 #ifndef PALM_2
10983 SOAP_FMAC1
10985 SOAP_FMAC2
10986 soap_outint(struct soap *soap, const char *tag, int id, const int *p, const char *type, int n)
10987 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
10988 || soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
10989 return soap->error;
10990 return soap_element_end_out(soap, tag);
10992 #endif
10994 /******************************************************************************/
10995 #ifndef PALM_2
10996 SOAP_FMAC1
10998 SOAP_FMAC2
10999 soap_s2int(struct soap *soap, const char *s, int *p)
11000 { if (s)
11001 { char *r;
11002 #ifndef WITH_NOIO
11003 #ifndef WITH_LEAN
11004 soap_reset_errno;
11005 #endif
11006 #endif
11007 *p = (int)soap_strtol(s, &r, 10);
11008 if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
11009 #ifndef WITH_NOIO
11010 #ifndef WITH_LEAN
11011 || soap_errno == SOAP_ERANGE
11012 #endif
11013 #endif
11015 soap->error = SOAP_TYPE;
11017 return soap->error;
11019 #endif
11021 /******************************************************************************/
11022 #ifndef PALM_2
11023 SOAP_FMAC1
11024 int *
11025 SOAP_FMAC2
11026 soap_inint(struct soap *soap, const char *tag, int *p, const char *type, int t)
11027 { if (soap_element_begin_in(soap, tag, 0, NULL))
11028 return NULL;
11029 #ifndef WITH_LEAN
11030 if (*soap->type
11031 && soap_match_tag(soap, soap->type, type)
11032 && soap_match_tag(soap, soap->type, ":int")
11033 && soap_match_tag(soap, soap->type, ":short")
11034 && soap_match_tag(soap, soap->type, ":byte"))
11035 { soap->error = SOAP_TYPE;
11036 soap_revert(soap);
11037 return NULL;
11039 #endif
11040 p = (int*)soap_id_enter(soap, soap->id, p, t, sizeof(int), 0, NULL, NULL, NULL);
11041 if (*soap->href)
11042 p = (int*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(int), 0, NULL);
11043 else if (p)
11044 { if (soap_s2int(soap, soap_value(soap), p))
11045 return NULL;
11047 if (soap->body && soap_element_end_in(soap, tag))
11048 return NULL;
11049 return p;
11051 #endif
11053 /******************************************************************************/
11054 #ifndef PALM_2
11055 SOAP_FMAC1
11056 const char*
11057 SOAP_FMAC2
11058 soap_long2s(struct soap *soap, long n)
11059 { sprintf(soap->tmpbuf, "%ld", n);
11060 return soap->tmpbuf;
11062 #endif
11064 /******************************************************************************/
11065 #ifndef PALM_2
11066 SOAP_FMAC1
11068 SOAP_FMAC2
11069 soap_outlong(struct soap *soap, const char *tag, int id, const long *p, const char *type, int n)
11070 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
11071 || soap_string_out(soap, soap_long2s(soap, *p), 0))
11072 return soap->error;
11073 return soap_element_end_out(soap, tag);
11075 #endif
11077 /******************************************************************************/
11078 #ifndef PALM_2
11079 SOAP_FMAC1
11081 SOAP_FMAC2
11082 soap_s2long(struct soap *soap, const char *s, long *p)
11083 { if (s)
11084 { char *r;
11085 #ifndef WITH_NOIO
11086 #ifndef WITH_LEAN
11087 soap_reset_errno;
11088 #endif
11089 #endif
11090 *p = soap_strtol(s, &r, 10);
11091 if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
11092 #ifndef WITH_NOIO
11093 #ifndef WITH_LEAN
11094 || soap_errno == SOAP_ERANGE
11095 #endif
11096 #endif
11098 soap->error = SOAP_TYPE;
11100 return soap->error;
11102 #endif
11104 /******************************************************************************/
11105 #ifndef PALM_2
11106 SOAP_FMAC1
11107 long *
11108 SOAP_FMAC2
11109 soap_inlong(struct soap *soap, const char *tag, long *p, const char *type, int t)
11110 { if (soap_element_begin_in(soap, tag, 0, NULL))
11111 return NULL;
11112 #ifndef WITH_LEAN
11113 if (*soap->type
11114 && soap_match_tag(soap, soap->type, type)
11115 && soap_match_tag(soap, soap->type, ":int")
11116 && soap_match_tag(soap, soap->type, ":short")
11117 && soap_match_tag(soap, soap->type, ":byte"))
11118 { soap->error = SOAP_TYPE;
11119 soap_revert(soap);
11120 return NULL;
11122 #endif
11123 p = (long*)soap_id_enter(soap, soap->id, p, t, sizeof(long), 0, NULL, NULL, NULL);
11124 if (*soap->href)
11125 p = (long*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(long), 0, NULL);
11126 else if (p)
11127 { if (soap_s2long(soap, soap_value(soap), p))
11128 return NULL;
11130 if (soap->body && soap_element_end_in(soap, tag))
11131 return NULL;
11132 return p;
11134 #endif
11136 /******************************************************************************/
11137 #ifndef WITH_LEAN
11138 SOAP_FMAC1
11139 const char*
11140 SOAP_FMAC2
11141 soap_LONG642s(struct soap *soap, LONG64 n)
11142 { sprintf(soap->tmpbuf, SOAP_LONG_FORMAT, n);
11143 return soap->tmpbuf;
11145 #endif
11147 /******************************************************************************/
11148 #ifndef WITH_LEAN
11149 SOAP_FMAC1
11151 SOAP_FMAC2
11152 soap_outLONG64(struct soap *soap, const char *tag, int id, const LONG64 *p, const char *type, int n)
11153 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
11154 || soap_string_out(soap, soap_LONG642s(soap, *p), 0))
11155 return soap->error;
11156 return soap_element_end_out(soap, tag);
11158 #endif
11160 /******************************************************************************/
11161 #ifndef WITH_LEAN
11162 SOAP_FMAC1
11164 SOAP_FMAC2
11165 soap_s2LONG64(struct soap *soap, const char *s, LONG64 *p)
11166 { if (s)
11168 #ifdef HAVE_STRTOLL
11169 char *r;
11170 #ifndef WITH_NOIO
11171 #ifndef WITH_LEAN
11172 soap_reset_errno;
11173 #endif
11174 #endif
11175 *p = strtoll(s, &r, 10);
11176 if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
11177 #ifndef WITH_NOIO
11178 #ifndef WITH_LEAN
11179 || soap_errno == SOAP_ERANGE
11180 #endif
11181 #endif
11183 #else
11184 # ifdef HAVE_SSCANF
11185 if (sscanf(s, SOAP_LONG_FORMAT, p) != 1)
11186 # endif
11187 #endif
11188 soap->error = SOAP_TYPE;
11190 return soap->error;
11192 #endif
11194 /******************************************************************************/
11195 #ifndef WITH_LEAN
11196 SOAP_FMAC1
11197 LONG64 *
11198 SOAP_FMAC2
11199 soap_inLONG64(struct soap *soap, const char *tag, LONG64 *p, const char *type, int t)
11200 { if (soap_element_begin_in(soap, tag, 0, NULL))
11201 return NULL;
11202 #ifndef WITH_LEAN
11203 if (*soap->type
11204 && soap_match_tag(soap, soap->type, type)
11205 && soap_match_tag(soap, soap->type, ":integer")
11206 && soap_match_tag(soap, soap->type, ":positiveInteger")
11207 && soap_match_tag(soap, soap->type, ":negativeInteger")
11208 && soap_match_tag(soap, soap->type, ":nonPositiveInteger")
11209 && soap_match_tag(soap, soap->type, ":nonNegativeInteger")
11210 && soap_match_tag(soap, soap->type, ":long")
11211 && soap_match_tag(soap, soap->type, ":int")
11212 && soap_match_tag(soap, soap->type, ":short")
11213 && soap_match_tag(soap, soap->type, ":byte"))
11214 { soap->error = SOAP_TYPE;
11215 soap_revert(soap);
11216 return NULL;
11218 #endif
11219 p = (LONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(LONG64), 0, NULL, NULL, NULL);
11220 if (*soap->href)
11221 p = (LONG64*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(LONG64), 0, NULL);
11222 else if (p)
11223 { if (soap_s2LONG64(soap, soap_value(soap), p))
11224 return NULL;
11226 if (soap->body && soap_element_end_in(soap, tag))
11227 return NULL;
11228 return p;
11230 #endif
11232 /******************************************************************************/
11233 #ifndef PALM_2
11234 SOAP_FMAC1
11235 const char*
11236 SOAP_FMAC2
11237 soap_byte2s(struct soap *soap, char n)
11238 { return soap_long2s(soap, (long)n);
11240 #endif
11242 /******************************************************************************/
11243 #ifndef PALM_2
11244 SOAP_FMAC1
11246 SOAP_FMAC2
11247 soap_outbyte(struct soap *soap, const char *tag, int id, const char *p, const char *type, int n)
11248 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
11249 || soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
11250 return soap->error;
11251 return soap_element_end_out(soap, tag);
11253 #endif
11255 /******************************************************************************/
11256 #ifndef PALM_2
11257 SOAP_FMAC1
11259 SOAP_FMAC2
11260 soap_s2byte(struct soap *soap, const char *s, char *p)
11261 { if (s)
11262 { long n;
11263 char *r;
11264 n = soap_strtol(s, &r, 10);
11265 if (s == r || *r || n < -128 || n > 127)
11266 soap->error = SOAP_TYPE;
11267 *p = (char)n;
11269 return soap->error;
11271 #endif
11273 /******************************************************************************/
11274 #ifndef PALM_2
11275 SOAP_FMAC1
11276 char *
11277 SOAP_FMAC2
11278 soap_inbyte(struct soap *soap, const char *tag, char *p, const char *type, int t)
11279 { if (soap_element_begin_in(soap, tag, 0, NULL))
11280 return NULL;
11281 #ifndef WITH_LEAN
11282 if (*soap->type
11283 && soap_match_tag(soap, soap->type, type)
11284 && soap_match_tag(soap, soap->type, ":byte"))
11285 { soap->error = SOAP_TYPE;
11286 soap_revert(soap);
11287 return NULL;
11289 #endif
11290 p = (char*)soap_id_enter(soap, soap->id, p, t, sizeof(char), 0, NULL, NULL, NULL);
11291 if (*soap->href)
11292 p = (char*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(char), 0, NULL);
11293 else if (p)
11294 { if (soap_s2byte(soap, soap_value(soap), p))
11295 return NULL;
11297 if (soap->body && soap_element_end_in(soap, tag))
11298 return NULL;
11299 return p;
11301 #endif
11303 /******************************************************************************/
11304 #ifndef PALM_2
11305 SOAP_FMAC1
11306 const char*
11307 SOAP_FMAC2
11308 soap_short2s(struct soap *soap, short n)
11309 { return soap_long2s(soap, (long)n);
11311 #endif
11313 /******************************************************************************/
11314 #ifndef PALM_2
11315 SOAP_FMAC1
11317 SOAP_FMAC2
11318 soap_outshort(struct soap *soap, const char *tag, int id, const short *p, const char *type, int n)
11319 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
11320 || soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
11321 return soap->error;
11322 return soap_element_end_out(soap, tag);
11324 #endif
11326 /******************************************************************************/
11327 #ifndef PALM_2
11328 SOAP_FMAC1
11330 SOAP_FMAC2
11331 soap_s2short(struct soap *soap, const char *s, short *p)
11332 { if (s)
11333 { long n;
11334 char *r;
11335 n = soap_strtol(s, &r, 10);
11336 if (s == r || *r || n < -32768 || n > 32767)
11337 soap->error = SOAP_TYPE;
11338 *p = (short)n;
11340 return soap->error;
11342 #endif
11344 /******************************************************************************/
11345 #ifndef PALM_2
11346 SOAP_FMAC1
11347 short *
11348 SOAP_FMAC2
11349 soap_inshort(struct soap *soap, const char *tag, short *p, const char *type, int t)
11350 { if (soap_element_begin_in(soap, tag, 0, NULL))
11351 return NULL;
11352 #ifndef WITH_LEAN
11353 if (*soap->type
11354 && soap_match_tag(soap, soap->type, type)
11355 && soap_match_tag(soap, soap->type, ":short")
11356 && soap_match_tag(soap, soap->type, ":byte"))
11357 { soap->error = SOAP_TYPE;
11358 soap_revert(soap);
11359 return NULL;
11361 #endif
11362 p = (short*)soap_id_enter(soap, soap->id, p, t, sizeof(short), 0, NULL, NULL, NULL);
11363 if (*soap->href)
11364 p = (short*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(short), 0, NULL);
11365 else if (p)
11366 { if (soap_s2short(soap, soap_value(soap), p))
11367 return NULL;
11369 if (soap->body && soap_element_end_in(soap, tag))
11370 return NULL;
11371 return p;
11373 #endif
11375 /******************************************************************************/
11376 #ifndef PALM_2
11377 SOAP_FMAC1
11378 const char*
11379 SOAP_FMAC2
11380 soap_float2s(struct soap *soap, float n)
11381 { char *s;
11382 if (soap_isnan((double)n))
11383 return "NaN";
11384 if (soap_ispinff(n))
11385 return "INF";
11386 if (soap_isninff(n))
11387 return "-INF";
11388 s = soap->tmpbuf;
11389 #if defined(HAVE_SPRINTF_L)
11390 sprintf_l(s, soap->c_locale, soap->float_format, n);
11391 #else
11392 sprintf(s, soap->float_format, n);
11393 s = strchr(s, ','); /* convert decimal comma to DP */
11394 if (s)
11395 *s = '.';
11396 #endif
11397 return soap->tmpbuf;
11399 #endif
11401 /******************************************************************************/
11402 #ifndef PALM_2
11403 SOAP_FMAC1
11405 SOAP_FMAC2
11406 soap_outfloat(struct soap *soap, const char *tag, int id, const float *p, const char *type, int n)
11407 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
11408 || soap_string_out(soap, soap_float2s(soap, *p), 0))
11409 return soap->error;
11410 return soap_element_end_out(soap, tag);
11412 #endif
11414 /******************************************************************************/
11415 #ifndef PALM_2
11416 SOAP_FMAC1
11418 SOAP_FMAC2
11419 soap_s2float(struct soap *soap, const char *s, float *p)
11420 { if (s)
11421 { if (!*s)
11422 return soap->error = SOAP_TYPE;
11423 if (!soap_tag_cmp(s, "INF"))
11424 *p = FLT_PINFTY;
11425 else if (!soap_tag_cmp(s, "+INF"))
11426 *p = FLT_PINFTY;
11427 else if (!soap_tag_cmp(s, "-INF"))
11428 *p = FLT_NINFTY;
11429 else if (!soap_tag_cmp(s, "NaN"))
11430 *p = FLT_NAN;
11431 else
11433 /* On some systems strtof requires -std=c99 or does not even link: so we try to use strtod first */
11434 #if defined(HAVE_STRTOD_L)
11435 char *r;
11436 *p = (float)strtod_l(s, &r, soap->c_locale);
11437 if (*r)
11438 #elif defined(HAVE_STRTOD)
11439 char *r;
11440 *p = (float)strtod(s, &r);
11441 if (*r)
11442 #elif defined(HAVE_STRTOF_L)
11443 char *r;
11444 *p = strtof_l((char*)s, &r, soap->c_locale);
11445 if (*r)
11446 #elif defined(HAVE_STRTOF)
11447 char *r;
11448 *p = strtof((char*)s, &r);
11449 if (*r)
11450 #endif
11452 #if defined(HAVE_SSCANF_L) && !defined(HAVE_STRTOF_L) && !defined(HAVE_STRTOD_L)
11453 if (sscanf_l(s, soap->c_locale, "%g", p) != 1)
11454 soap->error = SOAP_TYPE;
11455 #elif defined(HAVE_SSCANF)
11456 if (sscanf(s, "%g", p) != 1)
11457 soap->error = SOAP_TYPE;
11458 #else
11459 soap->error = SOAP_TYPE;
11460 #endif
11464 return soap->error;
11466 #endif
11468 /******************************************************************************/
11469 #ifndef WITH_LEAN
11470 static int soap_isnumeric(struct soap *soap, const char *type)
11471 { if (soap_match_tag(soap, soap->type, type)
11472 && soap_match_tag(soap, soap->type, ":float")
11473 && soap_match_tag(soap, soap->type, ":double")
11474 && soap_match_tag(soap, soap->type, ":decimal")
11475 && soap_match_tag(soap, soap->type, ":integer")
11476 && soap_match_tag(soap, soap->type, ":positiveInteger")
11477 && soap_match_tag(soap, soap->type, ":negativeInteger")
11478 && soap_match_tag(soap, soap->type, ":nonPositiveInteger")
11479 && soap_match_tag(soap, soap->type, ":nonNegativeInteger")
11480 && soap_match_tag(soap, soap->type, ":long")
11481 && soap_match_tag(soap, soap->type, ":int")
11482 && soap_match_tag(soap, soap->type, ":short")
11483 && soap_match_tag(soap, soap->type, ":byte")
11484 && soap_match_tag(soap, soap->type, ":unsignedLong")
11485 && soap_match_tag(soap, soap->type, ":unsignedInt")
11486 && soap_match_tag(soap, soap->type, ":unsignedShort")
11487 && soap_match_tag(soap, soap->type, ":unsignedByte"))
11488 { soap->error = SOAP_TYPE;
11489 soap_revert(soap);
11490 return SOAP_ERR;
11492 return SOAP_OK;
11494 #endif
11496 /******************************************************************************/
11497 #ifndef PALM_2
11498 SOAP_FMAC1
11499 float *
11500 SOAP_FMAC2
11501 soap_infloat(struct soap *soap, const char *tag, float *p, const char *type, int t)
11502 { if (soap_element_begin_in(soap, tag, 0, NULL))
11503 return NULL;
11504 #ifndef WITH_LEAN
11505 if (*soap->type != '\0' && soap_isnumeric(soap, type))
11506 return NULL;
11507 #endif
11508 p = (float*)soap_id_enter(soap, soap->id, p, t, sizeof(float), 0, NULL, NULL, NULL);
11509 if (*soap->href)
11510 p = (float*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(float), 0, NULL);
11511 else if (p)
11512 { if (soap_s2float(soap, soap_value(soap), p))
11513 return NULL;
11515 if (soap->body && soap_element_end_in(soap, tag))
11516 return NULL;
11517 return p;
11519 #endif
11521 /******************************************************************************/
11522 #ifndef PALM_2
11523 SOAP_FMAC1
11524 const char*
11525 SOAP_FMAC2
11526 soap_double2s(struct soap *soap, double n)
11527 { char *s;
11528 if (soap_isnan(n))
11529 return "NaN";
11530 if (soap_ispinfd(n))
11531 return "INF";
11532 if (soap_isninfd(n))
11533 return "-INF";
11534 s = soap->tmpbuf;
11535 #if defined(HAVE_SPRINTF_L)
11536 sprintf_l(s, soap->c_locale, soap->double_format, n);
11537 #else
11538 sprintf(s, soap->double_format, n);
11539 s = strchr(s, ','); /* convert decimal comma to DP */
11540 if (s)
11541 *s = '.';
11542 #endif
11543 return soap->tmpbuf;
11545 #endif
11547 /******************************************************************************/
11548 #ifndef PALM_2
11549 SOAP_FMAC1
11551 SOAP_FMAC2
11552 soap_outdouble(struct soap *soap, const char *tag, int id, const double *p, const char *type, int n)
11553 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
11554 || soap_string_out(soap, soap_double2s(soap, *p), 0))
11555 return soap->error;
11556 return soap_element_end_out(soap, tag);
11558 #endif
11560 /******************************************************************************/
11561 #ifndef PALM_2
11562 SOAP_FMAC1
11564 SOAP_FMAC2
11565 soap_s2double(struct soap *soap, const char *s, double *p)
11566 { if (s)
11567 { if (!*s)
11568 return soap->error = SOAP_TYPE;
11569 if (!soap_tag_cmp(s, "INF"))
11570 *p = DBL_PINFTY;
11571 else if (!soap_tag_cmp(s, "+INF"))
11572 *p = DBL_PINFTY;
11573 else if (!soap_tag_cmp(s, "-INF"))
11574 *p = DBL_NINFTY;
11575 else if (!soap_tag_cmp(s, "NaN"))
11576 *p = DBL_NAN;
11577 else
11579 #if defined(HAVE_STRTOD_L)
11580 char *r;
11581 *p = strtod_l(s, &r, soap->c_locale);
11582 if (*r)
11583 #elif defined(HAVE_STRTOD)
11584 char *r;
11585 *p = strtod(s, &r);
11586 if (*r)
11587 #endif
11589 #if defined(HAVE_SSCANF_L) && !defined(HAVE_STRTOF_L) && !defined(HAVE_STRTOD_L)
11590 if (sscanf_l(s, soap->c_locale, "%lg", p) != 1)
11591 soap->error = SOAP_TYPE;
11592 #elif defined(HAVE_SSCANF)
11593 if (sscanf(s, "%lg", p) != 1)
11594 soap->error = SOAP_TYPE;
11595 #else
11596 soap->error = SOAP_TYPE;
11597 #endif
11601 return soap->error;
11603 #endif
11605 /******************************************************************************/
11606 #ifndef PALM_2
11607 SOAP_FMAC1
11608 double *
11609 SOAP_FMAC2
11610 soap_indouble(struct soap *soap, const char *tag, double *p, const char *type, int t)
11611 { if (soap_element_begin_in(soap, tag, 0, NULL))
11612 return NULL;
11613 #ifndef WITH_LEAN
11614 if (*soap->type != '\0' && soap_isnumeric(soap, type))
11615 return NULL;
11616 #endif
11617 p = (double*)soap_id_enter(soap, soap->id, p, t, sizeof(double), 0, NULL, NULL, NULL);
11618 if (*soap->href)
11619 p = (double*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(double), 0, NULL);
11620 else if (p)
11621 { if (soap_s2double(soap, soap_value(soap), p))
11622 return NULL;
11624 if (soap->body && soap_element_end_in(soap, tag))
11625 return NULL;
11626 return p;
11628 #endif
11630 /******************************************************************************/
11631 #ifndef PALM_2
11632 SOAP_FMAC1
11633 const char*
11634 SOAP_FMAC2
11635 soap_unsignedByte2s(struct soap *soap, unsigned char n)
11636 { return soap_unsignedLong2s(soap, (unsigned long)n);
11638 #endif
11640 /******************************************************************************/
11641 #ifndef PALM_2
11642 SOAP_FMAC1
11644 SOAP_FMAC2
11645 soap_outunsignedByte(struct soap *soap, const char *tag, int id, const unsigned char *p, const char *type, int n)
11646 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
11647 || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0))
11648 return soap->error;
11649 return soap_element_end_out(soap, tag);
11651 #endif
11653 /******************************************************************************/
11654 #ifndef PALM_2
11655 SOAP_FMAC1
11657 SOAP_FMAC2
11658 soap_s2unsignedByte(struct soap *soap, const char *s, unsigned char *p)
11659 { if (s)
11660 { unsigned long n;
11661 char *r;
11662 n = soap_strtoul(s, &r, 10);
11663 if (s == r || *r || n > 255)
11664 soap->error = SOAP_TYPE;
11665 *p = (unsigned char)n;
11667 return soap->error;
11669 #endif
11671 /******************************************************************************/
11672 #ifndef PALM_2
11673 SOAP_FMAC1
11674 unsigned char *
11675 SOAP_FMAC2
11676 soap_inunsignedByte(struct soap *soap, const char *tag, unsigned char *p, const char *type, int t)
11677 { if (soap_element_begin_in(soap, tag, 0, NULL))
11678 return NULL;
11679 #ifndef WITH_LEAN
11680 if (*soap->type
11681 && soap_match_tag(soap, soap->type, type)
11682 && soap_match_tag(soap, soap->type, ":unsignedByte"))
11683 { soap->error = SOAP_TYPE;
11684 soap_revert(soap);
11685 return NULL;
11687 #endif
11688 p = (unsigned char*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned char), 0, NULL, NULL, NULL);
11689 if (*soap->href)
11690 p = (unsigned char*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned char), 0, NULL);
11691 else if (p)
11692 { if (soap_s2unsignedByte(soap, soap_value(soap), p))
11693 return NULL;
11695 if (soap->body && soap_element_end_in(soap, tag))
11696 return NULL;
11697 return p;
11699 #endif
11701 /******************************************************************************/
11702 #ifndef PALM_2
11703 SOAP_FMAC1
11704 const char*
11705 SOAP_FMAC2
11706 soap_unsignedShort2s(struct soap *soap, unsigned short n)
11707 { return soap_unsignedLong2s(soap, (unsigned long)n);
11709 #endif
11711 /******************************************************************************/
11712 #ifndef PALM_2
11713 SOAP_FMAC1
11715 SOAP_FMAC2
11716 soap_outunsignedShort(struct soap *soap, const char *tag, int id, const unsigned short *p, const char *type, int n)
11717 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
11718 || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0))
11719 return soap->error;
11720 return soap_element_end_out(soap, tag);
11722 #endif
11724 /******************************************************************************/
11725 #ifndef PALM_2
11726 SOAP_FMAC1
11728 SOAP_FMAC2
11729 soap_s2unsignedShort(struct soap *soap, const char *s, unsigned short *p)
11730 { if (s)
11731 { unsigned long n;
11732 char *r;
11733 n = soap_strtoul(s, &r, 10);
11734 if (s == r || *r || n > 65535)
11735 soap->error = SOAP_TYPE;
11736 *p = (unsigned short)n;
11738 return soap->error;
11740 #endif
11742 /******************************************************************************/
11743 #ifndef PALM_2
11744 SOAP_FMAC1
11745 unsigned short *
11746 SOAP_FMAC2
11747 soap_inunsignedShort(struct soap *soap, const char *tag, unsigned short *p, const char *type, int t)
11748 { if (soap_element_begin_in(soap, tag, 0, NULL))
11749 return NULL;
11750 #ifndef WITH_LEAN
11751 if (*soap->type
11752 && soap_match_tag(soap, soap->type, type)
11753 && soap_match_tag(soap, soap->type, ":unsignedShort")
11754 && soap_match_tag(soap, soap->type, ":unsignedByte"))
11755 { soap->error = SOAP_TYPE;
11756 soap_revert(soap);
11757 return NULL;
11759 #endif
11760 p = (unsigned short*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned short), 0, NULL, NULL, NULL);
11761 if (*soap->href)
11762 p = (unsigned short*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned short), 0, NULL);
11763 else if (p)
11764 { if (soap_s2unsignedShort(soap, soap_value(soap), p))
11765 return NULL;
11767 if (soap->body && soap_element_end_in(soap, tag))
11768 return NULL;
11769 return p;
11771 #endif
11773 /******************************************************************************/
11774 #ifndef PALM_2
11775 SOAP_FMAC1
11776 const char*
11777 SOAP_FMAC2
11778 soap_unsignedInt2s(struct soap *soap, unsigned int n)
11779 { return soap_unsignedLong2s(soap, (unsigned long)n);
11781 #endif
11783 /******************************************************************************/
11784 #ifndef PALM_2
11785 SOAP_FMAC1
11787 SOAP_FMAC2
11788 soap_outunsignedInt(struct soap *soap, const char *tag, int id, const unsigned int *p, const char *type, int n)
11789 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
11790 || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0))
11791 return soap->error;
11792 return soap_element_end_out(soap, tag);
11794 #endif
11796 /******************************************************************************/
11797 #ifndef PALM_2
11798 SOAP_FMAC1
11800 SOAP_FMAC2
11801 soap_s2unsignedInt(struct soap *soap, const char *s, unsigned int *p)
11802 { if (s)
11803 { char *r;
11804 #ifndef WITH_NOIO
11805 #ifndef WITH_LEAN
11806 soap_reset_errno;
11807 #endif
11808 #endif
11809 *p = (unsigned int)soap_strtoul(s, &r, 10);
11810 if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
11811 #ifndef WITH_NOIO
11812 #ifndef WITH_LEAN
11813 || soap_errno == SOAP_ERANGE
11814 #endif
11815 #endif
11817 soap->error = SOAP_TYPE;
11819 return soap->error;
11821 #endif
11823 /******************************************************************************/
11824 #ifndef PALM_2
11825 SOAP_FMAC1
11826 unsigned int *
11827 SOAP_FMAC2
11828 soap_inunsignedInt(struct soap *soap, const char *tag, unsigned int *p, const char *type, int t)
11829 { if (soap_element_begin_in(soap, tag, 0, NULL))
11830 return NULL;
11831 #ifndef WITH_LEAN
11832 if (*soap->type
11833 && soap_match_tag(soap, soap->type, type)
11834 && soap_match_tag(soap, soap->type, ":unsignedInt")
11835 && soap_match_tag(soap, soap->type, ":unsignedShort")
11836 && soap_match_tag(soap, soap->type, ":unsignedByte"))
11837 { soap->error = SOAP_TYPE;
11838 soap_revert(soap);
11839 return NULL;
11841 #endif
11842 p = (unsigned int*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned int), 0, NULL, NULL, NULL);
11843 if (*soap->href)
11844 p = (unsigned int*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned int), 0, NULL);
11845 else if (p)
11846 { if (soap_s2unsignedInt(soap, soap_value(soap), p))
11847 return NULL;
11849 if (soap->body && soap_element_end_in(soap, tag))
11850 return NULL;
11851 return p;
11853 #endif
11855 /******************************************************************************/
11856 #ifndef PALM_2
11857 SOAP_FMAC1
11858 const char*
11859 SOAP_FMAC2
11860 soap_unsignedLong2s(struct soap *soap, unsigned long n)
11861 { sprintf(soap->tmpbuf, "%lu", n);
11862 return soap->tmpbuf;
11864 #endif
11866 /******************************************************************************/
11867 #ifndef PALM_2
11868 SOAP_FMAC1
11870 SOAP_FMAC2
11871 soap_outunsignedLong(struct soap *soap, const char *tag, int id, const unsigned long *p, const char *type, int n)
11872 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
11873 || soap_string_out(soap, soap_unsignedLong2s(soap, *p), 0))
11874 return soap->error;
11875 return soap_element_end_out(soap, tag);
11877 #endif
11879 /******************************************************************************/
11880 #ifndef PALM_2
11881 SOAP_FMAC1
11883 SOAP_FMAC2
11884 soap_s2unsignedLong(struct soap *soap, const char *s, unsigned long *p)
11885 { if (s)
11886 { char *r;
11887 #ifndef WITH_NOIO
11888 #ifndef WITH_LEAN
11889 soap_reset_errno;
11890 #endif
11891 #endif
11892 *p = soap_strtoul(s, &r, 10);
11893 if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
11894 #ifndef WITH_NOIO
11895 #ifndef WITH_LEAN
11896 || soap_errno == SOAP_ERANGE
11897 #endif
11898 #endif
11900 soap->error = SOAP_TYPE;
11902 return soap->error;
11904 #endif
11906 /******************************************************************************/
11907 #ifndef PALM_2
11908 SOAP_FMAC1
11909 unsigned long *
11910 SOAP_FMAC2
11911 soap_inunsignedLong(struct soap *soap, const char *tag, unsigned long *p, const char *type, int t)
11912 { if (soap_element_begin_in(soap, tag, 0, NULL))
11913 return NULL;
11914 #ifndef WITH_LEAN
11915 if (*soap->type
11916 && soap_match_tag(soap, soap->type, type)
11917 && soap_match_tag(soap, soap->type, ":unsignedInt")
11918 && soap_match_tag(soap, soap->type, ":unsignedShort")
11919 && soap_match_tag(soap, soap->type, ":unsignedByte"))
11920 { soap->error = SOAP_TYPE;
11921 soap_revert(soap);
11922 return NULL;
11924 #endif
11925 p = (unsigned long*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned long), 0, NULL, NULL, NULL);
11926 if (*soap->href)
11927 p = (unsigned long*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned long), 0, NULL);
11928 else if (p)
11929 { if (soap_s2unsignedLong(soap, soap_value(soap), p))
11930 return NULL;
11932 if (soap->body && soap_element_end_in(soap, tag))
11933 return NULL;
11934 return p;
11936 #endif
11938 /******************************************************************************/
11939 #ifndef WITH_LEAN
11940 SOAP_FMAC1
11941 const char*
11942 SOAP_FMAC2
11943 soap_ULONG642s(struct soap *soap, ULONG64 n)
11944 { sprintf(soap->tmpbuf, SOAP_ULONG_FORMAT, n);
11945 return soap->tmpbuf;
11947 #endif
11949 /******************************************************************************/
11950 #ifndef WITH_LEAN
11951 SOAP_FMAC1
11953 SOAP_FMAC2
11954 soap_outULONG64(struct soap *soap, const char *tag, int id, const ULONG64 *p, const char *type, int n)
11955 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
11956 || soap_string_out(soap, soap_ULONG642s(soap, *p), 0))
11957 return soap->error;
11958 return soap_element_end_out(soap, tag);
11960 #endif
11962 /******************************************************************************/
11963 #ifndef WITH_LEAN
11964 SOAP_FMAC1
11966 SOAP_FMAC2
11967 soap_s2ULONG64(struct soap *soap, const char *s, ULONG64 *p)
11968 { if (s)
11970 #ifdef HAVE_STRTOULL
11971 char *r;
11972 #ifndef WITH_NOIO
11973 #ifndef WITH_LEAN
11974 soap_reset_errno;
11975 #endif
11976 #endif
11977 *p = strtoull(s, &r, 10);
11978 if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
11979 #ifndef WITH_NOIO
11980 #ifndef WITH_LEAN
11981 || soap_errno == SOAP_ERANGE
11982 #endif
11983 #endif
11985 #else
11986 #ifdef HAVE_SSCANF
11987 if (sscanf(s, SOAP_ULONG_FORMAT, p) != 1)
11988 #endif
11989 #endif
11990 soap->error = SOAP_TYPE;
11992 return soap->error;
11994 #endif
11996 /******************************************************************************/
11997 #ifndef WITH_LEAN
11998 SOAP_FMAC1
11999 ULONG64 *
12000 SOAP_FMAC2
12001 soap_inULONG64(struct soap *soap, const char *tag, ULONG64 *p, const char *type, int t)
12002 { if (soap_element_begin_in(soap, tag, 0, NULL))
12003 return NULL;
12004 if (*soap->type
12005 && soap_match_tag(soap, soap->type, type)
12006 && soap_match_tag(soap, soap->type, ":positiveInteger")
12007 && soap_match_tag(soap, soap->type, ":nonNegativeInteger")
12008 && soap_match_tag(soap, soap->type, ":unsignedLong")
12009 && soap_match_tag(soap, soap->type, ":unsignedInt")
12010 && soap_match_tag(soap, soap->type, ":unsignedShort")
12011 && soap_match_tag(soap, soap->type, ":unsignedByte"))
12012 { soap->error = SOAP_TYPE;
12013 soap_revert(soap);
12014 return NULL;
12016 p = (ULONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(ULONG64), 0, NULL, NULL, NULL);
12017 if (*soap->href)
12018 p = (ULONG64*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(ULONG64), 0, NULL);
12019 else if (p)
12020 { if (soap_s2ULONG64(soap, soap_value(soap), p))
12021 return NULL;
12023 if (soap->body && soap_element_end_in(soap, tag))
12024 return NULL;
12025 return p;
12027 #endif
12029 /******************************************************************************/
12030 #ifndef PALM_2
12031 SOAP_FMAC1
12033 SOAP_FMAC2
12034 soap_s2string(struct soap *soap, const char *s, char **t, long minlen, long maxlen)
12035 { if (s)
12036 { long l = (long)strlen(s);
12037 if ((maxlen >= 0 && l > maxlen) || l < minlen)
12038 return soap->error = SOAP_LENGTH;
12039 if (!(*t = soap_strdup(soap, s)))
12040 return soap->error = SOAP_EOM;
12041 if (!(soap->mode & (SOAP_ENC_LATIN | SOAP_C_UTFSTRING)))
12042 { char *r = *t;
12043 /* remove non-ASCII chars */
12044 for (s = *t; *s; s++)
12045 if (!(*s & 0x80))
12046 *r++ = *s;
12047 *r = '\0';
12050 return soap->error;
12052 #endif
12054 /******************************************************************************/
12055 #ifndef PALM_2
12056 SOAP_FMAC1
12058 SOAP_FMAC2
12059 soap_s2QName(struct soap *soap, const char *s, char **t, long minlen, long maxlen)
12060 { if (s)
12061 { long l = (long)strlen(s);
12062 if ((maxlen >= 0 && l > maxlen) || l < minlen)
12063 return soap->error = SOAP_LENGTH;
12064 soap->labidx = 0;
12065 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Normalized namespace(s) of QNames '%s'", s));
12066 /* convert (by prefix normalize prefix) all QNames in s */
12067 for (;;)
12068 { size_t n;
12069 struct soap_nlist *np;
12070 register const char *p;
12071 /* skip blanks */
12072 while (*s && soap_blank(*s))
12073 s++;
12074 if (!*s)
12075 break;
12076 /* find next QName */
12077 n = 1;
12078 while (s[n] && !soap_blank(s[n]))
12079 n++;
12080 np = soap->nlist;
12081 /* if there is no namespace stack, or prefix is "xml" then copy string */
12082 if (!np || !strncmp(s, "xml:", 4))
12083 { soap_append_lab(soap, s, n);
12085 else /* we normalize the QName by replacing its prefix */
12086 { for (p = s; *p && p < s + n; p++)
12087 if (*p == ':')
12088 break;
12089 if (*p == ':')
12090 { size_t k = p - s;
12091 while (np && (strncmp(np->id, s, k) || np->id[k]))
12092 np = np->next;
12093 p++;
12095 else
12096 { while (np && *np->id)
12097 np = np->next;
12098 p = s;
12100 /* replace prefix */
12101 if (np)
12102 { if (np->index >= 0 && soap->local_namespaces)
12103 { const char *q = soap->local_namespaces[np->index].id;
12104 if (q)
12105 soap_append_lab(soap, q, strlen(q));
12107 else if (np->ns)
12108 { soap_append_lab(soap, "\"", 1);
12109 soap_append_lab(soap, np->ns, strlen(np->ns));
12110 soap_append_lab(soap, "\"", 1);
12112 else
12113 { 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));
12114 return soap->error = SOAP_NAMESPACE;
12117 else if (s[n]) /* no namespace, part of string */
12118 { soap_append_lab(soap, s, n);
12120 else /* no namespace: assume "" namespace */
12121 { soap_append_lab(soap, "\"\"", 2);
12123 soap_append_lab(soap, ":", 1);
12124 soap_append_lab(soap, p, n - (p-s));
12126 /* advance to next and add spacing */
12127 s += n;
12128 if (*s)
12129 soap_append_lab(soap, " ", 1);
12131 soap_append_lab(soap, SOAP_STR_EOS, 1);
12132 *t = soap_strdup(soap, soap->labbuf);
12133 DBGLOG(TEST, SOAP_MESSAGE(fdebug, " into '%s'\n", *t));
12135 return soap->error;
12137 #endif
12139 /******************************************************************************/
12140 #ifndef PALM_2
12141 SOAP_FMAC1
12142 const char*
12143 SOAP_FMAC2
12144 soap_QName2s(struct soap *soap, const char *s)
12145 { const char *t = NULL;
12146 if (s)
12147 { soap->labidx = 0;
12148 for (;;)
12149 { size_t n;
12150 /* skip blanks */
12151 while (*s && soap_blank(*s))
12152 s++;
12153 if (!*s)
12154 break;
12155 /* find next QName */
12156 n = 1;
12157 while (s[n] && !soap_blank(s[n]))
12158 n++;
12159 /* normal prefix: pass string as is */
12160 if (*s != '"')
12161 { soap_append_lab(soap, s, n);
12162 #ifndef WITH_LEAN
12163 if ((soap->mode & SOAP_XML_CANONICAL))
12164 { const char *r = strchr(s, ':');
12165 if (r)
12166 soap_utilize_ns(soap, s, r - s);
12168 #endif
12170 else /* URL-based string prefix */
12171 { const char *q;
12172 s++;
12173 q = strchr(s, '"');
12174 if (q)
12175 { struct Namespace *p = soap->local_namespaces;
12176 if (p)
12177 { for (; p->id; p++)
12178 { if (p->ns)
12179 if (!soap_tag_cmp(s, p->ns))
12180 break;
12181 if (p->in)
12182 if (!soap_tag_cmp(s, p->in))
12183 break;
12186 /* URL is in the namespace table? */
12187 if (p && p->id)
12188 { soap_append_lab(soap, p->id, strlen(p->id));
12190 else /* not in namespace table: create xmlns binding */
12191 { char *r = soap_strdup(soap, s);
12192 r[q-s] = '\0';
12193 sprintf(soap->tmpbuf, "xmlns:_%d", soap->idnum++);
12194 soap_set_attr(soap, soap->tmpbuf, r, 1);
12195 soap_append_lab(soap, soap->tmpbuf + 6, strlen(soap->tmpbuf + 6));
12197 soap_append_lab(soap, q + 1, n - (q-s) - 1);
12200 /* advance to next and add spacing */
12201 s += n;
12202 if (*s)
12203 soap_append_lab(soap, " ", 1);
12205 soap_append_lab(soap, SOAP_STR_EOS, 1);
12206 t = soap_strdup(soap, soap->labbuf);
12208 return t;
12210 #endif
12212 /******************************************************************************/
12213 #ifndef WITH_LEAN
12214 SOAP_FMAC1
12216 SOAP_FMAC2
12217 soap_s2wchar(struct soap *soap, const char *s, wchar_t **t, long minlen, long maxlen)
12218 { if (s)
12219 { long l;
12220 wchar_t *r;
12221 *t = r = (wchar_t*)soap_malloc(soap, sizeof(wchar_t) * (strlen(s) + 1));
12222 if (!r)
12223 return soap->error = SOAP_EOM;
12224 if (soap->mode & SOAP_ENC_LATIN)
12225 { while (*s)
12226 *r++ = (wchar_t)*s++;
12228 else
12229 { /* Convert UTF8 to wchar */
12230 while (*s)
12231 { register soap_wchar c, c1, c2, c3, c4;
12232 c = (unsigned char)*s++;
12233 if (c < 0x80)
12234 *r++ = (wchar_t)c;
12235 else
12236 { c1 = (soap_wchar)*s++ & 0x3F;
12237 if (c < 0xE0)
12238 *r++ = (wchar_t)(((soap_wchar)(c & 0x1F) << 6) | c1);
12239 else
12240 { c2 = (soap_wchar)*s++ & 0x3F;
12241 if (c < 0xF0)
12242 *r++ = (wchar_t)(((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2);
12243 else
12244 { c3 = (soap_wchar)*s++ & 0x3F;
12245 if (c < 0xF8)
12246 *r++ = (wchar_t)(((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3);
12247 else
12248 { c4 = (soap_wchar)*s++ & 0x3F;
12249 if (c < 0xFC)
12250 *r++ = (wchar_t)(((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4);
12251 else
12252 *r++ = (wchar_t)(((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(*s++ & 0x3F));
12259 *r = L'\0';
12260 l = (long)(r - *t);
12261 if ((maxlen >= 0 && l > maxlen) || l < minlen)
12262 return soap->error = SOAP_LENGTH;
12264 return soap->error;
12266 #endif
12268 /******************************************************************************/
12269 #ifndef WITH_LEAN
12270 SOAP_FMAC1
12271 const char*
12272 SOAP_FMAC2
12273 soap_wchar2s(struct soap *soap, const wchar_t *s)
12274 { register soap_wchar c;
12275 register char *r, *t;
12276 const wchar_t *q = s;
12277 size_t n = 0;
12278 while ((c = *q++))
12279 { if (c > 0 && c < 0x80)
12280 n++;
12281 else
12282 n += 6;
12284 r = t = (char*)soap_malloc(soap, n + 1);
12285 if (r)
12286 { /* Convert wchar to UTF8 */
12287 while ((c = *s++))
12288 { if (c > 0 && c < 0x80)
12289 *t++ = (char)c;
12290 else
12291 { if (c < 0x0800)
12292 *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
12293 else
12294 { if (c < 0x010000)
12295 *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
12296 else
12297 { if (c < 0x200000)
12298 *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
12299 else
12300 { if (c < 0x04000000)
12301 *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
12302 else
12303 { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
12304 *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
12306 *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
12308 *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
12310 *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
12312 *t++ = (char)(0x80 | (c & 0x3F));
12315 *t = '\0';
12317 return r;
12319 #endif
12321 /******************************************************************************/
12322 #ifndef PALM_2
12323 SOAP_FMAC1
12325 SOAP_FMAC2
12326 soap_outstring(struct soap *soap, const char *tag, int id, char *const*p, const char *type, int n)
12327 { id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n);
12328 if (id < 0)
12329 return soap->error;
12330 if (!**p && (soap->mode & SOAP_C_NILSTRING))
12331 return soap_element_null(soap, tag, id, type);
12332 if (soap_element_begin_out(soap, tag, id, type)
12333 || soap_string_out(soap, *p, 0)
12334 || soap_element_end_out(soap, tag))
12335 return soap->error;
12336 return SOAP_OK;
12338 #endif
12340 /******************************************************************************/
12341 #ifndef PALM_2
12342 SOAP_FMAC1
12343 char **
12344 SOAP_FMAC2
12345 soap_instring(struct soap *soap, const char *tag, char **p, const char *type, int t, int flag, long minlen, long maxlen)
12346 { if (soap_element_begin_in(soap, tag, 1, NULL))
12347 { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG)
12348 return NULL;
12349 soap->error = SOAP_OK;
12351 if (!p)
12352 { if (!(p = (char**)soap_malloc(soap, sizeof(char*))))
12353 return NULL;
12355 if (soap->null)
12356 *p = NULL;
12357 else if (soap->body)
12358 { *p = soap_string_in(soap, flag, minlen, maxlen);
12359 if (!*p || !(char*)soap_id_enter(soap, soap->id, *p, t, sizeof(char*), 0, NULL, NULL, NULL))
12360 return NULL;
12361 if (!**p && tag && *tag == '-')
12362 { soap->error = SOAP_NO_TAG;
12363 return NULL;
12366 else if (tag && *tag == '-')
12367 { soap->error = SOAP_NO_TAG;
12368 return NULL;
12370 else if (!*soap->href && minlen > 0)
12371 { soap->error = SOAP_LENGTH;
12372 return NULL;
12374 else
12375 *p = soap_strdup(soap, SOAP_STR_EOS);
12376 if (*soap->href)
12377 p = (char**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(char**), 0);
12378 if (soap->body && soap_element_end_in(soap, tag))
12379 return NULL;
12380 return p;
12382 #endif
12384 /******************************************************************************/
12385 #ifndef WITH_LEANER
12386 #ifndef PALM_2
12387 SOAP_FMAC1
12389 SOAP_FMAC2
12390 soap_outwstring(struct soap *soap, const char *tag, int id, wchar_t *const*p, const char *type, int n)
12391 { id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n);
12392 if (id < 0)
12393 return soap->error;
12394 if (!**p && (soap->mode & SOAP_C_NILSTRING))
12395 return soap_element_null(soap, tag, id, type);
12396 if (soap_element_begin_out(soap, tag, id, type)
12397 || soap_wstring_out(soap, *p, 0)
12398 || soap_element_end_out(soap, tag))
12399 return soap->error;
12400 return SOAP_OK;
12402 #endif
12403 #endif
12405 /******************************************************************************/
12406 #ifndef WITH_LEANER
12407 #ifndef PALM_2
12408 SOAP_FMAC1
12409 wchar_t **
12410 SOAP_FMAC2
12411 soap_inwstring(struct soap *soap, const char *tag, wchar_t **p, const char *type, int t, long minlen, long maxlen)
12412 { if (soap_element_begin_in(soap, tag, 1, NULL))
12413 { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG)
12414 return NULL;
12415 soap->error = SOAP_OK;
12417 if (!p)
12418 { if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*))))
12419 return NULL;
12421 if (soap->body)
12422 { *p = soap_wstring_in(soap, 1, minlen, maxlen);
12423 if (!*p || !(wchar_t*)soap_id_enter(soap, soap->id, *p, t, sizeof(wchar_t*), 0, NULL, NULL, NULL))
12424 return NULL;
12425 if (!**p && tag && *tag == '-')
12426 { soap->error = SOAP_NO_TAG;
12427 return NULL;
12430 else if (tag && *tag == '-')
12431 { soap->error = SOAP_NO_TAG;
12432 return NULL;
12434 else if (soap->null)
12435 *p = NULL;
12436 else
12437 *p = soap_wstrdup(soap, (wchar_t*)SOAP_STR_EOS);
12438 if (*soap->href)
12439 p = (wchar_t**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(wchar_t**), 0);
12440 if (soap->body && soap_element_end_in(soap, tag))
12441 return NULL;
12442 return p;
12444 #endif
12445 #endif
12447 /******************************************************************************/
12448 #ifndef WITH_LEAN
12449 SOAP_FMAC1
12450 time_t
12451 SOAP_FMAC2
12452 soap_timegm(struct tm *T)
12454 #if defined(HAVE_TIMEGM)
12455 return timegm(T);
12456 #else
12457 time_t t, g, z;
12458 struct tm tm;
12459 t = mktime(T);
12460 if (t == (time_t)-1)
12461 return (time_t)-1;
12462 #ifdef HAVE_GMTIME_R
12463 gmtime_r(&t, &tm);
12464 #else
12465 tm = *gmtime(&t);
12466 #endif
12467 tm.tm_isdst = 0;
12468 g = mktime(&tm);
12469 if (g == (time_t)-1)
12470 return (time_t)-1;
12471 z = g - t;
12472 return t - z;
12473 #endif
12475 #endif
12477 /******************************************************************************/
12478 #ifndef WITH_LEAN
12479 SOAP_FMAC1
12480 const char*
12481 SOAP_FMAC2
12482 soap_dateTime2s(struct soap *soap, time_t n)
12483 { struct tm T, *pT = &T;
12484 #if defined(HAVE_GMTIME_R)
12485 if (gmtime_r(&n, pT))
12486 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT);
12487 #elif defined(HAVE_GMTIME)
12488 if ((pT = gmtime(&n)))
12489 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT);
12490 #elif defined(HAVE_GETTIMEOFDAY)
12491 struct timezone tz;
12492 memset((void*)&tz, 0, sizeof(tz));
12493 #if defined(HAVE_LOCALTIME_R)
12494 if (localtime_r(&n, pT))
12495 { struct timeval tv;
12496 gettimeofday(&tv, &tz);
12497 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
12498 sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60);
12500 #else
12501 if ((pT = localtime(&n)))
12502 { struct timeval tv;
12503 gettimeofday(&tv, &tz);
12504 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
12505 sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60);
12507 #endif
12508 #elif defined(HAVE_FTIME)
12509 struct timeb t;
12510 memset((void*)&t, 0, sizeof(t));
12511 #if defined(HAVE_LOCALTIME_R)
12512 if (localtime_r(&n, pT))
12514 #ifdef __BORLANDC__
12515 ::ftime(&t);
12516 #else
12517 ftime(&t);
12518 #endif
12519 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
12520 sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60);
12522 #else
12523 if ((pT = localtime(&n)))
12525 #ifdef __BORLANDC__
12526 ::ftime(&t);
12527 #else
12528 ftime(&t);
12529 #endif
12530 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
12531 sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60);
12533 #endif
12534 #elif defined(HAVE_LOCALTIME_R)
12535 if (localtime_r(&n, pT))
12536 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
12537 #else
12538 if ((pT = localtime(&n)))
12539 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
12540 #endif
12541 else
12542 strcpy(soap->tmpbuf, "1969-12-31T23:59:59Z");
12543 return soap->tmpbuf;
12545 #endif
12547 /******************************************************************************/
12548 #ifndef WITH_LEAN
12549 SOAP_FMAC1
12551 SOAP_FMAC2
12552 soap_outdateTime(struct soap *soap, const char *tag, int id, const time_t *p, const char *type, int n)
12553 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
12554 || soap_string_out(soap, soap_dateTime2s(soap, *p), 0))
12555 return soap->error;
12556 return soap_element_end_out(soap, tag);
12558 #endif
12560 /******************************************************************************/
12561 #ifndef WITH_LEAN
12562 SOAP_FMAC1
12564 SOAP_FMAC2
12565 soap_s2dateTime(struct soap *soap, const char *s, time_t *p)
12566 { if (s)
12567 { char zone[32];
12568 struct tm T;
12569 const char *t;
12570 *zone = '\0';
12571 memset((void*)&T, 0, sizeof(T));
12572 if (strchr(s, '-'))
12573 t = "%d-%d-%dT%d:%d:%d%31s";
12574 else if (strchr(s, ':'))
12575 t = "%4d%2d%2dT%d:%d:%d%31s";
12576 else /* parse non-XSD-standard alternative ISO 8601 format */
12577 t = "%4d%2d%2dT%2d%2d%2d%31s";
12578 if (sscanf(s, t, &T.tm_year, &T.tm_mon, &T.tm_mday, &T.tm_hour, &T.tm_min, &T.tm_sec, zone) < 6)
12579 return soap->error = SOAP_TYPE;
12580 if (T.tm_year == 1)
12581 T.tm_year = 70;
12582 else
12583 T.tm_year -= 1900;
12584 T.tm_mon--;
12585 if (*zone == '.')
12586 { for (s = zone + 1; *s; s++)
12587 if (*s < '0' || *s > '9')
12588 break;
12590 else
12591 s = zone;
12592 if (*s)
12594 #ifndef WITH_NOZONE
12595 if (*s == '+' || *s == '-')
12596 { int h = 0, m = 0;
12597 if (s[3] == ':')
12598 { /* +hh:mm */
12599 sscanf(s, "%d:%d", &h, &m);
12600 if (h < 0)
12601 m = -m;
12603 else /* +hhmm */
12604 { m = (int)soap_strtol(s, NULL, 10);
12605 h = m / 100;
12606 m = m % 100;
12608 T.tm_min -= m;
12609 T.tm_hour -= h;
12610 /* put hour and min in range */
12611 T.tm_hour += T.tm_min / 60;
12612 T.tm_min %= 60;
12613 if (T.tm_min < 0)
12614 { T.tm_min += 60;
12615 T.tm_hour--;
12617 T.tm_mday += T.tm_hour / 24;
12618 T.tm_hour %= 24;
12619 if (T.tm_hour < 0)
12620 { T.tm_hour += 24;
12621 T.tm_mday--;
12623 /* note: day of the month may be out of range, timegm() handles it */
12625 #endif
12626 *p = soap_timegm(&T);
12628 else /* no UTC or timezone, so assume we got a localtime */
12629 { T.tm_isdst = -1;
12630 *p = mktime(&T);
12633 return soap->error;
12635 #endif
12637 /******************************************************************************/
12638 #ifndef WITH_LEAN
12639 SOAP_FMAC1
12640 time_t *
12641 SOAP_FMAC2
12642 soap_indateTime(struct soap *soap, const char *tag, time_t *p, const char *type, int t)
12643 { if (soap_element_begin_in(soap, tag, 0, NULL))
12644 return NULL;
12645 if (*soap->type
12646 && soap_match_tag(soap, soap->type, type)
12647 && soap_match_tag(soap, soap->type, ":dateTime"))
12648 { soap->error = SOAP_TYPE;
12649 soap_revert(soap);
12650 return NULL;
12652 p = (time_t*)soap_id_enter(soap, soap->id, p, t, sizeof(time_t), 0, NULL, NULL, NULL);
12653 if (*soap->href)
12654 p = (time_t*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(time_t), 0, NULL);
12655 else if (p)
12656 { if (soap_s2dateTime(soap, soap_value(soap), p))
12657 return NULL;
12659 if (soap->body && soap_element_end_in(soap, tag))
12660 return NULL;
12661 return p;
12663 #endif
12665 /******************************************************************************/
12666 #ifndef PALM_2
12667 SOAP_FMAC1
12669 SOAP_FMAC2
12670 soap_outliteral(struct soap *soap, const char *tag, char *const*p, const char *type)
12671 { int i;
12672 const char *t = NULL;
12673 if (tag && *tag != '-')
12674 { if (soap->local_namespaces && (t = strchr(tag, ':')))
12675 { strncpy(soap->tmpbuf, tag, t-tag);
12676 soap->tmpbuf[t-tag] = '\0';
12677 for (i = 0; soap->local_namespaces[i].id; i++)
12678 if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id))
12679 break;
12680 t++;
12681 if (soap_element(soap, t, 0, type)
12682 || soap_attribute(soap, "xmlns", soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS)
12683 || soap_element_start_end_out(soap, NULL))
12684 return soap->error;
12686 else
12687 { t = tag;
12688 if (soap_element_begin_out(soap, t, 0, type))
12689 return soap->error;
12692 if (p && *p)
12693 { if (soap_send(soap, *p))
12694 return soap->error;
12696 if (t)
12697 return soap_element_end_out(soap, t);
12698 return SOAP_OK;
12700 #endif
12702 /******************************************************************************/
12703 #ifndef PALM_2
12704 SOAP_FMAC1
12705 char **
12706 SOAP_FMAC2
12707 soap_inliteral(struct soap *soap, const char *tag, char **p)
12708 { if (soap_element_begin_in(soap, tag, 1, NULL))
12709 { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT)
12710 return NULL;
12711 soap->error = SOAP_OK;
12713 if (!p)
12714 { if (!(p = (char**)soap_malloc(soap, sizeof(char*))))
12715 return NULL;
12717 if (soap->body || (tag && *tag == '-'))
12718 { *p = soap_string_in(soap, 0, -1, -1);
12719 if (!*p)
12720 return NULL;
12721 if (!**p && tag && *tag == '-')
12722 { soap->error = SOAP_NO_TAG;
12723 return NULL;
12726 else if (soap->null)
12727 *p = NULL;
12728 else
12729 *p = soap_strdup(soap, SOAP_STR_EOS);
12730 if (soap->body && soap_element_end_in(soap, tag))
12731 return NULL;
12732 return p;
12734 #endif
12736 /******************************************************************************/
12737 #ifndef WITH_LEANER
12738 #ifndef PALM_2
12739 SOAP_FMAC1
12741 SOAP_FMAC2
12742 soap_outwliteral(struct soap *soap, const char *tag, wchar_t *const*p, const char *type)
12743 { int i;
12744 const char *t = NULL;
12745 if (tag && *tag != '-')
12746 { if (soap->local_namespaces && (t = strchr(tag, ':')))
12747 { strncpy(soap->tmpbuf, tag, t-tag);
12748 soap->tmpbuf[t-tag] = '\0';
12749 for (i = 0; soap->local_namespaces[i].id; i++)
12750 if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id))
12751 break;
12752 t++;
12753 if (soap_element(soap, t, 0, type)
12754 || soap_attribute(soap, "xmlns", soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS)
12755 || soap_element_start_end_out(soap, NULL))
12756 return soap->error;
12758 else
12759 { t = tag;
12760 if (soap_element_begin_out(soap, t, 0, type))
12761 return soap->error;
12763 if (soap_send(soap, soap->tmpbuf))
12764 return soap->error;
12766 if (p)
12767 { wchar_t c;
12768 const wchar_t *s = *p;
12769 while ((c = *s++))
12770 { if (soap_pututf8(soap, (unsigned long)c))
12771 return soap->error;
12774 if (t)
12775 return soap_element_end_out(soap, t);
12776 return SOAP_OK;
12778 #endif
12779 #endif
12781 /******************************************************************************/
12782 #ifndef WITH_LEANER
12783 #ifndef PALM_2
12784 SOAP_FMAC1
12785 wchar_t **
12786 SOAP_FMAC2
12787 soap_inwliteral(struct soap *soap, const char *tag, wchar_t **p)
12788 { if (soap_element_begin_in(soap, tag, 1, NULL))
12789 { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT)
12790 return NULL;
12791 soap->error = SOAP_OK;
12793 if (!p)
12794 { if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*))))
12795 return NULL;
12797 if (soap->body)
12798 { *p = soap_wstring_in(soap, 0, -1, -1);
12799 if (!*p)
12800 return NULL;
12801 if (!**p && tag && *tag == '-')
12802 { soap->error = SOAP_NO_TAG;
12803 return NULL;
12806 else if (tag && *tag == '-')
12807 { soap->error = SOAP_NO_TAG;
12808 return NULL;
12810 else if (soap->null)
12811 *p = NULL;
12812 else
12813 *p = soap_wstrdup(soap, (wchar_t*)SOAP_STR_EOS);
12814 if (soap->body && soap_element_end_in(soap, tag))
12815 return NULL;
12816 return p;
12818 #endif
12819 #endif
12821 /******************************************************************************/
12822 #ifndef PALM_2
12823 SOAP_FMAC1
12824 const char *
12825 SOAP_FMAC2
12826 soap_value(struct soap *soap)
12827 { register size_t i;
12828 register soap_wchar c = 0;
12829 register char *s = soap->tmpbuf;
12830 if (!soap->body)
12831 return SOAP_STR_EOS;
12832 do c = soap_get(soap);
12833 while (soap_blank(c));
12834 for (i = 0; i < sizeof(soap->tmpbuf) - 1; i++)
12835 { if (c == SOAP_TT || c == SOAP_LT || (int)c == EOF)
12836 break;
12837 *s++ = (char)c;
12838 c = soap_get(soap);
12840 for (s--; i > 0; i--, s--)
12841 { if (!soap_blank(*s))
12842 break;
12844 s[1] = '\0';
12845 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element content value='%s'\n", soap->tmpbuf));
12846 if (c == SOAP_TT || c == SOAP_LT || (int)c == EOF)
12847 soap_unget(soap, c);
12848 else if (soap->mode & SOAP_XML_STRICT)
12849 { soap->error = SOAP_LENGTH;
12850 return NULL;
12852 #ifdef WITH_DOM
12853 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
12854 soap->dom->data = soap_strdup(soap, soap->tmpbuf);
12855 #endif
12856 return soap->tmpbuf; /* return non-null pointer */
12858 #endif
12860 /******************************************************************************/
12861 #if !defined(WITH_LEANER) || !defined(WITH_NOHTTP)
12862 #ifndef PALM_2
12863 SOAP_FMAC1
12865 SOAP_FMAC2
12866 soap_getline(struct soap *soap, char *s, int len)
12867 { int i = len;
12868 soap_wchar c = 0;
12869 for (;;)
12870 { while (--i > 0)
12871 { c = soap_getchar(soap);
12872 if (c == '\r' || c == '\n')
12873 break;
12874 if ((int)c == EOF)
12875 return soap->error = SOAP_EOF;
12876 *s++ = (char)c;
12878 if (c != '\n')
12879 c = soap_getchar(soap); /* got \r or something else, now get \n */
12880 if (c == '\n')
12881 { *s = '\0';
12882 if (i+1 == len) /* empty line: end of HTTP/MIME header */
12883 break;
12884 c = soap_get0(soap);
12885 if (c != ' ' && c != '\t') /* HTTP line continuation? */
12886 break;
12888 else if ((int)c == EOF)
12889 return soap->error = SOAP_EOF;
12890 if (i < 0)
12891 return soap->error = SOAP_HDR;
12893 return SOAP_OK;
12895 #endif
12896 #endif
12898 /******************************************************************************/
12899 #ifndef PALM_1
12900 static size_t
12901 soap_count_attachments(struct soap *soap)
12903 #ifndef WITH_LEANER
12904 register struct soap_multipart *content;
12905 register size_t count = soap->count;
12906 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the message size with attachments, current count=%lu\n", (unsigned long)count));
12907 if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
12908 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of DIME attachments\n"));
12909 for (content = soap->dime.first; content; content = content->next)
12910 { count += 12 + ((content->size+3)&(~3));
12911 if (content->id)
12912 count += ((strlen(content->id)+3)&(~3));
12913 if (content->type)
12914 count += ((strlen(content->type)+3)&(~3));
12915 if (content->options)
12916 count += ((((unsigned char)content->options[2] << 8) | ((unsigned char)content->options[3]))+7)&(~3);
12917 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of DIME attachment content is %lu bytes\n", (unsigned long)content->size));
12920 if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary)
12921 { register size_t n = strlen(soap->mime.boundary);
12922 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of MIME attachments\n"));
12923 for (content = soap->mime.first; content; content = content->next)
12924 { register const char *s;
12925 /* count \r\n--boundary\r\n */
12926 count += 6 + n;
12927 /* count Content-Type: ...\r\n */
12928 if (content->type)
12929 count += 16 + strlen(content->type);
12930 /* count Content-Transfer-Encoding: ...\r\n */
12931 s = soap_code_str(mime_codes, content->encoding);
12932 if (s)
12933 count += 29 + strlen(s);
12934 /* count Content-ID: ...\r\n */
12935 if (content->id)
12936 count += 14 + strlen(content->id);
12937 /* count Content-Location: ...\r\n */
12938 if (content->location)
12939 count += 20 + strlen(content->location);
12940 /* count Content-Description: ...\r\n */
12941 if (content->description)
12942 count += 23 + strlen(content->description);
12943 /* count \r\n...content */
12944 count += 2 + content->size;
12945 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of MIME attachment content is %lu bytes\n", (unsigned long)content->size));
12947 /* count \r\n--boundary-- */
12948 count += 6 + n;
12950 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New count is %lu bytes\n", (unsigned long)count));
12951 return count;
12952 #else
12953 return soap->count;
12954 #endif
12956 #endif
12958 /******************************************************************************/
12959 #ifndef WITH_LEANER
12960 #ifndef PALM_1
12961 static int
12962 soap_putdimefield(struct soap *soap, const char *s, size_t n)
12963 { if (soap_send_raw(soap, s, n))
12964 return soap->error;
12965 return soap_send_raw(soap, SOAP_STR_PADDING, -(long)n&3);
12967 #endif
12968 #endif
12970 /******************************************************************************/
12971 #ifndef WITH_LEANER
12972 #ifndef PALM_1
12973 SOAP_FMAC1
12974 char *
12975 SOAP_FMAC2
12976 soap_dime_option(struct soap *soap, unsigned short optype, const char *option)
12977 { size_t n;
12978 char *s = NULL;
12979 if (option)
12980 { n = strlen(option);
12981 s = (char*)soap_malloc(soap, n + 5);
12982 if (s)
12983 { s[0] = (char)(optype >> 8);
12984 s[1] = (char)(optype & 0xFF);
12985 s[2] = (char)(n >> 8);
12986 s[3] = (char)(n & 0xFF);
12987 strcpy(s + 4, option);
12990 return s;
12992 #endif
12993 #endif
12995 /******************************************************************************/
12996 #ifndef WITH_LEANER
12997 #ifndef PALM_1
12998 SOAP_FMAC1
13000 SOAP_FMAC2
13001 soap_putdimehdr(struct soap *soap)
13002 { unsigned char tmp[12];
13003 size_t optlen = 0, idlen = 0, typelen = 0;
13004 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Put DIME header id='%s'\n", soap->dime.id?soap->dime.id:SOAP_STR_EOS));
13005 if (soap->dime.options)
13006 optlen = (((unsigned char)soap->dime.options[2] << 8) | ((unsigned char)soap->dime.options[3])) + 4;
13007 if (soap->dime.id)
13008 { idlen = strlen(soap->dime.id);
13009 if (idlen > 0x0000FFFF)
13010 idlen = 0x0000FFFF;
13012 if (soap->dime.type)
13013 { typelen = strlen(soap->dime.type);
13014 if (typelen > 0x0000FFFF)
13015 typelen = 0x0000FFFF;
13017 tmp[0] = SOAP_DIME_VERSION | (soap->dime.flags & 0x7);
13018 tmp[1] = soap->dime.flags & 0xF0;
13019 tmp[2] = (char)(optlen >> 8);
13020 tmp[3] = (char)(optlen & 0xFF);
13021 tmp[4] = (char)(idlen >> 8);
13022 tmp[5] = (char)(idlen & 0xFF);
13023 tmp[6] = (char)(typelen >> 8);
13024 tmp[7] = (char)(typelen & 0xFF);
13025 tmp[8] = (char)(soap->dime.size >> 24);
13026 tmp[9] = (char)((soap->dime.size >> 16) & 0xFF);
13027 tmp[10] = (char)((soap->dime.size >> 8) & 0xFF);
13028 tmp[11] = (char)(soap->dime.size & 0xFF);
13029 if (soap_send_raw(soap, (char*)tmp, 12)
13030 || soap_putdimefield(soap, soap->dime.options, optlen)
13031 || soap_putdimefield(soap, soap->dime.id, idlen)
13032 || soap_putdimefield(soap, soap->dime.type, typelen))
13033 return soap->error;
13034 return SOAP_OK;
13036 #endif
13037 #endif
13039 /******************************************************************************/
13040 #ifndef WITH_LEANER
13041 #ifndef PALM_1
13042 SOAP_FMAC1
13044 SOAP_FMAC2
13045 soap_putdime(struct soap *soap)
13046 { struct soap_multipart *content;
13047 if (!(soap->mode & SOAP_ENC_DIME))
13048 return SOAP_OK;
13049 for (content = soap->dime.first; content; content = content->next)
13050 { void *handle;
13051 soap->dime.size = content->size;
13052 soap->dime.id = content->id;
13053 soap->dime.type = content->type;
13054 soap->dime.options = content->options;
13055 soap->dime.flags = SOAP_DIME_VERSION | SOAP_DIME_MEDIA;
13056 if (soap->fdimereadopen && ((handle = soap->fdimereadopen(soap, (void*)content->ptr, content->id, content->type, content->options)) || soap->error))
13057 { size_t size = content->size;
13058 if (!handle)
13059 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadopen failed\n"));
13060 return soap->error;
13062 if (!size && ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE))
13063 { size_t chunksize = sizeof(soap->tmpbuf);
13064 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming DIME\n"));
13066 { size = soap->fdimeread(soap, handle, soap->tmpbuf, chunksize);
13067 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread returned %lu bytes\n", (unsigned long)size));
13068 if (size < chunksize)
13069 { soap->dime.flags &= ~SOAP_DIME_CF;
13070 if (!content->next)
13071 soap->dime.flags |= SOAP_DIME_ME;
13073 else
13074 soap->dime.flags |= SOAP_DIME_CF;
13075 soap->dime.size = size;
13076 if (soap_putdimehdr(soap)
13077 || soap_putdimefield(soap, soap->tmpbuf, size))
13078 break;
13079 if (soap->dime.id)
13080 { soap->dime.flags &= ~(SOAP_DIME_MB | SOAP_DIME_MEDIA);
13081 soap->dime.id = NULL;
13082 soap->dime.type = NULL;
13083 soap->dime.options = NULL;
13085 } while (size >= chunksize);
13087 else
13088 { if (!content->next)
13089 soap->dime.flags |= SOAP_DIME_ME;
13090 if (soap_putdimehdr(soap))
13091 return soap->error;
13093 { size_t bufsize;
13094 if (size < sizeof(soap->tmpbuf))
13095 bufsize = size;
13096 else
13097 bufsize = sizeof(soap->tmpbuf);
13098 if (!(bufsize = soap->fdimeread(soap, handle, soap->tmpbuf, bufsize)))
13099 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size));
13100 soap->error = SOAP_EOF;
13101 break;
13103 if (soap_send_raw(soap, soap->tmpbuf, bufsize))
13104 break;
13105 size -= bufsize;
13106 } while (size);
13107 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n"));
13108 soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3);
13110 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n"));
13111 if (soap->fdimereadclose)
13112 soap->fdimereadclose(soap, handle);
13114 else
13115 { if (!content->next)
13116 soap->dime.flags |= SOAP_DIME_ME;
13117 if (soap_putdimehdr(soap)
13118 || soap_putdimefield(soap, (char*)content->ptr, content->size))
13119 return soap->error;
13122 return SOAP_OK;
13124 #endif
13125 #endif
13127 /******************************************************************************/
13128 #ifndef WITH_LEANER
13129 #ifndef PALM_1
13130 static char *
13131 soap_getdimefield(struct soap *soap, size_t n)
13132 { register soap_wchar c;
13133 register size_t i;
13134 register char *s;
13135 register char *p = NULL;
13136 if (n)
13137 { p = (char*)soap_malloc(soap, n + 1);
13138 if (p)
13139 { s = p;
13140 for (i = n; i > 0; i--)
13141 { if ((int)(c = soap_get1(soap)) == EOF)
13142 { soap->error = SOAP_EOF;
13143 return NULL;
13145 *s++ = (char)c;
13147 *s = '\0';
13148 if ((soap->error = soap_move(soap, -(long)n&3)))
13149 return NULL;
13151 else
13152 soap->error = SOAP_EOM;
13154 return p;
13156 #endif
13157 #endif
13159 /******************************************************************************/
13160 #ifndef WITH_LEANER
13161 #ifndef PALM_1
13162 SOAP_FMAC1
13164 SOAP_FMAC2
13165 soap_getdimehdr(struct soap *soap)
13166 { register soap_wchar c;
13167 register char *s;
13168 register int i;
13169 unsigned char tmp[12];
13170 size_t optlen, idlen, typelen;
13171 if (!(soap->mode & SOAP_ENC_DIME))
13172 return soap->error = SOAP_DIME_END;
13173 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME header\n"));
13174 if (soap->dime.buflen || soap->dime.chunksize)
13175 { if (soap_move(soap, (long)(soap->dime.size - soap_tell(soap))))
13176 return soap->error = SOAP_EOF;
13177 soap_unget(soap, soap_getchar(soap)); /* skip padding and get hdr */
13178 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... From chunked\n"));
13179 return SOAP_OK;
13181 s = (char*)tmp;
13182 for (i = 12; i > 0; i--)
13183 { if ((int)(c = soap_getchar(soap)) == EOF)
13184 return soap->error = SOAP_EOF;
13185 *s++ = (char)c;
13187 if ((tmp[0] & 0xF8) != SOAP_DIME_VERSION)
13188 return soap->error = SOAP_DIME_MISMATCH;
13189 soap->dime.flags = (tmp[0] & 0x7) | (tmp[1] & 0xF0);
13190 optlen = (tmp[2] << 8) | tmp[3];
13191 idlen = (tmp[4] << 8) | tmp[5];
13192 typelen = (tmp[6] << 8) | tmp[7];
13193 soap->dime.size = (tmp[8] << 24) | (tmp[9] << 16) | (tmp[10] << 8) | tmp[11];
13194 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME size=%lu flags=0x%X\n", (unsigned long)soap->dime.size, soap->dime.flags));
13195 if (!(soap->dime.options = soap_getdimefield(soap, optlen)) && soap->error)
13196 return soap->error;
13197 if (!(soap->dime.id = soap_getdimefield(soap, idlen)) && soap->error)
13198 return soap->error;
13199 if (!(soap->dime.type = soap_getdimefield(soap, typelen)) && soap->error)
13200 return soap->error;
13201 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));
13202 if (soap->dime.flags & SOAP_DIME_ME)
13203 soap->mode &= ~SOAP_ENC_DIME;
13204 return SOAP_OK;
13206 #endif
13207 #endif
13209 /******************************************************************************/
13210 #ifndef WITH_LEANER
13211 #ifndef PALM_1
13212 SOAP_FMAC1
13214 SOAP_FMAC2
13215 soap_getdime(struct soap *soap)
13216 { while (soap->dime.flags & SOAP_DIME_CF)
13217 { if (soap_getdimehdr(soap))
13218 return soap->error;
13219 if (soap_move(soap, (long)soap->dime.size))
13220 return soap->error = SOAP_EOF;
13222 if (soap_move(soap, (long)(((soap->dime.size+3)&(~3))-soap_tell(soap))))
13223 return soap->error = SOAP_EOF;
13224 for (;;)
13225 { register struct soap_multipart *content;
13226 if (soap_getdimehdr(soap))
13227 break;
13228 if (soap->fdimewriteopen && ((soap->dime.ptr = (char*)soap->fdimewriteopen(soap, soap->dime.id, soap->dime.type, soap->dime.options)) || soap->error))
13229 { const char *id, *type, *options;
13230 size_t size, n;
13231 if (!soap->dime.ptr)
13232 return soap->error;
13233 id = soap->dime.id;
13234 type = soap->dime.type;
13235 options = soap->dime.options;
13236 for (;;)
13237 { size = soap->dime.size;
13238 for (;;)
13239 { n = soap->buflen - soap->bufidx;
13240 if (size < n)
13241 n = size;
13242 if ((soap->error = soap->fdimewrite(soap, (void*)soap->dime.ptr, soap->buf + soap->bufidx, n)))
13243 break;
13244 size -= n;
13245 if (!size)
13246 { soap->bufidx += n;
13247 break;
13249 if (soap_recv(soap))
13250 { soap->error = SOAP_EOF;
13251 goto end;
13254 if (soap_move(soap, -(long)soap->dime.size&3))
13255 { soap->error = SOAP_EOF;
13256 break;
13258 if (!(soap->dime.flags & SOAP_DIME_CF))
13259 break;
13260 if (soap_getdimehdr(soap))
13261 break;
13263 end:
13264 if (soap->fdimewriteclose)
13265 soap->fdimewriteclose(soap, (void*)soap->dime.ptr);
13266 soap->dime.size = 0;
13267 soap->dime.id = id;
13268 soap->dime.type = type;
13269 soap->dime.options = options;
13271 else if (soap->dime.flags & SOAP_DIME_CF)
13272 { const char *id, *type, *options;
13273 id = soap->dime.id;
13274 type = soap->dime.type;
13275 options = soap->dime.options;
13276 if (soap_new_block(soap) == NULL)
13277 return SOAP_EOM;
13278 for (;;)
13279 { register soap_wchar c;
13280 register size_t i;
13281 register char *s;
13282 s = (char*)soap_push_block(soap, NULL, soap->dime.size);
13283 if (!s)
13284 return soap->error = SOAP_EOM;
13285 for (i = soap->dime.size; i > 0; i--)
13286 { if ((int)(c = soap_get1(soap)) == EOF)
13287 return soap->error = SOAP_EOF;
13288 *s++ = (char)c;
13290 if (soap_move(soap, -(long)soap->dime.size&3))
13291 return soap->error = SOAP_EOF;
13292 if (!(soap->dime.flags & SOAP_DIME_CF))
13293 break;
13294 if (soap_getdimehdr(soap))
13295 return soap->error;
13297 soap->dime.size = soap->blist->size++; /* allocate one more for '\0' */
13298 if (!(soap->dime.ptr = soap_save_block(soap, NULL, NULL, 0)))
13299 return soap->error;
13300 soap->dime.ptr[soap->dime.size] = '\0'; /* force 0-terminated */
13301 soap->dime.id = id;
13302 soap->dime.type = type;
13303 soap->dime.options = options;
13305 else
13306 soap->dime.ptr = soap_getdimefield(soap, soap->dime.size);
13307 content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, soap->dime.ptr, soap->dime.size);
13308 if (!content)
13309 return soap->error = SOAP_EOM;
13310 content->id = soap->dime.id;
13311 content->type = soap->dime.type;
13312 content->options = soap->dime.options;
13313 if (soap->error)
13314 return soap->error;
13315 soap_resolve_attachment(soap, content);
13317 if (soap->error != SOAP_DIME_END)
13318 return soap->error;
13319 return soap->error = SOAP_OK;
13321 #endif
13322 #endif
13324 /******************************************************************************/
13325 #ifndef WITH_LEANER
13326 #ifndef PALM_1
13327 SOAP_FMAC1
13329 SOAP_FMAC2
13330 soap_getmimehdr(struct soap *soap)
13331 { struct soap_multipart *content;
13333 { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
13334 return soap->error;
13336 while (!*soap->msgbuf);
13337 if (soap->msgbuf[0] == '-' && soap->msgbuf[1] == '-')
13338 { char *s = soap->msgbuf + strlen(soap->msgbuf) - 1;
13339 /* remove white space */
13340 while (soap_blank(*s))
13341 s--;
13342 s[1] = '\0';
13343 if (soap->mime.boundary)
13344 { if (strcmp(soap->msgbuf + 2, soap->mime.boundary))
13345 return soap->error = SOAP_MIME_ERROR;
13347 else
13348 soap->mime.boundary = soap_strdup(soap, soap->msgbuf + 2);
13349 if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
13350 return soap->error;
13352 if (soap_set_mime_attachment(soap, NULL, 0, SOAP_MIME_NONE, NULL, NULL, NULL, NULL))
13353 return soap->error = SOAP_EOM;
13354 content = soap->mime.last;
13355 for (;;)
13356 { register char *key = soap->msgbuf;
13357 register char *val;
13358 if (!*key)
13359 break;
13360 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "MIME header: %s\n", key));
13361 val = strchr(soap->msgbuf, ':');
13362 if (val)
13363 { *val = '\0';
13364 do val++;
13365 while (*val && *val <= 32);
13366 if (!soap_tag_cmp(key, "Content-ID"))
13367 content->id = soap_strdup(soap, val);
13368 else if (!soap_tag_cmp(key, "Content-Location"))
13369 content->location = soap_strdup(soap, val);
13370 else if (!soap_tag_cmp(key, "Content-Disposition"))
13371 content->id = soap_strdup(soap, soap_get_header_attribute(soap, val, "name"));
13372 else if (!soap_tag_cmp(key, "Content-Type"))
13373 content->type = soap_strdup(soap, val);
13374 else if (!soap_tag_cmp(key, "Content-Description"))
13375 content->description = soap_strdup(soap, val);
13376 else if (!soap_tag_cmp(key, "Content-Transfer-Encoding"))
13377 content->encoding = (enum soap_mime_encoding)soap_code_int(mime_codes, val, (long)SOAP_MIME_NONE);
13379 if (soap_getline(soap, key, sizeof(soap->msgbuf)))
13380 return soap->error;
13382 return SOAP_OK;
13384 #endif
13385 #endif
13387 /******************************************************************************/
13388 #ifndef WITH_LEANER
13389 #ifndef PALM_1
13390 SOAP_FMAC1
13392 SOAP_FMAC2
13393 soap_getmime(struct soap *soap)
13394 { while (soap_get_mime_attachment(soap, NULL))
13396 return soap->error;
13398 #endif
13399 #endif
13401 /******************************************************************************/
13402 #ifndef WITH_LEANER
13403 #ifndef PALM_1
13404 SOAP_FMAC1
13405 void
13406 SOAP_FMAC2
13407 soap_post_check_mime_attachments(struct soap *soap)
13408 { soap->imode |= SOAP_MIME_POSTCHECK;
13410 #endif
13411 #endif
13413 /******************************************************************************/
13414 #ifndef WITH_LEANER
13415 #ifndef PALM_1
13416 SOAP_FMAC1
13418 SOAP_FMAC2
13419 soap_check_mime_attachments(struct soap *soap)
13420 { if (soap->mode & SOAP_MIME_POSTCHECK)
13421 return soap_get_mime_attachment(soap, NULL) != NULL;
13422 return 0;
13424 #endif
13425 #endif
13427 /******************************************************************************/
13428 #ifndef WITH_LEANER
13429 #ifndef PALM_1
13430 SOAP_FMAC1
13431 struct soap_multipart *
13432 SOAP_FMAC2
13433 soap_get_mime_attachment(struct soap *soap, void *handle)
13434 { register soap_wchar c = 0;
13435 register size_t i, m = 0;
13436 register char *s, *t = NULL;
13437 register struct soap_multipart *content;
13438 register short flag = 0;
13439 if (!(soap->mode & SOAP_ENC_MIME))
13440 return NULL;
13441 content = soap->mime.last;
13442 if (!content)
13443 { if (soap_getmimehdr(soap))
13444 return NULL;
13445 content = soap->mime.last;
13447 else if (content != soap->mime.first)
13448 { if (soap->fmimewriteopen && ((content->ptr = (char*)soap->fmimewriteopen(soap, (void*)handle, content->id, content->type, content->description, content->encoding)) || soap->error))
13449 { if (!content->ptr)
13450 return NULL;
13453 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));
13454 if (!content->ptr && soap_new_block(soap) == NULL)
13455 { soap->error = SOAP_EOM;
13456 return NULL;
13458 for (;;)
13459 { if (content->ptr)
13460 s = soap->tmpbuf;
13461 else if (!(s = (char*)soap_push_block(soap, NULL, sizeof(soap->tmpbuf))))
13462 { soap->error = SOAP_EOM;
13463 return NULL;
13465 for (i = 0; i < sizeof(soap->tmpbuf); i++)
13466 { if (m > 0)
13467 { *s++ = *t++;
13468 m--;
13470 else
13471 { if (!flag)
13472 { c = soap_get1(soap);
13473 if ((int)c == EOF)
13474 { soap->error = SOAP_EOF;
13475 return NULL;
13478 if (flag || c == '\r')
13479 { t = soap->msgbuf;
13480 memset(t, 0, sizeof(soap->msgbuf));
13481 strcpy(t, "\n--");
13482 if (soap->mime.boundary)
13483 strncat(t, soap->mime.boundary, sizeof(soap->msgbuf)-4);
13484 do c = soap_getchar(soap);
13485 while (c == *t++);
13486 if ((int)c == EOF)
13487 { soap->error = SOAP_EOF;
13488 return NULL;
13490 if (!*--t)
13491 goto end;
13492 *t = (char)c;
13493 flag = (c == '\r');
13494 m = t - soap->msgbuf + 1 - flag;
13495 t = soap->msgbuf;
13496 c = '\r';
13498 *s++ = (char)c;
13501 if (content->ptr && soap->fmimewrite)
13502 { if ((soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i)))
13503 break;
13506 end:
13507 *s = '\0'; /* force 0-terminated */
13508 if (content->ptr)
13509 { if (!soap->error && soap->fmimewrite)
13510 soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i);
13511 if (soap->fmimewriteclose)
13512 soap->fmimewriteclose(soap, (void*)content->ptr);
13513 if (soap->error)
13514 return NULL;
13516 else
13517 { content->size = soap_size_block(soap, NULL, i+1)-1;
13518 content->ptr = soap_save_block(soap, NULL, NULL, 0);
13520 soap_resolve_attachment(soap, content);
13521 if (c == '-' && soap_getchar(soap) == '-')
13522 { soap->mode &= ~SOAP_ENC_MIME;
13523 if ((soap->mode & SOAP_MIME_POSTCHECK) && soap_end_recv(soap))
13524 return NULL;
13526 else
13527 { while (c != '\r' && (int)c != EOF && soap_blank(c))
13528 c = soap_getchar(soap);
13529 if (c != '\r' || soap_getchar(soap) != '\n')
13530 { soap->error = SOAP_MIME_ERROR;
13531 return NULL;
13533 if (soap_getmimehdr(soap))
13534 return NULL;
13536 return content;
13538 #endif
13539 #endif
13541 /******************************************************************************/
13542 #ifndef WITH_LEANER
13543 #ifndef PALM_1
13544 SOAP_FMAC1
13546 SOAP_FMAC2
13547 soap_match_cid(struct soap *soap, const char *s, const char *t)
13548 { register size_t n;
13549 if (!s)
13550 return 1;
13551 if (!strcmp(s, t))
13552 return 0;
13553 if (!strncmp(s, "cid:", 4))
13554 s += 4;
13555 n = strlen(t);
13556 if (*t == '<')
13557 { t++;
13558 n -= 2;
13560 if (!strncmp(s, t, n) && !s[n])
13561 return 0;
13562 soap_decode(soap->tmpbuf, sizeof(soap->tmpbuf), s, SOAP_STR_EOS);
13563 if (!strncmp(soap->tmpbuf, t, n) && !soap->tmpbuf[n])
13564 return 0;
13565 return 1;
13567 #endif
13568 #endif
13570 /******************************************************************************/
13571 #ifndef WITH_LEANER
13572 #ifndef PALM_1
13573 static void
13574 soap_resolve_attachment(struct soap *soap, struct soap_multipart *content)
13575 { if (content->id)
13576 { register struct soap_xlist **xp = &soap->xlist;
13577 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving attachment data for id=%s\n", content->id));
13578 while (*xp)
13579 { register struct soap_xlist *xq = *xp;
13580 if (!soap_match_cid(soap, xq->id, content->id))
13581 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Found matching attachment %s for content id=%s\n", xq->id, content->id));
13582 *xp = xq->next;
13583 *xq->ptr = (unsigned char*)content->ptr;
13584 *xq->size = (int)content->size;
13585 *xq->type = (char*)content->type;
13586 if (content->options)
13587 *xq->options = (char*)content->options;
13588 else
13589 *xq->options = (char*)content->description;
13590 SOAP_FREE(soap, xq);
13592 else
13593 xp = &(*xp)->next;
13597 #endif
13598 #endif
13600 /******************************************************************************/
13601 #ifndef WITH_LEANER
13602 #ifndef PALM_1
13603 SOAP_FMAC1
13605 SOAP_FMAC2
13606 soap_putmimehdr(struct soap *soap, struct soap_multipart *content)
13607 { const char *s;
13608 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "MIME attachment type=%s\n", content->type?content->type:SOAP_STR_EOS));
13609 if (soap_send3(soap, "\r\n--", soap->mime.boundary, "\r\n"))
13610 return soap->error;
13611 if (content->type && soap_send3(soap, "Content-Type: ", content->type, "\r\n"))
13612 return soap->error;
13613 s = soap_code_str(mime_codes, content->encoding);
13614 if (s && soap_send3(soap, "Content-Transfer-Encoding: ", s, "\r\n"))
13615 return soap->error;
13616 if (content->id && soap_send3(soap, "Content-ID: ", content->id, "\r\n"))
13617 return soap->error;
13618 if (content->location && soap_send3(soap, "Content-Location: ", content->location, "\r\n"))
13619 return soap->error;
13620 if (content->description && soap_send3(soap, "Content-Description: ", content->description, "\r\n"))
13621 return soap->error;
13622 return soap_send_raw(soap, "\r\n", 2);
13624 #endif
13625 #endif
13627 /******************************************************************************/
13628 #ifndef WITH_LEANER
13629 #ifndef PALM_1
13630 SOAP_FMAC1
13632 SOAP_FMAC2
13633 soap_putmime(struct soap *soap)
13634 { struct soap_multipart *content;
13635 if (!(soap->mode & SOAP_ENC_MIME) || !soap->mime.boundary)
13636 return SOAP_OK;
13637 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending MIME attachments\n"));
13638 for (content = soap->mime.first; content; content = content->next)
13639 { void *handle;
13640 if (soap->fmimereadopen && ((handle = soap->fmimereadopen(soap, (void*)content->ptr, content->id, content->type, content->description)) || soap->error))
13641 { size_t size = content->size;
13642 if (!handle)
13643 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimereadopen failed\n"));
13644 return soap->error;
13646 if (soap_putmimehdr(soap, content))
13647 return soap->error;
13648 if (!size)
13649 { if ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE)
13650 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming MIME\n"));
13652 { size = soap->fmimeread(soap, handle, soap->tmpbuf, sizeof(soap->tmpbuf));
13653 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread returned %lu bytes\n", (unsigned long)size));
13654 if (soap_send_raw(soap, soap->tmpbuf, size))
13655 break;
13656 } while (size);
13658 else
13659 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error: cannot chunk streaming MIME (no HTTP chunking)\n"));
13662 else
13663 { do
13664 { size_t bufsize;
13665 if (size < sizeof(soap->tmpbuf))
13666 bufsize = size;
13667 else
13668 bufsize = sizeof(soap->tmpbuf);
13669 if (!(bufsize = soap->fmimeread(soap, handle, soap->tmpbuf, bufsize)))
13670 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size));
13671 soap->error = SOAP_EOF;
13672 break;
13674 if (soap_send_raw(soap, soap->tmpbuf, bufsize))
13675 break;
13676 size -= bufsize;
13677 } while (size);
13679 if (soap->fmimereadclose)
13680 soap->fmimereadclose(soap, handle);
13682 else
13683 { if (soap_putmimehdr(soap, content)
13684 || soap_send_raw(soap, content->ptr, content->size))
13685 return soap->error;
13688 return soap_send3(soap, "\r\n--", soap->mime.boundary, "--");
13690 #endif
13691 #endif
13693 /******************************************************************************/
13694 #ifndef WITH_LEANER
13695 #ifndef PALM_1
13696 SOAP_FMAC1
13697 void
13698 SOAP_FMAC2
13699 soap_set_dime(struct soap *soap)
13700 { soap->omode |= SOAP_ENC_DIME;
13701 soap->dime.first = NULL;
13702 soap->dime.last = NULL;
13704 #endif
13705 #endif
13707 /******************************************************************************/
13708 #ifndef WITH_LEANER
13709 #ifndef PALM_1
13710 SOAP_FMAC1
13711 void
13712 SOAP_FMAC2
13713 soap_set_mime(struct soap *soap, const char *boundary, const char *start)
13714 { soap->omode |= SOAP_ENC_MIME;
13715 soap->mime.first = NULL;
13716 soap->mime.last = NULL;
13717 soap->mime.boundary = soap_strdup(soap, boundary);
13718 soap->mime.start = soap_strdup(soap, start);
13720 #endif
13721 #endif
13723 /******************************************************************************/
13724 #ifndef WITH_LEANER
13725 #ifndef PALM_1
13726 SOAP_FMAC1
13727 void
13728 SOAP_FMAC2
13729 soap_clr_dime(struct soap *soap)
13730 { soap->omode &= ~SOAP_ENC_DIME;
13731 soap->dime.first = NULL;
13732 soap->dime.last = NULL;
13734 #endif
13735 #endif
13737 /******************************************************************************/
13738 #ifndef WITH_LEANER
13739 #ifndef PALM_1
13740 SOAP_FMAC1
13741 void
13742 SOAP_FMAC2
13743 soap_clr_mime(struct soap *soap)
13744 { soap->omode &= ~SOAP_ENC_MIME;
13745 soap->mime.first = NULL;
13746 soap->mime.last = NULL;
13747 soap->mime.boundary = NULL;
13748 soap->mime.start = NULL;
13750 #endif
13751 #endif
13753 /******************************************************************************/
13754 #ifndef WITH_LEANER
13755 #ifndef PALM_1
13756 static struct soap_multipart*
13757 soap_new_multipart(struct soap *soap, struct soap_multipart **first, struct soap_multipart **last, char *ptr, size_t size)
13758 { struct soap_multipart *content;
13759 content = (struct soap_multipart*)soap_malloc(soap, sizeof(struct soap_multipart));
13760 if (content)
13761 { content->next = NULL;
13762 content->ptr = ptr;
13763 content->size = size;
13764 content->id = NULL;
13765 content->type = NULL;
13766 content->options = NULL;
13767 content->encoding = SOAP_MIME_NONE;
13768 content->location = NULL;
13769 content->description = NULL;
13770 if (!*first)
13771 *first = content;
13772 if (*last)
13773 (*last)->next = content;
13774 *last = content;
13776 return content;
13778 #endif
13779 #endif
13781 /******************************************************************************/
13782 #ifndef WITH_LEANER
13783 #ifndef PALM_1
13784 SOAP_FMAC1
13786 SOAP_FMAC2
13787 soap_set_dime_attachment(struct soap *soap, char *ptr, size_t size, const char *type, const char *id, unsigned short optype, const char *option)
13788 { struct soap_multipart *content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, ptr, size);
13789 if (!content)
13790 return SOAP_EOM;
13791 content->id = soap_strdup(soap, id);
13792 content->type = soap_strdup(soap, type);
13793 content->options = soap_dime_option(soap, optype, option);
13794 return SOAP_OK;
13796 #endif
13797 #endif
13799 /******************************************************************************/
13800 #ifndef WITH_LEANER
13801 #ifndef PALM_1
13802 SOAP_FMAC1
13804 SOAP_FMAC2
13805 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)
13806 { struct soap_multipart *content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, ptr, size);
13807 if (!content)
13808 return SOAP_EOM;
13809 content->id = soap_strdup(soap, id);
13810 content->type = soap_strdup(soap, type);
13811 content->encoding = encoding;
13812 content->location = soap_strdup(soap, location);
13813 content->description = soap_strdup(soap, description);
13814 return SOAP_OK;
13816 #endif
13817 #endif
13819 /******************************************************************************/
13820 #ifndef WITH_LEANER
13821 #ifndef PALM_1
13822 SOAP_FMAC1
13823 struct soap_multipart*
13824 SOAP_FMAC2
13825 soap_next_multipart(struct soap_multipart *content)
13826 { if (content)
13827 return content->next;
13828 return NULL;
13830 #endif
13831 #endif
13833 /******************************************************************************/
13834 #ifndef WITH_LEANER
13835 #ifndef PALM_1
13836 static void
13837 soap_select_mime_boundary(struct soap *soap)
13838 { while (!soap->mime.boundary || soap_valid_mime_boundary(soap))
13839 { register char *s = soap->mime.boundary;
13840 register size_t n = 0;
13841 if (s)
13842 n = strlen(s);
13843 if (n < 16)
13844 { n = 64;
13845 s = soap->mime.boundary = (char*)soap_malloc(soap, n + 1);
13846 if (!s)
13847 return;
13849 strcpy(s, "==");
13850 s += 2;
13851 n -= 4;
13852 while (n)
13853 { *s++ = soap_base64o[soap_random & 0x3F];
13854 n--;
13856 strcpy(s, "==");
13858 if (!soap->mime.start)
13859 soap->mime.start = "<SOAP-ENV:Envelope>";
13861 #endif
13862 #endif
13864 /******************************************************************************/
13865 #ifndef WITH_LEANER
13866 #ifndef PALM_1
13867 static int
13868 soap_valid_mime_boundary(struct soap *soap)
13869 { register struct soap_multipart *content;
13870 register size_t k;
13871 if (soap->fmimeread)
13872 return SOAP_OK;
13873 k = strlen(soap->mime.boundary);
13874 for (content = soap->mime.first; content; content = content->next)
13875 { if (content->ptr && content->size >= k)
13876 { register const char *p = (const char*)content->ptr;
13877 register size_t i;
13878 for (i = 0; i < content->size - k; i++, p++)
13879 { if (!strncmp(p, soap->mime.boundary, k))
13880 return SOAP_ERR;
13884 return SOAP_OK;
13886 #endif
13887 #endif
13889 /******************************************************************************/
13890 #ifdef WITH_GZIP
13891 #ifndef PALM_1
13892 static int
13893 soap_getgziphdr(struct soap *soap)
13894 { int i;
13895 soap_wchar c = 0, f = 0;
13896 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get gzip header\n"));
13897 for (i = 0; i < 9; i++)
13898 { if ((int)(c = soap_get1(soap) == EOF))
13899 return soap->error = SOAP_EOF;
13900 if (i == 1 && c == 8)
13901 soap->z_dict = 0;
13902 if (i == 2)
13903 f = c;
13905 if (f & 0x04) /* FEXTRA */
13906 { for (i = soap_get1(soap) | (soap_get1(soap) << 8); i; i--)
13907 { if ((int)soap_get1(soap) == EOF)
13908 return soap->error = SOAP_EOF;
13911 if (f & 0x08) /* skip FNAME */
13912 { do
13913 c = soap_get1(soap);
13914 while (c && (int)c != EOF);
13916 if ((int)c != EOF && (f & 0x10)) /* skip FCOMMENT */
13917 { do
13918 c = soap_get1(soap);
13919 while (c && (int)c != EOF);
13921 if ((int)c != EOF && (f & 0x02)) /* skip FHCRC (CRC32 is used) */
13922 { if ((int)(c = soap_get1(soap)) != EOF)
13923 c = soap_get1(soap);
13925 if ((int)c == EOF)
13926 return soap->error = SOAP_EOF;
13927 return SOAP_OK;
13929 #endif
13930 #endif
13932 /******************************************************************************/
13933 #ifndef PALM_1
13934 SOAP_FMAC1
13936 SOAP_FMAC2
13937 soap_begin_recv(struct soap *soap)
13938 { soap_wchar c;
13939 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing for input\n"));
13940 soap->error = SOAP_OK;
13941 soap_free_temp(soap);
13942 soap_set_local_namespaces(soap);
13943 soap->version = 0; /* don't assume we're parsing SOAP content by default */
13944 #ifndef WITH_NOIDREF
13945 soap_free_iht(soap);
13946 #endif
13947 if ((soap->imode & SOAP_IO) == SOAP_IO_CHUNK)
13948 soap->omode |= SOAP_IO_CHUNK;
13949 soap->imode &= ~(SOAP_IO | SOAP_ENC_MIME);
13950 soap->mode = soap->imode;
13951 if (!soap->keep_alive)
13952 { soap->buflen = 0;
13953 soap->bufidx = 0;
13955 if (!(soap->mode & SOAP_IO_KEEPALIVE))
13956 soap->keep_alive = 0;
13957 soap->ahead = 0;
13958 soap->peeked = 0;
13959 soap->level = 0;
13960 soap->part = SOAP_BEGIN;
13961 soap->alloced = 0;
13962 soap->count = 0;
13963 soap->length = 0;
13964 soap->cdata = 0;
13965 *soap->endpoint = '\0';
13966 soap->action = NULL;
13967 soap->header = NULL;
13968 soap->fault = NULL;
13969 soap->status = 0;
13970 #ifndef WITH_LEANER
13971 soap->dom = NULL;
13972 soap->dime.chunksize = 0;
13973 soap->dime.buflen = 0;
13974 soap->dime.list = NULL;
13975 soap->dime.first = NULL;
13976 soap->dime.last = NULL;
13977 soap->mime.list = NULL;
13978 soap->mime.first = NULL;
13979 soap->mime.last = NULL;
13980 soap->mime.boundary = NULL;
13981 soap->mime.start = NULL;
13982 #endif
13983 #ifdef WIN32
13984 #ifndef UNDER_CE
13985 #ifndef WITH_FASTCGI
13986 if (!soap_valid_socket(soap->socket))
13987 #ifdef __BORLANDC__
13988 setmode(soap->recvfd, _O_BINARY);
13989 #else
13990 _setmode(soap->recvfd, _O_BINARY);
13991 #endif
13992 #endif
13993 #endif
13994 #endif
13995 #ifdef WITH_ZLIB
13996 soap->mode &= ~SOAP_ENC_ZLIB;
13997 soap->zlib_in = SOAP_ZLIB_NONE;
13998 soap->zlib_out = SOAP_ZLIB_NONE;
13999 soap->d_stream->next_in = Z_NULL;
14000 soap->d_stream->avail_in = 0;
14001 soap->d_stream->next_out = (Byte*)soap->buf;
14002 soap->d_stream->avail_out = SOAP_BUFLEN;
14003 soap->z_ratio_in = 1.0;
14004 #endif
14005 #ifdef WITH_OPENSSL
14006 if (soap->ssl)
14007 ERR_clear_error();
14008 #endif
14009 #ifndef WITH_LEANER
14010 if (soap->fprepareinitrecv && (soap->error = soap->fprepareinitrecv(soap)))
14011 return soap->error;
14012 #endif
14013 c = soap_getchar(soap);
14014 #ifdef WITH_GZIP
14015 if (c == 0x1F)
14016 { if (soap_getgziphdr(soap))
14017 return soap->error;
14018 if (inflateInit2(soap->d_stream, -MAX_WBITS) != Z_OK)
14019 return soap->error = SOAP_ZLIB_ERROR;
14020 if (soap->z_dict)
14021 { if (inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len) != Z_OK)
14022 return soap->error = SOAP_ZLIB_ERROR;
14024 soap->zlib_state = SOAP_ZLIB_INFLATE;
14025 soap->mode |= SOAP_ENC_ZLIB;
14026 soap->zlib_in = SOAP_ZLIB_GZIP;
14027 soap->z_crc = crc32(0L, NULL, 0);
14028 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n"));
14029 if (!soap->z_buf)
14030 soap->z_buf = (char*)SOAP_MALLOC(soap, SOAP_BUFLEN);
14031 memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN);
14032 /* should not chunk over plain transport, so why bother to check? */
14033 /* if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) */
14034 /* soap->z_buflen = soap->bufidx; */
14035 /* else */
14036 soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx);
14037 soap->d_stream->avail_in = soap->buflen - soap->bufidx;
14038 soap->z_buflen = soap->buflen;
14039 soap->buflen = soap->bufidx;
14040 c = ' ';
14042 #endif
14043 while (soap_blank(c))
14044 c = soap_getchar(soap);
14045 #ifndef WITH_LEANER
14046 if (c == '-' && soap_get0(soap) == '-')
14047 soap->mode |= SOAP_ENC_MIME;
14048 else if ((c & 0xFFFC) == (SOAP_DIME_VERSION | SOAP_DIME_MB) && (soap_get0(soap) & 0xFFF0) == 0x20)
14049 soap->mode |= SOAP_ENC_DIME;
14050 else
14051 #endif
14052 { /* skip BOM */
14053 if (c == 0xEF && (c = soap_getchar(soap)) == 0xBB && (c = soap_getchar(soap)) == 0xBF)
14054 c = soap_getchar(soap);
14055 /* skip space */
14056 while (soap_blank(c))
14057 c = soap_getchar(soap);
14059 if ((int)c == EOF)
14060 return soap->error = SOAP_EOF;
14061 soap_unget(soap, c);
14062 #ifndef WITH_NOHTTP
14063 /* if not XML or MIME/DIME/ZLIB, assume HTTP header */
14064 if (c != '<' && !(soap->mode & (SOAP_ENC_MIME | SOAP_ENC_DIME | SOAP_ENC_ZLIB)))
14065 { soap_mode m = soap->imode;
14066 soap->mode &= ~SOAP_IO;
14067 soap->error = soap->fparse(soap);
14068 if (soap->error && soap->error < SOAP_STOP)
14069 { soap->keep_alive = 0; /* force close later */
14070 return soap->error;
14072 if (soap->error == SOAP_STOP)
14073 return soap->error;
14074 soap->mode = soap->imode; /* if imode is changed, effectuate */
14075 soap->imode = m; /* restore imode */
14076 #ifdef WITH_ZLIB
14077 soap->mode &= ~SOAP_ENC_ZLIB;
14078 #endif
14079 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
14080 { soap->chunkbuflen = soap->buflen;
14081 soap->buflen = soap->bufidx;
14082 soap->chunksize = 0;
14084 /* Note: fparse should not use soap_unget to push back last char */
14085 if (soap_get0(soap) == (int)EOF)
14086 { if (soap->status == 200)
14087 return soap->error = SOAP_NO_DATA; /* HTTP OK: always expect data */
14088 return soap->error = soap->status;
14090 #ifdef WITH_ZLIB
14091 if (soap->zlib_in != SOAP_ZLIB_NONE)
14093 #ifdef WITH_GZIP
14094 if (soap->zlib_in != SOAP_ZLIB_DEFLATE)
14095 { c = soap_get1(soap);
14096 if (c == 0x1F)
14097 { if (soap_getgziphdr(soap))
14098 return soap->error;
14099 if (inflateInit2(soap->d_stream, -MAX_WBITS) != Z_OK)
14100 return soap->error = SOAP_ZLIB_ERROR;
14101 soap->z_crc = crc32(0L, NULL, 0);
14102 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n"));
14104 else
14105 { soap_revget1(soap);
14106 if (inflateInit(soap->d_stream) != Z_OK)
14107 return soap->error = SOAP_ZLIB_ERROR;
14108 soap->zlib_in = SOAP_ZLIB_DEFLATE;
14111 else
14112 #endif
14113 if (inflateInit(soap->d_stream) != Z_OK)
14114 return soap->error = SOAP_ZLIB_ERROR;
14115 if (soap->z_dict)
14116 { if (inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len) != Z_OK)
14117 return soap->error = SOAP_ZLIB_ERROR;
14119 soap->zlib_state = SOAP_ZLIB_INFLATE;
14120 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate initialized\n"));
14121 soap->mode |= SOAP_ENC_ZLIB;
14122 if (!soap->z_buf)
14123 soap->z_buf = (char*)SOAP_MALLOC(soap, SOAP_BUFLEN);
14124 memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN);
14125 soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx);
14126 soap->d_stream->avail_in = soap->buflen - soap->bufidx;
14127 soap->z_buflen = soap->buflen;
14128 soap->buflen = soap->bufidx;
14130 #endif
14131 #ifndef WITH_LEANER
14132 if (soap->fpreparerecv && (soap->mode & SOAP_IO) != SOAP_IO_CHUNK && soap->buflen > soap->bufidx)
14133 { int r;
14134 if ((r = soap->fpreparerecv(soap, soap->buf + soap->bufidx, soap->buflen - soap->bufidx)))
14135 return soap->error = r;
14137 #endif
14138 if (soap->error)
14139 { if (soap->error == SOAP_FORM && soap->fform)
14140 { soap->error = soap->fform(soap);
14141 if (soap->error == SOAP_OK)
14142 soap->error = SOAP_STOP; /* prevents further processing */
14144 return soap->error;
14147 #endif
14148 #ifndef WITH_LEANER
14149 if (soap->mode & SOAP_ENC_MIME)
14150 { if (soap_getmimehdr(soap))
14151 return soap->error;
14152 if (soap->mime.start)
14153 { do
14154 { if (!soap->mime.last->id)
14155 break;
14156 if (!soap_match_cid(soap, soap->mime.start, soap->mime.last->id))
14157 break;
14158 } while (soap_get_mime_attachment(soap, NULL));
14160 if (soap_get_header_attribute(soap, soap->mime.first->type, "application/dime"))
14161 soap->mode |= SOAP_ENC_DIME;
14163 if (soap->mode & SOAP_ENC_DIME)
14164 { if (soap_getdimehdr(soap))
14165 return soap->error;
14166 if (soap->dime.flags & SOAP_DIME_CF)
14167 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked DIME SOAP message\n"));
14168 soap->dime.chunksize = soap->dime.size;
14169 if (soap->buflen - soap->bufidx >= soap->dime.chunksize)
14170 { soap->dime.buflen = soap->buflen;
14171 soap->buflen = soap->bufidx + soap->dime.chunksize;
14173 else
14174 soap->dime.chunksize -= soap->buflen - soap->bufidx;
14176 soap->count = soap->buflen - soap->bufidx;
14178 #endif
14179 return SOAP_OK;
14181 #endif
14183 /******************************************************************************/
14184 #ifndef PALM_2
14185 SOAP_FMAC1
14187 SOAP_FMAC2
14188 soap_envelope_begin_out(struct soap *soap)
14190 #ifndef WITH_LEANER
14191 size_t n = 0;
14192 if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && soap->mime.start && strlen(soap->mime.boundary) + strlen(soap->mime.start) < sizeof(soap->tmpbuf) - 80 )
14193 { const char *s;
14194 if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
14195 s = "application/dime";
14196 else if (soap->version == 2)
14197 { if (soap->mode & SOAP_ENC_MTOM)
14198 s = "application/xop+xml; charset=utf-8; type=\"application/soap+xml\"";
14199 else
14200 s = "application/soap+xml; charset=utf-8";
14202 else if (soap->mode & SOAP_ENC_MTOM)
14203 s = "application/xop+xml; charset=utf-8; type=\"text/xml\"";
14204 else
14205 s = "text/xml; charset=utf-8";
14206 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);
14207 n = strlen(soap->tmpbuf);
14208 if (soap_send_raw(soap, soap->tmpbuf, n))
14209 return soap->error;
14211 if (soap->mode & SOAP_IO_LENGTH)
14212 soap->dime.size = soap->count; /* DIME in MIME correction */
14213 if (!(soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME))
14214 { if (soap_putdimehdr(soap))
14215 return soap->error;
14217 #endif
14218 soap->part = SOAP_IN_ENVELOPE;
14219 return soap_element_begin_out(soap, "SOAP-ENV:Envelope", 0, NULL);
14221 #endif
14223 /******************************************************************************/
14224 #ifndef PALM_2
14225 SOAP_FMAC1
14227 SOAP_FMAC2
14228 soap_envelope_end_out(struct soap *soap)
14229 { if (soap_element_end_out(soap, "SOAP-ENV:Envelope") || ((soap->mode & SOAP_XML_INDENT) && soap_send_raw(soap, "\r\n", 2)))
14230 return soap->error;
14231 #ifndef WITH_LEANER
14232 if ((soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
14233 { soap->dime.size = soap->count - soap->dime.size; /* DIME in MIME correction */
14234 sprintf(soap->id, soap->dime_id_format, 0);
14235 soap->dime.id = soap->id;
14236 if (soap->local_namespaces)
14237 { if (soap->local_namespaces[0].out)
14238 soap->dime.type = (char*)soap->local_namespaces[0].out;
14239 else
14240 soap->dime.type = (char*)soap->local_namespaces[0].ns;
14242 soap->dime.options = NULL;
14243 soap->dime.flags = SOAP_DIME_MB | SOAP_DIME_ABSURI;
14244 if (!soap->dime.first)
14245 soap->dime.flags |= SOAP_DIME_ME;
14246 soap->count += 12 + ((strlen(soap->dime.id)+3)&(~3)) + (soap->dime.type ? ((strlen(soap->dime.type)+3)&(~3)) : 0);
14248 if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
14249 return soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3);
14250 #endif
14251 soap->part = SOAP_END_ENVELOPE;
14252 return SOAP_OK;
14254 #endif
14256 /******************************************************************************/
14257 #ifndef PALM_1
14258 static char*
14259 soap_get_http_body(struct soap *soap)
14261 #ifndef WITH_LEAN
14262 register size_t l = 0, n = 0;
14263 register char *s;
14264 /* get HTML body of HTTP error content */
14265 if (!(soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) != SOAP_IO_CHUNK)
14266 { n = soap->length;
14267 if (!n)
14268 return NULL;
14270 #ifdef WITH_FAST
14271 soap->labidx = 0; /* use look-aside buffer */
14272 #else
14273 if (soap_new_block(soap) == NULL)
14274 return NULL;
14275 #endif
14276 for (;;)
14278 #ifdef WITH_FAST
14279 register size_t i, k;
14280 if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */
14281 return NULL;
14282 s = soap->labbuf + soap->labidx; /* space to populate */
14283 k = soap->lablen - soap->labidx; /* number of bytes available */
14284 soap->labidx = soap->lablen; /* claim this space */
14285 #else
14286 register size_t i, k = SOAP_BLKLEN;
14287 if (!(s = (char*)soap_push_block(soap, NULL, k)))
14288 return NULL;
14289 #endif
14290 for (i = 0; i < k; i++)
14291 { register soap_wchar c = soap_getchar(soap);
14292 if ((int)c == EOF)
14293 goto end;
14294 *s++ = (char)(c & 0xFF);
14295 l++;
14296 if (n > 0 && l >= n)
14297 goto end;
14300 end:
14301 *s = '\0';
14302 #ifdef WITH_FAST
14303 s = soap_strdup(soap, soap->labbuf);
14304 #else
14305 soap_size_block(soap, NULL, i+1);
14306 s = soap_save_block(soap, NULL, 0);
14307 #endif
14308 return s;
14309 #else
14310 return NULL;
14311 #endif
14313 #endif
14315 /******************************************************************************/
14316 #ifndef PALM_1
14317 SOAP_FMAC1
14319 SOAP_FMAC2
14320 soap_envelope_begin_in(struct soap *soap)
14321 { register struct Namespace *p;
14322 soap->part = SOAP_IN_ENVELOPE;
14323 if (soap_element_begin_in(soap, "SOAP-ENV:Envelope", 0, NULL))
14324 { if (soap->error == SOAP_TAG_MISMATCH
14325 && !soap_element_begin_in(soap, "Envelope", 0, NULL))
14326 soap->error = SOAP_VERSIONMISMATCH;
14327 else if (soap->status)
14328 soap->error = soap->status;
14329 return soap->error;
14331 p = soap->local_namespaces;
14332 if (p)
14333 { const char *ns = p[0].out;
14334 if (!ns)
14335 ns = p[0].ns;
14336 if (!strcmp(ns, soap_env1))
14337 { soap->version = 1; /* make sure we use SOAP 1.1 */
14338 if (p[1].out)
14339 SOAP_FREE(soap, p[1].out);
14340 if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc1))))
14341 strcpy(p[1].out, soap_enc1);
14343 else if (!strcmp(ns, soap_env2))
14344 { soap->version = 2; /* make sure we use SOAP 1.2 */
14345 if (p[1].out)
14346 SOAP_FREE(soap, p[1].out);
14347 if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc2))))
14348 strcpy(p[1].out, soap_enc2);
14351 return SOAP_OK;
14353 #endif
14355 /******************************************************************************/
14356 #ifndef PALM_1
14357 SOAP_FMAC1
14359 SOAP_FMAC2
14360 soap_envelope_end_in(struct soap *soap)
14361 { soap->part = SOAP_END_ENVELOPE;
14362 return soap_element_end_in(soap, "SOAP-ENV:Envelope");
14364 #endif
14366 /******************************************************************************/
14367 #ifndef PALM_2
14368 SOAP_FMAC1
14370 SOAP_FMAC2
14371 soap_body_begin_out(struct soap *soap)
14372 { soap->part = SOAP_IN_BODY;
14373 if (soap->version == 1)
14374 soap->encoding = 1;
14375 #ifndef WITH_LEAN
14376 if ((soap->mode & SOAP_XML_SEC) && soap_set_attr(soap, "wsu:Id", "Body", 1))
14377 return soap->error;
14378 #endif
14379 if (soap_element(soap, "SOAP-ENV:Body", 0, NULL))
14380 return soap->error;
14381 return soap_element_start_end_out(soap, NULL);
14383 #endif
14385 /******************************************************************************/
14386 #ifndef PALM_2
14387 SOAP_FMAC1
14389 SOAP_FMAC2
14390 soap_body_end_out(struct soap *soap)
14391 { if (soap_element_end_out(soap, "SOAP-ENV:Body"))
14392 return soap->error;
14393 soap->part = SOAP_END_BODY;
14394 return SOAP_OK;
14396 #endif
14398 /******************************************************************************/
14399 #ifndef PALM_2
14400 SOAP_FMAC1
14402 SOAP_FMAC2
14403 soap_body_begin_in(struct soap *soap)
14404 { soap->part = SOAP_IN_BODY;
14405 if (soap_element_begin_in(soap, "SOAP-ENV:Body", 0, NULL))
14406 return soap->error;
14407 if (!soap->body)
14408 soap->part = SOAP_NO_BODY;
14409 return SOAP_OK;
14411 #endif
14413 /******************************************************************************/
14414 #ifndef PALM_2
14415 SOAP_FMAC1
14417 SOAP_FMAC2
14418 soap_body_end_in(struct soap *soap)
14419 { if (soap->part == SOAP_NO_BODY)
14420 return soap->error = SOAP_OK;
14421 soap->part = SOAP_END_BODY;
14422 return soap_element_end_in(soap, "SOAP-ENV:Body");
14424 #endif
14426 /******************************************************************************/
14427 #ifndef PALM_2
14428 SOAP_FMAC1
14430 SOAP_FMAC2
14431 soap_recv_header(struct soap *soap)
14432 { if (soap_getheader(soap) && soap->error == SOAP_TAG_MISMATCH)
14433 soap->error = SOAP_OK;
14434 if (soap->error == SOAP_OK && soap->fheader)
14435 soap->error = soap->fheader(soap);
14436 return soap->error;
14438 #endif
14440 /******************************************************************************/
14441 #ifndef PALM_1
14442 SOAP_FMAC1
14443 void
14444 SOAP_FMAC2
14445 soap_set_endpoint(struct soap *soap, const char *endpoint)
14446 { register const char *s;
14447 register size_t i, n;
14448 soap->endpoint[0] = '\0';
14449 soap->host[0] = '\0';
14450 soap->path[0] = '/';
14451 soap->path[1] = '\0';
14452 soap->port = 80;
14453 if (!endpoint || !*endpoint)
14454 return;
14455 #ifdef WITH_OPENSSL
14456 if (!soap_tag_cmp(endpoint, "https:*"))
14457 soap->port = 443;
14458 #endif
14459 strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint) - 1);
14460 soap->endpoint[sizeof(soap->endpoint) - 1] = '\0';
14461 s = strchr(endpoint, ':');
14462 if (s && s[1] == '/' && s[2] == '/')
14463 s += 3;
14464 else
14465 s = endpoint;
14466 n = strlen(s);
14467 if (n >= sizeof(soap->host))
14468 n = sizeof(soap->host) - 1;
14469 #ifdef WITH_IPV6
14470 if (s[0] == '[')
14471 { s++;
14472 for (i = 0; i < n; i++)
14473 { if (s[i] == ']')
14474 { s++;
14475 --n;
14476 break;
14478 soap->host[i] = s[i];
14481 else
14482 { for (i = 0; i < n; i++)
14483 { soap->host[i] = s[i];
14484 if (s[i] == '/' || s[i] == ':')
14485 break;
14488 #else
14489 for (i = 0; i < n; i++)
14490 { soap->host[i] = s[i];
14491 if (s[i] == '/' || s[i] == ':')
14492 break;
14494 #endif
14495 soap->host[i] = '\0';
14496 if (s[i] == ':')
14497 { soap->port = (int)soap_strtol(s + i + 1, NULL, 10);
14498 for (i++; i < n; i++)
14499 if (s[i] == '/')
14500 break;
14502 if (i < n && s[i])
14503 { strncpy(soap->path, s + i, sizeof(soap->path));
14504 soap->path[sizeof(soap->path) - 1] = '\0';
14507 #endif
14509 /******************************************************************************/
14510 #ifndef PALM_1
14511 SOAP_FMAC1
14513 SOAP_FMAC2
14514 soap_connect(struct soap *soap, const char *endpoint, const char *action)
14515 { return soap_connect_command(soap, SOAP_POST, endpoint, action);
14517 #endif
14519 /******************************************************************************/
14520 #ifndef PALM_1
14521 SOAP_FMAC1
14523 SOAP_FMAC2
14524 soap_connect_command(struct soap *soap, int http_command, const char *endpoints, const char *action)
14525 { char *endpoint;
14526 const char *s;
14527 if (endpoints && (s = strchr(endpoints, ' ')))
14528 { endpoint = (char*)SOAP_MALLOC(soap, strlen(endpoints) + 1);
14529 for (;;)
14530 { strncpy(endpoint, endpoints, s - endpoints);
14531 endpoint[s - endpoints] = '\0';
14532 if (soap_try_connect_command(soap, http_command, endpoint, action) != SOAP_TCP_ERROR)
14533 break;
14534 if (!*s)
14535 break;
14536 soap->error = SOAP_OK;
14537 while (*s == ' ')
14538 s++;
14539 endpoints = s;
14540 s = strchr(endpoints, ' ');
14541 if (!s)
14542 s = endpoints + strlen(endpoints);
14544 SOAP_FREE(soap, endpoint);
14546 else
14547 soap_try_connect_command(soap, http_command, endpoints, action);
14548 return soap->error;
14550 #endif
14552 /******************************************************************************/
14553 #ifndef PALM_1
14554 static int
14555 soap_try_connect_command(struct soap *soap, int http_command, const char *endpoint, const char *action)
14556 { char host[sizeof(soap->host)];
14557 int port;
14558 size_t count;
14559 soap->error = SOAP_OK;
14560 strcpy(host, soap->host); /* save previous host name: if != then reconnect */
14561 port = soap->port; /* save previous port to compare */
14562 soap->status = http_command;
14563 soap_set_endpoint(soap, endpoint);
14564 #ifndef WITH_LEANER
14565 if (soap->fconnect)
14566 { if ((soap->error = soap->fconnect(soap, endpoint, soap->host, soap->port)))
14567 return soap->error;
14569 else
14570 #endif
14571 if (soap->fopen && *soap->host)
14572 { if (!soap->keep_alive || !soap_valid_socket(soap->socket) || strcmp(soap->host, host) || soap->port != port || !soap->fpoll || soap->fpoll(soap))
14573 { soap->keep_alive = 0; /* to force close */
14574 soap->omode &= ~SOAP_IO_UDP; /* to force close */
14575 soap_closesock(soap);
14576 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Connect/reconnect to host='%s' path='%s' port=%d\n", soap->host, soap->path, soap->port));
14577 #ifndef WITH_LEAN
14578 if (!strncmp(endpoint, "soap.udp:", 9))
14579 soap->omode |= SOAP_IO_UDP;
14580 #endif
14581 soap->socket = soap->fopen(soap, endpoint, soap->host, soap->port);
14582 if (soap->error)
14583 return soap->error;
14584 soap->keep_alive = ((soap->omode & SOAP_IO_KEEPALIVE) != 0);
14587 count = soap_count_attachments(soap);
14588 if (soap_begin_send(soap))
14589 return soap->error;
14590 if (http_command == SOAP_GET)
14591 { soap->mode &= ~SOAP_IO;
14592 soap->mode |= SOAP_IO_BUFFER;
14594 #ifndef WITH_NOHTTP
14595 soap->action = soap_strdup(soap, action);
14596 if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML) && endpoint)
14597 { unsigned int k = soap->mode;
14598 soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB);
14599 if ((k & SOAP_IO) != SOAP_IO_FLUSH)
14600 soap->mode |= SOAP_IO_BUFFER;
14601 if ((soap->error = soap->fpost(soap, endpoint, soap->host, soap->port, soap->path, action, count)))
14602 return soap->error;
14603 #ifndef WITH_LEANER
14604 if ((k & SOAP_IO) == SOAP_IO_CHUNK)
14605 { if (soap_flush(soap))
14606 return soap->error;
14608 #endif
14609 soap->mode = k;
14611 if (http_command == SOAP_GET)
14612 return soap_end_send(soap);
14613 #endif
14614 return SOAP_OK;
14616 #endif
14618 /******************************************************************************/
14619 #ifndef WITH_LEAN
14620 SOAP_FMAC1
14621 char*
14622 SOAP_FMAC2
14623 soap_s2base64(struct soap *soap, const unsigned char *s, char *t, int n)
14624 { register int i;
14625 register unsigned long m;
14626 register char *p;
14627 if (!t)
14628 t = (char*)soap_malloc(soap, (n + 2) / 3 * 4 + 1);
14629 if (!t)
14630 return NULL;
14631 p = t;
14632 t[0] = '\0';
14633 if (!s)
14634 return p;
14635 for (; n > 2; n -= 3, s += 3)
14636 { m = s[0];
14637 m = (m << 8) | s[1];
14638 m = (m << 8) | s[2];
14639 for (i = 4; i > 0; m >>= 6)
14640 t[--i] = soap_base64o[m & 0x3F];
14641 t += 4;
14643 t[0] = '\0';
14644 if (n > 0)
14645 { m = 0;
14646 for (i = 0; i < n; i++)
14647 m = (m << 8) | *s++;
14648 for (; i < 3; i++)
14649 m <<= 8;
14650 for (i++; i > 0; m >>= 6)
14651 t[--i] = soap_base64o[m & 0x3F];
14652 for (i = 3; i > n; i--)
14653 t[i] = '=';
14654 t[4] = '\0';
14656 return p;
14658 #endif
14660 /******************************************************************************/
14661 #ifndef WITH_LEAN
14662 SOAP_FMAC1
14663 const char*
14664 SOAP_FMAC2
14665 soap_base642s(struct soap *soap, const char *s, char *t, size_t l, int *n)
14666 { register int i, j, c;
14667 register unsigned long m;
14668 register const char *p;
14669 if (!s || !*s)
14670 { if (n)
14671 *n = 0;
14672 if (soap->error)
14673 return NULL;
14674 return SOAP_NON_NULL;
14676 if (!t)
14677 { l = (strlen(s) + 3) / 4 * 3;
14678 t = (char*)soap_malloc(soap, l);
14680 if (!t)
14681 return NULL;
14682 p = t;
14683 if (n)
14684 *n = 0;
14685 for (;;)
14686 { for (i = 0; i < SOAP_BLKLEN; i++)
14687 { m = 0;
14688 j = 0;
14689 while (j < 4)
14690 { c = *s++;
14691 if (c == '=' || !c)
14692 { i *= 3;
14693 switch (j)
14694 { case 2:
14695 *t++ = (char)((m >> 4) & 0xFF);
14696 i++;
14697 break;
14698 case 3:
14699 *t++ = (char)((m >> 10) & 0xFF);
14700 *t++ = (char)((m >> 2) & 0xFF);
14701 i += 2;
14703 if (n)
14704 *n += i;
14705 return p;
14707 c -= '+';
14708 if (c >= 0 && c <= 79)
14709 { int b = soap_base64i[c];
14710 if (b >= 64)
14711 { soap->error = SOAP_TYPE;
14712 return NULL;
14714 m = (m << 6) + b;
14715 j++;
14717 else if (!soap_blank(c + '+'))
14718 { soap->error = SOAP_TYPE;
14719 return NULL;
14722 *t++ = (char)((m >> 16) & 0xFF);
14723 *t++ = (char)((m >> 8) & 0xFF);
14724 *t++ = (char)(m & 0xFF);
14725 if (l < 3)
14726 { if (n)
14727 *n += i;
14728 return p;
14730 l -= 3;
14732 if (n)
14733 *n += 3 * SOAP_BLKLEN;
14736 #endif
14738 /******************************************************************************/
14739 #ifndef WITH_LEAN
14740 SOAP_FMAC1
14741 char*
14742 SOAP_FMAC2
14743 soap_s2hex(struct soap *soap, const unsigned char *s, char *t, int n)
14744 { register char *p;
14745 if (!t)
14746 t = (char*)soap_malloc(soap, 2 * n + 1);
14747 if (!t)
14748 return NULL;
14749 p = t;
14750 t[0] = '\0';
14751 if (s)
14752 { for (; n > 0; n--)
14753 { register int m = *s++;
14754 *t++ = (char)((m >> 4) + (m > 159 ? 'a' - 10 : '0'));
14755 m &= 0x0F;
14756 *t++ = (char)(m + (m > 9 ? 'a' - 10 : '0'));
14759 *t++ = '\0';
14760 return p;
14762 #endif
14764 /******************************************************************************/
14765 #ifndef WITH_LEAN
14766 SOAP_FMAC1
14767 const char*
14768 SOAP_FMAC2
14769 soap_hex2s(struct soap *soap, const char *s, char *t, size_t l, int *n)
14770 { register const char *p;
14771 if (!s || !*s)
14772 { if (n)
14773 *n = 0;
14774 if (soap->error)
14775 return NULL;
14776 return SOAP_NON_NULL;
14778 if (!t)
14779 { l = strlen(s) / 2;
14780 t = (char*)soap_malloc(soap, l);
14782 if (!t)
14783 return NULL;
14784 p = t;
14785 while (l)
14786 { register int d1, d2;
14787 d1 = *s++;
14788 if (!d1)
14789 break;
14790 d2 = *s++;
14791 if (!d2)
14792 break;
14793 *t++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0');
14794 l--;
14796 if (n)
14797 *n = (int)(t - p);
14798 return p;
14800 #endif
14802 /******************************************************************************/
14803 #ifndef WITH_NOHTTP
14804 #ifndef PALM_1
14805 SOAP_FMAC1
14807 SOAP_FMAC2
14808 soap_puthttphdr(struct soap *soap, int status, size_t count)
14809 { if (soap->status != SOAP_GET)
14810 { register const char *s = "text/xml; charset=utf-8";
14811 register int err = SOAP_OK;
14812 #ifndef WITH_LEANER
14813 register const char *r = NULL;
14814 #endif
14815 if ((status == SOAP_FILE || soap->status == SOAP_POST_FILE) && soap->http_content)
14816 s = soap->http_content;
14817 else if (status == SOAP_HTML)
14818 s = "text/html; charset=utf-8";
14819 else if (count || ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK))
14820 { if (soap->version == 2)
14821 s = "application/soap+xml; charset=utf-8";
14823 #ifndef WITH_LEANER
14824 if (soap->mode & (SOAP_ENC_DIME | SOAP_ENC_MTOM))
14825 { if (soap->mode & SOAP_ENC_MTOM)
14826 { if (soap->version == 2)
14827 r = "application/soap+xml";
14828 else
14829 r = "text/xml";
14830 s = "application/xop+xml";
14832 else
14833 s = "application/dime";
14835 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)
14836 { register const char *t = strchr(s, ';');
14837 sprintf(soap->tmpbuf, "multipart/related; charset=utf-8; boundary=\"%s\"; type=\"", soap->mime.boundary);
14838 if (t)
14839 { strncat(soap->tmpbuf, s, t - s);
14840 soap->tmpbuf[sizeof(soap->tmpbuf)-1] = '\0';
14842 else
14843 strcat(soap->tmpbuf, s);
14844 if (soap->mime.start)
14845 { strcat(soap->tmpbuf, "\"; start=\"");
14846 strcat(soap->tmpbuf, soap->mime.start);
14848 strcat(soap->tmpbuf, "\"");
14849 if (r)
14850 { strcat(soap->tmpbuf, "; start-info=\"");
14851 strcat(soap->tmpbuf, r);
14852 strcat(soap->tmpbuf, "\"");
14854 s = soap->tmpbuf;
14856 #endif
14857 if (s && (err = soap->fposthdr(soap, "Content-Type", s)))
14858 return err;
14859 #ifdef WITH_ZLIB
14860 if ((soap->omode & SOAP_ENC_ZLIB))
14862 #ifdef WITH_GZIP
14863 err = soap->fposthdr(soap, "Content-Encoding", soap->zlib_out == SOAP_ZLIB_DEFLATE ? "deflate" : "gzip");
14864 #else
14865 err = soap->fposthdr(soap, "Content-Encoding", "deflate");
14866 #endif
14867 if (err)
14868 return err;
14870 #endif
14871 #ifndef WITH_LEANER
14872 if ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK)
14873 err = soap->fposthdr(soap, "Transfer-Encoding", "chunked");
14874 else
14875 #endif
14876 if (s)
14877 { sprintf(soap->tmpbuf, "%lu", (unsigned long)count);
14878 err = soap->fposthdr(soap, "Content-Length", soap->tmpbuf);
14880 if (err)
14881 return err;
14883 return soap->fposthdr(soap, "Connection", soap->keep_alive ? "keep-alive" : "close");
14885 #endif
14886 #endif
14888 /******************************************************************************/
14889 #ifndef WITH_LEAN
14890 static const char*
14891 soap_set_validation_fault(struct soap *soap, const char *s, const char *t)
14892 { if (*soap->tag)
14893 sprintf(soap->msgbuf, "Validation constraint violation: %s%s in element '%s'", s, t?t:SOAP_STR_EOS, soap->tag);
14894 else
14895 sprintf(soap->msgbuf, "Validation constraint violation: %s%s", s, t?t:SOAP_STR_EOS);
14896 return soap->msgbuf;
14898 #endif
14900 /******************************************************************************/
14901 #ifndef PALM_1
14902 SOAP_FMAC1
14903 void
14904 SOAP_FMAC2
14905 soap_set_fault(struct soap *soap)
14906 { const char **c = soap_faultcode(soap);
14907 const char **s = soap_faultstring(soap);
14908 if (soap->fseterror)
14909 soap->fseterror(soap, c, s);
14910 if (!*c)
14911 { if (soap->version == 2)
14912 *c = "SOAP-ENV:Sender";
14913 else
14914 *c = "SOAP-ENV:Client";
14916 if (*s)
14917 return;
14918 switch (soap->error)
14920 #ifndef WITH_LEAN
14921 case SOAP_CLI_FAULT:
14922 *s = "Client fault";
14923 break;
14924 case SOAP_SVR_FAULT:
14925 *s = "Server fault";
14926 break;
14927 case SOAP_TAG_MISMATCH:
14928 *s = soap_set_validation_fault(soap, "tag name or namespace mismatch", NULL);
14929 break;
14930 case SOAP_TYPE:
14931 *s = soap_set_validation_fault(soap, "data type mismatch ", soap->type);
14932 break;
14933 case SOAP_SYNTAX_ERROR:
14934 *s = "Well-formedness violation";
14935 break;
14936 case SOAP_NO_TAG:
14937 *s = "No XML root element";
14938 break;
14939 case SOAP_MUSTUNDERSTAND:
14940 *c = "SOAP-ENV:MustUnderstand";
14941 sprintf(soap->msgbuf, "The data in element '%s' must be understood but cannot be handled", soap->tag);
14942 *s = soap->msgbuf;
14943 break;
14944 case SOAP_VERSIONMISMATCH:
14945 *c = "SOAP-ENV:VersionMismatch";
14946 *s = "Invalid SOAP message or SOAP version mismatch";
14947 break;
14948 case SOAP_DATAENCODINGUNKNOWN:
14949 *c = "SOAP-ENV:DataEncodingUnknown";
14950 *s = "Unsupported SOAP data encoding";
14951 break;
14952 case SOAP_NAMESPACE:
14953 *s = soap_set_validation_fault(soap, "namespace error", NULL);
14954 break;
14955 case SOAP_USER_ERROR:
14956 *s = "User error";
14957 break;
14958 case SOAP_FATAL_ERROR:
14959 *s = "Fatal error";
14960 break;
14961 case SOAP_NO_METHOD:
14962 sprintf(soap->msgbuf, "Method '%s' not implemented: method name or namespace not recognized", soap->tag);
14963 *s = soap->msgbuf;
14964 break;
14965 case SOAP_NO_DATA:
14966 *s = "Data required for operation";
14967 break;
14968 case SOAP_GET_METHOD:
14969 *s = "HTTP GET method not implemented";
14970 break;
14971 case SOAP_PUT_METHOD:
14972 *s = "HTTP PUT method not implemented";
14973 break;
14974 case SOAP_HEAD_METHOD:
14975 *s = "HTTP HEAD method not implemented";
14976 break;
14977 case SOAP_HTTP_METHOD:
14978 *s = "HTTP method not implemented";
14979 break;
14980 case SOAP_EOM:
14981 *s = "Out of memory";
14982 break;
14983 case SOAP_MOE:
14984 *s = "Memory overflow or memory corruption error";
14985 break;
14986 case SOAP_HDR:
14987 *s = "Header line too long";
14988 break;
14989 case SOAP_IOB:
14990 *s = "Array index out of bounds";
14991 break;
14992 case SOAP_NULL:
14993 *s = soap_set_validation_fault(soap, "nil not allowed", NULL);
14994 break;
14995 case SOAP_DUPLICATE_ID:
14996 *s = soap_set_validation_fault(soap, "multiple definitions of id ", soap->id);
14997 if (soap->version == 2)
14998 *soap_faultsubcode(soap) = "SOAP-ENC:DuplicateID";
14999 break;
15000 case SOAP_MISSING_ID:
15001 *s = soap_set_validation_fault(soap, "missing id for ref ", soap->id);
15002 if (soap->version == 2)
15003 *soap_faultsubcode(soap) = "SOAP-ENC:MissingID";
15004 break;
15005 case SOAP_HREF:
15006 *s = soap_set_validation_fault(soap, "incompatible object type ref/id pair ", soap->id);
15007 break;
15008 case SOAP_FAULT:
15009 break;
15010 #ifndef WITH_NOIO
15011 case SOAP_UDP_ERROR:
15012 *s = "Message too large for UDP packet";
15013 break;
15014 case SOAP_TCP_ERROR:
15015 *s = tcp_error(soap);
15016 break;
15017 #endif
15018 case SOAP_HTTP_ERROR:
15019 *s = "An HTTP processing error occurred";
15020 break;
15021 case SOAP_SSL_ERROR:
15022 #ifdef WITH_OPENSSL
15023 *s = "SSL error";
15024 #else
15025 *s = "OpenSSL not installed: recompile with -DWITH_OPENSSL";
15026 #endif
15027 break;
15028 case SOAP_PLUGIN_ERROR:
15029 *s = "Plugin registry error";
15030 break;
15031 case SOAP_DIME_ERROR:
15032 *s = "DIME format error";
15033 break;
15034 case SOAP_DIME_HREF:
15035 *s = "DIME href to missing attachment";
15036 break;
15037 case SOAP_DIME_MISMATCH:
15038 *s = "DIME version/transmission error";
15039 break;
15040 case SOAP_DIME_END:
15041 *s = "End of DIME error";
15042 break;
15043 case SOAP_MIME_ERROR:
15044 *s = "MIME format error";
15045 break;
15046 case SOAP_MIME_HREF:
15047 *s = "MIME href to missing attachment";
15048 break;
15049 case SOAP_MIME_END:
15050 *s = "End of MIME error";
15051 break;
15052 case SOAP_ZLIB_ERROR:
15053 #ifdef WITH_ZLIB
15054 sprintf(soap->msgbuf, "Zlib/gzip error: '%s'", soap->d_stream->msg?soap->d_stream->msg:SOAP_STR_EOS);
15055 *s = soap->msgbuf;
15056 #else
15057 *s = "Zlib/gzip not installed for (de)compression: recompile with -DWITH_GZIP";
15058 #endif
15059 break;
15060 case SOAP_REQUIRED:
15061 *s = soap_set_validation_fault(soap, "missing required attribute", NULL);
15062 break;
15063 case SOAP_PROHIBITED:
15064 *s = soap_set_validation_fault(soap, "prohibited attribute present", NULL);
15065 break;
15066 case SOAP_OCCURS:
15067 *s = soap_set_validation_fault(soap, "occurrence violation", NULL);
15068 break;
15069 case SOAP_LENGTH:
15070 *s = soap_set_validation_fault(soap, "content range or length violation", NULL);
15071 break;
15072 case SOAP_FD_EXCEEDED:
15073 *s = "Maximum number of open connections was reached (no define HAVE_POLL): increase FD_SETSIZE";
15074 break;
15075 case SOAP_STOP:
15076 *s = "Stopped: no response to be sent or received (informative)";
15077 break;
15078 #endif
15079 case SOAP_EOF:
15080 #ifndef WITH_NOIO
15081 strcpy(soap->msgbuf, soap_strerror(soap));
15082 #ifndef WITH_LEAN
15083 if (strlen(soap->msgbuf) + 25 < sizeof(soap->msgbuf))
15084 { memmove(soap->msgbuf + 25, soap->msgbuf, strlen(soap->msgbuf) + 1);
15085 memcpy(soap->msgbuf, "End of file or no input: ", 25);
15087 #endif
15088 *s = soap->msgbuf;
15089 break;
15090 #else
15091 *s = "End of file or no input";
15092 break;
15093 #endif
15094 default:
15095 #ifndef WITH_NOHTTP
15096 #ifndef WITH_LEAN
15097 if (soap->error > 200 && soap->error < 600)
15098 { sprintf(soap->msgbuf, "HTTP Error: %d %s", soap->error, http_error(soap, soap->error));
15099 *s = soap->msgbuf;
15101 else
15102 #endif
15103 #endif
15104 { sprintf(soap->msgbuf, "Error %d", soap->error);
15105 *s = soap->msgbuf;
15109 #endif
15111 /******************************************************************************/
15112 #ifndef PALM_1
15113 SOAP_FMAC1
15115 SOAP_FMAC2
15116 soap_send_fault(struct soap *soap)
15117 { register int status = soap->error;
15118 if (status == SOAP_STOP)
15119 return soap_closesock(soap);
15120 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Sending back fault struct for error code %d\n", soap->error));
15121 soap->keep_alive = 0; /* to terminate connection */
15122 soap_set_fault(soap);
15123 if (soap->error < 200 && soap->error != SOAP_FAULT)
15124 soap->header = NULL;
15125 if (status != SOAP_EOF || (!soap->recv_timeout && !soap->send_timeout))
15126 { int r = 1;
15127 #ifndef WITH_NOIO
15128 if (soap->fpoll && soap->fpoll(soap))
15129 r = 0;
15130 #ifndef WITH_LEAN
15131 else if (soap_valid_socket(soap->socket))
15132 { r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_SND, 0);
15133 if (r > 0)
15134 { if (!(r & SOAP_TCP_SELECT_SND)
15135 || ((r & SOAP_TCP_SELECT_RCV)
15136 && recv(soap->socket, soap->tmpbuf, 1, MSG_PEEK) < 0))
15137 r = 0;
15140 #endif
15141 #endif
15142 if (r > 0)
15143 { soap->error = SOAP_OK;
15144 soap_serializeheader(soap);
15145 soap_serializefault(soap);
15146 soap_begin_count(soap);
15147 if (soap->mode & SOAP_IO_LENGTH)
15148 { soap_envelope_begin_out(soap);
15149 soap_putheader(soap);
15150 soap_body_begin_out(soap);
15151 soap_putfault(soap);
15152 soap_body_end_out(soap);
15153 soap_envelope_end_out(soap);
15155 soap_end_count(soap);
15156 if (soap_response(soap, status)
15157 || soap_envelope_begin_out(soap)
15158 || soap_putheader(soap)
15159 || soap_body_begin_out(soap)
15160 || soap_putfault(soap)
15161 || soap_body_end_out(soap)
15162 || soap_envelope_end_out(soap))
15163 return soap_closesock(soap);
15164 soap_end_send(soap);
15167 soap->error = status;
15168 return soap_closesock(soap);
15170 #endif
15172 /******************************************************************************/
15173 #ifndef PALM_1
15174 SOAP_FMAC1
15176 SOAP_FMAC2
15177 soap_recv_fault(struct soap *soap, int check)
15178 { register int status = soap->error;
15179 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Check if receiving SOAP Fault\n"));
15180 if (!check)
15181 { /* try getfault when no tag or tag mismatched at level 2, otherwise ret */
15182 if (soap->error != SOAP_NO_TAG
15183 && (soap->error != SOAP_TAG_MISMATCH || soap->level != 2))
15184 return soap->error;
15186 soap->error = SOAP_OK;
15187 if (soap_getfault(soap))
15188 { /* check flag set: check if SOAP Fault is present, if not just return */
15189 if (check && soap->error == SOAP_TAG_MISMATCH && soap->level == 2)
15190 return soap->error = SOAP_OK;
15191 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Error: soap_get_soapfault() failed. Is this a SOAP message at all?\n"));
15192 *soap_faultcode(soap) = (soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client");
15193 soap->error = status;
15194 soap_set_fault(soap);
15196 else
15197 { register const char *s = *soap_faultcode(soap);
15198 if (!soap_match_tag(soap, s, "SOAP-ENV:Server") || !soap_match_tag(soap, s, "SOAP-ENV:Receiver"))
15199 status = SOAP_SVR_FAULT;
15200 else if (!soap_match_tag(soap, s, "SOAP-ENV:Client") || !soap_match_tag(soap, s, "SOAP-ENV:Sender"))
15201 status = SOAP_CLI_FAULT;
15202 else if (!soap_match_tag(soap, s, "SOAP-ENV:MustUnderstand"))
15203 status = SOAP_MUSTUNDERSTAND;
15204 else if (!soap_match_tag(soap, s, "SOAP-ENV:VersionMismatch"))
15205 status = SOAP_VERSIONMISMATCH;
15206 else
15207 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Received SOAP Fault code %s\n", s));
15208 status = SOAP_FAULT;
15210 if (!soap_body_end_in(soap))
15211 soap_envelope_end_in(soap);
15213 soap_end_recv(soap);
15214 soap->error = status;
15215 return soap_closesock(soap);
15217 #endif
15219 /******************************************************************************/
15220 #ifndef WITH_NOHTTP
15221 #ifndef PALM_1
15222 SOAP_FMAC1
15224 SOAP_FMAC2
15225 soap_send_empty_response(struct soap *soap, int httpstatuscode)
15226 { register soap_mode m = soap->omode;
15227 soap->count = 0;
15228 if ((m & SOAP_IO) == SOAP_IO_CHUNK)
15229 soap->omode = (m & ~SOAP_IO) | SOAP_IO_BUFFER;
15230 if (soap_response(soap, httpstatuscode) || soap_end_send(soap))
15231 { soap->omode = m;
15232 return soap_closesock(soap);
15234 soap->omode = m;
15235 return soap->error = SOAP_STOP; /* stops the server's response */
15237 #endif
15238 #endif
15240 /******************************************************************************/
15241 #ifndef WITH_NOHTTP
15242 #ifndef PALM_1
15243 SOAP_FMAC1
15245 SOAP_FMAC2
15246 soap_recv_empty_response(struct soap *soap)
15247 { if (!soap_begin_recv(soap))
15248 soap_end_recv(soap);
15249 else if (soap->error == SOAP_NO_DATA || soap->error == 202)
15250 soap->error = SOAP_OK;
15251 return soap_closesock(soap);
15253 #endif
15254 #endif
15256 /******************************************************************************/
15257 #ifndef WITH_NOIO
15258 #ifndef PALM_1
15259 static const char*
15260 soap_strerror(struct soap *soap)
15261 { register int err = soap->errnum;
15262 if (err)
15264 #ifndef WIN32
15265 return strerror(err);
15266 #else
15267 #ifndef UNDER_CE
15268 DWORD len;
15269 *soap->msgbuf = '\0';
15270 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);
15271 #else
15272 DWORD i, len;
15273 *soap->msgbuf = '\0';
15274 len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, 0, (LPTSTR)soap->msgbuf, (DWORD)(sizeof(soap->msgbuf)/sizeof(TCHAR)), NULL);
15275 for (i = 0; i <= len; i++)
15276 { if (((TCHAR*)soap->msgbuf)[i] < 0x80)
15277 soap->msgbuf[i] = (char)((TCHAR*)soap->msgbuf)[i];
15278 else
15279 soap->msgbuf[i] = '?';
15281 #endif
15282 #endif
15284 else
15285 { char *s = soap->msgbuf;
15286 #ifndef WITH_LEAN
15287 int rt = soap->recv_timeout, st = soap->send_timeout;
15288 int ru = ' ', su = ' ';
15289 #endif
15290 strcpy(s, "Operation interrupted or timed out");
15291 #ifndef WITH_LEAN
15292 if (rt < 0)
15293 { rt = -rt;
15294 ru = 'u';
15296 if (st < 0)
15297 { st = -st;
15298 su = 'u';
15300 if (rt)
15301 sprintf(s + strlen(s), " (%d%cs receive delay)", rt, ru);
15302 if (st)
15303 sprintf(s + strlen(s), " (%d%cs send delay)", st, su);
15304 #endif
15306 return soap->msgbuf;
15308 #endif
15309 #endif
15311 /******************************************************************************/
15312 #ifndef PALM_2
15313 static int
15314 soap_set_error(struct soap *soap, const char *faultcode, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML, int soaperror)
15315 { *soap_faultcode(soap) = faultcode;
15316 if (faultsubcodeQName)
15317 *soap_faultsubcode(soap) = faultsubcodeQName;
15318 *soap_faultstring(soap) = faultstring;
15319 if (faultdetailXML && *faultdetailXML)
15320 { register const char **s = soap_faultdetail(soap);
15321 if (s)
15322 *s = faultdetailXML;
15324 return soap->error = soaperror;
15326 #endif
15328 /******************************************************************************/
15329 #ifndef PALM_2
15330 SOAP_FMAC1
15332 SOAP_FMAC2
15333 soap_set_sender_error(struct soap *soap, const char *faultstring, const char *faultdetailXML, int soaperror)
15334 { return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", NULL, faultstring, faultdetailXML, soaperror);
15336 #endif
15338 /******************************************************************************/
15339 #ifndef PALM_2
15340 SOAP_FMAC1
15342 SOAP_FMAC2
15343 soap_set_receiver_error(struct soap *soap, const char *faultstring, const char *faultdetailXML, int soaperror)
15344 { return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", NULL, faultstring, faultdetailXML, soaperror);
15346 #endif
15348 /******************************************************************************/
15349 #ifndef PALM_2
15350 static int
15351 soap_copy_fault(struct soap *soap, const char *faultcode, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML)
15352 { char *r = NULL, *s = NULL, *t = NULL;
15353 if (faultsubcodeQName)
15354 r = soap_strdup(soap, faultsubcodeQName);
15355 if (faultstring)
15356 s = soap_strdup(soap, faultstring);
15357 if (faultdetailXML)
15358 t = soap_strdup(soap, faultdetailXML);
15359 return soap_set_error(soap, faultcode, r, s, t, SOAP_FAULT);
15361 #endif
15363 /******************************************************************************/
15364 #ifndef PALM_2
15365 SOAP_FMAC1
15367 SOAP_FMAC2
15368 soap_sender_fault(struct soap *soap, const char *faultstring, const char *faultdetailXML)
15369 { return soap_sender_fault_subcode(soap, NULL, faultstring, faultdetailXML);
15371 #endif
15373 /******************************************************************************/
15374 #ifndef PALM_2
15375 SOAP_FMAC1
15377 SOAP_FMAC2
15378 soap_sender_fault_subcode(struct soap *soap, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML)
15379 { return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", faultsubcodeQName, faultstring, faultdetailXML);
15381 #endif
15383 /******************************************************************************/
15384 #ifndef PALM_2
15385 SOAP_FMAC1
15387 SOAP_FMAC2
15388 soap_receiver_fault(struct soap *soap, const char *faultstring, const char *faultdetailXML)
15389 { return soap_receiver_fault_subcode(soap, NULL, faultstring, faultdetailXML);
15391 #endif
15393 /******************************************************************************/
15394 #ifndef PALM_2
15395 SOAP_FMAC1
15397 SOAP_FMAC2
15398 soap_receiver_fault_subcode(struct soap *soap, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML)
15399 { return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", faultsubcodeQName, faultstring, faultdetailXML);
15401 #endif
15403 /******************************************************************************/
15404 #ifndef PALM_2
15405 #ifndef WITH_NOSTDLIB
15406 SOAP_FMAC1
15407 void
15408 SOAP_FMAC2
15409 soap_print_fault(struct soap *soap, FILE *fd)
15410 { if (soap_check_state(soap))
15411 fprintf(fd, "Error: soap struct state not initialized\n");
15412 else if (soap->error)
15413 { const char *c, *v = NULL, *s, **d;
15414 d = soap_faultcode(soap);
15415 if (!*d)
15416 soap_set_fault(soap);
15417 c = *d;
15418 if (soap->version == 2)
15419 v = *soap_faultsubcode(soap);
15420 s = *soap_faultstring(soap);
15421 d = soap_faultdetail(soap);
15422 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]");
15425 #endif
15426 #endif
15428 /******************************************************************************/
15429 #ifdef __cplusplus
15430 #ifndef WITH_LEAN
15431 #ifndef WITH_NOSTDLIB
15432 SOAP_FMAC1
15433 void
15434 SOAP_FMAC2
15435 soap_stream_fault(struct soap *soap, std::ostream& os)
15436 { if (soap_check_state(soap))
15437 os << "Error: soap struct state not initialized\n";
15438 else if (soap->error)
15439 { const char *c, *v = NULL, *s, **d;
15440 d = soap_faultcode(soap);
15441 if (!*d)
15442 soap_set_fault(soap);
15443 c = *d;
15444 if (soap->version == 2)
15445 v = *soap_faultsubcode(soap);
15446 s = *soap_faultstring(soap);
15447 d = soap_faultdetail(soap);
15448 os << (soap->version ? "SOAP 1." : "Error ")
15449 << (soap->version ? (int)soap->version : soap->error)
15450 << " fault: " << c
15451 << "[" << (v ? v : "no subcode") << "]"
15452 << std::endl
15453 << "\"" << (s ? s : "[no reason]") << "\""
15454 << std::endl
15455 << "Detail: " << (d && *d ? *d : "[no detail]")
15456 << std::endl;
15459 #endif
15460 #endif
15461 #endif
15463 /******************************************************************************/
15464 #ifndef WITH_LEAN
15465 #ifndef WITH_NOSTDLIB
15466 SOAP_FMAC1
15467 char*
15468 SOAP_FMAC2
15469 soap_sprint_fault(struct soap *soap, char *buf, size_t len)
15470 { if (soap_check_state(soap))
15471 strncpy(buf, "Error: soap struct not initialized", len);
15472 else if (soap->error)
15473 { const char *c, *v = NULL, *s, **d;
15474 d = soap_faultcode(soap);
15475 if (!*d)
15476 soap_set_fault(soap);
15477 c = *d;
15478 if (soap->version == 2)
15479 v = *soap_faultsubcode(soap);
15480 s = *soap_faultstring(soap);
15481 d = soap_faultdetail(soap);
15482 #ifdef HAVE_SNPRINTF
15483 # ifdef WIN32
15484 _snprintf
15485 # else
15486 snprintf
15487 # endif
15488 (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]");
15489 #else
15490 if (len > 40 + (v ? strlen(v) : 0) + (s ? strlen(s) : 0) + (d && *d ? strlen(*d) : 0))
15491 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]");
15492 else if (len > 40)
15493 sprintf(buf, "%s%d fault: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, c);
15494 else
15495 buf[0] = '\0';
15496 #endif
15498 return buf;
15500 #endif
15501 #endif
15503 /******************************************************************************/
15504 #ifndef PALM_1
15505 #ifndef WITH_NOSTDLIB
15506 SOAP_FMAC1
15507 void
15508 SOAP_FMAC2
15509 soap_print_fault_location(struct soap *soap, FILE *fd)
15511 #ifndef WITH_LEAN
15512 int i, j, c1, c2;
15513 if (soap->error && soap->error != SOAP_STOP && soap->bufidx <= soap->buflen && soap->buflen > 0 && soap->buflen <= SOAP_BUFLEN)
15514 { i = (int)soap->bufidx - 1;
15515 if (i <= 0)
15516 i = 0;
15517 c1 = soap->buf[i];
15518 soap->buf[i] = '\0';
15519 if ((int)soap->buflen >= i + 1024)
15520 j = i + 1023;
15521 else
15522 j = (int)soap->buflen - 1;
15523 c2 = soap->buf[j];
15524 soap->buf[j] = '\0';
15525 fprintf(fd, "%s%c\n<!-- ** HERE ** -->\n", soap->buf, c1);
15526 if (soap->bufidx < soap->buflen)
15527 fprintf(fd, "%s\n", soap->buf + soap->bufidx);
15528 soap->buf[i] = c1;
15529 soap->buf[j] = c2;
15531 #endif
15533 #endif
15534 #endif
15536 /******************************************************************************/
15537 #ifndef PALM_1
15538 SOAP_FMAC1
15540 SOAP_FMAC2
15541 soap_register_plugin_arg(struct soap *soap, int (*fcreate)(struct soap*, struct soap_plugin*, void*), void *arg)
15542 { register struct soap_plugin *p;
15543 register int r;
15544 if (!(p = (struct soap_plugin*)SOAP_MALLOC(soap, sizeof(struct soap_plugin))))
15545 return soap->error = SOAP_EOM;
15546 p->id = NULL;
15547 p->data = NULL;
15548 p->fcopy = NULL;
15549 p->fdelete = NULL;
15550 r = fcreate(soap, p, arg);
15551 if (!r && p->fdelete)
15552 { p->next = soap->plugins;
15553 soap->plugins = p;
15554 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Registered '%s' plugin\n", p->id));
15555 return SOAP_OK;
15557 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));
15558 SOAP_FREE(soap, p);
15559 return r;
15561 #endif
15563 /******************************************************************************/
15564 #ifndef PALM_1
15565 static void *
15566 fplugin(struct soap *soap, const char *id)
15567 { register struct soap_plugin *p;
15568 for (p = soap->plugins; p; p = p->next)
15569 if (p->id == id || !strcmp(p->id, id))
15570 return p->data;
15571 return NULL;
15573 #endif
15575 /******************************************************************************/
15576 #ifndef PALM_2
15577 SOAP_FMAC1
15578 void *
15579 SOAP_FMAC2
15580 soap_lookup_plugin(struct soap *soap, const char *id)
15581 { return soap->fplugin(soap, id);
15583 #endif
15585 /******************************************************************************/
15586 #ifdef __cplusplus
15588 #endif
15590 /******************************************************************************\
15592 * C++ soap struct methods
15594 \******************************************************************************/
15596 #ifdef __cplusplus
15597 soap::soap()
15598 { soap_init(this);
15600 #endif
15602 /******************************************************************************/
15603 #ifdef __cplusplus
15604 soap::soap(soap_mode m)
15605 { soap_init1(this, m);
15607 #endif
15609 /******************************************************************************/
15610 #ifdef __cplusplus
15611 soap::soap(soap_mode im, soap_mode om)
15612 { soap_init2(this, im, om);
15614 #endif
15616 /******************************************************************************/
15617 #ifdef __cplusplus
15618 soap::soap(const struct soap& soap)
15619 { soap_copy_context(this, &soap);
15621 #endif
15623 /******************************************************************************/
15624 #ifdef __cplusplus
15625 soap::~soap()
15626 { soap_destroy(this);
15627 soap_end(this);
15628 soap_done(this);
15630 #endif
15632 /******************************************************************************/