xref: /onnv-gate/usr/src/lib/libkmsagent/common/SOAP/stdsoap2.cpp (revision 12720:3db6e0082404)
1 /*
2  * CDDL HEADER START
3  *
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.
7  *
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.
12  *
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]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 /*
26 	stdsoap2.c[pp] 2.7.17
27 
28 	gSOAP runtime engine
29 
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:
36 
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
50 
51 
52   Wind River Systems Inc., for the following additions under gSOAP public license:
53   - vxWorks compatible
54 --------------------------------------------------------------------------------
55 gSOAP public license.
56 
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.
64 
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.
69 
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.
74 
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.
78 
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
82 
83 Author contact information:
84 engelen@genivia.com / engelen@acm.org
85 
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 --------------------------------------------------------------------------------
91 
92 Installation note:
93 
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
98 
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.
102 
103 */
104 
105 #ifdef AS400
106 # pragma convert(819)	/* EBCDIC to ASCII */
107 #endif
108 
109 #include "stdsoap2.h"
110 
111 /*
112  Oracle customization for OpenSSL 0.9.8 removal of deprecated function usage: RSA_generate_key
113 */
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
121 
122 #ifdef SOAP_MEM_DEBUG
123 #ifndef WIN32
124 #include <ucontext.h>   /* Oracle customization (for printstack(3C)) */
125 #endif
126 #endif
127 
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
140 
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
147 
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
152 
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 ''' */
159 
160 #define soap_blank(c)		((c) >= 0 && (c) <= 32)
161 #define soap_notblank(c)	((c) > 32)
162 
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
168 
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
176 
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
182 
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
188 
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
207 
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
214 
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
225 
226 #ifdef WITH_GZIP
227 static int soap_getgziphdr(struct soap*);
228 #endif
229 
230 #ifdef WITH_OPENSSL
231 int soap_ssl_init_done = 0;
232 
233 //
234 // Oracle customization
235 //
236 // Function ssl_auth_init was static, but is now exported for external override
237 /*
238 static int ssl_auth_init(struct soap*);
239 */
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
245 
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
251 
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
266 
267 #ifndef WITH_NOIO
268 
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
285 
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
290 
291 #if defined(WIN32)
292   #define SOAP_SOCKBLOCK(fd) \
293   { u_long blocking = 0; \
294     ioctlsocket(fd, FIONBIO, &blocking); \
295   }
296   #define SOAP_SOCKNONBLOCK(fd) \
297   { u_long nonblocking = 1; \
298     ioctlsocket(fd, FIONBIO, &nonblocking); \
299   }
300 #elif defined(VXWORKS)
301   #define SOAP_SOCKBLOCK(fd) \
302   { u_long blocking = 0; \
303     ioctl(fd, FIONBIO, (int)(&blocking)); \
304   }
305   #define SOAP_SOCKNONBLOCK(fd) \
306   { u_long nonblocking = 1; \
307     ioctl(fd, FIONBIO, (int)(&nonblocking)); \
308   }
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); \
316   }
317   #define SOAP_SOCKNONBLOCK(fd) \
318   { long nonblocking = 1; \
319     ioctl(fd, 0/*FIONBIO*/, &nonblocking); \
320   }
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
325 
326 #endif
327 
328 #if defined(PALM) && !defined(PALM_2)
329 unsigned short errno;
330 #endif
331 
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
339 
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
345 
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                   ";
350 */
351 #endif
352 
353 #ifndef SOAP_CANARY
354 # define SOAP_CANARY (0xC0DE)
355 #endif
356 
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)
361 
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 }
461 };
462 #endif
463 
464 #ifndef WITH_NOIO
465 #ifndef WITH_LEAN
466 static const struct soap_code_map h_error_codes[] =
467 {
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 }
484 };
485 #endif
486 #endif
487 
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 }
530 };
531 #endif
532 #endif
533 
534 #ifdef WITH_OPENSSL
535 static const struct soap_code_map h_ssl_error_codes[] =
536 {
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 }
546 };
547 #endif
548 
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 }
559 };
560 #endif
561 
562 #ifdef WIN32
563 static int tcp_done = 0;
564 #endif
565 
566 #if defined(HP_UX) && defined(HAVE_GETHOSTBYNAME_R)
567 extern int h_errno;
568 #endif
569 
570 /******************************************************************************/
571 #ifndef WITH_NOIO
572 #ifndef PALM_1
573 static int
fsend(struct soap * soap,const char * s,size_t n)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;
583   }
584 #endif
585   while (n)
586   { if (soap_valid_socket(soap->socket))
587     {
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;
606         }
607       }
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 */
631           do
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;
640           }
641           while (nwritten < 0 && --udp_repeat > 0);
642         }
643       }
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)
652       {
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;
659         }
660 #endif
661         if (err == SOAP_EWOULDBLOCK || err == SOAP_EAGAIN)
662         {
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;
675         }
676         else if (err && err != SOAP_EINTR)
677         { soap->errnum = err;
678           return SOAP_EOF;
679         }
680         nwritten = 0; /* and call write() again */
681       }
682     }
683     else
684     {
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)
709       {
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;
718         }
719         nwritten = 0; /* and call write() again */
720       }
721     }
722     n -= nwritten;
723     s += nwritten;
724   }
725   return SOAP_OK;
726 }
727 #endif
728 #endif
729 
730 /******************************************************************************/
731 #ifndef PALM_1
732 SOAP_FMAC1
733 int
734 SOAP_FMAC2
soap_send_raw(struct soap * soap,const char * s,size_t n)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;
745   }
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;
756     }
757     memcpy(soap->buf + soap->bufidx, s, n);
758     soap->bufidx += n;
759     return SOAP_OK;
760   }
761   return soap_flush_raw(soap, s, n);
762 }
763 #endif
764 
765 /******************************************************************************/
766 #ifndef PALM_1
767 SOAP_FMAC1
768 int
769 SOAP_FMAC2
soap_flush(struct soap * soap)770 soap_flush(struct soap *soap)
771 { register size_t n = soap->bufidx;
772   if (n)
773   {
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;
779     }
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
789       do
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;
794         }
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;
800         }
801       } while (soap->d_stream->avail_in);
802     }
803     else
804 #endif
805       return soap_flush_raw(soap, soap->buf, n);
806   }
807   return SOAP_OK;
808 }
809 #endif
810 
811 /******************************************************************************/
812 #ifndef PALM_1
813 SOAP_FMAC1
814 int
815 SOAP_FMAC2
soap_flush_raw(struct soap * soap,const char * s,size_t n)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;
823   }
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;
832   }
833   DBGMSG(SENT, s, n);
834 #endif
835   return soap->error = soap->fsend(soap, s, n);
836 }
837 #endif
838 
839 /******************************************************************************/
840 #ifndef PALM_1
841 SOAP_FMAC1
842 int
843 SOAP_FMAC2
soap_send(struct soap * soap,const char * s)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;
848 }
849 #endif
850 
851 /******************************************************************************/
852 #ifndef WITH_LEANER
853 #ifndef PALM_1
854 SOAP_FMAC1
855 int
856 SOAP_FMAC2
soap_send2(struct soap * soap,const char * s1,const char * s2)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);
861 }
862 #endif
863 #endif
864 
865 /******************************************************************************/
866 #ifndef WITH_LEANER
867 #ifndef PALM_1
868 SOAP_FMAC1
869 int
870 SOAP_FMAC2
soap_send3(struct soap * soap,const char * s1,const char * s2,const char * s3)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);
876 }
877 #endif
878 #endif
879 
880 /******************************************************************************/
881 #ifndef WITH_NOIO
882 #ifndef PALM_1
883 static size_t
frecv(struct soap * soap,char * s,size_t n)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;
893   }
894 #endif
895   if (soap_valid_socket(soap->socket))
896   { for (;;)
897     {
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;
915         }
916       }
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;
925       }
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;
931       }
932       else
933 #endif
934       {
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
944         }
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;
957         }
958       }
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;
973        }
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;
981       }
982 #endif
983     }
984   }
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
1007 }
1008 #endif
1009 #endif
1010 
1011 /******************************************************************************/
1012 #ifndef WITH_NOHTTP
1013 #ifndef PALM_1
1014 static soap_wchar
soap_getchunkchar(struct soap * soap)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;
1025 }
1026 #endif
1027 #endif
1028 
1029 /******************************************************************************/
1030 #ifndef PALM_1
1031 static int
soap_isxdigit(int c)1032 soap_isxdigit(int c)
1033 { return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
1034 }
1035 #endif
1036 
1037 /******************************************************************************/
1038 #ifndef PALM_1
1039 SOAP_FMAC1
1040 int
1041 SOAP_FMAC2
soap_recv_raw(struct soap * soap)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;
1067         }
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;
1078         }
1079       }
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;
1085       }
1086     }
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;
1091     }
1092     DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- compressed ----\n"));
1093   }
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;
1107       }
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;
1116       }
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;
1124       }
1125       do
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;
1143       }
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)));
1151       }
1152       else if (soap->chunkbuflen)
1153         soap->chunksize = 0;
1154       ret = soap->buflen - soap->bufidx;
1155       if (ret)
1156         break;
1157     }
1158   }
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);
1165   }
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;
1190       }
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
1197     }
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;
1203     }
1204   }
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;
1216 }
1217 #endif
1218 
1219 /******************************************************************************/
1220 #ifndef PALM_1
1221 SOAP_FMAC1
1222 int
1223 SOAP_FMAC2
soap_recv(struct soap * soap)1224 soap_recv(struct soap *soap)
1225 {
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;
1241       }
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;
1249       }
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;
1259         }
1260         else
1261           soap->dime.chunksize -= soap->buflen - soap->bufidx;
1262       }
1263       else
1264       { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Last chunk\n"));
1265         soap->dime.buflen = 0;
1266         soap->dime.chunksize = 0;
1267       }
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;
1271     }
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;
1280       }
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;
1285     }
1286   }
1287 #endif
1288   return soap_recv_raw(soap);
1289 }
1290 #endif
1291 
1292 /******************************************************************************/
1293 #ifndef PALM_1
1294 SOAP_FMAC1
1295 soap_wchar
1296 SOAP_FMAC2
soap_getchar(struct soap * soap)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;
1304   }
1305   return soap_get1(soap);
1306 }
1307 #endif
1308 
1309 /******************************************************************************/
1310 #ifndef PALM_1
1311 SOAP_FMAC1
1312 const struct soap_code_map*
1313 SOAP_FMAC2
soap_code(const struct soap_code_map * code_map,const char * str)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++;
1320     }
1321   }
1322   return NULL;
1323 }
1324 #endif
1325 
1326 /******************************************************************************/
1327 #ifndef PALM_1
1328 SOAP_FMAC1
1329 long
1330 SOAP_FMAC2
soap_code_int(const struct soap_code_map * code_map,const char * str,long other)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++;
1337     }
1338   }
1339   return other;
1340 }
1341 #endif
1342 
1343 /******************************************************************************/
1344 #ifndef PALM_1
1345 SOAP_FMAC1
1346 const char*
1347 SOAP_FMAC2
soap_code_str(const struct soap_code_map * code_map,long code)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;
1354 }
1355 #endif
1356 
1357 /******************************************************************************/
1358 #ifndef PALM_1
1359 SOAP_FMAC1
1360 long
1361 SOAP_FMAC2
soap_code_bits(const struct soap_code_map * code_map,const char * str)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;
1375         }
1376       }
1377       if (!p->string)
1378         return 0;
1379     }
1380   }
1381   return bits;
1382 }
1383 #endif
1384 
1385 /******************************************************************************/
1386 #ifndef PALM_1
1387 SOAP_FMAC1
1388 const char*
1389 SOAP_FMAC2
soap_code_list(struct soap * soap,const struct soap_code_map * code_map,long code)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;
1402       }
1403       code_map++;
1404     }
1405   }
1406   *t = '\0';
1407   return soap->tmpbuf;
1408 }
1409 #endif
1410 
1411 /******************************************************************************/
1412 #ifndef PALM_1
1413 static soap_wchar
soap_char(struct soap * soap)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;
1424   }
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);
1430   }
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
1446 }
1447 #endif
1448 
1449 /******************************************************************************/
1450 #ifdef WITH_LEAN
1451 #ifndef PALM_1
1452 soap_wchar
soap_get0(struct soap * soap)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];
1457 }
1458 #endif
1459 #endif
1460 
1461 /******************************************************************************/
1462 #ifdef WITH_LEAN
1463 #ifndef PALM_1
1464 soap_wchar
soap_get1(struct soap * soap)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++];
1469 }
1470 #endif
1471 #endif
1472 
1473 /******************************************************************************/
1474 #ifndef PALM_1
1475 SOAP_FMAC1
1476 soap_wchar
1477 SOAP_FMAC2
soap_get(struct soap * soap)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;
1484   }
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);
1497           }
1498           else
1499           { soap_unget(soap, ']');
1500             return ']';
1501           }
1502         }
1503         else
1504         { soap_revget1(soap);
1505           return ']';
1506         }
1507       }
1508       else
1509         return c;
1510     }
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;
1527             }
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);
1534             }
1535           }
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;
1544             }
1545             c = soap_get1(soap);
1546           }
1547           if ((int)c == EOF)
1548             break;
1549           c = soap_get1(soap);
1550           continue;
1551         }
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;
1564     }
1565     break;
1566   }
1567   return c;
1568 }
1569 #endif
1570 
1571 /******************************************************************************/
1572 #ifndef PALM_1
1573 static soap_wchar
soap_get_pi(struct soap * soap)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;
1586     }
1587     c = soap_getchar(soap);
1588   }
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;
1598       }
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;
1602       }
1603     }
1604   }
1605   if ((int)c != EOF)
1606     c = soap_getchar(soap);
1607   return c;
1608 }
1609 #endif
1610 
1611 /******************************************************************************/
1612 #ifndef WITH_LEANER
1613 #ifndef PALM_1
1614 SOAP_FMAC1
1615 int
1616 SOAP_FMAC2
soap_move(struct soap * soap,long n)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;
1623 }
1624 #endif
1625 #endif
1626 
1627 /******************************************************************************/
1628 #ifndef WITH_LEANER
1629 #ifndef PALM_1
1630 SOAP_FMAC1
1631 size_t
1632 SOAP_FMAC2
soap_tell(struct soap * soap)1633 soap_tell(struct soap *soap)
1634 { return soap->count - soap->buflen + soap->bufidx - (soap->ahead != 0);
1635 }
1636 #endif
1637 #endif
1638 
1639 /******************************************************************************/
1640 #ifndef PALM_1
1641 SOAP_FMAC1
1642 int
1643 SOAP_FMAC2
soap_pututf8(struct soap * soap,register unsigned long c)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);
1649   }
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));
1667           }
1668           *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
1669         }
1670         *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
1671       }
1672       *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
1673     }
1674     *t++ = (char)(0x80 | (c & 0x3F));
1675     *t = '\0';
1676   }
1677 #else
1678   sprintf(tmp, "&#%lu;", c);
1679 #endif
1680   return soap_send(soap, tmp);
1681 }
1682 #endif
1683 
1684 /******************************************************************************/
1685 #ifndef PALM_1
1686 SOAP_FMAC1
1687 soap_wchar
1688 SOAP_FMAC2
soap_getutf8(struct soap * soap)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;
1695   }
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;
1703   }
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);
1717 }
1718 #endif
1719 
1720 /******************************************************************************/
1721 #ifndef PALM_1
1722 SOAP_FMAC1
1723 int
1724 SOAP_FMAC2
soap_puthex(struct soap * soap,const unsigned char * s,int n)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;
1733   }
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;
1742   }
1743   return SOAP_OK;
1744 }
1745 #endif
1746 
1747 /******************************************************************************/
1748 #ifndef PALM_1
1749 SOAP_FMAC1
1750 unsigned char*
1751 SOAP_FMAC2
soap_gethex(struct soap * soap,int * n)1752 soap_gethex(struct soap *soap, int *n)
1753 {
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);
1758   }
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;
1782         }
1783       }
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;
1793       }
1794       *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0');
1795     }
1796   }
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;
1806     }
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;
1819         }
1820       }
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;
1828       }
1829       *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0');
1830     }
1831   }
1832 #endif
1833 }
1834 #endif
1835 
1836 /******************************************************************************/
1837 #ifndef PALM_1
1838 SOAP_FMAC1
1839 int
1840 SOAP_FMAC2
soap_putbase64(struct soap * soap,const unsigned char * s,int n)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;
1852   }
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;
1862   }
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;
1875   }
1876   return SOAP_OK;
1877 }
1878 #endif
1879 
1880 /******************************************************************************/
1881 #ifndef PALM_1
1882 SOAP_FMAC1
1883 unsigned char*
1884 SOAP_FMAC2
soap_getbase64(struct soap * soap,int * n,int malloc_flag)1885 soap_getbase64(struct soap *soap, int *n, int malloc_flag)
1886 {
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);
1891   }
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;
1909         do
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;
1922             }
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)
1930                 ;
1931             }
1932             soap_unget(soap, c);
1933             return p;
1934           }
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;
1941             }
1942             m = (m << 6) + b;
1943             j++;
1944           }
1945           else if (!soap_blank(c + '+'))
1946           { soap->error = SOAP_TYPE;
1947             return NULL;
1948           }
1949         } while (j < 4);
1950         *s++ = (char)((m >> 16) & 0xFF);
1951         *s++ = (char)((m >> 8) & 0xFF);
1952         *s++ = (char)(m & 0xFF);
1953       }
1954     }
1955   }
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;
1965     }
1966     for (i = 0; i < SOAP_BLKLEN; i++)
1967     { register unsigned long m = 0;
1968       register int j = 0;
1969       do
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;
1983           }
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)
1989               ;
1990           }
1991           soap_unget(soap, c);
1992           return p;
1993         }
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;
2000           }
2001           m = (m << 6) + b;
2002           j++;
2003         }
2004         else if (!soap_blank(c))
2005         { soap->error = SOAP_TYPE;
2006           return NULL;
2007         }
2008       } while (j < 4);
2009       *s++ = (char)((m >> 16) & 0xFF);
2010       *s++ = (char)((m >> 8) & 0xFF);
2011       *s++ = (char)(m & 0xFF);
2012     }
2013   }
2014 #endif
2015 }
2016 #endif
2017 
2018 /******************************************************************************/
2019 #ifndef WITH_LEANER
2020 #ifndef PALM_1
2021 SOAP_FMAC1
2022 int
2023 SOAP_FMAC2
soap_xop_forward(struct soap * soap,unsigned char ** ptr,int * size,char ** id,char ** type,char ** options)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;
2032     }
2033     if (soap->body && soap_element_end_in(soap, NULL))
2034       return soap->error;
2035   }
2036   soap->body = body;
2037   return SOAP_OK;
2038 }
2039 #endif
2040 #endif
2041 
2042 /******************************************************************************/
2043 #ifndef WITH_LEANER
2044 #ifndef PALM_1
2045 SOAP_FMAC1
2046 int
2047 SOAP_FMAC2
soap_dime_forward(struct soap * soap,unsigned char ** ptr,int * size,char ** id,char ** type,char ** options)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;
2069 }
2070 #endif
2071 #endif
2072 
2073 /******************************************************************************/
2074 #ifndef PALM_1
2075 SOAP_FMAC1
2076 char *
2077 SOAP_FMAC2
soap_strdup(struct soap * soap,const char * s)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;
2083 }
2084 #endif
2085 
2086 /******************************************************************************/
2087 #ifndef PALM_1
2088 SOAP_FMAC1
2089 wchar_t *
2090 SOAP_FMAC2
soap_wstrdup(struct soap * soap,const wchar_t * s)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));
2099   }
2100   return t;
2101 }
2102 #endif
2103 
2104 /******************************************************************************/
2105 #ifndef PALM_1
2106 SOAP_FMAC1
2107 struct soap_blist*
2108 SOAP_FMAC2
soap_new_block(struct soap * soap)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;
2115   }
2116   p->next = soap->blist;
2117   p->ptr = NULL;
2118   p->size = 0;
2119   soap->blist = p;
2120   return p;
2121 }
2122 #endif
2123 
2124 /******************************************************************************/
2125 #ifndef PALM_1
2126 SOAP_FMAC1
2127 void*
2128 SOAP_FMAC2
soap_push_block(struct soap * soap,struct soap_blist * b,size_t n)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;
2137   }
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);
2143 }
2144 #endif
2145 
2146 /******************************************************************************/
2147 #ifndef PALM_1
2148 SOAP_FMAC1
2149 void
2150 SOAP_FMAC2
soap_pop_block(struct soap * soap,struct soap_blist * b)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);
2162 }
2163 #endif
2164 
2165 /******************************************************************************/
2166 #ifndef WITH_NOIDREF
2167 #ifndef PALM_1
2168 static void
soap_update_ptrs(struct soap * soap,char * start,char * end,char * p1,char * p2)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);
2182       }
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);
2188         }
2189       }
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);
2195         }
2196       }
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);
2201         }
2202       }
2203     }
2204   }
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));
2213     }
2214   }
2215 #endif
2216 }
2217 #endif
2218 #endif
2219 
2220 /******************************************************************************/
2221 #ifndef WITH_NOIDREF
2222 #ifndef PALM_1
2223 static int
soap_has_copies(struct soap * soap,register const char * start,register const char * end)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;
2237     }
2238   }
2239   return SOAP_OK;
2240 }
2241 #endif
2242 #endif
2243 
2244 /******************************************************************************/
2245 #ifndef WITH_NOIDREF
2246 #ifndef PALM_1
2247 SOAP_FMAC1
2248 int
2249 SOAP_FMAC2
soap_resolve(struct soap * soap)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;
2269         }
2270       }
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;
2277       }
2278     }
2279   }
2280   do
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;
2290             do
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;
2297           }
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--;
2310             }
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;
2318           }
2319         }
2320       }
2321     }
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));
2328       }
2329     }
2330   }
2331 #endif
2332   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution done\n"));
2333   return SOAP_OK;
2334 }
2335 #endif
2336 #endif
2337 
2338 /******************************************************************************/
2339 #ifndef PALM_1
2340 SOAP_FMAC1
2341 size_t
2342 SOAP_FMAC2
soap_size_block(struct soap * soap,struct soap_blist * b,size_t n)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;
2349   }
2350   return b->size;
2351 }
2352 #endif
2353 
2354 /******************************************************************************/
2355 #ifndef PALM_1
2356 SOAP_FMAC1
2357 char*
2358 SOAP_FMAC2
soap_first_block(struct soap * soap,struct soap_blist * b)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;
2368   do
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);
2376 }
2377 #endif
2378 
2379 /******************************************************************************/
2380 #ifndef PALM_1
2381 SOAP_FMAC1
2382 char*
2383 SOAP_FMAC2
soap_next_block(struct soap * soap,struct soap_blist * b)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);
2395   }
2396   return NULL;
2397 }
2398 #endif
2399 
2400 /******************************************************************************/
2401 #ifndef PALM_1
2402 SOAP_FMAC1
2403 size_t
2404 SOAP_FMAC2
soap_block_size(struct soap * soap,struct soap_blist * b)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*));
2409 }
2410 #endif
2411 
2412 /******************************************************************************/
2413 #ifndef PALM_1
2414 SOAP_FMAC1
2415 void
2416 SOAP_FMAC2
soap_end_block(struct soap * soap,struct soap_blist * b)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);
2426     }
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;
2435         }
2436       }
2437     }
2438     SOAP_FREE(soap, b);
2439   }
2440   DBGLOG(TEST, if (soap->blist) SOAP_MESSAGE(fdebug, "Restore previous block sequence\n"));
2441 }
2442 #endif
2443 
2444 /******************************************************************************/
2445 #ifndef PALM_1
2446 SOAP_FMAC1
2447 char*
2448 SOAP_FMAC2
soap_save_block(struct soap * soap,struct soap_blist * b,char * p,int flag)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;
2468       }
2469     }
2470     else
2471       soap->error = SOAP_EOM;
2472   }
2473   soap_end_block(soap, b);
2474   return p;
2475 }
2476 #endif
2477 
2478 /******************************************************************************/
2479 #ifndef PALM_2
2480 SOAP_FMAC1
2481 char *
2482 SOAP_FMAC2
soap_putsize(struct soap * soap,const char * type,int size)2483 soap_putsize(struct soap *soap, const char *type, int size)
2484 { return soap_putsizes(soap, type, &size, 1);
2485 }
2486 #endif
2487 
2488 /******************************************************************************/
2489 #ifndef PALM_2
2490 SOAP_FMAC1
2491 char *
2492 SOAP_FMAC2
soap_putsizes(struct soap * soap,const char * type,const int * size,int dim)2493 soap_putsizes(struct soap *soap, const char *type, const int *size, int dim)
2494 { return soap_putsizesoffsets(soap, type, size, NULL, dim);
2495 }
2496 #endif
2497 
2498 /******************************************************************************/
2499 #ifndef PALM_2
2500 SOAP_FMAC1
2501 char *
2502 SOAP_FMAC2
soap_putsizesoffsets(struct soap * soap,const char * type,const int * size,const int * offset,int dim)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]);
2511   }
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]);
2517     }
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]);
2522     }
2523     strcat(soap->type, "]");
2524   }
2525   return soap->type;
2526 }
2527 #endif
2528 
2529 /******************************************************************************/
2530 #ifndef PALM_2
2531 SOAP_FMAC1
2532 char *
2533 SOAP_FMAC2
soap_putoffset(struct soap * soap,int offset)2534 soap_putoffset(struct soap *soap, int offset)
2535 { return soap_putoffsets(soap, &offset, 1);
2536 }
2537 #endif
2538 
2539 /******************************************************************************/
2540 #ifndef PALM_2
2541 SOAP_FMAC1
2542 char *
2543 SOAP_FMAC2
soap_putoffsets(struct soap * soap,const int * offset,int dim)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;
2551 }
2552 #endif
2553 
2554 /******************************************************************************/
2555 #ifndef PALM_2
2556 SOAP_FMAC1
2557 int
2558 SOAP_FMAC2
soap_size(const int * size,int dim)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;
2564 }
2565 #endif
2566 
2567 /******************************************************************************/
2568 #ifndef PALM_2
2569 SOAP_FMAC1
2570 int
2571 SOAP_FMAC2
soap_getoffsets(const char * attr,const int * size,int * offset,int dim)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, ',');
2580     }
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, ',');
2587     }
2588   return j;
2589 }
2590 #endif
2591 
2592 /******************************************************************************/
2593 #ifndef PALM_2
2594 SOAP_FMAC1
2595 int
2596 SOAP_FMAC2
soap_getsize(const char * attr1,const char * attr2,int * j)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;
2622     }
2623     if (!attr1)
2624       break;
2625     attr1++;
2626   }
2627   return n - *j;
2628 }
2629 #endif
2630 
2631 /******************************************************************************/
2632 #ifndef PALM_2
2633 SOAP_FMAC1
2634 int
2635 SOAP_FMAC2
soap_getsizes(const char * attr,int * size,int dim)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;
2642   do
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;
2652 }
2653 #endif
2654 
2655 /******************************************************************************/
2656 #ifndef PALM_2
2657 SOAP_FMAC1
2658 int
2659 SOAP_FMAC2
soap_getposition(const char * attr,int * pos)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;
2666   do
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;
2674 }
2675 #endif
2676 
2677 /******************************************************************************/
2678 #ifndef PALM_2
2679 SOAP_FMAC1
2680 struct soap_nlist *
2681 SOAP_FMAC2
soap_push_namespace(struct soap * soap,const char * id,const char * ns)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;
2696         }
2697         break;
2698       }
2699       if (p->out)
2700       { if (!strcmp(ns, p->out))
2701           break;
2702       }
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;
2708         }
2709       }
2710     }
2711     if (!p || !p->id)
2712       i = -1;
2713   }
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;
2720   }
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));
2730   }
2731   else
2732   { np->ns = NULL;
2733     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push OK ('%s' matches '%s' in namespace table)\n", id, p->id));
2734   }
2735   return np;
2736 }
2737 #endif
2738 
2739 /******************************************************************************/
2740 #ifndef PALM_2
2741 SOAP_FMAC1
2742 void
2743 SOAP_FMAC2
soap_pop_namespace(struct soap * soap)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);
2750   }
2751   soap->nlist = np;
2752 }
2753 #endif
2754 
2755 /******************************************************************************/
2756 #ifndef PALM_2
2757 SOAP_FMAC1
2758 int
2759 SOAP_FMAC2
soap_match_namespace(struct soap * soap,const char * id1,const char * id2,size_t n1,size_t n2)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;
2772   }
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;
2779 }
2780 #endif
2781 
2782 /******************************************************************************/
2783 #ifndef PALM_2
2784 SOAP_FMAC1
2785 const char*
2786 SOAP_FMAC2
soap_current_namespace(struct soap * soap,const char * tag)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;
2796   }
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;
2802   }
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);
2808   }
2809   return NULL;
2810 }
2811 #endif
2812 
2813 /******************************************************************************/
2814 #ifndef PALM_2
2815 SOAP_FMAC1
2816 int
2817 SOAP_FMAC2
soap_tag_cmp(const char * s,const char * t)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';
2830       }
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++;
2848         }
2849         break;
2850       }
2851     }
2852     s++;
2853     t++;
2854   }
2855   if (*t == '*' && !t[1])
2856     return 0;
2857   return *t;
2858 }
2859 #endif
2860 
2861 /******************************************************************************/
2862 #ifndef PALM_2
2863 SOAP_FMAC1
2864 int
2865 SOAP_FMAC2
soap_match_tag(struct soap * soap,const char * tag1,const char * tag2)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;
2882       }
2883     }
2884     else if (SOAP_STRCMP(tag1, t + 1))
2885     { return SOAP_TAG_MISMATCH;
2886     }
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;
2892     }
2893     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags and (default) namespaces match: '%s' '%s'\n", tag1, tag2));
2894     return SOAP_OK;
2895   }
2896   if (s)
2897   { if (SOAP_STRCMP(s + 1, tag2))
2898       return SOAP_TAG_MISMATCH;
2899   }
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;
2904 }
2905 #endif
2906 
2907 /******************************************************************************/
2908 #ifndef PALM_2
2909 SOAP_FMAC1
2910 int
2911 SOAP_FMAC2
soap_match_array(struct soap * soap,const char * type)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")
2917     )
2918     { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array type mismatch: '%s' '%s'\n", soap->arrayType, type));
2919       return SOAP_TAG_MISMATCH;
2920     }
2921   return SOAP_OK;
2922 }
2923 #endif
2924 
2925 /******************************************************************************\
2926  *
2927  *	SSL/TLS
2928  *
2929 \******************************************************************************/
2930 
2931 /******************************************************************************/
2932 #ifdef WITH_OPENSSL
2933 #ifndef PALM_2
2934 SOAP_FMAC1
2935 int
2936 SOAP_FMAC2
soap_rand()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;
2943 }
2944 #endif
2945 #endif
2946 
2947 /******************************************************************************/
2948 #ifdef WITH_OPENSSL
2949 #ifndef PALM_2
2950 SOAP_FMAC1
2951 int
2952 SOAP_FMAC2
soap_ssl_server_context(struct soap * soap,unsigned short flags,const char * keyfile,const char * password,const char * cafile,const char * capath,const char * dhfile,const char * randfile,const char * sid)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);
2968   }
2969   return err;
2970 }
2971 #endif
2972 #endif
2973 
2974 /******************************************************************************/
2975 #ifdef WITH_OPENSSL
2976 #ifndef PALM_2
2977 SOAP_FMAC1
2978 int
2979 SOAP_FMAC2
soap_ssl_client_context(struct soap * soap,unsigned short flags,const char * keyfile,const char * password,const char * cafile,const char * capath,const char * randfile)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);
2990 }
2991 #endif
2992 #endif
2993 
2994 /******************************************************************************/
2995 #ifdef WITH_OPENSSL
2996 #ifndef PALM_2
2997 SOAP_FMAC1
2998 void
2999 SOAP_FMAC2
soap_ssl_init()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));
3014       }
3015     }
3016   }
3017 }
3018 #endif
3019 #endif
3020 
3021 /******************************************************************************/
3022 #ifdef WITH_OPENSSL
3023 #ifndef PALM_1
3024 SOAP_FMAC1
3025 const char *
3026 SOAP_FMAC2
soap_ssl_error(struct soap * soap,int ret)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';
3035   }
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));
3047   }
3048   else
3049   { switch (ret)
3050     { case 0:
3051         {
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)
3059           {
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)
3064             {
3065                 strcat(soap->msgbuf, ". ");
3066             }
3067           }
3068           if (myerrno != 0)
3069           {
3070             /* display system error too */
3071             char *mystrerror = strerror(myerrno);
3072             if (strlen(mystrerror)
3073                 < (sizeof(soap->msgbuf) - strlen(soap->msgbuf)))
3074             {
3075                 strncat(soap->msgbuf + strlen(soap->msgbuf), mystrerror,
3076                     strlen(mystrerror));
3077             }
3078             else
3079             {
3080                 strncat(soap->msgbuf + strlen(soap->msgbuf), mystrerror,
3081                     (sizeof(soap->msgbuf) - strlen(soap->msgbuf)));
3082             }
3083             soap->msgbuf[sizeof(soap->msgbuf) - 1] = '\0';
3084           }
3085         }
3086         break;
3087       case -1:
3088         sprintf(soap->msgbuf, "Error observed by underlying BIO: %s", strerror(errno));
3089         break;
3090     }
3091   }
3092   return soap->msgbuf;
3093 }
3094 #endif
3095 #endif
3096 
3097 /******************************************************************************/
3098 #ifdef WITH_OPENSSL
3099 #ifndef PALM_1
3100 static int
ssl_password(char * buf,int num,int rwflag,void * userdata)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));
3105 }
3106 #endif
3107 #endif
3108 
3109 /******************************************************************************/
3110 #ifdef WITH_OPENSSL
3111 #ifndef PALM_1
3112 /*
3113 static int
3114 */
3115 int
ssl_auth_init(struct soap * soap)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
3129   }
3130   //
3131   // Oracle customization
3132   //
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
3136   //
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);
3142   }
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));
3148   }
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);
3152   }
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);
3160     }
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);
3163   }
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);
3169   }
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);
3176     }
3177   }
3178 #endif
3179   if ((soap->ssl_flags & SOAP_SSL_RSA))
3180   {
3181     /*
3182      Oracle customization for OpenSSL 0.9.8 removal of deprecated function usage: RSA_generate_key
3183     */
3184 #ifdef OPENSSL_NO_DEPRECATED
3185     RSA *rsa = RSA_new();
3186     if (!rsa)
3187     {
3188         return soap_set_receiver_error(soap, "SSL error", "Can't allocate RSA struct", SOAP_SSL_ERROR);
3189     }
3190 
3191     BIGNUM *e = BN_new();
3192     if (!e)
3193     {
3194         RSA_free(rsa);
3195         return soap_set_receiver_error(soap, "SSL error", "Can't allocate BIGNUM", SOAP_SSL_ERROR);
3196     }
3197     if (!BN_set_word(e, RSA_F4 ))
3198     {
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);
3202     }
3203 
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
3209     {
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);
3213     }
3214 
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);
3221 /*
3222  Oracle customization for OpenSSL 0.9.8 removal of deprecated function usage: RSA_generate_key
3223 */
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);
3228     }
3229     RSA_free(rsa);
3230 /*
3231  Oracle customization for OpenSSL 0.9.8 removal of deprecated function usage: RSA_generate_key
3232 */
3233 #ifdef OPENSSL_NO_DEPRECATED
3234       BN_free(e);
3235 #endif
3236   }
3237   else if (soap->dhfile)
3238   {
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
3255     }
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);
3263     }
3264     if (!dh || DH_check(dh, &n) != 1 || SSL_CTX_set_tmp_dh(soap->ctx, dh) < 0)
3265     {
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);
3271     }
3272 #ifndef OPENSSL_NO_DEPRECATED
3273     DH_free(dh);
3274 #endif
3275   }
3276 
3277   //
3278   // Oracle customization
3279   //
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
3283 
3284   flags = ((SSL_OP_ALL & ~SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG) | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
3285 
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;
3310 }
3311 #endif
3312 #endif
3313 
3314 /******************************************************************************/
3315 #ifdef WITH_OPENSSL
3316 #ifndef PALM_1
3317 static int
ssl_verify_callback(int ok,X509_STORE_CTX * store)3318 ssl_verify_callback(int ok, X509_STORE_CTX *store)
3319 {
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);
3329   }
3330 #endif
3331   /* Note: return 1 to continue, but unsafe progress will be terminated by SSL */
3332   return ok;
3333 }
3334 #endif
3335 #endif
3336 
3337 /******************************************************************************/
3338 #ifdef WITH_OPENSSL
3339 #ifndef PALM_1
3340 static int
ssl_verify_callback_allow_expired_certificate(int ok,X509_STORE_CTX * store)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)
3344   {
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;
3350   }
3351   /* Note: return 1 to continue, but unsafe progress will be terminated by SSL */
3352   return ok;
3353 }
3354 #endif
3355 #endif
3356 
3357 /******************************************************************************/
3358 #ifdef WITH_OPENSSL
3359 #ifndef WITH_NOIO
3360 #ifndef PALM_1
3361 SOAP_FMAC1
3362 int
3363 SOAP_FMAC2
soap_ssl_accept(struct soap * soap)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);
3375   }
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 )
3388   {
3389       retries = 10 * soap->ssl_accept_timeout;
3390   }
3391 #endif
3392 
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;
3402     }
3403     else
3404     { soap->errnum = soap_socket_errno(soap->socket);
3405       break;
3406     }
3407     if (retries-- <= 0)
3408       break;
3409   }
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;
3414   }
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);
3421     }
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);
3426     }
3427     X509_free(peer);
3428   }
3429   return SOAP_OK;
3430 }
3431 #endif
3432 #endif
3433 #endif
3434 
3435 /******************************************************************************\
3436  *
3437  *	TCP/UDP [SSL/TLS] IPv4 and IPv6
3438  *
3439 \******************************************************************************/
3440 
3441 /******************************************************************************/
3442 #ifndef WITH_NOIO
3443 #ifndef PALM_1
3444 static int
tcp_init(struct soap * soap)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;
3455   }
3456 #endif
3457   return 0;
3458 }
3459 #endif
3460 #endif
3461 
3462 /******************************************************************************/
3463 #ifndef WITH_NOIO
3464 #ifndef PALM_1
3465 static const char*
tcp_error(struct soap * soap)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:
3476     {
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;
3483       }
3484     }
3485   }
3486   return msg;
3487 }
3488 #endif
3489 #endif
3490 
3491 /******************************************************************************/
3492 #ifndef WITH_IPV6
3493 #ifndef WITH_NOIO
3494 #ifndef PALM_1
3495 static int
tcp_gethost(struct soap * soap,const char * addr,struct in_addr * inaddr)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;
3516   }
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;
3525   }
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;
3536   }
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;
3549   }
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;
3556 }
3557 #endif
3558 #endif
3559 #endif
3560 
3561 /******************************************************************************/
3562 #ifndef WITH_NOIO
3563 #ifndef PALM_1
3564 static SOAP_SOCKET
tcp_connect(struct soap * soap,const char * endpoint,const char * host,int port)3565 tcp_connect(struct soap *soap, const char *endpoint, const char *host, int port)
3566 {
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;
3586   }
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)
3607     {
3608       freeaddrinfo(res);
3609     }
3610     return SOAP_INVALID_SOCKET;
3611   }
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))
3628   {
3629 #ifdef WITH_IPV6
3630     if (res->ai_next)
3631     { res = res->ai_next;
3632       goto again;
3633     }
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;
3641   }
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;
3665     }
3666   }
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;
3675   }
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;
3684   }
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;
3693   }
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;
3702   }
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;
3712   }
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;
3723   }
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;
3734   }
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;
3745   }
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;
3751   }
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;
3762       }
3763     }
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;
3770     }
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;
3780     }
3781 #endif
3782   }
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;
3796     }
3797     soap->peer.sin_port = htons((short)soap->proxy_port);
3798   }
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;
3804     }
3805     soap->peer.sin_port = htons((short)port);
3806   }
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;
3818   }
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 (;;)
3828   {
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;
3840       }
3841       else if (soap->connect_timeout && (err == SOAP_EINPROGRESS || err == SOAP_EAGAIN || err == SOAP_EWOULDBLOCK))
3842       {
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;
3858           }
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;
3869           }
3870         }
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;
3883       }
3884 #endif
3885 #ifdef WITH_IPV6
3886       if (res->ai_next)
3887       { res = res->ai_next;
3888         soap->fclosesocket(soap, fd);
3889         goto again;
3890       }
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;
3901       }
3902     }
3903     else
3904       break;
3905   }
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:*"))
3918   {
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;
3936       }
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 */
3945           //
3946           // Oracle customization
3947           // TODO: returning soap->error may also be a bug
3948           //
3949           return soap->error;
3950         }
3951       }
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;
3958       }
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;
3968       }
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;
3976       }
3977       if (endpoint)
3978         strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint)-1); /* restore */
3979       soap->mode = m;
3980     }
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;
3986     }
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;
3994       }
3995     }
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;
4003     }
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;
4014     }
4015     else
4016       SOAP_SOCKBLOCK(fd)
4017 #endif
4018     //
4019     // Oracle customization
4020     //
4021     // Clear error queue of any errors remaining from a previous operation
4022     ERR_clear_error();
4023 
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) */
4027     do
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;
4042           }
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;
4049           }
4050         }
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;
4056         }
4057       }
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;
4069       }
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;
4081         }
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);
4110                 */
4111                 ext_data = meth->d2i(NULL, &data, ext->value->length);
4112               }
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;
4124                     }
4125                   }
4126                   sk_CONF_VALUE_pop_free(val, X509V3_conf_free);
4127                 }
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
4136 	      }
4137             }
4138             if (ok)
4139               break;
4140           }
4141         }
4142         //
4143         // Oracle customization
4144         //
4145         // the certificate subject name is an entity name, not a DNS name
4146         //
4147         /*
4148         if (!ok && (subj = X509_get_subject_name(peer)))
4149         { int i = -1;
4150           do
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);
4166                 }
4167               }
4168             }
4169           } while (!ok);
4170         }
4171         */
4172         X509_free(peer);
4173         /*
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;
4178         }
4179         */
4180       }
4181     }
4182 #ifdef SOAP_DEBUG
4183     //
4184     // Oracle customization for debug
4185     //
4186     if ( SSL_session_reused( soap->ssl ) == 1)
4187     {
4188       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL session reused\n"));
4189     }
4190     else
4191     {
4192       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL session negotiated\n"));
4193     }
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
4201   }
4202   return fd;
4203 }
4204 #endif
4205 #endif
4206 
4207 /******************************************************************************/
4208 #ifndef WITH_NOIO
4209 #ifndef PALM_1
4210 static int
tcp_select(struct soap * soap,SOAP_SOCKET s,int flags,int timeout)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;
4241     }
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;
4252     }
4253     else if (r < 0)
4254       soap->errnum = soap_socket_errno(s);
4255     return r;
4256   }
4257 #else
4258   { soap->error = SOAP_FD_EXCEEDED;
4259     return -1;
4260   }
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);
4268   }
4269   if (flags & SOAP_TCP_SELECT_SND)
4270   { sfd = &fd[1];
4271     FD_ZERO(sfd);
4272     FD_SET(s, sfd);
4273   }
4274   if (flags & SOAP_TCP_SELECT_ERR)
4275   { efd = &fd[2];
4276     FD_ZERO(efd);
4277     FD_SET(s, efd);
4278   }
4279   if (timeout >= 0)
4280   { tv.tv_sec = timeout;
4281     tv.tv_usec = 0;
4282   }
4283   else
4284   { tv.tv_sec = -timeout / 1000000;
4285     tv.tv_usec = -timeout % 1000000;
4286   }
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;
4296   }
4297   else if (r < 0)
4298     soap->errnum = soap_socket_errno(s);
4299   return r;
4300 }
4301 #endif
4302 #endif
4303 
4304 /******************************************************************************/
4305 #ifndef WITH_NOIO
4306 #ifndef PALM_1
4307 static SOAP_SOCKET
tcp_accept(struct soap * soap,SOAP_SOCKET s,struct sockaddr * a,int * n)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;
4321 }
4322 #endif
4323 #endif
4324 
4325 /******************************************************************************/
4326 #ifndef WITH_NOIO
4327 #ifndef PALM_1
4328 static int
tcp_disconnect(struct soap * soap)4329 tcp_disconnect(struct soap *soap)
4330 {
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;
4337     }
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;
4343       }
4344     }
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;
4352       }
4353     }
4354     if (r == 0)
4355     { if (soap_valid_socket(soap->socket))
4356       { if (!soap->fshutdownsocket(soap, soap->socket, 1))
4357         {
4358 #ifndef WITH_LEAN
4359 	  /*
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)
4363           */
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;
4372           }
4373 #else
4374           r = SSL_shutdown(soap->ssl);
4375 #endif
4376         }
4377       }
4378     }
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;
4386         }
4387       }
4388     }
4389     SSL_free(soap->ssl);
4390     soap->ssl = NULL;
4391     if (s)
4392       return SOAP_SSL_ERROR;
4393     ERR_remove_state(0);
4394   }
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;
4400   }
4401   return SOAP_OK;
4402 }
4403 #endif
4404 #endif
4405 
4406 /******************************************************************************/
4407 #ifndef WITH_NOIO
4408 #ifndef PALM_1
4409 static int
tcp_closesocket(struct soap * soap,SOAP_SOCKET fd)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);
4413 }
4414 #endif
4415 #endif
4416 
4417 /******************************************************************************/
4418 #ifndef WITH_NOIO
4419 #ifndef PALM_1
4420 static int
tcp_shutdownsocket(struct soap * soap,SOAP_SOCKET fd,int how)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);
4424 }
4425 #endif
4426 #endif
4427 
4428 /******************************************************************************/
4429 #ifndef WITH_NOIO
4430 #ifndef PALM_1
4431 SOAP_FMAC1
4432 SOAP_SOCKET
4433 SOAP_FMAC2
soap_bind(struct soap * soap,const char * host,int port,int backlog)4434 soap_bind(struct soap *soap, const char *host, int port, int backlog)
4435 {
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;
4457   }
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;
4463   }
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)
4480     {
4481       freeaddrinfo(addrinfo);
4482     }
4483     return SOAP_INVALID_SOCKET;
4484   }
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;
4505   }
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;
4524   }
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;
4529   }
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;
4534   }
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;
4539   }
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;
4545   }
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;
4554   }
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;
4563   }
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;
4573     }
4574   }
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;
4585   }
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;
4593   }
4594   return soap->master;
4595 }
4596 #endif
4597 #endif
4598 
4599 /******************************************************************************/
4600 #ifndef WITH_NOIO
4601 #ifndef PALM_1
4602 SOAP_FMAC1
4603 int
4604 SOAP_FMAC2
soap_poll(struct soap * soap)4605 soap_poll(struct soap *soap)
4606 {
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;
4613   }
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)
4619   {
4620 #ifdef WITH_OPENSSL
4621     if (soap->imode & SOAP_ENC_SSL)
4622     {
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;
4628     }
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;
4636   }
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;
4641     }
4642   }
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
4648 }
4649 #endif
4650 #endif
4651 
4652 /******************************************************************************/
4653 #ifndef WITH_NOIO
4654 #ifndef PALM_1
4655 SOAP_FMAC1
4656 SOAP_SOCKET
4657 SOAP_FMAC2
soap_accept(struct soap * soap)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;
4685           }
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;
4692             }
4693 	  }
4694         }
4695       }
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))
4703       {
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));
4708         //
4709         // Oracle customization
4710         //
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;
4731           }
4732         }
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;
4738         }
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;
4744         }
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;
4750         }
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;
4756         }
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;
4763         }
4764 #endif
4765 #endif
4766         soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0);
4767         return soap->socket;
4768       }
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;
4776       }
4777     }
4778   }
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;
4783   }
4784 }
4785 #endif
4786 #endif
4787 
4788 /******************************************************************************/
4789 #ifndef PALM_1
4790 SOAP_FMAC1
4791 int
4792 SOAP_FMAC2
soap_closesock(struct soap * soap)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;
4807   }
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;
4816 }
4817 #endif
4818 
4819 /******************************************************************************/
4820 #ifndef WITH_NOIO
4821 #ifndef PALM_2
4822 SOAP_FMAC1
4823 void
4824 SOAP_FMAC2
soap_cleanup(struct soap * soap)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
4833 }
4834 #endif
4835 #endif
4836 
4837 /******************************************************************************/
4838 #ifndef PALM_1
4839 SOAP_FMAC1
4840 void
4841 SOAP_FMAC2
soap_done(struct soap * soap)4842 soap_done(struct soap *soap)
4843 {
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;
4855   }
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;
4870   }
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;
4920   }
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;
4926     }
4927   }
4928 #ifdef WITH_OPENSSL
4929   if (soap->ssl)
4930   { SSL_free(soap->ssl);
4931     soap->ssl = NULL;
4932   }
4933   if (soap->state == SOAP_INIT)
4934   { if (soap->ctx)
4935     { SSL_CTX_free(soap->ctx);
4936       soap->ctx = NULL;
4937     }
4938   }
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;
4950   }
4951   if (soap->z_buf)
4952   { SOAP_FREE(soap, (void*)soap->z_buf);
4953     soap->z_buf = NULL;
4954   }
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;
4962     }
4963     soap_close_logfile(soap, i);
4964   }
4965   soap->state = SOAP_NONE;
4966 #endif
4967 #ifdef SOAP_MEM_DEBUG
4968   soap_free_mht(soap);
4969 #endif
4970 }
4971 #endif
4972 
4973 /******************************************************************************\
4974  *
4975  *	HTTP
4976  *
4977 \******************************************************************************/
4978 
4979 /******************************************************************************/
4980 #ifndef WITH_NOHTTP
4981 #ifndef PALM_1
4982 static int
http_parse(struct soap * soap)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;
4996   do
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;
5001     }
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;
5006     }
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;
5016         }
5017         return soap->error;
5018       }
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;
5041         }
5042       }
5043     }
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;
5053     }
5054   }
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;
5071     }
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;
5090 	}
5091         if (soap->error == SOAP_OK)
5092           soap->error = SOAP_STOP; /* prevents further processing */
5093         return soap->error;
5094       }
5095       if (status)
5096         return soap->error = status;
5097     }
5098     else if (status)
5099       return soap->error = status;
5100     else if (s)
5101       return soap->error = 405;
5102   }
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)
5111   */
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);
5121   }
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);
5124 }
5125 #endif
5126 #endif
5127 
5128 /******************************************************************************/
5129 #ifndef WITH_NOHTTP
5130 #ifndef PALM_1
5131 static int
http_parse_header(struct soap * soap,const char * key,const char * val)5132 http_parse_header(struct soap *soap, const char *key, const char *val)
5133 { if (!soap_tag_cmp(key, "Host"))
5134   {
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';
5143   }
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;
5155     }
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';
5161       }
5162       else
5163         soap->action = soap_strdup(soap, action);
5164     }
5165   }
5166 #endif
5167   else if (!soap_tag_cmp(key, "Content-Length"))
5168   { soap->length = soap_strtoul(val, NULL, 10);
5169   }
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
5183   }
5184 #ifdef WITH_ZLIB
5185   else if (!soap_tag_cmp(key, "Accept-Encoding"))
5186   {
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;
5196   }
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;
5202   }
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;
5208   }
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);
5220       }
5221     }
5222   }
5223   else if (!soap_tag_cmp(key, "WWW-Authenticate"))
5224   { soap->authrealm = soap_strdup(soap, soap_get_header_attribute(soap, val + 6, "realm"));
5225   }
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;
5231     }
5232   }
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';
5238     }
5239     else
5240       soap->action = soap_strdup(soap, val);
5241   }
5242   else if (!soap_tag_cmp(key, "Location"))
5243   { strncpy(soap->endpoint, val, sizeof(soap->endpoint));
5244     soap->endpoint[sizeof(soap->endpoint) - 1] = '\0';
5245   }
5246   else if (!soap_tag_cmp(key, "X-Forwarded-For"))
5247   { soap->proxy_from = soap_strdup(soap, val);
5248   }
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);
5255   }
5256 #endif
5257   return SOAP_OK;
5258 }
5259 #endif
5260 #endif
5261 
5262 /******************************************************************************/
5263 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
5264 #ifndef PALM_1
5265 SOAP_FMAC1
5266 const char*
5267 SOAP_FMAC2
soap_get_header_attribute(struct soap * soap,const char * line,const char * key)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;
5278     }
5279   }
5280   return NULL;
5281 }
5282 #endif
5283 #endif
5284 
5285 /******************************************************************************/
5286 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
5287 #ifndef PALM_1
5288 SOAP_FMAC1
5289 const char*
5290 SOAP_FMAC2
soap_decode_key(char * buf,size_t len,const char * val)5291 soap_decode_key(char *buf, size_t len, const char *val)
5292 { return soap_decode(buf, len, val, "=,;");
5293 }
5294 #endif
5295 #endif
5296 
5297 /******************************************************************************/
5298 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
5299 #ifndef PALM_1
5300 SOAP_FMAC1
5301 const char*
5302 SOAP_FMAC2
soap_decode_val(char * buf,size_t len,const char * val)5303 soap_decode_val(char *buf, size_t len, const char *val)
5304 { if (*val != '=')
5305   { *buf = '\0';
5306     return val;
5307   }
5308   return soap_decode(buf, len, val + 1, ",;");
5309 }
5310 #endif
5311 #endif
5312 
5313 /******************************************************************************/
5314 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
5315 #ifndef PALM_1
5316 static const char*
soap_decode(char * buf,size_t len,const char * val,const char * sep)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++;
5327   }
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;
5334       }
5335       else
5336         *t++ = *s++;
5337     }
5338   }
5339   *t = '\0';
5340   while (*s && !strchr(sep, *s))
5341     s++;
5342   return s;
5343 }
5344 #endif
5345 #endif
5346 
5347 /******************************************************************************/
5348 #ifndef WITH_NOHTTP
5349 #ifndef PALM_1
5350 static const char*
http_error(struct soap * soap,int status)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;
5359 }
5360 #endif
5361 #endif
5362 
5363 /******************************************************************************/
5364 #ifndef WITH_NOHTTP
5365 #ifndef PALM_1
5366 static int
http_get(struct soap * soap)5367 http_get(struct soap *soap)
5368 { return SOAP_GET_METHOD;
5369 }
5370 #endif
5371 #endif
5372 
5373 /******************************************************************************/
5374 #ifndef WITH_NOHTTP
5375 #ifndef PALM_1
5376 static int
http_405(struct soap * soap)5377 http_405(struct soap *soap)
5378 { return 405;
5379 }
5380 #endif
5381 #endif
5382 
5383 /******************************************************************************/
5384 #ifndef WITH_NOHTTP
5385 #ifndef PALM_1
5386 static int
http_post(struct soap * soap,const char * endpoint,const char * host,int port,const char * path,const char * action,size_t count)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';
5420   }
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;
5442   }
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;
5449   }
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;
5464   }
5465   return soap->fposthdr(soap, NULL, NULL);
5466 }
5467 #endif
5468 #endif
5469 
5470 /******************************************************************************/
5471 #ifndef WITH_NOHTTP
5472 #ifndef PALM_1
5473 static int
http_send_header(struct soap * soap,const char * s)5474 http_send_header(struct soap *soap, const char *s)
5475 { register const char *t;
5476   do
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;
5485 }
5486 #endif
5487 #endif
5488 
5489 /******************************************************************************/
5490 #ifndef WITH_NOHTTP
5491 #ifndef PALM_1
5492 static int
http_post_header(struct soap * soap,const char * key,const char * val)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;
5499   }
5500   return soap_send_raw(soap, "\r\n", 2);
5501 }
5502 #endif
5503 #endif
5504 
5505 /******************************************************************************/
5506 #ifndef WITH_NOHTTP
5507 #ifndef PALM_1
5508 static int
http_response(struct soap * soap,int status,size_t count)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;
5532     }
5533     else if ((err = soap->fposthdr(soap, "Status", s))) /* CGI header */
5534       return err;
5535   }
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;
5545     }
5546     else if ((status >= 301 && status <= 303) || status == 307)
5547     { if ((err = soap->fposthdr(soap, "Location", soap->endpoint)))
5548         return err;
5549     }
5550 #endif
5551   }
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;
5569     }
5570     else if ((err = soap->fposthdr(soap, "Status", s)))	/* CGI */
5571       return err;
5572   }
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);
5581 }
5582 #endif
5583 #endif
5584 
5585 /******************************************************************************/
5586 #ifndef PALM_1
5587 SOAP_FMAC1
5588 int
5589 SOAP_FMAC2
soap_response(struct soap * soap,int status)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;
5611     }
5612 #endif
5613     soap->mode = n;
5614   }
5615 #endif
5616   return SOAP_OK;
5617 }
5618 #endif
5619 
5620 /******************************************************************************\
5621  *
5622  *	HTTP Cookies
5623  *
5624 \******************************************************************************/
5625 
5626 #ifdef WITH_COOKIES
5627 /******************************************************************************/
5628 SOAP_FMAC1
5629 size_t
5630 SOAP_FMAC2
soap_encode_cookie(const char * s,char * t,size_t len)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;
5643     }
5644     else
5645       break;
5646   }
5647   *t = '\0';
5648   return len - n;
5649 }
5650 
5651 /******************************************************************************/
5652 SOAP_FMAC1
5653 struct soap_cookie*
5654 SOAP_FMAC2
soap_cookie(struct soap * soap,const char * name,const char * domain,const char * path)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;
5674   }
5675   return p;
5676 }
5677 
5678 /******************************************************************************/
5679 SOAP_FMAC1
5680 struct soap_cookie*
5681 SOAP_FMAC2
soap_set_cookie(struct soap * soap,const char * name,const char * value,const char * domain,const char * path)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;
5713       }
5714       else
5715       { SOAP_FREE(soap, q->name);
5716         SOAP_FREE(soap, q);
5717         q = NULL;
5718       }
5719     }
5720   }
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;
5728       }
5729     }
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;
5736       }
5737     }
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;
5744       }
5745     }
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;
5750   }
5751   return q;
5752 }
5753 
5754 /******************************************************************************/
5755 SOAP_FMAC1
5756 void
5757 SOAP_FMAC2
soap_clr_cookie(struct soap * soap,const char * name,const char * domain,const char * path)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;
5765   }
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;
5771   }
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);
5784     }
5785     else
5786       p = &q->next;
5787   }
5788 }
5789 
5790 /******************************************************************************/
5791 SOAP_FMAC1
5792 char *
5793 SOAP_FMAC2
soap_cookie_value(struct soap * soap,const char * name,const char * domain,const char * path)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;
5799 }
5800 
5801 /******************************************************************************/
5802 SOAP_FMAC1
5803 char *
5804 SOAP_FMAC2
soap_env_cookie_value(struct soap * soap,const char * name,const char * domain,const char * path)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;
5810 }
5811 
5812 /******************************************************************************/
5813 SOAP_FMAC1
5814 time_t
5815 SOAP_FMAC2
soap_cookie_expire(struct soap * soap,const char * name,const char * domain,const char * path)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;
5821 }
5822 
5823 /******************************************************************************/
5824 SOAP_FMAC1
5825 int
5826 SOAP_FMAC2
soap_set_cookie_expire(struct soap * soap,const char * name,long expire,const char * domain,const char * path)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;
5834   }
5835   return SOAP_ERR;
5836 }
5837 
5838 /******************************************************************************/
5839 SOAP_FMAC1
5840 int
5841 SOAP_FMAC2
soap_set_cookie_session(struct soap * soap,const char * name,const char * domain,const char * path)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;
5848   }
5849   return SOAP_ERR;
5850 }
5851 
5852 /******************************************************************************/
5853 SOAP_FMAC1
5854 int
5855 SOAP_FMAC2
soap_clr_cookie_session(struct soap * soap,const char * name,const char * domain,const char * path)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;
5862   }
5863   return SOAP_ERR;
5864 }
5865 
5866 /******************************************************************************/
5867 SOAP_FMAC1
5868 int
5869 SOAP_FMAC2
soap_putsetcookies(struct soap * soap)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)
5875   {
5876     if (p->modified
5877 #ifdef WITH_OPENSSL
5878      || (!p->env && !soap->ssl == !p->secure)
5879 #endif
5880        )
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);
5887       }
5888       if (p->domain && (int)strlen(p->domain) < tmp-s+4064)
5889       { strcpy(s, ";Domain=");
5890         strcat(s, p->domain);
5891       }
5892       else if (soap->cookie_domain && (int)strlen(soap->cookie_domain) < tmp-s+4064)
5893       { strcpy(s, ";Domain=");
5894         strcat(s, soap->cookie_domain);
5895       }
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);
5909           }
5910           else
5911             s += soap_encode_cookie(t, s, tmp-s+4064);
5912         }
5913       }
5914       if (p->version > 0 && s-tmp < 4060)
5915       { sprintf(s, ";Version=%u", p->version);
5916         s += strlen(s);
5917       }
5918       if (p->maxage >= 0 && s-tmp < 4060)
5919       { sprintf(s, ";Max-Age=%ld", p->maxage);
5920         s += strlen(s);
5921       }
5922       if (s-tmp < 4073
5923        && (p->secure
5924 #ifdef WITH_OPENSSL
5925        || soap->ssl
5926 #endif
5927          ))
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;
5932     }
5933   }
5934   return SOAP_OK;
5935 }
5936 
5937 /******************************************************************************/
5938 SOAP_FMAC1
5939 int
5940 SOAP_FMAC2
soap_putcookies(struct soap * soap,const char * domain,const char * path,int secure)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);
5962     }
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);
5976       }
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);
5986         }
5987       }
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;
5996         }
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);
6002         }
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);
6006         }
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;
6012       }
6013       p = &q->next;
6014     }
6015   }
6016   return SOAP_OK;
6017 }
6018 
6019 /******************************************************************************/
6020 SOAP_FMAC1
6021 void
6022 SOAP_FMAC2
soap_getcookies(struct soap * soap,const char * val)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);
6042       }
6043     }
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);
6049       }
6050       else
6051         t = NULL;
6052       if (p)
6053       { if (p->path)
6054           SOAP_FREE(soap, p->path);
6055         p->path = t;
6056       }
6057       else
6058       { if (path)
6059           SOAP_FREE(soap, path);
6060         path = t;
6061       }
6062     }
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);
6068       }
6069       else
6070         t = NULL;
6071       if (p)
6072       { if (p->domain)
6073           SOAP_FREE(soap, p->domain);
6074         p->domain = t;
6075       }
6076       else
6077       { if (domain)
6078           SOAP_FREE(soap, domain);
6079         domain = t;
6080       }
6081     }
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);
6089       }
6090       else
6091         p->path = NULL;
6092     }
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);
6100       }
6101       else
6102         p->domain = NULL;
6103     }
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);
6107     }
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);
6111     }
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);
6139       }
6140     }
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;
6151         }
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);
6161       }
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);
6169         }
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);
6177         }
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);
6185         }
6186         else
6187         { p->path = (char*)SOAP_MALLOC(soap, 2);
6188           strcpy(p->path, "/");
6189         }
6190         p->expire = 0;
6191         p->secure = 0;
6192         p->version = version;
6193       }
6194     }
6195   }
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;
6203     }
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);
6213   }
6214   if (domain)
6215     SOAP_FREE(soap, domain);
6216   if (path)
6217     SOAP_FREE(soap, path);
6218 }
6219 
6220 /******************************************************************************/
6221 SOAP_FMAC1
6222 int
6223 SOAP_FMAC2
soap_getenv_cookies(struct soap * soap)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;
6230   do
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;
6238 }
6239 
6240 /******************************************************************************/
6241 SOAP_FMAC1
6242 struct soap_cookie*
6243 SOAP_FMAC2
soap_copy_cookies(struct soap * copy,const struct soap * soap)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);
6254     }
6255     if (p->value)
6256     { if (((*q)->value = (char*)SOAP_MALLOC(copy, strlen(p->value)+1)))
6257         strcpy((*q)->value, p->value);
6258     }
6259     if (p->domain)
6260     { if (((*q)->domain = (char*)SOAP_MALLOC(copy, strlen(p->domain)+1)))
6261         strcpy((*q)->domain, p->domain);
6262     }
6263     if (p->path)
6264     { if (((*q)->path = (char*)SOAP_MALLOC(copy, strlen(p->path)+1)))
6265         strcpy((*q)->path, p->path);
6266     }
6267     q = &(*q)->next;
6268   }
6269   *q = NULL;
6270   return r;
6271 }
6272 
6273 /******************************************************************************/
6274 SOAP_FMAC1
6275 void
6276 SOAP_FMAC2
soap_free_cookies(struct soap * soap)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);
6289   }
6290 }
6291 
6292 /******************************************************************************/
6293 #endif /* WITH_COOKIES */
6294 
6295 /******************************************************************************/
6296 #ifndef WITH_NOIDREF
6297 #ifndef PALM_2
6298 SOAP_FMAC1
6299 size_t
6300 SOAP_FMAC2
soap_hash(register const char * s)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;
6306 }
6307 #endif
6308 #endif
6309 
6310 /******************************************************************************/
6311 #ifndef WITH_NOIDREF
6312 #ifndef PALM_1
6313 static void
soap_init_pht(struct soap * soap)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;
6320 }
6321 #endif
6322 #endif
6323 
6324 /******************************************************************************/
6325 #ifndef PALM_1
6326 SOAP_FMAC1
6327 struct soap*
6328 SOAP_FMAC2
soap_new1(soap_mode mode)6329 soap_new1(soap_mode mode)
6330 { return soap_new2(mode, mode);
6331 }
6332 #endif
6333 
6334 /******************************************************************************/
6335 #ifndef PALM_1
6336 SOAP_FMAC1
6337 struct soap*
6338 SOAP_FMAC2
soap_new()6339 soap_new()
6340 { return soap_new2(SOAP_IO_DEFAULT, SOAP_IO_DEFAULT);
6341 }
6342 #endif
6343 
6344 /******************************************************************************/
6345 #ifndef PALM_1
6346 SOAP_FMAC1
6347 struct soap*
6348 SOAP_FMAC2
soap_new2(soap_mode imode,soap_mode omode)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;
6354 }
6355 #endif
6356 
6357 /******************************************************************************/
6358 #ifndef PALM_1
6359 SOAP_FMAC1
6360 void
6361 SOAP_FMAC2
soap_free(struct soap * soap)6362 soap_free(struct soap *soap)
6363 { soap_done(soap);
6364   free(soap);
6365 }
6366 #endif
6367 
6368 /******************************************************************************/
6369 #ifndef PALM_1
6370 SOAP_FMAC1
6371 void
6372 SOAP_FMAC2
soap_del(struct soap * soap)6373 soap_del(struct soap *soap)
6374 { free(soap);
6375 }
6376 #endif
6377 
6378 /******************************************************************************/
6379 #ifndef WITH_NOIDREF
6380 #ifndef PALM_1
6381 static void
soap_free_pht(struct soap * soap)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);
6389   }
6390   soap->pblk = NULL;
6391   soap->pidx = 0;
6392   for (i = 0; i < (int)SOAP_PTRHASH; i++)
6393     soap->pht[i] = NULL;
6394 }
6395 #endif
6396 #endif
6397 
6398 /******************************************************************************/
6399 #ifndef WITH_NOIDREF
6400 #ifndef PALM_2
6401 SOAP_FMAC1
6402 int
6403 SOAP_FMAC2
soap_embed(struct soap * soap,const void * p,const struct soap_array * a,int n,const char * tag,int type)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);
6418   }
6419   return i;
6420 }
6421 #endif
6422 #endif
6423 
6424 /******************************************************************************/
6425 #ifndef WITH_NOIDREF
6426 #ifndef PALM_2
6427 SOAP_FMAC1
6428 int
6429 SOAP_FMAC2
soap_pointer_lookup(struct soap * soap,const void * p,int type,struct soap_plist ** ppp)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;
6439       }
6440     }
6441   }
6442   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d: not found\n", p, type));
6443   return 0;
6444 }
6445 #endif
6446 #endif
6447 
6448 /******************************************************************************/
6449 #ifndef WITH_NOIDREF
6450 #ifndef PALM_2
6451 SOAP_FMAC1
6452 int
6453 SOAP_FMAC2
soap_pointer_enter(struct soap * soap,const void * p,const struct soap_array * a,int n,int type,struct soap_plist ** ppp)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;
6462     }
6463     pb->next = soap->pblk;
6464     soap->pblk = pb;
6465     soap->pidx = 0;
6466   }
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;
6482 }
6483 #endif
6484 #endif
6485 
6486 /******************************************************************************/
6487 #ifndef WITH_NOIDREF
6488 #ifndef PALM_2
6489 SOAP_FMAC1
6490 int
6491 SOAP_FMAC2
soap_array_pointer_lookup(struct soap * soap,const void * p,const struct soap_array * a,int n,int type,struct soap_plist ** ppp)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;
6507       }
6508     }
6509   }
6510   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d: not found\n", a->__ptr, type));
6511   return 0;
6512 }
6513 #endif
6514 #endif
6515 
6516 /******************************************************************************/
6517 #ifndef PALM_1
6518 SOAP_FMAC1
6519 int
6520 SOAP_FMAC2
soap_begin_count(struct soap * soap)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
6536       ))
6537       soap->mode &= ~SOAP_IO_LENGTH;
6538     else
6539       soap->mode |= SOAP_IO_LENGTH;
6540   }
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;
6549   }
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;
6580 }
6581 #endif
6582 
6583 /******************************************************************************/
6584 #ifndef PALM_1
6585 SOAP_FMAC1
6586 int
6587 SOAP_FMAC2
soap_end_count(struct soap * soap)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;
6595 }
6596 #endif
6597 
6598 /******************************************************************************/
6599 #ifndef PALM_1
6600 SOAP_FMAC1
6601 int
6602 SOAP_FMAC2
soap_begin_send(struct soap * soap)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;
6614   }
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;
6621   }
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;
6628   }
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;
6641   }
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;
6662   }
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;
6691     }
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;
6699     }
6700     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflate initialized\n"));
6701     soap->zlib_state = SOAP_ZLIB_DEFLATE;
6702   }
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;
6715 }
6716 #endif
6717 
6718 /******************************************************************************/
6719 #ifndef WITH_NOIDREF
6720 #ifndef PALM_2
6721 SOAP_FMAC1
6722 void
6723 SOAP_FMAC2
soap_embedded(struct soap * soap,const void * p,int t)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));
6730   }
6731 }
6732 #endif
6733 #endif
6734 
6735 /******************************************************************************/
6736 #ifndef WITH_NOIDREF
6737 #ifndef PALM_2
6738 SOAP_FMAC1
6739 int
6740 SOAP_FMAC2
soap_reference(struct soap * soap,const void * p,int t)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;
6749     }
6750   }
6751   else if (soap_pointer_enter(soap, p, NULL, 0, t, &pp))
6752   { pp->mark1 = 0;
6753     pp->mark2 = 0;
6754   }
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;
6759 }
6760 #endif
6761 #endif
6762 
6763 /******************************************************************************/
6764 #ifndef WITH_NOIDREF
6765 #ifndef PALM_2
6766 SOAP_FMAC1
6767 int
6768 SOAP_FMAC2
soap_array_reference(struct soap * soap,const void * p,const struct soap_array * a,int n,int t)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;
6779     }
6780   }
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;
6786   }
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;
6789 }
6790 #endif
6791 #endif
6792 
6793 /******************************************************************************/
6794 #ifndef WITH_NOIDREF
6795 #ifndef PALM_2
6796 SOAP_FMAC1
6797 int
6798 SOAP_FMAC2
soap_embedded_id(struct soap * soap,int id,const void * p,int t)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));
6813       }
6814       return -1;
6815     }
6816     return id;
6817   }
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));
6828   }
6829   return id;
6830 }
6831 #endif
6832 #endif
6833 
6834 /******************************************************************************/
6835 #ifndef WITH_NOIDREF
6836 #ifndef PALM_2
6837 SOAP_FMAC1
6838 int
6839 SOAP_FMAC2
soap_is_embedded(struct soap * soap,struct soap_plist * pp)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;
6848   }
6849   if (soap->mode & SOAP_IO_LENGTH)
6850     return pp->mark1 == 1;
6851   return pp->mark2 == 1;
6852 }
6853 #endif
6854 #endif
6855 
6856 /******************************************************************************/
6857 #ifndef WITH_NOIDREF
6858 #ifndef PALM_2
6859 SOAP_FMAC1
6860 int
6861 SOAP_FMAC2
soap_is_single(struct soap * soap,struct soap_plist * pp)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;
6870 }
6871 #endif
6872 #endif
6873 
6874 /******************************************************************************/
6875 #ifndef WITH_NOIDREF
6876 #ifndef PALM_2
6877 SOAP_FMAC1
6878 void
6879 SOAP_FMAC2
soap_set_embedded(struct soap * soap,struct soap_plist * pp)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;
6887 }
6888 #endif
6889 #endif
6890 
6891 /******************************************************************************/
6892 #ifndef WITH_LEANER
6893 #ifndef PALM_1
6894 SOAP_FMAC1
6895 int
6896 SOAP_FMAC2
soap_attachment(struct soap * soap,const char * tag,int id,const void * p,const struct soap_array * a,const char * aid,const char * atype,const char * aoptions,int n,const char * type,int t)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)
6898 {
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;
6911     }
6912   }
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);
6918   }
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;
6926   }
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;
6939       }
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;
6948           }
6949         }
6950         else
6951           content->id = aid + 4;
6952       }
6953       else
6954         content->id = aid;
6955       content->type = atype;
6956       content->options = aoptions;
6957       content->encoding = SOAP_MIME_BINARY;
6958       pp->mark1 = 3;
6959     }
6960   }
6961   else if (pp)        /* Oracle customization */
6962     pp->mark2 = 3;
6963 #endif
6964   return -1;
6965 }
6966 #endif
6967 #endif
6968 
6969 /******************************************************************************/
6970 #ifndef WITH_NOIDREF
6971 #ifndef PALM_1
6972 static void
soap_init_iht(struct soap * soap)6973 soap_init_iht(struct soap *soap)
6974 { register int i;
6975   for (i = 0; i < SOAP_IDHASH; i++)
6976     soap->iht[i] = NULL;
6977 }
6978 #endif
6979 #endif
6980 
6981 /******************************************************************************/
6982 #ifndef WITH_NOIDREF
6983 #ifndef PALM_1
6984 static void
soap_free_iht(struct soap * soap)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);
6995       }
6996       p = ip->next;
6997       SOAP_FREE(soap, ip);
6998     }
6999     soap->iht[i] = NULL;
7000   }
7001 }
7002 #endif
7003 #endif
7004 
7005 /******************************************************************************/
7006 #ifndef WITH_NOIDREF
7007 #ifndef PALM_2
7008 SOAP_FMAC1
7009 struct soap_ilist *
7010 SOAP_FMAC2
soap_lookup(struct soap * soap,const char * id)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;
7017 }
7018 #endif
7019 #endif
7020 
7021 /******************************************************************************/
7022 #ifndef WITH_NOIDREF
7023 #ifndef PALM_2
7024 SOAP_FMAC1
7025 struct soap_ilist *
7026 SOAP_FMAC2
soap_enter(struct soap * soap,const char * id)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;
7036   }
7037   return ip;
7038 }
7039 #endif
7040 #endif
7041 
7042 /******************************************************************************/
7043 #ifndef PALM_2
7044 SOAP_FMAC1
7045 void*
7046 SOAP_FMAC2
soap_malloc(struct soap * soap,size_t n)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;
7061     }
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;
7068   }
7069   soap->alloced = 1;
7070   return p;
7071 }
7072 #endif
7073 
7074 /******************************************************************************/
7075 #ifdef SOAP_MEM_DEBUG
7076 static void
soap_init_mht(struct soap * soap)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;
7081 }
7082 #endif
7083 
7084 /******************************************************************************/
7085 #ifdef SOAP_MEM_DEBUG
7086 static void
soap_free_mht(struct soap * soap)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)
7094       {
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
7099       }
7100       free(mp);
7101     }
7102     soap->mht[i] = NULL;
7103   }
7104 }
7105 #endif
7106 
7107 /******************************************************************************/
7108 #ifdef SOAP_MEM_DEBUG
7109 SOAP_FMAC1
7110 void*
7111 SOAP_FMAC2
soap_track_malloc(struct soap * soap,const char * file,int line,size_t size)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;
7124   }
7125   return p;
7126 }
7127 #endif
7128 
7129 /******************************************************************************/
7130 #ifdef SOAP_MEM_DEBUG
7131 SOAP_FMAC1
7132 void
7133 SOAP_FMAC2
soap_track_free(struct soap * soap,const char * file,int line,void * p)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));
7145       }
7146       mp->live = 0;
7147     }
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);
7150   }
7151   else
7152     fprintf(stderr, "%s(%d): free(%p) pointer not malloced\n", file, line, p);
7153 }
7154 #endif
7155 
7156 /******************************************************************************/
7157 #ifdef SOAP_MEM_DEBUG
7158 static void
soap_track_unlink(struct soap * soap,const void * p)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;
7167 }
7168 #endif
7169 
7170 /******************************************************************************/
7171 #ifndef PALM_2
7172 SOAP_FMAC1
7173 void
7174 SOAP_FMAC2
soap_dealloc(struct soap * soap,void * p)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)
7181     {
7182       if (*(unsigned short*)(char*)(*q - sizeof(unsigned short)) != (unsigned short)SOAP_CANARY)
7183       {
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;
7192       }
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;
7198       }
7199     }
7200     soap_delete(soap, p);
7201   }
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)
7208       {
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;
7217       }
7218       soap->alist = *(void**)q;
7219       q -= *(size_t*)(q + sizeof(void*));
7220       SOAP_FREE(soap, q);
7221     }
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
7233   }
7234 }
7235 #endif
7236 
7237 /******************************************************************************/
7238 #ifndef PALM_2
7239 SOAP_FMAC1
7240 void
7241 SOAP_FMAC2
soap_delete(struct soap * soap,void * p)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
7257         }
7258         SOAP_FREE(soap, q);
7259         return;
7260       }
7261       cp = &(*cp)->next;
7262     }
7263     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: address not in list\n", p));
7264   }
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
7274       }
7275       SOAP_FREE(soap, q);
7276     }
7277   }
7278   soap->fault = NULL; /* this was possibly deallocated */
7279   soap->header = NULL; /* this was possibly deallocated */
7280 }
7281 #endif
7282 
7283 /******************************************************************************/
7284 #ifndef PALM_2
7285 SOAP_FMAC1
7286 void
7287 SOAP_FMAC2
soap_delegate_deletion(struct soap * soap,struct soap * soap_to)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)
7297   {
7298     if (*(unsigned short*)(char*)(*q - sizeof(unsigned short)) != (unsigned short)SOAP_CANARY)
7299     {
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;
7308     }
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;
7319       }
7320     }
7321 #endif
7322   }
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;
7331   }
7332   else
7333     soap_to->clist = soap->clist;
7334   soap->clist = NULL;
7335 }
7336 #endif
7337 
7338 /******************************************************************************/
7339 #ifndef PALM_2
7340 SOAP_FMAC1
7341 struct soap_clist *
7342 SOAP_FMAC2
soap_link(struct soap * soap,void * p,int t,int n,int (* fdelete)(struct soap_clist *))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;
7352   }
7353   return cp;
7354 }
7355 #endif
7356 
7357 /******************************************************************************/
7358 #ifndef PALM_2
7359 SOAP_FMAC1
7360 void
7361 SOAP_FMAC2
soap_unlink(struct soap * soap,const void * p)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;
7375     }
7376   }
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;
7384     }
7385   }
7386 }
7387 #endif
7388 
7389 /******************************************************************************/
7390 #ifndef WITH_NOIDREF
7391 #ifndef PALM_2
7392 SOAP_FMAC1
7393 int
7394 SOAP_FMAC2
soap_lookup_type(struct soap * soap,const char * id)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;
7402     }
7403   }
7404   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "lookup type id='%s' NOT FOUND! Need to get it from xsi:type\n", id));
7405   return 0;
7406 }
7407 #endif
7408 #endif
7409 
7410 /******************************************************************************/
7411 #ifndef WITH_NOIDREF
7412 #ifndef PALM_2
7413 SOAP_FMAC1
7414 void*
7415 SOAP_FMAC2
soap_id_lookup(struct soap * soap,const char * id,void ** p,int t,size_t n,unsigned int k)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;
7434   }
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)
7438     {
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;
7445     }
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"));
7454     }
7455     *p = ip->ptr;
7456   }
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;
7470       }
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"));
7476     }
7477     q = (void**)ip->link;
7478     ip->link = p;
7479     *p = (void*)q;
7480   }
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"));
7491     }
7492     q = (void**)ip->link;
7493     ip->link = p;
7494     *p = (void*)q;
7495   }
7496   return p;
7497 }
7498 #endif
7499 #endif
7500 
7501 /******************************************************************************/
7502 #ifndef WITH_NOIDREF
7503 #ifndef PALM_2
7504 SOAP_FMAC1
7505 void*
7506 SOAP_FMAC2
soap_id_forward(struct soap * soap,const char * href,void * p,size_t len,int st,int tt,size_t n,unsigned int k,void (* fcopy)(struct soap *,int,int,void *,size_t,const void *,size_t))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));
7523   }
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;
7531   }
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;
7537     }
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));
7549   }
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;
7554   }
7555   return p;
7556 }
7557 #endif
7558 #endif
7559 
7560 /******************************************************************************/
7561 #ifndef PALM_2
7562 SOAP_FMAC1
7563 void*
7564 SOAP_FMAC2
soap_id_enter(struct soap * soap,const char * id,void * p,int t,size_t n,unsigned int k,const char * type,const char * arrayType,void * (* finstantiate)(struct soap *,int,const char *,const char *,size_t *))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*))
7566 {
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;
7579   }
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));
7598   }
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;
7606   }
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;
7614   }
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));
7620   }
7621   return ip->ptr;
7622 #endif
7623 }
7624 #endif
7625 
7626 /******************************************************************************/
7627 #ifndef PALM_2
7628 SOAP_FMAC1
7629 void
7630 SOAP_FMAC2
soap_fcopy(struct soap * soap,int st,int tt,void * p,size_t len,const void * q,size_t n)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);
7634 }
7635 #endif
7636 
7637 /******************************************************************************/
7638 #ifndef PALM_1
7639 SOAP_FMAC1
7640 int
7641 SOAP_FMAC2
soap_end_send(struct soap * soap)7642 soap_end_send(struct soap *soap)
7643 {
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;
7652   }
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);
7671       }
7672       return soap->error;
7673     }
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;
7681       do
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;
7689           }
7690           soap->d_stream->next_out = (Byte*)soap->z_buf;
7691           soap->d_stream->avail_out = SOAP_BUFLEN;
7692         }
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;
7701       }
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));
7715       }
7716 #endif
7717     }
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++;
7732       }
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;
7739         }
7740       }
7741       soap_end_block(soap, NULL);
7742     }
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;
7748     }
7749 #endif
7750   }
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;
7765 }
7766 #endif
7767 
7768 /******************************************************************************/
7769 #ifndef PALM_1
7770 SOAP_FMAC1
7771 int
7772 SOAP_FMAC2
soap_end_recv(struct soap * soap)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;
7784   }
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)
7790   {
7791 #ifndef WITH_NOIDREF
7792     if (soap->mode & SOAP_MIME_POSTCHECK)
7793     { soap_resolve(soap);
7794       return SOAP_OK;
7795     }
7796 #endif
7797     if (soap_getmime(soap))
7798       return soap->error;
7799   }
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);
7808   }
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;
7834       }
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;
7838       }
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;
7842       }
7843     }
7844     soap->zlib_in = SOAP_ZLIB_NONE;
7845 #endif
7846   }
7847 #endif
7848   if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
7849     while ((int)soap_getchar(soap) != EOF) /* advance to last chunk */
7850       ;
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;
7860   }
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;
7868 }
7869 #endif
7870 
7871 /******************************************************************************/
7872 #ifndef PALM_1
7873 SOAP_FMAC1
7874 void
7875 SOAP_FMAC2
soap_free_temp(struct soap * soap)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);
7889   }
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;
7906       }
7907       if (soap->encodingStyle == ns->ns)
7908         soap->encodingStyle = SOAP_STR_EOS;
7909     }
7910     SOAP_FREE(soap, soap->local_namespaces);
7911     soap->local_namespaces = NULL;
7912   }
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;
7918   }
7919 #endif
7920 #ifndef WITH_NOIDREF
7921   soap_free_pht(soap);
7922   soap_free_iht(soap);
7923 #endif
7924 }
7925 #endif
7926 
7927 /******************************************************************************/
7928 #ifndef PALM_1
7929 static void
soap_free_ns(struct soap * soap)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);
7936   }
7937   soap->nlist = NULL;
7938 }
7939 #endif
7940 
7941 /******************************************************************************/
7942 #ifndef PALM_1
7943 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
7944 static void
soap_init_logs(struct soap * soap)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;
7950   }
7951 }
7952 #endif
7953 #endif
7954 
7955 /******************************************************************************/
7956 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
7957 SOAP_FMAC1
7958 void
7959 SOAP_FMAC2
soap_open_logfile(struct soap * soap,int i)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");
7963 }
7964 #endif
7965 
7966 /******************************************************************************/
7967 #ifdef SOAP_DEBUG
7968 static void
soap_close_logfile(struct soap * soap,int i)7969 soap_close_logfile(struct soap *soap, int i)
7970 { if (soap->fdebug[i])
7971   { fclose(soap->fdebug[i]);
7972     soap->fdebug[i] = NULL;
7973   }
7974 }
7975 #endif
7976 
7977 /******************************************************************************/
7978 #ifdef SOAP_DEBUG
7979 SOAP_FMAC1
7980 void
7981 SOAP_FMAC2
soap_close_logfiles(struct soap * soap)7982 soap_close_logfiles(struct soap *soap)
7983 { int i;
7984   for (i = 0; i < SOAP_MAXLOGS; i++)
7985     soap_close_logfile(soap, i);
7986 }
7987 #endif
7988 
7989 /******************************************************************************/
7990 #ifdef SOAP_DEBUG
7991 static void
soap_set_logfile(struct soap * soap,int i,const char * logfile)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;
8004 }
8005 #endif
8006 
8007 /******************************************************************************/
8008 #ifdef SOAP_DEBUG
8009 SOAP_FMAC1
8010 void
8011 SOAP_FMAC2
soap_set_recv_logfile(struct soap * soap,const char * logfile)8012 soap_set_recv_logfile(struct soap *soap, const char *logfile)
8013 { soap_set_logfile(soap, SOAP_INDEX_RECV, logfile);
8014 }
8015 #endif
8016 
8017 /******************************************************************************/
8018 #ifdef SOAP_DEBUG
8019 SOAP_FMAC1
8020 void
8021 SOAP_FMAC2
soap_set_sent_logfile(struct soap * soap,const char * logfile)8022 soap_set_sent_logfile(struct soap *soap, const char *logfile)
8023 { soap_set_logfile(soap, SOAP_INDEX_SENT, logfile);
8024 }
8025 #endif
8026 
8027 /******************************************************************************/
8028 #ifdef SOAP_DEBUG
8029 SOAP_FMAC1
8030 void
8031 SOAP_FMAC2
soap_set_test_logfile(struct soap * soap,const char * logfile)8032 soap_set_test_logfile(struct soap *soap, const char *logfile)
8033 { soap_set_logfile(soap, SOAP_INDEX_TEST, logfile);
8034 }
8035 #endif
8036 
8037 /******************************************************************************/
8038 #ifndef PALM_1
8039 SOAP_FMAC1
8040 struct soap*
8041 SOAP_FMAC2
soap_copy(const struct soap * soap)8042 soap_copy(const struct soap *soap)
8043 { return soap_copy_context((struct soap*)malloc(sizeof(struct soap)), soap);
8044 }
8045 #endif
8046 
8047 /******************************************************************************/
8048 #ifndef PALM_1
8049 SOAP_FMAC1
8050 struct soap*
8051 SOAP_FMAC2
soap_copy_context(struct soap * copy,const struct soap * soap)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;
8128       }
8129       q->next = copy->plugins;
8130       copy->plugins = q;
8131     }
8132   }
8133   return copy;
8134 }
8135 #endif
8136 
8137 /******************************************************************************/
8138 #ifndef PALM_1
8139 SOAP_FMAC1
8140 void
8141 SOAP_FMAC2
soap_copy_stream(struct soap * copy,struct soap * soap)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));
8191   }
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));
8196 }
8197 #endif
8198 
8199 /******************************************************************************/
8200 #ifndef PALM_1
8201 SOAP_FMAC1
8202 void
8203 SOAP_FMAC2
soap_free_stream(struct soap * soap)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
8218 }
8219 #endif
8220 
8221 /******************************************************************************/
8222 #ifndef PALM_1
8223 SOAP_FMAC1
8224 void
8225 SOAP_FMAC2
soap_init(struct soap * soap)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
8235 /*
8236  Oracle customization for KMS server debug
8237 */
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;
8472 }
8473 #endif
8474 
8475 /******************************************************************************/
8476 #ifndef PALM_1
8477 SOAP_FMAC1
8478 void
8479 SOAP_FMAC2
soap_init1(struct soap * soap,soap_mode mode)8480 soap_init1(struct soap *soap, soap_mode mode)
8481 { soap_init2(soap, mode, mode);
8482 }
8483 #endif
8484 
8485 /******************************************************************************/
8486 #ifndef PALM_1
8487 SOAP_FMAC1
8488 void
8489 SOAP_FMAC2
soap_init2(struct soap * soap,soap_mode imode,soap_mode omode)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);
8494 }
8495 #endif
8496 
8497 /******************************************************************************/
8498 #ifndef PALM_2
8499 SOAP_FMAC1
8500 void
8501 SOAP_FMAC2
soap_begin(struct soap * soap)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;
8507   }
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);
8531 }
8532 #endif
8533 
8534 /******************************************************************************/
8535 #ifndef PALM_2
8536 SOAP_FMAC1
8537 void
8538 SOAP_FMAC2
soap_end(struct soap * soap)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;
8548   }
8549   soap_closesock(soap);
8550 #ifdef SOAP_DEBUG
8551   soap_close_logfiles(soap);
8552 #endif
8553 #ifdef PALM
8554   palmNetLibClose();
8555 #endif
8556 }
8557 #endif
8558 
8559 /******************************************************************************/
8560 #ifndef PALM_1
8561 SOAP_FMAC1
8562 int
8563 SOAP_FMAC2
soap_set_namespaces(struct soap * soap,const struct Namespace * p)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;
8582     }
8583   }
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;
8593     }
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);
8599   }
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;
8606       }
8607     }
8608     SOAP_FREE(soap, ns);
8609   }
8610   soap->level = level; /* restore level */
8611   return SOAP_OK;
8612 }
8613 #endif
8614 
8615 /******************************************************************************/
8616 #ifndef PALM_1
8617 SOAP_FMAC1
8618 void
8619 SOAP_FMAC2
soap_set_local_namespaces(struct soap * soap)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;
8636       }
8637       soap->local_namespaces = ns2;
8638     }
8639   }
8640 }
8641 #endif
8642 
8643 /******************************************************************************/
8644 #ifndef WITH_LEAN
8645 #ifndef PALM_1
8646 SOAP_FMAC1
8647 const char *
8648 SOAP_FMAC2
soap_tagsearch(const char * big,const char * little)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;
8659       }
8660       if (*t == '\0' || *t == ' ')
8661       { if (i == n || (i && little[i-1] == ':'))
8662           return s;
8663       }
8664       s = strchr(t, ' ');
8665       if (s)
8666         s++;
8667     }
8668   }
8669   return NULL;
8670 }
8671 #endif
8672 #endif
8673 
8674 /******************************************************************************/
8675 #ifndef WITH_LEAN
8676 #ifndef PALM_1
8677 SOAP_FMAC1
8678 struct soap_nlist *
8679 SOAP_FMAC2
soap_lookup_ns(struct soap * soap,const char * tag,size_t n)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;
8685   }
8686   return NULL;
8687 }
8688 #endif
8689 #endif
8690 
8691 /******************************************************************************/
8692 #ifndef WITH_LEAN
8693 static struct soap_nlist *
soap_push_ns(struct soap * soap,const char * id,const char * ns,short utilized)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;
8703     }
8704     if (np)
8705     { if ((np->level < soap->level || !np->ns) && np->index == 1)
8706         utilized = 1;
8707       else
8708         return NULL;
8709     }
8710   }
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;
8721   }
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;
8732 }
8733 #endif
8734 
8735 /******************************************************************************/
8736 #ifndef WITH_LEAN
8737 static void
soap_utilize_ns(struct soap * soap,const char * tag,size_t n)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);
8744   }
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);
8749   }
8750 }
8751 #endif
8752 
8753 /******************************************************************************/
8754 #ifndef PALM_2
8755 SOAP_FMAC1
8756 int
8757 SOAP_FMAC2
soap_element(struct soap * soap,const char * tag,int id,const char * type)8758 soap_element(struct soap *soap, const char *tag, int id, const char *type)
8759 {
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;
8773   }
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;
8781     }
8782   }
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;
8806       }
8807       else
8808         soap->dom->elts = elt;
8809     }
8810     soap->dom = elt;
8811   }
8812   else
8813   {
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;
8821     }
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;
8826     }
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;
8841         }
8842       }
8843     }
8844     else
8845 #endif
8846     if (soap_send_raw(soap, "<", 1)
8847      || soap_send(soap, tag))
8848       return soap->error;
8849 #ifdef WITH_DOM
8850   }
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;
8864       }
8865     }
8866   }
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);
8873   }
8874 #endif
8875   if (id > 0)
8876   { sprintf(soap->tmpbuf, "_%d", id);
8877     if (soap_attribute(soap, "id", soap->tmpbuf))
8878       return soap->error;
8879   }
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);
8888     }
8889 #endif
8890   }
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;
8899   }
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;
8904     }
8905     if (soap_attribute(soap, "SOAP-ENV:mustUnderstand", soap->version == 2 ? "true" : "1"))
8906       return soap->error;
8907     soap->mustUnderstand = 0;
8908   }
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;
8916       }
8917       if (soap->encodingStyle && soap_attribute(soap, "SOAP-ENV:encodingStyle", soap->encodingStyle))
8918         return soap->error;
8919     }
8920     soap->encoding = 0;
8921   }
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;
8927 }
8928 #endif
8929 
8930 /******************************************************************************/
8931 #ifndef PALM_2
8932 SOAP_FMAC1
8933 int
8934 SOAP_FMAC2
soap_element_begin_out(struct soap * soap,const char * tag,int id,const char * type)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);
8941 }
8942 #endif
8943 
8944 /******************************************************************************/
8945 #ifndef PALM_2
8946 #ifndef HAVE_STRRCHR
8947 SOAP_FMAC1
8948 char*
8949 SOAP_FMAC2
soap_strrchr(const char * s,int t)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;
8956 }
8957 #endif
8958 #endif
8959 
8960 /******************************************************************************/
8961 #ifndef PALM_2
8962 #ifndef HAVE_STRTOL
8963 SOAP_FMAC1
8964 long
8965 SOAP_FMAC2
soap_strtol(const char * s,char ** t,int b)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;
8976     }
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++;
8985     }
8986     if (neg)
8987       n = -n;
8988   }
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++;
9002     }
9003   }
9004   if (t)
9005     *t = (char*)s;
9006   return n;
9007 }
9008 #endif
9009 #endif
9010 
9011 /******************************************************************************/
9012 #ifndef PALM_2
9013 #ifndef HAVE_STRTOUL
9014 SOAP_FMAC1
9015 unsigned long
9016 SOAP_FMAC2
soap_strtoul(const char * s,char ** t,int b)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++;
9031     }
9032   }
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++;
9046     }
9047   }
9048   if (t)
9049     *t = (char*)s;
9050   return n;
9051 }
9052 #endif
9053 #endif
9054 
9055 /******************************************************************************/
9056 #ifndef PALM_1
9057 SOAP_FMAC1
9058 int
9059 SOAP_FMAC2
soap_array_begin_out(struct soap * soap,const char * tag,int id,const char * type,const char * offset)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;
9075     }
9076   }
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;
9082   }
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);
9088   }
9089 #endif
9090   return soap_element_start_end_out(soap, NULL);
9091 }
9092 #endif
9093 
9094 /******************************************************************************/
9095 #ifndef PALM_1
9096 SOAP_FMAC1
9097 int
9098 SOAP_FMAC2
soap_element_start_end_out(struct soap * soap,const char * tag)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);
9109       }
9110     }
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;
9117       }
9118     }
9119   }
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;
9138       }
9139     }
9140     return SOAP_OK;
9141   }
9142 #endif
9143   for (tp = soap->attributes; tp; tp = tp->next)
9144   { if (tp->visible)
9145     {
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;
9156       }
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;
9167     }
9168   }
9169   if (tag)
9170   {
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;
9177     }
9178 #endif
9179     soap->level--;	/* decrement level just before /> */
9180     if (soap_send_raw(soap, "/>", 2))
9181       return soap->error;
9182     return SOAP_OK;
9183   }
9184   return soap_send_raw(soap, ">", 1);
9185 }
9186 #endif
9187 
9188 /******************************************************************************/
9189 #ifndef PALM_1
9190 SOAP_FMAC1
9191 int
9192 SOAP_FMAC2
soap_element_end_out(struct soap * soap,const char * tag)9193 soap_element_end_out(struct soap *soap, const char *tag)
9194 {
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;
9206   }
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;
9215     }
9216     soap->body = 0;
9217   }
9218   if ((soap->mode & SOAP_XML_DEFAULTNS) && (s = strchr(tag, ':')))
9219   { soap_pop_namespace(soap);
9220     tag = s + 1;
9221   }
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);
9228 }
9229 #endif
9230 
9231 /******************************************************************************/
9232 #ifndef PALM_1
9233 SOAP_FMAC1
9234 int
9235 SOAP_FMAC2
soap_element_ref(struct soap * soap,const char * tag,int id,int href)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;
9242   }
9243   sprintf(soap->href, "#_%d", href);
9244   return soap_element_href(soap, tag, id, s, soap->href + n);
9245 }
9246 #endif
9247 
9248 /******************************************************************************/
9249 #ifndef PALM_1
9250 SOAP_FMAC1
9251 int
9252 SOAP_FMAC2
soap_element_href(struct soap * soap,const char * tag,int id,const char * ref,const char * val)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;
9260 }
9261 #endif
9262 
9263 /******************************************************************************/
9264 #ifndef PALM_1
9265 SOAP_FMAC1
9266 int
9267 SOAP_FMAC2
soap_element_null(struct soap * soap,const char * tag,int id,const char * type)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);
9279   }
9280   soap->null = 1;
9281   soap->position = 0;
9282   soap->mustUnderstand = 0;
9283   return SOAP_OK;
9284 }
9285 #endif
9286 
9287 /******************************************************************************/
9288 #ifndef PALM_1
9289 SOAP_FMAC1
9290 int
9291 SOAP_FMAC2
soap_element_id(struct soap * soap,const char * tag,int id,const void * p,const struct soap_array * a,int n,const char * type,int t)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;
9296   }
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;
9310       }
9311       if (soap_is_single(soap, pp))
9312         return 0;
9313       soap_set_embedded(soap, pp);
9314     }
9315   }
9316   return id;
9317 #else
9318   return 0;
9319 #endif
9320 }
9321 #endif
9322 
9323 /******************************************************************************/
9324 #ifndef PALM_1
9325 SOAP_FMAC1
9326 int
9327 SOAP_FMAC2
soap_element_result(struct soap * soap,const char * tag)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;
9336   }
9337   return SOAP_OK;
9338 }
9339 #endif
9340 
9341 /******************************************************************************/
9342 #ifndef PALM_1
9343 SOAP_FMAC1
9344 void
9345 SOAP_FMAC2
soap_check_result(struct soap * soap,const char * tag)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? */
9350   }
9351 }
9352 #endif
9353 
9354 /******************************************************************************/
9355 #ifndef PALM_2
9356 SOAP_FMAC1
9357 int
9358 SOAP_FMAC2
soap_attribute(struct soap * soap,const char * name,const char * value)9359 soap_attribute(struct soap *soap, const char *name, const char *value)
9360 {
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;
9375   }
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);
9385     }
9386     */
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;
9391   }
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;
9401   }
9402   return SOAP_OK;
9403 }
9404 #endif
9405 
9406 /******************************************************************************/
9407 #ifndef PALM_2
9408 SOAP_FMAC1
9409 int
9410 SOAP_FMAC2
soap_element_begin_in(struct soap * soap,const char * tag,int nillable,const char * type)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 ));
9426     }
9427   }
9428   else if (soap->error == SOAP_NO_TAG && tag && *tag == '-')
9429     soap->error = SOAP_OK;
9430   return soap->error;
9431 }
9432 #endif
9433 
9434 /******************************************************************************/
9435 #ifndef PALM_2
9436 SOAP_FMAC1
9437 int
9438 SOAP_FMAC2
soap_element_end_in(struct soap * soap,const char * tag)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;
9454   }
9455 #endif
9456   if (soap->peeked)
9457   { if (*soap->tag)
9458       n++;
9459     soap->peeked = 0;
9460   }
9461   do
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);
9473       }
9474     }
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;
9481   }
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;
9496     }
9497   }
9498 #endif
9499   soap->level--;
9500   return SOAP_OK;
9501 }
9502 #endif
9503 
9504 /******************************************************************************/
9505 #ifndef PALM_2
9506 SOAP_FMAC1
9507 const char *
9508 SOAP_FMAC2
soap_attr_value(struct soap * soap,const char * name,int flag)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;
9516   }
9517   if (tp)
9518   { if (flag == 2 && (soap->mode & SOAP_XML_STRICT))
9519       soap->error = SOAP_PROHIBITED;
9520     else
9521       return tp->value;
9522   }
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;
9528 }
9529 #endif
9530 
9531 /******************************************************************************/
9532 #ifndef PALM_2
9533 SOAP_FMAC1
9534 int
9535 SOAP_FMAC2
soap_set_attr(struct soap * soap,const char * name,const char * value,int flag)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;
9544   }
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;
9559       }
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;
9564       }
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;
9572             }
9573           }
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;
9576         }
9577       }
9578       tp->next = *tpp;
9579       *tpp = tp;
9580     }
9581     else
9582 #endif
9583     { tp->next = soap->attributes;
9584       soap->attributes = tp;
9585     }
9586     strcpy(tp->name, name);
9587     tp->value = NULL;
9588   }
9589   else if (tp->visible)
9590   { return SOAP_OK;
9591   }
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;
9597   }
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));
9604     }
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';
9615     }
9616 #endif
9617   }
9618   else
9619     tp->visible = 1;
9620   return SOAP_OK;
9621 }
9622 #endif
9623 
9624 /******************************************************************************/
9625 #ifndef PALM_2
9626 SOAP_FMAC1
9627 void
9628 SOAP_FMAC2
soap_clr_attr(struct soap * soap)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;
9639     }
9640   }
9641   else
9642 #endif
9643   { for (tp = soap->attributes; tp; tp = tp->next)
9644       tp->visible = 0;
9645   }
9646 }
9647 #endif
9648 
9649 /******************************************************************************/
9650 #ifndef PALM_2
9651 static int
soap_getattrval(struct soap * soap,char * s,size_t n,soap_wchar d)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)
9657     {
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;
9670       }
9671       *s++ = '>';
9672       break;
9673     case SOAP_QT:
9674       if (c == d)
9675       { *s = '\0';
9676         return SOAP_OK;
9677       }
9678       *s++ = '"';
9679       break;
9680     case SOAP_AP:
9681       if (c == d)
9682       { *s = '\0';
9683         return SOAP_OK;
9684       }
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;
9696       }
9697     default:
9698       if ((int)c == EOF)
9699         return soap->error = SOAP_EOF;
9700       *s++ = (char)c;
9701     }
9702   }
9703   return soap->error = SOAP_EOM;
9704 }
9705 #endif
9706 
9707 /******************************************************************************/
9708 #ifdef WITH_FAST
9709 #ifndef PALM_2
9710 SOAP_FMAC1
9711 int
9712 SOAP_FMAC2
soap_store_lab(struct soap * soap,const char * s,size_t n)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);
9716 }
9717 #endif
9718 #endif
9719 
9720 /******************************************************************************/
9721 #ifdef WITH_FAST
9722 #ifndef PALM_2
9723 SOAP_FMAC1
9724 int
9725 SOAP_FMAC2
soap_append_lab(struct soap * soap,const char * s,size_t n)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;
9740     }
9741     if (t)
9742     { memcpy(soap->labbuf, t, soap->labidx);
9743       SOAP_FREE(soap, t);
9744     }
9745   }
9746   if (s)
9747   { memcpy(soap->labbuf + soap->labidx, s, n);
9748     soap->labidx += n;
9749   }
9750   return SOAP_OK;
9751 }
9752 #endif
9753 #endif
9754 
9755 /******************************************************************************/
9756 #ifndef PALM_2
9757 SOAP_FMAC1
9758 int
9759 SOAP_FMAC2
soap_peek_element(struct soap * soap)9760 soap_peek_element(struct soap *soap)
9761 {
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;
9775   }
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;
9796     do
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);
9805       }
9806     }
9807     while (soap_blank(c));
9808     *s = '\0';
9809     if (*soap->labbuf)
9810       lead = soap->labbuf;
9811   }
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;
9828   }
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);
9837   }
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;
9866       }
9867       else
9868         soap->dom->elts = elt;
9869     }
9870     soap->dom = elt;
9871     att = &elt->atts;
9872   }
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);
9884     }
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;
9900     }
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;
9909     }
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;
9916     }
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;
9928       }
9929       else
9930       { tp->next = soap->attributes;
9931         soap->attributes = tp;
9932       }
9933     }
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 */
9942       }
9943       if (soap_getattrval(soap, tp->value, tp->size, c))
9944       {
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;
9961           }
9962           else
9963             break;
9964         }
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;
9971         }
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;
9989           }
9990           else
9991             break;
9992         }
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);
9999         }
10000         soap_save_block(soap, NULL, s + tp->size, 0);
10001         tp->value = s;
10002         tp->size = n;
10003 #endif
10004       }
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
10012     }
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;
10022     }
10023   }
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);
10029   }
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;
10040   }
10041 #endif
10042   for (tp = soap->attributes; tp; tp = tp->next)
10043   { if (tp->visible && tp->value)
10044     {
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';
10052         }
10053       }
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';
10061         }
10062       }
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';
10068       }
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;
10074       }
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);
10082           }
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';
10087         }
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;
10101         }
10102       }
10103       else if (soap->version == 2)
10104       {
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';
10111         }
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;
10125         }
10126       }
10127       else
10128       { if (!soap_match_tag(soap, tp->name, "wsdl:required") && !strcmp(tp->value, "true"))
10129           soap->mustUnderstand = 1;
10130       }
10131     }
10132   }
10133   return soap->error = SOAP_OK;
10134 }
10135 #endif
10136 
10137 /******************************************************************************/
10138 #ifndef PALM_2
10139 SOAP_FMAC1
10140 void
10141 SOAP_FMAC2
soap_retry(struct soap * soap)10142 soap_retry(struct soap *soap)
10143 { soap->error = SOAP_OK;
10144   soap_revert(soap);
10145 }
10146 #endif
10147 
10148 /******************************************************************************/
10149 #ifndef PALM_2
10150 SOAP_FMAC1
10151 void
10152 SOAP_FMAC2
soap_revert(struct soap * soap)10153 soap_revert(struct soap *soap)
10154 { if (!soap->peeked)
10155   { soap->peeked = 1;
10156     if (soap->body)
10157       soap->level--;
10158   }
10159   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reverting last element (level=%u)\n", soap->level));
10160 }
10161 #endif
10162 
10163 /******************************************************************************/
10164 #ifndef PALM_2
10165 SOAP_FMAC1
10166 int
10167 SOAP_FMAC2
soap_string_out(struct soap * soap,const char * s,int flag)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;
10176   }
10177 #endif
10178   if (flag == 2 || soap->mode & SOAP_C_UTFSTRING)
10179     mask = 0;
10180   t = s;
10181   while ((c = *t++))
10182   { switch (c)
10183     {
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;
10189       }
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;
10196       }
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;
10218       }
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;
10225       }
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;
10238         }
10239       }
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;
10247       }
10248 #endif
10249     }
10250   }
10251   return soap_send_raw(soap, s, t - s - 1);
10252 }
10253 #endif
10254 
10255 /******************************************************************************/
10256 #ifndef PALM_2
10257 SOAP_FMAC1
10258 char *
10259 SOAP_FMAC2
soap_string_in(struct soap * soap,int flag,long minlen,long maxlen)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)
10274   {
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++ = '"';
10298         }
10299       }
10300     }
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;
10312   }
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 (;;)
10323     {
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;
10341         }
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));
10365                   }
10366                   *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
10367                 }
10368                 *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
10369               }
10370               *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
10371             }
10372             *t++ = (char)(0x80 | (c & 0x3F));
10373             m = (int)(t - buf) - 1;
10374             t = buf;
10375             *s++ = *t++;
10376             continue;
10377           }
10378         }
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;
10433         }
10434         switch (c)
10435         {
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);
10456           }
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;
10465             }
10466             n--;
10467           }
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;
10478             }
10479             else if (c == '-')
10480             { if ((c = soap_getchar(soap)) == '-')
10481                 state = 2;
10482               t = (char*)"!-";
10483               m = 2;
10484               soap_unget(soap, c);
10485             }
10486             else
10487             { t = (char*)"!";
10488               m = 1;
10489               soap_unget(soap, c);
10490             }
10491             *s++ = '<';
10492             break;
10493           }
10494           else if (c == '?')
10495             state = 3;
10496           else if (f && n == 0)
10497 	  { soap_revget1(soap);
10498 	    c = '<';
10499 	    goto end;
10500 	  }
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--;
10521             }
10522             else
10523             { *s++ = SOAP_UNKNOWN_CHAR;
10524               m = 0;
10525             }
10526           }
10527           else
10528 #endif
10529 #endif
10530             *s++ = (char)(c & 0xFF);
10531         }
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;
10537         }
10538       }
10539     }
10540   }
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 (;;)
10549   {
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;
10567       }
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));
10586                 }
10587                 *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
10588               }
10589               *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
10590             }
10591             *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
10592           }
10593           *t++ = (char)(0x80 | (c & 0x3F));
10594           m = (int)(t - buf) - 1;
10595           t = buf;
10596           *s++ = *t++;
10597           continue;
10598         }
10599       }
10600       else
10601         c = soap_getutf8(soap);
10602       switch (c)
10603       {
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);
10633         }
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;
10643         }
10644         break;
10645       case (soap_wchar)('>' | 0x80000000):
10646         if (flag)
10647           *s++ = '>';
10648         else
10649         { *s++ = '&';
10650           t = (char*)"gt;";
10651           m = 3;
10652         }
10653         break;
10654       case (soap_wchar)('&' | 0x80000000):
10655         if (flag)
10656           *s++ = '&';
10657         else
10658         { *s++ = '&';
10659           t = (char*)"amp;";
10660           m = 4;
10661         }
10662         break;
10663       case (soap_wchar)('"' | 0x80000000):
10664         if (flag)
10665           *s++ = '"';
10666         else
10667         { *s++ = '&';
10668           t = (char*)"quot;";
10669           m = 5;
10670         }
10671         break;
10672       case (soap_wchar)('\'' | 0x80000000):
10673         if (flag)
10674           *s++ = '\'';
10675         else
10676         { *s++ = '&';
10677           t = (char*)"apos;";
10678           m = 5;
10679         }
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--;
10692           }
10693           else
10694           { *s++ = SOAP_UNKNOWN_CHAR;
10695             m = 0;
10696           }
10697         }
10698         else
10699 #endif
10700 #endif
10701           *s++ = (char)(c & 0xFF);
10702       }
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;
10708       }
10709     }
10710   }
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;
10724   }
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;
10731   }
10732 #endif
10733   if (flag == 2)
10734     if (soap_s2QName(soap, t, &t, minlen, maxlen))
10735       return NULL;
10736   return t;
10737 }
10738 #endif
10739 
10740 /******************************************************************************/
10741 #ifndef WITH_LEANER
10742 #ifndef PALM_2
10743 SOAP_FMAC1
10744 int
10745 SOAP_FMAC2
soap_wstring_out(struct soap * soap,const wchar_t * s,int flag)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;
10760   }
10761 #endif
10762   while ((c = *s++))
10763   { switch (c)
10764     {
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;
10803       }
10804       else if (soap_pututf8(soap, (unsigned long)c))
10805         return soap->error;
10806       continue;
10807     }
10808     if (soap_send(soap, t))
10809       return soap->error;
10810   }
10811   return SOAP_OK;
10812 }
10813 #endif
10814 #endif
10815 
10816 /******************************************************************************/
10817 #ifndef WITH_LEANER
10818 #ifndef PALM_2
10819 SOAP_FMAC1
10820 wchar_t *
10821 SOAP_FMAC2
soap_wstring_in(struct soap * soap,int flag,long minlen,long maxlen)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)
10831     {
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++ = '"';
10854           }
10855         }
10856       }
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;
10867     }
10868   }
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;
10880       }
10881       c = soap_getutf8(soap);
10882       switch (c)
10883       {
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);
10912         }
10913         *s++ = '/';
10914         break;
10915       case '<':
10916         if (flag)
10917           *s++ = (soap_wchar)'<';
10918         else
10919         { *s++ = (soap_wchar)'&';
10920           t = (char*)"lt;";
10921         }
10922         break;
10923       case '>':
10924         if (flag)
10925           *s++ = (soap_wchar)'>';
10926         else
10927         { *s++ = (soap_wchar)'&';
10928           t = (char*)"gt;";
10929         }
10930         break;
10931       case '"':
10932         if (flag)
10933           *s++ = (soap_wchar)'"';
10934         else
10935         { *s++ = (soap_wchar)'&';
10936           t = (char*)"quot;";
10937         }
10938         break;
10939       default:
10940         if ((int)c == EOF)
10941           goto end;
10942         *s++ = (wchar_t)c & 0x7FFFFFFF;
10943       }
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;
10949       }
10950     }
10951   }
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;
10960   }
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;
10967 }
10968 #endif
10969 #endif
10970 
10971 /******************************************************************************/
10972 #ifndef PALM_2
10973 SOAP_FMAC1
10974 const char*
10975 SOAP_FMAC2
soap_int2s(struct soap * soap,int n)10976 soap_int2s(struct soap *soap, int n)
10977 { return soap_long2s(soap, (long)n);
10978 }
10979 #endif
10980 
10981 /******************************************************************************/
10982 #ifndef PALM_2
10983 SOAP_FMAC1
10984 int
10985 SOAP_FMAC2
soap_outint(struct soap * soap,const char * tag,int id,const int * p,const char * type,int n)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);
10991 }
10992 #endif
10993 
10994 /******************************************************************************/
10995 #ifndef PALM_2
10996 SOAP_FMAC1
10997 int
10998 SOAP_FMAC2
soap_s2int(struct soap * soap,const char * s,int * p)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
11014     )
11015       soap->error = SOAP_TYPE;
11016   }
11017   return soap->error;
11018 }
11019 #endif
11020 
11021 /******************************************************************************/
11022 #ifndef PALM_2
11023 SOAP_FMAC1
11024 int *
11025 SOAP_FMAC2
soap_inint(struct soap * soap,const char * tag,int * p,const char * type,int t)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;
11038   }
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;
11046   }
11047   if (soap->body && soap_element_end_in(soap, tag))
11048     return NULL;
11049   return p;
11050 }
11051 #endif
11052 
11053 /******************************************************************************/
11054 #ifndef PALM_2
11055 SOAP_FMAC1
11056 const char*
11057 SOAP_FMAC2
soap_long2s(struct soap * soap,long n)11058 soap_long2s(struct soap *soap, long n)
11059 { sprintf(soap->tmpbuf, "%ld", n);
11060   return soap->tmpbuf;
11061 }
11062 #endif
11063 
11064 /******************************************************************************/
11065 #ifndef PALM_2
11066 SOAP_FMAC1
11067 int
11068 SOAP_FMAC2
soap_outlong(struct soap * soap,const char * tag,int id,const long * p,const char * type,int n)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);
11074 }
11075 #endif
11076 
11077 /******************************************************************************/
11078 #ifndef PALM_2
11079 SOAP_FMAC1
11080 int
11081 SOAP_FMAC2
soap_s2long(struct soap * soap,const char * s,long * p)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
11097     )
11098       soap->error = SOAP_TYPE;
11099   }
11100   return soap->error;
11101 }
11102 #endif
11103 
11104 /******************************************************************************/
11105 #ifndef PALM_2
11106 SOAP_FMAC1
11107 long *
11108 SOAP_FMAC2
soap_inlong(struct soap * soap,const char * tag,long * p,const char * type,int t)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;
11121   }
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;
11129   }
11130   if (soap->body && soap_element_end_in(soap, tag))
11131     return NULL;
11132   return p;
11133 }
11134 #endif
11135 
11136 /******************************************************************************/
11137 #ifndef WITH_LEAN
11138 SOAP_FMAC1
11139 const char*
11140 SOAP_FMAC2
soap_LONG642s(struct soap * soap,LONG64 n)11141 soap_LONG642s(struct soap *soap, LONG64 n)
11142 { sprintf(soap->tmpbuf, SOAP_LONG_FORMAT, n);
11143   return soap->tmpbuf;
11144 }
11145 #endif
11146 
11147 /******************************************************************************/
11148 #ifndef WITH_LEAN
11149 SOAP_FMAC1
11150 int
11151 SOAP_FMAC2
soap_outLONG64(struct soap * soap,const char * tag,int id,const LONG64 * p,const char * type,int n)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);
11157 }
11158 #endif
11159 
11160 /******************************************************************************/
11161 #ifndef WITH_LEAN
11162 SOAP_FMAC1
11163 int
11164 SOAP_FMAC2
soap_s2LONG64(struct soap * soap,const char * s,LONG64 * p)11165 soap_s2LONG64(struct soap *soap, const char *s, LONG64 *p)
11166 { if (s)
11167   {
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
11182       )
11183 #else
11184 # ifdef HAVE_SSCANF
11185     if (sscanf(s, SOAP_LONG_FORMAT, p) != 1)
11186 # endif
11187 #endif
11188       soap->error = SOAP_TYPE;
11189   }
11190   return soap->error;
11191 }
11192 #endif
11193 
11194 /******************************************************************************/
11195 #ifndef WITH_LEAN
11196 SOAP_FMAC1
11197 LONG64 *
11198 SOAP_FMAC2
soap_inLONG64(struct soap * soap,const char * tag,LONG64 * p,const char * type,int t)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;
11217   }
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;
11225   }
11226   if (soap->body && soap_element_end_in(soap, tag))
11227     return NULL;
11228   return p;
11229 }
11230 #endif
11231 
11232 /******************************************************************************/
11233 #ifndef PALM_2
11234 SOAP_FMAC1
11235 const char*
11236 SOAP_FMAC2
soap_byte2s(struct soap * soap,char n)11237 soap_byte2s(struct soap *soap, char n)
11238 { return soap_long2s(soap, (long)n);
11239 }
11240 #endif
11241 
11242 /******************************************************************************/
11243 #ifndef PALM_2
11244 SOAP_FMAC1
11245 int
11246 SOAP_FMAC2
soap_outbyte(struct soap * soap,const char * tag,int id,const char * p,const char * type,int n)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);
11252 }
11253 #endif
11254 
11255 /******************************************************************************/
11256 #ifndef PALM_2
11257 SOAP_FMAC1
11258 int
11259 SOAP_FMAC2
soap_s2byte(struct soap * soap,const char * s,char * p)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;
11268   }
11269   return soap->error;
11270 }
11271 #endif
11272 
11273 /******************************************************************************/
11274 #ifndef PALM_2
11275 SOAP_FMAC1
11276 char *
11277 SOAP_FMAC2
soap_inbyte(struct soap * soap,const char * tag,char * p,const char * type,int t)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;
11288   }
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;
11296   }
11297   if (soap->body && soap_element_end_in(soap, tag))
11298     return NULL;
11299   return p;
11300 }
11301 #endif
11302 
11303 /******************************************************************************/
11304 #ifndef PALM_2
11305 SOAP_FMAC1
11306 const char*
11307 SOAP_FMAC2
soap_short2s(struct soap * soap,short n)11308 soap_short2s(struct soap *soap, short n)
11309 { return soap_long2s(soap, (long)n);
11310 }
11311 #endif
11312 
11313 /******************************************************************************/
11314 #ifndef PALM_2
11315 SOAP_FMAC1
11316 int
11317 SOAP_FMAC2
soap_outshort(struct soap * soap,const char * tag,int id,const short * p,const char * type,int n)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);
11323 }
11324 #endif
11325 
11326 /******************************************************************************/
11327 #ifndef PALM_2
11328 SOAP_FMAC1
11329 int
11330 SOAP_FMAC2
soap_s2short(struct soap * soap,const char * s,short * p)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;
11339   }
11340   return soap->error;
11341 }
11342 #endif
11343 
11344 /******************************************************************************/
11345 #ifndef PALM_2
11346 SOAP_FMAC1
11347 short *
11348 SOAP_FMAC2
soap_inshort(struct soap * soap,const char * tag,short * p,const char * type,int t)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;
11360   }
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;
11368   }
11369   if (soap->body && soap_element_end_in(soap, tag))
11370     return NULL;
11371   return p;
11372 }
11373 #endif
11374 
11375 /******************************************************************************/
11376 #ifndef PALM_2
11377 SOAP_FMAC1
11378 const char*
11379 SOAP_FMAC2
soap_float2s(struct soap * soap,float n)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;
11398 }
11399 #endif
11400 
11401 /******************************************************************************/
11402 #ifndef PALM_2
11403 SOAP_FMAC1
11404 int
11405 SOAP_FMAC2
soap_outfloat(struct soap * soap,const char * tag,int id,const float * p,const char * type,int n)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);
11411 }
11412 #endif
11413 
11414 /******************************************************************************/
11415 #ifndef PALM_2
11416 SOAP_FMAC1
11417 int
11418 SOAP_FMAC2
soap_s2float(struct soap * soap,const char * s,float * p)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
11432     {
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
11451       {
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
11461       }
11462     }
11463   }
11464   return soap->error;
11465 }
11466 #endif
11467 
11468 /******************************************************************************/
11469 #ifndef WITH_LEAN
soap_isnumeric(struct soap * soap,const char * type)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;
11491   }
11492   return SOAP_OK;
11493 }
11494 #endif
11495 
11496 /******************************************************************************/
11497 #ifndef PALM_2
11498 SOAP_FMAC1
11499 float *
11500 SOAP_FMAC2
soap_infloat(struct soap * soap,const char * tag,float * p,const char * type,int t)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;
11514   }
11515   if (soap->body && soap_element_end_in(soap, tag))
11516     return NULL;
11517   return p;
11518 }
11519 #endif
11520 
11521 /******************************************************************************/
11522 #ifndef PALM_2
11523 SOAP_FMAC1
11524 const char*
11525 SOAP_FMAC2
soap_double2s(struct soap * soap,double n)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;
11544 }
11545 #endif
11546 
11547 /******************************************************************************/
11548 #ifndef PALM_2
11549 SOAP_FMAC1
11550 int
11551 SOAP_FMAC2
soap_outdouble(struct soap * soap,const char * tag,int id,const double * p,const char * type,int n)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);
11557 }
11558 #endif
11559 
11560 /******************************************************************************/
11561 #ifndef PALM_2
11562 SOAP_FMAC1
11563 int
11564 SOAP_FMAC2
soap_s2double(struct soap * soap,const char * s,double * p)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
11578     {
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
11588       {
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
11598       }
11599     }
11600   }
11601   return soap->error;
11602 }
11603 #endif
11604 
11605 /******************************************************************************/
11606 #ifndef PALM_2
11607 SOAP_FMAC1
11608 double *
11609 SOAP_FMAC2
soap_indouble(struct soap * soap,const char * tag,double * p,const char * type,int t)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;
11623   }
11624   if (soap->body && soap_element_end_in(soap, tag))
11625     return NULL;
11626   return p;
11627 }
11628 #endif
11629 
11630 /******************************************************************************/
11631 #ifndef PALM_2
11632 SOAP_FMAC1
11633 const char*
11634 SOAP_FMAC2
soap_unsignedByte2s(struct soap * soap,unsigned char n)11635 soap_unsignedByte2s(struct soap *soap, unsigned char n)
11636 { return soap_unsignedLong2s(soap, (unsigned long)n);
11637 }
11638 #endif
11639 
11640 /******************************************************************************/
11641 #ifndef PALM_2
11642 SOAP_FMAC1
11643 int
11644 SOAP_FMAC2
soap_outunsignedByte(struct soap * soap,const char * tag,int id,const unsigned char * p,const char * type,int n)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);
11650 }
11651 #endif
11652 
11653 /******************************************************************************/
11654 #ifndef PALM_2
11655 SOAP_FMAC1
11656 int
11657 SOAP_FMAC2
soap_s2unsignedByte(struct soap * soap,const char * s,unsigned char * p)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;
11666   }
11667   return soap->error;
11668 }
11669 #endif
11670 
11671 /******************************************************************************/
11672 #ifndef PALM_2
11673 SOAP_FMAC1
11674 unsigned char *
11675 SOAP_FMAC2
soap_inunsignedByte(struct soap * soap,const char * tag,unsigned char * p,const char * type,int t)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;
11686   }
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;
11694   }
11695   if (soap->body && soap_element_end_in(soap, tag))
11696     return NULL;
11697   return p;
11698 }
11699 #endif
11700 
11701 /******************************************************************************/
11702 #ifndef PALM_2
11703 SOAP_FMAC1
11704 const char*
11705 SOAP_FMAC2
soap_unsignedShort2s(struct soap * soap,unsigned short n)11706 soap_unsignedShort2s(struct soap *soap, unsigned short n)
11707 { return soap_unsignedLong2s(soap, (unsigned long)n);
11708 }
11709 #endif
11710 
11711 /******************************************************************************/
11712 #ifndef PALM_2
11713 SOAP_FMAC1
11714 int
11715 SOAP_FMAC2
soap_outunsignedShort(struct soap * soap,const char * tag,int id,const unsigned short * p,const char * type,int n)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);
11721 }
11722 #endif
11723 
11724 /******************************************************************************/
11725 #ifndef PALM_2
11726 SOAP_FMAC1
11727 int
11728 SOAP_FMAC2
soap_s2unsignedShort(struct soap * soap,const char * s,unsigned short * p)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;
11737   }
11738   return soap->error;
11739 }
11740 #endif
11741 
11742 /******************************************************************************/
11743 #ifndef PALM_2
11744 SOAP_FMAC1
11745 unsigned short *
11746 SOAP_FMAC2
soap_inunsignedShort(struct soap * soap,const char * tag,unsigned short * p,const char * type,int t)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;
11758   }
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;
11766   }
11767   if (soap->body && soap_element_end_in(soap, tag))
11768     return NULL;
11769   return p;
11770 }
11771 #endif
11772 
11773 /******************************************************************************/
11774 #ifndef PALM_2
11775 SOAP_FMAC1
11776 const char*
11777 SOAP_FMAC2
soap_unsignedInt2s(struct soap * soap,unsigned int n)11778 soap_unsignedInt2s(struct soap *soap, unsigned int n)
11779 { return soap_unsignedLong2s(soap, (unsigned long)n);
11780 }
11781 #endif
11782 
11783 /******************************************************************************/
11784 #ifndef PALM_2
11785 SOAP_FMAC1
11786 int
11787 SOAP_FMAC2
soap_outunsignedInt(struct soap * soap,const char * tag,int id,const unsigned int * p,const char * type,int n)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);
11793 }
11794 #endif
11795 
11796 /******************************************************************************/
11797 #ifndef PALM_2
11798 SOAP_FMAC1
11799 int
11800 SOAP_FMAC2
soap_s2unsignedInt(struct soap * soap,const char * s,unsigned int * p)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
11816     )
11817       soap->error = SOAP_TYPE;
11818   }
11819   return soap->error;
11820 }
11821 #endif
11822 
11823 /******************************************************************************/
11824 #ifndef PALM_2
11825 SOAP_FMAC1
11826 unsigned int *
11827 SOAP_FMAC2
soap_inunsignedInt(struct soap * soap,const char * tag,unsigned int * p,const char * type,int t)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;
11840   }
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;
11848   }
11849   if (soap->body && soap_element_end_in(soap, tag))
11850     return NULL;
11851   return p;
11852 }
11853 #endif
11854 
11855 /******************************************************************************/
11856 #ifndef PALM_2
11857 SOAP_FMAC1
11858 const char*
11859 SOAP_FMAC2
soap_unsignedLong2s(struct soap * soap,unsigned long n)11860 soap_unsignedLong2s(struct soap *soap, unsigned long n)
11861 { sprintf(soap->tmpbuf, "%lu", n);
11862   return soap->tmpbuf;
11863 }
11864 #endif
11865 
11866 /******************************************************************************/
11867 #ifndef PALM_2
11868 SOAP_FMAC1
11869 int
11870 SOAP_FMAC2
soap_outunsignedLong(struct soap * soap,const char * tag,int id,const unsigned long * p,const char * type,int n)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);
11876 }
11877 #endif
11878 
11879 /******************************************************************************/
11880 #ifndef PALM_2
11881 SOAP_FMAC1
11882 int
11883 SOAP_FMAC2
soap_s2unsignedLong(struct soap * soap,const char * s,unsigned long * p)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
11899     )
11900       soap->error = SOAP_TYPE;
11901   }
11902   return soap->error;
11903 }
11904 #endif
11905 
11906 /******************************************************************************/
11907 #ifndef PALM_2
11908 SOAP_FMAC1
11909 unsigned long *
11910 SOAP_FMAC2
soap_inunsignedLong(struct soap * soap,const char * tag,unsigned long * p,const char * type,int t)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;
11923   }
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;
11931   }
11932   if (soap->body && soap_element_end_in(soap, tag))
11933     return NULL;
11934   return p;
11935 }
11936 #endif
11937 
11938 /******************************************************************************/
11939 #ifndef WITH_LEAN
11940 SOAP_FMAC1
11941 const char*
11942 SOAP_FMAC2
soap_ULONG642s(struct soap * soap,ULONG64 n)11943 soap_ULONG642s(struct soap *soap, ULONG64 n)
11944 { sprintf(soap->tmpbuf, SOAP_ULONG_FORMAT, n);
11945   return soap->tmpbuf;
11946 }
11947 #endif
11948 
11949 /******************************************************************************/
11950 #ifndef WITH_LEAN
11951 SOAP_FMAC1
11952 int
11953 SOAP_FMAC2
soap_outULONG64(struct soap * soap,const char * tag,int id,const ULONG64 * p,const char * type,int n)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);
11959 }
11960 #endif
11961 
11962 /******************************************************************************/
11963 #ifndef WITH_LEAN
11964 SOAP_FMAC1
11965 int
11966 SOAP_FMAC2
soap_s2ULONG64(struct soap * soap,const char * s,ULONG64 * p)11967 soap_s2ULONG64(struct soap *soap, const char *s, ULONG64 *p)
11968 { if (s)
11969   {
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
11984       )
11985 #else
11986 #ifdef HAVE_SSCANF
11987     if (sscanf(s, SOAP_ULONG_FORMAT, p) != 1)
11988 #endif
11989 #endif
11990       soap->error = SOAP_TYPE;
11991   }
11992   return soap->error;
11993 }
11994 #endif
11995 
11996 /******************************************************************************/
11997 #ifndef WITH_LEAN
11998 SOAP_FMAC1
11999 ULONG64 *
12000 SOAP_FMAC2
soap_inULONG64(struct soap * soap,const char * tag,ULONG64 * p,const char * type,int t)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;
12015   }
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;
12022   }
12023   if (soap->body && soap_element_end_in(soap, tag))
12024     return NULL;
12025   return p;
12026 }
12027 #endif
12028 
12029 /******************************************************************************/
12030 #ifndef PALM_2
12031 SOAP_FMAC1
12032 int
12033 SOAP_FMAC2
soap_s2string(struct soap * soap,const char * s,char ** t,long minlen,long maxlen)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';
12048     }
12049   }
12050   return soap->error;
12051 }
12052 #endif
12053 
12054 /******************************************************************************/
12055 #ifndef PALM_2
12056 SOAP_FMAC1
12057 int
12058 SOAP_FMAC2
soap_s2QName(struct soap * soap,const char * s,char ** t,long minlen,long maxlen)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);
12084       }
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++;
12094         }
12095         else
12096         { while (np && *np->id)
12097             np = np->next;
12098           p = s;
12099         }
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));
12106           }
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);
12111           }
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;
12115           }
12116         }
12117         else if (s[n]) /* no namespace, part of string */
12118         { soap_append_lab(soap, s, n);
12119         }
12120 	else /* no namespace: assume "" namespace */
12121         { soap_append_lab(soap, "\"\"", 2);
12122 	}
12123         soap_append_lab(soap, ":", 1);
12124         soap_append_lab(soap, p, n - (p-s));
12125       }
12126       /* advance to next and add spacing */
12127       s += n;
12128       if (*s)
12129         soap_append_lab(soap, " ", 1);
12130     }
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));
12134   }
12135   return soap->error;
12136 }
12137 #endif
12138 
12139 /******************************************************************************/
12140 #ifndef PALM_2
12141 SOAP_FMAC1
12142 const char*
12143 SOAP_FMAC2
soap_QName2s(struct soap * soap,const char * s)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);
12167         }
12168 #endif
12169       }
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;
12184             }
12185           }
12186           /* URL is in the namespace table? */
12187           if (p && p->id)
12188           { soap_append_lab(soap, p->id, strlen(p->id));
12189           }
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));
12196           }
12197           soap_append_lab(soap, q + 1, n - (q-s) - 1);
12198         }
12199       }
12200       /* advance to next and add spacing */
12201       s += n;
12202       if (*s)
12203         soap_append_lab(soap, " ", 1);
12204     }
12205     soap_append_lab(soap, SOAP_STR_EOS, 1);
12206     t = soap_strdup(soap, soap->labbuf);
12207   }
12208   return t;
12209 }
12210 #endif
12211 
12212 /******************************************************************************/
12213 #ifndef WITH_LEAN
12214 SOAP_FMAC1
12215 int
12216 SOAP_FMAC2
soap_s2wchar(struct soap * soap,const char * s,wchar_t ** t,long minlen,long maxlen)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++;
12227     }
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));
12253               }
12254             }
12255           }
12256         }
12257       }
12258     }
12259     *r = L'\0';
12260     l = (long)(r - *t);
12261     if ((maxlen >= 0 && l > maxlen) || l < minlen)
12262       return soap->error = SOAP_LENGTH;
12263   }
12264   return soap->error;
12265 }
12266 #endif
12267 
12268 /******************************************************************************/
12269 #ifndef WITH_LEAN
12270 SOAP_FMAC1
12271 const char*
12272 SOAP_FMAC2
soap_wchar2s(struct soap * soap,const wchar_t * s)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;
12283   }
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));
12305               }
12306               *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
12307             }
12308             *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
12309           }
12310           *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
12311         }
12312         *t++ = (char)(0x80 | (c & 0x3F));
12313       }
12314     }
12315     *t = '\0';
12316   }
12317   return r;
12318 }
12319 #endif
12320 
12321 /******************************************************************************/
12322 #ifndef PALM_2
12323 SOAP_FMAC1
12324 int
12325 SOAP_FMAC2
soap_outstring(struct soap * soap,const char * tag,int id,char * const * p,const char * type,int n)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;
12337 }
12338 #endif
12339 
12340 /******************************************************************************/
12341 #ifndef PALM_2
12342 SOAP_FMAC1
12343 char **
12344 SOAP_FMAC2
soap_instring(struct soap * soap,const char * tag,char ** p,const char * type,int t,int flag,long minlen,long maxlen)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;
12350   }
12351   if (!p)
12352   { if (!(p = (char**)soap_malloc(soap, sizeof(char*))))
12353       return NULL;
12354   }
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;
12364     }
12365   }
12366   else if (tag && *tag == '-')
12367   { soap->error = SOAP_NO_TAG;
12368     return NULL;
12369   }
12370   else if (!*soap->href && minlen > 0)
12371   { soap->error = SOAP_LENGTH;
12372     return NULL;
12373   }
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;
12381 }
12382 #endif
12383 
12384 /******************************************************************************/
12385 #ifndef WITH_LEANER
12386 #ifndef PALM_2
12387 SOAP_FMAC1
12388 int
12389 SOAP_FMAC2
soap_outwstring(struct soap * soap,const char * tag,int id,wchar_t * const * p,const char * type,int n)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;
12401 }
12402 #endif
12403 #endif
12404 
12405 /******************************************************************************/
12406 #ifndef WITH_LEANER
12407 #ifndef PALM_2
12408 SOAP_FMAC1
12409 wchar_t **
12410 SOAP_FMAC2
soap_inwstring(struct soap * soap,const char * tag,wchar_t ** p,const char * type,int t,long minlen,long maxlen)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;
12416   }
12417   if (!p)
12418   { if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*))))
12419       return NULL;
12420   }
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;
12428     }
12429   }
12430   else if (tag && *tag == '-')
12431   { soap->error = SOAP_NO_TAG;
12432     return NULL;
12433   }
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;
12443 }
12444 #endif
12445 #endif
12446 
12447 /******************************************************************************/
12448 #ifndef WITH_LEAN
12449 SOAP_FMAC1
12450 time_t
12451 SOAP_FMAC2
soap_timegm(struct tm * T)12452 soap_timegm(struct tm *T)
12453 {
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
12474 }
12475 #endif
12476 
12477 /******************************************************************************/
12478 #ifndef WITH_LEAN
12479 SOAP_FMAC1
12480 const char*
12481 SOAP_FMAC2
soap_dateTime2s(struct soap * soap,time_t n)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);
12499   }
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);
12506   }
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))
12513   {
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);
12521   }
12522 #else
12523   if ((pT = localtime(&n)))
12524   {
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);
12532   }
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;
12544 }
12545 #endif
12546 
12547 /******************************************************************************/
12548 #ifndef WITH_LEAN
12549 SOAP_FMAC1
12550 int
12551 SOAP_FMAC2
soap_outdateTime(struct soap * soap,const char * tag,int id,const time_t * p,const char * type,int n)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);
12557 }
12558 #endif
12559 
12560 /******************************************************************************/
12561 #ifndef WITH_LEAN
12562 SOAP_FMAC1
12563 int
12564 SOAP_FMAC2
soap_s2dateTime(struct soap * soap,const char * s,time_t * p)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;
12589     }
12590     else
12591       s = zone;
12592     if (*s)
12593     {
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;
12602         }
12603         else /* +hhmm */
12604         { m = (int)soap_strtol(s, NULL, 10);
12605           h = m / 100;
12606           m = m % 100;
12607         }
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--;
12616 	}
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--;
12622 	}
12623 	/* note: day of the month may be out of range, timegm() handles it */
12624       }
12625 #endif
12626       *p = soap_timegm(&T);
12627     }
12628     else /* no UTC or timezone, so assume we got a localtime */
12629     { T.tm_isdst = -1;
12630       *p = mktime(&T);
12631     }
12632   }
12633   return soap->error;
12634 }
12635 #endif
12636 
12637 /******************************************************************************/
12638 #ifndef WITH_LEAN
12639 SOAP_FMAC1
12640 time_t *
12641 SOAP_FMAC2
soap_indateTime(struct soap * soap,const char * tag,time_t * p,const char * type,int t)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;
12651   }
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;
12658   }
12659   if (soap->body && soap_element_end_in(soap, tag))
12660     return NULL;
12661   return p;
12662 }
12663 #endif
12664 
12665 /******************************************************************************/
12666 #ifndef PALM_2
12667 SOAP_FMAC1
12668 int
12669 SOAP_FMAC2
soap_outliteral(struct soap * soap,const char * tag,char * const * p,const char * type)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;
12685     }
12686     else
12687     { t = tag;
12688       if (soap_element_begin_out(soap, t, 0, type))
12689         return soap->error;
12690     }
12691   }
12692   if (p && *p)
12693   { if (soap_send(soap, *p))
12694       return soap->error;
12695   }
12696   if (t)
12697     return soap_element_end_out(soap, t);
12698   return SOAP_OK;
12699 }
12700 #endif
12701 
12702 /******************************************************************************/
12703 #ifndef PALM_2
12704 SOAP_FMAC1
12705 char **
12706 SOAP_FMAC2
soap_inliteral(struct soap * soap,const char * tag,char ** p)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;
12712   }
12713   if (!p)
12714   { if (!(p = (char**)soap_malloc(soap, sizeof(char*))))
12715       return NULL;
12716   }
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;
12724     }
12725   }
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;
12733 }
12734 #endif
12735 
12736 /******************************************************************************/
12737 #ifndef WITH_LEANER
12738 #ifndef PALM_2
12739 SOAP_FMAC1
12740 int
12741 SOAP_FMAC2
soap_outwliteral(struct soap * soap,const char * tag,wchar_t * const * p,const char * type)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;
12757     }
12758     else
12759     { t = tag;
12760       if (soap_element_begin_out(soap, t, 0, type))
12761         return soap->error;
12762     }
12763     if (soap_send(soap, soap->tmpbuf))
12764       return soap->error;
12765   }
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;
12772     }
12773   }
12774   if (t)
12775     return soap_element_end_out(soap, t);
12776   return SOAP_OK;
12777 }
12778 #endif
12779 #endif
12780 
12781 /******************************************************************************/
12782 #ifndef WITH_LEANER
12783 #ifndef PALM_2
12784 SOAP_FMAC1
12785 wchar_t **
12786 SOAP_FMAC2
soap_inwliteral(struct soap * soap,const char * tag,wchar_t ** p)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;
12792   }
12793   if (!p)
12794   { if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*))))
12795       return NULL;
12796   }
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;
12804     }
12805   }
12806   else if (tag && *tag == '-')
12807   { soap->error = SOAP_NO_TAG;
12808     return NULL;
12809   }
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;
12817 }
12818 #endif
12819 #endif
12820 
12821 /******************************************************************************/
12822 #ifndef PALM_2
12823 SOAP_FMAC1
12824 const char *
12825 SOAP_FMAC2
soap_value(struct soap * soap)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);
12839   }
12840   for (s--; i > 0; i--, s--)
12841   { if (!soap_blank(*s))
12842       break;
12843   }
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;
12851   }
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 */
12857 }
12858 #endif
12859 
12860 /******************************************************************************/
12861 #if !defined(WITH_LEANER) || !defined(WITH_NOHTTP)
12862 #ifndef PALM_2
12863 SOAP_FMAC1
12864 int
12865 SOAP_FMAC2
soap_getline(struct soap * soap,char * s,int len)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;
12877     }
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;
12887     }
12888     else if ((int)c == EOF)
12889       return soap->error = SOAP_EOF;
12890     if (i < 0)
12891       return soap->error = SOAP_HDR;
12892   }
12893   return SOAP_OK;
12894 }
12895 #endif
12896 #endif
12897 
12898 /******************************************************************************/
12899 #ifndef PALM_1
12900 static size_t
soap_count_attachments(struct soap * soap)12901 soap_count_attachments(struct soap *soap)
12902 {
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));
12918     }
12919   }
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));
12946     }
12947     /* count \r\n--boundary-- */
12948     count += 6 + n;
12949   }
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
12955 }
12956 #endif
12957 
12958 /******************************************************************************/
12959 #ifndef WITH_LEANER
12960 #ifndef PALM_1
12961 static int
soap_putdimefield(struct soap * soap,const char * s,size_t n)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);
12966 }
12967 #endif
12968 #endif
12969 
12970 /******************************************************************************/
12971 #ifndef WITH_LEANER
12972 #ifndef PALM_1
12973 SOAP_FMAC1
12974 char *
12975 SOAP_FMAC2
soap_dime_option(struct soap * soap,unsigned short optype,const char * option)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);
12988     }
12989   }
12990   return s;
12991 }
12992 #endif
12993 #endif
12994 
12995 /******************************************************************************/
12996 #ifndef WITH_LEANER
12997 #ifndef PALM_1
12998 SOAP_FMAC1
12999 int
13000 SOAP_FMAC2
soap_putdimehdr(struct soap * soap)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;
13011   }
13012   if (soap->dime.type)
13013   { typelen = strlen(soap->dime.type);
13014     if (typelen > 0x0000FFFF)
13015       typelen = 0x0000FFFF;
13016   }
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;
13035 }
13036 #endif
13037 #endif
13038 
13039 /******************************************************************************/
13040 #ifndef WITH_LEANER
13041 #ifndef PALM_1
13042 SOAP_FMAC1
13043 int
13044 SOAP_FMAC2
soap_putdime(struct soap * soap)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;
13061       }
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"));
13065         do
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;
13072           }
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;
13084           }
13085         } while (size >= chunksize);
13086       }
13087       else
13088       { if (!content->next)
13089           soap->dime.flags |= SOAP_DIME_ME;
13090         if (soap_putdimehdr(soap))
13091           return soap->error;
13092         do
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;
13102           }
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);
13109       }
13110       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n"));
13111       if (soap->fdimereadclose)
13112         soap->fdimereadclose(soap, handle);
13113     }
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;
13120     }
13121   }
13122   return SOAP_OK;
13123 }
13124 #endif
13125 #endif
13126 
13127 /******************************************************************************/
13128 #ifndef WITH_LEANER
13129 #ifndef PALM_1
13130 static char *
soap_getdimefield(struct soap * soap,size_t n)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;
13144         }
13145         *s++ = (char)c;
13146       }
13147       *s = '\0';
13148       if ((soap->error = soap_move(soap, -(long)n&3)))
13149         return NULL;
13150     }
13151     else
13152       soap->error = SOAP_EOM;
13153   }
13154   return p;
13155 }
13156 #endif
13157 #endif
13158 
13159 /******************************************************************************/
13160 #ifndef WITH_LEANER
13161 #ifndef PALM_1
13162 SOAP_FMAC1
13163 int
13164 SOAP_FMAC2
soap_getdimehdr(struct soap * soap)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;
13180   }
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;
13186   }
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;
13205 }
13206 #endif
13207 #endif
13208 
13209 /******************************************************************************/
13210 #ifndef WITH_LEANER
13211 #ifndef PALM_1
13212 SOAP_FMAC1
13213 int
13214 SOAP_FMAC2
soap_getdime(struct soap * soap)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;
13221   }
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;
13248           }
13249           if (soap_recv(soap))
13250           { soap->error = SOAP_EOF;
13251             goto end;
13252           }
13253         }
13254         if (soap_move(soap, -(long)soap->dime.size&3))
13255         { soap->error = SOAP_EOF;
13256           break;
13257         }
13258         if (!(soap->dime.flags & SOAP_DIME_CF))
13259           break;
13260         if (soap_getdimehdr(soap))
13261           break;
13262       }
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;
13270     }
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;
13289         }
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;
13296       }
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;
13304     }
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);
13316   }
13317   if (soap->error != SOAP_DIME_END)
13318     return soap->error;
13319   return soap->error = SOAP_OK;
13320 }
13321 #endif
13322 #endif
13323 
13324 /******************************************************************************/
13325 #ifndef WITH_LEANER
13326 #ifndef PALM_1
13327 SOAP_FMAC1
13328 int
13329 SOAP_FMAC2
soap_getmimehdr(struct soap * soap)13330 soap_getmimehdr(struct soap *soap)
13331 { struct soap_multipart *content;
13332   do
13333   { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
13334       return soap->error;
13335   }
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;
13346     }
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;
13351   }
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);
13378     }
13379     if (soap_getline(soap, key, sizeof(soap->msgbuf)))
13380       return soap->error;
13381   }
13382   return SOAP_OK;
13383 }
13384 #endif
13385 #endif
13386 
13387 /******************************************************************************/
13388 #ifndef WITH_LEANER
13389 #ifndef PALM_1
13390 SOAP_FMAC1
13391 int
13392 SOAP_FMAC2
soap_getmime(struct soap * soap)13393 soap_getmime(struct soap *soap)
13394 { while (soap_get_mime_attachment(soap, NULL))
13395     ;
13396   return soap->error;
13397 }
13398 #endif
13399 #endif
13400 
13401 /******************************************************************************/
13402 #ifndef WITH_LEANER
13403 #ifndef PALM_1
13404 SOAP_FMAC1
13405 void
13406 SOAP_FMAC2
soap_post_check_mime_attachments(struct soap * soap)13407 soap_post_check_mime_attachments(struct soap *soap)
13408 { soap->imode |= SOAP_MIME_POSTCHECK;
13409 }
13410 #endif
13411 #endif
13412 
13413 /******************************************************************************/
13414 #ifndef WITH_LEANER
13415 #ifndef PALM_1
13416 SOAP_FMAC1
13417 int
13418 SOAP_FMAC2
soap_check_mime_attachments(struct soap * soap)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;
13423 }
13424 #endif
13425 #endif
13426 
13427 /******************************************************************************/
13428 #ifndef WITH_LEANER
13429 #ifndef PALM_1
13430 SOAP_FMAC1
13431 struct soap_multipart *
13432 SOAP_FMAC2
soap_get_mime_attachment(struct soap * soap,void * handle)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;
13446   }
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;
13451     }
13452   }
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;
13457   }
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;
13464     }
13465     for (i = 0; i < sizeof(soap->tmpbuf); i++)
13466     { if (m > 0)
13467       { *s++ = *t++;
13468         m--;
13469       }
13470       else
13471       { if (!flag)
13472         { c = soap_get1(soap);
13473           if ((int)c == EOF)
13474           { soap->error = SOAP_EOF;
13475             return NULL;
13476           }
13477         }
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;
13489           }
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';
13497         }
13498         *s++ = (char)c;
13499       }
13500     }
13501     if (content->ptr && soap->fmimewrite)
13502     { if ((soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i)))
13503         break;
13504     }
13505   }
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;
13515   }
13516   else
13517   { content->size = soap_size_block(soap, NULL, i+1)-1;
13518     content->ptr = soap_save_block(soap, NULL, NULL, 0);
13519   }
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;
13525   }
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;
13532     }
13533     if (soap_getmimehdr(soap))
13534       return NULL;
13535   }
13536   return content;
13537 }
13538 #endif
13539 #endif
13540 
13541 /******************************************************************************/
13542 #ifndef WITH_LEANER
13543 #ifndef PALM_1
13544 SOAP_FMAC1
13545 int
13546 SOAP_FMAC2
soap_match_cid(struct soap * soap,const char * s,const char * t)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;
13559   }
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;
13566 }
13567 #endif
13568 #endif
13569 
13570 /******************************************************************************/
13571 #ifndef WITH_LEANER
13572 #ifndef PALM_1
13573 static void
soap_resolve_attachment(struct soap * soap,struct soap_multipart * content)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);
13591       }
13592       else
13593         xp = &(*xp)->next;
13594     }
13595   }
13596 }
13597 #endif
13598 #endif
13599 
13600 /******************************************************************************/
13601 #ifndef WITH_LEANER
13602 #ifndef PALM_1
13603 SOAP_FMAC1
13604 int
13605 SOAP_FMAC2
soap_putmimehdr(struct soap * soap,struct soap_multipart * content)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);
13623 }
13624 #endif
13625 #endif
13626 
13627 /******************************************************************************/
13628 #ifndef WITH_LEANER
13629 #ifndef PALM_1
13630 SOAP_FMAC1
13631 int
13632 SOAP_FMAC2
soap_putmime(struct soap * soap)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;
13645       }
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"));
13651           do
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);
13657         }
13658         else
13659         { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error: cannot chunk streaming MIME (no HTTP chunking)\n"));
13660         }
13661       }
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;
13673           }
13674           if (soap_send_raw(soap, soap->tmpbuf, bufsize))
13675             break;
13676           size -= bufsize;
13677         } while (size);
13678       }
13679       if (soap->fmimereadclose)
13680         soap->fmimereadclose(soap, handle);
13681     }
13682     else
13683     { if (soap_putmimehdr(soap, content)
13684        || soap_send_raw(soap, content->ptr, content->size))
13685         return soap->error;
13686     }
13687   }
13688   return soap_send3(soap, "\r\n--", soap->mime.boundary, "--");
13689 }
13690 #endif
13691 #endif
13692 
13693 /******************************************************************************/
13694 #ifndef WITH_LEANER
13695 #ifndef PALM_1
13696 SOAP_FMAC1
13697 void
13698 SOAP_FMAC2
soap_set_dime(struct soap * soap)13699 soap_set_dime(struct soap *soap)
13700 { soap->omode |= SOAP_ENC_DIME;
13701   soap->dime.first = NULL;
13702   soap->dime.last = NULL;
13703 }
13704 #endif
13705 #endif
13706 
13707 /******************************************************************************/
13708 #ifndef WITH_LEANER
13709 #ifndef PALM_1
13710 SOAP_FMAC1
13711 void
13712 SOAP_FMAC2
soap_set_mime(struct soap * soap,const char * boundary,const char * start)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);
13719 }
13720 #endif
13721 #endif
13722 
13723 /******************************************************************************/
13724 #ifndef WITH_LEANER
13725 #ifndef PALM_1
13726 SOAP_FMAC1
13727 void
13728 SOAP_FMAC2
soap_clr_dime(struct soap * soap)13729 soap_clr_dime(struct soap *soap)
13730 { soap->omode &= ~SOAP_ENC_DIME;
13731   soap->dime.first = NULL;
13732   soap->dime.last = NULL;
13733 }
13734 #endif
13735 #endif
13736 
13737 /******************************************************************************/
13738 #ifndef WITH_LEANER
13739 #ifndef PALM_1
13740 SOAP_FMAC1
13741 void
13742 SOAP_FMAC2
soap_clr_mime(struct soap * soap)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;
13749 }
13750 #endif
13751 #endif
13752 
13753 /******************************************************************************/
13754 #ifndef WITH_LEANER
13755 #ifndef PALM_1
13756 static struct soap_multipart*
soap_new_multipart(struct soap * soap,struct soap_multipart ** first,struct soap_multipart ** last,char * ptr,size_t size)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;
13775   }
13776   return content;
13777 }
13778 #endif
13779 #endif
13780 
13781 /******************************************************************************/
13782 #ifndef WITH_LEANER
13783 #ifndef PALM_1
13784 SOAP_FMAC1
13785 int
13786 SOAP_FMAC2
soap_set_dime_attachment(struct soap * soap,char * ptr,size_t size,const char * type,const char * id,unsigned short optype,const char * option)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;
13795 }
13796 #endif
13797 #endif
13798 
13799 /******************************************************************************/
13800 #ifndef WITH_LEANER
13801 #ifndef PALM_1
13802 SOAP_FMAC1
13803 int
13804 SOAP_FMAC2
soap_set_mime_attachment(struct soap * soap,char * ptr,size_t size,enum soap_mime_encoding encoding,const char * type,const char * id,const char * location,const char * description)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;
13815 }
13816 #endif
13817 #endif
13818 
13819 /******************************************************************************/
13820 #ifndef WITH_LEANER
13821 #ifndef PALM_1
13822 SOAP_FMAC1
13823 struct soap_multipart*
13824 SOAP_FMAC2
soap_next_multipart(struct soap_multipart * content)13825 soap_next_multipart(struct soap_multipart *content)
13826 { if (content)
13827     return content->next;
13828   return NULL;
13829 }
13830 #endif
13831 #endif
13832 
13833 /******************************************************************************/
13834 #ifndef WITH_LEANER
13835 #ifndef PALM_1
13836 static void
soap_select_mime_boundary(struct soap * soap)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;
13848     }
13849     strcpy(s, "==");
13850     s += 2;
13851     n -= 4;
13852     while (n)
13853     { *s++ = soap_base64o[soap_random & 0x3F];
13854       n--;
13855     }
13856     strcpy(s, "==");
13857   }
13858   if (!soap->mime.start)
13859     soap->mime.start = "<SOAP-ENV:Envelope>";
13860 }
13861 #endif
13862 #endif
13863 
13864 /******************************************************************************/
13865 #ifndef WITH_LEANER
13866 #ifndef PALM_1
13867 static int
soap_valid_mime_boundary(struct soap * soap)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;
13881       }
13882     }
13883   }
13884   return SOAP_OK;
13885 }
13886 #endif
13887 #endif
13888 
13889 /******************************************************************************/
13890 #ifdef WITH_GZIP
13891 #ifndef PALM_1
13892 static int
soap_getgziphdr(struct soap * soap)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;
13904   }
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;
13909     }
13910   }
13911   if (f & 0x08) /* skip FNAME */
13912   { do
13913       c = soap_get1(soap);
13914     while (c && (int)c != EOF);
13915   }
13916   if ((int)c != EOF && (f & 0x10)) /* skip FCOMMENT */
13917   { do
13918       c = soap_get1(soap);
13919     while (c && (int)c != EOF);
13920   }
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);
13924   }
13925   if ((int)c == EOF)
13926     return soap->error = SOAP_EOF;
13927   return SOAP_OK;
13928 }
13929 #endif
13930 #endif
13931 
13932 /******************************************************************************/
13933 #ifndef PALM_1
13934 SOAP_FMAC1
13935 int
13936 SOAP_FMAC2
soap_begin_recv(struct soap * soap)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;
13954   }
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;
14023     }
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 = ' ';
14041   }
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);
14058   }
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;
14071     }
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;
14083     }
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;
14089     }
14090 #ifdef WITH_ZLIB
14091     if (soap->zlib_in != SOAP_ZLIB_NONE)
14092     {
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"));
14103         }
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;
14109         }
14110       }
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;
14118       }
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;
14129     }
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;
14136     }
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 */
14143       }
14144       return soap->error;
14145     }
14146   }
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));
14159     }
14160     if (soap_get_header_attribute(soap, soap->mime.first->type, "application/dime"))
14161       soap->mode |= SOAP_ENC_DIME;
14162   }
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;
14172       }
14173       else
14174         soap->dime.chunksize -= soap->buflen - soap->bufidx;
14175     }
14176     soap->count = soap->buflen - soap->bufidx;
14177   }
14178 #endif
14179   return SOAP_OK;
14180 }
14181 #endif
14182 
14183 /******************************************************************************/
14184 #ifndef PALM_2
14185 SOAP_FMAC1
14186 int
14187 SOAP_FMAC2
soap_envelope_begin_out(struct soap * soap)14188 soap_envelope_begin_out(struct soap *soap)
14189 {
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";
14201     }
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;
14210   }
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;
14216   }
14217 #endif
14218   soap->part = SOAP_IN_ENVELOPE;
14219   return soap_element_begin_out(soap, "SOAP-ENV:Envelope", 0, NULL);
14220 }
14221 #endif
14222 
14223 /******************************************************************************/
14224 #ifndef PALM_2
14225 SOAP_FMAC1
14226 int
14227 SOAP_FMAC2
soap_envelope_end_out(struct soap * soap)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;
14241     }
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);
14247   }
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;
14253 }
14254 #endif
14255 
14256 /******************************************************************************/
14257 #ifndef PALM_1
14258 static char*
soap_get_http_body(struct soap * soap)14259 soap_get_http_body(struct soap *soap)
14260 {
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;
14269   }
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 (;;)
14277   {
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;
14298     }
14299   }
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
14312 }
14313 #endif
14314 
14315 /******************************************************************************/
14316 #ifndef PALM_1
14317 SOAP_FMAC1
14318 int
14319 SOAP_FMAC2
soap_envelope_begin_in(struct soap * soap)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;
14330   }
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);
14342     }
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);
14349     }
14350   }
14351   return SOAP_OK;
14352 }
14353 #endif
14354 
14355 /******************************************************************************/
14356 #ifndef PALM_1
14357 SOAP_FMAC1
14358 int
14359 SOAP_FMAC2
soap_envelope_end_in(struct soap * soap)14360 soap_envelope_end_in(struct soap *soap)
14361 { soap->part = SOAP_END_ENVELOPE;
14362   return soap_element_end_in(soap, "SOAP-ENV:Envelope");
14363 }
14364 #endif
14365 
14366 /******************************************************************************/
14367 #ifndef PALM_2
14368 SOAP_FMAC1
14369 int
14370 SOAP_FMAC2
soap_body_begin_out(struct soap * soap)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);
14382 }
14383 #endif
14384 
14385 /******************************************************************************/
14386 #ifndef PALM_2
14387 SOAP_FMAC1
14388 int
14389 SOAP_FMAC2
soap_body_end_out(struct soap * soap)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;
14395 }
14396 #endif
14397 
14398 /******************************************************************************/
14399 #ifndef PALM_2
14400 SOAP_FMAC1
14401 int
14402 SOAP_FMAC2
soap_body_begin_in(struct soap * soap)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;
14410 }
14411 #endif
14412 
14413 /******************************************************************************/
14414 #ifndef PALM_2
14415 SOAP_FMAC1
14416 int
14417 SOAP_FMAC2
soap_body_end_in(struct soap * soap)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");
14423 }
14424 #endif
14425 
14426 /******************************************************************************/
14427 #ifndef PALM_2
14428 SOAP_FMAC1
14429 int
14430 SOAP_FMAC2
soap_recv_header(struct soap * soap)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;
14437 }
14438 #endif
14439 
14440 /******************************************************************************/
14441 #ifndef PALM_1
14442 SOAP_FMAC1
14443 void
14444 SOAP_FMAC2
soap_set_endpoint(struct soap * soap,const char * endpoint)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;
14477       }
14478       soap->host[i] = s[i];
14479     }
14480   }
14481   else
14482   { for (i = 0; i < n; i++)
14483     { soap->host[i] = s[i];
14484       if (s[i] == '/' || s[i] == ':')
14485         break;
14486     }
14487   }
14488 #else
14489   for (i = 0; i < n; i++)
14490   { soap->host[i] = s[i];
14491     if (s[i] == '/' || s[i] == ':')
14492       break;
14493   }
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;
14501   }
14502   if (i < n && s[i])
14503   { strncpy(soap->path, s + i, sizeof(soap->path));
14504     soap->path[sizeof(soap->path) - 1] = '\0';
14505   }
14506 }
14507 #endif
14508 
14509 /******************************************************************************/
14510 #ifndef PALM_1
14511 SOAP_FMAC1
14512 int
14513 SOAP_FMAC2
soap_connect(struct soap * soap,const char * endpoint,const char * action)14514 soap_connect(struct soap *soap, const char *endpoint, const char *action)
14515 { return soap_connect_command(soap, SOAP_POST, endpoint, action);
14516 }
14517 #endif
14518 
14519 /******************************************************************************/
14520 #ifndef PALM_1
14521 SOAP_FMAC1
14522 int
14523 SOAP_FMAC2
soap_connect_command(struct soap * soap,int http_command,const char * endpoints,const char * action)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);
14543     }
14544     SOAP_FREE(soap, endpoint);
14545   }
14546   else
14547     soap_try_connect_command(soap, http_command, endpoints, action);
14548   return soap->error;
14549 }
14550 #endif
14551 
14552 /******************************************************************************/
14553 #ifndef PALM_1
14554 static int
soap_try_connect_command(struct soap * soap,int http_command,const char * endpoint,const char * action)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;
14568   }
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);
14585     }
14586   }
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;
14593   }
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;
14607     }
14608 #endif
14609     soap->mode = k;
14610   }
14611   if (http_command == SOAP_GET)
14612     return soap_end_send(soap);
14613 #endif
14614   return SOAP_OK;
14615 }
14616 #endif
14617 
14618 /******************************************************************************/
14619 #ifndef WITH_LEAN
14620 SOAP_FMAC1
14621 char*
14622 SOAP_FMAC2
soap_s2base64(struct soap * soap,const unsigned char * s,char * t,int n)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;
14642   }
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';
14655   }
14656   return p;
14657 }
14658 #endif
14659 
14660 /******************************************************************************/
14661 #ifndef WITH_LEAN
14662 SOAP_FMAC1
14663 const char*
14664 SOAP_FMAC2
soap_base642s(struct soap * soap,const char * s,char * t,size_t l,int * n)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;
14675   }
14676   if (!t)
14677   { l = (strlen(s) + 3) / 4 * 3;
14678     t = (char*)soap_malloc(soap, l);
14679   }
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;
14702           }
14703           if (n)
14704             *n += i;
14705           return p;
14706         }
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;
14713           }
14714           m = (m << 6) + b;
14715           j++;
14716         }
14717         else if (!soap_blank(c + '+'))
14718         { soap->error = SOAP_TYPE;
14719           return NULL;
14720         }
14721       }
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;
14729       }
14730       l -= 3;
14731     }
14732     if (n)
14733       *n += 3 * SOAP_BLKLEN;
14734   }
14735 }
14736 #endif
14737 
14738 /******************************************************************************/
14739 #ifndef WITH_LEAN
14740 SOAP_FMAC1
14741 char*
14742 SOAP_FMAC2
soap_s2hex(struct soap * soap,const unsigned char * s,char * t,int n)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'));
14757     }
14758   }
14759   *t++ = '\0';
14760   return p;
14761 }
14762 #endif
14763 
14764 /******************************************************************************/
14765 #ifndef WITH_LEAN
14766 SOAP_FMAC1
14767 const char*
14768 SOAP_FMAC2
soap_hex2s(struct soap * soap,const char * s,char * t,size_t l,int * n)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;
14777   }
14778   if (!t)
14779   { l = strlen(s) / 2;
14780     t = (char*)soap_malloc(soap, l);
14781   }
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--;
14795   }
14796   if (n)
14797     *n = (int)(t - p);
14798   return p;
14799 }
14800 #endif
14801 
14802 /******************************************************************************/
14803 #ifndef WITH_NOHTTP
14804 #ifndef PALM_1
14805 SOAP_FMAC1
14806 int
14807 SOAP_FMAC2
soap_puthttphdr(struct soap * soap,int status,size_t count)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";
14822     }
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";
14831       }
14832       else
14833         s = "application/dime";
14834     }
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';
14841       }
14842       else
14843         strcat(soap->tmpbuf, s);
14844       if (soap->mime.start)
14845       { strcat(soap->tmpbuf, "\"; start=\"");
14846         strcat(soap->tmpbuf, soap->mime.start);
14847       }
14848       strcat(soap->tmpbuf, "\"");
14849       if (r)
14850       { strcat(soap->tmpbuf, "; start-info=\"");
14851         strcat(soap->tmpbuf, r);
14852         strcat(soap->tmpbuf, "\"");
14853       }
14854       s = soap->tmpbuf;
14855     }
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))
14861     {
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;
14869     }
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);
14879     }
14880     if (err)
14881       return err;
14882   }
14883   return soap->fposthdr(soap, "Connection", soap->keep_alive ? "keep-alive" : "close");
14884 }
14885 #endif
14886 #endif
14887 
14888 /******************************************************************************/
14889 #ifndef WITH_LEAN
14890 static const char*
soap_set_validation_fault(struct soap * soap,const char * s,const char * t)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;
14897 }
14898 #endif
14899 
14900 /******************************************************************************/
14901 #ifndef PALM_1
14902 SOAP_FMAC1
14903 void
14904 SOAP_FMAC2
soap_set_fault(struct soap * soap)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";
14915   }
14916   if (*s)
14917     return;
14918   switch (soap->error)
14919   {
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);
15086       }
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;
15100       }
15101       else
15102 #endif
15103 #endif
15104       { sprintf(soap->msgbuf, "Error %d", soap->error);
15105         *s = soap->msgbuf;
15106       }
15107     }
15108 }
15109 #endif
15110 
15111 /******************************************************************************/
15112 #ifndef PALM_1
15113 SOAP_FMAC1
15114 int
15115 SOAP_FMAC2
soap_send_fault(struct soap * soap)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;
15138       }
15139     }
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);
15154       }
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);
15165     }
15166   }
15167   soap->error = status;
15168   return soap_closesock(soap);
15169 }
15170 #endif
15171 
15172 /******************************************************************************/
15173 #ifndef PALM_1
15174 SOAP_FMAC1
15175 int
15176 SOAP_FMAC2
soap_recv_fault(struct soap * soap,int check)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;
15185   }
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);
15195   }
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;
15209     }
15210     if (!soap_body_end_in(soap))
15211       soap_envelope_end_in(soap);
15212   }
15213   soap_end_recv(soap);
15214   soap->error = status;
15215   return soap_closesock(soap);
15216 }
15217 #endif
15218 
15219 /******************************************************************************/
15220 #ifndef WITH_NOHTTP
15221 #ifndef PALM_1
15222 SOAP_FMAC1
15223 int
15224 SOAP_FMAC2
soap_send_empty_response(struct soap * soap,int httpstatuscode)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);
15233   }
15234   soap->omode = m;
15235   return soap->error = SOAP_STOP; /* stops the server's response */
15236 }
15237 #endif
15238 #endif
15239 
15240 /******************************************************************************/
15241 #ifndef WITH_NOHTTP
15242 #ifndef PALM_1
15243 SOAP_FMAC1
15244 int
15245 SOAP_FMAC2
soap_recv_empty_response(struct soap * soap)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);
15252 }
15253 #endif
15254 #endif
15255 
15256 /******************************************************************************/
15257 #ifndef WITH_NOIO
15258 #ifndef PALM_1
15259 static const char*
soap_strerror(struct soap * soap)15260 soap_strerror(struct soap *soap)
15261 { register int err = soap->errnum;
15262   if (err)
15263   {
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] = '?';
15280     }
15281 #endif
15282 #endif
15283   }
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';
15295     }
15296     if (st < 0)
15297     { st = -st;
15298       su = 'u';
15299     }
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
15305   }
15306   return soap->msgbuf;
15307 }
15308 #endif
15309 #endif
15310 
15311 /******************************************************************************/
15312 #ifndef PALM_2
15313 static int
soap_set_error(struct soap * soap,const char * faultcode,const char * faultsubcodeQName,const char * faultstring,const char * faultdetailXML,int soaperror)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;
15323   }
15324   return soap->error = soaperror;
15325 }
15326 #endif
15327 
15328 /******************************************************************************/
15329 #ifndef PALM_2
15330 SOAP_FMAC1
15331 int
15332 SOAP_FMAC2
soap_set_sender_error(struct soap * soap,const char * faultstring,const char * faultdetailXML,int soaperror)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);
15335 }
15336 #endif
15337 
15338 /******************************************************************************/
15339 #ifndef PALM_2
15340 SOAP_FMAC1
15341 int
15342 SOAP_FMAC2
soap_set_receiver_error(struct soap * soap,const char * faultstring,const char * faultdetailXML,int soaperror)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);
15345 }
15346 #endif
15347 
15348 /******************************************************************************/
15349 #ifndef PALM_2
15350 static int
soap_copy_fault(struct soap * soap,const char * faultcode,const char * faultsubcodeQName,const char * faultstring,const char * faultdetailXML)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);
15360 }
15361 #endif
15362 
15363 /******************************************************************************/
15364 #ifndef PALM_2
15365 SOAP_FMAC1
15366 int
15367 SOAP_FMAC2
soap_sender_fault(struct soap * soap,const char * faultstring,const char * faultdetailXML)15368 soap_sender_fault(struct soap *soap, const char *faultstring, const char *faultdetailXML)
15369 { return soap_sender_fault_subcode(soap, NULL, faultstring, faultdetailXML);
15370 }
15371 #endif
15372 
15373 /******************************************************************************/
15374 #ifndef PALM_2
15375 SOAP_FMAC1
15376 int
15377 SOAP_FMAC2
soap_sender_fault_subcode(struct soap * soap,const char * faultsubcodeQName,const char * faultstring,const char * faultdetailXML)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);
15380 }
15381 #endif
15382 
15383 /******************************************************************************/
15384 #ifndef PALM_2
15385 SOAP_FMAC1
15386 int
15387 SOAP_FMAC2
soap_receiver_fault(struct soap * soap,const char * faultstring,const char * faultdetailXML)15388 soap_receiver_fault(struct soap *soap, const char *faultstring, const char *faultdetailXML)
15389 { return soap_receiver_fault_subcode(soap, NULL, faultstring, faultdetailXML);
15390 }
15391 #endif
15392 
15393 /******************************************************************************/
15394 #ifndef PALM_2
15395 SOAP_FMAC1
15396 int
15397 SOAP_FMAC2
soap_receiver_fault_subcode(struct soap * soap,const char * faultsubcodeQName,const char * faultstring,const char * faultdetailXML)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);
15400 }
15401 #endif
15402 
15403 /******************************************************************************/
15404 #ifndef PALM_2
15405 #ifndef WITH_NOSTDLIB
15406 SOAP_FMAC1
15407 void
15408 SOAP_FMAC2
soap_print_fault(struct soap * soap,FILE * fd)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]");
15423   }
15424 }
15425 #endif
15426 #endif
15427 
15428 /******************************************************************************/
15429 #ifdef __cplusplus
15430 #ifndef WITH_LEAN
15431 #ifndef WITH_NOSTDLIB
15432 SOAP_FMAC1
15433 void
15434 SOAP_FMAC2
soap_stream_fault(struct soap * soap,std::ostream & os)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;
15457   }
15458 }
15459 #endif
15460 #endif
15461 #endif
15462 
15463 /******************************************************************************/
15464 #ifndef WITH_LEAN
15465 #ifndef WITH_NOSTDLIB
15466 SOAP_FMAC1
15467 char*
15468 SOAP_FMAC2
soap_sprint_fault(struct soap * soap,char * buf,size_t len)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
15497   }
15498   return buf;
15499 }
15500 #endif
15501 #endif
15502 
15503 /******************************************************************************/
15504 #ifndef PALM_1
15505 #ifndef WITH_NOSTDLIB
15506 SOAP_FMAC1
15507 void
15508 SOAP_FMAC2
soap_print_fault_location(struct soap * soap,FILE * fd)15509 soap_print_fault_location(struct soap *soap, FILE *fd)
15510 {
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;
15530   }
15531 #endif
15532 }
15533 #endif
15534 #endif
15535 
15536 /******************************************************************************/
15537 #ifndef PALM_1
15538 SOAP_FMAC1
15539 int
15540 SOAP_FMAC2
soap_register_plugin_arg(struct soap * soap,int (* fcreate)(struct soap *,struct soap_plugin *,void *),void * arg)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;
15556   }
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;
15560 }
15561 #endif
15562 
15563 /******************************************************************************/
15564 #ifndef PALM_1
15565 static void *
fplugin(struct soap * soap,const char * id)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;
15572 }
15573 #endif
15574 
15575 /******************************************************************************/
15576 #ifndef PALM_2
15577 SOAP_FMAC1
15578 void *
15579 SOAP_FMAC2
soap_lookup_plugin(struct soap * soap,const char * id)15580 soap_lookup_plugin(struct soap *soap, const char *id)
15581 { return soap->fplugin(soap, id);
15582 }
15583 #endif
15584 
15585 /******************************************************************************/
15586 #ifdef __cplusplus
15587 }
15588 #endif
15589 
15590 /******************************************************************************\
15591  *
15592  *	C++ soap struct methods
15593  *
15594 \******************************************************************************/
15595 
15596 #ifdef __cplusplus
soap()15597 soap::soap()
15598 { soap_init(this);
15599 }
15600 #endif
15601 
15602 /******************************************************************************/
15603 #ifdef __cplusplus
soap(soap_mode m)15604 soap::soap(soap_mode m)
15605 { soap_init1(this, m);
15606 }
15607 #endif
15608 
15609 /******************************************************************************/
15610 #ifdef __cplusplus
soap(soap_mode im,soap_mode om)15611 soap::soap(soap_mode im, soap_mode om)
15612 { soap_init2(this, im, om);
15613 }
15614 #endif
15615 
15616 /******************************************************************************/
15617 #ifdef __cplusplus
soap(const struct soap & soap)15618 soap::soap(const struct soap& soap)
15619 { soap_copy_context(this, &soap);
15620 }
15621 #endif
15622 
15623 /******************************************************************************/
15624 #ifdef __cplusplus
~soap()15625 soap::~soap()
15626 { soap_destroy(this);
15627   soap_end(this);
15628   soap_done(this);
15629 }
15630 #endif
15631 
15632 /******************************************************************************/
15633