COPASI API  4.16.103
stdsoap2.cpp
Go to the documentation of this file.
1 // Begin CVS Header
2 // $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/MIRIAM/WebServicesIssues/stdsoap2.cpp,v $
3 // $Revision: 1.4 $
4 // $Name: $
5 // $Author: shoops $
6 // $Date: 2009/04/21 16:17:18 $
7 // End CVS Header
8 
9 // Copyright (C) 2008 by Pedro Mendes, Virginia Tech Intellectual
10 // Properties, Inc., EML Research, gGmbH, University of Heidelberg,
11 // and The University of Manchester.
12 // All rights reserved.
13 
14 /*
15  stdsoap2.c[pp] 2.7.12
16 
17  gSOAP runtime engine
18 
19 gSOAP XML Web services tools
20 Copyright (C) 2000-2008, Robert van Engelen, Genivia Inc., All Rights Reserved.
21 This part of the software is released under ONE of the following licenses:
22 GPL, or the gSOAP public license, or Genivia's license for commercial use.
23 --------------------------------------------------------------------------------
24 Contributors:
25 
26 Wind River Systems Inc., for the following additions under gSOAP public license:
27  - vxWorks compatible
28 --------------------------------------------------------------------------------
29 gSOAP public license.
30 
31 The contents of this file are subject to the gSOAP Public License Version 1.3
32 (the "License"); you may not use this file except in compliance with the
33 License. You may obtain a copy of the License at
34 http://www.cs.fsu.edu/~engelen/soaplicense.html
35 Software distributed under the License is distributed on an "AS IS" basis,
36 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
37 for the specific language governing rights and limitations under the License.
38 
39 The Initial Developer of the Original Code is Robert A. van Engelen.
40 Copyright (C) 2000-2008, Robert van Engelen, Genivia Inc., All Rights Reserved.
41 --------------------------------------------------------------------------------
42 GPL license.
43 
44 This program is free software; you can redistribute it and/or modify it under
45 the terms of the GNU General Public License as published by the Free Software
46 Foundation; either version 2 of the License, or (at your option) any later
47 version.
48 
49 This program is distributed in the hope that it will be useful, but WITHOUT ANY
50 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
51 PARTICULAR PURPOSE. See the GNU General Public License for more details.
52 
53 You should have received a copy of the GNU General Public License along with
54 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
55 Place, Suite 330, Boston, MA 02111-1307 USA
56 
57 Author contact information:
58 engelen@genivia.com / engelen@acm.org
59 
60 This program is released under the GPL with the additional exemption that
61 compiling, linking, and/or using OpenSSL is allowed.
62 --------------------------------------------------------------------------------
63 A commercial use license is available from Genivia, Inc., contact@genivia.com
64 --------------------------------------------------------------------------------
65 
66 Installation note:
67 
68 Win32 build needs winsock.dll (Visual C++ "wsock32.lib")
69 To do this in Visual C++ 6.0, go to "Project", "settings", select the "Link"
70 tab (the project file needs to be selected in the file view) and add
71 "wsock32.lib" to the "Object/library modules" entry
72 
73 On Mac OS X with gcc (GCC) 3.1 20020420 (prerelease) you MUST compile with
74 -fstack_check when using -O2 because gcc 3.1 has a bug that smashes the stack
75 when locally allocated data exceeds 64K.
76 
77  */
78 
79 #ifdef AS400
80 # pragma convert(819) /* EBCDIC to ASCII */
81 #endif
82 
83 #include "stdsoap2.h"
84 
85 #ifdef __BORLANDC__
86 # pragma warn -8060
87 #else
88 # ifdef WIN32
89 # ifdef UNDER_CE
90 # pragma comment(lib, "winsock.lib")
91 # else
92 # pragma comment(lib, "wsock32.lib")
93 # endif
94 # pragma warning(disable : 4996) /* disable deprecation warnings */
95 # endif
96 #endif
97 
98 #ifdef __cplusplus
99 SOAP_SOURCE_STAMP("@(#) stdsoap2.cpp ver 2.7.12 2008-10-01 00:00:00 GMT")
100 extern "C"
101 {
102 #else
103 SOAP_SOURCE_STAMP("@(#) stdsoap2.c ver 2.7.12 2008-10-01 00:00:00 GMT")
104 #endif
105 
106  /* 8bit character representing unknown/nonrepresentable character data (e.g. not supported by current locale with multibyte support enabled) */
107 #ifndef SOAP_UNKNOWN_CHAR
108 #define SOAP_UNKNOWN_CHAR (127)
109 #endif
110 
111  /* EOF=-1 */
112 #define SOAP_LT (soap_wchar)(-2) /* XML character '<' */
113 #define SOAP_TT (soap_wchar)(-3) /* XML character '</' */
114 #define SOAP_GT (soap_wchar)(-4) /* XML character '>' */
115 #define SOAP_QT (soap_wchar)(-5) /* XML character '"' */
116 #define SOAP_AP (soap_wchar)(-6) /* XML character ''' */
117 
118 #define soap_blank(c) ((c) >= 0 && (c) <= 32)
119 #define soap_notblank(c) ((c) > 32)
120 
121 #if defined(WIN32) && !defined(UNDER_CE)
122 #define soap_hash_ptr(p) ((PtrToUlong(p) >> 3) & (SOAP_PTRHASH - 1))
123 #else
124 #define soap_hash_ptr(p) ((size_t)(((unsigned long)(p) >> 3) & (SOAP_PTRHASH-1)))
125 #endif
126 
127 #ifndef PALM_1
128  static void soap_init_logs(struct soap*);
129 #endif
130 #ifdef SOAP_DEBUG
131  static void soap_close_logfile(struct soap*, int);
132  static void soap_set_logfile(struct soap*, int, const char*);
133 #endif
134 
135 #ifdef SOAP_MEM_DEBUG
136  static void soap_init_mht(struct soap*);
137  static void soap_free_mht(struct soap*);
138  static void soap_track_unlink(struct soap*, const void*);
139 #endif
140 
141 #ifndef PALM_2
142  static int soap_set_error(struct soap*, const char*, const char*, const char*, const char*, int);
143  static int soap_copy_fault(struct soap*, const char*, const char*, const char*, const char*);
144  static int soap_getattrval(struct soap*, char*, size_t, soap_wchar);
145 #endif
146 
147 #ifndef PALM_1
148  static void soap_free_ns(struct soap *soap);
149  static soap_wchar soap_char(struct soap*);
150  static soap_wchar soap_get_pi(struct soap*);
151  static int soap_isxdigit(int);
152  static void *fplugin(struct soap*, const char*);
153  static char *soap_get_http_body(struct soap*);
154  static size_t soap_count_attachments(struct soap *soap);
155  static int soap_try_connect_command(struct soap*, int http_command, const char *endpoint, const char *action);
156 #ifndef WITH_NOIDREF
157  static void soap_update_ptrs(struct soap*, char*, char*, char*, char*);
158  static int soap_has_copies(struct soap*, const char*, const char*);
159  static void soap_init_iht(struct soap*);
160  static void soap_free_iht(struct soap*);
161  static void soap_init_pht(struct soap*);
162  static void soap_free_pht(struct soap*);
163 #endif
164 #endif
165 
166 #ifndef WITH_LEAN
167  static const char *soap_set_validation_fault(struct soap*, const char*, const char*);
168  static int soap_isnumeric(struct soap*, const char*);
169  static struct soap_nlist *soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized);
170  static void soap_pop_ns(struct soap *soap);
171  static void soap_utilize_ns(struct soap *soap, const char *tag, size_t n);
172 #endif
173 
174 #ifndef WITH_LEANER
175 #ifndef PALM_1
176  static struct soap_multipart *soap_new_multipart(struct soap*, struct soap_multipart**, struct soap_multipart**, char*, size_t);
177  static int soap_putdimefield(struct soap*, const char*, size_t);
178  static char *soap_getdimefield(struct soap*, size_t);
179  static void soap_select_mime_boundary(struct soap*);
180  static int soap_valid_mime_boundary(struct soap*);
181  static void soap_resolve_attachment(struct soap*, struct soap_multipart*);
182 #endif
183 #endif
184 
185 #ifdef WITH_GZIP
186  static int soap_getgziphdr(struct soap*);
187 #endif
188 
189 #ifdef WITH_OPENSSL
190  int soap_ssl_init_done = 0;
191 
192  static int ssl_auth_init(struct soap*);
193  static int ssl_verify_callback(int, X509_STORE_CTX*);
194  static int ssl_verify_callback_allow_expired_certificate(int, X509_STORE_CTX*);
195  static int ssl_password(char*, int, int, void *);
196  /* The callback below is included for future references:
197  static DH *ssl_tmp_dh(SSL*, int, int);
198  */
199 #endif
200 
201 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
202 #ifndef PALM_1
203  static const char *soap_decode(char*, size_t, const char*, const char*);
204 #endif
205 #endif
206 
207 #ifndef WITH_NOHTTP
208 #ifndef PALM_1
209  static soap_wchar soap_getchunkchar(struct soap*);
210  static const char *http_error(struct soap*, int);
211  static int http_post(struct soap*, const char*, const char*, int, const char*, const char*, size_t);
212  static int http_get(struct soap*);
213  static int http_put(struct soap*);
214  static int http_del(struct soap*);
215  static int http_head(struct soap*);
216  static int http_send_header(struct soap*, const char*);
217  static int http_post_header(struct soap*, const char*, const char*);
218  static int http_response(struct soap*, int, size_t);
219  static int http_parse(struct soap*);
220  static int http_parse_header(struct soap*, const char*, const char*);
221 #endif
222 #endif
223 
224 #ifndef WITH_NOIO
225 
226 #ifndef PALM_1
227  static int fsend(struct soap*, const char*, size_t);
228  static size_t frecv(struct soap*, char*, size_t);
229  static int tcp_init(struct soap*);
230  static const char *tcp_error(struct soap*);
231 #ifndef WITH_IPV6
232  static int tcp_gethost(struct soap*, const char *addr, struct in_addr *inaddr);
233 #endif
234  static SOAP_SOCKET tcp_connect(struct soap*, const char *endpoint, const char *host, int port);
235  static SOAP_SOCKET tcp_accept(struct soap*, SOAP_SOCKET, struct sockaddr*, int*);
236  static int tcp_disconnect(struct soap*);
237  static int tcp_closesocket(struct soap*, SOAP_SOCKET);
238  static int tcp_shutdownsocket(struct soap*, SOAP_SOCKET, int);
239  static const char *soap_strerror(struct soap*);
240 #endif
241 
242 #if defined(WIN32)
243 #define SOAP_SOCKBLOCK(fd) \
244  {u_long blocking = 0; \
245  ioctlsocket(fd, FIONBIO, &blocking); \
246  }
247 #define SOAP_SOCKNONBLOCK(fd) \
248  {u_long nonblocking = 1; \
249  ioctlsocket(fd, FIONBIO, &nonblocking); \
250  }
251 #elif defined(VXWORKS)
252 #define SOAP_SOCKBLOCK(fd) \
253  {u_long blocking = 0; \
254  ioctl(fd, FIONBIO, (int)(&blocking)); \
255  }
256 #define SOAP_SOCKNONBLOCK(fd) \
257  {u_long nonblocking = 1; \
258  ioctl(fd, FIONBIO, (int)(&nonblocking)); \
259  }
260 #elif defined(PALM)
261 #define SOAP_SOCKBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)&~O_NONBLOCK);
262 #define SOAP_SOCKNONBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)|O_NONBLOCK);
263 #elif defined(SYMBIAN)
264 #define SOAP_SOCKBLOCK(fd) \
265  {long blocking = 0; \
266  ioctl(fd, 0/*FIONBIO*/, &blocking); \
267  }
268 #define SOAP_SOCKNONBLOCK(fd) \
269  {long nonblocking = 1; \
270  ioctl(fd, 0/*FIONBIO*/, &nonblocking); \
271  }
272 #else
273 #define SOAP_SOCKBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)&~O_NONBLOCK);
274 #define SOAP_SOCKNONBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)|O_NONBLOCK);
275 #endif
276 
277 #endif
278 
279 #if defined(PALM) && !defined(PALM_2)
280  unsigned short errno;
281 #endif
282 
283 #ifndef PALM_1
284  static const char soap_env1[42] = "http://schemas.xmlsoap.org/soap/envelope/";
285  static const char soap_enc1[42] = "http://schemas.xmlsoap.org/soap/encoding/";
286  static const char soap_env2[40] = "http://www.w3.org/2003/05/soap-envelope";
287  static const char soap_enc2[40] = "http://www.w3.org/2003/05/soap-encoding";
288  static const char soap_rpc[35] = "http://www.w3.org/2003/05/soap-rpc";
289 #endif
290 
291 #ifndef PALM_1
292  const struct soap_double_nan soap_double_nan = {0xFFFFFFFF, 0xFFFFFFFF};
293  static const char soap_base64o[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
294  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";
295 #endif
296 
297 #ifndef WITH_LEAN
298  static const char soap_indent[11] = "\n\t\t\t\t\t\t\t\t\t";
299  /* Alternative indentation form for SOAP_XML_INDENT:
300  static const char soap_indent[21] = "\n ";
301  */
302 #endif
303 
304 #ifndef SOAP_CANARY
305 # define SOAP_CANARY (0xC0DE)
306 #endif
307 
308  static const char soap_padding[4] = "\0\0\0";
309 #define SOAP_STR_PADDING (soap_padding)
310 #define SOAP_STR_EOS (soap_padding)
311 #define SOAP_NON_NULL (soap_padding)
312 
313 #ifndef WITH_LEAN
314  static const struct soap_code_map html_entity_codes[] = /* entities for XHTML parsing */
315  {{160, "nbsp" },
316  {161, "iexcl" },
317  {162, "cent" },
318  {163, "pound" },
319  {164, "curren" },
320  {165, "yen" },
321  {166, "brvbar" },
322  {167, "sect" },
323  {168, "uml" },
324  {169, "copy" },
325  {170, "ordf" },
326  {171, "laquo" },
327  {172, "not" },
328  {173, "shy" },
329  {174, "reg" },
330  {175, "macr" },
331  {176, "deg" },
332  {177, "plusmn" },
333  {178, "sup2" },
334  {179, "sup3" },
335  {180, "acute" },
336  {181, "micro" },
337  {182, "para" },
338  {183, "middot" },
339  {184, "cedil" },
340  {185, "sup1" },
341  {186, "ordm" },
342  {187, "raquo" },
343  {188, "frac14" },
344  {189, "frac12" },
345  {190, "frac34" },
346  {191, "iquest" },
347  {192, "Agrave" },
348  {193, "Aacute" },
349  {194, "Acirc" },
350  {195, "Atilde" },
351  {196, "Auml" },
352  {197, "Aring" },
353  {198, "AElig" },
354  {199, "Ccedil" },
355  {200, "Egrave" },
356  {201, "Eacute" },
357  {202, "Ecirc" },
358  {203, "Euml" },
359  {204, "Igrave" },
360  {205, "Iacute" },
361  {206, "Icirc" },
362  {207, "Iuml" },
363  {208, "ETH" },
364  {209, "Ntilde" },
365  {210, "Ograve" },
366  {211, "Oacute" },
367  {212, "Ocirc" },
368  {213, "Otilde" },
369  {214, "Ouml" },
370  {215, "times" },
371  {216, "Oslash" },
372  {217, "Ugrave" },
373  {218, "Uacute" },
374  {219, "Ucirc" },
375  {220, "Uuml" },
376  {221, "Yacute" },
377  {222, "THORN" },
378  {223, "szlig" },
379  {224, "agrave" },
380  {225, "aacute" },
381  {226, "acirc" },
382  {227, "atilde" },
383  {228, "auml" },
384  {229, "aring" },
385  {230, "aelig" },
386  {231, "ccedil" },
387  {232, "egrave" },
388  {233, "eacute" },
389  {234, "ecirc" },
390  {235, "euml" },
391  {236, "igrave" },
392  {237, "iacute" },
393  {238, "icirc" },
394  {239, "iuml" },
395  {240, "eth" },
396  {241, "ntilde" },
397  {242, "ograve" },
398  {243, "oacute" },
399  {244, "ocirc" },
400  {245, "otilde" },
401  {246, "ouml" },
402  {247, "divide" },
403  {248, "oslash" },
404  {249, "ugrave" },
405  {250, "uacute" },
406  {251, "ucirc" },
407  {252, "uuml" },
408  {253, "yacute" },
409  {254, "thorn" },
410  {255, "yuml" },
411  {0, NULL}
412  };
413 #endif
414 
415 #ifndef WITH_NOIO
416 #ifndef WITH_LEAN
417  static const struct soap_code_map h_error_codes[] =
418  {
419 #ifdef HOST_NOT_FOUND
420  {HOST_NOT_FOUND, "Host not found" },
421 #endif
422 #ifdef TRY_AGAIN
423  {TRY_AGAIN, "Try Again" },
424 #endif
425 #ifdef NO_RECOVERY
426  {NO_RECOVERY, "No Recovery" },
427 #endif
428 #ifdef NO_DATA
429  {NO_DATA, "No Data" },
430 #endif
431 #ifdef NO_ADDRESS
432  {NO_ADDRESS, "No Address" },
433 #endif
434  {0, NULL}
435  };
436 #endif
437 #endif
438 
439 #ifndef WITH_NOHTTP
440 #ifndef WITH_LEAN
441  static const struct soap_code_map h_http_error_codes[] =
442  {{200, "OK" },
443  {201, "Created" },
444  {202, "Accepted" },
445  {203, "Non-Authoritative Information" },
446  {204, "No Content" },
447  {205, "Reset Content" },
448  {206, "Partial Content" },
449  {300, "Multiple Choices" },
450  {301, "Moved Permanently" },
451  {302, "Found" },
452  {303, "See Other" },
453  {304, "Not Modified" },
454  {305, "Use Proxy" },
455  {307, "Temporary Redirect" },
456  {400, "Bad Request" },
457  {401, "Unauthorized" },
458  {402, "Payment Required" },
459  {403, "Forbidden" },
460  {404, "Not Found" },
461  {405, "Method Not Allowed" },
462  {406, "Not Acceptable" },
463  {407, "Proxy Authentication Required" },
464  {408, "Request Time-out" },
465  {409, "Conflict" },
466  {410, "Gone" },
467  {411, "Length Required" },
468  {412, "Precondition Failed" },
469  {413, "Request Entity Too Large" },
470  {414, "Request-URI Too Large" },
471  {415, "Unsupported Media Type" },
472  {416, "Requested range not satisfiable" },
473  {417, "Expectation Failed" },
474  {500, "Internal Server Error" },
475  {501, "Not Implemented" },
476  {502, "Bad Gateway" },
477  {503, "Service Unavailable" },
478  {504, "Gateway Time-out" },
479  {505, "HTTP Version not supported" },
480  {0, NULL}
481  };
482 #endif
483 #endif
484 
485 #ifdef WITH_OPENSSL
486  static const struct soap_code_map h_ssl_error_codes[] =
487  {
488 #define _SSL_ERROR(e) {e, #e}
489 
490  _SSL_ERROR(SSL_ERROR_SSL),
491  _SSL_ERROR(SSL_ERROR_ZERO_RETURN),
492  _SSL_ERROR(SSL_ERROR_WANT_READ),
493  _SSL_ERROR(SSL_ERROR_WANT_WRITE),
494  _SSL_ERROR(SSL_ERROR_WANT_CONNECT),
495  _SSL_ERROR(SSL_ERROR_WANT_X509_LOOKUP),
496  _SSL_ERROR(SSL_ERROR_SYSCALL),
497  {0, NULL}
498  };
499 #endif
500 
501 #ifndef WITH_LEANER
502  static const struct soap_code_map mime_codes[] =
503  {{SOAP_MIME_7BIT, "7bit" },
504  {SOAP_MIME_8BIT, "8bit" },
505  {SOAP_MIME_BINARY, "binary" },
506  {SOAP_MIME_QUOTED_PRINTABLE, "quoted-printable" },
507  {SOAP_MIME_BASE64, "base64" },
508  {SOAP_MIME_IETF_TOKEN, "ietf-token" },
509  {SOAP_MIME_X_TOKEN, "x-token" },
510  {0, NULL}
511  };
512 #endif
513 
514 #ifdef WIN32
515  static int tcp_done = 0;
516 #endif
517 
518 #if defined(HP_UX) && defined(HAVE_GETHOSTBYNAME_R)
519  extern int h_errno;
520 #endif
521 
522  /******************************************************************************/
523 #ifndef WITH_NOIO
524 #ifndef PALM_1
525  static int
526  fsend(struct soap *soap, const char *s, size_t n)
527  {
528  register int nwritten, err;
529 #if defined(__cplusplus) && !defined(WITH_LEAN) && !defined(WITH_COMPAT)
530 
531  if (soap->os)
532  {
533  soap->os->write(s, (std::streamsize)n);
534 
535  if (soap->os->good())
536  return SOAP_OK;
537 
538  soap->errnum = 0;
539  return SOAP_EOF;
540  }
541 
542 #endif
543 
544  while (n)
545  {
546  if (soap_valid_socket(soap->socket))
547  {
548 #ifndef WITH_LEAN
549 
550  if (soap->send_timeout)
551  {
552 #ifndef WIN32
553 
554  if ((int)soap->socket >= (int)FD_SETSIZE)
555  return SOAP_FD_EXCEEDED; /* Hint: MUST increase FD_SETSIZE */
556 
557 #endif
558 
559  for (;;)
560  {
561  struct timeval timeout;
562  fd_set fd;
563  register int r;
564 
565  if (soap->send_timeout > 0)
566  {
567  timeout.tv_sec = soap->send_timeout;
568  timeout.tv_usec = 0;
569  }
570  else
571  {
572  timeout.tv_sec = -soap->send_timeout / 1000000;
573  timeout.tv_usec = -soap->send_timeout % 1000000;
574  }
575 
576  FD_ZERO(&fd);
577  FD_SET(soap->socket, &fd);
578 #ifdef WITH_OPENSSL
579 
580  if (soap->ssl)
581  r = select((int)soap->socket + 1, &fd, &fd, &fd, &timeout);
582  else
583 #endif
584  r = select((int)soap->socket + 1, NULL, &fd, &fd, &timeout);
585 
586  if (r > 0)
587  break;
588 
589  if (!r)
590  {
591  soap->errnum = 0;
592  return SOAP_EOF;
593  }
594 
595  err = soap_socket_errno(soap->socket);
596 
597  if (err != SOAP_EINTR && err != SOAP_EAGAIN && err != SOAP_EWOULDBLOCK)
598  {
599  soap->errnum = err;
600  return SOAP_EOF;
601  }
602  }
603  }
604 
605 #endif
606 #ifdef WITH_OPENSSL
607 
608  if (soap->ssl)
609  nwritten = SSL_write(soap->ssl, s, (int)n);
610  else if (soap->bio)
611  nwritten = BIO_write(soap->bio, s, (int)n);
612  else
613 #endif
614 #ifndef WITH_LEAN
615  if ((soap->omode & SOAP_IO_UDP))
616  {
617  if (soap->peerlen)
618  nwritten = sendto(soap->socket, 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 
622  /* retry and back-off algorithm */
623 
624  /* TODO: this is not very clear from specs so verify and limit conditions under which we should loop (e.g. ENOBUFS) */
625  if (nwritten < 0)
626  {
627  struct timeval timeout;
628  fd_set fd;
629  int udp_repeat;
630  int udp_delay;
631 #ifndef WIN32
632 
633  if ((int)soap->socket >= (int)FD_SETSIZE)
634  return SOAP_FD_EXCEEDED; /* Hint: MUST increase FD_SETSIZE */
635 
636 #endif
637 
638  if ((soap->connect_flags & SO_BROADCAST))
639  udp_repeat = 3; /* SOAP-over-UDP MULTICAST_UDP_REPEAT - 1 */
640  else
641  udp_repeat = 1; /* SOAP-over-UDP UNICAST_UDP_REPEAT - 1 */
642 
643  udp_delay = (soap_random % 201) + 50; /* UDP_MIN_DELAY .. UDP_MAX_DELAY */
644 
645  do
646  {
647  timeout.tv_sec = 0;
648  timeout.tv_usec = 1000 * udp_delay; /* ms */
649  FD_ZERO(&fd);
650  FD_SET(soap->socket, &fd);
651  select((int)soap->socket + 1, NULL, NULL, &fd, &timeout);
652 
653  if (soap->peerlen)
654  nwritten = sendto(soap->socket, s, (SOAP_WINSOCKINT)n, soap->socket_flags, (struct sockaddr*) & soap->peer, (SOAP_WINSOCKINT)soap->peerlen);
655  else
656  nwritten = send(soap->socket, s, (SOAP_WINSOCKINT)n, soap->socket_flags);
657 
658  udp_delay <<= 1;
659 
660  if (udp_delay > 500) /* UDP_UPPER_DELAY */
661  udp_delay = 500;
662  }
663  while (nwritten < 0 && --udp_repeat > 0);
664  }
665  }
666  else
667 #endif
668 #if !defined(PALM) && !defined(AS400)
669  nwritten = send(soap->socket, s, (int)n, soap->socket_flags);
670 
671 #else
672  nwritten = send(soap->socket, (void*)s, n, soap->socket_flags);
673 #endif
674 
675  if (nwritten <= 0)
676  {
677 #if defined(WITH_OPENSSL) || !defined(WITH_LEAN)
678  register int r = 0;
679 #endif
680  err = soap_socket_errno(soap->socket);
681 #ifdef WITH_OPENSSL
682 
683  if (soap->ssl && (r = SSL_get_error(soap->ssl, nwritten)) != SSL_ERROR_NONE && r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE)
684  {
685  soap->errnum = err;
686  return SOAP_EOF;
687  }
688 
689 #endif
690 
691  if (err == SOAP_EWOULDBLOCK || err == SOAP_EAGAIN)
692  {
693 #ifndef WITH_LEAN
694  struct timeval timeout;
695  fd_set fd;
696 #ifndef WIN32
697 
698  if ((int)soap->socket >= (int)FD_SETSIZE)
699  return SOAP_FD_EXCEEDED; /* Hint: MUST increase FD_SETSIZE */
700 
701 #endif
702 
703  if (soap->send_timeout > 0)
704  {
705  timeout.tv_sec = soap->send_timeout;
706  timeout.tv_usec = 0;
707  }
708  else if (soap->send_timeout < 0)
709  {
710  timeout.tv_sec = -soap->send_timeout / 1000000;
711  timeout.tv_usec = -soap->send_timeout % 1000000;
712  }
713  else
714  {
715  timeout.tv_sec = 0;
716  timeout.tv_usec = 10000;
717  }
718 
719  FD_ZERO(&fd);
720  FD_SET(soap->socket, &fd);
721 #ifdef WITH_OPENSSL
722 
723  if (soap->ssl && r == SSL_ERROR_WANT_READ)
724  r = select((int)soap->socket + 1, &fd, NULL, &fd, &timeout);
725  else
726  r = select((int)soap->socket + 1, NULL, &fd, &fd, &timeout);
727 
728 #else
729  r = select((int)soap->socket + 1, NULL, &fd, &fd, &timeout);
730 #endif
731 
732  if (!r && soap->send_timeout)
733  {
734  soap->errnum = 0;
735  return SOAP_EOF;
736  }
737 
738  if (r < 0 && (r = soap_socket_errno(soap->socket)) != SOAP_EINTR)
739  {
740  soap->errnum = r;
741  return SOAP_EOF;
742  }
743 
744 #endif
745  }
746  else if (err && err != SOAP_EINTR)
747  {
748  soap->errnum = err;
749  return SOAP_EOF;
750  }
751 
752  nwritten = 0; /* and call write() again */
753  }
754  }
755  else
756  {
757 #ifdef WITH_FASTCGI
758  nwritten = fwrite((void*)s, 1, n, stdout);
759  fflush(stdout);
760 #else
761 #ifdef UNDER_CE
762  nwritten = fwrite(s, 1, n, soap->sendfd);
763 #else
764 #ifdef VXWORKS
765 #ifdef WMW_RPM_IO
766 
767  if (soap->rpmreqid)
768  nwritten = (httpBlockPut(soap->rpmreqid, s, n) == 0) ? n : -1;
769  else
770 #endif
771  nwritten = fwrite(s, sizeof(char), n, fdopen(soap->sendfd, "w"));
772 
773 #else
774 #ifdef WIN32
775  nwritten = _write(soap->sendfd, s, (unsigned int)n);
776 #else
777  nwritten = write(soap->sendfd, s, (unsigned int)n);
778 #endif
779 #endif
780 #endif
781 #endif
782 
783  if (nwritten <= 0)
784  {
785 #ifndef WITH_FASTCGI
786  err = soap_errno;
787 #else
788  err = EOF;
789 #endif
790 
791  if (err && err != SOAP_EINTR && err != SOAP_EWOULDBLOCK && err != SOAP_EAGAIN)
792  {
793  soap->errnum = err;
794  return SOAP_EOF;
795  }
796 
797  nwritten = 0; /* and call write() again */
798  }
799  }
800 
801  n -= nwritten;
802  s += nwritten;
803  }
804 
805  return SOAP_OK;
806  }
807 #endif
808 #endif
809 
810  /******************************************************************************/
811 #ifndef PALM_1
812  SOAP_FMAC1
813  int
814  SOAP_FMAC2
815  soap_send_raw(struct soap *soap, const char *s, size_t n)
816  {
817  if (!n)
818  return SOAP_OK;
819 
820  if (soap->mode & SOAP_IO_LENGTH)
821  {
822  soap->count += n;
823 #ifndef WITH_LEANER
824 
825  if (soap->fpreparesend && (soap->mode & SOAP_IO) != SOAP_IO_STORE)
826  return soap->error = soap->fpreparesend(soap, s, n);
827 
828 #endif
829  return SOAP_OK;
830  }
831 
832  if (soap->mode & SOAP_IO)
833  {
834  register size_t i = SOAP_BUFLEN - soap->bufidx;
835 
836  while (n >= i)
837  {
838  memcpy(soap->buf + soap->bufidx, s, i);
839  soap->bufidx = SOAP_BUFLEN;
840 
841  if (soap_flush(soap))
842  return soap->error;
843 
844  s += i;
845  n -= i;
846  i = SOAP_BUFLEN;
847  }
848 
849  memcpy(soap->buf + soap->bufidx, s, n);
850  soap->bufidx += n;
851  return SOAP_OK;
852  }
853 
854  return soap_flush_raw(soap, s, n);
855  }
856 #endif
857 
858  /******************************************************************************/
859 #ifndef PALM_1
860  SOAP_FMAC1
861  int
862  SOAP_FMAC2
863  soap_flush(struct soap *soap)
864  {
865  register size_t n = soap->bufidx;
866 
867  if (n)
868  {
869  soap->bufidx = 0;
870 #ifdef WITH_ZLIB
871 
872  if (soap->mode & SOAP_ENC_ZLIB)
873  {
874  soap->d_stream->next_in = (Byte*)soap->buf;
875  soap->d_stream->avail_in = (unsigned int)n;
876 #ifdef WITH_GZIP
877  soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)n);
878 #endif
879 
880  do
881  {
882  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating %u bytes\n", soap->d_stream->avail_in));
883 
884  if (deflate(soap->d_stream, Z_NO_FLUSH) != Z_OK)
885  {
886  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to deflate: %s\n", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS));
887  return soap->error = SOAP_ZLIB_ERROR;
888  }
889 
890  if (!soap->d_stream->avail_out)
891  {
892  if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN))
893  return soap->error;
894 
895  soap->d_stream->next_out = (Byte*)soap->z_buf;
896  soap->d_stream->avail_out = SOAP_BUFLEN;
897  }
898  }
899  while (soap->d_stream->avail_in);
900  }
901  else
902 #endif
903  return soap_flush_raw(soap, soap->buf, n);
904  }
905 
906  return SOAP_OK;
907  }
908 #endif
909 
910  /******************************************************************************/
911 #ifndef PALM_1
912  SOAP_FMAC1
913  int
914  SOAP_FMAC2
915  soap_flush_raw(struct soap *soap, const char *s, size_t n)
916  {
917  if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
918  {
919  register char *t;
920 
921  if (!(t = (char*)soap_push_block(soap, NULL, n)))
922  return soap->error = SOAP_EOM;
923 
924  memcpy(t, s, n);
925 #ifndef WITH_LEANER
926 
927  if (soap->fpreparesend)
928  return soap->error = soap->fpreparesend(soap, s, n);
929 
930 #endif
931  return SOAP_OK;
932  }
933 
934 #ifndef WITH_LEANER
935 
936  if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
937  {
938  char t[16];
939  sprintf(t, "\r\n%lX\r\n" + (soap->chunksize ? 0 : 2), (unsigned long)n);
940  DBGMSG(SENT, t, strlen(t));
941 
942  if ((soap->error = soap->fsend(soap, t, strlen(t))))
943  return soap->error;
944 
945  soap->chunksize += n;
946  }
947 
948  DBGMSG(SENT, s, n);
949 #endif
950  return soap->error = soap->fsend(soap, s, n);
951  }
952 #endif
953 
954  /******************************************************************************/
955 #ifndef PALM_1
956  SOAP_FMAC1
957  int
958  SOAP_FMAC2
959  soap_send(struct soap *soap, const char *s)
960  {
961  if (s)
962  return soap_send_raw(soap, s, strlen(s));
963 
964  return SOAP_OK;
965  }
966 #endif
967 
968  /******************************************************************************/
969 #ifndef WITH_LEANER
970 #ifndef PALM_1
971  SOAP_FMAC1
972  int
973  SOAP_FMAC2
974  soap_send2(struct soap *soap, const char *s1, const char *s2)
975  {
976  if (soap_send(soap, s1))
977  return soap->error;
978 
979  return soap_send(soap, s2);
980  }
981 #endif
982 #endif
983 
984  /******************************************************************************/
985 #ifndef WITH_LEANER
986 #ifndef PALM_1
987  SOAP_FMAC1
988  int
989  SOAP_FMAC2
990  soap_send3(struct soap *soap, const char *s1, const char *s2, const char *s3)
991  {
992  if (soap_send(soap, s1)
993  || soap_send(soap, s2))
994  return soap->error;
995 
996  return soap_send(soap, s3);
997  }
998 #endif
999 #endif
1000 
1001  /******************************************************************************/
1002 #ifndef WITH_NOIO
1003 #ifndef PALM_1
1004  static size_t
1005  frecv(struct soap *soap, char *s, size_t n)
1006  {
1007  register int r;
1008 #ifndef WITH_LEAN
1009  register int retries = 100; /* max 100 retries with non-blocking sockets */
1010 #endif
1011  soap->errnum = 0;
1012 #if defined(__cplusplus) && !defined(WITH_LEAN) && !defined(WITH_COMPAT)
1013 
1014  if (soap->is)
1015  {
1016  if (soap->is->good())
1017  return soap->is->read(s, (std::streamsize)n).gcount();
1018 
1019  return 0;
1020  }
1021 
1022 #endif
1023 
1024  if (soap_valid_socket(soap->socket))
1025  {
1026  for (;;)
1027  {
1028 #ifdef WITH_OPENSSL
1029  register int err = 0;
1030 #endif
1031 #ifndef WITH_LEAN
1032 #ifdef WITH_OPENSSL
1033 
1034  if (soap->recv_timeout && !soap->ssl) /* SSL: sockets are nonblocking */
1035 #else
1036  if (soap->recv_timeout)
1037 #endif
1038  {
1039 #ifndef WIN32
1040 
1041  if ((int)soap->socket >= (int)FD_SETSIZE)
1042  {
1043  soap->error = SOAP_FD_EXCEEDED;
1044  return 0; /* Hint: MUST increase FD_SETSIZE */
1045  }
1046 
1047 #endif
1048 
1049  for (;;)
1050  {
1051  struct timeval timeout;
1052  fd_set fd;
1053 
1054  if (soap->recv_timeout > 0)
1055  {
1056  timeout.tv_sec = soap->recv_timeout;
1057  timeout.tv_usec = 0;
1058  }
1059  else
1060  {
1061  timeout.tv_sec = -soap->recv_timeout / 1000000;
1062  timeout.tv_usec = -soap->recv_timeout % 1000000;
1063  }
1064 
1065  FD_ZERO(&fd);
1066  FD_SET(soap->socket, &fd);
1067  r = select((int)soap->socket + 1, &fd, NULL, &fd, &timeout);
1068 
1069  if (r > 0)
1070  break;
1071 
1072  if (!r)
1073  {
1074  soap->errnum = 0;
1075  return 0;
1076  }
1077 
1078  r = soap_socket_errno(soap->socket);
1079 
1080  if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
1081  {
1082  soap->errnum = r;
1083  return 0;
1084  }
1085  }
1086  }
1087 #endif
1088 #ifdef WITH_OPENSSL
1089 
1090  if (soap->ssl)
1091  {
1092  r = SSL_read(soap->ssl, s, (int)n);
1093 
1094  if (r > 0)
1095  return (size_t)r;
1096 
1097  err = SSL_get_error(soap->ssl, r);
1098 
1099  if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
1100  return 0;
1101  }
1102  else if (soap->bio)
1103  {
1104  r = BIO_read(soap->bio, s, (int)n);
1105 
1106  if (r > 0)
1107  return (size_t)r;
1108 
1109  return 0;
1110  }
1111  else
1112 #endif
1113 
1114  {
1115 #ifndef WITH_LEAN
1116 
1117  if ((soap->omode & SOAP_IO_UDP))
1118  {
1119  SOAP_SOCKLEN_T k = (SOAP_SOCKLEN_T)sizeof(soap->peer);
1120  memset((void*)&soap->peer, 0, sizeof(soap->peer));
1121  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 */
1122  soap->peerlen = (size_t)k;
1123 #ifndef WITH_IPV6
1124  soap->ip = ntohl(soap->peer.sin_addr.s_addr);
1125 #endif
1126  }
1127  else
1128 #endif
1129  r = recv(soap->socket, s, (int)n, soap->socket_flags);
1130 
1131 #ifdef PALM
1132  /* CycleSyncDisplay(curStatusMsg); */
1133 #endif
1134 
1135  if (r >= 0)
1136  return (size_t)r;
1137 
1138  r = soap_socket_errno(soap->socket);
1139 
1140  if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
1141  {
1142  soap->errnum = r;
1143  return 0;
1144  }
1145  }
1146 
1147 #ifndef WITH_LEAN
1148  {struct timeval timeout;
1149  fd_set fd;
1150 
1151  if (soap->recv_timeout > 0)
1152  {
1153  timeout.tv_sec = soap->recv_timeout;
1154  timeout.tv_usec = 0;
1155  }
1156  else if (soap->recv_timeout < 0)
1157  {
1158  timeout.tv_sec = -soap->recv_timeout / 1000000;
1159  timeout.tv_usec = -soap->recv_timeout % 1000000;
1160  }
1161  else
1162  {
1163  timeout.tv_sec = 5;
1164  timeout.tv_usec = 0;
1165  }
1166 
1167 #ifndef WIN32
1168 
1169  if ((int)soap->socket >= (int)FD_SETSIZE)
1170  {
1171  soap->error = SOAP_FD_EXCEEDED;
1172  return 0; /* Hint: MUST increase FD_SETSIZE */
1173  }
1174 
1175 #endif
1176  FD_ZERO(&fd);
1177  FD_SET(soap->socket, &fd);
1178 #ifdef WITH_OPENSSL
1179 
1180  if (soap->ssl && err == SSL_ERROR_WANT_WRITE)
1181  r = select((int)soap->socket + 1, NULL, &fd, &fd, &timeout);
1182  else
1183  r = select((int)soap->socket + 1, &fd, NULL, &fd, &timeout);
1184 
1185 #else
1186  r = select((int)soap->socket + 1, &fd, NULL, &fd, &timeout);
1187 #endif
1188 
1189  if (!r && soap->recv_timeout)
1190  {
1191  soap->errnum = 0;
1192  return 0;
1193  }
1194 
1195  if (r < 0)
1196  {
1197  r = soap_socket_errno(soap->socket);
1198 
1199  if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
1200  {
1201  soap->errnum = r;
1202  return 0;
1203  }
1204  }
1205 
1206  if (retries-- <= 0)
1207  {
1208  soap->errnum = soap_socket_errno(soap->socket);
1209  return 0;
1210  }
1211  }
1212 #endif
1213 #ifdef PALM
1214  r = soap_socket_errno(soap->socket);
1215 
1216  if (r != SOAP_EINTR && retries-- <= 0)
1217  {
1218  soap->errnum = r;
1219  return 0;
1220  }
1221 
1222 #endif
1223  }
1224  }
1225 
1226 #ifdef WITH_FASTCGI
1227  return fread(s, 1, n, stdin);
1228 #else
1229 #ifdef UNDER_CE
1230  return fread(s, 1, n, soap->recvfd);
1231 #else
1232 #ifdef WMW_RPM_IO
1233 
1234  if (soap->rpmreqid)
1235  r = httpBlockRead(soap->rpmreqid, s, n);
1236  else
1237 #endif
1238 #ifdef WIN32
1239  r = _read(soap->recvfd, s, (unsigned int)n);
1240 
1241 #else
1242  r = read(soap->recvfd, s, (unsigned int)n);
1243 #endif
1244 
1245  if (r >= 0)
1246  return (size_t)r;
1247 
1248  soap->errnum = soap_errno;
1249  return 0;
1250 #endif
1251 #endif
1252  }
1253 #endif
1254 #endif
1255 
1256  /******************************************************************************/
1257 #ifndef WITH_NOHTTP
1258 #ifndef PALM_1
1259  static soap_wchar
1260  soap_getchunkchar(struct soap *soap)
1261  {
1262  if (soap->bufidx < soap->buflen)
1263  return soap->buf[soap->bufidx++];
1264 
1265  soap->bufidx = 0;
1266  soap->buflen = soap->chunkbuflen = soap->frecv(soap, soap->buf, SOAP_BUFLEN);
1267  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket %d\n", (unsigned int)soap->buflen, soap->socket));
1268  DBGMSG(RECV, soap->buf, soap->buflen);
1269 
1270  if (soap->buflen)
1271  return soap->buf[soap->bufidx++];
1272 
1273  return EOF;
1274  }
1275 #endif
1276 #endif
1277 
1278  /******************************************************************************/
1279 #ifndef PALM_1
1280  static int
1282  {
1283  return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
1284  }
1285 #endif
1286 
1287  /******************************************************************************/
1288 #ifndef PALM_1
1289  SOAP_FMAC1
1290  int
1291  SOAP_FMAC2
1292  soap_recv_raw(struct soap *soap)
1293  {
1294  register size_t ret;
1295 #ifdef WITH_ZLIB
1296 
1297  if (soap->mode & SOAP_ENC_ZLIB)
1298  {
1299  if (soap->d_stream->next_out == Z_NULL)
1300  return EOF;
1301 
1302  if (soap->d_stream->avail_in || !soap->d_stream->avail_out)
1303  {
1304  register int r;
1305  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflating\n"));
1306  soap->d_stream->next_out = (Byte*)soap->buf;
1307  soap->d_stream->avail_out = SOAP_BUFLEN;
1308  r = inflate(soap->d_stream, Z_NO_FLUSH);
1309 
1310  if (r == Z_OK || r == Z_STREAM_END)
1311  {
1312  soap->bufidx = 0;
1313  ret = soap->buflen = SOAP_BUFLEN - soap->d_stream->avail_out;
1314 
1315  if (soap->zlib_in == SOAP_ZLIB_GZIP)
1316  soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)ret);
1317 
1318  if (r == Z_STREAM_END)
1319  {
1320  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out));
1321  soap->z_ratio_in = (float)soap->d_stream->total_in / (float)soap->d_stream->total_out;
1322  soap->d_stream->next_out = Z_NULL;
1323  }
1324 
1325  if (ret)
1326  {
1327  soap->count += ret;
1328  DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- decompressed ----\n"));
1329  DBGMSG(RECV, soap->buf, ret);
1330  DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n----\n"));
1331  return SOAP_OK;
1332  }
1333  }
1334  else if (r != Z_BUF_ERROR)
1335  {
1336  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate error: %s\n", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS));
1337  soap->d_stream->next_out = Z_NULL;
1338  soap->error = SOAP_ZLIB_ERROR;
1339  return EOF;
1340  }
1341  }
1342 
1343 zlib_again:
1344 
1345  if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK && !soap->chunksize)
1346  {
1347  memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN);
1348  soap->buflen = soap->z_buflen;
1349  }
1350 
1351  DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- compressed ----\n"));
1352  }
1353 
1354 #endif
1355 #ifndef WITH_NOHTTP
1356 
1357  if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) /* read HTTP chunked transfer */
1358  {
1359  for (;;)
1360  {
1361  register soap_wchar c;
1362  char *t, tmp[8];
1363 
1364  if (soap->chunksize)
1365  {
1366  soap->buflen = ret = soap->frecv(soap, soap->buf, soap->chunksize > SOAP_BUFLEN ? SOAP_BUFLEN : soap->chunksize);
1367  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk: read %u bytes\n", (unsigned int)ret));
1368  DBGMSG(RECV, soap->buf, ret);
1369  soap->bufidx = 0;
1370  soap->chunksize -= ret;
1371  break;
1372  }
1373 
1374  t = tmp;
1375 
1376  if (!soap->chunkbuflen)
1377  {
1378  soap->chunkbuflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN);
1379  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes (chunked) from socket %d\n", (unsigned int)ret, soap->socket));
1380  DBGMSG(RECV, soap->buf, ret);
1381  soap->bufidx = 0;
1382 
1383  if (!ret)
1384  return soap->ahead = EOF;
1385  }
1386  else
1387  soap->bufidx = soap->buflen;
1388 
1389  soap->buflen = soap->chunkbuflen;
1390  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk size (idx=%u len=%u)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen));
1391 
1392  while (!soap_isxdigit((int)(c = soap_getchunkchar(soap))))
1393  {
1394  if ((int)c == EOF)
1395  return soap->ahead = EOF;
1396  }
1397 
1398  do
1399  *t++ = (char)c;
1400 
1401  while (soap_isxdigit((int)(c = soap_getchunkchar(soap))) && t - tmp < 7);
1402 
1403  while ((int)c != EOF && c != '\n')
1404  c = soap_getchunkchar(soap);
1405 
1406  if ((int)c == EOF)
1407  return soap->ahead = EOF;
1408 
1409  *t = '\0';
1410  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunk size = %s (hex)\n", tmp));
1411  soap->chunksize = soap_strtoul(tmp, &t, 16);
1412 
1413  if (!soap->chunksize)
1414  {
1415  soap->chunkbuflen = 0;
1416  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of chunked message\n"));
1417 
1418  while ((int)c != EOF && c != '\n')
1419  c = soap_getchunkchar(soap);
1420 
1421  ret = 0;
1422  soap->ahead = EOF;
1423  break;
1424  }
1425 
1426  soap->buflen = soap->bufidx + soap->chunksize;
1427  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving buf len to idx=%u len=%u (%s)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen, tmp));
1428 
1429  if (soap->buflen > soap->chunkbuflen)
1430  {
1431  soap->buflen = soap->chunkbuflen;
1432  soap->chunksize -= soap->buflen - soap->bufidx;
1433  soap->chunkbuflen = 0;
1434  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Passed end of buffer for chunked HTTP (%u bytes left)\n", (unsigned int)(soap->buflen - soap->bufidx)));
1435  }
1436  else if (soap->chunkbuflen)
1437  soap->chunksize = 0;
1438 
1439  ret = soap->buflen - soap->bufidx;
1440 
1441  if (ret)
1442  break;
1443  }
1444  }
1445  else
1446 #endif
1447 
1448  {
1449  soap->bufidx = 0;
1450  soap->buflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN);
1451  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket %d\n", (unsigned int)ret, soap->socket));
1452  DBGMSG(RECV, soap->buf, ret);
1453  }
1454 
1455 #ifndef WITH_LEANER
1456 
1457  if (soap->fpreparerecv && (soap->error = soap->fpreparerecv(soap, soap->buf, ret)))
1458  return soap->error;
1459 
1460 #endif
1461 #ifdef WITH_ZLIB
1462 
1463  if (soap->mode & SOAP_ENC_ZLIB)
1464  {
1465  register int r;
1466  memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN);
1467  soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx);
1468  soap->d_stream->avail_in = (unsigned int)ret;
1469  soap->d_stream->next_out = (Byte*)soap->buf;
1470  soap->d_stream->avail_out = SOAP_BUFLEN;
1471  r = inflate(soap->d_stream, Z_NO_FLUSH);
1472 
1473  if (r == Z_OK || r == Z_STREAM_END)
1474  {
1475  soap->bufidx = 0;
1476  soap->z_buflen = soap->buflen;
1477  soap->buflen = SOAP_BUFLEN - soap->d_stream->avail_out;
1478 
1479  if (soap->zlib_in == SOAP_ZLIB_GZIP)
1480  soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen);
1481 
1482  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %u bytes\n", (unsigned int)soap->buflen));
1483 
1484  if (ret && !soap->buflen)
1485  goto zlib_again;
1486 
1487  ret = soap->buflen;
1488 
1489  if (r == Z_STREAM_END)
1490  {
1491  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated total %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out));
1492  soap->z_ratio_in = (float)soap->d_stream->total_in / (float)soap->d_stream->total_out;
1493  soap->d_stream->next_out = Z_NULL;
1494  }
1495 
1496  DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- decompressed ----\n"));
1497  DBGMSG(RECV, soap->buf, ret);
1498  }
1499  else
1500  {
1501  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to inflate: (%d) %s\n", r, soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS));
1502  soap->d_stream->next_out = Z_NULL;
1503  soap->error = SOAP_ZLIB_ERROR;
1504  return EOF;
1505  }
1506  }
1507 
1508 #endif
1509  soap->count += ret;
1510  return !ret;
1511  }
1512 #endif
1513 
1514  /******************************************************************************/
1515 #ifndef PALM_1
1516  SOAP_FMAC1
1517  int
1518  SOAP_FMAC2
1519  soap_recv(struct soap *soap)
1520  {
1521 #ifndef WITH_LEANER
1522 
1523  if (soap->mode & SOAP_ENC_DIME)
1524  {
1525  if (soap->dime.buflen)
1526  {
1527  char *s;
1528  int i;
1529  unsigned char tmp[12];
1530  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME hdr for chunked DIME is in buffer\n"));
1531  soap->count += soap->dime.buflen - soap->buflen;
1532  soap->buflen = soap->dime.buflen;
1533  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Skip padding (%ld bytes)\n", -(long)soap->dime.size&3));
1534 
1535  for (i = -(long)soap->dime.size & 3; i > 0; i--)
1536  {
1537  soap->bufidx++;
1538 
1539  if (soap->bufidx >= soap->buflen)
1540  if (soap_recv_raw(soap))
1541  return EOF;
1542  }
1543 
1544  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME hdr for next chunk\n"));
1545  s = (char*)tmp;
1546 
1547  for (i = 12; i > 0; i--)
1548  {
1549  *s++ = soap->buf[soap->bufidx++];
1550 
1551  if (soap->bufidx >= soap->buflen)
1552  if (soap_recv_raw(soap))
1553  return EOF;
1554  }
1555 
1556  soap->dime.flags = tmp[0] & 0x7;
1557  soap->dime.size = ((size_t)tmp[8] << 24) | ((size_t)tmp[9] << 16) | ((size_t)tmp[10] << 8) | ((size_t)tmp[11]);
1558  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME chunk (%u bytes)\n", (unsigned int)soap->dime.size));
1559 
1560  if (soap->dime.flags & SOAP_DIME_CF)
1561  {
1562  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "More chunking\n"));
1563  soap->dime.chunksize = soap->dime.size;
1564 
1565  if (soap->buflen - soap->bufidx >= soap->dime.size)
1566  {
1567  soap->dime.buflen = soap->buflen;
1568  soap->buflen = soap->bufidx + soap->dime.chunksize;
1569  }
1570  else
1571  soap->dime.chunksize -= soap->buflen - soap->bufidx;
1572  }
1573  else
1574  {
1575  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Last chunk\n"));
1576  soap->dime.buflen = 0;
1577  soap->dime.chunksize = 0;
1578  }
1579 
1580  soap->count = soap->buflen - soap->bufidx;
1581  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%u bytes remaining\n", (unsigned int)soap->count));
1582  return SOAP_OK;
1583  }
1584 
1585  if (soap->dime.chunksize)
1586  {
1587  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get next DIME hdr for chunked DIME (%u bytes chunk)\n", (unsigned int)soap->dime.chunksize));
1588 
1589  if (soap_recv_raw(soap))
1590  return EOF;
1591 
1592  if (soap->buflen - soap->bufidx >= soap->dime.chunksize)
1593  {
1594  soap->dime.buflen = soap->buflen;
1595  soap->count -= soap->buflen - soap->bufidx - soap->dime.chunksize;
1596  soap->buflen = soap->bufidx + soap->dime.chunksize;
1597  }
1598  else
1599  soap->dime.chunksize -= soap->buflen - soap->bufidx;
1600 
1601  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%lu bytes remaining, count=%u\n", (unsigned long)(soap->buflen - soap->bufidx), (unsigned int)soap->count));
1602  return SOAP_OK;
1603  }
1604  }
1605 
1606 #endif
1607  return soap_recv_raw(soap);
1608  }
1609 #endif
1610 
1611  /******************************************************************************/
1612 #ifndef PALM_1
1613  SOAP_FMAC1
1614  soap_wchar
1615  SOAP_FMAC2
1616  soap_getchar(struct soap *soap)
1617  {
1618  register soap_wchar c;
1619  c = soap->ahead;
1620 
1621  if (c)
1622  {
1623  if (c != EOF)
1624  soap->ahead = 0;
1625 
1626  return c;
1627  }
1628 
1629  return soap_get1(soap);
1630  }
1631 #endif
1632 
1633  /******************************************************************************/
1634 #ifndef PALM_1
1635  SOAP_FMAC1
1636  const struct soap_code_map*
1637  SOAP_FMAC2
1638 soap_code(const struct soap_code_map *code_map, const char *str)
1639  {
1640  if (code_map && str)
1641  {
1642  while (code_map->string)
1643  {
1644  if (!strcmp(str, code_map->string)) /* case sensitive */
1645  return code_map;
1646 
1647  code_map++;
1648  }
1649  }
1650 
1651  return NULL;
1652  }
1653 #endif
1654 
1655  /******************************************************************************/
1656 #ifndef PALM_1
1657  SOAP_FMAC1
1658  long
1659  SOAP_FMAC2
1660  soap_code_int(const struct soap_code_map *code_map, const char *str, long other)
1661  {
1662  if (code_map)
1663  {
1664  while (code_map->string)
1665  {
1666  if (!soap_tag_cmp(str, code_map->string)) /* case insensitive */
1667  return code_map->code;
1668 
1669  code_map++;
1670  }
1671  }
1672 
1673  return other;
1674  }
1675 #endif
1676 
1677  /******************************************************************************/
1678 #ifndef PALM_1
1679  SOAP_FMAC1
1680  const char*
1681  SOAP_FMAC2
1682  soap_code_str(const struct soap_code_map *code_map, long code)
1683  {
1684  if (!code_map)
1685  return NULL;
1686 
1687  while (code_map->code != code && code_map->string)
1688  code_map++;
1689 
1690  return code_map->string;
1691  }
1692 #endif
1693 
1694  /******************************************************************************/
1695 #ifndef PALM_1
1696  SOAP_FMAC1
1697  long
1698  SOAP_FMAC2
1699  soap_code_bits(const struct soap_code_map *code_map, const char *str)
1700  {
1701  register long bits = 0;
1702 
1703  if (code_map)
1704  {
1705  while (str && *str)
1706  {
1707  const struct soap_code_map *p;
1708 
1709  for (p = code_map; p->string; p++)
1710  {
1711  register size_t n = strlen(p->string);
1712 
1713  if (!strncmp(p->string, str, n) && soap_blank(str[n]))
1714  {
1715  bits |= p->code;
1716  str += n;
1717 
1718  while (*str > 0 && *str <= 32)
1719  str++;
1720 
1721  break;
1722  }
1723  }
1724 
1725  if (!p->string)
1726  return 0;
1727  }
1728  }
1729 
1730  return bits;
1731  }
1732 #endif
1733 
1734  /******************************************************************************/
1735 #ifndef PALM_1
1736  SOAP_FMAC1
1737  const char*
1738  SOAP_FMAC2
1739  soap_code_list(struct soap *soap, const struct soap_code_map *code_map, long code)
1740  {
1741  register char *t = soap->tmpbuf;
1742 
1743  if (code_map)
1744  {
1745  while (code_map->string)
1746  {
1747  if (code_map->code & code)
1748  {
1749  register const char *s = code_map->string;
1750 
1751  if (t != soap->tmpbuf)
1752  *t++ = ' ';
1753 
1754  while (*s && t < soap->tmpbuf + sizeof(soap->tmpbuf) - 1)
1755  *t++ = *s++;
1756 
1757  if (t == soap->tmpbuf + sizeof(soap->tmpbuf) - 1)
1758  break;
1759  }
1760 
1761  code_map++;
1762  }
1763  }
1764 
1765  *t = '\0';
1766  return soap->tmpbuf;
1767  }
1768 #endif
1769 
1770  /******************************************************************************/
1771 #ifndef PALM_1
1772  static soap_wchar
1773  soap_char(struct soap *soap)
1774  {
1775  char tmp[8];
1776  register int i;
1777  register soap_wchar c;
1778  register char *s = tmp;
1779 
1780  for (i = 0; i < 7; i++)
1781  {
1782  c = soap_get1(soap);
1783 
1784  if (c == ';' || (int)c == EOF)
1785  break;
1786 
1787  *s++ = (char)c;
1788  }
1789 
1790  *s = '\0';
1791 
1792  if (*tmp == '#')
1793  {
1794  if (tmp[1] == 'x' || tmp[1] == 'X')
1795  return soap_strtol(tmp + 2, NULL, 16);
1796 
1797  return atol(tmp + 1);
1798  }
1799 
1800  if (!strcmp(tmp, "lt"))
1801  return '<';
1802 
1803  if (!strcmp(tmp, "gt"))
1804  return '>';
1805 
1806  if (!strcmp(tmp, "amp"))
1807  return '&';
1808 
1809  if (!strcmp(tmp, "quot"))
1810  return '"';
1811 
1812  if (!strcmp(tmp, "apos"))
1813  return '\'';
1814 
1815 #ifndef WITH_LEAN
1816  return (soap_wchar)soap_code_int(html_entity_codes, tmp, SOAP_UNKNOWN_CHAR);
1817 #else
1818  return SOAP_UNKNOWN_CHAR; /* use this to represent unknown code */
1819 #endif
1820  }
1821 #endif
1822 
1823  /******************************************************************************/
1824 #ifdef WITH_LEAN
1825 #ifndef PALM_1
1826  soap_wchar
1827  soap_get0(struct soap *soap)
1828  {
1829  if (soap->bufidx >= soap->buflen && soap_recv(soap))
1830  return EOF;
1831 
1832  return (unsigned char)soap->buf[soap->bufidx];
1833  }
1834 #endif
1835 #endif
1836 
1837  /******************************************************************************/
1838 #ifdef WITH_LEAN
1839 #ifndef PALM_1
1840  soap_wchar
1841  soap_get1(struct soap *soap)
1842  {
1843  if (soap->bufidx >= soap->buflen && soap_recv(soap))
1844  return EOF;
1845 
1846  return (unsigned char)soap->buf[soap->bufidx++];
1847  }
1848 #endif
1849 #endif
1850 
1851  /******************************************************************************/
1852 #ifndef PALM_1
1853  SOAP_FMAC1
1854  soap_wchar
1855  SOAP_FMAC2
1856  soap_get(struct soap *soap)
1857  {
1858  register soap_wchar c;
1859  c = soap->ahead;
1860 
1861  if (c)
1862  {
1863  if ((int)c != EOF)
1864  soap->ahead = 0;
1865  }
1866  else
1867  c = soap_get1(soap);
1868 
1869  while ((int)c != EOF)
1870  {
1871  if (soap->cdata)
1872  {
1873  if (c == ']')
1874  {
1875  c = soap_get1(soap);
1876 
1877  if (c == ']')
1878  {
1879  c = soap_get0(soap);
1880 
1881  if (c == '>')
1882  {
1883  soap->cdata = 0;
1884  soap_get1(soap);
1885  c = soap_get1(soap);
1886  }
1887  else
1888  {
1889  soap_unget(soap, ']');
1890  return ']';
1891  }
1892  }
1893  else
1894  {
1895  soap_revget1(soap);
1896  return ']';
1897  }
1898  }
1899  else
1900  return c;
1901  }
1902 
1903  switch (c)
1904  {
1905  case '<':
1906 
1907  do c = soap_get1(soap);
1908 
1909  while (soap_blank(c));
1910 
1911  if (c == '!' || c == '?' || c == '%')
1912  {
1913  register int k = 1;
1914 
1915  if (c == '!')
1916  {
1917  c = soap_get1(soap);
1918 
1919  if (c == '[')
1920  {
1921  do c = soap_get1(soap);
1922 
1923  while ((int)c != EOF && c != '[');
1924 
1925  if ((int)c == EOF)
1926  break;
1927 
1928  soap->cdata = 1;
1929  c = soap_get1(soap);
1930  continue;
1931  }
1932 
1933  if (c == '-' && (c = soap_get1(soap)) == '-')
1934  {
1935  do
1936  {
1937  c = soap_get1(soap);
1938 
1939  if (c == '-' && (c = soap_get1(soap)) == '-')
1940  break;
1941  }
1942  while ((int)c != EOF);
1943  }
1944  }
1945  else if (c == '?')
1946  c = soap_get_pi(soap);
1947 
1948  while ((int)c != EOF)
1949  {
1950  if (c == '<')
1951  k++;
1952  else if (c == '>')
1953  {
1954  if (--k <= 0)
1955  break;
1956  }
1957 
1958  c = soap_get1(soap);
1959  }
1960 
1961  if ((int)c == EOF)
1962  break;
1963 
1964  c = soap_get1(soap);
1965  continue;
1966  }
1967 
1968  if (c == '/')
1969  return SOAP_TT;
1970 
1971  soap_revget1(soap);
1972  return SOAP_LT;
1973  case '>':
1974  return SOAP_GT;
1975  case '"':
1976  return SOAP_QT;
1977  case '\'':
1978  return SOAP_AP;
1979  case '&':
1980  return soap_char(soap) | 0x80000000;
1981  }
1982 
1983  break;
1984  }
1985 
1986  return c;
1987  }
1988 #endif
1989 
1990  /******************************************************************************/
1991 #ifndef PALM_1
1992  static soap_wchar
1993  soap_get_pi(struct soap *soap)
1994  {
1995  char buf[64];
1996  register char *s = buf;
1997  register int i = sizeof(buf);
1998  register soap_wchar c = soap_getchar(soap);
1999 
2000  /* This is a quick way to parse XML PI and we could use a callback instead to
2001  * enable applications to intercept processing instructions */
2002  while ((int)c != EOF && c != '?')
2003  {
2004  if (--i > 0)
2005  {
2006  if (soap_blank(c))
2007  c = ' ';
2008 
2009  *s++ = (char)c;
2010  }
2011 
2012  c = soap_getchar(soap);
2013  }
2014 
2015  *s = '\0';
2016  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "XML PI <?%s?>\n", buf));
2017 
2018  if (!strncmp(buf, "xml ", 4))
2019  {
2020  s = strstr(buf, " encoding=");
2021 
2022  if (s && s[10])
2023  {
2024  if (!soap_tag_cmp(s + 11, "iso-8859-1*")
2025  || !soap_tag_cmp(s + 11, "latin1*"))
2026  {
2027  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to latin1 encoding\n"));
2028  soap->mode |= SOAP_ENC_LATIN;
2029  }
2030  else if (!soap_tag_cmp(s + 11, "utf-8*"))
2031  {
2032  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to utf-8 encoding\n"));
2033  soap->mode &= ~SOAP_ENC_LATIN;
2034  }
2035  }
2036  }
2037 
2038  if ((int)c != EOF)
2039  c = soap_getchar(soap);
2040 
2041  return c;
2042  }
2043 #endif
2044 
2045  /******************************************************************************/
2046 #ifndef WITH_LEANER
2047 #ifndef PALM_1
2048  SOAP_FMAC1
2049  int
2050  SOAP_FMAC2
2051  soap_move(struct soap *soap, long n)
2052  {
2053  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving %ld bytes forward\n", (long)n));
2054 
2055  for (; n > 0; n--)
2056  if ((int)soap_getchar(soap) == EOF)
2057  return SOAP_EOF;
2058 
2059  return SOAP_OK;
2060  }
2061 #endif
2062 #endif
2063 
2064  /******************************************************************************/
2065 #ifndef WITH_LEANER
2066 #ifndef PALM_1
2067  SOAP_FMAC1
2068  size_t
2069  SOAP_FMAC2
2070  soap_tell(struct soap *soap)
2071  {
2072  return soap->count - soap->buflen + soap->bufidx - (soap->ahead != 0);
2073  }
2074 #endif
2075 #endif
2076 
2077  /******************************************************************************/
2078 #ifndef PALM_1
2079  SOAP_FMAC1
2080  int
2081  SOAP_FMAC2
2082  soap_pututf8(struct soap *soap, register unsigned long c)
2083  {
2084  char tmp[16];
2085 
2086  if (c < 0x80 && c > 0)
2087  {
2088  *tmp = (char)c;
2089  return soap_send_raw(soap, tmp, 1);
2090  }
2091 
2092 #ifndef WITH_LEAN
2093 
2094  if (c >= 0x80)
2095  {
2096  register char *t = tmp;
2097 
2098  if (c < 0x0800)
2099  *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
2100  else
2101  {
2102  if (c < 0x010000)
2103  *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
2104  else
2105  {
2106  if (c < 0x200000)
2107  *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
2108  else
2109  {
2110  if (c < 0x04000000)
2111  *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
2112  else
2113  {
2114  *t++ = (char)(0xFC | ((c >> 30) & 0x01));
2115  *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
2116  }
2117 
2118  *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
2119  }
2120 
2121  *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
2122  }
2123 
2124  *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
2125  }
2126 
2127  *t++ = (char)(0x80 | (c & 0x3F));
2128  *t = '\0';
2129  }
2130 
2131 #else
2132  sprintf(tmp, "&#%lu;", c);
2133 #endif
2134  return soap_send(soap, tmp);
2135  }
2136 #endif
2137 
2138  /******************************************************************************/
2139 #ifndef PALM_1
2140  SOAP_FMAC1
2141  soap_wchar
2142  SOAP_FMAC2
2143  soap_getutf8(struct soap *soap)
2144  {
2145  register soap_wchar c, c1, c2, c3, c4;
2146  c = soap->ahead;
2147 
2148  if (c > 0xFF)
2149  {
2150  soap->ahead = 0;
2151  return c;
2152  }
2153 
2154 again:
2155  c = soap_get(soap);
2156 
2157  if (c < 0x80 || (soap->mode & SOAP_ENC_LATIN))
2158  return c;
2159 
2160  c1 = soap_get1(soap);
2161 
2162  if (c1 < 0x80)
2163  {
2164  soap_revget1(soap); /* doesn't look like this is UTF8 */
2165  return c;
2166  }
2167 
2168  c1 &= 0x3F;
2169 
2170  if (c < 0xE0)
2171  return ((soap_wchar)(c & 0x1F) << 6) | c1;
2172 
2173  c2 = (soap_wchar)soap_get1(soap) & 0x3F;
2174 
2175  if (c == 0xEF && c1 == 0x3B && c2 == 0x3F) /* ignore UTF-8 BOM */
2176  goto again;
2177 
2178  if (c < 0xF0)
2179  return ((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2;
2180 
2181  c3 = (soap_wchar)soap_get1(soap) & 0x3F;
2182 
2183  if (c < 0xF8)
2184  return ((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3;
2185 
2186  c4 = (soap_wchar)soap_get1(soap) & 0x3F;
2187 
2188  if (c < 0xFC)
2189  return ((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4;
2190 
2191  return ((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(soap_get1(soap) & 0x3F);
2192  }
2193 #endif
2194 
2195  /******************************************************************************/
2196 #ifndef PALM_1
2197  SOAP_FMAC1
2198  int
2199  SOAP_FMAC2
2200  soap_puthex(struct soap *soap, const unsigned char *s, int n)
2201  {
2202  char d[2];
2203  register int i;
2204 #ifdef WITH_DOM
2205 
2206  if ((soap->mode & SOAP_XML_DOM) && soap->dom)
2207  {
2208  if (!(soap->dom->data = soap_s2hex(soap, s, NULL, n)))
2209  return soap->error;
2210 
2211  return SOAP_OK;
2212  }
2213 
2214 #endif
2215 
2216  for (i = 0; i < n; i++)
2217  {
2218  register int m = *s++;
2219  d[0] = (char)((m >> 4) + (m > 159 ? '7' : '0'));
2220  m &= 0x0F;
2221  d[1] = (char)(m + (m > 9 ? '7' : '0'));
2222 
2223  if (soap_send_raw(soap, d, 2))
2224  return soap->error;
2225  }
2226 
2227  return SOAP_OK;
2228  }
2229 #endif
2230 
2231  /******************************************************************************/
2232 #ifndef PALM_1
2233  SOAP_FMAC1
2234  unsigned char*
2235  SOAP_FMAC2
2236  soap_gethex(struct soap *soap, int *n)
2237  {
2238 #ifdef WITH_DOM
2239 
2240  if ((soap->mode & SOAP_XML_DOM) && soap->dom)
2241  {
2242  soap->dom->data = soap_string_in(soap, 0, -1, -1);
2243  return (unsigned char*)soap_hex2s(soap, soap->dom->data, NULL, 0, n);
2244  }
2245 
2246 #endif
2247 #ifdef WITH_FAST
2248  soap->labidx = 0;
2249 
2250  for (;;)
2251  {
2252  register char *s;
2253  register size_t i, k;
2254 
2255  if (soap_append_lab(soap, NULL, 0))
2256  return NULL;
2257 
2258  s = soap->labbuf + soap->labidx;
2259  k = soap->lablen - soap->labidx;
2260  soap->labidx = soap->lablen;
2261 
2262  for (i = 0; i < k; i++)
2263  {
2264  register char d1, d2;
2265  register soap_wchar c;
2266  c = soap_get(soap);
2267 
2268  if (soap_isxdigit(c))
2269  {
2270  d1 = (char)c;
2271  c = soap_get(soap);
2272 
2273  if (soap_isxdigit(c))
2274  d2 = (char)c;
2275  else
2276  {
2277  soap->error = SOAP_TYPE;
2278  return NULL;
2279  }
2280  }
2281  else
2282  {
2283  unsigned char *p;
2284  soap_unget(soap, c);
2285 
2286  if (n)
2287  *n = (int)(soap->lablen + i - k);
2288 
2289  p = (unsigned char*)soap_malloc(soap, soap->lablen + i - k);
2290 
2291  if (p)
2292  memcpy(p, soap->labbuf, soap->lablen + i - k);
2293 
2294  return p;
2295  }
2296 
2297  *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0');
2298  }
2299  }
2300 
2301 #else
2302 
2303  if (soap_new_block(soap) == NULL)
2304  return NULL;
2305 
2306  for (;;)
2307  {
2308  register int i;
2309  register char *s = (char*)soap_push_block(soap, NULL, SOAP_BLKLEN);
2310 
2311  if (!s)
2312  {
2313  soap_end_block(soap, NULL);
2314  return NULL;
2315  }
2316 
2317  for (i = 0; i < SOAP_BLKLEN; i++)
2318  {
2319  register char d1, d2;
2320  register soap_wchar c = soap_get(soap);
2321 
2322  if (soap_isxdigit(c))
2323  {
2324  d1 = (char)c;
2325  c = soap_get(soap);
2326 
2327  if (soap_isxdigit(c))
2328  d2 = (char)c;
2329  else
2330  {
2331  soap_end_block(soap, NULL);
2332  soap->error = SOAP_TYPE;
2333  return NULL;
2334  }
2335  }
2336  else
2337  {
2338  unsigned char *p;
2339  soap_unget(soap, c);
2340 
2341  if (n)
2342  *n = (int)soap_size_block(soap, NULL, i);
2343 
2344  p = (unsigned char*)soap_save_block(soap, NULL, 0);
2345  return p;
2346  }
2347 
2348  *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0');
2349  }
2350  }
2351 
2352 #endif
2353  }
2354 #endif
2355 
2356  /******************************************************************************/
2357 #ifndef PALM_1
2358  SOAP_FMAC1
2359  int
2360  SOAP_FMAC2
2361  soap_putbase64(struct soap *soap, const unsigned char *s, int n)
2362  {
2363  register int i;
2364  register unsigned long m;
2365  char d[4];
2366 
2367  if (!s)
2368  return SOAP_OK;
2369 
2370 #ifdef WITH_DOM
2371 
2372  if ((soap->mode & SOAP_XML_DOM) && soap->dom)
2373  {
2374  if (!(soap->dom->data = soap_s2base64(soap, s, NULL, n)))
2375  return soap->error;
2376 
2377  return SOAP_OK;
2378  }
2379 
2380 #endif
2381 
2382  for (; n > 2; n -= 3, s += 3)
2383  {
2384  m = s[0];
2385  m = (m << 8) | s[1];
2386  m = (m << 8) | s[2];
2387 
2388  for (i = 4; i > 0; m >>= 6)
2389  d[--i] = soap_base64o[m & 0x3F];
2390 
2391  if (soap_send_raw(soap, d, 4))
2392  return soap->error;
2393  }
2394 
2395  if (n > 0)
2396  {
2397  m = 0;
2398 
2399  for (i = 0; i < n; i++)
2400  m = (m << 8) | *s++;
2401 
2402  for (; i < 3; i++)
2403  m <<= 8;
2404 
2405  for (i++; i > 0; m >>= 6)
2406  d[--i] = soap_base64o[m & 0x3F];
2407 
2408  for (i = 3; i > n; i--)
2409  d[i] = '=';
2410 
2411  if (soap_send_raw(soap, d, 4))
2412  return soap->error;
2413  }
2414 
2415  return SOAP_OK;
2416  }
2417 #endif
2418 
2419  /******************************************************************************/
2420 #ifndef PALM_1
2421  SOAP_FMAC1
2422  unsigned char*
2423  SOAP_FMAC2
2424  soap_getbase64(struct soap *soap, int *n, int malloc_flag)
2425  {
2426 #ifdef WITH_DOM
2427 
2428  if ((soap->mode & SOAP_XML_DOM) && soap->dom)
2429  {
2430  soap->dom->data = soap_string_in(soap, 0, -1, -1);
2431  return (unsigned char*)soap_base642s(soap, soap->dom->data, NULL, 0, n);
2432  }
2433 
2434 #endif
2435 #ifdef WITH_FAST
2436  soap->labidx = 0;
2437 
2438  for (;;)
2439  {
2440  register size_t i, k;
2441  register char *s;
2442 
2443  if (soap_append_lab(soap, NULL, 2))
2444  return NULL;
2445 
2446  s = soap->labbuf + soap->labidx;
2447  k = soap->lablen - soap->labidx;
2448  soap->labidx = 3 * (soap->lablen / 3);
2449 
2450  if (!s)
2451  return NULL;
2452 
2453  if (k > 2)
2454  {
2455  for (i = 0; i < k - 2; i += 3)
2456  {
2457  register unsigned long m = 0;
2458  register int j = 0;
2459 
2460  do
2461  {
2462  register soap_wchar c = soap_get(soap);
2463 
2464  if (c == '=' || c < 0)
2465  {
2466  unsigned char *p;
2467 
2468  switch (j)
2469  {
2470  case 2:
2471  *s++ = (char)((m >> 4) & 0xFF);
2472  i++;
2473  break;
2474  case 3:
2475  *s++ = (char)((m >> 10) & 0xFF);
2476  *s++ = (char)((m >> 2) & 0xFF);
2477  i += 2;
2478  }
2479 
2480  if (n)
2481  *n = (int)(soap->lablen + i - k);
2482 
2483  p = (unsigned char*)soap_malloc(soap, soap->lablen + i - k);
2484 
2485  if (p)
2486  memcpy(p, soap->labbuf, soap->lablen + i - k);
2487 
2488  if (c >= 0)
2489  {
2490  while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT)
2491  ;
2492  }
2493 
2494  soap_unget(soap, c);
2495  return p;
2496  }
2497 
2498  c -= '+';
2499 
2500  if (c >= 0 && c <= 79)
2501  {
2502  register int b = soap_base64i[c];
2503 
2504  if (b >= 64)
2505  {
2506  soap->error = SOAP_TYPE;
2507  return NULL;
2508  }
2509 
2510  m = (m << 6) + b;
2511  j++;
2512  }
2513  else if (!soap_blank(c + '+'))
2514  {
2515  soap->error = SOAP_TYPE;
2516  return NULL;
2517  }
2518  }
2519  while (j < 4);
2520 
2521  *s++ = (char)((m >> 16) & 0xFF);
2522  *s++ = (char)((m >> 8) & 0xFF);
2523  *s++ = (char)(m & 0xFF);
2524  }
2525  }
2526  }
2527 
2528 #else
2529 
2530  if (soap_new_block(soap) == NULL)
2531  return NULL;
2532 
2533  for (;;)
2534  {
2535  register int i;
2536  register char *s = (char*)soap_push_block(soap, NULL, 3 * SOAP_BLKLEN); /* must be multiple of 3 */
2537 
2538  if (!s)
2539  {
2540  soap_end_block(soap, NULL);
2541  return NULL;
2542  }
2543 
2544  for (i = 0; i < SOAP_BLKLEN; i++)
2545  {
2546  register unsigned long m = 0;
2547  register int j = 0;
2548 
2549  do
2550  {
2551  register soap_wchar c = soap_get(soap);
2552 
2553  if (c == '=' || c < 0)
2554  {
2555  unsigned char *p;
2556  i *= 3;
2557 
2558  switch (j)
2559  {
2560  case 2:
2561  *s++ = (char)((m >> 4) & 0xFF);
2562  i++;
2563  break;
2564  case 3:
2565  *s++ = (char)((m >> 10) & 0xFF);
2566  *s++ = (char)((m >> 2) & 0xFF);
2567  i += 2;
2568  }
2569 
2570  if (n)
2571  *n = (int)soap_size_block(soap, NULL, i);
2572 
2573  p = (unsigned char*)soap_save_block(soap, NULL, 0);
2574 
2575  if (c >= 0)
2576  {
2577  while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT)
2578  ;
2579  }
2580 
2581  soap_unget(soap, c);
2582  return p;
2583  }
2584 
2585  c -= '+';
2586 
2587  if (c >= 0 && c <= 79)
2588  {
2589  int b = soap_base64i[c];
2590 
2591  if (b >= 64)
2592  {
2593  soap->error = SOAP_TYPE;
2594  return NULL;
2595  }
2596 
2597  m = (m << 6) + b;
2598  j++;
2599  }
2600  else if (!soap_blank(c))
2601  {
2602  soap->error = SOAP_TYPE;
2603  return NULL;
2604  }
2605  }
2606  while (j < 4);
2607 
2608  *s++ = (char)((m >> 16) & 0xFF);
2609  *s++ = (char)((m >> 8) & 0xFF);
2610  *s++ = (char)(m & 0xFF);
2611  }
2612  }
2613 
2614 #endif
2615  }
2616 #endif
2617 
2618  /******************************************************************************/
2619 #ifndef WITH_LEANER
2620 #ifndef PALM_1
2621  SOAP_FMAC1
2622  int
2623  SOAP_FMAC2
2624  soap_xop_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options)
2625  {/* Check MTOM xop:Include element (within hex/base64Binary) */
2626  /* TODO: this code to be obsoleted with new import/xop.h conventions */
2627  int body = soap->body; /* should save type too? */
2628 
2629  if (!soap_peek_element(soap))
2630  {
2631  if (!soap_element_begin_in(soap, "xop:Include", 0, NULL) && *soap->href)
2632  {
2633  if (soap_dime_forward(soap, ptr, size, id, type, options))
2634  return soap->error;
2635  }
2636 
2637  if (soap->body && soap_element_end_in(soap, NULL))
2638  return soap->error;
2639  }
2640 
2641  soap->body = body;
2642  return SOAP_OK;
2643  }
2644 #endif
2645 #endif
2646 
2647  /******************************************************************************/
2648 #ifndef WITH_LEANER
2649 #ifndef PALM_1
2650  SOAP_FMAC1
2651  int
2652  SOAP_FMAC2
2653  soap_dime_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options)
2654  {
2655  struct soap_xlist *xp;
2656  *ptr = NULL;
2657  *size = 0;
2658  *id = NULL;
2659  *type = NULL;
2660  *options = NULL;
2661 
2662  if (!*soap->href)
2663  return SOAP_OK;
2664 
2665  *id = soap_strdup(soap, soap->href);
2666  xp = (struct soap_xlist*)SOAP_MALLOC(soap, sizeof(struct soap_xlist));
2667 
2668  if (!xp)
2669  return soap->error = SOAP_EOM;
2670 
2671  xp->next = soap->xlist;
2672  xp->ptr = ptr;
2673  xp->size = size;
2674  xp->id = *id;
2675  xp->type = type;
2676  xp->options = options;
2677  soap->xlist = xp;
2678  return SOAP_OK;
2679  }
2680 #endif
2681 #endif
2682 
2683  /******************************************************************************/
2684 #ifndef PALM_1
2685  SOAP_FMAC1
2686  char *
2687  SOAP_FMAC2
2688  soap_strdup(struct soap *soap, const char *s)
2689  {
2690  char *t = NULL;
2691 
2692  if (s && (t = (char*)soap_malloc(soap, strlen(s) + 1)))
2693  strcpy(t, s);
2694 
2695  return t;
2696  }
2697 #endif
2698 
2699  /******************************************************************************/
2700 #ifndef PALM_1
2701  SOAP_FMAC1
2702  wchar_t *
2703  SOAP_FMAC2
2704  soap_wstrdup(struct soap *soap, const wchar_t *s)
2705  {
2706  wchar_t *t = NULL;
2707 
2708  if (s)
2709  {
2710  size_t n = 0;
2711 
2712  while (s[n])
2713  n++;
2714 
2715  if ((t = (wchar_t*)soap_malloc(soap, sizeof(wchar_t) * (n + 1))))
2716  memcpy(t, s, sizeof(wchar_t) * (n + 1));
2717  }
2718 
2719  return t;
2720  }
2721 #endif
2722 
2723  /******************************************************************************/
2724 #ifndef PALM_1
2725  SOAP_FMAC1
2726  struct soap_blist*
2727  SOAP_FMAC2
2728 soap_new_block(struct soap *soap)
2729  {
2730  struct soap_blist *p;
2731  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New block sequence (prev=%p)\n", soap->blist));
2732 
2733  if (!(p = (struct soap_blist*)SOAP_MALLOC(soap, sizeof(struct soap_blist))))
2734  {
2735  soap->error = SOAP_EOM;
2736  return NULL;
2737  }
2738 
2739  p->next = soap->blist;
2740  p->ptr = NULL;
2741  p->size = 0;
2742  soap->blist = p;
2743  return p;
2744  }
2745 #endif
2746 
2747  /******************************************************************************/
2748 #ifndef PALM_1
2749  SOAP_FMAC1
2750  void*
2751  SOAP_FMAC2
2752  soap_push_block(struct soap *soap, struct soap_blist *b, size_t n)
2753  {
2754  char *p;
2755 
2756  if (!b)
2757  b = soap->blist;
2758 
2759  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push block of %u bytes (%u bytes total)\n", (unsigned int)n, (unsigned int)b->size + (unsigned int)n));
2760 
2761  if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(char*) + sizeof(size_t))))
2762  {
2763  soap->error = SOAP_EOM;
2764  return NULL;
2765  }
2766 
2767  *(char**)p = b->ptr;
2768  *(size_t*)(p + sizeof(char*)) = n;
2769  b->ptr = p;
2770  b->size += n;
2771  return p + sizeof(char*) + sizeof(size_t);
2772  }
2773 #endif
2774 
2775  /******************************************************************************/
2776 #ifndef PALM_1
2777  SOAP_FMAC1
2778  void
2779  SOAP_FMAC2
2780  soap_pop_block(struct soap *soap, struct soap_blist *b)
2781  {
2782  char *p;
2783 
2784  if (!b)
2785  b = soap->blist;
2786 
2787  if (!b->ptr)
2788  return;
2789 
2790  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop block\n"));
2791  p = b->ptr;
2792  b->size -= *(size_t*)(p + sizeof(char*));
2793  b->ptr = *(char**)p;
2794  SOAP_FREE(soap, p);
2795  }
2796 #endif
2797 
2798  /******************************************************************************/
2799 #ifndef WITH_NOIDREF
2800 #ifndef PALM_1
2801  static void
2802  soap_update_ptrs(struct soap *soap, char *start, char *end, char *p1, char *p2)
2803  {
2804  int i;
2805  register struct soap_ilist *ip = NULL;
2806  register struct soap_flist *fp = NULL;
2807 #ifndef WITH_LEANER
2808  register struct soap_xlist *xp = NULL;
2809 #endif
2810  register void *p, **q;
2811 
2812  for (i = 0; i < SOAP_IDHASH; i++)
2813  {
2814  for (ip = soap->iht[i]; ip; ip = ip->next)
2815  {
2816  if (ip->ptr && (char*)ip->ptr >= start && (char*)ip->ptr < end)
2817  {
2818  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", ip->id, ip->ptr, (char*)ip->ptr + (p1 - p2)));
2819  ip->ptr = (char*)ip->ptr + (p1 - p2);
2820  }
2821 
2822  for (q = &ip->link; q; q = (void**)p)
2823  {
2824  p = *q;
2825 
2826  if (p && (char*)p >= start && (char*)p < end)
2827  {
2828  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Link update id='%s' %p\n", ip->id, p));
2829  *q = (char*)p + (p1 - p2);
2830  }
2831  }
2832 
2833  for (q = &ip->copy; q; q = (void**)p)
2834  {
2835  p = *q;
2836 
2837  if (p && (char*)p >= start && (char*)p < end)
2838  {
2839  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy chain update id='%s' %p\n", ip->id, p));
2840  *q = (char*)p + (p1 - p2);
2841  }
2842  }
2843 
2844  for (fp = ip->flist; fp; fp = fp->next)
2845  {
2846  if ((char*)fp->ptr >= start && (char*)fp->ptr < end)
2847  {
2848  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy list update id='%s' %p\n", ip->id, fp));
2849  fp->ptr = (char*)fp->ptr + (p1 - p2);
2850  }
2851  }
2852  }
2853  }
2854 
2855 #ifndef WITH_LEANER
2856 
2857  for (xp = soap->xlist; xp; xp = xp->next)
2858  {
2859  if (xp->ptr && (char*)xp->ptr >= start && (char*)xp->ptr < end)
2860  {
2861  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)));
2862  xp->ptr = (unsigned char**)((char*)xp->ptr + (p1 - p2));
2863  xp->size = (int*)((char*)xp->size + (p1 - p2));
2864  xp->type = (char**)((char*)xp->type + (p1 - p2));
2865  xp->options = (char**)((char*)xp->options + (p1 - p2));
2866  }
2867  }
2868 
2869 #endif
2870  }
2871 #endif
2872 #endif
2873 
2874  /******************************************************************************/
2875 #ifndef WITH_NOIDREF
2876 #ifndef PALM_1
2877  static int
2878  soap_has_copies(struct soap *soap, register const char *start, register const char *end)
2879  {
2880  register int i;
2881  register struct soap_ilist *ip = NULL;
2882  register struct soap_flist *fp = NULL;
2883  register const char *p;
2884 
2885  for (i = 0; i < SOAP_IDHASH; i++)
2886  {
2887  for (ip = soap->iht[i]; ip; ip = ip->next)
2888  {
2889  for (p = (const char*)ip->copy; p; p = *(const char**)p)
2890  if (p >= start && p < end)
2891  return SOAP_ERR;
2892 
2893  for (fp = ip->flist; fp; fp = fp->next)
2894  if ((const char*)fp->ptr >= start && (const char*)fp->ptr < end)
2895  return SOAP_ERR;
2896  }
2897  }
2898 
2899  return SOAP_OK;
2900  }
2901 #endif
2902 #endif
2903 
2904  /******************************************************************************/
2905 #ifndef WITH_NOIDREF
2906 #ifndef PALM_1
2907  SOAP_FMAC1
2908  int
2909  SOAP_FMAC2
2910  soap_resolve(struct soap *soap)
2911  {
2912  register int i;
2913  register struct soap_ilist *ip = NULL;
2914  register struct soap_flist *fp = NULL;
2915  short flag;
2916  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data\n"));
2917 
2918  for (i = 0; i < SOAP_IDHASH; i++)
2919  {
2920  for (ip = soap->iht[i]; ip; ip = ip->next)
2921  {
2922  if (ip->ptr)
2923  {
2924  register void * p, **q, *r;
2925  q = (void**)ip->link;
2926  ip->link = NULL;
2927  r = ip->ptr;
2928 
2929  DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing link chain to resolve id='%s'\n", ip->id));
2930 
2931  while (q)
2932  {
2933  p = *q;
2934  *q = r;
2935  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... link %p -> %p\n", q, r));
2936  q = (void**)p;
2937  }
2938  }
2939  else if (*ip->id == '#')
2940  {
2941  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Missing data for id='%s'\n", ip->id));
2942  strcpy(soap->id, ip->id + 1);
2943  return soap->error = SOAP_MISSING_ID;
2944  }
2945  }
2946  }
2947 
2948  do
2949  {
2950  flag = 0;
2951  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution phase\n"));
2952 
2953  for (i = 0; i < SOAP_IDHASH; i++)
2954  {
2955  for (ip = soap->iht[i]; ip; ip = ip->next)
2956  {
2957  if (ip->ptr && !soap_has_copies(soap, (const char*)ip->ptr, (const char*)ip->ptr + ip->size))
2958  {
2959  if (ip->copy)
2960  {
2961  register void * p, **q = (void**)ip->copy;
2962 
2963  DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing copy chain to resolve id='%s'\n", ip->id));
2964 
2965  ip->copy = NULL;
2966 
2967  do
2968  {
2969  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... copy %p -> %p (%u bytes)\n", ip->ptr, q, (unsigned int)ip->size));
2970  p = *q;
2971  memcpy(q, ip->ptr, ip->size);
2972  q = (void**)p;
2973  }
2974  while (q);
2975 
2976  flag = 1;
2977  }
2978 
2979  for (fp = ip->flist; fp; fp = ip->flist)
2980  {
2981  register unsigned int k = fp->level;
2982  register void *p = ip->ptr;
2983  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));
2984 
2985  while (ip->level < k)
2986  {
2987  register void **q = (void**)soap_malloc(soap, sizeof(void*));
2988 
2989  if (!q)
2990  return soap->error;
2991 
2992  *q = p;
2993  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level, new location=%p holds=%p...\n", q, *q));
2994  p = (void*)q;
2995  k--;
2996  }
2997 
2998  if (fp->fcopy)
2999  fp->fcopy(soap, ip->type, fp->type, fp->ptr, fp->len, p, ip->size);
3000  else
3001  soap_fcopy(soap, ip->type, fp->type, fp->ptr, fp->len, p, ip->size);
3002 
3003  ip->flist = fp->next;
3004  SOAP_FREE(soap, fp);
3005  flag = 1;
3006  }
3007  }
3008  }
3009  }
3010  }
3011  while (flag);
3012 
3013 #ifdef SOAP_DEBUG
3014 
3015  for (i = 0; i < SOAP_IDHASH; i++)
3016  {
3017  for (ip = soap->iht[i]; ip; ip = ip->next)
3018  {
3019  if (ip->copy || ip->flist)
3020  {
3021  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));
3022  }
3023  }
3024  }
3025 
3026 #endif
3027  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution done\n"));
3028  return SOAP_OK;
3029  }
3030 #endif
3031 #endif
3032 
3033  /******************************************************************************/
3034 #ifndef PALM_1
3035  SOAP_FMAC1
3036  size_t
3037  SOAP_FMAC2
3038  soap_size_block(struct soap *soap, struct soap_blist *b, size_t n)
3039  {
3040  if (!b)
3041  b = soap->blist;
3042 
3043  if (b->ptr)
3044  {
3045  b->size -= *(size_t*)(b->ptr + sizeof(char*)) - n;
3046  *(size_t*)(b->ptr + sizeof(char*)) = n;
3047  }
3048 
3049  return b->size;
3050  }
3051 #endif
3052 
3053  /******************************************************************************/
3054 #ifndef PALM_1
3055  SOAP_FMAC1
3056  char*
3057  SOAP_FMAC2
3058  soap_first_block(struct soap *soap, struct soap_blist *b)
3059  {
3060  char *p, *q, *r;
3061 
3062  if (!b)
3063  b = soap->blist;
3064 
3065  p = b->ptr;
3066 
3067  if (!p)
3068  return NULL;
3069 
3070  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "First block\n"));
3071  r = NULL;
3072 
3073  do
3074  {
3075  q = *(char**)p;
3076  *(char**)p = r;
3077  r = p;
3078  p = q;
3079  }
3080  while (p);
3081 
3082  b->ptr = r;
3083  return r + sizeof(char*) + sizeof(size_t);
3084  }
3085 #endif
3086 
3087  /******************************************************************************/
3088 #ifndef PALM_1
3089  SOAP_FMAC1
3090  char*
3091  SOAP_FMAC2
3092  soap_next_block(struct soap *soap, struct soap_blist *b)
3093  {
3094  char *p;
3095 
3096  if (!b)
3097  b = soap->blist;
3098 
3099  p = b->ptr;
3100 
3101  if (p)
3102  {
3103  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Next block\n"));
3104  b->ptr = *(char**)p;
3105  SOAP_FREE(soap, p);
3106 
3107  if (b->ptr)
3108  return b->ptr + sizeof(char*) + sizeof(size_t);
3109  }
3110 
3111  return NULL;
3112  }
3113 #endif
3114 
3115  /******************************************************************************/
3116 #ifndef PALM_1
3117  SOAP_FMAC1
3118  size_t
3119  SOAP_FMAC2
3120  soap_block_size(struct soap *soap, struct soap_blist *b)
3121  {
3122  if (!b)
3123  b = soap->blist;
3124 
3125  return *(size_t*)(b->ptr + sizeof(char*));
3126  }
3127 #endif
3128 
3129  /******************************************************************************/
3130 #ifndef PALM_1
3131  SOAP_FMAC1
3132  void
3133  SOAP_FMAC2
3134  soap_end_block(struct soap *soap, struct soap_blist *b)
3135  {
3136  char *p, *q;
3137 
3138  if (!b)
3139  b = soap->blist;
3140 
3141  if (b)
3142  {
3143  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of block sequence, free all remaining blocks\n"));
3144 
3145  for (p = b->ptr; p; p = q)
3146  {
3147  q = *(char**)p;
3148  SOAP_FREE(soap, p);
3149  }
3150 
3151  if (soap->blist == b)
3152  soap->blist = b->next;
3153  else
3154  {
3155  struct soap_blist *bp;
3156 
3157  for (bp = soap->blist; bp; bp = bp->next)
3158  {
3159  if (bp->next == b)
3160  {
3161  bp->next = b->next;
3162  break;
3163  }
3164  }
3165  }
3166 
3167  SOAP_FREE(soap, b);
3168  }
3169 
3170  DBGLOG(TEST, if (soap->blist) SOAP_MESSAGE(fdebug, "Restore previous block sequence\n"));
3171  }
3172 #endif
3173 
3174  /******************************************************************************/
3175 #ifndef PALM_1
3176  SOAP_FMAC1
3177  char*
3178  SOAP_FMAC2
3179  soap_save_block(struct soap *soap, struct soap_blist *b, char *p, int flag)
3180  {
3181  register size_t n;
3182  register char *q, *s;
3183 
3184  if (!b)
3185  b = soap->blist;
3186 
3187  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));
3188 
3189  if (b->size)
3190  {
3191  if (!p)
3192  p = (char*)soap_malloc(soap, b->size);
3193 
3194  if (p)
3195  {
3196  for (s = p, q = soap_first_block(soap, b); q; q = soap_next_block(soap, b))
3197  {
3198  n = soap_block_size(soap, b);
3199 #ifndef WITH_NOIDREF
3200 
3201  if (flag)
3202  soap_update_ptrs(soap, q, q + n, s, q);
3203 
3204 #endif
3205  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy %u bytes from %p to %p\n", (unsigned int)n, q, s));
3206  memcpy(s, q, n);
3207  s += n;
3208  }
3209  }
3210  else
3211  soap->error = SOAP_EOM;
3212  }
3213 
3214  soap_end_block(soap, b);
3215  return p;
3216  }
3217 #endif
3218 
3219  /******************************************************************************/
3220 #ifndef PALM_2
3221  SOAP_FMAC1
3222  char *
3223  SOAP_FMAC2
3224  soap_putsize(struct soap *soap, const char *type, int size)
3225  {
3226  return soap_putsizes(soap, type, &size, 1);
3227  }
3228 #endif
3229 
3230  /******************************************************************************/
3231 #ifndef PALM_2
3232  SOAP_FMAC1
3233  char *
3234  SOAP_FMAC2
3235  soap_putsizes(struct soap *soap, const char *type, const int *size, int dim)
3236  {
3237  return soap_putsizesoffsets(soap, type, size, NULL, dim);
3238  }
3239 #endif
3240 
3241  /******************************************************************************/
3242 #ifndef PALM_2
3243  SOAP_FMAC1
3244  char *
3245  SOAP_FMAC2
3246  soap_putsizesoffsets(struct soap *soap, const char *type, const int *size, const int *offset, int dim)
3247  {
3248  int i;
3249 
3250  if (!type)
3251  return NULL;
3252 
3253  if (soap->version == 2)
3254  {
3255  sprintf(soap->type, "%s[%d", type, size[0]);
3256 
3257  for (i = 1; i < dim; i++)
3258  sprintf(soap->type + strlen(soap->type), " %d", size[i]);
3259  }
3260  else
3261  {
3262  if (offset)
3263  {
3264  sprintf(soap->type, "%s[%d", type, size[0] + offset[0]);
3265 
3266  for (i = 1; i < dim; i++)
3267  sprintf(soap->type + strlen(soap->type), ",%d", size[i] + offset[i]);
3268  }
3269  else
3270  {
3271  sprintf(soap->type, "%s[%d", type, size[0]);
3272 
3273  for (i = 1; i < dim; i++)
3274  sprintf(soap->type + strlen(soap->type), ",%d", size[i]);
3275  }
3276 
3277  strcat(soap->type, "]");
3278  }
3279 
3280  return soap->type;
3281  }
3282 #endif
3283 
3284  /******************************************************************************/
3285 #ifndef PALM_2
3286  SOAP_FMAC1
3287  char *
3288  SOAP_FMAC2
3289  soap_putoffset(struct soap *soap, int offset)
3290  {
3291  return soap_putoffsets(soap, &offset, 1);
3292  }
3293 #endif
3294 
3295  /******************************************************************************/
3296 #ifndef PALM_2
3297  SOAP_FMAC1
3298  char *
3299  SOAP_FMAC2
3300  soap_putoffsets(struct soap *soap, const int *offset, int dim)
3301  {
3302  register int i;
3303  sprintf(soap->arrayOffset, "[%d", offset[0]);
3304 
3305  for (i = 1; i < dim; i++)
3306  sprintf(soap->arrayOffset + strlen(soap->arrayOffset), ",%d", offset[i]);
3307 
3308  strcat(soap->arrayOffset, "]");
3309  return soap->arrayOffset;
3310  }
3311 #endif
3312 
3313  /******************************************************************************/
3314 #ifndef PALM_2
3315  SOAP_FMAC1
3316  int
3317  SOAP_FMAC2
3318  soap_size(const int *size, int dim)
3319  {
3320  register int i, n = size[0];
3321 
3322  for (i = 1; i < dim; i++)
3323  n *= size[i];
3324 
3325  return n;
3326  }
3327 #endif
3328 
3329  /******************************************************************************/
3330 #ifndef PALM_2
3331  SOAP_FMAC1
3332  int
3333  SOAP_FMAC2
3334  soap_getoffsets(const char *attr, const int *size, int *offset, int dim)
3335  {
3336  register int i, j = 0;
3337 
3338  if (offset)
3339  for (i = 0; i < dim && attr && *attr; i++)
3340  {
3341  attr++;
3342  j *= size[i];
3343  j += offset[i] = (int)atol(attr);
3344  attr = strchr(attr, ',');
3345  }
3346  else
3347  for (i = 0; i < dim && attr && *attr; i++)
3348  {
3349  attr++;
3350  j *= size[i];
3351  j += (int)atol(attr);
3352  attr = strchr(attr, ',');
3353  }
3354 
3355  return j;
3356  }
3357 #endif
3358 
3359  /******************************************************************************/
3360 #ifndef PALM_2
3361  SOAP_FMAC1
3362  int
3363  SOAP_FMAC2
3364  soap_getsize(const char *attr1, const char *attr2, int *j)
3365  {
3366  register int n, k;
3367  char *s;
3368  *j = 0;
3369 
3370  if (!*attr1)
3371  return - 1;
3372 
3373  if (*attr1 == '[')
3374  attr1++;
3375 
3376  n = 1;
3377 
3378  for (;;)
3379  {
3380  k = (int)soap_strtol(attr1, &s, 10);
3381  n *= k;
3382 
3383  if (k < 0 || n > SOAP_MAXARRAYSIZE || s == attr1)
3384  return - 1;
3385 
3386  attr1 = strchr(s, ',');
3387 
3388  if (!attr1)
3389  attr1 = strchr(s, ' ');
3390 
3391  if (attr2 && *attr2)
3392  {
3393  attr2++;
3394  *j *= k;
3395  k = (int)soap_strtol(attr2, &s, 10);
3396  *j += k;
3397 
3398  if (k < 0)
3399  return - 1;
3400 
3401  attr2 = s;
3402  }
3403 
3404  if (!attr1)
3405  break;
3406 
3407  attr1++;
3408  }
3409 
3410  return n - *j;
3411  }
3412 #endif
3413 
3414  /******************************************************************************/
3415 #ifndef PALM_2
3416  SOAP_FMAC1
3417  int
3418  SOAP_FMAC2
3419  soap_getsizes(const char *attr, int *size, int dim)
3420  {
3421  register int i, k, n;
3422 
3423  if (!*attr)
3424  return - 1;
3425 
3426  i = (int)strlen(attr);
3427  n = 1;
3428 
3429  do
3430  {
3431  for (i = i - 1; i >= 0; i--)
3432  if (attr[i] == '[' || attr[i] == ',' || attr[i] == ' ')
3433  break;
3434 
3435  k = (int)atol(attr + i + 1);
3436  n *= size[--dim] = k;
3437 
3438  if (k < 0 || n > SOAP_MAXARRAYSIZE)
3439  return - 1;
3440  }
3441  while (i >= 0 && attr[i] != '[');
3442 
3443  return n;
3444  }
3445 #endif
3446 
3447  /******************************************************************************/
3448 #ifndef PALM_2
3449  SOAP_FMAC1
3450  int
3451  SOAP_FMAC2
3452  soap_getposition(const char *attr, int *pos)
3453  {
3454  register int i, n;
3455 
3456  if (!*attr)
3457  return - 1;
3458 
3459  n = 0;
3460  i = 1;
3461 
3462  do
3463  {
3464  pos[n++] = (int)atol(attr + i);
3465 
3466  while (attr[i] && attr[i] != ',' && attr[i] != ']')
3467  i++;
3468 
3469  if (attr[i] == ',')
3470  i++;
3471  }
3472  while (n < SOAP_MAXDIMS && attr[i] && attr[i] != ']');
3473 
3474  return n;
3475  }
3476 #endif
3477 
3478  /******************************************************************************/
3479 #ifndef PALM_2
3480  SOAP_FMAC1
3481  int
3482  SOAP_FMAC2
3483  soap_push_namespace(struct soap *soap, const char *id, const char *ns)
3484  {
3485  register struct soap_nlist *np;
3486  register struct Namespace *p;
3487  register short i = -1;
3488  register size_t n, k;
3489  n = strlen(id);
3490  k = strlen(ns) + 1;
3491  p = soap->local_namespaces;
3492 
3493  if (p)
3494  {
3495  for (i = 0; p->id; p++, i++)
3496  {
3497  if (p->ns && !strcmp(ns, p->ns))
3498  {
3499  if (p->out)
3500  {
3501  SOAP_FREE(soap, p->out);
3502  p->out = NULL;
3503  }
3504 
3505  break;
3506  }
3507 
3508  if (p->out)
3509  {
3510  if (!strcmp(ns, p->out))
3511  break;
3512  }
3513  else if (p->in)
3514  {
3515  if (!soap_tag_cmp(ns, p->in))
3516  {
3517  if ((p->out = (char*)SOAP_MALLOC(soap, k)))
3518  strcpy(p->out, ns);
3519 
3520  break;
3521  }
3522  }
3523  }
3524 
3525  if (!p || !p->id)
3526  i = -1;
3527  }
3528 
3529  if (i >= 0)
3530  k = 0;
3531 
3532  np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k);
3533 
3534  if (!np)
3535  return soap->error = SOAP_EOM;
3536 
3537  np->next = soap->nlist;
3538  soap->nlist = np;
3539  np->level = soap->level;
3540  np->index = i;
3541  strcpy(np->id, id);
3542  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push namespace binding (level=%u) '%s' '%s'\n", soap->level, id, ns));
3543 
3544  if (i < 0)
3545  {
3546  np->ns = np->id + n + 1;
3547  strcpy(np->ns, ns);
3548  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push NOT OK: no match found for '%s' in namespace mapping table (added to stack anyway)\n", ns));
3549  }
3550  else
3551  {
3552  np->ns = NULL;
3553  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push OK ('%s' matches '%s' in namespace table)\n", id, p->id));
3554  }
3555 
3556  return SOAP_OK;
3557  }
3558 #endif
3559 
3560  /******************************************************************************/
3561 #ifndef PALM_2
3562  SOAP_FMAC1
3563  void
3564  SOAP_FMAC2
3565  soap_pop_namespace(struct soap *soap)
3566  {
3567  register struct soap_nlist *np, *nq;
3568 
3569  for (np = soap->nlist; np && np->level >= soap->level; np = nq)
3570  {
3571  nq = np->next;
3572  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop namespace binding (level=%u) '%s'\n", soap->level, np->id));
3573  SOAP_FREE(soap, np);
3574  }
3575 
3576  soap->nlist = np;
3577  }
3578 #endif
3579 
3580  /******************************************************************************/
3581 #ifndef PALM_2
3582  SOAP_FMAC1
3583  int
3584  SOAP_FMAC2
3585  soap_match_namespace(struct soap *soap, const char *id1, const char *id2, size_t n1, size_t n2)
3586  {
3587  register struct soap_nlist *np = soap->nlist;
3588 
3589  while (np && (strncmp(np->id, id1, n1) || np->id[n1]))
3590  np = np->next;
3591 
3592  if (np)
3593  {
3594  if (np->index < 0
3595  || (soap->local_namespaces[np->index].id
3596  && (strncmp(soap->local_namespaces[np->index].id, id2, n2)
3597  || soap->local_namespaces[np->index].id[n2])))
3598  return SOAP_NAMESPACE;
3599 
3600  return SOAP_OK;
3601  }
3602 
3603  if (n1 == 3 && n1 == n2 && !strncmp(id1, "xml", 3) && !strncmp(id1, id2, 3))
3604  return SOAP_OK;
3605 
3606  return soap->error = SOAP_SYNTAX_ERROR;
3607  }
3608 #endif
3609 
3610  /******************************************************************************/
3611 #ifndef PALM_2
3612  SOAP_FMAC1
3613  const char*
3614  SOAP_FMAC2
3615  soap_current_namespace(struct soap *soap, const char *tag)
3616  {
3617  register struct soap_nlist *np;
3618  register const char *s;
3619 
3620  if (!tag || !strncmp(tag, "xml", 3))
3621  return NULL;
3622 
3623  np = soap->nlist;
3624 
3625  if (!(s = strchr(tag, ':')))
3626  {
3627  while (np && *np->id) /* find default namespace, if present */
3628  np = np->next;
3629  }
3630  else
3631  {
3632  while (np && (strncmp(np->id, tag, s - tag) || np->id[s - tag]))
3633  np = np->next;
3634 
3635  if (!np)
3636  soap->error = SOAP_NAMESPACE;
3637  }
3638 
3639  if (np)
3640  {
3641  if (np->index >= 0)
3642  return soap->namespaces[np->index].ns;
3643 
3644  if (np->ns)
3645  return soap_strdup(soap, np->ns);
3646  }
3647 
3648  return NULL;
3649  }
3650 #endif
3651 
3652  /******************************************************************************/
3653 #ifndef PALM_2
3654  SOAP_FMAC1
3655  int
3656  SOAP_FMAC2
3657  soap_tag_cmp(const char *s, const char *t)
3658  {
3659  for (;;)
3660  {
3661  register int c1 = *s;
3662  register int c2 = *t;
3663 
3664  if (!c1 || c1 == '"')
3665  break;
3666 
3667  if (c2 != '-')
3668  {
3669  if (c1 != c2)
3670  {
3671  if (c1 >= 'A' && c1 <= 'Z')
3672  c1 += 'a' - 'A';
3673 
3674  if (c2 >= 'A' && c2 <= 'Z')
3675  c2 += 'a' - 'A';
3676  }
3677 
3678  if (c1 != c2)
3679  {
3680  if (c2 != '*')
3681  return 1;
3682 
3683  c2 = *++t;
3684 
3685  if (!c2)
3686  return 0;
3687 
3688  if (c2 >= 'A' && c2 <= 'Z')
3689  c2 += 'a' - 'A';
3690 
3691  for (;;)
3692  {
3693  c1 = *s;
3694 
3695  if (!c1 || c1 == '"')
3696  break;
3697 
3698  if (c1 >= 'A' && c1 <= 'Z')
3699  c1 += 'a' - 'A';
3700 
3701  if (c1 == c2 && !soap_tag_cmp(s + 1, t + 1))
3702  return 0;
3703 
3704  s++;
3705  }
3706 
3707  break;
3708  }
3709  }
3710 
3711  s++;
3712  t++;
3713  }
3714 
3715  if (*t == '*' && !t[1])
3716  return 0;
3717 
3718  return *t;
3719  }
3720 #endif
3721 
3722  /******************************************************************************/
3723 #ifndef PALM_2
3724  SOAP_FMAC1
3725  int
3726  SOAP_FMAC2
3727  soap_match_tag(struct soap *soap, const char *tag1, const char *tag2)
3728  {
3729  register const char *s, *t;
3730  register int err;
3731 
3732  if (!tag1 || !tag2 || !*tag2)
3733  return SOAP_OK;
3734 
3735  s = strchr(tag1, ':');
3736  t = strchr(tag2, ':');
3737 
3738  if (t)
3739  {
3740  if (s)
3741  {
3742  if (t[1] && SOAP_STRCMP(s + 1, t + 1))
3743  return SOAP_TAG_MISMATCH;
3744 
3745  if (t != tag2 && (err = soap_match_namespace(soap, tag1, tag2, s - tag1, t - tag2)))
3746  {
3747  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2));
3748 
3749  if (err == SOAP_NAMESPACE)
3750  return SOAP_TAG_MISMATCH;
3751 
3752  return err;
3753  }
3754  }
3755  else if (SOAP_STRCMP(tag1, t + 1))
3756  {
3757  return SOAP_TAG_MISMATCH;
3758  }
3759  else if (t != tag2 && (err = soap_match_namespace(soap, tag1, tag2, 0, t - tag2)))
3760  {
3761  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2));
3762 
3763  if (err == SOAP_NAMESPACE)
3764  return SOAP_TAG_MISMATCH;
3765 
3766  return err;
3767  }
3768 
3769  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags and (default) namespaces match: '%s' '%s'\n", tag1, tag2));
3770  return SOAP_OK;
3771  }
3772 
3773  if (s)
3774  {
3775  if (SOAP_STRCMP(s + 1, tag2))
3776  return SOAP_TAG_MISMATCH;
3777  }
3778  else if (SOAP_STRCMP(tag1, tag2))
3779  return SOAP_TAG_MISMATCH;
3780 
3781  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags match: '%s' '%s'\n", tag1, tag2));
3782  return SOAP_OK;
3783  }
3784 #endif
3785 
3786  /******************************************************************************/
3787 #ifndef PALM_2
3788  SOAP_FMAC1
3789  int
3790  SOAP_FMAC2
3791  soap_match_array(struct soap *soap, const char *type)
3792  {
3793  if (*soap->arrayType)
3794  if (soap_match_tag(soap, soap->arrayType, type)
3795  && soap_match_tag(soap, soap->arrayType, "xsd:anyType")
3796  && soap_match_tag(soap, soap->arrayType, "xsd:ur-type")
3797  )
3798  {
3799  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array type mismatch: '%s' '%s'\n", soap->arrayType, type));
3800  return SOAP_TAG_MISMATCH;
3801  }
3802 
3803  return SOAP_OK;
3804  }
3805 #endif
3806 
3807  /******************************************************************************\
3808  *
3809  * SSL
3810  *
3811  \******************************************************************************/
3812 
3813 #ifdef WITH_OPENSSL
3814  /******************************************************************************/
3815 #ifndef PALM_2
3816  SOAP_FMAC1
3817  int
3818  SOAP_FMAC2
3819  soap_rand()
3820  {
3821  unsigned char buf[4];
3822 
3823  if (!soap_ssl_init_done)
3824  soap_ssl_init();
3825 
3826  RAND_pseudo_bytes(buf, 4);
3827  return *(int*)buf;
3828  }
3829 #endif
3830 
3831  /******************************************************************************/
3832 #ifndef PALM_2
3833  SOAP_FMAC1
3834  int
3835  SOAP_FMAC2
3836  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)
3837  {
3838  int err;
3839  soap->keyfile = keyfile;
3840  soap->password = password;
3841  soap->cafile = cafile;
3842  soap->capath = capath;
3843  soap->dhfile = dhfile;
3844  soap->randfile = randfile;
3845  soap->ssl_flags = flags | (dhfile == NULL ? SOAP_SSL_RSA : 0);
3846 
3847  if (!(err = soap->fsslauth(soap)))
3848  {
3849  if (sid)
3850  SSL_CTX_set_session_id_context(soap->ctx, (unsigned char*)sid, (unsigned int)strlen(sid));
3851  }
3852 
3853  return err;
3854  }
3855 #endif
3856 
3857  /******************************************************************************/
3858 #ifndef PALM_2
3859  SOAP_FMAC1
3860  int
3861  SOAP_FMAC2
3862  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)
3863  {
3864  soap->keyfile = keyfile;
3865  soap->password = password;
3866  soap->cafile = cafile;
3867  soap->capath = capath;
3868  soap->dhfile = NULL;
3869  soap->ssl_flags = flags;
3870  soap->randfile = randfile;
3871  soap->fsslverify = (flags & SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE) == 0 ? ssl_verify_callback : ssl_verify_callback_allow_expired_certificate;
3872  return soap->fsslauth(soap);
3873  }
3874 #endif
3875 
3876  /******************************************************************************/
3877 #ifndef PALM_2
3878  SOAP_FMAC1
3879  void
3880  SOAP_FMAC2
3881  soap_ssl_init()
3882  {/* Note: for MT systems, the main program MUST call soap_ssl_init() before any threads are started */
3883  if (!soap_ssl_init_done)
3884  {
3885  soap_ssl_init_done = 1;
3886  SSL_library_init();
3887 #ifndef WITH_LEAN
3888  SSL_load_error_strings();
3889 #endif
3890 
3891  if (!RAND_load_file("/dev/urandom", 1024))
3892  {
3893  char buf[1024];
3894  RAND_seed(buf, sizeof(buf));
3895 
3896  while (!RAND_status())
3897  {
3898  int r = rand();
3899  RAND_seed(&r, sizeof(int));
3900  }
3901  }
3902  }
3903  }
3904 #endif
3905 
3906  /******************************************************************************/
3907 #ifndef PALM_1
3908  SOAP_FMAC1
3909  const char *
3910  SOAP_FMAC2
3911  soap_ssl_error(struct soap *soap, int ret)
3912  {
3913  int err = SSL_get_error(soap->ssl, ret);
3914  const char *msg = soap_code_str(h_ssl_error_codes, err);
3915 
3916  if (msg)
3917  strcpy(soap->msgbuf, msg);
3918  else
3919  return ERR_error_string(err, soap->msgbuf);
3920 
3921  if (ERR_peek_error())
3922  {
3923  unsigned long r;
3924  strcat(soap->msgbuf, "\n");
3925 
3926  while ((r = ERR_get_error()))
3927  ERR_error_string_n(r, soap->msgbuf + strlen(soap->msgbuf), sizeof(soap->msgbuf) - strlen(soap->msgbuf));
3928  }
3929  else
3930  {
3931  switch (ret)
3932  {
3933  case 0:
3934  strcpy(soap->msgbuf, "EOF was observed that violates the protocol. The client probably provided invalid authentication information.");
3935  break;
3936  case - 1:
3937  sprintf(soap->msgbuf, "Error observed by underlying BIO: %s", strerror(errno));
3938  break;
3939  }
3940  }
3941 
3942  return soap->msgbuf;
3943  }
3944 #endif
3945 
3946  /******************************************************************************/
3947 #ifndef PALM_1
3948  static int
3949  ssl_password(char *buf, int num, int rwflag, void *userdata)
3950  {
3951  if (num < (int)strlen((char*)userdata) + 1)
3952  return 0;
3953 
3954  return (int)strlen(strcpy(buf, (char*)userdata));
3955  }
3956 #endif
3957 
3958  /******************************************************************************/
3959  /* This callback is included for future references. It should not be deleted
3960 #ifndef PALM_2
3961  static DH *
3962  ssl_tmp_dh(SSL *ssl, int is_export, int keylength)
3963  {static DH *dh512 = NULL;
3964  static DH *dh1024 = NULL;
3965  DH *dh;
3966  switch (keylength)
3967  {case 512:
3968  if (!dh512)
3969  {BIO *bio = BIO_new_file("dh512.pem", "r");
3970  if (bio)
3971  {dh512 = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
3972  BIO_free(bio);
3973  return dh512;
3974  }
3975  }
3976  else
3977  return dh512;
3978  default:
3979  if (!dh1024)
3980  {BIO *bio = BIO_new_file("dh1024.pem", "r");
3981  if (bio)
3982  {dh1024 = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
3983  BIO_free(bio);
3984  }
3985  }
3986  dh = dh1024;
3987  }
3988  return dh;
3989  }
3990 #endif
3991  */
3992 
3993  /******************************************************************************/
3994 #ifndef PALM_1
3995  static int
3996  ssl_auth_init(struct soap *soap)
3997  {
3998  long flags;
3999  int mode;
4000 
4001  if (!soap_ssl_init_done)
4002  soap_ssl_init();
4003 
4004  ERR_clear_error();
4005 
4006  if (!soap->ctx)
4007  {
4008  if (!(soap->ctx = SSL_CTX_new(SSLv23_method())))
4009  return soap_set_receiver_error(soap, "SSL error", "Can't setup context", SOAP_SSL_ERROR);
4010 
4011  /* Alters the behavior of SSL read/write:
4012  SSL_CTX_set_mode(soap->ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY);
4013  */
4014  }
4015 
4016  if (soap->randfile)
4017  {
4018  if (!RAND_load_file(soap->randfile, -1))
4019  return soap_set_receiver_error(soap, "SSL error", "Can't load randomness", SOAP_SSL_ERROR);
4020  }
4021 
4022  if (soap->cafile || soap->capath)
4023  {
4024  if (!SSL_CTX_load_verify_locations(soap->ctx, soap->cafile, soap->capath))
4025  return soap_set_receiver_error(soap, "SSL error", "Can't read CA file and directory", SOAP_SSL_ERROR);
4026 
4028  SSL_CTX_set_client_CA_list(soap->ctx, SSL_load_client_CA_file(soap->cafile));
4029  }
4030 
4031  if (!(soap->ssl_flags & SOAP_SSL_NO_DEFAULT_CA_PATH))
4032  {
4033  if (!SSL_CTX_set_default_verify_paths(soap->ctx))
4034  return soap_set_receiver_error(soap, "SSL error", "Can't read default CA file and/or directory", SOAP_SSL_ERROR);
4035  }
4036 
4037  /* This code assumes a typical scenario, see alternative code below */
4038  if (soap->keyfile)
4039  {
4040  if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile))
4041  return soap_set_receiver_error(soap, "SSL error", "Can't read certificate key file", SOAP_SSL_ERROR);
4042 
4043  if (soap->password)
4044  {
4045  SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password);
4046  SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password);
4047  }
4048 
4049  if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM))
4050  return soap_set_receiver_error(soap, "SSL error", "Can't read key file", SOAP_SSL_ERROR);
4051  }
4052 
4053  /* Suggested alternative approach to check the key file for certs (cafile=NULL):
4054  if (soap->password)
4055  {SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password);
4056  SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password);
4057  }
4058  if (!soap->cafile || !SSL_CTX_use_certificate_chain_file(soap->ctx, soap->cafile))
4059  {if (soap->keyfile)
4060  {if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile))
4061  return soap_set_receiver_error(soap, "SSL error", "Can't read certificate or key file", SOAP_SSL_ERROR);
4062  if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM))
4063  return soap_set_receiver_error(soap, "SSL error", "Can't read key file", SOAP_SSL_ERROR);
4064  }
4065  }
4066  */
4067  if ((soap->ssl_flags & SOAP_SSL_RSA))
4068  {
4069  RSA *rsa = RSA_generate_key(1024, RSA_F4, NULL, NULL);
4070 
4071  if (!SSL_CTX_set_tmp_rsa(soap->ctx, rsa))
4072  {
4073  if (rsa)
4074  RSA_free(rsa);
4075 
4076  return soap_set_receiver_error(soap, "SSL error", "Can't set RSA key", SOAP_SSL_ERROR);
4077  }
4078 
4079  RSA_free(rsa);
4080  }
4081  else if (soap->dhfile)
4082  {
4083  DH *dh = 0;
4084  BIO *bio;
4085  bio = BIO_new_file(soap->dhfile, "r");
4086 
4087  if (!bio)
4088  return soap_set_receiver_error(soap, "SSL error", "Can't read DH file", SOAP_SSL_ERROR);
4089 
4090  dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
4091  BIO_free(bio);
4092 
4093  if (SSL_CTX_set_tmp_dh(soap->ctx, dh) < 0)
4094  {
4095  if (dh)
4096  DH_free(dh);
4097 
4098  return soap_set_receiver_error(soap, "SSL error", "Can't set DH parameters", SOAP_SSL_ERROR);
4099  }
4100 
4101  DH_free(dh);
4102  }
4103 
4104  flags = (SSL_OP_ALL | SSL_OP_NO_SSLv2);
4105 
4106  if ((soap->ssl_flags & SOAP_SSLv3))
4107  flags |= SSL_OP_NO_TLSv1;
4108 
4109  if ((soap->ssl_flags & SOAP_TLSv1))
4110  flags |= SSL_OP_NO_SSLv3;
4111 
4112  SSL_CTX_set_options(soap->ctx, flags);
4113 
4115  mode = (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
4117  mode = SSL_VERIFY_PEER;
4118  else
4119  mode = SSL_VERIFY_NONE;
4120 
4121  SSL_CTX_set_verify(soap->ctx, mode, soap->fsslverify);
4122 #if (OPENSSL_VERSION_NUMBER < 0x00905100L)
4123  SSL_CTX_set_verify_depth(soap->ctx, 1);
4124 #else
4125  SSL_CTX_set_verify_depth(soap->ctx, 9);
4126 #endif
4127  return SOAP_OK;
4128  }
4129 #endif
4130 
4131  /******************************************************************************/
4132 #ifndef PALM_1
4133  static int
4134  ssl_verify_callback(int ok, X509_STORE_CTX *store)
4135  {
4136 #ifdef SOAP_DEBUG
4137 
4138  if (!ok)
4139  {
4140  char data[256];
4141  X509 *cert = X509_STORE_CTX_get_current_cert(store);
4142  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)));
4143  X509_NAME_oneline(X509_get_issuer_name(cert), data, sizeof(data));
4144  fprintf(stderr, "certificate issuer %s\n", data);
4145  X509_NAME_oneline(X509_get_subject_name(cert), data, sizeof(data));
4146  fprintf(stderr, "certificate subject %s\n", data);
4147  }
4148 
4149 #endif
4150  /* Note: return 1 to continue, but unsafe progress will be terminated by SSL */
4151  return ok;
4152  }
4153 #endif
4154 
4155  /******************************************************************************/
4156 #ifndef PALM_1
4157  static int
4158  ssl_verify_callback_allow_expired_certificate(int ok, X509_STORE_CTX *store)
4159  {
4160  ok = ssl_verify_callback(ok, store);
4161 
4162  if (ok == 0 && X509_STORE_CTX_get_error(store) == X509_V_ERR_CERT_HAS_EXPIRED)
4163  {
4164 #ifdef SOAP_DEBUG
4165  fprintf(stderr, "ignoring certificate expiration\n");
4166 #endif
4167  X509_STORE_CTX_set_error(store, X509_V_OK);
4168  ok = 1;
4169  }
4170 
4171  /* Note: return 1 to continue, but unsafe progress will be terminated by SSL */
4172  return ok;
4173  }
4174 #endif
4175 
4176  /******************************************************************************/
4177 #ifndef WITH_NOIO
4178 #ifndef PALM_1
4179  SOAP_FMAC1
4180  int
4181  SOAP_FMAC2
4182  soap_ssl_accept(struct soap *soap)
4183  {
4184  BIO *bio;
4185  int retries, r, s;
4186 
4187  if (!soap_valid_socket(soap->socket))
4188  return soap_set_receiver_error(soap, "SSL error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR);
4189 
4190  if (!soap->ctx && (soap->error = soap->fsslauth(soap)))
4191  return SOAP_SSL_ERROR;
4192 
4193  if (!soap->ssl)
4194  {
4195  soap->ssl = SSL_new(soap->ctx);
4196 
4197  if (!soap->ssl)
4198  return soap_set_receiver_error(soap, "SSL error", "SSL_new() failed in soap_ssl_accept()", SOAP_SSL_ERROR);
4199  }
4200  else
4201  SSL_clear(soap->ssl);
4202 
4203  soap->imode |= SOAP_ENC_SSL;
4204  soap->omode |= SOAP_ENC_SSL;
4205  /* Set SSL sockets to non-blocking */
4206  SOAP_SOCKNONBLOCK(soap->socket)
4207  bio = BIO_new_socket((int)soap->socket, BIO_NOCLOSE);
4208  SSL_set_bio(soap->ssl, bio, bio);
4209  retries = 100; /* 10 sec retries, 100 times 0.1 sec */
4210 
4211  while ((r = SSL_accept(soap->ssl)) <= 0)
4212  {
4213  int err = SSL_get_error(soap->ssl, r);
4214 
4215  if (err == SSL_ERROR_WANT_ACCEPT || err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
4216  {
4217  struct timeval timeout;
4218  fd_set fd;
4219 #ifndef WIN32
4220 
4221  if ((int)soap->socket >= (int)FD_SETSIZE)
4222  return SOAP_FD_EXCEEDED; /* Hint: MUST increase FD_SETSIZE */
4223 
4224 #endif
4225  timeout.tv_sec = 0;
4226  timeout.tv_usec = 100000;
4227  FD_ZERO(&fd);
4228  FD_SET(soap->socket, &fd);
4229 
4230  if (err == SSL_ERROR_WANT_READ)
4231  s = select((int)soap->socket + 1, &fd, NULL, &fd, &timeout);
4232  else
4233  s = select((int)soap->socket + 1, NULL, &fd, &fd, &timeout);
4234 
4235  if (s < 0 && (s = soap_socket_errno(soap->socket)) != SOAP_EINTR)
4236  {
4237  soap->errnum = s;
4238  break;
4239  }
4240  }
4241  else
4242  {
4243  soap->errnum = err;
4244  break;
4245  }
4246 
4247  if (retries-- <= 0)
4248  break;
4249  }
4250 
4251  if (r <= 0)
4252  {
4253  soap_set_receiver_error(soap, soap_ssl_error(soap, r), "SSL_accept() failed in soap_ssl_accept()", SOAP_SSL_ERROR);
4254  soap_closesock(soap);
4255  return SOAP_SSL_ERROR;
4256  }
4257 
4259  {
4260  X509 *peer;
4261  int err;
4262 
4263  if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK)
4264  {
4265  soap_closesock(soap);
4266  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);
4267  }
4268 
4269  peer = SSL_get_peer_certificate(soap->ssl);
4270 
4271  if (!peer)
4272  {
4273  soap_closesock(soap);
4274  return soap_set_sender_error(soap, "SSL error", "No SSL certificate was presented by the peer in soap_ssl_accept()", SOAP_SSL_ERROR);
4275  }
4276 
4277  X509_free(peer);
4278  }
4279 
4280  return SOAP_OK;
4281  }
4282 #endif
4283 #endif
4284 
4285  /******************************************************************************/
4286 #endif /* WITH_OPENSSL */
4287 
4288  /******************************************************************************/
4289 #ifndef WITH_NOIO
4290 #ifndef PALM_1
4291  static int
4292  tcp_init(struct soap *soap)
4293  {
4294  soap->errmode = 1;
4295 #ifdef WIN32
4296 
4297  if (tcp_done)
4298  return 0;
4299  else
4300  {
4301  WSADATA w;
4302 
4303  if (WSAStartup(MAKEWORD(1, 1), &w))
4304  return - 1;
4305 
4306  tcp_done = 1;
4307  }
4308 
4309 #endif
4310  return 0;
4311  }
4312 #endif
4313 #endif
4314 
4315  /******************************************************************************/
4316 #ifndef PALM_1
4317  SOAP_FMAC1
4318  void
4319  SOAP_FMAC2
4320  soap_done(struct soap *soap)
4321  {
4322 #ifdef SOAP_DEBUG
4323  int i;
4324 #endif
4325 
4326  if (soap_check_state(soap))
4327  return;
4328 
4329  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Done with context\n"));
4330  soap_free_temp(soap);
4331 
4332  while (soap->clist)
4333  {
4334  struct soap_clist *p = soap->clist->next;
4335  SOAP_FREE(soap, soap->clist);
4336  soap->clist = p;
4337  }
4338 
4339  soap->omode &= ~SOAP_IO_UDP; /* to force close the socket */
4340  soap->keep_alive = 0; /* to force close the socket */
4341  soap_closesock(soap);
4342 #ifdef WITH_COOKIES
4343  soap_free_cookies(soap);
4344 #endif
4345 
4346  while (soap->plugins)
4347  {
4348  register struct soap_plugin *p = soap->plugins->next;
4349  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Removing plugin '%s'\n", soap->plugins->id));
4350 
4351  if (soap->plugins->fcopy || soap->state == SOAP_INIT)
4352  soap->plugins->fdelete(soap, soap->plugins);
4353 
4354  SOAP_FREE(soap, soap->plugins);
4355  soap->plugins = p;
4356  }
4357 
4358  soap->fplugin = fplugin;
4359  soap->fmalloc = NULL;
4360 #ifndef WITH_NOHTTP
4361  soap->fpost = http_post;
4362  soap->fget = http_get;
4363  soap->fput = http_put;
4364  soap->fdel = http_del;
4365  soap->fhead = http_head;
4366  soap->fform = NULL;
4367  soap->fposthdr = http_post_header;
4368  soap->fresponse = http_response;
4369  soap->fparse = http_parse;
4370  soap->fparsehdr = http_parse_header;
4371 #endif
4372  soap->fheader = NULL;
4373 #ifndef WITH_NOIO
4374 #ifndef WITH_IPV6
4375  soap->fresolve = tcp_gethost;
4376 #else
4377  soap->fresolve = NULL;
4378 #endif
4379  soap->faccept = tcp_accept;
4380  soap->fopen = tcp_connect;
4381  soap->fclose = tcp_disconnect;
4382  soap->fclosesocket = tcp_closesocket;
4384  soap->fsend = fsend;
4385  soap->frecv = frecv;
4386  soap->fpoll = soap_poll;
4387 #else
4388  soap->fopen = NULL;
4389  soap->fclose = NULL;
4390  soap->fpoll = NULL;
4391 #endif
4392 #ifndef WITH_LEANER
4393  soap->fprepareinit = NULL;
4394  soap->fpreparesend = NULL;
4395  soap->fpreparerecv = NULL;
4396  soap->fpreparefinal = NULL;
4397 #endif
4398  soap->fseterror = NULL;
4399  soap->fignore = NULL;
4400  soap->fserveloop = NULL;
4401 #ifdef WITH_OPENSSL
4402 
4403  if (soap->session)
4404  {
4405  SSL_SESSION_free(soap->session);
4406  soap->session = NULL;
4407  }
4408 
4409 #endif
4410 
4411  if (soap->state == SOAP_INIT)
4412  {
4413  if (soap_valid_socket(soap->master))
4414  {
4415  soap->fclosesocket(soap, soap->master);
4416  soap->master = SOAP_INVALID_SOCKET;
4417  }
4418  }
4419 
4420 #ifdef WITH_OPENSSL
4421 
4422  if (soap->ssl)
4423  {
4424  SSL_free(soap->ssl);
4425  soap->ssl = NULL;
4426  }
4427 
4428  if (soap->state == SOAP_INIT)
4429  {
4430  if (soap->ctx)
4431  {
4432  SSL_CTX_free(soap->ctx);
4433  soap->ctx = NULL;
4434  }
4435  }
4436 
4437 #endif
4438 #ifdef WITH_OPENSSL
4439  ERR_remove_state(0);
4440 #endif
4441 #ifdef WITH_C_LOCALE
4442  freelocale(soap->c_locale);
4443 #endif
4444 #ifdef WITH_ZLIB
4445 
4446  if (soap->d_stream)
4447  {
4448  SOAP_FREE(soap, (void*)soap->d_stream);
4449  soap->d_stream = NULL;
4450  }
4451 
4452  if (soap->z_buf)
4453  {
4454  SOAP_FREE(soap, (void*)soap->z_buf);
4455  soap->z_buf = NULL;
4456  }
4457 
4458 #endif
4459 #ifdef SOAP_DEBUG
4460  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free logfiles\n"));
4461 
4462  for (i = 0; i < SOAP_MAXLOGS; i++)
4463  {
4464  if (soap->logfile[i])
4465  {
4466  SOAP_FREE(soap, (void*)soap->logfile[i]);
4467  soap->logfile[i] = NULL;
4468  }
4469 
4470  soap_close_logfile(soap, i);
4471  }
4472 
4473  soap->state = SOAP_NONE;
4474 #endif
4475 #ifdef SOAP_MEM_DEBUG
4476  soap_free_mht(soap);
4477 #endif
4478  }
4479 #endif
4480 
4481  /******************************************************************************/
4482 #ifndef WITH_NOIO
4483 #ifndef PALM_2
4484  SOAP_FMAC1
4485  void
4486  SOAP_FMAC2
4487  soap_cleanup(struct soap *soap)
4488  {
4489  soap_done(soap);
4490 #ifdef WIN32
4491 
4492  if (!tcp_done)
4493  return;
4494 
4495  tcp_done = 0;
4496  WSACleanup();
4497 #endif
4498  }
4499 #endif
4500 #endif
4501 
4502  /******************************************************************************/
4503 #ifndef WITH_NOIO
4504 #ifndef PALM_1
4505  static const char*
4506  tcp_error(struct soap *soap)
4507  {
4508  register const char *msg = NULL;
4509 
4510  switch (soap->errmode)
4511  {
4512  case 0:
4513  msg = soap_strerror(soap);
4514  break;
4515  case 1:
4516  msg = "WSAStartup failed";
4517  break;
4518  case 2:
4519  {
4520 #ifndef WITH_LEAN
4521  msg = soap_code_str(h_error_codes, soap->errnum);
4522 
4523  if (!msg)
4524 #endif
4525  {sprintf(soap->msgbuf, "TCP/UDP IP error %d", soap->errnum);
4526  msg = soap->msgbuf;
4527  }
4528  }
4529  }
4530 
4531  return msg;
4532  }
4533 #endif
4534 #endif
4535 
4536  /******************************************************************************/
4537 #ifndef WITH_NOHTTP
4538 #ifndef PALM_1
4539  static const char*
4540  http_error(struct soap *soap, int status)
4541  {
4542  register const char *msg = SOAP_STR_EOS;
4543 #ifndef WITH_LEAN
4544  msg = soap_code_str(h_http_error_codes, status);
4545 
4546  if (!msg)
4547  msg = SOAP_STR_EOS;
4548 
4549 #endif
4550  return msg;
4551  }
4552 #endif
4553 #endif
4554 
4555  /******************************************************************************/
4556 #ifndef WITH_IPV6
4557 #ifndef WITH_NOIO
4558 #ifndef PALM_1
4559  static int
4560  tcp_gethost(struct soap *soap, const char *addr, struct in_addr *inaddr)
4561  {
4562  soap_int32 iadd = -1;
4563  struct hostent hostent, *host = &hostent;
4564 #ifdef VXWORKS
4565  int hostint;
4566  /* inet_addr(), and hostGetByName() expect "char *"; addr is a "const char *". */
4567  iadd = inet_addr((char*)addr);
4568 #else
4569 #if defined(_AIX43) || ((defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R))
4570  struct hostent_data ht_data;
4571 #endif
4572 #ifdef AS400
4573  iadd = inet_addr((void*)addr);
4574 #else
4575  iadd = inet_addr(addr);
4576 #endif
4577 #endif
4578 
4579  if (iadd != -1)
4580  {
4581  memcpy(inaddr, &iadd, sizeof(iadd));
4582  return SOAP_OK;
4583  }
4584 
4585 #if defined(__GLIBC__) || (defined(HAVE_GETHOSTBYNAME_R) && (defined(FREEBSD) || defined(__FreeBSD__)))
4586 
4587  if (gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &host, &soap->errnum) < 0)
4588  host = NULL;
4589 
4590 #elif defined(_AIX43) || ((defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R))
4591  memset((void*)&ht_data, 0, sizeof(ht_data));
4592 
4593  if (gethostbyname_r(addr, &hostent, &ht_data) < 0)
4594  {
4595  host = NULL;
4596  soap->errnum = h_errno;
4597  }
4598 
4599 #elif defined(HAVE_GETHOSTBYNAME_R)
4600  host = gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &soap->errnum);
4601 #elif defined(VXWORKS)
4602  /* If the DNS resolver library resolvLib has been configured in the vxWorks
4603  * image, a query for the host IP address is sent to the DNS server, if the
4604  * name was not found in the local host table. */
4605  hostint = hostGetByName((char*)addr);
4606 
4607  if (hostint == ERROR)
4608  {
4609  host = NULL;
4610  soap->errnum = soap_errno;
4611  }
4612 
4613 #else
4614 #ifdef AS400
4615 
4616  if (!(host = gethostbyname((void*)addr)))
4617  soap->errnum = h_errno;
4618 
4619 #else
4620 
4621  if (!(host = gethostbyname(addr)))
4622  soap->errnum = h_errno;
4623 
4624 #endif
4625 #endif
4626 
4627  if (!host)
4628  {
4629  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Host name not found\n"));
4630  return SOAP_ERR;
4631  }
4632 
4633 #ifdef VXWORKS
4634  inaddr->s_addr = hostint;
4635 #else
4636  memcpy(inaddr, host->h_addr, host->h_length);
4637 #endif
4638  return SOAP_OK;
4639  }
4640 #endif
4641 #endif
4642 #endif
4643 
4644  /******************************************************************************/
4645 #ifndef WITH_NOIO
4646 #ifndef PALM_1
4647  static SOAP_SOCKET
4648  tcp_connect(struct soap *soap, const char *endpoint, const char *host, int port)
4649  {
4650 #ifdef WITH_IPV6
4651  struct addrinfo hints, *res, *ressave;
4652 #endif
4653  SOAP_SOCKET fd;
4654  int err = 0;
4655 #ifndef WITH_LEAN
4656  int retry = 10;
4657  int len = SOAP_BUFLEN;
4658  int set = 1;
4659 #endif
4660 
4661  if (soap_valid_socket(soap->socket))
4662  soap->fclosesocket(soap, soap->socket);
4663 
4664  soap->socket = SOAP_INVALID_SOCKET;
4665 
4666  if (tcp_init(soap))
4667  {
4668  soap->errnum = 0;
4669  soap_set_sender_error(soap, tcp_error(soap), "TCP init failed in tcp_connect()", SOAP_TCP_ERROR);
4670  return SOAP_INVALID_SOCKET;
4671  }
4672 
4673  soap->errmode = 0;
4674 #ifdef WITH_IPV6
4675  memset((void*)&hints, 0, sizeof(hints));
4676  hints.ai_family = PF_UNSPEC;
4677 #ifndef WITH_LEAN
4678 
4679  if ((soap->omode & SOAP_IO_UDP))
4680  hints.ai_socktype = SOCK_DGRAM;
4681  else
4682 #endif
4683  hints.ai_socktype = SOCK_STREAM;
4684 
4685  soap->errmode = 2;
4686 
4687  if (soap->proxy_host)
4688  err = getaddrinfo(soap->proxy_host, soap_int2s(soap, soap->proxy_port), &hints, &res);
4689  else
4690  err = getaddrinfo(host, soap_int2s(soap, port), &hints, &res);
4691 
4692  if (err)
4693  {
4694  soap_set_sender_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in tcp_connect()", SOAP_TCP_ERROR);
4695  return SOAP_INVALID_SOCKET;
4696  }
4697 
4698  ressave = res;
4699 again:
4700  fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
4701  soap->errmode = 0;
4702 #else
4703 #ifndef WITH_LEAN
4704 again:
4705 #endif
4706 #ifndef WITH_LEAN
4707 
4708  if ((soap->omode & SOAP_IO_UDP))
4709  fd = socket(AF_INET, SOCK_DGRAM, 0);
4710  else
4711 #endif
4712  fd = socket(AF_INET, SOCK_STREAM, 0);
4713 
4714 #endif
4715 
4716  if (!soap_valid_socket(fd))
4717  {
4718 #ifdef WITH_IPV6
4719 
4720  if (res->ai_next)
4721  {
4722  res = res->ai_next;
4723  goto again;
4724  }
4725 
4726 #endif
4727  soap->errnum = soap_socket_errno(fd);
4728  soap_set_sender_error(soap, tcp_error(soap), "socket failed in tcp_connect()", SOAP_TCP_ERROR);
4729 #ifdef WITH_IPV6
4730  freeaddrinfo(ressave);
4731 #endif
4732  return SOAP_INVALID_SOCKET;
4733  }
4734 
4735 #ifdef SOCKET_CLOSE_ON_EXEC
4736 #ifdef WIN32
4737 #ifndef UNDER_CE
4738  SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0);
4739 #endif
4740 #else
4741  fcntl(fd, F_SETFD, 1);
4742 #endif
4743 #endif
4744 #ifndef WITH_LEAN
4745 
4746  if (soap->connect_flags == SO_LINGER)
4747  {
4748  struct linger linger;
4749  memset((void*)&linger, 0, sizeof(linger));
4750  linger.l_onoff = 1;
4751  linger.l_linger = soap->linger_time;
4752 
4753  if (setsockopt(fd, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger)))
4754  {
4755  soap->errnum = soap_socket_errno(fd);
4756  soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in tcp_connect()", SOAP_TCP_ERROR);
4757  soap->fclosesocket(soap, fd);
4758 #ifdef WITH_IPV6
4759  freeaddrinfo(ressave);
4760 #endif
4761  return SOAP_INVALID_SOCKET;
4762  }
4763  }
4764  else if (soap->connect_flags && setsockopt(fd, SOL_SOCKET, soap->connect_flags, (char*)&set, sizeof(int)))
4765  {
4766  soap->errnum = soap_socket_errno(fd);
4767  soap_set_sender_error(soap, tcp_error(soap), "setsockopt failed in tcp_connect()", SOAP_TCP_ERROR);
4768  soap->fclosesocket(soap, fd);
4769 #ifdef WITH_IPV6
4770  freeaddrinfo(ressave);
4771 #endif
4772  return SOAP_INVALID_SOCKET;
4773  }
4774 
4775  if ((soap->keep_alive || soap->tcp_keep_alive) && setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
4776  {
4777  soap->errnum = soap_socket_errno(fd);
4778  soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in tcp_connect()", SOAP_TCP_ERROR);
4779  soap->fclosesocket(soap, fd);
4780 #ifdef WITH_IPV6
4781  freeaddrinfo(ressave);
4782 #endif
4783  return SOAP_INVALID_SOCKET;
4784  }
4785 
4786  if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
4787  {
4788  soap->errnum = soap_socket_errno(fd);
4789  soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in tcp_connect()", SOAP_TCP_ERROR);
4790  soap->fclosesocket(soap, fd);
4791 #ifdef WITH_IPV6
4792  freeaddrinfo(ressave);
4793 #endif
4794  return SOAP_INVALID_SOCKET;
4795  }
4796 
4797  if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
4798  {
4799  soap->errnum = soap_socket_errno(fd);
4800  soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in tcp_connect()", SOAP_TCP_ERROR);
4801  soap->fclosesocket(soap, fd);
4802 #ifdef WITH_IPV6
4803  freeaddrinfo(ressave);
4804 #endif
4805  return SOAP_INVALID_SOCKET;
4806  }
4807 
4808 #ifdef TCP_KEEPIDLE
4809 
4810  if (soap->tcp_keep_idle && setsockopt((SOAP_SOCKET)fd, IPPROTO_TCP, TCP_KEEPIDLE, (char*)&(soap->tcp_keep_idle), sizeof(int)))
4811  {
4812  soap->errnum = soap_socket_errno(fd);
4813  soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPIDLE failed in tcp_connect()", SOAP_TCP_ERROR);
4814  soap->fclosesocket(soap, (SOAP_SOCKET)fd);
4815 #ifdef WITH_IPV6
4816  freeaddrinfo(ressave);
4817 #endif
4818  return SOAP_INVALID_SOCKET;
4819  }
4820 
4821 #endif
4822 #ifdef TCP_KEEPINTVL
4823 
4824  if (soap->tcp_keep_intvl && setsockopt((SOAP_SOCKET)fd, IPPROTO_TCP, TCP_KEEPINTVL, (char*)&(soap->tcp_keep_intvl), sizeof(int)))
4825  {
4826  soap->errnum = soap_socket_errno(fd);
4827  soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPINTVL failed in tcp_connect()", SOAP_TCP_ERROR);
4828  soap->fclosesocket(soap, (SOAP_SOCKET)fd);
4829 #ifdef WITH_IPV6
4830  freeaddrinfo(ressave);
4831 #endif
4832  return SOAP_INVALID_SOCKET;
4833  }
4834 
4835 #endif
4836 #ifdef TCP_KEEPCNT
4837 
4838  if (soap->tcp_keep_cnt && setsockopt((SOAP_SOCKET)fd, IPPROTO_TCP, TCP_KEEPCNT, (char*)&(soap->tcp_keep_cnt), sizeof(int)))
4839  {
4840  soap->errnum = soap_socket_errno(fd);
4841  soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPCNT failed in tcp_connect()", SOAP_TCP_ERROR);
4842  soap->fclosesocket(soap, (SOAP_SOCKET)fd);
4843 #ifdef WITH_IPV6
4844  freeaddrinfo(ressave);
4845 #endif
4846  return SOAP_INVALID_SOCKET;
4847  }
4848 
4849 #endif
4850 #ifdef TCP_NODELAY
4851 
4852  if (!(soap->omode & SOAP_IO_UDP) && setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
4853  {
4854  soap->errnum = soap_socket_errno(fd);
4855  soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in tcp_connect()", SOAP_TCP_ERROR);
4856  soap->fclosesocket(soap, fd);
4857 #ifdef WITH_IPV6
4858  freeaddrinfo(ressave);
4859 #endif
4860  return SOAP_INVALID_SOCKET;
4861  }
4862 
4863 #endif
4864 #ifdef WITH_IPV6
4865 
4866  if ((soap->omode & SOAP_IO_UDP) && soap->ipv6_multicast_if)
4867  {
4868  struct sockaddr_in6 *in6addr = (struct sockaddr_in6*)res->ai_addr;
4869  in6addr->sin6_scope_id = soap->ipv6_multicast_if;
4870  }
4871 
4872 #elif defined(IP_MULTICAST_TTL)
4873 
4874  if ((soap->omode & SOAP_IO_UDP) && soap->ipv4_multicast_if)
4875  {
4876  if (soap->ipv4_multicast_ttl > 0)
4877  {
4878  char ttl = (char)(soap->ipv4_multicast_ttl);
4879 
4880  if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ttl, sizeof(ttl)))
4881  {
4882  soap->errnum = soap_socket_errno(fd);
4883  soap_set_sender_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_TTL failed in tcp_connect()", SOAP_TCP_ERROR);
4884  soap->fclosesocket(soap, fd);
4885  return SOAP_INVALID_SOCKET;
4886  }
4887  }
4888 
4889 #ifndef WINDOWS
4890 
4891  if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, (char*)soap->ipv4_multicast_if, sizeof(struct in_addr)))
4892  {
4893  soap->errnum = soap_socket_errno(fd);
4894  soap_set_sender_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR);
4895  soap->fclosesocket(soap, fd);
4896  return SOAP_INVALID_SOCKET;
4897  }
4898 
4899 #else
4900 #ifndef IP_MULTICAST_IF
4901 #define IP_MULTICAST_IF 2
4902 #endif
4903 
4904  if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, (char*)soap->ipv4_multicast_if, sizeof(struct in_addr)))
4905  {
4906  soap->errnum = soap_socket_errno(fd);
4907  soap_set_sender_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR);
4908  soap->fclosesocket(soap, fd);
4909  return SOAP_INVALID_SOCKET;
4910  }
4911 
4912 #endif
4913  }
4914 
4915 #endif
4916 #endif
4917  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Opening socket %d to host='%s' port=%d\n", fd, host, port));
4918 #ifndef WITH_IPV6
4919  soap->peerlen = sizeof(soap->peer);
4920  memset((void*)&soap->peer, 0, sizeof(soap->peer));
4921  soap->peer.sin_family = AF_INET;
4922  soap->errmode = 2;
4923 
4924  if (soap->proxy_host)
4925  {
4926  if (soap->fresolve(soap, soap->proxy_host, &soap->peer.sin_addr))
4927  {
4928  soap_set_sender_error(soap, tcp_error(soap), "get proxy host by name failed in tcp_connect()", SOAP_TCP_ERROR);
4929  soap->fclosesocket(soap, fd);
4930 #ifdef WITH_IPV6
4931  freeaddrinfo(ressave);
4932 #endif
4933  return SOAP_INVALID_SOCKET;
4934  }
4935 
4936  soap->peer.sin_port = htons((short)soap->proxy_port);
4937  }
4938  else
4939  {
4940  if (soap->fresolve(soap, host, &soap->peer.sin_addr))
4941  {
4942  soap_set_sender_error(soap, tcp_error(soap), "get host by name failed in tcp_connect()", SOAP_TCP_ERROR);
4943  soap->fclosesocket(soap, fd);
4944 #ifdef WITH_IPV6
4945  freeaddrinfo(ressave);
4946 #endif
4947  return SOAP_INVALID_SOCKET;
4948  }
4949 
4950  soap->peer.sin_port = htons((short)port);
4951  }
4952 
4953  soap->errmode = 0;
4954 #ifndef WITH_LEAN
4955 
4956  if ((soap->omode & SOAP_IO_UDP))
4957  {
4958 #ifdef WITH_IPV6
4959  freeaddrinfo(ressave);
4960 #endif
4961  return fd;
4962  }
4963 
4964 #endif
4965 #endif
4966 #ifndef WITH_LEAN
4967 
4968  if (soap->connect_timeout)
4969  SOAP_SOCKNONBLOCK(fd)
4970  else
4971  SOAP_SOCKBLOCK(fd)
4972 #endif
4973  for (;;)
4974  {
4975 #ifdef WITH_IPV6
4976 
4977  if (connect(fd, res->ai_addr, (int)res->ai_addrlen))
4978 #else
4979  if (connect(fd, (struct sockaddr*)&soap->peer, sizeof(soap->peer)))
4980 #endif
4981 
4982  {
4983  err = soap_socket_errno(fd);
4984 #ifndef WITH_LEAN
4985 
4986  if (err == SOAP_EADDRINUSE)
4987  {
4988  soap->fclosesocket(soap, fd);
4989 
4990  if (retry-- > 0)
4991  goto again;
4992  }
4993  else if (soap->connect_timeout && (err == SOAP_EINPROGRESS || err == SOAP_EAGAIN || err == SOAP_EWOULDBLOCK))
4994  {
4995  SOAP_SOCKLEN_T k;
4996 #ifndef WIN32
4997 
4998  if ((int)fd >= (int)FD_SETSIZE)
4999  {
5000  soap->error = SOAP_FD_EXCEEDED;
5001 #ifdef WITH_IPV6
5002  freeaddrinfo(ressave);
5003 #endif
5004  return SOAP_INVALID_SOCKET; /* Hint: MUST increase FD_SETSIZE */
5005  }
5006 
5007 #endif
5008 
5009  for (;;)
5010  {
5011  struct timeval timeout;
5012  fd_set fds;
5013  register int r;
5014 
5015  if (soap->connect_timeout > 0)
5016  {
5017  timeout.tv_sec = soap->connect_timeout;
5018  timeout.tv_usec = 0;
5019  }
5020  else
5021  {
5022  timeout.tv_sec = -soap->connect_timeout / 1000000;
5023  timeout.tv_usec = -soap->connect_timeout % 1000000;
5024  }
5025 
5026  FD_ZERO(&fds);
5027  FD_SET(fd, &fds);
5028  r = select((int)fd + 1, NULL, &fds, NULL, &timeout);
5029 
5030  if (r > 0)
5031  break;
5032 
5033  if (!r)
5034  {
5035  soap->errnum = 0;
5036  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n"));
5037  soap_set_sender_error(soap, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR);
5038  soap->fclosesocket(soap, fd);
5039 #ifdef WITH_IPV6
5040  freeaddrinfo(ressave);
5041 #endif
5042  return SOAP_INVALID_SOCKET;
5043  }
5044 
5045  r = soap_socket_errno(fd);
5046 
5047  if (r != SOAP_EINTR)
5048  {
5049  soap->errnum = r;
5050  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
5051  soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
5052  soap->fclosesocket(soap, fd);
5053 #ifdef WITH_IPV6
5054  freeaddrinfo(ressave);
5055 #endif
5056  return SOAP_INVALID_SOCKET;
5057  }
5058  }
5059 
5060  k = (SOAP_SOCKLEN_T)sizeof(soap->errnum);
5061 
5062  if (!getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*)&soap->errnum, &k) && !soap->errnum) /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
5063  break;
5064 
5065  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
5066 
5067  if (!soap->errnum)
5068  soap->errnum = soap_socket_errno(fd);
5069 
5070  soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
5071  soap->fclosesocket(soap, fd);
5072 #ifdef WITH_IPV6
5073  freeaddrinfo(ressave);
5074 #endif
5075  return SOAP_INVALID_SOCKET;
5076  }
5077 
5078 #endif
5079 #ifdef WITH_IPV6
5080 
5081  if (res->ai_next)
5082  {
5083  res = res->ai_next;
5084  soap->fclosesocket(soap, fd);
5085  goto again;
5086  }
5087 
5088 #endif
5089 
5090  if (err && err != SOAP_EINTR)
5091  {
5092  soap->errnum = err;
5093  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
5094  soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
5095  soap->fclosesocket(soap, fd);
5096 #ifdef WITH_IPV6
5097  freeaddrinfo(ressave);
5098 #endif
5099  return SOAP_INVALID_SOCKET;
5100  }
5101  }
5102  else
5103  break;
5104  }
5105 
5106 #ifdef WITH_IPV6
5107  soap->peerlen = 0; /* IPv6: already connected so use send() */
5108  freeaddrinfo(ressave);
5109 #endif
5110 #ifndef WITH_LEAN
5111 
5112  if (soap->recv_timeout || soap->send_timeout)
5113  SOAP_SOCKNONBLOCK(fd)
5114  else
5115  SOAP_SOCKBLOCK(fd)
5116 #endif
5117  soap->socket = fd;
5118 
5119  soap->imode &= ~SOAP_ENC_SSL;
5120  soap->omode &= ~SOAP_ENC_SSL;
5121 
5122  if (!soap_tag_cmp(endpoint, "https:*"))
5123  {
5124 #ifdef WITH_OPENSSL
5125  BIO *bio;
5126  int r;
5127 
5128  if (soap->proxy_host)
5129  {
5130  soap_mode m = soap->omode; /* make sure we only parse HTTP */
5131  size_t n = soap->count; /* save the content length */
5132  char *userid, *passwd;
5133  soap->omode &= ~SOAP_ENC; /* mask IO and ENC */
5134  soap->omode |= SOAP_IO_BUFFER;
5135  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connecting to %s proxy server\n", soap->proxy_http_version));
5136  sprintf(soap->tmpbuf, "CONNECT %s:%d HTTP/%s", host, port, soap->proxy_http_version);
5137 
5138  if (soap_begin_send(soap)
5139  || (soap->error = soap->fposthdr(soap, soap->tmpbuf, NULL)))
5140  {
5141  soap->fclosesocket(soap, fd);
5142  return SOAP_INVALID_SOCKET;
5143  }
5144 
5145 #ifndef WITH_LEAN
5146 
5147  if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761)
5148  {
5149  sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd);
5150  strcpy(soap->tmpbuf, "Basic ");
5151  soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262));
5152 
5153  if ((soap->error = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf)))
5154  {
5155  soap->fclosesocket(soap, fd);
5156  return soap->error;
5157  }
5158  }
5159 
5160 #endif
5161 
5162  if ((soap->error = soap->fposthdr(soap, NULL, NULL))
5163  || soap_flush(soap))
5164  {
5165  soap->fclosesocket(soap, fd);
5166  return SOAP_INVALID_SOCKET;
5167  }
5168 
5169  soap->omode = m;
5170  m = soap->imode;
5171  soap->imode &= ~SOAP_ENC; /* mask IO and ENC */
5172  userid = soap->userid; /* preserve */
5173  passwd = soap->passwd; /* preserve */
5174 
5175  if ((soap->error = soap->fparse(soap)))
5176  {
5177  soap->fclosesocket(soap, fd);
5178  return SOAP_INVALID_SOCKET;
5179  }
5180 
5181  soap->userid = userid; /* restore */
5182  soap->passwd = passwd; /* restore */
5183  soap->imode = m; /* restore */
5184  soap->count = n; /* restore */
5185 
5186  if (soap_begin_send(soap))
5187  {
5188  soap->fclosesocket(soap, fd);
5189  return SOAP_INVALID_SOCKET;
5190  }
5191 
5192  if (endpoint)
5193  strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint) - 1); /* restore */
5194  }
5195 
5196  if (!soap->ctx && (soap->error = soap->fsslauth(soap)))
5197  {
5198  soap_set_sender_error(soap, "SSL error", "SSL authentication failed in tcp_connect(): check password, key file, and ca file.", SOAP_SSL_ERROR);
5199  soap->fclosesocket(soap, fd);
5200  return SOAP_INVALID_SOCKET;
5201  }
5202 
5203  if (!soap->ssl)
5204  {
5205  soap->ssl = SSL_new(soap->ctx);
5206 
5207  if (!soap->ssl)
5208  {
5209  soap->fclosesocket(soap, fd);
5210  soap->error = SOAP_SSL_ERROR;
5211  return SOAP_INVALID_SOCKET;
5212  }
5213  }
5214  else
5215  SSL_clear(soap->ssl);
5216 
5217  if (soap->session)
5218  {
5219  if (!strcmp(soap->session_host, host) && soap->session_port == port)
5220  SSL_set_session(soap->ssl, soap->session);
5221 
5222  SSL_SESSION_free(soap->session);
5223  soap->session = NULL;
5224  }
5225 
5226  soap->imode |= SOAP_ENC_SSL;
5227  soap->omode |= SOAP_ENC_SSL;
5228  bio = BIO_new_socket((int)fd, BIO_NOCLOSE);
5229  SSL_set_bio(soap->ssl, bio, bio);
5230 #ifndef WITH_LEAN
5231 
5232  /* Connect timeout: set SSL sockets to non-blocking */
5233  if (soap->connect_timeout)
5234  SOAP_SOCKNONBLOCK(fd)
5235  else
5236  SOAP_SOCKBLOCK(fd)
5237 
5238  /* Try connecting until success or timeout */
5239  do
5240  {
5241  if ((r = SSL_connect(soap->ssl)) <= 0)
5242  {
5243  int err = SSL_get_error(soap->ssl, r);
5244 
5245  if (err != SSL_ERROR_WANT_CONNECT && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
5246  {
5247  soap_set_sender_error(soap, soap_ssl_error(soap, r), "SSL connect failed in tcp_connect()", SOAP_SSL_ERROR);
5248  soap->fclosesocket(soap, fd);
5249  return SOAP_INVALID_SOCKET;
5250  }
5251 
5252  if (soap->connect_timeout)
5253  {
5254  struct timeval timeout;
5255  fd_set fds;
5256 #ifndef WIN32
5257 
5258  if ((int)soap->socket >= (int)FD_SETSIZE)
5259  {
5260  soap->error = SOAP_FD_EXCEEDED;
5261  return SOAP_INVALID_SOCKET; /* Hint: MUST increase FD_SETSIZE */
5262  }
5263 
5264 #endif
5265 
5266  if (soap->connect_timeout > 0)
5267  {
5268  timeout.tv_sec = soap->connect_timeout;
5269  timeout.tv_usec = 0;
5270  }
5271  else
5272  {
5273  timeout.tv_sec = -soap->connect_timeout / 1000000;
5274  timeout.tv_usec = -soap->connect_timeout % 1000000;
5275  }
5276 
5277  FD_ZERO(&fds);
5278  FD_SET(fd, &fds);
5279 
5280  if (err == SSL_ERROR_WANT_READ)
5281  r = select((int)fd + 1, &fds, NULL, NULL, &timeout);
5282  else
5283  r = select((int)fd + 1, NULL, &fds, NULL, &timeout);
5284 
5285  if (r < 0)
5286  {
5287  soap->errnum = 0;
5288  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n"));
5289  soap_set_sender_error(soap, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR);
5290  soap->fclosesocket(soap, fd);
5291  return SOAP_INVALID_SOCKET;
5292  }
5293  }
5294  }
5295  }
5296  while (!SSL_is_init_finished(soap->ssl));
5297 
5298  /* Set SSL sockets to nonblocking */
5299  SOAP_SOCKNONBLOCK(fd)
5300 #endif
5301 
5302  /* Check server credentials when required */
5304  {
5305  int err;
5306 
5307  if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK)
5308  {
5309  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);
5310  soap->fclosesocket(soap, fd);
5311  return SOAP_INVALID_SOCKET;
5312  }
5313 
5314  if (!(soap->ssl_flags & SOAP_SSL_SKIP_HOST_CHECK))
5315  {
5316  X509_NAME *subj;
5317  int ext_count;
5318  int ok = 0;
5319  X509 *peer;
5320  peer = SSL_get_peer_certificate(soap->ssl);
5321 
5322  if (!peer)
5323  {
5324  soap_set_sender_error(soap, "SSL error", "No SSL certificate was presented by the peer in tcp_connect()", SOAP_SSL_ERROR);
5325  soap->fclosesocket(soap, fd);
5326  return SOAP_INVALID_SOCKET;
5327  }
5328 
5329  ext_count = X509_get_ext_count(peer);
5330 
5331  if (ext_count > 0)
5332  {
5333  int i;
5334 
5335  for (i = 0; i < ext_count; i++)
5336  {
5337  X509_EXTENSION *ext = X509_get_ext(peer, i);
5338  const char *ext_str = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));
5339 
5340  if (ext_str && !strcmp(ext_str, "subjectAltName"))
5341  {
5342  X509V3_EXT_METHOD *meth = X509V3_EXT_get(ext);
5343  void *ext_data;
5344 #if (OPENSSL_VERSION_NUMBER >= 0x0090800fL)
5345  const unsigned char *data;
5346 #else
5347  unsigned char *data;
5348 #endif
5349  STACK_OF(CONF_VALUE) *val;
5350  int j;
5351 
5352  if (!meth)
5353  break;
5354 
5355  data = ext->value->data;
5356 #if (OPENSSL_VERSION_NUMBER > 0x00907000L)
5357 
5358  if (meth->it)
5359  ext_data = ASN1_item_d2i(NULL, &data, ext->value->length, ASN1_ITEM_ptr(meth->it));
5360  else
5361  {/* OpenSSL not perfectly portable at this point (?):
5362  Some compilers appear to prefer
5363  meth->d2i(NULL, (const unsigned char**)&data, ...
5364  or
5365  meth->d2i(NULL, &data, ext->value->length);
5366  */
5367  ext_data = meth->d2i(NULL, &data, ext->value->length);
5368  }
5369 
5370 #else
5371  ext_data = meth->d2i(NULL, &data, ext->value->length);
5372 #endif
5373  val = meth->i2v(meth, ext_data, NULL);
5374 
5375  for (j = 0; j < sk_CONF_VALUE_num(val); j++)
5376  {
5377  CONF_VALUE *nval = sk_CONF_VALUE_value(val, j);
5378 
5379  if (nval && !strcmp(nval->name, "DNS") && !strcmp(nval->value, host))
5380  {
5381  ok = 1;
5382  break;
5383  }
5384  }
5385  }
5386 
5387  if (ok)
5388  break;
5389  }
5390  }
5391 
5392  if (!ok && (subj = X509_get_subject_name(peer)))
5393  {
5394  int i = -1;
5395 
5396  do
5397  {
5398  ASN1_STRING *name;
5399  i = X509_NAME_get_index_by_NID(subj, NID_commonName, i);
5400 
5401  if (i == -1)
5402  break;
5403 
5404  name = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subj, i));
5405 
5406  if (name)
5407  {
5408  if (!soap_tag_cmp(host, (const char*)name))
5409  ok = 1;
5410  else
5411  {
5412  unsigned char *tmp = NULL;
5413  ASN1_STRING_to_UTF8(&tmp, name);
5414 
5415  if (tmp)
5416  {
5417  if (!soap_tag_cmp(host, (const char*)tmp))
5418  ok = 1;
5419 
5420  OPENSSL_free(tmp);
5421  }
5422  }
5423  }
5424  }
5425  while (!ok);
5426  }
5427 
5428  X509_free(peer);
5429 
5430  if (!ok)
5431  {
5432  soap_set_sender_error(soap, "SSL error", "SSL certificate host name mismatch in tcp_connect()", SOAP_SSL_ERROR);
5433  soap->fclosesocket(soap, fd);
5434  return SOAP_INVALID_SOCKET;
5435  }
5436  }
5437  }
5438 
5439 #else
5440  soap->fclosesocket(soap, fd);
5441  soap->error = SOAP_SSL_ERROR;
5442  return SOAP_INVALID_SOCKET;
5443 #endif
5444  }
5445 
5446  return fd;
5447  }
5448 #endif
5449 #endif
5450 
5451  /******************************************************************************/
5452 #ifndef WITH_NOIO
5453 #ifndef PALM_1
5454  SOAP_FMAC1
5455  SOAP_SOCKET
5456  SOAP_FMAC2
5457  soap_bind(struct soap *soap, const char *host, int port, int backlog)
5458  {
5459 #ifdef WITH_IPV6
5460  struct addrinfo *addrinfo = NULL;
5461  struct addrinfo hints;
5462  struct addrinfo res;
5463  int err;
5464 #ifdef IPV6_V6ONLY
5465  int unset = 0;
5466 #ifdef SOL_IP
5467  int level = SOL_IP;
5468 #else
5469  int level = IPPROTO_IPV6;
5470 #endif
5471 #endif
5472 #endif
5473 #ifndef WITH_LEAN
5474  int len = SOAP_BUFLEN;
5475  int set = 1;
5476 #endif
5477 
5478  if (soap_valid_socket(soap->master))
5479  {
5480  soap->fclosesocket(soap, soap->master);
5481  soap->master = SOAP_INVALID_SOCKET;
5482  }
5483 
5484  soap->socket = SOAP_INVALID_SOCKET;
5485  soap->errmode = 1;
5486 
5487  if (tcp_init(soap))
5488  {
5489  soap_set_receiver_error(soap, tcp_error(soap), "TCP init failed in soap_bind()", SOAP_TCP_ERROR);
5490  return SOAP_INVALID_SOCKET;
5491  }
5492 
5493 #ifdef WITH_IPV6
5494  memset((void*)&hints, 0, sizeof(hints));
5495  hints.ai_family = PF_UNSPEC;
5496 #ifndef WITH_LEAN
5497 
5498  if ((soap->omode & SOAP_IO_UDP))
5499  hints.ai_socktype = SOCK_DGRAM;
5500  else
5501 #endif
5502  hints.ai_socktype = SOCK_STREAM;
5503 
5504  hints.ai_flags = AI_PASSIVE;
5505  soap->errmode = 2;
5506  err = getaddrinfo(host, soap_int2s(soap, port), &hints, &addrinfo);
5507 
5508  if (addrinfo)
5509  {
5510  res = *addrinfo;
5511  memcpy(&soap->peer, addrinfo->ai_addr, addrinfo->ai_addrlen);
5512  soap->peerlen = addrinfo->ai_addrlen;
5513  res.ai_addr = (struct sockaddr*) & soap->peer;
5514  res.ai_addrlen = soap->peerlen;
5515  freeaddrinfo(addrinfo);
5516  }
5517 
5518  if (err || !addrinfo)
5519  {
5520  soap_set_receiver_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in soap_bind()", SOAP_TCP_ERROR);
5521  return SOAP_INVALID_SOCKET;
5522  }
5523 
5524  soap->master = (int)socket(res.ai_family, res.ai_socktype, res.ai_protocol);
5525 #else
5526 #ifndef WITH_LEAN
5527 
5528  if ((soap->omode & SOAP_IO_UDP))
5529  soap->master = (int)socket(AF_INET, SOCK_DGRAM, 0);
5530  else
5531 #endif
5532  soap->master = (int)socket(AF_INET, SOCK_STREAM, 0);
5533 
5534 #endif
5535  soap->errmode = 0;
5536 
5537  if (!soap_valid_socket(soap->master))
5538  {
5539  soap->errnum = soap_socket_errno(soap->master);
5540  soap_set_receiver_error(soap, tcp_error(soap), "socket failed in soap_bind()", SOAP_TCP_ERROR);
5541  return SOAP_INVALID_SOCKET;
5542  }
5543 
5544 #ifndef WITH_LEAN
5545 
5546  if ((soap->omode & SOAP_IO_UDP))
5547  soap->socket = soap->master;
5548 
5549 #endif
5550 #ifdef SOCKET_CLOSE_ON_EXEC
5551 #ifdef WIN32
5552 #ifndef UNDER_CE
5553  SetHandleInformation((HANDLE)soap->master, HANDLE_FLAG_INHERIT, 0);
5554 #endif
5555 #else
5556  fcntl(soap->master, F_SETFD, 1);
5557 #endif
5558 #endif
5559 #ifndef WITH_LEAN
5560 
5561  if (soap->bind_flags && setsockopt(soap->master, SOL_SOCKET, soap->bind_flags, (char*)&set, sizeof(int)))
5562  {
5563  soap->errnum = soap_socket_errno(soap->master);
5564  soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_bind()", SOAP_TCP_ERROR);
5565  return SOAP_INVALID_SOCKET;
5566  }
5567 
5568  if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt(soap->master, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
5569  {
5570  soap->errnum = soap_socket_errno(soap->master);
5571  soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_bind()", SOAP_TCP_ERROR);
5572  return SOAP_INVALID_SOCKET;
5573  }
5574 
5575  if (setsockopt(soap->master, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
5576  {
5577  soap->errnum = soap_socket_errno(soap->master);
5578  soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_bind()", SOAP_TCP_ERROR);
5579  return SOAP_INVALID_SOCKET;
5580  }
5581 
5582  if (setsockopt(soap->master, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
5583  {
5584  soap->errnum = soap_socket_errno(soap->master);
5585  soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_bind()", SOAP_TCP_ERROR);
5586  return SOAP_INVALID_SOCKET;
5587  }
5588 
5589 #ifdef TCP_NODELAY
5590 
5591  if (!(soap->omode & SOAP_IO_UDP) && setsockopt(soap->master, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
5592  {
5593  soap->errnum = soap_socket_errno(soap->master);
5594  soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_bind()", SOAP_TCP_ERROR);
5595  return SOAP_INVALID_SOCKET;
5596  }
5597 
5598 #endif
5599 #endif
5600 #ifdef WITH_IPV6
5601 #ifdef IPV6_V6ONLY
5602 
5603  if (setsockopt(soap->master, level, IPV6_V6ONLY, (char*)&unset, sizeof(int)))
5604  {
5605  soap->errnum = soap_socket_errno(soap->master);
5606  soap_set_receiver_error(soap, tcp_error(soap), "setsockopt IPV6_V6ONLY failed in soap_bind()", SOAP_TCP_ERROR);
5607  return SOAP_INVALID_SOCKET;
5608  }
5609 
5610 #endif
5611  soap->errmode = 0;
5612 
5613  if (bind(soap->master, res.ai_addr, (int)res.ai_addrlen))
5614  {
5615  soap->errnum = soap_socket_errno(soap->master);
5616  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
5617  soap_closesock(soap);
5618  soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR);
5619  return SOAP_INVALID_SOCKET;
5620  }
5621 
5622 #else
5623  soap->peerlen = sizeof(soap->peer);
5624  memset((void*)&soap->peer, 0, sizeof(soap->peer));
5625  soap->peer.sin_family = AF_INET;
5626  soap->errmode = 2;
5627 
5628  if (host)
5629  {
5630  if (soap->fresolve(soap, host, &soap->peer.sin_addr))
5631  {
5632  soap_set_receiver_error(soap, tcp_error(soap), "get host by name failed in soap_bind()", SOAP_TCP_ERROR);
5633  return SOAP_INVALID_SOCKET;
5634  }
5635  }
5636  else
5637  soap->peer.sin_addr.s_addr = htonl(INADDR_ANY);
5638 
5639  soap->peer.sin_port = htons((short)port);
5640  soap->errmode = 0;
5641 
5642  if (bind(soap->master, (struct sockaddr*)&soap->peer, (int)soap->peerlen))
5643  {
5644  soap->errnum = soap_socket_errno(soap->master);
5645  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
5646  soap_closesock(soap);
5647  soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR);
5648  return SOAP_INVALID_SOCKET;
5649  }
5650 
5651 #endif
5652 
5653  if (!(soap->omode & SOAP_IO_UDP) && listen(soap->master, backlog))
5654  {
5655  soap->errnum = soap_socket_errno(soap->master);
5656  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
5657  soap_closesock(soap);
5658  soap_set_receiver_error(soap, tcp_error(soap), "listen failed in soap_bind()", SOAP_TCP_ERROR);
5659  return SOAP_INVALID_SOCKET;
5660  }
5661 
5662  return soap->master;
5663  }
5664 #endif
5665 #endif
5666 
5667  /******************************************************************************/
5668 #ifndef WITH_NOIO
5669 #ifndef PALM_1
5670  SOAP_FMAC1
5671  int
5672  SOAP_FMAC2
5673  soap_poll(struct soap *soap)
5674  {
5675 #ifndef WITH_LEAN
5676  struct timeval timeout;
5677  fd_set rfd, sfd, xfd;
5678  register int r;
5679 #ifndef WIN32
5680 
5681  if ((int)soap->socket >= (int)FD_SETSIZE)
5682  return SOAP_FD_EXCEEDED; /* Hint: MUST increase FD_SETSIZE */
5683 
5684 #endif
5685  timeout.tv_sec = 0;
5686  timeout.tv_usec = 0;
5687  FD_ZERO(&rfd);
5688  FD_ZERO(&sfd);
5689  FD_ZERO(&xfd);
5690 
5691  if (soap_valid_socket(soap->socket))
5692  {
5693  FD_SET(soap->socket, &rfd);
5694  FD_SET(soap->socket, &sfd);
5695  FD_SET(soap->socket, &xfd);
5696  r = select((int)soap->socket + 1, &rfd, &sfd, &xfd, &timeout);
5697 
5698  if (r > 0 && FD_ISSET(soap->socket, &xfd))
5699  r = -1;
5700  }
5701  else if (soap_valid_socket(soap->master))
5702  {
5703  FD_SET(soap->master, &sfd);
5704  r = select((int)soap->master + 1, NULL, &sfd, NULL, &timeout);
5705  }
5706  else
5707  return SOAP_OK;
5708 
5709  if (r > 0)
5710  {
5711 #ifdef WITH_OPENSSL
5712 
5713  if (soap->imode & SOAP_ENC_SSL)
5714  {
5715  if (soap_valid_socket(soap->socket)
5716  && FD_ISSET(soap->socket, &sfd)
5717  && (!FD_ISSET(soap->socket, &rfd)
5718  || SSL_peek(soap->ssl, soap->tmpbuf, 1) > 0))
5719  return SOAP_OK;
5720  }
5721  else
5722 #endif
5723  if (soap_valid_socket(soap->socket)
5724  && FD_ISSET(soap->socket, &sfd)
5725  && (!FD_ISSET(soap->socket, &rfd)
5726  || recv(soap->socket, soap->tmpbuf, 1, MSG_PEEK) > 0))
5727  return SOAP_OK;
5728  }
5729  else if (r < 0)
5730  {
5731  soap->errnum = soap_socket_errno(soap->master);
5732 
5734  {
5735  soap_set_receiver_error(soap, tcp_error(soap), "select failed in soap_poll()", SOAP_TCP_ERROR);
5736  return soap->error = SOAP_TCP_ERROR;
5737  }
5738  }
5739  else
5740  soap->errnum = 0;
5741 
5742  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Polling: other end down on socket=%d select=%d\n", soap->socket, r));
5743  return SOAP_EOF;
5744 #else
5745  return SOAP_OK;
5746 #endif
5747  }
5748 #endif
5749 #endif
5750 
5751  /******************************************************************************/
5752 #ifndef WITH_NOIO
5753 #ifndef PALM_1
5754  static SOAP_SOCKET
5755  tcp_accept(struct soap *soap, SOAP_SOCKET s, struct sockaddr *a, int *n)
5756  {
5757  SOAP_SOCKET fd;
5758  fd = accept(s, a, (SOAP_SOCKLEN_T*)n); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
5759 #ifdef SOCKET_CLOSE_ON_EXEC
5760 #ifdef WIN32
5761 #ifndef UNDER_CE
5762  SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0);
5763 #endif
5764 #else
5765  fcntl(fd, F_SETFD, FD_CLOEXEC);
5766 #endif
5767 #endif
5768  return fd;
5769  }
5770 #endif
5771 #endif
5772 
5773  /******************************************************************************/
5774 #ifndef WITH_NOIO
5775 #ifndef PALM_1
5776  SOAP_FMAC1
5777  SOAP_SOCKET
5778  SOAP_FMAC2
5779  soap_accept(struct soap *soap)
5780  {
5781  int n = (int)sizeof(soap->peer);
5782 #ifndef WITH_LEAN
5783  int len = SOAP_BUFLEN;
5784  int set = 1;
5785 #endif
5786  soap->error = SOAP_OK;
5787 #ifndef WITH_LEAN
5788 
5789  if ((soap->omode & SOAP_IO_UDP))
5790  return soap->socket = soap->master;
5791 
5792 #endif
5793  memset((void*)&soap->peer, 0, sizeof(soap->peer));
5794  soap->socket = SOAP_INVALID_SOCKET;
5795  soap->errmode = 0;
5796