PageRenderTime 151ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 2ms

/usr/src/lib/libkmsagent/common/SOAP/stdsoap2.cpp

https://bitbucket.org/a3217055/illumos-gate
C++ | 15632 lines | 14532 code | 411 blank | 689 comment | 3825 complexity | 41313bb0cdd7fc221e1d79b312e6d6df MD5 | raw file
Possible License(s): BSD-2-Clause, BSD-3-Clause, LGPL-2.0, 0BSD, AGPL-3.0, GPL-2.0, GPL-3.0, LGPL-2.1, LGPL-3.0, BSD-3-Clause-No-Nuclear-License-2014, MPL-2.0-no-copyleft-exception, AGPL-1.0
  1. /*
  2. * CDDL HEADER START
  3. *
  4. * The contents of this file are subject to the terms of the
  5. * Common Development and Distribution License (the "License").
  6. * You may not use this file except in compliance with the License.
  7. *
  8. * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  9. * or http://www.opensolaris.org/os/licensing.
  10. * See the License for the specific language governing permissions
  11. * and limitations under the License.
  12. *
  13. * When distributing Covered Code, include this CDDL HEADER in each
  14. * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15. * If applicable, add the following below this CDDL HEADER, with the
  16. * fields enclosed by brackets "[]" replaced with your own identifying
  17. * information: Portions Copyright [yyyy] [name of copyright owner]
  18. *
  19. * CDDL HEADER END
  20. */
  21. /*
  22. * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  23. */
  24. /*
  25. stdsoap2.c[pp] 2.7.17
  26. gSOAP runtime engine
  27. gSOAP XML Web services tools
  28. Copyright (C) 2000-2010, Robert van Engelen, Genivia Inc., All Rights Reserved.
  29. This part of the software is released under ONE of the following licenses:
  30. GPL, or the gSOAP public license, or Genivia's license for commercial use.
  31. --------------------------------------------------------------------------------
  32. Contributors:
  33. Oracle, Inc. - additions are noted in the code commented with
  34. "Oracle customization"
  35. - customization of the SSL accept timeout
  36. - work around for SSL_Sleep reporting closed connection
  37. - Function ssl_auth_init was static, but is now exported for external override
  38. - redirection of gSoap debug logs when debug builds enabled
  39. - added SSL_CTX_set_cipher_list call to restrict the cipher suite to RSA-2048/AES
  40. TLS_RSA_WITH_AES_256_CBC_SHA is defined in RFC 3268
  41. also see http://www.openssl.org/docs/apps/ciphers.html
  42. - Added SSL_OP_NO_SSLv3 to force use of TLS
  43. - bug fix: added call to close socket handle in various places noted in the code,
  44. since the caller overwrites soap->socket with the return value
  45. - compile warning cleanup
  46. Wind River Systems Inc., for the following additions under gSOAP public license:
  47. - vxWorks compatible
  48. --------------------------------------------------------------------------------
  49. gSOAP public license.
  50. The contents of this file are subject to the gSOAP Public License Version 1.3
  51. (the "License"); you may not use this file except in compliance with the
  52. License. You may obtain a copy of the License at
  53. http://www.cs.fsu.edu/~engelen/soaplicense.html
  54. Software distributed under the License is distributed on an "AS IS" basis,
  55. WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  56. for the specific language governing rights and limitations under the License.
  57. The Initial Developer of the Original Code is Robert A. van Engelen.
  58. Copyright (C) 2000-2010, Robert van Engelen, Genivia Inc., All Rights Reserved.
  59. --------------------------------------------------------------------------------
  60. GPL license.
  61. This program is free software; you can redistribute it and/or modify it under
  62. the terms of the GNU General Public License as published by the Free Software
  63. Foundation; either version 2 of the License, or (at your option) any later
  64. version.
  65. This program is distributed in the hope that it will be useful, but WITHOUT ANY
  66. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
  67. PARTICULAR PURPOSE. See the GNU General Public License for more details.
  68. You should have received a copy of the GNU General Public License along with
  69. this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  70. Place, Suite 330, Boston, MA 02111-1307 USA
  71. Author contact information:
  72. engelen@genivia.com / engelen@acm.org
  73. This program is released under the GPL with the additional exemption that
  74. compiling, linking, and/or using OpenSSL is allowed.
  75. --------------------------------------------------------------------------------
  76. A commercial use license is available from Genivia, Inc., contact@genivia.com
  77. --------------------------------------------------------------------------------
  78. Installation note:
  79. Win32 build needs winsock.dll (Visual C++ "wsock32.lib")
  80. To do this in Visual C++ 6.0, go to "Project", "settings", select the "Link"
  81. tab (the project file needs to be selected in the file view) and add
  82. "wsock32.lib" to the "Object/library modules" entry
  83. On Mac OS X with gcc (GCC) 3.1 20020420 (prerelease) you MUST compile with
  84. -fstack_check when using -O2 because gcc 3.1 has a bug that smashes the stack
  85. when locally allocated data exceeds 64K.
  86. */
  87. #ifdef AS400
  88. # pragma convert(819) /* EBCDIC to ASCII */
  89. #endif
  90. #include "stdsoap2.h"
  91. /*
  92. Oracle customization for OpenSSL 0.9.8 removal of deprecated function usage: RSA_generate_key
  93. */
  94. #ifdef WITH_OPENSSL
  95. #ifdef OPENSSL_NO_DEPRECATED
  96. #include <openssl/rsa.h>
  97. #include <openssl/bn.h>
  98. #include <openssl/dh.h>
  99. #endif
  100. #endif
  101. #ifdef SOAP_MEM_DEBUG
  102. #ifndef WIN32
  103. #include <ucontext.h> /* Oracle customization (for printstack(3C)) */
  104. #endif
  105. #endif
  106. #ifdef __BORLANDC__
  107. # pragma warn -8060
  108. #else
  109. # ifdef WIN32
  110. # ifdef UNDER_CE
  111. # pragma comment(lib, "winsock.lib")
  112. # else
  113. # pragma comment(lib, "wsock32.lib")
  114. # endif
  115. # pragma warning(disable : 4996) /* disable deprecation warnings */
  116. # endif
  117. #endif
  118. #ifdef __cplusplus
  119. SOAP_SOURCE_STAMP("@(#) stdsoap2.cpp ver 2.7.17 2010-05-10 00:00:00 GMT")
  120. extern "C" {
  121. #else
  122. SOAP_SOURCE_STAMP("@(#) stdsoap2.c ver 2.7.17 2010-05-10 00:00:00 GMT")
  123. #endif
  124. /* 8bit character representing unknown/nonrepresentable character data (e.g. not supported by current locale with multibyte support enabled) */
  125. #ifndef SOAP_UNKNOWN_CHAR
  126. #define SOAP_UNKNOWN_CHAR (127)
  127. #endif
  128. /* EOF=-1 */
  129. #define SOAP_LT (soap_wchar)(-2) /* XML character '<' */
  130. #define SOAP_TT (soap_wchar)(-3) /* XML character '</' */
  131. #define SOAP_GT (soap_wchar)(-4) /* XML character '>' */
  132. #define SOAP_QT (soap_wchar)(-5) /* XML character '"' */
  133. #define SOAP_AP (soap_wchar)(-6) /* XML character ''' */
  134. #define soap_blank(c) ((c) >= 0 && (c) <= 32)
  135. #define soap_notblank(c) ((c) > 32)
  136. #if defined(WIN32) && !defined(UNDER_CE)
  137. #define soap_hash_ptr(p) ((PtrToUlong(p) >> 3) & (SOAP_PTRHASH - 1))
  138. #else
  139. #define soap_hash_ptr(p) ((size_t)(((unsigned long)(p) >> 3) & (SOAP_PTRHASH-1)))
  140. #endif
  141. #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
  142. static void soap_init_logs(struct soap*);
  143. #endif
  144. #ifdef SOAP_DEBUG
  145. static void soap_close_logfile(struct soap*, int);
  146. static void soap_set_logfile(struct soap*, int, const char*);
  147. #endif
  148. #ifdef SOAP_MEM_DEBUG
  149. static void soap_init_mht(struct soap*);
  150. static void soap_free_mht(struct soap*);
  151. static void soap_track_unlink(struct soap*, const void*);
  152. #endif
  153. #ifndef PALM_2
  154. static int soap_set_error(struct soap*, const char*, const char*, const char*, const char*, int);
  155. static int soap_copy_fault(struct soap*, const char*, const char*, const char*, const char*);
  156. static int soap_getattrval(struct soap*, char*, size_t, soap_wchar);
  157. #endif
  158. #ifndef PALM_1
  159. static void soap_free_ns(struct soap *soap);
  160. static soap_wchar soap_char(struct soap*);
  161. static soap_wchar soap_get_pi(struct soap*);
  162. static int soap_isxdigit(int);
  163. static void *fplugin(struct soap*, const char*);
  164. static char *soap_get_http_body(struct soap*);
  165. static size_t soap_count_attachments(struct soap *soap);
  166. static int soap_try_connect_command(struct soap*, int http_command, const char *endpoint, const char *action);
  167. #ifndef WITH_NOIDREF
  168. static void soap_update_ptrs(struct soap*, char*, char*, char*, char*);
  169. static int soap_has_copies(struct soap*, const char*, const char*);
  170. static void soap_init_iht(struct soap*);
  171. static void soap_free_iht(struct soap*);
  172. static void soap_init_pht(struct soap*);
  173. static void soap_free_pht(struct soap*);
  174. #endif
  175. #endif
  176. #ifndef WITH_LEAN
  177. static const char *soap_set_validation_fault(struct soap*, const char*, const char*);
  178. static int soap_isnumeric(struct soap*, const char*);
  179. static struct soap_nlist *soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized);
  180. static void soap_utilize_ns(struct soap *soap, const char *tag, size_t n);
  181. #endif
  182. #ifndef WITH_LEANER
  183. #ifndef PALM_1
  184. static struct soap_multipart *soap_new_multipart(struct soap*, struct soap_multipart**, struct soap_multipart**, char*, size_t);
  185. static int soap_putdimefield(struct soap*, const char*, size_t);
  186. static char *soap_getdimefield(struct soap*, size_t);
  187. static void soap_select_mime_boundary(struct soap*);
  188. static int soap_valid_mime_boundary(struct soap*);
  189. static void soap_resolve_attachment(struct soap*, struct soap_multipart*);
  190. #endif
  191. #endif
  192. #ifdef WITH_GZIP
  193. static int soap_getgziphdr(struct soap*);
  194. #endif
  195. #ifdef WITH_OPENSSL
  196. int soap_ssl_init_done = 0;
  197. //
  198. // Oracle customization
  199. //
  200. // Function ssl_auth_init was static, but is now exported for external override
  201. /*
  202. static int ssl_auth_init(struct soap*);
  203. */
  204. int ssl_auth_init(struct soap*);
  205. static int ssl_verify_callback(int, X509_STORE_CTX*);
  206. static int ssl_verify_callback_allow_expired_certificate(int, X509_STORE_CTX*);
  207. static int ssl_password(char*, int, int, void *);
  208. #endif
  209. #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
  210. #ifndef PALM_1
  211. static const char *soap_decode(char*, size_t, const char*, const char*);
  212. #endif
  213. #endif
  214. #ifndef WITH_NOHTTP
  215. #ifndef PALM_1
  216. static soap_wchar soap_getchunkchar(struct soap*);
  217. static const char *http_error(struct soap*, int);
  218. static int http_get(struct soap*);
  219. static int http_405(struct soap*);
  220. static int http_post(struct soap*, const char*, const char*, int, const char*, const char*, size_t);
  221. static int http_send_header(struct soap*, const char*);
  222. static int http_post_header(struct soap*, const char*, const char*);
  223. static int http_response(struct soap*, int, size_t);
  224. static int http_parse(struct soap*);
  225. static int http_parse_header(struct soap*, const char*, const char*);
  226. #endif
  227. #endif
  228. #ifndef WITH_NOIO
  229. #ifndef PALM_1
  230. static int fsend(struct soap*, const char*, size_t);
  231. static size_t frecv(struct soap*, char*, size_t);
  232. static int tcp_init(struct soap*);
  233. static const char *tcp_error(struct soap*);
  234. #ifndef WITH_IPV6
  235. static int tcp_gethost(struct soap*, const char *addr, struct in_addr *inaddr);
  236. #endif
  237. static SOAP_SOCKET tcp_connect(struct soap*, const char *endpoint, const char *host, int port);
  238. static SOAP_SOCKET tcp_accept(struct soap*, SOAP_SOCKET, struct sockaddr*, int*);
  239. static int tcp_select(struct soap*, SOAP_SOCKET, int, int);
  240. static int tcp_disconnect(struct soap*);
  241. static int tcp_closesocket(struct soap*, SOAP_SOCKET);
  242. static int tcp_shutdownsocket(struct soap*, SOAP_SOCKET, int);
  243. static const char *soap_strerror(struct soap*);
  244. #endif
  245. #define SOAP_TCP_SELECT_RCV 0x1
  246. #define SOAP_TCP_SELECT_SND 0x2
  247. #define SOAP_TCP_SELECT_ERR 0x4
  248. #define SOAP_TCP_SELECT_ALL 0x7
  249. #if defined(WIN32)
  250. #define SOAP_SOCKBLOCK(fd) \
  251. { u_long blocking = 0; \
  252. ioctlsocket(fd, FIONBIO, &blocking); \
  253. }
  254. #define SOAP_SOCKNONBLOCK(fd) \
  255. { u_long nonblocking = 1; \
  256. ioctlsocket(fd, FIONBIO, &nonblocking); \
  257. }
  258. #elif defined(VXWORKS)
  259. #define SOAP_SOCKBLOCK(fd) \
  260. { u_long blocking = 0; \
  261. ioctl(fd, FIONBIO, (int)(&blocking)); \
  262. }
  263. #define SOAP_SOCKNONBLOCK(fd) \
  264. { u_long nonblocking = 1; \
  265. ioctl(fd, FIONBIO, (int)(&nonblocking)); \
  266. }
  267. #elif defined(PALM)
  268. #define SOAP_SOCKBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)&~O_NONBLOCK);
  269. #define SOAP_SOCKNONBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)|O_NONBLOCK);
  270. #elif defined(SYMBIAN)
  271. #define SOAP_SOCKBLOCK(fd) \
  272. { long blocking = 0; \
  273. ioctl(fd, 0/*FIONBIO*/, &blocking); \
  274. }
  275. #define SOAP_SOCKNONBLOCK(fd) \
  276. { long nonblocking = 1; \
  277. ioctl(fd, 0/*FIONBIO*/, &nonblocking); \
  278. }
  279. #else
  280. #define SOAP_SOCKBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)&~O_NONBLOCK);
  281. #define SOAP_SOCKNONBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)|O_NONBLOCK);
  282. #endif
  283. #endif
  284. #if defined(PALM) && !defined(PALM_2)
  285. unsigned short errno;
  286. #endif
  287. #ifndef PALM_1
  288. static const char soap_env1[42] = "http://schemas.xmlsoap.org/soap/envelope/";
  289. static const char soap_enc1[42] = "http://schemas.xmlsoap.org/soap/encoding/";
  290. static const char soap_env2[40] = "http://www.w3.org/2003/05/soap-envelope";
  291. static const char soap_enc2[40] = "http://www.w3.org/2003/05/soap-encoding";
  292. static const char soap_rpc[35] = "http://www.w3.org/2003/05/soap-rpc";
  293. #endif
  294. #ifndef PALM_1
  295. const struct soap_double_nan soap_double_nan = {0xFFFFFFFF, 0xFFFFFFFF};
  296. static const char soap_base64o[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  297. 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";
  298. #endif
  299. #ifndef WITH_LEAN
  300. static const char soap_indent[11] = "\n\t\t\t\t\t\t\t\t\t";
  301. /* Alternative indentation form for SOAP_XML_INDENT:
  302. static const char soap_indent[21] = "\n ";
  303. */
  304. #endif
  305. #ifndef SOAP_CANARY
  306. # define SOAP_CANARY (0xC0DE)
  307. #endif
  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. #ifndef WITH_LEAN
  313. static const struct soap_code_map html_entity_codes[] = /* entities for XHTML parsing */
  314. { { 160, "nbsp" },
  315. { 161, "iexcl" },
  316. { 162, "cent" },
  317. { 163, "pound" },
  318. { 164, "curren" },
  319. { 165, "yen" },
  320. { 166, "brvbar" },
  321. { 167, "sect" },
  322. { 168, "uml" },
  323. { 169, "copy" },
  324. { 170, "ordf" },
  325. { 171, "laquo" },
  326. { 172, "not" },
  327. { 173, "shy" },
  328. { 174, "reg" },
  329. { 175, "macr" },
  330. { 176, "deg" },
  331. { 177, "plusmn" },
  332. { 178, "sup2" },
  333. { 179, "sup3" },
  334. { 180, "acute" },
  335. { 181, "micro" },
  336. { 182, "para" },
  337. { 183, "middot" },
  338. { 184, "cedil" },
  339. { 185, "sup1" },
  340. { 186, "ordm" },
  341. { 187, "raquo" },
  342. { 188, "frac14" },
  343. { 189, "frac12" },
  344. { 190, "frac34" },
  345. { 191, "iquest" },
  346. { 192, "Agrave" },
  347. { 193, "Aacute" },
  348. { 194, "Acirc" },
  349. { 195, "Atilde" },
  350. { 196, "Auml" },
  351. { 197, "Aring" },
  352. { 198, "AElig" },
  353. { 199, "Ccedil" },
  354. { 200, "Egrave" },
  355. { 201, "Eacute" },
  356. { 202, "Ecirc" },
  357. { 203, "Euml" },
  358. { 204, "Igrave" },
  359. { 205, "Iacute" },
  360. { 206, "Icirc" },
  361. { 207, "Iuml" },
  362. { 208, "ETH" },
  363. { 209, "Ntilde" },
  364. { 210, "Ograve" },
  365. { 211, "Oacute" },
  366. { 212, "Ocirc" },
  367. { 213, "Otilde" },
  368. { 214, "Ouml" },
  369. { 215, "times" },
  370. { 216, "Oslash" },
  371. { 217, "Ugrave" },
  372. { 218, "Uacute" },
  373. { 219, "Ucirc" },
  374. { 220, "Uuml" },
  375. { 221, "Yacute" },
  376. { 222, "THORN" },
  377. { 223, "szlig" },
  378. { 224, "agrave" },
  379. { 225, "aacute" },
  380. { 226, "acirc" },
  381. { 227, "atilde" },
  382. { 228, "auml" },
  383. { 229, "aring" },
  384. { 230, "aelig" },
  385. { 231, "ccedil" },
  386. { 232, "egrave" },
  387. { 233, "eacute" },
  388. { 234, "ecirc" },
  389. { 235, "euml" },
  390. { 236, "igrave" },
  391. { 237, "iacute" },
  392. { 238, "icirc" },
  393. { 239, "iuml" },
  394. { 240, "eth" },
  395. { 241, "ntilde" },
  396. { 242, "ograve" },
  397. { 243, "oacute" },
  398. { 244, "ocirc" },
  399. { 245, "otilde" },
  400. { 246, "ouml" },
  401. { 247, "divide" },
  402. { 248, "oslash" },
  403. { 249, "ugrave" },
  404. { 250, "uacute" },
  405. { 251, "ucirc" },
  406. { 252, "uuml" },
  407. { 253, "yacute" },
  408. { 254, "thorn" },
  409. { 255, "yuml" },
  410. { 0, NULL }
  411. };
  412. #endif
  413. #ifndef WITH_NOIO
  414. #ifndef WITH_LEAN
  415. static const struct soap_code_map h_error_codes[] =
  416. {
  417. #ifdef HOST_NOT_FOUND
  418. { HOST_NOT_FOUND, "Host not found" },
  419. #endif
  420. #ifdef TRY_AGAIN
  421. { TRY_AGAIN, "Try Again" },
  422. #endif
  423. #ifdef NO_RECOVERY
  424. { NO_RECOVERY, "No Recovery" },
  425. #endif
  426. #ifdef NO_DATA
  427. { NO_DATA, "No Data" },
  428. #endif
  429. #ifdef NO_ADDRESS
  430. { NO_ADDRESS, "No Address" },
  431. #endif
  432. { 0, NULL }
  433. };
  434. #endif
  435. #endif
  436. #ifndef WITH_NOHTTP
  437. #ifndef WITH_LEAN
  438. static const struct soap_code_map h_http_error_codes[] =
  439. { { 200, "OK" },
  440. { 201, "Created" },
  441. { 202, "Accepted" },
  442. { 203, "Non-Authoritative Information" },
  443. { 204, "No Content" },
  444. { 205, "Reset Content" },
  445. { 206, "Partial Content" },
  446. { 300, "Multiple Choices" },
  447. { 301, "Moved Permanently" },
  448. { 302, "Found" },
  449. { 303, "See Other" },
  450. { 304, "Not Modified" },
  451. { 305, "Use Proxy" },
  452. { 307, "Temporary Redirect" },
  453. { 400, "Bad Request" },
  454. { 401, "Unauthorized" },
  455. { 402, "Payment Required" },
  456. { 403, "Forbidden" },
  457. { 404, "Not Found" },
  458. { 405, "Method Not Allowed" },
  459. { 406, "Not Acceptable" },
  460. { 407, "Proxy Authentication Required" },
  461. { 408, "Request Time-out" },
  462. { 409, "Conflict" },
  463. { 410, "Gone" },
  464. { 411, "Length Required" },
  465. { 412, "Precondition Failed" },
  466. { 413, "Request Entity Too Large" },
  467. { 414, "Request-URI Too Large" },
  468. { 415, "Unsupported Media Type" },
  469. { 416, "Requested range not satisfiable" },
  470. { 417, "Expectation Failed" },
  471. { 500, "Internal Server Error" },
  472. { 501, "Not Implemented" },
  473. { 502, "Bad Gateway" },
  474. { 503, "Service Unavailable" },
  475. { 504, "Gateway Time-out" },
  476. { 505, "HTTP Version not supported" },
  477. { 0, NULL }
  478. };
  479. #endif
  480. #endif
  481. #ifdef WITH_OPENSSL
  482. static const struct soap_code_map h_ssl_error_codes[] =
  483. {
  484. #define _SSL_ERROR(e) { e, #e }
  485. _SSL_ERROR(SSL_ERROR_SSL),
  486. _SSL_ERROR(SSL_ERROR_ZERO_RETURN),
  487. _SSL_ERROR(SSL_ERROR_WANT_READ),
  488. _SSL_ERROR(SSL_ERROR_WANT_WRITE),
  489. _SSL_ERROR(SSL_ERROR_WANT_CONNECT),
  490. _SSL_ERROR(SSL_ERROR_WANT_X509_LOOKUP),
  491. _SSL_ERROR(SSL_ERROR_SYSCALL),
  492. { 0, NULL }
  493. };
  494. #endif
  495. #ifndef WITH_LEANER
  496. static const struct soap_code_map mime_codes[] =
  497. { { SOAP_MIME_7BIT, "7bit" },
  498. { SOAP_MIME_8BIT, "8bit" },
  499. { SOAP_MIME_BINARY, "binary" },
  500. { SOAP_MIME_QUOTED_PRINTABLE, "quoted-printable" },
  501. { SOAP_MIME_BASE64, "base64" },
  502. { SOAP_MIME_IETF_TOKEN, "ietf-token" },
  503. { SOAP_MIME_X_TOKEN, "x-token" },
  504. { 0, NULL }
  505. };
  506. #endif
  507. #ifdef WIN32
  508. static int tcp_done = 0;
  509. #endif
  510. #if defined(HP_UX) && defined(HAVE_GETHOSTBYNAME_R)
  511. extern int h_errno;
  512. #endif
  513. /******************************************************************************/
  514. #ifndef WITH_NOIO
  515. #ifndef PALM_1
  516. static int
  517. fsend(struct soap *soap, const char *s, size_t n)
  518. { register int nwritten, err;
  519. #if defined(__cplusplus) && !defined(WITH_LEAN) && !defined(WITH_COMPAT)
  520. if (soap->os)
  521. { soap->os->write(s, (std::streamsize)n);
  522. if (soap->os->good())
  523. return SOAP_OK;
  524. soap->errnum = 0;
  525. return SOAP_EOF;
  526. }
  527. #endif
  528. while (n)
  529. { if (soap_valid_socket(soap->socket))
  530. {
  531. if (soap->send_timeout)
  532. { for (;;)
  533. { register int r;
  534. #ifdef WITH_OPENSSL
  535. if (soap->ssl)
  536. r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_ALL, soap->send_timeout);
  537. else
  538. #endif
  539. r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->send_timeout);
  540. if (r > 0)
  541. break;
  542. if (!r)
  543. return SOAP_EOF;
  544. err = soap->errnum;
  545. if (!err)
  546. return soap->error;
  547. if (err != SOAP_EINTR && err != SOAP_EAGAIN && err != SOAP_EWOULDBLOCK)
  548. return SOAP_EOF;
  549. }
  550. }
  551. #ifdef WITH_OPENSSL
  552. if (soap->ssl)
  553. nwritten = SSL_write(soap->ssl, s, (int)n);
  554. else if (soap->bio)
  555. nwritten = BIO_write(soap->bio, s, (int)n);
  556. else
  557. #endif
  558. #ifndef WITH_LEAN
  559. if ((soap->omode & SOAP_IO_UDP))
  560. { if (soap->peerlen)
  561. nwritten = sendto(soap->socket, (char*)s, (SOAP_WINSOCKINT)n, soap->socket_flags, (struct sockaddr*)&soap->peer, (SOAP_WINSOCKINT)soap->peerlen);
  562. else
  563. nwritten = send(soap->socket, s, (SOAP_WINSOCKINT)n, soap->socket_flags);
  564. /* retry and back-off algorithm */
  565. /* TODO: this is not very clear from specs so verify and limit conditions under which we should loop (e.g. ENOBUFS) */
  566. if (nwritten < 0)
  567. { int udp_repeat;
  568. int udp_delay;
  569. if ((soap->connect_flags & SO_BROADCAST))
  570. udp_repeat = 3; /* SOAP-over-UDP MULTICAST_UDP_REPEAT - 1 */
  571. else
  572. udp_repeat = 1; /* SOAP-over-UDP UNICAST_UDP_REPEAT - 1 */
  573. udp_delay = (soap_random % 201) + 50; /* UDP_MIN_DELAY .. UDP_MAX_DELAY */
  574. do
  575. { tcp_select(soap, soap->socket, SOAP_TCP_SELECT_ERR, -1000 * udp_delay);
  576. if (soap->peerlen)
  577. nwritten = sendto(soap->socket, (char*)s, (SOAP_WINSOCKINT)n, soap->socket_flags, (struct sockaddr*)&soap->peer, (SOAP_WINSOCKINT)soap->peerlen);
  578. else
  579. nwritten = send(soap->socket, s, (SOAP_WINSOCKINT)n, soap->socket_flags);
  580. udp_delay <<= 1;
  581. if (udp_delay > 500) /* UDP_UPPER_DELAY */
  582. udp_delay = 500;
  583. }
  584. while (nwritten < 0 && --udp_repeat > 0);
  585. }
  586. }
  587. else
  588. #endif
  589. #if !defined(PALM) && !defined(AS400)
  590. nwritten = send(soap->socket, s, (int)n, soap->socket_flags);
  591. #else
  592. nwritten = send(soap->socket, (void*)s, n, soap->socket_flags);
  593. #endif
  594. if (nwritten <= 0)
  595. {
  596. register int r = 0;
  597. err = soap_socket_errno(soap->socket);
  598. #ifdef WITH_OPENSSL
  599. if (soap->ssl && (r = SSL_get_error(soap->ssl, nwritten)) != SSL_ERROR_NONE && r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE)
  600. { soap->errnum = err;
  601. return SOAP_EOF;
  602. }
  603. #endif
  604. if (err == SOAP_EWOULDBLOCK || err == SOAP_EAGAIN)
  605. {
  606. #ifdef WITH_OPENSSL
  607. if (soap->ssl && r == SSL_ERROR_WANT_READ)
  608. r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->send_timeout ? soap->send_timeout : -10000);
  609. else
  610. r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->send_timeout ? soap->send_timeout : -10000);
  611. #else
  612. r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->send_timeout ? soap->send_timeout : -10000);
  613. #endif
  614. if (!r && soap->send_timeout)
  615. return SOAP_EOF;
  616. if (r < 0 && soap->errnum != SOAP_EINTR)
  617. return SOAP_EOF;
  618. }
  619. else if (err && err != SOAP_EINTR)
  620. { soap->errnum = err;
  621. return SOAP_EOF;
  622. }
  623. nwritten = 0; /* and call write() again */
  624. }
  625. }
  626. else
  627. {
  628. #ifdef WITH_FASTCGI
  629. nwritten = fwrite((void*)s, 1, n, stdout);
  630. fflush(stdout);
  631. #else
  632. #ifdef UNDER_CE
  633. nwritten = fwrite(s, 1, n, soap->sendfd);
  634. #else
  635. #ifdef VXWORKS
  636. #ifdef WMW_RPM_IO
  637. if (soap->rpmreqid)
  638. nwritten = (httpBlockPut(soap->rpmreqid, (char*)s, n) == 0) ? n : -1;
  639. else
  640. #endif
  641. nwritten = fwrite(s, sizeof(char), n, fdopen(soap->sendfd, "w"));
  642. #else
  643. #ifdef WIN32
  644. nwritten = _write(soap->sendfd, s, (unsigned int)n);
  645. #else
  646. nwritten = write(soap->sendfd, s, (unsigned int)n);
  647. #endif
  648. #endif
  649. #endif
  650. #endif
  651. if (nwritten <= 0)
  652. {
  653. #ifndef WITH_FASTCGI
  654. err = soap_errno;
  655. #else
  656. err = EOF;
  657. #endif
  658. if (err && err != SOAP_EINTR && err != SOAP_EWOULDBLOCK && err != SOAP_EAGAIN)
  659. { soap->errnum = err;
  660. return SOAP_EOF;
  661. }
  662. nwritten = 0; /* and call write() again */
  663. }
  664. }
  665. n -= nwritten;
  666. s += nwritten;
  667. }
  668. return SOAP_OK;
  669. }
  670. #endif
  671. #endif
  672. /******************************************************************************/
  673. #ifndef PALM_1
  674. SOAP_FMAC1
  675. int
  676. SOAP_FMAC2
  677. soap_send_raw(struct soap *soap, const char *s, size_t n)
  678. { if (!n)
  679. return SOAP_OK;
  680. if (soap->mode & SOAP_IO_LENGTH)
  681. { soap->count += n;
  682. #ifndef WITH_LEANER
  683. if (soap->fpreparesend && (soap->mode & SOAP_IO) != SOAP_IO_STORE)
  684. return soap->error = soap->fpreparesend(soap, s, n);
  685. #endif
  686. return SOAP_OK;
  687. }
  688. if (soap->mode & SOAP_IO)
  689. { register size_t i = SOAP_BUFLEN - soap->bufidx;
  690. while (n >= i)
  691. { memcpy(soap->buf + soap->bufidx, s, i);
  692. soap->bufidx = SOAP_BUFLEN;
  693. if (soap_flush(soap))
  694. return soap->error;
  695. s += i;
  696. n -= i;
  697. i = SOAP_BUFLEN;
  698. }
  699. memcpy(soap->buf + soap->bufidx, s, n);
  700. soap->bufidx += n;
  701. return SOAP_OK;
  702. }
  703. return soap_flush_raw(soap, s, n);
  704. }
  705. #endif
  706. /******************************************************************************/
  707. #ifndef PALM_1
  708. SOAP_FMAC1
  709. int
  710. SOAP_FMAC2
  711. soap_flush(struct soap *soap)
  712. { register size_t n = soap->bufidx;
  713. if (n)
  714. {
  715. #ifndef WITH_LEANER
  716. if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
  717. { register int r;
  718. if (soap->fpreparesend && (r = soap->fpreparesend(soap, soap->buf, n)))
  719. return soap->error = r;
  720. }
  721. #endif
  722. soap->bufidx = 0;
  723. #ifdef WITH_ZLIB
  724. if (soap->mode & SOAP_ENC_ZLIB)
  725. { soap->d_stream->next_in = (Byte*)soap->buf;
  726. soap->d_stream->avail_in = (unsigned int)n;
  727. #ifdef WITH_GZIP
  728. soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)n);
  729. #endif
  730. do
  731. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating %u bytes\n", soap->d_stream->avail_in));
  732. if (deflate(soap->d_stream, Z_NO_FLUSH) != Z_OK)
  733. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to deflate: %s\n", soap->d_stream->msg?soap->d_stream->msg:SOAP_STR_EOS));
  734. return soap->error = SOAP_ZLIB_ERROR;
  735. }
  736. if (!soap->d_stream->avail_out)
  737. { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN))
  738. return soap->error;
  739. soap->d_stream->next_out = (Byte*)soap->z_buf;
  740. soap->d_stream->avail_out = SOAP_BUFLEN;
  741. }
  742. } while (soap->d_stream->avail_in);
  743. }
  744. else
  745. #endif
  746. return soap_flush_raw(soap, soap->buf, n);
  747. }
  748. return SOAP_OK;
  749. }
  750. #endif
  751. /******************************************************************************/
  752. #ifndef PALM_1
  753. SOAP_FMAC1
  754. int
  755. SOAP_FMAC2
  756. soap_flush_raw(struct soap *soap, const char *s, size_t n)
  757. { if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
  758. { register char *t;
  759. if (!(t = (char*)soap_push_block(soap, NULL, n)))
  760. return soap->error = SOAP_EOM;
  761. memcpy(t, s, n);
  762. return SOAP_OK;
  763. }
  764. #ifndef WITH_LEANER
  765. if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
  766. { char t[16];
  767. sprintf(t, "\r\n%lX\r\n" + (soap->chunksize ? 0 : 2), (unsigned long)n);
  768. DBGMSG(SENT, t, strlen(t));
  769. if ((soap->error = soap->fsend(soap, t, strlen(t))))
  770. return soap->error;
  771. soap->chunksize += n;
  772. }
  773. DBGMSG(SENT, s, n);
  774. #endif
  775. return soap->error = soap->fsend(soap, s, n);
  776. }
  777. #endif
  778. /******************************************************************************/
  779. #ifndef PALM_1
  780. SOAP_FMAC1
  781. int
  782. SOAP_FMAC2
  783. soap_send(struct soap *soap, const char *s)
  784. { if (s)
  785. return soap_send_raw(soap, s, strlen(s));
  786. return SOAP_OK;
  787. }
  788. #endif
  789. /******************************************************************************/
  790. #ifndef WITH_LEANER
  791. #ifndef PALM_1
  792. SOAP_FMAC1
  793. int
  794. SOAP_FMAC2
  795. soap_send2(struct soap *soap, const char *s1, const char *s2)
  796. { if (soap_send(soap, s1))
  797. return soap->error;
  798. return soap_send(soap, s2);
  799. }
  800. #endif
  801. #endif
  802. /******************************************************************************/
  803. #ifndef WITH_LEANER
  804. #ifndef PALM_1
  805. SOAP_FMAC1
  806. int
  807. SOAP_FMAC2
  808. soap_send3(struct soap *soap, const char *s1, const char *s2, const char *s3)
  809. { if (soap_send(soap, s1)
  810. || soap_send(soap, s2))
  811. return soap->error;
  812. return soap_send(soap, s3);
  813. }
  814. #endif
  815. #endif
  816. /******************************************************************************/
  817. #ifndef WITH_NOIO
  818. #ifndef PALM_1
  819. static size_t
  820. frecv(struct soap *soap, char *s, size_t n)
  821. { register int r;
  822. register int retries = 100; /* max 100 retries with non-blocking sockets */
  823. soap->errnum = 0;
  824. #if defined(__cplusplus) && !defined(WITH_LEAN) && !defined(WITH_COMPAT)
  825. if (soap->is)
  826. { if (soap->is->good())
  827. return soap->is->read(s, (std::streamsize)n).gcount();
  828. return 0;
  829. }
  830. #endif
  831. if (soap_valid_socket(soap->socket))
  832. { for (;;)
  833. {
  834. #ifdef WITH_OPENSSL
  835. register int err = 0;
  836. #endif
  837. #ifdef WITH_OPENSSL
  838. if (soap->recv_timeout && !soap->ssl) /* SSL: sockets are nonblocking */
  839. #else
  840. if (soap->recv_timeout)
  841. #endif
  842. { for (;;)
  843. { r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->recv_timeout);
  844. if (r > 0)
  845. break;
  846. if (!r)
  847. return 0;
  848. r = soap->errnum;
  849. if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
  850. return 0;
  851. }
  852. }
  853. #ifdef WITH_OPENSSL
  854. if (soap->ssl)
  855. { r = SSL_read(soap->ssl, s, (int)n);
  856. if (r > 0)
  857. return (size_t)r;
  858. err = SSL_get_error(soap->ssl, r);
  859. if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
  860. return 0;
  861. }
  862. else if (soap->bio)
  863. { r = BIO_read(soap->bio, s, (int)n);
  864. if (r > 0)
  865. return (size_t)r;
  866. return 0;
  867. }
  868. else
  869. #endif
  870. {
  871. #ifndef WITH_LEAN
  872. if ((soap->omode & SOAP_IO_UDP))
  873. { SOAP_SOCKLEN_T k = (SOAP_SOCKLEN_T)sizeof(soap->peer);
  874. memset((void*)&soap->peer, 0, sizeof(soap->peer));
  875. 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 */
  876. soap->peerlen = (size_t)k;
  877. #ifndef WITH_IPV6
  878. soap->ip = ntohl(soap->peer.sin_addr.s_addr);
  879. #endif
  880. }
  881. else
  882. #endif
  883. r = recv(soap->socket, s, (int)n, soap->socket_flags);
  884. #ifdef PALM
  885. /* CycleSyncDisplay(curStatusMsg); */
  886. #endif
  887. if (r >= 0)
  888. return (size_t)r;
  889. r = soap_socket_errno(soap->socket);
  890. if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
  891. { soap->errnum = r;
  892. return 0;
  893. }
  894. }
  895. #ifdef WITH_OPENSSL
  896. if (soap->ssl && err == SSL_ERROR_WANT_WRITE)
  897. r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5);
  898. else
  899. r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5);
  900. #else
  901. r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5);
  902. #endif
  903. if (!r && soap->recv_timeout)
  904. return 0;
  905. if (r < 0)
  906. { r = soap->errnum;
  907. if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
  908. return 0;
  909. }
  910. if (retries-- <= 0)
  911. return 0;
  912. #ifdef PALM
  913. r = soap_socket_errno(soap->socket);
  914. if (r != SOAP_EINTR && retries-- <= 0)
  915. { soap->errnum = r;
  916. return 0;
  917. }
  918. #endif
  919. }
  920. }
  921. #ifdef WITH_FASTCGI
  922. return fread(s, 1, n, stdin);
  923. #else
  924. #ifdef UNDER_CE
  925. return fread(s, 1, n, soap->recvfd);
  926. #else
  927. #ifdef WMW_RPM_IO
  928. if (soap->rpmreqid)
  929. r = httpBlockRead(soap->rpmreqid, s, n);
  930. else
  931. #endif
  932. #ifdef WIN32
  933. r = _read(soap->recvfd, s, (unsigned int)n);
  934. #else
  935. r = read(soap->recvfd, s, (unsigned int)n);
  936. #endif
  937. if (r >= 0)
  938. return (size_t)r;
  939. soap->errnum = soap_errno;
  940. return 0;
  941. #endif
  942. #endif
  943. }
  944. #endif
  945. #endif
  946. /******************************************************************************/
  947. #ifndef WITH_NOHTTP
  948. #ifndef PALM_1
  949. static soap_wchar
  950. soap_getchunkchar(struct soap *soap)
  951. { if (soap->bufidx < soap->buflen)
  952. return soap->buf[soap->bufidx++];
  953. soap->bufidx = 0;
  954. soap->buflen = soap->chunkbuflen = soap->frecv(soap, soap->buf, SOAP_BUFLEN);
  955. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket %d\n", (unsigned int)soap->buflen, soap->socket));
  956. DBGMSG(RECV, soap->buf, soap->buflen);
  957. if (soap->buflen)
  958. return soap->buf[soap->bufidx++];
  959. return EOF;
  960. }
  961. #endif
  962. #endif
  963. /******************************************************************************/
  964. #ifndef PALM_1
  965. static int
  966. soap_isxdigit(int c)
  967. { return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
  968. }
  969. #endif
  970. /******************************************************************************/
  971. #ifndef PALM_1
  972. SOAP_FMAC1
  973. int
  974. SOAP_FMAC2
  975. soap_recv_raw(struct soap *soap)
  976. { register size_t ret;
  977. #if !defined(WITH_LEANER) || defined(WITH_ZLIB)
  978. register int r;
  979. #endif
  980. #ifdef WITH_ZLIB
  981. if (soap->mode & SOAP_ENC_ZLIB)
  982. { if (soap->d_stream->next_out == Z_NULL)
  983. return EOF;
  984. if (soap->d_stream->avail_in || !soap->d_stream->avail_out)
  985. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflating\n"));
  986. soap->d_stream->next_out = (Byte*)soap->buf;
  987. soap->d_stream->avail_out = SOAP_BUFLEN;
  988. r = inflate(soap->d_stream, Z_NO_FLUSH);
  989. if (r == Z_NEED_DICT && soap->z_dict)
  990. r = inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len);
  991. if (r == Z_OK || r == Z_STREAM_END)
  992. { soap->bufidx = 0;
  993. ret = soap->buflen = SOAP_BUFLEN - soap->d_stream->avail_out;
  994. if (soap->zlib_in == SOAP_ZLIB_GZIP)
  995. soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)ret);
  996. if (r == Z_STREAM_END)
  997. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out));
  998. soap->z_ratio_in = (float)soap->d_stream->total_in / (float)soap->d_stream->total_out;
  999. soap->d_stream->next_out = Z_NULL;
  1000. }
  1001. if (ret)
  1002. { soap->count += ret;
  1003. DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- decompressed ----\n"));
  1004. DBGMSG(RECV, soap->buf, ret);
  1005. DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n----\n"));
  1006. #ifndef WITH_LEANER
  1007. if (soap->fpreparerecv && (r = soap->fpreparerecv(soap, soap->buf, ret)))
  1008. return soap->error = r;
  1009. #endif
  1010. return SOAP_OK;
  1011. }
  1012. }
  1013. else if (r != Z_BUF_ERROR)
  1014. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate error: %s\n", soap->d_stream->msg?soap->d_stream->msg:SOAP_STR_EOS));
  1015. soap->d_stream->next_out = Z_NULL;
  1016. soap->error = SOAP_ZLIB_ERROR;
  1017. return EOF;
  1018. }
  1019. }
  1020. zlib_again:
  1021. if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK && !soap->chunksize)
  1022. { memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN);
  1023. soap->buflen = soap->z_buflen;
  1024. }
  1025. DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- compressed ----\n"));
  1026. }
  1027. #endif
  1028. #ifndef WITH_NOHTTP
  1029. if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) /* read HTTP chunked transfer */
  1030. { for (;;)
  1031. { register soap_wchar c;
  1032. char *t, tmp[8];
  1033. if (soap->chunksize)
  1034. { soap->buflen = ret = soap->frecv(soap, soap->buf, soap->chunksize > SOAP_BUFLEN ? SOAP_BUFLEN : soap->chunksize);
  1035. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk: read %u bytes\n", (unsigned int)ret));
  1036. DBGMSG(RECV, soap->buf, ret);
  1037. soap->bufidx = 0;
  1038. soap->chunksize -= ret;
  1039. break;
  1040. }
  1041. t = tmp;
  1042. if (!soap->chunkbuflen)
  1043. { soap->chunkbuflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN);
  1044. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes (chunked) from socket %d\n", (unsigned int)ret, soap->socket));
  1045. DBGMSG(RECV, soap->buf, ret);
  1046. soap->bufidx = 0;
  1047. if (!ret)
  1048. return soap->ahead = EOF;
  1049. }
  1050. else
  1051. soap->bufidx = soap->buflen;
  1052. soap->buflen = soap->chunkbuflen;
  1053. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk size (idx=%u len=%u)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen));
  1054. while (!soap_isxdigit((int)(c = soap_getchunkchar(soap))))
  1055. { if ((int)c == EOF)
  1056. return soap->ahead = EOF;
  1057. }
  1058. do
  1059. *t++ = (char)c;
  1060. while (soap_isxdigit((int)(c = soap_getchunkchar(soap))) && t - tmp < 7);
  1061. while ((int)c != EOF && c != '\n')
  1062. c = soap_getchunkchar(soap);
  1063. if ((int)c == EOF)
  1064. return soap->ahead = EOF;
  1065. *t = '\0';
  1066. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunk size = %s (hex)\n", tmp));
  1067. soap->chunksize = soap_strtoul(tmp, &t, 16);
  1068. if (!soap->chunksize)
  1069. { soap->chunkbuflen = 0;
  1070. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of chunked message\n"));
  1071. while ((int)c != EOF && c != '\n')
  1072. c = soap_getchunkchar(soap);
  1073. ret = 0;
  1074. soap->ahead = EOF;
  1075. break;
  1076. }
  1077. soap->buflen = soap->bufidx + soap->chunksize;
  1078. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving buf len to idx=%u len=%u (%s)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen, tmp));
  1079. if (soap->buflen > soap->chunkbuflen)
  1080. { soap->buflen = soap->chunkbuflen;
  1081. soap->chunksize -= soap->buflen - soap->bufidx;
  1082. soap->chunkbuflen = 0;
  1083. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Passed end of buffer for chunked HTTP (%u bytes left)\n", (unsigned int)(soap->buflen - soap->bufidx)));
  1084. }
  1085. else if (soap->chunkbuflen)
  1086. soap->chunksize = 0;
  1087. ret = soap->buflen - soap->bufidx;
  1088. if (ret)
  1089. break;
  1090. }
  1091. }
  1092. else
  1093. #endif
  1094. { soap->bufidx = 0;
  1095. soap->buflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN);
  1096. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket %d\n", (unsigned int)ret, soap->socket));
  1097. DBGMSG(RECV, soap->buf, ret);
  1098. }
  1099. #ifdef WITH_ZLIB
  1100. if (soap->mode & SOAP_ENC_ZLIB)
  1101. { memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN);
  1102. soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx);
  1103. soap->d_stream->avail_in = (unsigned int)ret;
  1104. soap->d_stream->next_out = (Byte*)soap->buf;
  1105. soap->d_stream->avail_out = SOAP_BUFLEN;
  1106. r = inflate(soap->d_stream, Z_NO_FLUSH);
  1107. if (r == Z_NEED_DICT && soap->z_dict)
  1108. r = inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len);
  1109. if (r == Z_OK || r == Z_STREAM_END)
  1110. { soap->bufidx = 0;
  1111. soap->z_buflen = soap->buflen;
  1112. soap->buflen = SOAP_BUFLEN - soap->d_stream->avail_out;
  1113. if (soap->zlib_in == SOAP_ZLIB_GZIP)
  1114. soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen);
  1115. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %u bytes\n", (unsigned int)soap->buflen));
  1116. if (ret && !soap->buflen && r != Z_STREAM_END)
  1117. goto zlib_again;
  1118. ret = soap->buflen;
  1119. if (r == Z_STREAM_END)
  1120. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated total %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out));
  1121. soap->z_ratio_in = (float)soap->d_stream->total_in / (float)soap->d_stream->total_out;
  1122. soap->d_stream->next_out = Z_NULL;
  1123. }
  1124. DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- decompressed ----\n"));
  1125. DBGMSG(RECV, soap->buf, ret);
  1126. #ifndef WITH_LEANER
  1127. if (soap->fpreparerecv && (r = soap->fpreparerecv(soap, soap->buf, ret)))
  1128. return soap->error = r;
  1129. #endif
  1130. }
  1131. else
  1132. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to inflate: (%d) %s\n", r, soap->d_stream->msg?soap->d_stream->msg:SOAP_STR_EOS));
  1133. soap->d_stream->next_out = Z_NULL;
  1134. soap->error = SOAP_ZLIB_ERROR;
  1135. return EOF;
  1136. }
  1137. }
  1138. #endif
  1139. #ifndef WITH_LEANER
  1140. if (soap->fpreparerecv
  1141. #ifdef WITH_ZLIB
  1142. && soap->zlib_in == SOAP_ZLIB_NONE
  1143. #endif
  1144. && (r = soap->fpreparerecv(soap, soap->buf + soap->bufidx, ret)))
  1145. return soap->error = r;
  1146. #endif
  1147. soap->count += ret;
  1148. return !ret;
  1149. }
  1150. #endif
  1151. /******************************************************************************/
  1152. #ifndef PALM_1
  1153. SOAP_FMAC1
  1154. int
  1155. SOAP_FMAC2
  1156. soap_recv(struct soap *soap)
  1157. {
  1158. #ifndef WITH_LEANER
  1159. if (soap->mode & SOAP_ENC_DIME)
  1160. { if (soap->dime.buflen)
  1161. { char *s;
  1162. int i;
  1163. unsigned char tmp[12];
  1164. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME hdr for chunked DIME is in buffer\n"));
  1165. soap->count += soap->dime.buflen - soap->buflen;
  1166. soap->buflen = soap->dime.buflen;
  1167. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Skip padding (%ld bytes)\n", -(long)soap->dime.size&3));
  1168. for (i = -(long)soap->dime.size&3; i > 0; i--)
  1169. { soap->bufidx++;
  1170. if (soap->bufidx >= soap->buflen)
  1171. if (soap_recv_raw(soap))
  1172. return EOF;
  1173. }
  1174. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME hdr for next chunk\n"));
  1175. s = (char*)tmp;
  1176. for (i = 12; i > 0; i--)
  1177. { *s++ = soap->buf[soap->bufidx++];
  1178. if (soap->bufidx >= soap->buflen)
  1179. if (soap_recv_raw(soap))
  1180. return EOF;
  1181. }
  1182. soap->dime.flags = tmp[0] & 0x7;
  1183. soap->dime.size = ((size_t)tmp[8] << 24) | ((size_t)tmp[9] << 16) | ((size_t)tmp[10] << 8) | ((size_t)tmp[11]);
  1184. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME chunk (%u bytes)\n", (unsigned int)soap->dime.size));
  1185. if (soap->dime.flags & SOAP_DIME_CF)
  1186. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "More chunking\n"));
  1187. soap->dime.chunksize = soap->dime.size;
  1188. if (soap->buflen - soap->bufidx >= soap->dime.size)
  1189. { soap->dime.buflen = soap->buflen;
  1190. soap->buflen = soap->bufidx + soap->dime.chunksize;
  1191. }
  1192. else
  1193. soap->dime.chunksize -= soap->buflen - soap->bufidx;
  1194. }
  1195. else
  1196. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Last chunk\n"));
  1197. soap->dime.buflen = 0;
  1198. soap->dime.chunksize = 0;
  1199. }
  1200. soap->count = soap->buflen - soap->bufidx;
  1201. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%u bytes remaining\n", (unsigned int)soap->count));
  1202. return SOAP_OK;
  1203. }
  1204. if (soap->dime.chunksize)
  1205. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get next DIME hdr for chunked DIME (%u bytes chunk)\n", (unsigned int)soap->dime.chunksize));
  1206. if (soap_recv_raw(soap))
  1207. return EOF;
  1208. if (soap->buflen - soap->bufidx >= soap->dime.chunksize)
  1209. { soap->dime.buflen = soap->buflen;
  1210. soap->count -= soap->buflen - soap->bufidx - soap->dime.chunksize;
  1211. soap->buflen = soap->bufidx + soap->dime.chunksize;
  1212. }
  1213. else
  1214. soap->dime.chunksize -= soap->buflen - soap->bufidx;
  1215. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%lu bytes remaining, count=%u\n", (unsigned long)(soap->buflen-soap->bufidx), (unsigned int)soap->count));
  1216. return SOAP_OK;
  1217. }
  1218. }
  1219. #endif
  1220. return soap_recv_raw(soap);
  1221. }
  1222. #endif
  1223. /******************************************************************************/
  1224. #ifndef PALM_1
  1225. SOAP_FMAC1
  1226. soap_wchar
  1227. SOAP_FMAC2
  1228. soap_getchar(struct soap *soap)
  1229. { register soap_wchar c;
  1230. c = soap->ahead;
  1231. if (c)
  1232. { if (c != EOF)
  1233. soap->ahead = 0;
  1234. return c;
  1235. }
  1236. return soap_get1(soap);
  1237. }
  1238. #endif
  1239. /******************************************************************************/
  1240. #ifndef PALM_1
  1241. SOAP_FMAC1
  1242. const struct soap_code_map*
  1243. SOAP_FMAC2
  1244. soap_code(const struct soap_code_map *code_map, const char *str)
  1245. { if (code_map && str)
  1246. { while (code_map->string)
  1247. { if (!strcmp(str, code_map->string)) /* case sensitive */
  1248. return code_map;
  1249. code_map++;
  1250. }
  1251. }
  1252. return NULL;
  1253. }
  1254. #endif
  1255. /******************************************************************************/
  1256. #ifndef PALM_1
  1257. SOAP_FMAC1
  1258. long
  1259. SOAP_FMAC2
  1260. soap_code_int(const struct soap_code_map *code_map, const char *str, long other)
  1261. { if (code_map)
  1262. { while (code_map->string)
  1263. { if (!soap_tag_cmp(str, code_map->string)) /* case insensitive */
  1264. return code_map->code;
  1265. code_map++;
  1266. }
  1267. }
  1268. return other;
  1269. }
  1270. #endif
  1271. /******************************************************************************/
  1272. #ifndef PALM_1
  1273. SOAP_FMAC1
  1274. const char*
  1275. SOAP_FMAC2
  1276. soap_code_str(const struct soap_code_map *code_map, long code)
  1277. { if (!code_map)
  1278. return NULL;
  1279. while (code_map->code != code && code_map->string)
  1280. code_map++;
  1281. return code_map->string;
  1282. }
  1283. #endif
  1284. /******************************************************************************/
  1285. #ifndef PALM_1
  1286. SOAP_FMAC1
  1287. long
  1288. SOAP_FMAC2
  1289. soap_code_bits(const struct soap_code_map *code_map, const char *str)
  1290. { register long bits = 0;
  1291. if (code_map)
  1292. { while (str && *str)
  1293. { const struct soap_code_map *p;
  1294. for (p = code_map; p->string; p++)
  1295. { register size_t n = strlen(p->string);
  1296. if (!strncmp(p->string, str, n) && soap_blank(str[n]))
  1297. { bits |= p->code;
  1298. str += n;
  1299. while (*str > 0 && *str <= 32)
  1300. str++;
  1301. break;
  1302. }
  1303. }
  1304. if (!p->string)
  1305. return 0;
  1306. }
  1307. }
  1308. return bits;
  1309. }
  1310. #endif
  1311. /******************************************************************************/
  1312. #ifndef PALM_1
  1313. SOAP_FMAC1
  1314. const char*
  1315. SOAP_FMAC2
  1316. soap_code_list(struct soap *soap, const struct soap_code_map *code_map, long code)
  1317. { register char *t = soap->tmpbuf;
  1318. if (code_map)
  1319. { while (code_map->string)
  1320. { if (code_map->code & code)
  1321. { register const char *s = code_map->string;
  1322. if (t != soap->tmpbuf)
  1323. *t++ = ' ';
  1324. while (*s && t < soap->tmpbuf + sizeof(soap->tmpbuf) - 1)
  1325. *t++ = *s++;
  1326. if (t == soap->tmpbuf + sizeof(soap->tmpbuf) - 1)
  1327. break;
  1328. }
  1329. code_map++;
  1330. }
  1331. }
  1332. *t = '\0';
  1333. return soap->tmpbuf;
  1334. }
  1335. #endif
  1336. /******************************************************************************/
  1337. #ifndef PALM_1
  1338. static soap_wchar
  1339. soap_char(struct soap *soap)
  1340. { char tmp[8];
  1341. register int i;
  1342. register soap_wchar c;
  1343. register char *s = tmp;
  1344. for (i = 0; i < 7; i++)
  1345. { c = soap_get1(soap);
  1346. if (c == ';' || (int)c == EOF)
  1347. break;
  1348. *s++ = (char)c;
  1349. }
  1350. *s = '\0';
  1351. if (*tmp == '#')
  1352. { if (tmp[1] == 'x' || tmp[1] == 'X')
  1353. return (soap_wchar)soap_strtol(tmp + 2, NULL, 16);
  1354. return (soap_wchar)soap_strtol(tmp + 1, NULL, 10);
  1355. }
  1356. if (!strcmp(tmp, "lt"))
  1357. return '<';
  1358. if (!strcmp(tmp, "gt"))
  1359. return '>';
  1360. if (!strcmp(tmp, "amp"))
  1361. return '&';
  1362. if (!strcmp(tmp, "quot"))
  1363. return '"';
  1364. if (!strcmp(tmp, "apos"))
  1365. return '\'';
  1366. #ifndef WITH_LEAN
  1367. return (soap_wchar)soap_code_int(html_entity_codes, tmp, SOAP_UNKNOWN_CHAR);
  1368. #else
  1369. return SOAP_UNKNOWN_CHAR; /* use this to represent unknown code */
  1370. #endif
  1371. }
  1372. #endif
  1373. /******************************************************************************/
  1374. #ifdef WITH_LEAN
  1375. #ifndef PALM_1
  1376. soap_wchar
  1377. soap_get0(struct soap *soap)
  1378. { if (soap->bufidx >= soap->buflen && soap_recv(soap))
  1379. return EOF;
  1380. return (unsigned char)soap->buf[soap->bufidx];
  1381. }
  1382. #endif
  1383. #endif
  1384. /******************************************************************************/
  1385. #ifdef WITH_LEAN
  1386. #ifndef PALM_1
  1387. soap_wchar
  1388. soap_get1(struct soap *soap)
  1389. { if (soap->bufidx >= soap->buflen && soap_recv(soap))
  1390. return EOF;
  1391. return (unsigned char)soap->buf[soap->bufidx++];
  1392. }
  1393. #endif
  1394. #endif
  1395. /******************************************************************************/
  1396. #ifndef PALM_1
  1397. SOAP_FMAC1
  1398. soap_wchar
  1399. SOAP_FMAC2
  1400. soap_get(struct soap *soap)
  1401. { register soap_wchar c;
  1402. c = soap->ahead;
  1403. if (c)
  1404. { if ((int)c != EOF)
  1405. soap->ahead = 0;
  1406. }
  1407. else
  1408. c = soap_get1(soap);
  1409. while ((int)c != EOF)
  1410. { if (soap->cdata)
  1411. { if (c == ']')
  1412. { c = soap_get1(soap);
  1413. if (c == ']')
  1414. { c = soap_get0(soap);
  1415. if (c == '>')
  1416. { soap->cdata = 0;
  1417. soap_get1(soap);
  1418. c = soap_get1(soap);
  1419. }
  1420. else
  1421. { soap_unget(soap, ']');
  1422. return ']';
  1423. }
  1424. }
  1425. else
  1426. { soap_revget1(soap);
  1427. return ']';
  1428. }
  1429. }
  1430. else
  1431. return c;
  1432. }
  1433. switch (c)
  1434. { case '<':
  1435. do c = soap_get1(soap);
  1436. while (soap_blank(c));
  1437. if (c == '!' || c == '?' || c == '%')
  1438. { register int k = 1;
  1439. if (c == '!')
  1440. { c = soap_get1(soap);
  1441. if (c == '[')
  1442. { do c = soap_get1(soap);
  1443. while ((int)c != EOF && c != '[');
  1444. if ((int)c == EOF)
  1445. break;
  1446. soap->cdata = 1;
  1447. c = soap_get1(soap);
  1448. continue;
  1449. }
  1450. if (c == '-' && (c = soap_get1(soap)) == '-')
  1451. { do
  1452. { c = soap_get1(soap);
  1453. if (c == '-' && (c = soap_get1(soap)) == '-')
  1454. break;
  1455. } while ((int)c != EOF);
  1456. }
  1457. }
  1458. else if (c == '?')
  1459. c = soap_get_pi(soap);
  1460. while ((int)c != EOF)
  1461. { if (c == '<')
  1462. k++;
  1463. else if (c == '>')
  1464. { if (--k <= 0)
  1465. break;
  1466. }
  1467. c = soap_get1(soap);
  1468. }
  1469. if ((int)c == EOF)
  1470. break;
  1471. c = soap_get1(soap);
  1472. continue;
  1473. }
  1474. if (c == '/')
  1475. return SOAP_TT;
  1476. soap_revget1(soap);
  1477. return SOAP_LT;
  1478. case '>':
  1479. return SOAP_GT;
  1480. case '"':
  1481. return SOAP_QT;
  1482. case '\'':
  1483. return SOAP_AP;
  1484. case '&':
  1485. return soap_char(soap) | 0x80000000;
  1486. }
  1487. break;
  1488. }
  1489. return c;
  1490. }
  1491. #endif
  1492. /******************************************************************************/
  1493. #ifndef PALM_1
  1494. static soap_wchar
  1495. soap_get_pi(struct soap *soap)
  1496. { char buf[64];
  1497. register char *s = buf;
  1498. register int i = sizeof(buf);
  1499. register soap_wchar c = soap_getchar(soap);
  1500. /* This is a quick way to parse XML PI and we could use a callback instead to
  1501. * enable applications to intercept processing instructions */
  1502. while ((int)c != EOF && c != '?')
  1503. { if (--i > 0)
  1504. { if (soap_blank(c))
  1505. c = ' ';
  1506. *s++ = (char)c;
  1507. }
  1508. c = soap_getchar(soap);
  1509. }
  1510. *s = '\0';
  1511. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "XML PI <?%s?>\n", buf));
  1512. if (!strncmp(buf, "xml ", 4))
  1513. { s = strstr(buf, " encoding=");
  1514. if (s && s[10])
  1515. { if (!soap_tag_cmp(s + 11, "iso-8859-1*")
  1516. || !soap_tag_cmp(s + 11, "latin1*"))
  1517. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to latin1 encoding\n"));
  1518. soap->mode |= SOAP_ENC_LATIN;
  1519. }
  1520. else if (!soap_tag_cmp(s + 11, "utf-8*"))
  1521. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to utf-8 encoding\n"));
  1522. soap->mode &= ~SOAP_ENC_LATIN;
  1523. }
  1524. }
  1525. }
  1526. if ((int)c != EOF)
  1527. c = soap_getchar(soap);
  1528. return c;
  1529. }
  1530. #endif
  1531. /******************************************************************************/
  1532. #ifndef WITH_LEANER
  1533. #ifndef PALM_1
  1534. SOAP_FMAC1
  1535. int
  1536. SOAP_FMAC2
  1537. soap_move(struct soap *soap, long n)
  1538. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving %ld bytes forward\n", (long)n));
  1539. for (; n > 0; n--)
  1540. if ((int)soap_getchar(soap) == EOF)
  1541. return SOAP_EOF;
  1542. return SOAP_OK;
  1543. }
  1544. #endif
  1545. #endif
  1546. /******************************************************************************/
  1547. #ifndef WITH_LEANER
  1548. #ifndef PALM_1
  1549. SOAP_FMAC1
  1550. size_t
  1551. SOAP_FMAC2
  1552. soap_tell(struct soap *soap)
  1553. { return soap->count - soap->buflen + soap->bufidx - (soap->ahead != 0);
  1554. }
  1555. #endif
  1556. #endif
  1557. /******************************************************************************/
  1558. #ifndef PALM_1
  1559. SOAP_FMAC1
  1560. int
  1561. SOAP_FMAC2
  1562. soap_pututf8(struct soap *soap, register unsigned long c)
  1563. { char tmp[16];
  1564. if (c < 0x80 && c > 0)
  1565. { *tmp = (char)c;
  1566. return soap_send_raw(soap, tmp, 1);
  1567. }
  1568. #ifndef WITH_LEAN
  1569. if (c >= 0x80)
  1570. { register char *t = tmp;
  1571. if (c < 0x0800)
  1572. *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
  1573. else
  1574. { if (c < 0x010000)
  1575. *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
  1576. else
  1577. { if (c < 0x200000)
  1578. *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
  1579. else
  1580. { if (c < 0x04000000)
  1581. *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
  1582. else
  1583. { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
  1584. *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
  1585. }
  1586. *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
  1587. }
  1588. *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
  1589. }
  1590. *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
  1591. }
  1592. *t++ = (char)(0x80 | (c & 0x3F));
  1593. *t = '\0';
  1594. }
  1595. #else
  1596. sprintf(tmp, "&#%lu;", c);
  1597. #endif
  1598. return soap_send(soap, tmp);
  1599. }
  1600. #endif
  1601. /******************************************************************************/
  1602. #ifndef PALM_1
  1603. SOAP_FMAC1
  1604. soap_wchar
  1605. SOAP_FMAC2
  1606. soap_getutf8(struct soap *soap)
  1607. { register soap_wchar c, c1, c2, c3, c4;
  1608. c = soap->ahead;
  1609. if (c > 0x7F)
  1610. { soap->ahead = 0;
  1611. return c;
  1612. }
  1613. c = soap_get(soap);
  1614. if (c < 0x80 || (soap->mode & SOAP_ENC_LATIN))
  1615. return c;
  1616. c1 = soap_get1(soap);
  1617. if (c1 < 0x80)
  1618. { soap_revget1(soap); /* doesn't look like this is UTF8 */
  1619. return c;
  1620. }
  1621. c1 &= 0x3F;
  1622. if (c < 0xE0)
  1623. return ((soap_wchar)(c & 0x1F) << 6) | c1;
  1624. c2 = (soap_wchar)soap_get1(soap) & 0x3F;
  1625. if (c < 0xF0)
  1626. return ((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2;
  1627. c3 = (soap_wchar)soap_get1(soap) & 0x3F;
  1628. if (c < 0xF8)
  1629. return ((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3;
  1630. c4 = (soap_wchar)soap_get1(soap) & 0x3F;
  1631. if (c < 0xFC)
  1632. return ((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4;
  1633. return ((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(soap_get1(soap) & 0x3F);
  1634. }
  1635. #endif
  1636. /******************************************************************************/
  1637. #ifndef PALM_1
  1638. SOAP_FMAC1
  1639. int
  1640. SOAP_FMAC2
  1641. soap_puthex(struct soap *soap, const unsigned char *s, int n)
  1642. { char d[2];
  1643. register int i;
  1644. #ifdef WITH_DOM
  1645. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  1646. { if (!(soap->dom->data = soap_s2hex(soap, s, NULL, n)))
  1647. return soap->error;
  1648. return SOAP_OK;
  1649. }
  1650. #endif
  1651. for (i = 0; i < n; i++)
  1652. { register int m = *s++;
  1653. d[0] = (char)((m >> 4) + (m > 159 ? '7' : '0'));
  1654. m &= 0x0F;
  1655. d[1] = (char)(m + (m > 9 ? '7' : '0'));
  1656. if (soap_send_raw(soap, d, 2))
  1657. return soap->error;
  1658. }
  1659. return SOAP_OK;
  1660. }
  1661. #endif
  1662. /******************************************************************************/
  1663. #ifndef PALM_1
  1664. SOAP_FMAC1
  1665. unsigned char*
  1666. SOAP_FMAC2
  1667. soap_gethex(struct soap *soap, int *n)
  1668. {
  1669. #ifdef WITH_DOM
  1670. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  1671. { soap->dom->data = soap_string_in(soap, 0, -1, -1);
  1672. return (unsigned char*)soap_hex2s(soap, soap->dom->data, NULL, 0, n);
  1673. }
  1674. #endif
  1675. #ifdef WITH_FAST
  1676. soap->labidx = 0;
  1677. for (;;)
  1678. { register char *s;
  1679. register size_t i, k;
  1680. if (soap_append_lab(soap, NULL, 0))
  1681. return NULL;
  1682. s = soap->labbuf + soap->labidx;
  1683. k = soap->lablen - soap->labidx;
  1684. soap->labidx = soap->lablen;
  1685. for (i = 0; i < k; i++)
  1686. { register char d1, d2;
  1687. register soap_wchar c;
  1688. c = soap_get(soap);
  1689. if (soap_isxdigit(c))
  1690. { d1 = (char)c;
  1691. c = soap_get(soap);
  1692. if (soap_isxdigit(c))
  1693. d2 = (char)c;
  1694. else
  1695. { soap->error = SOAP_TYPE;
  1696. return NULL;
  1697. }
  1698. }
  1699. else
  1700. { unsigned char *p;
  1701. soap_unget(soap, c);
  1702. if (n)
  1703. *n = (int)(soap->lablen + i - k);
  1704. p = (unsigned char*)soap_malloc(soap, soap->lablen + i - k);
  1705. if (p)
  1706. memcpy(p, soap->labbuf, soap->lablen + i - k);
  1707. return p;
  1708. }
  1709. *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0');
  1710. }
  1711. }
  1712. #else
  1713. if (soap_new_block(soap) == NULL)
  1714. return NULL;
  1715. for (;;)
  1716. { register int i;
  1717. register char *s = (char*)soap_push_block(soap, NULL, SOAP_BLKLEN);
  1718. if (!s)
  1719. { soap_end_block(soap, NULL);
  1720. return NULL;
  1721. }
  1722. for (i = 0; i < SOAP_BLKLEN; i++)
  1723. { register char d1, d2;
  1724. register soap_wchar c = soap_get(soap);
  1725. if (soap_isxdigit(c))
  1726. { d1 = (char)c;
  1727. c = soap_get(soap);
  1728. if (soap_isxdigit(c))
  1729. d2 = (char)c;
  1730. else
  1731. { soap_end_block(soap, NULL);
  1732. soap->error = SOAP_TYPE;
  1733. return NULL;
  1734. }
  1735. }
  1736. else
  1737. { unsigned char *p;
  1738. soap_unget(soap, c);
  1739. if (n)
  1740. *n = (int)soap_size_block(soap, NULL, i);
  1741. p = (unsigned char*)soap_save_block(soap, NULL, 0);
  1742. return p;
  1743. }
  1744. *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0');
  1745. }
  1746. }
  1747. #endif
  1748. }
  1749. #endif
  1750. /******************************************************************************/
  1751. #ifndef PALM_1
  1752. SOAP_FMAC1
  1753. int
  1754. SOAP_FMAC2
  1755. soap_putbase64(struct soap *soap, const unsigned char *s, int n)
  1756. { register int i;
  1757. register unsigned long m;
  1758. char d[4];
  1759. if (!s)
  1760. return SOAP_OK;
  1761. #ifdef WITH_DOM
  1762. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  1763. { if (!(soap->dom->data = soap_s2base64(soap, s, NULL, n)))
  1764. return soap->error;
  1765. return SOAP_OK;
  1766. }
  1767. #endif
  1768. for (; n > 2; n -= 3, s += 3)
  1769. { m = s[0];
  1770. m = (m << 8) | s[1];
  1771. m = (m << 8) | s[2];
  1772. for (i = 4; i > 0; m >>= 6)
  1773. d[--i] = soap_base64o[m & 0x3F];
  1774. if (soap_send_raw(soap, d, 4))
  1775. return soap->error;
  1776. }
  1777. if (n > 0)
  1778. { m = 0;
  1779. for (i = 0; i < n; i++)
  1780. m = (m << 8) | *s++;
  1781. for (; i < 3; i++)
  1782. m <<= 8;
  1783. for (i++; i > 0; m >>= 6)
  1784. d[--i] = soap_base64o[m & 0x3F];
  1785. for (i = 3; i > n; i--)
  1786. d[i] = '=';
  1787. if (soap_send_raw(soap, d, 4))
  1788. return soap->error;
  1789. }
  1790. return SOAP_OK;
  1791. }
  1792. #endif
  1793. /******************************************************************************/
  1794. #ifndef PALM_1
  1795. SOAP_FMAC1
  1796. unsigned char*
  1797. SOAP_FMAC2
  1798. soap_getbase64(struct soap *soap, int *n, int malloc_flag)
  1799. {
  1800. #ifdef WITH_DOM
  1801. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  1802. { soap->dom->data = soap_string_in(soap, 0, -1, -1);
  1803. return (unsigned char*)soap_base642s(soap, soap->dom->data, NULL, 0, n);
  1804. }
  1805. #endif
  1806. #ifdef WITH_FAST
  1807. soap->labidx = 0;
  1808. for (;;)
  1809. { register size_t i, k;
  1810. register char *s;
  1811. if (soap_append_lab(soap, NULL, 2))
  1812. return NULL;
  1813. s = soap->labbuf + soap->labidx;
  1814. k = soap->lablen - soap->labidx;
  1815. soap->labidx = 3 * (soap->lablen / 3);
  1816. if (!s)
  1817. return NULL;
  1818. if (k > 2)
  1819. { for (i = 0; i < k - 2; i += 3)
  1820. { register unsigned long m = 0;
  1821. register int j = 0;
  1822. do
  1823. { register soap_wchar c = soap_get(soap);
  1824. if (c == '=' || c < 0)
  1825. { unsigned char *p;
  1826. switch (j)
  1827. { case 2:
  1828. *s++ = (char)((m >> 4) & 0xFF);
  1829. i++;
  1830. break;
  1831. case 3:
  1832. *s++ = (char)((m >> 10) & 0xFF);
  1833. *s++ = (char)((m >> 2) & 0xFF);
  1834. i += 2;
  1835. }
  1836. if (n)
  1837. *n = (int)(soap->lablen + i - k);
  1838. p = (unsigned char*)soap_malloc(soap, soap->lablen + i - k);
  1839. if (p)
  1840. memcpy(p, soap->labbuf, soap->lablen + i - k);
  1841. if (c >= 0)
  1842. { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT)
  1843. ;
  1844. }
  1845. soap_unget(soap, c);
  1846. return p;
  1847. }
  1848. c -= '+';
  1849. if (c >= 0 && c <= 79)
  1850. { register int b = soap_base64i[c];
  1851. if (b >= 64)
  1852. { soap->error = SOAP_TYPE;
  1853. return NULL;
  1854. }
  1855. m = (m << 6) + b;
  1856. j++;
  1857. }
  1858. else if (!soap_blank(c + '+'))
  1859. { soap->error = SOAP_TYPE;
  1860. return NULL;
  1861. }
  1862. } while (j < 4);
  1863. *s++ = (char)((m >> 16) & 0xFF);
  1864. *s++ = (char)((m >> 8) & 0xFF);
  1865. *s++ = (char)(m & 0xFF);
  1866. }
  1867. }
  1868. }
  1869. #else
  1870. if (soap_new_block(soap) == NULL)
  1871. return NULL;
  1872. for (;;)
  1873. { register int i;
  1874. register char *s = (char*)soap_push_block(soap, NULL, 3 * SOAP_BLKLEN); /* must be multiple of 3 */
  1875. if (!s)
  1876. { soap_end_block(soap, NULL);
  1877. return NULL;
  1878. }
  1879. for (i = 0; i < SOAP_BLKLEN; i++)
  1880. { register unsigned long m = 0;
  1881. register int j = 0;
  1882. do
  1883. { register soap_wchar c = soap_get(soap);
  1884. if (c == '=' || c < 0)
  1885. { unsigned char *p;
  1886. i *= 3;
  1887. switch (j)
  1888. { case 2:
  1889. *s++ = (char)((m >> 4) & 0xFF);
  1890. i++;
  1891. break;
  1892. case 3:
  1893. *s++ = (char)((m >> 10) & 0xFF);
  1894. *s++ = (char)((m >> 2) & 0xFF);
  1895. i += 2;
  1896. }
  1897. if (n)
  1898. *n = (int)soap_size_block(soap, NULL, i);
  1899. p = (unsigned char*)soap_save_block(soap, NULL, 0);
  1900. if (c >= 0)
  1901. { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT)
  1902. ;
  1903. }
  1904. soap_unget(soap, c);
  1905. return p;
  1906. }
  1907. c -= '+';
  1908. if (c >= 0 && c <= 79)
  1909. { int b = soap_base64i[c];
  1910. if (b >= 64)
  1911. { soap->error = SOAP_TYPE;
  1912. return NULL;
  1913. }
  1914. m = (m << 6) + b;
  1915. j++;
  1916. }
  1917. else if (!soap_blank(c))
  1918. { soap->error = SOAP_TYPE;
  1919. return NULL;
  1920. }
  1921. } while (j < 4);
  1922. *s++ = (char)((m >> 16) & 0xFF);
  1923. *s++ = (char)((m >> 8) & 0xFF);
  1924. *s++ = (char)(m & 0xFF);
  1925. }
  1926. }
  1927. #endif
  1928. }
  1929. #endif
  1930. /******************************************************************************/
  1931. #ifndef WITH_LEANER
  1932. #ifndef PALM_1
  1933. SOAP_FMAC1
  1934. int
  1935. SOAP_FMAC2
  1936. soap_xop_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options)
  1937. { /* Check MTOM xop:Include element (within hex/base64Binary) */
  1938. /* TODO: this code to be obsoleted with new import/xop.h conventions */
  1939. int body = soap->body; /* should save type too? */
  1940. if (!soap_peek_element(soap))
  1941. { if (!soap_element_begin_in(soap, "xop:Include", 0, NULL) && *soap->href)
  1942. { if (soap_dime_forward(soap, ptr, size, id, type, options))
  1943. return soap->error;
  1944. }
  1945. if (soap->body && soap_element_end_in(soap, NULL))
  1946. return soap->error;
  1947. }
  1948. soap->body = body;
  1949. return SOAP_OK;
  1950. }
  1951. #endif
  1952. #endif
  1953. /******************************************************************************/
  1954. #ifndef WITH_LEANER
  1955. #ifndef PALM_1
  1956. SOAP_FMAC1
  1957. int
  1958. SOAP_FMAC2
  1959. soap_dime_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options)
  1960. { struct soap_xlist *xp;
  1961. *ptr = NULL;
  1962. *size = 0;
  1963. *id = NULL;
  1964. *type = NULL;
  1965. *options = NULL;
  1966. if (!*soap->href)
  1967. return SOAP_OK;
  1968. *id = soap_strdup(soap, soap->href);
  1969. xp = (struct soap_xlist*)SOAP_MALLOC(soap, sizeof(struct soap_xlist));
  1970. if (!xp)
  1971. return soap->error = SOAP_EOM;
  1972. xp->next = soap->xlist;
  1973. xp->ptr = ptr;
  1974. xp->size = size;
  1975. xp->id = *id;
  1976. xp->type = type;
  1977. xp->options = options;
  1978. soap->xlist = xp;
  1979. return SOAP_OK;
  1980. }
  1981. #endif
  1982. #endif
  1983. /******************************************************************************/
  1984. #ifndef PALM_1
  1985. SOAP_FMAC1
  1986. char *
  1987. SOAP_FMAC2
  1988. soap_strdup(struct soap *soap, const char *s)
  1989. { char *t = NULL;
  1990. if (s && (t = (char*)soap_malloc(soap, strlen(s) + 1)))
  1991. strcpy(t, s);
  1992. return t;
  1993. }
  1994. #endif
  1995. /******************************************************************************/
  1996. #ifndef PALM_1
  1997. SOAP_FMAC1
  1998. wchar_t *
  1999. SOAP_FMAC2
  2000. soap_wstrdup(struct soap *soap, const wchar_t *s)
  2001. { wchar_t *t = NULL;
  2002. if (s)
  2003. { size_t n = 0;
  2004. while (s[n])
  2005. n++;
  2006. if ((t = (wchar_t*)soap_malloc(soap, sizeof(wchar_t)*(n+1))))
  2007. memcpy(t, s, sizeof(wchar_t)*(n+1));
  2008. }
  2009. return t;
  2010. }
  2011. #endif
  2012. /******************************************************************************/
  2013. #ifndef PALM_1
  2014. SOAP_FMAC1
  2015. struct soap_blist*
  2016. SOAP_FMAC2
  2017. soap_new_block(struct soap *soap)
  2018. { struct soap_blist *p;
  2019. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New block sequence (prev=%p)\n", soap->blist));
  2020. if (!(p = (struct soap_blist*)SOAP_MALLOC(soap, sizeof(struct soap_blist))))
  2021. { soap->error = SOAP_EOM;
  2022. return NULL;
  2023. }
  2024. p->next = soap->blist;
  2025. p->ptr = NULL;
  2026. p->size = 0;
  2027. soap->blist = p;
  2028. return p;
  2029. }
  2030. #endif
  2031. /******************************************************************************/
  2032. #ifndef PALM_1
  2033. SOAP_FMAC1
  2034. void*
  2035. SOAP_FMAC2
  2036. soap_push_block(struct soap *soap, struct soap_blist *b, size_t n)
  2037. { char *p;
  2038. if (!b)
  2039. b = soap->blist;
  2040. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push block of %u bytes (%u bytes total)\n", (unsigned int)n, (unsigned int)b->size + (unsigned int)n));
  2041. if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(char*) + sizeof(size_t))))
  2042. { soap->error = SOAP_EOM;
  2043. return NULL;
  2044. }
  2045. *(char**)p = b->ptr;
  2046. *(size_t*)(p + sizeof(char*)) = n;
  2047. b->ptr = p;
  2048. b->size += n;
  2049. return p + sizeof(char*) + sizeof(size_t);
  2050. }
  2051. #endif
  2052. /******************************************************************************/
  2053. #ifndef PALM_1
  2054. SOAP_FMAC1
  2055. void
  2056. SOAP_FMAC2
  2057. soap_pop_block(struct soap *soap, struct soap_blist *b)
  2058. { char *p;
  2059. if (!b)
  2060. b = soap->blist;
  2061. if (!b->ptr)
  2062. return;
  2063. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop block\n"));
  2064. p = b->ptr;
  2065. b->size -= *(size_t*)(p + sizeof(char*));
  2066. b->ptr = *(char**)p;
  2067. SOAP_FREE(soap, p);
  2068. }
  2069. #endif
  2070. /******************************************************************************/
  2071. #ifndef WITH_NOIDREF
  2072. #ifndef PALM_1
  2073. static void
  2074. soap_update_ptrs(struct soap *soap, char *start, char *end, char *p1, char *p2)
  2075. { int i;
  2076. register struct soap_ilist *ip = NULL;
  2077. register struct soap_flist *fp = NULL;
  2078. #ifndef WITH_LEANER
  2079. register struct soap_xlist *xp = NULL;
  2080. #endif
  2081. register void *p, **q;
  2082. for (i = 0; i < SOAP_IDHASH; i++)
  2083. { for (ip = soap->iht[i]; ip; ip = ip->next)
  2084. { if (ip->ptr && (char*)ip->ptr >= start && (char*)ip->ptr < end)
  2085. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", ip->id, ip->ptr, (char*)ip->ptr + (p1-p2)));
  2086. ip->ptr = (char*)ip->ptr + (p1-p2);
  2087. }
  2088. for (q = &ip->link; q; q = (void**)p)
  2089. { p = *q;
  2090. if (p && (char*)p >= start && (char*)p < end)
  2091. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Link update id='%s' %p\n", ip->id, p));
  2092. *q = (char*)p + (p1-p2);
  2093. }
  2094. }
  2095. for (q = &ip->copy; q; q = (void**)p)
  2096. { p = *q;
  2097. if (p && (char*)p >= start && (char*)p < end)
  2098. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy chain update id='%s' %p\n", ip->id, p));
  2099. *q = (char*)p + (p1-p2);
  2100. }
  2101. }
  2102. for (fp = ip->flist; fp; fp = fp->next)
  2103. { if ((char*)fp->ptr >= start && (char*)fp->ptr < end)
  2104. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy list update id='%s' %p\n", ip->id, fp));
  2105. fp->ptr = (char*)fp->ptr + (p1-p2);
  2106. }
  2107. }
  2108. }
  2109. }
  2110. #ifndef WITH_LEANER
  2111. for (xp = soap->xlist; xp; xp = xp->next)
  2112. { if (xp->ptr && (char*)xp->ptr >= start && (char*)xp->ptr < end)
  2113. { 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)));
  2114. xp->ptr = (unsigned char**)((char*)xp->ptr + (p1-p2));
  2115. xp->size = (int*)((char*)xp->size + (p1-p2));
  2116. xp->type = (char**)((char*)xp->type + (p1-p2));
  2117. xp->options = (char**)((char*)xp->options + (p1-p2));
  2118. }
  2119. }
  2120. #endif
  2121. }
  2122. #endif
  2123. #endif
  2124. /******************************************************************************/
  2125. #ifndef WITH_NOIDREF
  2126. #ifndef PALM_1
  2127. static int
  2128. soap_has_copies(struct soap *soap, register const char *start, register const char *end)
  2129. { register int i;
  2130. register struct soap_ilist *ip = NULL;
  2131. register struct soap_flist *fp = NULL;
  2132. register const char *p;
  2133. for (i = 0; i < SOAP_IDHASH; i++)
  2134. { for (ip = soap->iht[i]; ip; ip = ip->next)
  2135. { for (p = (const char*)ip->copy; p; p = *(const char**)p)
  2136. if (p >= start && p < end)
  2137. return SOAP_ERR;
  2138. for (fp = ip->flist; fp; fp = fp->next)
  2139. if ((const char*)fp->ptr >= start && (const char*)fp->ptr < end)
  2140. return SOAP_ERR;
  2141. }
  2142. }
  2143. return SOAP_OK;
  2144. }
  2145. #endif
  2146. #endif
  2147. /******************************************************************************/
  2148. #ifndef WITH_NOIDREF
  2149. #ifndef PALM_1
  2150. SOAP_FMAC1
  2151. int
  2152. SOAP_FMAC2
  2153. soap_resolve(struct soap *soap)
  2154. { register int i;
  2155. register struct soap_ilist *ip = NULL;
  2156. register struct soap_flist *fp = NULL;
  2157. short flag;
  2158. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data\n"));
  2159. for (i = 0; i < SOAP_IDHASH; i++)
  2160. { for (ip = soap->iht[i]; ip; ip = ip->next)
  2161. { if (ip->ptr)
  2162. { register void *p, **q, *r;
  2163. q = (void**)ip->link;
  2164. ip->link = NULL;
  2165. r = ip->ptr;
  2166. DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing link chain to resolve id='%s'\n", ip->id));
  2167. while (q)
  2168. { p = *q;
  2169. *q = r;
  2170. DBGLOG(TEST,SOAP_MESSAGE(fdebug, "... link %p -> %p\n", q, r));
  2171. q = (void**)p;
  2172. }
  2173. }
  2174. else if (*ip->id == '#')
  2175. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Missing data for id='%s'\n", ip->id));
  2176. /* Oracle customization */
  2177. strncpy(soap->id, ip->id + 1, sizeof(soap->id) - 1);
  2178. soap->id[sizeof(soap->id) - 1] = '\0';
  2179. return soap->error = SOAP_MISSING_ID;
  2180. }
  2181. }
  2182. }
  2183. do
  2184. { flag = 0;
  2185. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution phase\n"));
  2186. for (i = 0; i < SOAP_IDHASH; i++)
  2187. { for (ip = soap->iht[i]; ip; ip = ip->next)
  2188. { if (ip->ptr && !soap_has_copies(soap, (const char*)ip->ptr, (const char*)ip->ptr + ip->size))
  2189. { if (ip->copy)
  2190. { register void *p, **q = (void**)ip->copy;
  2191. DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing copy chain to resolve id='%s'\n", ip->id));
  2192. ip->copy = NULL;
  2193. do
  2194. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... copy %p -> %p (%u bytes)\n", ip->ptr, q, (unsigned int)ip->size));
  2195. p = *q;
  2196. memcpy(q, ip->ptr, ip->size);
  2197. q = (void**)p;
  2198. } while (q);
  2199. flag = 1;
  2200. }
  2201. for (fp = ip->flist; fp; fp = ip->flist)
  2202. { register unsigned int k = fp->level;
  2203. register void *p = ip->ptr;
  2204. 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));
  2205. while (ip->level < k)
  2206. { register void **q = (void**)soap_malloc(soap, sizeof(void*));
  2207. if (!q)
  2208. return soap->error;
  2209. *q = p;
  2210. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level, new location=%p holds=%p...\n", q, *q));
  2211. p = (void*)q;
  2212. k--;
  2213. }
  2214. if (fp->fcopy)
  2215. fp->fcopy(soap, ip->type, fp->type, fp->ptr, fp->len, p, ip->size);
  2216. else
  2217. soap_fcopy(soap, ip->type, fp->type, fp->ptr, fp->len, p, ip->size);
  2218. ip->flist = fp->next;
  2219. SOAP_FREE(soap, fp);
  2220. flag = 1;
  2221. }
  2222. }
  2223. }
  2224. }
  2225. } while (flag);
  2226. #ifdef SOAP_DEBUG
  2227. for (i = 0; i < SOAP_IDHASH; i++)
  2228. { for (ip = soap->iht[i]; ip; ip = ip->next)
  2229. { if (ip->copy || ip->flist)
  2230. { 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));
  2231. }
  2232. }
  2233. }
  2234. #endif
  2235. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution done\n"));
  2236. return SOAP_OK;
  2237. }
  2238. #endif
  2239. #endif
  2240. /******************************************************************************/
  2241. #ifndef PALM_1
  2242. SOAP_FMAC1
  2243. size_t
  2244. SOAP_FMAC2
  2245. soap_size_block(struct soap *soap, struct soap_blist *b, size_t n)
  2246. { if (!b)
  2247. b = soap->blist;
  2248. if (b->ptr)
  2249. { b->size -= *(size_t*)(b->ptr + sizeof(char*)) - n;
  2250. *(size_t*)(b->ptr + sizeof(char*)) = n;
  2251. }
  2252. return b->size;
  2253. }
  2254. #endif
  2255. /******************************************************************************/
  2256. #ifndef PALM_1
  2257. SOAP_FMAC1
  2258. char*
  2259. SOAP_FMAC2
  2260. soap_first_block(struct soap *soap, struct soap_blist *b)
  2261. { char *p, *q, *r;
  2262. if (!b)
  2263. b = soap->blist;
  2264. p = b->ptr;
  2265. if (!p)
  2266. return NULL;
  2267. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "First block\n"));
  2268. r = NULL;
  2269. do
  2270. { q = *(char**)p;
  2271. *(char**)p = r;
  2272. r = p;
  2273. p = q;
  2274. } while (p);
  2275. b->ptr = r;
  2276. return r + sizeof(char*) + sizeof(size_t);
  2277. }
  2278. #endif
  2279. /******************************************************************************/
  2280. #ifndef PALM_1
  2281. SOAP_FMAC1
  2282. char*
  2283. SOAP_FMAC2
  2284. soap_next_block(struct soap *soap, struct soap_blist *b)
  2285. { char *p;
  2286. if (!b)
  2287. b = soap->blist;
  2288. p = b->ptr;
  2289. if (p)
  2290. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Next block\n"));
  2291. b->ptr = *(char**)p;
  2292. SOAP_FREE(soap, p);
  2293. if (b->ptr)
  2294. return b->ptr + sizeof(char*) + sizeof(size_t);
  2295. }
  2296. return NULL;
  2297. }
  2298. #endif
  2299. /******************************************************************************/
  2300. #ifndef PALM_1
  2301. SOAP_FMAC1
  2302. size_t
  2303. SOAP_FMAC2
  2304. soap_block_size(struct soap *soap, struct soap_blist *b)
  2305. { if (!b)
  2306. b = soap->blist;
  2307. return *(size_t*)(b->ptr + sizeof(char*));
  2308. }
  2309. #endif
  2310. /******************************************************************************/
  2311. #ifndef PALM_1
  2312. SOAP_FMAC1
  2313. void
  2314. SOAP_FMAC2
  2315. soap_end_block(struct soap *soap, struct soap_blist *b)
  2316. { char *p, *q;
  2317. if (!b)
  2318. b = soap->blist;
  2319. if (b)
  2320. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of block sequence, free all remaining blocks\n"));
  2321. for (p = b->ptr; p; p = q)
  2322. { q = *(char**)p;
  2323. SOAP_FREE(soap, p);
  2324. }
  2325. if (soap->blist == b)
  2326. soap->blist = b->next;
  2327. else
  2328. { struct soap_blist *bp;
  2329. for (bp = soap->blist; bp; bp = bp->next)
  2330. { if (bp->next == b)
  2331. { bp->next = b->next;
  2332. break;
  2333. }
  2334. }
  2335. }
  2336. SOAP_FREE(soap, b);
  2337. }
  2338. DBGLOG(TEST, if (soap->blist) SOAP_MESSAGE(fdebug, "Restore previous block sequence\n"));
  2339. }
  2340. #endif
  2341. /******************************************************************************/
  2342. #ifndef PALM_1
  2343. SOAP_FMAC1
  2344. char*
  2345. SOAP_FMAC2
  2346. soap_save_block(struct soap *soap, struct soap_blist *b, char *p, int flag)
  2347. { register size_t n;
  2348. register char *q, *s;
  2349. if (!b)
  2350. b = soap->blist;
  2351. 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));
  2352. if (b->size)
  2353. { if (!p)
  2354. p = (char*)soap_malloc(soap, b->size);
  2355. if (p)
  2356. { for (s = p, q = soap_first_block(soap, b); q; q = soap_next_block(soap, b))
  2357. { n = soap_block_size(soap, b);
  2358. #ifndef WITH_NOIDREF
  2359. if (flag)
  2360. soap_update_ptrs(soap, q, q + n, s, q);
  2361. #endif
  2362. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy %u bytes from %p to %p\n", (unsigned int)n, q, s));
  2363. memcpy(s, q, n);
  2364. s += n;
  2365. }
  2366. }
  2367. else
  2368. soap->error = SOAP_EOM;
  2369. }
  2370. soap_end_block(soap, b);
  2371. return p;
  2372. }
  2373. #endif
  2374. /******************************************************************************/
  2375. #ifndef PALM_2
  2376. SOAP_FMAC1
  2377. char *
  2378. SOAP_FMAC2
  2379. soap_putsize(struct soap *soap, const char *type, int size)
  2380. { return soap_putsizes(soap, type, &size, 1);
  2381. }
  2382. #endif
  2383. /******************************************************************************/
  2384. #ifndef PALM_2
  2385. SOAP_FMAC1
  2386. char *
  2387. SOAP_FMAC2
  2388. soap_putsizes(struct soap *soap, const char *type, const int *size, int dim)
  2389. { return soap_putsizesoffsets(soap, type, size, NULL, dim);
  2390. }
  2391. #endif
  2392. /******************************************************************************/
  2393. #ifndef PALM_2
  2394. SOAP_FMAC1
  2395. char *
  2396. SOAP_FMAC2
  2397. soap_putsizesoffsets(struct soap *soap, const char *type, const int *size, const int *offset, int dim)
  2398. { int i;
  2399. if (!type)
  2400. return NULL;
  2401. if (soap->version == 2)
  2402. { sprintf(soap->type, "%s[%d", type, size[0]);
  2403. for (i = 1; i < dim; i++)
  2404. sprintf(soap->type + strlen(soap->type), " %d", size[i]);
  2405. }
  2406. else
  2407. { if (offset)
  2408. { sprintf(soap->type, "%s[%d", type, size[0] + offset[0]);
  2409. for (i = 1; i < dim; i++)
  2410. sprintf(soap->type + strlen(soap->type), ",%d", size[i] + offset[i]);
  2411. }
  2412. else
  2413. { sprintf(soap->type, "%s[%d", type, size[0]);
  2414. for (i = 1; i < dim; i++)
  2415. sprintf(soap->type + strlen(soap->type), ",%d", size[i]);
  2416. }
  2417. strcat(soap->type, "]");
  2418. }
  2419. return soap->type;
  2420. }
  2421. #endif
  2422. /******************************************************************************/
  2423. #ifndef PALM_2
  2424. SOAP_FMAC1
  2425. char *
  2426. SOAP_FMAC2
  2427. soap_putoffset(struct soap *soap, int offset)
  2428. { return soap_putoffsets(soap, &offset, 1);
  2429. }
  2430. #endif
  2431. /******************************************************************************/
  2432. #ifndef PALM_2
  2433. SOAP_FMAC1
  2434. char *
  2435. SOAP_FMAC2
  2436. soap_putoffsets(struct soap *soap, const int *offset, int dim)
  2437. { register int i;
  2438. sprintf(soap->arrayOffset, "[%d", offset[0]);
  2439. for (i = 1; i < dim; i++)
  2440. sprintf(soap->arrayOffset + strlen(soap->arrayOffset), ",%d", offset[i]);
  2441. strcat(soap->arrayOffset, "]");
  2442. return soap->arrayOffset;
  2443. }
  2444. #endif
  2445. /******************************************************************************/
  2446. #ifndef PALM_2
  2447. SOAP_FMAC1
  2448. int
  2449. SOAP_FMAC2
  2450. soap_size(const int *size, int dim)
  2451. { register int i, n = size[0];
  2452. for (i = 1; i < dim; i++)
  2453. n *= size[i];
  2454. return n;
  2455. }
  2456. #endif
  2457. /******************************************************************************/
  2458. #ifndef PALM_2
  2459. SOAP_FMAC1
  2460. int
  2461. SOAP_FMAC2
  2462. soap_getoffsets(const char *attr, const int *size, int *offset, int dim)
  2463. { register int i, j = 0;
  2464. if (offset)
  2465. for (i = 0; i < dim && attr && *attr; i++)
  2466. { attr++;
  2467. j *= size[i];
  2468. j += offset[i] = (int)soap_strtol(attr, NULL, 10);
  2469. attr = strchr(attr, ',');
  2470. }
  2471. else
  2472. for (i = 0; i < dim && attr && *attr; i++)
  2473. { attr++;
  2474. j *= size[i];
  2475. j += (int)soap_strtol(attr, NULL, 10);
  2476. attr = strchr(attr, ',');
  2477. }
  2478. return j;
  2479. }
  2480. #endif
  2481. /******************************************************************************/
  2482. #ifndef PALM_2
  2483. SOAP_FMAC1
  2484. int
  2485. SOAP_FMAC2
  2486. soap_getsize(const char *attr1, const char *attr2, int *j)
  2487. { register int n, k;
  2488. char *s;
  2489. *j = 0;
  2490. if (!*attr1)
  2491. return -1;
  2492. if (*attr1 == '[')
  2493. attr1++;
  2494. n = 1;
  2495. for (;;)
  2496. { k = (int)soap_strtol(attr1, &s, 10);
  2497. n *= k;
  2498. if (k < 0 || n > SOAP_MAXARRAYSIZE || s == attr1)
  2499. return -1;
  2500. attr1 = strchr(s, ',');
  2501. if (!attr1)
  2502. attr1 = strchr(s, ' ');
  2503. if (attr2 && *attr2)
  2504. { attr2++;
  2505. *j *= k;
  2506. k = (int)soap_strtol(attr2, &s, 10);
  2507. *j += k;
  2508. if (k < 0)
  2509. return -1;
  2510. attr2 = s;
  2511. }
  2512. if (!attr1)
  2513. break;
  2514. attr1++;
  2515. }
  2516. return n - *j;
  2517. }
  2518. #endif
  2519. /******************************************************************************/
  2520. #ifndef PALM_2
  2521. SOAP_FMAC1
  2522. int
  2523. SOAP_FMAC2
  2524. soap_getsizes(const char *attr, int *size, int dim)
  2525. { register int i, k, n;
  2526. if (!*attr)
  2527. return -1;
  2528. i = (int)strlen(attr);
  2529. n = 1;
  2530. do
  2531. { for (i = i-1; i >= 0; i--)
  2532. if (attr[i] == '[' || attr[i] == ',' || attr[i] == ' ')
  2533. break;
  2534. k = (int)soap_strtol(attr + i + 1, NULL, 10);
  2535. n *= size[--dim] = k;
  2536. if (k < 0 || n > SOAP_MAXARRAYSIZE)
  2537. return -1;
  2538. } while (i >= 0 && attr[i] != '[');
  2539. return n;
  2540. }
  2541. #endif
  2542. /******************************************************************************/
  2543. #ifndef PALM_2
  2544. SOAP_FMAC1
  2545. int
  2546. SOAP_FMAC2
  2547. soap_getposition(const char *attr, int *pos)
  2548. { register int i, n;
  2549. if (!*attr)
  2550. return -1;
  2551. n = 0;
  2552. i = 1;
  2553. do
  2554. { pos[n++] = (int)soap_strtol(attr + i, NULL, 10);
  2555. while (attr[i] && attr[i] != ',' && attr[i] != ']')
  2556. i++;
  2557. if (attr[i] == ',')
  2558. i++;
  2559. } while (n < SOAP_MAXDIMS && attr[i] && attr[i] != ']');
  2560. return n;
  2561. }
  2562. #endif
  2563. /******************************************************************************/
  2564. #ifndef PALM_2
  2565. SOAP_FMAC1
  2566. struct soap_nlist *
  2567. SOAP_FMAC2
  2568. soap_push_namespace(struct soap *soap, const char *id, const char *ns)
  2569. { register struct soap_nlist *np;
  2570. register struct Namespace *p;
  2571. register short i = -1;
  2572. register size_t n, k;
  2573. n = strlen(id);
  2574. k = strlen(ns) + 1;
  2575. p = soap->local_namespaces;
  2576. if (p)
  2577. { for (i = 0; p->id; p++, i++)
  2578. { if (p->ns && !strcmp(ns, p->ns))
  2579. { if (p->out)
  2580. { SOAP_FREE(soap, p->out);
  2581. p->out = NULL;
  2582. }
  2583. break;
  2584. }
  2585. if (p->out)
  2586. { if (!strcmp(ns, p->out))
  2587. break;
  2588. }
  2589. else if (p->in)
  2590. { if (!soap_tag_cmp(ns, p->in))
  2591. { if ((p->out = (char*)SOAP_MALLOC(soap, k)))
  2592. strcpy(p->out, ns);
  2593. break;
  2594. }
  2595. }
  2596. }
  2597. if (!p || !p->id)
  2598. i = -1;
  2599. }
  2600. if (i >= 0)
  2601. k = 0;
  2602. np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k);
  2603. if (!np)
  2604. { soap->error = SOAP_EOM;
  2605. return NULL;
  2606. }
  2607. np->next = soap->nlist;
  2608. soap->nlist = np;
  2609. np->level = soap->level;
  2610. np->index = i;
  2611. strcpy(np->id, id);
  2612. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push namespace binding (level=%u) '%s' '%s'\n", soap->level, id, ns));
  2613. if (i < 0)
  2614. { np->ns = strcpy(np->id + n + 1, ns);
  2615. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push NOT OK: no match found for '%s' in namespace mapping table (added to stack anyway)\n", ns));
  2616. }
  2617. else
  2618. { np->ns = NULL;
  2619. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push OK ('%s' matches '%s' in namespace table)\n", id, p->id));
  2620. }
  2621. return np;
  2622. }
  2623. #endif
  2624. /******************************************************************************/
  2625. #ifndef PALM_2
  2626. SOAP_FMAC1
  2627. void
  2628. SOAP_FMAC2
  2629. soap_pop_namespace(struct soap *soap)
  2630. { register struct soap_nlist *np, *nq;
  2631. for (np = soap->nlist; np && np->level >= soap->level; np = nq)
  2632. { nq = np->next;
  2633. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop namespace binding (level=%u) '%s'\n", soap->level, np->id));
  2634. SOAP_FREE(soap, np);
  2635. }
  2636. soap->nlist = np;
  2637. }
  2638. #endif
  2639. /******************************************************************************/
  2640. #ifndef PALM_2
  2641. SOAP_FMAC1
  2642. int
  2643. SOAP_FMAC2
  2644. soap_match_namespace(struct soap *soap, const char *id1, const char *id2, size_t n1, size_t n2)
  2645. { register struct soap_nlist *np = soap->nlist;
  2646. while (np && (strncmp(np->id, id1, n1) || np->id[n1]))
  2647. np = np->next;
  2648. if (np)
  2649. { if (!(soap->mode & SOAP_XML_IGNORENS))
  2650. if (np->index < 0
  2651. || (soap->local_namespaces[np->index].id
  2652. && (strncmp(soap->local_namespaces[np->index].id, id2, n2)
  2653. || soap->local_namespaces[np->index].id[n2])))
  2654. return SOAP_NAMESPACE;
  2655. return SOAP_OK;
  2656. }
  2657. if (n1 == 0)
  2658. return SOAP_NAMESPACE;
  2659. if ((n1 == 3 && n1 == n2 && !strncmp(id1, "xml", 3) && !strncmp(id1, id2, 3))
  2660. || (soap->mode & SOAP_XML_IGNORENS))
  2661. return SOAP_OK;
  2662. return soap->error = SOAP_SYNTAX_ERROR;
  2663. }
  2664. #endif
  2665. /******************************************************************************/
  2666. #ifndef PALM_2
  2667. SOAP_FMAC1
  2668. const char*
  2669. SOAP_FMAC2
  2670. soap_current_namespace(struct soap *soap, const char *tag)
  2671. { register struct soap_nlist *np;
  2672. register const char *s;
  2673. if (!tag || !strncmp(tag, "xml", 3))
  2674. return NULL;
  2675. np = soap->nlist;
  2676. if (!(s = strchr(tag, ':')))
  2677. { while (np && *np->id) /* find default namespace, if present */
  2678. np = np->next;
  2679. }
  2680. else
  2681. { while (np && (strncmp(np->id, tag, s - tag) || np->id[s - tag]))
  2682. np = np->next;
  2683. if (!np)
  2684. soap->error = SOAP_NAMESPACE;
  2685. }
  2686. if (np)
  2687. { if (np->index >= 0)
  2688. return soap->namespaces[np->index].ns;
  2689. if (np->ns)
  2690. return soap_strdup(soap, np->ns);
  2691. }
  2692. return NULL;
  2693. }
  2694. #endif
  2695. /******************************************************************************/
  2696. #ifndef PALM_2
  2697. SOAP_FMAC1
  2698. int
  2699. SOAP_FMAC2
  2700. soap_tag_cmp(const char *s, const char *t)
  2701. { for (;;)
  2702. { register int c1 = *s;
  2703. register int c2 = *t;
  2704. if (!c1 || c1 == '"')
  2705. break;
  2706. if (c2 != '-')
  2707. { if (c1 != c2)
  2708. { if (c1 >= 'A' && c1 <= 'Z')
  2709. c1 += 'a' - 'A';
  2710. if (c2 >= 'A' && c2 <= 'Z')
  2711. c2 += 'a' - 'A';
  2712. }
  2713. if (c1 != c2)
  2714. { if (c2 != '*')
  2715. return 1;
  2716. c2 = *++t;
  2717. if (!c2)
  2718. return 0;
  2719. if (c2 >= 'A' && c2 <= 'Z')
  2720. c2 += 'a' - 'A';
  2721. for (;;)
  2722. { c1 = *s;
  2723. if (!c1 || c1 == '"')
  2724. break;
  2725. if (c1 >= 'A' && c1 <= 'Z')
  2726. c1 += 'a' - 'A';
  2727. if (c1 == c2 && !soap_tag_cmp(s + 1, t + 1))
  2728. return 0;
  2729. s++;
  2730. }
  2731. break;
  2732. }
  2733. }
  2734. s++;
  2735. t++;
  2736. }
  2737. if (*t == '*' && !t[1])
  2738. return 0;
  2739. return *t;
  2740. }
  2741. #endif
  2742. /******************************************************************************/
  2743. #ifndef PALM_2
  2744. SOAP_FMAC1
  2745. int
  2746. SOAP_FMAC2
  2747. soap_match_tag(struct soap *soap, const char *tag1, const char *tag2)
  2748. { register const char *s, *t;
  2749. register int err;
  2750. if (!tag1 || !tag2 || !*tag2)
  2751. return SOAP_OK;
  2752. s = strchr(tag1, ':');
  2753. t = strchr(tag2, ':');
  2754. if (t)
  2755. { if (s)
  2756. { if (t[1] && SOAP_STRCMP(s + 1, t + 1))
  2757. return SOAP_TAG_MISMATCH;
  2758. if (t != tag2 && (err = soap_match_namespace(soap, tag1, tag2, s - tag1, t - tag2)))
  2759. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2));
  2760. if (err == SOAP_NAMESPACE)
  2761. return SOAP_TAG_MISMATCH;
  2762. return err;
  2763. }
  2764. }
  2765. else if (SOAP_STRCMP(tag1, t + 1))
  2766. { return SOAP_TAG_MISMATCH;
  2767. }
  2768. else if (t != tag2 && (err = soap_match_namespace(soap, tag1, tag2, 0, t - tag2)))
  2769. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2));
  2770. if (err == SOAP_NAMESPACE)
  2771. return SOAP_TAG_MISMATCH;
  2772. return err;
  2773. }
  2774. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags and (default) namespaces match: '%s' '%s'\n", tag1, tag2));
  2775. return SOAP_OK;
  2776. }
  2777. if (s)
  2778. { if (SOAP_STRCMP(s + 1, tag2))
  2779. return SOAP_TAG_MISMATCH;
  2780. }
  2781. else if (SOAP_STRCMP(tag1, tag2))
  2782. return SOAP_TAG_MISMATCH;
  2783. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags match: '%s' '%s'\n", tag1, tag2));
  2784. return SOAP_OK;
  2785. }
  2786. #endif
  2787. /******************************************************************************/
  2788. #ifndef PALM_2
  2789. SOAP_FMAC1
  2790. int
  2791. SOAP_FMAC2
  2792. soap_match_array(struct soap *soap, const char *type)
  2793. { if (*soap->arrayType)
  2794. if (soap_match_tag(soap, soap->arrayType, type)
  2795. && soap_match_tag(soap, soap->arrayType, "xsd:anyType")
  2796. && soap_match_tag(soap, soap->arrayType, "xsd:ur-type")
  2797. )
  2798. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array type mismatch: '%s' '%s'\n", soap->arrayType, type));
  2799. return SOAP_TAG_MISMATCH;
  2800. }
  2801. return SOAP_OK;
  2802. }
  2803. #endif
  2804. /******************************************************************************\
  2805. *
  2806. * SSL/TLS
  2807. *
  2808. \******************************************************************************/
  2809. /******************************************************************************/
  2810. #ifdef WITH_OPENSSL
  2811. #ifndef PALM_2
  2812. SOAP_FMAC1
  2813. int
  2814. SOAP_FMAC2
  2815. soap_rand()
  2816. { unsigned char buf[4];
  2817. if (!soap_ssl_init_done)
  2818. soap_ssl_init();
  2819. RAND_pseudo_bytes(buf, 4);
  2820. return *(int*)buf;
  2821. }
  2822. #endif
  2823. #endif
  2824. /******************************************************************************/
  2825. #ifdef WITH_OPENSSL
  2826. #ifndef PALM_2
  2827. SOAP_FMAC1
  2828. int
  2829. SOAP_FMAC2
  2830. 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)
  2831. { int err;
  2832. soap->keyfile = keyfile;
  2833. soap->password = password;
  2834. soap->cafile = cafile;
  2835. soap->capath = capath;
  2836. soap->crlfile = NULL;
  2837. soap->dhfile = dhfile;
  2838. soap->randfile = randfile;
  2839. soap->ssl_flags = flags | (dhfile == NULL ? SOAP_SSL_RSA : 0);
  2840. if (!(err = soap->fsslauth(soap)))
  2841. { if (sid)
  2842. SSL_CTX_set_session_id_context(soap->ctx, (unsigned char*)sid, (unsigned int)strlen(sid));
  2843. else
  2844. SSL_CTX_set_session_cache_mode(soap->ctx, SSL_SESS_CACHE_OFF);
  2845. }
  2846. return err;
  2847. }
  2848. #endif
  2849. #endif
  2850. /******************************************************************************/
  2851. #ifdef WITH_OPENSSL
  2852. #ifndef PALM_2
  2853. SOAP_FMAC1
  2854. int
  2855. SOAP_FMAC2
  2856. 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)
  2857. { soap->keyfile = keyfile;
  2858. soap->password = password;
  2859. soap->cafile = cafile;
  2860. soap->capath = capath;
  2861. soap->dhfile = NULL;
  2862. soap->ssl_flags = flags;
  2863. soap->randfile = randfile;
  2864. soap->fsslverify = (flags & SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE) == 0 ? ssl_verify_callback : ssl_verify_callback_allow_expired_certificate;
  2865. return soap->fsslauth(soap);
  2866. }
  2867. #endif
  2868. #endif
  2869. /******************************************************************************/
  2870. #ifdef WITH_OPENSSL
  2871. #ifndef PALM_2
  2872. SOAP_FMAC1
  2873. void
  2874. SOAP_FMAC2
  2875. soap_ssl_init()
  2876. { /* Note: for MT systems, the main program MUST call soap_ssl_init() before any threads are started */
  2877. if (!soap_ssl_init_done)
  2878. { soap_ssl_init_done = 1;
  2879. SSL_library_init();
  2880. #ifndef WITH_LEAN
  2881. SSL_load_error_strings();
  2882. #endif
  2883. if (!RAND_load_file("/dev/urandom", 1024))
  2884. { char buf[1024];
  2885. RAND_seed(buf, sizeof(buf));
  2886. while (!RAND_status())
  2887. { int r = rand();
  2888. RAND_seed(&r, sizeof(int));
  2889. }
  2890. }
  2891. }
  2892. }
  2893. #endif
  2894. #endif
  2895. /******************************************************************************/
  2896. #ifdef WITH_OPENSSL
  2897. #ifndef PALM_1
  2898. SOAP_FMAC1
  2899. const char *
  2900. SOAP_FMAC2
  2901. soap_ssl_error(struct soap *soap, int ret)
  2902. { int err = SSL_get_error(soap->ssl, ret);
  2903. const char *msg = soap_code_str(h_ssl_error_codes, err);
  2904. size_t msgbufsize = sizeof(soap->msgbuf);
  2905. if (msg)
  2906. { /* Oracle customization */
  2907. strncpy(soap->msgbuf, msg, msgbufsize - 1);
  2908. soap->msgbuf[msgbufsize - 1] = '\0';
  2909. }
  2910. else
  2911. return ERR_error_string(err, soap->msgbuf);
  2912. if (ERR_peek_error())
  2913. { unsigned long r;
  2914. /* Oracle customization */
  2915. if (strlen(soap->msgbuf) < (msgbufsize-1))
  2916. strcat(soap->msgbuf, "\n");
  2917. else
  2918. soap->msgbuf[msgbufsize - 2] = '\n';
  2919. while ((r = ERR_get_error()))
  2920. ERR_error_string_n(r, soap->msgbuf + strlen(soap->msgbuf), sizeof(soap->msgbuf) - strlen(soap->msgbuf));
  2921. }
  2922. else
  2923. { switch (ret)
  2924. { case 0:
  2925. {
  2926. /* Oracle customization -- display SSL error code and string at the end */
  2927. int myerrno = errno;
  2928. unsigned long ec = ERR_get_error();
  2929. sprintf(soap->msgbuf,
  2930. "EOF was observed that violates the protocol. The client probably provided invalid authentication information. SSL error code is %s. ",
  2931. msg);
  2932. if (ec != 0)
  2933. {
  2934. /* display the next error string in the error queue */
  2935. ERR_error_string_n(ec, soap->msgbuf + strlen(soap->msgbuf),
  2936. sizeof(soap->msgbuf) - strlen(soap->msgbuf));
  2937. if (sizeof(soap->msgbuf) - strlen(soap->msgbuf) > 2)
  2938. {
  2939. strcat(soap->msgbuf, ". ");
  2940. }
  2941. }
  2942. if (myerrno != 0)
  2943. {
  2944. /* display system error too */
  2945. char *mystrerror = strerror(myerrno);
  2946. if (strlen(mystrerror)
  2947. < (sizeof(soap->msgbuf) - strlen(soap->msgbuf)))
  2948. {
  2949. strncat(soap->msgbuf + strlen(soap->msgbuf), mystrerror,
  2950. strlen(mystrerror));
  2951. }
  2952. else
  2953. {
  2954. strncat(soap->msgbuf + strlen(soap->msgbuf), mystrerror,
  2955. (sizeof(soap->msgbuf) - strlen(soap->msgbuf)));
  2956. }
  2957. soap->msgbuf[sizeof(soap->msgbuf) - 1] = '\0';
  2958. }
  2959. }
  2960. break;
  2961. case -1:
  2962. sprintf(soap->msgbuf, "Error observed by underlying BIO: %s", strerror(errno));
  2963. break;
  2964. }
  2965. }
  2966. return soap->msgbuf;
  2967. }
  2968. #endif
  2969. #endif
  2970. /******************************************************************************/
  2971. #ifdef WITH_OPENSSL
  2972. #ifndef PALM_1
  2973. static int
  2974. ssl_password(char *buf, int num, int rwflag, void *userdata)
  2975. { if (num < (int)strlen((char*)userdata) + 1)
  2976. return 0;
  2977. return (int)strlen(strcpy(buf, (char*)userdata));
  2978. }
  2979. #endif
  2980. #endif
  2981. /******************************************************************************/
  2982. #ifdef WITH_OPENSSL
  2983. #ifndef PALM_1
  2984. /*
  2985. static int
  2986. */
  2987. int
  2988. ssl_auth_init(struct soap *soap)
  2989. { long flags;
  2990. int mode;
  2991. if (!soap_ssl_init_done)
  2992. soap_ssl_init();
  2993. ERR_clear_error();
  2994. if (!soap->ctx)
  2995. { if (!(soap->ctx = SSL_CTX_new(SSLv23_method())))
  2996. return soap_set_receiver_error(soap, "SSL error", "Can't setup context", SOAP_SSL_ERROR);
  2997. /* The following alters the behavior of SSL read/write: */
  2998. #if 0
  2999. SSL_CTX_set_mode(soap->ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY);
  3000. #endif
  3001. }
  3002. //
  3003. // Oracle customization
  3004. //
  3005. // added SSL_CTX_set_cipher_list call to restrict the cipher suite to RSA-2048/AES
  3006. // TLS_RSA_WITH_AES_256_CBC_SHA is defined in RFC 3268
  3007. // also see http://www.openssl.org/docs/apps/ciphers.html
  3008. //
  3009. if (!SSL_CTX_set_cipher_list(soap->ctx, "AES256-SHA"))
  3010. return soap_set_receiver_error(soap, "SSL error", "Cannot set cipher suite", SOAP_SSL_ERROR);
  3011. if (soap->randfile)
  3012. { if (!RAND_load_file(soap->randfile, -1))
  3013. return soap_set_receiver_error(soap, "SSL error", "Can't load randomness", SOAP_SSL_ERROR);
  3014. }
  3015. if (soap->cafile || soap->capath)
  3016. { if (!SSL_CTX_load_verify_locations(soap->ctx, soap->cafile, soap->capath))
  3017. return soap_set_receiver_error(soap, "SSL error", "Can't read CA file and directory", SOAP_SSL_ERROR);
  3018. if (soap->cafile && (soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
  3019. SSL_CTX_set_client_CA_list(soap->ctx, SSL_load_client_CA_file(soap->cafile));
  3020. }
  3021. if (!(soap->ssl_flags & SOAP_SSL_NO_DEFAULT_CA_PATH))
  3022. { if (!SSL_CTX_set_default_verify_paths(soap->ctx))
  3023. return soap_set_receiver_error(soap, "SSL error", "Can't read default CA file and/or directory", SOAP_SSL_ERROR);
  3024. }
  3025. /* This code assumes a typical scenario, see alternative code below */
  3026. if (soap->keyfile)
  3027. { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile))
  3028. return soap_set_receiver_error(soap, "SSL error", "Can't read certificate key file", SOAP_SSL_ERROR);
  3029. if (soap->password)
  3030. { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password);
  3031. SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password);
  3032. }
  3033. if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM))
  3034. return soap_set_receiver_error(soap, "SSL error", "Can't read key file", SOAP_SSL_ERROR);
  3035. }
  3036. /* Suggested alternative approach to check the key file for certs (cafile=NULL):*/
  3037. #if 0
  3038. if (soap->password)
  3039. { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password);
  3040. SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password);
  3041. }
  3042. if (!soap->cafile || !SSL_CTX_use_certificate_chain_file(soap->ctx, soap->cafile))
  3043. { if (soap->keyfile)
  3044. { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile))
  3045. return soap_set_receiver_error(soap, "SSL error", "Can't read certificate or key file", SOAP_SSL_ERROR);
  3046. if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM))
  3047. return soap_set_receiver_error(soap, "SSL error", "Can't read key file", SOAP_SSL_ERROR);
  3048. }
  3049. }
  3050. #endif
  3051. if ((soap->ssl_flags & SOAP_SSL_RSA))
  3052. {
  3053. /*
  3054. Oracle customization for OpenSSL 0.9.8 removal of deprecated function usage: RSA_generate_key
  3055. */
  3056. #ifdef OPENSSL_NO_DEPRECATED
  3057. RSA *rsa = RSA_new();
  3058. if (!rsa)
  3059. {
  3060. return soap_set_receiver_error(soap, "SSL error", "Can't allocate RSA struct", SOAP_SSL_ERROR);
  3061. }
  3062. BIGNUM *e = BN_new();
  3063. if (!e)
  3064. {
  3065. RSA_free(rsa);
  3066. return soap_set_receiver_error(soap, "SSL error", "Can't allocate BIGNUM", SOAP_SSL_ERROR);
  3067. }
  3068. if (!BN_set_word(e, RSA_F4 ))
  3069. {
  3070. RSA_free(rsa);
  3071. BN_free(e);
  3072. return soap_set_receiver_error(soap, "SSL error", "Can't set BIGNUM value", SOAP_SSL_ERROR);
  3073. }
  3074. #if OPENSSL_VERSION_NUMBER > 0x00908000L
  3075. if (!RSA_generate_key_ex(rsa, 1024, e, NULL))
  3076. #else
  3077. if (( rsa = RSA_generate_key(1024, RSA_F4, NULL, NULL)) == NULL )
  3078. #endif
  3079. {
  3080. RSA_free(rsa);
  3081. BN_free(e);
  3082. return soap_set_receiver_error(soap, "SSL error", "Can't set RSA key", SOAP_SSL_ERROR);
  3083. }
  3084. #else
  3085. RSA *rsa = RSA_generate_key(1024, RSA_F4, NULL, NULL);
  3086. #endif
  3087. if (!SSL_CTX_set_tmp_rsa(soap->ctx, rsa))
  3088. { if (rsa)
  3089. RSA_free(rsa);
  3090. /*
  3091. Oracle customization for OpenSSL 0.9.8 removal of deprecated function usage: RSA_generate_key
  3092. */
  3093. #ifdef OPENSSL_NO_DEPRECATED
  3094. BN_free(e);
  3095. #endif
  3096. return soap_set_receiver_error(soap, "SSL error", "Can't set RSA key", SOAP_SSL_ERROR);
  3097. }
  3098. RSA_free(rsa);
  3099. /*
  3100. Oracle customization for OpenSSL 0.9.8 removal of deprecated function usage: RSA_generate_key
  3101. */
  3102. #ifdef OPENSSL_NO_DEPRECATED
  3103. BN_free(e);
  3104. #endif
  3105. }
  3106. else if (soap->dhfile)
  3107. {
  3108. DH *dh = 0;
  3109. #ifdef OPENSSL_NO_DEPRECATED
  3110. DH dhrec;
  3111. #endif
  3112. char *s;
  3113. int n = (int)soap_strtoul(soap->dhfile, &s, 10);
  3114. /* if dhfile is numeric, treat it as a key length to generate DH params which can take a while */
  3115. if (n >= 512 && s && *s == '\0') {
  3116. #if !defined(OPENSSL_NO_DEPRECATED) || OPENSSL_VERSION_NUMBER < 0x00908000L
  3117. dh = DH_generate_parameters(n, 2/*or 5*/, NULL, NULL);
  3118. #else
  3119. if (DH_generate_parameters_ex(&dhrec, n, 2/*or 5*/, NULL) == 0)
  3120. dh = &dhrec;
  3121. else
  3122. return soap_set_receiver_error(soap, "SSL error", "Can't compute DH params", SOAP_SSL_ERROR);
  3123. #endif
  3124. }
  3125. else
  3126. { BIO *bio;
  3127. bio = BIO_new_file(soap->dhfile, "r");
  3128. if (!bio)
  3129. return soap_set_receiver_error(soap, "SSL error", "Can't read DH file", SOAP_SSL_ERROR);
  3130. dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
  3131. BIO_free(bio);
  3132. }
  3133. if (!dh || DH_check(dh, &n) != 1 || SSL_CTX_set_tmp_dh(soap->ctx, dh) < 0)
  3134. {
  3135. #ifndef OPENSSL_NO_DEPRECATED
  3136. if (dh)
  3137. DH_free(dh);
  3138. #endif
  3139. return soap_set_receiver_error(soap, "SSL error", "Can't set DH parameters", SOAP_SSL_ERROR);
  3140. }
  3141. #ifndef OPENSSL_NO_DEPRECATED
  3142. DH_free(dh);
  3143. #endif
  3144. }
  3145. //
  3146. // Oracle customization
  3147. //
  3148. // Added SSL_OP_NO_SSLv3 to force use of TLS
  3149. // Added SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG to prevent forced downgrade
  3150. // of security level
  3151. flags = ((SSL_OP_ALL & ~SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG) | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
  3152. flags = (SSL_OP_ALL | SSL_OP_NO_SSLv2);
  3153. if ((soap->ssl_flags & SOAP_SSLv3))
  3154. flags |= SSL_OP_NO_TLSv1;
  3155. if ((soap->ssl_flags & SOAP_TLSv1))
  3156. flags |= SSL_OP_NO_SSLv3;
  3157. #ifdef SSL_OP_NO_TICKET
  3158. /* TLS extension is enabled by default in OPENSSL v0.9.8k
  3159. Disable it by adding SSL_OP_NO_TICKET */
  3160. flags |= SSL_OP_NO_TICKET;
  3161. #endif
  3162. SSL_CTX_set_options(soap->ctx, flags);
  3163. if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
  3164. mode = (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
  3165. else if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION))
  3166. mode = SSL_VERIFY_PEER;
  3167. else
  3168. mode = SSL_VERIFY_NONE;
  3169. SSL_CTX_set_verify(soap->ctx, mode, soap->fsslverify);
  3170. #if (OPENSSL_VERSION_NUMBER < 0x00905100L)
  3171. SSL_CTX_set_verify_depth(soap->ctx, 1);
  3172. #else
  3173. SSL_CTX_set_verify_depth(soap->ctx, 9);
  3174. #endif
  3175. return SOAP_OK;
  3176. }
  3177. #endif
  3178. #endif
  3179. /******************************************************************************/
  3180. #ifdef WITH_OPENSSL
  3181. #ifndef PALM_1
  3182. static int
  3183. ssl_verify_callback(int ok, X509_STORE_CTX *store)
  3184. {
  3185. #ifdef SOAP_DEBUG
  3186. if (!ok)
  3187. { char data[256];
  3188. X509 *cert = X509_STORE_CTX_get_current_cert(store);
  3189. 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)));
  3190. X509_NAME_oneline(X509_get_issuer_name(cert), data, sizeof(data));
  3191. fprintf(stderr, "certificate issuer %s\n", data);
  3192. X509_NAME_oneline(X509_get_subject_name(cert), data, sizeof(data));
  3193. fprintf(stderr, "certificate subject %s\n", data);
  3194. }
  3195. #endif
  3196. /* Note: return 1 to continue, but unsafe progress will be terminated by SSL */
  3197. return ok;
  3198. }
  3199. #endif
  3200. #endif
  3201. /******************************************************************************/
  3202. #ifdef WITH_OPENSSL
  3203. #ifndef PALM_1
  3204. static int
  3205. ssl_verify_callback_allow_expired_certificate(int ok, X509_STORE_CTX *store)
  3206. { ok = ssl_verify_callback(ok, store);
  3207. if (ok == 0 && X509_STORE_CTX_get_error(store) == X509_V_ERR_CERT_HAS_EXPIRED)
  3208. {
  3209. #ifdef SOAP_DEBUG
  3210. fprintf(stderr, "ignoring certificate expiration\n");
  3211. #endif
  3212. X509_STORE_CTX_set_error(store, X509_V_OK);
  3213. ok = 1;
  3214. }
  3215. /* Note: return 1 to continue, but unsafe progress will be terminated by SSL */
  3216. return ok;
  3217. }
  3218. #endif
  3219. #endif
  3220. /******************************************************************************/
  3221. #ifdef WITH_OPENSSL
  3222. #ifndef WITH_NOIO
  3223. #ifndef PALM_1
  3224. SOAP_FMAC1
  3225. int
  3226. SOAP_FMAC2
  3227. soap_ssl_accept(struct soap *soap)
  3228. { BIO *bio;
  3229. int retries, r, s;
  3230. if (!soap_valid_socket(soap->socket))
  3231. return soap_set_receiver_error(soap, "SSL error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR);
  3232. if (!soap->ctx && (soap->error = soap->fsslauth(soap)))
  3233. return SOAP_SSL_ERROR;
  3234. if (!soap->ssl)
  3235. { soap->ssl = SSL_new(soap->ctx);
  3236. if (!soap->ssl)
  3237. return soap_set_receiver_error(soap, "SSL error", "SSL_new() failed in soap_ssl_accept()", SOAP_SSL_ERROR);
  3238. }
  3239. else
  3240. SSL_clear(soap->ssl);
  3241. soap->imode |= SOAP_ENC_SSL;
  3242. soap->omode |= SOAP_ENC_SSL;
  3243. /* Set SSL sockets to non-blocking */
  3244. SOAP_SOCKNONBLOCK(soap->socket)
  3245. bio = BIO_new_socket((int)soap->socket, BIO_NOCLOSE);
  3246. SSL_set_bio(soap->ssl, bio, bio);
  3247. retries = 100; /* SSL_accept timeout: 10 sec retries, 100 times 0.1 sec */
  3248. #if defined(WITH_OPENSSL) && defined(KMS_SERVER)
  3249. /* Oracle customization for Ultra 2 KMS Server */
  3250. if (soap->ssl_accept_timeout > 0 )
  3251. {
  3252. retries = 10 * soap->ssl_accept_timeout;
  3253. }
  3254. #endif
  3255. while ((r = SSL_accept(soap->ssl)) <= 0)
  3256. { int err = SSL_get_error(soap->ssl, r);
  3257. if (err == SSL_ERROR_WANT_ACCEPT || err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
  3258. { if (err == SSL_ERROR_WANT_READ)
  3259. s = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000);
  3260. else
  3261. s = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000);
  3262. if (s < 0 && soap->errnum != SOAP_EINTR)
  3263. break;
  3264. }
  3265. else
  3266. { soap->errnum = soap_socket_errno(soap->socket);
  3267. break;
  3268. }
  3269. if (retries-- <= 0)
  3270. break;
  3271. }
  3272. if (r <= 0)
  3273. { soap_set_receiver_error(soap, soap_ssl_error(soap, r), "SSL_accept() failed in soap_ssl_accept()", SOAP_SSL_ERROR);
  3274. soap_closesock(soap);
  3275. return SOAP_SSL_ERROR;
  3276. }
  3277. if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
  3278. { X509 *peer;
  3279. int err;
  3280. if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK)
  3281. { soap_closesock(soap);
  3282. 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);
  3283. }
  3284. peer = SSL_get_peer_certificate(soap->ssl);
  3285. if (!peer)
  3286. { soap_closesock(soap);
  3287. return soap_set_sender_error(soap, "SSL error", "No SSL certificate was presented by the peer in soap_ssl_accept()", SOAP_SSL_ERROR);
  3288. }
  3289. X509_free(peer);
  3290. }
  3291. return SOAP_OK;
  3292. }
  3293. #endif
  3294. #endif
  3295. #endif
  3296. /******************************************************************************\
  3297. *
  3298. * TCP/UDP [SSL/TLS] IPv4 and IPv6
  3299. *
  3300. \******************************************************************************/
  3301. /******************************************************************************/
  3302. #ifndef WITH_NOIO
  3303. #ifndef PALM_1
  3304. static int
  3305. tcp_init(struct soap *soap)
  3306. { soap->errmode = 1;
  3307. #ifdef WIN32
  3308. if (tcp_done)
  3309. return 0;
  3310. else
  3311. { WSADATA w;
  3312. if (WSAStartup(MAKEWORD(1, 1), &w))
  3313. return -1;
  3314. tcp_done = 1;
  3315. }
  3316. #endif
  3317. return 0;
  3318. }
  3319. #endif
  3320. #endif
  3321. /******************************************************************************/
  3322. #ifndef WITH_NOIO
  3323. #ifndef PALM_1
  3324. static const char*
  3325. tcp_error(struct soap *soap)
  3326. { register const char *msg = NULL;
  3327. switch (soap->errmode)
  3328. { case 0:
  3329. msg = soap_strerror(soap);
  3330. break;
  3331. case 1:
  3332. msg = "WSAStartup failed";
  3333. break;
  3334. case 2:
  3335. {
  3336. #ifndef WITH_LEAN
  3337. msg = soap_code_str(h_error_codes, soap->errnum);
  3338. if (!msg)
  3339. #endif
  3340. { sprintf(soap->msgbuf, "TCP/UDP IP error %d", soap->errnum);
  3341. msg = soap->msgbuf;
  3342. }
  3343. }
  3344. }
  3345. return msg;
  3346. }
  3347. #endif
  3348. #endif
  3349. /******************************************************************************/
  3350. #ifndef WITH_IPV6
  3351. #ifndef WITH_NOIO
  3352. #ifndef PALM_1
  3353. static int
  3354. tcp_gethost(struct soap *soap, const char *addr, struct in_addr *inaddr)
  3355. { soap_int32 iadd = -1;
  3356. struct hostent hostent, *host = &hostent;
  3357. #ifdef VXWORKS
  3358. int hostint;
  3359. /* inet_addr(), and hostGetByName() expect "char *"; addr is a "const char *". */
  3360. iadd = inet_addr((char*)addr);
  3361. #else
  3362. #if defined(_AIX43) || ((defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R))
  3363. struct hostent_data ht_data;
  3364. #endif
  3365. #ifdef AS400
  3366. iadd = inet_addr((void*)addr);
  3367. #else
  3368. iadd = inet_addr(addr);
  3369. #endif
  3370. #endif
  3371. if (iadd != -1)
  3372. { memcpy(inaddr, &iadd, sizeof(iadd));
  3373. return SOAP_OK;
  3374. }
  3375. #if defined(__GLIBC__) || (defined(HAVE_GETHOSTBYNAME_R) && (defined(FREEBSD) || defined(__FreeBSD__)))
  3376. if (gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &host, &soap->errnum) < 0)
  3377. host = NULL;
  3378. #elif defined(_AIX43) || ((defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R))
  3379. memset((void*)&ht_data, 0, sizeof(ht_data));
  3380. if (gethostbyname_r(addr, &hostent, &ht_data) < 0)
  3381. { host = NULL;
  3382. soap->errnum = h_errno;
  3383. }
  3384. #elif defined(HAVE_GETHOSTBYNAME_R)
  3385. host = gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &soap->errnum);
  3386. #elif defined(VXWORKS)
  3387. /* If the DNS resolver library resolvLib has been configured in the vxWorks
  3388. * image, a query for the host IP address is sent to the DNS server, if the
  3389. * name was not found in the local host table. */
  3390. hostint = hostGetByName((char*)addr);
  3391. if (hostint == ERROR)
  3392. { host = NULL;
  3393. soap->errnum = soap_errno;
  3394. }
  3395. #else
  3396. #ifdef AS400
  3397. if (!(host = gethostbyname((void*)addr)))
  3398. soap->errnum = h_errno;
  3399. #else
  3400. if (!(host = gethostbyname(addr)))
  3401. soap->errnum = h_errno;
  3402. #endif
  3403. #endif
  3404. if (!host)
  3405. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Host name not found\n"));
  3406. return SOAP_ERR;
  3407. }
  3408. #ifdef VXWORKS
  3409. inaddr->s_addr = hostint;
  3410. #else
  3411. memcpy(inaddr, host->h_addr, host->h_length);
  3412. #endif
  3413. return SOAP_OK;
  3414. }
  3415. #endif
  3416. #endif
  3417. #endif
  3418. /******************************************************************************/
  3419. #ifndef WITH_NOIO
  3420. #ifndef PALM_1
  3421. static SOAP_SOCKET
  3422. tcp_connect(struct soap *soap, const char *endpoint, const char *host, int port)
  3423. {
  3424. #ifdef WITH_IPV6
  3425. struct addrinfo hints, *res, *ressave;
  3426. #endif
  3427. SOAP_SOCKET fd;
  3428. int err = 0;
  3429. #ifndef WITH_LEAN
  3430. int len = SOAP_BUFLEN;
  3431. int set = 1;
  3432. #endif
  3433. #if !defined(WITH_LEAN) || defined(WITH_OPENSSL)
  3434. int retries;
  3435. #endif
  3436. if (soap_valid_socket(soap->socket))
  3437. soap->fclosesocket(soap, soap->socket);
  3438. soap->socket = SOAP_INVALID_SOCKET;
  3439. if (tcp_init(soap))
  3440. { soap->errnum = 0;
  3441. soap_set_sender_error(soap, tcp_error(soap), "TCP init failed in tcp_connect()", SOAP_TCP_ERROR);
  3442. return SOAP_INVALID_SOCKET;
  3443. }
  3444. soap->errmode = 0;
  3445. #ifdef WITH_IPV6
  3446. memset((void*)&hints, 0, sizeof(hints));
  3447. hints.ai_family = PF_UNSPEC;
  3448. #ifndef WITH_LEAN
  3449. if ((soap->omode & SOAP_IO_UDP))
  3450. hints.ai_socktype = SOCK_DGRAM;
  3451. else
  3452. #endif
  3453. hints.ai_socktype = SOCK_STREAM;
  3454. soap->errmode = 2;
  3455. res = NULL;
  3456. if (soap->proxy_host)
  3457. err = getaddrinfo(soap->proxy_host, soap_int2s(soap, soap->proxy_port), &hints, &res);
  3458. else
  3459. err = getaddrinfo(host, soap_int2s(soap, port), &hints, &res);
  3460. /* Oracle customization: check err before using res */
  3461. if (err || (res==NULL))
  3462. { soap_set_sender_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in tcp_connect()", SOAP_TCP_ERROR);
  3463. if (res)
  3464. {
  3465. freeaddrinfo(res);
  3466. }
  3467. return SOAP_INVALID_SOCKET;
  3468. }
  3469. ressave = res;
  3470. again:
  3471. fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
  3472. soap->errmode = 0;
  3473. #else
  3474. #ifndef WITH_LEAN
  3475. again:
  3476. #endif
  3477. #ifndef WITH_LEAN
  3478. if ((soap->omode & SOAP_IO_UDP))
  3479. fd = socket(AF_INET, SOCK_DGRAM, 0);
  3480. else
  3481. #endif
  3482. fd = socket(AF_INET, SOCK_STREAM, 0);
  3483. #endif
  3484. if (!soap_valid_socket(fd))
  3485. {
  3486. #ifdef WITH_IPV6
  3487. if (res->ai_next)
  3488. { res = res->ai_next;
  3489. goto again;
  3490. }
  3491. #endif
  3492. soap->errnum = soap_socket_errno(fd);
  3493. soap_set_sender_error(soap, tcp_error(soap), "socket failed in tcp_connect()", SOAP_TCP_ERROR);
  3494. #ifdef WITH_IPV6
  3495. freeaddrinfo(ressave);
  3496. #endif
  3497. return SOAP_INVALID_SOCKET;
  3498. }
  3499. #ifdef SOCKET_CLOSE_ON_EXEC
  3500. #ifdef WIN32
  3501. #ifndef UNDER_CE
  3502. SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0);
  3503. #endif
  3504. #else
  3505. fcntl(fd, F_SETFD, 1);
  3506. #endif
  3507. #endif
  3508. #ifndef WITH_LEAN
  3509. if (soap->connect_flags == SO_LINGER)
  3510. { struct linger linger;
  3511. memset((void*)&linger, 0, sizeof(linger));
  3512. linger.l_onoff = 1;
  3513. linger.l_linger = soap->linger_time;
  3514. if (setsockopt(fd, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger)))
  3515. { soap->errnum = soap_socket_errno(fd);
  3516. soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in tcp_connect()", SOAP_TCP_ERROR);
  3517. soap->fclosesocket(soap, fd);
  3518. #ifdef WITH_IPV6
  3519. freeaddrinfo(ressave);
  3520. #endif
  3521. return SOAP_INVALID_SOCKET;
  3522. }
  3523. }
  3524. else if (soap->connect_flags && setsockopt(fd, SOL_SOCKET, soap->connect_flags, (char*)&set, sizeof(int)))
  3525. { soap->errnum = soap_socket_errno(fd);
  3526. soap_set_sender_error(soap, tcp_error(soap), "setsockopt failed in tcp_connect()", SOAP_TCP_ERROR);
  3527. soap->fclosesocket(soap, fd);
  3528. #ifdef WITH_IPV6
  3529. freeaddrinfo(ressave);
  3530. #endif
  3531. return SOAP_INVALID_SOCKET;
  3532. }
  3533. if ((soap->keep_alive || soap->tcp_keep_alive) && setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
  3534. { soap->errnum = soap_socket_errno(fd);
  3535. soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in tcp_connect()", SOAP_TCP_ERROR);
  3536. soap->fclosesocket(soap, fd);
  3537. #ifdef WITH_IPV6
  3538. freeaddrinfo(ressave);
  3539. #endif
  3540. return SOAP_INVALID_SOCKET;
  3541. }
  3542. if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
  3543. { soap->errnum = soap_socket_errno(fd);
  3544. soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in tcp_connect()", SOAP_TCP_ERROR);
  3545. soap->fclosesocket(soap, fd);
  3546. #ifdef WITH_IPV6
  3547. freeaddrinfo(ressave);
  3548. #endif
  3549. return SOAP_INVALID_SOCKET;
  3550. }
  3551. if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
  3552. { soap->errnum = soap_socket_errno(fd);
  3553. soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in tcp_connect()", SOAP_TCP_ERROR);
  3554. soap->fclosesocket(soap, fd);
  3555. #ifdef WITH_IPV6
  3556. freeaddrinfo(ressave);
  3557. #endif
  3558. return SOAP_INVALID_SOCKET;
  3559. }
  3560. #ifdef TCP_KEEPIDLE
  3561. if (soap->tcp_keep_idle && setsockopt((SOAP_SOCKET)fd, IPPROTO_TCP, TCP_KEEPIDLE, (char*)&(soap->tcp_keep_idle), sizeof(int)))
  3562. { soap->errnum = soap_socket_errno(fd);
  3563. soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPIDLE failed in tcp_connect()", SOAP_TCP_ERROR);
  3564. soap->fclosesocket(soap, (SOAP_SOCKET)fd);
  3565. #ifdef WITH_IPV6
  3566. freeaddrinfo(ressave);
  3567. #endif
  3568. return SOAP_INVALID_SOCKET;
  3569. }
  3570. #endif
  3571. #ifdef TCP_KEEPINTVL
  3572. if (soap->tcp_keep_intvl && setsockopt((SOAP_SOCKET)fd, IPPROTO_TCP, TCP_KEEPINTVL, (char*)&(soap->tcp_keep_intvl), sizeof(int)))
  3573. { soap->errnum = soap_socket_errno(fd);
  3574. soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPINTVL failed in tcp_connect()", SOAP_TCP_ERROR);
  3575. soap->fclosesocket(soap, (SOAP_SOCKET)fd);
  3576. #ifdef WITH_IPV6
  3577. freeaddrinfo(ressave);
  3578. #endif
  3579. return SOAP_INVALID_SOCKET;
  3580. }
  3581. #endif
  3582. #ifdef TCP_KEEPCNT
  3583. if (soap->tcp_keep_cnt && setsockopt((SOAP_SOCKET)fd, IPPROTO_TCP, TCP_KEEPCNT, (char*)&(soap->tcp_keep_cnt), sizeof(int)))
  3584. { soap->errnum = soap_socket_errno(fd);
  3585. soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPCNT failed in tcp_connect()", SOAP_TCP_ERROR);
  3586. soap->fclosesocket(soap, (SOAP_SOCKET)fd);
  3587. #ifdef WITH_IPV6
  3588. freeaddrinfo(ressave);
  3589. #endif
  3590. return SOAP_INVALID_SOCKET;
  3591. }
  3592. #endif
  3593. #ifdef TCP_NODELAY
  3594. if (!(soap->omode & SOAP_IO_UDP) && setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
  3595. { soap->errnum = soap_socket_errno(fd);
  3596. soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in tcp_connect()", SOAP_TCP_ERROR);
  3597. soap->fclosesocket(soap, fd);
  3598. #ifdef WITH_IPV6
  3599. freeaddrinfo(ressave);
  3600. #endif
  3601. return SOAP_INVALID_SOCKET;
  3602. }
  3603. #endif
  3604. #ifdef WITH_IPV6
  3605. if ((soap->omode & SOAP_IO_UDP) && soap->ipv6_multicast_if)
  3606. { struct sockaddr_in6 *in6addr = (struct sockaddr_in6*)res->ai_addr;
  3607. in6addr->sin6_scope_id = soap->ipv6_multicast_if;
  3608. }
  3609. #endif
  3610. #ifdef IP_MULTICAST_TTL
  3611. if ((soap->omode & SOAP_IO_UDP) && soap->ipv4_multicast_if && !soap->ipv6_multicast_if)
  3612. { if (soap->ipv4_multicast_ttl > 0)
  3613. { char ttl = (char)(soap->ipv4_multicast_ttl);
  3614. if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ttl, sizeof(ttl)))
  3615. { soap->errnum = soap_socket_errno(fd);
  3616. soap_set_sender_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_TTL failed in tcp_connect()", SOAP_TCP_ERROR);
  3617. soap->fclosesocket(soap, fd);
  3618. return SOAP_INVALID_SOCKET;
  3619. }
  3620. }
  3621. #ifndef WINDOWS
  3622. if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, (char*)soap->ipv4_multicast_if, sizeof(struct in_addr)))
  3623. { soap->errnum = soap_socket_errno(fd);
  3624. soap_set_sender_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR);
  3625. soap->fclosesocket(soap, fd);
  3626. return SOAP_INVALID_SOCKET;
  3627. }
  3628. #else
  3629. #ifndef IP_MULTICAST_IF
  3630. #define IP_MULTICAST_IF 2
  3631. #endif
  3632. if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, (char*)soap->ipv4_multicast_if, sizeof(struct in_addr)))
  3633. { soap->errnum = soap_socket_errno(fd);
  3634. soap_set_sender_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR);
  3635. soap->fclosesocket(soap, fd);
  3636. return SOAP_INVALID_SOCKET;
  3637. }
  3638. #endif
  3639. }
  3640. #endif
  3641. #endif
  3642. DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Opening socket %d to host='%s' port=%d\n", fd, host, port));
  3643. #ifndef WITH_IPV6
  3644. soap->peerlen = sizeof(soap->peer);
  3645. memset((void*)&soap->peer, 0, sizeof(soap->peer));
  3646. soap->peer.sin_family = AF_INET;
  3647. soap->errmode = 2;
  3648. if (soap->proxy_host)
  3649. { if (soap->fresolve(soap, soap->proxy_host, &soap->peer.sin_addr))
  3650. { soap_set_sender_error(soap, tcp_error(soap), "get proxy host by name failed in tcp_connect()", SOAP_TCP_ERROR);
  3651. soap->fclosesocket(soap, fd);
  3652. return SOAP_INVALID_SOCKET;
  3653. }
  3654. soap->peer.sin_port = htons((short)soap->proxy_port);
  3655. }
  3656. else
  3657. { if (soap->fresolve(soap, host, &soap->peer.sin_addr))
  3658. { soap_set_sender_error(soap, tcp_error(soap), "get host by name failed in tcp_connect()", SOAP_TCP_ERROR);
  3659. soap->fclosesocket(soap, fd);
  3660. return SOAP_INVALID_SOCKET;
  3661. }
  3662. soap->peer.sin_port = htons((short)port);
  3663. }
  3664. soap->errmode = 0;
  3665. #ifndef WITH_LEAN
  3666. if ((soap->omode & SOAP_IO_UDP))
  3667. return fd;
  3668. #endif
  3669. #else
  3670. if ((soap->omode & SOAP_IO_UDP))
  3671. { memcpy(&soap->peer, res->ai_addr, res->ai_addrlen);
  3672. soap->peerlen = res->ai_addrlen;
  3673. freeaddrinfo(ressave);
  3674. return fd;
  3675. }
  3676. #endif
  3677. #ifndef WITH_LEAN
  3678. if (soap->connect_timeout)
  3679. SOAP_SOCKNONBLOCK(fd)
  3680. else
  3681. SOAP_SOCKBLOCK(fd)
  3682. retries = 10;
  3683. #endif
  3684. for (;;)
  3685. {
  3686. #ifdef WITH_IPV6
  3687. if (connect(fd, res->ai_addr, (int)res->ai_addrlen))
  3688. #else
  3689. if (connect(fd, (struct sockaddr*)&soap->peer, sizeof(soap->peer)))
  3690. #endif
  3691. { err = soap_socket_errno(fd);
  3692. #ifndef WITH_LEAN
  3693. if (err == SOAP_EADDRINUSE)
  3694. { soap->fclosesocket(soap, fd);
  3695. if (retries-- > 0)
  3696. goto again;
  3697. }
  3698. else if (soap->connect_timeout && (err == SOAP_EINPROGRESS || err == SOAP_EAGAIN || err == SOAP_EWOULDBLOCK))
  3699. {
  3700. SOAP_SOCKLEN_T k;
  3701. for (;;)
  3702. { register int r;
  3703. r = tcp_select(soap, fd, SOAP_TCP_SELECT_SND, soap->connect_timeout);
  3704. if (r > 0)
  3705. break;
  3706. if (!r)
  3707. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n"));
  3708. soap_set_sender_error(soap, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR);
  3709. soap->fclosesocket(soap, fd);
  3710. soap->socket = SOAP_INVALID_SOCKET; /* Oracle customization */
  3711. #ifdef WITH_IPV6
  3712. freeaddrinfo(ressave);
  3713. #endif
  3714. return SOAP_INVALID_SOCKET;
  3715. }
  3716. r = soap->errnum;
  3717. if (r != SOAP_EINTR)
  3718. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
  3719. soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
  3720. soap->fclosesocket(soap, fd);
  3721. soap->socket = SOAP_INVALID_SOCKET; /* Oracle customization */
  3722. #ifdef WITH_IPV6
  3723. freeaddrinfo(ressave);
  3724. #endif
  3725. return SOAP_INVALID_SOCKET;
  3726. }
  3727. }
  3728. k = (SOAP_SOCKLEN_T)sizeof(soap->errnum);
  3729. if (!getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*)&soap->errnum, &k) && !soap->errnum) /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
  3730. break;
  3731. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
  3732. if (!soap->errnum)
  3733. soap->errnum = soap_socket_errno(fd);
  3734. soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
  3735. soap->fclosesocket(soap, fd);
  3736. #ifdef WITH_IPV6
  3737. freeaddrinfo(ressave);
  3738. #endif
  3739. return SOAP_INVALID_SOCKET;
  3740. }
  3741. #endif
  3742. #ifdef WITH_IPV6
  3743. if (res->ai_next)
  3744. { res = res->ai_next;
  3745. soap->fclosesocket(soap, fd);
  3746. goto again;
  3747. }
  3748. #endif
  3749. if (err && err != SOAP_EINTR)
  3750. { soap->errnum = err;
  3751. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
  3752. soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
  3753. soap->fclosesocket(soap, fd);
  3754. #ifdef WITH_IPV6
  3755. freeaddrinfo(ressave);
  3756. #endif
  3757. return SOAP_INVALID_SOCKET;
  3758. }
  3759. }
  3760. else
  3761. break;
  3762. }
  3763. #ifdef WITH_IPV6
  3764. soap->peerlen = 0; /* IPv6: already connected so use send() */
  3765. freeaddrinfo(ressave);
  3766. #endif
  3767. if (soap->recv_timeout || soap->send_timeout)
  3768. SOAP_SOCKNONBLOCK(fd)
  3769. else
  3770. SOAP_SOCKBLOCK(fd)
  3771. soap->socket = fd;
  3772. soap->imode &= ~SOAP_ENC_SSL;
  3773. soap->omode &= ~SOAP_ENC_SSL;
  3774. if (!soap_tag_cmp(endpoint, "https:*"))
  3775. {
  3776. #ifdef WITH_OPENSSL
  3777. BIO *bio;
  3778. int r;
  3779. if (soap->proxy_host)
  3780. { soap_mode m = soap->mode; /* preserve settings */
  3781. soap_mode om = soap->omode; /* make sure we only parse HTTP */
  3782. size_t n = soap->count; /* save the content length */
  3783. const char *userid, *passwd;
  3784. soap->omode &= ~SOAP_ENC; /* mask IO and ENC */
  3785. soap->omode |= SOAP_IO_BUFFER;
  3786. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connecting to %s proxy server\n", soap->proxy_http_version));
  3787. sprintf(soap->tmpbuf, "CONNECT %s:%d HTTP/%s", host, port, soap->proxy_http_version);
  3788. if (soap_begin_send(soap)
  3789. || (soap->error = soap->fposthdr(soap, soap->tmpbuf, NULL)))
  3790. { soap->fclosesocket(soap, fd);
  3791. soap->socket = SOAP_INVALID_SOCKET; /* Oracle customization */
  3792. return SOAP_INVALID_SOCKET;
  3793. }
  3794. #ifndef WITH_LEAN
  3795. if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761)
  3796. { sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd);
  3797. strcpy(soap->tmpbuf, "Basic ");
  3798. soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262));
  3799. if ((soap->error = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf)))
  3800. { soap->fclosesocket(soap, fd);
  3801. soap->socket = SOAP_INVALID_SOCKET; /* Oracle customization */
  3802. //
  3803. // Oracle customization
  3804. // TODO: returning soap->error may also be a bug
  3805. //
  3806. return soap->error;
  3807. }
  3808. }
  3809. #endif
  3810. if ((soap->error = soap->fposthdr(soap, NULL, NULL))
  3811. || soap_flush(soap))
  3812. { soap->fclosesocket(soap, fd);
  3813. soap->socket = SOAP_INVALID_SOCKET; /* Oracle customization */
  3814. return SOAP_INVALID_SOCKET;
  3815. }
  3816. soap->omode = om;
  3817. om = soap->imode;
  3818. soap->imode &= ~SOAP_ENC; /* mask IO and ENC */
  3819. userid = soap->userid; /* preserve */
  3820. passwd = soap->passwd; /* preserve */
  3821. if ((soap->error = soap->fparse(soap)))
  3822. { soap->fclosesocket(soap, fd);
  3823. soap->socket = SOAP_INVALID_SOCKET; /* Oracle customization */
  3824. return SOAP_INVALID_SOCKET;
  3825. }
  3826. soap->userid = userid; /* restore */
  3827. soap->passwd = passwd; /* restore */
  3828. soap->imode = om; /* restore */
  3829. soap->count = n; /* restore */
  3830. if (soap_begin_send(soap))
  3831. { soap->fclosesocket(soap, fd);
  3832. return SOAP_INVALID_SOCKET;
  3833. }
  3834. if (endpoint)
  3835. strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint)-1); /* restore */
  3836. soap->mode = m;
  3837. }
  3838. if (!soap->ctx && (soap->error = soap->fsslauth(soap)))
  3839. { soap_set_sender_error(soap, "SSL error", "SSL authentication failed in tcp_connect(): check password, key file, and ca file.", SOAP_SSL_ERROR);
  3840. soap->fclosesocket(soap, fd);
  3841. soap->socket = SOAP_INVALID_SOCKET; /* Oracle customization */
  3842. return SOAP_INVALID_SOCKET;
  3843. }
  3844. if (!soap->ssl)
  3845. { soap->ssl = SSL_new(soap->ctx);
  3846. if (!soap->ssl)
  3847. { soap->fclosesocket(soap, fd);
  3848. soap->socket = SOAP_INVALID_SOCKET; /* Oracle customization */
  3849. soap->error = SOAP_SSL_ERROR;
  3850. return SOAP_INVALID_SOCKET;
  3851. }
  3852. }
  3853. else
  3854. SSL_clear(soap->ssl);
  3855. if (soap->session)
  3856. { if (!strcmp(soap->session_host, host) && soap->session_port == port)
  3857. SSL_set_session(soap->ssl, soap->session);
  3858. SSL_SESSION_free(soap->session);
  3859. soap->session = NULL;
  3860. }
  3861. soap->imode |= SOAP_ENC_SSL;
  3862. soap->omode |= SOAP_ENC_SSL;
  3863. bio = BIO_new_socket((int)fd, BIO_NOCLOSE);
  3864. SSL_set_bio(soap->ssl, bio, bio);
  3865. retries = 0;
  3866. #ifndef WITH_LEAN
  3867. /* Connect timeout: set SSL sockets to non-blocking */
  3868. if (soap->connect_timeout)
  3869. { SOAP_SOCKNONBLOCK(fd)
  3870. retries = 10*soap->connect_timeout;
  3871. }
  3872. else
  3873. SOAP_SOCKBLOCK(fd)
  3874. #endif
  3875. //
  3876. // Oracle customization
  3877. //
  3878. // Clear error queue of any errors remaining from a previous operation
  3879. ERR_clear_error();
  3880. if (retries <= 0)
  3881. retries = 100; /* SSL connect timeout: 10 sec retries, 100 x 0.1 sec */
  3882. /* Try connecting until success or timeout (when nonblocking) */
  3883. do
  3884. { if ((r = SSL_connect(soap->ssl)) <= 0)
  3885. { int err = SSL_get_error(soap->ssl, r);
  3886. if (err == SSL_ERROR_WANT_CONNECT || err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
  3887. { register int s;
  3888. if (err == SSL_ERROR_WANT_READ)
  3889. s = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000);
  3890. else
  3891. s = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000);
  3892. if (s < 0 && soap->errnum != SOAP_EINTR)
  3893. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL_connect/select error in tcp_connect\n"));
  3894. soap_set_sender_error(soap, soap_ssl_error(soap, r), "SSL_connect failed in tcp_connect()", SOAP_TCP_ERROR);
  3895. soap->fclosesocket(soap, fd);
  3896. soap->socket = SOAP_INVALID_SOCKET; /* Oracle customization */
  3897. return SOAP_INVALID_SOCKET;
  3898. }
  3899. if (s == 0 && retries-- <= 0)
  3900. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL connect timeout\n"));
  3901. soap_set_sender_error(soap, "Timeout", "SSL connect failed in tcp_connect()", SOAP_TCP_ERROR);
  3902. soap->fclosesocket(soap, fd);
  3903. soap->socket = SOAP_INVALID_SOCKET; /* Oracle customization */
  3904. return SOAP_INVALID_SOCKET;
  3905. }
  3906. }
  3907. else
  3908. { soap_set_sender_error(soap, soap_ssl_error(soap, r), "SSL_connect error in tcp_connect()", SOAP_SSL_ERROR);
  3909. soap->fclosesocket(soap, fd);
  3910. soap->socket = SOAP_INVALID_SOCKET; /* Oracle customization */
  3911. return SOAP_INVALID_SOCKET;
  3912. }
  3913. }
  3914. } while (!SSL_is_init_finished(soap->ssl));
  3915. /* Set SSL sockets to nonblocking */
  3916. SOAP_SOCKNONBLOCK(fd)
  3917. /* Check server credentials when required */
  3918. if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION))
  3919. { int err;
  3920. if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK)
  3921. { 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);
  3922. soap->fclosesocket(soap, fd);
  3923. soap->socket = SOAP_INVALID_SOCKET; /* Oracle customization */
  3924. return SOAP_INVALID_SOCKET;
  3925. }
  3926. if (!(soap->ssl_flags & SOAP_SSL_SKIP_HOST_CHECK))
  3927. { /* Oracle customization: X509_NAME *subj; */
  3928. int ext_count;
  3929. int ok = 0;
  3930. X509 *peer;
  3931. peer = SSL_get_peer_certificate(soap->ssl);
  3932. if (!peer)
  3933. { soap_set_sender_error(soap, "SSL error", "No SSL certificate was presented by the peer in tcp_connect()", SOAP_SSL_ERROR);
  3934. soap->fclosesocket(soap, fd);
  3935. soap->socket = SOAP_INVALID_SOCKET; /* Oracle customization */
  3936. return SOAP_INVALID_SOCKET;
  3937. }
  3938. ext_count = X509_get_ext_count(peer);
  3939. if (ext_count > 0)
  3940. { int i;
  3941. for (i = 0; i < ext_count; i++)
  3942. { X509_EXTENSION *ext = X509_get_ext(peer, i);
  3943. const char *ext_str = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));
  3944. if (ext_str && !strcmp(ext_str, "subjectAltName"))
  3945. { X509V3_EXT_METHOD *meth = (X509V3_EXT_METHOD*)X509V3_EXT_get(ext);
  3946. void *ext_data;
  3947. #if (OPENSSL_VERSION_NUMBER >= 0x0090800fL)
  3948. const unsigned char *data;
  3949. #else
  3950. unsigned char *data;
  3951. #endif
  3952. STACK_OF(CONF_VALUE) *val;
  3953. int j;
  3954. if (!meth)
  3955. break;
  3956. data = ext->value->data;
  3957. #if (OPENSSL_VERSION_NUMBER > 0x00907000L)
  3958. if (meth->it)
  3959. ext_data = ASN1_item_d2i(NULL, &data, ext->value->length, ASN1_ITEM_ptr(meth->it));
  3960. else
  3961. { /* OpenSSL not perfectly portable at this point (?):
  3962. Some compilers appear to prefer
  3963. meth->d2i(NULL, (const unsigned char**)&data, ...
  3964. and others prefer
  3965. meth->d2i(NULL, &data, ext->value->length);
  3966. */
  3967. ext_data = meth->d2i(NULL, &data, ext->value->length);
  3968. }
  3969. #else
  3970. ext_data = meth->d2i(NULL, &data, ext->value->length);
  3971. #endif
  3972. if (ext_data)
  3973. { val = meth->i2v(meth, ext_data, NULL);
  3974. if (val)
  3975. { for (j = 0; j < sk_CONF_VALUE_num(val); j++)
  3976. { CONF_VALUE *nval = sk_CONF_VALUE_value(val, j);
  3977. if (nval && !strcmp(nval->name, "DNS") && !strcmp(nval->value, host))
  3978. { ok = 1;
  3979. break;
  3980. }
  3981. }
  3982. sk_CONF_VALUE_pop_free(val, X509V3_conf_free);
  3983. }
  3984. #if (OPENSSL_VERSION_NUMBER > 0x00907000L)
  3985. if (meth->it)
  3986. ASN1_item_free((ASN1_VALUE*)ext_data, ASN1_ITEM_ptr(meth->it));
  3987. else
  3988. meth->ext_free(ext_data);
  3989. #else
  3990. meth->ext_free(ext_data);
  3991. #endif
  3992. }
  3993. }
  3994. if (ok)
  3995. break;
  3996. }
  3997. }
  3998. //
  3999. // Oracle customization
  4000. //
  4001. // the certificate subject name is an entity name, not a DNS name
  4002. //
  4003. /*
  4004. if (!ok && (subj = X509_get_subject_name(peer)))
  4005. { int i = -1;
  4006. do
  4007. { ASN1_STRING *name;
  4008. i = X509_NAME_get_index_by_NID(subj, NID_commonName, i);
  4009. if (i == -1)
  4010. break;
  4011. name = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subj, i));
  4012. if (name)
  4013. { if (!soap_tag_cmp(host, (const char*)M_ASN1_STRING_data(name)))
  4014. ok = 1;
  4015. else
  4016. { unsigned char *tmp = NULL;
  4017. ASN1_STRING_to_UTF8(&tmp, name);
  4018. if (tmp)
  4019. { if (!soap_tag_cmp(host, (const char*)tmp))
  4020. ok = 1;
  4021. OPENSSL_free(tmp);
  4022. }
  4023. }
  4024. }
  4025. } while (!ok);
  4026. }
  4027. */
  4028. X509_free(peer);
  4029. /*
  4030. if (!ok)
  4031. { soap_set_sender_error(soap, "SSL error", "SSL certificate host name mismatch in tcp_connect()", SOAP_SSL_ERROR);
  4032. soap->fclosesocket(soap, fd);
  4033. return SOAP_INVALID_SOCKET;
  4034. }
  4035. */
  4036. }
  4037. }
  4038. #ifdef SOAP_DEBUG
  4039. //
  4040. // Oracle customization for debug
  4041. //
  4042. if ( SSL_session_reused( soap->ssl ) == 1)
  4043. {
  4044. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL session reused\n"));
  4045. }
  4046. else
  4047. {
  4048. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL session negotiated\n"));
  4049. }
  4050. #endif
  4051. #else
  4052. soap->fclosesocket(soap, fd);
  4053. soap->socket = SOAP_INVALID_SOCKET; /* Oracle customization */
  4054. soap->error = SOAP_SSL_ERROR;
  4055. return SOAP_INVALID_SOCKET;
  4056. #endif
  4057. }
  4058. return fd;
  4059. }
  4060. #endif
  4061. #endif
  4062. /******************************************************************************/
  4063. #ifndef WITH_NOIO
  4064. #ifndef PALM_1
  4065. static int
  4066. tcp_select(struct soap *soap, SOAP_SOCKET s, int flags, int timeout)
  4067. { register int r;
  4068. struct timeval tv;
  4069. fd_set fd[3], *rfd, *sfd, *efd;
  4070. soap->errnum = 0;
  4071. #ifndef WIN32
  4072. /* if fd max set size exceeded, use poll() when available */
  4073. #if defined(__QNX__) || defined(QNX) /* select() is not MT safe on some QNX */
  4074. if (1)
  4075. #else
  4076. if ((int)s >= (int)FD_SETSIZE)
  4077. #endif
  4078. #ifdef HAVE_POLL
  4079. { struct pollfd pollfd;
  4080. int retries = 0;
  4081. pollfd.fd = (int)s;
  4082. pollfd.events = 0;
  4083. if (flags & SOAP_TCP_SELECT_RCV)
  4084. pollfd.events |= POLLIN;
  4085. if (flags & SOAP_TCP_SELECT_SND)
  4086. pollfd.events |= POLLOUT;
  4087. if (flags & SOAP_TCP_SELECT_ERR)
  4088. pollfd.events |= POLLERR;
  4089. if (timeout < 0)
  4090. timeout /= -1000; /* -usec -> ms */
  4091. else if (timeout <= 1000000) /* avoid overflow */
  4092. timeout *= 1000; /* sec -> ms */
  4093. else
  4094. { retries = timeout / 1000000;
  4095. timeout = 1000000000;
  4096. }
  4097. do r = poll(&pollfd, 1, timeout);
  4098. while (r == 0 && retries--);
  4099. if (r > 0)
  4100. { r = 0;
  4101. if ((flags & SOAP_TCP_SELECT_RCV) && (pollfd.revents & POLLIN))
  4102. r |= SOAP_TCP_SELECT_RCV;
  4103. if ((flags & SOAP_TCP_SELECT_SND) && (pollfd.revents & POLLOUT))
  4104. r |= SOAP_TCP_SELECT_SND;
  4105. if ((flags & SOAP_TCP_SELECT_ERR) && (pollfd.revents & POLLERR))
  4106. r |= SOAP_TCP_SELECT_ERR;
  4107. }
  4108. else if (r < 0)
  4109. soap->errnum = soap_socket_errno(s);
  4110. return r;
  4111. }
  4112. #else
  4113. { soap->error = SOAP_FD_EXCEEDED;
  4114. return -1;
  4115. }
  4116. #endif
  4117. #endif
  4118. rfd = sfd = efd = NULL;
  4119. if (flags & SOAP_TCP_SELECT_RCV)
  4120. { rfd = &fd[0];
  4121. FD_ZERO(rfd);
  4122. FD_SET(s, rfd);
  4123. }
  4124. if (flags & SOAP_TCP_SELECT_SND)
  4125. { sfd = &fd[1];
  4126. FD_ZERO(sfd);
  4127. FD_SET(s, sfd);
  4128. }
  4129. if (flags & SOAP_TCP_SELECT_ERR)
  4130. { efd = &fd[2];
  4131. FD_ZERO(efd);
  4132. FD_SET(s, efd);
  4133. }
  4134. if (timeout >= 0)
  4135. { tv.tv_sec = timeout;
  4136. tv.tv_usec = 0;
  4137. }
  4138. else
  4139. { tv.tv_sec = -timeout / 1000000;
  4140. tv.tv_usec = -timeout % 1000000;
  4141. }
  4142. r = select((int)s + 1, rfd, sfd, efd, &tv);
  4143. if (r > 0)
  4144. { r = 0;
  4145. if ((flags & SOAP_TCP_SELECT_RCV) && FD_ISSET(s, rfd))
  4146. r |= SOAP_TCP_SELECT_RCV;
  4147. if ((flags & SOAP_TCP_SELECT_SND) && FD_ISSET(s, sfd))
  4148. r |= SOAP_TCP_SELECT_SND;
  4149. if ((flags & SOAP_TCP_SELECT_ERR) && FD_ISSET(s, efd))
  4150. r |= SOAP_TCP_SELECT_ERR;
  4151. }
  4152. else if (r < 0)
  4153. soap->errnum = soap_socket_errno(s);
  4154. return r;
  4155. }
  4156. #endif
  4157. #endif
  4158. /******************************************************************************/
  4159. #ifndef WITH_NOIO
  4160. #ifndef PALM_1
  4161. static SOAP_SOCKET
  4162. tcp_accept(struct soap *soap, SOAP_SOCKET s, struct sockaddr *a, int *n)
  4163. { SOAP_SOCKET fd;
  4164. fd = accept(s, a, (SOAP_SOCKLEN_T*)n); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
  4165. #ifdef SOCKET_CLOSE_ON_EXEC
  4166. #ifdef WIN32
  4167. #ifndef UNDER_CE
  4168. SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0);
  4169. #endif
  4170. #else
  4171. fcntl(fd, F_SETFD, FD_CLOEXEC);
  4172. #endif
  4173. #endif
  4174. return fd;
  4175. }
  4176. #endif
  4177. #endif
  4178. /******************************************************************************/
  4179. #ifndef WITH_NOIO
  4180. #ifndef PALM_1
  4181. static int
  4182. tcp_disconnect(struct soap *soap)
  4183. {
  4184. #ifdef WITH_OPENSSL
  4185. if (soap->ssl)
  4186. { int r, s = 0;
  4187. if (soap->session)
  4188. { SSL_SESSION_free(soap->session);
  4189. soap->session = NULL;
  4190. }
  4191. if (*soap->host)
  4192. { soap->session = SSL_get1_session(soap->ssl);
  4193. if (soap->session)
  4194. { strcpy(soap->session_host, soap->host);
  4195. soap->session_port = soap->port;
  4196. }
  4197. }
  4198. r = SSL_shutdown(soap->ssl);
  4199. /* SSL shutdown does not work when reads are pending */
  4200. while (SSL_want_read(soap->ssl))
  4201. { SSL_read(soap->ssl, NULL, 0);
  4202. if (soap_socket_errno(soap->socket) != SOAP_EAGAIN)
  4203. { r = SSL_shutdown(soap->ssl);
  4204. break;
  4205. }
  4206. }
  4207. if (r == 0)
  4208. { if (soap_valid_socket(soap->socket))
  4209. { if (!soap->fshutdownsocket(soap, soap->socket, 1))
  4210. {
  4211. #ifndef WITH_LEAN
  4212. /*
  4213. wait up to 10 seconds for close_notify to be sent by peer (if peer not
  4214. present, this avoids calling SSL_shutdown() which has a lengthy return
  4215. timeout)
  4216. */
  4217. r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, 10);
  4218. if (r <= 0 && soap->errnum != SOAP_EINTR)
  4219. { soap->errnum = 0;
  4220. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connection lost...\n"));
  4221. soap->fclosesocket(soap, soap->socket);
  4222. soap->socket = SOAP_INVALID_SOCKET;
  4223. ERR_remove_state(0);
  4224. return SOAP_OK;
  4225. }
  4226. #else
  4227. r = SSL_shutdown(soap->ssl);
  4228. #endif
  4229. }
  4230. }
  4231. }
  4232. if (r != 1)
  4233. { s = ERR_get_error();
  4234. if (s)
  4235. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown failed: %d\n", SSL_get_error(soap->ssl, r)));
  4236. if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP))
  4237. { soap->fclosesocket(soap, soap->socket);
  4238. soap->socket = SOAP_INVALID_SOCKET;
  4239. }
  4240. }
  4241. }
  4242. SSL_free(soap->ssl);
  4243. soap->ssl = NULL;
  4244. if (s)
  4245. return SOAP_SSL_ERROR;
  4246. ERR_remove_state(0);
  4247. }
  4248. #endif
  4249. if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP))
  4250. { soap->fshutdownsocket(soap, soap->socket, 2);
  4251. soap->fclosesocket(soap, soap->socket);
  4252. soap->socket = SOAP_INVALID_SOCKET;
  4253. }
  4254. return SOAP_OK;
  4255. }
  4256. #endif
  4257. #endif
  4258. /******************************************************************************/
  4259. #ifndef WITH_NOIO
  4260. #ifndef PALM_1
  4261. static int
  4262. tcp_closesocket(struct soap *soap, SOAP_SOCKET fd)
  4263. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Close socket %d\n", (int)fd));
  4264. return soap_closesocket(fd);
  4265. }
  4266. #endif
  4267. #endif
  4268. /******************************************************************************/
  4269. #ifndef WITH_NOIO
  4270. #ifndef PALM_1
  4271. static int
  4272. tcp_shutdownsocket(struct soap *soap, SOAP_SOCKET fd, int how)
  4273. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown socket %d how=%d\n", (int)fd, how));
  4274. return shutdown(fd, how);
  4275. }
  4276. #endif
  4277. #endif
  4278. /******************************************************************************/
  4279. #ifndef WITH_NOIO
  4280. #ifndef PALM_1
  4281. SOAP_FMAC1
  4282. SOAP_SOCKET
  4283. SOAP_FMAC2
  4284. soap_bind(struct soap *soap, const char *host, int port, int backlog)
  4285. {
  4286. #ifdef WITH_IPV6
  4287. struct addrinfo *addrinfo = NULL;
  4288. struct addrinfo hints;
  4289. struct addrinfo res;
  4290. int err;
  4291. #ifdef IPV6_V6ONLY
  4292. int unset = 0;
  4293. #ifdef SOL_IP
  4294. int level = SOL_IP;
  4295. #else
  4296. int level = IPPROTO_IPV6;
  4297. #endif
  4298. #endif
  4299. #endif
  4300. #ifndef WITH_LEAN
  4301. int len = SOAP_BUFLEN;
  4302. int set = 1;
  4303. #endif
  4304. if (soap_valid_socket(soap->master))
  4305. { soap->fclosesocket(soap, soap->master);
  4306. soap->master = SOAP_INVALID_SOCKET;
  4307. }
  4308. soap->socket = SOAP_INVALID_SOCKET;
  4309. soap->errmode = 1;
  4310. if (tcp_init(soap))
  4311. { soap_set_receiver_error(soap, tcp_error(soap), "TCP init failed in soap_bind()", SOAP_TCP_ERROR);
  4312. return SOAP_INVALID_SOCKET;
  4313. }
  4314. #ifdef WITH_IPV6
  4315. memset((void*)&hints, 0, sizeof(hints));
  4316. hints.ai_family = PF_UNSPEC;
  4317. #ifndef WITH_LEAN
  4318. if ((soap->omode & SOAP_IO_UDP))
  4319. hints.ai_socktype = SOCK_DGRAM;
  4320. else
  4321. #endif
  4322. hints.ai_socktype = SOCK_STREAM;
  4323. hints.ai_flags = AI_PASSIVE;
  4324. soap->errmode = 2;
  4325. /* Oracle customization: check err before using addrinfo */
  4326. err = getaddrinfo(host, soap_int2s(soap, port), &hints, &addrinfo);
  4327. if (err || !addrinfo)
  4328. { soap_set_receiver_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in soap_bind()", SOAP_TCP_ERROR);
  4329. if (addrinfo)
  4330. {
  4331. freeaddrinfo(addrinfo);
  4332. }
  4333. return SOAP_INVALID_SOCKET;
  4334. }
  4335. res = *addrinfo;
  4336. memcpy(&soap->peer, addrinfo->ai_addr, addrinfo->ai_addrlen);
  4337. soap->peerlen = addrinfo->ai_addrlen;
  4338. res.ai_addr = (struct sockaddr*)&soap->peer;
  4339. res.ai_addrlen = soap->peerlen;
  4340. freeaddrinfo(addrinfo);
  4341. soap->master = (int)socket(res.ai_family, res.ai_socktype, res.ai_protocol);
  4342. #else
  4343. #ifndef WITH_LEAN
  4344. if ((soap->omode & SOAP_IO_UDP))
  4345. soap->master = (int)socket(AF_INET, SOCK_DGRAM, 0);
  4346. else
  4347. #endif
  4348. soap->master = (int)socket(AF_INET, SOCK_STREAM, 0);
  4349. #endif
  4350. soap->errmode = 0;
  4351. if (!soap_valid_socket(soap->master))
  4352. { soap->errnum = soap_socket_errno(soap->master);
  4353. soap_set_receiver_error(soap, tcp_error(soap), "socket failed in soap_bind()", SOAP_TCP_ERROR);
  4354. return SOAP_INVALID_SOCKET;
  4355. }
  4356. #ifndef WITH_LEAN
  4357. if ((soap->omode & SOAP_IO_UDP))
  4358. soap->socket = soap->master;
  4359. #endif
  4360. #ifdef SOCKET_CLOSE_ON_EXEC
  4361. #ifdef WIN32
  4362. #ifndef UNDER_CE
  4363. SetHandleInformation((HANDLE)soap->master, HANDLE_FLAG_INHERIT, 0);
  4364. #endif
  4365. #else
  4366. fcntl(soap->master, F_SETFD, 1);
  4367. #endif
  4368. #endif
  4369. #ifndef WITH_LEAN
  4370. if (soap->bind_flags && setsockopt(soap->master, SOL_SOCKET, soap->bind_flags, (char*)&set, sizeof(int)))
  4371. { soap->errnum = soap_socket_errno(soap->master);
  4372. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_bind()", SOAP_TCP_ERROR);
  4373. return SOAP_INVALID_SOCKET;
  4374. }
  4375. if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt(soap->master, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
  4376. { soap->errnum = soap_socket_errno(soap->master);
  4377. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_bind()", SOAP_TCP_ERROR);
  4378. return SOAP_INVALID_SOCKET;
  4379. }
  4380. if (setsockopt(soap->master, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
  4381. { soap->errnum = soap_socket_errno(soap->master);
  4382. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_bind()", SOAP_TCP_ERROR);
  4383. return SOAP_INVALID_SOCKET;
  4384. }
  4385. if (setsockopt(soap->master, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
  4386. { soap->errnum = soap_socket_errno(soap->master);
  4387. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_bind()", SOAP_TCP_ERROR);
  4388. return SOAP_INVALID_SOCKET;
  4389. }
  4390. #ifdef TCP_NODELAY
  4391. if (!(soap->omode & SOAP_IO_UDP) && setsockopt(soap->master, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
  4392. { soap->errnum = soap_socket_errno(soap->master);
  4393. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_bind()", SOAP_TCP_ERROR);
  4394. return SOAP_INVALID_SOCKET;
  4395. }
  4396. #endif
  4397. #endif
  4398. #ifdef WITH_IPV6
  4399. #ifdef IPV6_V6ONLY
  4400. if (setsockopt(soap->master, level, IPV6_V6ONLY, (char*)&unset, sizeof(int)))
  4401. { soap->errnum = soap_socket_errno(soap->master);
  4402. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt IPV6_V6ONLY failed in soap_bind()", SOAP_TCP_ERROR);
  4403. return SOAP_INVALID_SOCKET;
  4404. }
  4405. #endif
  4406. soap->errmode = 0;
  4407. if (bind(soap->master, res.ai_addr, (int)res.ai_addrlen))
  4408. { soap->errnum = soap_socket_errno(soap->master);
  4409. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
  4410. soap_closesock(soap);
  4411. soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR);
  4412. return SOAP_INVALID_SOCKET;
  4413. }
  4414. #else
  4415. soap->peerlen = sizeof(soap->peer);
  4416. memset((void*)&soap->peer, 0, sizeof(soap->peer));
  4417. soap->peer.sin_family = AF_INET;
  4418. soap->errmode = 2;
  4419. if (host)
  4420. { if (soap->fresolve(soap, host, &soap->peer.sin_addr))
  4421. { soap_set_receiver_error(soap, tcp_error(soap), "get host by name failed in soap_bind()", SOAP_TCP_ERROR);
  4422. return SOAP_INVALID_SOCKET;
  4423. }
  4424. }
  4425. else
  4426. soap->peer.sin_addr.s_addr = htonl(INADDR_ANY);
  4427. soap->peer.sin_port = htons((short)port);
  4428. soap->errmode = 0;
  4429. if (bind(soap->master, (struct sockaddr*)&soap->peer, (int)soap->peerlen))
  4430. { soap->errnum = soap_socket_errno(soap->master);
  4431. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
  4432. soap_closesock(soap);
  4433. soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR);
  4434. return SOAP_INVALID_SOCKET;
  4435. }
  4436. #endif
  4437. if (!(soap->omode & SOAP_IO_UDP) && listen(soap->master, backlog))
  4438. { soap->errnum = soap_socket_errno(soap->master);
  4439. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
  4440. soap_closesock(soap);
  4441. soap_set_receiver_error(soap, tcp_error(soap), "listen failed in soap_bind()", SOAP_TCP_ERROR);
  4442. return SOAP_INVALID_SOCKET;
  4443. }
  4444. return soap->master;
  4445. }
  4446. #endif
  4447. #endif
  4448. /******************************************************************************/
  4449. #ifndef WITH_NOIO
  4450. #ifndef PALM_1
  4451. SOAP_FMAC1
  4452. int
  4453. SOAP_FMAC2
  4454. soap_poll(struct soap *soap)
  4455. {
  4456. #ifndef WITH_LEAN
  4457. register int r;
  4458. if (soap_valid_socket(soap->socket))
  4459. { r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_ALL, 0);
  4460. if (r > 0 && (r & SOAP_TCP_SELECT_ERR))
  4461. r = -1;
  4462. }
  4463. else if (soap_valid_socket(soap->master))
  4464. r = tcp_select(soap, soap->master, SOAP_TCP_SELECT_SND, 0);
  4465. else
  4466. return SOAP_OK;
  4467. if (r > 0)
  4468. {
  4469. #ifdef WITH_OPENSSL
  4470. if (soap->imode & SOAP_ENC_SSL)
  4471. {
  4472. if (soap_valid_socket(soap->socket)
  4473. && (r & SOAP_TCP_SELECT_SND)
  4474. && (!(r & SOAP_TCP_SELECT_RCV)
  4475. || SSL_peek(soap->ssl, soap->tmpbuf, 1) > 0))
  4476. return SOAP_OK;
  4477. }
  4478. else
  4479. #endif
  4480. if (soap_valid_socket(soap->socket)
  4481. && (r & SOAP_TCP_SELECT_SND)
  4482. && (!(r & SOAP_TCP_SELECT_RCV)
  4483. || recv(soap->socket, soap->tmpbuf, 1, MSG_PEEK) > 0))
  4484. return SOAP_OK;
  4485. }
  4486. else if (r < 0)
  4487. { if ((soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) && soap_socket_errno(soap->master) != SOAP_EINTR)
  4488. { soap_set_receiver_error(soap, tcp_error(soap), "select failed in soap_poll()", SOAP_TCP_ERROR);
  4489. return soap->error = SOAP_TCP_ERROR;
  4490. }
  4491. }
  4492. DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Polling: other end down on socket=%d select=%d\n", soap->socket, r));
  4493. return SOAP_EOF;
  4494. #else
  4495. return SOAP_OK;
  4496. #endif
  4497. }
  4498. #endif
  4499. #endif
  4500. /******************************************************************************/
  4501. #ifndef WITH_NOIO
  4502. #ifndef PALM_1
  4503. SOAP_FMAC1
  4504. SOAP_SOCKET
  4505. SOAP_FMAC2
  4506. soap_accept(struct soap *soap)
  4507. { int n = (int)sizeof(soap->peer);
  4508. #ifndef WITH_LEAN
  4509. int len = SOAP_BUFLEN;
  4510. int set = 1;
  4511. #endif
  4512. soap->error = SOAP_OK;
  4513. #ifndef WITH_LEAN
  4514. if ((soap->omode & SOAP_IO_UDP))
  4515. return soap->socket = soap->master;
  4516. #endif
  4517. memset((void*)&soap->peer, 0, sizeof(soap->peer));
  4518. soap->socket = SOAP_INVALID_SOCKET;
  4519. soap->errmode = 0;
  4520. soap->keep_alive = 0;
  4521. if (soap_valid_socket(soap->master))
  4522. { register int err;
  4523. for (;;)
  4524. { if (soap->accept_timeout || soap->send_timeout || soap->recv_timeout)
  4525. { for (;;)
  4526. { register int r;
  4527. r = tcp_select(soap, soap->master, SOAP_TCP_SELECT_ALL, soap->accept_timeout ? soap->accept_timeout : 60);
  4528. if (r > 0)
  4529. break;
  4530. if (!r && soap->accept_timeout)
  4531. { soap_set_receiver_error(soap, "Timeout", "accept failed in soap_accept()", SOAP_TCP_ERROR);
  4532. return SOAP_INVALID_SOCKET;
  4533. }
  4534. if (r < 0)
  4535. { r = soap->errnum;
  4536. if (r != SOAP_EINTR)
  4537. { soap_closesock(soap);
  4538. soap_set_sender_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR);
  4539. return SOAP_INVALID_SOCKET;
  4540. }
  4541. }
  4542. }
  4543. }
  4544. if (soap->accept_timeout || soap->send_timeout || soap->recv_timeout)
  4545. SOAP_SOCKNONBLOCK(soap->master)
  4546. else
  4547. SOAP_SOCKBLOCK(soap->master)
  4548. soap->socket = soap->faccept(soap, soap->master, (struct sockaddr*)&soap->peer, &n);
  4549. soap->peerlen = (size_t)n;
  4550. if (soap_valid_socket(soap->socket))
  4551. {
  4552. #ifdef WITH_IPV6
  4553. /* Use soap->host to store the numeric form of the remote host */
  4554. getnameinfo((struct sockaddr*)&soap->peer, n, soap->host, sizeof(soap->host), NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV);
  4555. DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket %d from %s\n", soap->socket, soap->host));
  4556. //
  4557. // Oracle customization
  4558. //
  4559. // bug fix: save off the remote host
  4560. strcpy(soap->session_host, soap->host);
  4561. soap->ip = 0; /* info stored in soap->peer and soap->host */
  4562. soap->port = 0; /* info stored in soap->peer and soap->host */
  4563. #else
  4564. soap->ip = ntohl(soap->peer.sin_addr.s_addr);
  4565. soap->port = (int)ntohs(soap->peer.sin_port); /* does not return port number on some systems */
  4566. DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket %d at port %d from IP %d.%d.%d.%d\n", soap->socket, soap->port, (int)(soap->ip>>24)&0xFF, (int)(soap->ip>>16)&0xFF, (int)(soap->ip>>8)&0xFF, (int)soap->ip&0xFF));
  4567. #endif
  4568. #ifndef WITH_LEAN
  4569. if (soap->accept_flags == SO_LINGER)
  4570. { struct linger linger;
  4571. memset((void*)&linger, 0, sizeof(linger));
  4572. linger.l_onoff = 1;
  4573. linger.l_linger = soap->linger_time;
  4574. if (setsockopt(soap->socket, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger)))
  4575. { soap->errnum = soap_socket_errno(soap->socket);
  4576. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in soap_accept()", SOAP_TCP_ERROR);
  4577. soap_closesock(soap);
  4578. return SOAP_INVALID_SOCKET;
  4579. }
  4580. }
  4581. else if (soap->accept_flags && setsockopt(soap->socket, SOL_SOCKET, soap->accept_flags, (char*)&set, sizeof(int)))
  4582. { soap->errnum = soap_socket_errno(soap->socket);
  4583. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_accept()", SOAP_TCP_ERROR);
  4584. soap_closesock(soap);
  4585. return SOAP_INVALID_SOCKET;
  4586. }
  4587. if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt(soap->socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
  4588. { soap->errnum = soap_socket_errno(soap->socket);
  4589. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_accept()", SOAP_TCP_ERROR);
  4590. soap_closesock(soap);
  4591. return SOAP_INVALID_SOCKET;
  4592. }
  4593. if (setsockopt(soap->socket, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
  4594. { soap->errnum = soap_socket_errno(soap->socket);
  4595. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_accept()", SOAP_TCP_ERROR);
  4596. soap_closesock(soap);
  4597. return SOAP_INVALID_SOCKET;
  4598. }
  4599. if (setsockopt(soap->socket, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
  4600. { soap->errnum = soap_socket_errno(soap->socket);
  4601. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_accept()", SOAP_TCP_ERROR);
  4602. soap_closesock(soap);
  4603. return SOAP_INVALID_SOCKET;
  4604. }
  4605. #ifdef TCP_NODELAY
  4606. if (!(soap->omode & SOAP_IO_UDP) && setsockopt(soap->socket, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
  4607. { soap->errnum = soap_socket_errno(soap->socket);
  4608. soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_accept()", SOAP_TCP_ERROR);
  4609. soap_closesock(soap);
  4610. return SOAP_INVALID_SOCKET;
  4611. }
  4612. #endif
  4613. #endif
  4614. soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0);
  4615. return soap->socket;
  4616. }
  4617. err = soap_socket_errno(soap->socket);
  4618. if (err != 0 && err != SOAP_EINTR && err != SOAP_EAGAIN && err != SOAP_EWOULDBLOCK)
  4619. { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept failed from %s\n", soap->host));
  4620. soap->errnum = err;
  4621. soap_set_receiver_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR);
  4622. soap_closesock(soap);
  4623. return SOAP_INVALID_SOCKET;
  4624. }
  4625. }
  4626. }
  4627. else
  4628. { soap->errnum = 0;
  4629. soap_set_receiver_error(soap, tcp_error(soap), "no master socket in soap_accept()", SOAP_TCP_ERROR);
  4630. return SOAP_INVALID_SOCKET;
  4631. }
  4632. }
  4633. #endif
  4634. #endif
  4635. /******************************************************************************/
  4636. #ifndef PALM_1
  4637. SOAP_FMAC1
  4638. int
  4639. SOAP_FMAC2
  4640. soap_closesock(struct soap *soap)
  4641. { register int status = soap->error;
  4642. #ifndef WITH_LEANER
  4643. soap->mime.first = NULL;
  4644. soap->mime.last = NULL;
  4645. soap->dime.first = NULL;
  4646. soap->dime.last = NULL;
  4647. #endif
  4648. if (soap->fdisconnect && (soap->error = soap->fdisconnect(soap)))
  4649. return soap->error;
  4650. if (status == SOAP_EOF || status == SOAP_TCP_ERROR || status == SOAP_SSL_ERROR || !soap->keep_alive)
  4651. { if (soap->fclose && (soap->error = soap->fclose(soap)))
  4652. return soap->error;
  4653. soap->keep_alive = 0;
  4654. }
  4655. #ifdef WITH_ZLIB
  4656. if (soap->zlib_state == SOAP_ZLIB_DEFLATE)
  4657. deflateEnd(soap->d_stream);
  4658. else if (soap->zlib_state == SOAP_ZLIB_INFLATE)
  4659. inflateEnd(soap->d_stream);
  4660. soap->zlib_state = SOAP_ZLIB_NONE;
  4661. #endif
  4662. return soap->error = status;
  4663. }
  4664. #endif
  4665. /******************************************************************************/
  4666. #ifndef WITH_NOIO
  4667. #ifndef PALM_2
  4668. SOAP_FMAC1
  4669. void
  4670. SOAP_FMAC2
  4671. soap_cleanup(struct soap *soap)
  4672. { soap_done(soap);
  4673. #ifdef WIN32
  4674. if (!tcp_done)
  4675. return;
  4676. tcp_done = 0;
  4677. WSACleanup();
  4678. #endif
  4679. }
  4680. #endif
  4681. #endif
  4682. /******************************************************************************/
  4683. #ifndef PALM_1
  4684. SOAP_FMAC1
  4685. void
  4686. SOAP_FMAC2
  4687. soap_done(struct soap *soap)
  4688. {
  4689. #ifdef SOAP_DEBUG
  4690. int i;
  4691. #endif
  4692. if (soap_check_state(soap))
  4693. return;
  4694. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Done with context\n"));
  4695. soap_free_temp(soap);
  4696. while (soap->clist)
  4697. { struct soap_clist *p = soap->clist->next;
  4698. SOAP_FREE(soap, soap->clist);
  4699. soap->clist = p;
  4700. }
  4701. if (soap->state == SOAP_INIT)
  4702. soap->omode &= ~SOAP_IO_UDP; /* to force close the socket */
  4703. soap->keep_alive = 0; /* to force close the socket */
  4704. soap_closesock(soap);
  4705. #ifdef WITH_COOKIES
  4706. soap_free_cookies(soap);
  4707. #endif
  4708. while (soap->plugins)
  4709. { register struct soap_plugin *p = soap->plugins->next;
  4710. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Removing plugin '%s'\n", soap->plugins->id));
  4711. if (soap->plugins->fcopy || soap->state == SOAP_INIT)
  4712. soap->plugins->fdelete(soap, soap->plugins);
  4713. SOAP_FREE(soap, soap->plugins);
  4714. soap->plugins = p;
  4715. }
  4716. soap->fplugin = fplugin;
  4717. soap->fmalloc = NULL;
  4718. #ifndef WITH_NOHTTP
  4719. soap->fpost = http_post;
  4720. soap->fget = http_get;
  4721. soap->fput = http_405;
  4722. soap->fdel = http_405;
  4723. soap->fhead = http_405;
  4724. soap->fform = NULL;
  4725. soap->fposthdr = http_post_header;
  4726. soap->fresponse = http_response;
  4727. soap->fparse = http_parse;
  4728. soap->fparsehdr = http_parse_header;
  4729. #endif
  4730. soap->fheader = NULL;
  4731. #ifndef WITH_NOIO
  4732. #ifndef WITH_IPV6
  4733. soap->fresolve = tcp_gethost;
  4734. #else
  4735. soap->fresolve = NULL;
  4736. #endif
  4737. soap->faccept = tcp_accept;
  4738. soap->fopen = tcp_connect;
  4739. soap->fclose = tcp_disconnect;
  4740. soap->fclosesocket = tcp_closesocket;
  4741. soap->fshutdownsocket = tcp_shutdownsocket;
  4742. soap->fsend = fsend;
  4743. soap->frecv = frecv;
  4744. soap->fpoll = soap_poll;
  4745. #else
  4746. soap->fopen = NULL;
  4747. soap->fclose = NULL;
  4748. soap->fpoll = NULL;
  4749. #endif
  4750. #ifndef WITH_LEANER
  4751. soap->fprepareinitsend = NULL;
  4752. soap->fprepareinitrecv = NULL;
  4753. soap->fpreparesend = NULL;
  4754. soap->fpreparerecv = NULL;
  4755. soap->fpreparefinalsend = NULL;
  4756. soap->fpreparefinalrecv = NULL;
  4757. #endif
  4758. soap->fseterror = NULL;
  4759. soap->fignore = NULL;
  4760. soap->fserveloop = NULL;
  4761. #ifdef WITH_OPENSSL
  4762. if (soap->session)
  4763. { SSL_SESSION_free(soap->session);
  4764. soap->session = NULL;
  4765. }
  4766. #endif
  4767. if (soap->state == SOAP_INIT)
  4768. { if (soap_valid_socket(soap->master))
  4769. { soap->fclosesocket(soap, soap->master);
  4770. soap->master = SOAP_INVALID_SOCKET;
  4771. }
  4772. }
  4773. #ifdef WITH_OPENSSL
  4774. if (soap->ssl)
  4775. { SSL_free(soap->ssl);
  4776. soap->ssl = NULL;
  4777. }
  4778. if (soap->state == SOAP_INIT)
  4779. { if (soap->ctx)
  4780. { SSL_CTX_free(soap->ctx);
  4781. soap->ctx = NULL;
  4782. }
  4783. }
  4784. #endif
  4785. #ifdef WITH_OPENSSL
  4786. ERR_remove_state(0);
  4787. #endif
  4788. #ifdef WITH_C_LOCALE
  4789. freelocale(soap->c_locale);
  4790. #endif
  4791. #ifdef WITH_ZLIB
  4792. if (soap->d_stream)
  4793. { SOAP_FREE(soap, (void*)soap->d_stream);
  4794. soap->d_stream = NULL;
  4795. }
  4796. if (soap->z_buf)
  4797. { SOAP_FREE(soap, (void*)soap->z_buf);
  4798. soap->z_buf = NULL;
  4799. }
  4800. #endif
  4801. #ifdef SOAP_DEBUG
  4802. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free logfiles\n"));
  4803. for (i = 0; i < SOAP_MAXLOGS; i++)
  4804. { if (soap->logfile[i])
  4805. { SOAP_FREE(soap, (void*)soap->logfile[i]);
  4806. soap->logfile[i] = NULL;
  4807. }
  4808. soap_close_logfile(soap, i);
  4809. }
  4810. soap->state = SOAP_NONE;
  4811. #endif
  4812. #ifdef SOAP_MEM_DEBUG
  4813. soap_free_mht(soap);
  4814. #endif
  4815. }
  4816. #endif
  4817. /******************************************************************************\
  4818. *
  4819. * HTTP
  4820. *
  4821. \******************************************************************************/
  4822. /******************************************************************************/
  4823. #ifndef WITH_NOHTTP
  4824. #ifndef PALM_1
  4825. static int
  4826. http_parse(struct soap *soap)
  4827. { char header[SOAP_HDRLEN], *s;
  4828. unsigned short httpcmd = 0, status = 0;
  4829. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Waiting for HTTP request/response...\n"));
  4830. *soap->endpoint = '\0';
  4831. soap->length = 0;
  4832. soap->userid = NULL;
  4833. soap->passwd = NULL;
  4834. soap->action = NULL;
  4835. soap->authrealm = NULL;
  4836. soap->proxy_from = NULL;
  4837. soap->http_content = NULL;
  4838. soap->status = 0;
  4839. do
  4840. { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
  4841. { if (soap->error == SOAP_EOF)
  4842. return SOAP_EOF;
  4843. return soap->error = 414;
  4844. }
  4845. if ((s = strchr(soap->msgbuf, ' ')))
  4846. { soap->status = (unsigned short)soap_strtoul(s, &s, 10);
  4847. if (!soap_blank(*s))
  4848. soap->status = 0;
  4849. }
  4850. else
  4851. soap->status = 0;
  4852. DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP status: %s\n", soap->msgbuf));
  4853. for (;;)
  4854. { if (soap_getline(soap, header, SOAP_HDRLEN))
  4855. { if (soap->error == SOAP_EOF)
  4856. { soap->error = SOAP_OK;
  4857. DBGLOG(TEST,SOAP_MESSAGE(fdebug, "EOF in HTTP header, continue anyway\n"));
  4858. break;
  4859. }
  4860. return soap->error;
  4861. }
  4862. if (!*header)
  4863. break;
  4864. DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP header: %s\n", header));
  4865. s = strchr(header, ':');
  4866. if (s)
  4867. { char *t;
  4868. *s = '\0';
  4869. do s++;
  4870. while (*s && *s <= 32);
  4871. if (*s == '"')
  4872. s++;
  4873. t = s + strlen(s) - 1;
  4874. while (t > s && *t <= 32)
  4875. t--;
  4876. if (t >= s && *t == '"')
  4877. t--;
  4878. t[1] = '\0';
  4879. if ((soap->error = soap->fparsehdr(soap, header, s)))
  4880. { if (soap->error < SOAP_STOP)
  4881. return soap->error;
  4882. status = soap->error;
  4883. soap->error = SOAP_OK;
  4884. }
  4885. }
  4886. }
  4887. } while (soap->status == 100);
  4888. DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Finished HTTP header parsing, status = %d\n", soap->status));
  4889. s = strstr(soap->msgbuf, "HTTP/");
  4890. if (s && s[7] != '1')
  4891. { if (soap->keep_alive == 1)
  4892. soap->keep_alive = 0;
  4893. if (soap->status == 0 && (soap->omode & SOAP_IO) == SOAP_IO_CHUNK) /* soap->status == 0 for HTTP request */
  4894. { soap->imode |= SOAP_IO_CHUNK;
  4895. soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE;
  4896. }
  4897. }
  4898. if (soap->keep_alive < 0)
  4899. soap->keep_alive = 1;
  4900. DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Keep alive connection = %d\n", soap->keep_alive));
  4901. if (soap->status == 0)
  4902. { size_t l = 0;
  4903. if (s)
  4904. { if (!strncmp(soap->msgbuf, "POST ", l = 5))
  4905. httpcmd = 1;
  4906. else if (!strncmp(soap->msgbuf, "GET ", l = 4))
  4907. httpcmd = 2;
  4908. else if (!strncmp(soap->msgbuf, "PUT ", l = 4))
  4909. httpcmd = 3;
  4910. else if (!strncmp(soap->msgbuf, "DELETE ", l = 7))
  4911. httpcmd = 4;
  4912. else if (!strncmp(soap->msgbuf, "HEAD ", l = 5))
  4913. httpcmd = 5;
  4914. }
  4915. if (s && httpcmd)
  4916. { size_t m = strlen(soap->endpoint);
  4917. size_t n = m + (s - soap->msgbuf) - l - 1;
  4918. if (m > n)
  4919. m = n;
  4920. if (n >= sizeof(soap->endpoint))
  4921. n = sizeof(soap->endpoint) - 1;
  4922. strncpy(soap->path, soap->msgbuf + l, n - m);
  4923. soap->path[n - m] = '\0';
  4924. strcat(soap->endpoint, soap->path);
  4925. DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Target endpoint='%s'\n", soap->endpoint));
  4926. if (httpcmd > 1)
  4927. { switch (httpcmd)
  4928. { case 2: soap->error = soap->fget(soap); break;
  4929. case 3: soap->error = soap->fput(soap); break;
  4930. case 4: soap->error = soap->fdel(soap); break;
  4931. case 5: soap->error = soap->fhead(soap); break;
  4932. default: soap->error = 405; break;
  4933. }
  4934. if (soap->error == SOAP_OK)
  4935. soap->error = SOAP_STOP; /* prevents further processing */
  4936. return soap->error;
  4937. }
  4938. if (status)
  4939. return soap->error = status;
  4940. }
  4941. else if (status)
  4942. return soap->error = status;
  4943. else if (s)
  4944. return soap->error = 405;
  4945. }
  4946. /* Status OK (HTTP 200) */
  4947. if (soap->status == 0 || soap->status == 200)
  4948. return SOAP_OK;
  4949. /* Status 201 (Created), 202 (Accepted), ... and HTTP 400 and 500 errors
  4950. may not have a body. When content length, content type, or chunking is
  4951. used assume there is a message to parse, either XML or HTTP.
  4952. This version allows parsing of content when length=0:
  4953. if (soap->length > 0 || soap->http_content || (soap->imode & SOAP_IO) == SOAP_IO_CHUNK)
  4954. */
  4955. if (soap->length > 0 || (soap->imode & SOAP_IO) == SOAP_IO_CHUNK)
  4956. { if (((soap->status > 200 && soap->status <= 299) || soap->status == 400 || soap->status == 500))
  4957. return SOAP_OK;
  4958. /* force close afterwards in soap_closesock() */
  4959. soap->keep_alive = 0;
  4960. /* read HTTP body for error details */
  4961. s = soap_get_http_body(soap);
  4962. if (s)
  4963. return soap_set_receiver_error(soap, soap->msgbuf, s, soap->status);
  4964. }
  4965. DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP error %d\n", soap->status));
  4966. return soap_set_receiver_error(soap, "HTTP Error", soap->msgbuf, soap->status);
  4967. }
  4968. #endif
  4969. #endif
  4970. /******************************************************************************/
  4971. #ifndef WITH_NOHTTP
  4972. #ifndef PALM_1
  4973. static int
  4974. http_parse_header(struct soap *soap, const char *key, const char *val)
  4975. { if (!soap_tag_cmp(key, "Host"))
  4976. {
  4977. #ifdef WITH_OPENSSL
  4978. if (soap->imode & SOAP_ENC_SSL)
  4979. strcpy(soap->endpoint, "https://");
  4980. else
  4981. #endif
  4982. strcpy(soap->endpoint, "http://");
  4983. strncat(soap->endpoint, val, sizeof(soap->endpoint) - 8);
  4984. soap->endpoint[sizeof(soap->endpoint) - 1] = '\0';
  4985. }
  4986. #ifndef WITH_LEANER
  4987. else if (!soap_tag_cmp(key, "Content-Type"))
  4988. { const char *action;
  4989. soap->http_content = soap_strdup(soap, val);
  4990. if (soap_get_header_attribute(soap, val, "application/dime"))
  4991. soap->imode |= SOAP_ENC_DIME;
  4992. else if (soap_get_header_attribute(soap, val, "multipart/related")
  4993. || soap_get_header_attribute(soap, val, "multipart/form-data"))
  4994. { soap->mime.boundary = soap_strdup(soap, soap_get_header_attribute(soap, val, "boundary"));
  4995. soap->mime.start = soap_strdup(soap, soap_get_header_attribute(soap, val, "start"));
  4996. soap->imode |= SOAP_ENC_MIME;
  4997. }
  4998. action = soap_get_header_attribute(soap, val, "action");
  4999. if (action)
  5000. { if (*action == '"')
  5001. { soap->action = soap_strdup(soap, action + 1);
  5002. soap->action[strlen(soap->action) - 1] = '\0';
  5003. }
  5004. else
  5005. soap->action = soap_strdup(soap, action);
  5006. }
  5007. }
  5008. #endif
  5009. else if (!soap_tag_cmp(key, "Content-Length"))
  5010. { soap->length = soap_strtoul(val, NULL, 10);
  5011. }
  5012. else if (!soap_tag_cmp(key, "Content-Encoding"))
  5013. { if (!soap_tag_cmp(val, "deflate"))
  5014. #ifdef WITH_ZLIB
  5015. soap->zlib_in = SOAP_ZLIB_DEFLATE;
  5016. #else
  5017. return SOAP_ZLIB_ERROR;
  5018. #endif
  5019. else if (!soap_tag_cmp(val, "gzip"))
  5020. #ifdef WITH_GZIP
  5021. soap->zlib_in = SOAP_ZLIB_GZIP;
  5022. #else
  5023. return SOAP_ZLIB_ERROR;
  5024. #endif
  5025. }
  5026. #ifdef WITH_ZLIB
  5027. else if (!soap_tag_cmp(key, "Accept-Encoding"))
  5028. {
  5029. #ifdef WITH_GZIP
  5030. if (strchr(val, '*') || soap_get_header_attribute(soap, val, "gzip"))
  5031. soap->zlib_out = SOAP_ZLIB_GZIP;
  5032. else
  5033. #endif
  5034. if (strchr(val, '*') || soap_get_header_attribute(soap, val, "deflate"))
  5035. soap->zlib_out = SOAP_ZLIB_DEFLATE;
  5036. else
  5037. soap->zlib_out = SOAP_ZLIB_NONE;
  5038. }
  5039. #endif
  5040. else if (!soap_tag_cmp(key, "Transfer-Encoding"))
  5041. { soap->imode &= ~SOAP_IO;
  5042. if (!soap_tag_cmp(val, "chunked"))
  5043. soap->imode |= SOAP_IO_CHUNK;
  5044. }
  5045. else if (!soap_tag_cmp(key, "Connection"))
  5046. { if (!soap_tag_cmp(val, "keep-alive"))
  5047. soap->keep_alive = -soap->keep_alive;
  5048. else if (!soap_tag_cmp(val, "close"))
  5049. soap->keep_alive = 0;
  5050. }
  5051. #ifndef WITH_LEAN
  5052. else if (!soap_tag_cmp(key, "Authorization"))
  5053. { if (!soap_tag_cmp(val, "Basic *"))
  5054. { int n;
  5055. char *s;
  5056. soap_base642s(soap, val + 6, soap->tmpbuf, sizeof(soap->tmpbuf) - 1, &n);
  5057. soap->tmpbuf[n] = '\0';
  5058. if ((s = strchr(soap->tmpbuf, ':')))
  5059. { *s = '\0';
  5060. soap->userid = soap_strdup(soap, soap->tmpbuf);
  5061. soap->passwd = soap_strdup(soap, s + 1);
  5062. }
  5063. }
  5064. }
  5065. else if (!soap_tag_cmp(key, "WWW-Authenticate"))
  5066. { soap->authrealm = soap_strdup(soap, soap_get_header_attribute(soap, val + 6, "realm"));
  5067. }
  5068. else if (!soap_tag_cmp(key, "Expect"))
  5069. { if (!soap_tag_cmp(val, "100-continue"))
  5070. { if ((soap->error = soap->fposthdr(soap, "HTTP/1.1 100 Continue", NULL))
  5071. || (soap->error = soap->fposthdr(soap, NULL, NULL)))
  5072. return soap->error;
  5073. }
  5074. }
  5075. #endif
  5076. else if (!soap_tag_cmp(key, "SOAPAction"))
  5077. { if (*val == '"')
  5078. { soap->action = soap_strdup(soap, val + 1);
  5079. soap->action[strlen(soap->action) - 1] = '\0';
  5080. }
  5081. else
  5082. soap->action = soap_strdup(soap, val);
  5083. }
  5084. else if (!soap_tag_cmp(key, "Location"))
  5085. { strncpy(soap->endpoint, val, sizeof(soap->endpoint));
  5086. soap->endpoint[sizeof(soap->endpoint) - 1] = '\0';
  5087. }
  5088. else if (!soap_tag_cmp(key, "X-Forwarded-For"))
  5089. { soap->proxy_from = soap_strdup(soap, val);
  5090. }
  5091. #ifdef WITH_COOKIES
  5092. else if (!soap_tag_cmp(key, "Cookie")
  5093. || !soap_tag_cmp(key, "Cookie2")
  5094. || !soap_tag_cmp(key, "Set-Cookie")
  5095. || !soap_tag_cmp(key, "Set-Cookie2"))
  5096. { soap_getcookies(soap, val);
  5097. }
  5098. #endif
  5099. return SOAP_OK;
  5100. }
  5101. #endif
  5102. #endif
  5103. /******************************************************************************/
  5104. #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
  5105. #ifndef PALM_1
  5106. SOAP_FMAC1
  5107. const char*
  5108. SOAP_FMAC2
  5109. soap_get_header_attribute(struct soap *soap, const char *line, const char *key)
  5110. { register const char *s = line;
  5111. if (s)
  5112. { while (*s)
  5113. { register short flag;
  5114. s = soap_decode_key(soap->tmpbuf, sizeof(soap->tmpbuf), s);
  5115. flag = soap_tag_cmp(soap->tmpbuf, key);
  5116. s = soap_decode_val(soap->tmpbuf, sizeof(soap->tmpbuf), s);
  5117. if (!flag)
  5118. return soap->tmpbuf;
  5119. }
  5120. }
  5121. return NULL;
  5122. }
  5123. #endif
  5124. #endif
  5125. /******************************************************************************/
  5126. #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
  5127. #ifndef PALM_1
  5128. SOAP_FMAC1
  5129. const char*
  5130. SOAP_FMAC2
  5131. soap_decode_key(char *buf, size_t len, const char *val)
  5132. { return soap_decode(buf, len, val, "=,;");
  5133. }
  5134. #endif
  5135. #endif
  5136. /******************************************************************************/
  5137. #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
  5138. #ifndef PALM_1
  5139. SOAP_FMAC1
  5140. const char*
  5141. SOAP_FMAC2
  5142. soap_decode_val(char *buf, size_t len, const char *val)
  5143. { if (*val != '=')
  5144. { *buf = '\0';
  5145. return val;
  5146. }
  5147. return soap_decode(buf, len, val + 1, ",;");
  5148. }
  5149. #endif
  5150. #endif
  5151. /******************************************************************************/
  5152. #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
  5153. #ifndef PALM_1
  5154. static const char*
  5155. soap_decode(char *buf, size_t len, const char *val, const char *sep)
  5156. { const char *s;
  5157. char *t = buf;
  5158. for (s = val; *s; s++)
  5159. if (*s != ' ' && *s != '\t' && !strchr(sep, *s))
  5160. break;
  5161. if (*s == '"')
  5162. { s++;
  5163. while (*s && *s != '"' && --len)
  5164. *t++ = *s++;
  5165. }
  5166. else
  5167. { while (*s && !soap_blank(*s) && !strchr(sep, *s) && --len)
  5168. { if (*s == '%')
  5169. { *t++ = ((s[1] >= 'A' ? (s[1] & 0x7) + 9 : s[1] - '0') << 4)
  5170. + (s[2] >= 'A' ? (s[2] & 0x7) + 9 : s[2] - '0');
  5171. s += 3;
  5172. }
  5173. else
  5174. *t++ = *s++;
  5175. }
  5176. }
  5177. *t = '\0';
  5178. while (*s && !strchr(sep, *s))
  5179. s++;
  5180. return s;
  5181. }
  5182. #endif
  5183. #endif
  5184. /******************************************************************************/
  5185. #ifndef WITH_NOHTTP
  5186. #ifndef PALM_1
  5187. static const char*
  5188. http_error(struct soap *soap, int status)
  5189. { register const char *msg = SOAP_STR_EOS;
  5190. #ifndef WITH_LEAN
  5191. msg = soap_code_str(h_http_error_codes, status);
  5192. if (!msg)
  5193. msg = SOAP_STR_EOS;
  5194. #endif
  5195. return msg;
  5196. }
  5197. #endif
  5198. #endif
  5199. /******************************************************************************/
  5200. #ifndef WITH_NOHTTP
  5201. #ifndef PALM_1
  5202. static int
  5203. http_get(struct soap *soap)
  5204. { return SOAP_GET_METHOD;
  5205. }
  5206. #endif
  5207. #endif
  5208. /******************************************************************************/
  5209. #ifndef WITH_NOHTTP
  5210. #ifndef PALM_1
  5211. static int
  5212. http_405(struct soap *soap)
  5213. { return 405;
  5214. }
  5215. #endif
  5216. #endif
  5217. /******************************************************************************/
  5218. #ifndef WITH_NOHTTP
  5219. #ifndef PALM_1
  5220. static int
  5221. http_post(struct soap *soap, const char *endpoint, const char *host, int port, const char *path, const char *action, size_t count)
  5222. { register const char *s;
  5223. register int err;
  5224. if (soap->status == SOAP_GET)
  5225. s = "GET";
  5226. else
  5227. s = "POST";
  5228. #ifdef PALM
  5229. if (!endpoint || (soap_tag_cmp(endpoint, "http:*") && soap_tag_cmp(endpoint, "https:*") && strncmp(endpoint, "httpg:", 6)) && strncmp(endpoint, "_beam:", 6) && strncmp(endpoint, "_local:", 7) && strncmp(endpoint, "_btobex:", 8))
  5230. #else
  5231. if (!endpoint || (soap_tag_cmp(endpoint, "http:*") && soap_tag_cmp(endpoint, "https:*") && strncmp(endpoint, "httpg:", 6)))
  5232. #endif
  5233. return SOAP_OK;
  5234. if (strlen(endpoint) + strlen(soap->http_version) > sizeof(soap->tmpbuf) - 80)
  5235. return soap->error = SOAP_EOM;
  5236. if (soap->proxy_host && soap_tag_cmp(endpoint, "https:*"))
  5237. sprintf(soap->tmpbuf, "%s %s HTTP/%s", s, endpoint, soap->http_version);
  5238. else
  5239. sprintf(soap->tmpbuf, "%s /%s HTTP/%s", s, (*path == '/' ? path + 1 : path), soap->http_version);
  5240. if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
  5241. return err;
  5242. #ifdef WITH_OPENSSL
  5243. if ((soap->ssl && soap->port != 443) || (!soap->ssl && soap->port != 80))
  5244. sprintf(soap->tmpbuf, "%s:%d", host, port);
  5245. else
  5246. strcpy(soap->tmpbuf, host);
  5247. #else
  5248. if (port != 80)
  5249. sprintf(soap->tmpbuf, "%s:%d", host, port);
  5250. else
  5251. { /* Oracle customization */
  5252. strncpy(soap->tmpbuf, host, sizeof(soap->tmpbuf) - 1);
  5253. soap->tmpbuf[sizeof(soap->tmpbuf) - 1] = '\0';
  5254. }
  5255. #endif
  5256. // Oracle customization
  5257. if ((err = soap->fposthdr(soap, "Host", soap->tmpbuf))
  5258. || (err = soap->fposthdr(soap, "User-Agent", "SunKMS gSOAP/2.7.17"))
  5259. || (err = soap_puthttphdr(soap, SOAP_OK, count)))
  5260. return err;
  5261. #ifdef WITH_ZLIB
  5262. #ifdef WITH_GZIP
  5263. if ((err = soap->fposthdr(soap, "Accept-Encoding", "gzip, deflate")))
  5264. #else
  5265. if ((err = soap->fposthdr(soap, "Accept-Encoding", "deflate")))
  5266. #endif
  5267. return err;
  5268. #endif
  5269. #ifndef WITH_LEAN
  5270. if (soap->userid && soap->passwd && strlen(soap->userid) + strlen(soap->passwd) < 761)
  5271. { sprintf(soap->tmpbuf + 262, "%s:%s", soap->userid, soap->passwd);
  5272. strcpy(soap->tmpbuf, "Basic ");
  5273. soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262));
  5274. if ((err = soap->fposthdr(soap, "Authorization", soap->tmpbuf)))
  5275. return err;
  5276. }
  5277. if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761)
  5278. { sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd);
  5279. strcpy(soap->tmpbuf, "Basic ");
  5280. soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262));
  5281. if ((err = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf)))
  5282. return err;
  5283. }
  5284. #endif
  5285. #ifdef WITH_COOKIES
  5286. #ifdef WITH_OPENSSL
  5287. if (soap_putcookies(soap, host, path, soap->ssl != NULL))
  5288. return soap->error;
  5289. #else
  5290. if (soap_putcookies(soap, host, path, 0))
  5291. return soap->error;
  5292. #endif
  5293. #endif
  5294. if (soap->status != SOAP_GET && (soap->version == 1 || (action && *action)))
  5295. { sprintf(soap->tmpbuf, "\"%s\"", action && strlen(action) < sizeof(soap->tmpbuf) - 3 ? action : SOAP_STR_EOS);
  5296. if ((err = soap->fposthdr(soap, "SOAPAction", soap->tmpbuf)))
  5297. return err;
  5298. }
  5299. return soap->fposthdr(soap, NULL, NULL);
  5300. }
  5301. #endif
  5302. #endif
  5303. /******************************************************************************/
  5304. #ifndef WITH_NOHTTP
  5305. #ifndef PALM_1
  5306. static int
  5307. http_send_header(struct soap *soap, const char *s)
  5308. { register const char *t;
  5309. do
  5310. { t = strchr(s, '\n'); /* disallow \n in HTTP headers */
  5311. if (!t)
  5312. t = s + strlen(s);
  5313. if (soap_send_raw(soap, s, t - s))
  5314. return soap->error;
  5315. s = t + 1;
  5316. } while (*t);
  5317. return SOAP_OK;
  5318. }
  5319. #endif
  5320. #endif
  5321. /******************************************************************************/
  5322. #ifndef WITH_NOHTTP
  5323. #ifndef PALM_1
  5324. static int
  5325. http_post_header(struct soap *soap, const char *key, const char *val)
  5326. { if (key)
  5327. { if (http_send_header(soap, key))
  5328. return soap->error;
  5329. if (val && (soap_send_raw(soap, ": ", 2) || http_send_header(soap, val)))
  5330. return soap->error;
  5331. }
  5332. return soap_send_raw(soap, "\r\n", 2);
  5333. }
  5334. #endif
  5335. #endif
  5336. /******************************************************************************/
  5337. #ifndef WITH_NOHTTP
  5338. #ifndef PALM_1
  5339. static int
  5340. http_response(struct soap *soap, int status, size_t count)
  5341. { register int err;
  5342. #ifdef WMW_RPM_IO
  5343. if (soap->rpmreqid)
  5344. httpOutputEnable(soap->rpmreqid);
  5345. #endif
  5346. if (strlen(soap->http_version) > 4)
  5347. return soap->error = SOAP_EOM;
  5348. if (!status || status == SOAP_HTML || status == SOAP_FILE)
  5349. { const char *s;
  5350. if (count || ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK))
  5351. s = "200 OK";
  5352. else
  5353. s = "202 ACCEPTED";
  5354. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Status = %s\n", s));
  5355. #ifdef WMW_RPM_IO
  5356. if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */
  5357. #else
  5358. if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application (socket) or CGI (stdin/out)? */
  5359. #endif
  5360. { sprintf(soap->tmpbuf, "HTTP/%s %s", soap->http_version, s);
  5361. if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
  5362. return err;
  5363. }
  5364. else if ((err = soap->fposthdr(soap, "Status", s))) /* CGI header */
  5365. return err;
  5366. }
  5367. else if (status >= 200 && status < 600)
  5368. { sprintf(soap->tmpbuf, "HTTP/%s %d %s", soap->http_version, status, http_error(soap, status));
  5369. if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
  5370. return err;
  5371. #ifndef WITH_LEAN
  5372. if (status == 401)
  5373. { sprintf(soap->tmpbuf, "Basic realm=\"%s\"", (soap->authrealm && strlen(soap->authrealm) < sizeof(soap->tmpbuf) - 14) ? soap->authrealm : "gSOAP Web Service");
  5374. if ((err = soap->fposthdr(soap, "WWW-Authenticate", soap->tmpbuf)))
  5375. return err;
  5376. }
  5377. else if ((status >= 301 && status <= 303) || status == 307)
  5378. { if ((err = soap->fposthdr(soap, "Location", soap->endpoint)))
  5379. return err;
  5380. }
  5381. #endif
  5382. }
  5383. else
  5384. { const char *s = *soap_faultcode(soap);
  5385. if (status >= SOAP_GET_METHOD && status <= SOAP_HTTP_METHOD)
  5386. s = "405 Method Not Allowed";
  5387. else if (soap->version == 2 && (!s || !strcmp(s, "SOAP-ENV:Sender")))
  5388. s = "400 Bad Request";
  5389. else
  5390. s = "500 Internal Server Error";
  5391. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error %s (status=%d)\n", s, status));
  5392. #ifdef WMW_RPM_IO
  5393. if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */
  5394. #else
  5395. if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application */
  5396. #endif
  5397. { sprintf(soap->tmpbuf, "HTTP/%s %s", soap->http_version, s);
  5398. if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
  5399. return err;
  5400. }
  5401. else if ((err = soap->fposthdr(soap, "Status", s))) /* CGI */
  5402. return err;
  5403. }
  5404. if ((err = soap->fposthdr(soap, "Server", "gSOAP/2.7"))
  5405. || (err = soap_puthttphdr(soap, status, count)))
  5406. return err;
  5407. #ifdef WITH_COOKIES
  5408. if (soap_putsetcookies(soap))
  5409. return soap->error;
  5410. #endif
  5411. return soap->fposthdr(soap, NULL, NULL);
  5412. }
  5413. #endif
  5414. #endif
  5415. /******************************************************************************/
  5416. #ifndef PALM_1
  5417. SOAP_FMAC1
  5418. int
  5419. SOAP_FMAC2
  5420. soap_response(struct soap *soap, int status)
  5421. { register size_t count;
  5422. if (!(soap->omode & (SOAP_ENC_XML | SOAP_IO_STORE /* this tests for chunking too */))
  5423. && (status == SOAP_HTML || status == SOAP_FILE))
  5424. soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE;
  5425. soap->status = status;
  5426. count = soap_count_attachments(soap);
  5427. if (soap_begin_send(soap))
  5428. return soap->error;
  5429. #ifndef WITH_NOHTTP
  5430. if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML))
  5431. { register int n = soap->mode;
  5432. soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB);
  5433. if ((n & SOAP_IO) != SOAP_IO_FLUSH)
  5434. soap->mode |= SOAP_IO_BUFFER;
  5435. if ((soap->error = soap->fresponse(soap, status, count)))
  5436. return soap->error;
  5437. #ifndef WITH_LEANER
  5438. if ((n & SOAP_IO) == SOAP_IO_CHUNK)
  5439. { if (soap_flush(soap))
  5440. return soap->error;
  5441. }
  5442. #endif
  5443. soap->mode = n;
  5444. }
  5445. #endif
  5446. return SOAP_OK;
  5447. }
  5448. #endif
  5449. /******************************************************************************\
  5450. *
  5451. * HTTP Cookies
  5452. *
  5453. \******************************************************************************/
  5454. #ifdef WITH_COOKIES
  5455. /******************************************************************************/
  5456. SOAP_FMAC1
  5457. size_t
  5458. SOAP_FMAC2
  5459. soap_encode_cookie(const char *s, char *t, size_t len)
  5460. { register int c;
  5461. register size_t n = len;
  5462. while ((c = *s++) && --n > 0)
  5463. { if (c > ' ' && c < 128 && !strchr("()<>@,;:\\\"/[]?={}#!$&'*+", c))
  5464. *t++ = c;
  5465. else if (n > 2)
  5466. { *t++ = '%';
  5467. *t++ = (c >> 4) + (c > 159 ? '7' : '0');
  5468. c &= 0xF;
  5469. *t++ = c + (c > 9 ? '7' : '0');
  5470. n -= 2;
  5471. }
  5472. else
  5473. break;
  5474. }
  5475. *t = '\0';
  5476. return len - n;
  5477. }
  5478. /******************************************************************************/
  5479. SOAP_FMAC1
  5480. struct soap_cookie*
  5481. SOAP_FMAC2
  5482. soap_cookie(struct soap *soap, const char *name, const char *domain, const char *path)
  5483. { struct soap_cookie *p;
  5484. if (!domain)
  5485. domain = soap->cookie_domain;
  5486. if (!path)
  5487. path = soap->cookie_path;
  5488. if (!path)
  5489. path = SOAP_STR_EOS;
  5490. else if (*path == '/')
  5491. path++;
  5492. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Search cookie %s domain=%s path=%s\n", name, domain?domain:"(null)", path?path:"(null)"));
  5493. for (p = soap->cookies; p; p = p->next)
  5494. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie in database: %s=%s domain=%s path=%s env=%hd\n", p->name, p->value?p->value:"(null)", p->domain?p->domain:"(null)", p->path?p->path:"(null)", p->env));
  5495. if (!strcmp(p->name, name)
  5496. && p->domain
  5497. && p->path
  5498. && !strcmp(p->domain, domain)
  5499. && (!*p->path || !strncmp(p->path, path, strlen(p->path))))
  5500. break;
  5501. }
  5502. return p;
  5503. }
  5504. /******************************************************************************/
  5505. SOAP_FMAC1
  5506. struct soap_cookie*
  5507. SOAP_FMAC2
  5508. soap_set_cookie(struct soap *soap, const char *name, const char *value, const char *domain, const char *path)
  5509. { struct soap_cookie **p, *q;
  5510. int n;
  5511. if (!domain)
  5512. domain = soap->cookie_domain;
  5513. if (!path)
  5514. path = soap->cookie_path;
  5515. if (!path)
  5516. path = SOAP_STR_EOS;
  5517. else if (*path == '/')
  5518. path++;
  5519. q = soap_cookie(soap, name, domain, path);
  5520. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set %scookie: %s=%s domain=%s path=%s\n", q ? SOAP_STR_EOS : "new ", name, value?value:"(null)", domain?domain:"(null)", path?path:"(null)"));
  5521. if (!q)
  5522. { if ((q = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie))))
  5523. { if ((q->name = (char*)SOAP_MALLOC(soap, strlen(name)+1)))
  5524. strcpy(q->name, name);
  5525. q->value = NULL;
  5526. q->domain = NULL;
  5527. q->path = NULL;
  5528. q->expire = 0;
  5529. q->maxage = -1;
  5530. q->version = 1;
  5531. q->secure = 0;
  5532. q->modified = 0;
  5533. for (p = &soap->cookies, n = soap->cookie_max; *p && n; p = &(*p)->next, n--)
  5534. if (!strcmp((*p)->name, name) && (*p)->path && path && strcmp((*p)->path, path) < 0)
  5535. break;
  5536. if (n)
  5537. { q->next = *p;
  5538. *p = q;
  5539. }
  5540. else
  5541. { SOAP_FREE(soap, q->name);
  5542. SOAP_FREE(soap, q);
  5543. q = NULL;
  5544. }
  5545. }
  5546. }
  5547. else
  5548. q->modified = 1;
  5549. if (q)
  5550. { if (q->value)
  5551. { if (!value || strcmp(value, q->value))
  5552. { SOAP_FREE(soap, q->value);
  5553. q->value = NULL;
  5554. }
  5555. }
  5556. if (value && *value && !q->value && (q->value = (char*)SOAP_MALLOC(soap, strlen(value)+1)))
  5557. strcpy(q->value, value);
  5558. if (q->domain)
  5559. { if (!domain || strcmp(domain, q->domain))
  5560. { SOAP_FREE(soap, q->domain);
  5561. q->domain = NULL;
  5562. }
  5563. }
  5564. if (domain && !q->domain && (q->domain = (char*)SOAP_MALLOC(soap, strlen(domain)+1)))
  5565. strcpy(q->domain, domain);
  5566. if (q->path)
  5567. { if (!path || strncmp(path, q->path, strlen(q->path)))
  5568. { SOAP_FREE(soap, q->path);
  5569. q->path = NULL;
  5570. }
  5571. }
  5572. if (path && !q->path && (q->path = (char*)SOAP_MALLOC(soap, strlen(path)+1)))
  5573. strcpy(q->path, path);
  5574. q->session = 1;
  5575. q->env = 0;
  5576. }
  5577. return q;
  5578. }
  5579. /******************************************************************************/
  5580. SOAP_FMAC1
  5581. void
  5582. SOAP_FMAC2
  5583. soap_clr_cookie(struct soap *soap, const char *name, const char *domain, const char *path)
  5584. { struct soap_cookie **p, *q;
  5585. if (!domain)
  5586. domain = soap->cookie_domain;
  5587. if (!domain)
  5588. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error in clear cookie %s: cookie domain not set\n", name?name:"(null)"));
  5589. return;
  5590. }
  5591. if (!path)
  5592. path = soap->cookie_path;
  5593. if (!path)
  5594. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error in clear cookie %s: cookie path not set\n", name?name:"(null)"));
  5595. return;
  5596. }
  5597. if (*path == '/')
  5598. path++;
  5599. for (p = &soap->cookies, q = *p; q; q = *p)
  5600. { if (!strcmp(q->name, name) && !strcmp(q->domain, domain) && !strncmp(q->path, path, strlen(q->path)))
  5601. { if (q->value)
  5602. SOAP_FREE(soap, q->value);
  5603. if (q->domain)
  5604. SOAP_FREE(soap, q->domain);
  5605. if (q->path)
  5606. SOAP_FREE(soap, q->path);
  5607. *p = q->next;
  5608. SOAP_FREE(soap, q);
  5609. }
  5610. else
  5611. p = &q->next;
  5612. }
  5613. }
  5614. /******************************************************************************/
  5615. SOAP_FMAC1
  5616. char *
  5617. SOAP_FMAC2
  5618. soap_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path)
  5619. { struct soap_cookie *p;
  5620. if ((p = soap_cookie(soap, name, domain, path)))
  5621. return p->value;
  5622. return NULL;
  5623. }
  5624. /******************************************************************************/
  5625. SOAP_FMAC1
  5626. char *
  5627. SOAP_FMAC2
  5628. soap_env_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path)
  5629. { struct soap_cookie *p;
  5630. if ((p = soap_cookie(soap, name, domain, path)) && p->env)
  5631. return p->value;
  5632. return NULL;
  5633. }
  5634. /******************************************************************************/
  5635. SOAP_FMAC1
  5636. time_t
  5637. SOAP_FMAC2
  5638. soap_cookie_expire(struct soap *soap, const char *name, const char *domain, const char *path)
  5639. { struct soap_cookie *p;
  5640. if ((p = soap_cookie(soap, name, domain, path)))
  5641. return p->expire;
  5642. return -1;
  5643. }
  5644. /******************************************************************************/
  5645. SOAP_FMAC1
  5646. int
  5647. SOAP_FMAC2
  5648. soap_set_cookie_expire(struct soap *soap, const char *name, long expire, const char *domain, const char *path)
  5649. { struct soap_cookie *p;
  5650. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set cookie expiration max-age %ld: %s domain=%s path=%s\n", expire, name, domain?domain:"(null)", path?path:"(null)"));
  5651. if ((p = soap_cookie(soap, name, domain, path)))
  5652. { p->maxage = expire;
  5653. p->modified = 1;
  5654. return SOAP_OK;
  5655. }
  5656. return SOAP_ERR;
  5657. }
  5658. /******************************************************************************/
  5659. SOAP_FMAC1
  5660. int
  5661. SOAP_FMAC2
  5662. soap_set_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path)
  5663. { struct soap_cookie *p;
  5664. if ((p = soap_cookie(soap, name, domain, path)))
  5665. { p->session = 1;
  5666. p->modified = 1;
  5667. return SOAP_OK;
  5668. }
  5669. return SOAP_ERR;
  5670. }
  5671. /******************************************************************************/
  5672. SOAP_FMAC1
  5673. int
  5674. SOAP_FMAC2
  5675. soap_clr_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path)
  5676. { struct soap_cookie *p;
  5677. if ((p = soap_cookie(soap, name, domain, path)))
  5678. { p->session = 0;
  5679. p->modified = 1;
  5680. return SOAP_OK;
  5681. }
  5682. return SOAP_ERR;
  5683. }
  5684. /******************************************************************************/
  5685. SOAP_FMAC1
  5686. int
  5687. SOAP_FMAC2
  5688. soap_putsetcookies(struct soap *soap)
  5689. { struct soap_cookie *p;
  5690. char *s, tmp[4096];
  5691. const char *t;
  5692. for (p = soap->cookies; p; p = p->next)
  5693. {
  5694. if (p->modified
  5695. #ifdef WITH_OPENSSL
  5696. || (!p->env && !soap->ssl == !p->secure)
  5697. #endif
  5698. )
  5699. { s = tmp;
  5700. if (p->name)
  5701. s += soap_encode_cookie(p->name, s, tmp-s+4064);
  5702. if (p->value && *p->value)
  5703. { *s++ = '=';
  5704. s += soap_encode_cookie(p->value, s, tmp-s+4064);
  5705. }
  5706. if (p->domain && (int)strlen(p->domain) < tmp-s+4064)
  5707. { strcpy(s, ";Domain=");
  5708. strcat(s, p->domain);
  5709. }
  5710. else if (soap->cookie_domain && (int)strlen(soap->cookie_domain) < tmp-s+4064)
  5711. { strcpy(s, ";Domain=");
  5712. strcat(s, soap->cookie_domain);
  5713. }
  5714. strcat(s, ";Path=/");
  5715. s += strlen(s);
  5716. if (p->path)
  5717. t = p->path;
  5718. else
  5719. t = soap->cookie_path;
  5720. if (t)
  5721. { if (*t == '/')
  5722. t++;
  5723. if ((int)strlen(t) < tmp-s+4064)
  5724. { if (strchr(t, '%')) /* already URL encoded? */
  5725. { strcpy(s, t);
  5726. s += strlen(s);
  5727. }
  5728. else
  5729. s += soap_encode_cookie(t, s, tmp-s+4064);
  5730. }
  5731. }
  5732. if (p->version > 0 && s-tmp < 4060)
  5733. { sprintf(s, ";Version=%u", p->version);
  5734. s += strlen(s);
  5735. }
  5736. if (p->maxage >= 0 && s-tmp < 4060)
  5737. { sprintf(s, ";Max-Age=%ld", p->maxage);
  5738. s += strlen(s);
  5739. }
  5740. if (s-tmp < 4073
  5741. && (p->secure
  5742. #ifdef WITH_OPENSSL
  5743. || soap->ssl
  5744. #endif
  5745. ))
  5746. strcpy(s, ";Secure");
  5747. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set-Cookie: %s\n", tmp));
  5748. if ((soap->error = soap->fposthdr(soap, "Set-Cookie", tmp)))
  5749. return soap->error;
  5750. }
  5751. }
  5752. return SOAP_OK;
  5753. }
  5754. /******************************************************************************/
  5755. SOAP_FMAC1
  5756. int
  5757. SOAP_FMAC2
  5758. soap_putcookies(struct soap *soap, const char *domain, const char *path, int secure)
  5759. { struct soap_cookie **p, *q;
  5760. unsigned int version = 0;
  5761. time_t now = time(NULL);
  5762. char *s, tmp[4096];
  5763. p = &soap->cookies;
  5764. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending cookies for domain=%s path=%s\n", domain, path));
  5765. if (*path == '/')
  5766. path++;
  5767. while ((q = *p))
  5768. { if (q->expire && now > q->expire)
  5769. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie %s expired\n", q->name));
  5770. SOAP_FREE(soap, q->name);
  5771. if (q->value)
  5772. SOAP_FREE(soap, q->value);
  5773. if (q->domain)
  5774. SOAP_FREE(soap, q->domain);
  5775. if (q->path)
  5776. SOAP_FREE(soap, q->path);
  5777. *p = q->next;
  5778. SOAP_FREE(soap, q);
  5779. }
  5780. else
  5781. { int flag;
  5782. char *t = q->domain;
  5783. size_t n = 0;
  5784. if (!t)
  5785. flag = 1;
  5786. else
  5787. { const char *r = strchr(t, ':');
  5788. if (r)
  5789. n = r - t;
  5790. else
  5791. n = strlen(t);
  5792. flag = !strncmp(t, domain, n);
  5793. }
  5794. /* domain-level cookies, cannot compile when WITH_NOIO set */
  5795. #ifndef WITH_NOIO
  5796. if (!flag)
  5797. { struct hostent *hostent = gethostbyname((char*)domain);
  5798. if (hostent)
  5799. { const char *r = strchr(hostent->h_name, '.');
  5800. if (!r)
  5801. r = hostent->h_name;
  5802. flag = !strncmp(t, r, n);
  5803. }
  5804. }
  5805. #endif
  5806. if (flag
  5807. && (!q->path || !strncmp(q->path, path, strlen(q->path)))
  5808. && (!q->secure || secure))
  5809. { s = tmp;
  5810. if (q->version != version)
  5811. { sprintf(s, "$Version=%u;", q->version);
  5812. version = q->version;
  5813. }
  5814. if (q->name)
  5815. s += soap_encode_cookie(q->name, s, tmp-s+4080);
  5816. if (q->value && *q->value)
  5817. { *s++ = '=';
  5818. s += soap_encode_cookie(q->value, s, tmp-s+4080);
  5819. }
  5820. if (q->path && *q->path && (int)strlen(q->path) < tmp-s+4080)
  5821. { sprintf(s, ";$Path=\"/%s\"", (*q->path == '/' ? q->path + 1 : q->path));
  5822. s += strlen(s);
  5823. }
  5824. if (q->domain && (int)strlen(q->domain) < tmp-s+4080)
  5825. sprintf(s, ";$Domain=\"%s\"", q->domain);
  5826. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie: %s\n", tmp));
  5827. if ((soap->error = soap->fposthdr(soap, "Cookie", tmp)))
  5828. return soap->error;
  5829. }
  5830. p = &q->next;
  5831. }
  5832. }
  5833. return SOAP_OK;
  5834. }
  5835. /******************************************************************************/
  5836. SOAP_FMAC1
  5837. void
  5838. SOAP_FMAC2
  5839. soap_getcookies(struct soap *soap, const char *val)
  5840. { struct soap_cookie *p = NULL, *q;
  5841. const char *s;
  5842. char *t, tmp[4096]; /* cookie size is up to 4096 bytes [RFC2109] */
  5843. char *domain = NULL;
  5844. char *path = NULL;
  5845. unsigned int version = 0;
  5846. time_t now = time(NULL);
  5847. if (!val)
  5848. return;
  5849. s = val;
  5850. while (*s)
  5851. { s = soap_decode_key(tmp, sizeof(tmp), s);
  5852. if (!soap_tag_cmp(tmp, "$Version"))
  5853. { if ((s = soap_decode_val(tmp, sizeof(tmp), s)))
  5854. { if (p)
  5855. p->version = (int)soap_strtol(tmp, NULL, 10);
  5856. else
  5857. version = (int)soap_strtol(tmp, NULL, 10);
  5858. }
  5859. }
  5860. else if (!soap_tag_cmp(tmp, "$Path"))
  5861. { s = soap_decode_val(tmp, sizeof(tmp), s);
  5862. if (*tmp)
  5863. { if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1)))
  5864. strcpy(t, tmp);
  5865. }
  5866. else
  5867. t = NULL;
  5868. if (p)
  5869. { if (p->path)
  5870. SOAP_FREE(soap, p->path);
  5871. p->path = t;
  5872. }
  5873. else
  5874. { if (path)
  5875. SOAP_FREE(soap, path);
  5876. path = t;
  5877. }
  5878. }
  5879. else if (!soap_tag_cmp(tmp, "$Domain"))
  5880. { s = soap_decode_val(tmp, sizeof(tmp), s);
  5881. if (*tmp)
  5882. { if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1)))
  5883. strcpy(t, tmp);
  5884. }
  5885. else
  5886. t = NULL;
  5887. if (p)
  5888. { if (p->domain)
  5889. SOAP_FREE(soap, p->domain);
  5890. p->domain = t;
  5891. }
  5892. else
  5893. { if (domain)
  5894. SOAP_FREE(soap, domain);
  5895. domain = t;
  5896. }
  5897. }
  5898. else if (p && !soap_tag_cmp(tmp, "Path"))
  5899. { if (p->path)
  5900. SOAP_FREE(soap, p->path);
  5901. s = soap_decode_val(tmp, sizeof(tmp), s);
  5902. if (*tmp)
  5903. { if ((p->path = (char*)SOAP_MALLOC(soap, strlen(tmp)+1)))
  5904. strcpy(p->path, tmp);
  5905. }
  5906. else
  5907. p->path = NULL;
  5908. }
  5909. else if (p && !soap_tag_cmp(tmp, "Domain"))
  5910. { if (p->domain)
  5911. SOAP_FREE(soap, p->domain);
  5912. s = soap_decode_val(tmp, sizeof(tmp), s);
  5913. if (*tmp)
  5914. { if ((p->domain = (char*)SOAP_MALLOC(soap, strlen(tmp)+1)))
  5915. strcpy(p->domain, tmp);
  5916. }
  5917. else
  5918. p->domain = NULL;
  5919. }
  5920. else if (p && !soap_tag_cmp(tmp, "Version"))
  5921. { s = soap_decode_val(tmp, sizeof(tmp), s);
  5922. p->version = (unsigned int)soap_strtoul(tmp, NULL, 10);
  5923. }
  5924. else if (p && !soap_tag_cmp(tmp, "Max-Age"))
  5925. { s = soap_decode_val(tmp, sizeof(tmp), s);
  5926. p->expire = now + soap_strtol(tmp, NULL, 10);
  5927. }
  5928. else if (p && !soap_tag_cmp(tmp, "Expires"))
  5929. { struct tm T;
  5930. char a[3];
  5931. static const char mns[] = "anebarprayunulugepctovec";
  5932. s = soap_decode_val(tmp, sizeof(tmp), s);
  5933. if (strlen(tmp) > 20)
  5934. { memset((void*)&T, 0, sizeof(T));
  5935. a[0] = tmp[4];
  5936. a[1] = tmp[5];
  5937. a[2] = '\0';
  5938. T.tm_mday = (int)soap_strtol(a, NULL, 10);
  5939. a[0] = tmp[8];
  5940. a[1] = tmp[9];
  5941. T.tm_mon = (int)(strstr(mns, a) - mns) / 2;
  5942. a[0] = tmp[11];
  5943. a[1] = tmp[12];
  5944. T.tm_year = 100 + (int)soap_strtol(a, NULL, 10);
  5945. a[0] = tmp[13];
  5946. a[1] = tmp[14];
  5947. T.tm_hour = (int)soap_strtol(a, NULL, 10);
  5948. a[0] = tmp[16];
  5949. a[1] = tmp[17];
  5950. T.tm_min = (int)soap_strtol(a, NULL, 10);
  5951. a[0] = tmp[19];
  5952. a[1] = tmp[20];
  5953. T.tm_sec = (int)soap_strtol(a, NULL, 10);
  5954. p->expire = soap_timegm(&T);
  5955. }
  5956. }
  5957. else if (p && !soap_tag_cmp(tmp, "Secure"))
  5958. p->secure = 1;
  5959. else
  5960. { if (p)
  5961. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie %s=%s domain=%s path=%s expire=%ld secure=%d\n", p->name, p->value?p->value:"(null)", p->domain?p->domain:"(null)", p->path?p->path:"(null)", p->expire, p->secure));
  5962. if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path)))
  5963. { q->version = p->version;
  5964. q->expire = p->expire;
  5965. q->secure = p->secure;
  5966. q->env = 1;
  5967. }
  5968. if (p->name)
  5969. SOAP_FREE(soap, p->name);
  5970. if (p->value)
  5971. SOAP_FREE(soap, p->value);
  5972. if (p->domain)
  5973. SOAP_FREE(soap, p->domain);
  5974. if (p->path)
  5975. SOAP_FREE(soap, p->path);
  5976. SOAP_FREE(soap, p);
  5977. }
  5978. if ((p = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie))))
  5979. { p->name = (char*)SOAP_MALLOC(soap, strlen(tmp)+1);
  5980. strcpy(p->name, tmp);
  5981. s = soap_decode_val(tmp, sizeof(tmp), s);
  5982. if (*tmp)
  5983. { p->value = (char*)SOAP_MALLOC(soap, strlen(tmp)+1);
  5984. strcpy(p->value, tmp);
  5985. }
  5986. else
  5987. p->value = NULL;
  5988. if (domain)
  5989. p->domain = domain;
  5990. else if (*soap->host)
  5991. { p->domain = (char*)SOAP_MALLOC(soap, strlen(soap->host)+1);
  5992. strcpy(p->domain, soap->host);
  5993. }
  5994. else
  5995. p->domain = NULL;
  5996. if (path)
  5997. p->path = path;
  5998. else if (soap->path && *soap->path)
  5999. { p->path = (char*)SOAP_MALLOC(soap, strlen(soap->path)+1);
  6000. strcpy(p->path, soap->path);
  6001. }
  6002. else
  6003. { p->path = (char*)SOAP_MALLOC(soap, 2);
  6004. strcpy(p->path, "/");
  6005. }
  6006. p->expire = 0;
  6007. p->secure = 0;
  6008. p->version = version;
  6009. }
  6010. }
  6011. }
  6012. if (p)
  6013. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie %s=%s domain=%s path=%s expire=%ld secure=%d\n", p->name, p->value?p->value:"(null)", p->domain?p->domain:"(null)", p->path?p->path:"(null)", p->expire, p->secure));
  6014. if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path)))
  6015. { q->version = p->version;
  6016. q->expire = p->expire;
  6017. q->secure = p->secure;
  6018. q->env = 1;
  6019. }
  6020. if (p->name)
  6021. SOAP_FREE(soap, p->name);
  6022. if (p->value)
  6023. SOAP_FREE(soap, p->value);
  6024. if (p->domain)
  6025. SOAP_FREE(soap, p->domain);
  6026. if (p->path)
  6027. SOAP_FREE(soap, p->path);
  6028. SOAP_FREE(soap, p);
  6029. }
  6030. if (domain)
  6031. SOAP_FREE(soap, domain);
  6032. if (path)
  6033. SOAP_FREE(soap, path);
  6034. }
  6035. /******************************************************************************/
  6036. SOAP_FMAC1
  6037. int
  6038. SOAP_FMAC2
  6039. soap_getenv_cookies(struct soap *soap)
  6040. { struct soap_cookie *p;
  6041. const char *s;
  6042. char key[4096], val[4096]; /* cookie size is up to 4096 bytes [RFC2109] */
  6043. if (!(s = getenv("HTTP_COOKIE")))
  6044. return SOAP_ERR;
  6045. do
  6046. { s = soap_decode_key(key, sizeof(key), s);
  6047. s = soap_decode_val(val, sizeof(val), s);
  6048. p = soap_set_cookie(soap, key, val, NULL, NULL);
  6049. if (p)
  6050. p->env = 1;
  6051. } while (*s);
  6052. return SOAP_OK;
  6053. }
  6054. /******************************************************************************/
  6055. SOAP_FMAC1
  6056. struct soap_cookie*
  6057. SOAP_FMAC2
  6058. soap_copy_cookies(struct soap *copy, const struct soap *soap)
  6059. { struct soap_cookie *p, **q, *r;
  6060. q = &r;
  6061. for (p = soap->cookies; p; p = p->next)
  6062. { if (!(*q = (struct soap_cookie*)SOAP_MALLOC(copy, sizeof(struct soap_cookie))))
  6063. return r;
  6064. **q = *p;
  6065. if (p->name)
  6066. { if (((*q)->name = (char*)SOAP_MALLOC(copy, strlen(p->name)+1)))
  6067. strcpy((*q)->name, p->name);
  6068. }
  6069. if (p->value)
  6070. { if (((*q)->value = (char*)SOAP_MALLOC(copy, strlen(p->value)+1)))
  6071. strcpy((*q)->value, p->value);
  6072. }
  6073. if (p->domain)
  6074. { if (((*q)->domain = (char*)SOAP_MALLOC(copy, strlen(p->domain)+1)))
  6075. strcpy((*q)->domain, p->domain);
  6076. }
  6077. if (p->path)
  6078. { if (((*q)->path = (char*)SOAP_MALLOC(copy, strlen(p->path)+1)))
  6079. strcpy((*q)->path, p->path);
  6080. }
  6081. q = &(*q)->next;
  6082. }
  6083. *q = NULL;
  6084. return r;
  6085. }
  6086. /******************************************************************************/
  6087. SOAP_FMAC1
  6088. void
  6089. SOAP_FMAC2
  6090. soap_free_cookies(struct soap *soap)
  6091. { struct soap_cookie *p;
  6092. for (p = soap->cookies; p; p = soap->cookies)
  6093. { soap->cookies = p->next;
  6094. SOAP_FREE(soap, p->name);
  6095. if (p->value)
  6096. SOAP_FREE(soap, p->value);
  6097. if (p->domain)
  6098. SOAP_FREE(soap, p->domain);
  6099. if (p->path)
  6100. SOAP_FREE(soap, p->path);
  6101. SOAP_FREE(soap, p);
  6102. }
  6103. }
  6104. /******************************************************************************/
  6105. #endif /* WITH_COOKIES */
  6106. /******************************************************************************/
  6107. #ifndef WITH_NOIDREF
  6108. #ifndef PALM_2
  6109. SOAP_FMAC1
  6110. size_t
  6111. SOAP_FMAC2
  6112. soap_hash(register const char *s)
  6113. { register size_t h = 0;
  6114. while (*s)
  6115. h = 65599*h + *s++;
  6116. return h % SOAP_IDHASH;
  6117. }
  6118. #endif
  6119. #endif
  6120. /******************************************************************************/
  6121. #ifndef WITH_NOIDREF
  6122. #ifndef PALM_1
  6123. static void
  6124. soap_init_pht(struct soap *soap)
  6125. { register int i;
  6126. soap->pblk = NULL;
  6127. soap->pidx = 0;
  6128. for (i = 0; i < (int)SOAP_PTRHASH; i++)
  6129. soap->pht[i] = NULL;
  6130. }
  6131. #endif
  6132. #endif
  6133. /******************************************************************************/
  6134. #ifndef PALM_1
  6135. SOAP_FMAC1
  6136. struct soap*
  6137. SOAP_FMAC2
  6138. soap_new1(soap_mode mode)
  6139. { return soap_new2(mode, mode);
  6140. }
  6141. #endif
  6142. /******************************************************************************/
  6143. #ifndef PALM_1
  6144. SOAP_FMAC1
  6145. struct soap*
  6146. SOAP_FMAC2
  6147. soap_new()
  6148. { return soap_new2(SOAP_IO_DEFAULT, SOAP_IO_DEFAULT);
  6149. }
  6150. #endif
  6151. /******************************************************************************/
  6152. #ifndef PALM_1
  6153. SOAP_FMAC1
  6154. struct soap*
  6155. SOAP_FMAC2
  6156. soap_new2(soap_mode imode, soap_mode omode)
  6157. { struct soap *soap = (struct soap*)malloc(sizeof(struct soap));
  6158. if (soap)
  6159. soap_init2(soap, imode, omode);
  6160. return soap;
  6161. }
  6162. #endif
  6163. /******************************************************************************/
  6164. #ifndef PALM_1
  6165. SOAP_FMAC1
  6166. void
  6167. SOAP_FMAC2
  6168. soap_free(struct soap *soap)
  6169. { soap_done(soap);
  6170. free(soap);
  6171. }
  6172. #endif
  6173. /******************************************************************************/
  6174. #ifndef PALM_1
  6175. SOAP_FMAC1
  6176. void
  6177. SOAP_FMAC2
  6178. soap_del(struct soap *soap)
  6179. { free(soap);
  6180. }
  6181. #endif
  6182. /******************************************************************************/
  6183. #ifndef WITH_NOIDREF
  6184. #ifndef PALM_1
  6185. static void
  6186. soap_free_pht(struct soap *soap)
  6187. { register struct soap_pblk *pb, *next;
  6188. register int i;
  6189. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free pointer hashtable\n"));
  6190. for (pb = soap->pblk; pb; pb = next)
  6191. { next = pb->next;
  6192. SOAP_FREE(soap, pb);
  6193. }
  6194. soap->pblk = NULL;
  6195. soap->pidx = 0;
  6196. for (i = 0; i < (int)SOAP_PTRHASH; i++)
  6197. soap->pht[i] = NULL;
  6198. }
  6199. #endif
  6200. #endif
  6201. /******************************************************************************/
  6202. #ifndef WITH_NOIDREF
  6203. #ifndef PALM_2
  6204. SOAP_FMAC1
  6205. int
  6206. SOAP_FMAC2
  6207. soap_embed(struct soap *soap, const void *p, const struct soap_array *a, int n, const char *tag, int type)
  6208. { register int i;
  6209. struct soap_plist *pp;
  6210. if (soap->version == 2)
  6211. soap->encoding = 1;
  6212. if (a)
  6213. i = soap_array_pointer_lookup(soap, p, a, n, type, &pp);
  6214. else
  6215. i = soap_pointer_lookup(soap, p, type, &pp);
  6216. if (i)
  6217. { if (soap_is_embedded(soap, pp)
  6218. || soap_is_single(soap, pp))
  6219. return 0;
  6220. soap_set_embedded(soap, pp);
  6221. }
  6222. return i;
  6223. }
  6224. #endif
  6225. #endif
  6226. /******************************************************************************/
  6227. #ifndef WITH_NOIDREF
  6228. #ifndef PALM_2
  6229. SOAP_FMAC1
  6230. int
  6231. SOAP_FMAC2
  6232. soap_pointer_lookup(struct soap *soap, const void *p, int type, struct soap_plist **ppp)
  6233. { register struct soap_plist *pp;
  6234. *ppp = NULL;
  6235. if (p)
  6236. { for (pp = soap->pht[soap_hash_ptr(p)]; pp; pp = pp->next)
  6237. { if (pp->ptr == p && pp->type == type)
  6238. { *ppp = pp;
  6239. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d id=%d\n", p, type, pp->id));
  6240. return pp->id;
  6241. }
  6242. }
  6243. }
  6244. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d: not found\n", p, type));
  6245. return 0;
  6246. }
  6247. #endif
  6248. #endif
  6249. /******************************************************************************/
  6250. #ifndef WITH_NOIDREF
  6251. #ifndef PALM_2
  6252. SOAP_FMAC1
  6253. int
  6254. SOAP_FMAC2
  6255. soap_pointer_enter(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp)
  6256. { register size_t h;
  6257. register struct soap_plist *pp;
  6258. if (!soap->pblk || soap->pidx >= SOAP_PTRBLK)
  6259. { register struct soap_pblk *pb = (struct soap_pblk*)SOAP_MALLOC(soap, sizeof(struct soap_pblk));
  6260. if (!pb)
  6261. { soap->error = SOAP_EOM;
  6262. return 0;
  6263. }
  6264. pb->next = soap->pblk;
  6265. soap->pblk = pb;
  6266. soap->pidx = 0;
  6267. }
  6268. *ppp = pp = &soap->pblk->plist[soap->pidx++];
  6269. if (a)
  6270. h = soap_hash_ptr(a->__ptr);
  6271. else
  6272. h = soap_hash_ptr(p);
  6273. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pointer enter location=%p array=%p size=%d dim=%d type=%d id=%d\n", p, a?a->__ptr:NULL, a?a->__size:0, n, type, soap->idnum+1));
  6274. pp->next = soap->pht[h];
  6275. pp->type = type;
  6276. pp->mark1 = 0;
  6277. pp->mark2 = 0;
  6278. pp->ptr = p;
  6279. pp->array = a;
  6280. soap->pht[h] = pp;
  6281. pp->id = ++soap->idnum;
  6282. return pp->id;
  6283. }
  6284. #endif
  6285. #endif
  6286. /******************************************************************************/
  6287. #ifndef WITH_NOIDREF
  6288. #ifndef PALM_2
  6289. SOAP_FMAC1
  6290. int
  6291. SOAP_FMAC2
  6292. soap_array_pointer_lookup(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp)
  6293. { register struct soap_plist *pp;
  6294. *ppp = NULL;
  6295. if (!p || !a->__ptr)
  6296. return 0;
  6297. for (pp = soap->pht[soap_hash_ptr(a->__ptr)]; pp; pp = pp->next)
  6298. { if (pp->type == type && pp->array && pp->array->__ptr == a->__ptr)
  6299. { register int i;
  6300. for (i = 0; i < n; i++)
  6301. if (((const int*)&pp->array->__size)[i] != ((const int*)&a->__size)[i])
  6302. break;
  6303. if (i == n)
  6304. { *ppp = pp;
  6305. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d id=%d\n", a->__ptr, type, pp->id));
  6306. return pp->id;
  6307. }
  6308. }
  6309. }
  6310. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d: not found\n", a->__ptr, type));
  6311. return 0;
  6312. }
  6313. #endif
  6314. #endif
  6315. /******************************************************************************/
  6316. #ifndef PALM_1
  6317. SOAP_FMAC1
  6318. int
  6319. SOAP_FMAC2
  6320. soap_begin_count(struct soap *soap)
  6321. { soap_free_ns(soap);
  6322. #ifndef WITH_LEANER
  6323. if ((soap->mode & SOAP_ENC_DIME) || (soap->omode & SOAP_ENC_DIME))
  6324. soap->mode = soap->omode | SOAP_IO_LENGTH | SOAP_ENC_DIME;
  6325. else
  6326. #endif
  6327. { soap->mode = soap->omode;
  6328. if ((soap->mode & SOAP_IO_UDP))
  6329. soap->mode |= SOAP_ENC_XML;
  6330. if ((soap->mode & SOAP_IO) == SOAP_IO_STORE
  6331. || (((soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_ENC_XML))
  6332. #ifndef WITH_LEANER
  6333. && !soap->fpreparesend
  6334. #endif
  6335. ))
  6336. soap->mode &= ~SOAP_IO_LENGTH;
  6337. else
  6338. soap->mode |= SOAP_IO_LENGTH;
  6339. }
  6340. #ifdef WITH_ZLIB
  6341. if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH)
  6342. { if (!(soap->mode & SOAP_ENC_DIME))
  6343. soap->mode &= ~SOAP_IO_LENGTH;
  6344. if (soap->mode & SOAP_ENC_XML)
  6345. soap->mode |= SOAP_IO_BUFFER;
  6346. else
  6347. soap->mode |= SOAP_IO_STORE;
  6348. }
  6349. #endif
  6350. if (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH))
  6351. soap->mode |= SOAP_XML_TREE;
  6352. #ifndef WITH_LEANER
  6353. if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME))
  6354. soap->mode |= SOAP_ENC_MIME;
  6355. else if (!(soap->mode & SOAP_ENC_MIME))
  6356. soap->mode &= ~SOAP_ENC_MTOM;
  6357. if (soap->mode & SOAP_ENC_MIME)
  6358. soap_select_mime_boundary(soap);
  6359. soap->dime.list = soap->dime.last; /* keep track of last DIME attachment */
  6360. #endif
  6361. soap->count = 0;
  6362. soap->ns = 0;
  6363. soap->null = 0;
  6364. soap->position = 0;
  6365. soap->mustUnderstand = 0;
  6366. soap->encoding = 0;
  6367. soap->part = SOAP_BEGIN;
  6368. soap->idnum = 0;
  6369. soap_clr_attr(soap);
  6370. soap_set_local_namespaces(soap);
  6371. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin count phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, (unsigned int)soap->mode, (unsigned long)soap->count));
  6372. #ifndef WITH_LEANER
  6373. soap->dime.count = 0; /* count # of attachments */
  6374. soap->dime.size = 0; /* accumulate total size of attachments */
  6375. if (soap->fprepareinitsend && (soap->mode & SOAP_IO) != SOAP_IO_STORE)
  6376. return soap->error = soap->fprepareinitsend(soap);
  6377. #endif
  6378. return SOAP_OK;
  6379. }
  6380. #endif
  6381. /******************************************************************************/
  6382. #ifndef PALM_1
  6383. SOAP_FMAC1
  6384. int
  6385. SOAP_FMAC2
  6386. soap_end_count(struct soap *soap)
  6387. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of count phase\n"));
  6388. #ifndef WITH_LEANER
  6389. if (soap->fpreparefinalsend && (soap->mode & SOAP_IO_LENGTH))
  6390. return soap->error = soap->fpreparefinalsend(soap);
  6391. #endif
  6392. return SOAP_OK;
  6393. }
  6394. #endif
  6395. /******************************************************************************/
  6396. #ifndef PALM_1
  6397. SOAP_FMAC1
  6398. int
  6399. SOAP_FMAC2
  6400. soap_begin_send(struct soap *soap)
  6401. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing for output\n"));
  6402. soap_free_ns(soap);
  6403. soap->error = SOAP_OK;
  6404. soap->mode = soap->omode | (soap->mode & (SOAP_IO_LENGTH | SOAP_ENC_DIME));
  6405. #ifdef WITH_ZLIB
  6406. if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH)
  6407. { if (soap->mode & SOAP_ENC_XML)
  6408. soap->mode |= SOAP_IO_BUFFER;
  6409. else
  6410. soap->mode |= SOAP_IO_STORE;
  6411. }
  6412. #endif
  6413. #ifndef WITH_LEAN
  6414. if ((soap->mode & SOAP_IO_UDP))
  6415. { soap->mode |= SOAP_ENC_XML;
  6416. if (soap->count > SOAP_BUFLEN)
  6417. return soap->error = SOAP_UDP_ERROR;
  6418. }
  6419. #endif
  6420. if ((soap->mode & SOAP_IO) == SOAP_IO_FLUSH && soap_valid_socket(soap->socket))
  6421. { if (soap->count || (soap->mode & SOAP_IO_LENGTH) || (soap->mode & SOAP_ENC_XML))
  6422. soap->mode |= SOAP_IO_BUFFER;
  6423. else
  6424. soap->mode |= SOAP_IO_STORE;
  6425. }
  6426. soap->mode &= ~SOAP_IO_LENGTH;
  6427. if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
  6428. if (soap_new_block(soap) == NULL)
  6429. return soap->error;
  6430. if (!(soap->mode & SOAP_IO_KEEPALIVE))
  6431. soap->keep_alive = 0;
  6432. if (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH))
  6433. soap->mode |= SOAP_XML_TREE;
  6434. #ifndef WITH_LEANER
  6435. if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME))
  6436. { soap->mode |= SOAP_ENC_MIME;
  6437. soap->mode &= ~SOAP_ENC_DIME;
  6438. }
  6439. else if (!(soap->mode & SOAP_ENC_MIME))
  6440. soap->mode &= ~SOAP_ENC_MTOM;
  6441. if (soap->mode & SOAP_ENC_MIME)
  6442. soap_select_mime_boundary(soap);
  6443. #ifdef WIN32
  6444. #ifndef UNDER_CE
  6445. #ifndef WITH_FASTCGI
  6446. if (!soap_valid_socket(soap->socket)) /* Set win32 stdout or soap->sendfd to BINARY, e.g. to support DIME */
  6447. #ifdef __BORLANDC__
  6448. setmode(soap->sendfd, _O_BINARY);
  6449. #else
  6450. _setmode(soap->sendfd, _O_BINARY);
  6451. #endif
  6452. #endif
  6453. #endif
  6454. #endif
  6455. #endif
  6456. if (soap->mode & SOAP_IO)
  6457. { soap->bufidx = 0;
  6458. soap->buflen = 0;
  6459. }
  6460. soap->chunksize = 0;
  6461. soap->ns = 0;
  6462. soap->null = 0;
  6463. soap->position = 0;
  6464. soap->mustUnderstand = 0;
  6465. soap->encoding = 0;
  6466. soap->idnum = 0;
  6467. soap->level = 0;
  6468. soap_clr_attr(soap);
  6469. soap_set_local_namespaces(soap);
  6470. #ifdef WITH_ZLIB
  6471. soap->z_ratio_out = 1.0;
  6472. if ((soap->mode & SOAP_ENC_ZLIB) && soap->zlib_state != SOAP_ZLIB_DEFLATE)
  6473. { if (!soap->z_buf)
  6474. soap->z_buf = (char*)SOAP_MALLOC(soap, SOAP_BUFLEN);
  6475. soap->d_stream->next_out = (Byte*)soap->z_buf;
  6476. soap->d_stream->avail_out = SOAP_BUFLEN;
  6477. #ifdef WITH_GZIP
  6478. if (soap->zlib_out != SOAP_ZLIB_DEFLATE)
  6479. { memcpy(soap->z_buf, "\37\213\10\0\0\0\0\0\0\377", 10);
  6480. soap->d_stream->next_out = (Byte*)soap->z_buf + 10;
  6481. soap->d_stream->avail_out = SOAP_BUFLEN - 10;
  6482. soap->z_crc = crc32(0L, NULL, 0);
  6483. soap->zlib_out = SOAP_ZLIB_GZIP;
  6484. if (soap->z_dict)
  6485. *((Byte*)soap->z_buf + 2) = 0xff;
  6486. if (deflateInit2(soap->d_stream, soap->z_level, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY) != Z_OK)
  6487. return soap->error = SOAP_ZLIB_ERROR;
  6488. }
  6489. else
  6490. #endif
  6491. if (deflateInit(soap->d_stream, soap->z_level) != Z_OK)
  6492. return soap->error = SOAP_ZLIB_ERROR;
  6493. if (soap->z_dict)
  6494. { if (deflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len) != Z_OK)
  6495. return soap->error = SOAP_ZLIB_ERROR;
  6496. }
  6497. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflate initialized\n"));
  6498. soap->zlib_state = SOAP_ZLIB_DEFLATE;
  6499. }
  6500. #endif
  6501. #ifdef WITH_OPENSSL
  6502. if (soap->ssl)
  6503. ERR_clear_error();
  6504. #endif
  6505. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin send phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count));
  6506. soap->part = SOAP_BEGIN;
  6507. #ifndef WITH_LEANER
  6508. if (soap->fprepareinitsend && (soap->mode & SOAP_IO) == SOAP_IO_STORE)
  6509. soap->fprepareinitsend(soap);
  6510. #endif
  6511. return SOAP_OK;
  6512. }
  6513. #endif
  6514. /******************************************************************************/
  6515. #ifndef WITH_NOIDREF
  6516. #ifndef PALM_2
  6517. SOAP_FMAC1
  6518. void
  6519. SOAP_FMAC2
  6520. soap_embedded(struct soap *soap, const void *p, int t)
  6521. { struct soap_plist *pp;
  6522. if (soap_pointer_lookup(soap, p, t, &pp))
  6523. { pp->mark1 = 1;
  6524. pp->mark2 = 1;
  6525. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded %p type=%d mark set to 1\n", p, t));
  6526. }
  6527. }
  6528. #endif
  6529. #endif
  6530. /******************************************************************************/
  6531. #ifndef WITH_NOIDREF
  6532. #ifndef PALM_2
  6533. SOAP_FMAC1
  6534. int
  6535. SOAP_FMAC2
  6536. soap_reference(struct soap *soap, const void *p, int t)
  6537. { struct soap_plist *pp;
  6538. if (!p || (soap->mode & SOAP_XML_TREE))
  6539. return 1;
  6540. if (soap_pointer_lookup(soap, p, t, &pp))
  6541. { if (pp->mark1 == 0)
  6542. { pp->mark1 = 2;
  6543. pp->mark2 = 2;
  6544. }
  6545. }
  6546. else if (soap_pointer_enter(soap, p, NULL, 0, t, &pp))
  6547. { pp->mark1 = 0;
  6548. pp->mark2 = 0;
  6549. }
  6550. else
  6551. return 1;
  6552. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reference %p type=%d (%d %d)\n", p, t, (int)pp->mark1, (int)pp->mark2));
  6553. return pp->mark1;
  6554. }
  6555. #endif
  6556. #endif
  6557. /******************************************************************************/
  6558. #ifndef WITH_NOIDREF
  6559. #ifndef PALM_2
  6560. SOAP_FMAC1
  6561. int
  6562. SOAP_FMAC2
  6563. soap_array_reference(struct soap *soap, const void *p, const struct soap_array *a, int n, int t)
  6564. { register int i;
  6565. struct soap_plist *pp;
  6566. if (!p || !a->__ptr)
  6567. return 1;
  6568. i = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
  6569. if (i)
  6570. { if (pp->mark1 == 0)
  6571. { pp->mark1 = 2;
  6572. pp->mark2 = 2;
  6573. }
  6574. }
  6575. else if (!soap_pointer_enter(soap, p, a, n, t, &pp))
  6576. return 1;
  6577. else
  6578. { pp->mark1 = 0;
  6579. pp->mark2 = 0;
  6580. }
  6581. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array reference %p ptr=%p dim=%d type=%d (%d %d)\n", p, a->__ptr, n, t, (int)pp->mark1, (int)pp->mark2));
  6582. return pp->mark1;
  6583. }
  6584. #endif
  6585. #endif
  6586. /******************************************************************************/
  6587. #ifndef WITH_NOIDREF
  6588. #ifndef PALM_2
  6589. SOAP_FMAC1
  6590. int
  6591. SOAP_FMAC2
  6592. soap_embedded_id(struct soap *soap, int id, const void *p, int t)
  6593. { struct soap_plist *pp = NULL;
  6594. if (soap->mode & SOAP_XML_TREE)
  6595. return id;
  6596. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id %p type=%d id=%d\n", p, t, id));
  6597. if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER)
  6598. { if (id < 0)
  6599. { id = soap_pointer_lookup(soap, p, t, &pp);
  6600. if (id)
  6601. { if (soap->mode & SOAP_IO_LENGTH)
  6602. pp->mark1 = 2;
  6603. else
  6604. pp->mark2 = 2;
  6605. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id multiref id=%d %p type=%d = (%d %d)\n", id, p, t, (int)pp->mark1, (int)pp->mark2));
  6606. }
  6607. return -1;
  6608. }
  6609. return id;
  6610. }
  6611. if (id < 0)
  6612. id = soap_pointer_lookup(soap, p, t, &pp);
  6613. else if (id && !soap_pointer_lookup(soap, p, t, &pp))
  6614. return 0;
  6615. if (id && pp)
  6616. { if (soap->mode & SOAP_IO_LENGTH)
  6617. pp->mark1 = 1;
  6618. else
  6619. pp->mark2 = 1;
  6620. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id embedded ref id=%d %p type=%d = (%d %d)\n", id, p, t, (int)pp->mark1, (int)pp->mark2));
  6621. }
  6622. return id;
  6623. }
  6624. #endif
  6625. #endif
  6626. /******************************************************************************/
  6627. #ifndef WITH_NOIDREF
  6628. #ifndef PALM_2
  6629. SOAP_FMAC1
  6630. int
  6631. SOAP_FMAC2
  6632. soap_is_embedded(struct soap *soap, struct soap_plist *pp)
  6633. { if (!pp)
  6634. return 0;
  6635. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Is embedded? %d %d\n", (int)pp->mark1, (int)pp->mark2));
  6636. if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER)
  6637. { if (soap->mode & SOAP_IO_LENGTH)
  6638. return pp->mark1 != 0;
  6639. return pp->mark2 != 0;
  6640. }
  6641. if (soap->mode & SOAP_IO_LENGTH)
  6642. return pp->mark1 == 1;
  6643. return pp->mark2 == 1;
  6644. }
  6645. #endif
  6646. #endif
  6647. /******************************************************************************/
  6648. #ifndef WITH_NOIDREF
  6649. #ifndef PALM_2
  6650. SOAP_FMAC1
  6651. int
  6652. SOAP_FMAC2
  6653. soap_is_single(struct soap *soap, struct soap_plist *pp)
  6654. { if (soap->part == SOAP_IN_HEADER)
  6655. return 1;
  6656. if (!pp)
  6657. return 0;
  6658. if (soap->mode & SOAP_IO_LENGTH)
  6659. return pp->mark1 == 0;
  6660. return pp->mark2 == 0;
  6661. }
  6662. #endif
  6663. #endif
  6664. /******************************************************************************/
  6665. #ifndef WITH_NOIDREF
  6666. #ifndef PALM_2
  6667. SOAP_FMAC1
  6668. void
  6669. SOAP_FMAC2
  6670. soap_set_embedded(struct soap *soap, struct soap_plist *pp)
  6671. { if (!pp)
  6672. return;
  6673. if (soap->mode & SOAP_IO_LENGTH)
  6674. pp->mark1 = 1;
  6675. else
  6676. pp->mark2 = 1;
  6677. }
  6678. #endif
  6679. #endif
  6680. /******************************************************************************/
  6681. #ifndef WITH_LEANER
  6682. #ifndef PALM_1
  6683. SOAP_FMAC1
  6684. int
  6685. SOAP_FMAC2
  6686. soap_attachment(struct soap *soap, const char *tag, int id, const void *p, const struct soap_array *a, const char *aid, const char *atype, const char *aoptions, int n, const char *type, int t)
  6687. {
  6688. #ifndef WITH_NOIDREF
  6689. struct soap_plist *pp = NULL; /* Oracle customization */
  6690. int i;
  6691. if (!p || !a->__ptr || (!aid && !atype))
  6692. return soap_element_id(soap, tag, id, p, a, n, type, t);
  6693. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attachment tag='%s' id='%s' (%d) type='%s'\n", tag, aid?aid:SOAP_STR_EOS, id, atype?atype:SOAP_STR_EOS));
  6694. i = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
  6695. if (!i)
  6696. { i = soap_pointer_enter(soap, p, a, n, t, &pp);
  6697. if (!i)
  6698. { soap->error = SOAP_EOM;
  6699. return -1;
  6700. }
  6701. }
  6702. if (id <= 0)
  6703. id = i;
  6704. if (!aid)
  6705. { sprintf(soap->tmpbuf, soap->dime_id_format, id);
  6706. aid = soap_strdup(soap, soap->tmpbuf);
  6707. }
  6708. /* Add MTOM xop:Include element when necessary */
  6709. /* TODO: this code to be obsoleted with new import/xop.h conventions */
  6710. if ((soap->mode & SOAP_ENC_MTOM) && strcmp(tag, "xop:Include"))
  6711. { if (soap_element_begin_out(soap, tag, 0, type)
  6712. || soap_element_href(soap, "xop:Include", 0, "xmlns:xop=\"http://www.w3.org/2004/08/xop/include\" href", aid)
  6713. || soap_element_end_out(soap, tag))
  6714. return soap->error;
  6715. }
  6716. else if (soap_element_href(soap, tag, 0, "href", aid))
  6717. return soap->error;
  6718. if (soap->mode & SOAP_IO_LENGTH)
  6719. { if (pp && (pp->mark1 != 3)) /* Oracle customization */
  6720. { struct soap_multipart *content;
  6721. if (soap->mode & SOAP_ENC_MTOM)
  6722. content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, (char*)a->__ptr, a->__size);
  6723. else
  6724. content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, (char*)a->__ptr, a->__size);
  6725. if (!content)
  6726. { soap->error = SOAP_EOM;
  6727. return -1;
  6728. }
  6729. if (!strncmp(aid, "cid:", 4)) /* RFC 2111 */
  6730. { if (soap->mode & SOAP_ENC_MTOM)
  6731. { char *s = (char*)soap_malloc(soap, strlen(aid) - 1);
  6732. if (s)
  6733. { *s = '<';
  6734. strcpy(s + 1, aid + 4);
  6735. strcat(s, ">");
  6736. content->id = s;
  6737. }
  6738. }
  6739. else
  6740. content->id = aid + 4;
  6741. }
  6742. else
  6743. content->id = aid;
  6744. content->type = atype;
  6745. content->options = aoptions;
  6746. content->encoding = SOAP_MIME_BINARY;
  6747. pp->mark1 = 3;
  6748. }
  6749. }
  6750. else if (pp) /* Oracle customization */
  6751. pp->mark2 = 3;
  6752. #endif
  6753. return -1;
  6754. }
  6755. #endif
  6756. #endif
  6757. /******************************************************************************/
  6758. #ifndef WITH_NOIDREF
  6759. #ifndef PALM_1
  6760. static void
  6761. soap_init_iht(struct soap *soap)
  6762. { register int i;
  6763. for (i = 0; i < SOAP_IDHASH; i++)
  6764. soap->iht[i] = NULL;
  6765. }
  6766. #endif
  6767. #endif
  6768. /******************************************************************************/
  6769. #ifndef WITH_NOIDREF
  6770. #ifndef PALM_1
  6771. static void
  6772. soap_free_iht(struct soap *soap)
  6773. { register int i;
  6774. register struct soap_ilist *ip = NULL, *p = NULL;
  6775. register struct soap_flist *fp = NULL, *fq = NULL;
  6776. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free ID hashtable\n"));
  6777. for (i = 0; i < SOAP_IDHASH; i++)
  6778. { for (ip = soap->iht[i]; ip; ip = p)
  6779. { for (fp = ip->flist; fp; fp = fq)
  6780. { fq = fp->next;
  6781. SOAP_FREE(soap, fp);
  6782. }
  6783. p = ip->next;
  6784. SOAP_FREE(soap, ip);
  6785. }
  6786. soap->iht[i] = NULL;
  6787. }
  6788. }
  6789. #endif
  6790. #endif
  6791. /******************************************************************************/
  6792. #ifndef WITH_NOIDREF
  6793. #ifndef PALM_2
  6794. SOAP_FMAC1
  6795. struct soap_ilist *
  6796. SOAP_FMAC2
  6797. soap_lookup(struct soap *soap, const char *id)
  6798. { register struct soap_ilist *ip = NULL;
  6799. for (ip = soap->iht[soap_hash(id)]; ip; ip = ip->next)
  6800. if (!strcmp(ip->id, id))
  6801. return ip;
  6802. return NULL;
  6803. }
  6804. #endif
  6805. #endif
  6806. /******************************************************************************/
  6807. #ifndef WITH_NOIDREF
  6808. #ifndef PALM_2
  6809. SOAP_FMAC1
  6810. struct soap_ilist *
  6811. SOAP_FMAC2
  6812. soap_enter(struct soap *soap, const char *id)
  6813. { register size_t h;
  6814. register struct soap_ilist *ip;
  6815. ip = (struct soap_ilist*)SOAP_MALLOC(soap, sizeof(struct soap_ilist) + strlen(id));
  6816. if (ip)
  6817. { h = soap_hash(id);
  6818. strcpy(ip->id, id);
  6819. ip->next = soap->iht[h];
  6820. soap->iht[h] = ip;
  6821. }
  6822. return ip;
  6823. }
  6824. #endif
  6825. #endif
  6826. /******************************************************************************/
  6827. #ifndef PALM_2
  6828. SOAP_FMAC1
  6829. void*
  6830. SOAP_FMAC2
  6831. soap_malloc(struct soap *soap, size_t n)
  6832. { register char *p;
  6833. if (!n)
  6834. return (void*)SOAP_NON_NULL;
  6835. if (!soap)
  6836. return SOAP_MALLOC(soap, n);
  6837. if (soap->fmalloc)
  6838. p = (char*)soap->fmalloc(soap, n);
  6839. else
  6840. { n += sizeof(short);
  6841. n += (-(long)n) & (sizeof(void*)-1); /* align at 4-, 8- or 16-byte boundary */
  6842. if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(void*) + sizeof(size_t))))
  6843. { soap->error = SOAP_EOM;
  6844. return NULL;
  6845. }
  6846. /* set the canary to detect corruption */
  6847. *(unsigned short*)(p + n - sizeof(unsigned short)) = (unsigned short)SOAP_CANARY;
  6848. /* keep chain of alloced cells for destruction */
  6849. *(void**)(p + n) = soap->alist;
  6850. *(size_t*)(p + n + sizeof(void*)) = n;
  6851. soap->alist = p + n;
  6852. }
  6853. soap->alloced = 1;
  6854. return p;
  6855. }
  6856. #endif
  6857. /******************************************************************************/
  6858. #ifdef SOAP_MEM_DEBUG
  6859. static void
  6860. soap_init_mht(struct soap *soap)
  6861. { register int i;
  6862. for (i = 0; i < (int)SOAP_PTRHASH; i++)
  6863. soap->mht[i] = NULL;
  6864. }
  6865. #endif
  6866. /******************************************************************************/
  6867. #ifdef SOAP_MEM_DEBUG
  6868. static void
  6869. soap_free_mht(struct soap *soap)
  6870. { register int i;
  6871. register struct soap_mlist *mp, *mq;
  6872. for (i = 0; i < (int)SOAP_PTRHASH; i++)
  6873. { for (mp = soap->mht[i]; mp; mp = mq)
  6874. { mq = mp->next;
  6875. if (mp->live)
  6876. {
  6877. fprintf(stderr, "%s(%d): malloc() = %p not freed (memory leak or forgot to call soap_end()?)\n", mp->file, mp->line, mp->ptr);
  6878. #ifndef WIN32
  6879. (void) printstack( 2 ); /* Oracle customization */
  6880. #endif
  6881. }
  6882. free(mp);
  6883. }
  6884. soap->mht[i] = NULL;
  6885. }
  6886. }
  6887. #endif
  6888. /******************************************************************************/
  6889. #ifdef SOAP_MEM_DEBUG
  6890. SOAP_FMAC1
  6891. void*
  6892. SOAP_FMAC2
  6893. soap_track_malloc(struct soap *soap, const char *file, int line, size_t size)
  6894. { register void *p = malloc(size);
  6895. if (soap)
  6896. { register size_t h = soap_hash_ptr(p);
  6897. register struct soap_mlist *mp = (struct soap_mlist*)malloc(sizeof(struct soap_mlist));
  6898. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): malloc(%lu) = %p\n", file, line, (unsigned long)size, p));
  6899. mp->next = soap->mht[h];
  6900. mp->ptr = p;
  6901. mp->file = file;
  6902. mp->line = line;
  6903. mp->live = 1;
  6904. soap->mht[h] = mp;
  6905. }
  6906. return p;
  6907. }
  6908. #endif
  6909. /******************************************************************************/
  6910. #ifdef SOAP_MEM_DEBUG
  6911. SOAP_FMAC1
  6912. void
  6913. SOAP_FMAC2
  6914. soap_track_free(struct soap *soap, const char *file, int line, void *p)
  6915. { register size_t h = soap_hash_ptr(p);
  6916. register struct soap_mlist *mp;
  6917. for (mp = soap->mht[h]; mp; mp = mp->next)
  6918. if (mp->ptr == p)
  6919. break;
  6920. if (mp)
  6921. { if (mp->live)
  6922. { free(p);
  6923. if (soap->fdebug[SOAP_INDEX_TEST])
  6924. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): free(%p)\n", file, line, p));
  6925. }
  6926. mp->live = 0;
  6927. }
  6928. else
  6929. fprintf(stderr, "%s(%d): free(%p) double free of pointer malloced at %s(%d)\n", file, line, p, mp->file, mp->line);
  6930. }
  6931. else
  6932. fprintf(stderr, "%s(%d): free(%p) pointer not malloced\n", file, line, p);
  6933. }
  6934. #endif
  6935. /******************************************************************************/
  6936. #ifdef SOAP_MEM_DEBUG
  6937. static void
  6938. soap_track_unlink(struct soap *soap, const void *p)
  6939. { register size_t h = soap_hash_ptr(p);
  6940. register struct soap_mlist *mp;
  6941. for (mp = soap->mht[h]; mp; mp = mp->next)
  6942. if (mp->ptr == p)
  6943. break;
  6944. if (mp)
  6945. mp->live = 0;
  6946. }
  6947. #endif
  6948. /******************************************************************************/
  6949. #ifndef PALM_2
  6950. SOAP_FMAC1
  6951. void
  6952. SOAP_FMAC2
  6953. soap_dealloc(struct soap *soap, void *p)
  6954. { if (soap_check_state(soap))
  6955. return;
  6956. if (p)
  6957. { register char **q;
  6958. for (q = (char**)&soap->alist; *q; q = *(char***)q)
  6959. {
  6960. if (*(unsigned short*)(char*)(*q - sizeof(unsigned short)) != (unsigned short)SOAP_CANARY)
  6961. {
  6962. #ifdef SOAP_MEM_DEBUG
  6963. fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n");
  6964. #endif
  6965. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n"));
  6966. DBGHEX(TEST, *q - 200, 200);
  6967. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n"));
  6968. soap->error = SOAP_MOE;
  6969. return;
  6970. }
  6971. if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*))))
  6972. { *q = **(char***)q;
  6973. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Freed data at %p\n", p));
  6974. SOAP_FREE(soap, p);
  6975. return;
  6976. }
  6977. }
  6978. soap_delete(soap, p);
  6979. }
  6980. else
  6981. { register char *q;
  6982. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free all soap_malloc() data\n"));
  6983. while (soap->alist)
  6984. { q = (char*)soap->alist;
  6985. if (*(unsigned short*)(char*)(q - sizeof(unsigned short)) != (unsigned short)SOAP_CANARY)
  6986. {
  6987. #ifdef SOAP_MEM_DEBUG
  6988. fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n");
  6989. #endif
  6990. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n"));
  6991. DBGHEX(TEST, q - 200, 200);
  6992. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n"));
  6993. soap->error = SOAP_MOE;
  6994. return;
  6995. }
  6996. soap->alist = *(void**)q;
  6997. q -= *(size_t*)(q + sizeof(void*));
  6998. SOAP_FREE(soap, q);
  6999. }
  7000. /* we must assume these were deallocated: */
  7001. soap->action = NULL;
  7002. soap->fault = NULL;
  7003. soap->header = NULL;
  7004. soap->userid = NULL;
  7005. soap->passwd = NULL;
  7006. soap->authrealm = NULL;
  7007. soap->http_content = NULL;
  7008. #ifndef WITH_LEANER
  7009. soap_clr_mime(soap);
  7010. #endif
  7011. }
  7012. }
  7013. #endif
  7014. /******************************************************************************/
  7015. #ifndef PALM_2
  7016. SOAP_FMAC1
  7017. void
  7018. SOAP_FMAC2
  7019. soap_delete(struct soap *soap, void *p)
  7020. { register struct soap_clist **cp;
  7021. if (soap_check_state(soap))
  7022. return;
  7023. cp = &soap->clist;
  7024. if (p)
  7025. { while (*cp)
  7026. { if (p == (*cp)->ptr)
  7027. { register struct soap_clist *q = *cp;
  7028. *cp = q->next;
  7029. if (q->fdelete(q))
  7030. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: deletion callback failed for object type %d\n", q->ptr, q->type));
  7031. #ifdef SOAP_MEM_DEBUG
  7032. fprintf(stderr, "new(object type = %d) = %p not freed: deletion callback failed\n", q->type, q->ptr);
  7033. #endif
  7034. }
  7035. SOAP_FREE(soap, q);
  7036. return;
  7037. }
  7038. cp = &(*cp)->next;
  7039. }
  7040. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: address not in list\n", p));
  7041. }
  7042. else
  7043. { while (*cp)
  7044. { register struct soap_clist *q = *cp;
  7045. *cp = q->next;
  7046. if (q->fdelete(q))
  7047. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: deletion callback failed for object type %d\n", q->ptr, q->type));
  7048. #ifdef SOAP_MEM_DEBUG
  7049. fprintf(stderr, "new(object type = %d) = %p not freed: deletion callback failed\n", q->type, q->ptr);
  7050. #endif
  7051. }
  7052. SOAP_FREE(soap, q);
  7053. }
  7054. }
  7055. soap->fault = NULL; /* this was possibly deallocated */
  7056. soap->header = NULL; /* this was possibly deallocated */
  7057. }
  7058. #endif
  7059. /******************************************************************************/
  7060. #ifndef PALM_2
  7061. SOAP_FMAC1
  7062. void
  7063. SOAP_FMAC2
  7064. soap_delegate_deletion(struct soap *soap, struct soap *soap_to)
  7065. { register struct soap_clist *cp;
  7066. register char **q;
  7067. #ifdef SOAP_MEM_DEBUG
  7068. register void *p;
  7069. register struct soap_mlist **mp, *mq;
  7070. size_t h;
  7071. #endif
  7072. for (q = (char**)&soap->alist; *q; q = *(char***)q)
  7073. {
  7074. if (*(unsigned short*)(char*)(*q - sizeof(unsigned short)) != (unsigned short)SOAP_CANARY)
  7075. {
  7076. #ifdef SOAP_MEM_DEBUG
  7077. fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n");
  7078. #endif
  7079. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n"));
  7080. DBGHEX(TEST, *q - 200, 200);
  7081. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n"));
  7082. soap->error = SOAP_MOE;
  7083. return;
  7084. }
  7085. #ifdef SOAP_MEM_DEBUG
  7086. p = (void*)(*q - *(size_t*)(*q + sizeof(void*)));
  7087. h = soap_hash_ptr(p);
  7088. for (mp = &soap->mht[h]; *mp; mp = &(*mp)->next)
  7089. { if ((*mp)->ptr == p)
  7090. { mq = *mp;
  7091. *mp = mq->next;
  7092. mq->next = soap_to->mht[h];
  7093. soap_to->mht[h] = mq;
  7094. break;
  7095. }
  7096. }
  7097. #endif
  7098. }
  7099. *q = (char*)soap_to->alist;
  7100. soap_to->alist = soap->alist;
  7101. soap->alist = NULL;
  7102. cp = soap_to->clist;
  7103. if (cp)
  7104. { while (cp->next)
  7105. cp = cp->next;
  7106. cp->next = soap->clist;
  7107. }
  7108. else
  7109. soap_to->clist = soap->clist;
  7110. soap->clist = NULL;
  7111. }
  7112. #endif
  7113. /******************************************************************************/
  7114. #ifndef PALM_2
  7115. SOAP_FMAC1
  7116. struct soap_clist *
  7117. SOAP_FMAC2
  7118. soap_link(struct soap *soap, void *p, int t, int n, int (*fdelete)(struct soap_clist*))
  7119. { register struct soap_clist *cp;
  7120. if ((cp = (struct soap_clist*)SOAP_MALLOC(soap, sizeof(struct soap_clist))))
  7121. { cp->next = soap->clist;
  7122. cp->type = t;
  7123. cp->size = n;
  7124. cp->ptr = p;
  7125. cp->fdelete = fdelete;
  7126. soap->clist = cp;
  7127. }
  7128. return cp;
  7129. }
  7130. #endif
  7131. /******************************************************************************/
  7132. #ifndef PALM_2
  7133. SOAP_FMAC1
  7134. void
  7135. SOAP_FMAC2
  7136. soap_unlink(struct soap *soap, const void *p)
  7137. { register char **q;
  7138. register struct soap_clist **cp;
  7139. if (!soap || !p)
  7140. return;
  7141. for (q = (char**)&soap->alist; *q; q = *(char***)q)
  7142. { if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*))))
  7143. { *q = **(char***)q;
  7144. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked data %p\n", p));
  7145. #ifdef SOAP_MEM_DEBUG
  7146. soap_track_unlink(soap, p);
  7147. #endif
  7148. return;
  7149. }
  7150. }
  7151. for (cp = &soap->clist; *cp; cp = &(*cp)->next)
  7152. { if (p == (*cp)->ptr)
  7153. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked class instance %p\n", p));
  7154. q = (char**)*cp;
  7155. *cp = (*cp)->next;
  7156. SOAP_FREE(soap, q);
  7157. return;
  7158. }
  7159. }
  7160. }
  7161. #endif
  7162. /******************************************************************************/
  7163. #ifndef WITH_NOIDREF
  7164. #ifndef PALM_2
  7165. SOAP_FMAC1
  7166. int
  7167. SOAP_FMAC2
  7168. soap_lookup_type(struct soap *soap, const char *id)
  7169. { register struct soap_ilist *ip;
  7170. if (id && *id)
  7171. { ip = soap_lookup(soap, id);
  7172. if (ip)
  7173. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup id='%s' type=%d\n", id, ip->type));
  7174. return ip->type;
  7175. }
  7176. }
  7177. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "lookup type id='%s' NOT FOUND! Need to get it from xsi:type\n", id));
  7178. return 0;
  7179. }
  7180. #endif
  7181. #endif
  7182. /******************************************************************************/
  7183. #ifndef WITH_NOIDREF
  7184. #ifndef PALM_2
  7185. SOAP_FMAC1
  7186. void*
  7187. SOAP_FMAC2
  7188. soap_id_lookup(struct soap *soap, const char *id, void **p, int t, size_t n, unsigned int k)
  7189. { struct soap_ilist *ip;
  7190. void **q;
  7191. if (!p || !id || !*id)
  7192. return p;
  7193. ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */
  7194. if (!ip)
  7195. { if (!(ip = soap_enter(soap, id))) /* new hash table entry for string id */
  7196. return NULL;
  7197. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding first href='%s' type=%d %p (%u bytes)\n", id, t, p, (unsigned int)n));
  7198. ip->type = t;
  7199. ip->size = n;
  7200. ip->link = p;
  7201. ip->copy = NULL;
  7202. ip->flist = NULL;
  7203. ip->ptr = NULL;
  7204. ip->level = k;
  7205. *p = NULL;
  7206. }
  7207. else if (ip->ptr)
  7208. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolved href='%s' type=%d location=%p (%u bytes)\n", id, t, ip->ptr, (unsigned int)n));
  7209. if (ip->type != t)
  7210. {
  7211. /* Oracle customization */
  7212. strncpy(soap->id, id, sizeof(soap->id) - 1);
  7213. soap->id[sizeof(soap->id) - 1] = '\0';
  7214. soap->error = SOAP_HREF;
  7215. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility: href='%s' id-type=%d href-type=%d\n", id, ip->type, t));
  7216. return NULL;
  7217. }
  7218. while (ip->level < k)
  7219. { q = (void**)soap_malloc(soap, sizeof(void*));
  7220. if (!q)
  7221. return NULL;
  7222. *p = (void*)q;
  7223. p = q;
  7224. k--;
  7225. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n"));
  7226. }
  7227. *p = ip->ptr;
  7228. }
  7229. else if (ip->level > k)
  7230. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving level %u pointers to href='%s'\n", ip->level, id));
  7231. while (ip->level > k)
  7232. { void *s, **r = &ip->link;
  7233. q = (void**)ip->link;
  7234. while (q)
  7235. { *r = (void*)soap_malloc(soap, sizeof(void*));
  7236. if (!*r)
  7237. return NULL;
  7238. s = *q;
  7239. *q = *r;
  7240. r = (void**)*r;
  7241. q = (void**)s;
  7242. }
  7243. *r = NULL;
  7244. ip->size = n;
  7245. ip->copy = NULL;
  7246. ip->level = ip->level - 1;
  7247. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n"));
  7248. }
  7249. q = (void**)ip->link;
  7250. ip->link = p;
  7251. *p = (void*)q;
  7252. }
  7253. else
  7254. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarded href='%s' type=%d location=%p (%u bytes)\n", id, t, p, (unsigned int)n));
  7255. while (ip->level < k)
  7256. { q = (void**)soap_malloc(soap, sizeof(void*));
  7257. if (!q)
  7258. return NULL;
  7259. *p = q;
  7260. p = q;
  7261. k--;
  7262. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n"));
  7263. }
  7264. q = (void**)ip->link;
  7265. ip->link = p;
  7266. *p = (void*)q;
  7267. }
  7268. return p;
  7269. }
  7270. #endif
  7271. #endif
  7272. /******************************************************************************/
  7273. #ifndef WITH_NOIDREF
  7274. #ifndef PALM_2
  7275. SOAP_FMAC1
  7276. void*
  7277. SOAP_FMAC2
  7278. soap_id_forward(struct soap *soap, const char *href, void *p, size_t len, int st, int tt, size_t n, unsigned int k, void (*fcopy)(struct soap*, int, int, void*, size_t, const void*, size_t))
  7279. { struct soap_ilist *ip;
  7280. if (!p || !href || !*href)
  7281. return p;
  7282. ip = soap_lookup(soap, href); /* lookup pointer to hash table entry for string id */
  7283. if (!ip)
  7284. { if (!(ip = soap_enter(soap, href))) /* new hash table entry for string id */
  7285. return NULL;
  7286. ip->type = st;
  7287. ip->size = n;
  7288. ip->link = NULL;
  7289. ip->copy = NULL;
  7290. ip->ptr = NULL;
  7291. ip->level = 0;
  7292. ip->flist = NULL;
  7293. DBGLOG(TEST,SOAP_MESSAGE(fdebug, "New entry href='%s' type=%d size=%lu level=%d location=%p\n", href, st, (unsigned long)n, k, p));
  7294. }
  7295. else if (ip->type != st || (ip->level == k && ip->size != n))
  7296. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n", href, ip->type, (unsigned long)ip->size, k, st, (unsigned long)n));
  7297. /* Oracle customization */
  7298. strncpy(soap->id, href, sizeof(soap->id) - 1);
  7299. soap->id[sizeof(soap->id) - 1] = '\0';
  7300. soap->error = SOAP_HREF;
  7301. return NULL;
  7302. }
  7303. if (fcopy || n < sizeof(void*) || *href != '#')
  7304. { register struct soap_flist *fp = (struct soap_flist*)SOAP_MALLOC(soap, sizeof(struct soap_flist));
  7305. if (!fp)
  7306. { soap->error = SOAP_EOM;
  7307. return NULL;
  7308. }
  7309. fp->next = ip->flist;
  7310. fp->type = tt;
  7311. fp->ptr = p;
  7312. fp->level = k;
  7313. fp->len = len;
  7314. if (fcopy)
  7315. fp->fcopy = fcopy;
  7316. else
  7317. fp->fcopy = soap_fcopy;
  7318. ip->flist = fp;
  7319. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding type=%d (target type=%d) size=%lu location=%p level=%u len=%lu href='%s'\n", st, tt, (unsigned long)n, p, k, (unsigned long)len, href));
  7320. }
  7321. else
  7322. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding copying address %p for type=%d href='%s'\n", p, st, href));
  7323. *(void**)p = ip->copy;
  7324. ip->copy = p;
  7325. }
  7326. return p;
  7327. }
  7328. #endif
  7329. #endif
  7330. /******************************************************************************/
  7331. #ifndef PALM_2
  7332. SOAP_FMAC1
  7333. void*
  7334. SOAP_FMAC2
  7335. soap_id_enter(struct soap *soap, const char *id, void *p, int t, size_t n, unsigned int k, const char *type, const char *arrayType, void *(*finstantiate)(struct soap*, int, const char*, const char*, size_t*))
  7336. {
  7337. #ifndef WITH_NOIDREF
  7338. struct soap_ilist *ip;
  7339. #endif
  7340. DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Enter id='%s' type=%d loc=%p size=%lu level=%u\n", id, t, p, (unsigned long)n, k));
  7341. soap->alloced = 0;
  7342. if (!p)
  7343. { if (finstantiate)
  7344. p = finstantiate(soap, t, type, arrayType, &n);
  7345. else
  7346. p = soap_malloc(soap, n);
  7347. if (p)
  7348. soap->alloced = 1;
  7349. }
  7350. #ifndef WITH_NOIDREF
  7351. if (!id || !*id)
  7352. #endif
  7353. return p;
  7354. #ifndef WITH_NOIDREF
  7355. ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */
  7356. DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Lookup entry id='%s for location=%p'\n", id, p));
  7357. if (!ip)
  7358. { if (!(ip = soap_enter(soap, id))) /* new hash table entry for string id */
  7359. return NULL;
  7360. ip->type = t;
  7361. ip->link = NULL;
  7362. ip->copy = NULL;
  7363. ip->flist = NULL;
  7364. ip->size = n;
  7365. ip->ptr = p;
  7366. ip->level = k;
  7367. DBGLOG(TEST,SOAP_MESSAGE(fdebug, "New entry id='%s' type=%d size=%lu level=%u location=%p\n", id, t, (unsigned long)n, k, p));
  7368. }
  7369. else if ((ip->type != t || (ip->level == k && ip->size != n)) && (ip->copy || ip->flist))
  7370. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n", id, ip->type, (unsigned long)ip->size, k, t, (unsigned long)n));
  7371. /* Oracle customization */
  7372. strncpy(soap->id, id, sizeof(soap->id) - 1);
  7373. soap->id[sizeof(soap->id) - 1] = '\0';
  7374. soap->error = SOAP_HREF;
  7375. return NULL;
  7376. }
  7377. else if (ip->ptr)
  7378. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Multiply defined id='%s'\n", id));
  7379. /* Oracle customization */
  7380. strncpy(soap->id, id, sizeof(soap->id) - 1);
  7381. soap->id[sizeof(soap->id) - 1] = '\0';
  7382. soap->error = SOAP_DUPLICATE_ID;
  7383. return NULL;
  7384. }
  7385. else
  7386. { ip->size = n;
  7387. ip->ptr = p;
  7388. ip->level = k;
  7389. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update entry id='%s' type=%d location=%p size=%lu level=%u\n", id, t, p, (unsigned long)n, k));
  7390. }
  7391. return ip->ptr;
  7392. #endif
  7393. }
  7394. #endif
  7395. /******************************************************************************/
  7396. #ifndef PALM_2
  7397. SOAP_FMAC1
  7398. void
  7399. SOAP_FMAC2
  7400. soap_fcopy(struct soap *soap, int st, int tt, void *p, size_t len, const void *q, size_t n)
  7401. { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Copying data type=%d (target type=%d) %p -> %p (%lu bytes)\n", st, tt, q, p, (unsigned long)n));
  7402. memcpy(p, q, n);
  7403. }
  7404. #endif
  7405. /******************************************************************************/
  7406. #ifndef PALM_1
  7407. SOAP_FMAC1
  7408. int
  7409. SOAP_FMAC2
  7410. soap_end_send(struct soap *soap)
  7411. {
  7412. #ifndef WITH_LEANER
  7413. int err;
  7414. if (soap->dime.list)
  7415. { /* SOAP body referenced attachments must appear first */
  7416. soap->dime.last->next = soap->dime.first;
  7417. soap->dime.first = soap->dime.list->next;
  7418. soap->dime.list->next = NULL;
  7419. soap->dime.last = soap->dime.list;
  7420. }
  7421. if (!(err = soap_putdime(soap)))
  7422. err = soap_putmime(soap);
  7423. soap->mime.list = NULL;
  7424. soap->mime.first = NULL;
  7425. soap->mime.last = NULL;
  7426. soap->dime.list = NULL;
  7427. soap->dime.first = NULL;
  7428. soap->dime.last = NULL;
  7429. if (err)
  7430. return err;
  7431. #endif
  7432. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End send\n"));
  7433. if (soap->mode & SOAP_IO) /* need to flush the remaining data in buffer */
  7434. { if (soap_flush(soap))
  7435. #ifdef WITH_ZLIB
  7436. { if (soap->mode & SOAP_ENC_ZLIB && soap->zlib_state == SOAP_ZLIB_DEFLATE)
  7437. { soap->zlib_state = SOAP_ZLIB_NONE;
  7438. deflateEnd(soap->d_stream);
  7439. }
  7440. return soap->error;
  7441. }
  7442. #else
  7443. return soap->error;
  7444. #endif
  7445. #ifdef WITH_ZLIB
  7446. if (soap->mode & SOAP_ENC_ZLIB)
  7447. { int r;
  7448. soap->d_stream->avail_in = 0;
  7449. do
  7450. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating remainder\n"));
  7451. r = deflate(soap->d_stream, Z_FINISH);
  7452. if (soap->d_stream->avail_out != SOAP_BUFLEN)
  7453. { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN - soap->d_stream->avail_out))
  7454. { soap->zlib_state = SOAP_ZLIB_NONE;
  7455. deflateEnd(soap->d_stream);
  7456. return soap->error;
  7457. }
  7458. soap->d_stream->next_out = (Byte*)soap->z_buf;
  7459. soap->d_stream->avail_out = SOAP_BUFLEN;
  7460. }
  7461. } while (r == Z_OK);
  7462. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflated total %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out));
  7463. soap->z_ratio_out = (float)soap->d_stream->total_out / (float)soap->d_stream->total_in;
  7464. soap->mode &= ~SOAP_ENC_ZLIB;
  7465. soap->zlib_state = SOAP_ZLIB_NONE;
  7466. if (deflateEnd(soap->d_stream) != Z_OK || r != Z_STREAM_END)
  7467. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to end deflate: %s\n", soap->d_stream->msg?soap->d_stream->msg:SOAP_STR_EOS));
  7468. return soap->error = SOAP_ZLIB_ERROR;
  7469. }
  7470. #ifdef WITH_GZIP
  7471. if (soap->zlib_out != SOAP_ZLIB_DEFLATE)
  7472. { soap->z_buf[0] = soap->z_crc & 0xFF;
  7473. soap->z_buf[1] = (soap->z_crc >> 8) & 0xFF;
  7474. soap->z_buf[2] = (soap->z_crc >> 16) & 0xFF;
  7475. soap->z_buf[3] = (soap->z_crc >> 24) & 0xFF;
  7476. soap->z_buf[4] = soap->d_stream->total_in & 0xFF;
  7477. soap->z_buf[5] = (soap->d_stream->total_in >> 8) & 0xFF;
  7478. soap->z_buf[6] = (soap->d_stream->total_in >> 16) & 0xFF;
  7479. soap->z_buf[7] = (soap->d_stream->total_in >> 24) & 0xFF;
  7480. if (soap_flush_raw(soap, soap->z_buf, 8))
  7481. return soap->error;
  7482. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip crc32=%lu\n", (unsigned long)soap->z_crc));
  7483. }
  7484. #endif
  7485. }
  7486. #endif
  7487. if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
  7488. { char *p;
  7489. #ifndef WITH_NOHTTP
  7490. if (!(soap->mode & SOAP_ENC_XML))
  7491. { soap->mode--;
  7492. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending buffered message of length %u\n", (unsigned int)soap->blist->size));
  7493. if (soap->status >= SOAP_POST)
  7494. soap->error = soap->fpost(soap, soap->endpoint, soap->host, soap->port, soap->path, soap->action, soap->blist->size);
  7495. else if (soap->status != SOAP_STOP)
  7496. soap->error = soap->fresponse(soap, soap->status, soap->blist->size);
  7497. if (soap->error || soap_flush(soap))
  7498. return soap->error;
  7499. soap->mode++;
  7500. }
  7501. #endif
  7502. for (p = soap_first_block(soap, NULL); p; p = soap_next_block(soap, NULL))
  7503. { DBGMSG(SENT, p, soap_block_size(soap, NULL));
  7504. if ((soap->error = soap->fsend(soap, p, soap_block_size(soap, NULL))))
  7505. { soap_end_block(soap, NULL);
  7506. return soap->error;
  7507. }
  7508. }
  7509. soap_end_block(soap, NULL);
  7510. }
  7511. #ifndef WITH_LEANER
  7512. else if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
  7513. { DBGMSG(SENT, "\r\n0\r\n\r\n", 7);
  7514. if ((soap->error = soap->fsend(soap, "\r\n0\r\n\r\n", 7)))
  7515. return soap->error;
  7516. }
  7517. #endif
  7518. }
  7519. #ifdef WITH_TCPFIN
  7520. #ifdef WITH_OPENSSL
  7521. if (!soap->ssl && soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP))
  7522. soap->fshutdownsocket(soap, soap->socket, 1); /* Send TCP FIN */
  7523. #else
  7524. if (soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP))
  7525. soap->fshutdownsocket(soap, soap->socket, 1); /* Send TCP FIN */
  7526. #endif
  7527. #endif
  7528. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of send phase\n"));
  7529. soap->omode &= ~SOAP_XML_SEC;
  7530. soap->count = 0;
  7531. soap->part = SOAP_END;
  7532. return SOAP_OK;
  7533. }
  7534. #endif
  7535. /******************************************************************************/
  7536. #ifndef PALM_1
  7537. SOAP_FMAC1
  7538. int
  7539. SOAP_FMAC2
  7540. soap_end_recv(struct soap *soap)
  7541. { soap->part = SOAP_END;
  7542. #ifndef WITH_LEAN
  7543. soap->wsuid = NULL; /* reset before next send */
  7544. soap->c14nexclude = NULL; /* reset before next send */
  7545. #endif
  7546. #ifndef WITH_LEANER
  7547. if ((soap->mode & SOAP_ENC_DIME) && soap_getdime(soap))
  7548. { soap->dime.first = NULL;
  7549. soap->dime.last = NULL;
  7550. return soap->error;
  7551. }
  7552. soap->dime.list = soap->dime.first;
  7553. soap->dime.first = NULL;
  7554. soap->dime.last = NULL;
  7555. /* Check if MIME attachments and mime-post-check flag is set, if set call soap_resolve() and return */
  7556. if (soap->mode & SOAP_ENC_MIME)
  7557. {
  7558. #ifndef WITH_NOIDREF
  7559. if (soap->mode & SOAP_MIME_POSTCHECK)
  7560. { soap_resolve(soap);
  7561. return SOAP_OK;
  7562. }
  7563. #endif
  7564. if (soap_getmime(soap))
  7565. return soap->error;
  7566. }
  7567. soap->mime.list = soap->mime.first;
  7568. soap->mime.first = NULL;
  7569. soap->mime.last = NULL;
  7570. soap->mime.boundary = NULL;
  7571. if (soap->xlist)
  7572. { struct soap_multipart *content;
  7573. for (content = soap->mime.list; content; content = content->next)
  7574. soap_resolve_attachment(soap, content);
  7575. }
  7576. #endif
  7577. DBGLOG(TEST,SOAP_MESSAGE(fdebug, "End of receive message ok\n"));
  7578. #ifdef WITH_ZLIB
  7579. if (soap->mode & SOAP_ENC_ZLIB)
  7580. { /* Make sure end of compressed content is reached */
  7581. while (soap->d_stream->next_out != Z_NULL)
  7582. if ((int)soap_get1(soap) == EOF)
  7583. break;
  7584. soap->mode &= ~SOAP_ENC_ZLIB;
  7585. memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN);
  7586. soap->bufidx = (char*)soap->d_stream->next_in - soap->z_buf;
  7587. soap->buflen = soap->z_buflen;
  7588. soap->zlib_state = SOAP_ZLIB_NONE;
  7589. if (inflateEnd(soap->d_stream) != Z_OK)
  7590. return soap->error = SOAP_ZLIB_ERROR;
  7591. DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Inflate end ok\n"));
  7592. #ifdef WITH_GZIP
  7593. if (soap->zlib_in == SOAP_ZLIB_GZIP)
  7594. { soap_wchar c;
  7595. short i;
  7596. DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Inflate gzip crc check\n"));
  7597. for (i = 0; i < 8; i++)
  7598. { if ((int)(c = soap_get1(soap)) == EOF)
  7599. return soap->error = SOAP_EOF;
  7600. soap->z_buf[i] = (char)c;
  7601. }
  7602. if (soap->z_crc != ((uLong)(unsigned char)soap->z_buf[0] | ((uLong)(unsigned char)soap->z_buf[1] << 8) | ((uLong)(unsigned char)soap->z_buf[2] << 16) | ((uLong)(unsigned char)soap->z_buf[3] << 24)))
  7603. { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: crc check failed, message corrupted? (crc32=%lu)\n", (unsigned long)soap->z_crc));
  7604. return soap->error = SOAP_ZLIB_ERROR;
  7605. }
  7606. if (soap->d_stream->total_out != ((uLong)(unsigned char)soap->z_buf[4] | ((uLong)(unsigned char)soap->z_buf[5] << 8) | ((uLong)(unsigned char)soap->z_buf[6] << 16) | ((uLong)(unsigned char)soap->z_buf[7] << 24)))
  7607. { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: incorrect message length\n"));
  7608. return soap->error = SOAP_ZLIB_ERROR;
  7609. }
  7610. }
  7611. soap->zlib_in = SOAP_ZLIB_NONE;
  7612. #endif
  7613. }
  7614. #endif
  7615. if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
  7616. while ((int)soap_getchar(soap) != EOF) /* advance to last chunk */
  7617. ;
  7618. #ifndef WITH_NOIDREF
  7619. if (soap_resolve(soap))
  7620. return soap->error;
  7621. #endif
  7622. #ifndef WITH_LEANER
  7623. if (soap->xlist)
  7624. { if (soap->mode & SOAP_ENC_MTOM)
  7625. return soap->error = SOAP_MIME_HREF;
  7626. return soap->error = SOAP_DIME_HREF;
  7627. }
  7628. #endif
  7629. soap_free_ns(soap);
  7630. #ifndef WITH_LEANER
  7631. if (soap->fpreparefinalrecv)
  7632. return soap->error = soap->fpreparefinalrecv(soap);
  7633. #endif
  7634. return SOAP_OK;
  7635. }
  7636. #endif
  7637. /******************************************************************************/
  7638. #ifndef PALM_1
  7639. SOAP_FMAC1
  7640. void
  7641. SOAP_FMAC2
  7642. soap_free_temp(struct soap *soap)
  7643. { register struct soap_attribute *tp, *tq;
  7644. register struct Namespace *ns;
  7645. soap_free_ns(soap);
  7646. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free any remaining temp blocks\n"));
  7647. while (soap->blist)
  7648. soap_end_block(soap, NULL);
  7649. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute storage\n"));
  7650. for (tp = soap->attributes; tp; tp = tq)
  7651. { tq = tp->next;
  7652. if (tp->value)
  7653. SOAP_FREE(soap, tp->value);
  7654. SOAP_FREE(soap, tp);
  7655. }
  7656. soap->attributes = NULL;
  7657. #ifdef WITH_FAST
  7658. if (soap->labbuf)
  7659. SOAP_FREE(soap, soap->labbuf);
  7660. soap->labbuf = NULL;
  7661. soap->lablen = 0;
  7662. soap->labidx = 0;
  7663. #endif
  7664. ns = soap->local_namespaces;
  7665. if (ns)
  7666. { for (; ns->id; ns++)
  7667. { if (ns->out)
  7668. { if (soap->encodingStyle == ns->out)
  7669. soap->encodingStyle = SOAP_STR_EOS;
  7670. SOAP_FREE(soap, ns->out);
  7671. ns->out = NULL;
  7672. }
  7673. if (soap->encodingStyle == ns->ns)
  7674. soap->encodingStyle = SOAP_STR_EOS;
  7675. }
  7676. SOAP_FREE(soap, soap->local_namespaces);
  7677. soap->local_namespaces = NULL;
  7678. }
  7679. #ifndef WITH_LEANER
  7680. while (soap->xlist)
  7681. { struct soap_xlist *xp = soap->xlist->next;
  7682. SOAP_FREE(soap, soap->xlist);
  7683. soap->xlist = xp;
  7684. }
  7685. #endif
  7686. #ifndef WITH_NOIDREF
  7687. soap_free_pht(soap);
  7688. soap_free_iht(soap);
  7689. #endif
  7690. }
  7691. #endif
  7692. /******************************************************************************/
  7693. #ifndef PALM_1
  7694. static void
  7695. soap_free_ns(struct soap *soap)
  7696. { register struct soap_nlist *np, *nq;
  7697. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free namespace stack\n"));
  7698. for (np = soap->nlist; np; np = nq)
  7699. { nq = np->next;
  7700. SOAP_FREE(soap, np);
  7701. }
  7702. soap->nlist = NULL;
  7703. }
  7704. #endif
  7705. /******************************************************************************/
  7706. #ifndef PALM_1
  7707. #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
  7708. static void
  7709. soap_init_logs(struct soap *soap)
  7710. { int i;
  7711. for (i = 0; i < SOAP_MAXLOGS; i++)
  7712. { soap->logfile[i] = NULL;
  7713. soap->fdebug[i] = NULL;
  7714. }
  7715. }
  7716. #endif
  7717. #endif
  7718. /******************************************************************************/
  7719. #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
  7720. SOAP_FMAC1
  7721. void
  7722. SOAP_FMAC2
  7723. soap_open_logfile(struct soap *soap, int i)
  7724. { if (soap->logfile[i])
  7725. soap->fdebug[i] = fopen(soap->logfile[i], i < 2 ? "ab" : "a");
  7726. }
  7727. #endif
  7728. /******************************************************************************/
  7729. #ifdef SOAP_DEBUG
  7730. static void
  7731. soap_close_logfile(struct soap *soap, int i)
  7732. { if (soap->fdebug[i])
  7733. { fclose(soap->fdebug[i]);
  7734. soap->fdebug[i] = NULL;
  7735. }
  7736. }
  7737. #endif
  7738. /******************************************************************************/
  7739. #ifdef SOAP_DEBUG
  7740. SOAP_FMAC1
  7741. void
  7742. SOAP_FMAC2
  7743. soap_close_logfiles(struct soap *soap)
  7744. { int i;
  7745. for (i = 0; i < SOAP_MAXLOGS; i++)
  7746. soap_close_logfile(soap, i);
  7747. }
  7748. #endif
  7749. /******************************************************************************/
  7750. #ifdef SOAP_DEBUG
  7751. static void
  7752. soap_set_logfile(struct soap *soap, int i, const char *logfile)
  7753. { const char *s;
  7754. char *t = NULL;
  7755. soap_close_logfile(soap, i);
  7756. s = soap->logfile[i];
  7757. soap->logfile[i] = logfile;
  7758. if (s)
  7759. SOAP_FREE(soap, (void*)s);
  7760. if (logfile)
  7761. if ((t = (char*)SOAP_MALLOC(soap, strlen(logfile) + 1)))
  7762. strcpy(t, logfile);
  7763. soap->logfile[i] = t;
  7764. }
  7765. #endif
  7766. /******************************************************************************/
  7767. #ifdef SOAP_DEBUG
  7768. SOAP_FMAC1
  7769. void
  7770. SOAP_FMAC2
  7771. soap_set_recv_logfile(struct soap *soap, const char *logfile)
  7772. { soap_set_logfile(soap, SOAP_INDEX_RECV, logfile);
  7773. }
  7774. #endif
  7775. /******************************************************************************/
  7776. #ifdef SOAP_DEBUG
  7777. SOAP_FMAC1
  7778. void
  7779. SOAP_FMAC2
  7780. soap_set_sent_logfile(struct soap *soap, const char *logfile)
  7781. { soap_set_logfile(soap, SOAP_INDEX_SENT, logfile);
  7782. }
  7783. #endif
  7784. /******************************************************************************/
  7785. #ifdef SOAP_DEBUG
  7786. SOAP_FMAC1
  7787. void
  7788. SOAP_FMAC2
  7789. soap_set_test_logfile(struct soap *soap, const char *logfile)
  7790. { soap_set_logfile(soap, SOAP_INDEX_TEST, logfile);
  7791. }
  7792. #endif
  7793. /******************************************************************************/
  7794. #ifndef PALM_1
  7795. SOAP_FMAC1
  7796. struct soap*
  7797. SOAP_FMAC2
  7798. soap_copy(const struct soap *soap)
  7799. { return soap_copy_context((struct soap*)malloc(sizeof(struct soap)), soap);
  7800. }
  7801. #endif
  7802. /******************************************************************************/
  7803. #ifndef PALM_1
  7804. SOAP_FMAC1
  7805. struct soap*
  7806. SOAP_FMAC2
  7807. soap_copy_context(struct soap *copy, const struct soap *soap)
  7808. { if (soap_check_state(soap))
  7809. return NULL;
  7810. if (copy)
  7811. { register struct soap_plugin *p = NULL;
  7812. #ifdef __cplusplus
  7813. *copy = *soap;
  7814. #else
  7815. memcpy(copy, soap, sizeof(struct soap));
  7816. #endif
  7817. copy->state = SOAP_COPY;
  7818. copy->error = SOAP_OK;
  7819. copy->userid = NULL;
  7820. copy->passwd = NULL;
  7821. copy->nlist = NULL;
  7822. copy->blist = NULL;
  7823. copy->clist = NULL;
  7824. copy->alist = NULL;
  7825. copy->attributes = NULL;
  7826. copy->labbuf = NULL;
  7827. copy->lablen = 0;
  7828. copy->labidx = 0;
  7829. #ifdef SOAP_MEM_DEBUG
  7830. soap_init_mht(copy);
  7831. #endif
  7832. #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
  7833. soap_init_logs(copy);
  7834. #endif
  7835. #ifdef SOAP_DEBUG
  7836. soap_set_test_logfile(copy, soap->logfile[SOAP_INDEX_TEST]);
  7837. soap_set_sent_logfile(copy, soap->logfile[SOAP_INDEX_SENT]);
  7838. soap_set_recv_logfile(copy, soap->logfile[SOAP_INDEX_RECV]);
  7839. #endif
  7840. #ifdef WITH_C_LOCALE
  7841. copy->c_locale = duplocale(soap->c_locale);
  7842. #else
  7843. copy->c_locale = NULL;
  7844. #endif
  7845. #ifdef WITH_OPENSSL
  7846. copy->bio = NULL;
  7847. copy->ssl = NULL;
  7848. copy->session = NULL;
  7849. #endif
  7850. #ifdef WITH_ZLIB
  7851. copy->d_stream = (z_stream*)SOAP_MALLOC(copy, sizeof(z_stream));
  7852. copy->d_stream->zalloc = Z_NULL;
  7853. copy->d_stream->zfree = Z_NULL;
  7854. copy->d_stream->opaque = Z_NULL;
  7855. copy->z_buf = NULL;
  7856. #endif
  7857. copy->local_namespaces = NULL;
  7858. #ifndef WITH_NOIDREF
  7859. soap_init_iht(copy);
  7860. soap_init_pht(copy);
  7861. #endif
  7862. copy->header = NULL;
  7863. copy->fault = NULL;
  7864. copy->action = NULL;
  7865. #ifndef WITH_LEAN
  7866. #ifdef WITH_COOKIES
  7867. copy->cookies = soap_copy_cookies(copy, soap);
  7868. #else
  7869. copy->cookies = NULL;
  7870. #endif
  7871. #endif
  7872. copy->plugins = NULL;
  7873. for (p = soap->plugins; p; p = p->next)
  7874. { register struct soap_plugin *q = (struct soap_plugin*)SOAP_MALLOC(copy, sizeof(struct soap_plugin));
  7875. if (!q)
  7876. return NULL;
  7877. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying plugin '%s'\n", p->id));
  7878. *q = *p;
  7879. if (p->fcopy && p->fcopy(copy, q, p))
  7880. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not copy plugin '%s'\n", p->id));
  7881. SOAP_FREE(copy, q);
  7882. return NULL;
  7883. }
  7884. q->next = copy->plugins;
  7885. copy->plugins = q;
  7886. }
  7887. }
  7888. return copy;
  7889. }
  7890. #endif
  7891. /******************************************************************************/
  7892. #ifndef PALM_1
  7893. SOAP_FMAC1
  7894. void
  7895. SOAP_FMAC2
  7896. soap_copy_stream(struct soap *copy, struct soap *soap)
  7897. { copy->mode = soap->mode;
  7898. copy->imode = soap->imode;
  7899. copy->omode = soap->omode;
  7900. copy->socket = soap->socket;
  7901. copy->recv_timeout = soap->recv_timeout;
  7902. copy->send_timeout = soap->send_timeout;
  7903. #if defined(__cplusplus) && !defined(WITH_LEAN)
  7904. copy->os = soap->os;
  7905. copy->is = soap->is;
  7906. #endif
  7907. copy->sendfd = soap->sendfd;
  7908. copy->recvfd = soap->recvfd;
  7909. copy->bufidx = soap->bufidx;
  7910. copy->buflen = soap->buflen;
  7911. copy->ahead = soap->ahead;
  7912. copy->cdata = soap->cdata;
  7913. copy->chunksize = soap->chunksize;
  7914. copy->chunkbuflen = soap->chunkbuflen;
  7915. copy->keep_alive = soap->keep_alive;
  7916. copy->tcp_keep_alive = soap->tcp_keep_alive;
  7917. copy->tcp_keep_idle = soap->tcp_keep_idle;
  7918. copy->tcp_keep_intvl = soap->tcp_keep_intvl;
  7919. copy->tcp_keep_cnt = soap->tcp_keep_cnt;
  7920. copy->max_keep_alive = soap->max_keep_alive;
  7921. #ifndef WITH_NOIO
  7922. copy->peer = soap->peer;
  7923. copy->peerlen = soap->peerlen;
  7924. #endif
  7925. #ifdef WITH_OPENSSL
  7926. copy->bio = soap->bio;
  7927. copy->ssl = soap->ssl;
  7928. copy->ctx = soap->ctx;
  7929. #endif
  7930. #ifdef WITH_ZLIB
  7931. copy->zlib_state = soap->zlib_state;
  7932. copy->zlib_in = soap->zlib_in;
  7933. copy->zlib_out = soap->zlib_out;
  7934. copy->d_stream = (z_stream*)SOAP_MALLOC(copy, sizeof(z_stream));
  7935. memcpy(copy->d_stream, soap->d_stream, sizeof(z_stream));
  7936. copy->z_crc = soap->z_crc;
  7937. copy->z_ratio_in = soap->z_ratio_in;
  7938. copy->z_ratio_out = soap->z_ratio_out;
  7939. copy->z_buf = NULL;
  7940. copy->z_buflen = soap->z_buflen;
  7941. copy->z_level = soap->z_level;
  7942. if (soap->z_buf && soap->zlib_state != SOAP_ZLIB_NONE)
  7943. { copy->z_buf = (char*)SOAP_MALLOC(copy, SOAP_BUFLEN);
  7944. memcpy(copy->z_buf, soap->z_buf, sizeof(soap->z_buf));
  7945. }
  7946. copy->z_dict = soap->z_dict;
  7947. copy->z_dict_len = soap->z_dict_len;
  7948. #endif
  7949. memcpy(copy->buf, soap->buf, sizeof(soap->buf));
  7950. }
  7951. #endif
  7952. /******************************************************************************/
  7953. #ifndef PALM_1
  7954. SOAP_FMAC1
  7955. void
  7956. SOAP_FMAC2
  7957. soap_free_stream(struct soap *soap)
  7958. { soap->socket = SOAP_INVALID_SOCKET;
  7959. #ifdef WITH_OPENSSL
  7960. soap->bio = NULL;
  7961. soap->ssl = NULL;
  7962. #endif
  7963. #ifdef WITH_ZLIB
  7964. if (soap->d_stream)
  7965. SOAP_FREE(soap, soap->d_stream);
  7966. soap->d_stream = NULL;
  7967. if (soap->z_buf)
  7968. SOAP_FREE(soap, soap->z_buf);
  7969. soap->z_buf = NULL;
  7970. #endif
  7971. }
  7972. #endif
  7973. /******************************************************************************/
  7974. #ifndef PALM_1
  7975. SOAP_FMAC1
  7976. void
  7977. SOAP_FMAC2
  7978. soap_init(struct soap *soap)
  7979. { soap->state = SOAP_INIT;
  7980. #ifdef SOAP_MEM_DEBUG
  7981. soap_init_mht(soap);
  7982. #endif
  7983. #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
  7984. soap_init_logs(soap);
  7985. #endif
  7986. #ifdef SOAP_DEBUG
  7987. /*
  7988. Oracle customization for KMS server debug
  7989. */
  7990. #ifdef SOAP_DEBUG_SERVER
  7991. soap_set_test_logfile(soap, "/var/log/SUNWkms2/TEST.log");
  7992. soap_set_sent_logfile(soap, "/var/log/SUNWkms2/SENT.log");
  7993. soap_set_recv_logfile(soap, "/var/log/SUNWkms2/RECV.log");
  7994. #else
  7995. soap_set_test_logfile(soap, "TEST.log");
  7996. soap_set_sent_logfile(soap, "SENT.log");
  7997. soap_set_recv_logfile(soap, "RECV.log");
  7998. #endif
  7999. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing context\n"));
  8000. #endif
  8001. soap->version = 0;
  8002. soap_imode(soap, SOAP_IO_DEFAULT);
  8003. soap_omode(soap, SOAP_IO_DEFAULT);
  8004. soap->plugins = NULL;
  8005. soap->user = NULL;
  8006. soap->userid = NULL;
  8007. soap->passwd = NULL;
  8008. #ifndef WITH_NOHTTP
  8009. soap->fpost = http_post;
  8010. soap->fget = http_get;
  8011. soap->fput = http_405;
  8012. soap->fdel = http_405;
  8013. soap->fhead = http_405;
  8014. soap->fform = NULL;
  8015. soap->fposthdr = http_post_header;
  8016. soap->fresponse = http_response;
  8017. soap->fparse = http_parse;
  8018. soap->fparsehdr = http_parse_header;
  8019. #endif
  8020. soap->fheader = NULL;
  8021. soap->fconnect = NULL;
  8022. soap->fdisconnect = NULL;
  8023. #ifndef WITH_NOIO
  8024. soap->ipv6_multicast_if = 0;
  8025. soap->ipv4_multicast_if = NULL;
  8026. #ifndef WITH_IPV6
  8027. soap->fresolve = tcp_gethost;
  8028. #else
  8029. soap->fresolve = NULL;
  8030. #endif
  8031. soap->faccept = tcp_accept;
  8032. soap->fopen = tcp_connect;
  8033. soap->fclose = tcp_disconnect;
  8034. soap->fclosesocket = tcp_closesocket;
  8035. soap->fshutdownsocket = tcp_shutdownsocket;
  8036. soap->fsend = fsend;
  8037. soap->frecv = frecv;
  8038. soap->fpoll = soap_poll;
  8039. #else
  8040. soap->fopen = NULL;
  8041. soap->fclose = NULL;
  8042. soap->fpoll = NULL;
  8043. #endif
  8044. soap->fseterror = NULL;
  8045. soap->fignore = NULL;
  8046. soap->fserveloop = NULL;
  8047. soap->fplugin = fplugin;
  8048. soap->fmalloc = NULL;
  8049. #ifndef WITH_LEANER
  8050. soap->fprepareinitsend = NULL;
  8051. soap->fprepareinitrecv = NULL;
  8052. soap->fpreparesend = NULL;
  8053. soap->fpreparerecv = NULL;
  8054. soap->fpreparefinalsend = NULL;
  8055. soap->fpreparefinalrecv = NULL;
  8056. soap->fdimereadopen = NULL;
  8057. soap->fdimewriteopen = NULL;
  8058. soap->fdimereadclose = NULL;
  8059. soap->fdimewriteclose = NULL;
  8060. soap->fdimeread = NULL;
  8061. soap->fdimewrite = NULL;
  8062. soap->fmimereadopen = NULL;
  8063. soap->fmimewriteopen = NULL;
  8064. soap->fmimereadclose = NULL;
  8065. soap->fmimewriteclose = NULL;
  8066. soap->fmimeread = NULL;
  8067. soap->fmimewrite = NULL;
  8068. #endif
  8069. soap->float_format = "%.9G"; /* Alternative: use "%G" */
  8070. soap->double_format = "%.17lG"; /* Alternative: use "%lG" */
  8071. soap->dime_id_format = "cid:id%d"; /* default DIME id format */
  8072. soap->http_version = "1.1";
  8073. soap->proxy_http_version = "1.0";
  8074. soap->http_content = NULL;
  8075. soap->actor = NULL;
  8076. soap->lang = "en";
  8077. soap->keep_alive = 0;
  8078. soap->tcp_keep_alive = 0;
  8079. soap->tcp_keep_idle = 0;
  8080. soap->tcp_keep_intvl = 0;
  8081. soap->tcp_keep_cnt = 0;
  8082. soap->max_keep_alive = SOAP_MAXKEEPALIVE;
  8083. soap->recv_timeout = 0;
  8084. soap->send_timeout = 0;
  8085. soap->connect_timeout = 0;
  8086. soap->accept_timeout = 0;
  8087. #if defined(WITH_OPENSSL) && defined(KMS_SERVER)
  8088. /* Oracle customization for Ultra 2 KMS Server */
  8089. soap->ssl_accept_timeout = 0;
  8090. #endif
  8091. soap->socket_flags = 0;
  8092. soap->connect_flags = 0;
  8093. soap->bind_flags = 0;
  8094. soap->accept_flags = 0;
  8095. soap->linger_time = 0;
  8096. soap->ip = 0;
  8097. soap->labbuf = NULL;
  8098. soap->lablen = 0;
  8099. soap->labidx = 0;
  8100. soap->encodingStyle = SOAP_STR_EOS;
  8101. #ifndef WITH_NONAMESPACES
  8102. soap->namespaces = namespaces;
  8103. #else
  8104. soap->namespaces = NULL;
  8105. #endif
  8106. soap->local_namespaces = NULL;
  8107. soap->nlist = NULL;
  8108. soap->blist = NULL;
  8109. soap->clist = NULL;
  8110. soap->alist = NULL;
  8111. soap->attributes = NULL;
  8112. soap->header = NULL;
  8113. soap->fault = NULL;
  8114. soap->master = SOAP_INVALID_SOCKET;
  8115. soap->socket = SOAP_INVALID_SOCKET;
  8116. soap->os = NULL;
  8117. soap->is = NULL;
  8118. #ifndef WITH_LEANER
  8119. soap->dom = NULL;
  8120. soap->dime.list = NULL;
  8121. soap->dime.first = NULL;
  8122. soap->dime.last = NULL;
  8123. soap->mime.list = NULL;
  8124. soap->mime.first = NULL;
  8125. soap->mime.last = NULL;
  8126. soap->mime.boundary = NULL;
  8127. soap->mime.start = NULL;
  8128. soap->xlist = NULL;
  8129. #endif
  8130. #ifndef UNDER_CE
  8131. soap->recvfd = 0;
  8132. soap->sendfd = 1;
  8133. #else
  8134. soap->recvfd = stdin;
  8135. soap->sendfd = stdout;
  8136. #endif
  8137. soap->host[0] = '\0';
  8138. soap->session_host[0] = '\0'; /* Oracle customization */
  8139. soap->session_port = 0; /* Oracle customization */
  8140. soap->port = 0;
  8141. soap->action = NULL;
  8142. soap->proxy_host = NULL;
  8143. soap->proxy_port = 8080;
  8144. soap->proxy_userid = NULL;
  8145. soap->proxy_passwd = NULL;
  8146. soap->authrealm = NULL;
  8147. soap->prolog = NULL;
  8148. #ifdef WITH_ZLIB
  8149. soap->zlib_state = SOAP_ZLIB_NONE;
  8150. soap->zlib_in = SOAP_ZLIB_NONE;
  8151. soap->zlib_out = SOAP_ZLIB_NONE;
  8152. soap->d_stream = (z_stream*)SOAP_MALLOC(soap, sizeof(z_stream));
  8153. soap->d_stream->zalloc = Z_NULL;
  8154. soap->d_stream->zfree = Z_NULL;
  8155. soap->d_stream->opaque = Z_NULL;
  8156. soap->z_buf = NULL;
  8157. soap->z_level = 6;
  8158. soap->z_dict = NULL;
  8159. soap->z_dict_len = 0;
  8160. #endif
  8161. #ifndef WITH_LEAN
  8162. soap->wsuid = NULL;
  8163. soap->c14nexclude = NULL;
  8164. soap->cookies = NULL;
  8165. soap->cookie_domain = NULL;
  8166. soap->cookie_path = NULL;
  8167. soap->cookie_max = 32;
  8168. #endif
  8169. #ifdef WMW_RPM_IO
  8170. soap->rpmreqid = NULL;
  8171. #endif
  8172. #ifdef PALM
  8173. palmNetLibOpen();
  8174. #endif
  8175. #ifndef WITH_NOIDREF
  8176. soap_init_iht(soap);
  8177. soap_init_pht(soap);
  8178. #endif
  8179. #ifdef WITH_OPENSSL
  8180. if (!soap_ssl_init_done)
  8181. soap_ssl_init();
  8182. soap->fsslauth = ssl_auth_init;
  8183. soap->fsslverify = ssl_verify_callback;
  8184. soap->bio = NULL;
  8185. soap->ssl = NULL;
  8186. soap->ctx = NULL;
  8187. soap->ssl_flags = SOAP_SSL_DEFAULT;
  8188. soap->keyfile = NULL;
  8189. soap->password = NULL;
  8190. soap->dhfile = NULL;
  8191. soap->cafile = NULL;
  8192. soap->capath = NULL;
  8193. soap->crlfile = NULL;
  8194. soap->randfile = NULL;
  8195. soap->session = NULL;
  8196. #endif
  8197. #ifdef WITH_C_LOCALE
  8198. soap->c_locale = newlocale(LC_ALL_MASK, "C", NULL);
  8199. #else
  8200. soap->c_locale = NULL;
  8201. #endif
  8202. soap->buflen = 0;
  8203. soap->bufidx = 0;
  8204. #ifndef WITH_LEANER
  8205. soap->dime.chunksize = 0;
  8206. soap->dime.buflen = 0;
  8207. #endif
  8208. soap->null = 0;
  8209. soap->position = 0;
  8210. soap->encoding = 0;
  8211. soap->mustUnderstand = 0;
  8212. soap->ns = 0;
  8213. soap->part = SOAP_END;
  8214. soap->alloced = 0;
  8215. soap->count = 0;
  8216. soap->length = 0;
  8217. soap->cdata = 0;
  8218. soap->peeked = 0;
  8219. soap->ahead = 0;
  8220. soap->idnum = 0;
  8221. soap->level = 0;
  8222. soap->endpoint[0] = '\0';
  8223. soap->error = SOAP_OK;
  8224. }
  8225. #endif
  8226. /******************************************************************************/
  8227. #ifndef PALM_1
  8228. SOAP_FMAC1
  8229. void
  8230. SOAP_FMAC2
  8231. soap_init1(struct soap *soap, soap_mode mode)
  8232. { soap_init2(soap, mode, mode);
  8233. }
  8234. #endif
  8235. /******************************************************************************/
  8236. #ifndef PALM_1
  8237. SOAP_FMAC1
  8238. void
  8239. SOAP_FMAC2
  8240. soap_init2(struct soap *soap, soap_mode imode, soap_mode omode)
  8241. { soap_init(soap);
  8242. soap_imode(soap, imode);
  8243. soap_omode(soap, omode);
  8244. }
  8245. #endif
  8246. /******************************************************************************/
  8247. #ifndef PALM_2
  8248. SOAP_FMAC1
  8249. void
  8250. SOAP_FMAC2
  8251. soap_begin(struct soap *soap)
  8252. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reinitializing context\n"));
  8253. if (!soap->keep_alive)
  8254. { soap->buflen = 0;
  8255. soap->bufidx = 0;
  8256. }
  8257. soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0);
  8258. soap->null = 0;
  8259. soap->position = 0;
  8260. soap->encoding = 0;
  8261. soap->mustUnderstand = 0;
  8262. soap->mode = 0;
  8263. soap->ns = 0;
  8264. soap->part = SOAP_END;
  8265. soap->alloced = 0;
  8266. soap->count = 0;
  8267. soap->length = 0;
  8268. soap->cdata = 0;
  8269. soap->error = SOAP_OK;
  8270. soap->peeked = 0;
  8271. soap->ahead = 0;
  8272. soap->idnum = 0;
  8273. soap->level = 0;
  8274. soap->endpoint[0] = '\0';
  8275. #ifndef WITH_LEANER
  8276. soap->dime.chunksize = 0;
  8277. soap->dime.buflen = 0;
  8278. #endif
  8279. soap_free_temp(soap);
  8280. }
  8281. #endif
  8282. /******************************************************************************/
  8283. #ifndef PALM_2
  8284. SOAP_FMAC1
  8285. void
  8286. SOAP_FMAC2
  8287. soap_end(struct soap *soap)
  8288. { if (soap_check_state(soap))
  8289. return;
  8290. soap_free_temp(soap);
  8291. soap_dealloc(soap, NULL);
  8292. while (soap->clist)
  8293. { register struct soap_clist *cp = soap->clist->next;
  8294. SOAP_FREE(soap, soap->clist);
  8295. soap->clist = cp;
  8296. }
  8297. soap_closesock(soap);
  8298. #ifdef SOAP_DEBUG
  8299. soap_close_logfiles(soap);
  8300. #endif
  8301. #ifdef PALM
  8302. palmNetLibClose();
  8303. #endif
  8304. }
  8305. #endif
  8306. /******************************************************************************/
  8307. #ifndef PALM_1
  8308. SOAP_FMAC1
  8309. int
  8310. SOAP_FMAC2
  8311. soap_set_namespaces(struct soap *soap, const struct Namespace *p)
  8312. { register struct Namespace *ns = soap->local_namespaces;
  8313. register struct soap_nlist *np, *nq, *nr;
  8314. register unsigned int level = soap->level;
  8315. soap->namespaces = p;
  8316. soap->local_namespaces = NULL;
  8317. soap_set_local_namespaces(soap);
  8318. /* reverse the namespace list */
  8319. np = soap->nlist;
  8320. soap->nlist = NULL;
  8321. if (np)
  8322. { nq = np->next;
  8323. np->next = NULL;
  8324. while (nq)
  8325. { nr = nq->next;
  8326. nq->next = np;
  8327. np = nq;
  8328. nq = nr;
  8329. }
  8330. }
  8331. /* then push on new stack */
  8332. while (np)
  8333. { register const char *s;
  8334. soap->level = np->level; /* preserve element nesting level */
  8335. s = np->ns;
  8336. if (!s && np->index >= 0 && ns)
  8337. { s = ns[np->index].out;
  8338. if (!s)
  8339. s = ns[np->index].ns;
  8340. }
  8341. if (s && soap_push_namespace(soap, np->id, s) == NULL)
  8342. return soap->error;
  8343. nq = np;
  8344. np = np->next;
  8345. SOAP_FREE(soap, nq);
  8346. }
  8347. if (ns)
  8348. { register int i;
  8349. for (i = 0; ns[i].id; i++)
  8350. { if (ns[i].out)
  8351. { SOAP_FREE(soap, ns[i].out);
  8352. ns[i].out = NULL;
  8353. }
  8354. }
  8355. SOAP_FREE(soap, ns);
  8356. }
  8357. soap->level = level; /* restore level */
  8358. return SOAP_OK;
  8359. }
  8360. #endif
  8361. /******************************************************************************/
  8362. #ifndef PALM_1
  8363. SOAP_FMAC1
  8364. void
  8365. SOAP_FMAC2
  8366. soap_set_local_namespaces(struct soap *soap)
  8367. { if (soap->namespaces && !soap->local_namespaces)
  8368. { register const struct Namespace *ns1;
  8369. register struct Namespace *ns2;
  8370. register size_t n = 1;
  8371. for (ns1 = soap->namespaces; ns1->id; ns1++)
  8372. n++;
  8373. n *= sizeof(struct Namespace);
  8374. ns2 = (struct Namespace*)SOAP_MALLOC(soap, n);
  8375. if (ns2)
  8376. { memcpy(ns2, soap->namespaces, n);
  8377. if (ns2[0].ns)
  8378. { if (!strcmp(ns2[0].ns, soap_env1))
  8379. soap->version = 1;
  8380. else
  8381. soap->version = 2;
  8382. }
  8383. soap->local_namespaces = ns2;
  8384. }
  8385. }
  8386. }
  8387. #endif
  8388. /******************************************************************************/
  8389. #ifndef WITH_LEAN
  8390. #ifndef PALM_1
  8391. SOAP_FMAC1
  8392. const char *
  8393. SOAP_FMAC2
  8394. soap_tagsearch(const char *big, const char *little)
  8395. { if (little)
  8396. { register size_t n = strlen(little);
  8397. register const char *s = big;
  8398. while (s)
  8399. { register const char *t = s;
  8400. register size_t i;
  8401. for (i = 0; i < n; i++, t++)
  8402. { if (*t != little[i])
  8403. break;
  8404. }
  8405. if (*t == '\0' || *t == ' ')
  8406. { if (i == n || (i && little[i-1] == ':'))
  8407. return s;
  8408. }
  8409. s = strchr(t, ' ');
  8410. if (s)
  8411. s++;
  8412. }
  8413. }
  8414. return NULL;
  8415. }
  8416. #endif
  8417. #endif
  8418. /******************************************************************************/
  8419. #ifndef WITH_LEAN
  8420. #ifndef PALM_1
  8421. SOAP_FMAC1
  8422. struct soap_nlist *
  8423. SOAP_FMAC2
  8424. soap_lookup_ns(struct soap *soap, const char *tag, size_t n)
  8425. { register struct soap_nlist *np;
  8426. for (np = soap->nlist; np; np = np->next)
  8427. { if (!strncmp(np->id, tag, n) && !np->id[n])
  8428. return np;
  8429. }
  8430. return NULL;
  8431. }
  8432. #endif
  8433. #endif
  8434. /******************************************************************************/
  8435. #ifndef WITH_LEAN
  8436. static struct soap_nlist *
  8437. soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized)
  8438. { register struct soap_nlist *np;
  8439. size_t n, k;
  8440. if (soap_tagsearch(soap->c14nexclude, id))
  8441. return NULL;
  8442. if (!utilized)
  8443. { for (np = soap->nlist; np; np = np->next)
  8444. { if (!strcmp(np->id, id) && (!np->ns || !strcmp(np->ns, ns)))
  8445. break;
  8446. }
  8447. if (np)
  8448. { if ((np->level < soap->level || !np->ns) && np->index == 1)
  8449. utilized = 1;
  8450. else
  8451. return NULL;
  8452. }
  8453. }
  8454. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Adding namespace binding (level=%u) '%s' '%s' utilized=%d\n", soap->level, id, ns?ns:"(null)", utilized));
  8455. n = strlen(id);
  8456. if (ns)
  8457. k = strlen(ns);
  8458. else
  8459. k = 0;
  8460. np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k + 1);
  8461. if (!np)
  8462. { soap->error = SOAP_EOM;
  8463. return NULL;
  8464. }
  8465. np->next = soap->nlist;
  8466. soap->nlist = np;
  8467. strcpy(np->id, id);
  8468. if (ns)
  8469. np->ns = strcpy(np->id + n + 1, ns);
  8470. else
  8471. np->ns = NULL;
  8472. np->level = soap->level;
  8473. np->index = utilized;
  8474. return np;
  8475. }
  8476. #endif
  8477. /******************************************************************************/
  8478. #ifndef WITH_LEAN
  8479. static void
  8480. soap_utilize_ns(struct soap *soap, const char *tag, size_t n)
  8481. { register struct soap_nlist *np = soap_lookup_ns(soap, tag, n);
  8482. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Utilizing namespace of '%s'\n", tag));
  8483. if (np)
  8484. { if (np->index == 0)
  8485. soap_push_ns(soap, np->id, np->ns, 1);
  8486. }
  8487. else if (strncmp(tag, "xml", 3))
  8488. { strncpy(soap->tmpbuf, tag, n);
  8489. soap->tmpbuf[n] = '\0';
  8490. soap_push_ns(soap, soap->tmpbuf, NULL, 1);
  8491. }
  8492. }
  8493. #endif
  8494. /******************************************************************************/
  8495. #ifndef PALM_2
  8496. SOAP_FMAC1
  8497. int
  8498. SOAP_FMAC2
  8499. soap_element(struct soap *soap, const char *tag, int id, const char *type)
  8500. {
  8501. #ifndef WITH_LEAN
  8502. register const char *s;
  8503. #endif
  8504. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element begin tag='%s' id='%d' type='%s'\n", tag, id, type?type:SOAP_STR_EOS));
  8505. #ifdef WITH_DOM
  8506. #ifndef WITH_LEAN
  8507. if (soap->wsuid && soap_tagsearch(soap->wsuid, tag))
  8508. { int i;
  8509. for (s = tag, i = 0; *s && i < sizeof(soap->tag); s++, i++)
  8510. soap->tag[i] = *s == ':' ? '-' : *s;
  8511. soap->tag[sizeof(soap->tag) - 1] = '\0';
  8512. if (soap_set_attr(soap, "wsu:Id", soap->tag, 1))
  8513. return soap->error;
  8514. }
  8515. #endif
  8516. if (soap->part == SOAP_BEGIN_SECURITY && (soap->mode & SOAP_XML_CANONICAL) && !(soap->mode & SOAP_DOM_ASIS))
  8517. { register struct soap_nlist *np;
  8518. /* wsu:Id found: clear xmlns renderings, so re-emit them for exc-c14n */
  8519. for (np = soap->nlist; np; np = np->next)
  8520. { if (np->index == 2)
  8521. np->index = 0;
  8522. }
  8523. }
  8524. if (soap->mode & SOAP_XML_DOM)
  8525. { register struct soap_dom_element *elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element));
  8526. if (!elt)
  8527. return soap->error;
  8528. elt->soap = soap;
  8529. elt->next = NULL;
  8530. elt->prnt = soap->dom;
  8531. elt->name = soap_strdup(soap, tag);
  8532. elt->elts = NULL;
  8533. elt->atts = NULL;
  8534. elt->nstr = NULL;
  8535. elt->data = NULL;
  8536. elt->wide = NULL;
  8537. elt->node = NULL;
  8538. elt->type = 0;
  8539. elt->head = NULL;
  8540. elt->tail = NULL;
  8541. if (soap->dom)
  8542. { struct soap_dom_element *p = soap->dom->elts;
  8543. if (p)
  8544. { while (p->next)
  8545. p = p->next;
  8546. p->next = elt;
  8547. }
  8548. else
  8549. soap->dom->elts = elt;
  8550. }
  8551. soap->dom = elt;
  8552. }
  8553. else
  8554. {
  8555. #endif
  8556. soap->level++;
  8557. #ifndef WITH_LEAN
  8558. if (!soap->ns)
  8559. { if (!(soap->mode & SOAP_XML_CANONICAL)
  8560. && soap_send(soap, soap->prolog ? soap->prolog : "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"))
  8561. return soap->error;
  8562. }
  8563. else if (soap->mode & SOAP_XML_INDENT)
  8564. { if (soap->ns == 1 && soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1))
  8565. return soap->error;
  8566. soap->body = 1;
  8567. }
  8568. if ((soap->mode & SOAP_XML_DEFAULTNS) && (s = strchr(tag, ':')))
  8569. { struct Namespace *ns = soap->local_namespaces;
  8570. size_t n = s - tag;
  8571. if (soap_send_raw(soap, "<", 1)
  8572. || soap_send(soap, s + 1))
  8573. return soap->error;
  8574. if (soap->nlist && !strncmp(soap->nlist->id, tag, n) && !soap->nlist->id[n])
  8575. ns = NULL;
  8576. for (; ns && ns->id; ns++)
  8577. { if (*ns->id && (ns->out || ns->ns) && !strncmp(ns->id, tag, n) && !ns->id[n])
  8578. { soap_push_ns(soap, ns->id, ns->out ? ns->out : ns->ns, 0);
  8579. if (soap_attribute(soap, "xmlns", ns->out ? ns->out : ns->ns))
  8580. return soap->error;
  8581. break;
  8582. }
  8583. }
  8584. }
  8585. else
  8586. #endif
  8587. if (soap_send_raw(soap, "<", 1)
  8588. || soap_send(soap, tag))
  8589. return soap->error;
  8590. #ifdef WITH_DOM
  8591. }
  8592. #endif
  8593. if (!soap->ns)
  8594. { struct Namespace *ns;
  8595. int k = -1;
  8596. #ifndef WITH_LEAN
  8597. if ((soap->mode & SOAP_XML_DEFAULTNS))
  8598. k = 4; /* only produce the first four required entries */
  8599. #endif
  8600. for (ns = soap->local_namespaces; ns && ns->id && k; ns++, k--)
  8601. { if (*ns->id && (ns->out || ns->ns))
  8602. { sprintf(soap->tmpbuf, "xmlns:%s", ns->id);
  8603. if (soap_attribute(soap, soap->tmpbuf, ns->out ? ns->out : ns->ns))
  8604. return soap->error;
  8605. }
  8606. }
  8607. }
  8608. soap->ns = 1; /* namespace table control: ns = 0 or 2 to start, then 1 to stop dumping the table */
  8609. #ifndef WITH_LEAN
  8610. if (soap->mode & SOAP_XML_CANONICAL)
  8611. { const char *t = strchr(tag, ':');
  8612. if (t)
  8613. soap_utilize_ns(soap, tag, t - tag);
  8614. }
  8615. #endif
  8616. if (id > 0)
  8617. { sprintf(soap->tmpbuf, "_%d", id);
  8618. if (soap_attribute(soap, "id", soap->tmpbuf))
  8619. return soap->error;
  8620. }
  8621. if (type && *type && (!(soap->mode & SOAP_XML_SEC) || soap->part == SOAP_IN_BODY))
  8622. { if (soap_attribute(soap, "xsi:type", type))
  8623. return soap->error;
  8624. #ifndef WITH_LEAN
  8625. if (soap->mode & SOAP_XML_CANONICAL)
  8626. { const char *t = strchr(type, ':');
  8627. if (t)
  8628. soap_utilize_ns(soap, type, t - type);
  8629. }
  8630. #endif
  8631. }
  8632. if (soap->null && soap->position > 0)
  8633. { register int i;
  8634. sprintf(soap->tmpbuf, "[%d", soap->positions[0]);
  8635. for (i = 1; i < soap->position; i++)
  8636. sprintf(soap->tmpbuf + strlen(soap->tmpbuf), ",%d", soap->positions[i]);
  8637. strcat(soap->tmpbuf, "]");
  8638. if (soap_attribute(soap, "SOAP-ENC:position", soap->tmpbuf))
  8639. return soap->error;
  8640. }
  8641. if (soap->mustUnderstand)
  8642. { if (soap->actor && *soap->actor)
  8643. { if (soap_attribute(soap, soap->version == 2 ? "SOAP-ENV:role" : "SOAP-ENV:actor", soap->actor))
  8644. return soap->error;
  8645. }
  8646. if (soap_attribute(soap, "SOAP-ENV:mustUnderstand", soap->version == 2 ? "true" : "1"))
  8647. return soap->error;
  8648. soap->mustUnderstand = 0;
  8649. }
  8650. if (soap->encoding)
  8651. { if (soap->encodingStyle && soap->local_namespaces)
  8652. { if (!*soap->encodingStyle)
  8653. { if (soap->local_namespaces[1].out)
  8654. soap->encodingStyle = soap->local_namespaces[1].out;
  8655. else
  8656. soap->encodingStyle = soap->local_namespaces[1].ns;
  8657. }
  8658. if (soap->encodingStyle && soap_attribute(soap, "SOAP-ENV:encodingStyle", soap->encodingStyle))
  8659. return soap->error;
  8660. }
  8661. soap->encoding = 0;
  8662. }
  8663. soap->null = 0;
  8664. soap->position = 0;
  8665. if (soap->part == SOAP_BEGIN_SECURITY && (soap->mode & SOAP_XML_CANONICAL))
  8666. soap->part = SOAP_IN_SECURITY;
  8667. return SOAP_OK;
  8668. }
  8669. #endif
  8670. /******************************************************************************/
  8671. #ifndef PALM_2
  8672. SOAP_FMAC1
  8673. int
  8674. SOAP_FMAC2
  8675. soap_element_begin_out(struct soap *soap, const char *tag, int id, const char *type)
  8676. { if (*tag == '-')
  8677. return SOAP_OK;
  8678. if (soap_element(soap, tag, id, type))
  8679. return soap->error;
  8680. return soap_element_start_end_out(soap, NULL);
  8681. }
  8682. #endif
  8683. /******************************************************************************/
  8684. #ifndef PALM_2
  8685. #ifndef HAVE_STRRCHR
  8686. SOAP_FMAC1
  8687. char*
  8688. SOAP_FMAC2
  8689. soap_strrchr(const char *s, int t)
  8690. { register char *r = NULL;
  8691. while (*s)
  8692. if (*s++ == t)
  8693. r = (char*)s - 1;
  8694. return r;
  8695. }
  8696. #endif
  8697. #endif
  8698. /******************************************************************************/
  8699. #ifndef PALM_2
  8700. #ifndef HAVE_STRTOL
  8701. SOAP_FMAC1
  8702. long
  8703. SOAP_FMAC2
  8704. soap_strtol(const char *s, char **t, int b)
  8705. { register long n = 0;
  8706. register int c;
  8707. while (*s > 0 && *s <= 32)
  8708. s++;
  8709. if (b == 10)
  8710. { short neg = 0;
  8711. if (*s == '-')
  8712. { s++;
  8713. neg = 1;
  8714. }
  8715. else if (*s == '+')
  8716. s++;
  8717. while ((c = *s) && c >= '0' && c <= '9')
  8718. { if (n >= 214748364 && (n > 214748364 || c >= '8'))
  8719. break;
  8720. n *= 10;
  8721. n += c - '0';
  8722. s++;
  8723. }
  8724. if (neg)
  8725. n = -n;
  8726. }
  8727. else /* assume b == 16 and value is always positive */
  8728. { while ((c = *s))
  8729. { if (c >= '0' && c <= '9')
  8730. c -= '0';
  8731. else if (c >= 'A' && c <= 'F')
  8732. c -= 'A' - 10;
  8733. else if (c >= 'a' && c <= 'f')
  8734. c -= 'a' - 10;
  8735. if (n > 0x07FFFFFF)
  8736. break;
  8737. n <<= 4;
  8738. n += c;
  8739. s++;
  8740. }
  8741. }
  8742. if (t)
  8743. *t = (char*)s;
  8744. return n;
  8745. }
  8746. #endif
  8747. #endif
  8748. /******************************************************************************/
  8749. #ifndef PALM_2
  8750. #ifndef HAVE_STRTOUL
  8751. SOAP_FMAC1
  8752. unsigned long
  8753. SOAP_FMAC2
  8754. soap_strtoul(const char *s, char **t, int b)
  8755. { unsigned long n = 0;
  8756. register int c;
  8757. while (*s > 0 && *s <= 32)
  8758. s++;
  8759. if (b == 10)
  8760. { if (*s == '+')
  8761. s++;
  8762. while ((c = *s) && c >= '0' && c <= '9')
  8763. { if (n >= 429496729 && (n > 429496729 || c >= '6'))
  8764. break;
  8765. n *= 10;
  8766. n += c - '0';
  8767. s++;
  8768. }
  8769. }
  8770. else /* b == 16 */
  8771. { while ((c = *s))
  8772. { if (c >= '0' && c <= '9')
  8773. c -= '0';
  8774. else if (c >= 'A' && c <= 'F')
  8775. c -= 'A' - 10;
  8776. else if (c >= 'a' && c <= 'f')
  8777. c -= 'a' - 10;
  8778. if (n > 0x0FFFFFFF)
  8779. break;
  8780. n <<= 4;
  8781. n += c;
  8782. s++;
  8783. }
  8784. }
  8785. if (t)
  8786. *t = (char*)s;
  8787. return n;
  8788. }
  8789. #endif
  8790. #endif
  8791. /******************************************************************************/
  8792. #ifndef PALM_1
  8793. SOAP_FMAC1
  8794. int
  8795. SOAP_FMAC2
  8796. soap_array_begin_out(struct soap *soap, const char *tag, int id, const char *type, const char *offset)
  8797. { if (!type || !*type)
  8798. return soap_element_begin_out(soap, tag, id, NULL);
  8799. if (soap_element(soap, tag, id, "SOAP-ENC:Array"))
  8800. return soap->error;
  8801. if (soap->version == 2)
  8802. { const char *s;
  8803. s = soap_strrchr(type, '[');
  8804. if ((size_t)(s - type) < sizeof(soap->tmpbuf))
  8805. { strncpy(soap->tmpbuf, type, s - type);
  8806. soap->tmpbuf[s - type] = '\0';
  8807. if (soap_attribute(soap, "SOAP-ENC:itemType", soap->tmpbuf))
  8808. return soap->error;
  8809. if (s && (soap_attribute(soap, "SOAP-ENC:arraySize", s + 1)))
  8810. return soap->error;
  8811. }
  8812. }
  8813. else
  8814. { if (offset && soap_attribute(soap, "SOAP-ENC:offset", offset))
  8815. return soap->error;
  8816. if (soap_attribute(soap, "SOAP-ENC:arrayType", type))
  8817. return soap->error;
  8818. }
  8819. #ifndef WITH_LEAN
  8820. if ((soap->mode & SOAP_XML_CANONICAL))
  8821. { const char *s = strchr(type, ':');
  8822. if (s)
  8823. soap_utilize_ns(soap, type, s - type);
  8824. }
  8825. #endif
  8826. return soap_element_start_end_out(soap, NULL);
  8827. }
  8828. #endif
  8829. /******************************************************************************/
  8830. #ifndef PALM_1
  8831. SOAP_FMAC1
  8832. int
  8833. SOAP_FMAC2
  8834. soap_element_start_end_out(struct soap *soap, const char *tag)
  8835. { register struct soap_attribute *tp;
  8836. #ifndef WITH_LEAN
  8837. if (soap->mode & SOAP_XML_CANONICAL)
  8838. { struct soap_nlist *np;
  8839. for (tp = soap->attributes; tp; tp = tp->next)
  8840. { if (tp->visible && tp->name)
  8841. { const char *s = strchr(tp->name, ':');
  8842. if (s)
  8843. soap_utilize_ns(soap, tp->name, s - tp->name);
  8844. }
  8845. }
  8846. for (np = soap->nlist; np; np = np->next)
  8847. { if (np->index == 1 && np->ns)
  8848. { sprintf(soap->tmpbuf, "xmlns:%s", np->id);
  8849. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enabling utilized binding (level=%u) %s='%s'\n", np->level, soap->tmpbuf, np->ns));
  8850. soap_set_attr(soap, soap->tmpbuf, np->ns, 1);
  8851. np->index = 2;
  8852. }
  8853. }
  8854. }
  8855. #endif
  8856. #ifdef WITH_DOM
  8857. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  8858. { register struct soap_dom_attribute **att;
  8859. att = &soap->dom->atts;
  8860. for (tp = soap->attributes; tp; tp = tp->next)
  8861. { if (tp->visible)
  8862. { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
  8863. if (!*att)
  8864. return soap->error;
  8865. (*att)->next = NULL;
  8866. (*att)->nstr = NULL;
  8867. (*att)->name = soap_strdup(soap, tp->name);
  8868. (*att)->data = soap_strdup(soap, tp->value);
  8869. (*att)->wide = NULL;
  8870. (*att)->soap = soap;
  8871. att = &(*att)->next;
  8872. tp->visible = 0;
  8873. }
  8874. }
  8875. return SOAP_OK;
  8876. }
  8877. #endif
  8878. for (tp = soap->attributes; tp; tp = tp->next)
  8879. { if (tp->visible)
  8880. {
  8881. #ifndef WITH_LEAN
  8882. const char *s;
  8883. if ((soap->mode & SOAP_XML_DEFAULTNS) && (s = strchr(tp->name, ':')))
  8884. { size_t n = s - tp->name;
  8885. if (soap->nlist && !strncmp(soap->nlist->id, tp->name, n) && !soap->nlist->id[n])
  8886. s++;
  8887. else
  8888. s = tp->name;
  8889. if (soap_send(soap, " ") || soap_send(soap, s))
  8890. return soap->error;
  8891. }
  8892. else
  8893. #endif
  8894. if (soap_send(soap, " ") || soap_send(soap, tp->name))
  8895. return soap->error;
  8896. if (tp->visible == 2 && tp->value)
  8897. if (soap_send_raw(soap, "=\"", 2)
  8898. || soap_string_out(soap, tp->value, tp->flag)
  8899. || soap_send_raw(soap, "\"", 1))
  8900. return soap->error;
  8901. tp->visible = 0;
  8902. }
  8903. }
  8904. if (tag)
  8905. {
  8906. #ifndef WITH_LEAN
  8907. if (soap->mode & SOAP_XML_CANONICAL)
  8908. { if (soap_send_raw(soap, ">", 1)
  8909. || soap_element_end_out(soap, tag))
  8910. return soap->error;
  8911. return SOAP_OK;
  8912. }
  8913. #endif
  8914. soap->level--; /* decrement level just before /> */
  8915. if (soap_send_raw(soap, "/>", 2))
  8916. return soap->error;
  8917. return SOAP_OK;
  8918. }
  8919. return soap_send_raw(soap, ">", 1);
  8920. }
  8921. #endif
  8922. /******************************************************************************/
  8923. #ifndef PALM_1
  8924. SOAP_FMAC1
  8925. int
  8926. SOAP_FMAC2
  8927. soap_element_end_out(struct soap *soap, const char *tag)
  8928. {
  8929. #ifndef WITH_LEAN
  8930. const char *s;
  8931. #endif
  8932. if (*tag == '-')
  8933. return SOAP_OK;
  8934. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element ending tag='%s'\n", tag));
  8935. #ifdef WITH_DOM
  8936. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  8937. { if (soap->dom->prnt)
  8938. soap->dom = soap->dom->prnt;
  8939. return SOAP_OK;
  8940. }
  8941. #endif
  8942. #ifndef WITH_LEAN
  8943. if (soap->mode & SOAP_XML_CANONICAL)
  8944. soap_pop_namespace(soap);
  8945. if (soap->mode & SOAP_XML_INDENT)
  8946. { if (!soap->body)
  8947. { if (soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1))
  8948. return soap->error;
  8949. }
  8950. soap->body = 0;
  8951. }
  8952. if ((soap->mode & SOAP_XML_DEFAULTNS) && (s = strchr(tag, ':')))
  8953. { soap_pop_namespace(soap);
  8954. tag = s + 1;
  8955. }
  8956. #endif
  8957. if (soap_send_raw(soap, "</", 2)
  8958. || soap_send(soap, tag))
  8959. return soap->error;
  8960. soap->level--; /* decrement level just before > */
  8961. return soap_send_raw(soap, ">", 1);
  8962. }
  8963. #endif
  8964. /******************************************************************************/
  8965. #ifndef PALM_1
  8966. SOAP_FMAC1
  8967. int
  8968. SOAP_FMAC2
  8969. soap_element_ref(struct soap *soap, const char *tag, int id, int href)
  8970. { register int n = 0;
  8971. const char *s = "href";
  8972. if (soap->version == 2)
  8973. { s = "SOAP-ENC:ref";
  8974. n = 1;
  8975. }
  8976. sprintf(soap->href, "#_%d", href);
  8977. return soap_element_href(soap, tag, id, s, soap->href + n);
  8978. }
  8979. #endif
  8980. /******************************************************************************/
  8981. #ifndef PALM_1
  8982. SOAP_FMAC1
  8983. int
  8984. SOAP_FMAC2
  8985. soap_element_href(struct soap *soap, const char *tag, int id, const char *ref, const char *val)
  8986. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element '%s' reference %s='%s'\n", tag, ref, val));
  8987. if (soap_element(soap, tag, id, NULL)
  8988. || soap_attribute(soap, ref, val)
  8989. || soap_element_start_end_out(soap, tag))
  8990. return soap->error;
  8991. return SOAP_OK;
  8992. }
  8993. #endif
  8994. /******************************************************************************/
  8995. #ifndef PALM_1
  8996. SOAP_FMAC1
  8997. int
  8998. SOAP_FMAC2
  8999. soap_element_null(struct soap *soap, const char *tag, int id, const char *type)
  9000. { struct soap_attribute *tp;
  9001. for (tp = soap->attributes; tp; tp = tp->next)
  9002. if (tp->visible)
  9003. break;
  9004. if (tp || (soap->version == 2 && soap->position > 0) || id > 0 || (soap->mode & SOAP_XML_NIL))
  9005. { if (soap_element(soap, tag, id, type))
  9006. return soap->error;
  9007. if (!tp && soap_attribute(soap, "xsi:nil", "true"))
  9008. return soap->error;
  9009. return soap_element_start_end_out(soap, tag);
  9010. }
  9011. soap->null = 1;
  9012. soap->position = 0;
  9013. soap->mustUnderstand = 0;
  9014. return SOAP_OK;
  9015. }
  9016. #endif
  9017. /******************************************************************************/
  9018. #ifndef PALM_1
  9019. SOAP_FMAC1
  9020. int
  9021. SOAP_FMAC2
  9022. soap_element_id(struct soap *soap, const char *tag, int id, const void *p, const struct soap_array *a, int n, const char *type, int t)
  9023. { if (!p)
  9024. { soap_element_null(soap, tag, id, type);
  9025. return -1;
  9026. }
  9027. #ifndef WITH_NOIDREF
  9028. if (soap->mode & SOAP_XML_TREE)
  9029. return 0;
  9030. if (id < 0)
  9031. { struct soap_plist *pp;
  9032. if (a)
  9033. id = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
  9034. else
  9035. id = soap_pointer_lookup(soap, p, t, &pp);
  9036. if (id)
  9037. { if (soap_is_embedded(soap, pp))
  9038. { soap_element_ref(soap, tag, 0, id);
  9039. return -1;
  9040. }
  9041. if (soap_is_single(soap, pp))
  9042. return 0;
  9043. soap_set_embedded(soap, pp);
  9044. }
  9045. }
  9046. return id;
  9047. #else
  9048. return 0;
  9049. #endif
  9050. }
  9051. #endif
  9052. /******************************************************************************/
  9053. #ifndef PALM_1
  9054. SOAP_FMAC1
  9055. int
  9056. SOAP_FMAC2
  9057. soap_element_result(struct soap *soap, const char *tag)
  9058. { if (soap->version == 2 && soap->encodingStyle)
  9059. { if (soap_element(soap, "SOAP-RPC:result", 0, NULL)
  9060. || soap_attribute(soap, "xmlns:SOAP-RPC", soap_rpc)
  9061. || soap_element_start_end_out(soap, NULL)
  9062. || soap_string_out(soap, tag, 0)
  9063. || soap_element_end_out(soap, "SOAP-RPC:result"))
  9064. return soap->error;
  9065. }
  9066. return SOAP_OK;
  9067. }
  9068. #endif
  9069. /******************************************************************************/
  9070. #ifndef PALM_1
  9071. SOAP_FMAC1
  9072. void
  9073. SOAP_FMAC2
  9074. soap_check_result(struct soap *soap, const char *tag)
  9075. { if (soap->version == 2 && soap->encodingStyle)
  9076. { soap_instring(soap, ":result", NULL, NULL, 0, 2, -1, -1);
  9077. /* just ignore content for compliance reasons, but should compare tag to element's QName value? */
  9078. }
  9079. }
  9080. #endif
  9081. /******************************************************************************/
  9082. #ifndef PALM_2
  9083. SOAP_FMAC1
  9084. int
  9085. SOAP_FMAC2
  9086. soap_attribute(struct soap *soap, const char *name, const char *value)
  9087. {
  9088. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attribute '%s'='%s'\n", name, value));
  9089. #ifdef WITH_DOM
  9090. if ((soap->mode & SOAP_XML_DOM) && !(soap->mode & SOAP_XML_CANONICAL) && soap->dom)
  9091. { register struct soap_dom_attribute *a = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
  9092. if (!a)
  9093. return soap->error;
  9094. a->next = soap->dom->atts;
  9095. a->nstr = NULL;
  9096. a->name = soap_strdup(soap, name);
  9097. a->data = soap_strdup(soap, value);
  9098. a->wide = NULL;
  9099. a->soap = soap;
  9100. soap->dom->atts = a;
  9101. return SOAP_OK;
  9102. }
  9103. #endif
  9104. #ifndef WITH_LEAN
  9105. if (soap->mode & SOAP_XML_CANONICAL)
  9106. { /* TODO: consider using this code to handle default namespace bindings
  9107. if (!strncmp(name, "xmlns", 5) && (name[5] == ':' || name[5] == '\0'))
  9108. { if (name[5] == ':')
  9109. soap_push_ns(soap, name + 6, value, 0);
  9110. else
  9111. soap_push_ns(soap, "", value, 0);
  9112. }
  9113. */
  9114. if (!strncmp(name, "xmlns:", 6))
  9115. soap_push_ns(soap, name + 6, value, 0);
  9116. else if (soap_set_attr(soap, name, value, 1))
  9117. return soap->error;
  9118. }
  9119. else
  9120. #endif
  9121. { if (soap_send(soap, " ") || soap_send(soap, name))
  9122. return soap->error;
  9123. if (value)
  9124. if (soap_send_raw(soap, "=\"", 2)
  9125. || soap_string_out(soap, value, 1)
  9126. || soap_send_raw(soap, "\"", 1))
  9127. return soap->error;
  9128. }
  9129. return SOAP_OK;
  9130. }
  9131. #endif
  9132. /******************************************************************************/
  9133. #ifndef PALM_2
  9134. SOAP_FMAC1
  9135. int
  9136. SOAP_FMAC2
  9137. soap_element_begin_in(struct soap *soap, const char *tag, int nillable, const char *type)
  9138. { if (!soap_peek_element(soap))
  9139. { if (soap->other)
  9140. return soap->error = SOAP_TAG_MISMATCH;
  9141. if (tag && *tag == '-')
  9142. return SOAP_OK;
  9143. if (!(soap->error = soap_match_tag(soap, soap->tag, tag)))
  9144. { soap->peeked = 0;
  9145. if (type && *soap->type && soap_match_tag(soap, soap->type, type))
  9146. return soap->error = SOAP_TYPE;
  9147. if (!nillable && soap->null && (soap->mode & SOAP_XML_STRICT))
  9148. return soap->error = SOAP_NULL;
  9149. if (soap->body)
  9150. soap->level++;
  9151. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:SOAP_STR_EOS ));
  9152. }
  9153. }
  9154. else if (soap->error == SOAP_NO_TAG && tag && *tag == '-')
  9155. soap->error = SOAP_OK;
  9156. return soap->error;
  9157. }
  9158. #endif
  9159. /******************************************************************************/
  9160. #ifndef PALM_2
  9161. SOAP_FMAC1
  9162. int
  9163. SOAP_FMAC2
  9164. soap_element_end_in(struct soap *soap, const char *tag)
  9165. { register soap_wchar c;
  9166. register char *s;
  9167. register int n = 0;
  9168. if (tag && *tag == '-')
  9169. return SOAP_OK;
  9170. if (soap->error == SOAP_NO_TAG)
  9171. soap->error = SOAP_OK;
  9172. #ifdef WITH_DOM
  9173. /* this whitespace or mixed content is not insignificant for DOM */
  9174. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  9175. { if (!soap->peeked && !soap_string_in(soap, 3, -1, -1))
  9176. return soap->error;
  9177. if (soap->dom->prnt)
  9178. soap->dom = soap->dom->prnt;
  9179. }
  9180. #endif
  9181. if (soap->peeked)
  9182. { if (*soap->tag)
  9183. n++;
  9184. soap->peeked = 0;
  9185. }
  9186. do
  9187. { while (((c = soap_get(soap)) != SOAP_TT))
  9188. { if ((int)c == EOF)
  9189. return soap->error = SOAP_EOF;
  9190. if (c == SOAP_LT)
  9191. n++;
  9192. else if (c == '/')
  9193. { c = soap_get(soap);
  9194. if (c == SOAP_GT)
  9195. n--;
  9196. else
  9197. soap_unget(soap, c);
  9198. }
  9199. }
  9200. } while (n--);
  9201. s = soap->tag;
  9202. n = sizeof(soap->tag);
  9203. while (soap_notblank(c = soap_get(soap)))
  9204. { if (--n > 0)
  9205. *s++ = (char)c;
  9206. }
  9207. *s = '\0';
  9208. if ((int)c == EOF)
  9209. return soap->error = SOAP_EOF;
  9210. while (soap_blank(c))
  9211. c = soap_get(soap);
  9212. if (c != SOAP_GT)
  9213. return soap->error = SOAP_SYNTAX_ERROR;
  9214. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:SOAP_STR_EOS));
  9215. #ifndef WITH_LEAN
  9216. if (tag && (soap->mode & SOAP_XML_STRICT))
  9217. { soap_pop_namespace(soap);
  9218. if (soap_match_tag(soap, soap->tag, tag))
  9219. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element tag name does not match\n"));
  9220. return soap->error = SOAP_SYNTAX_ERROR;
  9221. }
  9222. }
  9223. #endif
  9224. soap->level--;
  9225. return SOAP_OK;
  9226. }
  9227. #endif
  9228. /******************************************************************************/
  9229. #ifndef PALM_2
  9230. SOAP_FMAC1
  9231. const char *
  9232. SOAP_FMAC2
  9233. soap_attr_value(struct soap *soap, const char *name, int flag)
  9234. { register struct soap_attribute *tp;
  9235. if (*name == '-')
  9236. return SOAP_STR_EOS;
  9237. for (tp = soap->attributes; tp; tp = tp->next)
  9238. { if (tp->visible && !soap_match_tag(soap, tp->name, name))
  9239. break;
  9240. }
  9241. if (tp)
  9242. { if (flag == 2 && (soap->mode & SOAP_XML_STRICT))
  9243. soap->error = SOAP_PROHIBITED;
  9244. else
  9245. return tp->value;
  9246. }
  9247. else if (flag == 1 && (soap->mode & SOAP_XML_STRICT))
  9248. soap->error = SOAP_REQUIRED;
  9249. else
  9250. soap->error = SOAP_OK;
  9251. return NULL;
  9252. }
  9253. #endif
  9254. /******************************************************************************/
  9255. #ifndef PALM_2
  9256. SOAP_FMAC1
  9257. int
  9258. SOAP_FMAC2
  9259. soap_set_attr(struct soap *soap, const char *name, const char *value, int flag)
  9260. { register struct soap_attribute *tp;
  9261. if (*name == '-')
  9262. return SOAP_OK;
  9263. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set attribute %s='%s'\n", name, value?value:SOAP_STR_EOS));
  9264. for (tp = soap->attributes; tp; tp = tp->next)
  9265. { if (!strcmp(tp->name, name))
  9266. break;
  9267. }
  9268. if (!tp)
  9269. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute %s\n", name));
  9270. if (!(tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(name))))
  9271. return soap->error = SOAP_EOM;
  9272. tp->ns = NULL;
  9273. #ifndef WITH_LEAN
  9274. if ((soap->mode & SOAP_XML_CANONICAL))
  9275. { struct soap_attribute **tpp = &soap->attributes;
  9276. const char *s = strchr(name, ':');
  9277. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inserting attribute %s for c14n\n", name))
  9278. if (!strncmp(name, "xmlns", 5))
  9279. { for (; *tpp; tpp = &(*tpp)->next)
  9280. if (strncmp((*tpp)->name, "xmlns", 5) || strcmp((*tpp)->name + 5, name + 5) > 0)
  9281. break;
  9282. }
  9283. else if (!s)
  9284. { for (; *tpp; tpp = &(*tpp)->next)
  9285. if (strncmp((*tpp)->name, "xmlns", 5) && ((*tpp)->ns || strcmp((*tpp)->name, name) > 0))
  9286. break;
  9287. }
  9288. else
  9289. { int k;
  9290. for (; *tpp; tpp = &(*tpp)->next)
  9291. { if (!strncmp((*tpp)->name, "xmlns:", 6) && !strncmp((*tpp)->name + 6, name, s - name) && !(*tpp)->name[6 + s - name])
  9292. { if (!tp->ns)
  9293. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Canonicalization: prefix %s=%p (%s)\n", name, (*tpp)->ns, (*tpp)->ns));
  9294. tp->ns = (*tpp)->ns;
  9295. }
  9296. }
  9297. else if (strncmp((*tpp)->name, "xmlns", 5) && (*tpp)->ns && tp->ns && ((k = strcmp((*tpp)->ns, tp->ns)) > 0 || (!k && strcmp((*tpp)->name, name) > 0)))
  9298. break;
  9299. }
  9300. }
  9301. tp->next = *tpp;
  9302. *tpp = tp;
  9303. }
  9304. else
  9305. #endif
  9306. { tp->next = soap->attributes;
  9307. soap->attributes = tp;
  9308. }
  9309. strcpy(tp->name, name);
  9310. tp->value = NULL;
  9311. }
  9312. else if (tp->visible)
  9313. { return SOAP_OK;
  9314. }
  9315. else if (value && tp->value && tp->size <= strlen(value))
  9316. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute value of %s (free %p)\n", name, tp->value));
  9317. SOAP_FREE(soap, tp->value);
  9318. tp->value = NULL;
  9319. tp->ns = NULL;
  9320. }
  9321. if (value)
  9322. { if (!tp->value)
  9323. { tp->size = strlen(value) + 1;
  9324. if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size)))
  9325. return soap->error = SOAP_EOM;
  9326. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute value for %s (%p)\n", tp->name, tp->value));
  9327. }
  9328. strcpy(tp->value, value);
  9329. if (!strncmp(tp->name, "xmlns:", 6))
  9330. tp->ns = tp->value;
  9331. tp->visible = 2;
  9332. tp->flag = flag;
  9333. #ifndef WITH_LEAN
  9334. if (soap->part != SOAP_IN_SECURITY && !strcmp(name, "wsu:Id"))
  9335. { soap->part = SOAP_BEGIN_SECURITY;
  9336. strncpy(soap->id, value, sizeof(soap->id));
  9337. soap->id[sizeof(soap->id)-1] = '\0';
  9338. }
  9339. #endif
  9340. }
  9341. else
  9342. tp->visible = 1;
  9343. return SOAP_OK;
  9344. }
  9345. #endif
  9346. /******************************************************************************/
  9347. #ifndef PALM_2
  9348. SOAP_FMAC1
  9349. void
  9350. SOAP_FMAC2
  9351. soap_clr_attr(struct soap *soap)
  9352. { register struct soap_attribute *tp;
  9353. #ifndef WITH_LEAN
  9354. if ((soap->mode & SOAP_XML_CANONICAL))
  9355. { while (soap->attributes)
  9356. { tp = soap->attributes->next;
  9357. if (soap->attributes->value)
  9358. SOAP_FREE(soap, soap->attributes->value);
  9359. SOAP_FREE(soap, soap->attributes);
  9360. soap->attributes = tp;
  9361. }
  9362. }
  9363. else
  9364. #endif
  9365. { for (tp = soap->attributes; tp; tp = tp->next)
  9366. tp->visible = 0;
  9367. }
  9368. }
  9369. #endif
  9370. /******************************************************************************/
  9371. #ifndef PALM_2
  9372. static int
  9373. soap_getattrval(struct soap *soap, char *s, size_t n, soap_wchar d)
  9374. { register size_t i;
  9375. for (i = 0; i < n; i++)
  9376. { register soap_wchar c = soap_get(soap);
  9377. switch (c)
  9378. {
  9379. case SOAP_TT:
  9380. *s++ = '<';
  9381. soap_unget(soap, '/');
  9382. break;
  9383. case SOAP_LT:
  9384. *s++ = '<';
  9385. break;
  9386. case SOAP_GT:
  9387. if (d == ' ')
  9388. { soap_unget(soap, c);
  9389. *s = '\0';
  9390. return SOAP_OK;
  9391. }
  9392. *s++ = '>';
  9393. break;
  9394. case SOAP_QT:
  9395. if (c == d)
  9396. { *s = '\0';
  9397. return SOAP_OK;
  9398. }
  9399. *s++ = '"';
  9400. break;
  9401. case SOAP_AP:
  9402. if (c == d)
  9403. { *s = '\0';
  9404. return SOAP_OK;
  9405. }
  9406. *s++ = '\'';
  9407. break;
  9408. case '\t':
  9409. case '\n':
  9410. case '\r':
  9411. case ' ':
  9412. case '/':
  9413. if (d == ' ')
  9414. { soap_unget(soap, c);
  9415. *s = '\0';
  9416. return SOAP_OK;
  9417. }
  9418. default:
  9419. if ((int)c == EOF)
  9420. return soap->error = SOAP_EOF;
  9421. *s++ = (char)c;
  9422. }
  9423. }
  9424. return soap->error = SOAP_EOM;
  9425. }
  9426. #endif
  9427. /******************************************************************************/
  9428. #ifdef WITH_FAST
  9429. #ifndef PALM_2
  9430. SOAP_FMAC1
  9431. int
  9432. SOAP_FMAC2
  9433. soap_store_lab(struct soap *soap, const char *s, size_t n)
  9434. { soap->labidx = 0;
  9435. return soap_append_lab(soap, s, n);
  9436. }
  9437. #endif
  9438. #endif
  9439. /******************************************************************************/
  9440. #ifdef WITH_FAST
  9441. #ifndef PALM_2
  9442. SOAP_FMAC1
  9443. int
  9444. SOAP_FMAC2
  9445. soap_append_lab(struct soap *soap, const char *s, size_t n)
  9446. { if (soap->labidx + n >= soap->lablen)
  9447. { register char *t = soap->labbuf;
  9448. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enlarging look-aside buffer to append data, old size=%lu", (unsigned long)soap->lablen));
  9449. if (soap->lablen == 0)
  9450. soap->lablen = SOAP_LABLEN;
  9451. while (soap->labidx + n >= soap->lablen)
  9452. soap->lablen <<= 1;
  9453. DBGLOG(TEST, SOAP_MESSAGE(fdebug, ", new size=%lu\n", (unsigned long)soap->lablen));
  9454. soap->labbuf = (char*)SOAP_MALLOC(soap, soap->lablen);
  9455. if (!soap->labbuf)
  9456. { if (t)
  9457. SOAP_FREE(soap, t);
  9458. return soap->error = SOAP_EOM;
  9459. }
  9460. if (t)
  9461. { memcpy(soap->labbuf, t, soap->labidx);
  9462. SOAP_FREE(soap, t);
  9463. }
  9464. }
  9465. if (s)
  9466. { memcpy(soap->labbuf + soap->labidx, s, n);
  9467. soap->labidx += n;
  9468. }
  9469. return SOAP_OK;
  9470. }
  9471. #endif
  9472. #endif
  9473. /******************************************************************************/
  9474. #ifndef PALM_2
  9475. SOAP_FMAC1
  9476. int
  9477. SOAP_FMAC2
  9478. soap_peek_element(struct soap *soap)
  9479. {
  9480. #ifdef WITH_DOM
  9481. register struct soap_dom_attribute **att = NULL;
  9482. register char *lead = NULL;
  9483. #endif
  9484. register struct soap_attribute *tp, *tq = NULL;
  9485. register const char *t;
  9486. register char *s;
  9487. register soap_wchar c;
  9488. register int i;
  9489. if (soap->peeked)
  9490. { if (!*soap->tag)
  9491. return soap->error = SOAP_NO_TAG;
  9492. return SOAP_OK;
  9493. }
  9494. soap->peeked = 1;
  9495. soap->id[0] = '\0';
  9496. soap->href[0] = '\0';
  9497. soap->type[0] = '\0';
  9498. soap->arrayType[0] = '\0';
  9499. soap->arraySize[0] = '\0';
  9500. soap->arrayOffset[0] = '\0';
  9501. soap->other = 0;
  9502. soap->root = -1;
  9503. soap->position = 0;
  9504. soap->null = 0;
  9505. soap->mustUnderstand = 0;
  9506. /* skip BOM */
  9507. if ((c = soap_getchar(soap)) != 0xEF || (c = soap_get1(soap)) != 0xBB || (c = soap_get1(soap)) != 0xBF)
  9508. soap_unget(soap, c);
  9509. c = soap_get(soap);
  9510. #ifdef WITH_DOM
  9511. /* whitespace leading to start tag is not insignificant for DOM */
  9512. if (soap_blank(c))
  9513. { soap->labidx = 0;
  9514. do
  9515. { if (soap_append_lab(soap, NULL, 0))
  9516. return soap->error;
  9517. s = soap->labbuf + soap->labidx;
  9518. i = soap->lablen - soap->labidx;
  9519. soap->labidx = soap->lablen;
  9520. while (soap_blank(c) && i--)
  9521. { *s++ = c;
  9522. c = soap_get(soap);
  9523. }
  9524. }
  9525. while (soap_blank(c));
  9526. *s = '\0';
  9527. if (*soap->labbuf)
  9528. lead = soap->labbuf;
  9529. }
  9530. #else
  9531. /* skip space */
  9532. while (soap_blank(c))
  9533. c = soap_get(soap);
  9534. #endif
  9535. if (c != SOAP_LT)
  9536. { *soap->tag = '\0';
  9537. if ((int)c == EOF)
  9538. return soap->error = SOAP_EOF;
  9539. soap_unget(soap, c);
  9540. #ifdef WITH_DOM
  9541. /* whitespace leading to end tag is not insignificant for DOM */
  9542. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  9543. soap->dom->tail = soap_strdup(soap, lead);
  9544. #endif
  9545. return soap->error = SOAP_NO_TAG;
  9546. }
  9547. s = soap->tag;
  9548. do c = soap_get1(soap);
  9549. while (soap_blank(c));
  9550. i = sizeof(soap->tag);
  9551. while (c != '>' && c != '/' && soap_notblank(c) && (int)c != EOF)
  9552. { if (--i > 0)
  9553. *s++ = (char)c;
  9554. c = soap_get1(soap);
  9555. }
  9556. while (soap_blank(c))
  9557. c = soap_get1(soap);
  9558. *s = '\0';
  9559. #ifdef WITH_DOM
  9560. if (soap->mode & SOAP_XML_DOM)
  9561. { register struct soap_dom_element *elt;
  9562. elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element));
  9563. if (!elt)
  9564. return soap->error;
  9565. elt->next = NULL;
  9566. elt->nstr = NULL;
  9567. elt->name = soap_strdup(soap, soap->tag);
  9568. elt->prnt = soap->dom;
  9569. elt->elts = NULL;
  9570. elt->atts = NULL;
  9571. elt->data = NULL;
  9572. elt->wide = NULL;
  9573. elt->type = 0;
  9574. elt->node = NULL;
  9575. elt->head = soap_strdup(soap, lead);
  9576. elt->tail = NULL;
  9577. elt->soap = soap;
  9578. if (soap->dom)
  9579. { struct soap_dom_element *p = soap->dom->elts;
  9580. if (p)
  9581. { while (p->next)
  9582. p = p->next;
  9583. p->next = elt;
  9584. }
  9585. else
  9586. soap->dom->elts = elt;
  9587. }
  9588. soap->dom = elt;
  9589. att = &elt->atts;
  9590. }
  9591. #endif
  9592. soap_pop_namespace(soap);
  9593. for (tp = soap->attributes; tp; tp = tp->next)
  9594. tp->visible = 0;
  9595. while ((int)c != EOF && c != '>' && c != '/')
  9596. { s = soap->tmpbuf;
  9597. i = sizeof(soap->tmpbuf);
  9598. while (c != '=' && c != '>' && c != '/' && soap_notblank(c) && (int)c != EOF)
  9599. { if (--i > 0)
  9600. *s++ = (char)c;
  9601. c = soap_get1(soap);
  9602. }
  9603. *s = '\0';
  9604. if (i == sizeof(soap->tmpbuf))
  9605. return soap->error = SOAP_SYNTAX_ERROR;
  9606. #ifdef WITH_DOM
  9607. /* add attribute name to dom */
  9608. if (att)
  9609. { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
  9610. if (!*att)
  9611. return soap->error;
  9612. (*att)->next = NULL;
  9613. (*att)->nstr = NULL;
  9614. (*att)->name = soap_strdup(soap, soap->tmpbuf);
  9615. (*att)->data = NULL;
  9616. (*att)->wide = NULL;
  9617. (*att)->soap = soap;
  9618. }
  9619. #endif
  9620. if (!strncmp(soap->tmpbuf, "xmlns", 5))
  9621. { if (soap->tmpbuf[5] == ':')
  9622. t = soap->tmpbuf + 6;
  9623. else if (soap->tmpbuf[5])
  9624. t = NULL;
  9625. else
  9626. t = SOAP_STR_EOS;
  9627. }
  9628. else
  9629. t = NULL;
  9630. tq = NULL;
  9631. for (tp = soap->attributes; tp; tq = tp, tp = tp->next)
  9632. { if (!SOAP_STRCMP(tp->name, soap->tmpbuf))
  9633. break;
  9634. }
  9635. if (!tp)
  9636. { tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(soap->tmpbuf));
  9637. if (!tp)
  9638. return soap->error = SOAP_EOM;
  9639. strcpy(tp->name, soap->tmpbuf);
  9640. tp->value = NULL;
  9641. tp->size = 0;
  9642. /* if attribute name is qualified, append it to the end of the list */
  9643. if (tq && strchr(soap->tmpbuf, ':'))
  9644. { tq->next = tp;
  9645. tp->next = NULL;
  9646. }
  9647. else
  9648. { tp->next = soap->attributes;
  9649. soap->attributes = tp;
  9650. }
  9651. }
  9652. while (soap_blank(c))
  9653. c = soap_get1(soap);
  9654. if (c == '=')
  9655. { do c = soap_getutf8(soap);
  9656. while (soap_blank(c));
  9657. if (c != SOAP_QT && c != SOAP_AP)
  9658. { soap_unget(soap, c);
  9659. c = ' '; /* blank delimiter */
  9660. }
  9661. if (soap_getattrval(soap, tp->value, tp->size, c))
  9662. {
  9663. #ifdef WITH_FAST
  9664. if (soap->error != SOAP_EOM)
  9665. return soap->error;
  9666. soap->error = SOAP_OK;
  9667. if (soap_store_lab(soap, tp->value, tp->size))
  9668. return soap->error;
  9669. if (tp->value)
  9670. SOAP_FREE(soap, tp->value);
  9671. for (;;)
  9672. { if (soap_getattrval(soap, soap->labbuf + soap->labidx, soap->lablen - soap->labidx, c))
  9673. { if (soap->error != SOAP_EOM)
  9674. return soap->error;
  9675. soap->error = SOAP_OK;
  9676. soap->labidx = soap->lablen;
  9677. if (soap_append_lab(soap, NULL, 0))
  9678. return soap->error;
  9679. }
  9680. else
  9681. break;
  9682. }
  9683. if (soap->labidx)
  9684. tp->size = soap->lablen;
  9685. else
  9686. { tp->size = strlen(soap->labbuf) + 1;
  9687. if (tp->size < SOAP_LABLEN)
  9688. tp->size = SOAP_LABLEN;
  9689. }
  9690. if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size)))
  9691. return soap->error = SOAP_EOM;
  9692. strcpy(tp->value, soap->labbuf);
  9693. #else
  9694. size_t n;
  9695. if (soap->error != SOAP_EOM)
  9696. return soap->error;
  9697. soap->error = SOAP_OK;
  9698. if (soap_new_block(soap) == NULL)
  9699. return soap->error;
  9700. for (;;)
  9701. { if (!(s = (char*)soap_push_block(soap, NULL, SOAP_BLKLEN)))
  9702. return soap->error;
  9703. if (soap_getattrval(soap, s, SOAP_BLKLEN, c))
  9704. { if (soap->error != SOAP_EOM)
  9705. return soap->error;
  9706. soap->error = SOAP_OK;
  9707. }
  9708. else
  9709. break;
  9710. }
  9711. n = tp->size + soap->blist->size;
  9712. if (!(s = (char*)SOAP_MALLOC(soap, n)))
  9713. return soap->error = SOAP_EOM;
  9714. if (tp->value)
  9715. { memcpy(s, tp->value, tp->size);
  9716. SOAP_FREE(soap, tp->value);
  9717. }
  9718. soap_save_block(soap, NULL, s + tp->size, 0);
  9719. tp->value = s;
  9720. tp->size = n;
  9721. #endif
  9722. }
  9723. do c = soap_get1(soap);
  9724. while (soap_blank(c));
  9725. tp->visible = 2; /* seen this attribute w/ value */
  9726. #ifdef WITH_DOM
  9727. if (att)
  9728. (*att)->data = soap_strdup(soap, tp->value);
  9729. #endif
  9730. }
  9731. else
  9732. tp->visible = 1; /* seen this attribute w/o value */
  9733. #ifdef WITH_DOM
  9734. if (att)
  9735. att = &(*att)->next;
  9736. #endif
  9737. if (t && tp->value)
  9738. { if (soap_push_namespace(soap, t, tp->value) == NULL)
  9739. return soap->error;
  9740. }
  9741. }
  9742. #ifdef WITH_DOM
  9743. if (att)
  9744. { soap->dom->nstr = soap_current_namespace(soap, soap->tag);
  9745. for (att = &soap->dom->atts; *att; att = &(*att)->next)
  9746. (*att)->nstr = soap_current_namespace(soap, (*att)->name);
  9747. }
  9748. #endif
  9749. if ((int)c == EOF)
  9750. return soap->error = SOAP_EOF;
  9751. if (!(soap->body = (c != '/')))
  9752. do c = soap_get1(soap);
  9753. while (soap_blank(c));
  9754. #ifdef WITH_DOM
  9755. if (soap->mode & SOAP_XML_DOM)
  9756. { if (!soap->body && soap->dom->prnt)
  9757. soap->dom = soap->dom->prnt;
  9758. }
  9759. #endif
  9760. for (tp = soap->attributes; tp; tp = tp->next)
  9761. { if (tp->visible && tp->value)
  9762. {
  9763. #ifndef WITH_NOIDREF
  9764. if (!strcmp(tp->name, "id"))
  9765. { if ((soap->version > 0 && !(soap->mode & SOAP_XML_TREE))
  9766. || (soap->mode & SOAP_XML_GRAPH))
  9767. { *soap->id = '#';
  9768. strncpy(soap->id + 1, tp->value, sizeof(soap->id) - 2);
  9769. soap->id[sizeof(soap->id)-1] = '\0';
  9770. }
  9771. }
  9772. else if (!strcmp(tp->name, "href"))
  9773. { if (soap->version == 1
  9774. || (soap->mode & SOAP_XML_GRAPH)
  9775. || (soap->mode & SOAP_ENC_MTOM)
  9776. || (soap->mode & SOAP_ENC_DIME))
  9777. { strncpy(soap->href, tp->value, sizeof(soap->href) - 1);
  9778. soap->href[sizeof(soap->href)-1] = '\0';
  9779. }
  9780. }
  9781. else
  9782. #endif
  9783. if (!soap_match_tag(soap, tp->name, "xsi:type"))
  9784. { strncpy(soap->type, tp->value, sizeof(soap->type) - 1);
  9785. soap->type[sizeof(soap->type)-1] = '\0';
  9786. }
  9787. else if ((!soap_match_tag(soap, tp->name, "xsi:null")
  9788. || !soap_match_tag(soap, tp->name, "xsi:nil"))
  9789. && (!strcmp(tp->value, "1")
  9790. || !strcmp(tp->value, "true")))
  9791. { soap->null = 1;
  9792. }
  9793. else if (soap->version == 1)
  9794. { if (!soap_match_tag(soap, tp->name, "SOAP-ENC:arrayType"))
  9795. { s = soap_strrchr(tp->value, '[');
  9796. if (s && (size_t)(s - tp->value) < sizeof(soap->arrayType))
  9797. { strncpy(soap->arrayType, tp->value, s - tp->value);
  9798. soap->arrayType[s - tp->value] = '\0';
  9799. strncpy(soap->arraySize, s, sizeof(soap->arraySize) - 1);
  9800. }
  9801. else
  9802. strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1);
  9803. soap->arraySize[sizeof(soap->arrayType)-1] = '\0';
  9804. soap->arrayType[sizeof(soap->arrayType)-1] = '\0';
  9805. }
  9806. else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:offset"))
  9807. strncpy(soap->arrayOffset, tp->value, sizeof(soap->arrayOffset));
  9808. else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:position"))
  9809. soap->position = soap_getposition(tp->value, soap->positions);
  9810. else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:root"))
  9811. soap->root = ((!strcmp(tp->value, "1") || !strcmp(tp->value, "true")));
  9812. else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand")
  9813. && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true")))
  9814. soap->mustUnderstand = 1;
  9815. else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:actor"))
  9816. { if ((!soap->actor || strcmp(soap->actor, tp->value))
  9817. && strcmp(tp->value, "http://schemas.xmlsoap.org/soap/actor/next"))
  9818. soap->other = 1;
  9819. }
  9820. }
  9821. else if (soap->version == 2)
  9822. {
  9823. #ifndef WITH_NOIDREF
  9824. if (!strcmp(tp->name, "ref")
  9825. || !soap_match_tag(soap, tp->name, "SOAP-ENC:ref"))
  9826. { *soap->href = '#';
  9827. strncpy(soap->href + 1, tp->value, sizeof(soap->href) - 2);
  9828. soap->href[sizeof(soap->href)-1] = '\0';
  9829. }
  9830. else
  9831. #endif
  9832. if (!soap_match_tag(soap, tp->name, "SOAP-ENC:itemType"))
  9833. strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1);
  9834. else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:arraySize"))
  9835. strncpy(soap->arraySize, tp->value, sizeof(soap->arraySize) - 1);
  9836. else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand")
  9837. && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true")))
  9838. soap->mustUnderstand = 1;
  9839. else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:role"))
  9840. { if ((!soap->actor || strcmp(soap->actor, tp->value))
  9841. && strcmp(tp->value, "http://www.w3.org/2003/05/soap-envelope/role/next"))
  9842. soap->other = 1;
  9843. }
  9844. }
  9845. else
  9846. { if (!soap_match_tag(soap, tp->name, "wsdl:required") && !strcmp(tp->value, "true"))
  9847. soap->mustUnderstand = 1;
  9848. }
  9849. }
  9850. }
  9851. return soap->error = SOAP_OK;
  9852. }
  9853. #endif
  9854. /******************************************************************************/
  9855. #ifndef PALM_2
  9856. SOAP_FMAC1
  9857. void
  9858. SOAP_FMAC2
  9859. soap_retry(struct soap *soap)
  9860. { soap->error = SOAP_OK;
  9861. soap_revert(soap);
  9862. }
  9863. #endif
  9864. /******************************************************************************/
  9865. #ifndef PALM_2
  9866. SOAP_FMAC1
  9867. void
  9868. SOAP_FMAC2
  9869. soap_revert(struct soap *soap)
  9870. { if (!soap->peeked)
  9871. { soap->peeked = 1;
  9872. if (soap->body)
  9873. soap->level--;
  9874. }
  9875. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reverting last element (level=%u)\n", soap->level));
  9876. }
  9877. #endif
  9878. /******************************************************************************/
  9879. #ifndef PALM_2
  9880. SOAP_FMAC1
  9881. int
  9882. SOAP_FMAC2
  9883. soap_string_out(struct soap *soap, const char *s, int flag)
  9884. { register const char *t;
  9885. register soap_wchar c;
  9886. register soap_wchar mask = (soap_wchar)0xFFFFFF80UL;
  9887. #ifdef WITH_DOM
  9888. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  9889. { soap->dom->data = soap_strdup(soap, s);
  9890. return SOAP_OK;
  9891. }
  9892. #endif
  9893. if (flag == 2 || soap->mode & SOAP_C_UTFSTRING)
  9894. mask = 0;
  9895. t = s;
  9896. while ((c = *t++))
  9897. { switch (c)
  9898. {
  9899. case 0x09:
  9900. if (flag)
  9901. { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&#x9;", 5))
  9902. return soap->error;
  9903. s = t;
  9904. }
  9905. break;
  9906. case 0x0A:
  9907. if (flag || !(soap->mode & SOAP_XML_CANONICAL))
  9908. { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&#xA;", 5))
  9909. return soap->error;
  9910. s = t;
  9911. }
  9912. break;
  9913. case 0x0D:
  9914. if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&#xD;", 5))
  9915. return soap->error;
  9916. s = t;
  9917. break;
  9918. case '&':
  9919. if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&amp;", 5))
  9920. return soap->error;
  9921. s = t;
  9922. break;
  9923. case '<':
  9924. if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&lt;", 4))
  9925. return soap->error;
  9926. s = t;
  9927. break;
  9928. case '>':
  9929. if (!flag)
  9930. { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&gt;", 4))
  9931. return soap->error;
  9932. s = t;
  9933. }
  9934. break;
  9935. case '"':
  9936. if (flag)
  9937. { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&quot;", 6))
  9938. return soap->error;
  9939. s = t;
  9940. }
  9941. break;
  9942. default:
  9943. #ifndef WITH_LEANER
  9944. #ifdef HAVE_MBTOWC
  9945. if (soap->mode & SOAP_C_MBSTRING)
  9946. { wchar_t wc;
  9947. register int m = mbtowc(&wc, t - 1, MB_CUR_MAX);
  9948. if (m > 0 && wc != c)
  9949. { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, wc))
  9950. return soap->error;
  9951. s = t += m - 1;
  9952. continue;
  9953. }
  9954. }
  9955. #endif
  9956. #endif
  9957. #ifndef WITH_NOSTRINGTOUTF8
  9958. if ((c & mask) || !(c & 0xFFFFFFE0UL))
  9959. { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned char)c))
  9960. return soap->error;
  9961. s = t;
  9962. }
  9963. #endif
  9964. }
  9965. }
  9966. return soap_send_raw(soap, s, t - s - 1);
  9967. }
  9968. #endif
  9969. /******************************************************************************/
  9970. #ifndef PALM_2
  9971. SOAP_FMAC1
  9972. char *
  9973. SOAP_FMAC2
  9974. soap_string_in(struct soap *soap, int flag, long minlen, long maxlen)
  9975. { register char *s;
  9976. char *t = NULL;
  9977. register size_t i;
  9978. register long l = 0;
  9979. register int n = 0, f = 0, m = 0;
  9980. register soap_wchar c;
  9981. #if !defined(WITH_LEANER) && defined(HAVE_WCTOMB)
  9982. char buf[MB_LEN_MAX > 8 ? MB_LEN_MAX : 8];
  9983. #else
  9984. char buf[8];
  9985. #endif
  9986. DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading string content, flag=%d\n", flag));
  9987. if (soap->peeked && *soap->tag)
  9988. {
  9989. #ifndef WITH_LEAN
  9990. struct soap_attribute *tp;
  9991. DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String content includes tag '%s' and attributes\n", soap->tag));
  9992. t = soap->tmpbuf;
  9993. *t = '<';
  9994. t[sizeof(soap->tmpbuf)-1] = '\0';
  9995. strncpy(t + 1, soap->tag, sizeof(soap->tmpbuf) - 2);
  9996. t += strlen(t);
  9997. for (tp = soap->attributes; tp; tp = tp->next)
  9998. { if (tp->visible)
  9999. { if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2)
  10000. break;
  10001. *t++ = ' ';
  10002. strcpy(t, tp->name);
  10003. t += strlen(t);
  10004. if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2)
  10005. break; /* too many or large attribute values */
  10006. if (tp->value)
  10007. { *t++ = '=';
  10008. *t++ = '"';
  10009. strcpy(t, tp->value);
  10010. t += strlen(t);
  10011. *t++ = '"';
  10012. }
  10013. }
  10014. }
  10015. if (!soap->body)
  10016. *t++ = '/';
  10017. *t++ = '>';
  10018. *t = '\0';
  10019. t = soap->tmpbuf;
  10020. m = (int)strlen(soap->tmpbuf);
  10021. #endif
  10022. if (soap->body)
  10023. n = 1;
  10024. f = 1;
  10025. soap->peeked = 0;
  10026. }
  10027. #ifdef WITH_CDATA
  10028. if (!flag)
  10029. { register int state = 0;
  10030. #ifdef WITH_FAST
  10031. soap->labidx = 0; /* use look-aside buffer */
  10032. #else
  10033. if (soap_new_block(soap) == NULL)
  10034. return NULL;
  10035. #endif
  10036. for (;;)
  10037. {
  10038. #ifdef WITH_FAST
  10039. register size_t k;
  10040. if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */
  10041. return NULL;
  10042. s = soap->labbuf + soap->labidx; /* space to populate */
  10043. k = soap->lablen - soap->labidx; /* number of bytes available */
  10044. soap->labidx = soap->lablen; /* claim this space */
  10045. #else
  10046. register size_t k = SOAP_BLKLEN;
  10047. if (!(s = (char*)soap_push_block(soap, NULL, k)))
  10048. return NULL;
  10049. #endif
  10050. for (i = 0; i < k; i++)
  10051. { if (m > 0)
  10052. { *s++ = *t++; /* copy multibyte characters */
  10053. m--;
  10054. continue;
  10055. }
  10056. c = soap_getchar(soap);
  10057. if ((int)c == EOF)
  10058. goto end;
  10059. if (c >= 0x80 && state != 1 && !(soap->mode & SOAP_ENC_LATIN))
  10060. { soap_unget(soap, c);
  10061. c = soap_getutf8(soap);
  10062. if (soap->mode & SOAP_C_UTFSTRING)
  10063. { c &= 0x7FFFFFFF;
  10064. t = buf;
  10065. if (c < 0x0800)
  10066. *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
  10067. else
  10068. { if (c < 0x010000)
  10069. *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
  10070. else
  10071. { if (c < 0x200000)
  10072. *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
  10073. else
  10074. { if (c < 0x04000000)
  10075. *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
  10076. else
  10077. { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
  10078. *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
  10079. }
  10080. *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
  10081. }
  10082. *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
  10083. }
  10084. *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
  10085. }
  10086. *t++ = (char)(0x80 | (c & 0x3F));
  10087. m = (int)(t - buf) - 1;
  10088. t = buf;
  10089. *s++ = *t++;
  10090. continue;
  10091. }
  10092. }
  10093. switch (state)
  10094. { case 1:
  10095. if (c == ']')
  10096. state = 4;
  10097. *s++ = c;
  10098. continue;
  10099. case 2:
  10100. if (c == '-')
  10101. state = 6;
  10102. *s++ = c;
  10103. continue;
  10104. case 3:
  10105. if (c == '?')
  10106. state = 8;
  10107. *s++ = c;
  10108. continue;
  10109. /* CDATA */
  10110. case 4:
  10111. if (c == ']')
  10112. state = 5;
  10113. else
  10114. state = 1;
  10115. *s++ = c;
  10116. continue;
  10117. case 5:
  10118. if (c == '>')
  10119. state = 0;
  10120. else
  10121. state = 1;
  10122. *s++ = c;
  10123. continue;
  10124. /* comment */
  10125. case 6:
  10126. if (c == '-')
  10127. state = 7;
  10128. else
  10129. state = 2;
  10130. *s++ = c;
  10131. continue;
  10132. case 7:
  10133. if (c == '>')
  10134. state = 0;
  10135. else
  10136. state = 2;
  10137. *s++ = c;
  10138. continue;
  10139. /* PI */
  10140. case 8:
  10141. if (c == '>')
  10142. state = 0;
  10143. else
  10144. state = 3;
  10145. *s++ = c;
  10146. continue;
  10147. }
  10148. switch (c)
  10149. {
  10150. case SOAP_TT:
  10151. if (n == 0)
  10152. goto end;
  10153. n--;
  10154. *s++ = '<';
  10155. t = (char*)"/";
  10156. m = 1;
  10157. break;
  10158. case SOAP_LT:
  10159. if (f && n == 0)
  10160. goto end;
  10161. n++;
  10162. *s++ = '<';
  10163. break;
  10164. case '/':
  10165. if (n > 0)
  10166. { c = soap_getchar(soap);
  10167. if (c == '>')
  10168. n--;
  10169. soap_unget(soap, c);
  10170. }
  10171. *s++ = '/';
  10172. break;
  10173. case '<':
  10174. c = soap_getchar(soap);
  10175. if (c == '/')
  10176. { if (n == 0)
  10177. { c = SOAP_TT;
  10178. goto end;
  10179. }
  10180. n--;
  10181. }
  10182. else if (c == '!')
  10183. { c = soap_getchar(soap);
  10184. if (c == '[')
  10185. { do c = soap_getchar(soap);
  10186. while ((int)c != EOF && c != '[');
  10187. if ((int)c == EOF)
  10188. goto end;
  10189. t = (char*)"![CDATA[";
  10190. m = 8;
  10191. state = 1;
  10192. }
  10193. else if (c == '-')
  10194. { if ((c = soap_getchar(soap)) == '-')
  10195. state = 2;
  10196. t = (char*)"!-";
  10197. m = 2;
  10198. soap_unget(soap, c);
  10199. }
  10200. else
  10201. { t = (char*)"!";
  10202. m = 1;
  10203. soap_unget(soap, c);
  10204. }
  10205. *s++ = '<';
  10206. break;
  10207. }
  10208. else if (c == '?')
  10209. state = 3;
  10210. else if (f && n == 0)
  10211. { soap_revget1(soap);
  10212. c = '<';
  10213. goto end;
  10214. }
  10215. else
  10216. n++;
  10217. soap_unget(soap, c);
  10218. *s++ = '<';
  10219. break;
  10220. case '>':
  10221. *s++ = '>';
  10222. break;
  10223. case '"':
  10224. *s++ = '"';
  10225. break;
  10226. default:
  10227. #ifndef WITH_LEANER
  10228. #ifdef HAVE_WCTOMB
  10229. if (soap->mode & SOAP_C_MBSTRING)
  10230. { m = wctomb(buf, c & 0x7FFFFFFF);
  10231. if (m >= 1 && m <= (int)MB_CUR_MAX)
  10232. { t = buf;
  10233. *s++ = *t++;
  10234. m--;
  10235. }
  10236. else
  10237. { *s++ = SOAP_UNKNOWN_CHAR;
  10238. m = 0;
  10239. }
  10240. }
  10241. else
  10242. #endif
  10243. #endif
  10244. *s++ = (char)(c & 0xFF);
  10245. }
  10246. l++;
  10247. if (maxlen >= 0 && l > maxlen)
  10248. { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
  10249. soap->error = SOAP_LENGTH;
  10250. return NULL;
  10251. }
  10252. }
  10253. }
  10254. }
  10255. #endif
  10256. #ifdef WITH_FAST
  10257. soap->labidx = 0; /* use look-aside buffer */
  10258. #else
  10259. if (soap_new_block(soap) == NULL)
  10260. return NULL;
  10261. #endif
  10262. for (;;)
  10263. {
  10264. #ifdef WITH_FAST
  10265. register size_t k;
  10266. if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */
  10267. return NULL;
  10268. s = soap->labbuf + soap->labidx; /* space to populate */
  10269. k = soap->lablen - soap->labidx; /* number of bytes available */
  10270. soap->labidx = soap->lablen; /* claim this space */
  10271. #else
  10272. register size_t k = SOAP_BLKLEN;
  10273. if (!(s = (char*)soap_push_block(soap, NULL, k)))
  10274. return NULL;
  10275. #endif
  10276. for (i = 0; i < k; i++)
  10277. { if (m > 0)
  10278. { *s++ = *t++; /* copy multibyte characters */
  10279. m--;
  10280. continue;
  10281. }
  10282. if (soap->mode & SOAP_C_UTFSTRING)
  10283. { if (((c = soap_get(soap)) & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP)
  10284. { c &= 0x7FFFFFFF;
  10285. t = buf;
  10286. if (c < 0x0800)
  10287. *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
  10288. else
  10289. { if (c < 0x010000)
  10290. *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
  10291. else
  10292. { if (c < 0x200000)
  10293. *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
  10294. else
  10295. { if (c < 0x04000000)
  10296. *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
  10297. else
  10298. { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
  10299. *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
  10300. }
  10301. *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
  10302. }
  10303. *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
  10304. }
  10305. *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
  10306. }
  10307. *t++ = (char)(0x80 | (c & 0x3F));
  10308. m = (int)(t - buf) - 1;
  10309. t = buf;
  10310. *s++ = *t++;
  10311. continue;
  10312. }
  10313. }
  10314. else
  10315. c = soap_getutf8(soap);
  10316. switch (c)
  10317. {
  10318. case SOAP_TT:
  10319. if (n == 0)
  10320. goto end;
  10321. n--;
  10322. *s++ = '<';
  10323. t = (char*)"/";
  10324. m = 1;
  10325. break;
  10326. case SOAP_LT:
  10327. if (f && n == 0)
  10328. goto end;
  10329. n++;
  10330. *s++ = '<';
  10331. break;
  10332. case SOAP_GT:
  10333. *s++ = '>';
  10334. break;
  10335. case SOAP_QT:
  10336. *s++ = '"';
  10337. break;
  10338. case SOAP_AP:
  10339. *s++ = '\'';
  10340. break;
  10341. case '/':
  10342. if (n > 0)
  10343. { c = soap_get(soap);
  10344. if (c == SOAP_GT)
  10345. n--;
  10346. soap_unget(soap, c);
  10347. }
  10348. *s++ = '/';
  10349. break;
  10350. case (soap_wchar)('<' | 0x80000000):
  10351. if (flag)
  10352. *s++ = '<';
  10353. else
  10354. { *s++ = '&';
  10355. t = (char*)"lt;";
  10356. m = 3;
  10357. }
  10358. break;
  10359. case (soap_wchar)('>' | 0x80000000):
  10360. if (flag)
  10361. *s++ = '>';
  10362. else
  10363. { *s++ = '&';
  10364. t = (char*)"gt;";
  10365. m = 3;
  10366. }
  10367. break;
  10368. case (soap_wchar)('&' | 0x80000000):
  10369. if (flag)
  10370. *s++ = '&';
  10371. else
  10372. { *s++ = '&';
  10373. t = (char*)"amp;";
  10374. m = 4;
  10375. }
  10376. break;
  10377. case (soap_wchar)('"' | 0x80000000):
  10378. if (flag)
  10379. *s++ = '"';
  10380. else
  10381. { *s++ = '&';
  10382. t = (char*)"quot;";
  10383. m = 5;
  10384. }
  10385. break;
  10386. case (soap_wchar)('\'' | 0x80000000):
  10387. if (flag)
  10388. *s++ = '\'';
  10389. else
  10390. { *s++ = '&';
  10391. t = (char*)"apos;";
  10392. m = 5;
  10393. }
  10394. break;
  10395. default:
  10396. if ((int)c == EOF)
  10397. goto end;
  10398. #ifndef WITH_LEANER
  10399. #ifdef HAVE_WCTOMB
  10400. if (soap->mode & SOAP_C_MBSTRING)
  10401. { m = wctomb(buf, c & 0x7FFFFFFF);
  10402. if (m >= 1 && m <= (int)MB_CUR_MAX)
  10403. { t = buf;
  10404. *s++ = *t++;
  10405. m--;
  10406. }
  10407. else
  10408. { *s++ = SOAP_UNKNOWN_CHAR;
  10409. m = 0;
  10410. }
  10411. }
  10412. else
  10413. #endif
  10414. #endif
  10415. *s++ = (char)(c & 0xFF);
  10416. }
  10417. l++;
  10418. if (maxlen >= 0 && l > maxlen)
  10419. { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
  10420. soap->error = SOAP_LENGTH;
  10421. return NULL;
  10422. }
  10423. }
  10424. }
  10425. end:
  10426. soap_unget(soap, c);
  10427. *s = '\0';
  10428. #ifdef WITH_FAST
  10429. t = soap_strdup(soap, soap->labbuf);
  10430. #else
  10431. soap_size_block(soap, NULL, i+1);
  10432. t = soap_save_block(soap, NULL, 0);
  10433. #endif
  10434. if (l < minlen)
  10435. { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen));
  10436. soap->error = SOAP_LENGTH;
  10437. return NULL;
  10438. }
  10439. #ifdef WITH_DOM
  10440. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  10441. { if (flag == 3)
  10442. soap->dom->tail = t;
  10443. else
  10444. soap->dom->data = t;
  10445. }
  10446. #endif
  10447. if (flag == 2)
  10448. if (soap_s2QName(soap, t, &t, minlen, maxlen))
  10449. return NULL;
  10450. return t;
  10451. }
  10452. #endif
  10453. /******************************************************************************/
  10454. #ifndef WITH_LEANER
  10455. #ifndef PALM_2
  10456. SOAP_FMAC1
  10457. int
  10458. SOAP_FMAC2
  10459. soap_wstring_out(struct soap *soap, const wchar_t *s, int flag)
  10460. { const char *t;
  10461. char tmp;
  10462. register soap_wchar c;
  10463. #ifdef WITH_DOM
  10464. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  10465. { wchar_t *r = (wchar_t*)s;
  10466. int n = 1;
  10467. while (*r++)
  10468. n++;
  10469. soap->dom->wide = r = (wchar_t*)soap_malloc(soap, n * sizeof(wchar_t));
  10470. while (n--)
  10471. *r++ = *s++;
  10472. return SOAP_OK;
  10473. }
  10474. #endif
  10475. while ((c = *s++))
  10476. { switch (c)
  10477. {
  10478. case 0x09:
  10479. if (flag)
  10480. t = "&#x9;";
  10481. else
  10482. t = "\t";
  10483. break;
  10484. case 0x0A:
  10485. if (flag || !(soap->mode & SOAP_XML_CANONICAL))
  10486. t = "&#xA;";
  10487. else
  10488. t = "\n";
  10489. break;
  10490. case 0x0D:
  10491. t = "&#xD;";
  10492. break;
  10493. case '&':
  10494. t = "&amp;";
  10495. break;
  10496. case '<':
  10497. t = "&lt;";
  10498. break;
  10499. case '>':
  10500. if (flag)
  10501. t = ">";
  10502. else
  10503. t = "&gt;";
  10504. break;
  10505. case '"':
  10506. if (flag)
  10507. t = "&quot;";
  10508. else
  10509. t = "\"";
  10510. break;
  10511. default:
  10512. if (c >= 0x20 && c < 0x80)
  10513. { tmp = (char)c;
  10514. if (soap_send_raw(soap, &tmp, 1))
  10515. return soap->error;
  10516. }
  10517. else if (soap_pututf8(soap, (unsigned long)c))
  10518. return soap->error;
  10519. continue;
  10520. }
  10521. if (soap_send(soap, t))
  10522. return soap->error;
  10523. }
  10524. return SOAP_OK;
  10525. }
  10526. #endif
  10527. #endif
  10528. /******************************************************************************/
  10529. #ifndef WITH_LEANER
  10530. #ifndef PALM_2
  10531. SOAP_FMAC1
  10532. wchar_t *
  10533. SOAP_FMAC2
  10534. soap_wstring_in(struct soap *soap, int flag, long minlen, long maxlen)
  10535. { wchar_t *s;
  10536. register int i, n = 0, f = 0;
  10537. register long l = 0;
  10538. register soap_wchar c;
  10539. char *t = NULL;
  10540. DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading wide string content\n"));
  10541. if (soap->peeked)
  10542. { if (*soap->tag)
  10543. {
  10544. #ifndef WITH_LEAN
  10545. struct soap_attribute *tp;
  10546. t = soap->tmpbuf;
  10547. *t = '<';
  10548. t[sizeof(soap->tmpbuf)-1] = '\0';
  10549. strncpy(t + 1, soap->tag, sizeof(soap->tmpbuf) - 2);
  10550. t += strlen(t);
  10551. for (tp = soap->attributes; tp; tp = tp->next)
  10552. { if (tp->visible)
  10553. { if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2)
  10554. break;
  10555. *t++ = ' ';
  10556. strcpy(t, tp->name);
  10557. t += strlen(t);
  10558. if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2)
  10559. break;
  10560. if (tp->value)
  10561. { *t++ = '=';
  10562. *t++ = '"';
  10563. strcpy(t, tp->value);
  10564. t += strlen(t);
  10565. *t++ = '"';
  10566. }
  10567. }
  10568. }
  10569. if (!soap->body)
  10570. *t++ = '/';
  10571. *t++ = '>';
  10572. *t = '\0';
  10573. t = soap->tmpbuf;
  10574. #endif
  10575. if (soap->body)
  10576. n = 1;
  10577. f = 1;
  10578. soap->peeked = 0;
  10579. }
  10580. }
  10581. if (soap_new_block(soap) == NULL)
  10582. return NULL;
  10583. for (;;)
  10584. { if (!(s = (wchar_t*)soap_push_block(soap, NULL, sizeof(wchar_t)*SOAP_BLKLEN)))
  10585. return NULL;
  10586. for (i = 0; i < SOAP_BLKLEN; i++)
  10587. { if (t)
  10588. { *s++ = (wchar_t)*t++;
  10589. if (!*t)
  10590. t = NULL;
  10591. continue;
  10592. }
  10593. c = soap_getutf8(soap);
  10594. switch (c)
  10595. {
  10596. case SOAP_TT:
  10597. if (n == 0)
  10598. goto end;
  10599. n--;
  10600. *s++ = '<';
  10601. soap_unget(soap, '/');
  10602. break;
  10603. case SOAP_LT:
  10604. if (f && n == 0)
  10605. goto end;
  10606. n++;
  10607. *s++ = '<';
  10608. break;
  10609. case SOAP_GT:
  10610. *s++ = '>';
  10611. break;
  10612. case SOAP_QT:
  10613. *s++ = '"';
  10614. break;
  10615. case SOAP_AP:
  10616. *s++ = '\'';
  10617. break;
  10618. case '/':
  10619. if (n > 0)
  10620. { c = soap_getutf8(soap);
  10621. if (c == SOAP_GT)
  10622. n--;
  10623. soap_unget(soap, c);
  10624. }
  10625. *s++ = '/';
  10626. break;
  10627. case '<':
  10628. if (flag)
  10629. *s++ = (soap_wchar)'<';
  10630. else
  10631. { *s++ = (soap_wchar)'&';
  10632. t = (char*)"lt;";
  10633. }
  10634. break;
  10635. case '>':
  10636. if (flag)
  10637. *s++ = (soap_wchar)'>';
  10638. else
  10639. { *s++ = (soap_wchar)'&';
  10640. t = (char*)"gt;";
  10641. }
  10642. break;
  10643. case '"':
  10644. if (flag)
  10645. *s++ = (soap_wchar)'"';
  10646. else
  10647. { *s++ = (soap_wchar)'&';
  10648. t = (char*)"quot;";
  10649. }
  10650. break;
  10651. default:
  10652. if ((int)c == EOF)
  10653. goto end;
  10654. *s++ = (wchar_t)c & 0x7FFFFFFF;
  10655. }
  10656. l++;
  10657. if (maxlen >= 0 && l > maxlen)
  10658. { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
  10659. soap->error = SOAP_LENGTH;
  10660. return NULL;
  10661. }
  10662. }
  10663. }
  10664. end:
  10665. soap_unget(soap, c);
  10666. *s = '\0';
  10667. soap_size_block(soap, NULL, sizeof(wchar_t) * (i + 1));
  10668. if (l < minlen)
  10669. { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen));
  10670. soap->error = SOAP_LENGTH;
  10671. return NULL;
  10672. }
  10673. s = (wchar_t*)soap_save_block(soap, NULL, NULL, 0);
  10674. #ifdef WITH_DOM
  10675. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  10676. soap->dom->wide = s;
  10677. #endif
  10678. return s;
  10679. }
  10680. #endif
  10681. #endif
  10682. /******************************************************************************/
  10683. #ifndef PALM_2
  10684. SOAP_FMAC1
  10685. const char*
  10686. SOAP_FMAC2
  10687. soap_int2s(struct soap *soap, int n)
  10688. { return soap_long2s(soap, (long)n);
  10689. }
  10690. #endif
  10691. /******************************************************************************/
  10692. #ifndef PALM_2
  10693. SOAP_FMAC1
  10694. int
  10695. SOAP_FMAC2
  10696. soap_outint(struct soap *soap, const char *tag, int id, const int *p, const char *type, int n)
  10697. { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  10698. || soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
  10699. return soap->error;
  10700. return soap_element_end_out(soap, tag);
  10701. }
  10702. #endif
  10703. /******************************************************************************/
  10704. #ifndef PALM_2
  10705. SOAP_FMAC1
  10706. int
  10707. SOAP_FMAC2
  10708. soap_s2int(struct soap *soap, const char *s, int *p)
  10709. { if (s)
  10710. { char *r;
  10711. #ifndef WITH_NOIO
  10712. #ifndef WITH_LEAN
  10713. soap_reset_errno;
  10714. #endif
  10715. #endif
  10716. *p = (int)soap_strtol(s, &r, 10);
  10717. if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
  10718. #ifndef WITH_NOIO
  10719. #ifndef WITH_LEAN
  10720. || soap_errno == SOAP_ERANGE
  10721. #endif
  10722. #endif
  10723. )
  10724. soap->error = SOAP_TYPE;
  10725. }
  10726. return soap->error;
  10727. }
  10728. #endif
  10729. /******************************************************************************/
  10730. #ifndef PALM_2
  10731. SOAP_FMAC1
  10732. int *
  10733. SOAP_FMAC2
  10734. soap_inint(struct soap *soap, const char *tag, int *p, const char *type, int t)
  10735. { if (soap_element_begin_in(soap, tag, 0, NULL))
  10736. return NULL;
  10737. #ifndef WITH_LEAN
  10738. if (*soap->type
  10739. && soap_match_tag(soap, soap->type, type)
  10740. && soap_match_tag(soap, soap->type, ":int")
  10741. && soap_match_tag(soap, soap->type, ":short")
  10742. && soap_match_tag(soap, soap->type, ":byte"))
  10743. { soap->error = SOAP_TYPE;
  10744. soap_revert(soap);
  10745. return NULL;
  10746. }
  10747. #endif
  10748. p = (int*)soap_id_enter(soap, soap->id, p, t, sizeof(int), 0, NULL, NULL, NULL);
  10749. if (*soap->href)
  10750. p = (int*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(int), 0, NULL);
  10751. else if (p)
  10752. { if (soap_s2int(soap, soap_value(soap), p))
  10753. return NULL;
  10754. }
  10755. if (soap->body && soap_element_end_in(soap, tag))
  10756. return NULL;
  10757. return p;
  10758. }
  10759. #endif
  10760. /******************************************************************************/
  10761. #ifndef PALM_2
  10762. SOAP_FMAC1
  10763. const char*
  10764. SOAP_FMAC2
  10765. soap_long2s(struct soap *soap, long n)
  10766. { sprintf(soap->tmpbuf, "%ld", n);
  10767. return soap->tmpbuf;
  10768. }
  10769. #endif
  10770. /******************************************************************************/
  10771. #ifndef PALM_2
  10772. SOAP_FMAC1
  10773. int
  10774. SOAP_FMAC2
  10775. soap_outlong(struct soap *soap, const char *tag, int id, const long *p, const char *type, int n)
  10776. { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  10777. || soap_string_out(soap, soap_long2s(soap, *p), 0))
  10778. return soap->error;
  10779. return soap_element_end_out(soap, tag);
  10780. }
  10781. #endif
  10782. /******************************************************************************/
  10783. #ifndef PALM_2
  10784. SOAP_FMAC1
  10785. int
  10786. SOAP_FMAC2
  10787. soap_s2long(struct soap *soap, const char *s, long *p)
  10788. { if (s)
  10789. { char *r;
  10790. #ifndef WITH_NOIO
  10791. #ifndef WITH_LEAN
  10792. soap_reset_errno;
  10793. #endif
  10794. #endif
  10795. *p = soap_strtol(s, &r, 10);
  10796. if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
  10797. #ifndef WITH_NOIO
  10798. #ifndef WITH_LEAN
  10799. || soap_errno == SOAP_ERANGE
  10800. #endif
  10801. #endif
  10802. )
  10803. soap->error = SOAP_TYPE;
  10804. }
  10805. return soap->error;
  10806. }
  10807. #endif
  10808. /******************************************************************************/
  10809. #ifndef PALM_2
  10810. SOAP_FMAC1
  10811. long *
  10812. SOAP_FMAC2
  10813. soap_inlong(struct soap *soap, const char *tag, long *p, const char *type, int t)
  10814. { if (soap_element_begin_in(soap, tag, 0, NULL))
  10815. return NULL;
  10816. #ifndef WITH_LEAN
  10817. if (*soap->type
  10818. && soap_match_tag(soap, soap->type, type)
  10819. && soap_match_tag(soap, soap->type, ":int")
  10820. && soap_match_tag(soap, soap->type, ":short")
  10821. && soap_match_tag(soap, soap->type, ":byte"))
  10822. { soap->error = SOAP_TYPE;
  10823. soap_revert(soap);
  10824. return NULL;
  10825. }
  10826. #endif
  10827. p = (long*)soap_id_enter(soap, soap->id, p, t, sizeof(long), 0, NULL, NULL, NULL);
  10828. if (*soap->href)
  10829. p = (long*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(long), 0, NULL);
  10830. else if (p)
  10831. { if (soap_s2long(soap, soap_value(soap), p))
  10832. return NULL;
  10833. }
  10834. if (soap->body && soap_element_end_in(soap, tag))
  10835. return NULL;
  10836. return p;
  10837. }
  10838. #endif
  10839. /******************************************************************************/
  10840. #ifndef WITH_LEAN
  10841. SOAP_FMAC1
  10842. const char*
  10843. SOAP_FMAC2
  10844. soap_LONG642s(struct soap *soap, LONG64 n)
  10845. { sprintf(soap->tmpbuf, SOAP_LONG_FORMAT, n);
  10846. return soap->tmpbuf;
  10847. }
  10848. #endif
  10849. /******************************************************************************/
  10850. #ifndef WITH_LEAN
  10851. SOAP_FMAC1
  10852. int
  10853. SOAP_FMAC2
  10854. soap_outLONG64(struct soap *soap, const char *tag, int id, const LONG64 *p, const char *type, int n)
  10855. { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  10856. || soap_string_out(soap, soap_LONG642s(soap, *p), 0))
  10857. return soap->error;
  10858. return soap_element_end_out(soap, tag);
  10859. }
  10860. #endif
  10861. /******************************************************************************/
  10862. #ifndef WITH_LEAN
  10863. SOAP_FMAC1
  10864. int
  10865. SOAP_FMAC2
  10866. soap_s2LONG64(struct soap *soap, const char *s, LONG64 *p)
  10867. { if (s)
  10868. {
  10869. #ifdef HAVE_STRTOLL
  10870. char *r;
  10871. #ifndef WITH_NOIO
  10872. #ifndef WITH_LEAN
  10873. soap_reset_errno;
  10874. #endif
  10875. #endif
  10876. *p = strtoll(s, &r, 10);
  10877. if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
  10878. #ifndef WITH_NOIO
  10879. #ifndef WITH_LEAN
  10880. || soap_errno == SOAP_ERANGE
  10881. #endif
  10882. #endif
  10883. )
  10884. #else
  10885. # ifdef HAVE_SSCANF
  10886. if (sscanf(s, SOAP_LONG_FORMAT, p) != 1)
  10887. # endif
  10888. #endif
  10889. soap->error = SOAP_TYPE;
  10890. }
  10891. return soap->error;
  10892. }
  10893. #endif
  10894. /******************************************************************************/
  10895. #ifndef WITH_LEAN
  10896. SOAP_FMAC1
  10897. LONG64 *
  10898. SOAP_FMAC2
  10899. soap_inLONG64(struct soap *soap, const char *tag, LONG64 *p, const char *type, int t)
  10900. { if (soap_element_begin_in(soap, tag, 0, NULL))
  10901. return NULL;
  10902. #ifndef WITH_LEAN
  10903. if (*soap->type
  10904. && soap_match_tag(soap, soap->type, type)
  10905. && soap_match_tag(soap, soap->type, ":integer")
  10906. && soap_match_tag(soap, soap->type, ":positiveInteger")
  10907. && soap_match_tag(soap, soap->type, ":negativeInteger")
  10908. && soap_match_tag(soap, soap->type, ":nonPositiveInteger")
  10909. && soap_match_tag(soap, soap->type, ":nonNegativeInteger")
  10910. && soap_match_tag(soap, soap->type, ":long")
  10911. && soap_match_tag(soap, soap->type, ":int")
  10912. && soap_match_tag(soap, soap->type, ":short")
  10913. && soap_match_tag(soap, soap->type, ":byte"))
  10914. { soap->error = SOAP_TYPE;
  10915. soap_revert(soap);
  10916. return NULL;
  10917. }
  10918. #endif
  10919. p = (LONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(LONG64), 0, NULL, NULL, NULL);
  10920. if (*soap->href)
  10921. p = (LONG64*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(LONG64), 0, NULL);
  10922. else if (p)
  10923. { if (soap_s2LONG64(soap, soap_value(soap), p))
  10924. return NULL;
  10925. }
  10926. if (soap->body && soap_element_end_in(soap, tag))
  10927. return NULL;
  10928. return p;
  10929. }
  10930. #endif
  10931. /******************************************************************************/
  10932. #ifndef PALM_2
  10933. SOAP_FMAC1
  10934. const char*
  10935. SOAP_FMAC2
  10936. soap_byte2s(struct soap *soap, char n)
  10937. { return soap_long2s(soap, (long)n);
  10938. }
  10939. #endif
  10940. /******************************************************************************/
  10941. #ifndef PALM_2
  10942. SOAP_FMAC1
  10943. int
  10944. SOAP_FMAC2
  10945. soap_outbyte(struct soap *soap, const char *tag, int id, const char *p, const char *type, int n)
  10946. { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  10947. || soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
  10948. return soap->error;
  10949. return soap_element_end_out(soap, tag);
  10950. }
  10951. #endif
  10952. /******************************************************************************/
  10953. #ifndef PALM_2
  10954. SOAP_FMAC1
  10955. int
  10956. SOAP_FMAC2
  10957. soap_s2byte(struct soap *soap, const char *s, char *p)
  10958. { if (s)
  10959. { long n;
  10960. char *r;
  10961. n = soap_strtol(s, &r, 10);
  10962. if (s == r || *r || n < -128 || n > 127)
  10963. soap->error = SOAP_TYPE;
  10964. *p = (char)n;
  10965. }
  10966. return soap->error;
  10967. }
  10968. #endif
  10969. /******************************************************************************/
  10970. #ifndef PALM_2
  10971. SOAP_FMAC1
  10972. char *
  10973. SOAP_FMAC2
  10974. soap_inbyte(struct soap *soap, const char *tag, char *p, const char *type, int t)
  10975. { if (soap_element_begin_in(soap, tag, 0, NULL))
  10976. return NULL;
  10977. #ifndef WITH_LEAN
  10978. if (*soap->type
  10979. && soap_match_tag(soap, soap->type, type)
  10980. && soap_match_tag(soap, soap->type, ":byte"))
  10981. { soap->error = SOAP_TYPE;
  10982. soap_revert(soap);
  10983. return NULL;
  10984. }
  10985. #endif
  10986. p = (char*)soap_id_enter(soap, soap->id, p, t, sizeof(char), 0, NULL, NULL, NULL);
  10987. if (*soap->href)
  10988. p = (char*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(char), 0, NULL);
  10989. else if (p)
  10990. { if (soap_s2byte(soap, soap_value(soap), p))
  10991. return NULL;
  10992. }
  10993. if (soap->body && soap_element_end_in(soap, tag))
  10994. return NULL;
  10995. return p;
  10996. }
  10997. #endif
  10998. /******************************************************************************/
  10999. #ifndef PALM_2
  11000. SOAP_FMAC1
  11001. const char*
  11002. SOAP_FMAC2
  11003. soap_short2s(struct soap *soap, short n)
  11004. { return soap_long2s(soap, (long)n);
  11005. }
  11006. #endif
  11007. /******************************************************************************/
  11008. #ifndef PALM_2
  11009. SOAP_FMAC1
  11010. int
  11011. SOAP_FMAC2
  11012. soap_outshort(struct soap *soap, const char *tag, int id, const short *p, const char *type, int n)
  11013. { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  11014. || soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
  11015. return soap->error;
  11016. return soap_element_end_out(soap, tag);
  11017. }
  11018. #endif
  11019. /******************************************************************************/
  11020. #ifndef PALM_2
  11021. SOAP_FMAC1
  11022. int
  11023. SOAP_FMAC2
  11024. soap_s2short(struct soap *soap, const char *s, short *p)
  11025. { if (s)
  11026. { long n;
  11027. char *r;
  11028. n = soap_strtol(s, &r, 10);
  11029. if (s == r || *r || n < -32768 || n > 32767)
  11030. soap->error = SOAP_TYPE;
  11031. *p = (short)n;
  11032. }
  11033. return soap->error;
  11034. }
  11035. #endif
  11036. /******************************************************************************/
  11037. #ifndef PALM_2
  11038. SOAP_FMAC1
  11039. short *
  11040. SOAP_FMAC2
  11041. soap_inshort(struct soap *soap, const char *tag, short *p, const char *type, int t)
  11042. { if (soap_element_begin_in(soap, tag, 0, NULL))
  11043. return NULL;
  11044. #ifndef WITH_LEAN
  11045. if (*soap->type
  11046. && soap_match_tag(soap, soap->type, type)
  11047. && soap_match_tag(soap, soap->type, ":short")
  11048. && soap_match_tag(soap, soap->type, ":byte"))
  11049. { soap->error = SOAP_TYPE;
  11050. soap_revert(soap);
  11051. return NULL;
  11052. }
  11053. #endif
  11054. p = (short*)soap_id_enter(soap, soap->id, p, t, sizeof(short), 0, NULL, NULL, NULL);
  11055. if (*soap->href)
  11056. p = (short*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(short), 0, NULL);
  11057. else if (p)
  11058. { if (soap_s2short(soap, soap_value(soap), p))
  11059. return NULL;
  11060. }
  11061. if (soap->body && soap_element_end_in(soap, tag))
  11062. return NULL;
  11063. return p;
  11064. }
  11065. #endif
  11066. /******************************************************************************/
  11067. #ifndef PALM_2
  11068. SOAP_FMAC1
  11069. const char*
  11070. SOAP_FMAC2
  11071. soap_float2s(struct soap *soap, float n)
  11072. { char *s;
  11073. if (soap_isnan((double)n))
  11074. return "NaN";
  11075. if (soap_ispinff(n))
  11076. return "INF";
  11077. if (soap_isninff(n))
  11078. return "-INF";
  11079. s = soap->tmpbuf;
  11080. #if defined(HAVE_SPRINTF_L)
  11081. sprintf_l(s, soap->c_locale, soap->float_format, n);
  11082. #else
  11083. sprintf(s, soap->float_format, n);
  11084. s = strchr(s, ','); /* convert decimal comma to DP */
  11085. if (s)
  11086. *s = '.';
  11087. #endif
  11088. return soap->tmpbuf;
  11089. }
  11090. #endif
  11091. /******************************************************************************/
  11092. #ifndef PALM_2
  11093. SOAP_FMAC1
  11094. int
  11095. SOAP_FMAC2
  11096. soap_outfloat(struct soap *soap, const char *tag, int id, const float *p, const char *type, int n)
  11097. { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  11098. || soap_string_out(soap, soap_float2s(soap, *p), 0))
  11099. return soap->error;
  11100. return soap_element_end_out(soap, tag);
  11101. }
  11102. #endif
  11103. /******************************************************************************/
  11104. #ifndef PALM_2
  11105. SOAP_FMAC1
  11106. int
  11107. SOAP_FMAC2
  11108. soap_s2float(struct soap *soap, const char *s, float *p)
  11109. { if (s)
  11110. { if (!*s)
  11111. return soap->error = SOAP_TYPE;
  11112. if (!soap_tag_cmp(s, "INF"))
  11113. *p = FLT_PINFTY;
  11114. else if (!soap_tag_cmp(s, "+INF"))
  11115. *p = FLT_PINFTY;
  11116. else if (!soap_tag_cmp(s, "-INF"))
  11117. *p = FLT_NINFTY;
  11118. else if (!soap_tag_cmp(s, "NaN"))
  11119. *p = FLT_NAN;
  11120. else
  11121. {
  11122. /* On some systems strtof requires -std=c99 or does not even link: so we try to use strtod first */
  11123. #if defined(HAVE_STRTOD_L)
  11124. char *r;
  11125. *p = (float)strtod_l(s, &r, soap->c_locale);
  11126. if (*r)
  11127. #elif defined(HAVE_STRTOD)
  11128. char *r;
  11129. *p = (float)strtod(s, &r);
  11130. if (*r)
  11131. #elif defined(HAVE_STRTOF_L)
  11132. char *r;
  11133. *p = strtof_l((char*)s, &r, soap->c_locale);
  11134. if (*r)
  11135. #elif defined(HAVE_STRTOF)
  11136. char *r;
  11137. *p = strtof((char*)s, &r);
  11138. if (*r)
  11139. #endif
  11140. {
  11141. #if defined(HAVE_SSCANF_L) && !defined(HAVE_STRTOF_L) && !defined(HAVE_STRTOD_L)
  11142. if (sscanf_l(s, soap->c_locale, "%g", p) != 1)
  11143. soap->error = SOAP_TYPE;
  11144. #elif defined(HAVE_SSCANF)
  11145. if (sscanf(s, "%g", p) != 1)
  11146. soap->error = SOAP_TYPE;
  11147. #else
  11148. soap->error = SOAP_TYPE;
  11149. #endif
  11150. }
  11151. }
  11152. }
  11153. return soap->error;
  11154. }
  11155. #endif
  11156. /******************************************************************************/
  11157. #ifndef WITH_LEAN
  11158. static int soap_isnumeric(struct soap *soap, const char *type)
  11159. { if (soap_match_tag(soap, soap->type, type)
  11160. && soap_match_tag(soap, soap->type, ":float")
  11161. && soap_match_tag(soap, soap->type, ":double")
  11162. && soap_match_tag(soap, soap->type, ":decimal")
  11163. && soap_match_tag(soap, soap->type, ":integer")
  11164. && soap_match_tag(soap, soap->type, ":positiveInteger")
  11165. && soap_match_tag(soap, soap->type, ":negativeInteger")
  11166. && soap_match_tag(soap, soap->type, ":nonPositiveInteger")
  11167. && soap_match_tag(soap, soap->type, ":nonNegativeInteger")
  11168. && soap_match_tag(soap, soap->type, ":long")
  11169. && soap_match_tag(soap, soap->type, ":int")
  11170. && soap_match_tag(soap, soap->type, ":short")
  11171. && soap_match_tag(soap, soap->type, ":byte")
  11172. && soap_match_tag(soap, soap->type, ":unsignedLong")
  11173. && soap_match_tag(soap, soap->type, ":unsignedInt")
  11174. && soap_match_tag(soap, soap->type, ":unsignedShort")
  11175. && soap_match_tag(soap, soap->type, ":unsignedByte"))
  11176. { soap->error = SOAP_TYPE;
  11177. soap_revert(soap);
  11178. return SOAP_ERR;
  11179. }
  11180. return SOAP_OK;
  11181. }
  11182. #endif
  11183. /******************************************************************************/
  11184. #ifndef PALM_2
  11185. SOAP_FMAC1
  11186. float *
  11187. SOAP_FMAC2
  11188. soap_infloat(struct soap *soap, const char *tag, float *p, const char *type, int t)
  11189. { if (soap_element_begin_in(soap, tag, 0, NULL))
  11190. return NULL;
  11191. #ifndef WITH_LEAN
  11192. if (*soap->type != '\0' && soap_isnumeric(soap, type))
  11193. return NULL;
  11194. #endif
  11195. p = (float*)soap_id_enter(soap, soap->id, p, t, sizeof(float), 0, NULL, NULL, NULL);
  11196. if (*soap->href)
  11197. p = (float*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(float), 0, NULL);
  11198. else if (p)
  11199. { if (soap_s2float(soap, soap_value(soap), p))
  11200. return NULL;
  11201. }
  11202. if (soap->body && soap_element_end_in(soap, tag))
  11203. return NULL;
  11204. return p;
  11205. }
  11206. #endif
  11207. /******************************************************************************/
  11208. #ifndef PALM_2
  11209. SOAP_FMAC1
  11210. const char*
  11211. SOAP_FMAC2
  11212. soap_double2s(struct soap *soap, double n)
  11213. { char *s;
  11214. if (soap_isnan(n))
  11215. return "NaN";
  11216. if (soap_ispinfd(n))
  11217. return "INF";
  11218. if (soap_isninfd(n))
  11219. return "-INF";
  11220. s = soap->tmpbuf;
  11221. #if defined(HAVE_SPRINTF_L)
  11222. sprintf_l(s, soap->c_locale, soap->double_format, n);
  11223. #else
  11224. sprintf(s, soap->double_format, n);
  11225. s = strchr(s, ','); /* convert decimal comma to DP */
  11226. if (s)
  11227. *s = '.';
  11228. #endif
  11229. return soap->tmpbuf;
  11230. }
  11231. #endif
  11232. /******************************************************************************/
  11233. #ifndef PALM_2
  11234. SOAP_FMAC1
  11235. int
  11236. SOAP_FMAC2
  11237. soap_outdouble(struct soap *soap, const char *tag, int id, const double *p, const char *type, int n)
  11238. { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  11239. || soap_string_out(soap, soap_double2s(soap, *p), 0))
  11240. return soap->error;
  11241. return soap_element_end_out(soap, tag);
  11242. }
  11243. #endif
  11244. /******************************************************************************/
  11245. #ifndef PALM_2
  11246. SOAP_FMAC1
  11247. int
  11248. SOAP_FMAC2
  11249. soap_s2double(struct soap *soap, const char *s, double *p)
  11250. { if (s)
  11251. { if (!*s)
  11252. return soap->error = SOAP_TYPE;
  11253. if (!soap_tag_cmp(s, "INF"))
  11254. *p = DBL_PINFTY;
  11255. else if (!soap_tag_cmp(s, "+INF"))
  11256. *p = DBL_PINFTY;
  11257. else if (!soap_tag_cmp(s, "-INF"))
  11258. *p = DBL_NINFTY;
  11259. else if (!soap_tag_cmp(s, "NaN"))
  11260. *p = DBL_NAN;
  11261. else
  11262. {
  11263. #if defined(HAVE_STRTOD_L)
  11264. char *r;
  11265. *p = strtod_l(s, &r, soap->c_locale);
  11266. if (*r)
  11267. #elif defined(HAVE_STRTOD)
  11268. char *r;
  11269. *p = strtod(s, &r);
  11270. if (*r)
  11271. #endif
  11272. {
  11273. #if defined(HAVE_SSCANF_L) && !defined(HAVE_STRTOF_L) && !defined(HAVE_STRTOD_L)
  11274. if (sscanf_l(s, soap->c_locale, "%lg", p) != 1)
  11275. soap->error = SOAP_TYPE;
  11276. #elif defined(HAVE_SSCANF)
  11277. if (sscanf(s, "%lg", p) != 1)
  11278. soap->error = SOAP_TYPE;
  11279. #else
  11280. soap->error = SOAP_TYPE;
  11281. #endif
  11282. }
  11283. }
  11284. }
  11285. return soap->error;
  11286. }
  11287. #endif
  11288. /******************************************************************************/
  11289. #ifndef PALM_2
  11290. SOAP_FMAC1
  11291. double *
  11292. SOAP_FMAC2
  11293. soap_indouble(struct soap *soap, const char *tag, double *p, const char *type, int t)
  11294. { if (soap_element_begin_in(soap, tag, 0, NULL))
  11295. return NULL;
  11296. #ifndef WITH_LEAN
  11297. if (*soap->type != '\0' && soap_isnumeric(soap, type))
  11298. return NULL;
  11299. #endif
  11300. p = (double*)soap_id_enter(soap, soap->id, p, t, sizeof(double), 0, NULL, NULL, NULL);
  11301. if (*soap->href)
  11302. p = (double*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(double), 0, NULL);
  11303. else if (p)
  11304. { if (soap_s2double(soap, soap_value(soap), p))
  11305. return NULL;
  11306. }
  11307. if (soap->body && soap_element_end_in(soap, tag))
  11308. return NULL;
  11309. return p;
  11310. }
  11311. #endif
  11312. /******************************************************************************/
  11313. #ifndef PALM_2
  11314. SOAP_FMAC1
  11315. const char*
  11316. SOAP_FMAC2
  11317. soap_unsignedByte2s(struct soap *soap, unsigned char n)
  11318. { return soap_unsignedLong2s(soap, (unsigned long)n);
  11319. }
  11320. #endif
  11321. /******************************************************************************/
  11322. #ifndef PALM_2
  11323. SOAP_FMAC1
  11324. int
  11325. SOAP_FMAC2
  11326. soap_outunsignedByte(struct soap *soap, const char *tag, int id, const unsigned char *p, const char *type, int n)
  11327. { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  11328. || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0))
  11329. return soap->error;
  11330. return soap_element_end_out(soap, tag);
  11331. }
  11332. #endif
  11333. /******************************************************************************/
  11334. #ifndef PALM_2
  11335. SOAP_FMAC1
  11336. int
  11337. SOAP_FMAC2
  11338. soap_s2unsignedByte(struct soap *soap, const char *s, unsigned char *p)
  11339. { if (s)
  11340. { unsigned long n;
  11341. char *r;
  11342. n = soap_strtoul(s, &r, 10);
  11343. if (s == r || *r || n > 255)
  11344. soap->error = SOAP_TYPE;
  11345. *p = (unsigned char)n;
  11346. }
  11347. return soap->error;
  11348. }
  11349. #endif
  11350. /******************************************************************************/
  11351. #ifndef PALM_2
  11352. SOAP_FMAC1
  11353. unsigned char *
  11354. SOAP_FMAC2
  11355. soap_inunsignedByte(struct soap *soap, const char *tag, unsigned char *p, const char *type, int t)
  11356. { if (soap_element_begin_in(soap, tag, 0, NULL))
  11357. return NULL;
  11358. #ifndef WITH_LEAN
  11359. if (*soap->type
  11360. && soap_match_tag(soap, soap->type, type)
  11361. && soap_match_tag(soap, soap->type, ":unsignedByte"))
  11362. { soap->error = SOAP_TYPE;
  11363. soap_revert(soap);
  11364. return NULL;
  11365. }
  11366. #endif
  11367. p = (unsigned char*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned char), 0, NULL, NULL, NULL);
  11368. if (*soap->href)
  11369. p = (unsigned char*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned char), 0, NULL);
  11370. else if (p)
  11371. { if (soap_s2unsignedByte(soap, soap_value(soap), p))
  11372. return NULL;
  11373. }
  11374. if (soap->body && soap_element_end_in(soap, tag))
  11375. return NULL;
  11376. return p;
  11377. }
  11378. #endif
  11379. /******************************************************************************/
  11380. #ifndef PALM_2
  11381. SOAP_FMAC1
  11382. const char*
  11383. SOAP_FMAC2
  11384. soap_unsignedShort2s(struct soap *soap, unsigned short n)
  11385. { return soap_unsignedLong2s(soap, (unsigned long)n);
  11386. }
  11387. #endif
  11388. /******************************************************************************/
  11389. #ifndef PALM_2
  11390. SOAP_FMAC1
  11391. int
  11392. SOAP_FMAC2
  11393. soap_outunsignedShort(struct soap *soap, const char *tag, int id, const unsigned short *p, const char *type, int n)
  11394. { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  11395. || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0))
  11396. return soap->error;
  11397. return soap_element_end_out(soap, tag);
  11398. }
  11399. #endif
  11400. /******************************************************************************/
  11401. #ifndef PALM_2
  11402. SOAP_FMAC1
  11403. int
  11404. SOAP_FMAC2
  11405. soap_s2unsignedShort(struct soap *soap, const char *s, unsigned short *p)
  11406. { if (s)
  11407. { unsigned long n;
  11408. char *r;
  11409. n = soap_strtoul(s, &r, 10);
  11410. if (s == r || *r || n > 65535)
  11411. soap->error = SOAP_TYPE;
  11412. *p = (unsigned short)n;
  11413. }
  11414. return soap->error;
  11415. }
  11416. #endif
  11417. /******************************************************************************/
  11418. #ifndef PALM_2
  11419. SOAP_FMAC1
  11420. unsigned short *
  11421. SOAP_FMAC2
  11422. soap_inunsignedShort(struct soap *soap, const char *tag, unsigned short *p, const char *type, int t)
  11423. { if (soap_element_begin_in(soap, tag, 0, NULL))
  11424. return NULL;
  11425. #ifndef WITH_LEAN
  11426. if (*soap->type
  11427. && soap_match_tag(soap, soap->type, type)
  11428. && soap_match_tag(soap, soap->type, ":unsignedShort")
  11429. && soap_match_tag(soap, soap->type, ":unsignedByte"))
  11430. { soap->error = SOAP_TYPE;
  11431. soap_revert(soap);
  11432. return NULL;
  11433. }
  11434. #endif
  11435. p = (unsigned short*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned short), 0, NULL, NULL, NULL);
  11436. if (*soap->href)
  11437. p = (unsigned short*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned short), 0, NULL);
  11438. else if (p)
  11439. { if (soap_s2unsignedShort(soap, soap_value(soap), p))
  11440. return NULL;
  11441. }
  11442. if (soap->body && soap_element_end_in(soap, tag))
  11443. return NULL;
  11444. return p;
  11445. }
  11446. #endif
  11447. /******************************************************************************/
  11448. #ifndef PALM_2
  11449. SOAP_FMAC1
  11450. const char*
  11451. SOAP_FMAC2
  11452. soap_unsignedInt2s(struct soap *soap, unsigned int n)
  11453. { return soap_unsignedLong2s(soap, (unsigned long)n);
  11454. }
  11455. #endif
  11456. /******************************************************************************/
  11457. #ifndef PALM_2
  11458. SOAP_FMAC1
  11459. int
  11460. SOAP_FMAC2
  11461. soap_outunsignedInt(struct soap *soap, const char *tag, int id, const unsigned int *p, const char *type, int n)
  11462. { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  11463. || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0))
  11464. return soap->error;
  11465. return soap_element_end_out(soap, tag);
  11466. }
  11467. #endif
  11468. /******************************************************************************/
  11469. #ifndef PALM_2
  11470. SOAP_FMAC1
  11471. int
  11472. SOAP_FMAC2
  11473. soap_s2unsignedInt(struct soap *soap, const char *s, unsigned int *p)
  11474. { if (s)
  11475. { char *r;
  11476. #ifndef WITH_NOIO
  11477. #ifndef WITH_LEAN
  11478. soap_reset_errno;
  11479. #endif
  11480. #endif
  11481. *p = (unsigned int)soap_strtoul(s, &r, 10);
  11482. if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
  11483. #ifndef WITH_NOIO
  11484. #ifndef WITH_LEAN
  11485. || soap_errno == SOAP_ERANGE
  11486. #endif
  11487. #endif
  11488. )
  11489. soap->error = SOAP_TYPE;
  11490. }
  11491. return soap->error;
  11492. }
  11493. #endif
  11494. /******************************************************************************/
  11495. #ifndef PALM_2
  11496. SOAP_FMAC1
  11497. unsigned int *
  11498. SOAP_FMAC2
  11499. soap_inunsignedInt(struct soap *soap, const char *tag, unsigned int *p, const char *type, int t)
  11500. { if (soap_element_begin_in(soap, tag, 0, NULL))
  11501. return NULL;
  11502. #ifndef WITH_LEAN
  11503. if (*soap->type
  11504. && soap_match_tag(soap, soap->type, type)
  11505. && soap_match_tag(soap, soap->type, ":unsignedInt")
  11506. && soap_match_tag(soap, soap->type, ":unsignedShort")
  11507. && soap_match_tag(soap, soap->type, ":unsignedByte"))
  11508. { soap->error = SOAP_TYPE;
  11509. soap_revert(soap);
  11510. return NULL;
  11511. }
  11512. #endif
  11513. p = (unsigned int*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned int), 0, NULL, NULL, NULL);
  11514. if (*soap->href)
  11515. p = (unsigned int*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned int), 0, NULL);
  11516. else if (p)
  11517. { if (soap_s2unsignedInt(soap, soap_value(soap), p))
  11518. return NULL;
  11519. }
  11520. if (soap->body && soap_element_end_in(soap, tag))
  11521. return NULL;
  11522. return p;
  11523. }
  11524. #endif
  11525. /******************************************************************************/
  11526. #ifndef PALM_2
  11527. SOAP_FMAC1
  11528. const char*
  11529. SOAP_FMAC2
  11530. soap_unsignedLong2s(struct soap *soap, unsigned long n)
  11531. { sprintf(soap->tmpbuf, "%lu", n);
  11532. return soap->tmpbuf;
  11533. }
  11534. #endif
  11535. /******************************************************************************/
  11536. #ifndef PALM_2
  11537. SOAP_FMAC1
  11538. int
  11539. SOAP_FMAC2
  11540. soap_outunsignedLong(struct soap *soap, const char *tag, int id, const unsigned long *p, const char *type, int n)
  11541. { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  11542. || soap_string_out(soap, soap_unsignedLong2s(soap, *p), 0))
  11543. return soap->error;
  11544. return soap_element_end_out(soap, tag);
  11545. }
  11546. #endif
  11547. /******************************************************************************/
  11548. #ifndef PALM_2
  11549. SOAP_FMAC1
  11550. int
  11551. SOAP_FMAC2
  11552. soap_s2unsignedLong(struct soap *soap, const char *s, unsigned long *p)
  11553. { if (s)
  11554. { char *r;
  11555. #ifndef WITH_NOIO
  11556. #ifndef WITH_LEAN
  11557. soap_reset_errno;
  11558. #endif
  11559. #endif
  11560. *p = soap_strtoul(s, &r, 10);
  11561. if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
  11562. #ifndef WITH_NOIO
  11563. #ifndef WITH_LEAN
  11564. || soap_errno == SOAP_ERANGE
  11565. #endif
  11566. #endif
  11567. )
  11568. soap->error = SOAP_TYPE;
  11569. }
  11570. return soap->error;
  11571. }
  11572. #endif
  11573. /******************************************************************************/
  11574. #ifndef PALM_2
  11575. SOAP_FMAC1
  11576. unsigned long *
  11577. SOAP_FMAC2
  11578. soap_inunsignedLong(struct soap *soap, const char *tag, unsigned long *p, const char *type, int t)
  11579. { if (soap_element_begin_in(soap, tag, 0, NULL))
  11580. return NULL;
  11581. #ifndef WITH_LEAN
  11582. if (*soap->type
  11583. && soap_match_tag(soap, soap->type, type)
  11584. && soap_match_tag(soap, soap->type, ":unsignedInt")
  11585. && soap_match_tag(soap, soap->type, ":unsignedShort")
  11586. && soap_match_tag(soap, soap->type, ":unsignedByte"))
  11587. { soap->error = SOAP_TYPE;
  11588. soap_revert(soap);
  11589. return NULL;
  11590. }
  11591. #endif
  11592. p = (unsigned long*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned long), 0, NULL, NULL, NULL);
  11593. if (*soap->href)
  11594. p = (unsigned long*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned long), 0, NULL);
  11595. else if (p)
  11596. { if (soap_s2unsignedLong(soap, soap_value(soap), p))
  11597. return NULL;
  11598. }
  11599. if (soap->body && soap_element_end_in(soap, tag))
  11600. return NULL;
  11601. return p;
  11602. }
  11603. #endif
  11604. /******************************************************************************/
  11605. #ifndef WITH_LEAN
  11606. SOAP_FMAC1
  11607. const char*
  11608. SOAP_FMAC2
  11609. soap_ULONG642s(struct soap *soap, ULONG64 n)
  11610. { sprintf(soap->tmpbuf, SOAP_ULONG_FORMAT, n);
  11611. return soap->tmpbuf;
  11612. }
  11613. #endif
  11614. /******************************************************************************/
  11615. #ifndef WITH_LEAN
  11616. SOAP_FMAC1
  11617. int
  11618. SOAP_FMAC2
  11619. soap_outULONG64(struct soap *soap, const char *tag, int id, const ULONG64 *p, const char *type, int n)
  11620. { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  11621. || soap_string_out(soap, soap_ULONG642s(soap, *p), 0))
  11622. return soap->error;
  11623. return soap_element_end_out(soap, tag);
  11624. }
  11625. #endif
  11626. /******************************************************************************/
  11627. #ifndef WITH_LEAN
  11628. SOAP_FMAC1
  11629. int
  11630. SOAP_FMAC2
  11631. soap_s2ULONG64(struct soap *soap, const char *s, ULONG64 *p)
  11632. { if (s)
  11633. {
  11634. #ifdef HAVE_STRTOULL
  11635. char *r;
  11636. #ifndef WITH_NOIO
  11637. #ifndef WITH_LEAN
  11638. soap_reset_errno;
  11639. #endif
  11640. #endif
  11641. *p = strtoull(s, &r, 10);
  11642. if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
  11643. #ifndef WITH_NOIO
  11644. #ifndef WITH_LEAN
  11645. || soap_errno == SOAP_ERANGE
  11646. #endif
  11647. #endif
  11648. )
  11649. #else
  11650. #ifdef HAVE_SSCANF
  11651. if (sscanf(s, SOAP_ULONG_FORMAT, p) != 1)
  11652. #endif
  11653. #endif
  11654. soap->error = SOAP_TYPE;
  11655. }
  11656. return soap->error;
  11657. }
  11658. #endif
  11659. /******************************************************************************/
  11660. #ifndef WITH_LEAN
  11661. SOAP_FMAC1
  11662. ULONG64 *
  11663. SOAP_FMAC2
  11664. soap_inULONG64(struct soap *soap, const char *tag, ULONG64 *p, const char *type, int t)
  11665. { if (soap_element_begin_in(soap, tag, 0, NULL))
  11666. return NULL;
  11667. if (*soap->type
  11668. && soap_match_tag(soap, soap->type, type)
  11669. && soap_match_tag(soap, soap->type, ":positiveInteger")
  11670. && soap_match_tag(soap, soap->type, ":nonNegativeInteger")
  11671. && soap_match_tag(soap, soap->type, ":unsignedLong")
  11672. && soap_match_tag(soap, soap->type, ":unsignedInt")
  11673. && soap_match_tag(soap, soap->type, ":unsignedShort")
  11674. && soap_match_tag(soap, soap->type, ":unsignedByte"))
  11675. { soap->error = SOAP_TYPE;
  11676. soap_revert(soap);
  11677. return NULL;
  11678. }
  11679. p = (ULONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(ULONG64), 0, NULL, NULL, NULL);
  11680. if (*soap->href)
  11681. p = (ULONG64*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(ULONG64), 0, NULL);
  11682. else if (p)
  11683. { if (soap_s2ULONG64(soap, soap_value(soap), p))
  11684. return NULL;
  11685. }
  11686. if (soap->body && soap_element_end_in(soap, tag))
  11687. return NULL;
  11688. return p;
  11689. }
  11690. #endif
  11691. /******************************************************************************/
  11692. #ifndef PALM_2
  11693. SOAP_FMAC1
  11694. int
  11695. SOAP_FMAC2
  11696. soap_s2string(struct soap *soap, const char *s, char **t, long minlen, long maxlen)
  11697. { if (s)
  11698. { long l = (long)strlen(s);
  11699. if ((maxlen >= 0 && l > maxlen) || l < minlen)
  11700. return soap->error = SOAP_LENGTH;
  11701. if (!(*t = soap_strdup(soap, s)))
  11702. return soap->error = SOAP_EOM;
  11703. if (!(soap->mode & (SOAP_ENC_LATIN | SOAP_C_UTFSTRING)))
  11704. { char *r = *t;
  11705. /* remove non-ASCII chars */
  11706. for (s = *t; *s; s++)
  11707. if (!(*s & 0x80))
  11708. *r++ = *s;
  11709. *r = '\0';
  11710. }
  11711. }
  11712. return soap->error;
  11713. }
  11714. #endif
  11715. /******************************************************************************/
  11716. #ifndef PALM_2
  11717. SOAP_FMAC1
  11718. int
  11719. SOAP_FMAC2
  11720. soap_s2QName(struct soap *soap, const char *s, char **t, long minlen, long maxlen)
  11721. { if (s)
  11722. { long l = (long)strlen(s);
  11723. if ((maxlen >= 0 && l > maxlen) || l < minlen)
  11724. return soap->error = SOAP_LENGTH;
  11725. soap->labidx = 0;
  11726. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Normalized namespace(s) of QNames '%s'", s));
  11727. /* convert (by prefix normalize prefix) all QNames in s */
  11728. for (;;)
  11729. { size_t n;
  11730. struct soap_nlist *np;
  11731. register const char *p;
  11732. /* skip blanks */
  11733. while (*s && soap_blank(*s))
  11734. s++;
  11735. if (!*s)
  11736. break;
  11737. /* find next QName */
  11738. n = 1;
  11739. while (s[n] && !soap_blank(s[n]))
  11740. n++;
  11741. np = soap->nlist;
  11742. /* if there is no namespace stack, or prefix is "xml" then copy string */
  11743. if (!np || !strncmp(s, "xml:", 4))
  11744. { soap_append_lab(soap, s, n);
  11745. }
  11746. else /* we normalize the QName by replacing its prefix */
  11747. { for (p = s; *p && p < s + n; p++)
  11748. if (*p == ':')
  11749. break;
  11750. if (*p == ':')
  11751. { size_t k = p - s;
  11752. while (np && (strncmp(np->id, s, k) || np->id[k]))
  11753. np = np->next;
  11754. p++;
  11755. }
  11756. else
  11757. { while (np && *np->id)
  11758. np = np->next;
  11759. p = s;
  11760. }
  11761. /* replace prefix */
  11762. if (np)
  11763. { if (np->index >= 0 && soap->local_namespaces)
  11764. { const char *q = soap->local_namespaces[np->index].id;
  11765. if (q)
  11766. soap_append_lab(soap, q, strlen(q));
  11767. }
  11768. else if (np->ns)
  11769. { soap_append_lab(soap, "\"", 1);
  11770. soap_append_lab(soap, np->ns, strlen(np->ns));
  11771. soap_append_lab(soap, "\"", 1);
  11772. }
  11773. else
  11774. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\nNamespace prefix of '%s' not defined (index=%d, URI=%s)\n", s, np->index, np->ns?np->ns:SOAP_STR_EOS));
  11775. return soap->error = SOAP_NAMESPACE;
  11776. }
  11777. }
  11778. else if (s[n]) /* no namespace, part of string */
  11779. { soap_append_lab(soap, s, n);
  11780. }
  11781. else /* no namespace: assume "" namespace */
  11782. { soap_append_lab(soap, "\"\"", 2);
  11783. }
  11784. soap_append_lab(soap, ":", 1);
  11785. soap_append_lab(soap, p, n - (p-s));
  11786. }
  11787. /* advance to next and add spacing */
  11788. s += n;
  11789. if (*s)
  11790. soap_append_lab(soap, " ", 1);
  11791. }
  11792. soap_append_lab(soap, SOAP_STR_EOS, 1);
  11793. *t = soap_strdup(soap, soap->labbuf);
  11794. DBGLOG(TEST, SOAP_MESSAGE(fdebug, " into '%s'\n", *t));
  11795. }
  11796. return soap->error;
  11797. }
  11798. #endif
  11799. /******************************************************************************/
  11800. #ifndef PALM_2
  11801. SOAP_FMAC1
  11802. const char*
  11803. SOAP_FMAC2
  11804. soap_QName2s(struct soap *soap, const char *s)
  11805. { const char *t = NULL;
  11806. if (s)
  11807. { soap->labidx = 0;
  11808. for (;;)
  11809. { size_t n;
  11810. /* skip blanks */
  11811. while (*s && soap_blank(*s))
  11812. s++;
  11813. if (!*s)
  11814. break;
  11815. /* find next QName */
  11816. n = 1;
  11817. while (s[n] && !soap_blank(s[n]))
  11818. n++;
  11819. /* normal prefix: pass string as is */
  11820. if (*s != '"')
  11821. { soap_append_lab(soap, s, n);
  11822. #ifndef WITH_LEAN
  11823. if ((soap->mode & SOAP_XML_CANONICAL))
  11824. { const char *r = strchr(s, ':');
  11825. if (r)
  11826. soap_utilize_ns(soap, s, r - s);
  11827. }
  11828. #endif
  11829. }
  11830. else /* URL-based string prefix */
  11831. { const char *q;
  11832. s++;
  11833. q = strchr(s, '"');
  11834. if (q)
  11835. { struct Namespace *p = soap->local_namespaces;
  11836. if (p)
  11837. { for (; p->id; p++)
  11838. { if (p->ns)
  11839. if (!soap_tag_cmp(s, p->ns))
  11840. break;
  11841. if (p->in)
  11842. if (!soap_tag_cmp(s, p->in))
  11843. break;
  11844. }
  11845. }
  11846. /* URL is in the namespace table? */
  11847. if (p && p->id)
  11848. { soap_append_lab(soap, p->id, strlen(p->id));
  11849. }
  11850. else /* not in namespace table: create xmlns binding */
  11851. { char *r = soap_strdup(soap, s);
  11852. r[q-s] = '\0';
  11853. sprintf(soap->tmpbuf, "xmlns:_%d", soap->idnum++);
  11854. soap_set_attr(soap, soap->tmpbuf, r, 1);
  11855. soap_append_lab(soap, soap->tmpbuf + 6, strlen(soap->tmpbuf + 6));
  11856. }
  11857. soap_append_lab(soap, q + 1, n - (q-s) - 1);
  11858. }
  11859. }
  11860. /* advance to next and add spacing */
  11861. s += n;
  11862. if (*s)
  11863. soap_append_lab(soap, " ", 1);
  11864. }
  11865. soap_append_lab(soap, SOAP_STR_EOS, 1);
  11866. t = soap_strdup(soap, soap->labbuf);
  11867. }
  11868. return t;
  11869. }
  11870. #endif
  11871. /******************************************************************************/
  11872. #ifndef WITH_LEAN
  11873. SOAP_FMAC1
  11874. int
  11875. SOAP_FMAC2
  11876. soap_s2wchar(struct soap *soap, const char *s, wchar_t **t, long minlen, long maxlen)
  11877. { if (s)
  11878. { long l;
  11879. wchar_t *r;
  11880. *t = r = (wchar_t*)soap_malloc(soap, sizeof(wchar_t) * (strlen(s) + 1));
  11881. if (!r)
  11882. return soap->error = SOAP_EOM;
  11883. if (soap->mode & SOAP_ENC_LATIN)
  11884. { while (*s)
  11885. *r++ = (wchar_t)*s++;
  11886. }
  11887. else
  11888. { /* Convert UTF8 to wchar */
  11889. while (*s)
  11890. { register soap_wchar c, c1, c2, c3, c4;
  11891. c = (unsigned char)*s++;
  11892. if (c < 0x80)
  11893. *r++ = (wchar_t)c;
  11894. else
  11895. { c1 = (soap_wchar)*s++ & 0x3F;
  11896. if (c < 0xE0)
  11897. *r++ = (wchar_t)(((soap_wchar)(c & 0x1F) << 6) | c1);
  11898. else
  11899. { c2 = (soap_wchar)*s++ & 0x3F;
  11900. if (c < 0xF0)
  11901. *r++ = (wchar_t)(((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2);
  11902. else
  11903. { c3 = (soap_wchar)*s++ & 0x3F;
  11904. if (c < 0xF8)
  11905. *r++ = (wchar_t)(((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3);
  11906. else
  11907. { c4 = (soap_wchar)*s++ & 0x3F;
  11908. if (c < 0xFC)
  11909. *r++ = (wchar_t)(((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4);
  11910. else
  11911. *r++ = (wchar_t)(((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(*s++ & 0x3F));
  11912. }
  11913. }
  11914. }
  11915. }
  11916. }
  11917. }
  11918. *r = L'\0';
  11919. l = (long)(r - *t);
  11920. if ((maxlen >= 0 && l > maxlen) || l < minlen)
  11921. return soap->error = SOAP_LENGTH;
  11922. }
  11923. return soap->error;
  11924. }
  11925. #endif
  11926. /******************************************************************************/
  11927. #ifndef WITH_LEAN
  11928. SOAP_FMAC1
  11929. const char*
  11930. SOAP_FMAC2
  11931. soap_wchar2s(struct soap *soap, const wchar_t *s)
  11932. { register soap_wchar c;
  11933. register char *r, *t;
  11934. const wchar_t *q = s;
  11935. size_t n = 0;
  11936. while ((c = *q++))
  11937. { if (c > 0 && c < 0x80)
  11938. n++;
  11939. else
  11940. n += 6;
  11941. }
  11942. r = t = (char*)soap_malloc(soap, n + 1);
  11943. if (r)
  11944. { /* Convert wchar to UTF8 */
  11945. while ((c = *s++))
  11946. { if (c > 0 && c < 0x80)
  11947. *t++ = (char)c;
  11948. else
  11949. { if (c < 0x0800)
  11950. *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
  11951. else
  11952. { if (c < 0x010000)
  11953. *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
  11954. else
  11955. { if (c < 0x200000)
  11956. *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
  11957. else
  11958. { if (c < 0x04000000)
  11959. *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
  11960. else
  11961. { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
  11962. *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
  11963. }
  11964. *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
  11965. }
  11966. *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
  11967. }
  11968. *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
  11969. }
  11970. *t++ = (char)(0x80 | (c & 0x3F));
  11971. }
  11972. }
  11973. *t = '\0';
  11974. }
  11975. return r;
  11976. }
  11977. #endif
  11978. /******************************************************************************/
  11979. #ifndef PALM_2
  11980. SOAP_FMAC1
  11981. int
  11982. SOAP_FMAC2
  11983. soap_outstring(struct soap *soap, const char *tag, int id, char *const*p, const char *type, int n)
  11984. { id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n);
  11985. if (id < 0)
  11986. return soap->error;
  11987. if (!**p && (soap->mode & SOAP_C_NILSTRING))
  11988. return soap_element_null(soap, tag, id, type);
  11989. if (soap_element_begin_out(soap, tag, id, type)
  11990. || soap_string_out(soap, *p, 0)
  11991. || soap_element_end_out(soap, tag))
  11992. return soap->error;
  11993. return SOAP_OK;
  11994. }
  11995. #endif
  11996. /******************************************************************************/
  11997. #ifndef PALM_2
  11998. SOAP_FMAC1
  11999. char **
  12000. SOAP_FMAC2
  12001. soap_instring(struct soap *soap, const char *tag, char **p, const char *type, int t, int flag, long minlen, long maxlen)
  12002. { if (soap_element_begin_in(soap, tag, 1, NULL))
  12003. { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG)
  12004. return NULL;
  12005. soap->error = SOAP_OK;
  12006. }
  12007. if (!p)
  12008. { if (!(p = (char**)soap_malloc(soap, sizeof(char*))))
  12009. return NULL;
  12010. }
  12011. if (soap->null)
  12012. *p = NULL;
  12013. else if (soap->body)
  12014. { *p = soap_string_in(soap, flag, minlen, maxlen);
  12015. if (!*p || !(char*)soap_id_enter(soap, soap->id, *p, t, sizeof(char*), 0, NULL, NULL, NULL))
  12016. return NULL;
  12017. if (!**p && tag && *tag == '-')
  12018. { soap->error = SOAP_NO_TAG;
  12019. return NULL;
  12020. }
  12021. }
  12022. else if (tag && *tag == '-')
  12023. { soap->error = SOAP_NO_TAG;
  12024. return NULL;
  12025. }
  12026. else if (!*soap->href && minlen > 0)
  12027. { soap->error = SOAP_LENGTH;
  12028. return NULL;
  12029. }
  12030. else
  12031. *p = soap_strdup(soap, SOAP_STR_EOS);
  12032. if (*soap->href)
  12033. p = (char**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(char**), 0);
  12034. if (soap->body && soap_element_end_in(soap, tag))
  12035. return NULL;
  12036. return p;
  12037. }
  12038. #endif
  12039. /******************************************************************************/
  12040. #ifndef WITH_LEANER
  12041. #ifndef PALM_2
  12042. SOAP_FMAC1
  12043. int
  12044. SOAP_FMAC2
  12045. soap_outwstring(struct soap *soap, const char *tag, int id, wchar_t *const*p, const char *type, int n)
  12046. { id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n);
  12047. if (id < 0)
  12048. return soap->error;
  12049. if (!**p && (soap->mode & SOAP_C_NILSTRING))
  12050. return soap_element_null(soap, tag, id, type);
  12051. if (soap_element_begin_out(soap, tag, id, type)
  12052. || soap_wstring_out(soap, *p, 0)
  12053. || soap_element_end_out(soap, tag))
  12054. return soap->error;
  12055. return SOAP_OK;
  12056. }
  12057. #endif
  12058. #endif
  12059. /******************************************************************************/
  12060. #ifndef WITH_LEANER
  12061. #ifndef PALM_2
  12062. SOAP_FMAC1
  12063. wchar_t **
  12064. SOAP_FMAC2
  12065. soap_inwstring(struct soap *soap, const char *tag, wchar_t **p, const char *type, int t, long minlen, long maxlen)
  12066. { if (soap_element_begin_in(soap, tag, 1, NULL))
  12067. { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG)
  12068. return NULL;
  12069. soap->error = SOAP_OK;
  12070. }
  12071. if (!p)
  12072. { if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*))))
  12073. return NULL;
  12074. }
  12075. if (soap->body)
  12076. { *p = soap_wstring_in(soap, 1, minlen, maxlen);
  12077. if (!*p || !(wchar_t*)soap_id_enter(soap, soap->id, *p, t, sizeof(wchar_t*), 0, NULL, NULL, NULL))
  12078. return NULL;
  12079. if (!**p && tag && *tag == '-')
  12080. { soap->error = SOAP_NO_TAG;
  12081. return NULL;
  12082. }
  12083. }
  12084. else if (tag && *tag == '-')
  12085. { soap->error = SOAP_NO_TAG;
  12086. return NULL;
  12087. }
  12088. else if (soap->null)
  12089. *p = NULL;
  12090. else
  12091. *p = soap_wstrdup(soap, (wchar_t*)SOAP_STR_EOS);
  12092. if (*soap->href)
  12093. p = (wchar_t**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(wchar_t**), 0);
  12094. if (soap->body && soap_element_end_in(soap, tag))
  12095. return NULL;
  12096. return p;
  12097. }
  12098. #endif
  12099. #endif
  12100. /******************************************************************************/
  12101. #ifndef WITH_LEAN
  12102. SOAP_FMAC1
  12103. time_t
  12104. SOAP_FMAC2
  12105. soap_timegm(struct tm *T)
  12106. {
  12107. #if defined(HAVE_TIMEGM)
  12108. return timegm(T);
  12109. #else
  12110. time_t t, g, z;
  12111. struct tm tm;
  12112. t = mktime(T);
  12113. if (t == (time_t)-1)
  12114. return (time_t)-1;
  12115. #ifdef HAVE_GMTIME_R
  12116. gmtime_r(&t, &tm);
  12117. #else
  12118. tm = *gmtime(&t);
  12119. #endif
  12120. tm.tm_isdst = 0;
  12121. g = mktime(&tm);
  12122. if (g == (time_t)-1)
  12123. return (time_t)-1;
  12124. z = g - t;
  12125. return t - z;
  12126. #endif
  12127. }
  12128. #endif
  12129. /******************************************************************************/
  12130. #ifndef WITH_LEAN
  12131. SOAP_FMAC1
  12132. const char*
  12133. SOAP_FMAC2
  12134. soap_dateTime2s(struct soap *soap, time_t n)
  12135. { struct tm T, *pT = &T;
  12136. #if defined(HAVE_GMTIME_R)
  12137. if (gmtime_r(&n, pT))
  12138. strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT);
  12139. #elif defined(HAVE_GMTIME)
  12140. if ((pT = gmtime(&n)))
  12141. strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT);
  12142. #elif defined(HAVE_GETTIMEOFDAY)
  12143. struct timezone tz;
  12144. memset((void*)&tz, 0, sizeof(tz));
  12145. #if defined(HAVE_LOCALTIME_R)
  12146. if (localtime_r(&n, pT))
  12147. { struct timeval tv;
  12148. gettimeofday(&tv, &tz);
  12149. strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
  12150. sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60);
  12151. }
  12152. #else
  12153. if ((pT = localtime(&n)))
  12154. { struct timeval tv;
  12155. gettimeofday(&tv, &tz);
  12156. strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
  12157. sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60);
  12158. }
  12159. #endif
  12160. #elif defined(HAVE_FTIME)
  12161. struct timeb t;
  12162. memset((void*)&t, 0, sizeof(t));
  12163. #if defined(HAVE_LOCALTIME_R)
  12164. if (localtime_r(&n, pT))
  12165. {
  12166. #ifdef __BORLANDC__
  12167. ::ftime(&t);
  12168. #else
  12169. ftime(&t);
  12170. #endif
  12171. strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
  12172. sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60);
  12173. }
  12174. #else
  12175. if ((pT = localtime(&n)))
  12176. {
  12177. #ifdef __BORLANDC__
  12178. ::ftime(&t);
  12179. #else
  12180. ftime(&t);
  12181. #endif
  12182. strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
  12183. sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60);
  12184. }
  12185. #endif
  12186. #elif defined(HAVE_LOCALTIME_R)
  12187. if (localtime_r(&n, pT))
  12188. strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
  12189. #else
  12190. if ((pT = localtime(&n)))
  12191. strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
  12192. #endif
  12193. else
  12194. strcpy(soap->tmpbuf, "1969-12-31T23:59:59Z");
  12195. return soap->tmpbuf;
  12196. }
  12197. #endif
  12198. /******************************************************************************/
  12199. #ifndef WITH_LEAN
  12200. SOAP_FMAC1
  12201. int
  12202. SOAP_FMAC2
  12203. soap_outdateTime(struct soap *soap, const char *tag, int id, const time_t *p, const char *type, int n)
  12204. { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
  12205. || soap_string_out(soap, soap_dateTime2s(soap, *p), 0))
  12206. return soap->error;
  12207. return soap_element_end_out(soap, tag);
  12208. }
  12209. #endif
  12210. /******************************************************************************/
  12211. #ifndef WITH_LEAN
  12212. SOAP_FMAC1
  12213. int
  12214. SOAP_FMAC2
  12215. soap_s2dateTime(struct soap *soap, const char *s, time_t *p)
  12216. { if (s)
  12217. { char zone[32];
  12218. struct tm T;
  12219. const char *t;
  12220. *zone = '\0';
  12221. memset((void*)&T, 0, sizeof(T));
  12222. if (strchr(s, '-'))
  12223. t = "%d-%d-%dT%d:%d:%d%31s";
  12224. else if (strchr(s, ':'))
  12225. t = "%4d%2d%2dT%d:%d:%d%31s";
  12226. else /* parse non-XSD-standard alternative ISO 8601 format */
  12227. t = "%4d%2d%2dT%2d%2d%2d%31s";
  12228. if (sscanf(s, t, &T.tm_year, &T.tm_mon, &T.tm_mday, &T.tm_hour, &T.tm_min, &T.tm_sec, zone) < 6)
  12229. return soap->error = SOAP_TYPE;
  12230. if (T.tm_year == 1)
  12231. T.tm_year = 70;
  12232. else
  12233. T.tm_year -= 1900;
  12234. T.tm_mon--;
  12235. if (*zone == '.')
  12236. { for (s = zone + 1; *s; s++)
  12237. if (*s < '0' || *s > '9')
  12238. break;
  12239. }
  12240. else
  12241. s = zone;
  12242. if (*s)
  12243. {
  12244. #ifndef WITH_NOZONE
  12245. if (*s == '+' || *s == '-')
  12246. { int h = 0, m = 0;
  12247. if (s[3] == ':')
  12248. { /* +hh:mm */
  12249. sscanf(s, "%d:%d", &h, &m);
  12250. if (h < 0)
  12251. m = -m;
  12252. }
  12253. else /* +hhmm */
  12254. { m = (int)soap_strtol(s, NULL, 10);
  12255. h = m / 100;
  12256. m = m % 100;
  12257. }
  12258. T.tm_min -= m;
  12259. T.tm_hour -= h;
  12260. /* put hour and min in range */
  12261. T.tm_hour += T.tm_min / 60;
  12262. T.tm_min %= 60;
  12263. if (T.tm_min < 0)
  12264. { T.tm_min += 60;
  12265. T.tm_hour--;
  12266. }
  12267. T.tm_mday += T.tm_hour / 24;
  12268. T.tm_hour %= 24;
  12269. if (T.tm_hour < 0)
  12270. { T.tm_hour += 24;
  12271. T.tm_mday--;
  12272. }
  12273. /* note: day of the month may be out of range, timegm() handles it */
  12274. }
  12275. #endif
  12276. *p = soap_timegm(&T);
  12277. }
  12278. else /* no UTC or timezone, so assume we got a localtime */
  12279. { T.tm_isdst = -1;
  12280. *p = mktime(&T);
  12281. }
  12282. }
  12283. return soap->error;
  12284. }
  12285. #endif
  12286. /******************************************************************************/
  12287. #ifndef WITH_LEAN
  12288. SOAP_FMAC1
  12289. time_t *
  12290. SOAP_FMAC2
  12291. soap_indateTime(struct soap *soap, const char *tag, time_t *p, const char *type, int t)
  12292. { if (soap_element_begin_in(soap, tag, 0, NULL))
  12293. return NULL;
  12294. if (*soap->type
  12295. && soap_match_tag(soap, soap->type, type)
  12296. && soap_match_tag(soap, soap->type, ":dateTime"))
  12297. { soap->error = SOAP_TYPE;
  12298. soap_revert(soap);
  12299. return NULL;
  12300. }
  12301. p = (time_t*)soap_id_enter(soap, soap->id, p, t, sizeof(time_t), 0, NULL, NULL, NULL);
  12302. if (*soap->href)
  12303. p = (time_t*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(time_t), 0, NULL);
  12304. else if (p)
  12305. { if (soap_s2dateTime(soap, soap_value(soap), p))
  12306. return NULL;
  12307. }
  12308. if (soap->body && soap_element_end_in(soap, tag))
  12309. return NULL;
  12310. return p;
  12311. }
  12312. #endif
  12313. /******************************************************************************/
  12314. #ifndef PALM_2
  12315. SOAP_FMAC1
  12316. int
  12317. SOAP_FMAC2
  12318. soap_outliteral(struct soap *soap, const char *tag, char *const*p, const char *type)
  12319. { int i;
  12320. const char *t = NULL;
  12321. if (tag && *tag != '-')
  12322. { if (soap->local_namespaces && (t = strchr(tag, ':')))
  12323. { strncpy(soap->tmpbuf, tag, t-tag);
  12324. soap->tmpbuf[t-tag] = '\0';
  12325. for (i = 0; soap->local_namespaces[i].id; i++)
  12326. if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id))
  12327. break;
  12328. t++;
  12329. if (soap_element(soap, t, 0, type)
  12330. || soap_attribute(soap, "xmlns", soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS)
  12331. || soap_element_start_end_out(soap, NULL))
  12332. return soap->error;
  12333. }
  12334. else
  12335. { t = tag;
  12336. if (soap_element_begin_out(soap, t, 0, type))
  12337. return soap->error;
  12338. }
  12339. }
  12340. if (p && *p)
  12341. { if (soap_send(soap, *p))
  12342. return soap->error;
  12343. }
  12344. if (t)
  12345. return soap_element_end_out(soap, t);
  12346. return SOAP_OK;
  12347. }
  12348. #endif
  12349. /******************************************************************************/
  12350. #ifndef PALM_2
  12351. SOAP_FMAC1
  12352. char **
  12353. SOAP_FMAC2
  12354. soap_inliteral(struct soap *soap, const char *tag, char **p)
  12355. { if (soap_element_begin_in(soap, tag, 1, NULL))
  12356. { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT)
  12357. return NULL;
  12358. soap->error = SOAP_OK;
  12359. }
  12360. if (!p)
  12361. { if (!(p = (char**)soap_malloc(soap, sizeof(char*))))
  12362. return NULL;
  12363. }
  12364. if (soap->body || (tag && *tag == '-'))
  12365. { *p = soap_string_in(soap, 0, -1, -1);
  12366. if (!*p)
  12367. return NULL;
  12368. if (!**p && tag && *tag == '-')
  12369. { soap->error = SOAP_NO_TAG;
  12370. return NULL;
  12371. }
  12372. }
  12373. else if (soap->null)
  12374. *p = NULL;
  12375. else
  12376. *p = soap_strdup(soap, SOAP_STR_EOS);
  12377. if (soap->body && soap_element_end_in(soap, tag))
  12378. return NULL;
  12379. return p;
  12380. }
  12381. #endif
  12382. /******************************************************************************/
  12383. #ifndef WITH_LEANER
  12384. #ifndef PALM_2
  12385. SOAP_FMAC1
  12386. int
  12387. SOAP_FMAC2
  12388. soap_outwliteral(struct soap *soap, const char *tag, wchar_t *const*p, const char *type)
  12389. { int i;
  12390. const char *t = NULL;
  12391. if (tag && *tag != '-')
  12392. { if (soap->local_namespaces && (t = strchr(tag, ':')))
  12393. { strncpy(soap->tmpbuf, tag, t-tag);
  12394. soap->tmpbuf[t-tag] = '\0';
  12395. for (i = 0; soap->local_namespaces[i].id; i++)
  12396. if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id))
  12397. break;
  12398. t++;
  12399. if (soap_element(soap, t, 0, type)
  12400. || soap_attribute(soap, "xmlns", soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS)
  12401. || soap_element_start_end_out(soap, NULL))
  12402. return soap->error;
  12403. }
  12404. else
  12405. { t = tag;
  12406. if (soap_element_begin_out(soap, t, 0, type))
  12407. return soap->error;
  12408. }
  12409. if (soap_send(soap, soap->tmpbuf))
  12410. return soap->error;
  12411. }
  12412. if (p)
  12413. { wchar_t c;
  12414. const wchar_t *s = *p;
  12415. while ((c = *s++))
  12416. { if (soap_pututf8(soap, (unsigned long)c))
  12417. return soap->error;
  12418. }
  12419. }
  12420. if (t)
  12421. return soap_element_end_out(soap, t);
  12422. return SOAP_OK;
  12423. }
  12424. #endif
  12425. #endif
  12426. /******************************************************************************/
  12427. #ifndef WITH_LEANER
  12428. #ifndef PALM_2
  12429. SOAP_FMAC1
  12430. wchar_t **
  12431. SOAP_FMAC2
  12432. soap_inwliteral(struct soap *soap, const char *tag, wchar_t **p)
  12433. { if (soap_element_begin_in(soap, tag, 1, NULL))
  12434. { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT)
  12435. return NULL;
  12436. soap->error = SOAP_OK;
  12437. }
  12438. if (!p)
  12439. { if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*))))
  12440. return NULL;
  12441. }
  12442. if (soap->body)
  12443. { *p = soap_wstring_in(soap, 0, -1, -1);
  12444. if (!*p)
  12445. return NULL;
  12446. if (!**p && tag && *tag == '-')
  12447. { soap->error = SOAP_NO_TAG;
  12448. return NULL;
  12449. }
  12450. }
  12451. else if (tag && *tag == '-')
  12452. { soap->error = SOAP_NO_TAG;
  12453. return NULL;
  12454. }
  12455. else if (soap->null)
  12456. *p = NULL;
  12457. else
  12458. *p = soap_wstrdup(soap, (wchar_t*)SOAP_STR_EOS);
  12459. if (soap->body && soap_element_end_in(soap, tag))
  12460. return NULL;
  12461. return p;
  12462. }
  12463. #endif
  12464. #endif
  12465. /******************************************************************************/
  12466. #ifndef PALM_2
  12467. SOAP_FMAC1
  12468. const char *
  12469. SOAP_FMAC2
  12470. soap_value(struct soap *soap)
  12471. { register size_t i;
  12472. register soap_wchar c = 0;
  12473. register char *s = soap->tmpbuf;
  12474. if (!soap->body)
  12475. return SOAP_STR_EOS;
  12476. do c = soap_get(soap);
  12477. while (soap_blank(c));
  12478. for (i = 0; i < sizeof(soap->tmpbuf) - 1; i++)
  12479. { if (c == SOAP_TT || c == SOAP_LT || (int)c == EOF)
  12480. break;
  12481. *s++ = (char)c;
  12482. c = soap_get(soap);
  12483. }
  12484. for (s--; i > 0; i--, s--)
  12485. { if (!soap_blank(*s))
  12486. break;
  12487. }
  12488. s[1] = '\0';
  12489. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element content value='%s'\n", soap->tmpbuf));
  12490. if (c == SOAP_TT || c == SOAP_LT || (int)c == EOF)
  12491. soap_unget(soap, c);
  12492. else if (soap->mode & SOAP_XML_STRICT)
  12493. { soap->error = SOAP_LENGTH;
  12494. return NULL;
  12495. }
  12496. #ifdef WITH_DOM
  12497. if ((soap->mode & SOAP_XML_DOM) && soap->dom)
  12498. soap->dom->data = soap_strdup(soap, soap->tmpbuf);
  12499. #endif
  12500. return soap->tmpbuf; /* return non-null pointer */
  12501. }
  12502. #endif
  12503. /******************************************************************************/
  12504. #if !defined(WITH_LEANER) || !defined(WITH_NOHTTP)
  12505. #ifndef PALM_2
  12506. SOAP_FMAC1
  12507. int
  12508. SOAP_FMAC2
  12509. soap_getline(struct soap *soap, char *s, int len)
  12510. { int i = len;
  12511. soap_wchar c = 0;
  12512. for (;;)
  12513. { while (--i > 0)
  12514. { c = soap_getchar(soap);
  12515. if (c == '\r' || c == '\n')
  12516. break;
  12517. if ((int)c == EOF)
  12518. return soap->error = SOAP_EOF;
  12519. *s++ = (char)c;
  12520. }
  12521. if (c != '\n')
  12522. c = soap_getchar(soap); /* got \r or something else, now get \n */
  12523. if (c == '\n')
  12524. { *s = '\0';
  12525. if (i+1 == len) /* empty line: end of HTTP/MIME header */
  12526. break;
  12527. c = soap_get0(soap);
  12528. if (c != ' ' && c != '\t') /* HTTP line continuation? */
  12529. break;
  12530. }
  12531. else if ((int)c == EOF)
  12532. return soap->error = SOAP_EOF;
  12533. if (i < 0)
  12534. return soap->error = SOAP_HDR;
  12535. }
  12536. return SOAP_OK;
  12537. }
  12538. #endif
  12539. #endif
  12540. /******************************************************************************/
  12541. #ifndef PALM_1
  12542. static size_t
  12543. soap_count_attachments(struct soap *soap)
  12544. {
  12545. #ifndef WITH_LEANER
  12546. register struct soap_multipart *content;
  12547. register size_t count = soap->count;
  12548. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the message size with attachments, current count=%lu\n", (unsigned long)count));
  12549. if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
  12550. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of DIME attachments\n"));
  12551. for (content = soap->dime.first; content; content = content->next)
  12552. { count += 12 + ((content->size+3)&(~3));
  12553. if (content->id)
  12554. count += ((strlen(content->id)+3)&(~3));
  12555. if (content->type)
  12556. count += ((strlen(content->type)+3)&(~3));
  12557. if (content->options)
  12558. count += ((((unsigned char)content->options[2] << 8) | ((unsigned char)content->options[3]))+7)&(~3);
  12559. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of DIME attachment content is %lu bytes\n", (unsigned long)content->size));
  12560. }
  12561. }
  12562. if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary)
  12563. { register size_t n = strlen(soap->mime.boundary);
  12564. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of MIME attachments\n"));
  12565. for (content = soap->mime.first; content; content = content->next)
  12566. { register const char *s;
  12567. /* count \r\n--boundary\r\n */
  12568. count += 6 + n;
  12569. /* count Content-Type: ...\r\n */
  12570. if (content->type)
  12571. count += 16 + strlen(content->type);
  12572. /* count Content-Transfer-Encoding: ...\r\n */
  12573. s = soap_code_str(mime_codes, content->encoding);
  12574. if (s)
  12575. count += 29 + strlen(s);
  12576. /* count Content-ID: ...\r\n */
  12577. if (content->id)
  12578. count += 14 + strlen(content->id);
  12579. /* count Content-Location: ...\r\n */
  12580. if (content->location)
  12581. count += 20 + strlen(content->location);
  12582. /* count Content-Description: ...\r\n */
  12583. if (content->description)
  12584. count += 23 + strlen(content->description);
  12585. /* count \r\n...content */
  12586. count += 2 + content->size;
  12587. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of MIME attachment content is %lu bytes\n", (unsigned long)content->size));
  12588. }
  12589. /* count \r\n--boundary-- */
  12590. count += 6 + n;
  12591. }
  12592. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New count is %lu bytes\n", (unsigned long)count));
  12593. return count;
  12594. #else
  12595. return soap->count;
  12596. #endif
  12597. }
  12598. #endif
  12599. /******************************************************************************/
  12600. #ifndef WITH_LEANER
  12601. #ifndef PALM_1
  12602. static int
  12603. soap_putdimefield(struct soap *soap, const char *s, size_t n)
  12604. { if (soap_send_raw(soap, s, n))
  12605. return soap->error;
  12606. return soap_send_raw(soap, SOAP_STR_PADDING, -(long)n&3);
  12607. }
  12608. #endif
  12609. #endif
  12610. /******************************************************************************/
  12611. #ifndef WITH_LEANER
  12612. #ifndef PALM_1
  12613. SOAP_FMAC1
  12614. char *
  12615. SOAP_FMAC2
  12616. soap_dime_option(struct soap *soap, unsigned short optype, const char *option)
  12617. { size_t n;
  12618. char *s = NULL;
  12619. if (option)
  12620. { n = strlen(option);
  12621. s = (char*)soap_malloc(soap, n + 5);
  12622. if (s)
  12623. { s[0] = (char)(optype >> 8);
  12624. s[1] = (char)(optype & 0xFF);
  12625. s[2] = (char)(n >> 8);
  12626. s[3] = (char)(n & 0xFF);
  12627. strcpy(s + 4, option);
  12628. }
  12629. }
  12630. return s;
  12631. }
  12632. #endif
  12633. #endif
  12634. /******************************************************************************/
  12635. #ifndef WITH_LEANER
  12636. #ifndef PALM_1
  12637. SOAP_FMAC1
  12638. int
  12639. SOAP_FMAC2
  12640. soap_putdimehdr(struct soap *soap)
  12641. { unsigned char tmp[12];
  12642. size_t optlen = 0, idlen = 0, typelen = 0;
  12643. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Put DIME header id='%s'\n", soap->dime.id?soap->dime.id:SOAP_STR_EOS));
  12644. if (soap->dime.options)
  12645. optlen = (((unsigned char)soap->dime.options[2] << 8) | ((unsigned char)soap->dime.options[3])) + 4;
  12646. if (soap->dime.id)
  12647. { idlen = strlen(soap->dime.id);
  12648. if (idlen > 0x0000FFFF)
  12649. idlen = 0x0000FFFF;
  12650. }
  12651. if (soap->dime.type)
  12652. { typelen = strlen(soap->dime.type);
  12653. if (typelen > 0x0000FFFF)
  12654. typelen = 0x0000FFFF;
  12655. }
  12656. tmp[0] = SOAP_DIME_VERSION | (soap->dime.flags & 0x7);
  12657. tmp[1] = soap->dime.flags & 0xF0;
  12658. tmp[2] = (char)(optlen >> 8);
  12659. tmp[3] = (char)(optlen & 0xFF);
  12660. tmp[4] = (char)(idlen >> 8);
  12661. tmp[5] = (char)(idlen & 0xFF);
  12662. tmp[6] = (char)(typelen >> 8);
  12663. tmp[7] = (char)(typelen & 0xFF);
  12664. tmp[8] = (char)(soap->dime.size >> 24);
  12665. tmp[9] = (char)((soap->dime.size >> 16) & 0xFF);
  12666. tmp[10] = (char)((soap->dime.size >> 8) & 0xFF);
  12667. tmp[11] = (char)(soap->dime.size & 0xFF);
  12668. if (soap_send_raw(soap, (char*)tmp, 12)
  12669. || soap_putdimefield(soap, soap->dime.options, optlen)
  12670. || soap_putdimefield(soap, soap->dime.id, idlen)
  12671. || soap_putdimefield(soap, soap->dime.type, typelen))
  12672. return soap->error;
  12673. return SOAP_OK;
  12674. }
  12675. #endif
  12676. #endif
  12677. /******************************************************************************/
  12678. #ifndef WITH_LEANER
  12679. #ifndef PALM_1
  12680. SOAP_FMAC1
  12681. int
  12682. SOAP_FMAC2
  12683. soap_putdime(struct soap *soap)
  12684. { struct soap_multipart *content;
  12685. if (!(soap->mode & SOAP_ENC_DIME))
  12686. return SOAP_OK;
  12687. for (content = soap->dime.first; content; content = content->next)
  12688. { void *handle;
  12689. soap->dime.size = content->size;
  12690. soap->dime.id = content->id;
  12691. soap->dime.type = content->type;
  12692. soap->dime.options = content->options;
  12693. soap->dime.flags = SOAP_DIME_VERSION | SOAP_DIME_MEDIA;
  12694. if (soap->fdimereadopen && ((handle = soap->fdimereadopen(soap, (void*)content->ptr, content->id, content->type, content->options)) || soap->error))
  12695. { size_t size = content->size;
  12696. if (!handle)
  12697. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadopen failed\n"));
  12698. return soap->error;
  12699. }
  12700. if (!size && ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE))
  12701. { size_t chunksize = sizeof(soap->tmpbuf);
  12702. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming DIME\n"));
  12703. do
  12704. { size = soap->fdimeread(soap, handle, soap->tmpbuf, chunksize);
  12705. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread returned %lu bytes\n", (unsigned long)size));
  12706. if (size < chunksize)
  12707. { soap->dime.flags &= ~SOAP_DIME_CF;
  12708. if (!content->next)
  12709. soap->dime.flags |= SOAP_DIME_ME;
  12710. }
  12711. else
  12712. soap->dime.flags |= SOAP_DIME_CF;
  12713. soap->dime.size = size;
  12714. if (soap_putdimehdr(soap)
  12715. || soap_putdimefield(soap, soap->tmpbuf, size))
  12716. break;
  12717. if (soap->dime.id)
  12718. { soap->dime.flags &= ~(SOAP_DIME_MB | SOAP_DIME_MEDIA);
  12719. soap->dime.id = NULL;
  12720. soap->dime.type = NULL;
  12721. soap->dime.options = NULL;
  12722. }
  12723. } while (size >= chunksize);
  12724. }
  12725. else
  12726. { if (!content->next)
  12727. soap->dime.flags |= SOAP_DIME_ME;
  12728. if (soap_putdimehdr(soap))
  12729. return soap->error;
  12730. do
  12731. { size_t bufsize;
  12732. if (size < sizeof(soap->tmpbuf))
  12733. bufsize = size;
  12734. else
  12735. bufsize = sizeof(soap->tmpbuf);
  12736. if (!(bufsize = soap->fdimeread(soap, handle, soap->tmpbuf, bufsize)))
  12737. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size));
  12738. soap->error = SOAP_EOF;
  12739. break;
  12740. }
  12741. if (soap_send_raw(soap, soap->tmpbuf, bufsize))
  12742. break;
  12743. size -= bufsize;
  12744. } while (size);
  12745. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n"));
  12746. soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3);
  12747. }
  12748. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n"));
  12749. if (soap->fdimereadclose)
  12750. soap->fdimereadclose(soap, handle);
  12751. }
  12752. else
  12753. { if (!content->next)
  12754. soap->dime.flags |= SOAP_DIME_ME;
  12755. if (soap_putdimehdr(soap)
  12756. || soap_putdimefield(soap, (char*)content->ptr, content->size))
  12757. return soap->error;
  12758. }
  12759. }
  12760. return SOAP_OK;
  12761. }
  12762. #endif
  12763. #endif
  12764. /******************************************************************************/
  12765. #ifndef WITH_LEANER
  12766. #ifndef PALM_1
  12767. static char *
  12768. soap_getdimefield(struct soap *soap, size_t n)
  12769. { register soap_wchar c;
  12770. register size_t i;
  12771. register char *s;
  12772. register char *p = NULL;
  12773. if (n)
  12774. { p = (char*)soap_malloc(soap, n + 1);
  12775. if (p)
  12776. { s = p;
  12777. for (i = n; i > 0; i--)
  12778. { if ((int)(c = soap_get1(soap)) == EOF)
  12779. { soap->error = SOAP_EOF;
  12780. return NULL;
  12781. }
  12782. *s++ = (char)c;
  12783. }
  12784. *s = '\0';
  12785. if ((soap->error = soap_move(soap, -(long)n&3)))
  12786. return NULL;
  12787. }
  12788. else
  12789. soap->error = SOAP_EOM;
  12790. }
  12791. return p;
  12792. }
  12793. #endif
  12794. #endif
  12795. /******************************************************************************/
  12796. #ifndef WITH_LEANER
  12797. #ifndef PALM_1
  12798. SOAP_FMAC1
  12799. int
  12800. SOAP_FMAC2
  12801. soap_getdimehdr(struct soap *soap)
  12802. { register soap_wchar c;
  12803. register char *s;
  12804. register int i;
  12805. unsigned char tmp[12];
  12806. size_t optlen, idlen, typelen;
  12807. if (!(soap->mode & SOAP_ENC_DIME))
  12808. return soap->error = SOAP_DIME_END;
  12809. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME header\n"));
  12810. if (soap->dime.buflen || soap->dime.chunksize)
  12811. { if (soap_move(soap, (long)(soap->dime.size - soap_tell(soap))))
  12812. return soap->error = SOAP_EOF;
  12813. soap_unget(soap, soap_getchar(soap)); /* skip padding and get hdr */
  12814. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... From chunked\n"));
  12815. return SOAP_OK;
  12816. }
  12817. s = (char*)tmp;
  12818. for (i = 12; i > 0; i--)
  12819. { if ((int)(c = soap_getchar(soap)) == EOF)
  12820. return soap->error = SOAP_EOF;
  12821. *s++ = (char)c;
  12822. }
  12823. if ((tmp[0] & 0xF8) != SOAP_DIME_VERSION)
  12824. return soap->error = SOAP_DIME_MISMATCH;
  12825. soap->dime.flags = (tmp[0] & 0x7) | (tmp[1] & 0xF0);
  12826. optlen = (tmp[2] << 8) | tmp[3];
  12827. idlen = (tmp[4] << 8) | tmp[5];
  12828. typelen = (tmp[6] << 8) | tmp[7];
  12829. soap->dime.size = (tmp[8] << 24) | (tmp[9] << 16) | (tmp[10] << 8) | tmp[11];
  12830. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME size=%lu flags=0x%X\n", (unsigned long)soap->dime.size, soap->dime.flags));
  12831. if (!(soap->dime.options = soap_getdimefield(soap, optlen)) && soap->error)
  12832. return soap->error;
  12833. if (!(soap->dime.id = soap_getdimefield(soap, idlen)) && soap->error)
  12834. return soap->error;
  12835. if (!(soap->dime.type = soap_getdimefield(soap, typelen)) && soap->error)
  12836. return soap->error;
  12837. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME id=%s, type=%s, options=%s\n", soap->dime.id?soap->dime.id:SOAP_STR_EOS, soap->dime.type?soap->dime.type:"", soap->dime.options?soap->dime.options+4:SOAP_STR_EOS));
  12838. if (soap->dime.flags & SOAP_DIME_ME)
  12839. soap->mode &= ~SOAP_ENC_DIME;
  12840. return SOAP_OK;
  12841. }
  12842. #endif
  12843. #endif
  12844. /******************************************************************************/
  12845. #ifndef WITH_LEANER
  12846. #ifndef PALM_1
  12847. SOAP_FMAC1
  12848. int
  12849. SOAP_FMAC2
  12850. soap_getdime(struct soap *soap)
  12851. { while (soap->dime.flags & SOAP_DIME_CF)
  12852. { if (soap_getdimehdr(soap))
  12853. return soap->error;
  12854. if (soap_move(soap, (long)soap->dime.size))
  12855. return soap->error = SOAP_EOF;
  12856. }
  12857. if (soap_move(soap, (long)(((soap->dime.size+3)&(~3))-soap_tell(soap))))
  12858. return soap->error = SOAP_EOF;
  12859. for (;;)
  12860. { register struct soap_multipart *content;
  12861. if (soap_getdimehdr(soap))
  12862. break;
  12863. if (soap->fdimewriteopen && ((soap->dime.ptr = (char*)soap->fdimewriteopen(soap, soap->dime.id, soap->dime.type, soap->dime.options)) || soap->error))
  12864. { const char *id, *type, *options;
  12865. size_t size, n;
  12866. if (!soap->dime.ptr)
  12867. return soap->error;
  12868. id = soap->dime.id;
  12869. type = soap->dime.type;
  12870. options = soap->dime.options;
  12871. for (;;)
  12872. { size = soap->dime.size;
  12873. for (;;)
  12874. { n = soap->buflen - soap->bufidx;
  12875. if (size < n)
  12876. n = size;
  12877. if ((soap->error = soap->fdimewrite(soap, (void*)soap->dime.ptr, soap->buf + soap->bufidx, n)))
  12878. break;
  12879. size -= n;
  12880. if (!size)
  12881. { soap->bufidx += n;
  12882. break;
  12883. }
  12884. if (soap_recv(soap))
  12885. { soap->error = SOAP_EOF;
  12886. goto end;
  12887. }
  12888. }
  12889. if (soap_move(soap, -(long)soap->dime.size&3))
  12890. { soap->error = SOAP_EOF;
  12891. break;
  12892. }
  12893. if (!(soap->dime.flags & SOAP_DIME_CF))
  12894. break;
  12895. if (soap_getdimehdr(soap))
  12896. break;
  12897. }
  12898. end:
  12899. if (soap->fdimewriteclose)
  12900. soap->fdimewriteclose(soap, (void*)soap->dime.ptr);
  12901. soap->dime.size = 0;
  12902. soap->dime.id = id;
  12903. soap->dime.type = type;
  12904. soap->dime.options = options;
  12905. }
  12906. else if (soap->dime.flags & SOAP_DIME_CF)
  12907. { const char *id, *type, *options;
  12908. id = soap->dime.id;
  12909. type = soap->dime.type;
  12910. options = soap->dime.options;
  12911. if (soap_new_block(soap) == NULL)
  12912. return SOAP_EOM;
  12913. for (;;)
  12914. { register soap_wchar c;
  12915. register size_t i;
  12916. register char *s;
  12917. s = (char*)soap_push_block(soap, NULL, soap->dime.size);
  12918. if (!s)
  12919. return soap->error = SOAP_EOM;
  12920. for (i = soap->dime.size; i > 0; i--)
  12921. { if ((int)(c = soap_get1(soap)) == EOF)
  12922. return soap->error = SOAP_EOF;
  12923. *s++ = (char)c;
  12924. }
  12925. if (soap_move(soap, -(long)soap->dime.size&3))
  12926. return soap->error = SOAP_EOF;
  12927. if (!(soap->dime.flags & SOAP_DIME_CF))
  12928. break;
  12929. if (soap_getdimehdr(soap))
  12930. return soap->error;
  12931. }
  12932. soap->dime.size = soap->blist->size++; /* allocate one more for '\0' */
  12933. if (!(soap->dime.ptr = soap_save_block(soap, NULL, NULL, 0)))
  12934. return soap->error;
  12935. soap->dime.ptr[soap->dime.size] = '\0'; /* force 0-terminated */
  12936. soap->dime.id = id;
  12937. soap->dime.type = type;
  12938. soap->dime.options = options;
  12939. }
  12940. else
  12941. soap->dime.ptr = soap_getdimefield(soap, soap->dime.size);
  12942. content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, soap->dime.ptr, soap->dime.size);
  12943. if (!content)
  12944. return soap->error = SOAP_EOM;
  12945. content->id = soap->dime.id;
  12946. content->type = soap->dime.type;
  12947. content->options = soap->dime.options;
  12948. if (soap->error)
  12949. return soap->error;
  12950. soap_resolve_attachment(soap, content);
  12951. }
  12952. if (soap->error != SOAP_DIME_END)
  12953. return soap->error;
  12954. return soap->error = SOAP_OK;
  12955. }
  12956. #endif
  12957. #endif
  12958. /******************************************************************************/
  12959. #ifndef WITH_LEANER
  12960. #ifndef PALM_1
  12961. SOAP_FMAC1
  12962. int
  12963. SOAP_FMAC2
  12964. soap_getmimehdr(struct soap *soap)
  12965. { struct soap_multipart *content;
  12966. do
  12967. { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
  12968. return soap->error;
  12969. }
  12970. while (!*soap->msgbuf);
  12971. if (soap->msgbuf[0] == '-' && soap->msgbuf[1] == '-')
  12972. { char *s = soap->msgbuf + strlen(soap->msgbuf) - 1;
  12973. /* remove white space */
  12974. while (soap_blank(*s))
  12975. s--;
  12976. s[1] = '\0';
  12977. if (soap->mime.boundary)
  12978. { if (strcmp(soap->msgbuf + 2, soap->mime.boundary))
  12979. return soap->error = SOAP_MIME_ERROR;
  12980. }
  12981. else
  12982. soap->mime.boundary = soap_strdup(soap, soap->msgbuf + 2);
  12983. if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
  12984. return soap->error;
  12985. }
  12986. if (soap_set_mime_attachment(soap, NULL, 0, SOAP_MIME_NONE, NULL, NULL, NULL, NULL))
  12987. return soap->error = SOAP_EOM;
  12988. content = soap->mime.last;
  12989. for (;;)
  12990. { register char *key = soap->msgbuf;
  12991. register char *val;
  12992. if (!*key)
  12993. break;
  12994. DBGLOG(TEST,SOAP_MESSAGE(fdebug, "MIME header: %s\n", key));
  12995. val = strchr(soap->msgbuf, ':');
  12996. if (val)
  12997. { *val = '\0';
  12998. do val++;
  12999. while (*val && *val <= 32);
  13000. if (!soap_tag_cmp(key, "Content-ID"))
  13001. content->id = soap_strdup(soap, val);
  13002. else if (!soap_tag_cmp(key, "Content-Location"))
  13003. content->location = soap_strdup(soap, val);
  13004. else if (!soap_tag_cmp(key, "Content-Disposition"))
  13005. content->id = soap_strdup(soap, soap_get_header_attribute(soap, val, "name"));
  13006. else if (!soap_tag_cmp(key, "Content-Type"))
  13007. content->type = soap_strdup(soap, val);
  13008. else if (!soap_tag_cmp(key, "Content-Description"))
  13009. content->description = soap_strdup(soap, val);
  13010. else if (!soap_tag_cmp(key, "Content-Transfer-Encoding"))
  13011. content->encoding = (enum soap_mime_encoding)soap_code_int(mime_codes, val, (long)SOAP_MIME_NONE);
  13012. }
  13013. if (soap_getline(soap, key, sizeof(soap->msgbuf)))
  13014. return soap->error;
  13015. }
  13016. return SOAP_OK;
  13017. }
  13018. #endif
  13019. #endif
  13020. /******************************************************************************/
  13021. #ifndef WITH_LEANER
  13022. #ifndef PALM_1
  13023. SOAP_FMAC1
  13024. int
  13025. SOAP_FMAC2
  13026. soap_getmime(struct soap *soap)
  13027. { while (soap_get_mime_attachment(soap, NULL))
  13028. ;
  13029. return soap->error;
  13030. }
  13031. #endif
  13032. #endif
  13033. /******************************************************************************/
  13034. #ifndef WITH_LEANER
  13035. #ifndef PALM_1
  13036. SOAP_FMAC1
  13037. void
  13038. SOAP_FMAC2
  13039. soap_post_check_mime_attachments(struct soap *soap)
  13040. { soap->imode |= SOAP_MIME_POSTCHECK;
  13041. }
  13042. #endif
  13043. #endif
  13044. /******************************************************************************/
  13045. #ifndef WITH_LEANER
  13046. #ifndef PALM_1
  13047. SOAP_FMAC1
  13048. int
  13049. SOAP_FMAC2
  13050. soap_check_mime_attachments(struct soap *soap)
  13051. { if (soap->mode & SOAP_MIME_POSTCHECK)
  13052. return soap_get_mime_attachment(soap, NULL) != NULL;
  13053. return 0;
  13054. }
  13055. #endif
  13056. #endif
  13057. /******************************************************************************/
  13058. #ifndef WITH_LEANER
  13059. #ifndef PALM_1
  13060. SOAP_FMAC1
  13061. struct soap_multipart *
  13062. SOAP_FMAC2
  13063. soap_get_mime_attachment(struct soap *soap, void *handle)
  13064. { register soap_wchar c = 0;
  13065. register size_t i, m = 0;
  13066. register char *s, *t = NULL;
  13067. register struct soap_multipart *content;
  13068. register short flag = 0;
  13069. if (!(soap->mode & SOAP_ENC_MIME))
  13070. return NULL;
  13071. content = soap->mime.last;
  13072. if (!content)
  13073. { if (soap_getmimehdr(soap))
  13074. return NULL;
  13075. content = soap->mime.last;
  13076. }
  13077. else if (content != soap->mime.first)
  13078. { if (soap->fmimewriteopen && ((content->ptr = (char*)soap->fmimewriteopen(soap, (void*)handle, content->id, content->type, content->description, content->encoding)) || soap->error))
  13079. { if (!content->ptr)
  13080. return NULL;
  13081. }
  13082. }
  13083. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Parsing MIME content id=%s type=%s\n", content->id?content->id:SOAP_STR_EOS, content->type?content->type:SOAP_STR_EOS));
  13084. if (!content->ptr && soap_new_block(soap) == NULL)
  13085. { soap->error = SOAP_EOM;
  13086. return NULL;
  13087. }
  13088. for (;;)
  13089. { if (content->ptr)
  13090. s = soap->tmpbuf;
  13091. else if (!(s = (char*)soap_push_block(soap, NULL, sizeof(soap->tmpbuf))))
  13092. { soap->error = SOAP_EOM;
  13093. return NULL;
  13094. }
  13095. for (i = 0; i < sizeof(soap->tmpbuf); i++)
  13096. { if (m > 0)
  13097. { *s++ = *t++;
  13098. m--;
  13099. }
  13100. else
  13101. { if (!flag)
  13102. { c = soap_get1(soap);
  13103. if ((int)c == EOF)
  13104. { soap->error = SOAP_EOF;
  13105. return NULL;
  13106. }
  13107. }
  13108. if (flag || c == '\r')
  13109. { t = soap->msgbuf;
  13110. memset(t, 0, sizeof(soap->msgbuf));
  13111. strcpy(t, "\n--");
  13112. if (soap->mime.boundary)
  13113. strncat(t, soap->mime.boundary, sizeof(soap->msgbuf)-4);
  13114. do c = soap_getchar(soap);
  13115. while (c == *t++);
  13116. if ((int)c == EOF)
  13117. { soap->error = SOAP_EOF;
  13118. return NULL;
  13119. }
  13120. if (!*--t)
  13121. goto end;
  13122. *t = (char)c;
  13123. flag = (c == '\r');
  13124. m = t - soap->msgbuf + 1 - flag;
  13125. t = soap->msgbuf;
  13126. c = '\r';
  13127. }
  13128. *s++ = (char)c;
  13129. }
  13130. }
  13131. if (content->ptr && soap->fmimewrite)
  13132. { if ((soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i)))
  13133. break;
  13134. }
  13135. }
  13136. end:
  13137. *s = '\0'; /* force 0-terminated */
  13138. if (content->ptr)
  13139. { if (!soap->error && soap->fmimewrite)
  13140. soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i);
  13141. if (soap->fmimewriteclose)
  13142. soap->fmimewriteclose(soap, (void*)content->ptr);
  13143. if (soap->error)
  13144. return NULL;
  13145. }
  13146. else
  13147. { content->size = soap_size_block(soap, NULL, i+1)-1;
  13148. content->ptr = soap_save_block(soap, NULL, NULL, 0);
  13149. }
  13150. soap_resolve_attachment(soap, content);
  13151. if (c == '-' && soap_getchar(soap) == '-')
  13152. { soap->mode &= ~SOAP_ENC_MIME;
  13153. if ((soap->mode & SOAP_MIME_POSTCHECK) && soap_end_recv(soap))
  13154. return NULL;
  13155. }
  13156. else
  13157. { while (c != '\r' && (int)c != EOF && soap_blank(c))
  13158. c = soap_getchar(soap);
  13159. if (c != '\r' || soap_getchar(soap) != '\n')
  13160. { soap->error = SOAP_MIME_ERROR;
  13161. return NULL;
  13162. }
  13163. if (soap_getmimehdr(soap))
  13164. return NULL;
  13165. }
  13166. return content;
  13167. }
  13168. #endif
  13169. #endif
  13170. /******************************************************************************/
  13171. #ifndef WITH_LEANER
  13172. #ifndef PALM_1
  13173. SOAP_FMAC1
  13174. int
  13175. SOAP_FMAC2
  13176. soap_match_cid(struct soap *soap, const char *s, const char *t)
  13177. { register size_t n;
  13178. if (!s)
  13179. return 1;
  13180. if (!strcmp(s, t))
  13181. return 0;
  13182. if (!strncmp(s, "cid:", 4))
  13183. s += 4;
  13184. n = strlen(t);
  13185. if (*t == '<')
  13186. { t++;
  13187. n -= 2;
  13188. }
  13189. if (!strncmp(s, t, n) && !s[n])
  13190. return 0;
  13191. soap_decode(soap->tmpbuf, sizeof(soap->tmpbuf), s, SOAP_STR_EOS);
  13192. if (!strncmp(soap->tmpbuf, t, n) && !soap->tmpbuf[n])
  13193. return 0;
  13194. return 1;
  13195. }
  13196. #endif
  13197. #endif
  13198. /******************************************************************************/
  13199. #ifndef WITH_LEANER
  13200. #ifndef PALM_1
  13201. static void
  13202. soap_resolve_attachment(struct soap *soap, struct soap_multipart *content)
  13203. { if (content->id)
  13204. { register struct soap_xlist **xp = &soap->xlist;
  13205. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving attachment data for id=%s\n", content->id));
  13206. while (*xp)
  13207. { register struct soap_xlist *xq = *xp;
  13208. if (!soap_match_cid(soap, xq->id, content->id))
  13209. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Found matching attachment %s for content id=%s\n", xq->id, content->id));
  13210. *xp = xq->next;
  13211. *xq->ptr = (unsigned char*)content->ptr;
  13212. *xq->size = (int)content->size;
  13213. *xq->type = (char*)content->type;
  13214. if (content->options)
  13215. *xq->options = (char*)content->options;
  13216. else
  13217. *xq->options = (char*)content->description;
  13218. SOAP_FREE(soap, xq);
  13219. }
  13220. else
  13221. xp = &(*xp)->next;
  13222. }
  13223. }
  13224. }
  13225. #endif
  13226. #endif
  13227. /******************************************************************************/
  13228. #ifndef WITH_LEANER
  13229. #ifndef PALM_1
  13230. SOAP_FMAC1
  13231. int
  13232. SOAP_FMAC2
  13233. soap_putmimehdr(struct soap *soap, struct soap_multipart *content)
  13234. { const char *s;
  13235. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "MIME attachment type=%s\n", content->type?content->type:SOAP_STR_EOS));
  13236. if (soap_send3(soap, "\r\n--", soap->mime.boundary, "\r\n"))
  13237. return soap->error;
  13238. if (content->type && soap_send3(soap, "Content-Type: ", content->type, "\r\n"))
  13239. return soap->error;
  13240. s = soap_code_str(mime_codes, content->encoding);
  13241. if (s && soap_send3(soap, "Content-Transfer-Encoding: ", s, "\r\n"))
  13242. return soap->error;
  13243. if (content->id && soap_send3(soap, "Content-ID: ", content->id, "\r\n"))
  13244. return soap->error;
  13245. if (content->location && soap_send3(soap, "Content-Location: ", content->location, "\r\n"))
  13246. return soap->error;
  13247. if (content->description && soap_send3(soap, "Content-Description: ", content->description, "\r\n"))
  13248. return soap->error;
  13249. return soap_send_raw(soap, "\r\n", 2);
  13250. }
  13251. #endif
  13252. #endif
  13253. /******************************************************************************/
  13254. #ifndef WITH_LEANER
  13255. #ifndef PALM_1
  13256. SOAP_FMAC1
  13257. int
  13258. SOAP_FMAC2
  13259. soap_putmime(struct soap *soap)
  13260. { struct soap_multipart *content;
  13261. if (!(soap->mode & SOAP_ENC_MIME) || !soap->mime.boundary)
  13262. return SOAP_OK;
  13263. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending MIME attachments\n"));
  13264. for (content = soap->mime.first; content; content = content->next)
  13265. { void *handle;
  13266. if (soap->fmimereadopen && ((handle = soap->fmimereadopen(soap, (void*)content->ptr, content->id, content->type, content->description)) || soap->error))
  13267. { size_t size = content->size;
  13268. if (!handle)
  13269. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimereadopen failed\n"));
  13270. return soap->error;
  13271. }
  13272. if (soap_putmimehdr(soap, content))
  13273. return soap->error;
  13274. if (!size)
  13275. { if ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE)
  13276. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming MIME\n"));
  13277. do
  13278. { size = soap->fmimeread(soap, handle, soap->tmpbuf, sizeof(soap->tmpbuf));
  13279. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread returned %lu bytes\n", (unsigned long)size));
  13280. if (soap_send_raw(soap, soap->tmpbuf, size))
  13281. break;
  13282. } while (size);
  13283. }
  13284. else
  13285. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error: cannot chunk streaming MIME (no HTTP chunking)\n"));
  13286. }
  13287. }
  13288. else
  13289. { do
  13290. { size_t bufsize;
  13291. if (size < sizeof(soap->tmpbuf))
  13292. bufsize = size;
  13293. else
  13294. bufsize = sizeof(soap->tmpbuf);
  13295. if (!(bufsize = soap->fmimeread(soap, handle, soap->tmpbuf, bufsize)))
  13296. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size));
  13297. soap->error = SOAP_EOF;
  13298. break;
  13299. }
  13300. if (soap_send_raw(soap, soap->tmpbuf, bufsize))
  13301. break;
  13302. size -= bufsize;
  13303. } while (size);
  13304. }
  13305. if (soap->fmimereadclose)
  13306. soap->fmimereadclose(soap, handle);
  13307. }
  13308. else
  13309. { if (soap_putmimehdr(soap, content)
  13310. || soap_send_raw(soap, content->ptr, content->size))
  13311. return soap->error;
  13312. }
  13313. }
  13314. return soap_send3(soap, "\r\n--", soap->mime.boundary, "--");
  13315. }
  13316. #endif
  13317. #endif
  13318. /******************************************************************************/
  13319. #ifndef WITH_LEANER
  13320. #ifndef PALM_1
  13321. SOAP_FMAC1
  13322. void
  13323. SOAP_FMAC2
  13324. soap_set_dime(struct soap *soap)
  13325. { soap->omode |= SOAP_ENC_DIME;
  13326. soap->dime.first = NULL;
  13327. soap->dime.last = NULL;
  13328. }
  13329. #endif
  13330. #endif
  13331. /******************************************************************************/
  13332. #ifndef WITH_LEANER
  13333. #ifndef PALM_1
  13334. SOAP_FMAC1
  13335. void
  13336. SOAP_FMAC2
  13337. soap_set_mime(struct soap *soap, const char *boundary, const char *start)
  13338. { soap->omode |= SOAP_ENC_MIME;
  13339. soap->mime.first = NULL;
  13340. soap->mime.last = NULL;
  13341. soap->mime.boundary = soap_strdup(soap, boundary);
  13342. soap->mime.start = soap_strdup(soap, start);
  13343. }
  13344. #endif
  13345. #endif
  13346. /******************************************************************************/
  13347. #ifndef WITH_LEANER
  13348. #ifndef PALM_1
  13349. SOAP_FMAC1
  13350. void
  13351. SOAP_FMAC2
  13352. soap_clr_dime(struct soap *soap)
  13353. { soap->omode &= ~SOAP_ENC_DIME;
  13354. soap->dime.first = NULL;
  13355. soap->dime.last = NULL;
  13356. }
  13357. #endif
  13358. #endif
  13359. /******************************************************************************/
  13360. #ifndef WITH_LEANER
  13361. #ifndef PALM_1
  13362. SOAP_FMAC1
  13363. void
  13364. SOAP_FMAC2
  13365. soap_clr_mime(struct soap *soap)
  13366. { soap->omode &= ~SOAP_ENC_MIME;
  13367. soap->mime.first = NULL;
  13368. soap->mime.last = NULL;
  13369. soap->mime.boundary = NULL;
  13370. soap->mime.start = NULL;
  13371. }
  13372. #endif
  13373. #endif
  13374. /******************************************************************************/
  13375. #ifndef WITH_LEANER
  13376. #ifndef PALM_1
  13377. static struct soap_multipart*
  13378. soap_new_multipart(struct soap *soap, struct soap_multipart **first, struct soap_multipart **last, char *ptr, size_t size)
  13379. { struct soap_multipart *content;
  13380. content = (struct soap_multipart*)soap_malloc(soap, sizeof(struct soap_multipart));
  13381. if (content)
  13382. { content->next = NULL;
  13383. content->ptr = ptr;
  13384. content->size = size;
  13385. content->id = NULL;
  13386. content->type = NULL;
  13387. content->options = NULL;
  13388. content->encoding = SOAP_MIME_NONE;
  13389. content->location = NULL;
  13390. content->description = NULL;
  13391. if (!*first)
  13392. *first = content;
  13393. if (*last)
  13394. (*last)->next = content;
  13395. *last = content;
  13396. }
  13397. return content;
  13398. }
  13399. #endif
  13400. #endif
  13401. /******************************************************************************/
  13402. #ifndef WITH_LEANER
  13403. #ifndef PALM_1
  13404. SOAP_FMAC1
  13405. int
  13406. SOAP_FMAC2
  13407. soap_set_dime_attachment(struct soap *soap, char *ptr, size_t size, const char *type, const char *id, unsigned short optype, const char *option)
  13408. { struct soap_multipart *content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, ptr, size);
  13409. if (!content)
  13410. return SOAP_EOM;
  13411. content->id = soap_strdup(soap, id);
  13412. content->type = soap_strdup(soap, type);
  13413. content->options = soap_dime_option(soap, optype, option);
  13414. return SOAP_OK;
  13415. }
  13416. #endif
  13417. #endif
  13418. /******************************************************************************/
  13419. #ifndef WITH_LEANER
  13420. #ifndef PALM_1
  13421. SOAP_FMAC1
  13422. int
  13423. SOAP_FMAC2
  13424. soap_set_mime_attachment(struct soap *soap, char *ptr, size_t size, enum soap_mime_encoding encoding, const char *type, const char *id, const char *location, const char *description)
  13425. { struct soap_multipart *content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, ptr, size);
  13426. if (!content)
  13427. return SOAP_EOM;
  13428. content->id = soap_strdup(soap, id);
  13429. content->type = soap_strdup(soap, type);
  13430. content->encoding = encoding;
  13431. content->location = soap_strdup(soap, location);
  13432. content->description = soap_strdup(soap, description);
  13433. return SOAP_OK;
  13434. }
  13435. #endif
  13436. #endif
  13437. /******************************************************************************/
  13438. #ifndef WITH_LEANER
  13439. #ifndef PALM_1
  13440. SOAP_FMAC1
  13441. struct soap_multipart*
  13442. SOAP_FMAC2
  13443. soap_next_multipart(struct soap_multipart *content)
  13444. { if (content)
  13445. return content->next;
  13446. return NULL;
  13447. }
  13448. #endif
  13449. #endif
  13450. /******************************************************************************/
  13451. #ifndef WITH_LEANER
  13452. #ifndef PALM_1
  13453. static void
  13454. soap_select_mime_boundary(struct soap *soap)
  13455. { while (!soap->mime.boundary || soap_valid_mime_boundary(soap))
  13456. { register char *s = soap->mime.boundary;
  13457. register size_t n = 0;
  13458. if (s)
  13459. n = strlen(s);
  13460. if (n < 16)
  13461. { n = 64;
  13462. s = soap->mime.boundary = (char*)soap_malloc(soap, n + 1);
  13463. if (!s)
  13464. return;
  13465. }
  13466. strcpy(s, "==");
  13467. s += 2;
  13468. n -= 4;
  13469. while (n)
  13470. { *s++ = soap_base64o[soap_random & 0x3F];
  13471. n--;
  13472. }
  13473. strcpy(s, "==");
  13474. }
  13475. if (!soap->mime.start)
  13476. soap->mime.start = "<SOAP-ENV:Envelope>";
  13477. }
  13478. #endif
  13479. #endif
  13480. /******************************************************************************/
  13481. #ifndef WITH_LEANER
  13482. #ifndef PALM_1
  13483. static int
  13484. soap_valid_mime_boundary(struct soap *soap)
  13485. { register struct soap_multipart *content;
  13486. register size_t k;
  13487. if (soap->fmimeread)
  13488. return SOAP_OK;
  13489. k = strlen(soap->mime.boundary);
  13490. for (content = soap->mime.first; content; content = content->next)
  13491. { if (content->ptr && content->size >= k)
  13492. { register const char *p = (const char*)content->ptr;
  13493. register size_t i;
  13494. for (i = 0; i < content->size - k; i++, p++)
  13495. { if (!strncmp(p, soap->mime.boundary, k))
  13496. return SOAP_ERR;
  13497. }
  13498. }
  13499. }
  13500. return SOAP_OK;
  13501. }
  13502. #endif
  13503. #endif
  13504. /******************************************************************************/
  13505. #ifdef WITH_GZIP
  13506. #ifndef PALM_1
  13507. static int
  13508. soap_getgziphdr(struct soap *soap)
  13509. { int i;
  13510. soap_wchar c = 0, f = 0;
  13511. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get gzip header\n"));
  13512. for (i = 0; i < 9; i++)
  13513. { if ((int)(c = soap_get1(soap) == EOF))
  13514. return soap->error = SOAP_EOF;
  13515. if (i == 1 && c == 8)
  13516. soap->z_dict = 0;
  13517. if (i == 2)
  13518. f = c;
  13519. }
  13520. if (f & 0x04) /* FEXTRA */
  13521. { for (i = soap_get1(soap) | (soap_get1(soap) << 8); i; i--)
  13522. { if ((int)soap_get1(soap) == EOF)
  13523. return soap->error = SOAP_EOF;
  13524. }
  13525. }
  13526. if (f & 0x08) /* skip FNAME */
  13527. { do
  13528. c = soap_get1(soap);
  13529. while (c && (int)c != EOF);
  13530. }
  13531. if ((int)c != EOF && (f & 0x10)) /* skip FCOMMENT */
  13532. { do
  13533. c = soap_get1(soap);
  13534. while (c && (int)c != EOF);
  13535. }
  13536. if ((int)c != EOF && (f & 0x02)) /* skip FHCRC (CRC32 is used) */
  13537. { if ((int)(c = soap_get1(soap)) != EOF)
  13538. c = soap_get1(soap);
  13539. }
  13540. if ((int)c == EOF)
  13541. return soap->error = SOAP_EOF;
  13542. return SOAP_OK;
  13543. }
  13544. #endif
  13545. #endif
  13546. /******************************************************************************/
  13547. #ifndef PALM_1
  13548. SOAP_FMAC1
  13549. int
  13550. SOAP_FMAC2
  13551. soap_begin_recv(struct soap *soap)
  13552. { soap_wchar c;
  13553. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing for input\n"));
  13554. soap->error = SOAP_OK;
  13555. soap_free_temp(soap);
  13556. soap_set_local_namespaces(soap);
  13557. soap->version = 0; /* don't assume we're parsing SOAP content by default */
  13558. #ifndef WITH_NOIDREF
  13559. soap_free_iht(soap);
  13560. #endif
  13561. if ((soap->imode & SOAP_IO) == SOAP_IO_CHUNK)
  13562. soap->omode |= SOAP_IO_CHUNK;
  13563. soap->imode &= ~(SOAP_IO | SOAP_ENC_MIME);
  13564. soap->mode = soap->imode;
  13565. if (!soap->keep_alive)
  13566. { soap->buflen = 0;
  13567. soap->bufidx = 0;
  13568. }
  13569. if (!(soap->mode & SOAP_IO_KEEPALIVE))
  13570. soap->keep_alive = 0;
  13571. soap->ahead = 0;
  13572. soap->peeked = 0;
  13573. soap->level = 0;
  13574. soap->part = SOAP_BEGIN;
  13575. soap->alloced = 0;
  13576. soap->count = 0;
  13577. soap->length = 0;
  13578. soap->cdata = 0;
  13579. *soap->endpoint = '\0';
  13580. soap->action = NULL;
  13581. soap->header = NULL;
  13582. soap->fault = NULL;
  13583. soap->status = 0;
  13584. #ifndef WITH_LEANER
  13585. soap->dom = NULL;
  13586. soap->dime.chunksize = 0;
  13587. soap->dime.buflen = 0;
  13588. soap->dime.list = NULL;
  13589. soap->dime.first = NULL;
  13590. soap->dime.last = NULL;
  13591. soap->mime.list = NULL;
  13592. soap->mime.first = NULL;
  13593. soap->mime.last = NULL;
  13594. soap->mime.boundary = NULL;
  13595. soap->mime.start = NULL;
  13596. #endif
  13597. #ifdef WIN32
  13598. #ifndef UNDER_CE
  13599. #ifndef WITH_FASTCGI
  13600. if (!soap_valid_socket(soap->socket))
  13601. #ifdef __BORLANDC__
  13602. setmode(soap->recvfd, _O_BINARY);
  13603. #else
  13604. _setmode(soap->recvfd, _O_BINARY);
  13605. #endif
  13606. #endif
  13607. #endif
  13608. #endif
  13609. #ifdef WITH_ZLIB
  13610. soap->mode &= ~SOAP_ENC_ZLIB;
  13611. soap->zlib_in = SOAP_ZLIB_NONE;
  13612. soap->zlib_out = SOAP_ZLIB_NONE;
  13613. soap->d_stream->next_in = Z_NULL;
  13614. soap->d_stream->avail_in = 0;
  13615. soap->d_stream->next_out = (Byte*)soap->buf;
  13616. soap->d_stream->avail_out = SOAP_BUFLEN;
  13617. soap->z_ratio_in = 1.0;
  13618. #endif
  13619. #ifdef WITH_OPENSSL
  13620. if (soap->ssl)
  13621. ERR_clear_error();
  13622. #endif
  13623. #ifndef WITH_LEANER
  13624. if (soap->fprepareinitrecv && (soap->error = soap->fprepareinitrecv(soap)))
  13625. return soap->error;
  13626. #endif
  13627. c = soap_getchar(soap);
  13628. #ifdef WITH_GZIP
  13629. if (c == 0x1F)
  13630. { if (soap_getgziphdr(soap))
  13631. return soap->error;
  13632. if (inflateInit2(soap->d_stream, -MAX_WBITS) != Z_OK)
  13633. return soap->error = SOAP_ZLIB_ERROR;
  13634. if (soap->z_dict)
  13635. { if (inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len) != Z_OK)
  13636. return soap->error = SOAP_ZLIB_ERROR;
  13637. }
  13638. soap->zlib_state = SOAP_ZLIB_INFLATE;
  13639. soap->mode |= SOAP_ENC_ZLIB;
  13640. soap->zlib_in = SOAP_ZLIB_GZIP;
  13641. soap->z_crc = crc32(0L, NULL, 0);
  13642. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n"));
  13643. if (!soap->z_buf)
  13644. soap->z_buf = (char*)SOAP_MALLOC(soap, SOAP_BUFLEN);
  13645. memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN);
  13646. /* should not chunk over plain transport, so why bother to check? */
  13647. /* if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) */
  13648. /* soap->z_buflen = soap->bufidx; */
  13649. /* else */
  13650. soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx);
  13651. soap->d_stream->avail_in = soap->buflen - soap->bufidx;
  13652. soap->z_buflen = soap->buflen;
  13653. soap->buflen = soap->bufidx;
  13654. c = ' ';
  13655. }
  13656. #endif
  13657. while (soap_blank(c))
  13658. c = soap_getchar(soap);
  13659. #ifndef WITH_LEANER
  13660. if (c == '-' && soap_get0(soap) == '-')
  13661. soap->mode |= SOAP_ENC_MIME;
  13662. else if ((c & 0xFFFC) == (SOAP_DIME_VERSION | SOAP_DIME_MB) && (soap_get0(soap) & 0xFFF0) == 0x20)
  13663. soap->mode |= SOAP_ENC_DIME;
  13664. else
  13665. #endif
  13666. { /* skip BOM */
  13667. if (c == 0xEF && (c = soap_getchar(soap)) == 0xBB && (c = soap_getchar(soap)) == 0xBF)
  13668. c = soap_getchar(soap);
  13669. /* skip space */
  13670. while (soap_blank(c))
  13671. c = soap_getchar(soap);
  13672. }
  13673. if ((int)c == EOF)
  13674. return soap->error = SOAP_EOF;
  13675. soap_unget(soap, c);
  13676. #ifndef WITH_NOHTTP
  13677. /* if not XML or MIME/DIME/ZLIB, assume HTTP header */
  13678. if (c != '<' && !(soap->mode & (SOAP_ENC_MIME | SOAP_ENC_DIME | SOAP_ENC_ZLIB)))
  13679. { soap_mode m = soap->imode;
  13680. soap->mode &= ~SOAP_IO;
  13681. soap->error = soap->fparse(soap);
  13682. if (soap->error && soap->error < SOAP_STOP)
  13683. { soap->keep_alive = 0; /* force close later */
  13684. return soap->error;
  13685. }
  13686. if (soap->error == SOAP_STOP)
  13687. return soap->error;
  13688. soap->mode = soap->imode; /* if imode is changed, effectuate */
  13689. soap->imode = m; /* restore imode */
  13690. #ifdef WITH_ZLIB
  13691. soap->mode &= ~SOAP_ENC_ZLIB;
  13692. #endif
  13693. if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
  13694. { soap->chunkbuflen = soap->buflen;
  13695. soap->buflen = soap->bufidx;
  13696. soap->chunksize = 0;
  13697. }
  13698. /* Note: fparse should not use soap_unget to push back last char */
  13699. if (soap_get0(soap) == (int)EOF)
  13700. { if (soap->status == 200)
  13701. return soap->error = SOAP_NO_DATA; /* HTTP OK: always expect data */
  13702. return soap->error = soap->status;
  13703. }
  13704. #ifdef WITH_ZLIB
  13705. if (soap->zlib_in != SOAP_ZLIB_NONE)
  13706. {
  13707. #ifdef WITH_GZIP
  13708. if (soap->zlib_in != SOAP_ZLIB_DEFLATE)
  13709. { c = soap_get1(soap);
  13710. if (c == 0x1F)
  13711. { if (soap_getgziphdr(soap))
  13712. return soap->error;
  13713. if (inflateInit2(soap->d_stream, -MAX_WBITS) != Z_OK)
  13714. return soap->error = SOAP_ZLIB_ERROR;
  13715. soap->z_crc = crc32(0L, NULL, 0);
  13716. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n"));
  13717. }
  13718. else
  13719. { soap_revget1(soap);
  13720. if (inflateInit(soap->d_stream) != Z_OK)
  13721. return soap->error = SOAP_ZLIB_ERROR;
  13722. soap->zlib_in = SOAP_ZLIB_DEFLATE;
  13723. }
  13724. }
  13725. else
  13726. #endif
  13727. if (inflateInit(soap->d_stream) != Z_OK)
  13728. return soap->error = SOAP_ZLIB_ERROR;
  13729. if (soap->z_dict)
  13730. { if (inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len) != Z_OK)
  13731. return soap->error = SOAP_ZLIB_ERROR;
  13732. }
  13733. soap->zlib_state = SOAP_ZLIB_INFLATE;
  13734. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate initialized\n"));
  13735. soap->mode |= SOAP_ENC_ZLIB;
  13736. if (!soap->z_buf)
  13737. soap->z_buf = (char*)SOAP_MALLOC(soap, SOAP_BUFLEN);
  13738. memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN);
  13739. soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx);
  13740. soap->d_stream->avail_in = soap->buflen - soap->bufidx;
  13741. soap->z_buflen = soap->buflen;
  13742. soap->buflen = soap->bufidx;
  13743. }
  13744. #endif
  13745. #ifndef WITH_LEANER
  13746. if (soap->fpreparerecv && (soap->mode & SOAP_IO) != SOAP_IO_CHUNK && soap->buflen > soap->bufidx)
  13747. { int r;
  13748. if ((r = soap->fpreparerecv(soap, soap->buf + soap->bufidx, soap->buflen - soap->bufidx)))
  13749. return soap->error = r;
  13750. }
  13751. #endif
  13752. if (soap->error)
  13753. { if (soap->error == SOAP_FORM && soap->fform)
  13754. { soap->error = soap->fform(soap);
  13755. if (soap->error == SOAP_OK)
  13756. soap->error = SOAP_STOP; /* prevents further processing */
  13757. }
  13758. return soap->error;
  13759. }
  13760. }
  13761. #endif
  13762. #ifndef WITH_LEANER
  13763. if (soap->mode & SOAP_ENC_MIME)
  13764. { if (soap_getmimehdr(soap))
  13765. return soap->error;
  13766. if (soap->mime.start)
  13767. { do
  13768. { if (!soap->mime.last->id)
  13769. break;
  13770. if (!soap_match_cid(soap, soap->mime.start, soap->mime.last->id))
  13771. break;
  13772. } while (soap_get_mime_attachment(soap, NULL));
  13773. }
  13774. if (soap_get_header_attribute(soap, soap->mime.first->type, "application/dime"))
  13775. soap->mode |= SOAP_ENC_DIME;
  13776. }
  13777. if (soap->mode & SOAP_ENC_DIME)
  13778. { if (soap_getdimehdr(soap))
  13779. return soap->error;
  13780. if (soap->dime.flags & SOAP_DIME_CF)
  13781. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked DIME SOAP message\n"));
  13782. soap->dime.chunksize = soap->dime.size;
  13783. if (soap->buflen - soap->bufidx >= soap->dime.chunksize)
  13784. { soap->dime.buflen = soap->buflen;
  13785. soap->buflen = soap->bufidx + soap->dime.chunksize;
  13786. }
  13787. else
  13788. soap->dime.chunksize -= soap->buflen - soap->bufidx;
  13789. }
  13790. soap->count = soap->buflen - soap->bufidx;
  13791. }
  13792. #endif
  13793. return SOAP_OK;
  13794. }
  13795. #endif
  13796. /******************************************************************************/
  13797. #ifndef PALM_2
  13798. SOAP_FMAC1
  13799. int
  13800. SOAP_FMAC2
  13801. soap_envelope_begin_out(struct soap *soap)
  13802. {
  13803. #ifndef WITH_LEANER
  13804. size_t n = 0;
  13805. if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && soap->mime.start && strlen(soap->mime.boundary) + strlen(soap->mime.start) < sizeof(soap->tmpbuf) - 80 )
  13806. { const char *s;
  13807. if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
  13808. s = "application/dime";
  13809. else if (soap->version == 2)
  13810. { if (soap->mode & SOAP_ENC_MTOM)
  13811. s = "application/xop+xml; charset=utf-8; type=\"application/soap+xml\"";
  13812. else
  13813. s = "application/soap+xml; charset=utf-8";
  13814. }
  13815. else if (soap->mode & SOAP_ENC_MTOM)
  13816. s = "application/xop+xml; charset=utf-8; type=\"text/xml\"";
  13817. else
  13818. s = "text/xml; charset=utf-8";
  13819. sprintf(soap->tmpbuf, "--%s\r\nContent-Type: %s\r\nContent-Transfer-Encoding: binary\r\nContent-ID: %s\r\n\r\n", soap->mime.boundary, s, soap->mime.start);
  13820. n = strlen(soap->tmpbuf);
  13821. if (soap_send_raw(soap, soap->tmpbuf, n))
  13822. return soap->error;
  13823. }
  13824. if (soap->mode & SOAP_IO_LENGTH)
  13825. soap->dime.size = soap->count; /* DIME in MIME correction */
  13826. if (!(soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME))
  13827. { if (soap_putdimehdr(soap))
  13828. return soap->error;
  13829. }
  13830. #endif
  13831. soap->part = SOAP_IN_ENVELOPE;
  13832. return soap_element_begin_out(soap, "SOAP-ENV:Envelope", 0, NULL);
  13833. }
  13834. #endif
  13835. /******************************************************************************/
  13836. #ifndef PALM_2
  13837. SOAP_FMAC1
  13838. int
  13839. SOAP_FMAC2
  13840. soap_envelope_end_out(struct soap *soap)
  13841. { if (soap_element_end_out(soap, "SOAP-ENV:Envelope") || ((soap->mode & SOAP_XML_INDENT) && soap_send_raw(soap, "\r\n", 2)))
  13842. return soap->error;
  13843. #ifndef WITH_LEANER
  13844. if ((soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
  13845. { soap->dime.size = soap->count - soap->dime.size; /* DIME in MIME correction */
  13846. sprintf(soap->id, soap->dime_id_format, 0);
  13847. soap->dime.id = soap->id;
  13848. if (soap->local_namespaces)
  13849. { if (soap->local_namespaces[0].out)
  13850. soap->dime.type = (char*)soap->local_namespaces[0].out;
  13851. else
  13852. soap->dime.type = (char*)soap->local_namespaces[0].ns;
  13853. }
  13854. soap->dime.options = NULL;
  13855. soap->dime.flags = SOAP_DIME_MB | SOAP_DIME_ABSURI;
  13856. if (!soap->dime.first)
  13857. soap->dime.flags |= SOAP_DIME_ME;
  13858. soap->count += 12 + ((strlen(soap->dime.id)+3)&(~3)) + (soap->dime.type ? ((strlen(soap->dime.type)+3)&(~3)) : 0);
  13859. }
  13860. if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
  13861. return soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3);
  13862. #endif
  13863. soap->part = SOAP_END_ENVELOPE;
  13864. return SOAP_OK;
  13865. }
  13866. #endif
  13867. /******************************************************************************/
  13868. #ifndef PALM_1
  13869. static char*
  13870. soap_get_http_body(struct soap *soap)
  13871. {
  13872. #ifndef WITH_LEAN
  13873. register size_t l = 0, n = 0;
  13874. register char *s;
  13875. /* get HTML body of HTTP error content */
  13876. if (!(soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) != SOAP_IO_CHUNK)
  13877. { n = soap->length;
  13878. if (!n)
  13879. return NULL;
  13880. }
  13881. #ifdef WITH_FAST
  13882. soap->labidx = 0; /* use look-aside buffer */
  13883. #else
  13884. if (soap_new_block(soap) == NULL)
  13885. return NULL;
  13886. #endif
  13887. for (;;)
  13888. {
  13889. #ifdef WITH_FAST
  13890. register size_t i, k;
  13891. if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */
  13892. return NULL;
  13893. s = soap->labbuf + soap->labidx; /* space to populate */
  13894. k = soap->lablen - soap->labidx; /* number of bytes available */
  13895. soap->labidx = soap->lablen; /* claim this space */
  13896. #else
  13897. register size_t i, k = SOAP_BLKLEN;
  13898. if (!(s = (char*)soap_push_block(soap, NULL, k)))
  13899. return NULL;
  13900. #endif
  13901. for (i = 0; i < k; i++)
  13902. { register soap_wchar c = soap_getchar(soap);
  13903. if ((int)c == EOF)
  13904. goto end;
  13905. *s++ = (char)(c & 0xFF);
  13906. l++;
  13907. if (n > 0 && l >= n)
  13908. goto end;
  13909. }
  13910. }
  13911. end:
  13912. *s = '\0';
  13913. #ifdef WITH_FAST
  13914. s = soap_strdup(soap, soap->labbuf);
  13915. #else
  13916. soap_size_block(soap, NULL, i+1);
  13917. s = soap_save_block(soap, NULL, 0);
  13918. #endif
  13919. return s;
  13920. #else
  13921. return NULL;
  13922. #endif
  13923. }
  13924. #endif
  13925. /******************************************************************************/
  13926. #ifndef PALM_1
  13927. SOAP_FMAC1
  13928. int
  13929. SOAP_FMAC2
  13930. soap_envelope_begin_in(struct soap *soap)
  13931. { register struct Namespace *p;
  13932. soap->part = SOAP_IN_ENVELOPE;
  13933. if (soap_element_begin_in(soap, "SOAP-ENV:Envelope", 0, NULL))
  13934. { if (soap->error == SOAP_TAG_MISMATCH
  13935. && !soap_element_begin_in(soap, "Envelope", 0, NULL))
  13936. soap->error = SOAP_VERSIONMISMATCH;
  13937. else if (soap->status)
  13938. soap->error = soap->status;
  13939. return soap->error;
  13940. }
  13941. p = soap->local_namespaces;
  13942. if (p)
  13943. { const char *ns = p[0].out;
  13944. if (!ns)
  13945. ns = p[0].ns;
  13946. if (!strcmp(ns, soap_env1))
  13947. { soap->version = 1; /* make sure we use SOAP 1.1 */
  13948. if (p[1].out)
  13949. SOAP_FREE(soap, p[1].out);
  13950. if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc1))))
  13951. strcpy(p[1].out, soap_enc1);
  13952. }
  13953. else if (!strcmp(ns, soap_env2))
  13954. { soap->version = 2; /* make sure we use SOAP 1.2 */
  13955. if (p[1].out)
  13956. SOAP_FREE(soap, p[1].out);
  13957. if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc2))))
  13958. strcpy(p[1].out, soap_enc2);
  13959. }
  13960. }
  13961. return SOAP_OK;
  13962. }
  13963. #endif
  13964. /******************************************************************************/
  13965. #ifndef PALM_1
  13966. SOAP_FMAC1
  13967. int
  13968. SOAP_FMAC2
  13969. soap_envelope_end_in(struct soap *soap)
  13970. { soap->part = SOAP_END_ENVELOPE;
  13971. return soap_element_end_in(soap, "SOAP-ENV:Envelope");
  13972. }
  13973. #endif
  13974. /******************************************************************************/
  13975. #ifndef PALM_2
  13976. SOAP_FMAC1
  13977. int
  13978. SOAP_FMAC2
  13979. soap_body_begin_out(struct soap *soap)
  13980. { soap->part = SOAP_IN_BODY;
  13981. if (soap->version == 1)
  13982. soap->encoding = 1;
  13983. #ifndef WITH_LEAN
  13984. if ((soap->mode & SOAP_XML_SEC) && soap_set_attr(soap, "wsu:Id", "Body", 1))
  13985. return soap->error;
  13986. #endif
  13987. if (soap_element(soap, "SOAP-ENV:Body", 0, NULL))
  13988. return soap->error;
  13989. return soap_element_start_end_out(soap, NULL);
  13990. }
  13991. #endif
  13992. /******************************************************************************/
  13993. #ifndef PALM_2
  13994. SOAP_FMAC1
  13995. int
  13996. SOAP_FMAC2
  13997. soap_body_end_out(struct soap *soap)
  13998. { if (soap_element_end_out(soap, "SOAP-ENV:Body"))
  13999. return soap->error;
  14000. soap->part = SOAP_END_BODY;
  14001. return SOAP_OK;
  14002. }
  14003. #endif
  14004. /******************************************************************************/
  14005. #ifndef PALM_2
  14006. SOAP_FMAC1
  14007. int
  14008. SOAP_FMAC2
  14009. soap_body_begin_in(struct soap *soap)
  14010. { soap->part = SOAP_IN_BODY;
  14011. if (soap_element_begin_in(soap, "SOAP-ENV:Body", 0, NULL))
  14012. return soap->error;
  14013. if (!soap->body)
  14014. soap->part = SOAP_NO_BODY;
  14015. return SOAP_OK;
  14016. }
  14017. #endif
  14018. /******************************************************************************/
  14019. #ifndef PALM_2
  14020. SOAP_FMAC1
  14021. int
  14022. SOAP_FMAC2
  14023. soap_body_end_in(struct soap *soap)
  14024. { if (soap->part == SOAP_NO_BODY)
  14025. return soap->error = SOAP_OK;
  14026. soap->part = SOAP_END_BODY;
  14027. return soap_element_end_in(soap, "SOAP-ENV:Body");
  14028. }
  14029. #endif
  14030. /******************************************************************************/
  14031. #ifndef PALM_2
  14032. SOAP_FMAC1
  14033. int
  14034. SOAP_FMAC2
  14035. soap_recv_header(struct soap *soap)
  14036. { if (soap_getheader(soap) && soap->error == SOAP_TAG_MISMATCH)
  14037. soap->error = SOAP_OK;
  14038. if (soap->error == SOAP_OK && soap->fheader)
  14039. soap->error = soap->fheader(soap);
  14040. return soap->error;
  14041. }
  14042. #endif
  14043. /******************************************************************************/
  14044. #ifndef PALM_1
  14045. SOAP_FMAC1
  14046. void
  14047. SOAP_FMAC2
  14048. soap_set_endpoint(struct soap *soap, const char *endpoint)
  14049. { register const char *s;
  14050. register size_t i, n;
  14051. soap->endpoint[0] = '\0';
  14052. soap->host[0] = '\0';
  14053. soap->path[0] = '/';
  14054. soap->path[1] = '\0';
  14055. soap->port = 80;
  14056. if (!endpoint || !*endpoint)
  14057. return;
  14058. #ifdef WITH_OPENSSL
  14059. if (!soap_tag_cmp(endpoint, "https:*"))
  14060. soap->port = 443;
  14061. #endif
  14062. strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint) - 1);
  14063. soap->endpoint[sizeof(soap->endpoint) - 1] = '\0';
  14064. s = strchr(endpoint, ':');
  14065. if (s && s[1] == '/' && s[2] == '/')
  14066. s += 3;
  14067. else
  14068. s = endpoint;
  14069. n = strlen(s);
  14070. if (n >= sizeof(soap->host))
  14071. n = sizeof(soap->host) - 1;
  14072. #ifdef WITH_IPV6
  14073. if (s[0] == '[')
  14074. { s++;
  14075. for (i = 0; i < n; i++)
  14076. { if (s[i] == ']')
  14077. { s++;
  14078. --n;
  14079. break;
  14080. }
  14081. soap->host[i] = s[i];
  14082. }
  14083. }
  14084. else
  14085. { for (i = 0; i < n; i++)
  14086. { soap->host[i] = s[i];
  14087. if (s[i] == '/' || s[i] == ':')
  14088. break;
  14089. }
  14090. }
  14091. #else
  14092. for (i = 0; i < n; i++)
  14093. { soap->host[i] = s[i];
  14094. if (s[i] == '/' || s[i] == ':')
  14095. break;
  14096. }
  14097. #endif
  14098. soap->host[i] = '\0';
  14099. if (s[i] == ':')
  14100. { soap->port = (int)soap_strtol(s + i + 1, NULL, 10);
  14101. for (i++; i < n; i++)
  14102. if (s[i] == '/')
  14103. break;
  14104. }
  14105. if (i < n && s[i])
  14106. { strncpy(soap->path, s + i, sizeof(soap->path));
  14107. soap->path[sizeof(soap->path) - 1] = '\0';
  14108. }
  14109. }
  14110. #endif
  14111. /******************************************************************************/
  14112. #ifndef PALM_1
  14113. SOAP_FMAC1
  14114. int
  14115. SOAP_FMAC2
  14116. soap_connect(struct soap *soap, const char *endpoint, const char *action)
  14117. { return soap_connect_command(soap, SOAP_POST, endpoint, action);
  14118. }
  14119. #endif
  14120. /******************************************************************************/
  14121. #ifndef PALM_1
  14122. SOAP_FMAC1
  14123. int
  14124. SOAP_FMAC2
  14125. soap_connect_command(struct soap *soap, int http_command, const char *endpoints, const char *action)
  14126. { char *endpoint;
  14127. const char *s;
  14128. if (endpoints && (s = strchr(endpoints, ' ')))
  14129. { endpoint = (char*)SOAP_MALLOC(soap, strlen(endpoints) + 1);
  14130. for (;;)
  14131. { strncpy(endpoint, endpoints, s - endpoints);
  14132. endpoint[s - endpoints] = '\0';
  14133. if (soap_try_connect_command(soap, http_command, endpoint, action) != SOAP_TCP_ERROR)
  14134. break;
  14135. if (!*s)
  14136. break;
  14137. soap->error = SOAP_OK;
  14138. while (*s == ' ')
  14139. s++;
  14140. endpoints = s;
  14141. s = strchr(endpoints, ' ');
  14142. if (!s)
  14143. s = endpoints + strlen(endpoints);
  14144. }
  14145. SOAP_FREE(soap, endpoint);
  14146. }
  14147. else
  14148. soap_try_connect_command(soap, http_command, endpoints, action);
  14149. return soap->error;
  14150. }
  14151. #endif
  14152. /******************************************************************************/
  14153. #ifndef PALM_1
  14154. static int
  14155. soap_try_connect_command(struct soap *soap, int http_command, const char *endpoint, const char *action)
  14156. { char host[sizeof(soap->host)];
  14157. int port;
  14158. size_t count;
  14159. soap->error = SOAP_OK;
  14160. strcpy(host, soap->host); /* save previous host name: if != then reconnect */
  14161. port = soap->port; /* save previous port to compare */
  14162. soap->status = http_command;
  14163. soap_set_endpoint(soap, endpoint);
  14164. #ifndef WITH_LEANER
  14165. if (soap->fconnect)
  14166. { if ((soap->error = soap->fconnect(soap, endpoint, soap->host, soap->port)))
  14167. return soap->error;
  14168. }
  14169. else
  14170. #endif
  14171. if (soap->fopen && *soap->host)
  14172. { if (!soap->keep_alive || !soap_valid_socket(soap->socket) || strcmp(soap->host, host) || soap->port != port || !soap->fpoll || soap->fpoll(soap))
  14173. { soap->keep_alive = 0; /* to force close */
  14174. soap->omode &= ~SOAP_IO_UDP; /* to force close */
  14175. soap_closesock(soap);
  14176. DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Connect/reconnect to host='%s' path='%s' port=%d\n", soap->host, soap->path, soap->port));
  14177. #ifndef WITH_LEAN
  14178. if (!strncmp(endpoint, "soap.udp:", 9))
  14179. soap->omode |= SOAP_IO_UDP;
  14180. #endif
  14181. soap->socket = soap->fopen(soap, endpoint, soap->host, soap->port);
  14182. if (soap->error)
  14183. return soap->error;
  14184. soap->keep_alive = ((soap->omode & SOAP_IO_KEEPALIVE) != 0);
  14185. }
  14186. }
  14187. count = soap_count_attachments(soap);
  14188. if (soap_begin_send(soap))
  14189. return soap->error;
  14190. if (http_command == SOAP_GET)
  14191. { soap->mode &= ~SOAP_IO;
  14192. soap->mode |= SOAP_IO_BUFFER;
  14193. }
  14194. #ifndef WITH_NOHTTP
  14195. soap->action = soap_strdup(soap, action);
  14196. if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML) && endpoint)
  14197. { unsigned int k = soap->mode;
  14198. soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB);
  14199. if ((k & SOAP_IO) != SOAP_IO_FLUSH)
  14200. soap->mode |= SOAP_IO_BUFFER;
  14201. if ((soap->error = soap->fpost(soap, endpoint, soap->host, soap->port, soap->path, action, count)))
  14202. return soap->error;
  14203. #ifndef WITH_LEANER
  14204. if ((k & SOAP_IO) == SOAP_IO_CHUNK)
  14205. { if (soap_flush(soap))
  14206. return soap->error;
  14207. }
  14208. #endif
  14209. soap->mode = k;
  14210. }
  14211. if (http_command == SOAP_GET)
  14212. return soap_end_send(soap);
  14213. #endif
  14214. return SOAP_OK;
  14215. }
  14216. #endif
  14217. /******************************************************************************/
  14218. #ifndef WITH_LEAN
  14219. SOAP_FMAC1
  14220. char*
  14221. SOAP_FMAC2
  14222. soap_s2base64(struct soap *soap, const unsigned char *s, char *t, int n)
  14223. { register int i;
  14224. register unsigned long m;
  14225. register char *p;
  14226. if (!t)
  14227. t = (char*)soap_malloc(soap, (n + 2) / 3 * 4 + 1);
  14228. if (!t)
  14229. return NULL;
  14230. p = t;
  14231. t[0] = '\0';
  14232. if (!s)
  14233. return p;
  14234. for (; n > 2; n -= 3, s += 3)
  14235. { m = s[0];
  14236. m = (m << 8) | s[1];
  14237. m = (m << 8) | s[2];
  14238. for (i = 4; i > 0; m >>= 6)
  14239. t[--i] = soap_base64o[m & 0x3F];
  14240. t += 4;
  14241. }
  14242. t[0] = '\0';
  14243. if (n > 0)
  14244. { m = 0;
  14245. for (i = 0; i < n; i++)
  14246. m = (m << 8) | *s++;
  14247. for (; i < 3; i++)
  14248. m <<= 8;
  14249. for (i++; i > 0; m >>= 6)
  14250. t[--i] = soap_base64o[m & 0x3F];
  14251. for (i = 3; i > n; i--)
  14252. t[i] = '=';
  14253. t[4] = '\0';
  14254. }
  14255. return p;
  14256. }
  14257. #endif
  14258. /******************************************************************************/
  14259. #ifndef WITH_LEAN
  14260. SOAP_FMAC1
  14261. const char*
  14262. SOAP_FMAC2
  14263. soap_base642s(struct soap *soap, const char *s, char *t, size_t l, int *n)
  14264. { register int i, j, c;
  14265. register unsigned long m;
  14266. register const char *p;
  14267. if (!s || !*s)
  14268. { if (n)
  14269. *n = 0;
  14270. if (soap->error)
  14271. return NULL;
  14272. return SOAP_NON_NULL;
  14273. }
  14274. if (!t)
  14275. { l = (strlen(s) + 3) / 4 * 3;
  14276. t = (char*)soap_malloc(soap, l);
  14277. }
  14278. if (!t)
  14279. return NULL;
  14280. p = t;
  14281. if (n)
  14282. *n = 0;
  14283. for (;;)
  14284. { for (i = 0; i < SOAP_BLKLEN; i++)
  14285. { m = 0;
  14286. j = 0;
  14287. while (j < 4)
  14288. { c = *s++;
  14289. if (c == '=' || !c)
  14290. { i *= 3;
  14291. switch (j)
  14292. { case 2:
  14293. *t++ = (char)((m >> 4) & 0xFF);
  14294. i++;
  14295. break;
  14296. case 3:
  14297. *t++ = (char)((m >> 10) & 0xFF);
  14298. *t++ = (char)((m >> 2) & 0xFF);
  14299. i += 2;
  14300. }
  14301. if (n)
  14302. *n += i;
  14303. return p;
  14304. }
  14305. c -= '+';
  14306. if (c >= 0 && c <= 79)
  14307. { int b = soap_base64i[c];
  14308. if (b >= 64)
  14309. { soap->error = SOAP_TYPE;
  14310. return NULL;
  14311. }
  14312. m = (m << 6) + b;
  14313. j++;
  14314. }
  14315. else if (!soap_blank(c + '+'))
  14316. { soap->error = SOAP_TYPE;
  14317. return NULL;
  14318. }
  14319. }
  14320. *t++ = (char)((m >> 16) & 0xFF);
  14321. *t++ = (char)((m >> 8) & 0xFF);
  14322. *t++ = (char)(m & 0xFF);
  14323. if (l < 3)
  14324. { if (n)
  14325. *n += i;
  14326. return p;
  14327. }
  14328. l -= 3;
  14329. }
  14330. if (n)
  14331. *n += 3 * SOAP_BLKLEN;
  14332. }
  14333. }
  14334. #endif
  14335. /******************************************************************************/
  14336. #ifndef WITH_LEAN
  14337. SOAP_FMAC1
  14338. char*
  14339. SOAP_FMAC2
  14340. soap_s2hex(struct soap *soap, const unsigned char *s, char *t, int n)
  14341. { register char *p;
  14342. if (!t)
  14343. t = (char*)soap_malloc(soap, 2 * n + 1);
  14344. if (!t)
  14345. return NULL;
  14346. p = t;
  14347. t[0] = '\0';
  14348. if (s)
  14349. { for (; n > 0; n--)
  14350. { register int m = *s++;
  14351. *t++ = (char)((m >> 4) + (m > 159 ? 'a' - 10 : '0'));
  14352. m &= 0x0F;
  14353. *t++ = (char)(m + (m > 9 ? 'a' - 10 : '0'));
  14354. }
  14355. }
  14356. *t++ = '\0';
  14357. return p;
  14358. }
  14359. #endif
  14360. /******************************************************************************/
  14361. #ifndef WITH_LEAN
  14362. SOAP_FMAC1
  14363. const char*
  14364. SOAP_FMAC2
  14365. soap_hex2s(struct soap *soap, const char *s, char *t, size_t l, int *n)
  14366. { register const char *p;
  14367. if (!s || !*s)
  14368. { if (n)
  14369. *n = 0;
  14370. if (soap->error)
  14371. return NULL;
  14372. return SOAP_NON_NULL;
  14373. }
  14374. if (!t)
  14375. { l = strlen(s) / 2;
  14376. t = (char*)soap_malloc(soap, l);
  14377. }
  14378. if (!t)
  14379. return NULL;
  14380. p = t;
  14381. while (l)
  14382. { register int d1, d2;
  14383. d1 = *s++;
  14384. if (!d1)
  14385. break;
  14386. d2 = *s++;
  14387. if (!d2)
  14388. break;
  14389. *t++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0');
  14390. l--;
  14391. }
  14392. if (n)
  14393. *n = (int)(t - p);
  14394. return p;
  14395. }
  14396. #endif
  14397. /******************************************************************************/
  14398. #ifndef WITH_NOHTTP
  14399. #ifndef PALM_1
  14400. SOAP_FMAC1
  14401. int
  14402. SOAP_FMAC2
  14403. soap_puthttphdr(struct soap *soap, int status, size_t count)
  14404. { if (soap->status != SOAP_GET)
  14405. { register const char *s = "text/xml; charset=utf-8";
  14406. register int err = SOAP_OK;
  14407. #ifndef WITH_LEANER
  14408. register const char *r = NULL;
  14409. #endif
  14410. if ((status == SOAP_FILE || soap->status == SOAP_POST_FILE) && soap->http_content)
  14411. s = soap->http_content;
  14412. else if (status == SOAP_HTML)
  14413. s = "text/html; charset=utf-8";
  14414. else if (count || ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK))
  14415. { if (soap->version == 2)
  14416. s = "application/soap+xml; charset=utf-8";
  14417. }
  14418. #ifndef WITH_LEANER
  14419. if (soap->mode & (SOAP_ENC_DIME | SOAP_ENC_MTOM))
  14420. { if (soap->mode & SOAP_ENC_MTOM)
  14421. { if (soap->version == 2)
  14422. r = "application/soap+xml";
  14423. else
  14424. r = "text/xml";
  14425. s = "application/xop+xml";
  14426. }
  14427. else
  14428. s = "application/dime";
  14429. }
  14430. if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && strlen(soap->mime.boundary) + strlen(soap->mime.start ? soap->mime.start : SOAP_STR_EOS) < sizeof(soap->tmpbuf) - 80)
  14431. { register const char *t = strchr(s, ';');
  14432. sprintf(soap->tmpbuf, "multipart/related; charset=utf-8; boundary=\"%s\"; type=\"", soap->mime.boundary);
  14433. if (t)
  14434. { strncat(soap->tmpbuf, s, t - s);
  14435. soap->tmpbuf[sizeof(soap->tmpbuf)-1] = '\0';
  14436. }
  14437. else
  14438. strcat(soap->tmpbuf, s);
  14439. if (soap->mime.start)
  14440. { strcat(soap->tmpbuf, "\"; start=\"");
  14441. strcat(soap->tmpbuf, soap->mime.start);
  14442. }
  14443. strcat(soap->tmpbuf, "\"");
  14444. if (r)
  14445. { strcat(soap->tmpbuf, "; start-info=\"");
  14446. strcat(soap->tmpbuf, r);
  14447. strcat(soap->tmpbuf, "\"");
  14448. }
  14449. s = soap->tmpbuf;
  14450. }
  14451. #endif
  14452. if (s && (err = soap->fposthdr(soap, "Content-Type", s)))
  14453. return err;
  14454. #ifdef WITH_ZLIB
  14455. if ((soap->omode & SOAP_ENC_ZLIB))
  14456. {
  14457. #ifdef WITH_GZIP
  14458. err = soap->fposthdr(soap, "Content-Encoding", soap->zlib_out == SOAP_ZLIB_DEFLATE ? "deflate" : "gzip");
  14459. #else
  14460. err = soap->fposthdr(soap, "Content-Encoding", "deflate");
  14461. #endif
  14462. if (err)
  14463. return err;
  14464. }
  14465. #endif
  14466. #ifndef WITH_LEANER
  14467. if ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK)
  14468. err = soap->fposthdr(soap, "Transfer-Encoding", "chunked");
  14469. else
  14470. #endif
  14471. if (s)
  14472. { sprintf(soap->tmpbuf, "%lu", (unsigned long)count);
  14473. err = soap->fposthdr(soap, "Content-Length", soap->tmpbuf);
  14474. }
  14475. if (err)
  14476. return err;
  14477. }
  14478. return soap->fposthdr(soap, "Connection", soap->keep_alive ? "keep-alive" : "close");
  14479. }
  14480. #endif
  14481. #endif
  14482. /******************************************************************************/
  14483. #ifndef WITH_LEAN
  14484. static const char*
  14485. soap_set_validation_fault(struct soap *soap, const char *s, const char *t)
  14486. { if (*soap->tag)
  14487. sprintf(soap->msgbuf, "Validation constraint violation: %s%s in element '%s'", s, t?t:SOAP_STR_EOS, soap->tag);
  14488. else
  14489. sprintf(soap->msgbuf, "Validation constraint violation: %s%s", s, t?t:SOAP_STR_EOS);
  14490. return soap->msgbuf;
  14491. }
  14492. #endif
  14493. /******************************************************************************/
  14494. #ifndef PALM_1
  14495. SOAP_FMAC1
  14496. void
  14497. SOAP_FMAC2
  14498. soap_set_fault(struct soap *soap)
  14499. { const char **c = soap_faultcode(soap);
  14500. const char **s = soap_faultstring(soap);
  14501. if (soap->fseterror)
  14502. soap->fseterror(soap, c, s);
  14503. if (!*c)
  14504. { if (soap->version == 2)
  14505. *c = "SOAP-ENV:Sender";
  14506. else
  14507. *c = "SOAP-ENV:Client";
  14508. }
  14509. if (*s)
  14510. return;
  14511. switch (soap->error)
  14512. {
  14513. #ifndef WITH_LEAN
  14514. case SOAP_CLI_FAULT:
  14515. *s = "Client fault";
  14516. break;
  14517. case SOAP_SVR_FAULT:
  14518. *s = "Server fault";
  14519. break;
  14520. case SOAP_TAG_MISMATCH:
  14521. *s = soap_set_validation_fault(soap, "tag name or namespace mismatch", NULL);
  14522. break;
  14523. case SOAP_TYPE:
  14524. *s = soap_set_validation_fault(soap, "data type mismatch ", soap->type);
  14525. break;
  14526. case SOAP_SYNTAX_ERROR:
  14527. *s = "Well-formedness violation";
  14528. break;
  14529. case SOAP_NO_TAG:
  14530. *s = "No XML root element";
  14531. break;
  14532. case SOAP_MUSTUNDERSTAND:
  14533. *c = "SOAP-ENV:MustUnderstand";
  14534. sprintf(soap->msgbuf, "The data in element '%s' must be understood but cannot be handled", soap->tag);
  14535. *s = soap->msgbuf;
  14536. break;
  14537. case SOAP_VERSIONMISMATCH:
  14538. *c = "SOAP-ENV:VersionMismatch";
  14539. *s = "Invalid SOAP message or SOAP version mismatch";
  14540. break;
  14541. case SOAP_DATAENCODINGUNKNOWN:
  14542. *c = "SOAP-ENV:DataEncodingUnknown";
  14543. *s = "Unsupported SOAP data encoding";
  14544. break;
  14545. case SOAP_NAMESPACE:
  14546. *s = soap_set_validation_fault(soap, "namespace error", NULL);
  14547. break;
  14548. case SOAP_USER_ERROR:
  14549. *s = "User error";
  14550. break;
  14551. case SOAP_FATAL_ERROR:
  14552. *s = "Fatal error";
  14553. break;
  14554. case SOAP_NO_METHOD:
  14555. sprintf(soap->msgbuf, "Method '%s' not implemented: method name or namespace not recognized", soap->tag);
  14556. *s = soap->msgbuf;
  14557. break;
  14558. case SOAP_NO_DATA:
  14559. *s = "Data required for operation";
  14560. break;
  14561. case SOAP_GET_METHOD:
  14562. *s = "HTTP GET method not implemented";
  14563. break;
  14564. case SOAP_PUT_METHOD:
  14565. *s = "HTTP PUT method not implemented";
  14566. break;
  14567. case SOAP_HEAD_METHOD:
  14568. *s = "HTTP HEAD method not implemented";
  14569. break;
  14570. case SOAP_HTTP_METHOD:
  14571. *s = "HTTP method not implemented";
  14572. break;
  14573. case SOAP_EOM:
  14574. *s = "Out of memory";
  14575. break;
  14576. case SOAP_MOE:
  14577. *s = "Memory overflow or memory corruption error";
  14578. break;
  14579. case SOAP_HDR:
  14580. *s = "Header line too long";
  14581. break;
  14582. case SOAP_IOB:
  14583. *s = "Array index out of bounds";
  14584. break;
  14585. case SOAP_NULL:
  14586. *s = soap_set_validation_fault(soap, "nil not allowed", NULL);
  14587. break;
  14588. case SOAP_DUPLICATE_ID:
  14589. *s = soap_set_validation_fault(soap, "multiple definitions of id ", soap->id);
  14590. if (soap->version == 2)
  14591. *soap_faultsubcode(soap) = "SOAP-ENC:DuplicateID";
  14592. break;
  14593. case SOAP_MISSING_ID:
  14594. *s = soap_set_validation_fault(soap, "missing id for ref ", soap->id);
  14595. if (soap->version == 2)
  14596. *soap_faultsubcode(soap) = "SOAP-ENC:MissingID";
  14597. break;
  14598. case SOAP_HREF:
  14599. *s = soap_set_validation_fault(soap, "incompatible object type ref/id pair ", soap->id);
  14600. break;
  14601. case SOAP_FAULT:
  14602. break;
  14603. #ifndef WITH_NOIO
  14604. case SOAP_UDP_ERROR:
  14605. *s = "Message too large for UDP packet";
  14606. break;
  14607. case SOAP_TCP_ERROR:
  14608. *s = tcp_error(soap);
  14609. break;
  14610. #endif
  14611. case SOAP_HTTP_ERROR:
  14612. *s = "An HTTP processing error occurred";
  14613. break;
  14614. case SOAP_SSL_ERROR:
  14615. #ifdef WITH_OPENSSL
  14616. *s = "SSL error";
  14617. #else
  14618. *s = "OpenSSL not installed: recompile with -DWITH_OPENSSL";
  14619. #endif
  14620. break;
  14621. case SOAP_PLUGIN_ERROR:
  14622. *s = "Plugin registry error";
  14623. break;
  14624. case SOAP_DIME_ERROR:
  14625. *s = "DIME format error";
  14626. break;
  14627. case SOAP_DIME_HREF:
  14628. *s = "DIME href to missing attachment";
  14629. break;
  14630. case SOAP_DIME_MISMATCH:
  14631. *s = "DIME version/transmission error";
  14632. break;
  14633. case SOAP_DIME_END:
  14634. *s = "End of DIME error";
  14635. break;
  14636. case SOAP_MIME_ERROR:
  14637. *s = "MIME format error";
  14638. break;
  14639. case SOAP_MIME_HREF:
  14640. *s = "MIME href to missing attachment";
  14641. break;
  14642. case SOAP_MIME_END:
  14643. *s = "End of MIME error";
  14644. break;
  14645. case SOAP_ZLIB_ERROR:
  14646. #ifdef WITH_ZLIB
  14647. sprintf(soap->msgbuf, "Zlib/gzip error: '%s'", soap->d_stream->msg?soap->d_stream->msg:SOAP_STR_EOS);
  14648. *s = soap->msgbuf;
  14649. #else
  14650. *s = "Zlib/gzip not installed for (de)compression: recompile with -DWITH_GZIP";
  14651. #endif
  14652. break;
  14653. case SOAP_REQUIRED:
  14654. *s = soap_set_validation_fault(soap, "missing required attribute", NULL);
  14655. break;
  14656. case SOAP_PROHIBITED:
  14657. *s = soap_set_validation_fault(soap, "prohibited attribute present", NULL);
  14658. break;
  14659. case SOAP_OCCURS:
  14660. *s = soap_set_validation_fault(soap, "occurrence violation", NULL);
  14661. break;
  14662. case SOAP_LENGTH:
  14663. *s = soap_set_validation_fault(soap, "content range or length violation", NULL);
  14664. break;
  14665. case SOAP_FD_EXCEEDED:
  14666. *s = "Maximum number of open connections was reached (no define HAVE_POLL): increase FD_SETSIZE";
  14667. break;
  14668. case SOAP_STOP:
  14669. *s = "Stopped: no response to be sent or received (informative)";
  14670. break;
  14671. #endif
  14672. case SOAP_EOF:
  14673. #ifndef WITH_NOIO
  14674. strcpy(soap->msgbuf, soap_strerror(soap));
  14675. #ifndef WITH_LEAN
  14676. if (strlen(soap->msgbuf) + 25 < sizeof(soap->msgbuf))
  14677. { memmove(soap->msgbuf + 25, soap->msgbuf, strlen(soap->msgbuf) + 1);
  14678. memcpy(soap->msgbuf, "End of file or no input: ", 25);
  14679. }
  14680. #endif
  14681. *s = soap->msgbuf;
  14682. break;
  14683. #else
  14684. *s = "End of file or no input";
  14685. break;
  14686. #endif
  14687. default:
  14688. #ifndef WITH_NOHTTP
  14689. #ifndef WITH_LEAN
  14690. if (soap->error > 200 && soap->error < 600)
  14691. { sprintf(soap->msgbuf, "HTTP Error: %d %s", soap->error, http_error(soap, soap->error));
  14692. *s = soap->msgbuf;
  14693. }
  14694. else
  14695. #endif
  14696. #endif
  14697. { sprintf(soap->msgbuf, "Error %d", soap->error);
  14698. *s = soap->msgbuf;
  14699. }
  14700. }
  14701. }
  14702. #endif
  14703. /******************************************************************************/
  14704. #ifndef PALM_1
  14705. SOAP_FMAC1
  14706. int
  14707. SOAP_FMAC2
  14708. soap_send_fault(struct soap *soap)
  14709. { register int status = soap->error;
  14710. if (status == SOAP_STOP)
  14711. return soap_closesock(soap);
  14712. DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Sending back fault struct for error code %d\n", soap->error));
  14713. soap->keep_alive = 0; /* to terminate connection */
  14714. soap_set_fault(soap);
  14715. if (soap->error < 200 && soap->error != SOAP_FAULT)
  14716. soap->header = NULL;
  14717. if (status != SOAP_EOF || (!soap->recv_timeout && !soap->send_timeout))
  14718. { int r = 1;
  14719. #ifndef WITH_NOIO
  14720. if (soap->fpoll && soap->fpoll(soap))
  14721. r = 0;
  14722. #ifndef WITH_LEAN
  14723. else if (soap_valid_socket(soap->socket))
  14724. { r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_SND, 0);
  14725. if (r > 0)
  14726. { if (!(r & SOAP_TCP_SELECT_SND)
  14727. || ((r & SOAP_TCP_SELECT_RCV)
  14728. && recv(soap->socket, soap->tmpbuf, 1, MSG_PEEK) < 0))
  14729. r = 0;
  14730. }
  14731. }
  14732. #endif
  14733. #endif
  14734. if (r > 0)
  14735. { soap->error = SOAP_OK;
  14736. soap_serializeheader(soap);
  14737. soap_serializefault(soap);
  14738. soap_begin_count(soap);
  14739. if (soap->mode & SOAP_IO_LENGTH)
  14740. { soap_envelope_begin_out(soap);
  14741. soap_putheader(soap);
  14742. soap_body_begin_out(soap);
  14743. soap_putfault(soap);
  14744. soap_body_end_out(soap);
  14745. soap_envelope_end_out(soap);
  14746. }
  14747. soap_end_count(soap);
  14748. if (soap_response(soap, status)
  14749. || soap_envelope_begin_out(soap)
  14750. || soap_putheader(soap)
  14751. || soap_body_begin_out(soap)
  14752. || soap_putfault(soap)
  14753. || soap_body_end_out(soap)
  14754. || soap_envelope_end_out(soap))
  14755. return soap_closesock(soap);
  14756. soap_end_send(soap);
  14757. }
  14758. }
  14759. soap->error = status;
  14760. return soap_closesock(soap);
  14761. }
  14762. #endif
  14763. /******************************************************************************/
  14764. #ifndef PALM_1
  14765. SOAP_FMAC1
  14766. int
  14767. SOAP_FMAC2
  14768. soap_recv_fault(struct soap *soap, int check)
  14769. { register int status = soap->error;
  14770. DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Check if receiving SOAP Fault\n"));
  14771. if (!check)
  14772. { /* try getfault when no tag or tag mismatched at level 2, otherwise ret */
  14773. if (soap->error != SOAP_NO_TAG
  14774. && (soap->error != SOAP_TAG_MISMATCH || soap->level != 2))
  14775. return soap->error;
  14776. }
  14777. soap->error = SOAP_OK;
  14778. if (soap_getfault(soap))
  14779. { /* check flag set: check if SOAP Fault is present, if not just return */
  14780. if (check && soap->error == SOAP_TAG_MISMATCH && soap->level == 2)
  14781. return soap->error = SOAP_OK;
  14782. DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Error: soap_get_soapfault() failed. Is this a SOAP message at all?\n"));
  14783. *soap_faultcode(soap) = (soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client");
  14784. soap->error = status;
  14785. soap_set_fault(soap);
  14786. }
  14787. else
  14788. { register const char *s = *soap_faultcode(soap);
  14789. if (!soap_match_tag(soap, s, "SOAP-ENV:Server") || !soap_match_tag(soap, s, "SOAP-ENV:Receiver"))
  14790. status = SOAP_SVR_FAULT;
  14791. else if (!soap_match_tag(soap, s, "SOAP-ENV:Client") || !soap_match_tag(soap, s, "SOAP-ENV:Sender"))
  14792. status = SOAP_CLI_FAULT;
  14793. else if (!soap_match_tag(soap, s, "SOAP-ENV:MustUnderstand"))
  14794. status = SOAP_MUSTUNDERSTAND;
  14795. else if (!soap_match_tag(soap, s, "SOAP-ENV:VersionMismatch"))
  14796. status = SOAP_VERSIONMISMATCH;
  14797. else
  14798. { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Received SOAP Fault code %s\n", s));
  14799. status = SOAP_FAULT;
  14800. }
  14801. if (!soap_body_end_in(soap))
  14802. soap_envelope_end_in(soap);
  14803. }
  14804. soap_end_recv(soap);
  14805. soap->error = status;
  14806. return soap_closesock(soap);
  14807. }
  14808. #endif
  14809. /******************************************************************************/
  14810. #ifndef WITH_NOHTTP
  14811. #ifndef PALM_1
  14812. SOAP_FMAC1
  14813. int
  14814. SOAP_FMAC2
  14815. soap_send_empty_response(struct soap *soap, int httpstatuscode)
  14816. { register soap_mode m = soap->omode;
  14817. soap->count = 0;
  14818. if ((m & SOAP_IO) == SOAP_IO_CHUNK)
  14819. soap->omode = (m & ~SOAP_IO) | SOAP_IO_BUFFER;
  14820. if (soap_response(soap, httpstatuscode) || soap_end_send(soap))
  14821. { soap->omode = m;
  14822. return soap_closesock(soap);
  14823. }
  14824. soap->omode = m;
  14825. return soap->error = SOAP_STOP; /* stops the server's response */
  14826. }
  14827. #endif
  14828. #endif
  14829. /******************************************************************************/
  14830. #ifndef WITH_NOHTTP
  14831. #ifndef PALM_1
  14832. SOAP_FMAC1
  14833. int
  14834. SOAP_FMAC2
  14835. soap_recv_empty_response(struct soap *soap)
  14836. { if (!soap_begin_recv(soap))
  14837. soap_end_recv(soap);
  14838. else if (soap->error == SOAP_NO_DATA || soap->error == 202)
  14839. soap->error = SOAP_OK;
  14840. return soap_closesock(soap);
  14841. }
  14842. #endif
  14843. #endif
  14844. /******************************************************************************/
  14845. #ifndef WITH_NOIO
  14846. #ifndef PALM_1
  14847. static const char*
  14848. soap_strerror(struct soap *soap)
  14849. { register int err = soap->errnum;
  14850. if (err)
  14851. {
  14852. #ifndef WIN32
  14853. return strerror(err);
  14854. #else
  14855. #ifndef UNDER_CE
  14856. DWORD len;
  14857. *soap->msgbuf = '\0';
  14858. len = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)soap->msgbuf, (DWORD)sizeof(soap->msgbuf), NULL);
  14859. #else
  14860. DWORD i, len;
  14861. *soap->msgbuf = '\0';
  14862. len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, 0, (LPTSTR)soap->msgbuf, (DWORD)(sizeof(soap->msgbuf)/sizeof(TCHAR)), NULL);
  14863. for (i = 0; i <= len; i++)
  14864. { if (((TCHAR*)soap->msgbuf)[i] < 0x80)
  14865. soap->msgbuf[i] = (char)((TCHAR*)soap->msgbuf)[i];
  14866. else
  14867. soap->msgbuf[i] = '?';
  14868. }
  14869. #endif
  14870. #endif
  14871. }
  14872. else
  14873. { char *s = soap->msgbuf;
  14874. #ifndef WITH_LEAN
  14875. int rt = soap->recv_timeout, st = soap->send_timeout;
  14876. int ru = ' ', su = ' ';
  14877. #endif
  14878. strcpy(s, "Operation interrupted or timed out");
  14879. #ifndef WITH_LEAN
  14880. if (rt < 0)
  14881. { rt = -rt;
  14882. ru = 'u';
  14883. }
  14884. if (st < 0)
  14885. { st = -st;
  14886. su = 'u';
  14887. }
  14888. if (rt)
  14889. sprintf(s + strlen(s), " (%d%cs receive delay)", rt, ru);
  14890. if (st)
  14891. sprintf(s + strlen(s), " (%d%cs send delay)", st, su);
  14892. #endif
  14893. }
  14894. return soap->msgbuf;
  14895. }
  14896. #endif
  14897. #endif
  14898. /******************************************************************************/
  14899. #ifndef PALM_2
  14900. static int
  14901. soap_set_error(struct soap *soap, const char *faultcode, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML, int soaperror)
  14902. { *soap_faultcode(soap) = faultcode;
  14903. if (faultsubcodeQName)
  14904. *soap_faultsubcode(soap) = faultsubcodeQName;
  14905. *soap_faultstring(soap) = faultstring;
  14906. if (faultdetailXML && *faultdetailXML)
  14907. { register const char **s = soap_faultdetail(soap);
  14908. if (s)
  14909. *s = faultdetailXML;
  14910. }
  14911. return soap->error = soaperror;
  14912. }
  14913. #endif
  14914. /******************************************************************************/
  14915. #ifndef PALM_2
  14916. SOAP_FMAC1
  14917. int
  14918. SOAP_FMAC2
  14919. soap_set_sender_error(struct soap *soap, const char *faultstring, const char *faultdetailXML, int soaperror)
  14920. { return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", NULL, faultstring, faultdetailXML, soaperror);
  14921. }
  14922. #endif
  14923. /******************************************************************************/
  14924. #ifndef PALM_2
  14925. SOAP_FMAC1
  14926. int
  14927. SOAP_FMAC2
  14928. soap_set_receiver_error(struct soap *soap, const char *faultstring, const char *faultdetailXML, int soaperror)
  14929. { return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", NULL, faultstring, faultdetailXML, soaperror);
  14930. }
  14931. #endif
  14932. /******************************************************************************/
  14933. #ifndef PALM_2
  14934. static int
  14935. soap_copy_fault(struct soap *soap, const char *faultcode, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML)
  14936. { char *r = NULL, *s = NULL, *t = NULL;
  14937. if (faultsubcodeQName)
  14938. r = soap_strdup(soap, faultsubcodeQName);
  14939. if (faultstring)
  14940. s = soap_strdup(soap, faultstring);
  14941. if (faultdetailXML)
  14942. t = soap_strdup(soap, faultdetailXML);
  14943. return soap_set_error(soap, faultcode, r, s, t, SOAP_FAULT);
  14944. }
  14945. #endif
  14946. /******************************************************************************/
  14947. #ifndef PALM_2
  14948. SOAP_FMAC1
  14949. int
  14950. SOAP_FMAC2
  14951. soap_sender_fault(struct soap *soap, const char *faultstring, const char *faultdetailXML)
  14952. { return soap_sender_fault_subcode(soap, NULL, faultstring, faultdetailXML);
  14953. }
  14954. #endif
  14955. /******************************************************************************/
  14956. #ifndef PALM_2
  14957. SOAP_FMAC1
  14958. int
  14959. SOAP_FMAC2
  14960. soap_sender_fault_subcode(struct soap *soap, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML)
  14961. { return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", faultsubcodeQName, faultstring, faultdetailXML);
  14962. }
  14963. #endif
  14964. /******************************************************************************/
  14965. #ifndef PALM_2
  14966. SOAP_FMAC1
  14967. int
  14968. SOAP_FMAC2
  14969. soap_receiver_fault(struct soap *soap, const char *faultstring, const char *faultdetailXML)
  14970. { return soap_receiver_fault_subcode(soap, NULL, faultstring, faultdetailXML);
  14971. }
  14972. #endif
  14973. /******************************************************************************/
  14974. #ifndef PALM_2
  14975. SOAP_FMAC1
  14976. int
  14977. SOAP_FMAC2
  14978. soap_receiver_fault_subcode(struct soap *soap, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML)
  14979. { return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", faultsubcodeQName, faultstring, faultdetailXML);
  14980. }
  14981. #endif
  14982. /******************************************************************************/
  14983. #ifndef PALM_2
  14984. #ifndef WITH_NOSTDLIB
  14985. SOAP_FMAC1
  14986. void
  14987. SOAP_FMAC2
  14988. soap_print_fault(struct soap *soap, FILE *fd)
  14989. { if (soap_check_state(soap))
  14990. fprintf(fd, "Error: soap struct state not initialized\n");
  14991. else if (soap->error)
  14992. { const char *c, *v = NULL, *s, **d;
  14993. d = soap_faultcode(soap);
  14994. if (!*d)
  14995. soap_set_fault(soap);
  14996. c = *d;
  14997. if (soap->version == 2)
  14998. v = *soap_faultsubcode(soap);
  14999. s = *soap_faultstring(soap);
  15000. d = soap_faultdetail(soap);
  15001. fprintf(fd, "%s%d fault: %s [%s]\n\"%s\"\nDetail: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, c, v ? v : "no subcode", s ? s : "[no reason]", d && *d ? *d : "[no detail]");
  15002. }
  15003. }
  15004. #endif
  15005. #endif
  15006. /******************************************************************************/
  15007. #ifdef __cplusplus
  15008. #ifndef WITH_LEAN
  15009. #ifndef WITH_NOSTDLIB
  15010. SOAP_FMAC1
  15011. void
  15012. SOAP_FMAC2
  15013. soap_stream_fault(struct soap *soap, std::ostream& os)
  15014. { if (soap_check_state(soap))
  15015. os << "Error: soap struct state not initialized\n";
  15016. else if (soap->error)
  15017. { const char *c, *v = NULL, *s, **d;
  15018. d = soap_faultcode(soap);
  15019. if (!*d)
  15020. soap_set_fault(soap);
  15021. c = *d;
  15022. if (soap->version == 2)
  15023. v = *soap_faultsubcode(soap);
  15024. s = *soap_faultstring(soap);
  15025. d = soap_faultdetail(soap);
  15026. os << (soap->version ? "SOAP 1." : "Error ")
  15027. << (soap->version ? (int)soap->version : soap->error)
  15028. << " fault: " << c
  15029. << "[" << (v ? v : "no subcode") << "]"
  15030. << std::endl
  15031. << "\"" << (s ? s : "[no reason]") << "\""
  15032. << std::endl
  15033. << "Detail: " << (d && *d ? *d : "[no detail]")
  15034. << std::endl;
  15035. }
  15036. }
  15037. #endif
  15038. #endif
  15039. #endif
  15040. /******************************************************************************/
  15041. #ifndef WITH_LEAN
  15042. #ifndef WITH_NOSTDLIB
  15043. SOAP_FMAC1
  15044. char*
  15045. SOAP_FMAC2
  15046. soap_sprint_fault(struct soap *soap, char *buf, size_t len)
  15047. { if (soap_check_state(soap))
  15048. strncpy(buf, "Error: soap struct not initialized", len);
  15049. else if (soap->error)
  15050. { const char *c, *v = NULL, *s, **d;
  15051. d = soap_faultcode(soap);
  15052. if (!*d)
  15053. soap_set_fault(soap);
  15054. c = *d;
  15055. if (soap->version == 2)
  15056. v = *soap_faultsubcode(soap);
  15057. s = *soap_faultstring(soap);
  15058. d = soap_faultdetail(soap);
  15059. #ifdef HAVE_SNPRINTF
  15060. # ifdef WIN32
  15061. _snprintf
  15062. # else
  15063. snprintf
  15064. # endif
  15065. (buf, len, "%s%d fault: %s [%s]\n\"%s\"\nDetail: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, c, v ? v : "no subcode", s ? s : "[no reason]", d && *d ? *d : "[no detail]");
  15066. #else
  15067. if (len > 40 + (v ? strlen(v) : 0) + (s ? strlen(s) : 0) + (d && *d ? strlen(*d) : 0))
  15068. sprintf(buf, "%s%d fault: %s [%s]\n\"%s\"\nDetail: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, c, v ? v : "no subcode", s ? s : "[no reason]", d && *d ? *d : "[no detail]");
  15069. else if (len > 40)
  15070. sprintf(buf, "%s%d fault: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, c);
  15071. else
  15072. buf[0] = '\0';
  15073. #endif
  15074. }
  15075. return buf;
  15076. }
  15077. #endif
  15078. #endif
  15079. /******************************************************************************/
  15080. #ifndef PALM_1
  15081. #ifndef WITH_NOSTDLIB
  15082. SOAP_FMAC1
  15083. void
  15084. SOAP_FMAC2
  15085. soap_print_fault_location(struct soap *soap, FILE *fd)
  15086. {
  15087. #ifndef WITH_LEAN
  15088. int i, j, c1, c2;
  15089. if (soap->error && soap->error != SOAP_STOP && soap->bufidx <= soap->buflen && soap->buflen > 0 && soap->buflen <= SOAP_BUFLEN)
  15090. { i = (int)soap->bufidx - 1;
  15091. if (i <= 0)
  15092. i = 0;
  15093. c1 = soap->buf[i];
  15094. soap->buf[i] = '\0';
  15095. if ((int)soap->buflen >= i + 1024)
  15096. j = i + 1023;
  15097. else
  15098. j = (int)soap->buflen - 1;
  15099. c2 = soap->buf[j];
  15100. soap->buf[j] = '\0';
  15101. fprintf(fd, "%s%c\n<!-- ** HERE ** -->\n", soap->buf, c1);
  15102. if (soap->bufidx < soap->buflen)
  15103. fprintf(fd, "%s\n", soap->buf + soap->bufidx);
  15104. soap->buf[i] = c1;
  15105. soap->buf[j] = c2;
  15106. }
  15107. #endif
  15108. }
  15109. #endif
  15110. #endif
  15111. /******************************************************************************/
  15112. #ifndef PALM_1
  15113. SOAP_FMAC1
  15114. int
  15115. SOAP_FMAC2
  15116. soap_register_plugin_arg(struct soap *soap, int (*fcreate)(struct soap*, struct soap_plugin*, void*), void *arg)
  15117. { register struct soap_plugin *p;
  15118. register int r;
  15119. if (!(p = (struct soap_plugin*)SOAP_MALLOC(soap, sizeof(struct soap_plugin))))
  15120. return soap->error = SOAP_EOM;
  15121. p->id = NULL;
  15122. p->data = NULL;
  15123. p->fcopy = NULL;
  15124. p->fdelete = NULL;
  15125. r = fcreate(soap, p, arg);
  15126. if (!r && p->fdelete)
  15127. { p->next = soap->plugins;
  15128. soap->plugins = p;
  15129. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Registered '%s' plugin\n", p->id));
  15130. return SOAP_OK;
  15131. }
  15132. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not register plugin '%s': plugin returned error %d (or fdelete callback not set)\n", p->id?p->id:"?", r));
  15133. SOAP_FREE(soap, p);
  15134. return r;
  15135. }
  15136. #endif
  15137. /******************************************************************************/
  15138. #ifndef PALM_1
  15139. static void *
  15140. fplugin(struct soap *soap, const char *id)
  15141. { register struct soap_plugin *p;
  15142. for (p = soap->plugins; p; p = p->next)
  15143. if (p->id == id || !strcmp(p->id, id))
  15144. return p->data;
  15145. return NULL;
  15146. }
  15147. #endif
  15148. /******************************************************************************/
  15149. #ifndef PALM_2
  15150. SOAP_FMAC1
  15151. void *
  15152. SOAP_FMAC2
  15153. soap_lookup_plugin(struct soap *soap, const char *id)
  15154. { return soap->fplugin(soap, id);
  15155. }
  15156. #endif
  15157. /******************************************************************************/
  15158. #ifdef __cplusplus
  15159. }
  15160. #endif
  15161. /******************************************************************************\
  15162. *
  15163. * C++ soap struct methods
  15164. *
  15165. \******************************************************************************/
  15166. #ifdef __cplusplus
  15167. soap::soap()
  15168. { soap_init(this);
  15169. }
  15170. #endif
  15171. /******************************************************************************/
  15172. #ifdef __cplusplus
  15173. soap::soap(soap_mode m)
  15174. { soap_init1(this, m);
  15175. }
  15176. #endif
  15177. /******************************************************************************/
  15178. #ifdef __cplusplus
  15179. soap::soap(soap_mode im, soap_mode om)
  15180. { soap_init2(this, im, om);
  15181. }
  15182. #endif
  15183. /******************************************************************************/
  15184. #ifdef __cplusplus
  15185. soap::soap(const struct soap& soap)
  15186. { soap_copy_context(this, &soap);
  15187. }
  15188. #endif
  15189. /******************************************************************************/
  15190. #ifdef __cplusplus
  15191. soap::~soap()
  15192. { soap_destroy(this);
  15193. soap_end(this);
  15194. soap_done(this);
  15195. }
  15196. #endif
  15197. /******************************************************************************/