Mercurial > repos > ktnyt > gembassy
comparison GEMBASSY-1.0.3/gsoap/stdsoap2.c @ 0:8300eb051bea draft
Initial upload
author | ktnyt |
---|---|
date | Fri, 26 Jun 2015 05:19:29 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:8300eb051bea |
---|---|
1 /* | |
2 stdsoap2.c[pp] 2.8.17r | |
3 | |
4 gSOAP runtime engine | |
5 | |
6 gSOAP XML Web services tools | |
7 Copyright (C) 2000-2013, Robert van Engelen, Genivia Inc., All Rights Reserved. | |
8 This part of the software is released under ONE of the following licenses: | |
9 GPL, or the gSOAP public license, or Genivia's license for commercial use. | |
10 -------------------------------------------------------------------------------- | |
11 Contributors: | |
12 | |
13 Wind River Systems Inc., for the following additions under gSOAP public license: | |
14 - vxWorks compatible options | |
15 -------------------------------------------------------------------------------- | |
16 gSOAP public license. | |
17 | |
18 The contents of this file are subject to the gSOAP Public License Version 1.3 | |
19 (the "License"); you may not use this file except in compliance with the | |
20 License. You may obtain a copy of the License at | |
21 http://www.cs.fsu.edu/~engelen/soaplicense.html | |
22 Software distributed under the License is distributed on an "AS IS" basis, | |
23 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |
24 for the specific language governing rights and limitations under the License. | |
25 | |
26 The Initial Developer of the Original Code is Robert A. van Engelen. | |
27 Copyright (C) 2000-2013, Robert van Engelen, Genivia Inc., All Rights Reserved. | |
28 -------------------------------------------------------------------------------- | |
29 GPL license. | |
30 | |
31 This program is free software; you can redistribute it and/or modify it under | |
32 the terms of the GNU General Public License as published by the Free Software | |
33 Foundation; either version 2 of the License, or (at your option) any later | |
34 version. | |
35 | |
36 This program is distributed in the hope that it will be useful, but WITHOUT ANY | |
37 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A | |
38 PARTICULAR PURPOSE. See the GNU General Public License for more details. | |
39 | |
40 You should have received a copy of the GNU General Public License along with | |
41 this program; if not, write to the Free Software Foundation, Inc., 59 Temple | |
42 Place, Suite 330, Boston, MA 02111-1307 USA | |
43 | |
44 Author contact information: | |
45 engelen@genivia.com / engelen@acm.org | |
46 | |
47 This program is released under the GPL with the additional exemption that | |
48 compiling, linking, and/or using OpenSSL is allowed. | |
49 -------------------------------------------------------------------------------- | |
50 A commercial use license is available from Genivia, Inc., contact@genivia.com | |
51 -------------------------------------------------------------------------------- | |
52 */ | |
53 | |
54 #define GSOAP_LIB_VERSION 20817 | |
55 | |
56 #ifdef AS400 | |
57 # pragma convert(819) /* EBCDIC to ASCII */ | |
58 #endif | |
59 | |
60 #include "stdsoap2.h" | |
61 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE) | |
62 #include <ipcom_key_db.h> | |
63 #endif | |
64 #if GSOAP_VERSION != GSOAP_LIB_VERSION | |
65 # error "GSOAP VERSION MISMATCH IN LIBRARY: PLEASE REINSTALL PACKAGE" | |
66 #endif | |
67 | |
68 #ifdef __BORLANDC__ | |
69 # pragma warn -8060 | |
70 #else | |
71 # ifdef WIN32 | |
72 # ifdef UNDER_CE | |
73 # pragma comment(lib, "ws2.lib") /* WinCE */ | |
74 # else | |
75 # pragma comment(lib, "ws2_32.lib") | |
76 # endif | |
77 # pragma warning(disable : 4996) /* disable deprecation warnings */ | |
78 # endif | |
79 #endif | |
80 | |
81 #ifdef __cplusplus | |
82 SOAP_SOURCE_STAMP("@(#) stdsoap2.cpp ver 2.8.17r 2013-12-18 00:00:00 GMT") | |
83 extern "C" { | |
84 #else | |
85 SOAP_SOURCE_STAMP("@(#) stdsoap2.c ver 2.8.17r 2013-12-18 00:00:00 GMT") | |
86 #endif | |
87 | |
88 /* 8bit character representing unknown/nonrepresentable character data (e.g. not supported by current locale with multibyte support enabled) */ | |
89 #ifndef SOAP_UNKNOWN_CHAR | |
90 #define SOAP_UNKNOWN_CHAR (127) | |
91 #endif | |
92 | |
93 /* EOF=-1 */ | |
94 #define SOAP_LT (soap_wchar)(-2) /* XML-specific '<' */ | |
95 #define SOAP_TT (soap_wchar)(-3) /* XML-specific '</' */ | |
96 #define SOAP_GT (soap_wchar)(-4) /* XML-specific '>' */ | |
97 #define SOAP_QT (soap_wchar)(-5) /* XML-specific '"' */ | |
98 #define SOAP_AP (soap_wchar)(-6) /* XML-specific ''' */ | |
99 | |
100 #define soap_blank(c) ((c)+1 > 0 && (c) <= 32) | |
101 #define soap_notblank(c) ((c) > 32) | |
102 | |
103 #if defined(WIN32) && !defined(UNDER_CE) | |
104 #define soap_hash_ptr(p) ((PtrToUlong(p) >> 3) & (SOAP_PTRHASH - 1)) | |
105 #else | |
106 #define soap_hash_ptr(p) ((size_t)(((unsigned long)(p) >> 3) & (SOAP_PTRHASH-1))) | |
107 #endif | |
108 | |
109 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG) | |
110 static void soap_init_logs(struct soap*); | |
111 #endif | |
112 #ifdef SOAP_DEBUG | |
113 static void soap_close_logfile(struct soap*, int); | |
114 static void soap_set_logfile(struct soap*, int, const char*); | |
115 #endif | |
116 | |
117 #ifdef SOAP_MEM_DEBUG | |
118 static void soap_init_mht(struct soap*); | |
119 static void soap_free_mht(struct soap*); | |
120 static void soap_track_unlink(struct soap*, const void*); | |
121 #endif | |
122 | |
123 #ifndef PALM_2 | |
124 static int soap_set_error(struct soap*, const char*, const char*, const char*, const char*, int); | |
125 static int soap_copy_fault(struct soap*, const char*, const char*, const char*, const char*); | |
126 static int soap_getattrval(struct soap*, char*, size_t, soap_wchar); | |
127 #endif | |
128 | |
129 #ifndef PALM_1 | |
130 static void soap_free_ns(struct soap *soap); | |
131 static soap_wchar soap_char(struct soap*); | |
132 static soap_wchar soap_get_pi(struct soap*); | |
133 static int soap_isxdigit(int); | |
134 static void *fplugin(struct soap*, const char*); | |
135 static size_t soap_count_attachments(struct soap *soap); | |
136 static int soap_try_connect_command(struct soap*, int http_command, const char *endpoint, const char *action); | |
137 #ifdef WITH_NTLM | |
138 static int soap_ntlm_handshake(struct soap *soap, int command, const char *endpoint, const char *host, int port); | |
139 #endif | |
140 #ifndef WITH_NOIDREF | |
141 static int soap_has_copies(struct soap*, const char*, const char*); | |
142 static void soap_init_iht(struct soap*); | |
143 static void soap_free_iht(struct soap*); | |
144 static void soap_init_pht(struct soap*); | |
145 static void soap_free_pht(struct soap*); | |
146 #endif | |
147 #endif | |
148 | |
149 #ifndef WITH_LEAN | |
150 static const char *soap_set_validation_fault(struct soap*, const char*, const char*); | |
151 static int soap_isnumeric(struct soap*, const char*); | |
152 static struct soap_nlist *soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized); | |
153 static void soap_utilize_ns(struct soap *soap, const char *tag); | |
154 #endif | |
155 | |
156 #ifndef WITH_LEANER | |
157 #ifndef PALM_1 | |
158 static struct soap_multipart *soap_new_multipart(struct soap*, struct soap_multipart**, struct soap_multipart**, char*, size_t); | |
159 static int soap_putdimefield(struct soap*, const char*, size_t); | |
160 static char *soap_getdimefield(struct soap*, size_t); | |
161 static void soap_select_mime_boundary(struct soap*); | |
162 static int soap_valid_mime_boundary(struct soap*); | |
163 static void soap_resolve_attachment(struct soap*, struct soap_multipart*); | |
164 #endif | |
165 #endif | |
166 | |
167 #ifdef WITH_GZIP | |
168 static int soap_getgziphdr(struct soap*); | |
169 #endif | |
170 | |
171 #ifdef WITH_OPENSSL | |
172 # ifndef SOAP_SSL_RSA_BITS | |
173 # define SOAP_SSL_RSA_BITS 2048 | |
174 # endif | |
175 static int soap_ssl_init_done = 0; | |
176 static int ssl_auth_init(struct soap*); | |
177 static int ssl_verify_callback(int, X509_STORE_CTX*); | |
178 static int ssl_verify_callback_allow_expired_certificate(int, X509_STORE_CTX*); | |
179 static int ssl_password(char*, int, int, void *); | |
180 #endif | |
181 | |
182 #ifdef WITH_GNUTLS | |
183 # ifndef SOAP_SSL_RSA_BITS | |
184 # define SOAP_SSL_RSA_BITS 2048 | |
185 # endif | |
186 static int soap_ssl_init_done = 0; | |
187 static const char *ssl_verify(struct soap *soap, const char *host); | |
188 # if defined(HAVE_PTHREAD_H) | |
189 # include <pthread.h> | |
190 /* make GNUTLS thread safe with pthreads */ | |
191 GCRY_THREAD_OPTION_PTHREAD_IMPL; | |
192 # elif defined(HAVE_PTH_H) | |
193 #include <pth.h> | |
194 /* make GNUTLS thread safe with PTH */ | |
195 GCRY_THREAD_OPTION_PTH_IMPL; | |
196 # endif | |
197 #endif | |
198 | |
199 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) | |
200 #ifndef PALM_1 | |
201 static const char *soap_decode(char*, size_t, const char*, const char*); | |
202 #endif | |
203 #endif | |
204 | |
205 #ifndef WITH_NOHTTP | |
206 #ifndef PALM_1 | |
207 static soap_wchar soap_getchunkchar(struct soap*); | |
208 static const char *http_error(struct soap*, int); | |
209 static int http_get(struct soap*); | |
210 static int http_405(struct soap*); | |
211 static int http_200(struct soap*); | |
212 static int http_post(struct soap*, const char*, const char*, int, const char*, const char*, size_t); | |
213 static int http_send_header(struct soap*, const char*); | |
214 static int http_post_header(struct soap*, const char*, const char*); | |
215 static int http_response(struct soap*, int, size_t); | |
216 static int http_parse(struct soap*); | |
217 static int http_parse_header(struct soap*, const char*, const char*); | |
218 #endif | |
219 #endif | |
220 | |
221 #ifndef WITH_NOIO | |
222 | |
223 #ifndef PALM_1 | |
224 static int fsend(struct soap*, const char*, size_t); | |
225 static size_t frecv(struct soap*, char*, size_t); | |
226 static int tcp_init(struct soap*); | |
227 static const char *tcp_error(struct soap*); | |
228 #ifndef WITH_IPV6 | |
229 static int tcp_gethost(struct soap*, const char *addr, struct in_addr *inaddr); | |
230 #endif | |
231 static SOAP_SOCKET tcp_connect(struct soap*, const char *endpoint, const char *host, int port); | |
232 static SOAP_SOCKET tcp_accept(struct soap*, SOAP_SOCKET, struct sockaddr*, int*); | |
233 static int tcp_select(struct soap*, SOAP_SOCKET, int, int); | |
234 static int tcp_disconnect(struct soap*); | |
235 static int tcp_closesocket(struct soap*, SOAP_SOCKET); | |
236 static int tcp_shutdownsocket(struct soap*, SOAP_SOCKET, int); | |
237 static const char *soap_strerror(struct soap*); | |
238 #endif | |
239 | |
240 #define SOAP_TCP_SELECT_RCV 0x1 | |
241 #define SOAP_TCP_SELECT_SND 0x2 | |
242 #define SOAP_TCP_SELECT_ERR 0x4 | |
243 #define SOAP_TCP_SELECT_ALL 0x7 | |
244 | |
245 #if defined(WIN32) | |
246 #define SOAP_SOCKBLOCK(fd) \ | |
247 { u_long blocking = 0; \ | |
248 ioctlsocket(fd, FIONBIO, &blocking); \ | |
249 } | |
250 #define SOAP_SOCKNONBLOCK(fd) \ | |
251 { u_long nonblocking = 1; \ | |
252 ioctlsocket(fd, FIONBIO, &nonblocking); \ | |
253 } | |
254 #elif defined(VXWORKS) | |
255 #define SOAP_SOCKBLOCK(fd) \ | |
256 { u_long blocking = 0; \ | |
257 ioctl(fd, FIONBIO, (int)(&blocking)); \ | |
258 } | |
259 #define SOAP_SOCKNONBLOCK(fd) \ | |
260 { u_long nonblocking = 1; \ | |
261 ioctl(fd, FIONBIO, (int)(&nonblocking)); \ | |
262 } | |
263 #elif defined(__VMS) | |
264 #define SOAP_SOCKBLOCK(fd) \ | |
265 { int blocking = 0; \ | |
266 ioctl(fd, FIONBIO, &blocking); \ | |
267 } | |
268 #define SOAP_SOCKNONBLOCK(fd) \ | |
269 { int nonblocking = 1; \ | |
270 ioctl(fd, FIONBIO, &nonblocking); \ | |
271 } | |
272 #elif defined(PALM) | |
273 #define SOAP_SOCKBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)&~O_NONBLOCK); | |
274 #define SOAP_SOCKNONBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)|O_NONBLOCK); | |
275 #elif defined(SYMBIAN) | |
276 #define SOAP_SOCKBLOCK(fd) \ | |
277 { long blocking = 0; \ | |
278 ioctl(fd, 0/*FIONBIO*/, &blocking); \ | |
279 } | |
280 #define SOAP_SOCKNONBLOCK(fd) \ | |
281 { long nonblocking = 1; \ | |
282 ioctl(fd, 0/*FIONBIO*/, &nonblocking); \ | |
283 } | |
284 #else | |
285 #define SOAP_SOCKBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)&~O_NONBLOCK); | |
286 #define SOAP_SOCKNONBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)|O_NONBLOCK); | |
287 #endif | |
288 | |
289 #endif | |
290 | |
291 #if defined(PALM) && !defined(PALM_2) | |
292 unsigned short errno; | |
293 #endif | |
294 | |
295 #ifndef PALM_1 | |
296 static const char soap_env1[42] = "http://schemas.xmlsoap.org/soap/envelope/"; | |
297 static const char soap_enc1[42] = "http://schemas.xmlsoap.org/soap/encoding/"; | |
298 static const char soap_env2[40] = "http://www.w3.org/2003/05/soap-envelope"; | |
299 static const char soap_enc2[40] = "http://www.w3.org/2003/05/soap-encoding"; | |
300 static const char soap_rpc[35] = "http://www.w3.org/2003/05/soap-rpc"; | |
301 #endif | |
302 | |
303 #ifndef PALM_1 | |
304 const union soap_double_nan soap_double_nan = {{0xFFFFFFFF, 0xFFFFFFFF}}; | |
305 const char soap_base64o[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | |
306 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"; | |
307 #endif | |
308 | |
309 #ifndef WITH_LEAN | |
310 static const char soap_indent[11] = "\n\t\t\t\t\t\t\t\t\t"; | |
311 /* Alternative indentation form for SOAP_XML_INDENT: | |
312 static const char soap_indent[21] = "\n "; | |
313 */ | |
314 #endif | |
315 | |
316 #ifndef SOAP_CANARY | |
317 # define SOAP_CANARY (0xC0DE) | |
318 #endif | |
319 | |
320 static const char soap_padding[4] = "\0\0\0"; | |
321 #define SOAP_STR_PADDING (soap_padding) | |
322 #define SOAP_STR_EOS (soap_padding) | |
323 #define SOAP_NON_NULL (soap_padding) | |
324 | |
325 #ifndef WITH_LEAN | |
326 static const struct soap_code_map html_entity_codes[] = /* entities for XHTML parsing */ | |
327 { { 160, "nbsp" }, | |
328 { 161, "iexcl" }, | |
329 { 162, "cent" }, | |
330 { 163, "pound" }, | |
331 { 164, "curren" }, | |
332 { 165, "yen" }, | |
333 { 166, "brvbar" }, | |
334 { 167, "sect" }, | |
335 { 168, "uml" }, | |
336 { 169, "copy" }, | |
337 { 170, "ordf" }, | |
338 { 171, "laquo" }, | |
339 { 172, "not" }, | |
340 { 173, "shy" }, | |
341 { 174, "reg" }, | |
342 { 175, "macr" }, | |
343 { 176, "deg" }, | |
344 { 177, "plusmn" }, | |
345 { 178, "sup2" }, | |
346 { 179, "sup3" }, | |
347 { 180, "acute" }, | |
348 { 181, "micro" }, | |
349 { 182, "para" }, | |
350 { 183, "middot" }, | |
351 { 184, "cedil" }, | |
352 { 185, "sup1" }, | |
353 { 186, "ordm" }, | |
354 { 187, "raquo" }, | |
355 { 188, "frac14" }, | |
356 { 189, "frac12" }, | |
357 { 190, "frac34" }, | |
358 { 191, "iquest" }, | |
359 { 192, "Agrave" }, | |
360 { 193, "Aacute" }, | |
361 { 194, "Acirc" }, | |
362 { 195, "Atilde" }, | |
363 { 196, "Auml" }, | |
364 { 197, "Aring" }, | |
365 { 198, "AElig" }, | |
366 { 199, "Ccedil" }, | |
367 { 200, "Egrave" }, | |
368 { 201, "Eacute" }, | |
369 { 202, "Ecirc" }, | |
370 { 203, "Euml" }, | |
371 { 204, "Igrave" }, | |
372 { 205, "Iacute" }, | |
373 { 206, "Icirc" }, | |
374 { 207, "Iuml" }, | |
375 { 208, "ETH" }, | |
376 { 209, "Ntilde" }, | |
377 { 210, "Ograve" }, | |
378 { 211, "Oacute" }, | |
379 { 212, "Ocirc" }, | |
380 { 213, "Otilde" }, | |
381 { 214, "Ouml" }, | |
382 { 215, "times" }, | |
383 { 216, "Oslash" }, | |
384 { 217, "Ugrave" }, | |
385 { 218, "Uacute" }, | |
386 { 219, "Ucirc" }, | |
387 { 220, "Uuml" }, | |
388 { 221, "Yacute" }, | |
389 { 222, "THORN" }, | |
390 { 223, "szlig" }, | |
391 { 224, "agrave" }, | |
392 { 225, "aacute" }, | |
393 { 226, "acirc" }, | |
394 { 227, "atilde" }, | |
395 { 228, "auml" }, | |
396 { 229, "aring" }, | |
397 { 230, "aelig" }, | |
398 { 231, "ccedil" }, | |
399 { 232, "egrave" }, | |
400 { 233, "eacute" }, | |
401 { 234, "ecirc" }, | |
402 { 235, "euml" }, | |
403 { 236, "igrave" }, | |
404 { 237, "iacute" }, | |
405 { 238, "icirc" }, | |
406 { 239, "iuml" }, | |
407 { 240, "eth" }, | |
408 { 241, "ntilde" }, | |
409 { 242, "ograve" }, | |
410 { 243, "oacute" }, | |
411 { 244, "ocirc" }, | |
412 { 245, "otilde" }, | |
413 { 246, "ouml" }, | |
414 { 247, "divide" }, | |
415 { 248, "oslash" }, | |
416 { 249, "ugrave" }, | |
417 { 250, "uacute" }, | |
418 { 251, "ucirc" }, | |
419 { 252, "uuml" }, | |
420 { 253, "yacute" }, | |
421 { 254, "thorn" }, | |
422 { 255, "yuml" }, | |
423 { 0, NULL } | |
424 }; | |
425 #endif | |
426 | |
427 #ifndef WITH_NOIO | |
428 #ifndef WITH_LEAN | |
429 static const struct soap_code_map h_error_codes[] = | |
430 { | |
431 #ifdef HOST_NOT_FOUND | |
432 { HOST_NOT_FOUND, "Host not found" }, | |
433 #endif | |
434 #ifdef TRY_AGAIN | |
435 { TRY_AGAIN, "Try Again" }, | |
436 #endif | |
437 #ifdef NO_RECOVERY | |
438 { NO_RECOVERY, "No Recovery" }, | |
439 #endif | |
440 #ifdef NO_DATA | |
441 { NO_DATA, "No Data" }, | |
442 #endif | |
443 #ifdef NO_ADDRESS | |
444 { NO_ADDRESS, "No Address" }, | |
445 #endif | |
446 { 0, NULL } | |
447 }; | |
448 #endif | |
449 #endif | |
450 | |
451 #ifndef WITH_NOHTTP | |
452 #ifndef WITH_LEAN | |
453 static const struct soap_code_map h_http_error_codes[] = | |
454 { { 200, "OK" }, | |
455 { 201, "Created" }, | |
456 { 202, "Accepted" }, | |
457 { 203, "Non-Authoritative Information" }, | |
458 { 204, "No Content" }, | |
459 { 205, "Reset Content" }, | |
460 { 206, "Partial Content" }, | |
461 { 300, "Multiple Choices" }, | |
462 { 301, "Moved Permanently" }, | |
463 { 302, "Found" }, | |
464 { 303, "See Other" }, | |
465 { 304, "Not Modified" }, | |
466 { 305, "Use Proxy" }, | |
467 { 307, "Temporary Redirect" }, | |
468 { 400, "Bad Request" }, | |
469 { 401, "Unauthorized" }, | |
470 { 402, "Payment Required" }, | |
471 { 403, "Forbidden" }, | |
472 { 404, "Not Found" }, | |
473 { 405, "Method Not Allowed" }, | |
474 { 406, "Not Acceptable" }, | |
475 { 407, "Proxy Authentication Required" }, | |
476 { 408, "Request Time-out" }, | |
477 { 409, "Conflict" }, | |
478 { 410, "Gone" }, | |
479 { 411, "Length Required" }, | |
480 { 412, "Precondition Failed" }, | |
481 { 413, "Request Entity Too Large" }, | |
482 { 414, "Request-URI Too Large" }, | |
483 { 415, "Unsupported Media Type" }, | |
484 { 416, "Requested range not satisfiable" }, | |
485 { 417, "Expectation Failed" }, | |
486 { 500, "Internal Server Error" }, | |
487 { 501, "Not Implemented" }, | |
488 { 502, "Bad Gateway" }, | |
489 { 503, "Service Unavailable" }, | |
490 { 504, "Gateway Time-out" }, | |
491 { 505, "HTTP Version not supported" }, | |
492 { 0, NULL } | |
493 }; | |
494 #endif | |
495 #endif | |
496 | |
497 #ifdef WITH_OPENSSL | |
498 static const struct soap_code_map h_ssl_error_codes[] = | |
499 { | |
500 #define _SSL_ERROR(e) { e, #e } | |
501 _SSL_ERROR(SSL_ERROR_SSL), | |
502 _SSL_ERROR(SSL_ERROR_ZERO_RETURN), | |
503 _SSL_ERROR(SSL_ERROR_WANT_READ), | |
504 _SSL_ERROR(SSL_ERROR_WANT_WRITE), | |
505 _SSL_ERROR(SSL_ERROR_WANT_CONNECT), | |
506 _SSL_ERROR(SSL_ERROR_WANT_X509_LOOKUP), | |
507 _SSL_ERROR(SSL_ERROR_SYSCALL), | |
508 { 0, NULL } | |
509 }; | |
510 #endif | |
511 | |
512 #ifndef WITH_LEANER | |
513 static const struct soap_code_map mime_codes[] = | |
514 { { SOAP_MIME_7BIT, "7bit" }, | |
515 { SOAP_MIME_8BIT, "8bit" }, | |
516 { SOAP_MIME_BINARY, "binary" }, | |
517 { SOAP_MIME_QUOTED_PRINTABLE, "quoted-printable" }, | |
518 { SOAP_MIME_BASE64, "base64" }, | |
519 { SOAP_MIME_IETF_TOKEN, "ietf-token" }, | |
520 { SOAP_MIME_X_TOKEN, "x-token" }, | |
521 { 0, NULL } | |
522 }; | |
523 #endif | |
524 | |
525 #ifdef WIN32 | |
526 static int tcp_done = 0; | |
527 #endif | |
528 | |
529 #if defined(HP_UX) && defined(HAVE_GETHOSTBYNAME_R) | |
530 extern int h_errno; | |
531 #endif | |
532 | |
533 /******************************************************************************/ | |
534 #ifndef WITH_NOIO | |
535 #ifndef PALM_1 | |
536 static int | |
537 fsend(struct soap *soap, const char *s, size_t n) | |
538 { register int nwritten, err; | |
539 SOAP_SOCKET sk; | |
540 #if defined(__cplusplus) && !defined(WITH_LEAN) && !defined(WITH_COMPAT) | |
541 if (soap->os) | |
542 { soap->os->write(s, (std::streamsize)n); | |
543 if (soap->os->good()) | |
544 return SOAP_OK; | |
545 soap->errnum = 0; | |
546 return SOAP_EOF; | |
547 } | |
548 #endif | |
549 sk = soap->sendsk; | |
550 if (!soap_valid_socket(sk)) | |
551 sk = soap->socket; | |
552 while (n) | |
553 { if (soap_valid_socket(sk)) | |
554 { | |
555 if (soap->send_timeout) | |
556 { for (;;) | |
557 { register int r; | |
558 #ifdef WITH_OPENSSL | |
559 if (soap->ssl) | |
560 r = tcp_select(soap, sk, SOAP_TCP_SELECT_ALL, soap->send_timeout); | |
561 else | |
562 #endif | |
563 #ifdef WITH_GNUTLS | |
564 if (soap->session) | |
565 r = tcp_select(soap, sk, SOAP_TCP_SELECT_ALL, soap->send_timeout); | |
566 else | |
567 #endif | |
568 r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->send_timeout); | |
569 if (r > 0) | |
570 break; | |
571 if (!r) | |
572 return SOAP_EOF; | |
573 err = soap->errnum; | |
574 if (!err) | |
575 return soap->error; | |
576 if (err != SOAP_EAGAIN && err != SOAP_EWOULDBLOCK) | |
577 return SOAP_EOF; | |
578 } | |
579 } | |
580 #ifdef WITH_OPENSSL | |
581 if (soap->ssl) | |
582 nwritten = SSL_write(soap->ssl, s, (int)n); | |
583 else if (soap->bio) | |
584 nwritten = BIO_write(soap->bio, s, (int)n); | |
585 else | |
586 #endif | |
587 #ifdef WITH_GNUTLS | |
588 if (soap->session) | |
589 nwritten = gnutls_record_send(soap->session, s, n); | |
590 else | |
591 #endif | |
592 #ifndef WITH_LEAN | |
593 if ((soap->omode & SOAP_IO_UDP)) | |
594 { if (soap->peerlen) | |
595 nwritten = sendto(sk, (char*)s, (SOAP_WINSOCKINT)n, soap->socket_flags, (struct sockaddr*)&soap->peer, (SOAP_WINSOCKINT)soap->peerlen); | |
596 else | |
597 nwritten = send(sk, s, (SOAP_WINSOCKINT)n, soap->socket_flags); | |
598 /* retry and back-off algorithm */ | |
599 /* TODO: this is not very clear from specs so verify and limit conditions under which we should loop (e.g. ENOBUFS) */ | |
600 if (nwritten < 0) | |
601 { int udp_repeat; | |
602 int udp_delay; | |
603 if ((soap->connect_flags & SO_BROADCAST)) | |
604 udp_repeat = 2; /* SOAP-over-UDP MULTICAST_UDP_REPEAT - 1 */ | |
605 else | |
606 udp_repeat = 1; /* SOAP-over-UDP UNICAST_UDP_REPEAT - 1 */ | |
607 udp_delay = ((unsigned int)soap_random % 201) + 50; /* UDP_MIN_DELAY .. UDP_MAX_DELAY */ | |
608 do | |
609 { tcp_select(soap, sk, SOAP_TCP_SELECT_ERR, -1000 * udp_delay); | |
610 if (soap->peerlen) | |
611 nwritten = sendto(sk, (char*)s, (SOAP_WINSOCKINT)n, soap->socket_flags, (struct sockaddr*)&soap->peer, (SOAP_WINSOCKINT)soap->peerlen); | |
612 else | |
613 nwritten = send(sk, s, (SOAP_WINSOCKINT)n, soap->socket_flags); | |
614 udp_delay <<= 1; | |
615 if (udp_delay > 500) /* UDP_UPPER_DELAY */ | |
616 udp_delay = 500; | |
617 } | |
618 while (nwritten < 0 && --udp_repeat > 0); | |
619 } | |
620 if (nwritten < 0) | |
621 { err = soap_socket_errno(sk); | |
622 if (err && err != SOAP_EINTR) | |
623 { soap->errnum = err; | |
624 return SOAP_EOF; | |
625 } | |
626 nwritten = 0; /* and call write() again */ | |
627 } | |
628 } | |
629 else | |
630 #endif | |
631 #if !defined(PALM) && !defined(AS400) | |
632 nwritten = send(sk, s, (int)n, soap->socket_flags); | |
633 #else | |
634 nwritten = send(sk, (void*)s, n, soap->socket_flags); | |
635 #endif | |
636 if (nwritten <= 0) | |
637 { | |
638 register int r = 0; | |
639 err = soap_socket_errno(sk); | |
640 #ifdef WITH_OPENSSL | |
641 if (soap->ssl && (r = SSL_get_error(soap->ssl, nwritten)) != SSL_ERROR_NONE && r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE) | |
642 { soap->errnum = err; | |
643 return SOAP_EOF; | |
644 } | |
645 #endif | |
646 #ifdef WITH_GNUTLS | |
647 if (soap->session) | |
648 { if (nwritten == GNUTLS_E_INTERRUPTED) | |
649 err = SOAP_EINTR; | |
650 else if (nwritten == GNUTLS_E_AGAIN) | |
651 err = SOAP_EAGAIN; | |
652 } | |
653 #endif | |
654 if (err == SOAP_EWOULDBLOCK || err == SOAP_EAGAIN) | |
655 { | |
656 #if defined(WITH_OPENSSL) | |
657 if (soap->ssl && r == SSL_ERROR_WANT_READ) | |
658 r = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->send_timeout ? soap->send_timeout : -10000); | |
659 else | |
660 #elif defined(WITH_GNUTLS) | |
661 if (soap->session && !gnutls_record_get_direction(soap->session)) | |
662 r = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->send_timeout ? soap->send_timeout : -10000); | |
663 else | |
664 #endif | |
665 r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->send_timeout ? soap->send_timeout : -10000); | |
666 if (!r && soap->send_timeout) | |
667 return SOAP_EOF; | |
668 if (r < 0) | |
669 return SOAP_EOF; | |
670 } | |
671 else if (err && err != SOAP_EINTR) | |
672 { soap->errnum = err; | |
673 return SOAP_EOF; | |
674 } | |
675 nwritten = 0; /* and call write() again */ | |
676 } | |
677 } | |
678 else | |
679 { | |
680 #ifdef WITH_FASTCGI | |
681 nwritten = fwrite((void*)s, 1, n, stdout); | |
682 fflush(stdout); | |
683 #else | |
684 #ifdef UNDER_CE | |
685 nwritten = fwrite(s, 1, n, soap->sendfd); | |
686 #else | |
687 #ifdef VXWORKS | |
688 #ifdef WMW_RPM_IO | |
689 if (soap->rpmreqid) | |
690 nwritten = (httpBlockPut(soap->rpmreqid, (char*)s, n) == 0) ? n : -1; | |
691 else | |
692 #endif | |
693 nwritten = fwrite(s, sizeof(char), n, fdopen(soap->sendfd, "w")); | |
694 #else | |
695 #ifdef WIN32 | |
696 nwritten = _write(soap->sendfd, s, (unsigned int)n); | |
697 #else | |
698 nwritten = write(soap->sendfd, s, (unsigned int)n); | |
699 #endif | |
700 #endif | |
701 #endif | |
702 #endif | |
703 if (nwritten <= 0) | |
704 { | |
705 #ifndef WITH_FASTCGI | |
706 err = soap_errno; | |
707 #else | |
708 err = EOF; | |
709 #endif | |
710 if (err && err != SOAP_EINTR && err != SOAP_EWOULDBLOCK && err != SOAP_EAGAIN) | |
711 { soap->errnum = err; | |
712 return SOAP_EOF; | |
713 } | |
714 nwritten = 0; /* and call write() again */ | |
715 } | |
716 } | |
717 n -= nwritten; | |
718 s += nwritten; | |
719 } | |
720 return SOAP_OK; | |
721 } | |
722 #endif | |
723 #endif | |
724 | |
725 /******************************************************************************/ | |
726 #ifndef PALM_1 | |
727 SOAP_FMAC1 | |
728 int | |
729 SOAP_FMAC2 | |
730 soap_send_raw(struct soap *soap, const char *s, size_t n) | |
731 { if (!n) | |
732 return SOAP_OK; | |
733 #ifndef WITH_LEANER | |
734 if (soap->fpreparesend && (soap->mode & SOAP_IO) != SOAP_IO_STORE && (soap->mode & SOAP_IO_LENGTH) && (soap->error = soap->fpreparesend(soap, s, n))) | |
735 return soap->error; | |
736 if (soap->ffiltersend && (soap->error = soap->ffiltersend(soap, &s, &n))) | |
737 return soap->error; | |
738 #endif | |
739 if (soap->mode & SOAP_IO_LENGTH) | |
740 soap->count += n; | |
741 else if (soap->mode & SOAP_IO) | |
742 { register size_t i = SOAP_BUFLEN - soap->bufidx; | |
743 while (n >= i) | |
744 { memcpy(soap->buf + soap->bufidx, s, i); | |
745 soap->bufidx = SOAP_BUFLEN; | |
746 if (soap_flush(soap)) | |
747 return soap->error; | |
748 s += i; | |
749 n -= i; | |
750 i = SOAP_BUFLEN; | |
751 } | |
752 memcpy(soap->buf + soap->bufidx, s, n); | |
753 soap->bufidx += n; | |
754 } | |
755 else | |
756 return soap_flush_raw(soap, s, n); | |
757 return SOAP_OK; | |
758 } | |
759 #endif | |
760 | |
761 /******************************************************************************/ | |
762 #ifndef PALM_1 | |
763 SOAP_FMAC1 | |
764 int | |
765 SOAP_FMAC2 | |
766 soap_flush(struct soap *soap) | |
767 { register size_t n = soap->bufidx; | |
768 if (n) | |
769 { | |
770 #ifndef WITH_LEANER | |
771 if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) | |
772 { register int r; | |
773 if (soap->fpreparesend && (r = soap->fpreparesend(soap, soap->buf, n))) | |
774 return soap->error = r; | |
775 } | |
776 #endif | |
777 soap->bufidx = 0; | |
778 #ifdef WITH_ZLIB | |
779 if (soap->mode & SOAP_ENC_ZLIB) | |
780 { soap->d_stream->next_in = (Byte*)soap->buf; | |
781 soap->d_stream->avail_in = (unsigned int)n; | |
782 #ifdef WITH_GZIP | |
783 soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)n); | |
784 #endif | |
785 do | |
786 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating %u bytes\n", soap->d_stream->avail_in)); | |
787 if (deflate(soap->d_stream, Z_NO_FLUSH) != Z_OK) | |
788 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to deflate: %s\n", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS)); | |
789 return soap->error = SOAP_ZLIB_ERROR; | |
790 } | |
791 if (!soap->d_stream->avail_out) | |
792 { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN)) | |
793 return soap->error; | |
794 soap->d_stream->next_out = (Byte*)soap->z_buf; | |
795 soap->d_stream->avail_out = SOAP_BUFLEN; | |
796 } | |
797 } while (soap->d_stream->avail_in); | |
798 } | |
799 else | |
800 #endif | |
801 return soap_flush_raw(soap, soap->buf, n); | |
802 } | |
803 return SOAP_OK; | |
804 } | |
805 #endif | |
806 | |
807 /******************************************************************************/ | |
808 #ifndef PALM_1 | |
809 SOAP_FMAC1 | |
810 int | |
811 SOAP_FMAC2 | |
812 soap_flush_raw(struct soap *soap, const char *s, size_t n) | |
813 { if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) | |
814 { register char *t; | |
815 if (!(t = (char*)soap_push_block(soap, NULL, n))) | |
816 return soap->error = SOAP_EOM; | |
817 memcpy(t, s, n); | |
818 return SOAP_OK; | |
819 } | |
820 #ifndef WITH_LEANER | |
821 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) | |
822 { char t[16]; | |
823 #ifdef HAVE_SNPRINTF | |
824 soap_snprintf(t, sizeof(t), &"\r\n%lX\r\n"[soap->chunksize ? 0 : 2], (unsigned long)n); | |
825 #else | |
826 sprintf(t, &"\r\n%lX\r\n"[soap->chunksize ? 0 : 2], (unsigned long)n); | |
827 #endif | |
828 DBGMSG(SENT, t, strlen(t)); | |
829 if ((soap->error = soap->fsend(soap, t, strlen(t)))) | |
830 return soap->error; | |
831 soap->chunksize += n; | |
832 } | |
833 DBGMSG(SENT, s, n); | |
834 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Send %u bytes to socket=%d/fd=%d\n", (unsigned int)n, soap->socket, soap->sendfd)); | |
835 #endif | |
836 return soap->error = soap->fsend(soap, s, n); | |
837 } | |
838 #endif | |
839 | |
840 /******************************************************************************/ | |
841 #ifndef PALM_1 | |
842 SOAP_FMAC1 | |
843 int | |
844 SOAP_FMAC2 | |
845 soap_send(struct soap *soap, const char *s) | |
846 { if (s) | |
847 return soap_send_raw(soap, s, strlen(s)); | |
848 return SOAP_OK; | |
849 } | |
850 #endif | |
851 | |
852 /******************************************************************************/ | |
853 #ifndef WITH_LEANER | |
854 #ifndef PALM_1 | |
855 SOAP_FMAC1 | |
856 int | |
857 SOAP_FMAC2 | |
858 soap_send2(struct soap *soap, const char *s1, const char *s2) | |
859 { if (soap_send(soap, s1)) | |
860 return soap->error; | |
861 return soap_send(soap, s2); | |
862 } | |
863 #endif | |
864 #endif | |
865 | |
866 /******************************************************************************/ | |
867 #ifndef WITH_LEANER | |
868 #ifndef PALM_1 | |
869 SOAP_FMAC1 | |
870 int | |
871 SOAP_FMAC2 | |
872 soap_send3(struct soap *soap, const char *s1, const char *s2, const char *s3) | |
873 { if (soap_send(soap, s1) | |
874 || soap_send(soap, s2)) | |
875 return soap->error; | |
876 return soap_send(soap, s3); | |
877 } | |
878 #endif | |
879 #endif | |
880 | |
881 /******************************************************************************/ | |
882 #ifndef WITH_NOIO | |
883 #ifndef PALM_1 | |
884 static size_t | |
885 frecv(struct soap *soap, char *s, size_t n) | |
886 { register int r; | |
887 register int retries = 100; /* max 100 retries with non-blocking sockets */ | |
888 SOAP_SOCKET sk; | |
889 soap->errnum = 0; | |
890 #if defined(__cplusplus) && !defined(WITH_LEAN) && !defined(WITH_COMPAT) | |
891 if (soap->is) | |
892 { if (soap->is->good()) | |
893 return soap->is->read(s, (std::streamsize)n).gcount(); | |
894 return 0; | |
895 } | |
896 #endif | |
897 sk = soap->recvsk; | |
898 if (!soap_valid_socket(sk)) | |
899 sk = soap->socket; | |
900 if (soap_valid_socket(sk)) | |
901 { for (;;) | |
902 { | |
903 #ifdef WITH_OPENSSL | |
904 register int err = 0; | |
905 #endif | |
906 #ifdef WITH_OPENSSL | |
907 if (soap->recv_timeout && !soap->ssl) /* SSL: sockets are nonblocking */ | |
908 #else | |
909 if (soap->recv_timeout) | |
910 #endif | |
911 { for (;;) | |
912 { r = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->recv_timeout); | |
913 if (r > 0) | |
914 break; | |
915 if (!r) | |
916 return 0; | |
917 r = soap->errnum; | |
918 if (r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK) | |
919 return 0; | |
920 } | |
921 } | |
922 #ifdef WITH_OPENSSL | |
923 if (soap->ssl) | |
924 { r = SSL_read(soap->ssl, s, (int)n); | |
925 if (r > 0) | |
926 return (size_t)r; | |
927 err = SSL_get_error(soap->ssl, r); | |
928 if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) | |
929 return 0; | |
930 } | |
931 else if (soap->bio) | |
932 { r = BIO_read(soap->bio, s, (int)n); | |
933 if (r > 0) | |
934 return (size_t)r; | |
935 return 0; | |
936 } | |
937 else | |
938 #endif | |
939 #ifdef WITH_GNUTLS | |
940 if (soap->session) | |
941 { r = (int)gnutls_record_recv(soap->session, s, n); | |
942 if (r >= 0) | |
943 return (size_t)r; | |
944 } | |
945 else | |
946 #endif | |
947 { | |
948 #ifndef WITH_LEAN | |
949 if ((soap->omode & SOAP_IO_UDP)) | |
950 { SOAP_SOCKLEN_T k = (SOAP_SOCKLEN_T)sizeof(soap->peer); | |
951 memset((void*)&soap->peer, 0, sizeof(soap->peer)); | |
952 r = recvfrom(sk, s, (SOAP_WINSOCKINT)n, soap->socket_flags, (struct sockaddr*)&soap->peer, &k); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */ | |
953 soap->peerlen = (size_t)k; | |
954 #ifndef WITH_IPV6 | |
955 soap->ip = ntohl(soap->peer.sin_addr.s_addr); | |
956 #endif | |
957 } | |
958 else | |
959 #endif | |
960 r = recv(sk, s, (int)n, soap->socket_flags); | |
961 #ifdef PALM | |
962 /* CycleSyncDisplay(curStatusMsg); */ | |
963 #endif | |
964 if (r >= 0) | |
965 return (size_t)r; | |
966 r = soap_socket_errno(sk); | |
967 if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK) | |
968 { soap->errnum = r; | |
969 return 0; | |
970 } | |
971 } | |
972 #if defined(WITH_OPENSSL) | |
973 if (soap->ssl && err == SSL_ERROR_WANT_WRITE) | |
974 r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5); | |
975 else | |
976 #elif defined(WITH_GNUTLS) | |
977 if (soap->session && gnutls_record_get_direction(soap->session)) | |
978 r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5); | |
979 else | |
980 #endif | |
981 r = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5); | |
982 if (!r && soap->recv_timeout) | |
983 return 0; | |
984 if (r < 0) | |
985 { r = soap->errnum; | |
986 if (r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK) | |
987 return 0; | |
988 } | |
989 if (retries-- <= 0) | |
990 return 0; | |
991 #ifdef PALM | |
992 r = soap_socket_errno(sk); | |
993 if (r != SOAP_EINTR && retries-- <= 0) | |
994 { soap->errnum = r; | |
995 return 0; | |
996 } | |
997 #endif | |
998 } | |
999 } | |
1000 #ifdef WITH_FASTCGI | |
1001 return fread(s, 1, n, stdin); | |
1002 #else | |
1003 #ifdef UNDER_CE | |
1004 return fread(s, 1, n, soap->recvfd); | |
1005 #else | |
1006 #ifdef WMW_RPM_IO | |
1007 if (soap->rpmreqid) | |
1008 r = httpBlockRead(soap->rpmreqid, s, n); | |
1009 else | |
1010 #endif | |
1011 #ifdef WIN32 | |
1012 r = _read(soap->recvfd, s, (unsigned int)n); | |
1013 #else | |
1014 r = read(soap->recvfd, s, (unsigned int)n); | |
1015 #endif | |
1016 if (r >= 0) | |
1017 return (size_t)r; | |
1018 soap->errnum = soap_errno; | |
1019 return 0; | |
1020 #endif | |
1021 #endif | |
1022 } | |
1023 #endif | |
1024 #endif | |
1025 | |
1026 /******************************************************************************/ | |
1027 #ifndef WITH_NOHTTP | |
1028 #ifndef PALM_1 | |
1029 static soap_wchar | |
1030 soap_getchunkchar(struct soap *soap) | |
1031 { if (soap->bufidx < soap->buflen) | |
1032 return soap->buf[soap->bufidx++]; | |
1033 soap->bufidx = 0; | |
1034 soap->buflen = soap->chunkbuflen = soap->frecv(soap, soap->buf, SOAP_BUFLEN); | |
1035 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket=%d/fd=%d\n", (unsigned int)soap->buflen, soap->socket, soap->recvfd)); | |
1036 DBGMSG(RECV, soap->buf, soap->buflen); | |
1037 if (soap->buflen) | |
1038 return soap->buf[soap->bufidx++]; | |
1039 return EOF; | |
1040 } | |
1041 #endif | |
1042 #endif | |
1043 | |
1044 /******************************************************************************/ | |
1045 #ifndef PALM_1 | |
1046 static int | |
1047 soap_isxdigit(int c) | |
1048 { return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); | |
1049 } | |
1050 #endif | |
1051 | |
1052 /******************************************************************************/ | |
1053 #ifndef PALM_1 | |
1054 SOAP_FMAC1 | |
1055 int | |
1056 SOAP_FMAC2 | |
1057 soap_recv_raw(struct soap *soap) | |
1058 { register size_t ret; | |
1059 #if !defined(WITH_LEANER) || defined(WITH_ZLIB) | |
1060 register int r; | |
1061 #endif | |
1062 #ifdef WITH_ZLIB | |
1063 if (soap->mode & SOAP_ENC_ZLIB) | |
1064 { if (soap->d_stream->next_out == Z_NULL) | |
1065 { soap->bufidx = soap->buflen = 0; | |
1066 return EOF; | |
1067 } | |
1068 if (soap->d_stream->avail_in || !soap->d_stream->avail_out) | |
1069 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflating\n")); | |
1070 soap->d_stream->next_out = (Byte*)soap->buf; | |
1071 soap->d_stream->avail_out = SOAP_BUFLEN; | |
1072 r = inflate(soap->d_stream, Z_NO_FLUSH); | |
1073 if (r == Z_NEED_DICT && soap->z_dict) | |
1074 r = inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len); | |
1075 if (r == Z_OK || r == Z_STREAM_END) | |
1076 { soap->bufidx = 0; | |
1077 ret = soap->buflen = SOAP_BUFLEN - soap->d_stream->avail_out; | |
1078 if (soap->zlib_in == SOAP_ZLIB_GZIP) | |
1079 soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)ret); | |
1080 if (r == Z_STREAM_END) | |
1081 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out)); | |
1082 soap->z_ratio_in = (float)soap->d_stream->total_in / (float)soap->d_stream->total_out; | |
1083 soap->d_stream->next_out = Z_NULL; | |
1084 } | |
1085 if (ret) | |
1086 { soap->count += ret; | |
1087 DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- decompressed ----\n")); | |
1088 DBGMSG(RECV, soap->buf, ret); | |
1089 DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n----\n")); | |
1090 #ifndef WITH_LEANER | |
1091 if (soap->fpreparerecv && (r = soap->fpreparerecv(soap, soap->buf, ret))) | |
1092 return soap->error = r; | |
1093 #endif | |
1094 return SOAP_OK; | |
1095 } | |
1096 } | |
1097 else if (r != Z_BUF_ERROR) | |
1098 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate error: %s\n", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS)); | |
1099 soap->d_stream->next_out = Z_NULL; | |
1100 return soap->error = SOAP_ZLIB_ERROR; | |
1101 } | |
1102 } | |
1103 zlib_again: | |
1104 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK && !soap->chunksize) | |
1105 { memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN); | |
1106 soap->buflen = soap->z_buflen; | |
1107 } | |
1108 DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- compressed ----\n")); | |
1109 } | |
1110 #endif | |
1111 #ifndef WITH_NOHTTP | |
1112 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) /* read HTTP chunked transfer */ | |
1113 { for (;;) | |
1114 { register soap_wchar c; | |
1115 char *t, tmp[17]; | |
1116 if (soap->chunksize) | |
1117 { soap->buflen = ret = soap->frecv(soap, soap->buf, soap->chunksize > SOAP_BUFLEN ? SOAP_BUFLEN : soap->chunksize); | |
1118 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk: read %u bytes\n", (unsigned int)ret)); | |
1119 DBGMSG(RECV, soap->buf, ret); | |
1120 soap->bufidx = 0; | |
1121 soap->chunksize -= ret; | |
1122 break; | |
1123 } | |
1124 t = tmp; | |
1125 if (!soap->chunkbuflen) | |
1126 { soap->chunkbuflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN); | |
1127 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes (chunked) from socket=%d\n", (unsigned int)ret, soap->socket)); | |
1128 DBGMSG(RECV, soap->buf, ret); | |
1129 soap->bufidx = 0; | |
1130 if (!ret) | |
1131 { soap->ahead = EOF; | |
1132 return EOF; | |
1133 } | |
1134 } | |
1135 else | |
1136 soap->bufidx = soap->buflen; | |
1137 soap->buflen = soap->chunkbuflen; | |
1138 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk size (idx=%u len=%u)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen)); | |
1139 while (!soap_isxdigit((int)(c = soap_getchunkchar(soap)))) | |
1140 { if ((int)c == EOF) | |
1141 { soap->ahead = EOF; | |
1142 return EOF; | |
1143 } | |
1144 } | |
1145 do | |
1146 *t++ = (char)c; | |
1147 while (soap_isxdigit((int)(c = soap_getchunkchar(soap))) && (size_t)(t - tmp) < sizeof(tmp)-1); | |
1148 while ((int)c != EOF && c != '\n') | |
1149 c = soap_getchunkchar(soap); | |
1150 if ((int)c == EOF) | |
1151 { soap->ahead = EOF; | |
1152 return EOF; | |
1153 } | |
1154 *t = '\0'; | |
1155 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunk size = %s (hex)\n", tmp)); | |
1156 soap->chunksize = (size_t)soap_strtoul(tmp, &t, 16); | |
1157 if (!soap->chunksize) | |
1158 { soap->bufidx = soap->buflen = soap->chunkbuflen = 0; | |
1159 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of chunked message\n")); | |
1160 while ((int)c != EOF && c != '\n') | |
1161 c = soap_getchunkchar(soap); | |
1162 ret = 0; | |
1163 soap->ahead = EOF; | |
1164 break; | |
1165 } | |
1166 soap->buflen = soap->bufidx + soap->chunksize; | |
1167 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving buf len to idx=%u len=%u (%s)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen, tmp)); | |
1168 if (soap->buflen > soap->chunkbuflen) | |
1169 { soap->buflen = soap->chunkbuflen; | |
1170 soap->chunksize -= soap->buflen - soap->bufidx; | |
1171 soap->chunkbuflen = 0; | |
1172 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Passed end of buffer for chunked HTTP (%u bytes left)\n", (unsigned int)(soap->buflen - soap->bufidx))); | |
1173 } | |
1174 else if (soap->chunkbuflen) | |
1175 soap->chunksize = 0; | |
1176 ret = soap->buflen - soap->bufidx; | |
1177 if (ret) | |
1178 break; | |
1179 } | |
1180 } | |
1181 else | |
1182 #endif | |
1183 { soap->bufidx = 0; | |
1184 soap->buflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN); | |
1185 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket=%d/fd=%d\n", (unsigned int)ret, soap->socket, soap->recvfd)); | |
1186 DBGMSG(RECV, soap->buf, ret); | |
1187 } | |
1188 #ifdef WITH_ZLIB | |
1189 if (soap->mode & SOAP_ENC_ZLIB) | |
1190 { memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); | |
1191 soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx); | |
1192 soap->d_stream->avail_in = (unsigned int)ret; | |
1193 soap->d_stream->next_out = (Byte*)soap->buf; | |
1194 soap->d_stream->avail_out = SOAP_BUFLEN; | |
1195 r = inflate(soap->d_stream, Z_NO_FLUSH); | |
1196 if (r == Z_NEED_DICT && soap->z_dict) | |
1197 r = inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len); | |
1198 if (r == Z_OK || r == Z_STREAM_END) | |
1199 { soap->bufidx = 0; | |
1200 soap->z_buflen = soap->buflen; | |
1201 soap->buflen = SOAP_BUFLEN - soap->d_stream->avail_out; | |
1202 if (soap->zlib_in == SOAP_ZLIB_GZIP) | |
1203 soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen); | |
1204 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %u bytes\n", (unsigned int)soap->buflen)); | |
1205 if (ret && !soap->buflen && r != Z_STREAM_END) | |
1206 goto zlib_again; | |
1207 ret = soap->buflen; | |
1208 if (r == Z_STREAM_END) | |
1209 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated total %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out)); | |
1210 soap->z_ratio_in = (float)soap->d_stream->total_in / (float)soap->d_stream->total_out; | |
1211 soap->d_stream->next_out = Z_NULL; | |
1212 } | |
1213 DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- decompressed ----\n")); | |
1214 DBGMSG(RECV, soap->buf, ret); | |
1215 #ifndef WITH_LEANER | |
1216 if (soap->fpreparerecv && (r = soap->fpreparerecv(soap, soap->buf, ret))) | |
1217 return soap->error = r; | |
1218 #endif | |
1219 } | |
1220 else | |
1221 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to inflate: (%d) %s\n", r, soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS)); | |
1222 soap->d_stream->next_out = Z_NULL; | |
1223 return soap->error = SOAP_ZLIB_ERROR; | |
1224 } | |
1225 } | |
1226 #endif | |
1227 #ifndef WITH_LEANER | |
1228 if (soap->fpreparerecv | |
1229 #ifdef WITH_ZLIB | |
1230 && soap->zlib_in == SOAP_ZLIB_NONE | |
1231 #endif | |
1232 && (r = soap->fpreparerecv(soap, soap->buf + soap->bufidx, ret))) | |
1233 return soap->error = r; | |
1234 #endif | |
1235 soap->count += ret; | |
1236 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read count=%lu (+%lu)\n", (unsigned long)soap->count, (unsigned long)ret)); | |
1237 return !ret; | |
1238 } | |
1239 #endif | |
1240 | |
1241 /******************************************************************************/ | |
1242 #ifndef PALM_1 | |
1243 SOAP_FMAC1 | |
1244 int | |
1245 SOAP_FMAC2 | |
1246 soap_recv(struct soap *soap) | |
1247 { | |
1248 #ifndef WITH_LEANER | |
1249 if (soap->mode & SOAP_ENC_DIME) | |
1250 { if (soap->dime.buflen) | |
1251 { char *s; | |
1252 int i; | |
1253 unsigned char tmp[12]; | |
1254 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME hdr for chunked DIME is in buffer\n")); | |
1255 soap->count += soap->dime.buflen - soap->buflen; | |
1256 soap->buflen = soap->dime.buflen; | |
1257 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Skip padding (%ld bytes)\n", -(long)soap->dime.size&3)); | |
1258 for (i = -(long)soap->dime.size&3; i > 0; i--) | |
1259 { soap->bufidx++; | |
1260 if (soap->bufidx >= soap->buflen) | |
1261 if (soap_recv_raw(soap)) | |
1262 return EOF; | |
1263 } | |
1264 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME hdr for next chunk\n")); | |
1265 s = (char*)tmp; | |
1266 for (i = 12; i > 0; i--) | |
1267 { *s++ = soap->buf[soap->bufidx++]; | |
1268 if (soap->bufidx >= soap->buflen) | |
1269 if (soap_recv_raw(soap)) | |
1270 return EOF; | |
1271 } | |
1272 soap->dime.flags = tmp[0] & 0x7; | |
1273 soap->dime.size = ((size_t)tmp[8] << 24) | ((size_t)tmp[9] << 16) | ((size_t)tmp[10] << 8) | ((size_t)tmp[11]); | |
1274 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME chunk (%u bytes)\n", (unsigned int)soap->dime.size)); | |
1275 if (soap->dime.flags & SOAP_DIME_CF) | |
1276 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "More chunking\n")); | |
1277 soap->dime.chunksize = soap->dime.size; | |
1278 if (soap->buflen - soap->bufidx >= soap->dime.size) | |
1279 { soap->dime.buflen = soap->buflen; | |
1280 soap->buflen = soap->bufidx + soap->dime.chunksize; | |
1281 } | |
1282 else | |
1283 soap->dime.chunksize -= soap->buflen - soap->bufidx; | |
1284 } | |
1285 else | |
1286 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Last chunk\n")); | |
1287 soap->dime.buflen = 0; | |
1288 soap->dime.chunksize = 0; | |
1289 } | |
1290 soap->count = soap->buflen - soap->bufidx; | |
1291 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%u bytes remaining\n", (unsigned int)soap->count)); | |
1292 return SOAP_OK; | |
1293 } | |
1294 if (soap->dime.chunksize) | |
1295 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get next DIME hdr for chunked DIME (%u bytes chunk)\n", (unsigned int)soap->dime.chunksize)); | |
1296 if (soap_recv_raw(soap)) | |
1297 return EOF; | |
1298 if (soap->buflen - soap->bufidx >= soap->dime.chunksize) | |
1299 { soap->dime.buflen = soap->buflen; | |
1300 soap->count -= soap->buflen - soap->bufidx - soap->dime.chunksize; | |
1301 soap->buflen = soap->bufidx + soap->dime.chunksize; | |
1302 } | |
1303 else | |
1304 soap->dime.chunksize -= soap->buflen - soap->bufidx; | |
1305 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%lu bytes remaining, count=%lu\n", (unsigned long)(soap->buflen-soap->bufidx), (unsigned long)soap->count)); | |
1306 return SOAP_OK; | |
1307 } | |
1308 } | |
1309 while (soap->ffilterrecv) | |
1310 { int err, last = soap->filterstop; | |
1311 if (last) | |
1312 soap->bufidx = soap->buflen = 0; | |
1313 if ((err = soap->ffilterrecv(soap, soap->buf, &soap->buflen, sizeof(soap->buf)))) | |
1314 return soap->error = err; | |
1315 if (soap->buflen) | |
1316 { soap->bufidx = 0; | |
1317 soap->filterstop = last; | |
1318 return SOAP_OK; | |
1319 } | |
1320 if (last) | |
1321 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Returning postponed error %d\n", last)); | |
1322 soap->filterstop = SOAP_OK; | |
1323 return last; | |
1324 } | |
1325 soap->filterstop = soap_recv_raw(soap); /* do not call again after EOF */ | |
1326 } | |
1327 #endif | |
1328 return soap_recv_raw(soap); | |
1329 } | |
1330 #endif | |
1331 | |
1332 /******************************************************************************/ | |
1333 #ifndef PALM_1 | |
1334 SOAP_FMAC1 | |
1335 soap_wchar | |
1336 SOAP_FMAC2 | |
1337 soap_getchar(struct soap *soap) | |
1338 { register soap_wchar c; | |
1339 c = soap->ahead; | |
1340 if (c) | |
1341 { if (c != EOF) | |
1342 soap->ahead = 0; | |
1343 return c; | |
1344 } | |
1345 return soap_get1(soap); | |
1346 } | |
1347 #endif | |
1348 | |
1349 /******************************************************************************/ | |
1350 #ifndef PALM_1 | |
1351 SOAP_FMAC1 | |
1352 const struct soap_code_map* | |
1353 SOAP_FMAC2 | |
1354 soap_code(const struct soap_code_map *code_map, const char *str) | |
1355 { if (code_map && str) | |
1356 { while (code_map->string) | |
1357 { if (!strcmp(str, code_map->string)) /* case sensitive */ | |
1358 return code_map; | |
1359 code_map++; | |
1360 } | |
1361 } | |
1362 return NULL; | |
1363 } | |
1364 #endif | |
1365 | |
1366 /******************************************************************************/ | |
1367 #ifndef PALM_1 | |
1368 SOAP_FMAC1 | |
1369 long | |
1370 SOAP_FMAC2 | |
1371 soap_code_int(const struct soap_code_map *code_map, const char *str, long other) | |
1372 { if (code_map) | |
1373 { while (code_map->string) | |
1374 { if (!soap_tag_cmp(str, code_map->string)) /* case insensitive */ | |
1375 return code_map->code; | |
1376 code_map++; | |
1377 } | |
1378 } | |
1379 return other; | |
1380 } | |
1381 #endif | |
1382 | |
1383 /******************************************************************************/ | |
1384 #ifndef PALM_1 | |
1385 SOAP_FMAC1 | |
1386 const char* | |
1387 SOAP_FMAC2 | |
1388 soap_code_str(const struct soap_code_map *code_map, long code) | |
1389 { if (!code_map) | |
1390 return NULL; | |
1391 while (code_map->code != code && code_map->string) | |
1392 code_map++; | |
1393 return code_map->string; | |
1394 } | |
1395 #endif | |
1396 | |
1397 /******************************************************************************/ | |
1398 #ifndef PALM_1 | |
1399 SOAP_FMAC1 | |
1400 long | |
1401 SOAP_FMAC2 | |
1402 soap_code_bits(const struct soap_code_map *code_map, const char *str) | |
1403 { register long bits = 0; | |
1404 if (code_map) | |
1405 { while (str && *str) | |
1406 { const struct soap_code_map *p; | |
1407 for (p = code_map; p->string; p++) | |
1408 { register size_t n = strlen(p->string); | |
1409 if (!strncmp(p->string, str, n) && soap_blank((soap_wchar)str[n])) | |
1410 { bits |= p->code; | |
1411 str += n; | |
1412 while (*str > 0 && *str <= 32) | |
1413 str++; | |
1414 break; | |
1415 } | |
1416 } | |
1417 if (!p->string) | |
1418 return 0; | |
1419 } | |
1420 } | |
1421 return bits; | |
1422 } | |
1423 #endif | |
1424 | |
1425 /******************************************************************************/ | |
1426 #ifndef PALM_1 | |
1427 SOAP_FMAC1 | |
1428 const char* | |
1429 SOAP_FMAC2 | |
1430 soap_code_list(struct soap *soap, const struct soap_code_map *code_map, long code) | |
1431 { register char *t = soap->tmpbuf; | |
1432 if (code_map) | |
1433 { while (code_map->string) | |
1434 { if (code_map->code & code) | |
1435 { register const char *s = code_map->string; | |
1436 if (t != soap->tmpbuf) | |
1437 *t++ = ' '; | |
1438 while (*s && t < soap->tmpbuf + sizeof(soap->tmpbuf) - 1) | |
1439 *t++ = *s++; | |
1440 if (t == soap->tmpbuf + sizeof(soap->tmpbuf) - 1) | |
1441 break; | |
1442 } | |
1443 code_map++; | |
1444 } | |
1445 } | |
1446 *t = '\0'; | |
1447 return soap->tmpbuf; | |
1448 } | |
1449 #endif | |
1450 | |
1451 /******************************************************************************/ | |
1452 #ifndef PALM_1 | |
1453 static soap_wchar | |
1454 soap_char(struct soap *soap) | |
1455 { char tmp[8]; | |
1456 register int i; | |
1457 register soap_wchar c; | |
1458 register char *s = tmp; | |
1459 for (i = 0; i < 7; i++) | |
1460 { c = soap_get1(soap); | |
1461 if (c == ';' || (int)c == EOF) | |
1462 break; | |
1463 *s++ = (char)c; | |
1464 } | |
1465 *s = '\0'; | |
1466 if (*tmp == '#') | |
1467 { if (tmp[1] == 'x' || tmp[1] == 'X') | |
1468 return (soap_wchar)soap_strtol(tmp + 2, NULL, 16); | |
1469 return (soap_wchar)soap_strtol(tmp + 1, NULL, 10); | |
1470 } | |
1471 if (!strcmp(tmp, "lt")) | |
1472 return '<'; | |
1473 if (!strcmp(tmp, "gt")) | |
1474 return '>'; | |
1475 if (!strcmp(tmp, "amp")) | |
1476 return '&'; | |
1477 if (!strcmp(tmp, "quot")) | |
1478 return '"'; | |
1479 if (!strcmp(tmp, "apos")) | |
1480 return '\''; | |
1481 #ifndef WITH_LEAN | |
1482 return (soap_wchar)soap_code_int(html_entity_codes, tmp, SOAP_UNKNOWN_CHAR); | |
1483 #else | |
1484 return SOAP_UNKNOWN_CHAR; /* use this to represent unknown code */ | |
1485 #endif | |
1486 } | |
1487 #endif | |
1488 | |
1489 /******************************************************************************/ | |
1490 #ifdef WITH_LEAN | |
1491 #ifndef PALM_1 | |
1492 soap_wchar | |
1493 soap_get0(struct soap *soap) | |
1494 { if (soap->bufidx >= soap->buflen && soap_recv(soap)) | |
1495 return EOF; | |
1496 return (unsigned char)soap->buf[soap->bufidx]; | |
1497 } | |
1498 #endif | |
1499 #endif | |
1500 | |
1501 /******************************************************************************/ | |
1502 #ifdef WITH_LEAN | |
1503 #ifndef PALM_1 | |
1504 soap_wchar | |
1505 soap_get1(struct soap *soap) | |
1506 { if (soap->bufidx >= soap->buflen && soap_recv(soap)) | |
1507 return EOF; | |
1508 return (unsigned char)soap->buf[soap->bufidx++]; | |
1509 } | |
1510 #endif | |
1511 #endif | |
1512 | |
1513 /******************************************************************************/ | |
1514 #ifndef PALM_1 | |
1515 SOAP_FMAC1 | |
1516 soap_wchar | |
1517 SOAP_FMAC2 | |
1518 soap_get(struct soap *soap) | |
1519 { register soap_wchar c; | |
1520 c = soap->ahead; | |
1521 if (c) | |
1522 { if ((int)c != EOF) | |
1523 soap->ahead = 0; | |
1524 } | |
1525 else | |
1526 c = soap_get1(soap); | |
1527 while ((int)c != EOF) | |
1528 { if (soap->cdata) | |
1529 { if (c == ']') | |
1530 { c = soap_get1(soap); | |
1531 if (c == ']') | |
1532 { c = soap_get0(soap); | |
1533 if (c == '>') | |
1534 { soap->cdata = 0; | |
1535 c = soap_get1(soap); | |
1536 c = soap_get1(soap); | |
1537 } | |
1538 else | |
1539 { soap_unget(soap, ']'); | |
1540 return ']'; | |
1541 } | |
1542 } | |
1543 else | |
1544 { soap_revget1(soap); | |
1545 return ']'; | |
1546 } | |
1547 } | |
1548 else | |
1549 return c; | |
1550 } | |
1551 switch (c) | |
1552 { case '<': | |
1553 do c = soap_get1(soap); | |
1554 while (soap_blank(c)); | |
1555 if (c == '!' || c == '?' || c == '%') | |
1556 { register int k = 1; | |
1557 if (c == '!') | |
1558 { c = soap_get1(soap); | |
1559 if (c == '[') | |
1560 { do c = soap_get1(soap); | |
1561 while ((int)c != EOF && c != '['); | |
1562 if ((int)c == EOF) | |
1563 break; | |
1564 soap->cdata = 1; | |
1565 c = soap_get1(soap); | |
1566 continue; | |
1567 } | |
1568 if (c == '-' && (c = soap_get1(soap)) == '-') | |
1569 { do | |
1570 { c = soap_get1(soap); | |
1571 if (c == '-' && (c = soap_get1(soap)) == '-') | |
1572 break; | |
1573 } while ((int)c != EOF); | |
1574 } | |
1575 } | |
1576 else if (c == '?') | |
1577 c = soap_get_pi(soap); | |
1578 while ((int)c != EOF) | |
1579 { if (c == '<') | |
1580 k++; | |
1581 else if (c == '>') | |
1582 { if (--k <= 0) | |
1583 break; | |
1584 } | |
1585 c = soap_get1(soap); | |
1586 } | |
1587 if ((int)c == EOF) | |
1588 break; | |
1589 c = soap_get1(soap); | |
1590 continue; | |
1591 } | |
1592 if (c == '/') | |
1593 return SOAP_TT; | |
1594 soap_revget1(soap); | |
1595 return SOAP_LT; | |
1596 case '>': | |
1597 return SOAP_GT; | |
1598 case '"': | |
1599 return SOAP_QT; | |
1600 case '\'': | |
1601 return SOAP_AP; | |
1602 case '&': | |
1603 return soap_char(soap) | 0x80000000; | |
1604 } | |
1605 break; | |
1606 } | |
1607 return c; | |
1608 } | |
1609 #endif | |
1610 | |
1611 /******************************************************************************/ | |
1612 #ifndef PALM_1 | |
1613 static soap_wchar | |
1614 soap_get_pi(struct soap *soap) | |
1615 { char buf[64]; | |
1616 register char *s = buf; | |
1617 register int i = sizeof(buf); | |
1618 register soap_wchar c = soap_getchar(soap); | |
1619 /* This is a quick way to parse XML PI and we could use a callback instead to | |
1620 * enable applications to intercept processing instructions */ | |
1621 while ((int)c != EOF && c != '?') | |
1622 { if (--i > 0) | |
1623 { if (soap_blank(c)) | |
1624 c = ' '; | |
1625 *s++ = (char)c; | |
1626 } | |
1627 c = soap_getchar(soap); | |
1628 } | |
1629 *s = '\0'; | |
1630 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "XML PI <?%s?>\n", buf)); | |
1631 if (!strncmp(buf, "xml ", 4)) | |
1632 { s = strstr(buf, " encoding="); | |
1633 if (s && s[10]) | |
1634 { if (!soap_tag_cmp(s + 11, "iso-8859-1*") | |
1635 || !soap_tag_cmp(s + 11, "latin1*")) | |
1636 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to latin1 encoding\n")); | |
1637 soap->mode |= SOAP_ENC_LATIN; | |
1638 } | |
1639 else if (!soap_tag_cmp(s + 11, "utf-8*")) | |
1640 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to utf-8 encoding\n")); | |
1641 soap->mode &= ~SOAP_ENC_LATIN; | |
1642 } | |
1643 } | |
1644 } | |
1645 if ((int)c != EOF) | |
1646 c = soap_getchar(soap); | |
1647 return c; | |
1648 } | |
1649 #endif | |
1650 | |
1651 /******************************************************************************/ | |
1652 #ifndef WITH_LEANER | |
1653 #ifndef PALM_1 | |
1654 SOAP_FMAC1 | |
1655 int | |
1656 SOAP_FMAC2 | |
1657 soap_move(struct soap *soap, size_t n) | |
1658 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving %lu bytes forward\n", (unsigned long)n)); | |
1659 for (; n; n--) | |
1660 if ((int)soap_getchar(soap) == EOF) | |
1661 return SOAP_EOF; | |
1662 return SOAP_OK; | |
1663 } | |
1664 #endif | |
1665 #endif | |
1666 | |
1667 /******************************************************************************/ | |
1668 #ifndef WITH_LEANER | |
1669 #ifndef PALM_1 | |
1670 SOAP_FMAC1 | |
1671 size_t | |
1672 SOAP_FMAC2 | |
1673 soap_tell(struct soap *soap) | |
1674 { return soap->count - soap->buflen + soap->bufidx - (soap->ahead != 0); | |
1675 } | |
1676 #endif | |
1677 #endif | |
1678 | |
1679 /******************************************************************************/ | |
1680 #ifndef PALM_1 | |
1681 SOAP_FMAC1 | |
1682 int | |
1683 SOAP_FMAC2 | |
1684 soap_pututf8(struct soap *soap, register unsigned long c) | |
1685 { char tmp[16]; | |
1686 if (c < 0x80 && c > 0) | |
1687 { *tmp = (char)c; | |
1688 return soap_send_raw(soap, tmp, 1); | |
1689 } | |
1690 #ifndef WITH_LEAN | |
1691 if (c >= 0x80) | |
1692 { register char *t = tmp; | |
1693 if (c < 0x0800) | |
1694 *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); | |
1695 else | |
1696 { if (c < 0x010000) | |
1697 *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); | |
1698 else | |
1699 { if (c < 0x200000) | |
1700 *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); | |
1701 else | |
1702 { if (c < 0x04000000) | |
1703 *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); | |
1704 else | |
1705 { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); | |
1706 *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); | |
1707 } | |
1708 *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); | |
1709 } | |
1710 *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); | |
1711 } | |
1712 *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); | |
1713 } | |
1714 *t++ = (char)(0x80 | (c & 0x3F)); | |
1715 *t = '\0'; | |
1716 } | |
1717 else | |
1718 #endif | |
1719 #ifdef HAVE_SNPRINTF | |
1720 soap_snprintf(tmp, sizeof(tmp), "&#%lu;", c); | |
1721 #else | |
1722 sprintf(tmp, "&#%lu;", c); | |
1723 #endif | |
1724 return soap_send(soap, tmp); | |
1725 } | |
1726 #endif | |
1727 | |
1728 /******************************************************************************/ | |
1729 #ifndef PALM_1 | |
1730 SOAP_FMAC1 | |
1731 soap_wchar | |
1732 SOAP_FMAC2 | |
1733 soap_getutf8(struct soap *soap) | |
1734 { register soap_wchar c, c1, c2, c3, c4; | |
1735 c = soap->ahead; | |
1736 if (c >= 0x80) | |
1737 soap->ahead = 0; | |
1738 else | |
1739 c = soap_get(soap); | |
1740 if (c < 0x80 || c > 0xFF || (soap->mode & SOAP_ENC_LATIN)) | |
1741 return c; | |
1742 c1 = soap_get1(soap); | |
1743 if (c1 < 0x80) | |
1744 { soap_revget1(soap); /* doesn't look like this is UTF8 */ | |
1745 return c; | |
1746 } | |
1747 c1 &= 0x3F; | |
1748 if (c < 0xE0) | |
1749 return ((soap_wchar)(c & 0x1F) << 6) | c1; | |
1750 c2 = (soap_wchar)soap_get1(soap) & 0x3F; | |
1751 if (c < 0xF0) | |
1752 return ((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2; | |
1753 c3 = (soap_wchar)soap_get1(soap) & 0x3F; | |
1754 if (c < 0xF8) | |
1755 return ((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3; | |
1756 c4 = (soap_wchar)soap_get1(soap) & 0x3F; | |
1757 if (c < 0xFC) | |
1758 return ((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4; | |
1759 return ((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(soap_get1(soap) & 0x3F); | |
1760 } | |
1761 #endif | |
1762 | |
1763 /******************************************************************************/ | |
1764 #ifndef PALM_1 | |
1765 SOAP_FMAC1 | |
1766 int | |
1767 SOAP_FMAC2 | |
1768 soap_puthex(struct soap *soap, const unsigned char *s, int n) | |
1769 { char d[2]; | |
1770 register int i; | |
1771 #ifdef WITH_DOM | |
1772 if ((soap->mode & SOAP_XML_DOM) && soap->dom) | |
1773 { if (!(soap->dom->data = soap_s2hex(soap, s, NULL, n))) | |
1774 return soap->error; | |
1775 return SOAP_OK; | |
1776 } | |
1777 #endif | |
1778 for (i = 0; i < n; i++) | |
1779 { register int m = *s++; | |
1780 d[0] = (char)((m >> 4) + (m > 159 ? '7' : '0')); | |
1781 m &= 0x0F; | |
1782 d[1] = (char)(m + (m > 9 ? '7' : '0')); | |
1783 if (soap_send_raw(soap, d, 2)) | |
1784 return soap->error; | |
1785 } | |
1786 return SOAP_OK; | |
1787 } | |
1788 #endif | |
1789 | |
1790 /******************************************************************************/ | |
1791 #ifndef PALM_1 | |
1792 SOAP_FMAC1 | |
1793 unsigned char* | |
1794 SOAP_FMAC2 | |
1795 soap_gethex(struct soap *soap, int *n) | |
1796 { | |
1797 #ifdef WITH_DOM | |
1798 if ((soap->mode & SOAP_XML_DOM) && soap->dom) | |
1799 { soap->dom->data = soap_string_in(soap, 0, -1, -1); | |
1800 return (unsigned char*)soap_hex2s(soap, soap->dom->data, NULL, 0, n); | |
1801 } | |
1802 #endif | |
1803 #ifdef WITH_FAST | |
1804 soap->labidx = 0; | |
1805 for (;;) | |
1806 { register char *s; | |
1807 register size_t i, k; | |
1808 if (soap_append_lab(soap, NULL, 0)) | |
1809 return NULL; | |
1810 s = soap->labbuf + soap->labidx; | |
1811 k = soap->lablen - soap->labidx; | |
1812 soap->labidx = soap->lablen; | |
1813 for (i = 0; i < k; i++) | |
1814 { register char d1, d2; | |
1815 register soap_wchar c; | |
1816 c = soap_get(soap); | |
1817 if (soap_isxdigit(c)) | |
1818 { d1 = (char)c; | |
1819 c = soap_get(soap); | |
1820 if (soap_isxdigit(c)) | |
1821 d2 = (char)c; | |
1822 else | |
1823 { soap->error = SOAP_TYPE; | |
1824 return NULL; | |
1825 } | |
1826 } | |
1827 else | |
1828 { unsigned char *p; | |
1829 soap_unget(soap, c); | |
1830 if (n) | |
1831 *n = (int)(soap->lablen + i - k); | |
1832 p = (unsigned char*)soap_malloc(soap, soap->lablen + i - k); | |
1833 if (p) | |
1834 memcpy(p, soap->labbuf, soap->lablen + i - k); | |
1835 return p; | |
1836 } | |
1837 *s++ = (char)(((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0')); | |
1838 } | |
1839 } | |
1840 #else | |
1841 if (soap_new_block(soap) == NULL) | |
1842 return NULL; | |
1843 for (;;) | |
1844 { register int i; | |
1845 register char *s = (char*)soap_push_block(soap, NULL, SOAP_BLKLEN); | |
1846 if (!s) | |
1847 { soap_end_block(soap, NULL); | |
1848 return NULL; | |
1849 } | |
1850 for (i = 0; i < SOAP_BLKLEN; i++) | |
1851 { register char d1, d2; | |
1852 register soap_wchar c = soap_get(soap); | |
1853 if (soap_isxdigit(c)) | |
1854 { d1 = (char)c; | |
1855 c = soap_get(soap); | |
1856 if (soap_isxdigit(c)) | |
1857 d2 = (char)c; | |
1858 else | |
1859 { soap_end_block(soap, NULL); | |
1860 soap->error = SOAP_TYPE; | |
1861 return NULL; | |
1862 } | |
1863 } | |
1864 else | |
1865 { unsigned char *p; | |
1866 soap_unget(soap, c); | |
1867 if (n) | |
1868 *n = (int)soap_size_block(soap, NULL, i); | |
1869 p = (unsigned char*)soap_save_block(soap, NULL, 0); | |
1870 return p; | |
1871 } | |
1872 *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'); | |
1873 } | |
1874 } | |
1875 #endif | |
1876 } | |
1877 #endif | |
1878 | |
1879 /******************************************************************************/ | |
1880 #ifndef PALM_1 | |
1881 SOAP_FMAC1 | |
1882 int | |
1883 SOAP_FMAC2 | |
1884 soap_putbase64(struct soap *soap, const unsigned char *s, int n) | |
1885 { register int i; | |
1886 register unsigned long m; | |
1887 char d[4]; | |
1888 if (!s) | |
1889 return SOAP_OK; | |
1890 #ifdef WITH_DOM | |
1891 if ((soap->mode & SOAP_XML_DOM) && soap->dom) | |
1892 { if (!(soap->dom->data = soap_s2base64(soap, s, NULL, n))) | |
1893 return soap->error; | |
1894 return SOAP_OK; | |
1895 } | |
1896 #endif | |
1897 for (; n > 2; n -= 3, s += 3) | |
1898 { m = s[0]; | |
1899 m = (m << 8) | s[1]; | |
1900 m = (m << 8) | s[2]; | |
1901 for (i = 4; i > 0; m >>= 6) | |
1902 d[--i] = soap_base64o[m & 0x3F]; | |
1903 if (soap_send_raw(soap, d, 4)) | |
1904 return soap->error; | |
1905 } | |
1906 if (n > 0) | |
1907 { m = 0; | |
1908 for (i = 0; i < n; i++) | |
1909 m = (m << 8) | *s++; | |
1910 for (; i < 3; i++) | |
1911 m <<= 8; | |
1912 for (i++; i > 0; m >>= 6) | |
1913 d[--i] = soap_base64o[m & 0x3F]; | |
1914 for (i = 3; i > n; i--) | |
1915 d[i] = '='; | |
1916 if (soap_send_raw(soap, d, 4)) | |
1917 return soap->error; | |
1918 } | |
1919 return SOAP_OK; | |
1920 } | |
1921 #endif | |
1922 | |
1923 /******************************************************************************/ | |
1924 #ifndef PALM_1 | |
1925 SOAP_FMAC1 | |
1926 unsigned char* | |
1927 SOAP_FMAC2 | |
1928 soap_getbase64(struct soap *soap, int *n, int malloc_flag) | |
1929 { (void)malloc_flag; | |
1930 #ifdef WITH_DOM | |
1931 if ((soap->mode & SOAP_XML_DOM) && soap->dom) | |
1932 { soap->dom->data = soap_string_in(soap, 0, -1, -1); | |
1933 return (unsigned char*)soap_base642s(soap, soap->dom->data, NULL, 0, n); | |
1934 } | |
1935 #endif | |
1936 #ifdef WITH_FAST | |
1937 soap->labidx = 0; | |
1938 for (;;) | |
1939 { register size_t i, k; | |
1940 register char *s; | |
1941 if (soap_append_lab(soap, NULL, 2)) | |
1942 return NULL; | |
1943 s = soap->labbuf + soap->labidx; | |
1944 k = soap->lablen - soap->labidx; | |
1945 soap->labidx = 3 * (soap->lablen / 3); | |
1946 if (!s) | |
1947 return NULL; | |
1948 if (k > 2) | |
1949 { for (i = 0; i < k - 2; i += 3) | |
1950 { register unsigned long m = 0; | |
1951 register int j = 0; | |
1952 do | |
1953 { register soap_wchar c = soap_get(soap); | |
1954 if (c < SOAP_AP) | |
1955 c &= 0x7FFFFFFF; | |
1956 if (c == '=' || c < 0) | |
1957 { unsigned char *p; | |
1958 switch (j) | |
1959 { case 2: | |
1960 *s++ = (char)((m >> 4) & 0xFF); | |
1961 i++; | |
1962 break; | |
1963 case 3: | |
1964 *s++ = (char)((m >> 10) & 0xFF); | |
1965 *s++ = (char)((m >> 2) & 0xFF); | |
1966 i += 2; | |
1967 } | |
1968 if (n) | |
1969 *n = (int)(soap->lablen + i - k); | |
1970 p = (unsigned char*)soap_malloc(soap, soap->lablen + i - k); | |
1971 if (p) | |
1972 memcpy(p, soap->labbuf, soap->lablen + i - k); | |
1973 if (c >= 0) | |
1974 { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT) | |
1975 ; | |
1976 } | |
1977 soap_unget(soap, c); | |
1978 return p; | |
1979 } | |
1980 c -= '+'; | |
1981 if (c >= 0 && c <= 79) | |
1982 { register int b = soap_base64i[c]; | |
1983 if (b >= 64) | |
1984 { soap->error = SOAP_TYPE; | |
1985 return NULL; | |
1986 } | |
1987 m = (m << 6) + b; | |
1988 j++; | |
1989 } | |
1990 else if (!soap_blank(c + '+')) | |
1991 { soap->error = SOAP_TYPE; | |
1992 return NULL; | |
1993 } | |
1994 } while (j < 4); | |
1995 *s++ = (char)((m >> 16) & 0xFF); | |
1996 *s++ = (char)((m >> 8) & 0xFF); | |
1997 *s++ = (char)(m & 0xFF); | |
1998 } | |
1999 } | |
2000 } | |
2001 #else | |
2002 if (soap_new_block(soap) == NULL) | |
2003 return NULL; | |
2004 for (;;) | |
2005 { register int i; | |
2006 register char *s = (char*)soap_push_block(soap, NULL, 3 * SOAP_BLKLEN); /* must be multiple of 3 */ | |
2007 if (!s) | |
2008 { soap_end_block(soap, NULL); | |
2009 return NULL; | |
2010 } | |
2011 for (i = 0; i < SOAP_BLKLEN; i++) | |
2012 { register unsigned long m = 0; | |
2013 register int j = 0; | |
2014 do | |
2015 { register soap_wchar c = soap_get(soap); | |
2016 if (c == '=' || c < 0) | |
2017 { unsigned char *p; | |
2018 i *= 3; | |
2019 switch (j) | |
2020 { case 2: | |
2021 *s++ = (char)((m >> 4) & 0xFF); | |
2022 i++; | |
2023 break; | |
2024 case 3: | |
2025 *s++ = (char)((m >> 10) & 0xFF); | |
2026 *s++ = (char)((m >> 2) & 0xFF); | |
2027 i += 2; | |
2028 } | |
2029 if (n) | |
2030 *n = (int)soap_size_block(soap, NULL, i); | |
2031 p = (unsigned char*)soap_save_block(soap, NULL, 0); | |
2032 if (c >= 0) | |
2033 { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT) | |
2034 ; | |
2035 } | |
2036 soap_unget(soap, c); | |
2037 return p; | |
2038 } | |
2039 c -= '+'; | |
2040 if (c >= 0 && c <= 79) | |
2041 { int b = soap_base64i[c]; | |
2042 if (b >= 64) | |
2043 { soap->error = SOAP_TYPE; | |
2044 return NULL; | |
2045 } | |
2046 m = (m << 6) + b; | |
2047 j++; | |
2048 } | |
2049 else if (!soap_blank(c)) | |
2050 { soap->error = SOAP_TYPE; | |
2051 return NULL; | |
2052 } | |
2053 } while (j < 4); | |
2054 *s++ = (char)((m >> 16) & 0xFF); | |
2055 *s++ = (char)((m >> 8) & 0xFF); | |
2056 *s++ = (char)(m & 0xFF); | |
2057 } | |
2058 } | |
2059 #endif | |
2060 } | |
2061 #endif | |
2062 | |
2063 /******************************************************************************/ | |
2064 #ifndef WITH_LEANER | |
2065 #ifndef PALM_1 | |
2066 SOAP_FMAC1 | |
2067 int | |
2068 SOAP_FMAC2 | |
2069 soap_xop_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options) | |
2070 { /* Check MTOM xop:Include element (within hex/base64Binary) */ | |
2071 /* TODO: this code to be obsoleted with new import/xop.h conventions */ | |
2072 short body = soap->body; /* should save type too? */ | |
2073 if (!soap_peek_element(soap)) | |
2074 { if (!soap_element_begin_in(soap, "xop:Include", 0, NULL)) | |
2075 { if (soap_dime_forward(soap, ptr, size, id, type, options) | |
2076 || (soap->body && soap_element_end_in(soap, "xop:Include"))) | |
2077 return soap->error; | |
2078 } | |
2079 } | |
2080 soap->body = body; | |
2081 return SOAP_OK; | |
2082 } | |
2083 #endif | |
2084 #endif | |
2085 | |
2086 /******************************************************************************/ | |
2087 #ifndef WITH_LEANER | |
2088 #ifndef PALM_1 | |
2089 SOAP_FMAC1 | |
2090 int | |
2091 SOAP_FMAC2 | |
2092 soap_dime_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options) | |
2093 { struct soap_xlist *xp; | |
2094 *ptr = NULL; | |
2095 *size = 0; | |
2096 *id = NULL; | |
2097 *type = NULL; | |
2098 *options = NULL; | |
2099 if (!*soap->href) | |
2100 return SOAP_OK; | |
2101 *id = soap_strdup(soap, soap->href); | |
2102 xp = (struct soap_xlist*)SOAP_MALLOC(soap, sizeof(struct soap_xlist)); | |
2103 if (!xp) | |
2104 return soap->error = SOAP_EOM; | |
2105 xp->next = soap->xlist; | |
2106 xp->ptr = ptr; | |
2107 xp->size = size; | |
2108 xp->id = *id; | |
2109 xp->type = type; | |
2110 xp->options = options; | |
2111 soap->xlist = xp; | |
2112 return SOAP_OK; | |
2113 } | |
2114 #endif | |
2115 #endif | |
2116 | |
2117 /******************************************************************************/ | |
2118 #ifndef PALM_1 | |
2119 SOAP_FMAC1 | |
2120 char * | |
2121 SOAP_FMAC2 | |
2122 soap_strdup(struct soap *soap, const char *s) | |
2123 { char *t = NULL; | |
2124 if (s && (t = (char*)soap_malloc(soap, strlen(s) + 1))) | |
2125 strcpy(t, s); | |
2126 return t; | |
2127 } | |
2128 #endif | |
2129 | |
2130 /******************************************************************************/ | |
2131 #ifndef PALM_1 | |
2132 SOAP_FMAC1 | |
2133 wchar_t * | |
2134 SOAP_FMAC2 | |
2135 soap_wstrdup(struct soap *soap, const wchar_t *s) | |
2136 { wchar_t *t = NULL; | |
2137 if (s) | |
2138 { size_t n = 0; | |
2139 while (s[n]) | |
2140 n++; | |
2141 if ((t = (wchar_t*)soap_malloc(soap, sizeof(wchar_t)*(n+1)))) | |
2142 memcpy(t, s, sizeof(wchar_t)*(n+1)); | |
2143 } | |
2144 return t; | |
2145 } | |
2146 #endif | |
2147 | |
2148 /******************************************************************************/ | |
2149 #ifndef PALM_1 | |
2150 SOAP_FMAC1 | |
2151 struct soap_blist* | |
2152 SOAP_FMAC2 | |
2153 soap_new_block(struct soap *soap) | |
2154 { struct soap_blist *p; | |
2155 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New block sequence (prev=%p)\n", soap->blist)); | |
2156 if (!(p = (struct soap_blist*)SOAP_MALLOC(soap, sizeof(struct soap_blist)))) | |
2157 { soap->error = SOAP_EOM; | |
2158 return NULL; | |
2159 } | |
2160 p->next = soap->blist; | |
2161 p->ptr = NULL; | |
2162 p->size = 0; | |
2163 soap->blist = p; | |
2164 return p; | |
2165 } | |
2166 #endif | |
2167 | |
2168 /******************************************************************************/ | |
2169 #ifndef PALM_1 | |
2170 SOAP_FMAC1 | |
2171 void* | |
2172 SOAP_FMAC2 | |
2173 soap_push_block(struct soap *soap, struct soap_blist *b, size_t n) | |
2174 { char *p; | |
2175 if (!b) | |
2176 b = soap->blist; | |
2177 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push block of %u bytes (%u bytes total)\n", (unsigned int)n, (unsigned int)b->size + (unsigned int)n)); | |
2178 if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(char*) + sizeof(size_t)))) | |
2179 { soap->error = SOAP_EOM; | |
2180 return NULL; | |
2181 } | |
2182 *(char**)p = b->ptr; | |
2183 *(size_t*)(p + sizeof(char*)) = n; | |
2184 b->ptr = p; | |
2185 b->size += n; | |
2186 return p + sizeof(char*) + sizeof(size_t); | |
2187 } | |
2188 #endif | |
2189 | |
2190 /******************************************************************************/ | |
2191 #ifndef PALM_1 | |
2192 SOAP_FMAC1 | |
2193 void | |
2194 SOAP_FMAC2 | |
2195 soap_pop_block(struct soap *soap, struct soap_blist *b) | |
2196 { char *p; | |
2197 if (!b) | |
2198 b = soap->blist; | |
2199 if (!b->ptr) | |
2200 return; | |
2201 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop block\n")); | |
2202 p = b->ptr; | |
2203 b->size -= *(size_t*)(p + sizeof(char*)); | |
2204 b->ptr = *(char**)p; | |
2205 SOAP_FREE(soap, p); | |
2206 } | |
2207 #endif | |
2208 | |
2209 /******************************************************************************/ | |
2210 #ifndef PALM_1 | |
2211 SOAP_FMAC1 | |
2212 void | |
2213 SOAP_FMAC2 | |
2214 soap_update_pointers(struct soap *soap, char *start, char *end, char *p1, char *p2) | |
2215 { | |
2216 #ifndef WITH_NOIDREF | |
2217 int i; | |
2218 register struct soap_ilist *ip = NULL; | |
2219 register struct soap_flist *fp = NULL; | |
2220 #ifndef WITH_LEANER | |
2221 register struct soap_xlist *xp = NULL; | |
2222 #endif | |
2223 register void *p, **q; | |
2224 for (i = 0; i < SOAP_IDHASH; i++) | |
2225 { for (ip = soap->iht[i]; ip; ip = ip->next) | |
2226 { if (ip->ptr && (char*)ip->ptr >= start && (char*)ip->ptr < end) | |
2227 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", ip->id, ip->ptr, (char*)ip->ptr + (p1-p2))); | |
2228 ip->ptr = (char*)ip->ptr + (p1-p2); | |
2229 } | |
2230 for (q = &ip->link; q; q = (void**)p) | |
2231 { p = *q; | |
2232 if (p && (char*)p >= start && (char*)p < end) | |
2233 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Link update id='%s' %p\n", ip->id, p)); | |
2234 *q = (char*)p + (p1-p2); | |
2235 } | |
2236 } | |
2237 for (q = &ip->copy; q; q = (void**)p) | |
2238 { p = *q; | |
2239 if (p && (char*)p >= start && (char*)p < end) | |
2240 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy chain update id='%s' %p\n", ip->id, p)); | |
2241 *q = (char*)p + (p1-p2); | |
2242 } | |
2243 } | |
2244 for (fp = ip->flist; fp; fp = fp->next) | |
2245 { if ((char*)fp->ptr >= start && (char*)fp->ptr < end) | |
2246 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy list update id='%s' %p\n", ip->id, fp)); | |
2247 fp->ptr = (char*)fp->ptr + (p1-p2); | |
2248 } | |
2249 } | |
2250 } | |
2251 } | |
2252 #ifndef WITH_LEANER | |
2253 for (xp = soap->xlist; xp; xp = xp->next) | |
2254 { if (xp->ptr && (char*)xp->ptr >= start && (char*)xp->ptr < end) | |
2255 { 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))); | |
2256 xp->ptr = (unsigned char**)((char*)xp->ptr + (p1-p2)); | |
2257 xp->size = (int*)((char*)xp->size + (p1-p2)); | |
2258 xp->type = (char**)((char*)xp->type + (p1-p2)); | |
2259 xp->options = (char**)((char*)xp->options + (p1-p2)); | |
2260 } | |
2261 } | |
2262 #endif | |
2263 #else | |
2264 (void)soap; (void)start; (void)end; (void)p1; (void)p2; | |
2265 #endif | |
2266 } | |
2267 #endif | |
2268 | |
2269 /******************************************************************************/ | |
2270 #ifndef WITH_NOIDREF | |
2271 #ifndef PALM_1 | |
2272 static int | |
2273 soap_has_copies(struct soap *soap, register const char *start, register const char *end) | |
2274 { register int i; | |
2275 register struct soap_ilist *ip = NULL; | |
2276 register struct soap_flist *fp = NULL; | |
2277 register const char *p; | |
2278 for (i = 0; i < SOAP_IDHASH; i++) | |
2279 { for (ip = soap->iht[i]; ip; ip = ip->next) | |
2280 { for (p = (const char*)ip->copy; p; p = *(const char**)p) | |
2281 if (p >= start && p < end) | |
2282 return SOAP_ERR; | |
2283 for (fp = ip->flist; fp; fp = fp->next) | |
2284 if ((const char*)fp->ptr >= start && (const char*)fp->ptr < end) | |
2285 return SOAP_ERR; | |
2286 } | |
2287 } | |
2288 return SOAP_OK; | |
2289 } | |
2290 #endif | |
2291 #endif | |
2292 | |
2293 /******************************************************************************/ | |
2294 #ifndef WITH_NOIDREF | |
2295 #ifndef PALM_1 | |
2296 SOAP_FMAC1 | |
2297 int | |
2298 SOAP_FMAC2 | |
2299 soap_resolve(struct soap *soap) | |
2300 { register int i; | |
2301 register struct soap_ilist *ip = NULL; | |
2302 register struct soap_flist *fp = NULL; | |
2303 short flag; | |
2304 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data\n")); | |
2305 for (i = 0; i < SOAP_IDHASH; i++) | |
2306 { for (ip = soap->iht[i]; ip; ip = ip->next) | |
2307 { if (ip->ptr) | |
2308 { register void *p, **q, *r; | |
2309 q = (void**)ip->link; | |
2310 ip->link = NULL; | |
2311 r = ip->ptr; | |
2312 DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing link chain to resolve id='%s'\n", ip->id)); | |
2313 while (q) | |
2314 { p = *q; | |
2315 *q = r; | |
2316 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "... link %p -> %p\n", q, r)); | |
2317 q = (void**)p; | |
2318 } | |
2319 } | |
2320 else if (*ip->id == '#') | |
2321 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Missing data for id='%s'\n", ip->id)); | |
2322 strcpy(soap->id, ip->id + 1); | |
2323 return soap->error = SOAP_MISSING_ID; | |
2324 } | |
2325 } | |
2326 } | |
2327 do | |
2328 { flag = 0; | |
2329 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution phase\n")); | |
2330 for (i = 0; i < SOAP_IDHASH; i++) | |
2331 { for (ip = soap->iht[i]; ip; ip = ip->next) | |
2332 { if (ip->ptr && !soap_has_copies(soap, (const char*)ip->ptr, (const char*)ip->ptr + ip->size)) | |
2333 { if (ip->copy) | |
2334 { register void *p, **q = (void**)ip->copy; | |
2335 DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing copy chain to resolve id='%s'\n", ip->id)); | |
2336 ip->copy = NULL; | |
2337 do | |
2338 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... copy %p -> %p (%u bytes)\n", ip->ptr, q, (unsigned int)ip->size)); | |
2339 p = *q; | |
2340 memcpy(q, ip->ptr, ip->size); | |
2341 q = (void**)p; | |
2342 } while (q); | |
2343 flag = 1; | |
2344 } | |
2345 for (fp = ip->flist; fp; fp = ip->flist) | |
2346 { register unsigned int k = fp->level; | |
2347 register void *p = ip->ptr; | |
2348 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)); | |
2349 while (ip->level < k) | |
2350 { register void **q = (void**)soap_malloc(soap, sizeof(void*)); | |
2351 if (!q) | |
2352 return soap->error; | |
2353 *q = p; | |
2354 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level, new location=%p holds=%p...\n", q, *q)); | |
2355 p = (void*)q; | |
2356 k--; | |
2357 } | |
2358 if (fp->fcopy) | |
2359 fp->fcopy(soap, ip->type, fp->type, fp->ptr, fp->len, p, ip->size); | |
2360 else | |
2361 soap_fcopy(soap, ip->type, fp->type, fp->ptr, fp->len, p, ip->size); | |
2362 ip->flist = fp->next; | |
2363 SOAP_FREE(soap, fp); | |
2364 flag = 1; | |
2365 } | |
2366 } | |
2367 } | |
2368 } | |
2369 } while (flag); | |
2370 #ifdef SOAP_DEBUG | |
2371 for (i = 0; i < SOAP_IDHASH; i++) | |
2372 { for (ip = soap->iht[i]; ip; ip = ip->next) | |
2373 { if (ip->copy || ip->flist) | |
2374 { 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)); | |
2375 } | |
2376 } | |
2377 } | |
2378 #endif | |
2379 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution done\n")); | |
2380 return SOAP_OK; | |
2381 } | |
2382 #endif | |
2383 #endif | |
2384 | |
2385 /******************************************************************************/ | |
2386 #ifndef PALM_1 | |
2387 SOAP_FMAC1 | |
2388 size_t | |
2389 SOAP_FMAC2 | |
2390 soap_size_block(struct soap *soap, struct soap_blist *b, size_t n) | |
2391 { if (!b) | |
2392 b = soap->blist; | |
2393 if (b->ptr) | |
2394 { b->size -= *(size_t*)(b->ptr + sizeof(char*)) - n; | |
2395 *(size_t*)(b->ptr + sizeof(char*)) = n; | |
2396 } | |
2397 return b->size; | |
2398 } | |
2399 #endif | |
2400 | |
2401 /******************************************************************************/ | |
2402 #ifndef PALM_1 | |
2403 SOAP_FMAC1 | |
2404 char* | |
2405 SOAP_FMAC2 | |
2406 soap_first_block(struct soap *soap, struct soap_blist *b) | |
2407 { char *p, *q, *r; | |
2408 if (!b) | |
2409 b = soap->blist; | |
2410 p = b->ptr; | |
2411 if (!p) | |
2412 return NULL; | |
2413 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "First block\n")); | |
2414 r = NULL; | |
2415 do | |
2416 { q = *(char**)p; | |
2417 *(char**)p = r; | |
2418 r = p; | |
2419 p = q; | |
2420 } while (p); | |
2421 b->ptr = r; | |
2422 return r + sizeof(char*) + sizeof(size_t); | |
2423 } | |
2424 #endif | |
2425 | |
2426 /******************************************************************************/ | |
2427 #ifndef PALM_1 | |
2428 SOAP_FMAC1 | |
2429 char* | |
2430 SOAP_FMAC2 | |
2431 soap_next_block(struct soap *soap, struct soap_blist *b) | |
2432 { char *p; | |
2433 if (!b) | |
2434 b = soap->blist; | |
2435 p = b->ptr; | |
2436 if (p) | |
2437 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Next block\n")); | |
2438 b->ptr = *(char**)p; | |
2439 SOAP_FREE(soap, p); | |
2440 if (b->ptr) | |
2441 return b->ptr + sizeof(char*) + sizeof(size_t); | |
2442 } | |
2443 return NULL; | |
2444 } | |
2445 #endif | |
2446 | |
2447 /******************************************************************************/ | |
2448 #ifndef PALM_1 | |
2449 SOAP_FMAC1 | |
2450 size_t | |
2451 SOAP_FMAC2 | |
2452 soap_block_size(struct soap *soap, struct soap_blist *b) | |
2453 { if (!b) | |
2454 b = soap->blist; | |
2455 return *(size_t*)(b->ptr + sizeof(char*)); | |
2456 } | |
2457 #endif | |
2458 | |
2459 /******************************************************************************/ | |
2460 #ifndef PALM_1 | |
2461 SOAP_FMAC1 | |
2462 void | |
2463 SOAP_FMAC2 | |
2464 soap_end_block(struct soap *soap, struct soap_blist *b) | |
2465 { char *p, *q; | |
2466 if (!b) | |
2467 b = soap->blist; | |
2468 if (b) | |
2469 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of block sequence, free all remaining blocks\n")); | |
2470 for (p = b->ptr; p; p = q) | |
2471 { q = *(char**)p; | |
2472 SOAP_FREE(soap, p); | |
2473 } | |
2474 if (soap->blist == b) | |
2475 soap->blist = b->next; | |
2476 else | |
2477 { struct soap_blist *bp; | |
2478 for (bp = soap->blist; bp; bp = bp->next) | |
2479 { if (bp->next == b) | |
2480 { bp->next = b->next; | |
2481 break; | |
2482 } | |
2483 } | |
2484 } | |
2485 SOAP_FREE(soap, b); | |
2486 } | |
2487 DBGLOG(TEST, if (soap->blist) SOAP_MESSAGE(fdebug, "Restore previous block sequence\n")); | |
2488 } | |
2489 #endif | |
2490 | |
2491 /******************************************************************************/ | |
2492 #ifndef PALM_1 | |
2493 SOAP_FMAC1 | |
2494 char* | |
2495 SOAP_FMAC2 | |
2496 soap_save_block(struct soap *soap, struct soap_blist *b, char *p, int flag) | |
2497 { register size_t n; | |
2498 register char *q, *s; | |
2499 if (!b) | |
2500 b = soap->blist; | |
2501 if (b->size) | |
2502 { if (!p) | |
2503 p = (char*)soap_malloc(soap, b->size); | |
2504 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)); | |
2505 if (p) | |
2506 { for (s = p, q = soap_first_block(soap, b); q; q = soap_next_block(soap, b)) | |
2507 { n = soap_block_size(soap, b); | |
2508 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy %u bytes from %p to %p\n", (unsigned int)n, q, s)); | |
2509 #ifndef WITH_NOIDREF | |
2510 if (flag) | |
2511 soap_update_pointers(soap, q, q + n, s, q); | |
2512 #endif | |
2513 memcpy(s, q, n); | |
2514 s += n; | |
2515 } | |
2516 } | |
2517 else | |
2518 soap->error = SOAP_EOM; | |
2519 } | |
2520 soap_end_block(soap, b); | |
2521 return p; | |
2522 } | |
2523 #endif | |
2524 | |
2525 /******************************************************************************/ | |
2526 #ifndef PALM_2 | |
2527 SOAP_FMAC1 | |
2528 char * | |
2529 SOAP_FMAC2 | |
2530 soap_putsize(struct soap *soap, const char *type, int size) | |
2531 { return soap_putsizes(soap, type, &size, 1); | |
2532 } | |
2533 #endif | |
2534 | |
2535 /******************************************************************************/ | |
2536 #ifndef PALM_2 | |
2537 SOAP_FMAC1 | |
2538 char * | |
2539 SOAP_FMAC2 | |
2540 soap_putsizes(struct soap *soap, const char *type, const int *size, int dim) | |
2541 { return soap_putsizesoffsets(soap, type, size, NULL, dim); | |
2542 } | |
2543 #endif | |
2544 | |
2545 /******************************************************************************/ | |
2546 #ifndef PALM_2 | |
2547 SOAP_FMAC1 | |
2548 char * | |
2549 SOAP_FMAC2 | |
2550 soap_putsizesoffsets(struct soap *soap, const char *type, const int *size, const int *offset, int dim) | |
2551 { register int i; | |
2552 register size_t l; | |
2553 if (!type || strlen(type) + 13 > sizeof(soap->type)) /* prevent overruns */ | |
2554 return NULL; | |
2555 if (soap->version == 2) | |
2556 { | |
2557 #ifdef HAVE_SNPRINTF | |
2558 soap_snprintf(soap->type, sizeof(soap->type) - 1, "%s[%d", type, size[0]); | |
2559 #else | |
2560 sprintf(soap->type, "%s[%d", type, size[0]); | |
2561 #endif | |
2562 for (i = 1; i < dim; i++) | |
2563 { | |
2564 #ifdef HAVE_SNPRINTF | |
2565 l = strlen(soap->type); | |
2566 soap_snprintf(soap->type + l, sizeof(soap->type) - l - 1, " %d", size[i]); | |
2567 #else | |
2568 if ((l = strlen(soap->type)) + 13 > sizeof(soap->type)) | |
2569 return NULL; | |
2570 sprintf(soap->type + l, " %d", size[i]); | |
2571 #endif | |
2572 } | |
2573 } | |
2574 else | |
2575 { if (offset) | |
2576 { | |
2577 #ifdef HAVE_SNPRINTF | |
2578 soap_snprintf(soap->type, sizeof(soap->type) - 1, "%s[%d", type, size[0] + offset[0]); | |
2579 #else | |
2580 sprintf(soap->type, "%s[%d", type, size[0] + offset[0]); | |
2581 #endif | |
2582 for (i = 1; i < dim; i++) | |
2583 { | |
2584 #ifdef HAVE_SNPRINTF | |
2585 l = strlen(soap->type); | |
2586 soap_snprintf(soap->type + l, sizeof(soap->type) - l - 1, ",%d", size[i] + offset[i]); | |
2587 #else | |
2588 if ((l = strlen(soap->type)) + 13 > sizeof(soap->type)) | |
2589 return NULL; | |
2590 sprintf(soap->type + l, ",%d", size[i] + offset[i]); | |
2591 #endif | |
2592 } | |
2593 } | |
2594 else | |
2595 { | |
2596 #ifdef HAVE_SNPRINTF | |
2597 soap_snprintf(soap->type, sizeof(soap->type) - 1, "%s[%d", type, size[0]); | |
2598 #else | |
2599 sprintf(soap->type, "%s[%d", type, size[0]); | |
2600 #endif | |
2601 for (i = 1; i < dim; i++) | |
2602 { | |
2603 #ifdef HAVE_SNPRINTF | |
2604 l = strlen(soap->type); | |
2605 soap_snprintf(soap->type + l, sizeof(soap->type) - l - 1, ",%d", size[i]); | |
2606 #else | |
2607 if ((l = strlen(soap->type)) + 13 > sizeof(soap->type)) | |
2608 return NULL; | |
2609 sprintf(soap->type + l, ",%d", size[i]); | |
2610 #endif | |
2611 } | |
2612 } | |
2613 } | |
2614 strcat(soap->type, "]"); | |
2615 return soap->type; | |
2616 } | |
2617 #endif | |
2618 | |
2619 /******************************************************************************/ | |
2620 #ifndef PALM_2 | |
2621 SOAP_FMAC1 | |
2622 char * | |
2623 SOAP_FMAC2 | |
2624 soap_putoffset(struct soap *soap, int offset) | |
2625 { return soap_putoffsets(soap, &offset, 1); | |
2626 } | |
2627 #endif | |
2628 | |
2629 /******************************************************************************/ | |
2630 #ifndef PALM_2 | |
2631 SOAP_FMAC1 | |
2632 char * | |
2633 SOAP_FMAC2 | |
2634 soap_putoffsets(struct soap *soap, const int *offset, int dim) | |
2635 { register int i; | |
2636 register size_t l; | |
2637 #ifdef HAVE_SNPRINTF | |
2638 soap_snprintf(soap->arrayOffset, sizeof(soap->arrayOffset) - 1, "[%d", offset[0]); | |
2639 #else | |
2640 if (sizeof(soap->arrayOffset) < 13) /* prevent overruns */ | |
2641 return NULL; | |
2642 sprintf(soap->arrayOffset, "[%d", offset[0]); | |
2643 #endif | |
2644 for (i = 1; i < dim; i++) | |
2645 { | |
2646 #ifdef HAVE_SNPRINTF | |
2647 l = strlen(soap->arrayOffset); | |
2648 soap_snprintf(soap->arrayOffset + l, sizeof(soap->arrayOffset) - l - 1, ",%d", offset[i]); | |
2649 #else | |
2650 if ((l = strlen(soap->arrayOffset)) + 13 > sizeof(soap->arrayOffset)) | |
2651 return NULL; | |
2652 sprintf(soap->arrayOffset + l, ",%d", offset[i]); | |
2653 #endif | |
2654 } | |
2655 strcat(soap->arrayOffset, "]"); | |
2656 return soap->arrayOffset; | |
2657 } | |
2658 #endif | |
2659 | |
2660 /******************************************************************************/ | |
2661 #ifndef PALM_2 | |
2662 SOAP_FMAC1 | |
2663 int | |
2664 SOAP_FMAC2 | |
2665 soap_size(const int *size, int dim) | |
2666 { register int i, n = size[0]; | |
2667 for (i = 1; i < dim; i++) | |
2668 n *= size[i]; | |
2669 return n; | |
2670 } | |
2671 #endif | |
2672 | |
2673 /******************************************************************************/ | |
2674 #ifndef PALM_2 | |
2675 SOAP_FMAC1 | |
2676 int | |
2677 SOAP_FMAC2 | |
2678 soap_getoffsets(const char *attr, const int *size, int *offset, int dim) | |
2679 { register int i, j = 0; | |
2680 if (offset) | |
2681 for (i = 0; i < dim && attr && *attr; i++) | |
2682 { attr++; | |
2683 j *= size[i]; | |
2684 j += offset[i] = (int)soap_strtol(attr, NULL, 10); | |
2685 attr = strchr(attr, ','); | |
2686 } | |
2687 else | |
2688 for (i = 0; i < dim && attr && *attr; i++) | |
2689 { attr++; | |
2690 j *= size[i]; | |
2691 j += (int)soap_strtol(attr, NULL, 10); | |
2692 attr = strchr(attr, ','); | |
2693 } | |
2694 return j; | |
2695 } | |
2696 #endif | |
2697 | |
2698 /******************************************************************************/ | |
2699 #ifndef PALM_2 | |
2700 SOAP_FMAC1 | |
2701 int | |
2702 SOAP_FMAC2 | |
2703 soap_getsize(const char *attr1, const char *attr2, int *j) | |
2704 { register int n, k; | |
2705 char *s; | |
2706 *j = 0; | |
2707 if (!*attr1) | |
2708 return -1; | |
2709 if (*attr1 == '[') | |
2710 attr1++; | |
2711 n = 1; | |
2712 for (;;) | |
2713 { k = (int)soap_strtol(attr1, &s, 10); | |
2714 n *= k; | |
2715 if (k < 0 || n > SOAP_MAXARRAYSIZE || s == attr1) | |
2716 return -1; | |
2717 attr1 = strchr(s, ','); | |
2718 if (!attr1) | |
2719 attr1 = strchr(s, ' '); | |
2720 if (attr2 && *attr2) | |
2721 { attr2++; | |
2722 *j *= k; | |
2723 k = (int)soap_strtol(attr2, &s, 10); | |
2724 *j += k; | |
2725 if (k < 0) | |
2726 return -1; | |
2727 attr2 = s; | |
2728 } | |
2729 if (!attr1) | |
2730 break; | |
2731 attr1++; | |
2732 } | |
2733 return n - *j; | |
2734 } | |
2735 #endif | |
2736 | |
2737 /******************************************************************************/ | |
2738 #ifndef PALM_2 | |
2739 SOAP_FMAC1 | |
2740 int | |
2741 SOAP_FMAC2 | |
2742 soap_getsizes(const char *attr, int *size, int dim) | |
2743 { register int i, k, n; | |
2744 if (!*attr) | |
2745 return -1; | |
2746 i = (int)strlen(attr); | |
2747 n = 1; | |
2748 do | |
2749 { for (i = i-1; i >= 0; i--) | |
2750 if (attr[i] == '[' || attr[i] == ',' || attr[i] == ' ') | |
2751 break; | |
2752 k = (int)soap_strtol(attr + i + 1, NULL, 10); | |
2753 n *= size[--dim] = k; | |
2754 if (k < 0 || n > SOAP_MAXARRAYSIZE) | |
2755 return -1; | |
2756 } while (i >= 0 && attr[i] != '['); | |
2757 return n; | |
2758 } | |
2759 #endif | |
2760 | |
2761 /******************************************************************************/ | |
2762 #ifndef PALM_2 | |
2763 SOAP_FMAC1 | |
2764 int | |
2765 SOAP_FMAC2 | |
2766 soap_getposition(const char *attr, int *pos) | |
2767 { register int i, n; | |
2768 if (!*attr) | |
2769 return -1; | |
2770 n = 0; | |
2771 i = 1; | |
2772 do | |
2773 { pos[n++] = (int)soap_strtol(attr + i, NULL, 10); | |
2774 while (attr[i] && attr[i] != ',' && attr[i] != ']') | |
2775 i++; | |
2776 if (attr[i] == ',') | |
2777 i++; | |
2778 } while (n < SOAP_MAXDIMS && attr[i] && attr[i] != ']'); | |
2779 return n; | |
2780 } | |
2781 #endif | |
2782 | |
2783 /******************************************************************************/ | |
2784 #ifndef PALM_2 | |
2785 SOAP_FMAC1 | |
2786 struct soap_nlist * | |
2787 SOAP_FMAC2 | |
2788 soap_push_namespace(struct soap *soap, const char *id, const char *ns) | |
2789 { register struct soap_nlist *np; | |
2790 register struct Namespace *p; | |
2791 register short i = -1; | |
2792 register size_t n, k; | |
2793 n = strlen(id); | |
2794 k = strlen(ns) + 1; | |
2795 p = soap->local_namespaces; | |
2796 if (p) | |
2797 { for (i = 0; p->id; p++, i++) | |
2798 { if (p->ns && !strcmp(ns, p->ns)) | |
2799 break; | |
2800 if (p->out) | |
2801 { if (!strcmp(ns, p->out)) | |
2802 break; | |
2803 } | |
2804 else if (p->in) | |
2805 { if (!soap_tag_cmp(ns, p->in)) | |
2806 { if ((p->out = (char*)SOAP_MALLOC(soap, k))) | |
2807 strcpy(p->out, ns); | |
2808 break; | |
2809 } | |
2810 } | |
2811 } | |
2812 if (!p || !p->id) | |
2813 i = -1; | |
2814 } | |
2815 if (i >= 0) | |
2816 k = 0; | |
2817 np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k); | |
2818 if (!np) | |
2819 { soap->error = SOAP_EOM; | |
2820 return NULL; | |
2821 } | |
2822 np->next = soap->nlist; | |
2823 soap->nlist = np; | |
2824 np->level = soap->level; | |
2825 np->index = i; | |
2826 strcpy((char*)np->id, id); | |
2827 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push namespace binding (level=%u) '%s' '%s'\n", soap->level, id, ns)); | |
2828 if (i < 0) | |
2829 { np->ns = strcpy((char*)np->id + n + 1, ns); | |
2830 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push NOT OK: no match found for '%s' in namespace mapping table (added to stack anyway)\n", ns)); | |
2831 } | |
2832 else | |
2833 { np->ns = NULL; | |
2834 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push OK ('%s' matches '%s' in namespace table)\n", id, p->id)); | |
2835 } | |
2836 return np; | |
2837 } | |
2838 #endif | |
2839 | |
2840 /******************************************************************************/ | |
2841 #ifndef PALM_2 | |
2842 SOAP_FMAC1 | |
2843 void | |
2844 SOAP_FMAC2 | |
2845 soap_pop_namespace(struct soap *soap) | |
2846 { register struct soap_nlist *np, *nq; | |
2847 for (np = soap->nlist; np && np->level >= soap->level; np = nq) | |
2848 { nq = np->next; | |
2849 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop namespace binding (level=%u) '%s'\n", soap->level, np->id)); | |
2850 SOAP_FREE(soap, np); | |
2851 } | |
2852 soap->nlist = np; | |
2853 } | |
2854 #endif | |
2855 | |
2856 /******************************************************************************/ | |
2857 #ifndef PALM_2 | |
2858 SOAP_FMAC1 | |
2859 int | |
2860 SOAP_FMAC2 | |
2861 soap_match_namespace(struct soap *soap, const char *id1, const char *id2, size_t n1, size_t n2) | |
2862 { register struct soap_nlist *np = soap->nlist; | |
2863 const char *s; | |
2864 while (np && (strncmp(np->id, id1, n1) || np->id[n1])) | |
2865 np = np->next; | |
2866 if (np) | |
2867 { if (!(soap->mode & SOAP_XML_IGNORENS)) | |
2868 if (np->index < 0 | |
2869 || ((s = soap->local_namespaces[np->index].id) && (strncmp(s, id2, n2) || (s[n2] && s[n2] != '_')))) | |
2870 return SOAP_NAMESPACE; | |
2871 return SOAP_OK; | |
2872 } | |
2873 if (n1 == 0) | |
2874 return (soap->mode & SOAP_XML_IGNORENS) ? SOAP_OK : SOAP_NAMESPACE; | |
2875 if ((n1 == 3 && n1 == n2 && !strncmp(id1, "xml", 3) && !strncmp(id1, id2, 3)) | |
2876 || (soap->mode & SOAP_XML_IGNORENS)) | |
2877 return SOAP_OK; | |
2878 return soap->error = SOAP_SYNTAX_ERROR; | |
2879 } | |
2880 #endif | |
2881 | |
2882 /******************************************************************************/ | |
2883 #ifndef PALM_2 | |
2884 SOAP_FMAC1 | |
2885 const char* | |
2886 SOAP_FMAC2 | |
2887 soap_current_namespace(struct soap *soap, const char *tag) | |
2888 { register struct soap_nlist *np; | |
2889 register const char *s; | |
2890 if (!tag || !strncmp(tag, "xml", 3)) | |
2891 return NULL; | |
2892 np = soap->nlist; | |
2893 if (!(s = strchr(tag, ':'))) | |
2894 { while (np && *np->id) /* find default namespace, if present */ | |
2895 np = np->next; | |
2896 } | |
2897 else | |
2898 { while (np && (strncmp(np->id, tag, s - tag) || np->id[s - tag])) | |
2899 np = np->next; | |
2900 if (!np) | |
2901 soap->error = SOAP_NAMESPACE; | |
2902 } | |
2903 if (np) | |
2904 { if (np->index >= 0) | |
2905 return soap->namespaces[np->index].ns; | |
2906 if (np->ns) | |
2907 return soap_strdup(soap, np->ns); | |
2908 } | |
2909 return NULL; | |
2910 } | |
2911 #endif | |
2912 | |
2913 /******************************************************************************/ | |
2914 #ifndef PALM_2 | |
2915 SOAP_FMAC1 | |
2916 int | |
2917 SOAP_FMAC2 | |
2918 soap_tag_cmp(const char *s, const char *t) | |
2919 { for (;;) | |
2920 { register int c1 = *s; | |
2921 register int c2 = *t; | |
2922 if (!c1 || c1 == '"') | |
2923 break; | |
2924 if (c2 != '-') | |
2925 { if (c1 != c2) | |
2926 { if (c1 >= 'A' && c1 <= 'Z') | |
2927 c1 += 'a' - 'A'; | |
2928 if (c2 >= 'A' && c2 <= 'Z') | |
2929 c2 += 'a' - 'A'; | |
2930 } | |
2931 if (c1 != c2) | |
2932 { if (c2 != '*') | |
2933 return 1; | |
2934 c2 = *++t; | |
2935 if (!c2) | |
2936 return 0; | |
2937 if (c2 >= 'A' && c2 <= 'Z') | |
2938 c2 += 'a' - 'A'; | |
2939 for (;;) | |
2940 { c1 = *s; | |
2941 if (!c1 || c1 == '"') | |
2942 break; | |
2943 if (c1 >= 'A' && c1 <= 'Z') | |
2944 c1 += 'a' - 'A'; | |
2945 if (c1 == c2 && !soap_tag_cmp(s + 1, t + 1)) | |
2946 return 0; | |
2947 s++; | |
2948 } | |
2949 break; | |
2950 } | |
2951 } | |
2952 s++; | |
2953 t++; | |
2954 } | |
2955 if (*t == '*' && !t[1]) | |
2956 return 0; | |
2957 return *t; | |
2958 } | |
2959 #endif | |
2960 | |
2961 /******************************************************************************/ | |
2962 #ifndef PALM_2 | |
2963 SOAP_FMAC1 | |
2964 int | |
2965 SOAP_FMAC2 | |
2966 soap_match_tag(struct soap *soap, const char *tag1, const char *tag2) | |
2967 { register const char *s, *t; | |
2968 register int err; | |
2969 if (!tag1 || !tag2 || !*tag2) | |
2970 return SOAP_OK; | |
2971 s = strchr(tag1, ':'); | |
2972 t = strchr(tag2, ':'); | |
2973 if (t) | |
2974 { if (s) | |
2975 { if (t[1] && SOAP_STRCMP(s + 1, t + 1)) | |
2976 return SOAP_TAG_MISMATCH; | |
2977 if (t != tag2 && (err = soap_match_namespace(soap, tag1, tag2, s - tag1, t - tag2))) | |
2978 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2)); | |
2979 if (err == SOAP_NAMESPACE) | |
2980 return SOAP_TAG_MISMATCH; | |
2981 return err; | |
2982 } | |
2983 } | |
2984 else if (!t[1]) | |
2985 { err = soap_match_namespace(soap, tag1, tag2, 0, t - tag2); | |
2986 if (err == SOAP_NAMESPACE) | |
2987 return SOAP_TAG_MISMATCH; | |
2988 } | |
2989 else if (SOAP_STRCMP(tag1, t + 1)) | |
2990 { return SOAP_TAG_MISMATCH; | |
2991 } | |
2992 else if (t != tag2 && (err = soap_match_namespace(soap, tag1, tag2, 0, t - tag2))) | |
2993 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2)); | |
2994 if (err == SOAP_NAMESPACE) | |
2995 return SOAP_TAG_MISMATCH; | |
2996 return err; | |
2997 } | |
2998 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags and (default) namespaces match: '%s' '%s'\n", tag1, tag2)); | |
2999 return SOAP_OK; | |
3000 } | |
3001 if (s) | |
3002 { if (SOAP_STRCMP(s + 1, tag2)) | |
3003 return SOAP_TAG_MISMATCH; | |
3004 } | |
3005 else if (SOAP_STRCMP(tag1, tag2)) | |
3006 return SOAP_TAG_MISMATCH; | |
3007 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags match: '%s' '%s'\n", tag1, tag2)); | |
3008 return SOAP_OK; | |
3009 } | |
3010 #endif | |
3011 | |
3012 /******************************************************************************/ | |
3013 #ifndef PALM_2 | |
3014 SOAP_FMAC1 | |
3015 int | |
3016 SOAP_FMAC2 | |
3017 soap_match_array(struct soap *soap, const char *type) | |
3018 { if (*soap->arrayType) | |
3019 if (soap_match_tag(soap, soap->arrayType, type) | |
3020 && soap_match_tag(soap, soap->arrayType, "xsd:anyType") | |
3021 && soap_match_tag(soap, soap->arrayType, "xsd:ur-type") | |
3022 ) | |
3023 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array type mismatch: '%s' '%s'\n", soap->arrayType, type)); | |
3024 return SOAP_TAG_MISMATCH; | |
3025 } | |
3026 return SOAP_OK; | |
3027 } | |
3028 #endif | |
3029 | |
3030 /******************************************************************************\ | |
3031 * | |
3032 * SSL/TLS | |
3033 * | |
3034 \******************************************************************************/ | |
3035 | |
3036 /******************************************************************************/ | |
3037 #ifdef WITH_OPENSSL | |
3038 #ifndef PALM_2 | |
3039 SOAP_FMAC1 | |
3040 int | |
3041 SOAP_FMAC2 | |
3042 soap_rand() | |
3043 { unsigned char buf[4]; | |
3044 if (!soap_ssl_init_done) | |
3045 soap_ssl_init(); | |
3046 RAND_pseudo_bytes(buf, 4); | |
3047 return *(int*)buf; | |
3048 } | |
3049 #endif | |
3050 #endif | |
3051 | |
3052 /******************************************************************************/ | |
3053 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) | |
3054 #ifndef PALM_2 | |
3055 SOAP_FMAC1 | |
3056 int | |
3057 SOAP_FMAC2 | |
3058 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE) | |
3059 soap_ssl_server_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *keyid, const char *password, const char *cafile, const char *capath, const char *dhfile, const char *randfile, const char *sid) | |
3060 #else | |
3061 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) | |
3062 #endif | |
3063 { int err; | |
3064 soap->keyfile = keyfile; | |
3065 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE) | |
3066 soap->keyid = keyid; | |
3067 #endif | |
3068 soap->password = password; | |
3069 soap->cafile = cafile; | |
3070 soap->capath = capath; | |
3071 soap->crlfile = NULL; | |
3072 #ifdef WITH_OPENSSL | |
3073 soap->dhfile = dhfile; | |
3074 soap->randfile = randfile; | |
3075 #endif | |
3076 soap->ssl_flags = flags | (dhfile == NULL ? SOAP_SSL_RSA : 0); | |
3077 #ifdef WITH_GNUTLS | |
3078 if (dhfile) | |
3079 { char *s; | |
3080 int n = (int)soap_strtoul(dhfile, &s, 10); | |
3081 if (!soap->dh_params) | |
3082 gnutls_dh_params_init(&soap->dh_params); | |
3083 /* if dhfile is numeric, treat it as a key length to generate DH params which can take a while */ | |
3084 if (n >= 512 && s && *s == '\0') | |
3085 gnutls_dh_params_generate2(soap->dh_params, (unsigned int)n); | |
3086 else | |
3087 { unsigned int dparams_len; | |
3088 unsigned char dparams_buf[1024]; | |
3089 FILE *fd = fopen(dhfile, "r"); | |
3090 if (!fd) | |
3091 return soap_set_receiver_error(soap, "SSL/TLS error", "Invalid DH file", SOAP_SSL_ERROR); | |
3092 dparams_len = (unsigned int)fread(dparams_buf, 1, sizeof(dparams_buf), fd); | |
3093 fclose(fd); | |
3094 gnutls_datum_t dparams = { dparams_buf, dparams_len }; | |
3095 if (gnutls_dh_params_import_pkcs3(soap->dh_params, &dparams, GNUTLS_X509_FMT_PEM)) | |
3096 return soap_set_receiver_error(soap, "SSL/TLS error", "Invalid DH file", SOAP_SSL_ERROR); | |
3097 } | |
3098 } | |
3099 else | |
3100 { if (!soap->rsa_params) | |
3101 gnutls_rsa_params_init(&soap->rsa_params); | |
3102 gnutls_rsa_params_generate2(soap->rsa_params, SOAP_SSL_RSA_BITS); | |
3103 } | |
3104 if (soap->session) | |
3105 { gnutls_deinit(soap->session); | |
3106 soap->session = NULL; | |
3107 } | |
3108 if (soap->xcred) | |
3109 { gnutls_certificate_free_credentials(soap->xcred); | |
3110 soap->xcred = NULL; | |
3111 } | |
3112 #endif | |
3113 err = soap->fsslauth(soap); | |
3114 #ifdef WITH_OPENSSL | |
3115 if (!err) | |
3116 { if (sid) | |
3117 SSL_CTX_set_session_id_context(soap->ctx, (unsigned char*)sid, (unsigned int)strlen(sid)); | |
3118 else | |
3119 SSL_CTX_set_session_cache_mode(soap->ctx, SSL_SESS_CACHE_OFF); | |
3120 } | |
3121 #endif | |
3122 return err; | |
3123 } | |
3124 #endif | |
3125 #endif | |
3126 | |
3127 /******************************************************************************/ | |
3128 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) | |
3129 #ifndef PALM_2 | |
3130 SOAP_FMAC1 | |
3131 int | |
3132 SOAP_FMAC2 | |
3133 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE) | |
3134 soap_ssl_client_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *keyid, const char *password, const char *cafile, const char *capath, const char *randfile) | |
3135 #else | |
3136 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) | |
3137 #endif | |
3138 { soap->keyfile = keyfile; | |
3139 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE) | |
3140 soap->keyid = keyid; | |
3141 #endif | |
3142 soap->password = password; | |
3143 soap->cafile = cafile; | |
3144 soap->capath = capath; | |
3145 soap->ssl_flags = SOAP_SSL_CLIENT | flags; | |
3146 #ifdef WITH_OPENSSL | |
3147 soap->dhfile = NULL; | |
3148 soap->randfile = randfile; | |
3149 soap->fsslverify = (flags & SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE) == 0 ? ssl_verify_callback : ssl_verify_callback_allow_expired_certificate; | |
3150 #endif | |
3151 #ifdef WITH_GNUTLS | |
3152 if (soap->session) | |
3153 { gnutls_deinit(soap->session); | |
3154 soap->session = NULL; | |
3155 } | |
3156 if (soap->xcred) | |
3157 { gnutls_certificate_free_credentials(soap->xcred); | |
3158 soap->xcred = NULL; | |
3159 } | |
3160 #endif | |
3161 return soap->fsslauth(soap); | |
3162 } | |
3163 #endif | |
3164 #endif | |
3165 | |
3166 /******************************************************************************/ | |
3167 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) | |
3168 #ifndef PALM_2 | |
3169 SOAP_FMAC1 | |
3170 void | |
3171 SOAP_FMAC2 | |
3172 soap_ssl_init() | |
3173 { /* Note: for MT systems, the main program MUST call soap_ssl_init() before any threads are started */ | |
3174 if (!soap_ssl_init_done) | |
3175 { soap_ssl_init_done = 1; | |
3176 #ifdef WITH_OPENSSL | |
3177 SSL_library_init(); | |
3178 OpenSSL_add_all_algorithms(); /* 2.8.1 change (wsseapi.c) */ | |
3179 OpenSSL_add_all_digests(); | |
3180 #ifndef WITH_LEAN | |
3181 SSL_load_error_strings(); | |
3182 #endif | |
3183 if (!RAND_load_file("/dev/urandom", 1024)) | |
3184 { char buf[1024]; | |
3185 RAND_seed(buf, sizeof(buf)); | |
3186 while (!RAND_status()) | |
3187 { int r = rand(); | |
3188 RAND_seed(&r, sizeof(int)); | |
3189 } | |
3190 } | |
3191 #endif | |
3192 #ifdef WITH_GNUTLS | |
3193 # if defined(HAVE_PTHREAD_H) | |
3194 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); | |
3195 # elif defined(HAVE_PTH_H) | |
3196 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth); | |
3197 # endif | |
3198 gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM, 0); | |
3199 gcry_control(GCRYCTL_DISABLE_SECMEM, 0); | |
3200 gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); /* libgcrypt init done */ | |
3201 gnutls_global_init(); | |
3202 #endif | |
3203 } | |
3204 } | |
3205 #endif | |
3206 #endif | |
3207 | |
3208 /******************************************************************************/ | |
3209 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) | |
3210 #ifndef PALM_1 | |
3211 SOAP_FMAC1 | |
3212 const char * | |
3213 SOAP_FMAC2 | |
3214 soap_ssl_error(struct soap *soap, int ret) | |
3215 { | |
3216 #ifdef WITH_OPENSSL | |
3217 int err = SSL_get_error(soap->ssl, ret); | |
3218 const char *msg = soap_code_str(h_ssl_error_codes, err); | |
3219 if (msg) | |
3220 strcpy(soap->msgbuf, msg); | |
3221 else | |
3222 return ERR_error_string(err, soap->msgbuf); | |
3223 if (ERR_peek_error()) | |
3224 { unsigned long r; | |
3225 strcat(soap->msgbuf, "\n"); | |
3226 while ((r = ERR_get_error())) | |
3227 ERR_error_string_n(r, soap->msgbuf + strlen(soap->msgbuf), sizeof(soap->msgbuf) - strlen(soap->msgbuf)); | |
3228 } | |
3229 else | |
3230 { switch (ret) | |
3231 { case 0: | |
3232 strcpy(soap->msgbuf, "EOF was observed that violates the SSL/TLS protocol. The client probably provided invalid authentication information."); | |
3233 break; | |
3234 case -1: | |
3235 #ifdef HAVE_SNPRINTF | |
3236 soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "Error observed by underlying SSL/TLS BIO: %s", strerror(errno)); | |
3237 #else | |
3238 { const char *s = strerror(errno); | |
3239 size_t l = strlen(s); | |
3240 sprintf(soap->msgbuf, "Error observed by underlying SSL/TLS BIO: %s", l + 44 < sizeof(soap->msgbuf) ? s : SOAP_STR_EOS); | |
3241 } | |
3242 #endif | |
3243 break; | |
3244 } | |
3245 } | |
3246 return soap->msgbuf; | |
3247 #endif | |
3248 #ifdef WITH_GNUTLS | |
3249 return gnutls_strerror(ret); | |
3250 #endif | |
3251 } | |
3252 #endif | |
3253 #endif | |
3254 | |
3255 /******************************************************************************/ | |
3256 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) | |
3257 #ifndef PALM_1 | |
3258 static int | |
3259 ssl_auth_init(struct soap *soap) | |
3260 { | |
3261 #ifdef WITH_OPENSSL | |
3262 long flags; | |
3263 int mode; | |
3264 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE) | |
3265 EVP_PKEY* pkey; | |
3266 #endif | |
3267 if (!soap_ssl_init_done) | |
3268 soap_ssl_init(); | |
3269 ERR_clear_error(); | |
3270 if (!soap->ctx) | |
3271 { if (!(soap->ctx = SSL_CTX_new(SSLv23_method()))) | |
3272 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't setup context", SOAP_SSL_ERROR); | |
3273 /* The following alters the behavior of SSL read/write: */ | |
3274 #if 0 | |
3275 SSL_CTX_set_mode(soap->ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY); | |
3276 #endif | |
3277 } | |
3278 if (soap->randfile) | |
3279 { if (!RAND_load_file(soap->randfile, -1)) | |
3280 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't load randomness", SOAP_SSL_ERROR); | |
3281 } | |
3282 if (soap->cafile || soap->capath) | |
3283 { if (!SSL_CTX_load_verify_locations(soap->ctx, soap->cafile, soap->capath)) | |
3284 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CA file", SOAP_SSL_ERROR); | |
3285 if (soap->cafile && (soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION)) | |
3286 SSL_CTX_set_client_CA_list(soap->ctx, SSL_load_client_CA_file(soap->cafile)); | |
3287 } | |
3288 if (!(soap->ssl_flags & SOAP_SSL_NO_DEFAULT_CA_PATH)) | |
3289 { if (!SSL_CTX_set_default_verify_paths(soap->ctx)) | |
3290 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read default CA file and/or directory", SOAP_SSL_ERROR); | |
3291 } | |
3292 /* This code assumes a typical scenario, see alternative code below */ | |
3293 if (soap->keyfile) | |
3294 { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile)) | |
3295 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read certificate key file", SOAP_SSL_ERROR); | |
3296 if (soap->password) | |
3297 { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password); | |
3298 SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password); | |
3299 } | |
3300 if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM)) | |
3301 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read key file", SOAP_SSL_ERROR); | |
3302 #ifndef WM_SECURE_KEY_STORAGE | |
3303 if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM)) | |
3304 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read key file", SOAP_SSL_ERROR); | |
3305 #endif | |
3306 } | |
3307 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE) | |
3308 if (NULL == (pkey = ipcom_key_db_pkey_get(soap->keyid))) | |
3309 return soap_set_receiver_error(soap, "SSL error", "Can't find key", SOAP_SSL_ERROR); | |
3310 if (0 == SSL_CTX_use_PrivateKey(soap->ctx, pkey)) | |
3311 return soap_set_receiver_error(soap, "SSL error", "Can't read key", SOAP_SSL_ERROR); | |
3312 #endif | |
3313 /* Suggested alternative approach to check the key file for certs (cafile=NULL):*/ | |
3314 #if 0 | |
3315 if (soap->password) | |
3316 { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password); | |
3317 SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password); | |
3318 } | |
3319 if (!soap->cafile || !SSL_CTX_use_certificate_chain_file(soap->ctx, soap->cafile)) | |
3320 { if (soap->keyfile) | |
3321 { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile)) | |
3322 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read certificate or key file", SOAP_SSL_ERROR); | |
3323 if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM)) | |
3324 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read key file", SOAP_SSL_ERROR); | |
3325 } | |
3326 } | |
3327 #endif | |
3328 if ((soap->ssl_flags & SOAP_SSL_RSA)) | |
3329 { RSA *rsa = RSA_generate_key(SOAP_SSL_RSA_BITS, RSA_F4, NULL, NULL); | |
3330 if (!SSL_CTX_set_tmp_rsa(soap->ctx, rsa)) | |
3331 { if (rsa) | |
3332 RSA_free(rsa); | |
3333 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't set RSA key", SOAP_SSL_ERROR); | |
3334 } | |
3335 RSA_free(rsa); | |
3336 } | |
3337 else if (soap->dhfile) | |
3338 { DH *dh = 0; | |
3339 char *s; | |
3340 int n = (int)soap_strtoul(soap->dhfile, &s, 10); | |
3341 /* if dhfile is numeric, treat it as a key length to generate DH params which can take a while */ | |
3342 if (n >= 512 && s && *s == '\0') | |
3343 #if defined(VXWORKS) | |
3344 DH_generate_parameters_ex(dh, n, 2/*or 5*/, NULL); | |
3345 #else | |
3346 dh = DH_generate_parameters(n, 2/*or 5*/, NULL, NULL); | |
3347 #endif | |
3348 else | |
3349 { BIO *bio; | |
3350 bio = BIO_new_file(soap->dhfile, "r"); | |
3351 if (!bio) | |
3352 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read DH file", SOAP_SSL_ERROR); | |
3353 dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); | |
3354 BIO_free(bio); | |
3355 } | |
3356 if (!dh || DH_check(dh, &n) != 1 || SSL_CTX_set_tmp_dh(soap->ctx, dh) < 0) | |
3357 { if (dh) | |
3358 DH_free(dh); | |
3359 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't set DH parameters", SOAP_SSL_ERROR); | |
3360 } | |
3361 DH_free(dh); | |
3362 } | |
3363 flags = (SSL_OP_ALL | SSL_OP_NO_SSLv2); /* disable SSL v2 */ | |
3364 if ((soap->ssl_flags & SOAP_SSLv3)) | |
3365 flags |= SSL_OP_NO_TLSv1; | |
3366 if ((soap->ssl_flags & SOAP_TLSv1)) | |
3367 flags |= SSL_OP_NO_SSLv3; | |
3368 #ifdef SSL_OP_NO_TICKET | |
3369 /* TLS extension is enabled by default in OPENSSL v0.9.8k | |
3370 Disable it by adding SSL_OP_NO_TICKET */ | |
3371 flags |= SSL_OP_NO_TICKET; | |
3372 #endif | |
3373 SSL_CTX_set_options(soap->ctx, flags); | |
3374 if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION)) | |
3375 mode = (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT); | |
3376 else if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION)) | |
3377 mode = SSL_VERIFY_PEER; | |
3378 else | |
3379 mode = SSL_VERIFY_NONE; | |
3380 SSL_CTX_set_verify(soap->ctx, mode, soap->fsslverify); | |
3381 #if (OPENSSL_VERSION_NUMBER < 0x00905100L) | |
3382 SSL_CTX_set_verify_depth(soap->ctx, 1); | |
3383 #else | |
3384 SSL_CTX_set_verify_depth(soap->ctx, 9); | |
3385 #endif | |
3386 #endif | |
3387 #ifdef WITH_GNUTLS | |
3388 int ret; | |
3389 if (!soap_ssl_init_done) | |
3390 soap_ssl_init(); | |
3391 if (!soap->xcred) | |
3392 { gnutls_certificate_allocate_credentials(&soap->xcred); | |
3393 if (soap->cafile) | |
3394 { if (gnutls_certificate_set_x509_trust_file(soap->xcred, soap->cafile, GNUTLS_X509_FMT_PEM) < 0) | |
3395 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CA file", SOAP_SSL_ERROR); | |
3396 } | |
3397 if (soap->crlfile) | |
3398 { if (gnutls_certificate_set_x509_crl_file(soap->xcred, soap->crlfile, GNUTLS_X509_FMT_PEM) < 0) | |
3399 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CRL file", SOAP_SSL_ERROR); | |
3400 } | |
3401 if (soap->keyfile) | |
3402 { if (gnutls_certificate_set_x509_key_file(soap->xcred, soap->keyfile, soap->keyfile, GNUTLS_X509_FMT_PEM) < 0) /* TODO: GNUTLS need to concat cert and key in single key file */ | |
3403 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read key file", SOAP_SSL_ERROR); | |
3404 } | |
3405 } | |
3406 if ((soap->ssl_flags & SOAP_SSL_CLIENT)) | |
3407 { gnutls_init(&soap->session, GNUTLS_CLIENT); | |
3408 if (soap->cafile || soap->crlfile || soap->keyfile) | |
3409 { ret = gnutls_priority_set_direct(soap->session, "PERFORMANCE", NULL); | |
3410 if (ret < 0) | |
3411 return soap_set_receiver_error(soap, soap_ssl_error(soap, ret), "SSL/TLS set priority error", SOAP_SSL_ERROR); | |
3412 gnutls_credentials_set(soap->session, GNUTLS_CRD_CERTIFICATE, soap->xcred); | |
3413 } | |
3414 else | |
3415 { if (!soap->acred) | |
3416 gnutls_anon_allocate_client_credentials(&soap->acred); | |
3417 gnutls_init(&soap->session, GNUTLS_CLIENT); | |
3418 gnutls_priority_set_direct(soap->session, "PERFORMANCE:+ANON-DH:!ARCFOUR-128", NULL); | |
3419 gnutls_credentials_set(soap->session, GNUTLS_CRD_ANON, soap->acred); | |
3420 } | |
3421 } | |
3422 else | |
3423 { if (!soap->keyfile) | |
3424 return soap_set_receiver_error(soap, "SSL/TLS error", "No key file: anonymous server authentication not supported in this release", SOAP_SSL_ERROR); | |
3425 if ((soap->ssl_flags & SOAP_SSL_RSA) && soap->rsa_params) | |
3426 gnutls_certificate_set_rsa_export_params(soap->xcred, soap->rsa_params); | |
3427 else if (soap->dh_params) | |
3428 gnutls_certificate_set_dh_params(soap->xcred, soap->dh_params); | |
3429 if (!soap->cache) | |
3430 gnutls_priority_init(&soap->cache, "NORMAL", NULL); | |
3431 gnutls_init(&soap->session, GNUTLS_SERVER); | |
3432 gnutls_priority_set(soap->session, soap->cache); | |
3433 gnutls_credentials_set(soap->session, GNUTLS_CRD_CERTIFICATE, soap->xcred); | |
3434 if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION)) | |
3435 gnutls_certificate_server_set_request(soap->session, GNUTLS_CERT_REQUEST); | |
3436 gnutls_session_enable_compatibility_mode(soap->session); | |
3437 if ((soap->ssl_flags & SOAP_TLSv1)) | |
3438 { int protocol_priority[] = { GNUTLS_TLS1_0, 0 }; | |
3439 if (gnutls_protocol_set_priority(soap->session, protocol_priority) != GNUTLS_E_SUCCESS) | |
3440 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't set TLS v1.0 protocol", SOAP_SSL_ERROR); | |
3441 } | |
3442 } | |
3443 #endif | |
3444 return SOAP_OK; | |
3445 } | |
3446 #endif | |
3447 #endif | |
3448 | |
3449 /******************************************************************************/ | |
3450 #ifdef WITH_OPENSSL | |
3451 #ifndef PALM_1 | |
3452 static int | |
3453 ssl_password(char *buf, int num, int rwflag, void *userdata) | |
3454 { if (num < (int)strlen((char*)userdata) + 1) | |
3455 return 0; | |
3456 return (int)strlen(strcpy(buf, (char*)userdata)); | |
3457 } | |
3458 #endif | |
3459 #endif | |
3460 | |
3461 /******************************************************************************/ | |
3462 #ifdef WITH_OPENSSL | |
3463 #ifndef PALM_1 | |
3464 static int | |
3465 ssl_verify_callback(int ok, X509_STORE_CTX *store) | |
3466 { | |
3467 #ifdef SOAP_DEBUG | |
3468 if (!ok) | |
3469 { char buf[1024]; | |
3470 int err = X509_STORE_CTX_get_error(store); | |
3471 X509 *cert = X509_STORE_CTX_get_current_cert(store); | |
3472 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(err)); | |
3473 X509_NAME_oneline(X509_get_issuer_name(cert), buf, sizeof(buf)); | |
3474 fprintf(stderr, "certificate issuer %s\n", buf); | |
3475 X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); | |
3476 fprintf(stderr, "certificate subject %s\n", buf); | |
3477 /* accept self signed certificates and certificates out of date */ | |
3478 switch (err) | |
3479 { case X509_V_ERR_CERT_NOT_YET_VALID: | |
3480 case X509_V_ERR_CERT_HAS_EXPIRED: | |
3481 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: | |
3482 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: | |
3483 X509_STORE_CTX_set_error(store, X509_V_OK); | |
3484 ok = 1; | |
3485 } | |
3486 } | |
3487 #endif | |
3488 /* Note: return 1 to continue, but unsafe progress will be terminated by OpenSSL */ | |
3489 return ok; | |
3490 } | |
3491 #endif | |
3492 #endif | |
3493 | |
3494 /******************************************************************************/ | |
3495 #ifdef WITH_OPENSSL | |
3496 #ifndef PALM_1 | |
3497 static int | |
3498 ssl_verify_callback_allow_expired_certificate(int ok, X509_STORE_CTX *store) | |
3499 { ok = ssl_verify_callback(ok, store); | |
3500 if (!ok) | |
3501 { /* accept self signed certificates and certificates out of date */ | |
3502 switch (X509_STORE_CTX_get_error(store)) | |
3503 { case X509_V_ERR_CERT_NOT_YET_VALID: | |
3504 case X509_V_ERR_CERT_HAS_EXPIRED: | |
3505 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: | |
3506 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: | |
3507 X509_STORE_CTX_set_error(store, X509_V_OK); | |
3508 ok = 1; | |
3509 } | |
3510 } | |
3511 /* Note: return 1 to continue, but unsafe progress will be terminated by SSL */ | |
3512 return ok; | |
3513 } | |
3514 #endif | |
3515 #endif | |
3516 | |
3517 /******************************************************************************/ | |
3518 #ifdef WITH_GNUTLS | |
3519 static const char * | |
3520 ssl_verify(struct soap *soap, const char *host) | |
3521 { unsigned int status; | |
3522 const char *err = NULL; | |
3523 int r = gnutls_certificate_verify_peers2(soap->session, &status); | |
3524 if (r < 0) | |
3525 err = "Certificate verify error"; | |
3526 else if ((status & GNUTLS_CERT_INVALID)) | |
3527 err = "The certificate is not trusted"; | |
3528 else if ((status & GNUTLS_CERT_SIGNER_NOT_FOUND)) | |
3529 err = "The certificate hasn't got a known issuer"; | |
3530 else if ((status & GNUTLS_CERT_REVOKED)) | |
3531 err = "The certificate has been revoked"; | |
3532 else if (gnutls_certificate_type_get(soap->session) == GNUTLS_CRT_X509) | |
3533 { gnutls_x509_crt_t cert; | |
3534 const gnutls_datum_t *cert_list; | |
3535 unsigned int cert_list_size; | |
3536 if (gnutls_x509_crt_init(&cert) < 0) | |
3537 err = "Could not get X509 certificates"; | |
3538 else if ((cert_list = gnutls_certificate_get_peers(soap->session, &cert_list_size)) == NULL) | |
3539 err = "Could not get X509 certificates"; | |
3540 else if (gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0) | |
3541 err = "Error parsing X509 certificate"; | |
3542 else if (!(soap->ssl_flags & SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE) && gnutls_x509_crt_get_expiration_time(cert) < time(NULL)) | |
3543 err = "The certificate has expired"; | |
3544 else if (!(soap->ssl_flags & SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE) && gnutls_x509_crt_get_activation_time(cert) > time(NULL)) | |
3545 err = "The certificate is not yet activated"; | |
3546 else if (host && !(soap->ssl_flags & SOAP_SSL_SKIP_HOST_CHECK)) | |
3547 { if (!gnutls_x509_crt_check_hostname(cert, host)) | |
3548 err = "Certificate host name mismatch"; | |
3549 } | |
3550 gnutls_x509_crt_deinit(cert); | |
3551 } | |
3552 return err; | |
3553 } | |
3554 #endif | |
3555 | |
3556 /******************************************************************************/ | |
3557 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) | |
3558 #ifndef WITH_NOIO | |
3559 #ifndef PALM_1 | |
3560 SOAP_FMAC1 | |
3561 int | |
3562 SOAP_FMAC2 | |
3563 soap_ssl_accept(struct soap *soap) | |
3564 { SOAP_SOCKET sk = soap->socket; | |
3565 #ifdef WITH_OPENSSL | |
3566 BIO *bio; | |
3567 int retries, r, s; | |
3568 if (!soap_valid_socket(sk)) | |
3569 return soap_set_receiver_error(soap, "SSL/TLS error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR); | |
3570 soap->ssl_flags &= ~SOAP_SSL_CLIENT; | |
3571 if (!soap->ctx && (soap->error = soap->fsslauth(soap))) | |
3572 return soap->error; | |
3573 if (!soap->ssl) | |
3574 { soap->ssl = SSL_new(soap->ctx); | |
3575 if (!soap->ssl) | |
3576 return soap_set_receiver_error(soap, "SSL/TLS error", "SSL_new() failed in soap_ssl_accept()", SOAP_SSL_ERROR); | |
3577 } | |
3578 else | |
3579 SSL_clear(soap->ssl); | |
3580 bio = BIO_new_socket((int)sk, BIO_NOCLOSE); | |
3581 SSL_set_bio(soap->ssl, bio, bio); | |
3582 /* Set SSL sockets to non-blocking */ | |
3583 retries = 0; | |
3584 if (soap->accept_timeout) | |
3585 { SOAP_SOCKNONBLOCK(sk) | |
3586 retries = 10*soap->accept_timeout; | |
3587 } | |
3588 if (retries <= 0) | |
3589 retries = 100; /* timeout: 10 sec retries, 100 times 0.1 sec */ | |
3590 while ((r = SSL_accept(soap->ssl)) <= 0) | |
3591 { int err; | |
3592 if (retries-- <= 0) | |
3593 break; | |
3594 err = SSL_get_error(soap->ssl, r); | |
3595 if (err == SSL_ERROR_WANT_ACCEPT || err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) | |
3596 { if (err == SSL_ERROR_WANT_READ) | |
3597 s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000); | |
3598 else | |
3599 s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000); | |
3600 if (s < 0) | |
3601 break; | |
3602 } | |
3603 else | |
3604 { soap->errnum = soap_socket_errno(sk); | |
3605 break; | |
3606 } | |
3607 } | |
3608 if (r <= 0) | |
3609 { soap_set_receiver_error(soap, soap_ssl_error(soap, r), "SSL_accept() failed in soap_ssl_accept()", SOAP_SSL_ERROR); | |
3610 soap_closesock(soap); | |
3611 return SOAP_SSL_ERROR; | |
3612 } | |
3613 if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION)) | |
3614 { X509 *peer; | |
3615 int err; | |
3616 if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK) | |
3617 { soap_closesock(soap); | |
3618 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); | |
3619 } | |
3620 peer = SSL_get_peer_certificate(soap->ssl); | |
3621 if (!peer) | |
3622 { soap_closesock(soap); | |
3623 return soap_set_sender_error(soap, "SSL/TLS error", "No SSL certificate was presented by the peer in soap_ssl_accept()", SOAP_SSL_ERROR); | |
3624 } | |
3625 X509_free(peer); | |
3626 } | |
3627 #endif | |
3628 #ifdef WITH_GNUTLS | |
3629 int retries = 0, r; | |
3630 if (!soap_valid_socket(sk)) | |
3631 return soap_set_receiver_error(soap, "SSL/TLS error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR); | |
3632 soap->ssl_flags &= ~SOAP_SSL_CLIENT; | |
3633 if (!soap->session && (soap->error = soap->fsslauth(soap))) | |
3634 { soap_closesock(soap); | |
3635 return soap->error; | |
3636 } | |
3637 gnutls_transport_set_ptr(soap->session, (gnutls_transport_ptr_t)(long)sk); | |
3638 /* Set SSL sockets to non-blocking */ | |
3639 if (soap->accept_timeout) | |
3640 { SOAP_SOCKNONBLOCK(sk) | |
3641 retries = 10*soap->accept_timeout; | |
3642 } | |
3643 if (retries <= 0) | |
3644 retries = 100; /* timeout: 10 sec retries, 100 times 0.1 sec */ | |
3645 while ((r = gnutls_handshake(soap->session))) | |
3646 { int s; | |
3647 /* GNUTLS repeat handhake when GNUTLS_E_AGAIN */ | |
3648 if (retries-- <= 0) | |
3649 break; | |
3650 if (r == GNUTLS_E_AGAIN || r == GNUTLS_E_INTERRUPTED) | |
3651 { if (!gnutls_record_get_direction(soap->session)) | |
3652 s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000); | |
3653 else | |
3654 s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000); | |
3655 if (s < 0) | |
3656 break; | |
3657 } | |
3658 else | |
3659 { soap->errnum = soap_socket_errno(sk); | |
3660 break; | |
3661 } | |
3662 } | |
3663 if (r) | |
3664 { soap_closesock(soap); | |
3665 return soap_set_receiver_error(soap, soap_ssl_error(soap, r), "SSL/TLS handshake failed", SOAP_SSL_ERROR); | |
3666 } | |
3667 if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION)) | |
3668 { const char *err = ssl_verify(soap, NULL); | |
3669 if (err) | |
3670 { soap_closesock(soap); | |
3671 return soap_set_receiver_error(soap, "SSL/TLS error", err, SOAP_SSL_ERROR); | |
3672 } | |
3673 } | |
3674 #endif | |
3675 if (soap->recv_timeout || soap->send_timeout) | |
3676 SOAP_SOCKNONBLOCK(sk) | |
3677 else | |
3678 SOAP_SOCKBLOCK(sk) | |
3679 soap->imode |= SOAP_ENC_SSL; | |
3680 soap->omode |= SOAP_ENC_SSL; | |
3681 return SOAP_OK; | |
3682 } | |
3683 #endif | |
3684 #endif | |
3685 #endif | |
3686 | |
3687 /******************************************************************************\ | |
3688 * | |
3689 * TCP/UDP [SSL/TLS] IPv4 and IPv6 | |
3690 * | |
3691 \******************************************************************************/ | |
3692 | |
3693 /******************************************************************************/ | |
3694 #ifndef WITH_NOIO | |
3695 #ifndef PALM_1 | |
3696 static int | |
3697 tcp_init(struct soap *soap) | |
3698 { soap->errmode = 1; | |
3699 #ifdef WIN32 | |
3700 if (tcp_done) | |
3701 return 0; | |
3702 else | |
3703 { WSADATA w; | |
3704 if (WSAStartup(MAKEWORD(1, 1), &w)) | |
3705 return -1; | |
3706 tcp_done = 1; | |
3707 } | |
3708 #endif | |
3709 return 0; | |
3710 } | |
3711 #endif | |
3712 #endif | |
3713 | |
3714 /******************************************************************************/ | |
3715 #ifndef WITH_NOIO | |
3716 #ifndef PALM_1 | |
3717 static const char* | |
3718 tcp_error(struct soap *soap) | |
3719 { register const char *msg = NULL; | |
3720 switch (soap->errmode) | |
3721 { case 0: | |
3722 msg = soap_strerror(soap); | |
3723 break; | |
3724 case 1: | |
3725 msg = "WSAStartup failed"; | |
3726 break; | |
3727 case 2: | |
3728 { | |
3729 #ifndef WITH_LEAN | |
3730 msg = soap_code_str(h_error_codes, soap->errnum); | |
3731 if (!msg) | |
3732 #endif | |
3733 { | |
3734 #ifdef HAVE_SNPRINTF | |
3735 soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "TCP/UDP IP error %d", soap->errnum); | |
3736 #else | |
3737 sprintf(soap->msgbuf, "TCP/UDP IP error %d", soap->errnum); | |
3738 #endif | |
3739 msg = soap->msgbuf; | |
3740 } | |
3741 } | |
3742 } | |
3743 return msg; | |
3744 } | |
3745 #endif | |
3746 #endif | |
3747 | |
3748 /******************************************************************************/ | |
3749 #ifndef WITH_IPV6 | |
3750 #ifndef WITH_NOIO | |
3751 #ifndef PALM_1 | |
3752 static int | |
3753 tcp_gethost(struct soap *soap, const char *addr, struct in_addr *inaddr) | |
3754 { soap_int32 iadd = -1; | |
3755 struct hostent hostent, *host = &hostent; | |
3756 #ifdef VXWORKS | |
3757 int hostint; | |
3758 /* inet_addr(), and hostGetByName() expect "char *"; addr is a "const char *". */ | |
3759 iadd = inet_addr((char*)addr); | |
3760 #else | |
3761 #if defined(_AIX43) || ((defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R)) | |
3762 struct hostent_data ht_data; | |
3763 #endif | |
3764 #ifdef AS400 | |
3765 iadd = inet_addr((void*)addr); | |
3766 #else | |
3767 iadd = inet_addr(addr); | |
3768 #endif | |
3769 #endif | |
3770 if (iadd != -1) | |
3771 { memcpy(inaddr, &iadd, sizeof(iadd)); | |
3772 return SOAP_OK; | |
3773 } | |
3774 #if defined(__GLIBC__) || (defined(HAVE_GETHOSTBYNAME_R) && (defined(FREEBSD) || defined(__FreeBSD__))) || defined(__ANDROID__) | |
3775 if (gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &host, &soap->errnum) < 0) | |
3776 host = NULL; | |
3777 #elif defined(_AIX43) || ((defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R)) | |
3778 memset((void*)&ht_data, 0, sizeof(ht_data)); | |
3779 if (gethostbyname_r(addr, &hostent, &ht_data) < 0) | |
3780 { host = NULL; | |
3781 soap->errnum = h_errno; | |
3782 } | |
3783 #elif defined(HAVE_GETHOSTBYNAME_R) | |
3784 host = gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &soap->errnum); | |
3785 #elif defined(VXWORKS) | |
3786 /* If the DNS resolver library resolvLib has been configured in the vxWorks | |
3787 * image, a query for the host IP address is sent to the DNS server, if the | |
3788 * name was not found in the local host table. */ | |
3789 hostint = hostGetByName((char*)addr); | |
3790 if (hostint == ERROR) | |
3791 { host = NULL; | |
3792 soap->errnum = soap_errno; | |
3793 } | |
3794 #else | |
3795 #ifdef AS400 | |
3796 if (!(host = gethostbyname((void*)addr))) | |
3797 soap->errnum = h_errno; | |
3798 #else | |
3799 if (!(host = gethostbyname(addr))) | |
3800 soap->errnum = h_errno; | |
3801 #endif | |
3802 #endif | |
3803 if (!host) | |
3804 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Host name not found\n")); | |
3805 return SOAP_ERR; | |
3806 } | |
3807 #ifdef VXWORKS | |
3808 inaddr->s_addr = hostint; | |
3809 #else | |
3810 memcpy(inaddr, host->h_addr, host->h_length); | |
3811 #endif | |
3812 return SOAP_OK; | |
3813 } | |
3814 #endif | |
3815 #endif | |
3816 #endif | |
3817 | |
3818 /******************************************************************************/ | |
3819 #ifndef WITH_NOIO | |
3820 #ifndef PALM_1 | |
3821 static SOAP_SOCKET | |
3822 tcp_connect(struct soap *soap, const char *endpoint, const char *host, int port) | |
3823 { | |
3824 #ifdef WITH_IPV6 | |
3825 struct addrinfo hints, *res, *ressave; | |
3826 #endif | |
3827 SOAP_SOCKET sk; | |
3828 int err = 0; | |
3829 #ifndef WITH_LEAN | |
3830 #ifndef WIN32 | |
3831 int len = SOAP_BUFLEN; | |
3832 #else | |
3833 int len = SOAP_BUFLEN + 1; /* speeds up windows xfer */ | |
3834 #endif | |
3835 int set = 1; | |
3836 #endif | |
3837 #if !defined(WITH_LEAN) || defined(WITH_OPENSSL) || defined(WITH_GNUTLS) | |
3838 int retries; | |
3839 #endif | |
3840 if (soap_valid_socket(soap->socket)) | |
3841 soap->fclosesocket(soap, soap->socket); | |
3842 soap->socket = SOAP_INVALID_SOCKET; | |
3843 if (tcp_init(soap)) | |
3844 { soap->errnum = 0; | |
3845 soap_set_sender_error(soap, tcp_error(soap), "TCP init failed in tcp_connect()", SOAP_TCP_ERROR); | |
3846 return SOAP_INVALID_SOCKET; | |
3847 } | |
3848 soap->errmode = 0; | |
3849 #ifdef WITH_IPV6 | |
3850 memset((void*)&hints, 0, sizeof(hints)); | |
3851 hints.ai_family = PF_UNSPEC; | |
3852 #ifndef WITH_LEAN | |
3853 if ((soap->omode & SOAP_IO_UDP)) | |
3854 hints.ai_socktype = SOCK_DGRAM; | |
3855 else | |
3856 #endif | |
3857 hints.ai_socktype = SOCK_STREAM; | |
3858 soap->errmode = 2; | |
3859 if (soap->proxy_host) | |
3860 err = getaddrinfo(soap->proxy_host, soap_int2s(soap, soap->proxy_port), &hints, &res); | |
3861 else | |
3862 err = getaddrinfo(host, soap_int2s(soap, port), &hints, &res); | |
3863 if (err) | |
3864 { soap_set_sender_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in tcp_connect()", SOAP_TCP_ERROR); | |
3865 return SOAP_INVALID_SOCKET; | |
3866 } | |
3867 ressave = res; | |
3868 again: | |
3869 sk = socket(res->ai_family, res->ai_socktype, res->ai_protocol); | |
3870 soap->errmode = 0; | |
3871 #else | |
3872 #ifndef WITH_LEAN | |
3873 again: | |
3874 #endif | |
3875 #ifndef WITH_LEAN | |
3876 if ((soap->omode & SOAP_IO_UDP)) | |
3877 sk = socket(AF_INET, SOCK_DGRAM, 0); | |
3878 else | |
3879 #endif | |
3880 sk = socket(AF_INET, SOCK_STREAM, 0); | |
3881 #endif | |
3882 if (!soap_valid_socket(sk)) | |
3883 { | |
3884 #ifdef WITH_IPV6 | |
3885 if (res->ai_next) | |
3886 { res = res->ai_next; | |
3887 goto again; | |
3888 } | |
3889 #endif | |
3890 soap->errnum = soap_socket_errno(sk); | |
3891 soap_set_sender_error(soap, tcp_error(soap), "socket failed in tcp_connect()", SOAP_TCP_ERROR); | |
3892 #ifdef WITH_IPV6 | |
3893 freeaddrinfo(ressave); | |
3894 #endif | |
3895 return SOAP_INVALID_SOCKET; | |
3896 } | |
3897 #ifdef SOCKET_CLOSE_ON_EXEC | |
3898 #ifdef WIN32 | |
3899 #ifndef UNDER_CE | |
3900 SetHandleInformation((HANDLE)sk, HANDLE_FLAG_INHERIT, 0); | |
3901 #endif | |
3902 #else | |
3903 fcntl(sk, F_SETFD, 1); | |
3904 #endif | |
3905 #endif | |
3906 #ifndef WITH_LEAN | |
3907 if (soap->connect_flags == SO_LINGER) | |
3908 { struct linger linger; | |
3909 memset((void*)&linger, 0, sizeof(linger)); | |
3910 linger.l_onoff = 1; | |
3911 linger.l_linger = soap->linger_time; | |
3912 if (setsockopt(sk, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger))) | |
3913 { soap->errnum = soap_socket_errno(sk); | |
3914 soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in tcp_connect()", SOAP_TCP_ERROR); | |
3915 soap->fclosesocket(soap, sk); | |
3916 #ifdef WITH_IPV6 | |
3917 freeaddrinfo(ressave); | |
3918 #endif | |
3919 return SOAP_INVALID_SOCKET; | |
3920 } | |
3921 } | |
3922 else if (soap->connect_flags && setsockopt(sk, SOL_SOCKET, soap->connect_flags, (char*)&set, sizeof(int))) | |
3923 { soap->errnum = soap_socket_errno(sk); | |
3924 soap_set_sender_error(soap, tcp_error(soap), "setsockopt failed in tcp_connect()", SOAP_TCP_ERROR); | |
3925 soap->fclosesocket(soap, sk); | |
3926 #ifdef WITH_IPV6 | |
3927 freeaddrinfo(ressave); | |
3928 #endif | |
3929 return SOAP_INVALID_SOCKET; | |
3930 } | |
3931 if ((soap->keep_alive || soap->tcp_keep_alive) && setsockopt(sk, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) | |
3932 { soap->errnum = soap_socket_errno(sk); | |
3933 soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in tcp_connect()", SOAP_TCP_ERROR); | |
3934 soap->fclosesocket(soap, sk); | |
3935 #ifdef WITH_IPV6 | |
3936 freeaddrinfo(ressave); | |
3937 #endif | |
3938 return SOAP_INVALID_SOCKET; | |
3939 } | |
3940 if (setsockopt(sk, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) | |
3941 { soap->errnum = soap_socket_errno(sk); | |
3942 soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in tcp_connect()", SOAP_TCP_ERROR); | |
3943 soap->fclosesocket(soap, sk); | |
3944 #ifdef WITH_IPV6 | |
3945 freeaddrinfo(ressave); | |
3946 #endif | |
3947 return SOAP_INVALID_SOCKET; | |
3948 } | |
3949 if (setsockopt(sk, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) | |
3950 { soap->errnum = soap_socket_errno(sk); | |
3951 soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in tcp_connect()", SOAP_TCP_ERROR); | |
3952 soap->fclosesocket(soap, sk); | |
3953 #ifdef WITH_IPV6 | |
3954 freeaddrinfo(ressave); | |
3955 #endif | |
3956 return SOAP_INVALID_SOCKET; | |
3957 } | |
3958 #ifdef TCP_KEEPIDLE | |
3959 if (soap->tcp_keep_idle && setsockopt((SOAP_SOCKET)sk, IPPROTO_TCP, TCP_KEEPIDLE, (char*)&(soap->tcp_keep_idle), sizeof(int))) | |
3960 { soap->errnum = soap_socket_errno(sk); | |
3961 soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPIDLE failed in tcp_connect()", SOAP_TCP_ERROR); | |
3962 soap->fclosesocket(soap, (SOAP_SOCKET)sk); | |
3963 #ifdef WITH_IPV6 | |
3964 freeaddrinfo(ressave); | |
3965 #endif | |
3966 return SOAP_INVALID_SOCKET; | |
3967 } | |
3968 #endif | |
3969 #ifdef TCP_KEEPINTVL | |
3970 if (soap->tcp_keep_intvl && setsockopt((SOAP_SOCKET)sk, IPPROTO_TCP, TCP_KEEPINTVL, (char*)&(soap->tcp_keep_intvl), sizeof(int))) | |
3971 { soap->errnum = soap_socket_errno(sk); | |
3972 soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPINTVL failed in tcp_connect()", SOAP_TCP_ERROR); | |
3973 soap->fclosesocket(soap, (SOAP_SOCKET)sk); | |
3974 #ifdef WITH_IPV6 | |
3975 freeaddrinfo(ressave); | |
3976 #endif | |
3977 return SOAP_INVALID_SOCKET; | |
3978 } | |
3979 #endif | |
3980 #ifdef TCP_KEEPCNT | |
3981 if (soap->tcp_keep_cnt && setsockopt((SOAP_SOCKET)sk, IPPROTO_TCP, TCP_KEEPCNT, (char*)&(soap->tcp_keep_cnt), sizeof(int))) | |
3982 { soap->errnum = soap_socket_errno(sk); | |
3983 soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPCNT failed in tcp_connect()", SOAP_TCP_ERROR); | |
3984 soap->fclosesocket(soap, (SOAP_SOCKET)sk); | |
3985 #ifdef WITH_IPV6 | |
3986 freeaddrinfo(ressave); | |
3987 #endif | |
3988 return SOAP_INVALID_SOCKET; | |
3989 } | |
3990 #endif | |
3991 #ifdef TCP_NODELAY | |
3992 if (!(soap->omode & SOAP_IO_UDP) && setsockopt(sk, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) | |
3993 { soap->errnum = soap_socket_errno(sk); | |
3994 soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in tcp_connect()", SOAP_TCP_ERROR); | |
3995 soap->fclosesocket(soap, sk); | |
3996 #ifdef WITH_IPV6 | |
3997 freeaddrinfo(ressave); | |
3998 #endif | |
3999 return SOAP_INVALID_SOCKET; | |
4000 } | |
4001 #endif | |
4002 #ifdef WITH_IPV6 | |
4003 if ((soap->omode & SOAP_IO_UDP) && soap->ipv6_multicast_if) | |
4004 { struct sockaddr_in6 *in6addr = (struct sockaddr_in6*)res->ai_addr; | |
4005 in6addr->sin6_scope_id = soap->ipv6_multicast_if; | |
4006 } | |
4007 #endif | |
4008 #ifdef IP_MULTICAST_TTL | |
4009 if ((soap->omode & SOAP_IO_UDP)) | |
4010 { if (soap->ipv4_multicast_ttl) | |
4011 { unsigned char ttl = soap->ipv4_multicast_ttl; | |
4012 if (setsockopt(sk, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ttl, sizeof(ttl))) | |
4013 { soap->errnum = soap_socket_errno(sk); | |
4014 soap_set_sender_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_TTL failed in tcp_connect()", SOAP_TCP_ERROR); | |
4015 soap->fclosesocket(soap, sk); | |
4016 return SOAP_INVALID_SOCKET; | |
4017 } | |
4018 } | |
4019 if ((soap->omode & SOAP_IO_UDP) && soap->ipv4_multicast_if && !soap->ipv6_multicast_if) | |
4020 { if (setsockopt(sk, IPPROTO_IP, IP_MULTICAST_IF, (char*)soap->ipv4_multicast_if, sizeof(struct in_addr))) | |
4021 #ifndef WINDOWS | |
4022 { soap->errnum = soap_socket_errno(sk); | |
4023 soap_set_sender_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR); | |
4024 soap->fclosesocket(soap, sk); | |
4025 return SOAP_INVALID_SOCKET; | |
4026 } | |
4027 #else | |
4028 #ifndef IP_MULTICAST_IF | |
4029 #define IP_MULTICAST_IF 2 | |
4030 #endif | |
4031 if (setsockopt(sk, IPPROTO_IP, IP_MULTICAST_IF, (char*)soap->ipv4_multicast_if, sizeof(struct in_addr))) | |
4032 { soap->errnum = soap_socket_errno(sk); | |
4033 soap_set_sender_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR); | |
4034 soap->fclosesocket(soap, sk); | |
4035 return SOAP_INVALID_SOCKET; | |
4036 } | |
4037 #endif | |
4038 } | |
4039 } | |
4040 #endif | |
4041 #endif | |
4042 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Opening socket=%d to host='%s' port=%d\n", sk, host, port)); | |
4043 #ifndef WITH_IPV6 | |
4044 soap->peerlen = sizeof(soap->peer); | |
4045 memset((void*)&soap->peer, 0, sizeof(soap->peer)); | |
4046 soap->peer.sin_family = AF_INET; | |
4047 soap->errmode = 2; | |
4048 if (soap->proxy_host) | |
4049 { if (soap->fresolve(soap, soap->proxy_host, &soap->peer.sin_addr)) | |
4050 { soap_set_sender_error(soap, tcp_error(soap), "get proxy host by name failed in tcp_connect()", SOAP_TCP_ERROR); | |
4051 soap->fclosesocket(soap, sk); | |
4052 return SOAP_INVALID_SOCKET; | |
4053 } | |
4054 soap->peer.sin_port = htons((short)soap->proxy_port); | |
4055 } | |
4056 else | |
4057 { if (soap->fresolve(soap, host, &soap->peer.sin_addr)) | |
4058 { soap_set_sender_error(soap, tcp_error(soap), "get host by name failed in tcp_connect()", SOAP_TCP_ERROR); | |
4059 soap->fclosesocket(soap, sk); | |
4060 return SOAP_INVALID_SOCKET; | |
4061 } | |
4062 soap->peer.sin_port = htons((short)port); | |
4063 } | |
4064 soap->errmode = 0; | |
4065 #ifndef WITH_LEAN | |
4066 if ((soap->omode & SOAP_IO_UDP)) | |
4067 return sk; | |
4068 #endif | |
4069 #else | |
4070 if ((soap->omode & SOAP_IO_UDP)) | |
4071 { memcpy(&soap->peer, res->ai_addr, res->ai_addrlen); | |
4072 soap->peerlen = res->ai_addrlen; | |
4073 freeaddrinfo(ressave); | |
4074 return sk; | |
4075 } | |
4076 #endif | |
4077 #ifndef WITH_LEAN | |
4078 if (soap->connect_timeout) | |
4079 SOAP_SOCKNONBLOCK(sk) | |
4080 else | |
4081 SOAP_SOCKBLOCK(sk) | |
4082 retries = 10; | |
4083 #endif | |
4084 for (;;) | |
4085 { | |
4086 #ifdef WITH_IPV6 | |
4087 if (connect(sk, res->ai_addr, (int)res->ai_addrlen)) | |
4088 #else | |
4089 if (connect(sk, (struct sockaddr*)&soap->peer, sizeof(soap->peer))) | |
4090 #endif | |
4091 { err = soap_socket_errno(sk); | |
4092 #ifndef WITH_LEAN | |
4093 if (err == SOAP_EADDRINUSE) | |
4094 { soap->fclosesocket(soap, sk); | |
4095 if (retries-- > 0) | |
4096 goto again; | |
4097 } | |
4098 else if (soap->connect_timeout && (err == SOAP_EINPROGRESS || err == SOAP_EAGAIN || err == SOAP_EWOULDBLOCK)) | |
4099 { | |
4100 SOAP_SOCKLEN_T k; | |
4101 for (;;) | |
4102 { register int r; | |
4103 r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND, soap->connect_timeout); | |
4104 if (r > 0) | |
4105 break; | |
4106 if (!r) | |
4107 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n")); | |
4108 soap_set_sender_error(soap, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR); | |
4109 soap->fclosesocket(soap, sk); | |
4110 #ifdef WITH_IPV6 | |
4111 freeaddrinfo(ressave); | |
4112 #endif | |
4113 return SOAP_INVALID_SOCKET; | |
4114 } | |
4115 r = soap->errnum = soap_socket_errno(sk); | |
4116 if (r != SOAP_EINTR) | |
4117 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); | |
4118 soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR); | |
4119 soap->fclosesocket(soap, sk); | |
4120 #ifdef WITH_IPV6 | |
4121 freeaddrinfo(ressave); | |
4122 #endif | |
4123 return SOAP_INVALID_SOCKET; | |
4124 } | |
4125 } | |
4126 k = (SOAP_SOCKLEN_T)sizeof(soap->errnum); | |
4127 if (!getsockopt(sk, SOL_SOCKET, SO_ERROR, (char*)&soap->errnum, &k) && !soap->errnum) /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */ | |
4128 break; | |
4129 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); | |
4130 if (!soap->errnum) | |
4131 soap->errnum = soap_socket_errno(sk); | |
4132 soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR); | |
4133 soap->fclosesocket(soap, sk); | |
4134 #ifdef WITH_IPV6 | |
4135 freeaddrinfo(ressave); | |
4136 #endif | |
4137 return SOAP_INVALID_SOCKET; | |
4138 } | |
4139 #endif | |
4140 #ifdef WITH_IPV6 | |
4141 if (res->ai_next) | |
4142 { res = res->ai_next; | |
4143 soap->fclosesocket(soap, sk); | |
4144 goto again; | |
4145 } | |
4146 #endif | |
4147 if (err && err != SOAP_EINTR) | |
4148 { soap->errnum = err; | |
4149 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); | |
4150 soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR); | |
4151 soap->fclosesocket(soap, sk); | |
4152 #ifdef WITH_IPV6 | |
4153 freeaddrinfo(ressave); | |
4154 #endif | |
4155 return SOAP_INVALID_SOCKET; | |
4156 } | |
4157 } | |
4158 else | |
4159 break; | |
4160 } | |
4161 #ifdef WITH_IPV6 | |
4162 soap->peerlen = 0; /* IPv6: already connected so use send() */ | |
4163 freeaddrinfo(ressave); | |
4164 #endif | |
4165 soap->socket = sk; | |
4166 soap->imode &= ~SOAP_ENC_SSL; | |
4167 soap->omode &= ~SOAP_ENC_SSL; | |
4168 if (!soap_tag_cmp(endpoint, "https:*")) | |
4169 { | |
4170 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) | |
4171 #ifdef WITH_OPENSSL | |
4172 BIO *bio; | |
4173 #endif | |
4174 int r; | |
4175 if (soap->proxy_host) | |
4176 { soap_mode m = soap->mode; /* preserve settings */ | |
4177 soap_mode om = soap->omode; /* make sure we only parse HTTP */ | |
4178 size_t n = soap->count; /* save the content length */ | |
4179 const char *userid, *passwd; | |
4180 int status = soap->status; /* save the current status/command */ | |
4181 short keep_alive = soap->keep_alive; /* save the KA status */ | |
4182 soap->omode &= ~SOAP_ENC; /* mask IO and ENC */ | |
4183 soap->omode |= SOAP_IO_BUFFER; | |
4184 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connecting to %s proxy server %s for destination endpoint %s\n", soap->proxy_http_version, soap->proxy_host, endpoint)); | |
4185 #ifdef WITH_NTLM | |
4186 if (soap->ntlm_challenge) | |
4187 { if (soap_ntlm_handshake(soap, SOAP_CONNECT, endpoint, host, port)) | |
4188 return soap->error; | |
4189 } | |
4190 #endif | |
4191 if (soap_begin_send(soap)) | |
4192 { soap->fclosesocket(soap, sk); | |
4193 return SOAP_INVALID_SOCKET; | |
4194 } | |
4195 soap->status = SOAP_CONNECT; | |
4196 soap->keep_alive = 1; | |
4197 if ((soap->error = soap->fpost(soap, endpoint, host, port, NULL, NULL, 0)) | |
4198 || soap_end_send_flush(soap)) | |
4199 { soap->fclosesocket(soap, sk); | |
4200 return SOAP_INVALID_SOCKET; | |
4201 } | |
4202 soap->keep_alive = keep_alive; | |
4203 soap->omode = om; | |
4204 om = soap->imode; | |
4205 soap->imode &= ~SOAP_ENC; /* mask IO and ENC */ | |
4206 userid = soap->userid; /* preserve */ | |
4207 passwd = soap->passwd; /* preserve */ | |
4208 if ((soap->error = soap->fparse(soap))) | |
4209 { soap->fclosesocket(soap, sk); | |
4210 return SOAP_INVALID_SOCKET; | |
4211 } | |
4212 soap->status = status; /* restore */ | |
4213 soap->userid = userid; /* restore */ | |
4214 soap->passwd = passwd; /* restore */ | |
4215 soap->imode = om; /* restore */ | |
4216 soap->count = n; /* restore */ | |
4217 if (soap_begin_send(soap)) | |
4218 { soap->fclosesocket(soap, sk); | |
4219 return SOAP_INVALID_SOCKET; | |
4220 } | |
4221 if (endpoint) | |
4222 { strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint)); /* restore */ | |
4223 soap->endpoint[sizeof(soap->endpoint) - 1] = '\0'; | |
4224 } | |
4225 soap->mode = m; | |
4226 } | |
4227 #ifdef WITH_OPENSSL | |
4228 soap->ssl_flags |= SOAP_SSL_CLIENT; | |
4229 if (!soap->ctx && (soap->error = soap->fsslauth(soap))) | |
4230 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL required, but no ctx set\n")); | |
4231 soap->fclosesocket(soap, sk); | |
4232 soap->error = SOAP_SSL_ERROR; | |
4233 return SOAP_INVALID_SOCKET; | |
4234 } | |
4235 if (!soap->ssl) | |
4236 { soap->ssl = SSL_new(soap->ctx); | |
4237 if (!soap->ssl) | |
4238 { soap->fclosesocket(soap, sk); | |
4239 soap->error = SOAP_SSL_ERROR; | |
4240 return SOAP_INVALID_SOCKET; | |
4241 } | |
4242 } | |
4243 else | |
4244 SSL_clear(soap->ssl); | |
4245 if (soap->session) | |
4246 { if (!strcmp(soap->session_host, host) && soap->session_port == port) | |
4247 SSL_set_session(soap->ssl, soap->session); | |
4248 SSL_SESSION_free(soap->session); | |
4249 soap->session = NULL; | |
4250 } | |
4251 soap->imode |= SOAP_ENC_SSL; | |
4252 soap->omode |= SOAP_ENC_SSL; | |
4253 bio = BIO_new_socket((int)sk, BIO_NOCLOSE); | |
4254 SSL_set_bio(soap->ssl, bio, bio); | |
4255 /* Connect timeout: set SSL sockets to non-blocking */ | |
4256 retries = 0; | |
4257 if (soap->connect_timeout) | |
4258 { SOAP_SOCKNONBLOCK(sk) | |
4259 retries = 10*soap->connect_timeout; | |
4260 } | |
4261 else | |
4262 SOAP_SOCKBLOCK(sk) | |
4263 if (retries <= 0) | |
4264 retries = 100; /* timeout: 10 sec retries, 100 times 0.1 sec */ | |
4265 /* Try connecting until success or timeout (when nonblocking) */ | |
4266 do | |
4267 { if ((r = SSL_connect(soap->ssl)) <= 0) | |
4268 { int err = SSL_get_error(soap->ssl, r); | |
4269 if (err == SSL_ERROR_WANT_CONNECT || err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) | |
4270 { register int s; | |
4271 if (err == SSL_ERROR_WANT_READ) | |
4272 s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000); | |
4273 else | |
4274 s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000); | |
4275 if (s < 0) | |
4276 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL_connect/select error in tcp_connect\n")); | |
4277 soap_set_sender_error(soap, soap_ssl_error(soap, r), "SSL_connect failed in tcp_connect()", SOAP_TCP_ERROR); | |
4278 soap->fclosesocket(soap, sk); | |
4279 return SOAP_INVALID_SOCKET; | |
4280 } | |
4281 if (s == 0 && retries-- <= 0) | |
4282 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL/TLS connect timeout\n")); | |
4283 soap_set_sender_error(soap, "Timeout", "SSL_connect failed in tcp_connect()", SOAP_TCP_ERROR); | |
4284 soap->fclosesocket(soap, sk); | |
4285 return SOAP_INVALID_SOCKET; | |
4286 } | |
4287 } | |
4288 else | |
4289 { soap_set_sender_error(soap, soap_ssl_error(soap, r), "SSL_connect error in tcp_connect()", SOAP_SSL_ERROR); | |
4290 soap->fclosesocket(soap, sk); | |
4291 return SOAP_INVALID_SOCKET; | |
4292 } | |
4293 } | |
4294 } while (!SSL_is_init_finished(soap->ssl)); | |
4295 /* Set SSL sockets to nonblocking */ | |
4296 SOAP_SOCKNONBLOCK(sk) | |
4297 /* Check server credentials when required */ | |
4298 if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION)) | |
4299 { int err; | |
4300 if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK) | |
4301 { soap_set_sender_error(soap, X509_verify_cert_error_string(err), "SSL/TLS certificate presented by peer cannot be verified in tcp_connect()", SOAP_SSL_ERROR); | |
4302 soap->fclosesocket(soap, sk); | |
4303 return SOAP_INVALID_SOCKET; | |
4304 } | |
4305 if (!(soap->ssl_flags & SOAP_SSL_SKIP_HOST_CHECK)) | |
4306 { X509_NAME *subj; | |
4307 STACK_OF(CONF_VALUE) *val = NULL; | |
4308 #if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) | |
4309 GENERAL_NAMES *names = NULL; | |
4310 #else | |
4311 int ext_count; | |
4312 #endif | |
4313 int ok = 0; | |
4314 X509 *peer = SSL_get_peer_certificate(soap->ssl); | |
4315 if (!peer) | |
4316 { soap_set_sender_error(soap, "SSL/TLS error", "No SSL/TLS certificate was presented by the peer in tcp_connect()", SOAP_SSL_ERROR); | |
4317 soap->fclosesocket(soap, sk); | |
4318 return SOAP_INVALID_SOCKET; | |
4319 } | |
4320 #if (OPENSSL_VERSION_NUMBER < 0x0090800fL) | |
4321 ext_count = X509_get_ext_count(peer); | |
4322 if (ext_count > 0) | |
4323 { int i; | |
4324 for (i = 0; i < ext_count; i++) | |
4325 { X509_EXTENSION *ext = X509_get_ext(peer, i); | |
4326 const char *ext_str = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext))); | |
4327 if (ext_str && !strcmp(ext_str, "subjectAltName")) | |
4328 { X509V3_EXT_METHOD *meth = (X509V3_EXT_METHOD*)X509V3_EXT_get(ext); | |
4329 unsigned char *data; | |
4330 if (!meth) | |
4331 break; | |
4332 data = ext->value->data; | |
4333 if (data) | |
4334 { | |
4335 #if (OPENSSL_VERSION_NUMBER > 0x00907000L) | |
4336 void *ext_data; | |
4337 if (meth->it) | |
4338 ext_data = ASN1_item_d2i(NULL, &data, ext->value->length, ASN1_ITEM_ptr(meth->it)); | |
4339 else | |
4340 { /* OpenSSL is not portable at this point (?): | |
4341 Some compilers appear to prefer | |
4342 meth->d2i(NULL, (const unsigned char**)&data, ... | |
4343 and others prefer | |
4344 meth->d2i(NULL, &data, ext->value->length); | |
4345 */ | |
4346 ext_data = meth->d2i(NULL, &data, ext->value->length); | |
4347 } | |
4348 if (ext_data) | |
4349 val = meth->i2v(meth, ext_data, NULL); | |
4350 else | |
4351 val = NULL; | |
4352 if (meth->it) | |
4353 ASN1_item_free((ASN1_VALUE*)ext_data, ASN1_ITEM_ptr(meth->it)); | |
4354 else | |
4355 meth->ext_free(ext_data); | |
4356 #else | |
4357 void *ext_data = meth->d2i(NULL, &data, ext->value->length); | |
4358 if (ext_data) | |
4359 val = meth->i2v(meth, ext_data, NULL); | |
4360 meth->ext_free(ext_data); | |
4361 #endif | |
4362 if (val) | |
4363 { int j; | |
4364 for (j = 0; j < sk_CONF_VALUE_num(val); j++) | |
4365 { CONF_VALUE *nval = sk_CONF_VALUE_value(val, j); | |
4366 if (nval && !strcmp(nval->name, "DNS") && !strcmp(nval->value, host)) | |
4367 { ok = 1; | |
4368 break; | |
4369 } | |
4370 } | |
4371 sk_CONF_VALUE_pop_free(val, X509V3_conf_free); | |
4372 } | |
4373 } | |
4374 } | |
4375 if (ok) | |
4376 break; | |
4377 } | |
4378 } | |
4379 #else | |
4380 names = (GENERAL_NAMES*)X509_get_ext_d2i(peer, NID_subject_alt_name, NULL, NULL); | |
4381 if (names) | |
4382 { val = i2v_GENERAL_NAMES(NULL, names, val); | |
4383 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free); | |
4384 } | |
4385 if (val) | |
4386 { int j; | |
4387 for (j = 0; j < sk_CONF_VALUE_num(val); j++) | |
4388 { CONF_VALUE *nval = sk_CONF_VALUE_value(val, j); | |
4389 if (nval && !strcmp(nval->name, "DNS") && !strcmp(nval->value, host)) | |
4390 { ok = 1; | |
4391 break; | |
4392 } | |
4393 } | |
4394 sk_CONF_VALUE_pop_free(val, X509V3_conf_free); | |
4395 } | |
4396 #endif | |
4397 if (!ok && (subj = X509_get_subject_name(peer))) | |
4398 { int i = -1; | |
4399 do | |
4400 { ASN1_STRING *name; | |
4401 i = X509_NAME_get_index_by_NID(subj, NID_commonName, i); | |
4402 if (i == -1) | |
4403 break; | |
4404 name = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subj, i)); | |
4405 if (name) | |
4406 { if (!soap_tag_cmp(host, (const char*)M_ASN1_STRING_data(name))) | |
4407 ok = 1; | |
4408 else | |
4409 { unsigned char *tmp = NULL; | |
4410 ASN1_STRING_to_UTF8(&tmp, name); | |
4411 if (tmp) | |
4412 { if (!soap_tag_cmp(host, (const char*)tmp)) | |
4413 ok = 1; | |
4414 else if (tmp[0] == '*') /* wildcard domain */ | |
4415 { const char *t = strchr(host, '.'); | |
4416 if (t && !soap_tag_cmp(t, (const char*)tmp+1)) | |
4417 ok = 1; | |
4418 } | |
4419 OPENSSL_free(tmp); | |
4420 } | |
4421 } | |
4422 } | |
4423 } while (!ok); | |
4424 } | |
4425 X509_free(peer); | |
4426 if (!ok) | |
4427 { soap_set_sender_error(soap, "SSL/TLS error", "SSL/TLS certificate host name mismatch in tcp_connect()", SOAP_SSL_ERROR); | |
4428 soap->fclosesocket(soap, sk); | |
4429 return SOAP_INVALID_SOCKET; | |
4430 } | |
4431 } | |
4432 } | |
4433 #endif | |
4434 #ifdef WITH_GNUTLS | |
4435 soap->ssl_flags |= SOAP_SSL_CLIENT; | |
4436 if (!soap->session && (soap->error = soap->fsslauth(soap))) | |
4437 { soap->fclosesocket(soap, sk); | |
4438 return SOAP_INVALID_SOCKET; | |
4439 } | |
4440 gnutls_transport_set_ptr(soap->session, (gnutls_transport_ptr_t)(long)sk); | |
4441 /* Set SSL sockets to non-blocking */ | |
4442 if (soap->connect_timeout) | |
4443 { SOAP_SOCKNONBLOCK(sk) | |
4444 retries = 10*soap->connect_timeout; | |
4445 } | |
4446 else | |
4447 SOAP_SOCKBLOCK(sk) | |
4448 if (retries <= 0) | |
4449 retries = 100; /* timeout: 10 sec retries, 100 times 0.1 sec */ | |
4450 while ((r = gnutls_handshake(soap->session))) | |
4451 { int s; | |
4452 /* GNUTLS repeat handhake when GNUTLS_E_AGAIN */ | |
4453 if (retries-- <= 0) | |
4454 break; | |
4455 if (r == GNUTLS_E_AGAIN || r == GNUTLS_E_INTERRUPTED) | |
4456 { if (!gnutls_record_get_direction(soap->session)) | |
4457 s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000); | |
4458 else | |
4459 s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000); | |
4460 if (s < 0) | |
4461 break; | |
4462 } | |
4463 else | |
4464 { soap->errnum = soap_socket_errno(sk); | |
4465 break; | |
4466 } | |
4467 } | |
4468 if (r) | |
4469 { soap_set_sender_error(soap, soap_ssl_error(soap, r), "SSL/TLS handshake failed", SOAP_SSL_ERROR); | |
4470 soap->fclosesocket(soap, sk); | |
4471 return SOAP_INVALID_SOCKET; | |
4472 } | |
4473 if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION)) | |
4474 { const char *err = ssl_verify(soap, host); | |
4475 if (err) | |
4476 { soap->fclosesocket(soap, sk); | |
4477 soap->error = soap_set_sender_error(soap, "SSL/TLS error", err, SOAP_SSL_ERROR); | |
4478 return SOAP_INVALID_SOCKET; | |
4479 } | |
4480 } | |
4481 #endif | |
4482 #else | |
4483 soap->fclosesocket(soap, sk); | |
4484 soap->error = SOAP_SSL_ERROR; | |
4485 return SOAP_INVALID_SOCKET; | |
4486 #endif | |
4487 } | |
4488 if (soap->recv_timeout || soap->send_timeout) | |
4489 SOAP_SOCKNONBLOCK(sk) | |
4490 else | |
4491 SOAP_SOCKBLOCK(sk) | |
4492 return sk; | |
4493 } | |
4494 #endif | |
4495 #endif | |
4496 | |
4497 /******************************************************************************/ | |
4498 #ifndef WITH_NOIO | |
4499 #ifndef PALM_1 | |
4500 static int | |
4501 tcp_select(struct soap *soap, SOAP_SOCKET sk, int flags, int timeout) | |
4502 { int r; | |
4503 struct timeval tv; | |
4504 fd_set fd[3], *rfd, *sfd, *efd; | |
4505 int retries = 0; | |
4506 int eintr = SOAP_MAXEINTR; | |
4507 soap->errnum = 0; | |
4508 #ifndef WIN32 | |
4509 #if !defined(FD_SETSIZE) || defined(__QNX__) || defined(QNX) | |
4510 /* no FD_SETSIZE or select() is not MT safe on some QNX: always poll */ | |
4511 if (1) | |
4512 #else | |
4513 /* if fd max set size exceeded, use poll() */ | |
4514 if ((int)sk >= (int)FD_SETSIZE) | |
4515 #endif | |
4516 #ifdef HAVE_POLL | |
4517 { struct pollfd pollfd; | |
4518 pollfd.fd = (int)sk; | |
4519 pollfd.events = 0; | |
4520 if (flags & SOAP_TCP_SELECT_RCV) | |
4521 pollfd.events |= POLLIN; | |
4522 if (flags & SOAP_TCP_SELECT_SND) | |
4523 pollfd.events |= POLLOUT; | |
4524 if (flags & SOAP_TCP_SELECT_ERR) | |
4525 pollfd.events |= POLLERR; | |
4526 if (timeout <= 0) | |
4527 timeout /= -1000; /* -usec -> ms */ | |
4528 else | |
4529 { retries = timeout - 1; | |
4530 timeout = 1000; | |
4531 } | |
4532 do | |
4533 { r = poll(&pollfd, 1, timeout); | |
4534 if (r < 0 && (soap->errnum = soap_socket_errno(sk)) == SOAP_EINTR && eintr--) | |
4535 continue; | |
4536 } while (r == 0 && retries--); | |
4537 if (r > 0) | |
4538 { r = 0; | |
4539 if ((flags & SOAP_TCP_SELECT_RCV) && (pollfd.revents & POLLIN)) | |
4540 r |= SOAP_TCP_SELECT_RCV; | |
4541 if ((flags & SOAP_TCP_SELECT_SND) && (pollfd.revents & POLLOUT)) | |
4542 r |= SOAP_TCP_SELECT_SND; | |
4543 if ((flags & SOAP_TCP_SELECT_ERR) && (pollfd.revents & POLLERR)) | |
4544 r |= SOAP_TCP_SELECT_ERR; | |
4545 } | |
4546 return r; | |
4547 } | |
4548 #else | |
4549 { soap->error = SOAP_FD_EXCEEDED; | |
4550 return -1; | |
4551 } | |
4552 #endif | |
4553 #endif | |
4554 if (timeout > 0) | |
4555 retries = timeout - 1; | |
4556 do | |
4557 { rfd = sfd = efd = NULL; | |
4558 if (flags & SOAP_TCP_SELECT_RCV) | |
4559 { rfd = &fd[0]; | |
4560 FD_ZERO(rfd); | |
4561 FD_SET(sk, rfd); | |
4562 } | |
4563 if (flags & SOAP_TCP_SELECT_SND) | |
4564 { sfd = &fd[1]; | |
4565 FD_ZERO(sfd); | |
4566 FD_SET(sk, sfd); | |
4567 } | |
4568 if (flags & SOAP_TCP_SELECT_ERR) | |
4569 { efd = &fd[2]; | |
4570 FD_ZERO(efd); | |
4571 FD_SET(sk, efd); | |
4572 } | |
4573 if (timeout <= 0) | |
4574 { tv.tv_sec = -timeout / 1000000; | |
4575 tv.tv_usec = -timeout % 1000000; | |
4576 } | |
4577 else | |
4578 { tv.tv_sec = 1; | |
4579 tv.tv_usec = 0; | |
4580 } | |
4581 r = select((int)sk + 1, rfd, sfd, efd, &tv); | |
4582 if (r < 0 && (soap->errnum = soap_socket_errno(sk)) == SOAP_EINTR && eintr--) | |
4583 continue; | |
4584 } while (r == 0 && retries--); | |
4585 if (r > 0) | |
4586 { r = 0; | |
4587 if ((flags & SOAP_TCP_SELECT_RCV) && FD_ISSET(sk, rfd)) | |
4588 r |= SOAP_TCP_SELECT_RCV; | |
4589 if ((flags & SOAP_TCP_SELECT_SND) && FD_ISSET(sk, sfd)) | |
4590 r |= SOAP_TCP_SELECT_SND; | |
4591 if ((flags & SOAP_TCP_SELECT_ERR) && FD_ISSET(sk, efd)) | |
4592 r |= SOAP_TCP_SELECT_ERR; | |
4593 } | |
4594 return r; | |
4595 } | |
4596 #endif | |
4597 #endif | |
4598 | |
4599 /******************************************************************************/ | |
4600 #ifndef WITH_NOIO | |
4601 #ifndef PALM_1 | |
4602 static SOAP_SOCKET | |
4603 tcp_accept(struct soap *soap, SOAP_SOCKET s, struct sockaddr *a, int *n) | |
4604 { SOAP_SOCKET sk; | |
4605 (void)soap; | |
4606 sk = accept(s, a, (SOAP_SOCKLEN_T*)n); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */ | |
4607 #ifdef SOCKET_CLOSE_ON_EXEC | |
4608 #ifdef WIN32 | |
4609 #ifndef UNDER_CE | |
4610 SetHandleInformation((HANDLE)sk, HANDLE_FLAG_INHERIT, 0); | |
4611 #endif | |
4612 #else | |
4613 fcntl(sk, F_SETFD, FD_CLOEXEC); | |
4614 #endif | |
4615 #endif | |
4616 return sk; | |
4617 } | |
4618 #endif | |
4619 #endif | |
4620 | |
4621 /******************************************************************************/ | |
4622 #ifndef WITH_NOIO | |
4623 #ifndef PALM_1 | |
4624 static int | |
4625 tcp_disconnect(struct soap *soap) | |
4626 { | |
4627 #ifdef WITH_OPENSSL | |
4628 if (soap->ssl) | |
4629 { int r, s = 0; | |
4630 if (soap->session) | |
4631 { SSL_SESSION_free(soap->session); | |
4632 soap->session = NULL; | |
4633 } | |
4634 if (*soap->host) | |
4635 { soap->session = SSL_get1_session(soap->ssl); | |
4636 if (soap->session) | |
4637 { strcpy(soap->session_host, soap->host); | |
4638 soap->session_port = soap->port; | |
4639 } | |
4640 } | |
4641 r = SSL_shutdown(soap->ssl); | |
4642 /* SSL shutdown does not work when reads are pending, non-blocking */ | |
4643 if (r == 0) | |
4644 { while (SSL_want_read(soap->ssl)) | |
4645 { if (SSL_read(soap->ssl, NULL, 0) | |
4646 || soap_socket_errno(soap->socket) != SOAP_EAGAIN) | |
4647 { r = SSL_shutdown(soap->ssl); | |
4648 break; | |
4649 } | |
4650 } | |
4651 } | |
4652 if (r == 0) | |
4653 { if (soap_valid_socket(soap->socket)) | |
4654 { if (!soap->fshutdownsocket(soap, soap->socket, SOAP_SHUT_WR)) | |
4655 { | |
4656 #if !defined(WITH_LEAN) && !defined(WIN32) | |
4657 /* | |
4658 wait up to 5 seconds for close_notify to be sent by peer (if peer not | |
4659 present, this avoids calling SSL_shutdown() which has a lengthy return | |
4660 timeout) | |
4661 */ | |
4662 r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, 5); | |
4663 if (r <= 0) | |
4664 { soap->errnum = 0; | |
4665 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connection lost...\n")); | |
4666 soap->fclosesocket(soap, soap->socket); | |
4667 soap->socket = SOAP_INVALID_SOCKET; | |
4668 ERR_remove_state(0); | |
4669 SSL_free(soap->ssl); | |
4670 soap->ssl = NULL; | |
4671 return SOAP_OK; | |
4672 } | |
4673 #else | |
4674 r = SSL_shutdown(soap->ssl); | |
4675 #endif | |
4676 } | |
4677 } | |
4678 } | |
4679 if (r != 1) | |
4680 { s = ERR_get_error(); | |
4681 if (s) | |
4682 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown failed: %d\n", SSL_get_error(soap->ssl, r))); | |
4683 if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP)) | |
4684 { soap->fclosesocket(soap, soap->socket); | |
4685 soap->socket = SOAP_INVALID_SOCKET; | |
4686 } | |
4687 } | |
4688 } | |
4689 SSL_free(soap->ssl); | |
4690 soap->ssl = NULL; | |
4691 if (s) | |
4692 return SOAP_SSL_ERROR; | |
4693 ERR_remove_state(0); | |
4694 } | |
4695 #endif | |
4696 #ifdef WITH_GNUTLS | |
4697 if (soap->session) | |
4698 { gnutls_bye(soap->session, GNUTLS_SHUT_RDWR); | |
4699 gnutls_deinit(soap->session); | |
4700 soap->session = NULL; | |
4701 } | |
4702 #endif | |
4703 if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP)) | |
4704 { soap->fshutdownsocket(soap, soap->socket, SOAP_SHUT_RDWR); | |
4705 soap->fclosesocket(soap, soap->socket); | |
4706 soap->socket = SOAP_INVALID_SOCKET; | |
4707 } | |
4708 return SOAP_OK; | |
4709 } | |
4710 #endif | |
4711 #endif | |
4712 | |
4713 /******************************************************************************/ | |
4714 #ifndef WITH_NOIO | |
4715 #ifndef PALM_1 | |
4716 static int | |
4717 tcp_closesocket(struct soap *soap, SOAP_SOCKET sk) | |
4718 { (void)soap; | |
4719 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Close socket=%d\n", (int)sk)); | |
4720 return soap_closesocket(sk); | |
4721 } | |
4722 #endif | |
4723 #endif | |
4724 | |
4725 /******************************************************************************/ | |
4726 #ifndef WITH_NOIO | |
4727 #ifndef PALM_1 | |
4728 static int | |
4729 tcp_shutdownsocket(struct soap *soap, SOAP_SOCKET sk, int how) | |
4730 { (void)soap; | |
4731 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown socket=%d how=%d\n", (int)sk, how)); | |
4732 return shutdown(sk, how); | |
4733 } | |
4734 #endif | |
4735 #endif | |
4736 | |
4737 /******************************************************************************/ | |
4738 #ifndef WITH_NOIO | |
4739 #ifndef PALM_1 | |
4740 SOAP_FMAC1 | |
4741 SOAP_SOCKET | |
4742 SOAP_FMAC2 | |
4743 soap_bind(struct soap *soap, const char *host, int port, int backlog) | |
4744 { | |
4745 #ifdef WITH_IPV6 | |
4746 struct addrinfo *addrinfo = NULL; | |
4747 struct addrinfo hints; | |
4748 struct addrinfo res; | |
4749 int err; | |
4750 #ifdef WITH_NO_IPV6_V6ONLY | |
4751 int unset = 0; | |
4752 #endif | |
4753 #endif | |
4754 #ifndef WITH_LEAN | |
4755 #ifndef WIN32 | |
4756 int len = SOAP_BUFLEN; | |
4757 #else | |
4758 int len = SOAP_BUFLEN + 1; /* speeds up windows xfer */ | |
4759 #endif | |
4760 int set = 1; | |
4761 #endif | |
4762 if (soap_valid_socket(soap->master)) | |
4763 { soap->fclosesocket(soap, soap->master); | |
4764 soap->master = SOAP_INVALID_SOCKET; | |
4765 } | |
4766 soap->socket = SOAP_INVALID_SOCKET; | |
4767 soap->errmode = 1; | |
4768 if (tcp_init(soap)) | |
4769 { soap_set_receiver_error(soap, tcp_error(soap), "TCP init failed in soap_bind()", SOAP_TCP_ERROR); | |
4770 return SOAP_INVALID_SOCKET; | |
4771 } | |
4772 #ifdef WITH_IPV6 | |
4773 memset((void*)&hints, 0, sizeof(hints)); | |
4774 hints.ai_family = PF_UNSPEC; | |
4775 #ifndef WITH_LEAN | |
4776 if ((soap->omode & SOAP_IO_UDP)) | |
4777 hints.ai_socktype = SOCK_DGRAM; | |
4778 else | |
4779 #endif | |
4780 hints.ai_socktype = SOCK_STREAM; | |
4781 hints.ai_flags = AI_PASSIVE; | |
4782 soap->errmode = 2; | |
4783 err = getaddrinfo(host, soap_int2s(soap, port), &hints, &addrinfo); | |
4784 if (err || !addrinfo) | |
4785 { soap_set_receiver_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in soap_bind()", SOAP_TCP_ERROR); | |
4786 return SOAP_INVALID_SOCKET; | |
4787 } | |
4788 res = *addrinfo; | |
4789 memcpy(&soap->peer, addrinfo->ai_addr, addrinfo->ai_addrlen); | |
4790 soap->peerlen = addrinfo->ai_addrlen; | |
4791 res.ai_addr = (struct sockaddr*)&soap->peer; | |
4792 res.ai_addrlen = soap->peerlen; | |
4793 freeaddrinfo(addrinfo); | |
4794 soap->master = (int)socket(res.ai_family, res.ai_socktype, res.ai_protocol); | |
4795 #else | |
4796 #ifndef WITH_LEAN | |
4797 if ((soap->omode & SOAP_IO_UDP)) | |
4798 soap->master = (int)socket(AF_INET, SOCK_DGRAM, 0); | |
4799 else | |
4800 #endif | |
4801 soap->master = (int)socket(AF_INET, SOCK_STREAM, 0); | |
4802 #endif | |
4803 soap->errmode = 0; | |
4804 if (!soap_valid_socket(soap->master)) | |
4805 { soap->errnum = soap_socket_errno(soap->master); | |
4806 soap_set_receiver_error(soap, tcp_error(soap), "socket failed in soap_bind()", SOAP_TCP_ERROR); | |
4807 return SOAP_INVALID_SOCKET; | |
4808 } | |
4809 soap->port = port; | |
4810 #ifndef WITH_LEAN | |
4811 if ((soap->omode & SOAP_IO_UDP)) | |
4812 soap->socket = soap->master; | |
4813 #endif | |
4814 #ifdef SOCKET_CLOSE_ON_EXEC | |
4815 #ifdef WIN32 | |
4816 #ifndef UNDER_CE | |
4817 SetHandleInformation((HANDLE)soap->master, HANDLE_FLAG_INHERIT, 0); | |
4818 #endif | |
4819 #else | |
4820 fcntl(soap->master, F_SETFD, 1); | |
4821 #endif | |
4822 #endif | |
4823 #ifndef WITH_LEAN | |
4824 if (soap->bind_flags && setsockopt(soap->master, SOL_SOCKET, soap->bind_flags, (char*)&set, sizeof(int))) | |
4825 { soap->errnum = soap_socket_errno(soap->master); | |
4826 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_bind()", SOAP_TCP_ERROR); | |
4827 return SOAP_INVALID_SOCKET; | |
4828 } | |
4829 if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && (!((soap->imode | soap->omode) & SOAP_IO_UDP)) && setsockopt(soap->master, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) | |
4830 { soap->errnum = soap_socket_errno(soap->master); | |
4831 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_bind()", SOAP_TCP_ERROR); | |
4832 return SOAP_INVALID_SOCKET; | |
4833 } | |
4834 if (setsockopt(soap->master, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) | |
4835 { soap->errnum = soap_socket_errno(soap->master); | |
4836 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_bind()", SOAP_TCP_ERROR); | |
4837 return SOAP_INVALID_SOCKET; | |
4838 } | |
4839 if (setsockopt(soap->master, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) | |
4840 { soap->errnum = soap_socket_errno(soap->master); | |
4841 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_bind()", SOAP_TCP_ERROR); | |
4842 return SOAP_INVALID_SOCKET; | |
4843 } | |
4844 #ifdef TCP_NODELAY | |
4845 if (!(soap->omode & SOAP_IO_UDP) && setsockopt(soap->master, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) | |
4846 { soap->errnum = soap_socket_errno(soap->master); | |
4847 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_bind()", SOAP_TCP_ERROR); | |
4848 return SOAP_INVALID_SOCKET; | |
4849 } | |
4850 #endif | |
4851 #endif | |
4852 #ifdef WITH_IPV6 | |
4853 #ifdef WITH_IPV6_V6ONLY | |
4854 if (setsockopt(soap->master, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&set, sizeof(int))) | |
4855 { soap->errnum = soap_socket_errno(soap->master); | |
4856 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt set IPV6_V6ONLY failed in soap_bind()", SOAP_TCP_ERROR); | |
4857 return SOAP_INVALID_SOCKET; | |
4858 } | |
4859 #endif | |
4860 #ifdef WITH_NO_IPV6_V6ONLY | |
4861 if (setsockopt(soap->master, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&unset, sizeof(int))) | |
4862 { soap->errnum = soap_socket_errno(soap->master); | |
4863 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt unset IPV6_V6ONLY failed in soap_bind()", SOAP_TCP_ERROR); | |
4864 return SOAP_INVALID_SOCKET; | |
4865 } | |
4866 #endif | |
4867 soap->errmode = 0; | |
4868 if (bind(soap->master, res.ai_addr, (int)res.ai_addrlen)) | |
4869 { soap->errnum = soap_socket_errno(soap->master); | |
4870 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n")); | |
4871 soap_closesock(soap); | |
4872 soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR); | |
4873 return SOAP_INVALID_SOCKET; | |
4874 } | |
4875 #else | |
4876 soap->peerlen = sizeof(soap->peer); | |
4877 memset((void*)&soap->peer, 0, sizeof(soap->peer)); | |
4878 soap->peer.sin_family = AF_INET; | |
4879 soap->errmode = 2; | |
4880 if (host) | |
4881 { if (soap->fresolve(soap, host, &soap->peer.sin_addr)) | |
4882 { soap_set_receiver_error(soap, tcp_error(soap), "get host by name failed in soap_bind()", SOAP_TCP_ERROR); | |
4883 return SOAP_INVALID_SOCKET; | |
4884 } | |
4885 } | |
4886 else | |
4887 soap->peer.sin_addr.s_addr = htonl(INADDR_ANY); | |
4888 soap->peer.sin_port = htons((short)port); | |
4889 soap->errmode = 0; | |
4890 if (bind(soap->master, (struct sockaddr*)&soap->peer, (int)soap->peerlen)) | |
4891 { soap->errnum = soap_socket_errno(soap->master); | |
4892 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n")); | |
4893 soap_closesock(soap); | |
4894 soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR); | |
4895 return SOAP_INVALID_SOCKET; | |
4896 } | |
4897 #endif | |
4898 if (!(soap->omode & SOAP_IO_UDP) && listen(soap->master, backlog)) | |
4899 { soap->errnum = soap_socket_errno(soap->master); | |
4900 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n")); | |
4901 soap_closesock(soap); | |
4902 soap_set_receiver_error(soap, tcp_error(soap), "listen failed in soap_bind()", SOAP_TCP_ERROR); | |
4903 return SOAP_INVALID_SOCKET; | |
4904 } | |
4905 return soap->master; | |
4906 } | |
4907 #endif | |
4908 #endif | |
4909 | |
4910 /******************************************************************************/ | |
4911 #ifndef WITH_NOIO | |
4912 #ifndef PALM_1 | |
4913 SOAP_FMAC1 | |
4914 int | |
4915 SOAP_FMAC2 | |
4916 soap_poll(struct soap *soap) | |
4917 { | |
4918 #ifndef WITH_LEAN | |
4919 register int r; | |
4920 if (soap_valid_socket(soap->socket)) | |
4921 { r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_ALL, 0); | |
4922 if (r > 0 && (r & SOAP_TCP_SELECT_ERR)) | |
4923 r = -1; | |
4924 } | |
4925 else if (soap_valid_socket(soap->master)) | |
4926 r = tcp_select(soap, soap->master, SOAP_TCP_SELECT_SND, 0); | |
4927 else | |
4928 return SOAP_OK; /* OK when no socket! */ | |
4929 if (r > 0) | |
4930 { | |
4931 #ifdef WITH_OPENSSL | |
4932 if (soap->imode & SOAP_ENC_SSL) | |
4933 { | |
4934 if (soap_valid_socket(soap->socket) | |
4935 && (r & SOAP_TCP_SELECT_SND) | |
4936 && (!(r & SOAP_TCP_SELECT_RCV) | |
4937 || SSL_peek(soap->ssl, soap->tmpbuf, 1) > 0)) | |
4938 return SOAP_OK; | |
4939 } | |
4940 else | |
4941 #endif | |
4942 { int t; | |
4943 if (soap_valid_socket(soap->socket) | |
4944 && (r & SOAP_TCP_SELECT_SND) | |
4945 && (!(r & SOAP_TCP_SELECT_RCV) | |
4946 || recv(soap->socket, (char*)&t, 1, MSG_PEEK) > 0)) | |
4947 return SOAP_OK; | |
4948 } | |
4949 } | |
4950 else if (r < 0) | |
4951 { if ((soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) && soap_socket_errno(soap->master) != SOAP_EINTR) | |
4952 { soap_set_receiver_error(soap, tcp_error(soap), "select failed in soap_poll()", SOAP_TCP_ERROR); | |
4953 return soap->error = SOAP_TCP_ERROR; | |
4954 } | |
4955 } | |
4956 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Polling: other end down on socket=%d select=%d\n", soap->socket, r)); | |
4957 return SOAP_EOF; | |
4958 #else | |
4959 return SOAP_OK; | |
4960 #endif | |
4961 } | |
4962 #endif | |
4963 #endif | |
4964 | |
4965 /******************************************************************************/ | |
4966 #ifndef WITH_NOIO | |
4967 #ifndef PALM_1 | |
4968 SOAP_FMAC1 | |
4969 SOAP_SOCKET | |
4970 SOAP_FMAC2 | |
4971 soap_accept(struct soap *soap) | |
4972 { int n = (int)sizeof(soap->peer); | |
4973 register int err; | |
4974 #ifndef WITH_LEAN | |
4975 #ifndef WIN32 | |
4976 int len = SOAP_BUFLEN; | |
4977 #else | |
4978 int len = SOAP_BUFLEN + 1; /* speeds up windows xfer */ | |
4979 #endif | |
4980 int set = 1; | |
4981 #endif | |
4982 soap->error = SOAP_OK; | |
4983 memset((void*)&soap->peer, 0, sizeof(soap->peer)); | |
4984 soap->socket = SOAP_INVALID_SOCKET; | |
4985 soap->errmode = 0; | |
4986 soap->keep_alive = 0; | |
4987 if (!soap_valid_socket(soap->master)) | |
4988 { soap->errnum = 0; | |
4989 soap_set_receiver_error(soap, tcp_error(soap), "no master socket in soap_accept()", SOAP_TCP_ERROR); | |
4990 return SOAP_INVALID_SOCKET; | |
4991 } | |
4992 #ifndef WITH_LEAN | |
4993 if ((soap->omode & SOAP_IO_UDP)) | |
4994 return soap->socket = soap->master; | |
4995 #endif | |
4996 for (;;) | |
4997 { if (soap->accept_timeout || soap->send_timeout || soap->recv_timeout) | |
4998 { for (;;) | |
4999 { register int r; | |
5000 r = tcp_select(soap, soap->master, SOAP_TCP_SELECT_ALL, soap->accept_timeout ? soap->accept_timeout : 60); | |
5001 if (r > 0) | |
5002 break; | |
5003 if (!r && soap->accept_timeout) | |
5004 { soap_set_receiver_error(soap, "Timeout", "accept failed in soap_accept()", SOAP_TCP_ERROR); | |
5005 return SOAP_INVALID_SOCKET; | |
5006 } | |
5007 if (r < 0) | |
5008 { r = soap->errnum; | |
5009 if (r != SOAP_EINTR) | |
5010 { soap_closesock(soap); | |
5011 soap_set_sender_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR); | |
5012 return SOAP_INVALID_SOCKET; | |
5013 } | |
5014 } | |
5015 } | |
5016 } | |
5017 if (soap->accept_timeout) | |
5018 SOAP_SOCKNONBLOCK(soap->master) | |
5019 else | |
5020 SOAP_SOCKBLOCK(soap->master) | |
5021 soap->socket = soap->faccept(soap, soap->master, (struct sockaddr*)&soap->peer, &n); | |
5022 soap->peerlen = (size_t)n; | |
5023 if (soap_valid_socket(soap->socket)) | |
5024 { | |
5025 #ifdef WITH_IPV6 | |
5026 unsigned int ip1, ip2, ip3, ip4; | |
5027 char port[16]; | |
5028 getnameinfo((struct sockaddr*)&soap->peer, n, soap->host, sizeof(soap->host), port, 16, NI_NUMERICHOST | NI_NUMERICSERV); | |
5029 sscanf(soap->host, "%u.%u.%u.%u", &ip1, &ip2, &ip3, &ip4); | |
5030 soap->ip = (unsigned long)ip1 << 24 | (unsigned long)ip2 << 16 | (unsigned long)ip3 << 8 | (unsigned long)ip4; | |
5031 soap->port = soap_strtol(port, NULL, 10); | |
5032 #else | |
5033 soap->ip = ntohl(soap->peer.sin_addr.s_addr); | |
5034 #ifdef HAVE_SNPRINTF | |
5035 soap_snprintf(soap->host, sizeof(soap->host), "%u.%u.%u.%u", (int)(soap->ip>>24)&0xFF, (int)(soap->ip>>16)&0xFF, (int)(soap->ip>>8)&0xFF, (int)soap->ip&0xFF); | |
5036 #else | |
5037 sprintf(soap->host, "%u.%u.%u.%u", (int)(soap->ip>>24)&0xFF, (int)(soap->ip>>16)&0xFF, (int)(soap->ip>>8)&0xFF, (int)soap->ip&0xFF); | |
5038 #endif | |
5039 soap->port = (int)ntohs(soap->peer.sin_port); /* does not return port number on some systems */ | |
5040 #endif | |
5041 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket=%d at port=%d from IP='%s'\n", soap->socket, soap->port, soap->host)); | |
5042 #ifndef WITH_LEAN | |
5043 if (soap->accept_flags == SO_LINGER) | |
5044 { struct linger linger; | |
5045 memset((void*)&linger, 0, sizeof(linger)); | |
5046 linger.l_onoff = 1; | |
5047 linger.l_linger = soap->linger_time; | |
5048 if (setsockopt(soap->socket, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger))) | |
5049 { soap->errnum = soap_socket_errno(soap->socket); | |
5050 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in soap_accept()", SOAP_TCP_ERROR); | |
5051 soap_closesock(soap); | |
5052 return SOAP_INVALID_SOCKET; | |
5053 } | |
5054 } | |
5055 else if (soap->accept_flags && setsockopt(soap->socket, SOL_SOCKET, soap->accept_flags, (char*)&set, sizeof(int))) | |
5056 { soap->errnum = soap_socket_errno(soap->socket); | |
5057 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_accept()", SOAP_TCP_ERROR); | |
5058 soap_closesock(soap); | |
5059 return SOAP_INVALID_SOCKET; | |
5060 } | |
5061 if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt(soap->socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) | |
5062 { soap->errnum = soap_socket_errno(soap->socket); | |
5063 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_accept()", SOAP_TCP_ERROR); | |
5064 soap_closesock(soap); | |
5065 return SOAP_INVALID_SOCKET; | |
5066 } | |
5067 if (setsockopt(soap->socket, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) | |
5068 { soap->errnum = soap_socket_errno(soap->socket); | |
5069 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_accept()", SOAP_TCP_ERROR); | |
5070 soap_closesock(soap); | |
5071 return SOAP_INVALID_SOCKET; | |
5072 } | |
5073 if (setsockopt(soap->socket, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) | |
5074 { soap->errnum = soap_socket_errno(soap->socket); | |
5075 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_accept()", SOAP_TCP_ERROR); | |
5076 soap_closesock(soap); | |
5077 return SOAP_INVALID_SOCKET; | |
5078 } | |
5079 #ifdef TCP_NODELAY | |
5080 if (setsockopt(soap->socket, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) | |
5081 { soap->errnum = soap_socket_errno(soap->socket); | |
5082 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_accept()", SOAP_TCP_ERROR); | |
5083 soap_closesock(soap); | |
5084 return SOAP_INVALID_SOCKET; | |
5085 } | |
5086 #endif | |
5087 #endif | |
5088 soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0); | |
5089 if (soap->send_timeout || soap->recv_timeout) | |
5090 SOAP_SOCKNONBLOCK(soap->socket) | |
5091 else | |
5092 SOAP_SOCKBLOCK(soap->socket) | |
5093 return soap->socket; | |
5094 } | |
5095 err = soap_socket_errno(soap->socket); | |
5096 if (err != 0 && err != SOAP_EINTR && err != SOAP_EAGAIN && err != SOAP_EWOULDBLOCK) | |
5097 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept failed from %s\n", soap->host)); | |
5098 soap->errnum = err; | |
5099 soap_set_receiver_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR); | |
5100 soap_closesock(soap); | |
5101 return SOAP_INVALID_SOCKET; | |
5102 } | |
5103 } | |
5104 } | |
5105 #endif | |
5106 #endif | |
5107 | |
5108 /******************************************************************************/ | |
5109 #ifndef PALM_1 | |
5110 SOAP_FMAC1 | |
5111 int | |
5112 SOAP_FMAC2 | |
5113 soap_closesock(struct soap *soap) | |
5114 { register int status = soap->error; | |
5115 #ifndef WITH_LEANER | |
5116 if (status) /* close on error: attachment state is not to be trusted */ | |
5117 { soap->mime.first = NULL; | |
5118 soap->mime.last = NULL; | |
5119 soap->dime.first = NULL; | |
5120 soap->dime.last = NULL; | |
5121 } | |
5122 #endif | |
5123 if (soap->fdisconnect && (soap->error = soap->fdisconnect(soap))) | |
5124 return soap->error; | |
5125 if (status == SOAP_EOF || status == SOAP_TCP_ERROR || status == SOAP_SSL_ERROR || !soap->keep_alive) | |
5126 { if (soap->fclose && (soap->error = soap->fclose(soap))) | |
5127 return soap->error; | |
5128 soap->keep_alive = 0; | |
5129 } | |
5130 #ifdef WITH_ZLIB | |
5131 if (!(soap->mode & SOAP_MIME_POSTCHECK)) | |
5132 { if (soap->zlib_state == SOAP_ZLIB_DEFLATE) | |
5133 deflateEnd(soap->d_stream); | |
5134 else if (soap->zlib_state == SOAP_ZLIB_INFLATE) | |
5135 inflateEnd(soap->d_stream); | |
5136 soap->zlib_state = SOAP_ZLIB_NONE; | |
5137 } | |
5138 #endif | |
5139 return soap->error = status; | |
5140 } | |
5141 #endif | |
5142 | |
5143 /******************************************************************************/ | |
5144 #ifndef WITH_NOIO | |
5145 #ifndef PALM_1 | |
5146 SOAP_FMAC1 | |
5147 int | |
5148 SOAP_FMAC2 | |
5149 soap_force_closesock(struct soap *soap) | |
5150 { soap->keep_alive = 0; | |
5151 if (soap_valid_socket(soap->socket)) | |
5152 return soap_closesocket(soap->socket); | |
5153 return SOAP_OK; | |
5154 } | |
5155 #endif | |
5156 #endif | |
5157 | |
5158 /******************************************************************************/ | |
5159 #ifndef WITH_NOIO | |
5160 #ifndef PALM_2 | |
5161 SOAP_FMAC1 | |
5162 void | |
5163 SOAP_FMAC2 | |
5164 soap_cleanup(struct soap *soap) | |
5165 { soap_done(soap); | |
5166 #ifdef WIN32 | |
5167 if (!tcp_done) | |
5168 return; | |
5169 tcp_done = 0; | |
5170 WSACleanup(); | |
5171 #endif | |
5172 } | |
5173 #endif | |
5174 #endif | |
5175 | |
5176 /******************************************************************************/ | |
5177 #ifndef PALM_1 | |
5178 SOAP_FMAC1 | |
5179 void | |
5180 SOAP_FMAC2 | |
5181 soap_done(struct soap *soap) | |
5182 { | |
5183 #ifdef SOAP_DEBUG | |
5184 int i; | |
5185 #endif | |
5186 if (soap_check_state(soap)) | |
5187 return; | |
5188 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Done with context%s\n", soap->state == SOAP_COPY ? " copy" : "")); | |
5189 soap_free_temp(soap); | |
5190 while (soap->clist) | |
5191 { struct soap_clist *p = soap->clist->next; | |
5192 SOAP_FREE(soap, soap->clist); | |
5193 soap->clist = p; | |
5194 } | |
5195 if (soap->state == SOAP_INIT) | |
5196 soap->omode &= ~SOAP_IO_UDP; /* to force close the socket */ | |
5197 soap->keep_alive = 0; /* to force close the socket */ | |
5198 if (soap->master == soap->socket) /* do not close twice */ | |
5199 soap->master = SOAP_INVALID_SOCKET; | |
5200 soap_closesock(soap); | |
5201 #ifdef WITH_COOKIES | |
5202 soap_free_cookies(soap); | |
5203 #endif | |
5204 while (soap->plugins) | |
5205 { register struct soap_plugin *p = soap->plugins->next; | |
5206 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Removing plugin '%s'\n", soap->plugins->id)); | |
5207 if (soap->plugins->fcopy || soap->state == SOAP_INIT) | |
5208 soap->plugins->fdelete(soap, soap->plugins); | |
5209 SOAP_FREE(soap, soap->plugins); | |
5210 soap->plugins = p; | |
5211 } | |
5212 soap->fplugin = fplugin; | |
5213 soap->fmalloc = NULL; | |
5214 #ifndef WITH_NOHTTP | |
5215 soap->fpost = http_post; | |
5216 soap->fget = http_get; | |
5217 soap->fput = http_405; | |
5218 soap->fdel = http_405; | |
5219 soap->fopt = http_200; | |
5220 soap->fhead = http_200; | |
5221 soap->fform = NULL; | |
5222 soap->fposthdr = http_post_header; | |
5223 soap->fresponse = http_response; | |
5224 soap->fparse = http_parse; | |
5225 soap->fparsehdr = http_parse_header; | |
5226 #endif | |
5227 soap->fheader = NULL; | |
5228 #ifndef WITH_NOIO | |
5229 #ifndef WITH_IPV6 | |
5230 soap->fresolve = tcp_gethost; | |
5231 #else | |
5232 soap->fresolve = NULL; | |
5233 #endif | |
5234 soap->faccept = tcp_accept; | |
5235 soap->fopen = tcp_connect; | |
5236 soap->fclose = tcp_disconnect; | |
5237 soap->fclosesocket = tcp_closesocket; | |
5238 soap->fshutdownsocket = tcp_shutdownsocket; | |
5239 soap->fsend = fsend; | |
5240 soap->frecv = frecv; | |
5241 soap->fpoll = soap_poll; | |
5242 #else | |
5243 soap->fopen = NULL; | |
5244 soap->fclose = NULL; | |
5245 soap->fpoll = NULL; | |
5246 #endif | |
5247 #ifndef WITH_LEANER | |
5248 soap->feltbegin = NULL; | |
5249 soap->feltendin = NULL; | |
5250 soap->feltbegout = NULL; | |
5251 soap->feltendout = NULL; | |
5252 soap->fprepareinitsend = NULL; | |
5253 soap->fprepareinitrecv = NULL; | |
5254 soap->fpreparesend = NULL; | |
5255 soap->fpreparerecv = NULL; | |
5256 soap->fpreparefinalsend = NULL; | |
5257 soap->fpreparefinalrecv = NULL; | |
5258 soap->ffiltersend = NULL; | |
5259 soap->ffilterrecv = NULL; | |
5260 #endif | |
5261 soap->fseterror = NULL; | |
5262 soap->fignore = NULL; | |
5263 soap->fserveloop = NULL; | |
5264 #ifdef WITH_OPENSSL | |
5265 if (soap->session) | |
5266 { SSL_SESSION_free(soap->session); | |
5267 soap->session = NULL; | |
5268 } | |
5269 #endif | |
5270 if (soap->state == SOAP_INIT) | |
5271 { if (soap_valid_socket(soap->master)) | |
5272 { soap->fclosesocket(soap, soap->master); | |
5273 soap->master = SOAP_INVALID_SOCKET; | |
5274 } | |
5275 } | |
5276 #ifdef WITH_OPENSSL | |
5277 if (soap->ssl) | |
5278 { SSL_free(soap->ssl); | |
5279 soap->ssl = NULL; | |
5280 } | |
5281 if (soap->state == SOAP_INIT) | |
5282 { if (soap->ctx) | |
5283 { SSL_CTX_free(soap->ctx); | |
5284 soap->ctx = NULL; | |
5285 } | |
5286 } | |
5287 ERR_remove_state(0); | |
5288 #endif | |
5289 #ifdef WITH_GNUTLS | |
5290 if (soap->state == SOAP_INIT) | |
5291 { if (soap->xcred) | |
5292 { gnutls_certificate_free_credentials(soap->xcred); | |
5293 soap->xcred = NULL; | |
5294 } | |
5295 if (soap->acred) | |
5296 { gnutls_anon_free_client_credentials(soap->acred); | |
5297 soap->acred = NULL; | |
5298 } | |
5299 if (soap->cache) | |
5300 { gnutls_priority_deinit(soap->cache); | |
5301 soap->cache = NULL; | |
5302 } | |
5303 if (soap->dh_params) | |
5304 { gnutls_dh_params_deinit(soap->dh_params); | |
5305 soap->dh_params = NULL; | |
5306 } | |
5307 if (soap->rsa_params) | |
5308 { gnutls_rsa_params_deinit(soap->rsa_params); | |
5309 soap->rsa_params = NULL; | |
5310 } | |
5311 } | |
5312 if (soap->session) | |
5313 { gnutls_deinit(soap->session); | |
5314 soap->session = NULL; | |
5315 } | |
5316 #endif | |
5317 #ifdef WITH_C_LOCALE | |
5318 # ifdef WIN32 | |
5319 _free_locale(soap->c_locale); | |
5320 # else | |
5321 freelocale(soap->c_locale); | |
5322 # endif | |
5323 #endif | |
5324 #ifdef WITH_ZLIB | |
5325 if (soap->d_stream) | |
5326 { SOAP_FREE(soap, (void*)soap->d_stream); | |
5327 soap->d_stream = NULL; | |
5328 } | |
5329 if (soap->z_buf) | |
5330 { SOAP_FREE(soap, (void*)soap->z_buf); | |
5331 soap->z_buf = NULL; | |
5332 } | |
5333 #endif | |
5334 #ifdef SOAP_DEBUG | |
5335 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free logfiles\n")); | |
5336 for (i = 0; i < SOAP_MAXLOGS; i++) | |
5337 { if (soap->logfile[i]) | |
5338 { SOAP_FREE(soap, (void*)soap->logfile[i]); | |
5339 soap->logfile[i] = NULL; | |
5340 } | |
5341 soap_close_logfile(soap, i); | |
5342 } | |
5343 soap->state = SOAP_NONE; | |
5344 #endif | |
5345 #ifdef SOAP_MEM_DEBUG | |
5346 soap_free_mht(soap); | |
5347 #endif | |
5348 } | |
5349 #endif | |
5350 | |
5351 /******************************************************************************\ | |
5352 * | |
5353 * HTTP | |
5354 * | |
5355 \******************************************************************************/ | |
5356 | |
5357 /******************************************************************************/ | |
5358 #ifndef WITH_NOHTTP | |
5359 #ifndef PALM_1 | |
5360 static int | |
5361 http_parse(struct soap *soap) | |
5362 { char header[SOAP_HDRLEN], *s; | |
5363 unsigned short httpcmd = 0; | |
5364 int status = 0; | |
5365 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Waiting for HTTP request/response...\n")); | |
5366 *soap->endpoint = '\0'; | |
5367 #ifdef WITH_NTLM | |
5368 if (!soap->ntlm_challenge) | |
5369 #endif | |
5370 { soap->userid = NULL; | |
5371 soap->passwd = NULL; | |
5372 soap->authrealm = NULL; | |
5373 } | |
5374 #ifdef WITH_NTLM | |
5375 soap->ntlm_challenge = NULL; | |
5376 #endif | |
5377 soap->proxy_from = NULL; | |
5378 do | |
5379 { soap->length = 0; | |
5380 soap->http_content = NULL; | |
5381 soap->action = NULL; | |
5382 soap->status = 0; | |
5383 soap->body = 1; | |
5384 if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) | |
5385 { if (soap->error == SOAP_EOF) | |
5386 return SOAP_EOF; | |
5387 return soap->error = 414; | |
5388 } | |
5389 if ((s = strchr(soap->msgbuf, ' '))) | |
5390 { soap->status = (unsigned short)soap_strtoul(s, &s, 10); | |
5391 if (!soap_blank((soap_wchar)*s)) | |
5392 soap->status = 0; | |
5393 } | |
5394 else | |
5395 soap->status = 0; | |
5396 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP status: %s\n", soap->msgbuf)); | |
5397 for (;;) | |
5398 { if (soap_getline(soap, header, SOAP_HDRLEN)) | |
5399 { if (soap->error == SOAP_EOF) | |
5400 { soap->error = SOAP_OK; | |
5401 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "EOF in HTTP header, continue anyway\n")); | |
5402 break; | |
5403 } | |
5404 return soap->error; | |
5405 } | |
5406 if (!*header) | |
5407 break; | |
5408 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP header: %s\n", header)); | |
5409 s = strchr(header, ':'); | |
5410 if (s) | |
5411 { char *t; | |
5412 *s = '\0'; | |
5413 do s++; | |
5414 while (*s && *s <= 32); | |
5415 if (*s == '"') | |
5416 s++; | |
5417 t = s + strlen(s) - 1; | |
5418 while (t > s && *t <= 32) | |
5419 t--; | |
5420 if (t >= s && *t == '"') | |
5421 t--; | |
5422 t[1] = '\0'; | |
5423 if ((soap->error = soap->fparsehdr(soap, header, s))) | |
5424 { if (soap->error < SOAP_STOP) | |
5425 return soap->error; | |
5426 status = soap->error; | |
5427 soap->error = SOAP_OK; | |
5428 } | |
5429 } | |
5430 } | |
5431 } while (soap->status == 100); | |
5432 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Finished HTTP header parsing, status = %d\n", soap->status)); | |
5433 s = strstr(soap->msgbuf, "HTTP/"); | |
5434 if (s && s[7] != '1') | |
5435 { if (soap->keep_alive == 1) | |
5436 soap->keep_alive = 0; | |
5437 if (soap->status == 0 && (soap->omode & SOAP_IO) == SOAP_IO_CHUNK) /* soap->status == 0 for HTTP request */ | |
5438 soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE; /* HTTP 1.0 does not support chunked transfers */ | |
5439 } | |
5440 if (soap->keep_alive < 0) | |
5441 soap->keep_alive = 1; | |
5442 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Keep alive connection = %d\n", soap->keep_alive)); | |
5443 if (soap->status == 0) | |
5444 { size_t l = 0; | |
5445 if (s) | |
5446 { if (!strncmp(soap->msgbuf, "POST ", l = 5)) | |
5447 httpcmd = 1; | |
5448 else if (!strncmp(soap->msgbuf, "PUT ", l = 4)) | |
5449 httpcmd = 2; | |
5450 else if (!strncmp(soap->msgbuf, "GET ", l = 4)) | |
5451 httpcmd = 3; | |
5452 else if (!strncmp(soap->msgbuf, "DELETE ", l = 7)) | |
5453 httpcmd = 4; | |
5454 else if (!strncmp(soap->msgbuf, "OPTIONS ", l = 8)) | |
5455 httpcmd = 5; | |
5456 else if (!strncmp(soap->msgbuf, "HEAD ", l = 5)) | |
5457 httpcmd = 6; | |
5458 } | |
5459 if (s && httpcmd) | |
5460 { size_t m = strlen(soap->endpoint); | |
5461 size_t n = m + (s - soap->msgbuf) - l - 1; | |
5462 size_t k; | |
5463 if (n >= sizeof(soap->endpoint)) | |
5464 n = sizeof(soap->endpoint) - 1; | |
5465 if (m > n) | |
5466 m = n; | |
5467 k = n - m + 1; | |
5468 if (k > sizeof(soap->path)) | |
5469 k = sizeof(soap->path); | |
5470 strncpy(soap->path, soap->msgbuf + l, k); | |
5471 soap->path[k - 1] = '\0'; | |
5472 if (*soap->path && *soap->path != '/') | |
5473 *soap->endpoint = '\0'; | |
5474 strcat(soap->endpoint, soap->path); | |
5475 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Target endpoint='%s'\n", soap->endpoint)); | |
5476 if (httpcmd > 1) | |
5477 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP %s handler\n", soap->msgbuf)); | |
5478 switch (httpcmd) | |
5479 { case 2: soap->error = soap->fput(soap); break; | |
5480 case 3: soap->error = soap->fget(soap); break; | |
5481 case 4: soap->error = soap->fdel(soap); break; | |
5482 case 5: soap->error = soap->fopt(soap); break; | |
5483 case 6: soap->error = soap->fhead(soap); break; | |
5484 default: soap->error = 405; break; | |
5485 } | |
5486 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP handler return = %d\n", soap->error)); | |
5487 if (soap->error == SOAP_OK) | |
5488 soap->error = SOAP_STOP; /* prevents further processing */ | |
5489 return soap->error; | |
5490 } | |
5491 if (status) | |
5492 return soap->error = status; | |
5493 } | |
5494 else if (status) | |
5495 return soap->error = status; | |
5496 else if (s) | |
5497 return soap->error = 405; | |
5498 return SOAP_OK; | |
5499 } | |
5500 #if 0 | |
5501 if (soap->length > 0 || (soap->http_content && (!soap->keep_alive || soap->recv_timeout)) || (soap->imode & SOAP_IO) == SOAP_IO_CHUNK) | |
5502 #endif | |
5503 if (soap->body) | |
5504 { if ((soap->status >= 200 && soap->status <= 299) /* OK, Accepted, etc */ | |
5505 || soap->status == 400 /* Bad Request */ | |
5506 || soap->status == 500) /* Internal Server Error */ | |
5507 return SOAP_OK; | |
5508 /* force close afterwards in soap_closesock() */ | |
5509 soap->keep_alive = 0; | |
5510 #ifndef WITH_LEAN | |
5511 /* read HTTP body for error details */ | |
5512 s = soap_get_http_body(soap, NULL); | |
5513 if (s) | |
5514 return soap_set_receiver_error(soap, soap->msgbuf, s, soap->status); | |
5515 #endif | |
5516 } | |
5517 else if (soap->status >= 200 && soap->status <= 299) | |
5518 return soap->error = soap->status; | |
5519 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP error %d\n", soap->status)); | |
5520 return soap_set_receiver_error(soap, "HTTP Error", soap->msgbuf, soap->status); | |
5521 } | |
5522 #endif | |
5523 #endif | |
5524 | |
5525 /******************************************************************************/ | |
5526 #ifndef WITH_NOHTTP | |
5527 #ifndef PALM_1 | |
5528 static int | |
5529 http_parse_header(struct soap *soap, const char *key, const char *val) | |
5530 { if (!soap_tag_cmp(key, "Host")) | |
5531 { | |
5532 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) | |
5533 if (soap->imode & SOAP_ENC_SSL) | |
5534 strcpy(soap->endpoint, "https://"); | |
5535 else | |
5536 #endif | |
5537 strcpy(soap->endpoint, "http://"); | |
5538 strncat(soap->endpoint, val, sizeof(soap->endpoint) - 8); | |
5539 } | |
5540 #ifndef WITH_LEANER | |
5541 else if (!soap_tag_cmp(key, "Content-Type")) | |
5542 { const char *action; | |
5543 soap->http_content = soap_strdup(soap, val); | |
5544 if (soap_get_header_attribute(soap, val, "application/dime")) | |
5545 soap->imode |= SOAP_ENC_DIME; | |
5546 else if (soap_get_header_attribute(soap, val, "multipart/related") | |
5547 || soap_get_header_attribute(soap, val, "multipart/form-data")) | |
5548 { soap->mime.boundary = soap_strdup(soap, soap_get_header_attribute(soap, val, "boundary")); | |
5549 soap->mime.start = soap_strdup(soap, soap_get_header_attribute(soap, val, "start")); | |
5550 soap->imode |= SOAP_ENC_MIME; | |
5551 } | |
5552 action = soap_get_header_attribute(soap, val, "action"); | |
5553 if (action) | |
5554 { if (*action == '"') | |
5555 { soap->action = soap_strdup(soap, action + 1); | |
5556 if (*soap->action) | |
5557 soap->action[strlen(soap->action) - 1] = '\0'; | |
5558 } | |
5559 else | |
5560 soap->action = soap_strdup(soap, action); | |
5561 } | |
5562 } | |
5563 #endif | |
5564 else if (!soap_tag_cmp(key, "Content-Length")) | |
5565 { soap->length = soap_strtoul(val, NULL, 10); | |
5566 if (!soap->length) | |
5567 soap->body = 0; | |
5568 } | |
5569 else if (!soap_tag_cmp(key, "Content-Encoding")) | |
5570 { if (!soap_tag_cmp(val, "deflate")) | |
5571 #ifdef WITH_ZLIB | |
5572 soap->zlib_in = SOAP_ZLIB_DEFLATE; | |
5573 #else | |
5574 return SOAP_ZLIB_ERROR; | |
5575 #endif | |
5576 else if (!soap_tag_cmp(val, "gzip")) | |
5577 #ifdef WITH_GZIP | |
5578 soap->zlib_in = SOAP_ZLIB_GZIP; | |
5579 #else | |
5580 return SOAP_ZLIB_ERROR; | |
5581 #endif | |
5582 } | |
5583 #ifdef WITH_ZLIB | |
5584 else if (!soap_tag_cmp(key, "Accept-Encoding")) | |
5585 { | |
5586 #ifdef WITH_GZIP | |
5587 if (strchr(val, '*') || soap_get_header_attribute(soap, val, "gzip")) | |
5588 soap->zlib_out = SOAP_ZLIB_GZIP; | |
5589 else | |
5590 #endif | |
5591 if (strchr(val, '*') || soap_get_header_attribute(soap, val, "deflate")) | |
5592 soap->zlib_out = SOAP_ZLIB_DEFLATE; | |
5593 else | |
5594 soap->zlib_out = SOAP_ZLIB_NONE; | |
5595 } | |
5596 #endif | |
5597 else if (!soap_tag_cmp(key, "Transfer-Encoding")) | |
5598 { soap->imode &= ~SOAP_IO; | |
5599 if (!soap_tag_cmp(val, "chunked")) | |
5600 soap->imode |= SOAP_IO_CHUNK; | |
5601 } | |
5602 else if (!soap_tag_cmp(key, "Connection")) | |
5603 { if (!soap_tag_cmp(val, "keep-alive")) | |
5604 soap->keep_alive = -soap->keep_alive; | |
5605 else if (!soap_tag_cmp(val, "close")) | |
5606 soap->keep_alive = 0; | |
5607 } | |
5608 #ifndef WITH_LEAN | |
5609 else if (!soap_tag_cmp(key, "Authorization") || !soap_tag_cmp(key, "Proxy-Authorization")) | |
5610 { | |
5611 #ifdef WITH_NTLM | |
5612 if (!soap_tag_cmp(val, "NTLM*")) | |
5613 soap->ntlm_challenge = soap_strdup(soap, val + 4); | |
5614 else | |
5615 #endif | |
5616 if (!soap_tag_cmp(val, "Basic *")) | |
5617 { int n; | |
5618 char *s; | |
5619 soap_base642s(soap, val + 6, soap->tmpbuf, sizeof(soap->tmpbuf) - 1, &n); | |
5620 soap->tmpbuf[n] = '\0'; | |
5621 if ((s = strchr(soap->tmpbuf, ':'))) | |
5622 { *s = '\0'; | |
5623 soap->userid = soap_strdup(soap, soap->tmpbuf); | |
5624 soap->passwd = soap_strdup(soap, s + 1); | |
5625 } | |
5626 } | |
5627 } | |
5628 else if (!soap_tag_cmp(key, "WWW-Authenticate") || !soap_tag_cmp(key, "Proxy-Authenticate")) | |
5629 { | |
5630 #ifdef WITH_NTLM | |
5631 if (!soap_tag_cmp(val, "NTLM*")) | |
5632 soap->ntlm_challenge = soap_strdup(soap, val + 4); | |
5633 else | |
5634 #endif | |
5635 soap->authrealm = soap_strdup(soap, soap_get_header_attribute(soap, val + 6, "realm")); | |
5636 } | |
5637 else if (!soap_tag_cmp(key, "Expect")) | |
5638 { if (!soap_tag_cmp(val, "100-continue")) | |
5639 { if ((soap->error = soap->fposthdr(soap, "HTTP/1.1 100 Continue", NULL)) | |
5640 || (soap->error = soap->fposthdr(soap, NULL, NULL))) | |
5641 return soap->error; | |
5642 } | |
5643 } | |
5644 #endif | |
5645 else if (!soap_tag_cmp(key, "SOAPAction")) | |
5646 { if (*val == '"') | |
5647 { soap->action = soap_strdup(soap, val + 1); | |
5648 if (*soap->action) | |
5649 soap->action[strlen(soap->action) - 1] = '\0'; | |
5650 } | |
5651 else | |
5652 soap->action = soap_strdup(soap, val); | |
5653 } | |
5654 else if (!soap_tag_cmp(key, "Location")) | |
5655 { strncpy(soap->endpoint, val, sizeof(soap->endpoint)); | |
5656 soap->endpoint[sizeof(soap->endpoint) - 1] = '\0'; | |
5657 } | |
5658 else if (!soap_tag_cmp(key, "X-Forwarded-For")) | |
5659 { soap->proxy_from = soap_strdup(soap, val); | |
5660 } | |
5661 #ifdef WITH_COOKIES | |
5662 else if (!soap_tag_cmp(key, "Cookie") | |
5663 || !soap_tag_cmp(key, "Cookie2") | |
5664 || !soap_tag_cmp(key, "Set-Cookie") | |
5665 || !soap_tag_cmp(key, "Set-Cookie2")) | |
5666 { soap_getcookies(soap, val); | |
5667 } | |
5668 #endif | |
5669 return SOAP_OK; | |
5670 } | |
5671 #endif | |
5672 #endif | |
5673 | |
5674 /******************************************************************************/ | |
5675 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) | |
5676 #ifndef PALM_1 | |
5677 SOAP_FMAC1 | |
5678 const char* | |
5679 SOAP_FMAC2 | |
5680 soap_get_header_attribute(struct soap *soap, const char *line, const char *key) | |
5681 { register const char *s = line; | |
5682 if (s) | |
5683 { while (*s) | |
5684 { register short flag; | |
5685 s = soap_decode_key(soap->tmpbuf, sizeof(soap->tmpbuf), s); | |
5686 flag = soap_tag_cmp(soap->tmpbuf, key); | |
5687 s = soap_decode_val(soap->tmpbuf, sizeof(soap->tmpbuf), s); | |
5688 if (!flag) | |
5689 return soap->tmpbuf; | |
5690 } | |
5691 } | |
5692 return NULL; | |
5693 } | |
5694 #endif | |
5695 #endif | |
5696 | |
5697 /******************************************************************************/ | |
5698 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) | |
5699 #ifndef PALM_1 | |
5700 SOAP_FMAC1 | |
5701 const char* | |
5702 SOAP_FMAC2 | |
5703 soap_decode_key(char *buf, size_t len, const char *val) | |
5704 { return soap_decode(buf, len, val, "=,;"); | |
5705 } | |
5706 #endif | |
5707 #endif | |
5708 | |
5709 /******************************************************************************/ | |
5710 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) | |
5711 #ifndef PALM_1 | |
5712 SOAP_FMAC1 | |
5713 const char* | |
5714 SOAP_FMAC2 | |
5715 soap_decode_val(char *buf, size_t len, const char *val) | |
5716 { if (*val != '=') | |
5717 { *buf = '\0'; | |
5718 return val; | |
5719 } | |
5720 return soap_decode(buf, len, val + 1, ",;"); | |
5721 } | |
5722 #endif | |
5723 #endif | |
5724 | |
5725 /******************************************************************************/ | |
5726 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) | |
5727 #ifndef PALM_1 | |
5728 static const char* | |
5729 soap_decode(char *buf, size_t len, const char *val, const char *sep) | |
5730 { const char *s; | |
5731 char *t = buf; | |
5732 size_t i = len; | |
5733 for (s = val; *s; s++) | |
5734 if (*s != ' ' && *s != '\t' && !strchr(sep, *s)) | |
5735 break; | |
5736 if (len > 0) | |
5737 { if (*s == '"') | |
5738 { s++; | |
5739 while (*s && *s != '"' && --i) | |
5740 *t++ = *s++; | |
5741 } | |
5742 else | |
5743 { while (*s && !soap_blank((soap_wchar)*s) && !strchr(sep, *s) && --i) | |
5744 { if (*s == '%' && s[1] && s[2]) | |
5745 { *t++ = ((s[1] >= 'A' ? (s[1] & 0x7) + 9 : s[1] - '0') << 4) | |
5746 + (s[2] >= 'A' ? (s[2] & 0x7) + 9 : s[2] - '0'); | |
5747 s += 3; | |
5748 } | |
5749 else | |
5750 *t++ = *s++; | |
5751 } | |
5752 } | |
5753 buf[len - 1] = '\0'; /* appease */ | |
5754 } | |
5755 *t = '\0'; | |
5756 while (*s && !strchr(sep, *s)) | |
5757 s++; | |
5758 return s; | |
5759 } | |
5760 #endif | |
5761 #endif | |
5762 | |
5763 /******************************************************************************/ | |
5764 #ifndef WITH_NOHTTP | |
5765 #ifndef PALM_1 | |
5766 static const char* | |
5767 http_error(struct soap *soap, int status) | |
5768 { register const char *msg = SOAP_STR_EOS; | |
5769 (void)soap; | |
5770 #ifndef WITH_LEAN | |
5771 msg = soap_code_str(h_http_error_codes, status); | |
5772 if (!msg) | |
5773 msg = SOAP_STR_EOS; | |
5774 #endif | |
5775 return msg; | |
5776 } | |
5777 #endif | |
5778 #endif | |
5779 | |
5780 /******************************************************************************/ | |
5781 | |
5782 #ifndef WITH_NOHTTP | |
5783 #ifndef PALM_1 | |
5784 static int | |
5785 http_get(struct soap *soap) | |
5786 { (void)soap; | |
5787 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "HTTP GET request\n")); | |
5788 return SOAP_GET_METHOD; | |
5789 } | |
5790 #endif | |
5791 #endif | |
5792 | |
5793 /******************************************************************************/ | |
5794 #ifndef WITH_NOHTTP | |
5795 #ifndef PALM_1 | |
5796 static int | |
5797 http_405(struct soap *soap) | |
5798 { (void)soap; | |
5799 return 405; | |
5800 } | |
5801 #endif | |
5802 #endif | |
5803 | |
5804 /******************************************************************************/ | |
5805 #ifndef WITH_NOHTTP | |
5806 #ifndef PALM_1 | |
5807 static int | |
5808 http_200(struct soap *soap) | |
5809 { return soap_send_empty_response(soap, 200); | |
5810 } | |
5811 #endif | |
5812 #endif | |
5813 | |
5814 /******************************************************************************/ | |
5815 #ifndef WITH_NOHTTP | |
5816 #ifndef PALM_1 | |
5817 static int | |
5818 http_post(struct soap *soap, const char *endpoint, const char *host, int port, const char *path, const char *action, size_t count) | |
5819 { register const char *s; | |
5820 register int err; | |
5821 switch (soap->status) | |
5822 { case SOAP_GET: | |
5823 s = "GET"; | |
5824 break; | |
5825 case SOAP_PUT: | |
5826 s = "PUT"; | |
5827 break; | |
5828 case SOAP_DEL: | |
5829 s = "DELETE"; | |
5830 break; | |
5831 case SOAP_CONNECT: | |
5832 s = "CONNECT"; | |
5833 break; | |
5834 default: | |
5835 s = "POST"; | |
5836 } | |
5837 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "HTTP %s to %s\n", s, endpoint ? endpoint : "(null)")); | |
5838 #ifdef PALM | |
5839 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)) | |
5840 #else | |
5841 if (!endpoint || (soap_tag_cmp(endpoint, "http:*") && soap_tag_cmp(endpoint, "https:*") && strncmp(endpoint, "httpg:", 6))) | |
5842 #endif | |
5843 return SOAP_OK; | |
5844 if (strlen(endpoint) + strlen(soap->http_version) > sizeof(soap->tmpbuf) - 80 | |
5845 || strlen(host) + strlen(soap->http_version) > sizeof(soap->tmpbuf) - 80) | |
5846 return soap->error = SOAP_EOM; /* prevent overrun (note that 'host' and 'soap->host' are substrings of 'endpoint') */ | |
5847 if (soap->status == SOAP_CONNECT) | |
5848 { | |
5849 #ifdef HAVE_SNPRINTF | |
5850 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%s %s:%d HTTP/%s", s, soap->host, soap->port, soap->http_version); | |
5851 #else | |
5852 sprintf(soap->tmpbuf, "%s %s:%d HTTP/%s", s, soap->host, soap->port, soap->http_version); | |
5853 #endif | |
5854 } | |
5855 else if (soap->proxy_host && endpoint) | |
5856 { | |
5857 #ifdef HAVE_SNPRINTF | |
5858 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%s %s HTTP/%s", s, endpoint, soap->http_version); | |
5859 #else | |
5860 sprintf(soap->tmpbuf, "%s %s HTTP/%s", s, endpoint, soap->http_version); | |
5861 #endif | |
5862 } | |
5863 else | |
5864 { | |
5865 #ifdef HAVE_SNPRINTF | |
5866 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%s /%s HTTP/%s", s, (*path == '/' ? path + 1 : path), soap->http_version); | |
5867 #else | |
5868 sprintf(soap->tmpbuf, "%s /%s HTTP/%s", s, (*path == '/' ? path + 1 : path), soap->http_version); | |
5869 #endif | |
5870 } | |
5871 if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) | |
5872 return err; | |
5873 #ifdef WITH_OPENSSL | |
5874 if ((soap->ssl && port != 443) || (!soap->ssl && port != 80)) | |
5875 #else | |
5876 if (port != 80) | |
5877 #endif | |
5878 { | |
5879 #ifdef WITH_IPV6 | |
5880 if (*host != '[' && strchr(host, ':')) | |
5881 { | |
5882 #ifdef HAVE_SNPRINTF | |
5883 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "[%s]:%d", host, port); /* RFC 2732 */ | |
5884 #else | |
5885 sprintf(soap->tmpbuf, "[%s]:%d", host, port); /* RFC 2732 */ | |
5886 #endif | |
5887 } | |
5888 else | |
5889 #endif | |
5890 { | |
5891 #ifdef HAVE_SNPRINTF | |
5892 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%s:%d", host, port); | |
5893 #else | |
5894 sprintf(soap->tmpbuf, "%s:%d", host, port); | |
5895 #endif | |
5896 } | |
5897 } | |
5898 else | |
5899 { | |
5900 #ifdef WITH_IPV6 | |
5901 if (*host != '[' && strchr(host, ':')) | |
5902 { | |
5903 #ifdef HAVE_SNPRINTF | |
5904 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "[%s]", host); /* RFC 2732 */ | |
5905 #else | |
5906 sprintf(soap->tmpbuf, "[%s]", host); /* RFC 2732 */ | |
5907 #endif | |
5908 } | |
5909 else | |
5910 #endif | |
5911 strcpy(soap->tmpbuf, host); | |
5912 } | |
5913 if ((err = soap->fposthdr(soap, "Host", soap->tmpbuf))) | |
5914 return err; | |
5915 if ((err = soap->fposthdr(soap, "User-Agent", "gSOAP/2.8"))) | |
5916 return err; | |
5917 if ((err = soap_puthttphdr(soap, SOAP_OK, count))) | |
5918 return err; | |
5919 #ifdef WITH_ZLIB | |
5920 #ifdef WITH_GZIP | |
5921 if ((err = soap->fposthdr(soap, "Accept-Encoding", "gzip, deflate"))) | |
5922 #else | |
5923 if ((err = soap->fposthdr(soap, "Accept-Encoding", "deflate"))) | |
5924 #endif | |
5925 return err; | |
5926 #endif | |
5927 #ifndef WITH_LEAN | |
5928 #ifdef WITH_NTLM | |
5929 if (soap->ntlm_challenge && strlen(soap->ntlm_challenge) + 6 < sizeof(soap->tmpbuf)) | |
5930 { if (*soap->ntlm_challenge) | |
5931 { | |
5932 #ifdef HAVE_SNPRINTF | |
5933 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "NTLM %s", soap->ntlm_challenge); | |
5934 #else | |
5935 sprintf(soap->tmpbuf, "NTLM %s", soap->ntlm_challenge); | |
5936 #endif | |
5937 if (soap->proxy_host) | |
5938 { if ((err = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf))) | |
5939 return err; | |
5940 } | |
5941 else if ((err = soap->fposthdr(soap, "Authorization", soap->tmpbuf))) | |
5942 return err; | |
5943 } | |
5944 } | |
5945 else | |
5946 { | |
5947 #endif | |
5948 if (soap->userid && soap->passwd && strlen(soap->userid) + strlen(soap->passwd) < 761) | |
5949 { strcpy(soap->tmpbuf, "Basic "); | |
5950 #ifdef HAVE_SNPRINTF | |
5951 soap_snprintf(soap->tmpbuf + 262, sizeof(soap->tmpbuf) - 262, "%s:%s", soap->userid, soap->passwd); | |
5952 #else | |
5953 sprintf(soap->tmpbuf + 262, "%s:%s", soap->userid, soap->passwd); | |
5954 #endif | |
5955 soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262)); | |
5956 if ((err = soap->fposthdr(soap, "Authorization", soap->tmpbuf))) | |
5957 return err; | |
5958 } | |
5959 if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761) | |
5960 { strcpy(soap->tmpbuf, "Basic "); | |
5961 #ifdef HAVE_SNPRINTF | |
5962 soap_snprintf(soap->tmpbuf + 262, sizeof(soap->tmpbuf) - 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd); | |
5963 #else | |
5964 sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd); | |
5965 #endif | |
5966 soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262)); | |
5967 if ((err = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf))) | |
5968 return err; | |
5969 } | |
5970 #ifdef WITH_NTLM | |
5971 } | |
5972 #endif | |
5973 #endif | |
5974 #ifdef WITH_COOKIES | |
5975 #ifdef WITH_OPENSSL | |
5976 if (soap_putcookies(soap, host, path, soap->ssl != NULL)) | |
5977 return soap->error; | |
5978 #else | |
5979 if (soap_putcookies(soap, host, path, 0)) | |
5980 return soap->error; | |
5981 #endif | |
5982 #endif | |
5983 if (action && soap->status != SOAP_GET && soap->status != SOAP_DEL) | |
5984 { | |
5985 #ifdef HAVE_SNPRINTF | |
5986 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "\"%s\"", action); | |
5987 #else | |
5988 sprintf(soap->tmpbuf, "\"%s\"", strlen(action) < sizeof(soap->tmpbuf) - 3 ? action : SOAP_STR_EOS); | |
5989 #endif | |
5990 if ((err = soap->fposthdr(soap, "SOAPAction", soap->tmpbuf))) | |
5991 return err; | |
5992 } | |
5993 return soap->fposthdr(soap, NULL, NULL); | |
5994 } | |
5995 #endif | |
5996 #endif | |
5997 | |
5998 /******************************************************************************/ | |
5999 #ifndef WITH_NOHTTP | |
6000 #ifndef PALM_1 | |
6001 static int | |
6002 http_send_header(struct soap *soap, const char *s) | |
6003 { register const char *t; | |
6004 do | |
6005 { t = strchr(s, '\n'); /* disallow \n in HTTP headers */ | |
6006 if (!t) | |
6007 t = s + strlen(s); | |
6008 if (soap_send_raw(soap, s, t - s)) | |
6009 return soap->error; | |
6010 s = t + 1; | |
6011 } while (*t); | |
6012 return SOAP_OK; | |
6013 } | |
6014 #endif | |
6015 #endif | |
6016 | |
6017 /******************************************************************************/ | |
6018 #ifndef WITH_NOHTTP | |
6019 #ifndef PALM_1 | |
6020 static int | |
6021 http_post_header(struct soap *soap, const char *key, const char *val) | |
6022 { if (key) | |
6023 { if (http_send_header(soap, key)) | |
6024 return soap->error; | |
6025 if (val && (soap_send_raw(soap, ": ", 2) || http_send_header(soap, val))) | |
6026 return soap->error; | |
6027 } | |
6028 return soap_send_raw(soap, "\r\n", 2); | |
6029 } | |
6030 #endif | |
6031 #endif | |
6032 | |
6033 /******************************************************************************/ | |
6034 #ifndef WITH_NOHTTP | |
6035 #ifndef PALM_1 | |
6036 static int | |
6037 http_response(struct soap *soap, int status, size_t count) | |
6038 { register int err; | |
6039 char http[10]; | |
6040 int code = status; | |
6041 const char *line; | |
6042 #ifdef WMW_RPM_IO | |
6043 if (soap->rpmreqid) | |
6044 httpOutputEnable(soap->rpmreqid); | |
6045 #endif | |
6046 if (!soap->http_version || strlen(soap->http_version) > 4) | |
6047 return soap->error = SOAP_EOM; | |
6048 #ifdef WMW_RPM_IO | |
6049 if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */ | |
6050 #else | |
6051 if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application (socket) or CGI (stdin/out)? */ | |
6052 #endif | |
6053 { | |
6054 #ifdef HAVE_SNPRINTF | |
6055 soap_snprintf(http, sizeof(http), "HTTP/%s", soap->http_version); | |
6056 #else | |
6057 sprintf(http, "HTTP/%s", soap->http_version); | |
6058 #endif | |
6059 } | |
6060 else | |
6061 strcpy(http, "Status:"); | |
6062 if (!status || status == SOAP_HTML || status == SOAP_FILE) | |
6063 { if (count || ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK)) | |
6064 code = 200; | |
6065 else | |
6066 code = 202; | |
6067 } | |
6068 else if (status < 200 || status >= 600) | |
6069 { const char *s = *soap_faultcode(soap); | |
6070 if (status >= SOAP_GET_METHOD && status <= SOAP_HTTP_METHOD) | |
6071 code = 405; | |
6072 else if (soap->version == 2 && (!s || !strcmp(s, "SOAP-ENV:Sender"))) | |
6073 code = 400; | |
6074 else | |
6075 code = 500; | |
6076 } | |
6077 line = http_error(soap, code); | |
6078 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "HTTP Status = %d %s\n", code, line)); | |
6079 #ifdef HAVE_SNPRINTF | |
6080 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%s %d %s", http, code, line); | |
6081 #else | |
6082 sprintf(soap->tmpbuf, "%s %d %s", http, code, line); | |
6083 #endif | |
6084 if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) | |
6085 return err; | |
6086 #ifndef WITH_LEAN | |
6087 if (status == 401) | |
6088 { | |
6089 #ifdef HAVE_SNPRINTF | |
6090 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "Basic realm=\"%s\"", (soap->authrealm && strlen(soap->authrealm) < sizeof(soap->tmpbuf) - 14) ? soap->authrealm : "gSOAP Web Service"); | |
6091 #else | |
6092 sprintf(soap->tmpbuf, "Basic realm=\"%s\"", (soap->authrealm && strlen(soap->authrealm) < sizeof(soap->tmpbuf) - 14) ? soap->authrealm : "gSOAP Web Service"); | |
6093 #endif | |
6094 if ((err = soap->fposthdr(soap, "WWW-Authenticate", soap->tmpbuf))) | |
6095 return err; | |
6096 } | |
6097 else if ((status >= 301 && status <= 303) || status == 307) | |
6098 { if ((err = soap->fposthdr(soap, "Location", soap->endpoint))) | |
6099 return err; | |
6100 } | |
6101 #endif | |
6102 if ((err = soap->fposthdr(soap, "Server", "gSOAP/2.8")) | |
6103 || (err = soap_puthttphdr(soap, status, count))) | |
6104 return err; | |
6105 #ifdef WITH_COOKIES | |
6106 if (soap_putsetcookies(soap)) | |
6107 return soap->error; | |
6108 #endif | |
6109 return soap->fposthdr(soap, NULL, NULL); | |
6110 } | |
6111 #endif | |
6112 #endif | |
6113 | |
6114 /******************************************************************************/ | |
6115 #ifndef PALM_1 | |
6116 SOAP_FMAC1 | |
6117 int | |
6118 SOAP_FMAC2 | |
6119 soap_response(struct soap *soap, int status) | |
6120 { register size_t count; | |
6121 if (!(soap->omode & (SOAP_ENC_XML | SOAP_IO_STORE /* this tests for chunking too */)) | |
6122 && (status == SOAP_HTML || status == SOAP_FILE)) | |
6123 soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE; | |
6124 soap->status = status; | |
6125 count = soap_count_attachments(soap); | |
6126 if (soap_begin_send(soap)) | |
6127 return soap->error; | |
6128 #ifndef WITH_NOHTTP | |
6129 if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML)) | |
6130 { register int n = soap->mode; | |
6131 soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB); | |
6132 if ((n & SOAP_IO) != SOAP_IO_FLUSH) | |
6133 soap->mode |= SOAP_IO_BUFFER; | |
6134 if ((soap->error = soap->fresponse(soap, status, count))) | |
6135 return soap->error; | |
6136 #ifndef WITH_LEANER | |
6137 if ((n & SOAP_IO) == SOAP_IO_CHUNK) | |
6138 { if (soap_flush(soap)) | |
6139 return soap->error; | |
6140 } | |
6141 #endif | |
6142 soap->mode = n; | |
6143 } | |
6144 #endif | |
6145 return SOAP_OK; | |
6146 } | |
6147 #endif | |
6148 | |
6149 /******************************************************************************/ | |
6150 #ifndef PALM_1 | |
6151 SOAP_FMAC1 | |
6152 const char* | |
6153 SOAP_FMAC2 | |
6154 soap_url(struct soap *soap, const char *s, const char *t) | |
6155 { if (!t || (*t != '/' && *t != '?') || strlen(s) + strlen(t) >= sizeof(soap->msgbuf)) | |
6156 return s; | |
6157 strcpy(soap->msgbuf, s); | |
6158 strcat(soap->msgbuf, t); | |
6159 return soap->msgbuf; | |
6160 } | |
6161 #endif | |
6162 | |
6163 /******************************************************************************/ | |
6164 #ifndef PALM_1 | |
6165 SOAP_FMAC1 | |
6166 size_t | |
6167 SOAP_FMAC2 | |
6168 soap_encode_url(const char *s, char *t, size_t len) | |
6169 { register int c; | |
6170 register size_t n = len; | |
6171 while ((c = *s++) && --n > 0) | |
6172 { if (c > ' ' && c < 128 && !strchr("()<>@,;:\\\"/[]?={}#!$&'*+", c)) | |
6173 *t++ = c; | |
6174 else if (n > 2) | |
6175 { *t++ = '%'; | |
6176 *t++ = (c >> 4) + (c > 159 ? '7' : '0'); | |
6177 c &= 0xF; | |
6178 *t++ = c + (c > 9 ? '7' : '0'); | |
6179 n -= 2; | |
6180 } | |
6181 else | |
6182 break; | |
6183 } | |
6184 *t = '\0'; | |
6185 return len - n; | |
6186 } | |
6187 #endif | |
6188 | |
6189 /******************************************************************************/ | |
6190 #ifndef PALM_1 | |
6191 SOAP_FMAC1 | |
6192 const char* | |
6193 SOAP_FMAC2 | |
6194 soap_encode_url_string(struct soap *soap, const char *s) | |
6195 { if (s) | |
6196 { size_t n = 3*strlen(s)+1; | |
6197 char *t = (char*)soap_malloc(soap, n); | |
6198 if (t) | |
6199 { soap_encode_url(s, t, n); | |
6200 return t; | |
6201 } | |
6202 } | |
6203 return SOAP_STR_EOS; | |
6204 } | |
6205 #endif | |
6206 | |
6207 /******************************************************************************\ | |
6208 * | |
6209 * HTTP Cookies | |
6210 * | |
6211 \******************************************************************************/ | |
6212 | |
6213 #ifdef WITH_COOKIES | |
6214 /******************************************************************************/ | |
6215 SOAP_FMAC1 | |
6216 struct soap_cookie* | |
6217 SOAP_FMAC2 | |
6218 soap_cookie(struct soap *soap, const char *name, const char *domain, const char *path) | |
6219 { struct soap_cookie *p; | |
6220 if (!domain) | |
6221 domain = soap->cookie_domain; | |
6222 if (!path) | |
6223 path = soap->cookie_path; | |
6224 if (!path) | |
6225 path = SOAP_STR_EOS; | |
6226 else if (*path == '/') | |
6227 path++; | |
6228 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Search cookie='%s' domain='%s' path='%s'\n", name, domain ? domain : "(null)", path ? path : "(null)")); | |
6229 for (p = soap->cookies; p; p = p->next) | |
6230 { 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)); | |
6231 if (!strcmp(p->name, name) | |
6232 && p->domain | |
6233 && p->path | |
6234 && !strcmp(p->domain, domain) | |
6235 && (!*p->path || !strncmp(p->path, path, strlen(p->path)))) | |
6236 break; | |
6237 } | |
6238 return p; | |
6239 } | |
6240 | |
6241 /******************************************************************************/ | |
6242 SOAP_FMAC1 | |
6243 struct soap_cookie* | |
6244 SOAP_FMAC2 | |
6245 soap_set_cookie(struct soap *soap, const char *name, const char *value, const char *domain, const char *path) | |
6246 { struct soap_cookie **p, *q; | |
6247 int n; | |
6248 if (!domain) | |
6249 domain = soap->cookie_domain; | |
6250 if (!path) | |
6251 path = soap->cookie_path; | |
6252 if (!path) | |
6253 path = SOAP_STR_EOS; | |
6254 else if (*path == '/') | |
6255 path++; | |
6256 q = soap_cookie(soap, name, domain, path); | |
6257 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)")); | |
6258 if (!q) | |
6259 { if ((q = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie)))) | |
6260 { if ((q->name = (char*)SOAP_MALLOC(soap, strlen(name)+1))) | |
6261 strcpy(q->name, name); | |
6262 q->value = NULL; | |
6263 q->domain = NULL; | |
6264 q->path = NULL; | |
6265 q->expire = 0; | |
6266 q->maxage = -1; | |
6267 q->version = 1; | |
6268 q->secure = 0; | |
6269 q->modified = 0; | |
6270 for (p = &soap->cookies, n = soap->cookie_max; *p && n; p = &(*p)->next, n--) | |
6271 if (!strcmp((*p)->name, name) && (*p)->path && path && strcmp((*p)->path, path) < 0) | |
6272 break; | |
6273 if (n) | |
6274 { q->next = *p; | |
6275 *p = q; | |
6276 } | |
6277 else | |
6278 { SOAP_FREE(soap, q->name); | |
6279 SOAP_FREE(soap, q); | |
6280 q = NULL; | |
6281 } | |
6282 } | |
6283 } | |
6284 else | |
6285 q->modified = 1; | |
6286 if (q) | |
6287 { if (q->value) | |
6288 { if (!value || strcmp(value, q->value)) | |
6289 { SOAP_FREE(soap, q->value); | |
6290 q->value = NULL; | |
6291 } | |
6292 } | |
6293 if (value && *value && !q->value && (q->value = (char*)SOAP_MALLOC(soap, strlen(value)+1))) | |
6294 strcpy(q->value, value); | |
6295 if (q->domain) | |
6296 { if (!domain || strcmp(domain, q->domain)) | |
6297 { SOAP_FREE(soap, q->domain); | |
6298 q->domain = NULL; | |
6299 } | |
6300 } | |
6301 if (domain && !q->domain && (q->domain = (char*)SOAP_MALLOC(soap, strlen(domain)+1))) | |
6302 strcpy(q->domain, domain); | |
6303 if (q->path) | |
6304 { if (!path || strncmp(path, q->path, strlen(q->path))) | |
6305 { SOAP_FREE(soap, q->path); | |
6306 q->path = NULL; | |
6307 } | |
6308 } | |
6309 if (path && !q->path && (q->path = (char*)SOAP_MALLOC(soap, strlen(path)+1))) | |
6310 strcpy(q->path, path); | |
6311 q->session = 1; | |
6312 q->env = 0; | |
6313 } | |
6314 return q; | |
6315 } | |
6316 | |
6317 /******************************************************************************/ | |
6318 SOAP_FMAC1 | |
6319 void | |
6320 SOAP_FMAC2 | |
6321 soap_clr_cookie(struct soap *soap, const char *name, const char *domain, const char *path) | |
6322 { struct soap_cookie **p, *q; | |
6323 if (!domain) | |
6324 domain = soap->cookie_domain; | |
6325 if (!domain) | |
6326 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error in clear cookie='%s': cookie domain not set\n", name ? name : "(null)")); | |
6327 return; | |
6328 } | |
6329 if (!path) | |
6330 path = soap->cookie_path; | |
6331 if (!path) | |
6332 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error in clear cookie='%s': cookie path not set\n", name ? name : "(null)")); | |
6333 return; | |
6334 } | |
6335 if (*path == '/') | |
6336 path++; | |
6337 for (p = &soap->cookies, q = *p; q; q = *p) | |
6338 { if (!strcmp(q->name, name) && !strcmp(q->domain, domain) && !strncmp(q->path, path, strlen(q->path))) | |
6339 { if (q->value) | |
6340 SOAP_FREE(soap, q->value); | |
6341 if (q->domain) | |
6342 SOAP_FREE(soap, q->domain); | |
6343 if (q->path) | |
6344 SOAP_FREE(soap, q->path); | |
6345 *p = q->next; | |
6346 SOAP_FREE(soap, q); | |
6347 } | |
6348 else | |
6349 p = &q->next; | |
6350 } | |
6351 } | |
6352 | |
6353 /******************************************************************************/ | |
6354 SOAP_FMAC1 | |
6355 char * | |
6356 SOAP_FMAC2 | |
6357 soap_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path) | |
6358 { struct soap_cookie *p; | |
6359 if ((p = soap_cookie(soap, name, domain, path))) | |
6360 return p->value; | |
6361 return NULL; | |
6362 } | |
6363 | |
6364 /******************************************************************************/ | |
6365 SOAP_FMAC1 | |
6366 char * | |
6367 SOAP_FMAC2 | |
6368 soap_env_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path) | |
6369 { struct soap_cookie *p; | |
6370 if ((p = soap_cookie(soap, name, domain, path)) && p->env) | |
6371 return p->value; | |
6372 return NULL; | |
6373 } | |
6374 | |
6375 /******************************************************************************/ | |
6376 SOAP_FMAC1 | |
6377 time_t | |
6378 SOAP_FMAC2 | |
6379 soap_cookie_expire(struct soap *soap, const char *name, const char *domain, const char *path) | |
6380 { struct soap_cookie *p; | |
6381 if ((p = soap_cookie(soap, name, domain, path))) | |
6382 return p->expire; | |
6383 return -1; | |
6384 } | |
6385 | |
6386 /******************************************************************************/ | |
6387 SOAP_FMAC1 | |
6388 int | |
6389 SOAP_FMAC2 | |
6390 soap_set_cookie_expire(struct soap *soap, const char *name, long expire, const char *domain, const char *path) | |
6391 { struct soap_cookie *p; | |
6392 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set cookie expiration max-age=%ld: cookie='%s' domain='%s' path='%s'\n", expire, name, domain ? domain : "(null)", path ? path : "(null)")); | |
6393 if ((p = soap_cookie(soap, name, domain, path))) | |
6394 { p->maxage = expire; | |
6395 p->modified = 1; | |
6396 return SOAP_OK; | |
6397 } | |
6398 return SOAP_ERR; | |
6399 } | |
6400 | |
6401 /******************************************************************************/ | |
6402 SOAP_FMAC1 | |
6403 int | |
6404 SOAP_FMAC2 | |
6405 soap_set_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path) | |
6406 { struct soap_cookie *p; | |
6407 if ((p = soap_cookie(soap, name, domain, path))) | |
6408 { p->session = 1; | |
6409 p->modified = 1; | |
6410 return SOAP_OK; | |
6411 } | |
6412 return SOAP_ERR; | |
6413 } | |
6414 | |
6415 /******************************************************************************/ | |
6416 SOAP_FMAC1 | |
6417 int | |
6418 SOAP_FMAC2 | |
6419 soap_clr_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path) | |
6420 { struct soap_cookie *p; | |
6421 if ((p = soap_cookie(soap, name, domain, path))) | |
6422 { p->session = 0; | |
6423 p->modified = 1; | |
6424 return SOAP_OK; | |
6425 } | |
6426 return SOAP_ERR; | |
6427 } | |
6428 | |
6429 /******************************************************************************/ | |
6430 SOAP_FMAC1 | |
6431 int | |
6432 SOAP_FMAC2 | |
6433 soap_putsetcookies(struct soap *soap) | |
6434 { struct soap_cookie *p; | |
6435 char *s, tmp[4096]; | |
6436 const char *t; | |
6437 for (p = soap->cookies; p; p = p->next) | |
6438 { | |
6439 if (p->modified | |
6440 #ifdef WITH_OPENSSL | |
6441 || (!p->env && !soap->ssl == !p->secure) | |
6442 #endif | |
6443 ) | |
6444 { s = tmp; | |
6445 if (p->name) | |
6446 s += soap_encode_url(p->name, s, tmp-s+4064); | |
6447 if (p->value && *p->value) | |
6448 { *s++ = '='; | |
6449 s += soap_encode_url(p->value, s, tmp-s+4064); | |
6450 } | |
6451 if (p->domain && (int)strlen(p->domain) < tmp-s+4064) | |
6452 { strcpy(s, ";Domain="); | |
6453 strcat(s, p->domain); | |
6454 } | |
6455 else if (soap->cookie_domain && (int)strlen(soap->cookie_domain) < tmp-s+4064) | |
6456 { strcpy(s, ";Domain="); | |
6457 strcat(s, soap->cookie_domain); | |
6458 } | |
6459 strcat(s, ";Path=/"); | |
6460 s += strlen(s); | |
6461 if (p->path) | |
6462 t = p->path; | |
6463 else | |
6464 t = soap->cookie_path; | |
6465 if (t) | |
6466 { if (*t == '/') | |
6467 t++; | |
6468 if ((int)strlen(t) < tmp-s+4064) | |
6469 { if (strchr(t, '%')) /* already URL encoded? */ | |
6470 { strcpy(s, t); | |
6471 s += strlen(s); | |
6472 } | |
6473 else | |
6474 s += soap_encode_url(t, s, tmp-s+4064); | |
6475 } | |
6476 } | |
6477 if (p->version > 0 && s-tmp < 4060) | |
6478 { | |
6479 #ifdef HAVE_SNPRINTF | |
6480 soap_snprintf(s, 4096 - (s-tmp), ";Version=%u", p->version); | |
6481 #else | |
6482 sprintf(s, ";Version=%u", p->version); | |
6483 #endif | |
6484 s += strlen(s); | |
6485 } | |
6486 if (p->maxage >= 0 && s-tmp < 4060) | |
6487 { | |
6488 #ifdef HAVE_SNPRINTF | |
6489 soap_snprintf(s, 4096 - (s-tmp), ";Max-Age=%ld", p->maxage); | |
6490 #else | |
6491 sprintf(s, ";Max-Age=%ld", p->maxage); | |
6492 #endif | |
6493 s += strlen(s); | |
6494 } | |
6495 if (s-tmp < 4073 | |
6496 && (p->secure | |
6497 #ifdef WITH_OPENSSL | |
6498 || soap->ssl | |
6499 #endif | |
6500 )) | |
6501 strcpy(s, ";Secure"); | |
6502 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set-Cookie: %s\n", tmp)); | |
6503 if ((soap->error = soap->fposthdr(soap, "Set-Cookie", tmp))) | |
6504 return soap->error; | |
6505 } | |
6506 } | |
6507 return SOAP_OK; | |
6508 } | |
6509 | |
6510 /******************************************************************************/ | |
6511 SOAP_FMAC1 | |
6512 int | |
6513 SOAP_FMAC2 | |
6514 soap_putcookies(struct soap *soap, const char *domain, const char *path, int secure) | |
6515 { struct soap_cookie **p, *q; | |
6516 unsigned int version = 0; | |
6517 time_t now = time(NULL); | |
6518 char *s, tmp[4096]; | |
6519 if (!domain || !path) | |
6520 return SOAP_OK; | |
6521 s = tmp; | |
6522 p = &soap->cookies; | |
6523 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending cookies for domain='%s' path='%s'\n", domain, path)); | |
6524 if (*path == '/') | |
6525 path++; | |
6526 while ((q = *p)) | |
6527 { if (q->expire && now > q->expire) | |
6528 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie %s expired\n", q->name)); | |
6529 SOAP_FREE(soap, q->name); | |
6530 if (q->value) | |
6531 SOAP_FREE(soap, q->value); | |
6532 if (q->domain) | |
6533 SOAP_FREE(soap, q->domain); | |
6534 if (q->path) | |
6535 SOAP_FREE(soap, q->path); | |
6536 *p = q->next; | |
6537 SOAP_FREE(soap, q); | |
6538 } | |
6539 else | |
6540 { int flag; | |
6541 char *t = q->domain; | |
6542 size_t n = 0; | |
6543 if (!t) | |
6544 flag = 1; | |
6545 else | |
6546 { const char *r = strchr(t, ':'); | |
6547 if (r) | |
6548 n = r - t; | |
6549 else | |
6550 n = strlen(t); | |
6551 flag = !strncmp(t, domain, n); | |
6552 } | |
6553 /* domain-level cookies, cannot compile when WITH_NOIO set */ | |
6554 #ifndef WITH_NOIO | |
6555 if (!flag) | |
6556 { struct hostent *hostent = gethostbyname((char*)domain); | |
6557 if (hostent) | |
6558 { const char *r = strchr(hostent->h_name, '.'); | |
6559 if (!r) | |
6560 r = hostent->h_name; | |
6561 flag = !strncmp(t, r, n); | |
6562 } | |
6563 } | |
6564 #endif | |
6565 if (flag | |
6566 && (!q->path || !strncmp(q->path, path, strlen(q->path))) | |
6567 && (!q->secure || secure)) | |
6568 { size_t n = 12; | |
6569 if (q->name) | |
6570 n += 3*strlen(q->name); | |
6571 if (q->value && *q->value) | |
6572 n += 3*strlen(q->value) + 1; | |
6573 if (q->path && *q->path) | |
6574 n += strlen(q->path) + 9; | |
6575 if (q->domain) | |
6576 n += strlen(q->domain) + 11; | |
6577 if (tmp - s + n > sizeof(tmp)) | |
6578 { if (s == tmp) | |
6579 return SOAP_OK; /* HTTP header size overflow */ | |
6580 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie: %s\n", tmp)); | |
6581 if ((soap->error = soap->fposthdr(soap, "Cookie", tmp))) | |
6582 return soap->error; | |
6583 s = tmp; | |
6584 } | |
6585 else if (s != tmp) | |
6586 { strcat(s, " "); | |
6587 s++; | |
6588 } | |
6589 if (q->version != version && s-tmp < 4060) | |
6590 { | |
6591 #ifdef HAVE_SNPRINTF | |
6592 soap_snprintf(s, 4096 - (s-tmp), "$Version=%u;", q->version); | |
6593 #else | |
6594 sprintf(s, "$Version=%u;", q->version); | |
6595 #endif | |
6596 version = q->version; | |
6597 s += strlen(s); | |
6598 } | |
6599 if (q->name) | |
6600 s += soap_encode_url(q->name, s, tmp+sizeof(tmp)-s-16); | |
6601 if (q->value && *q->value) | |
6602 { *s++ = '='; | |
6603 s += soap_encode_url(q->value, s, tmp+sizeof(tmp)-s-16); | |
6604 } | |
6605 if (q->path && (s-tmp) + strlen(q->path) < 4060) | |
6606 { | |
6607 #ifdef HAVE_SNPRINTF | |
6608 soap_snprintf(s, 4096 - (s-tmp), ";$Path=\"/%s\"", (*q->path == '/' ? q->path + 1 : q->path)); | |
6609 #else | |
6610 sprintf(s, ";$Path=\"/%s\"", (*q->path == '/' ? q->path + 1 : q->path)); | |
6611 #endif | |
6612 s += strlen(s); | |
6613 } | |
6614 if (q->domain && (s-tmp) + strlen(q->domain) < 4060) | |
6615 { | |
6616 #ifdef HAVE_SNPRINTF | |
6617 soap_snprintf(s, 4096 - (s-tmp), ";$Domain=\"%s\"", q->domain); | |
6618 #else | |
6619 sprintf(s, ";$Domain=\"%s\"", q->domain); | |
6620 #endif | |
6621 s += strlen(s); | |
6622 } | |
6623 } | |
6624 p = &q->next; | |
6625 } | |
6626 } | |
6627 if (s != tmp) | |
6628 if ((soap->error = soap->fposthdr(soap, "Cookie", tmp))) | |
6629 return soap->error; | |
6630 return SOAP_OK; | |
6631 } | |
6632 | |
6633 /******************************************************************************/ | |
6634 SOAP_FMAC1 | |
6635 void | |
6636 SOAP_FMAC2 | |
6637 soap_getcookies(struct soap *soap, const char *val) | |
6638 { struct soap_cookie *p = NULL, *q; | |
6639 const char *s; | |
6640 char *t, tmp[4096]; /* cookie size is up to 4096 bytes [RFC2109] */ | |
6641 char *domain = NULL; | |
6642 char *path = NULL; | |
6643 unsigned int version = 0; | |
6644 time_t now = time(NULL); | |
6645 if (!val) | |
6646 return; | |
6647 s = val; | |
6648 while (*s) | |
6649 { s = soap_decode_key(tmp, sizeof(tmp), s); | |
6650 if (!soap_tag_cmp(tmp, "$Version")) | |
6651 { if ((s = soap_decode_val(tmp, sizeof(tmp), s))) | |
6652 { if (p) | |
6653 p->version = (int)soap_strtol(tmp, NULL, 10); | |
6654 else | |
6655 version = (int)soap_strtol(tmp, NULL, 10); | |
6656 } | |
6657 } | |
6658 else if (!soap_tag_cmp(tmp, "$Path")) | |
6659 { s = soap_decode_val(tmp, sizeof(tmp), s); | |
6660 if (*tmp) | |
6661 { if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) | |
6662 strcpy(t, tmp); | |
6663 } | |
6664 else | |
6665 t = NULL; | |
6666 if (p) | |
6667 { if (p->path) | |
6668 SOAP_FREE(soap, p->path); | |
6669 p->path = t; | |
6670 } | |
6671 else | |
6672 { if (path) | |
6673 SOAP_FREE(soap, path); | |
6674 path = t; | |
6675 } | |
6676 } | |
6677 else if (!soap_tag_cmp(tmp, "$Domain")) | |
6678 { s = soap_decode_val(tmp, sizeof(tmp), s); | |
6679 if (*tmp) | |
6680 { if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) | |
6681 strcpy(t, tmp); | |
6682 } | |
6683 else | |
6684 t = NULL; | |
6685 if (p) | |
6686 { if (p->domain) | |
6687 SOAP_FREE(soap, p->domain); | |
6688 p->domain = t; | |
6689 } | |
6690 else | |
6691 { if (domain) | |
6692 SOAP_FREE(soap, domain); | |
6693 domain = t; | |
6694 } | |
6695 } | |
6696 else if (p && !soap_tag_cmp(tmp, "Path")) | |
6697 { if (p->path) | |
6698 SOAP_FREE(soap, p->path); | |
6699 s = soap_decode_val(tmp, sizeof(tmp), s); | |
6700 if (*tmp) | |
6701 { if ((p->path = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) | |
6702 strcpy(p->path, tmp); | |
6703 } | |
6704 else | |
6705 p->path = NULL; | |
6706 } | |
6707 else if (p && !soap_tag_cmp(tmp, "Domain")) | |
6708 { if (p->domain) | |
6709 SOAP_FREE(soap, p->domain); | |
6710 s = soap_decode_val(tmp, sizeof(tmp), s); | |
6711 if (*tmp) | |
6712 { if ((p->domain = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) | |
6713 strcpy(p->domain, tmp); | |
6714 } | |
6715 else | |
6716 p->domain = NULL; | |
6717 } | |
6718 else if (p && !soap_tag_cmp(tmp, "Version")) | |
6719 { s = soap_decode_val(tmp, sizeof(tmp), s); | |
6720 p->version = (unsigned int)soap_strtoul(tmp, NULL, 10); | |
6721 } | |
6722 else if (p && !soap_tag_cmp(tmp, "Max-Age")) | |
6723 { s = soap_decode_val(tmp, sizeof(tmp), s); | |
6724 p->expire = now + soap_strtol(tmp, NULL, 10); | |
6725 } | |
6726 else if (p && !soap_tag_cmp(tmp, "Expires")) | |
6727 { struct tm T; | |
6728 char a[3]; | |
6729 static const char mns[] = "anebarprayunulugepctovec"; | |
6730 s = soap_decode_val(tmp, sizeof(tmp), s); | |
6731 if (strlen(tmp) > 20) | |
6732 { memset((void*)&T, 0, sizeof(T)); | |
6733 a[0] = tmp[4]; | |
6734 a[1] = tmp[5]; | |
6735 a[2] = '\0'; | |
6736 T.tm_mday = (int)soap_strtol(a, NULL, 10); | |
6737 a[0] = tmp[8]; | |
6738 a[1] = tmp[9]; | |
6739 T.tm_mon = (int)(strstr(mns, a) - mns) / 2; | |
6740 a[0] = tmp[11]; | |
6741 a[1] = tmp[12]; | |
6742 T.tm_year = 100 + (int)soap_strtol(a, NULL, 10); | |
6743 a[0] = tmp[13]; | |
6744 a[1] = tmp[14]; | |
6745 T.tm_hour = (int)soap_strtol(a, NULL, 10); | |
6746 a[0] = tmp[16]; | |
6747 a[1] = tmp[17]; | |
6748 T.tm_min = (int)soap_strtol(a, NULL, 10); | |
6749 a[0] = tmp[19]; | |
6750 a[1] = tmp[20]; | |
6751 T.tm_sec = (int)soap_strtol(a, NULL, 10); | |
6752 p->expire = soap_timegm(&T); | |
6753 } | |
6754 } | |
6755 else if (p && !soap_tag_cmp(tmp, "Secure")) | |
6756 p->secure = 1; | |
6757 else | |
6758 { if (p) | |
6759 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie='%s' value='%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)); | |
6760 if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path))) | |
6761 { q->version = p->version; | |
6762 q->expire = p->expire; | |
6763 q->secure = p->secure; | |
6764 q->env = 1; | |
6765 } | |
6766 if (p->name) | |
6767 SOAP_FREE(soap, p->name); | |
6768 if (p->value) | |
6769 SOAP_FREE(soap, p->value); | |
6770 if (p->domain) | |
6771 SOAP_FREE(soap, p->domain); | |
6772 if (p->path) | |
6773 SOAP_FREE(soap, p->path); | |
6774 SOAP_FREE(soap, p); | |
6775 } | |
6776 if ((p = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie)))) | |
6777 { p->name = (char*)SOAP_MALLOC(soap, strlen(tmp)+1); | |
6778 strcpy(p->name, tmp); | |
6779 s = soap_decode_val(tmp, sizeof(tmp), s); | |
6780 if (*tmp) | |
6781 { p->value = (char*)SOAP_MALLOC(soap, strlen(tmp)+1); | |
6782 strcpy(p->value, tmp); | |
6783 } | |
6784 else | |
6785 p->value = NULL; | |
6786 if (domain) | |
6787 p->domain = domain; | |
6788 else if (*soap->host) | |
6789 { p->domain = (char*)SOAP_MALLOC(soap, strlen(soap->host)+1); | |
6790 strcpy(p->domain, soap->host); | |
6791 } | |
6792 else | |
6793 p->domain = NULL; | |
6794 if (path) | |
6795 p->path = path; | |
6796 else if (soap->path && *soap->path) | |
6797 { p->path = (char*)SOAP_MALLOC(soap, strlen(soap->path)+1); | |
6798 strcpy(p->path, soap->path); | |
6799 } | |
6800 else | |
6801 { p->path = (char*)SOAP_MALLOC(soap, 2); | |
6802 strcpy(p->path, "/"); | |
6803 } | |
6804 p->expire = 0; | |
6805 p->secure = 0; | |
6806 p->version = version; | |
6807 } | |
6808 } | |
6809 } | |
6810 if (p) | |
6811 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie='%s' value='%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)); | |
6812 if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path))) | |
6813 { q->version = p->version; | |
6814 q->expire = p->expire; | |
6815 q->secure = p->secure; | |
6816 q->env = 1; | |
6817 } | |
6818 if (p->name) | |
6819 SOAP_FREE(soap, p->name); | |
6820 if (p->value) | |
6821 SOAP_FREE(soap, p->value); | |
6822 if (p->domain) | |
6823 SOAP_FREE(soap, p->domain); | |
6824 if (p->path) | |
6825 SOAP_FREE(soap, p->path); | |
6826 SOAP_FREE(soap, p); | |
6827 } | |
6828 if (domain) | |
6829 SOAP_FREE(soap, domain); | |
6830 if (path) | |
6831 SOAP_FREE(soap, path); | |
6832 } | |
6833 | |
6834 /******************************************************************************/ | |
6835 SOAP_FMAC1 | |
6836 int | |
6837 SOAP_FMAC2 | |
6838 soap_getenv_cookies(struct soap *soap) | |
6839 { struct soap_cookie *p; | |
6840 const char *s; | |
6841 char key[4096], val[4096]; /* cookie size is up to 4096 bytes [RFC2109] */ | |
6842 if (!(s = getenv("HTTP_COOKIE"))) | |
6843 return SOAP_ERR; | |
6844 do | |
6845 { s = soap_decode_key(key, sizeof(key), s); | |
6846 s = soap_decode_val(val, sizeof(val), s); | |
6847 p = soap_set_cookie(soap, key, val, NULL, NULL); | |
6848 if (p) | |
6849 p->env = 1; | |
6850 } while (*s); | |
6851 return SOAP_OK; | |
6852 } | |
6853 | |
6854 /******************************************************************************/ | |
6855 SOAP_FMAC1 | |
6856 struct soap_cookie* | |
6857 SOAP_FMAC2 | |
6858 soap_copy_cookies(struct soap *copy, const struct soap *soap) | |
6859 { struct soap_cookie *p, **q, *r; | |
6860 q = &r; | |
6861 for (p = soap->cookies; p; p = p->next) | |
6862 { if (!(*q = (struct soap_cookie*)SOAP_MALLOC(copy, sizeof(struct soap_cookie)))) | |
6863 return r; | |
6864 **q = *p; | |
6865 if (p->name) | |
6866 { if (((*q)->name = (char*)SOAP_MALLOC(copy, strlen(p->name)+1))) | |
6867 strcpy((*q)->name, p->name); | |
6868 } | |
6869 if (p->value) | |
6870 { if (((*q)->value = (char*)SOAP_MALLOC(copy, strlen(p->value)+1))) | |
6871 strcpy((*q)->value, p->value); | |
6872 } | |
6873 if (p->domain) | |
6874 { if (((*q)->domain = (char*)SOAP_MALLOC(copy, strlen(p->domain)+1))) | |
6875 strcpy((*q)->domain, p->domain); | |
6876 } | |
6877 if (p->path) | |
6878 { if (((*q)->path = (char*)SOAP_MALLOC(copy, strlen(p->path)+1))) | |
6879 strcpy((*q)->path, p->path); | |
6880 } | |
6881 q = &(*q)->next; | |
6882 } | |
6883 *q = NULL; | |
6884 return r; | |
6885 } | |
6886 | |
6887 /******************************************************************************/ | |
6888 SOAP_FMAC1 | |
6889 void | |
6890 SOAP_FMAC2 | |
6891 soap_free_cookies(struct soap *soap) | |
6892 { struct soap_cookie *p; | |
6893 for (p = soap->cookies; p; p = soap->cookies) | |
6894 { soap->cookies = p->next; | |
6895 SOAP_FREE(soap, p->name); | |
6896 if (p->value) | |
6897 SOAP_FREE(soap, p->value); | |
6898 if (p->domain) | |
6899 SOAP_FREE(soap, p->domain); | |
6900 if (p->path) | |
6901 SOAP_FREE(soap, p->path); | |
6902 SOAP_FREE(soap, p); | |
6903 } | |
6904 } | |
6905 | |
6906 /******************************************************************************/ | |
6907 #endif /* WITH_COOKIES */ | |
6908 | |
6909 /******************************************************************************/ | |
6910 #ifndef WITH_NOIDREF | |
6911 #ifndef PALM_2 | |
6912 SOAP_FMAC1 | |
6913 size_t | |
6914 SOAP_FMAC2 | |
6915 soap_hash(register const char *s) | |
6916 { register size_t h = 0; | |
6917 while (*s) | |
6918 h = 65599*h + *s++; | |
6919 return h % SOAP_IDHASH; | |
6920 } | |
6921 #endif | |
6922 #endif | |
6923 | |
6924 /******************************************************************************/ | |
6925 #ifndef WITH_NOIDREF | |
6926 #ifndef PALM_1 | |
6927 static void | |
6928 soap_init_pht(struct soap *soap) | |
6929 { register int i; | |
6930 soap->pblk = NULL; | |
6931 soap->pidx = 0; | |
6932 for (i = 0; i < (int)SOAP_PTRHASH; i++) | |
6933 soap->pht[i] = NULL; | |
6934 } | |
6935 #endif | |
6936 #endif | |
6937 | |
6938 /******************************************************************************/ | |
6939 #ifndef PALM_1 | |
6940 SOAP_FMAC1 | |
6941 struct soap* | |
6942 SOAP_FMAC2 | |
6943 soap_versioning(soap_new)(soap_mode imode, soap_mode omode) | |
6944 { struct soap *soap = (struct soap*)malloc(sizeof(struct soap)); | |
6945 if (soap) | |
6946 soap_versioning(soap_init)(soap, imode, omode); | |
6947 return soap; | |
6948 } | |
6949 #endif | |
6950 | |
6951 /******************************************************************************/ | |
6952 #ifndef PALM_1 | |
6953 SOAP_FMAC1 | |
6954 void | |
6955 SOAP_FMAC2 | |
6956 soap_free(struct soap *soap) | |
6957 { soap_done(soap); | |
6958 free(soap); | |
6959 } | |
6960 #endif | |
6961 | |
6962 /******************************************************************************/ | |
6963 #ifndef PALM_1 | |
6964 SOAP_FMAC1 | |
6965 void | |
6966 SOAP_FMAC2 | |
6967 soap_del(struct soap *soap) | |
6968 { free(soap); | |
6969 } | |
6970 #endif | |
6971 | |
6972 /******************************************************************************/ | |
6973 #ifndef WITH_NOIDREF | |
6974 #ifndef PALM_1 | |
6975 static void | |
6976 soap_free_pht(struct soap *soap) | |
6977 { register struct soap_pblk *pb, *next; | |
6978 register int i; | |
6979 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free pointer hashtable\n")); | |
6980 for (pb = soap->pblk; pb; pb = next) | |
6981 { next = pb->next; | |
6982 SOAP_FREE(soap, pb); | |
6983 } | |
6984 soap->pblk = NULL; | |
6985 soap->pidx = 0; | |
6986 for (i = 0; i < (int)SOAP_PTRHASH; i++) | |
6987 soap->pht[i] = NULL; | |
6988 } | |
6989 #endif | |
6990 #endif | |
6991 | |
6992 /******************************************************************************/ | |
6993 #ifndef WITH_NOIDREF | |
6994 #ifndef PALM_2 | |
6995 SOAP_FMAC1 | |
6996 int | |
6997 SOAP_FMAC2 | |
6998 soap_embed(struct soap *soap, const void *p, const struct soap_array *a, int n, const char *tag, int type) | |
6999 { register int i; | |
7000 struct soap_plist *pp; | |
7001 (void)soap; | |
7002 if (soap->version == 2) | |
7003 soap->encoding = 1; | |
7004 if (a) | |
7005 i = soap_array_pointer_lookup(soap, p, a, n, type, &pp); | |
7006 else | |
7007 i = soap_pointer_lookup(soap, p, type, &pp); | |
7008 if (i) | |
7009 { if (soap_is_embedded(soap, pp) | |
7010 || soap_is_single(soap, pp)) | |
7011 return 0; | |
7012 soap_set_embedded(soap, pp); | |
7013 } | |
7014 return i; | |
7015 } | |
7016 #endif | |
7017 #endif | |
7018 | |
7019 /******************************************************************************/ | |
7020 #ifndef WITH_NOIDREF | |
7021 #ifndef PALM_2 | |
7022 SOAP_FMAC1 | |
7023 int | |
7024 SOAP_FMAC2 | |
7025 soap_pointer_lookup(struct soap *soap, const void *p, int type, struct soap_plist **ppp) | |
7026 { register struct soap_plist *pp; | |
7027 *ppp = NULL; | |
7028 if (p) | |
7029 { for (pp = soap->pht[soap_hash_ptr(p)]; pp; pp = pp->next) | |
7030 { if (pp->ptr == p && pp->type == type) | |
7031 { *ppp = pp; | |
7032 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d id=%d\n", p, type, pp->id)); | |
7033 return pp->id; | |
7034 } | |
7035 } | |
7036 } | |
7037 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d: not found\n", p, type)); | |
7038 return 0; | |
7039 } | |
7040 #endif | |
7041 #endif | |
7042 | |
7043 /******************************************************************************/ | |
7044 #ifndef WITH_NOIDREF | |
7045 #ifndef PALM_2 | |
7046 SOAP_FMAC1 | |
7047 int | |
7048 SOAP_FMAC2 | |
7049 soap_pointer_enter(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp) | |
7050 { register size_t h; | |
7051 register struct soap_plist *pp; | |
7052 (void)n; | |
7053 if (!soap->pblk || soap->pidx >= SOAP_PTRBLK) | |
7054 { register struct soap_pblk *pb = (struct soap_pblk*)SOAP_MALLOC(soap, sizeof(struct soap_pblk)); | |
7055 if (!pb) | |
7056 { soap->error = SOAP_EOM; | |
7057 return 0; | |
7058 } | |
7059 pb->next = soap->pblk; | |
7060 soap->pblk = pb; | |
7061 soap->pidx = 0; | |
7062 } | |
7063 *ppp = pp = &soap->pblk->plist[soap->pidx++]; | |
7064 if (a) | |
7065 h = soap_hash_ptr(a->__ptr); | |
7066 else | |
7067 h = soap_hash_ptr(p); | |
7068 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)); | |
7069 pp->next = soap->pht[h]; | |
7070 pp->type = type; | |
7071 pp->mark1 = 0; | |
7072 pp->mark2 = 0; | |
7073 pp->ptr = p; | |
7074 pp->array = a; | |
7075 soap->pht[h] = pp; | |
7076 pp->id = ++soap->idnum; | |
7077 return pp->id; | |
7078 } | |
7079 #endif | |
7080 #endif | |
7081 | |
7082 /******************************************************************************/ | |
7083 #ifndef WITH_NOIDREF | |
7084 #ifndef PALM_2 | |
7085 SOAP_FMAC1 | |
7086 int | |
7087 SOAP_FMAC2 | |
7088 soap_array_pointer_lookup(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp) | |
7089 { register struct soap_plist *pp; | |
7090 *ppp = NULL; | |
7091 if (!p || !a->__ptr) | |
7092 return 0; | |
7093 for (pp = soap->pht[soap_hash_ptr(a->__ptr)]; pp; pp = pp->next) | |
7094 { if (pp->type == type && pp->array && pp->array->__ptr == a->__ptr) | |
7095 { register int i; | |
7096 for (i = 0; i < n; i++) | |
7097 if (((const int*)&pp->array->__size)[i] != ((const int*)&a->__size)[i]) | |
7098 break; | |
7099 if (i == n) | |
7100 { *ppp = pp; | |
7101 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d id=%d\n", a->__ptr, type, pp->id)); | |
7102 return pp->id; | |
7103 } | |
7104 } | |
7105 } | |
7106 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d: not found\n", a->__ptr, type)); | |
7107 return 0; | |
7108 } | |
7109 #endif | |
7110 #endif | |
7111 | |
7112 /******************************************************************************/ | |
7113 #ifndef PALM_1 | |
7114 SOAP_FMAC1 | |
7115 int | |
7116 SOAP_FMAC2 | |
7117 soap_begin_count(struct soap *soap) | |
7118 { soap_free_ns(soap); | |
7119 #ifndef WITH_LEANER | |
7120 if ((soap->mode & SOAP_ENC_DIME) || (soap->omode & SOAP_ENC_DIME)) | |
7121 soap->mode = soap->omode | SOAP_IO_LENGTH | SOAP_ENC_DIME; | |
7122 else | |
7123 #endif | |
7124 { soap->mode = soap->omode; | |
7125 if ((soap->mode & SOAP_IO_UDP)) | |
7126 soap->mode |= SOAP_ENC_XML; | |
7127 if ((soap->mode & SOAP_IO) == SOAP_IO_STORE | |
7128 || (((soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_ENC_XML)) | |
7129 #ifndef WITH_LEANER | |
7130 && !soap->fpreparesend | |
7131 #endif | |
7132 )) | |
7133 soap->mode &= ~SOAP_IO_LENGTH; | |
7134 else | |
7135 soap->mode |= SOAP_IO_LENGTH; | |
7136 } | |
7137 #ifdef WITH_ZLIB | |
7138 if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH) | |
7139 { if (!(soap->mode & SOAP_ENC_DIME)) | |
7140 soap->mode &= ~SOAP_IO_LENGTH; | |
7141 if (soap->mode & SOAP_ENC_XML) | |
7142 soap->mode |= SOAP_IO_BUFFER; | |
7143 else | |
7144 soap->mode |= SOAP_IO_STORE; | |
7145 } | |
7146 #endif | |
7147 #ifndef WITH_LEANER | |
7148 if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME)) | |
7149 soap->mode |= SOAP_ENC_MIME; | |
7150 else if (!(soap->mode & SOAP_ENC_MIME)) | |
7151 soap->mode &= ~SOAP_ENC_MTOM; | |
7152 if (soap->mode & SOAP_ENC_MIME) | |
7153 soap_select_mime_boundary(soap); | |
7154 soap->dime.list = soap->dime.last; /* keep track of last DIME attachment */ | |
7155 #endif | |
7156 soap->count = 0; | |
7157 soap->ns = 0; | |
7158 soap->null = 0; | |
7159 soap->position = 0; | |
7160 soap->mustUnderstand = 0; | |
7161 soap->encoding = 0; | |
7162 soap->part = SOAP_BEGIN; | |
7163 soap->event = 0; | |
7164 soap->evlev = 0; | |
7165 soap->idnum = 0; | |
7166 soap_clr_attr(soap); | |
7167 soap_set_local_namespaces(soap); | |
7168 #ifndef WITH_LEANER | |
7169 soap->dime.count = 0; /* count # of attachments */ | |
7170 soap->dime.size = 0; /* accumulate total size of attachments */ | |
7171 if (soap->fprepareinitsend && (soap->mode & SOAP_IO) != SOAP_IO_STORE && (soap->error = soap->fprepareinitsend(soap))) | |
7172 return soap->error; | |
7173 #endif | |
7174 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)); | |
7175 return SOAP_OK; | |
7176 } | |
7177 #endif | |
7178 | |
7179 /******************************************************************************/ | |
7180 #ifndef PALM_1 | |
7181 SOAP_FMAC1 | |
7182 int | |
7183 SOAP_FMAC2 | |
7184 soap_end_count(struct soap *soap) | |
7185 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of count phase\n")); | |
7186 #ifndef WITH_LEANER | |
7187 if ((soap->mode & SOAP_IO_LENGTH)) | |
7188 { if (soap->fpreparefinalsend && (soap->error = soap->fpreparefinalsend(soap))) | |
7189 return soap->error; | |
7190 } | |
7191 #endif | |
7192 return SOAP_OK; | |
7193 } | |
7194 #endif | |
7195 | |
7196 /******************************************************************************/ | |
7197 #ifndef PALM_1 | |
7198 SOAP_FMAC1 | |
7199 int | |
7200 SOAP_FMAC2 | |
7201 soap_begin_send(struct soap *soap) | |
7202 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing for output to socket=%d/fd=%d\n", soap->socket, soap->sendfd)); | |
7203 soap_free_ns(soap); | |
7204 soap->error = SOAP_OK; | |
7205 soap->mode = soap->omode | (soap->mode & (SOAP_IO_LENGTH | SOAP_ENC_DIME)); | |
7206 #ifdef WITH_ZLIB | |
7207 if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH) | |
7208 { if (soap->mode & SOAP_ENC_XML) | |
7209 soap->mode |= SOAP_IO_BUFFER; | |
7210 else | |
7211 soap->mode |= SOAP_IO_STORE; | |
7212 } | |
7213 #endif | |
7214 #ifndef WITH_LEAN | |
7215 if ((soap->mode & SOAP_IO_UDP)) | |
7216 { soap->mode |= SOAP_ENC_XML; | |
7217 if (soap->count > SOAP_BUFLEN) | |
7218 return soap->error = SOAP_UDP_ERROR; | |
7219 } | |
7220 #endif | |
7221 if ((soap->mode & SOAP_IO) == SOAP_IO_FLUSH && soap_valid_socket(soap->socket)) | |
7222 { if (soap->count || (soap->mode & SOAP_IO_LENGTH) || (soap->mode & SOAP_ENC_XML)) | |
7223 soap->mode |= SOAP_IO_BUFFER; | |
7224 else | |
7225 soap->mode |= SOAP_IO_STORE; | |
7226 } | |
7227 soap->mode &= ~SOAP_IO_LENGTH; | |
7228 if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) | |
7229 if (soap_new_block(soap) == NULL) | |
7230 return soap->error; | |
7231 if (!(soap->mode & SOAP_IO_KEEPALIVE)) | |
7232 soap->keep_alive = 0; | |
7233 #ifndef WITH_LEANER | |
7234 if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME)) | |
7235 { soap->mode |= SOAP_ENC_MIME; | |
7236 soap->mode &= ~SOAP_ENC_DIME; | |
7237 } | |
7238 else if (!(soap->mode & SOAP_ENC_MIME)) | |
7239 soap->mode &= ~SOAP_ENC_MTOM; | |
7240 if (soap->mode & SOAP_ENC_MIME) | |
7241 soap_select_mime_boundary(soap); | |
7242 #ifdef WIN32 | |
7243 #ifndef UNDER_CE | |
7244 #ifndef WITH_FASTCGI | |
7245 if (!soap_valid_socket(soap->socket) && !soap->os) /* Set win32 stdout or soap->sendfd to BINARY, e.g. to support DIME */ | |
7246 #ifdef __BORLANDC__ | |
7247 setmode(soap->sendfd, _O_BINARY); | |
7248 #else | |
7249 _setmode(soap->sendfd, _O_BINARY); | |
7250 #endif | |
7251 #endif | |
7252 #endif | |
7253 #endif | |
7254 #endif | |
7255 if (soap->mode & SOAP_IO) | |
7256 { soap->bufidx = 0; | |
7257 soap->buflen = 0; | |
7258 } | |
7259 soap->chunksize = 0; | |
7260 soap->ns = 0; | |
7261 soap->null = 0; | |
7262 soap->position = 0; | |
7263 soap->mustUnderstand = 0; | |
7264 soap->encoding = 0; | |
7265 soap->idnum = 0; | |
7266 soap->level = 0; | |
7267 soap_clr_attr(soap); | |
7268 soap_set_local_namespaces(soap); | |
7269 #ifdef WITH_ZLIB | |
7270 soap->z_ratio_out = 1.0; | |
7271 if ((soap->mode & SOAP_ENC_ZLIB) && soap->zlib_state != SOAP_ZLIB_DEFLATE) | |
7272 { if (!soap->z_buf) | |
7273 soap->z_buf = (char*)SOAP_MALLOC(soap, SOAP_BUFLEN); | |
7274 soap->d_stream->next_out = (Byte*)soap->z_buf; | |
7275 soap->d_stream->avail_out = SOAP_BUFLEN; | |
7276 #ifdef WITH_GZIP | |
7277 if (soap->zlib_out != SOAP_ZLIB_DEFLATE) | |
7278 { memcpy(soap->z_buf, "\37\213\10\0\0\0\0\0\0\377", 10); | |
7279 soap->d_stream->next_out = (Byte*)soap->z_buf + 10; | |
7280 soap->d_stream->avail_out = SOAP_BUFLEN - 10; | |
7281 soap->z_crc = crc32(0L, NULL, 0); | |
7282 soap->zlib_out = SOAP_ZLIB_GZIP; | |
7283 if (soap->z_dict) | |
7284 *((Byte*)soap->z_buf + 2) = 0xff; | |
7285 if (deflateInit2(soap->d_stream, soap->z_level, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY) != Z_OK) | |
7286 return soap->error = SOAP_ZLIB_ERROR; | |
7287 } | |
7288 else | |
7289 #endif | |
7290 if (deflateInit(soap->d_stream, soap->z_level) != Z_OK) | |
7291 return soap->error = SOAP_ZLIB_ERROR; | |
7292 if (soap->z_dict) | |
7293 { if (deflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len) != Z_OK) | |
7294 return soap->error = SOAP_ZLIB_ERROR; | |
7295 } | |
7296 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflate initialized\n")); | |
7297 soap->zlib_state = SOAP_ZLIB_DEFLATE; | |
7298 } | |
7299 #endif | |
7300 #ifdef WITH_OPENSSL | |
7301 if (soap->ssl) | |
7302 ERR_clear_error(); | |
7303 #endif | |
7304 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin send phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count)); | |
7305 soap->part = SOAP_BEGIN; | |
7306 #ifndef WITH_LEANER | |
7307 if (soap->fprepareinitsend && (soap->mode & SOAP_IO) == SOAP_IO_STORE && (soap->error = soap->fprepareinitsend(soap))) | |
7308 return soap->error; | |
7309 #endif | |
7310 return SOAP_OK; | |
7311 } | |
7312 #endif | |
7313 | |
7314 /******************************************************************************/ | |
7315 #ifndef WITH_NOIDREF | |
7316 #ifndef PALM_2 | |
7317 SOAP_FMAC1 | |
7318 void | |
7319 SOAP_FMAC2 | |
7320 soap_embedded(struct soap *soap, const void *p, int t) | |
7321 { struct soap_plist *pp; | |
7322 if (soap_pointer_lookup(soap, p, t, &pp)) | |
7323 { pp->mark1 = 1; | |
7324 pp->mark2 = 1; | |
7325 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded %p type=%d mark set to 1\n", p, t)); | |
7326 } | |
7327 } | |
7328 #endif | |
7329 #endif | |
7330 | |
7331 /******************************************************************************/ | |
7332 #ifndef WITH_NOIDREF | |
7333 #ifndef PALM_2 | |
7334 SOAP_FMAC1 | |
7335 int | |
7336 SOAP_FMAC2 | |
7337 soap_reference(struct soap *soap, const void *p, int t) | |
7338 { struct soap_plist *pp; | |
7339 if (!p || (!soap->encodingStyle && !(soap->omode & (SOAP_ENC_DIME|SOAP_ENC_MIME|SOAP_ENC_MTOM|SOAP_XML_GRAPH))) || (soap->omode & SOAP_XML_TREE)) | |
7340 return 1; | |
7341 if (soap_pointer_lookup(soap, p, t, &pp)) | |
7342 { if (pp->mark1 == 0) | |
7343 { pp->mark1 = 2; | |
7344 pp->mark2 = 2; | |
7345 } | |
7346 } | |
7347 else if (!soap_pointer_enter(soap, p, NULL, 0, t, &pp)) | |
7348 return 1; | |
7349 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reference %p type=%d (%d %d)\n", p, t, (int)pp->mark1, (int)pp->mark2)); | |
7350 return pp->mark1; | |
7351 } | |
7352 #endif | |
7353 #endif | |
7354 | |
7355 /******************************************************************************/ | |
7356 #ifndef WITH_NOIDREF | |
7357 #ifndef PALM_2 | |
7358 SOAP_FMAC1 | |
7359 int | |
7360 SOAP_FMAC2 | |
7361 soap_array_reference(struct soap *soap, const void *p, const struct soap_array *a, int n, int t) | |
7362 { struct soap_plist *pp; | |
7363 if (!p || !a->__ptr || (!soap->encodingStyle && !(soap->omode & (SOAP_ENC_DIME|SOAP_ENC_MIME|SOAP_ENC_MTOM|SOAP_XML_GRAPH))) || (soap->omode & SOAP_XML_TREE)) | |
7364 return 1; | |
7365 if (soap_array_pointer_lookup(soap, p, a, n, t, &pp)) | |
7366 { if (pp->mark1 == 0) | |
7367 { pp->mark1 = 2; | |
7368 pp->mark2 = 2; | |
7369 } | |
7370 } | |
7371 else if (!soap_pointer_enter(soap, p, a, n, t, &pp)) | |
7372 return 1; | |
7373 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)); | |
7374 return pp->mark1; | |
7375 } | |
7376 #endif | |
7377 #endif | |
7378 | |
7379 /******************************************************************************/ | |
7380 #ifndef WITH_NOIDREF | |
7381 #ifndef PALM_2 | |
7382 SOAP_FMAC1 | |
7383 int | |
7384 SOAP_FMAC2 | |
7385 soap_embedded_id(struct soap *soap, int id, const void *p, int t) | |
7386 { struct soap_plist *pp = NULL; | |
7387 if (!id || (!soap->encodingStyle && !(soap->omode & SOAP_XML_GRAPH)) || (soap->omode & SOAP_XML_TREE)) | |
7388 return id; | |
7389 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id %p type=%d id=%d\n", p, t, id)); | |
7390 if (soap->version == 1 && soap->part != SOAP_IN_HEADER) | |
7391 { if (id < 0) | |
7392 { id = soap_pointer_lookup(soap, p, t, &pp); | |
7393 if (id) | |
7394 { if (soap->mode & SOAP_IO_LENGTH) | |
7395 pp->mark1 = 2; | |
7396 else | |
7397 pp->mark2 = 2; | |
7398 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)); | |
7399 } | |
7400 return -1; | |
7401 } | |
7402 return id; | |
7403 } | |
7404 if (id < 0) | |
7405 id = soap_pointer_lookup(soap, p, t, &pp); | |
7406 else if (id && !soap_pointer_lookup(soap, p, t, &pp)) | |
7407 return 0; | |
7408 if (id && pp) | |
7409 { if (soap->mode & SOAP_IO_LENGTH) | |
7410 pp->mark1 = 1; | |
7411 else | |
7412 pp->mark2 = 1; | |
7413 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)); | |
7414 } | |
7415 return id; | |
7416 } | |
7417 #endif | |
7418 #endif | |
7419 | |
7420 /******************************************************************************/ | |
7421 #ifndef WITH_NOIDREF | |
7422 #ifndef PALM_2 | |
7423 SOAP_FMAC1 | |
7424 int | |
7425 SOAP_FMAC2 | |
7426 soap_is_embedded(struct soap *soap, struct soap_plist *pp) | |
7427 { if (!pp) | |
7428 return 0; | |
7429 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Is embedded? %d %d\n", (int)pp->mark1, (int)pp->mark2)); | |
7430 if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER) | |
7431 { if (soap->mode & SOAP_IO_LENGTH) | |
7432 return pp->mark1 != 0; | |
7433 return pp->mark2 != 0; | |
7434 } | |
7435 if (soap->mode & SOAP_IO_LENGTH) | |
7436 return pp->mark1 == 1; | |
7437 return pp->mark2 == 1; | |
7438 } | |
7439 #endif | |
7440 #endif | |
7441 | |
7442 /******************************************************************************/ | |
7443 #ifndef WITH_NOIDREF | |
7444 #ifndef PALM_2 | |
7445 SOAP_FMAC1 | |
7446 int | |
7447 SOAP_FMAC2 | |
7448 soap_is_single(struct soap *soap, struct soap_plist *pp) | |
7449 { if (soap->part == SOAP_IN_HEADER) | |
7450 return 1; | |
7451 if (!pp) | |
7452 return 0; | |
7453 if (soap->mode & SOAP_IO_LENGTH) | |
7454 return pp->mark1 == 0; | |
7455 return pp->mark2 == 0; | |
7456 } | |
7457 #endif | |
7458 #endif | |
7459 | |
7460 /******************************************************************************/ | |
7461 #ifndef WITH_NOIDREF | |
7462 #ifndef PALM_2 | |
7463 SOAP_FMAC1 | |
7464 void | |
7465 SOAP_FMAC2 | |
7466 soap_set_embedded(struct soap *soap, struct soap_plist *pp) | |
7467 { if (!pp) | |
7468 return; | |
7469 if (soap->mode & SOAP_IO_LENGTH) | |
7470 pp->mark1 = 1; | |
7471 else | |
7472 pp->mark2 = 1; | |
7473 } | |
7474 #endif | |
7475 #endif | |
7476 | |
7477 /******************************************************************************/ | |
7478 #ifndef WITH_LEANER | |
7479 #ifndef PALM_1 | |
7480 SOAP_FMAC1 | |
7481 int | |
7482 SOAP_FMAC2 | |
7483 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) | |
7484 { | |
7485 #ifndef WITH_NOIDREF | |
7486 struct soap_plist *pp; | |
7487 int i; | |
7488 if (!p || !a->__ptr || (!aid && !atype)) | |
7489 return soap_element_id(soap, tag, id, p, a, n, type, t); | |
7490 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)); | |
7491 i = soap_array_pointer_lookup(soap, p, a, n, t, &pp); | |
7492 if (!i) | |
7493 { i = soap_pointer_enter(soap, p, a, n, t, &pp); | |
7494 if (!i) | |
7495 { soap->error = SOAP_EOM; | |
7496 return -1; | |
7497 } | |
7498 } | |
7499 if (id <= 0) | |
7500 id = i; | |
7501 if (!aid) | |
7502 { | |
7503 #ifdef HAVE_SNPRINTF | |
7504 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), soap->dime_id_format, id); | |
7505 #else | |
7506 sprintf(soap->tmpbuf, soap->dime_id_format, id); | |
7507 #endif | |
7508 aid = soap_strdup(soap, soap->tmpbuf); | |
7509 } | |
7510 /* Add MTOM xop:Include element when necessary */ | |
7511 /* TODO: this code to be obsoleted with new import/xop.h conventions */ | |
7512 if ((soap->mode & SOAP_ENC_MTOM) && strcmp(tag, "xop:Include")) | |
7513 { if (soap_element_begin_out(soap, tag, 0, type) | |
7514 || soap_element_href(soap, "xop:Include", 0, "xmlns:xop=\"http://www.w3.org/2004/08/xop/include\" href", aid) | |
7515 || soap_element_end_out(soap, tag)) | |
7516 return soap->error; | |
7517 } | |
7518 else if (soap_element_href(soap, tag, 0, "href", aid)) | |
7519 return soap->error; | |
7520 if (soap->mode & SOAP_IO_LENGTH) | |
7521 { if (pp->mark1 != 3) | |
7522 { struct soap_multipart *content; | |
7523 if (soap->mode & SOAP_ENC_MTOM) | |
7524 content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, (char*)a->__ptr, a->__size); | |
7525 else | |
7526 content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, (char*)a->__ptr, a->__size); | |
7527 if (!content) | |
7528 { soap->error = SOAP_EOM; | |
7529 return -1; | |
7530 } | |
7531 if (!strncmp(aid, "cid:", 4)) /* RFC 2111 */ | |
7532 { if (soap->mode & SOAP_ENC_MTOM) | |
7533 { char *s = (char*)soap_malloc(soap, strlen(aid) - 1); | |
7534 if (s) | |
7535 { *s = '<'; | |
7536 strcpy(s + 1, aid + 4); | |
7537 strcat(s, ">"); | |
7538 content->id = s; | |
7539 } | |
7540 } | |
7541 else | |
7542 content->id = aid + 4; | |
7543 } | |
7544 else | |
7545 content->id = aid; | |
7546 content->type = atype; | |
7547 content->options = aoptions; | |
7548 content->encoding = SOAP_MIME_BINARY; | |
7549 pp->mark1 = 3; | |
7550 } | |
7551 } | |
7552 else | |
7553 pp->mark2 = 3; | |
7554 #endif | |
7555 return -1; | |
7556 } | |
7557 #endif | |
7558 #endif | |
7559 | |
7560 /******************************************************************************/ | |
7561 #ifndef WITH_NOIDREF | |
7562 #ifndef PALM_1 | |
7563 static void | |
7564 soap_init_iht(struct soap *soap) | |
7565 { register int i; | |
7566 for (i = 0; i < SOAP_IDHASH; i++) | |
7567 soap->iht[i] = NULL; | |
7568 } | |
7569 #endif | |
7570 #endif | |
7571 | |
7572 /******************************************************************************/ | |
7573 #ifndef WITH_NOIDREF | |
7574 #ifndef PALM_1 | |
7575 static void | |
7576 soap_free_iht(struct soap *soap) | |
7577 { register int i; | |
7578 register struct soap_ilist *ip = NULL, *p = NULL; | |
7579 register struct soap_flist *fp = NULL, *fq = NULL; | |
7580 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free ID hashtable\n")); | |
7581 for (i = 0; i < SOAP_IDHASH; i++) | |
7582 { for (ip = soap->iht[i]; ip; ip = p) | |
7583 { for (fp = ip->flist; fp; fp = fq) | |
7584 { fq = fp->next; | |
7585 SOAP_FREE(soap, fp); | |
7586 } | |
7587 p = ip->next; | |
7588 SOAP_FREE(soap, ip); | |
7589 } | |
7590 soap->iht[i] = NULL; | |
7591 } | |
7592 } | |
7593 #endif | |
7594 #endif | |
7595 | |
7596 /******************************************************************************/ | |
7597 #ifndef WITH_NOIDREF | |
7598 #ifndef PALM_2 | |
7599 SOAP_FMAC1 | |
7600 struct soap_ilist * | |
7601 SOAP_FMAC2 | |
7602 soap_lookup(struct soap *soap, const char *id) | |
7603 { register struct soap_ilist *ip = NULL; | |
7604 for (ip = soap->iht[soap_hash(id)]; ip; ip = ip->next) | |
7605 if (!strcmp(ip->id, id)) | |
7606 return ip; | |
7607 return NULL; | |
7608 } | |
7609 #endif | |
7610 #endif | |
7611 | |
7612 /******************************************************************************/ | |
7613 #ifndef WITH_NOIDREF | |
7614 #ifndef PALM_2 | |
7615 SOAP_FMAC1 | |
7616 struct soap_ilist * | |
7617 SOAP_FMAC2 | |
7618 soap_enter(struct soap *soap, const char *id) | |
7619 { register size_t h; | |
7620 register struct soap_ilist *ip; | |
7621 ip = (struct soap_ilist*)SOAP_MALLOC(soap, sizeof(struct soap_ilist) + strlen(id)); | |
7622 if (ip) | |
7623 { strcpy((char*)ip->id, id); | |
7624 h = soap_hash(id); /* h = (HASH(id) % SOAP_IDHASH) so soap->iht[h] is safe */ | |
7625 ip->next = soap->iht[h]; | |
7626 soap->iht[h] = ip; | |
7627 } | |
7628 return ip; | |
7629 } | |
7630 #endif | |
7631 #endif | |
7632 | |
7633 /******************************************************************************/ | |
7634 #ifndef PALM_2 | |
7635 SOAP_FMAC1 | |
7636 void* | |
7637 SOAP_FMAC2 | |
7638 soap_malloc(struct soap *soap, size_t n) | |
7639 { register char *p; | |
7640 if (!n) | |
7641 return (void*)SOAP_NON_NULL; | |
7642 if (!soap) | |
7643 return SOAP_MALLOC(soap, n); | |
7644 if (soap->fmalloc) | |
7645 p = (char*)soap->fmalloc(soap, n); | |
7646 else | |
7647 { n += sizeof(short); | |
7648 n += (-(long)n) & (sizeof(void*)-1); /* align at 4-, 8- or 16-byte boundary */ | |
7649 if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(void*) + sizeof(size_t)))) | |
7650 { soap->error = SOAP_EOM; | |
7651 return NULL; | |
7652 } | |
7653 /* set the canary to detect corruption */ | |
7654 *(unsigned short*)(p + n - sizeof(unsigned short)) = (unsigned short)SOAP_CANARY; | |
7655 /* keep chain of alloced cells for destruction */ | |
7656 *(void**)(p + n) = soap->alist; | |
7657 *(size_t*)(p + n + sizeof(void*)) = n; | |
7658 soap->alist = p + n; | |
7659 } | |
7660 soap->alloced = 1; | |
7661 return p; | |
7662 } | |
7663 #endif | |
7664 | |
7665 /******************************************************************************/ | |
7666 #ifdef SOAP_MEM_DEBUG | |
7667 static void | |
7668 soap_init_mht(struct soap *soap) | |
7669 { register int i; | |
7670 for (i = 0; i < (int)SOAP_PTRHASH; i++) | |
7671 soap->mht[i] = NULL; | |
7672 } | |
7673 #endif | |
7674 | |
7675 /******************************************************************************/ | |
7676 #ifdef SOAP_MEM_DEBUG | |
7677 static void | |
7678 soap_free_mht(struct soap *soap) | |
7679 { register int i; | |
7680 register struct soap_mlist *mp, *mq; | |
7681 for (i = 0; i < (int)SOAP_PTRHASH; i++) | |
7682 { for (mp = soap->mht[i]; mp; mp = mq) | |
7683 { mq = mp->next; | |
7684 if (mp->live) | |
7685 fprintf(stderr, "%s(%d): malloc() = %p not freed (memory leak or forgot to call soap_end()?)\n", mp->file, mp->line, mp->ptr); | |
7686 free(mp); | |
7687 } | |
7688 soap->mht[i] = NULL; | |
7689 } | |
7690 } | |
7691 #endif | |
7692 | |
7693 /******************************************************************************/ | |
7694 #ifdef SOAP_MEM_DEBUG | |
7695 SOAP_FMAC1 | |
7696 void* | |
7697 SOAP_FMAC2 | |
7698 soap_track_malloc(struct soap *soap, const char *file, int line, size_t size) | |
7699 { register void *p = malloc(size); | |
7700 if (soap) | |
7701 { register size_t h = soap_hash_ptr(p); | |
7702 register struct soap_mlist *mp = (struct soap_mlist*)malloc(sizeof(struct soap_mlist)); | |
7703 if (soap->fdebug[SOAP_INDEX_TEST]) | |
7704 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): malloc(%lu) = %p\n", file, line, (unsigned long)size, p)); | |
7705 } | |
7706 mp->next = soap->mht[h]; | |
7707 mp->ptr = p; | |
7708 mp->file = file; | |
7709 mp->line = line; | |
7710 mp->live = 1; | |
7711 soap->mht[h] = mp; | |
7712 } | |
7713 return p; | |
7714 } | |
7715 #endif | |
7716 | |
7717 /******************************************************************************/ | |
7718 #ifdef SOAP_MEM_DEBUG | |
7719 SOAP_FMAC1 | |
7720 void | |
7721 SOAP_FMAC2 | |
7722 soap_track_free(struct soap *soap, const char *file, int line, void *p) | |
7723 { register size_t h = soap_hash_ptr(p); | |
7724 register struct soap_mlist *mp; | |
7725 for (mp = soap->mht[h]; mp; mp = mp->next) | |
7726 if (mp->ptr == p) | |
7727 break; | |
7728 if (mp) | |
7729 { if (mp->live) | |
7730 { free(p); | |
7731 if (soap->fdebug[SOAP_INDEX_TEST]) | |
7732 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): free(%p)\n", file, line, p)); | |
7733 } | |
7734 mp->live = 0; | |
7735 } | |
7736 else | |
7737 fprintf(stderr, "%s(%d): free(%p) double free of pointer malloced at %s(%d)\n", file, line, p, mp->file, mp->line); | |
7738 } | |
7739 else | |
7740 fprintf(stderr, "%s(%d): free(%p) pointer not malloced\n", file, line, p); | |
7741 } | |
7742 #endif | |
7743 | |
7744 /******************************************************************************/ | |
7745 #ifdef SOAP_MEM_DEBUG | |
7746 static void | |
7747 soap_track_unlink(struct soap *soap, const void *p) | |
7748 { register size_t h = soap_hash_ptr(p); | |
7749 register struct soap_mlist *mp; | |
7750 for (mp = soap->mht[h]; mp; mp = mp->next) | |
7751 if (mp->ptr == p) | |
7752 break; | |
7753 if (mp) | |
7754 mp->live = 0; | |
7755 } | |
7756 #endif | |
7757 | |
7758 /******************************************************************************/ | |
7759 #ifndef PALM_2 | |
7760 SOAP_FMAC1 | |
7761 void | |
7762 SOAP_FMAC2 | |
7763 soap_dealloc(struct soap *soap, void *p) | |
7764 { if (soap_check_state(soap)) | |
7765 return; | |
7766 if (p) | |
7767 { register char **q; | |
7768 for (q = (char**)&soap->alist; *q; q = *(char***)q) | |
7769 { | |
7770 if (*(unsigned short*)(char*)(*q - sizeof(unsigned short)) != (unsigned short)SOAP_CANARY) | |
7771 { | |
7772 #ifdef SOAP_MEM_DEBUG | |
7773 fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n"); | |
7774 #endif | |
7775 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n")); | |
7776 DBGHEX(TEST, *q - 200, 200); | |
7777 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n")); | |
7778 soap->error = SOAP_MOE; | |
7779 return; | |
7780 } | |
7781 if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*)))) | |
7782 { *q = **(char***)q; | |
7783 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Freed data at %p\n", p)); | |
7784 SOAP_FREE(soap, p); | |
7785 return; | |
7786 } | |
7787 } | |
7788 soap_delete(soap, p); | |
7789 } | |
7790 else | |
7791 { register char *q; | |
7792 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free all soap_malloc() data\n")); | |
7793 while (soap->alist) | |
7794 { q = (char*)soap->alist; | |
7795 if (*(unsigned short*)(char*)(q - sizeof(unsigned short)) != (unsigned short)SOAP_CANARY) | |
7796 { | |
7797 #ifdef SOAP_MEM_DEBUG | |
7798 fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n"); | |
7799 #endif | |
7800 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n")); | |
7801 DBGHEX(TEST, q - 200, 200); | |
7802 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n")); | |
7803 soap->error = SOAP_MOE; | |
7804 return; | |
7805 } | |
7806 soap->alist = *(void**)q; | |
7807 q -= *(size_t*)(q + sizeof(void*)); | |
7808 SOAP_FREE(soap, q); | |
7809 } | |
7810 /* we must assume these were deallocated: */ | |
7811 soap->http_content = NULL; | |
7812 soap->action = NULL; | |
7813 soap->fault = NULL; | |
7814 soap->header = NULL; | |
7815 soap->userid = NULL; | |
7816 soap->passwd = NULL; | |
7817 soap->authrealm = NULL; | |
7818 #ifdef WITH_NTLM | |
7819 soap->ntlm_challenge = NULL; | |
7820 #endif | |
7821 #ifndef WITH_LEANER | |
7822 soap_clr_mime(soap); | |
7823 #endif | |
7824 } | |
7825 } | |
7826 #endif | |
7827 | |
7828 /******************************************************************************/ | |
7829 #ifndef PALM_2 | |
7830 SOAP_FMAC1 | |
7831 void | |
7832 SOAP_FMAC2 | |
7833 soap_delete(struct soap *soap, void *p) | |
7834 { register struct soap_clist **cp; | |
7835 if (soap_check_state(soap)) | |
7836 return; | |
7837 cp = &soap->clist; | |
7838 if (p) | |
7839 { while (*cp) | |
7840 { if (p == (*cp)->ptr) | |
7841 { register struct soap_clist *q = *cp; | |
7842 *cp = q->next; | |
7843 if (q->fdelete(q)) | |
7844 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: deletion callback failed for object type %d\n", q->ptr, q->type)); | |
7845 #ifdef SOAP_MEM_DEBUG | |
7846 fprintf(stderr, "new(object type = %d) = %p not freed: deletion callback failed\n", q->type, q->ptr); | |
7847 #endif | |
7848 } | |
7849 SOAP_FREE(soap, q); | |
7850 return; | |
7851 } | |
7852 cp = &(*cp)->next; | |
7853 } | |
7854 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: address not in list\n", p)); | |
7855 } | |
7856 else | |
7857 { while (*cp) | |
7858 { register struct soap_clist *q = *cp; | |
7859 *cp = q->next; | |
7860 if (q->fdelete(q)) | |
7861 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: deletion callback failed for object type %d\n", q->ptr, q->type)); | |
7862 #ifdef SOAP_MEM_DEBUG | |
7863 fprintf(stderr, "new(object type = %d) = %p not freed: deletion callback failed\n", q->type, q->ptr); | |
7864 #endif | |
7865 } | |
7866 SOAP_FREE(soap, q); | |
7867 } | |
7868 } | |
7869 soap->fault = NULL; /* this was possibly deallocated */ | |
7870 soap->header = NULL; /* this was possibly deallocated */ | |
7871 } | |
7872 #endif | |
7873 | |
7874 /******************************************************************************/ | |
7875 #ifndef PALM_2 | |
7876 SOAP_FMAC1 | |
7877 void | |
7878 SOAP_FMAC2 | |
7879 soap_delegate_deletion(struct soap *soap, struct soap *soap_to) | |
7880 { register struct soap_clist *cp; | |
7881 register char **q; | |
7882 #ifdef SOAP_MEM_DEBUG | |
7883 register void *p; | |
7884 register struct soap_mlist **mp, *mq; | |
7885 size_t h; | |
7886 #endif | |
7887 for (q = (char**)&soap->alist; *q; q = *(char***)q) | |
7888 { | |
7889 if (*(unsigned short*)(char*)(*q - sizeof(unsigned short)) != (unsigned short)SOAP_CANARY) | |
7890 { | |
7891 #ifdef SOAP_MEM_DEBUG | |
7892 fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n"); | |
7893 #endif | |
7894 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n")); | |
7895 DBGHEX(TEST, *q - 200, 200); | |
7896 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n")); | |
7897 soap->error = SOAP_MOE; | |
7898 return; | |
7899 } | |
7900 #ifdef SOAP_MEM_DEBUG | |
7901 p = (void*)(*q - *(size_t*)(*q + sizeof(void*))); | |
7902 h = soap_hash_ptr(p); | |
7903 for (mp = &soap->mht[h]; *mp; mp = &(*mp)->next) | |
7904 { if ((*mp)->ptr == p) | |
7905 { mq = *mp; | |
7906 *mp = mq->next; | |
7907 mq->next = soap_to->mht[h]; | |
7908 soap_to->mht[h] = mq; | |
7909 break; | |
7910 } | |
7911 } | |
7912 #endif | |
7913 } | |
7914 *q = (char*)soap_to->alist; | |
7915 soap_to->alist = soap->alist; | |
7916 soap->alist = NULL; | |
7917 #ifdef SOAP_MEM_DEBUG | |
7918 cp = soap->clist; | |
7919 while (cp) | |
7920 { h = soap_hash_ptr(cp); | |
7921 for (mp = &soap->mht[h]; *mp; mp = &(*mp)->next) | |
7922 { if ((*mp)->ptr == cp) | |
7923 { mq = *mp; | |
7924 *mp = mq->next; | |
7925 mq->next = soap_to->mht[h]; | |
7926 soap_to->mht[h] = mq; | |
7927 break; | |
7928 } | |
7929 } | |
7930 cp = cp->next; | |
7931 } | |
7932 #endif | |
7933 cp = soap_to->clist; | |
7934 if (cp) | |
7935 { while (cp->next) | |
7936 cp = cp->next; | |
7937 cp->next = soap->clist; | |
7938 } | |
7939 else | |
7940 soap_to->clist = soap->clist; | |
7941 soap->clist = NULL; | |
7942 } | |
7943 #endif | |
7944 | |
7945 /******************************************************************************/ | |
7946 #ifndef PALM_2 | |
7947 SOAP_FMAC1 | |
7948 struct soap_clist * | |
7949 SOAP_FMAC2 | |
7950 soap_link(struct soap *soap, void *p, int t, int n, int (*fdelete)(struct soap_clist*)) | |
7951 { register struct soap_clist *cp; | |
7952 if ((cp = (struct soap_clist*)SOAP_MALLOC(soap, sizeof(struct soap_clist)))) | |
7953 { cp->next = soap->clist; | |
7954 cp->type = t; | |
7955 cp->size = n; | |
7956 cp->ptr = p; | |
7957 cp->fdelete = fdelete; | |
7958 soap->clist = cp; | |
7959 } | |
7960 return cp; | |
7961 } | |
7962 #endif | |
7963 | |
7964 /******************************************************************************/ | |
7965 #ifndef PALM_2 | |
7966 SOAP_FMAC1 | |
7967 int | |
7968 SOAP_FMAC2 | |
7969 soap_unlink(struct soap *soap, const void *p) | |
7970 { register char **q; | |
7971 register struct soap_clist **cp; | |
7972 if (soap && p) | |
7973 { for (q = (char**)&soap->alist; *q; q = *(char***)q) | |
7974 { if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*)))) | |
7975 { *q = **(char***)q; | |
7976 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked data %p\n", p)); | |
7977 #ifdef SOAP_MEM_DEBUG | |
7978 soap_track_unlink(soap, p); | |
7979 #endif | |
7980 return SOAP_OK; /* found and removed from dealloc chain */ | |
7981 } | |
7982 } | |
7983 for (cp = &soap->clist; *cp; cp = &(*cp)->next) | |
7984 { if (p == (*cp)->ptr) | |
7985 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked class instance %p\n", p)); | |
7986 q = (char**)*cp; | |
7987 *cp = (*cp)->next; | |
7988 SOAP_FREE(soap, q); | |
7989 return SOAP_OK; /* found and removed from dealloc chain */ | |
7990 } | |
7991 } | |
7992 } | |
7993 return SOAP_ERR; | |
7994 } | |
7995 #endif | |
7996 | |
7997 /******************************************************************************/ | |
7998 #ifndef WITH_NOIDREF | |
7999 #ifndef PALM_2 | |
8000 SOAP_FMAC1 | |
8001 int | |
8002 SOAP_FMAC2 | |
8003 soap_lookup_type(struct soap *soap, const char *id) | |
8004 { register struct soap_ilist *ip; | |
8005 if (id && *id) | |
8006 { ip = soap_lookup(soap, id); | |
8007 if (ip) | |
8008 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup id='%s' type=%d\n", id, ip->type)); | |
8009 return ip->type; | |
8010 } | |
8011 } | |
8012 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "lookup type id='%s' NOT FOUND! Need to get it from xsi:type\n", id)); | |
8013 return 0; | |
8014 } | |
8015 #endif | |
8016 #endif | |
8017 | |
8018 /******************************************************************************/ | |
8019 #ifndef WITH_NOIDREF | |
8020 #ifndef PALM_2 | |
8021 SOAP_FMAC1 | |
8022 void* | |
8023 SOAP_FMAC2 | |
8024 soap_id_lookup(struct soap *soap, const char *id, void **p, int t, size_t n, unsigned int k) | |
8025 { struct soap_ilist *ip; | |
8026 void **q; | |
8027 if (!p || !id || !*id) | |
8028 return p; | |
8029 ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */ | |
8030 if (!ip) | |
8031 { if (!(ip = soap_enter(soap, id))) /* new hash table entry for string id */ | |
8032 return NULL; | |
8033 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding first href='%s' type=%d %p (%u bytes)\n", id, t, p, (unsigned int)n)); | |
8034 ip->type = t; | |
8035 ip->size = n; | |
8036 ip->link = p; | |
8037 ip->copy = NULL; | |
8038 ip->flist = NULL; | |
8039 ip->ptr = NULL; | |
8040 ip->level = k; | |
8041 *p = NULL; | |
8042 } | |
8043 else if (ip->ptr) | |
8044 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolved href='%s' type=%d location=%p (%u bytes)\n", id, t, ip->ptr, (unsigned int)n)); | |
8045 if (ip->type != t) | |
8046 { strcpy(soap->id, id); | |
8047 soap->error = SOAP_HREF; | |
8048 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility: href='%s' id-type=%d href-type=%d\n", id, ip->type, t)); | |
8049 return NULL; | |
8050 } | |
8051 while (ip->level < k) | |
8052 { q = (void**)soap_malloc(soap, sizeof(void*)); | |
8053 if (!q) | |
8054 return NULL; | |
8055 *p = (void*)q; | |
8056 p = q; | |
8057 k--; | |
8058 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); | |
8059 } | |
8060 *p = ip->ptr; | |
8061 } | |
8062 else if (ip->level > k) | |
8063 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving level %u pointers to href='%s'\n", ip->level, id)); | |
8064 while (ip->level > k) | |
8065 { void *s, **r = &ip->link; | |
8066 q = (void**)ip->link; | |
8067 while (q) | |
8068 { *r = (void*)soap_malloc(soap, sizeof(void*)); | |
8069 if (!*r) | |
8070 return NULL; | |
8071 s = *q; | |
8072 *q = *r; | |
8073 r = (void**)*r; | |
8074 q = (void**)s; | |
8075 } | |
8076 *r = NULL; | |
8077 ip->size = n; | |
8078 ip->copy = NULL; | |
8079 ip->level = ip->level - 1; | |
8080 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); | |
8081 } | |
8082 q = (void**)ip->link; | |
8083 ip->link = p; | |
8084 *p = (void*)q; | |
8085 } | |
8086 else | |
8087 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarded href='%s' type=%d location=%p (%u bytes)\n", id, t, p, (unsigned int)n)); | |
8088 while (ip->level < k) | |
8089 { q = (void**)soap_malloc(soap, sizeof(void*)); | |
8090 if (!q) | |
8091 return NULL; | |
8092 *p = q; | |
8093 p = q; | |
8094 k--; | |
8095 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); | |
8096 } | |
8097 q = (void**)ip->link; | |
8098 ip->link = p; | |
8099 *p = (void*)q; | |
8100 } | |
8101 return p; | |
8102 } | |
8103 #endif | |
8104 #endif | |
8105 | |
8106 /******************************************************************************/ | |
8107 #ifndef WITH_NOIDREF | |
8108 #ifndef PALM_2 | |
8109 SOAP_FMAC1 | |
8110 void* | |
8111 SOAP_FMAC2 | |
8112 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)) | |
8113 { struct soap_ilist *ip; | |
8114 if (!p || !href || !*href) | |
8115 return p; | |
8116 ip = soap_lookup(soap, href); /* lookup pointer to hash table entry for string id */ | |
8117 if (!ip) | |
8118 { if (!(ip = soap_enter(soap, href))) /* new hash table entry for string id */ | |
8119 return NULL; | |
8120 ip->type = st; | |
8121 ip->size = n; | |
8122 ip->link = NULL; | |
8123 ip->copy = NULL; | |
8124 ip->ptr = NULL; | |
8125 ip->level = 0; | |
8126 ip->flist = NULL; | |
8127 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)); | |
8128 } | |
8129 else if (ip->type != st || (ip->level == k && ip->size != n)) | |
8130 { 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)); | |
8131 strcpy(soap->id, href); | |
8132 soap->error = SOAP_HREF; | |
8133 return NULL; | |
8134 } | |
8135 if (fcopy || n < sizeof(void*) || *href != '#') | |
8136 { register struct soap_flist *fp = (struct soap_flist*)SOAP_MALLOC(soap, sizeof(struct soap_flist)); | |
8137 if (!fp) | |
8138 { soap->error = SOAP_EOM; | |
8139 return NULL; | |
8140 } | |
8141 fp->next = ip->flist; | |
8142 fp->type = tt; | |
8143 fp->ptr = p; | |
8144 fp->level = k; | |
8145 fp->len = len; | |
8146 if (fcopy) | |
8147 fp->fcopy = fcopy; | |
8148 else | |
8149 fp->fcopy = soap_fcopy; | |
8150 ip->flist = fp; | |
8151 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)); | |
8152 } | |
8153 else | |
8154 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding copying address %p for type=%d href='%s'\n", p, st, href)); | |
8155 *(void**)p = ip->copy; | |
8156 ip->copy = p; | |
8157 } | |
8158 return p; | |
8159 } | |
8160 #endif | |
8161 #endif | |
8162 | |
8163 /******************************************************************************/ | |
8164 #ifndef PALM_2 | |
8165 SOAP_FMAC1 | |
8166 void* | |
8167 SOAP_FMAC2 | |
8168 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*)) | |
8169 { | |
8170 #ifndef WITH_NOIDREF | |
8171 struct soap_ilist *ip; | |
8172 #endif | |
8173 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Enter id='%s' type=%d loc=%p size=%lu level=%u\n", id, t, p, (unsigned long)n, k)); | |
8174 soap->alloced = 0; | |
8175 if (!p) | |
8176 { if (finstantiate) | |
8177 p = finstantiate(soap, t, type, arrayType, &n); | |
8178 else | |
8179 p = soap_malloc(soap, n); | |
8180 if (p) | |
8181 soap->alloced = 1; | |
8182 } | |
8183 #ifndef WITH_NOIDREF | |
8184 if (!id || !*id) | |
8185 #endif | |
8186 return p; | |
8187 #ifndef WITH_NOIDREF | |
8188 ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */ | |
8189 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Lookup entry id='%s for location=%p'\n", id, p)); | |
8190 if (!ip) | |
8191 { if (!(ip = soap_enter(soap, id))) /* new hash table entry for string id */ | |
8192 return NULL; | |
8193 ip->type = t; | |
8194 ip->link = NULL; | |
8195 ip->copy = NULL; | |
8196 ip->flist = NULL; | |
8197 ip->size = n; | |
8198 ip->ptr = p; | |
8199 ip->level = k; | |
8200 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)); | |
8201 } | |
8202 else if ((ip->type != t || (ip->level == k && ip->size != n)) && (ip->copy || ip->flist)) | |
8203 { 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)); | |
8204 strcpy(soap->id, id); | |
8205 soap->error = SOAP_HREF; | |
8206 return NULL; | |
8207 } | |
8208 else if (ip->ptr) | |
8209 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Multiply defined id='%s'\n", id)); | |
8210 strcpy(soap->id, id); | |
8211 soap->error = SOAP_DUPLICATE_ID; | |
8212 return NULL; | |
8213 } | |
8214 else | |
8215 { ip->size = n; | |
8216 ip->ptr = p; | |
8217 ip->level = k; | |
8218 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)); | |
8219 } | |
8220 return ip->ptr; | |
8221 #endif | |
8222 } | |
8223 #endif | |
8224 | |
8225 /******************************************************************************/ | |
8226 #ifndef PALM_2 | |
8227 SOAP_FMAC1 | |
8228 void | |
8229 SOAP_FMAC2 | |
8230 soap_fcopy(struct soap *soap, int st, int tt, void *p, size_t len, const void *q, size_t n) | |
8231 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Copying data type=%d (target type=%d) %p -> %p (%lu bytes)\n", st, tt, q, p, (unsigned long)n)); | |
8232 memcpy(p, q, n); | |
8233 (void)soap; (void)st; (void)tt; (void)len; | |
8234 } | |
8235 #endif | |
8236 | |
8237 /******************************************************************************/ | |
8238 #ifndef PALM_1 | |
8239 SOAP_FMAC1 | |
8240 int | |
8241 SOAP_FMAC2 | |
8242 soap_end_send(struct soap *soap) | |
8243 { | |
8244 #ifndef WITH_LEANER | |
8245 int err; | |
8246 if (soap->dime.list) | |
8247 { /* SOAP body referenced attachments must appear first */ | |
8248 soap->dime.last->next = soap->dime.first; | |
8249 soap->dime.first = soap->dime.list->next; | |
8250 soap->dime.list->next = NULL; | |
8251 soap->dime.last = soap->dime.list; | |
8252 } | |
8253 if (!(err = soap_putdime(soap))) | |
8254 err = soap_putmime(soap); | |
8255 soap->mime.list = NULL; | |
8256 soap->mime.first = NULL; | |
8257 soap->mime.last = NULL; | |
8258 soap->dime.list = NULL; | |
8259 soap->dime.first = NULL; | |
8260 soap->dime.last = NULL; | |
8261 if (err) | |
8262 return err; | |
8263 #endif | |
8264 return soap_end_send_flush(soap); | |
8265 } | |
8266 #endif | |
8267 | |
8268 /******************************************************************************/ | |
8269 #ifndef PALM_1 | |
8270 SOAP_FMAC1 | |
8271 int | |
8272 SOAP_FMAC2 | |
8273 soap_end_send_flush(struct soap *soap) | |
8274 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End send mode=0x%x\n", soap->mode)); | |
8275 if (soap->mode & SOAP_IO) /* need to flush the remaining data in buffer */ | |
8276 { if (soap_flush(soap)) | |
8277 #ifdef WITH_ZLIB | |
8278 { if (soap->mode & SOAP_ENC_ZLIB && soap->zlib_state == SOAP_ZLIB_DEFLATE) | |
8279 { soap->zlib_state = SOAP_ZLIB_NONE; | |
8280 deflateEnd(soap->d_stream); | |
8281 } | |
8282 return soap->error; | |
8283 } | |
8284 #else | |
8285 return soap->error; | |
8286 #endif | |
8287 #ifdef WITH_ZLIB | |
8288 if (soap->mode & SOAP_ENC_ZLIB) | |
8289 { int r; | |
8290 soap->d_stream->avail_in = 0; | |
8291 do | |
8292 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating remainder\n")); | |
8293 r = deflate(soap->d_stream, Z_FINISH); | |
8294 if (soap->d_stream->avail_out != SOAP_BUFLEN) | |
8295 { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN - soap->d_stream->avail_out)) | |
8296 { soap->zlib_state = SOAP_ZLIB_NONE; | |
8297 deflateEnd(soap->d_stream); | |
8298 return soap->error; | |
8299 } | |
8300 soap->d_stream->next_out = (Byte*)soap->z_buf; | |
8301 soap->d_stream->avail_out = SOAP_BUFLEN; | |
8302 } | |
8303 } while (r == Z_OK); | |
8304 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflated total %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out)); | |
8305 soap->z_ratio_out = (float)soap->d_stream->total_out / (float)soap->d_stream->total_in; | |
8306 soap->mode &= ~SOAP_ENC_ZLIB; | |
8307 soap->zlib_state = SOAP_ZLIB_NONE; | |
8308 if (deflateEnd(soap->d_stream) != Z_OK || r != Z_STREAM_END) | |
8309 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to end deflate: %s\n", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS)); | |
8310 return soap->error = SOAP_ZLIB_ERROR; | |
8311 } | |
8312 #ifdef WITH_GZIP | |
8313 if (soap->zlib_out != SOAP_ZLIB_DEFLATE) | |
8314 { soap->z_buf[0] = soap->z_crc & 0xFF; | |
8315 soap->z_buf[1] = (soap->z_crc >> 8) & 0xFF; | |
8316 soap->z_buf[2] = (soap->z_crc >> 16) & 0xFF; | |
8317 soap->z_buf[3] = (soap->z_crc >> 24) & 0xFF; | |
8318 soap->z_buf[4] = soap->d_stream->total_in & 0xFF; | |
8319 soap->z_buf[5] = (soap->d_stream->total_in >> 8) & 0xFF; | |
8320 soap->z_buf[6] = (soap->d_stream->total_in >> 16) & 0xFF; | |
8321 soap->z_buf[7] = (soap->d_stream->total_in >> 24) & 0xFF; | |
8322 if (soap_flush_raw(soap, soap->z_buf, 8)) | |
8323 return soap->error; | |
8324 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip crc32=%lu\n", (unsigned long)soap->z_crc)); | |
8325 } | |
8326 #endif | |
8327 } | |
8328 #endif | |
8329 if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) | |
8330 { char *p; | |
8331 #ifndef WITH_NOHTTP | |
8332 if (!(soap->mode & SOAP_ENC_XML)) | |
8333 { soap->mode--; | |
8334 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending buffered message of length %u\n", (unsigned int)soap->blist->size)); | |
8335 if (soap->status >= SOAP_POST) | |
8336 soap->error = soap->fpost(soap, soap->endpoint, soap->host, soap->port, soap->path, soap->action, soap->blist->size); | |
8337 else if (soap->status != SOAP_STOP) | |
8338 soap->error = soap->fresponse(soap, soap->status, soap->blist->size); | |
8339 if (soap->error || soap_flush(soap)) | |
8340 return soap->error; | |
8341 soap->mode++; | |
8342 } | |
8343 #endif | |
8344 for (p = soap_first_block(soap, NULL); p; p = soap_next_block(soap, NULL)) | |
8345 { DBGMSG(SENT, p, soap_block_size(soap, NULL)); | |
8346 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Send %u bytes to socket=%d/fd=%d\n", (unsigned int)soap_block_size(soap, NULL), soap->socket, soap->sendfd)); | |
8347 if ((soap->error = soap->fsend(soap, p, soap_block_size(soap, NULL)))) | |
8348 { soap_end_block(soap, NULL); | |
8349 return soap->error; | |
8350 } | |
8351 } | |
8352 soap_end_block(soap, NULL); | |
8353 if (soap->fpreparefinalsend && (soap->error = soap->fpreparefinalsend(soap))) | |
8354 return soap->error; | |
8355 } | |
8356 #ifndef WITH_LEANER | |
8357 else if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) | |
8358 { DBGMSG(SENT, "\r\n0\r\n\r\n", 7); | |
8359 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Send 7 bytes to socket=%d/fd=%d\n", soap->socket, soap->sendfd)); | |
8360 if ((soap->error = soap->fsend(soap, "\r\n0\r\n\r\n", 7))) | |
8361 return soap->error; | |
8362 } | |
8363 #endif | |
8364 } | |
8365 #ifdef WITH_TCPFIN | |
8366 #ifdef WITH_OPENSSL | |
8367 if (!soap->ssl && soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP)) | |
8368 soap->fshutdownsocket(soap, soap->socket, SOAP_SHUT_WR); /* Send TCP FIN */ | |
8369 #else | |
8370 if (soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP)) | |
8371 soap->fshutdownsocket(soap, soap->socket, SOAP_SHUT_WR); /* Send TCP FIN */ | |
8372 #endif | |
8373 #endif | |
8374 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of send phase\n")); | |
8375 soap->omode &= ~SOAP_SEC_WSUID; | |
8376 soap->count = 0; | |
8377 soap->part = SOAP_END; | |
8378 return SOAP_OK; | |
8379 } | |
8380 #endif | |
8381 | |
8382 /******************************************************************************/ | |
8383 #ifndef PALM_1 | |
8384 SOAP_FMAC1 | |
8385 int | |
8386 SOAP_FMAC2 | |
8387 soap_end_recv(struct soap *soap) | |
8388 { soap->part = SOAP_END; | |
8389 #ifndef WITH_LEAN | |
8390 soap->wsuid = NULL; /* reset before next send */ | |
8391 soap->c14nexclude = NULL; /* reset before next send */ | |
8392 #endif | |
8393 #ifndef WITH_LEANER | |
8394 soap->ffilterrecv = NULL; | |
8395 if ((soap->mode & SOAP_ENC_DIME) && soap_getdime(soap)) | |
8396 { soap->dime.first = NULL; | |
8397 soap->dime.last = NULL; | |
8398 return soap->error; | |
8399 } | |
8400 soap->dime.list = soap->dime.first; | |
8401 soap->dime.first = NULL; | |
8402 soap->dime.last = NULL; | |
8403 /* Check if MIME attachments and mime-post-check flag is set, if so call soap_resolve() and return */ | |
8404 if (soap->mode & SOAP_ENC_MIME) | |
8405 { if (soap->mode & SOAP_MIME_POSTCHECK) | |
8406 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Post checking MIME attachments\n")); | |
8407 if (!soap->keep_alive) | |
8408 soap->keep_alive = -1; | |
8409 #ifndef WITH_NOIDREF | |
8410 soap_resolve(soap); | |
8411 #endif | |
8412 return SOAP_OK; | |
8413 } | |
8414 if (soap_getmime(soap)) | |
8415 return soap->error; | |
8416 } | |
8417 soap->mime.list = soap->mime.first; | |
8418 soap->mime.first = NULL; | |
8419 soap->mime.last = NULL; | |
8420 soap->mime.boundary = NULL; | |
8421 if (soap->xlist) | |
8422 { struct soap_multipart *content; | |
8423 for (content = soap->mime.list; content; content = content->next) | |
8424 soap_resolve_attachment(soap, content); | |
8425 } | |
8426 #endif | |
8427 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "End of receive message ok\n")); | |
8428 #ifdef WITH_ZLIB | |
8429 if (soap->mode & SOAP_ENC_ZLIB) | |
8430 { /* Make sure end of compressed content is reached */ | |
8431 while (soap->d_stream->next_out != Z_NULL) | |
8432 if ((int)soap_get1(soap) == EOF) | |
8433 break; | |
8434 soap->mode &= ~SOAP_ENC_ZLIB; | |
8435 memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN); | |
8436 soap->bufidx = (char*)soap->d_stream->next_in - soap->z_buf; | |
8437 soap->buflen = soap->z_buflen; | |
8438 soap->zlib_state = SOAP_ZLIB_NONE; | |
8439 if (inflateEnd(soap->d_stream) != Z_OK) | |
8440 return soap->error = SOAP_ZLIB_ERROR; | |
8441 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Inflate end ok\n")); | |
8442 #ifdef WITH_GZIP | |
8443 if (soap->zlib_in == SOAP_ZLIB_GZIP) | |
8444 { soap_wchar c; | |
8445 short i; | |
8446 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Inflate gzip crc check\n")); | |
8447 for (i = 0; i < 8; i++) | |
8448 { if ((int)(c = soap_get1(soap)) == EOF) | |
8449 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: unable to read crc value\n")); | |
8450 return soap->error = SOAP_ZLIB_ERROR; | |
8451 } | |
8452 soap->z_buf[i] = (char)c; | |
8453 } | |
8454 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))) | |
8455 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip inflate error: crc check failed, message corrupted? (crc32=%lu)\n", (unsigned long)soap->z_crc)); | |
8456 return soap->error = SOAP_ZLIB_ERROR; | |
8457 } | |
8458 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))) | |
8459 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip inflate error: incorrect message length\n")); | |
8460 return soap->error = SOAP_ZLIB_ERROR; | |
8461 } | |
8462 } | |
8463 soap->zlib_in = SOAP_ZLIB_NONE; | |
8464 #endif | |
8465 } | |
8466 #endif | |
8467 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) | |
8468 while (soap->ahead != EOF && !soap_recv_raw(soap)) | |
8469 ; | |
8470 #ifndef WITH_NOIDREF | |
8471 if (soap_resolve(soap)) | |
8472 return soap->error; | |
8473 #endif | |
8474 #ifndef WITH_LEANER | |
8475 if (soap->xlist) | |
8476 { if (soap->mode & SOAP_ENC_MTOM) | |
8477 return soap->error = SOAP_MIME_HREF; | |
8478 return soap->error = SOAP_DIME_HREF; | |
8479 } | |
8480 #endif | |
8481 soap_free_ns(soap); | |
8482 #ifndef WITH_LEANER | |
8483 if (soap->fpreparefinalrecv) | |
8484 return soap->error = soap->fpreparefinalrecv(soap); | |
8485 #endif | |
8486 return SOAP_OK; | |
8487 } | |
8488 #endif | |
8489 | |
8490 /******************************************************************************/ | |
8491 #ifndef PALM_1 | |
8492 SOAP_FMAC1 | |
8493 void | |
8494 SOAP_FMAC2 | |
8495 soap_free_temp(struct soap *soap) | |
8496 { register struct soap_attribute *tp, *tq; | |
8497 register struct Namespace *ns; | |
8498 soap_free_ns(soap); | |
8499 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free any remaining temp blocks\n")); | |
8500 while (soap->blist) | |
8501 soap_end_block(soap, NULL); | |
8502 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute storage\n")); | |
8503 for (tp = soap->attributes; tp; tp = tq) | |
8504 { tq = tp->next; | |
8505 if (tp->value) | |
8506 SOAP_FREE(soap, tp->value); | |
8507 SOAP_FREE(soap, tp); | |
8508 } | |
8509 soap->attributes = NULL; | |
8510 #ifdef WITH_FAST | |
8511 if (soap->labbuf) | |
8512 SOAP_FREE(soap, soap->labbuf); | |
8513 soap->labbuf = NULL; | |
8514 soap->lablen = 0; | |
8515 soap->labidx = 0; | |
8516 #endif | |
8517 ns = soap->local_namespaces; | |
8518 if (ns) | |
8519 { for (; ns->id; ns++) | |
8520 { if (ns->out) | |
8521 { SOAP_FREE(soap, ns->out); | |
8522 ns->out = NULL; | |
8523 } | |
8524 } | |
8525 SOAP_FREE(soap, soap->local_namespaces); | |
8526 soap->local_namespaces = NULL; | |
8527 } | |
8528 #ifndef WITH_LEANER | |
8529 while (soap->xlist) | |
8530 { struct soap_xlist *xp = soap->xlist->next; | |
8531 SOAP_FREE(soap, soap->xlist); | |
8532 soap->xlist = xp; | |
8533 } | |
8534 #endif | |
8535 #ifndef WITH_NOIDREF | |
8536 soap_free_pht(soap); | |
8537 soap_free_iht(soap); | |
8538 #endif | |
8539 } | |
8540 #endif | |
8541 | |
8542 /******************************************************************************/ | |
8543 #ifndef PALM_1 | |
8544 static void | |
8545 soap_free_ns(struct soap *soap) | |
8546 { register struct soap_nlist *np, *nq; | |
8547 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free namespace stack\n")); | |
8548 for (np = soap->nlist; np; np = nq) | |
8549 { nq = np->next; | |
8550 SOAP_FREE(soap, np); | |
8551 } | |
8552 soap->nlist = NULL; | |
8553 } | |
8554 #endif | |
8555 | |
8556 /******************************************************************************/ | |
8557 #ifndef PALM_1 | |
8558 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG) | |
8559 static void | |
8560 soap_init_logs(struct soap *soap) | |
8561 { int i; | |
8562 for (i = 0; i < SOAP_MAXLOGS; i++) | |
8563 { soap->logfile[i] = NULL; | |
8564 soap->fdebug[i] = NULL; | |
8565 } | |
8566 } | |
8567 #endif | |
8568 #endif | |
8569 | |
8570 /******************************************************************************/ | |
8571 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG) | |
8572 SOAP_FMAC1 | |
8573 void | |
8574 SOAP_FMAC2 | |
8575 soap_open_logfile(struct soap *soap, int i) | |
8576 { if (soap->logfile[i]) | |
8577 soap->fdebug[i] = fopen(soap->logfile[i], i < 2 ? "ab" : "a"); | |
8578 } | |
8579 #endif | |
8580 | |
8581 /******************************************************************************/ | |
8582 #ifdef SOAP_DEBUG | |
8583 static void | |
8584 soap_close_logfile(struct soap *soap, int i) | |
8585 { if (soap->fdebug[i]) | |
8586 { fclose(soap->fdebug[i]); | |
8587 soap->fdebug[i] = NULL; | |
8588 } | |
8589 } | |
8590 #endif | |
8591 | |
8592 /******************************************************************************/ | |
8593 #ifdef SOAP_DEBUG | |
8594 SOAP_FMAC1 | |
8595 void | |
8596 SOAP_FMAC2 | |
8597 soap_close_logfiles(struct soap *soap) | |
8598 { int i; | |
8599 for (i = 0; i < SOAP_MAXLOGS; i++) | |
8600 soap_close_logfile(soap, i); | |
8601 } | |
8602 #endif | |
8603 | |
8604 /******************************************************************************/ | |
8605 #ifdef SOAP_DEBUG | |
8606 static void | |
8607 soap_set_logfile(struct soap *soap, int i, const char *logfile) | |
8608 { const char *s; | |
8609 char *t = NULL; | |
8610 soap_close_logfile(soap, i); | |
8611 s = soap->logfile[i]; | |
8612 soap->logfile[i] = logfile; | |
8613 if (s) | |
8614 SOAP_FREE(soap, (void*)s); | |
8615 if (logfile) | |
8616 if ((t = (char*)SOAP_MALLOC(soap, strlen(logfile) + 1))) | |
8617 strcpy(t, logfile); | |
8618 soap->logfile[i] = t; | |
8619 } | |
8620 #endif | |
8621 | |
8622 /******************************************************************************/ | |
8623 SOAP_FMAC1 | |
8624 void | |
8625 SOAP_FMAC2 | |
8626 soap_set_recv_logfile(struct soap *soap, const char *logfile) | |
8627 { | |
8628 #ifdef SOAP_DEBUG | |
8629 soap_set_logfile(soap, SOAP_INDEX_RECV, logfile); | |
8630 #endif | |
8631 } | |
8632 | |
8633 /******************************************************************************/ | |
8634 SOAP_FMAC1 | |
8635 void | |
8636 SOAP_FMAC2 | |
8637 soap_set_sent_logfile(struct soap *soap, const char *logfile) | |
8638 { | |
8639 #ifdef SOAP_DEBUG | |
8640 soap_set_logfile(soap, SOAP_INDEX_SENT, logfile); | |
8641 #endif | |
8642 } | |
8643 | |
8644 /******************************************************************************/ | |
8645 SOAP_FMAC1 | |
8646 void | |
8647 SOAP_FMAC2 | |
8648 soap_set_test_logfile(struct soap *soap, const char *logfile) | |
8649 { | |
8650 #ifdef SOAP_DEBUG | |
8651 soap_set_logfile(soap, SOAP_INDEX_TEST, logfile); | |
8652 #endif | |
8653 } | |
8654 | |
8655 /******************************************************************************/ | |
8656 #ifndef PALM_1 | |
8657 SOAP_FMAC1 | |
8658 struct soap* | |
8659 SOAP_FMAC2 | |
8660 soap_copy(const struct soap *soap) | |
8661 { return soap_copy_context((struct soap*)malloc(sizeof(struct soap)), soap); | |
8662 } | |
8663 #endif | |
8664 | |
8665 /******************************************************************************/ | |
8666 #ifndef PALM_1 | |
8667 SOAP_FMAC1 | |
8668 struct soap* | |
8669 SOAP_FMAC2 | |
8670 soap_copy_context(struct soap *copy, const struct soap *soap) | |
8671 { if (copy == soap) | |
8672 return copy; | |
8673 if (soap_check_state(soap)) | |
8674 return NULL; | |
8675 if (copy) | |
8676 { register struct soap_plugin *p = NULL; | |
8677 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying context\n")); | |
8678 #ifdef __cplusplus | |
8679 *copy = *soap; | |
8680 #else | |
8681 memcpy(copy, soap, sizeof(struct soap)); | |
8682 #endif | |
8683 copy->state = SOAP_COPY; | |
8684 copy->error = SOAP_OK; | |
8685 copy->userid = NULL; | |
8686 copy->passwd = NULL; | |
8687 #ifdef WITH_NTLM | |
8688 copy->ntlm_challenge = NULL; | |
8689 #endif | |
8690 copy->nlist = NULL; | |
8691 copy->blist = NULL; | |
8692 copy->clist = NULL; | |
8693 copy->alist = NULL; | |
8694 copy->attributes = NULL; | |
8695 copy->labbuf = NULL; | |
8696 copy->lablen = 0; | |
8697 copy->labidx = 0; | |
8698 #ifdef SOAP_MEM_DEBUG | |
8699 soap_init_mht(copy); | |
8700 #endif | |
8701 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG) | |
8702 soap_init_logs(copy); | |
8703 #endif | |
8704 #ifdef SOAP_DEBUG | |
8705 soap_set_test_logfile(copy, soap->logfile[SOAP_INDEX_TEST]); | |
8706 soap_set_sent_logfile(copy, soap->logfile[SOAP_INDEX_SENT]); | |
8707 soap_set_recv_logfile(copy, soap->logfile[SOAP_INDEX_RECV]); | |
8708 #endif | |
8709 copy->namespaces = soap->local_namespaces; | |
8710 copy->local_namespaces = NULL; | |
8711 soap_set_local_namespaces(copy); /* copy content of soap->local_namespaces */ | |
8712 copy->namespaces = soap->namespaces; /* point to shared read-only namespaces table */ | |
8713 #ifdef WITH_C_LOCALE | |
8714 # ifdef WIN32 | |
8715 copy->c_locale = _create_locale(LC_ALL, "C"); | |
8716 # else | |
8717 copy->c_locale = duplocale(soap->c_locale); | |
8718 # endif | |
8719 #else | |
8720 copy->c_locale = NULL; | |
8721 #endif | |
8722 #ifdef WITH_OPENSSL | |
8723 copy->bio = NULL; | |
8724 copy->ssl = NULL; | |
8725 copy->session = NULL; | |
8726 #endif | |
8727 #ifdef WITH_GNUTLS | |
8728 copy->session = NULL; | |
8729 #endif | |
8730 #ifdef WITH_ZLIB | |
8731 copy->d_stream = (z_stream*)SOAP_MALLOC(copy, sizeof(z_stream)); | |
8732 copy->d_stream->zalloc = Z_NULL; | |
8733 copy->d_stream->zfree = Z_NULL; | |
8734 copy->d_stream->opaque = Z_NULL; | |
8735 copy->z_buf = NULL; | |
8736 #endif | |
8737 #ifndef WITH_NOIDREF | |
8738 soap_init_iht(copy); | |
8739 soap_init_pht(copy); | |
8740 #endif | |
8741 copy->header = NULL; | |
8742 copy->fault = NULL; | |
8743 copy->action = NULL; | |
8744 #ifndef WITH_LEAN | |
8745 #ifdef WITH_COOKIES | |
8746 copy->cookies = soap_copy_cookies(copy, soap); | |
8747 #else | |
8748 copy->cookies = NULL; | |
8749 #endif | |
8750 #endif | |
8751 copy->plugins = NULL; | |
8752 for (p = soap->plugins; p; p = p->next) | |
8753 { register struct soap_plugin *q = (struct soap_plugin*)SOAP_MALLOC(copy, sizeof(struct soap_plugin)); | |
8754 if (!q) | |
8755 return NULL; | |
8756 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying plugin '%s'\n", p->id)); | |
8757 *q = *p; | |
8758 if (p->fcopy && p->fcopy(copy, q, p)) | |
8759 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not copy plugin '%s'\n", p->id)); | |
8760 SOAP_FREE(copy, q); | |
8761 return NULL; | |
8762 } | |
8763 q->next = copy->plugins; | |
8764 copy->plugins = q; | |
8765 } | |
8766 } | |
8767 return copy; | |
8768 } | |
8769 #endif | |
8770 | |
8771 /******************************************************************************/ | |
8772 #ifndef PALM_1 | |
8773 SOAP_FMAC1 | |
8774 void | |
8775 SOAP_FMAC2 | |
8776 soap_copy_stream(struct soap *copy, struct soap *soap) | |
8777 { struct soap_attribute *tp = NULL, *tq; | |
8778 if (copy == soap) | |
8779 return; | |
8780 copy->header = soap->header; | |
8781 copy->mode = soap->mode; | |
8782 copy->imode = soap->imode; | |
8783 copy->omode = soap->omode; | |
8784 copy->master = soap->master; | |
8785 copy->socket = soap->socket; | |
8786 copy->sendsk = soap->sendsk; | |
8787 copy->recvsk = soap->recvsk; | |
8788 copy->recv_timeout = soap->recv_timeout; | |
8789 copy->send_timeout = soap->send_timeout; | |
8790 #if defined(__cplusplus) && !defined(WITH_LEAN) | |
8791 copy->os = soap->os; | |
8792 copy->is = soap->is; | |
8793 #endif | |
8794 copy->sendfd = soap->sendfd; | |
8795 copy->recvfd = soap->recvfd; | |
8796 copy->bufidx = soap->bufidx; | |
8797 copy->buflen = soap->buflen; | |
8798 copy->ahead = soap->ahead; | |
8799 copy->cdata = soap->cdata; | |
8800 copy->chunksize = soap->chunksize; | |
8801 copy->chunkbuflen = soap->chunkbuflen; | |
8802 copy->keep_alive = soap->keep_alive; | |
8803 copy->tcp_keep_alive = soap->tcp_keep_alive; | |
8804 copy->tcp_keep_idle = soap->tcp_keep_idle; | |
8805 copy->tcp_keep_intvl = soap->tcp_keep_intvl; | |
8806 copy->tcp_keep_cnt = soap->tcp_keep_cnt; | |
8807 copy->max_keep_alive = soap->max_keep_alive; | |
8808 #ifndef WITH_NOIO | |
8809 copy->peer = soap->peer; | |
8810 copy->peerlen = soap->peerlen; | |
8811 copy->ip = soap->ip; | |
8812 copy->port = soap->port; | |
8813 memcpy(copy->host, soap->host, sizeof(soap->host)); | |
8814 memcpy(copy->endpoint, soap->endpoint, sizeof(soap->endpoint)); | |
8815 #endif | |
8816 #ifdef WITH_OPENSSL | |
8817 copy->bio = soap->bio; | |
8818 copy->ctx = soap->ctx; | |
8819 copy->ssl = soap->ssl; | |
8820 #endif | |
8821 #ifdef WITH_GNUTLS | |
8822 copy->session = soap->session; | |
8823 #endif | |
8824 #ifdef WITH_ZLIB | |
8825 copy->zlib_state = soap->zlib_state; | |
8826 copy->zlib_in = soap->zlib_in; | |
8827 copy->zlib_out = soap->zlib_out; | |
8828 if (!copy->d_stream) | |
8829 copy->d_stream = (z_stream*)SOAP_MALLOC(copy, sizeof(z_stream)); | |
8830 if (copy->d_stream) | |
8831 memcpy(copy->d_stream, soap->d_stream, sizeof(z_stream)); | |
8832 copy->z_crc = soap->z_crc; | |
8833 copy->z_ratio_in = soap->z_ratio_in; | |
8834 copy->z_ratio_out = soap->z_ratio_out; | |
8835 copy->z_buf = NULL; | |
8836 copy->z_buflen = soap->z_buflen; | |
8837 copy->z_level = soap->z_level; | |
8838 if (soap->z_buf && soap->zlib_state != SOAP_ZLIB_NONE) | |
8839 { copy->z_buf = (char*)SOAP_MALLOC(copy, SOAP_BUFLEN); | |
8840 if (copy->z_buf) | |
8841 memcpy(copy->z_buf, soap->z_buf, SOAP_BUFLEN); | |
8842 } | |
8843 copy->z_dict = soap->z_dict; | |
8844 copy->z_dict_len = soap->z_dict_len; | |
8845 #endif | |
8846 memcpy(copy->buf, soap->buf, sizeof(soap->buf)); | |
8847 /* copy XML parser state */ | |
8848 soap_free_ns(copy); | |
8849 soap_set_local_namespaces(copy); | |
8850 copy->version = soap->version; | |
8851 if (soap->nlist && soap->local_namespaces) | |
8852 { register struct soap_nlist *np = NULL, *nq; | |
8853 /* copy reversed nlist */ | |
8854 for (nq = soap->nlist; nq; nq = nq->next) | |
8855 { register struct soap_nlist *nr = np; | |
8856 size_t n = sizeof(struct soap_nlist) + strlen(nq->id); | |
8857 np = (struct soap_nlist*)SOAP_MALLOC(copy, n); | |
8858 if (!np) | |
8859 break; | |
8860 memcpy(np, nq, n); | |
8861 np->next = nr; | |
8862 } | |
8863 while (np) | |
8864 { register const char *s = np->ns; | |
8865 copy->level = np->level; /* preserve element nesting level */ | |
8866 if (!s && np->index >= 0) | |
8867 { s = soap->local_namespaces[np->index].out; | |
8868 if (!s) | |
8869 s = soap->local_namespaces[np->index].ns; | |
8870 } | |
8871 if (s && soap_push_namespace(copy, np->id, s) == NULL) | |
8872 break; | |
8873 nq = np; | |
8874 np = np->next; | |
8875 SOAP_FREE(copy, nq); | |
8876 } | |
8877 } | |
8878 memcpy(copy->tag, soap->tag, sizeof(copy->tag)); | |
8879 memcpy(copy->id, soap->id, sizeof(copy->id)); | |
8880 memcpy(copy->href, soap->href, sizeof(copy->href)); | |
8881 memcpy(copy->type, soap->type, sizeof(copy->type)); | |
8882 copy->other = soap->other; | |
8883 copy->root = soap->root; | |
8884 copy->null = soap->null; | |
8885 copy->body = soap->body; | |
8886 copy->part = soap->part; | |
8887 copy->mustUnderstand = soap->mustUnderstand; | |
8888 copy->level = soap->level; | |
8889 copy->peeked = soap->peeked; | |
8890 /* copy attributes */ | |
8891 for (tq = soap->attributes; tq; tq = tq->next) | |
8892 { struct soap_attribute *tr = tp; | |
8893 size_t n = sizeof(struct soap_attribute) + strlen(tq->name); | |
8894 tp = (struct soap_attribute*)SOAP_MALLOC(copy, n); | |
8895 memcpy(tp, tq, n); | |
8896 if (tp->size) | |
8897 { tp->value = (char*)SOAP_MALLOC(copy, tp->size); | |
8898 if (tp->value) | |
8899 strcpy(tp->value, tq->value); | |
8900 } | |
8901 tp->ns = NULL; | |
8902 tp->next = tr; | |
8903 } | |
8904 copy->attributes = tp; | |
8905 } | |
8906 #endif | |
8907 | |
8908 /******************************************************************************/ | |
8909 #ifndef PALM_1 | |
8910 SOAP_FMAC1 | |
8911 void | |
8912 SOAP_FMAC2 | |
8913 soap_free_stream(struct soap *soap) | |
8914 { soap->socket = SOAP_INVALID_SOCKET; | |
8915 soap->sendsk = SOAP_INVALID_SOCKET; | |
8916 soap->recvsk = SOAP_INVALID_SOCKET; | |
8917 #ifdef WITH_OPENSSL | |
8918 soap->bio = NULL; | |
8919 soap->ctx = NULL; | |
8920 soap->ssl = NULL; | |
8921 #endif | |
8922 #ifdef WITH_GNUTLS | |
8923 soap->xcred = NULL; | |
8924 soap->acred = NULL; | |
8925 soap->cache = NULL; | |
8926 soap->session = NULL; | |
8927 soap->dh_params = NULL; | |
8928 soap->rsa_params = NULL; | |
8929 #endif | |
8930 #ifdef WITH_ZLIB | |
8931 if (soap->z_buf) | |
8932 SOAP_FREE(soap, soap->z_buf); | |
8933 soap->z_buf = NULL; | |
8934 #endif | |
8935 } | |
8936 #endif | |
8937 | |
8938 /******************************************************************************/ | |
8939 #ifndef PALM_1 | |
8940 SOAP_FMAC1 | |
8941 void | |
8942 SOAP_FMAC2 | |
8943 soap_initialize(struct soap *soap) | |
8944 { soap_versioning(soap_init)(soap, SOAP_IO_DEFAULT, SOAP_IO_DEFAULT); | |
8945 } | |
8946 #endif | |
8947 | |
8948 /******************************************************************************/ | |
8949 #ifndef PALM_1 | |
8950 SOAP_FMAC1 | |
8951 void | |
8952 SOAP_FMAC2 | |
8953 soap_versioning(soap_init)(struct soap *soap, soap_mode imode, soap_mode omode) | |
8954 { size_t i; | |
8955 soap->state = SOAP_INIT; | |
8956 #ifdef SOAP_MEM_DEBUG | |
8957 soap_init_mht(soap); | |
8958 #endif | |
8959 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG) | |
8960 soap_init_logs(soap); | |
8961 #endif | |
8962 #ifdef SOAP_DEBUG | |
8963 #ifdef TANDEM_NONSTOP | |
8964 soap_set_test_logfile(soap, "TESTLOG"); | |
8965 soap_set_sent_logfile(soap, "SENTLOG"); | |
8966 soap_set_recv_logfile(soap, "RECVLOG"); | |
8967 #else | |
8968 soap_set_test_logfile(soap, "TEST.log"); | |
8969 soap_set_sent_logfile(soap, "SENT.log"); | |
8970 soap_set_recv_logfile(soap, "RECV.log"); | |
8971 #endif | |
8972 #endif | |
8973 soap->version = 0; | |
8974 soap_mode(soap, imode); | |
8975 soap_imode(soap, imode); | |
8976 soap_omode(soap, omode); | |
8977 soap->plugins = NULL; | |
8978 soap->user = NULL; | |
8979 for (i = 0; i < sizeof(soap->data)/sizeof(*soap->data); i++) | |
8980 soap->data[i] = NULL; | |
8981 soap->userid = NULL; | |
8982 soap->passwd = NULL; | |
8983 soap->authrealm = NULL; | |
8984 #ifdef WITH_NTLM | |
8985 soap->ntlm_challenge = NULL; | |
8986 #endif | |
8987 #ifndef WITH_NOHTTP | |
8988 soap->fpost = http_post; | |
8989 soap->fget = http_get; | |
8990 soap->fput = http_405; | |
8991 soap->fdel = http_405; | |
8992 soap->fopt = http_200; | |
8993 soap->fhead = http_200; | |
8994 soap->fform = NULL; | |
8995 soap->fposthdr = http_post_header; | |
8996 soap->fresponse = http_response; | |
8997 soap->fparse = http_parse; | |
8998 soap->fparsehdr = http_parse_header; | |
8999 #endif | |
9000 soap->fheader = NULL; | |
9001 soap->fconnect = NULL; | |
9002 soap->fdisconnect = NULL; | |
9003 #ifndef WITH_NOIO | |
9004 soap->ipv6_multicast_if = 0; /* in_addr_t value */ | |
9005 soap->ipv4_multicast_if = NULL; /* points to struct in_addr or in_addr_t */ | |
9006 soap->ipv4_multicast_ttl = 0; /* 0: use default */ | |
9007 #ifndef WITH_IPV6 | |
9008 soap->fresolve = tcp_gethost; | |
9009 #else | |
9010 soap->fresolve = NULL; | |
9011 #endif | |
9012 soap->faccept = tcp_accept; | |
9013 soap->fopen = tcp_connect; | |
9014 soap->fclose = tcp_disconnect; | |
9015 soap->fclosesocket = tcp_closesocket; | |
9016 soap->fshutdownsocket = tcp_shutdownsocket; | |
9017 soap->fsend = fsend; | |
9018 soap->frecv = frecv; | |
9019 soap->fpoll = soap_poll; | |
9020 #else | |
9021 soap->fopen = NULL; | |
9022 soap->fclose = NULL; | |
9023 soap->fpoll = NULL; | |
9024 #endif | |
9025 soap->fseterror = NULL; | |
9026 soap->fignore = NULL; | |
9027 soap->fserveloop = NULL; | |
9028 soap->fplugin = fplugin; | |
9029 soap->fmalloc = NULL; | |
9030 #ifndef WITH_LEANER | |
9031 soap->feltbegin = NULL; | |
9032 soap->feltendin = NULL; | |
9033 soap->feltbegout = NULL; | |
9034 soap->feltendout = NULL; | |
9035 soap->fprepareinitsend = NULL; | |
9036 soap->fprepareinitrecv = NULL; | |
9037 soap->fpreparesend = NULL; | |
9038 soap->fpreparerecv = NULL; | |
9039 soap->fpreparefinalsend = NULL; | |
9040 soap->fpreparefinalrecv = NULL; | |
9041 soap->ffiltersend = NULL; | |
9042 soap->ffilterrecv = NULL; | |
9043 soap->fdimereadopen = NULL; | |
9044 soap->fdimewriteopen = NULL; | |
9045 soap->fdimereadclose = NULL; | |
9046 soap->fdimewriteclose = NULL; | |
9047 soap->fdimeread = NULL; | |
9048 soap->fdimewrite = NULL; | |
9049 soap->fmimereadopen = NULL; | |
9050 soap->fmimewriteopen = NULL; | |
9051 soap->fmimereadclose = NULL; | |
9052 soap->fmimewriteclose = NULL; | |
9053 soap->fmimeread = NULL; | |
9054 soap->fmimewrite = NULL; | |
9055 #endif | |
9056 soap->float_format = "%.9G"; /* Alternative: use "%G" */ | |
9057 soap->double_format = "%.17lG"; /* Alternative: use "%lG" */ | |
9058 soap->dime_id_format = "cid:id%d"; /* default DIME id format */ | |
9059 soap->http_version = "1.1"; | |
9060 soap->proxy_http_version = "1.0"; | |
9061 soap->http_content = NULL; | |
9062 soap->actor = NULL; | |
9063 soap->lang = "en"; | |
9064 soap->keep_alive = 0; | |
9065 soap->tcp_keep_alive = 0; | |
9066 soap->tcp_keep_idle = 0; | |
9067 soap->tcp_keep_intvl = 0; | |
9068 soap->tcp_keep_cnt = 0; | |
9069 soap->max_keep_alive = SOAP_MAXKEEPALIVE; | |
9070 soap->recv_timeout = 0; | |
9071 soap->send_timeout = 0; | |
9072 soap->connect_timeout = 0; | |
9073 soap->accept_timeout = 0; | |
9074 soap->socket_flags = 0; | |
9075 soap->connect_flags = 0; | |
9076 soap->bind_flags = 0; | |
9077 soap->accept_flags = 0; | |
9078 soap->linger_time = 0; | |
9079 soap->ip = 0; | |
9080 soap->labbuf = NULL; | |
9081 soap->lablen = 0; | |
9082 soap->labidx = 0; | |
9083 soap->encodingStyle = NULL; | |
9084 #ifndef WITH_NONAMESPACES | |
9085 soap->namespaces = namespaces; | |
9086 #else | |
9087 soap->namespaces = NULL; | |
9088 #endif | |
9089 soap->local_namespaces = NULL; | |
9090 soap->nlist = NULL; | |
9091 soap->blist = NULL; | |
9092 soap->clist = NULL; | |
9093 soap->alist = NULL; | |
9094 soap->attributes = NULL; | |
9095 soap->header = NULL; | |
9096 soap->fault = NULL; | |
9097 soap->master = SOAP_INVALID_SOCKET; | |
9098 soap->socket = SOAP_INVALID_SOCKET; | |
9099 soap->sendsk = SOAP_INVALID_SOCKET; | |
9100 soap->recvsk = SOAP_INVALID_SOCKET; | |
9101 soap->os = NULL; | |
9102 soap->is = NULL; | |
9103 #ifndef WITH_LEANER | |
9104 soap->dom = NULL; | |
9105 soap->dime.list = NULL; | |
9106 soap->dime.first = NULL; | |
9107 soap->dime.last = NULL; | |
9108 soap->mime.list = NULL; | |
9109 soap->mime.first = NULL; | |
9110 soap->mime.last = NULL; | |
9111 soap->mime.boundary = NULL; | |
9112 soap->mime.start = NULL; | |
9113 soap->xlist = NULL; | |
9114 #endif | |
9115 #ifndef UNDER_CE | |
9116 soap->recvfd = 0; | |
9117 soap->sendfd = 1; | |
9118 #else | |
9119 soap->recvfd = stdin; | |
9120 soap->sendfd = stdout; | |
9121 #endif | |
9122 soap->host[0] = '\0'; | |
9123 soap->port = 0; | |
9124 soap->action = NULL; | |
9125 soap->proxy_host = NULL; | |
9126 soap->proxy_port = 8080; | |
9127 soap->proxy_userid = NULL; | |
9128 soap->proxy_passwd = NULL; | |
9129 soap->prolog = NULL; | |
9130 #ifdef WITH_ZLIB | |
9131 soap->zlib_state = SOAP_ZLIB_NONE; | |
9132 soap->zlib_in = SOAP_ZLIB_NONE; | |
9133 soap->zlib_out = SOAP_ZLIB_NONE; | |
9134 soap->d_stream = (z_stream*)SOAP_MALLOC(soap, sizeof(z_stream)); | |
9135 soap->d_stream->zalloc = Z_NULL; | |
9136 soap->d_stream->zfree = Z_NULL; | |
9137 soap->d_stream->opaque = Z_NULL; | |
9138 soap->z_buf = NULL; | |
9139 soap->z_level = 6; | |
9140 soap->z_dict = NULL; | |
9141 soap->z_dict_len = 0; | |
9142 #endif | |
9143 #ifndef WITH_LEAN | |
9144 soap->wsuid = NULL; | |
9145 soap->c14nexclude = NULL; | |
9146 soap->cookies = NULL; | |
9147 soap->cookie_domain = NULL; | |
9148 soap->cookie_path = NULL; | |
9149 soap->cookie_max = 32; | |
9150 #endif | |
9151 #ifdef WMW_RPM_IO | |
9152 soap->rpmreqid = NULL; | |
9153 #endif | |
9154 #ifdef PALM | |
9155 palmNetLibOpen(); | |
9156 #endif | |
9157 #ifndef WITH_NOIDREF | |
9158 soap_init_iht(soap); | |
9159 soap_init_pht(soap); | |
9160 #endif | |
9161 #ifdef WITH_OPENSSL | |
9162 if (!soap_ssl_init_done) | |
9163 soap_ssl_init(); | |
9164 soap->fsslauth = ssl_auth_init; | |
9165 soap->fsslverify = ssl_verify_callback; | |
9166 soap->bio = NULL; | |
9167 soap->ssl = NULL; | |
9168 soap->ctx = NULL; | |
9169 soap->session = NULL; | |
9170 soap->ssl_flags = SOAP_SSL_DEFAULT; | |
9171 soap->keyfile = NULL; | |
9172 soap->keyid = NULL; | |
9173 soap->password = NULL; | |
9174 soap->cafile = NULL; | |
9175 soap->capath = NULL; | |
9176 soap->crlfile = NULL; | |
9177 soap->dhfile = NULL; | |
9178 soap->randfile = NULL; | |
9179 #endif | |
9180 #ifdef WITH_GNUTLS | |
9181 if (!soap_ssl_init_done) | |
9182 soap_ssl_init(); | |
9183 soap->fsslauth = ssl_auth_init; | |
9184 soap->fsslverify = NULL; | |
9185 soap->xcred = NULL; | |
9186 soap->acred = NULL; | |
9187 soap->cache = NULL; | |
9188 soap->session = NULL; | |
9189 soap->ssl_flags = SOAP_SSL_DEFAULT; | |
9190 soap->keyfile = NULL; | |
9191 soap->keyid = NULL; | |
9192 soap->password = NULL; | |
9193 soap->cafile = NULL; | |
9194 soap->capath = NULL; | |
9195 soap->crlfile = NULL; | |
9196 soap->dh_params = NULL; | |
9197 soap->rsa_params = NULL; | |
9198 #endif | |
9199 #ifdef WITH_C_LOCALE | |
9200 # ifdef WIN32 | |
9201 soap->c_locale = _create_locale(LC_ALL, "C"); | |
9202 # else | |
9203 soap->c_locale = newlocale(LC_ALL_MASK, "C", NULL); | |
9204 # endif | |
9205 #else | |
9206 soap->c_locale = NULL; | |
9207 #endif | |
9208 soap->buflen = 0; | |
9209 soap->bufidx = 0; | |
9210 #ifndef WITH_LEANER | |
9211 soap->dime.chunksize = 0; | |
9212 soap->dime.buflen = 0; | |
9213 #endif | |
9214 soap->null = 0; | |
9215 soap->position = 0; | |
9216 soap->encoding = 0; | |
9217 soap->mustUnderstand = 0; | |
9218 soap->ns = 0; | |
9219 soap->part = SOAP_END; | |
9220 soap->event = 0; | |
9221 soap->evlev = 0; | |
9222 soap->alloced = 0; | |
9223 soap->count = 0; | |
9224 soap->length = 0; | |
9225 soap->cdata = 0; | |
9226 soap->peeked = 0; | |
9227 soap->ahead = 0; | |
9228 soap->idnum = 0; | |
9229 soap->level = 0; | |
9230 soap->endpoint[0] = '\0'; | |
9231 soap->error = SOAP_OK; | |
9232 } | |
9233 #endif | |
9234 | |
9235 /******************************************************************************/ | |
9236 #ifndef PALM_2 | |
9237 SOAP_FMAC1 | |
9238 void | |
9239 SOAP_FMAC2 | |
9240 soap_begin(struct soap *soap) | |
9241 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reinitializing context\n")); | |
9242 if (!soap->keep_alive) | |
9243 { soap->buflen = 0; | |
9244 soap->bufidx = 0; | |
9245 } | |
9246 soap->null = 0; | |
9247 soap->position = 0; | |
9248 soap->encoding = 0; | |
9249 soap->mustUnderstand = 0; | |
9250 soap->mode = 0; | |
9251 soap->ns = 0; | |
9252 soap->part = SOAP_END; | |
9253 soap->event = 0; | |
9254 soap->evlev = 0; | |
9255 soap->alloced = 0; | |
9256 soap->count = 0; | |
9257 soap->length = 0; | |
9258 soap->cdata = 0; | |
9259 soap->error = SOAP_OK; | |
9260 soap->peeked = 0; | |
9261 soap->ahead = 0; | |
9262 soap->idnum = 0; | |
9263 soap->level = 0; | |
9264 soap->endpoint[0] = '\0'; | |
9265 soap->encodingStyle = SOAP_STR_EOS; | |
9266 #ifndef WITH_LEANER | |
9267 soap->dime.chunksize = 0; | |
9268 soap->dime.buflen = 0; | |
9269 #endif | |
9270 soap_free_temp(soap); | |
9271 } | |
9272 #endif | |
9273 | |
9274 /******************************************************************************/ | |
9275 #ifndef PALM_2 | |
9276 SOAP_FMAC1 | |
9277 void | |
9278 SOAP_FMAC2 | |
9279 soap_end(struct soap *soap) | |
9280 { if (soap_check_state(soap)) | |
9281 return; | |
9282 soap_free_temp(soap); | |
9283 soap_dealloc(soap, NULL); | |
9284 while (soap->clist) | |
9285 { register struct soap_clist *cp = soap->clist->next; | |
9286 SOAP_FREE(soap, soap->clist); | |
9287 soap->clist = cp; | |
9288 } | |
9289 soap_closesock(soap); | |
9290 #ifdef SOAP_DEBUG | |
9291 soap_close_logfiles(soap); | |
9292 #endif | |
9293 #ifdef PALM | |
9294 palmNetLibClose(); | |
9295 #endif | |
9296 } | |
9297 #endif | |
9298 | |
9299 /******************************************************************************/ | |
9300 #ifndef PALM_1 | |
9301 SOAP_FMAC1 | |
9302 void | |
9303 SOAP_FMAC2 | |
9304 soap_set_version(struct soap *soap, short version) | |
9305 { soap_set_local_namespaces(soap); | |
9306 if (soap->version != version) | |
9307 { if (version == 1) | |
9308 { soap->local_namespaces[0].ns = soap_env1; | |
9309 soap->local_namespaces[1].ns = soap_enc1; | |
9310 } | |
9311 else if (version == 2) | |
9312 { soap->local_namespaces[0].ns = soap_env2; | |
9313 soap->local_namespaces[1].ns = soap_enc2; | |
9314 } | |
9315 soap->version = version; | |
9316 } | |
9317 } | |
9318 #endif | |
9319 | |
9320 /******************************************************************************/ | |
9321 #ifndef PALM_1 | |
9322 SOAP_FMAC1 | |
9323 int | |
9324 SOAP_FMAC2 | |
9325 soap_set_namespaces(struct soap *soap, const struct Namespace *p) | |
9326 { register struct Namespace *ns = soap->local_namespaces; | |
9327 register struct soap_nlist *np, *nq, *nr; | |
9328 register unsigned int level = soap->level; | |
9329 soap->namespaces = p; | |
9330 soap->local_namespaces = NULL; | |
9331 soap_set_local_namespaces(soap); | |
9332 /* reverse the namespace list */ | |
9333 np = soap->nlist; | |
9334 soap->nlist = NULL; | |
9335 if (np) | |
9336 { nq = np->next; | |
9337 np->next = NULL; | |
9338 while (nq) | |
9339 { nr = nq->next; | |
9340 nq->next = np; | |
9341 np = nq; | |
9342 nq = nr; | |
9343 } | |
9344 } | |
9345 /* then push on new stack */ | |
9346 while (np) | |
9347 { register const char *s; | |
9348 soap->level = np->level; /* preserve element nesting level */ | |
9349 s = np->ns; | |
9350 if (!s && np->index >= 0 && ns) | |
9351 { s = ns[np->index].out; | |
9352 if (!s) | |
9353 s = ns[np->index].ns; | |
9354 } | |
9355 if (s && soap_push_namespace(soap, np->id, s) == NULL) | |
9356 return soap->error; | |
9357 nq = np; | |
9358 np = np->next; | |
9359 SOAP_FREE(soap, nq); | |
9360 } | |
9361 if (ns) | |
9362 { register int i; | |
9363 for (i = 0; ns[i].id; i++) | |
9364 { if (ns[i].out) | |
9365 { SOAP_FREE(soap, ns[i].out); | |
9366 ns[i].out = NULL; | |
9367 } | |
9368 } | |
9369 SOAP_FREE(soap, ns); | |
9370 } | |
9371 soap->level = level; /* restore level */ | |
9372 return SOAP_OK; | |
9373 } | |
9374 #endif | |
9375 | |
9376 /******************************************************************************/ | |
9377 #ifndef PALM_1 | |
9378 SOAP_FMAC1 | |
9379 void | |
9380 SOAP_FMAC2 | |
9381 soap_set_local_namespaces(struct soap *soap) | |
9382 { if (soap->namespaces && !soap->local_namespaces) | |
9383 { register const struct Namespace *ns1; | |
9384 register struct Namespace *ns2; | |
9385 register size_t n = 1; | |
9386 for (ns1 = soap->namespaces; ns1->id; ns1++) | |
9387 n++; | |
9388 n *= sizeof(struct Namespace); | |
9389 ns2 = (struct Namespace*)SOAP_MALLOC(soap, n); | |
9390 if (ns2) | |
9391 { memcpy(ns2, soap->namespaces, n); | |
9392 if (ns2[0].ns) | |
9393 { if (!strcmp(ns2[0].ns, soap_env1)) | |
9394 soap->version = 1; | |
9395 else if (!strcmp(ns2[0].ns, soap_env2)) | |
9396 soap->version = 2; | |
9397 } | |
9398 soap->local_namespaces = ns2; | |
9399 for (; ns2->id; ns2++) | |
9400 ns2->out = NULL; | |
9401 } | |
9402 } | |
9403 } | |
9404 #endif | |
9405 | |
9406 /******************************************************************************/ | |
9407 #ifndef WITH_LEAN | |
9408 #ifndef PALM_1 | |
9409 SOAP_FMAC1 | |
9410 const char * | |
9411 SOAP_FMAC2 | |
9412 soap_tagsearch(const char *big, const char *little) | |
9413 { if (little) | |
9414 { register size_t n = strlen(little); | |
9415 register const char *s = big; | |
9416 while (s) | |
9417 { register const char *t = s; | |
9418 register size_t i; | |
9419 for (i = 0; i < n; i++, t++) | |
9420 { if (*t != little[i]) | |
9421 break; | |
9422 } | |
9423 if (*t == '\0' || *t == ' ') | |
9424 { if (i == n || (i && little[i-1] == ':')) | |
9425 return s; | |
9426 } | |
9427 s = strchr(t, ' '); | |
9428 if (s) | |
9429 s++; | |
9430 } | |
9431 } | |
9432 return NULL; | |
9433 } | |
9434 #endif | |
9435 #endif | |
9436 | |
9437 /******************************************************************************/ | |
9438 #ifndef WITH_LEAN | |
9439 #ifndef PALM_1 | |
9440 SOAP_FMAC1 | |
9441 struct soap_nlist * | |
9442 SOAP_FMAC2 | |
9443 soap_lookup_ns(struct soap *soap, const char *tag, size_t n) | |
9444 { register struct soap_nlist *np; | |
9445 for (np = soap->nlist; np; np = np->next) | |
9446 { if (!strncmp(np->id, tag, n) && !np->id[n]) | |
9447 return np; | |
9448 } | |
9449 return NULL; | |
9450 } | |
9451 #endif | |
9452 #endif | |
9453 | |
9454 /******************************************************************************/ | |
9455 #ifndef WITH_LEAN | |
9456 static struct soap_nlist * | |
9457 soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized) | |
9458 { register struct soap_nlist *np; | |
9459 size_t n, k; | |
9460 if (soap_tagsearch(soap->c14nexclude, id)) | |
9461 return NULL; | |
9462 if (!utilized) | |
9463 { for (np = soap->nlist; np; np = np->next) | |
9464 { if (!strcmp(np->id, id) && (!np->ns || !strcmp(np->ns, ns))) | |
9465 break; | |
9466 } | |
9467 if (np) | |
9468 { if ((np->level < soap->level || !np->ns) && np->index == 1) | |
9469 utilized = 1; | |
9470 else | |
9471 return NULL; | |
9472 } | |
9473 } | |
9474 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Adding namespace binding (level=%u) '%s' '%s' utilized=%d\n", soap->level, id, ns ? ns : "(null)", utilized)); | |
9475 n = strlen(id); | |
9476 if (ns) | |
9477 k = strlen(ns); | |
9478 else | |
9479 k = 0; | |
9480 np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k + 1); | |
9481 if (!np) | |
9482 { soap->error = SOAP_EOM; | |
9483 return NULL; | |
9484 } | |
9485 np->next = soap->nlist; | |
9486 soap->nlist = np; | |
9487 strcpy((char*)np->id, id); | |
9488 if (ns) | |
9489 np->ns = strcpy((char*)np->id + n + 1, ns); | |
9490 else | |
9491 np->ns = NULL; | |
9492 np->level = soap->level; | |
9493 np->index = utilized; | |
9494 return np; | |
9495 } | |
9496 #endif | |
9497 | |
9498 /******************************************************************************/ | |
9499 #ifndef WITH_LEAN | |
9500 static void | |
9501 soap_utilize_ns(struct soap *soap, const char *tag) | |
9502 { register struct soap_nlist *np; | |
9503 size_t n = 0; | |
9504 const char *t = strchr(tag, ':'); | |
9505 if (t) | |
9506 { n = t - tag; | |
9507 if (n >= sizeof(soap->tmpbuf)) | |
9508 n = sizeof(soap->tmpbuf) - 1; | |
9509 } | |
9510 np = soap_lookup_ns(soap, tag, n); | |
9511 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Utilizing namespace of '%s'\n", tag)); | |
9512 if (np) | |
9513 { if (np->index <= 0) | |
9514 soap_push_ns(soap, np->id, np->ns, 1); | |
9515 } | |
9516 else if (strncmp(tag, "xml", 3)) | |
9517 { strncpy(soap->tmpbuf, tag, n); | |
9518 soap->tmpbuf[n] = '\0'; | |
9519 soap_push_ns(soap, soap->tmpbuf, NULL, 1); | |
9520 } | |
9521 } | |
9522 #endif | |
9523 | |
9524 /******************************************************************************/ | |
9525 #ifndef PALM_2 | |
9526 SOAP_FMAC1 | |
9527 int | |
9528 SOAP_FMAC2 | |
9529 soap_element(struct soap *soap, const char *tag, int id, const char *type) | |
9530 { | |
9531 #ifndef WITH_LEAN | |
9532 register const char *s; | |
9533 #endif | |
9534 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element begin tag='%s' level='%u' id='%d' type='%s'\n", tag, soap->level, id, type ? type : SOAP_STR_EOS)); | |
9535 soap->level++; | |
9536 #ifdef WITH_DOM | |
9537 #ifndef WITH_LEAN | |
9538 if (soap->wsuid && soap_tagsearch(soap->wsuid, tag)) | |
9539 { size_t i; | |
9540 for (s = tag, i = 0; *s && i < sizeof(soap->tag) - 1; s++, i++) | |
9541 soap->tag[i] = *s == ':' ? '-' : *s; | |
9542 soap->tag[i] = '\0'; | |
9543 if (soap_set_attr(soap, "wsu:Id", soap->tag, 1)) | |
9544 return soap->error; | |
9545 } | |
9546 if ((soap->mode & SOAP_XML_CANONICAL) && !(soap->mode & SOAP_DOM_ASIS)) | |
9547 { if (soap->evlev >= soap->level) | |
9548 soap->evlev = 0; | |
9549 if (soap->event == SOAP_SEC_BEGIN && !soap->evlev) | |
9550 { register struct soap_nlist *np; | |
9551 /* non-nested wsu:Id found: clear xmlns, re-emit them for exc-c14n */ | |
9552 for (np = soap->nlist; np; np = np->next) | |
9553 { if (np->index == 2) | |
9554 { struct soap_nlist *np1 = soap_push_ns(soap, np->id, np->ns, 1); | |
9555 if (np1) | |
9556 np1->index = 0; | |
9557 } | |
9558 } | |
9559 soap->evlev = soap->level; | |
9560 } | |
9561 } | |
9562 #endif | |
9563 if (soap->mode & SOAP_XML_DOM) | |
9564 { register struct soap_dom_element *elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element)); | |
9565 if (!elt) | |
9566 return soap->error; | |
9567 elt->soap = soap; | |
9568 elt->next = NULL; | |
9569 elt->prnt = soap->dom; | |
9570 elt->name = soap_strdup(soap, tag); | |
9571 elt->elts = NULL; | |
9572 elt->atts = NULL; | |
9573 elt->nstr = NULL; | |
9574 elt->data = NULL; | |
9575 elt->wide = NULL; | |
9576 elt->node = NULL; | |
9577 elt->type = 0; | |
9578 elt->head = NULL; | |
9579 elt->tail = NULL; | |
9580 if (soap->dom) | |
9581 { struct soap_dom_element *p = soap->dom->elts; | |
9582 if (p) | |
9583 { while (p->next) | |
9584 p = p->next; | |
9585 p->next = elt; | |
9586 } | |
9587 else | |
9588 soap->dom->elts = elt; | |
9589 } | |
9590 soap->dom = elt; | |
9591 } | |
9592 else | |
9593 { | |
9594 #endif | |
9595 #ifndef WITH_LEAN | |
9596 if (!soap->ns) | |
9597 { if (!(soap->mode & SOAP_XML_CANONICAL) | |
9598 && soap_send(soap, soap->prolog ? soap->prolog : "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")) | |
9599 return soap->error; | |
9600 } | |
9601 else if (soap->mode & SOAP_XML_INDENT) | |
9602 { if (soap->ns == 1 && soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1)) | |
9603 return soap->error; | |
9604 soap->body = 1; | |
9605 } | |
9606 if ((soap->mode & SOAP_XML_DEFAULTNS) && (s = strchr(tag, ':'))) | |
9607 { struct Namespace *ns = soap->local_namespaces; | |
9608 size_t n = s - tag; | |
9609 if (soap_send_raw(soap, "<", 1) | |
9610 || soap_send(soap, s + 1)) | |
9611 return soap->error; | |
9612 if (soap->nlist && !strncmp(soap->nlist->id, tag, n) && !soap->nlist->id[n]) | |
9613 ns = NULL; | |
9614 for (; ns && ns->id; ns++) | |
9615 { if (*ns->id && (ns->out || ns->ns) && !strncmp(ns->id, tag, n) && !ns->id[n]) | |
9616 { soap_push_ns(soap, ns->id, ns->out ? ns->out : ns->ns, 0); | |
9617 if (soap_attribute(soap, "xmlns", ns->out ? ns->out : ns->ns)) | |
9618 return soap->error; | |
9619 break; | |
9620 } | |
9621 } | |
9622 } | |
9623 else | |
9624 #endif | |
9625 if (soap_send_raw(soap, "<", 1) | |
9626 || soap_send(soap, tag)) | |
9627 return soap->error; | |
9628 #ifdef WITH_DOM | |
9629 } | |
9630 #endif | |
9631 if (!soap->ns) | |
9632 { struct Namespace *ns = soap->local_namespaces; | |
9633 int k = -1; | |
9634 if (ns) | |
9635 { | |
9636 #ifndef WITH_LEAN | |
9637 if ((soap->mode & SOAP_XML_DEFAULTNS)) | |
9638 { if (soap->version) | |
9639 k = 4; /* first four required entries */ | |
9640 else if (!(soap->mode & SOAP_XML_NOTYPE) || (soap->mode & SOAP_XML_NIL)) | |
9641 { ns += 2; | |
9642 k = 2; /* next two entries */ | |
9643 } | |
9644 else | |
9645 k = 0; /* no entries */ | |
9646 } | |
9647 #endif | |
9648 while (k-- && ns->id) | |
9649 { if (*ns->id && (ns->out || ns->ns)) | |
9650 { | |
9651 #ifdef HAVE_SNPRINTF | |
9652 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "xmlns:%s", ns->id); | |
9653 #else | |
9654 sprintf(soap->tmpbuf, "xmlns:%s", ns->id); | |
9655 #endif | |
9656 if (soap_attribute(soap, soap->tmpbuf, ns->out ? ns->out : ns->ns)) | |
9657 return soap->error; | |
9658 } | |
9659 ns++; | |
9660 } | |
9661 } | |
9662 } | |
9663 soap->ns = 1; /* namespace table control: ns = 0 or 2 to start, then 1 to stop dumping the table */ | |
9664 #ifndef WITH_LEAN | |
9665 if (soap->mode & SOAP_XML_CANONICAL) | |
9666 soap_utilize_ns(soap, tag); | |
9667 #endif | |
9668 if (id > 0) | |
9669 { | |
9670 #ifdef HAVE_SNPRINTF | |
9671 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "_%d", id); | |
9672 #else | |
9673 sprintf(soap->tmpbuf, "_%d", id); | |
9674 #endif | |
9675 if (soap->version == 2) | |
9676 { if (soap_attribute(soap, "SOAP-ENC:id", soap->tmpbuf)) | |
9677 return soap->error; | |
9678 } | |
9679 else if (soap_attribute(soap, "id", soap->tmpbuf)) | |
9680 return soap->error; | |
9681 } | |
9682 if (type && *type && !(soap->mode & SOAP_XML_NOTYPE) && soap->part != SOAP_IN_HEADER) | |
9683 { const char *t = type; | |
9684 #ifndef WITH_LEAN | |
9685 if (soap->mode & SOAP_XML_DEFAULTNS) | |
9686 { t = strchr(type, ':'); | |
9687 if (t) | |
9688 t++; | |
9689 else | |
9690 t = type; | |
9691 } | |
9692 #endif | |
9693 if (soap->attributes ? soap_set_attr(soap, "xsi:type", t, 1) : soap_attribute(soap, "xsi:type", t)) | |
9694 return soap->error; | |
9695 #ifndef WITH_LEAN | |
9696 if (soap->mode & SOAP_XML_CANONICAL) | |
9697 soap_utilize_ns(soap, type); | |
9698 #endif | |
9699 } | |
9700 if (soap->null && soap->position > 0) | |
9701 { register int i; | |
9702 #ifdef HAVE_SNPRINTF | |
9703 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf) - 1, "[%d", soap->positions[0]); | |
9704 #else | |
9705 sprintf(soap->tmpbuf, "[%d", soap->positions[0]); | |
9706 #endif | |
9707 for (i = 1; i < soap->position; i++) | |
9708 { register size_t l = strlen(soap->tmpbuf); | |
9709 #ifdef HAVE_SNPRINTF | |
9710 soap_snprintf(soap->tmpbuf + l, sizeof(soap->tmpbuf)-l-1, ",%d", soap->positions[i]); | |
9711 #else | |
9712 if (l + 13 < sizeof(soap->tmpbuf)) | |
9713 sprintf(soap->tmpbuf + l, ",%d", soap->positions[i]); | |
9714 #endif | |
9715 } | |
9716 strcat(soap->tmpbuf, "]"); | |
9717 if (soap_attribute(soap, "SOAP-ENC:position", soap->tmpbuf)) | |
9718 return soap->error; | |
9719 } | |
9720 if (soap->mustUnderstand) | |
9721 { if (soap->actor && *soap->actor) | |
9722 { if (soap_attribute(soap, soap->version == 2 ? "SOAP-ENV:role" : "SOAP-ENV:actor", soap->actor)) | |
9723 return soap->error; | |
9724 } | |
9725 if (soap_attribute(soap, "SOAP-ENV:mustUnderstand", soap->version == 2 ? "true" : "1")) | |
9726 return soap->error; | |
9727 soap->mustUnderstand = 0; | |
9728 } | |
9729 if (soap->encoding) | |
9730 { if (soap->encodingStyle && soap->local_namespaces && soap->local_namespaces[0].id && soap->local_namespaces[1].id) | |
9731 { if (!*soap->encodingStyle) | |
9732 { if (soap->local_namespaces[1].out) | |
9733 soap->encodingStyle = soap->local_namespaces[1].out; | |
9734 else | |
9735 soap->encodingStyle = soap->local_namespaces[1].ns; | |
9736 } | |
9737 if (soap->encodingStyle && soap_attribute(soap, "SOAP-ENV:encodingStyle", soap->encodingStyle)) | |
9738 return soap->error; | |
9739 } | |
9740 else | |
9741 soap->encodingStyle = NULL; | |
9742 soap->encoding = 0; | |
9743 } | |
9744 soap->null = 0; | |
9745 soap->position = 0; | |
9746 if (soap->event == SOAP_SEC_BEGIN) | |
9747 soap->event = 0; | |
9748 return SOAP_OK; | |
9749 } | |
9750 #endif | |
9751 | |
9752 /******************************************************************************/ | |
9753 #ifndef PALM_2 | |
9754 SOAP_FMAC1 | |
9755 int | |
9756 SOAP_FMAC2 | |
9757 soap_element_begin_out(struct soap *soap, const char *tag, int id, const char *type) | |
9758 { if (*tag == '-') | |
9759 return SOAP_OK; | |
9760 if (soap_element(soap, tag, id, type)) | |
9761 return soap->error; | |
9762 #ifdef WITH_DOM | |
9763 if (soap_element_start_end_out(soap, NULL)) | |
9764 return soap->error; | |
9765 if (soap->feltbegout) | |
9766 return soap->error = soap->feltbegout(soap, tag); | |
9767 return SOAP_OK; | |
9768 #else | |
9769 return soap_element_start_end_out(soap, NULL); | |
9770 #endif | |
9771 } | |
9772 #endif | |
9773 | |
9774 /******************************************************************************/ | |
9775 #ifndef PALM_2 | |
9776 #ifndef HAVE_STRRCHR | |
9777 SOAP_FMAC1 | |
9778 char* | |
9779 SOAP_FMAC2 | |
9780 soap_strrchr(const char *s, int t) | |
9781 { register char *r = NULL; | |
9782 while (*s) | |
9783 if (*s++ == t) | |
9784 r = (char*)s - 1; | |
9785 return r; | |
9786 } | |
9787 #endif | |
9788 #endif | |
9789 | |
9790 /******************************************************************************/ | |
9791 #ifndef PALM_2 | |
9792 #ifndef HAVE_STRTOL | |
9793 SOAP_FMAC1 | |
9794 long | |
9795 SOAP_FMAC2 | |
9796 soap_strtol(const char *s, char **t, int b) | |
9797 { register long n = 0; | |
9798 register int c; | |
9799 while (*s > 0 && *s <= 32) | |
9800 s++; | |
9801 if (b == 10) | |
9802 { short neg = 0; | |
9803 if (*s == '-') | |
9804 { s++; | |
9805 neg = 1; | |
9806 } | |
9807 else if (*s == '+') | |
9808 s++; | |
9809 while ((c = *s) && c >= '0' && c <= '9') | |
9810 { if (n >= 214748364 && (n > 214748364 || c >= '8')) | |
9811 break; | |
9812 n *= 10; | |
9813 n += c - '0'; | |
9814 s++; | |
9815 } | |
9816 if (neg) | |
9817 n = -n; | |
9818 } | |
9819 else /* assume b == 16 and value is always positive */ | |
9820 { while ((c = *s)) | |
9821 { if (c >= '0' && c <= '9') | |
9822 c -= '0'; | |
9823 else if (c >= 'A' && c <= 'F') | |
9824 c -= 'A' - 10; | |
9825 else if (c >= 'a' && c <= 'f') | |
9826 c -= 'a' - 10; | |
9827 if (n > 0x07FFFFFF) | |
9828 break; | |
9829 n <<= 4; | |
9830 n += c; | |
9831 s++; | |
9832 } | |
9833 } | |
9834 if (t) | |
9835 *t = (char*)s; | |
9836 return n; | |
9837 } | |
9838 #endif | |
9839 #endif | |
9840 | |
9841 /******************************************************************************/ | |
9842 #ifndef PALM_2 | |
9843 #ifndef HAVE_STRTOUL | |
9844 SOAP_FMAC1 | |
9845 unsigned long | |
9846 SOAP_FMAC2 | |
9847 soap_strtoul(const char *s, char **t, int b) | |
9848 { unsigned long n = 0; | |
9849 register int c; | |
9850 while (*s > 0 && *s <= 32) | |
9851 s++; | |
9852 if (b == 10) | |
9853 { if (*s == '+') | |
9854 s++; | |
9855 while ((c = *s) && c >= '0' && c <= '9') | |
9856 { if (n >= 429496729 && (n > 429496729 || c >= '6')) | |
9857 break; | |
9858 n *= 10; | |
9859 n += c - '0'; | |
9860 s++; | |
9861 } | |
9862 } | |
9863 else /* b == 16 */ | |
9864 { while ((c = *s)) | |
9865 { if (c >= '0' && c <= '9') | |
9866 c -= '0'; | |
9867 else if (c >= 'A' && c <= 'F') | |
9868 c -= 'A' - 10; | |
9869 else if (c >= 'a' && c <= 'f') | |
9870 c -= 'a' - 10; | |
9871 if (n > 0x0FFFFFFF) | |
9872 break; | |
9873 n <<= 4; | |
9874 n += c; | |
9875 s++; | |
9876 } | |
9877 } | |
9878 if (t) | |
9879 *t = (char*)s; | |
9880 return n; | |
9881 } | |
9882 #endif | |
9883 #endif | |
9884 | |
9885 /******************************************************************************/ | |
9886 #ifndef PALM_1 | |
9887 SOAP_FMAC1 | |
9888 int | |
9889 SOAP_FMAC2 | |
9890 soap_array_begin_out(struct soap *soap, const char *tag, int id, const char *type, const char *offset) | |
9891 { if (!type || !*type) | |
9892 return soap_element_begin_out(soap, tag, id, NULL); | |
9893 if (soap_element(soap, tag, id, "SOAP-ENC:Array")) | |
9894 return soap->error; | |
9895 if (soap->version == 2) | |
9896 { const char *s; | |
9897 s = soap_strrchr(type, '['); | |
9898 if (s && (size_t)(s - type) < sizeof(soap->tmpbuf)) | |
9899 { strncpy(soap->tmpbuf, type, s - type); | |
9900 soap->tmpbuf[s - type] = '\0'; | |
9901 if (soap_attribute(soap, "SOAP-ENC:itemType", soap->tmpbuf)) | |
9902 return soap->error; | |
9903 s++; | |
9904 if (*s) | |
9905 { strncpy(soap->tmpbuf, s, sizeof(soap->tmpbuf)); | |
9906 soap->tmpbuf[sizeof(soap->tmpbuf) - 1] = '\0'; | |
9907 soap->tmpbuf[strlen(soap->tmpbuf) - 1] = '\0'; | |
9908 if (soap_attribute(soap, "SOAP-ENC:arraySize", soap->tmpbuf)) | |
9909 return soap->error; | |
9910 } | |
9911 } | |
9912 } | |
9913 else | |
9914 { if (offset && soap_attribute(soap, "SOAP-ENC:offset", offset)) | |
9915 return soap->error; | |
9916 if (soap_attribute(soap, "SOAP-ENC:arrayType", type)) | |
9917 return soap->error; | |
9918 } | |
9919 #ifndef WITH_LEAN | |
9920 if ((soap->mode & SOAP_XML_CANONICAL)) | |
9921 soap_utilize_ns(soap, type); | |
9922 #endif | |
9923 return soap_element_start_end_out(soap, NULL); | |
9924 } | |
9925 #endif | |
9926 | |
9927 /******************************************************************************/ | |
9928 #ifndef PALM_1 | |
9929 SOAP_FMAC1 | |
9930 int | |
9931 SOAP_FMAC2 | |
9932 soap_element_start_end_out(struct soap *soap, const char *tag) | |
9933 { register struct soap_attribute *tp; | |
9934 #ifndef WITH_LEAN | |
9935 if (soap->mode & SOAP_XML_CANONICAL) | |
9936 { struct soap_nlist *np; | |
9937 for (tp = soap->attributes; tp; tp = tp->next) | |
9938 { if (tp->visible && tp->name) | |
9939 soap_utilize_ns(soap, tp->name); | |
9940 } | |
9941 for (np = soap->nlist; np; np = np->next) | |
9942 { if (np->index == 1 && np->ns) | |
9943 { if (*(np->id)) | |
9944 { | |
9945 #ifdef HAVE_SNPRINTF | |
9946 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "xmlns:%s", np->id); | |
9947 #else | |
9948 sprintf(soap->tmpbuf, "xmlns:%s", np->id); | |
9949 #endif | |
9950 } | |
9951 else | |
9952 strcpy(soap->tmpbuf, "xmlns"); | |
9953 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enabling utilized binding (level=%u) %s='%s'\n", np->level, soap->tmpbuf, np->ns)); | |
9954 soap_set_attr(soap, soap->tmpbuf, np->ns, 1); | |
9955 np->index = 2; | |
9956 } | |
9957 } | |
9958 } | |
9959 #endif | |
9960 #ifdef WITH_DOM | |
9961 if ((soap->mode & SOAP_XML_DOM) && soap->dom) | |
9962 { register struct soap_dom_attribute **att; | |
9963 att = &soap->dom->atts; | |
9964 for (tp = soap->attributes; tp; tp = tp->next) | |
9965 { if (tp->visible) | |
9966 { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); | |
9967 if (!*att) | |
9968 return soap->error; | |
9969 (*att)->next = NULL; | |
9970 (*att)->nstr = NULL; | |
9971 (*att)->name = soap_strdup(soap, tp->name); | |
9972 (*att)->data = soap_strdup(soap, tp->value); | |
9973 (*att)->wide = NULL; | |
9974 (*att)->soap = soap; | |
9975 att = &(*att)->next; | |
9976 tp->visible = 0; | |
9977 } | |
9978 } | |
9979 return SOAP_OK; | |
9980 } | |
9981 #endif | |
9982 for (tp = soap->attributes; tp; tp = tp->next) | |
9983 { if (tp->visible) | |
9984 { | |
9985 #ifndef WITH_LEAN | |
9986 const char *s; | |
9987 if ((soap->mode & SOAP_XML_DEFAULTNS) && (s = strchr(tp->name, ':'))) | |
9988 { size_t n = s - tp->name; | |
9989 if (soap->nlist && !strncmp(soap->nlist->id, tp->name, n) && !soap->nlist->id[n]) | |
9990 s++; | |
9991 else | |
9992 s = tp->name; | |
9993 if (soap_send(soap, " ") || soap_send(soap, s)) | |
9994 return soap->error; | |
9995 } | |
9996 else | |
9997 #endif | |
9998 if (soap_send(soap, " ") || soap_send(soap, tp->name)) | |
9999 return soap->error; | |
10000 if (tp->visible == 2 && tp->value) | |
10001 if (soap_send_raw(soap, "=\"", 2) | |
10002 || soap_string_out(soap, tp->value, tp->flag) | |
10003 || soap_send_raw(soap, "\"", 1)) | |
10004 return soap->error; | |
10005 tp->visible = 0; | |
10006 } | |
10007 } | |
10008 if (tag) | |
10009 { | |
10010 #ifndef WITH_LEAN | |
10011 if (soap->mode & SOAP_XML_CANONICAL) | |
10012 { if (soap_send_raw(soap, ">", 1) | |
10013 || soap_element_end_out(soap, tag)) | |
10014 return soap->error; | |
10015 return SOAP_OK; | |
10016 } | |
10017 #endif | |
10018 soap->level--; /* decrement level just before /> */ | |
10019 return soap_send_raw(soap, "/>", 2); | |
10020 } | |
10021 return soap_send_raw(soap, ">", 1); | |
10022 } | |
10023 #endif | |
10024 | |
10025 /******************************************************************************/ | |
10026 #ifndef PALM_1 | |
10027 SOAP_FMAC1 | |
10028 int | |
10029 SOAP_FMAC2 | |
10030 soap_element_end_out(struct soap *soap, const char *tag) | |
10031 { | |
10032 #ifndef WITH_LEAN | |
10033 const char *s; | |
10034 #endif | |
10035 if (*tag == '-') | |
10036 return SOAP_OK; | |
10037 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element ending tag='%s'\n", tag)); | |
10038 #ifdef WITH_DOM | |
10039 if (soap->feltendout && (soap->error = soap->feltendout(soap, tag))) | |
10040 return soap->error; | |
10041 if ((soap->mode & SOAP_XML_DOM) && soap->dom) | |
10042 { if (soap->dom->prnt) | |
10043 soap->dom = soap->dom->prnt; | |
10044 return SOAP_OK; | |
10045 } | |
10046 #endif | |
10047 #ifndef WITH_LEAN | |
10048 if (soap->mode & SOAP_XML_CANONICAL) | |
10049 soap_pop_namespace(soap); | |
10050 if (soap->mode & SOAP_XML_INDENT) | |
10051 { if (!soap->body) | |
10052 { if (soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1)) | |
10053 return soap->error; | |
10054 } | |
10055 soap->body = 0; | |
10056 } | |
10057 if ((soap->mode & SOAP_XML_DEFAULTNS) && (s = strchr(tag, ':'))) | |
10058 { soap_pop_namespace(soap); | |
10059 tag = s + 1; | |
10060 } | |
10061 #endif | |
10062 if (soap_send_raw(soap, "</", 2) | |
10063 || soap_send(soap, tag)) | |
10064 return soap->error; | |
10065 soap->level--; /* decrement level just before > */ | |
10066 return soap_send_raw(soap, ">", 1); | |
10067 } | |
10068 #endif | |
10069 | |
10070 /******************************************************************************/ | |
10071 #ifndef PALM_1 | |
10072 SOAP_FMAC1 | |
10073 int | |
10074 SOAP_FMAC2 | |
10075 soap_element_ref(struct soap *soap, const char *tag, int id, int href) | |
10076 { register const char *s = "ref"; | |
10077 register int n = 1; | |
10078 if (soap->version == 1) | |
10079 { s = "href"; | |
10080 n = 0; | |
10081 } | |
10082 else if (soap->version == 2) | |
10083 s = "SOAP-ENC:ref"; | |
10084 #ifdef HAVE_SNPRINTF | |
10085 soap_snprintf(soap->href, sizeof(soap->href), "#_%d", href); | |
10086 #else | |
10087 sprintf(soap->href, "#_%d", href); | |
10088 #endif | |
10089 return soap_element_href(soap, tag, id, s, soap->href + n); | |
10090 } | |
10091 #endif | |
10092 | |
10093 /******************************************************************************/ | |
10094 #ifndef PALM_1 | |
10095 SOAP_FMAC1 | |
10096 int | |
10097 SOAP_FMAC2 | |
10098 soap_element_href(struct soap *soap, const char *tag, int id, const char *ref, const char *val) | |
10099 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element '%s' reference %s='%s'\n", tag, ref, val)); | |
10100 if (soap_element(soap, tag, id, NULL) | |
10101 || soap_attribute(soap, ref, val) | |
10102 || soap_element_start_end_out(soap, tag)) | |
10103 return soap->error; | |
10104 return SOAP_OK; | |
10105 } | |
10106 #endif | |
10107 | |
10108 /******************************************************************************/ | |
10109 #ifndef PALM_1 | |
10110 SOAP_FMAC1 | |
10111 int | |
10112 SOAP_FMAC2 | |
10113 soap_element_null(struct soap *soap, const char *tag, int id, const char *type) | |
10114 { struct soap_attribute *tp = NULL; | |
10115 for (tp = soap->attributes; tp; tp = tp->next) | |
10116 if (tp->visible) | |
10117 break; | |
10118 if (tp || (soap->version == 2 && soap->position > 0) || id > 0 || (soap->mode & SOAP_XML_NIL)) | |
10119 { if (soap_element(soap, tag, id, type) | |
10120 || (!tp && soap_attribute(soap, "xsi:nil", "true"))) | |
10121 return soap->error; | |
10122 return soap_element_start_end_out(soap, tag); | |
10123 } | |
10124 soap->null = 1; | |
10125 soap->position = 0; | |
10126 soap->mustUnderstand = 0; | |
10127 return SOAP_OK; | |
10128 } | |
10129 #endif | |
10130 | |
10131 /******************************************************************************/ | |
10132 #ifndef PALM_1 | |
10133 SOAP_FMAC1 | |
10134 int | |
10135 SOAP_FMAC2 | |
10136 soap_element_nil(struct soap *soap, const char *tag) | |
10137 { if (soap_element(soap, tag, -1, NULL) | |
10138 || ((soap->mode & SOAP_XML_NIL) && soap_attribute(soap, "xsi:nil", "true"))) | |
10139 return soap->error; | |
10140 return soap_element_start_end_out(soap, tag); | |
10141 } | |
10142 #endif | |
10143 | |
10144 /******************************************************************************/ | |
10145 #ifndef PALM_1 | |
10146 SOAP_FMAC1 | |
10147 int | |
10148 SOAP_FMAC2 | |
10149 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) | |
10150 { if (!p) | |
10151 { soap->error = soap_element_null(soap, tag, id, type); | |
10152 return -1; | |
10153 } | |
10154 #ifndef WITH_NOIDREF | |
10155 if ((!soap->encodingStyle && !(soap->omode & SOAP_XML_GRAPH)) || (soap->omode & SOAP_XML_TREE)) | |
10156 return 0; | |
10157 if (id < 0) | |
10158 { struct soap_plist *pp; | |
10159 if (a) | |
10160 id = soap_array_pointer_lookup(soap, p, a, n, t, &pp); | |
10161 else | |
10162 id = soap_pointer_lookup(soap, p, t, &pp); | |
10163 if (id) | |
10164 { if (soap_is_embedded(soap, pp)) | |
10165 { soap_element_ref(soap, tag, 0, id); | |
10166 return -1; | |
10167 } | |
10168 if (soap_is_single(soap, pp)) | |
10169 return 0; | |
10170 soap_set_embedded(soap, pp); | |
10171 } | |
10172 } | |
10173 return id; | |
10174 #else | |
10175 return 0; | |
10176 #endif | |
10177 } | |
10178 #endif | |
10179 | |
10180 /******************************************************************************/ | |
10181 #ifndef PALM_1 | |
10182 SOAP_FMAC1 | |
10183 int | |
10184 SOAP_FMAC2 | |
10185 soap_element_result(struct soap *soap, const char *tag) | |
10186 { if (soap->version == 2 && soap->encodingStyle) | |
10187 { if (soap_element(soap, "SOAP-RPC:result", 0, NULL) | |
10188 || soap_attribute(soap, "xmlns:SOAP-RPC", soap_rpc) | |
10189 || soap_element_start_end_out(soap, NULL) | |
10190 || soap_string_out(soap, tag, 0) | |
10191 || soap_element_end_out(soap, "SOAP-RPC:result")) | |
10192 return soap->error; | |
10193 } | |
10194 return SOAP_OK; | |
10195 } | |
10196 #endif | |
10197 | |
10198 /******************************************************************************/ | |
10199 #ifndef PALM_1 | |
10200 SOAP_FMAC1 | |
10201 void | |
10202 SOAP_FMAC2 | |
10203 soap_check_result(struct soap *soap, const char *tag) | |
10204 { if (soap->version == 2 && soap->encodingStyle) | |
10205 { soap_instring(soap, ":result", NULL, NULL, 0, 2, -1, -1); | |
10206 /* just ignore content for compliance reasons, but should compare tag to element's QName value? */ | |
10207 } | |
10208 (void)tag; | |
10209 } | |
10210 #endif | |
10211 | |
10212 /******************************************************************************/ | |
10213 #ifndef PALM_2 | |
10214 SOAP_FMAC1 | |
10215 int | |
10216 SOAP_FMAC2 | |
10217 soap_attribute(struct soap *soap, const char *name, const char *value) | |
10218 { | |
10219 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attribute '%s'='%s'\n", name, value)); | |
10220 #ifdef WITH_DOM | |
10221 if ((soap->mode & SOAP_XML_DOM) && !(soap->mode & SOAP_XML_CANONICAL) && soap->dom) | |
10222 { register struct soap_dom_attribute *a = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); | |
10223 if (!a) | |
10224 return soap->error; | |
10225 a->next = soap->dom->atts; | |
10226 a->nstr = NULL; | |
10227 a->name = soap_strdup(soap, name); | |
10228 a->data = soap_strdup(soap, value); | |
10229 a->wide = NULL; | |
10230 a->soap = soap; | |
10231 soap->dom->atts = a; | |
10232 return SOAP_OK; | |
10233 } | |
10234 #endif | |
10235 #ifndef WITH_LEAN | |
10236 if (soap->mode & SOAP_XML_CANONICAL) | |
10237 { /* push namespace */ | |
10238 if (!strncmp(name, "xmlns", 5) && (name[5] == ':' || name[5] == '\0')) | |
10239 soap_push_ns(soap, name + 5 + (name[5] == ':'), value, 0); | |
10240 else if (soap_set_attr(soap, name, value, 1)) | |
10241 return soap->error; | |
10242 } | |
10243 else | |
10244 #endif | |
10245 { if (soap_send(soap, " ") || soap_send(soap, name)) | |
10246 return soap->error; | |
10247 if (value) | |
10248 if (soap_send_raw(soap, "=\"", 2) | |
10249 || soap_string_out(soap, value, 1) | |
10250 || soap_send_raw(soap, "\"", 1)) | |
10251 return soap->error; | |
10252 } | |
10253 return SOAP_OK; | |
10254 } | |
10255 #endif | |
10256 | |
10257 /******************************************************************************/ | |
10258 #ifndef PALM_2 | |
10259 SOAP_FMAC1 | |
10260 int | |
10261 SOAP_FMAC2 | |
10262 soap_element_begin_in(struct soap *soap, const char *tag, int nillable, const char *type) | |
10263 { if (!soap_peek_element(soap)) | |
10264 { if (soap->other) | |
10265 return soap->error = SOAP_TAG_MISMATCH; | |
10266 if (tag && *tag == '-') | |
10267 return SOAP_OK; | |
10268 if (!(soap->error = soap_match_tag(soap, soap->tag, tag))) | |
10269 { soap->peeked = 0; | |
10270 if (type && *soap->type && soap_match_tag(soap, soap->type, type)) | |
10271 return soap->error = SOAP_TYPE; | |
10272 if (!nillable && soap->null && (soap->mode & SOAP_XML_STRICT)) | |
10273 return soap->error = SOAP_NULL; | |
10274 if (soap->body) | |
10275 soap->level++; | |
10276 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag ? tag : SOAP_STR_EOS )); | |
10277 soap->error = SOAP_OK; | |
10278 } | |
10279 } | |
10280 else if (soap->error == SOAP_NO_TAG && tag && *tag == '-') | |
10281 soap->error = SOAP_OK; | |
10282 return soap->error; | |
10283 } | |
10284 #endif | |
10285 | |
10286 /******************************************************************************/ | |
10287 #ifndef PALM_2 | |
10288 SOAP_FMAC1 | |
10289 int | |
10290 SOAP_FMAC2 | |
10291 soap_element_end_in(struct soap *soap, const char *tag) | |
10292 { register soap_wchar c; | |
10293 register char *s; | |
10294 register int n = 0; | |
10295 if (tag && *tag == '-') | |
10296 return SOAP_OK; | |
10297 if (soap->error == SOAP_NO_TAG) | |
10298 soap->error = SOAP_OK; | |
10299 #ifdef WITH_DOM | |
10300 /* this whitespace or mixed content is significant for DOM */ | |
10301 if ((soap->mode & SOAP_XML_DOM) && soap->dom) | |
10302 { if (!soap->peeked && !soap_string_in(soap, 3, -1, -1)) | |
10303 return soap->error; | |
10304 if (soap->dom->prnt) | |
10305 soap->dom = soap->dom->prnt; | |
10306 } | |
10307 #endif | |
10308 if (soap->peeked) | |
10309 { if (*soap->tag) | |
10310 n++; | |
10311 soap->peeked = 0; | |
10312 } | |
10313 do | |
10314 { while (((c = soap_get(soap)) != SOAP_TT)) | |
10315 { if ((int)c == EOF) | |
10316 return soap->error = SOAP_CHK_EOF; | |
10317 if (c == SOAP_LT) | |
10318 n++; | |
10319 else if (c == '/') | |
10320 { c = soap_get(soap); | |
10321 if (c == SOAP_GT) | |
10322 n--; | |
10323 else | |
10324 soap_unget(soap, c); | |
10325 } | |
10326 } | |
10327 } while (n--); | |
10328 s = soap->tag; | |
10329 n = sizeof(soap->tag); | |
10330 while (soap_notblank(c = soap_get(soap))) | |
10331 { if (--n > 0) | |
10332 *s++ = (char)c; | |
10333 } | |
10334 *s = '\0'; | |
10335 if ((int)c == EOF) | |
10336 return soap->error = SOAP_CHK_EOF; | |
10337 while (soap_blank(c)) | |
10338 c = soap_get(soap); | |
10339 if (c != SOAP_GT) | |
10340 return soap->error = SOAP_SYNTAX_ERROR; | |
10341 #ifndef WITH_LEAN | |
10342 #ifdef WITH_DOM | |
10343 if (soap->feltendin) | |
10344 { soap->level--; | |
10345 return soap->error = soap->feltendin(soap, soap->tag, tag); | |
10346 } | |
10347 #endif | |
10348 if (tag && (soap->mode & SOAP_XML_STRICT)) | |
10349 { soap_pop_namespace(soap); | |
10350 if (soap_match_tag(soap, soap->tag, tag)) | |
10351 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element tag '%s' does not match '%s'\n", soap->tag, tag ? tag : SOAP_STR_EOS)); | |
10352 return soap->error = SOAP_SYNTAX_ERROR; | |
10353 } | |
10354 } | |
10355 #endif | |
10356 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag ? tag : SOAP_STR_EOS)); | |
10357 soap->level--; | |
10358 return SOAP_OK; | |
10359 } | |
10360 #endif | |
10361 | |
10362 /******************************************************************************/ | |
10363 #ifndef PALM_2 | |
10364 SOAP_FMAC1 | |
10365 const char * | |
10366 SOAP_FMAC2 | |
10367 soap_attr_value(struct soap *soap, const char *name, int flag) | |
10368 { register struct soap_attribute *tp; | |
10369 if (*name == '-') | |
10370 return SOAP_STR_EOS; | |
10371 for (tp = soap->attributes; tp; tp = tp->next) | |
10372 { if (tp->visible && !soap_match_tag(soap, tp->name, name)) | |
10373 break; | |
10374 } | |
10375 if (tp) | |
10376 { if (flag == 2 && (soap->mode & SOAP_XML_STRICT)) | |
10377 soap->error = SOAP_PROHIBITED; | |
10378 else | |
10379 return tp->value; | |
10380 } | |
10381 else if (flag == 1 && (soap->mode & SOAP_XML_STRICT)) | |
10382 soap->error = SOAP_REQUIRED; | |
10383 else | |
10384 soap->error = SOAP_OK; | |
10385 return NULL; | |
10386 } | |
10387 #endif | |
10388 | |
10389 /******************************************************************************/ | |
10390 #ifndef PALM_2 | |
10391 SOAP_FMAC1 | |
10392 int | |
10393 SOAP_FMAC2 | |
10394 soap_set_attr(struct soap *soap, const char *name, const char *value, int flag) | |
10395 { register struct soap_attribute *tp; | |
10396 if (*name == '-') | |
10397 return SOAP_OK; | |
10398 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set attribute %s='%s'\n", name, value ? value : SOAP_STR_EOS)); | |
10399 for (tp = soap->attributes; tp; tp = tp->next) | |
10400 { if (!strcmp(tp->name, name)) | |
10401 break; | |
10402 } | |
10403 if (!tp) | |
10404 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute %s\n", name)); | |
10405 if (!(tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(name)))) | |
10406 return soap->error = SOAP_EOM; | |
10407 tp->ns = NULL; | |
10408 #ifndef WITH_LEAN | |
10409 if ((soap->mode & SOAP_XML_CANONICAL)) | |
10410 { struct soap_attribute **tpp = &soap->attributes; | |
10411 const char *s = strchr(name, ':'); | |
10412 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inserting attribute %s for c14n\n", name)); | |
10413 if (!strncmp(name, "xmlns", 5)) | |
10414 { for (; *tpp; tpp = &(*tpp)->next) | |
10415 if (strncmp((*tpp)->name, "xmlns", 5) || strcmp((*tpp)->name + 5, name + 5) > 0) | |
10416 break; | |
10417 } | |
10418 else if (!s) | |
10419 { for (; *tpp; tpp = &(*tpp)->next) | |
10420 if (strncmp((*tpp)->name, "xmlns", 5) && ((*tpp)->ns || strcmp((*tpp)->name, name) > 0)) | |
10421 break; | |
10422 } | |
10423 else | |
10424 { struct soap_nlist *np = soap_lookup_ns(soap, name, s - name); | |
10425 if (np) | |
10426 tp->ns = np->ns; | |
10427 else | |
10428 { struct soap_attribute *tq; | |
10429 for (tq = soap->attributes; tq; tq = tq->next) | |
10430 { if (!strncmp(tq->name, "xmlns:", 6) && !strncmp(tq->name + 6, name, s - name) && !tq->name[6 + s - name]) | |
10431 { tp->ns = tq->ns; | |
10432 break; | |
10433 } | |
10434 } | |
10435 } | |
10436 for (; *tpp; tpp = &(*tpp)->next) | |
10437 { int k; | |
10438 if (strncmp((*tpp)->name, "xmlns", 5) && (*tpp)->ns && tp->ns && ((k = strcmp((*tpp)->ns, tp->ns)) > 0 || (!k && strcmp((*tpp)->name, name) > 0))) | |
10439 break; | |
10440 } | |
10441 } | |
10442 tp->next = *tpp; | |
10443 *tpp = tp; | |
10444 } | |
10445 else | |
10446 #endif | |
10447 { tp->next = soap->attributes; | |
10448 soap->attributes = tp; | |
10449 } | |
10450 strcpy((char*)tp->name, name); | |
10451 tp->value = NULL; | |
10452 } | |
10453 else if (tp->visible) | |
10454 { return SOAP_OK; | |
10455 } | |
10456 else if (value && tp->value && tp->size <= strlen(value)) | |
10457 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute value of %s (free %p)\n", name, tp->value)); | |
10458 SOAP_FREE(soap, tp->value); | |
10459 tp->value = NULL; | |
10460 tp->ns = NULL; | |
10461 } | |
10462 if (value) | |
10463 { if (!tp->value) | |
10464 { tp->size = strlen(value) + 1; | |
10465 if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size))) | |
10466 return soap->error = SOAP_EOM; | |
10467 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute value for %s (%p)\n", tp->name, tp->value)); | |
10468 } | |
10469 strcpy(tp->value, value); | |
10470 if (!strncmp(tp->name, "xmlns:", 6)) | |
10471 tp->ns = tp->value; | |
10472 tp->visible = 2; | |
10473 tp->flag = (short)flag; | |
10474 #ifndef WITH_LEAN | |
10475 if (!strcmp(name, "wsu:Id")) | |
10476 { soap->event = SOAP_SEC_BEGIN; | |
10477 strncpy(soap->id, value, sizeof(soap->id)); | |
10478 soap->id[sizeof(soap->id) - 1] = '\0'; | |
10479 } | |
10480 #endif | |
10481 } | |
10482 else | |
10483 tp->visible = 1; | |
10484 return SOAP_OK; | |
10485 } | |
10486 #endif | |
10487 | |
10488 /******************************************************************************/ | |
10489 #ifndef PALM_2 | |
10490 SOAP_FMAC1 | |
10491 void | |
10492 SOAP_FMAC2 | |
10493 soap_clr_attr(struct soap *soap) | |
10494 { register struct soap_attribute *tp; | |
10495 #ifndef WITH_LEAN | |
10496 if ((soap->mode & SOAP_XML_CANONICAL)) | |
10497 { while (soap->attributes) | |
10498 { tp = soap->attributes->next; | |
10499 if (soap->attributes->value) | |
10500 SOAP_FREE(soap, soap->attributes->value); | |
10501 SOAP_FREE(soap, soap->attributes); | |
10502 soap->attributes = tp; | |
10503 } | |
10504 } | |
10505 else | |
10506 #endif | |
10507 { for (tp = soap->attributes; tp; tp = tp->next) | |
10508 tp->visible = 0; | |
10509 } | |
10510 } | |
10511 #endif | |
10512 | |
10513 /******************************************************************************/ | |
10514 #ifndef PALM_2 | |
10515 static int | |
10516 soap_getattrval(struct soap *soap, char *s, size_t n, soap_wchar d) | |
10517 { register size_t i; | |
10518 for (i = 0; i < n; i++) | |
10519 { register soap_wchar c = soap_get(soap); | |
10520 switch (c) | |
10521 { | |
10522 case SOAP_TT: | |
10523 *s++ = '<'; | |
10524 soap_unget(soap, '/'); | |
10525 break; | |
10526 case SOAP_LT: | |
10527 *s++ = '<'; | |
10528 break; | |
10529 case SOAP_GT: | |
10530 if (d == ' ') | |
10531 { soap_unget(soap, c); | |
10532 *s = '\0'; | |
10533 return SOAP_OK; | |
10534 } | |
10535 *s++ = '>'; | |
10536 break; | |
10537 case SOAP_QT: | |
10538 if (c == d) | |
10539 { *s = '\0'; | |
10540 return SOAP_OK; | |
10541 } | |
10542 *s++ = '"'; | |
10543 break; | |
10544 case SOAP_AP: | |
10545 if (c == d) | |
10546 { *s = '\0'; | |
10547 return SOAP_OK; | |
10548 } | |
10549 *s++ = '\''; | |
10550 break; | |
10551 case '\t': | |
10552 case '\n': | |
10553 case '\r': | |
10554 case ' ': | |
10555 case '/': | |
10556 if (d == ' ') | |
10557 { soap_unget(soap, c); | |
10558 *s = '\0'; | |
10559 return SOAP_OK; | |
10560 } | |
10561 default: | |
10562 if ((int)c == EOF) | |
10563 { *s = '\0'; | |
10564 return soap->error = SOAP_CHK_EOF; | |
10565 } | |
10566 *s++ = (char)c; | |
10567 } | |
10568 } | |
10569 return soap->error = SOAP_EOM; | |
10570 } | |
10571 #endif | |
10572 | |
10573 /******************************************************************************/ | |
10574 #ifdef WITH_FAST | |
10575 #ifndef PALM_2 | |
10576 SOAP_FMAC1 | |
10577 int | |
10578 SOAP_FMAC2 | |
10579 soap_store_lab(struct soap *soap, const char *s, size_t n) | |
10580 { soap->labidx = 0; | |
10581 return soap_append_lab(soap, s, n); | |
10582 } | |
10583 #endif | |
10584 #endif | |
10585 | |
10586 /******************************************************************************/ | |
10587 #ifdef WITH_FAST | |
10588 #ifndef PALM_2 | |
10589 SOAP_FMAC1 | |
10590 int | |
10591 SOAP_FMAC2 | |
10592 soap_append_lab(struct soap *soap, const char *s, size_t n) | |
10593 { if (soap->labidx + n >= soap->lablen) | |
10594 { register char *t = soap->labbuf; | |
10595 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enlarging look-aside buffer to append data, size=%lu\n", (unsigned long)soap->lablen)); | |
10596 if (soap->lablen == 0) | |
10597 soap->lablen = SOAP_LABLEN; | |
10598 while (soap->labidx + n >= soap->lablen) | |
10599 soap->lablen <<= 1; | |
10600 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New look-aside buffer size=%lu\n", (unsigned long)soap->lablen)); | |
10601 soap->labbuf = (char*)SOAP_MALLOC(soap, soap->lablen); | |
10602 if (!soap->labbuf) | |
10603 { if (t) | |
10604 SOAP_FREE(soap, t); | |
10605 return soap->error = SOAP_EOM; | |
10606 } | |
10607 if (t) | |
10608 { memcpy(soap->labbuf, t, soap->labidx); | |
10609 SOAP_FREE(soap, t); | |
10610 } | |
10611 } | |
10612 if (s) | |
10613 { memcpy(soap->labbuf + soap->labidx, s, n); | |
10614 soap->labidx += n; | |
10615 } | |
10616 return SOAP_OK; | |
10617 } | |
10618 #endif | |
10619 #endif | |
10620 | |
10621 /******************************************************************************/ | |
10622 #ifndef PALM_2 | |
10623 SOAP_FMAC1 | |
10624 int | |
10625 SOAP_FMAC2 | |
10626 soap_peek_element(struct soap *soap) | |
10627 { | |
10628 #ifdef WITH_DOM | |
10629 register struct soap_dom_attribute **att = NULL; | |
10630 register char *lead = NULL; | |
10631 #endif | |
10632 register struct soap_attribute *tp, *tq = NULL; | |
10633 register const char *t; | |
10634 register char *s; | |
10635 register soap_wchar c; | |
10636 register int i; | |
10637 if (soap->peeked) | |
10638 { if (!*soap->tag) | |
10639 return soap->error = SOAP_NO_TAG; | |
10640 return SOAP_OK; | |
10641 } | |
10642 soap->peeked = 1; | |
10643 soap->id[0] = '\0'; | |
10644 soap->href[0] = '\0'; | |
10645 soap->type[0] = '\0'; | |
10646 soap->arrayType[0] = '\0'; | |
10647 soap->arraySize[0] = '\0'; | |
10648 soap->arrayOffset[0] = '\0'; | |
10649 soap->other = 0; | |
10650 soap->root = -1; | |
10651 soap->position = 0; | |
10652 soap->null = 0; | |
10653 soap->mustUnderstand = 0; | |
10654 /* UTF-8 BOM? */ | |
10655 c = soap_getchar(soap); | |
10656 if (c == 0xEF && soap_get0(soap) == 0xBB) | |
10657 { c = soap_get1(soap); | |
10658 if ((c = soap_get1(soap)) == 0xBF) | |
10659 soap->mode &= ~SOAP_ENC_LATIN; | |
10660 else | |
10661 soap_unget(soap, (0x0F << 12) | (0xBB << 6) | (c & 0x3F)); /* UTF-8 */ | |
10662 } | |
10663 else if ((c == 0xFE && soap_get0(soap) == 0xFF) /* UTF-16 BE */ | |
10664 || (c == 0xFF && soap_get0(soap) == 0xFE)) /* UTF-16 LE */ | |
10665 return soap->error = SOAP_UTF_ERROR; | |
10666 else | |
10667 soap_unget(soap, c); | |
10668 c = soap_get(soap); | |
10669 #ifdef WITH_DOM | |
10670 /* whitespace leading to tag is not insignificant for DOM */ | |
10671 if (soap_blank(c)) | |
10672 { soap->labidx = 0; | |
10673 do | |
10674 { if (soap_append_lab(soap, NULL, 0)) | |
10675 return soap->error; | |
10676 s = soap->labbuf + soap->labidx; | |
10677 i = soap->lablen - soap->labidx; | |
10678 soap->labidx = soap->lablen; | |
10679 while (soap_blank(c) && i--) | |
10680 { *s++ = c; | |
10681 c = soap_get(soap); | |
10682 } | |
10683 } | |
10684 while (soap_blank(c)); | |
10685 *s = '\0'; | |
10686 lead = soap->labbuf; | |
10687 } | |
10688 #else | |
10689 /* skip space */ | |
10690 while (soap_blank(c)) | |
10691 c = soap_get(soap); | |
10692 #endif | |
10693 if (c != SOAP_LT) | |
10694 { *soap->tag = '\0'; | |
10695 if ((int)c == EOF) | |
10696 return soap->error = SOAP_CHK_EOF; | |
10697 soap_unget(soap, c); | |
10698 #ifdef WITH_DOM | |
10699 /* whitespace leading to end tag is significant for DOM */ | |
10700 if ((soap->mode & SOAP_XML_DOM) && soap->dom) | |
10701 { if (lead && *lead) | |
10702 soap->dom->tail = soap_strdup(soap, lead); | |
10703 else | |
10704 soap->dom->tail = (char*)SOAP_STR_EOS; | |
10705 } | |
10706 #endif | |
10707 return soap->error = SOAP_NO_TAG; | |
10708 } | |
10709 do c = soap_get1(soap); | |
10710 while (soap_blank(c)); | |
10711 s = soap->tag; | |
10712 i = sizeof(soap->tag); | |
10713 while (c != '>' && c != '/' && soap_notblank(c) && (int)c != EOF) | |
10714 { if (--i > 0) | |
10715 *s++ = (char)c; | |
10716 c = soap_get1(soap); | |
10717 } | |
10718 *s = '\0'; | |
10719 while (soap_blank(c)) | |
10720 c = soap_get1(soap); | |
10721 #ifdef WITH_DOM | |
10722 if (soap->mode & SOAP_XML_DOM) | |
10723 { register struct soap_dom_element *elt; | |
10724 elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element)); | |
10725 if (!elt) | |
10726 return soap->error; | |
10727 elt->next = NULL; | |
10728 elt->nstr = NULL; | |
10729 elt->name = soap_strdup(soap, soap->tag); | |
10730 elt->prnt = soap->dom; | |
10731 elt->elts = NULL; | |
10732 elt->atts = NULL; | |
10733 elt->data = NULL; | |
10734 elt->wide = NULL; | |
10735 elt->type = 0; | |
10736 elt->node = NULL; | |
10737 elt->head = soap_strdup(soap, lead); | |
10738 elt->tail = NULL; | |
10739 elt->soap = soap; | |
10740 if (soap->dom) | |
10741 { struct soap_dom_element *p = soap->dom->elts; | |
10742 if (p) | |
10743 { while (p->next) | |
10744 p = p->next; | |
10745 p->next = elt; | |
10746 } | |
10747 else | |
10748 soap->dom->elts = elt; | |
10749 } | |
10750 soap->dom = elt; | |
10751 att = &elt->atts; | |
10752 } | |
10753 #endif | |
10754 soap_pop_namespace(soap); | |
10755 for (tp = soap->attributes; tp; tp = tp->next) | |
10756 tp->visible = 0; | |
10757 while ((int)c != EOF && c != '>' && c != '/') | |
10758 { s = soap->tmpbuf; | |
10759 i = sizeof(soap->tmpbuf); | |
10760 while (c != '=' && c != '>' && c != '/' && soap_notblank(c) && (int)c != EOF) | |
10761 { if (--i > 0) | |
10762 *s++ = (char)c; | |
10763 c = soap_get1(soap); | |
10764 } | |
10765 *s = '\0'; | |
10766 if (i == sizeof(soap->tmpbuf)) | |
10767 return soap->error = SOAP_SYNTAX_ERROR; | |
10768 #ifdef WITH_DOM | |
10769 /* add attribute name to dom */ | |
10770 if (att) | |
10771 { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); | |
10772 if (!*att) | |
10773 return soap->error; | |
10774 (*att)->next = NULL; | |
10775 (*att)->nstr = NULL; | |
10776 (*att)->name = soap_strdup(soap, soap->tmpbuf); | |
10777 (*att)->data = NULL; | |
10778 (*att)->wide = NULL; | |
10779 (*att)->soap = soap; | |
10780 } | |
10781 #endif | |
10782 if (!strncmp(soap->tmpbuf, "xmlns", 5)) | |
10783 { if (soap->tmpbuf[5] == ':') | |
10784 t = soap->tmpbuf + 6; | |
10785 else if (soap->tmpbuf[5]) | |
10786 t = NULL; | |
10787 else | |
10788 t = SOAP_STR_EOS; | |
10789 } | |
10790 else | |
10791 t = NULL; | |
10792 tq = NULL; | |
10793 for (tp = soap->attributes; tp; tq = tp, tp = tp->next) | |
10794 { if (!SOAP_STRCMP(tp->name, soap->tmpbuf)) | |
10795 break; | |
10796 } | |
10797 if (!tp) | |
10798 { tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(soap->tmpbuf)); | |
10799 if (!tp) | |
10800 return soap->error = SOAP_EOM; | |
10801 strcpy((char*)tp->name, soap->tmpbuf); | |
10802 tp->value = NULL; | |
10803 tp->size = 0; | |
10804 tp->ns = NULL; | |
10805 /* if attribute name is qualified, append it to the end of the list */ | |
10806 if (tq && strchr(soap->tmpbuf, ':')) | |
10807 { tq->next = tp; | |
10808 tp->next = NULL; | |
10809 } | |
10810 else | |
10811 { tp->next = soap->attributes; | |
10812 soap->attributes = tp; | |
10813 } | |
10814 } | |
10815 while (soap_blank(c)) | |
10816 c = soap_get1(soap); | |
10817 if (c == '=') | |
10818 { do c = soap_getutf8(soap); | |
10819 while (soap_blank(c)); | |
10820 if (c != SOAP_QT && c != SOAP_AP) | |
10821 { soap_unget(soap, c); | |
10822 c = ' '; /* blank delimiter */ | |
10823 } | |
10824 if (soap_getattrval(soap, tp->value, tp->size, c)) | |
10825 { | |
10826 #ifdef WITH_FAST | |
10827 if (soap->error != SOAP_EOM) | |
10828 return soap->error; | |
10829 soap->error = SOAP_OK; | |
10830 if (soap_store_lab(soap, tp->value, tp->size)) | |
10831 return soap->error; | |
10832 if (tp->value) | |
10833 SOAP_FREE(soap, tp->value); | |
10834 tp->value = NULL; | |
10835 for (;;) | |
10836 { if (soap_getattrval(soap, soap->labbuf + soap->labidx, soap->lablen - soap->labidx, c)) | |
10837 { if (soap->error != SOAP_EOM) | |
10838 return soap->error; | |
10839 soap->error = SOAP_OK; | |
10840 soap->labidx = soap->lablen; | |
10841 if (soap_append_lab(soap, NULL, 0)) | |
10842 return soap->error; | |
10843 } | |
10844 else | |
10845 break; | |
10846 } | |
10847 if (soap->labidx) | |
10848 tp->size = soap->lablen; | |
10849 else | |
10850 { tp->size = strlen(soap->labbuf) + 1; | |
10851 if (tp->size < SOAP_LABLEN) | |
10852 tp->size = SOAP_LABLEN; | |
10853 } | |
10854 if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size))) | |
10855 return soap->error = SOAP_EOM; | |
10856 strcpy(tp->value, soap->labbuf); | |
10857 #else | |
10858 size_t n; | |
10859 if (soap->error != SOAP_EOM) | |
10860 return soap->error; | |
10861 soap->error = SOAP_OK; | |
10862 if (soap_new_block(soap) == NULL) | |
10863 return soap->error; | |
10864 for (;;) | |
10865 { if (!(s = (char*)soap_push_block(soap, NULL, SOAP_BLKLEN))) | |
10866 return soap->error; | |
10867 if (soap_getattrval(soap, s, SOAP_BLKLEN, c)) | |
10868 { if (soap->error != SOAP_EOM) | |
10869 return soap->error; | |
10870 soap->error = SOAP_OK; | |
10871 } | |
10872 else | |
10873 break; | |
10874 } | |
10875 n = tp->size + soap->blist->size; | |
10876 if (!(s = (char*)SOAP_MALLOC(soap, n))) | |
10877 return soap->error = SOAP_EOM; | |
10878 if (tp->value) | |
10879 { memcpy(s, tp->value, tp->size); | |
10880 SOAP_FREE(soap, tp->value); | |
10881 } | |
10882 soap_save_block(soap, NULL, s + tp->size, 0); | |
10883 tp->value = s; | |
10884 tp->size = n; | |
10885 #endif | |
10886 } | |
10887 do c = soap_get1(soap); | |
10888 while (soap_blank(c)); | |
10889 tp->visible = 2; /* seen this attribute w/ value */ | |
10890 #ifdef WITH_DOM | |
10891 if (att) | |
10892 (*att)->data = soap_strdup(soap, tp->value); | |
10893 #endif | |
10894 } | |
10895 else | |
10896 tp->visible = 1; /* seen this attribute w/o value */ | |
10897 #ifdef WITH_DOM | |
10898 if (att) | |
10899 att = &(*att)->next; | |
10900 #endif | |
10901 if (t && tp->value) | |
10902 { if (soap_push_namespace(soap, t, tp->value) == NULL) | |
10903 return soap->error; | |
10904 } | |
10905 } | |
10906 #ifdef WITH_DOM | |
10907 if (att) | |
10908 { soap->dom->nstr = soap_current_namespace(soap, soap->tag); | |
10909 for (att = &soap->dom->atts; *att; att = &(*att)->next) | |
10910 (*att)->nstr = soap_current_namespace(soap, (*att)->name); | |
10911 } | |
10912 #endif | |
10913 if ((int)c == EOF) | |
10914 return soap->error = SOAP_CHK_EOF; | |
10915 if (!(soap->body = (c != '/'))) | |
10916 do c = soap_get1(soap); | |
10917 while (soap_blank(c)); | |
10918 #ifdef WITH_DOM | |
10919 if (soap->mode & SOAP_XML_DOM) | |
10920 { if (!soap->body && soap->dom->prnt) | |
10921 soap->dom = soap->dom->prnt; | |
10922 } | |
10923 #endif | |
10924 for (tp = soap->attributes; tp; tp = tp->next) | |
10925 { if (tp->visible && tp->value) | |
10926 { | |
10927 #ifndef WITH_NOIDREF | |
10928 if (!strcmp(tp->name, "id")) | |
10929 { if ((soap->version > 0 && !(soap->imode & SOAP_XML_TREE)) | |
10930 || (soap->mode & SOAP_XML_GRAPH)) | |
10931 { *soap->id = '#'; | |
10932 strncpy(soap->id + 1, tp->value, sizeof(soap->id) - 2); | |
10933 soap->id[sizeof(soap->id) - 1] = '\0'; | |
10934 } | |
10935 } | |
10936 else if (!strcmp(tp->name, "href")) | |
10937 { if ((soap->version == 1 && !(soap->imode & SOAP_XML_TREE)) | |
10938 || (soap->mode & SOAP_XML_GRAPH) | |
10939 || (soap->mode & SOAP_ENC_MTOM) | |
10940 || (soap->mode & SOAP_ENC_DIME)) | |
10941 { strncpy(soap->href, tp->value, sizeof(soap->href) - 1); | |
10942 soap->href[sizeof(soap->href) - 1] = '\0'; | |
10943 } | |
10944 } | |
10945 else if (!strcmp(tp->name, "ref")) | |
10946 { if ((soap->version == 2 && !(soap->imode & SOAP_XML_TREE)) | |
10947 || (soap->mode & SOAP_XML_GRAPH)) | |
10948 { *soap->href = '#'; | |
10949 strncpy(soap->href + (*tp->value != '#'), tp->value, sizeof(soap->href) - 2); | |
10950 soap->href[sizeof(soap->href) - 1] = '\0'; | |
10951 } | |
10952 } | |
10953 else | |
10954 #endif | |
10955 if (!soap_match_tag(soap, tp->name, "xsi:type")) | |
10956 { strncpy(soap->type, tp->value, sizeof(soap->type) - 1); | |
10957 soap->type[sizeof(soap->type) - 1] = '\0'; | |
10958 } | |
10959 else if ((!soap_match_tag(soap, tp->name, "xsi:null") | |
10960 || !soap_match_tag(soap, tp->name, "xsi:nil")) | |
10961 && (!strcmp(tp->value, "1") | |
10962 || !strcmp(tp->value, "true"))) | |
10963 { soap->null = 1; | |
10964 } | |
10965 else if (soap->version == 1) | |
10966 { if (!soap_match_tag(soap, tp->name, "SOAP-ENC:arrayType")) | |
10967 { s = soap_strrchr(tp->value, '['); | |
10968 if (s && (size_t)(s - tp->value) < sizeof(soap->arrayType)) | |
10969 { strncpy(soap->arrayType, tp->value, s - tp->value); | |
10970 soap->arrayType[s - tp->value] = '\0'; | |
10971 strncpy(soap->arraySize, s, sizeof(soap->arraySize)); | |
10972 } | |
10973 else | |
10974 strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType)); | |
10975 soap->arraySize[sizeof(soap->arraySize) - 1] = '\0'; | |
10976 soap->arrayType[sizeof(soap->arrayType) - 1] = '\0'; | |
10977 } | |
10978 else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:offset")) | |
10979 strncpy(soap->arrayOffset, tp->value, sizeof(soap->arrayOffset)); | |
10980 else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:position")) | |
10981 soap->position = soap_getposition(tp->value, soap->positions); | |
10982 else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:root")) | |
10983 soap->root = ((!strcmp(tp->value, "1") || !strcmp(tp->value, "true"))); | |
10984 else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand") | |
10985 && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true"))) | |
10986 soap->mustUnderstand = 1; | |
10987 else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:actor")) | |
10988 { if ((!soap->actor || strcmp(soap->actor, tp->value)) | |
10989 && strcmp(tp->value, "http://schemas.xmlsoap.org/soap/actor/next")) | |
10990 soap->other = 1; | |
10991 } | |
10992 } | |
10993 else if (soap->version == 2) | |
10994 { | |
10995 #ifndef WITH_NOIDREF | |
10996 if (!soap_match_tag(soap, tp->name, "SOAP-ENC:id")) | |
10997 { *soap->id = '#'; | |
10998 strncpy(soap->id + 1, tp->value, sizeof(soap->id) - 2); | |
10999 soap->id[sizeof(soap->id) - 1] = '\0'; | |
11000 } | |
11001 else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:ref")) | |
11002 { *soap->href = '#'; | |
11003 strncpy(soap->href + (*tp->value != '#'), tp->value, sizeof(soap->href) - 2); | |
11004 soap->href[sizeof(soap->href) - 1] = '\0'; | |
11005 } | |
11006 else | |
11007 #endif | |
11008 if (!soap_match_tag(soap, tp->name, "SOAP-ENC:itemType")) | |
11009 strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1); | |
11010 else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:arraySize")) | |
11011 strncpy(soap->arraySize, tp->value, sizeof(soap->arraySize) - 1); | |
11012 else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand") | |
11013 && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true"))) | |
11014 soap->mustUnderstand = 1; | |
11015 else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:role")) | |
11016 { if ((!soap->actor || strcmp(soap->actor, tp->value)) | |
11017 && strcmp(tp->value, "http://www.w3.org/2003/05/soap-envelope/role/next")) | |
11018 soap->other = 1; | |
11019 } | |
11020 } | |
11021 else | |
11022 { if (!soap_match_tag(soap, tp->name, "wsdl:required") && !strcmp(tp->value, "true")) | |
11023 soap->mustUnderstand = 1; | |
11024 } | |
11025 } | |
11026 } | |
11027 #ifdef WITH_DOM | |
11028 if (soap->feltbegin) | |
11029 return soap->error = soap->feltbegin(soap, soap->tag); | |
11030 #endif | |
11031 return soap->error = SOAP_OK; | |
11032 } | |
11033 #endif | |
11034 | |
11035 /******************************************************************************/ | |
11036 #ifndef PALM_2 | |
11037 SOAP_FMAC1 | |
11038 void | |
11039 SOAP_FMAC2 | |
11040 soap_retry(struct soap *soap) | |
11041 { soap->error = SOAP_OK; | |
11042 soap_revert(soap); | |
11043 } | |
11044 #endif | |
11045 | |
11046 /******************************************************************************/ | |
11047 #ifndef PALM_2 | |
11048 SOAP_FMAC1 | |
11049 void | |
11050 SOAP_FMAC2 | |
11051 soap_revert(struct soap *soap) | |
11052 { if (!soap->peeked) | |
11053 { soap->peeked = 1; | |
11054 if (soap->body) | |
11055 soap->level--; | |
11056 } | |
11057 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reverting to last element '%s' (level=%u)\n", soap->tag, soap->level)); | |
11058 } | |
11059 #endif | |
11060 | |
11061 /******************************************************************************/ | |
11062 #ifndef PALM_2 | |
11063 SOAP_FMAC1 | |
11064 int | |
11065 SOAP_FMAC2 | |
11066 soap_string_out(struct soap *soap, const char *s, int flag) | |
11067 { register const char *t; | |
11068 register soap_wchar c; | |
11069 register soap_wchar mask = (soap_wchar)0xFFFFFF80UL; | |
11070 #ifdef WITH_DOM | |
11071 if ((soap->mode & SOAP_XML_DOM) && soap->dom) | |
11072 { soap->dom->data = soap_strdup(soap, s); | |
11073 return SOAP_OK; | |
11074 } | |
11075 #endif | |
11076 if (flag == 2 || soap->mode & SOAP_C_UTFSTRING) | |
11077 mask = 0; | |
11078 t = s; | |
11079 while ((c = *t++)) | |
11080 { switch (c) | |
11081 { | |
11082 case 0x09: | |
11083 if (flag) | |
11084 { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "	", 5)) | |
11085 return soap->error; | |
11086 s = t; | |
11087 } | |
11088 break; | |
11089 case 0x0A: | |
11090 if (flag || !(soap->mode & SOAP_XML_CANONICAL)) | |
11091 { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "
", 5)) | |
11092 return soap->error; | |
11093 s = t; | |
11094 } | |
11095 break; | |
11096 case 0x0D: | |
11097 if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "
", 5)) | |
11098 return soap->error; | |
11099 s = t; | |
11100 break; | |
11101 case '&': | |
11102 if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&", 5)) | |
11103 return soap->error; | |
11104 s = t; | |
11105 break; | |
11106 case '<': | |
11107 if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "<", 4)) | |
11108 return soap->error; | |
11109 s = t; | |
11110 break; | |
11111 case '>': | |
11112 if (!flag) | |
11113 { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, ">", 4)) | |
11114 return soap->error; | |
11115 s = t; | |
11116 } | |
11117 break; | |
11118 case '"': | |
11119 if (flag) | |
11120 { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, """, 6)) | |
11121 return soap->error; | |
11122 s = t; | |
11123 } | |
11124 break; | |
11125 default: | |
11126 #ifndef WITH_LEANER | |
11127 #ifdef HAVE_MBTOWC | |
11128 if (soap->mode & SOAP_C_MBSTRING) | |
11129 { wchar_t wc; | |
11130 register int m = mbtowc(&wc, t - 1, MB_CUR_MAX); | |
11131 if (m > 0 && !((soap_wchar)wc == c && m == 1 && c < 0x80)) | |
11132 { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned long)wc)) | |
11133 return soap->error; | |
11134 s = t += m - 1; | |
11135 continue; | |
11136 } | |
11137 } | |
11138 #endif | |
11139 #endif | |
11140 #ifndef WITH_NOSTRINGTOUTF8 | |
11141 if ((c & mask) || !(c & 0xFFFFFFE0UL)) | |
11142 { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned char)c)) | |
11143 return soap->error; | |
11144 s = t; | |
11145 } | |
11146 #endif | |
11147 } | |
11148 } | |
11149 return soap_send_raw(soap, s, t - s - 1); | |
11150 } | |
11151 #endif | |
11152 | |
11153 /******************************************************************************/ | |
11154 #ifndef PALM_2 | |
11155 SOAP_FMAC1 | |
11156 char * | |
11157 SOAP_FMAC2 | |
11158 soap_string_in(struct soap *soap, int flag, long minlen, long maxlen) | |
11159 { register char *s; | |
11160 char *t = NULL; | |
11161 register size_t i; | |
11162 register long l = 0; | |
11163 register int n = 0, f = 0, m = 0; | |
11164 register soap_wchar c; | |
11165 #if !defined(WITH_LEANER) && defined(HAVE_WCTOMB) | |
11166 char buf[MB_LEN_MAX > 8 ? MB_LEN_MAX : 8]; | |
11167 #else | |
11168 char buf[8]; | |
11169 #endif | |
11170 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading string content, flag=%d\n", flag)); | |
11171 if (soap->peeked && *soap->tag) | |
11172 { | |
11173 #ifndef WITH_LEAN | |
11174 struct soap_attribute *tp; | |
11175 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String content includes tag '%s' and attributes\n", soap->tag)); | |
11176 t = soap->tmpbuf; | |
11177 *t = '<'; | |
11178 strncpy(t + 1, soap->tag, sizeof(soap->tmpbuf) - 2); | |
11179 t[sizeof(soap->tmpbuf) - 1] = '\0'; | |
11180 t += strlen(t); | |
11181 for (tp = soap->attributes; tp; tp = tp->next) | |
11182 { if (tp->visible) | |
11183 { if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2) | |
11184 break; | |
11185 *t++ = ' '; | |
11186 strcpy(t, tp->name); | |
11187 t += strlen(t); | |
11188 if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2) | |
11189 break; /* too many or large attribute values */ | |
11190 if (tp->value) | |
11191 { *t++ = '='; | |
11192 *t++ = '"'; | |
11193 strcpy(t, tp->value); | |
11194 t += strlen(t); | |
11195 *t++ = '"'; | |
11196 } | |
11197 } | |
11198 } | |
11199 if (!soap->body) | |
11200 *t++ = '/'; | |
11201 *t++ = '>'; | |
11202 *t = '\0'; | |
11203 t = soap->tmpbuf; | |
11204 m = (int)strlen(soap->tmpbuf); | |
11205 #endif | |
11206 if (soap->body) | |
11207 n = 1; | |
11208 f = 1; | |
11209 soap->peeked = 0; | |
11210 } | |
11211 #ifdef WITH_CDATA | |
11212 if (!flag) | |
11213 { register int state = 0; | |
11214 #ifdef WITH_FAST | |
11215 soap->labidx = 0; /* use look-aside buffer */ | |
11216 #else | |
11217 if (soap_new_block(soap) == NULL) | |
11218 return NULL; | |
11219 #endif | |
11220 for (;;) | |
11221 { | |
11222 #ifdef WITH_FAST | |
11223 register size_t k; | |
11224 if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */ | |
11225 return NULL; | |
11226 s = soap->labbuf + soap->labidx; /* space to populate */ | |
11227 k = soap->lablen - soap->labidx; /* number of bytes available */ | |
11228 soap->labidx = soap->lablen; /* claim this space */ | |
11229 #else | |
11230 register size_t k = SOAP_BLKLEN; | |
11231 if (!(s = (char*)soap_push_block(soap, NULL, k))) | |
11232 return NULL; | |
11233 #endif | |
11234 for (i = 0; i < k; i++) | |
11235 { if (m > 0) | |
11236 { *s++ = *t++; /* copy multibyte characters */ | |
11237 m--; | |
11238 continue; | |
11239 } | |
11240 c = soap_getchar(soap); | |
11241 if ((int)c == EOF) | |
11242 goto end; | |
11243 if ((c >= 0x80 || c < SOAP_AP) && state != 1 && !(soap->mode & SOAP_ENC_LATIN)) | |
11244 { if ((c & 0x7FFFFFFF) >= 0x80) | |
11245 { soap_unget(soap, c); | |
11246 c = soap_getutf8(soap); | |
11247 } | |
11248 if ((c & 0x7FFFFFFF) >= 0x80 && (!flag || (soap->mode & SOAP_C_UTFSTRING))) | |
11249 { c &= 0x7FFFFFFF; | |
11250 t = buf; | |
11251 if (c < 0x0800) | |
11252 *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); | |
11253 else | |
11254 { if (c < 0x010000) | |
11255 *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); | |
11256 else | |
11257 { if (c < 0x200000) | |
11258 *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); | |
11259 else | |
11260 { if (c < 0x04000000) | |
11261 *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); | |
11262 else | |
11263 { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); | |
11264 *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); | |
11265 } | |
11266 *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); | |
11267 } | |
11268 *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); | |
11269 } | |
11270 *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); | |
11271 } | |
11272 *t++ = (char)(0x80 | (c & 0x3F)); | |
11273 m = (int)(t - buf) - 1; | |
11274 t = buf; | |
11275 *s++ = *t++; | |
11276 continue; | |
11277 } | |
11278 } | |
11279 switch (state) | |
11280 { case 1: | |
11281 if (c == ']') | |
11282 state = 4; | |
11283 *s++ = (char)c; | |
11284 continue; | |
11285 case 2: | |
11286 if (c == '-') | |
11287 state = 6; | |
11288 *s++ = (char)c; | |
11289 continue; | |
11290 case 3: | |
11291 if (c == '?') | |
11292 state = 8; | |
11293 *s++ = (char)c; | |
11294 continue; | |
11295 /* CDATA */ | |
11296 case 4: | |
11297 if (c == ']') | |
11298 state = 5; | |
11299 else | |
11300 state = 1; | |
11301 *s++ = (char)c; | |
11302 continue; | |
11303 case 5: | |
11304 if (c == '>') | |
11305 state = 0; | |
11306 else if (c != ']') | |
11307 state = 1; | |
11308 *s++ = (char)c; | |
11309 continue; | |
11310 /* comment */ | |
11311 case 6: | |
11312 if (c == '-') | |
11313 state = 7; | |
11314 else | |
11315 state = 2; | |
11316 *s++ = (char)c; | |
11317 continue; | |
11318 case 7: | |
11319 if (c == '>') | |
11320 state = 0; | |
11321 else if (c != '-') | |
11322 state = 2; | |
11323 *s++ = (char)c; | |
11324 continue; | |
11325 /* PI */ | |
11326 case 8: | |
11327 if (c == '>') | |
11328 state = 0; | |
11329 else if (c != '?') | |
11330 state = 3; | |
11331 *s++ = (char)c; | |
11332 continue; | |
11333 } | |
11334 switch (c) | |
11335 { | |
11336 case SOAP_TT: | |
11337 if (n == 0) | |
11338 goto end; | |
11339 n--; | |
11340 *s++ = '<'; | |
11341 t = (char*)"/"; | |
11342 m = 1; | |
11343 break; | |
11344 case SOAP_LT: | |
11345 if (f && n == 0) | |
11346 goto end; | |
11347 n++; | |
11348 *s++ = '<'; | |
11349 break; | |
11350 case SOAP_GT: | |
11351 *s++ = '>'; | |
11352 break; | |
11353 case SOAP_QT: | |
11354 *s++ = '"'; | |
11355 break; | |
11356 case SOAP_AP: | |
11357 *s++ = '\''; | |
11358 break; | |
11359 case '/': | |
11360 if (n > 0) | |
11361 { c = soap_getchar(soap); | |
11362 if (c == '>') | |
11363 n--; | |
11364 soap_unget(soap, c); | |
11365 } | |
11366 *s++ = '/'; | |
11367 break; | |
11368 case '<': | |
11369 c = soap_getchar(soap); | |
11370 if (c == '/') | |
11371 { if (n == 0) | |
11372 { c = SOAP_TT; | |
11373 goto end; | |
11374 } | |
11375 n--; | |
11376 } | |
11377 else if (c == '!') | |
11378 { c = soap_getchar(soap); | |
11379 if (c == '[') | |
11380 { do c = soap_getchar(soap); | |
11381 while ((int)c != EOF && c != '['); | |
11382 if ((int)c == EOF) | |
11383 goto end; | |
11384 t = (char*)"![CDATA["; | |
11385 m = 8; | |
11386 state = 1; | |
11387 } | |
11388 else if (c == '-') | |
11389 { if ((c = soap_getchar(soap)) == '-') | |
11390 state = 2; | |
11391 t = (char*)"!-"; | |
11392 m = 2; | |
11393 soap_unget(soap, c); | |
11394 } | |
11395 else | |
11396 { t = (char*)"!"; | |
11397 m = 1; | |
11398 soap_unget(soap, c); | |
11399 } | |
11400 *s++ = '<'; | |
11401 break; | |
11402 } | |
11403 else if (c == '?') | |
11404 state = 3; | |
11405 else if (f && n == 0) | |
11406 { soap_revget1(soap); | |
11407 c = '<'; | |
11408 goto end; | |
11409 } | |
11410 else | |
11411 n++; | |
11412 soap_unget(soap, c); | |
11413 *s++ = '<'; | |
11414 break; | |
11415 case '>': | |
11416 *s++ = '>'; | |
11417 break; | |
11418 case '"': | |
11419 *s++ = '"'; | |
11420 break; | |
11421 default: | |
11422 #ifndef WITH_LEANER | |
11423 #ifdef HAVE_WCTOMB | |
11424 if (soap->mode & SOAP_C_MBSTRING) | |
11425 { m = wctomb(buf, (wchar_t)(c & 0x7FFFFFFF)); | |
11426 if (m >= 1 && m <= (int)MB_CUR_MAX) | |
11427 { t = buf; | |
11428 *s++ = *t++; | |
11429 m--; | |
11430 } | |
11431 else | |
11432 { *s++ = SOAP_UNKNOWN_CHAR; | |
11433 m = 0; | |
11434 } | |
11435 } | |
11436 else | |
11437 #endif | |
11438 #endif | |
11439 *s++ = (char)(c & 0xFF); | |
11440 } | |
11441 l++; | |
11442 if (maxlen >= 0 && l > maxlen) | |
11443 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); | |
11444 soap->error = SOAP_LENGTH; | |
11445 return NULL; | |
11446 } | |
11447 } | |
11448 } | |
11449 } | |
11450 #endif | |
11451 #ifdef WITH_FAST | |
11452 soap->labidx = 0; /* use look-aside buffer */ | |
11453 #else | |
11454 if (soap_new_block(soap) == NULL) | |
11455 return NULL; | |
11456 #endif | |
11457 for (;;) | |
11458 { | |
11459 #ifdef WITH_FAST | |
11460 register size_t k; | |
11461 if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */ | |
11462 return NULL; | |
11463 s = soap->labbuf + soap->labidx; /* space to populate */ | |
11464 k = soap->lablen - soap->labidx; /* number of bytes available */ | |
11465 soap->labidx = soap->lablen; /* claim this space */ | |
11466 #else | |
11467 register size_t k = SOAP_BLKLEN; | |
11468 if (!(s = (char*)soap_push_block(soap, NULL, k))) | |
11469 return NULL; | |
11470 #endif | |
11471 for (i = 0; i < k; i++) | |
11472 { if (m > 0) | |
11473 { *s++ = *t++; /* copy multibyte characters */ | |
11474 m--; | |
11475 continue; | |
11476 } | |
11477 #ifndef WITH_CDATA | |
11478 if (!flag) | |
11479 c = soap_getchar(soap); | |
11480 else | |
11481 #endif | |
11482 if ((soap->mode & SOAP_C_UTFSTRING)) | |
11483 { if (((c = soap_get(soap)) & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP) | |
11484 { c &= 0x7FFFFFFF; | |
11485 t = buf; | |
11486 if (c < 0x0800) | |
11487 *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); | |
11488 else | |
11489 { if (c < 0x010000) | |
11490 *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); | |
11491 else | |
11492 { if (c < 0x200000) | |
11493 *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); | |
11494 else | |
11495 { if (c < 0x04000000) | |
11496 *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); | |
11497 else | |
11498 { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); | |
11499 *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); | |
11500 } | |
11501 *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); | |
11502 } | |
11503 *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); | |
11504 } | |
11505 *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); | |
11506 } | |
11507 *t++ = (char)(0x80 | (c & 0x3F)); | |
11508 m = (int)(t - buf) - 1; | |
11509 t = buf; | |
11510 *s++ = *t++; | |
11511 continue; | |
11512 } | |
11513 } | |
11514 else | |
11515 c = soap_getutf8(soap); | |
11516 switch (c) | |
11517 { | |
11518 case SOAP_TT: | |
11519 if (n == 0) | |
11520 goto end; | |
11521 n--; | |
11522 *s++ = '<'; | |
11523 t = (char*)"/"; | |
11524 m = 1; | |
11525 break; | |
11526 case SOAP_LT: | |
11527 if (f && n == 0) | |
11528 goto end; | |
11529 n++; | |
11530 *s++ = '<'; | |
11531 break; | |
11532 case SOAP_GT: | |
11533 *s++ = '>'; | |
11534 break; | |
11535 case SOAP_QT: | |
11536 *s++ = '"'; | |
11537 break; | |
11538 case SOAP_AP: | |
11539 *s++ = '\''; | |
11540 break; | |
11541 case '/': | |
11542 if (n > 0) | |
11543 { if (!flag) | |
11544 { c = soap_getchar(soap); | |
11545 if (c == '>') | |
11546 n--; | |
11547 } | |
11548 else | |
11549 { c = soap_get(soap); | |
11550 if (c == SOAP_GT) | |
11551 n--; | |
11552 } | |
11553 soap_unget(soap, c); | |
11554 } | |
11555 *s++ = '/'; | |
11556 break; | |
11557 case (soap_wchar)('<' | 0x80000000): | |
11558 if (flag) | |
11559 *s++ = '<'; | |
11560 else | |
11561 { *s++ = '&'; | |
11562 t = (char*)"lt;"; | |
11563 m = 3; | |
11564 } | |
11565 break; | |
11566 case (soap_wchar)('>' | 0x80000000): | |
11567 if (flag) | |
11568 *s++ = '>'; | |
11569 else | |
11570 { *s++ = '&'; | |
11571 t = (char*)"gt;"; | |
11572 m = 3; | |
11573 } | |
11574 break; | |
11575 case (soap_wchar)('&' | 0x80000000): | |
11576 if (flag) | |
11577 *s++ = '&'; | |
11578 else | |
11579 { *s++ = '&'; | |
11580 t = (char*)"amp;"; | |
11581 m = 4; | |
11582 } | |
11583 break; | |
11584 case (soap_wchar)('"' | 0x80000000): | |
11585 if (flag) | |
11586 *s++ = '"'; | |
11587 else | |
11588 { *s++ = '&'; | |
11589 t = (char*)"quot;"; | |
11590 m = 5; | |
11591 } | |
11592 break; | |
11593 case (soap_wchar)('\'' | 0x80000000): | |
11594 if (flag) | |
11595 *s++ = '\''; | |
11596 else | |
11597 { *s++ = '&'; | |
11598 t = (char*)"apos;"; | |
11599 m = 5; | |
11600 } | |
11601 break; | |
11602 default: | |
11603 if ((int)c == EOF) | |
11604 goto end; | |
11605 #ifndef WITH_CDATA | |
11606 if (c == '<' && !flag) | |
11607 { if (f && n == 0) | |
11608 goto end; | |
11609 c = soap_getchar(soap); | |
11610 soap_unget(soap, c); | |
11611 if (c == '/') | |
11612 { c = SOAP_TT; | |
11613 if (n == 0) | |
11614 goto end; | |
11615 n--; | |
11616 } | |
11617 else | |
11618 n++; | |
11619 *s++ = '<'; | |
11620 break; | |
11621 } | |
11622 else | |
11623 #endif | |
11624 #ifndef WITH_LEANER | |
11625 #ifdef HAVE_WCTOMB | |
11626 if (soap->mode & SOAP_C_MBSTRING) | |
11627 { m = wctomb(buf, (wchar_t)(c & 0x7FFFFFFF)); | |
11628 if (m >= 1 && m <= (int)MB_CUR_MAX) | |
11629 { t = buf; | |
11630 *s++ = *t++; | |
11631 m--; | |
11632 } | |
11633 else | |
11634 { *s++ = SOAP_UNKNOWN_CHAR; | |
11635 m = 0; | |
11636 } | |
11637 } | |
11638 else | |
11639 #endif | |
11640 #endif | |
11641 *s++ = (char)(c & 0xFF); | |
11642 } | |
11643 l++; | |
11644 if (maxlen >= 0 && l > maxlen) | |
11645 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); | |
11646 soap->error = SOAP_LENGTH; | |
11647 return NULL; | |
11648 } | |
11649 } | |
11650 } | |
11651 end: | |
11652 soap_unget(soap, c); | |
11653 *s = '\0'; | |
11654 #ifdef WITH_FAST | |
11655 t = soap_strdup(soap, soap->labbuf); | |
11656 #else | |
11657 soap_size_block(soap, NULL, i + 1); | |
11658 t = soap_save_block(soap, NULL, 0); | |
11659 #endif | |
11660 if (l < minlen) | |
11661 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen)); | |
11662 soap->error = SOAP_LENGTH; | |
11663 return NULL; | |
11664 } | |
11665 #ifdef WITH_DOM | |
11666 if ((soap->mode & SOAP_XML_DOM) && soap->dom) | |
11667 { if (flag == 3) | |
11668 soap->dom->tail = t; | |
11669 else | |
11670 soap->dom->data = t; | |
11671 } | |
11672 #endif | |
11673 if (flag == 2) | |
11674 if (soap_s2QName(soap, t, &t, minlen, maxlen)) | |
11675 return NULL; | |
11676 return t; | |
11677 } | |
11678 #endif | |
11679 | |
11680 /******************************************************************************/ | |
11681 #ifndef WITH_LEANER | |
11682 #ifndef PALM_2 | |
11683 SOAP_FMAC1 | |
11684 int | |
11685 SOAP_FMAC2 | |
11686 soap_wstring_out(struct soap *soap, const wchar_t *s, int flag) | |
11687 { const char *t; | |
11688 char tmp; | |
11689 register soap_wchar c; | |
11690 #ifdef WITH_DOM | |
11691 if ((soap->mode & SOAP_XML_DOM) && soap->dom) | |
11692 { wchar_t *r = (wchar_t*)s; | |
11693 int n = 1; | |
11694 while (*r++) | |
11695 n++; | |
11696 soap->dom->wide = r = (wchar_t*)soap_malloc(soap, n * sizeof(wchar_t)); | |
11697 while (n--) | |
11698 *r++ = *s++; | |
11699 return SOAP_OK; | |
11700 } | |
11701 #endif | |
11702 while ((c = *s++)) | |
11703 { switch (c) | |
11704 { | |
11705 case 0x09: | |
11706 if (flag) | |
11707 t = "	"; | |
11708 else | |
11709 t = "\t"; | |
11710 break; | |
11711 case 0x0A: | |
11712 if (flag || !(soap->mode & SOAP_XML_CANONICAL)) | |
11713 t = "
"; | |
11714 else | |
11715 t = "\n"; | |
11716 break; | |
11717 case 0x0D: | |
11718 t = "
"; | |
11719 break; | |
11720 case '&': | |
11721 t = "&"; | |
11722 break; | |
11723 case '<': | |
11724 t = "<"; | |
11725 break; | |
11726 case '>': | |
11727 if (flag) | |
11728 t = ">"; | |
11729 else | |
11730 t = ">"; | |
11731 break; | |
11732 case '"': | |
11733 if (flag) | |
11734 t = """; | |
11735 else | |
11736 t = "\""; | |
11737 break; | |
11738 default: | |
11739 if (c >= 0x20 && c < 0x80) | |
11740 { tmp = (char)c; | |
11741 if (soap_send_raw(soap, &tmp, 1)) | |
11742 return soap->error; | |
11743 } | |
11744 else | |
11745 { /* check for UTF16 encoding when wchar_t is too small to hold UCS */ | |
11746 if (sizeof(wchar_t) < 4 && (c & 0xFC00) == 0xD800) | |
11747 { register soap_wchar d = *s++; | |
11748 if ((d & 0xFC00) == 0xDC00) | |
11749 c = ((c - 0xD800) << 10) + (d - 0xDC00) + 0x10000; | |
11750 else | |
11751 c = 0xFFFD; /* Malformed */ | |
11752 } | |
11753 if (soap_pututf8(soap, (unsigned long)c)) | |
11754 return soap->error; | |
11755 } | |
11756 continue; | |
11757 } | |
11758 if (soap_send(soap, t)) | |
11759 return soap->error; | |
11760 } | |
11761 return SOAP_OK; | |
11762 } | |
11763 #endif | |
11764 #endif | |
11765 | |
11766 /******************************************************************************/ | |
11767 #ifndef WITH_LEANER | |
11768 #ifndef PALM_2 | |
11769 SOAP_FMAC1 | |
11770 wchar_t * | |
11771 SOAP_FMAC2 | |
11772 soap_wstring_in(struct soap *soap, int flag, long minlen, long maxlen) | |
11773 { wchar_t *s; | |
11774 register int i, n = 0, f = 0; | |
11775 register long l = 0; | |
11776 register soap_wchar c; | |
11777 char *t = NULL; | |
11778 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading wide string content\n")); | |
11779 if (soap->peeked) | |
11780 { if (*soap->tag) | |
11781 { | |
11782 #ifndef WITH_LEAN | |
11783 struct soap_attribute *tp; | |
11784 t = soap->tmpbuf; | |
11785 *t = '<'; | |
11786 strncpy(t + 1, soap->tag, sizeof(soap->tmpbuf) - 2); | |
11787 t[sizeof(soap->tmpbuf) - 1] = '\0'; | |
11788 t += strlen(t); | |
11789 for (tp = soap->attributes; tp; tp = tp->next) | |
11790 { if (tp->visible) | |
11791 { if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2) | |
11792 break; | |
11793 *t++ = ' '; | |
11794 strcpy(t, tp->name); | |
11795 t += strlen(t); | |
11796 if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2) | |
11797 break; | |
11798 if (tp->value) | |
11799 { *t++ = '='; | |
11800 *t++ = '"'; | |
11801 strcpy(t, tp->value); | |
11802 t += strlen(t); | |
11803 *t++ = '"'; | |
11804 } | |
11805 } | |
11806 } | |
11807 if (!soap->body) | |
11808 *t++ = '/'; | |
11809 *t++ = '>'; | |
11810 *t = '\0'; | |
11811 t = soap->tmpbuf; | |
11812 #endif | |
11813 if (soap->body) | |
11814 n = 1; | |
11815 f = 1; | |
11816 soap->peeked = 0; | |
11817 } | |
11818 } | |
11819 if (soap_new_block(soap) == NULL) | |
11820 return NULL; | |
11821 for (;;) | |
11822 { if (!(s = (wchar_t*)soap_push_block(soap, NULL, sizeof(wchar_t)*SOAP_BLKLEN))) | |
11823 return NULL; | |
11824 for (i = 0; i < SOAP_BLKLEN; i++) | |
11825 { if (t) | |
11826 { *s++ = (wchar_t)*t++; | |
11827 if (!*t) | |
11828 t = NULL; | |
11829 continue; | |
11830 } | |
11831 c = soap_getutf8(soap); | |
11832 switch (c) | |
11833 { | |
11834 case SOAP_TT: | |
11835 if (n == 0) | |
11836 goto end; | |
11837 n--; | |
11838 *s++ = '<'; | |
11839 soap_unget(soap, '/'); | |
11840 break; | |
11841 case SOAP_LT: | |
11842 if (f && n == 0) | |
11843 goto end; | |
11844 n++; | |
11845 *s++ = '<'; | |
11846 break; | |
11847 case SOAP_GT: | |
11848 *s++ = '>'; | |
11849 break; | |
11850 case SOAP_QT: | |
11851 *s++ = '"'; | |
11852 break; | |
11853 case SOAP_AP: | |
11854 *s++ = '\''; | |
11855 break; | |
11856 case '/': | |
11857 if (n > 0) | |
11858 { c = soap_getutf8(soap); | |
11859 if (c == SOAP_GT) | |
11860 n--; | |
11861 soap_unget(soap, c); | |
11862 } | |
11863 *s++ = '/'; | |
11864 break; | |
11865 case '<': | |
11866 if (flag) | |
11867 *s++ = (soap_wchar)'<'; | |
11868 else | |
11869 { *s++ = (soap_wchar)'&'; | |
11870 t = (char*)"lt;"; | |
11871 } | |
11872 break; | |
11873 case '>': | |
11874 if (flag) | |
11875 *s++ = (soap_wchar)'>'; | |
11876 else | |
11877 { *s++ = (soap_wchar)'&'; | |
11878 t = (char*)"gt;"; | |
11879 } | |
11880 break; | |
11881 case '"': | |
11882 if (flag) | |
11883 *s++ = (soap_wchar)'"'; | |
11884 else | |
11885 { *s++ = (soap_wchar)'&'; | |
11886 t = (char*)"quot;"; | |
11887 } | |
11888 break; | |
11889 default: | |
11890 if ((int)c == EOF) | |
11891 goto end; | |
11892 /* use UTF16 encoding when wchar_t is too small to hold UCS */ | |
11893 if (sizeof(wchar_t) < 4 && c > 0xFFFF) | |
11894 { register soap_wchar c1, c2; | |
11895 c1 = 0xD800 - (0x10000 >> 10) + (c >> 10); | |
11896 c2 = 0xDC00 + (c & 0x3FF); | |
11897 c = c1; | |
11898 soap_unget(soap, c2); | |
11899 } | |
11900 *s++ = (wchar_t)c & 0x7FFFFFFF; | |
11901 } | |
11902 l++; | |
11903 if (maxlen >= 0 && l > maxlen) | |
11904 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); | |
11905 soap->error = SOAP_LENGTH; | |
11906 return NULL; | |
11907 } | |
11908 } | |
11909 } | |
11910 end: | |
11911 soap_unget(soap, c); | |
11912 *s = '\0'; | |
11913 soap_size_block(soap, NULL, sizeof(wchar_t) * (i + 1)); | |
11914 if (l < minlen) | |
11915 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen)); | |
11916 soap->error = SOAP_LENGTH; | |
11917 return NULL; | |
11918 } | |
11919 s = (wchar_t*)soap_save_block(soap, NULL, NULL, 0); | |
11920 #ifdef WITH_DOM | |
11921 if ((soap->mode & SOAP_XML_DOM) && soap->dom) | |
11922 soap->dom->wide = s; | |
11923 #endif | |
11924 return s; | |
11925 } | |
11926 #endif | |
11927 #endif | |
11928 | |
11929 /******************************************************************************/ | |
11930 #ifndef PALM_2 | |
11931 SOAP_FMAC1 | |
11932 const char* | |
11933 SOAP_FMAC2 | |
11934 soap_int2s(struct soap *soap, int n) | |
11935 { return soap_long2s(soap, (long)n); | |
11936 } | |
11937 #endif | |
11938 | |
11939 /******************************************************************************/ | |
11940 #ifndef PALM_2 | |
11941 SOAP_FMAC1 | |
11942 int | |
11943 SOAP_FMAC2 | |
11944 soap_outint(struct soap *soap, const char *tag, int id, const int *p, const char *type, int n) | |
11945 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) | |
11946 || soap_string_out(soap, soap_long2s(soap, (long)*p), 0)) | |
11947 return soap->error; | |
11948 return soap_element_end_out(soap, tag); | |
11949 } | |
11950 #endif | |
11951 | |
11952 /******************************************************************************/ | |
11953 #ifndef PALM_2 | |
11954 SOAP_FMAC1 | |
11955 int | |
11956 SOAP_FMAC2 | |
11957 soap_s2int(struct soap *soap, const char *s, int *p) | |
11958 { if (s) | |
11959 { long n; | |
11960 char *r; | |
11961 #ifndef WITH_NOIO | |
11962 #ifndef WITH_LEAN | |
11963 soap_reset_errno; | |
11964 #endif | |
11965 #endif | |
11966 n = soap_strtol(s, &r, 10); | |
11967 if (s == r || *r | |
11968 #ifndef WITH_LEAN | |
11969 || n != (int)n | |
11970 #endif | |
11971 #ifndef WITH_NOIO | |
11972 #ifndef WITH_LEAN | |
11973 || soap_errno == SOAP_ERANGE | |
11974 #endif | |
11975 #endif | |
11976 ) | |
11977 soap->error = SOAP_TYPE; | |
11978 *p = (int)n; | |
11979 } | |
11980 return soap->error; | |
11981 } | |
11982 #endif | |
11983 | |
11984 /******************************************************************************/ | |
11985 #ifndef PALM_2 | |
11986 SOAP_FMAC1 | |
11987 int * | |
11988 SOAP_FMAC2 | |
11989 soap_inint(struct soap *soap, const char *tag, int *p, const char *type, int t) | |
11990 { if (soap_element_begin_in(soap, tag, 0, NULL)) | |
11991 return NULL; | |
11992 #ifndef WITH_LEAN | |
11993 if (*soap->type | |
11994 && soap_match_tag(soap, soap->type, type) | |
11995 && soap_match_tag(soap, soap->type, ":int") | |
11996 && soap_match_tag(soap, soap->type, ":short") | |
11997 && soap_match_tag(soap, soap->type, ":byte")) | |
11998 { soap->error = SOAP_TYPE; | |
11999 soap_revert(soap); | |
12000 return NULL; | |
12001 } | |
12002 #endif | |
12003 p = (int*)soap_id_enter(soap, soap->id, p, t, sizeof(int), 0, NULL, NULL, NULL); | |
12004 if (*soap->href) | |
12005 p = (int*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(int), 0, NULL); | |
12006 else if (p) | |
12007 { if (soap_s2int(soap, soap_value(soap), p)) | |
12008 return NULL; | |
12009 } | |
12010 if (soap->body && soap_element_end_in(soap, tag)) | |
12011 return NULL; | |
12012 return p; | |
12013 } | |
12014 #endif | |
12015 | |
12016 /******************************************************************************/ | |
12017 #ifndef PALM_2 | |
12018 SOAP_FMAC1 | |
12019 const char* | |
12020 SOAP_FMAC2 | |
12021 soap_long2s(struct soap *soap, long n) | |
12022 { | |
12023 #ifdef HAVE_SNPRINTF | |
12024 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%ld", n); | |
12025 #else | |
12026 sprintf(soap->tmpbuf, "%ld", n); | |
12027 #endif | |
12028 return soap->tmpbuf; | |
12029 } | |
12030 #endif | |
12031 | |
12032 /******************************************************************************/ | |
12033 #ifndef PALM_2 | |
12034 SOAP_FMAC1 | |
12035 int | |
12036 SOAP_FMAC2 | |
12037 soap_outlong(struct soap *soap, const char *tag, int id, const long *p, const char *type, int n) | |
12038 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) | |
12039 || soap_string_out(soap, soap_long2s(soap, *p), 0)) | |
12040 return soap->error; | |
12041 return soap_element_end_out(soap, tag); | |
12042 } | |
12043 #endif | |
12044 | |
12045 /******************************************************************************/ | |
12046 #ifndef PALM_2 | |
12047 SOAP_FMAC1 | |
12048 int | |
12049 SOAP_FMAC2 | |
12050 soap_s2long(struct soap *soap, const char *s, long *p) | |
12051 { if (s) | |
12052 { char *r; | |
12053 #ifndef WITH_NOIO | |
12054 #ifndef WITH_LEAN | |
12055 soap_reset_errno; | |
12056 #endif | |
12057 #endif | |
12058 *p = soap_strtol(s, &r, 10); | |
12059 if (s == r || *r | |
12060 #ifndef WITH_NOIO | |
12061 #ifndef WITH_LEAN | |
12062 || soap_errno == SOAP_ERANGE | |
12063 #endif | |
12064 #endif | |
12065 ) | |
12066 soap->error = SOAP_TYPE; | |
12067 } | |
12068 return soap->error; | |
12069 } | |
12070 #endif | |
12071 | |
12072 /******************************************************************************/ | |
12073 #ifndef PALM_2 | |
12074 SOAP_FMAC1 | |
12075 long * | |
12076 SOAP_FMAC2 | |
12077 soap_inlong(struct soap *soap, const char *tag, long *p, const char *type, int t) | |
12078 { if (soap_element_begin_in(soap, tag, 0, NULL)) | |
12079 return NULL; | |
12080 #ifndef WITH_LEAN | |
12081 if (*soap->type | |
12082 && soap_match_tag(soap, soap->type, type) | |
12083 && soap_match_tag(soap, soap->type, ":int") | |
12084 && soap_match_tag(soap, soap->type, ":short") | |
12085 && soap_match_tag(soap, soap->type, ":byte")) | |
12086 { soap->error = SOAP_TYPE; | |
12087 soap_revert(soap); | |
12088 return NULL; | |
12089 } | |
12090 #endif | |
12091 p = (long*)soap_id_enter(soap, soap->id, p, t, sizeof(long), 0, NULL, NULL, NULL); | |
12092 if (*soap->href) | |
12093 p = (long*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(long), 0, NULL); | |
12094 else if (p) | |
12095 { if (soap_s2long(soap, soap_value(soap), p)) | |
12096 return NULL; | |
12097 } | |
12098 if (soap->body && soap_element_end_in(soap, tag)) | |
12099 return NULL; | |
12100 return p; | |
12101 } | |
12102 #endif | |
12103 | |
12104 /******************************************************************************/ | |
12105 #ifndef WITH_LEAN | |
12106 SOAP_FMAC1 | |
12107 const char* | |
12108 SOAP_FMAC2 | |
12109 soap_LONG642s(struct soap *soap, LONG64 n) | |
12110 { | |
12111 #ifdef HAVE_SNPRINTF | |
12112 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), SOAP_LONG_FORMAT, n); | |
12113 #else | |
12114 sprintf(soap->tmpbuf, SOAP_LONG_FORMAT, n); | |
12115 #endif | |
12116 return soap->tmpbuf; | |
12117 } | |
12118 #endif | |
12119 | |
12120 /******************************************************************************/ | |
12121 #ifndef WITH_LEAN | |
12122 SOAP_FMAC1 | |
12123 int | |
12124 SOAP_FMAC2 | |
12125 soap_outLONG64(struct soap *soap, const char *tag, int id, const LONG64 *p, const char *type, int n) | |
12126 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) | |
12127 || soap_string_out(soap, soap_LONG642s(soap, *p), 0)) | |
12128 return soap->error; | |
12129 return soap_element_end_out(soap, tag); | |
12130 } | |
12131 #endif | |
12132 | |
12133 /******************************************************************************/ | |
12134 #ifndef WITH_LEAN | |
12135 SOAP_FMAC1 | |
12136 int | |
12137 SOAP_FMAC2 | |
12138 soap_s2LONG64(struct soap *soap, const char *s, LONG64 *p) | |
12139 { if (s) | |
12140 { | |
12141 #ifdef HAVE_STRTOLL | |
12142 char *r; | |
12143 #ifndef WITH_NOIO | |
12144 #ifndef WITH_LEAN | |
12145 soap_reset_errno; | |
12146 #endif | |
12147 #endif | |
12148 *p = soap_strtoll(s, &r, 10); | |
12149 if (s == r || *r | |
12150 #ifndef WITH_NOIO | |
12151 #ifndef WITH_LEAN | |
12152 || soap_errno == SOAP_ERANGE | |
12153 #endif | |
12154 #endif | |
12155 ) | |
12156 #else | |
12157 # ifdef HAVE_SSCANF | |
12158 if (sscanf(s, SOAP_LONG_FORMAT, p) != 1) | |
12159 # endif | |
12160 #endif | |
12161 soap->error = SOAP_TYPE; | |
12162 } | |
12163 return soap->error; | |
12164 } | |
12165 #endif | |
12166 | |
12167 /******************************************************************************/ | |
12168 #ifndef WITH_LEAN | |
12169 SOAP_FMAC1 | |
12170 LONG64 * | |
12171 SOAP_FMAC2 | |
12172 soap_inLONG64(struct soap *soap, const char *tag, LONG64 *p, const char *type, int t) | |
12173 { if (soap_element_begin_in(soap, tag, 0, NULL)) | |
12174 return NULL; | |
12175 #ifndef WITH_LEAN | |
12176 if (*soap->type | |
12177 && soap_match_tag(soap, soap->type, type) | |
12178 && soap_match_tag(soap, soap->type, ":integer") | |
12179 && soap_match_tag(soap, soap->type, ":positiveInteger") | |
12180 && soap_match_tag(soap, soap->type, ":negativeInteger") | |
12181 && soap_match_tag(soap, soap->type, ":nonPositiveInteger") | |
12182 && soap_match_tag(soap, soap->type, ":nonNegativeInteger") | |
12183 && soap_match_tag(soap, soap->type, ":long") | |
12184 && soap_match_tag(soap, soap->type, ":int") | |
12185 && soap_match_tag(soap, soap->type, ":short") | |
12186 && soap_match_tag(soap, soap->type, ":byte")) | |
12187 { soap->error = SOAP_TYPE; | |
12188 soap_revert(soap); | |
12189 return NULL; | |
12190 } | |
12191 #endif | |
12192 p = (LONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(LONG64), 0, NULL, NULL, NULL); | |
12193 if (*soap->href) | |
12194 p = (LONG64*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(LONG64), 0, NULL); | |
12195 else if (p) | |
12196 { if (soap_s2LONG64(soap, soap_value(soap), p)) | |
12197 return NULL; | |
12198 } | |
12199 if (soap->body && soap_element_end_in(soap, tag)) | |
12200 return NULL; | |
12201 return p; | |
12202 } | |
12203 #endif | |
12204 | |
12205 /******************************************************************************/ | |
12206 #ifndef PALM_2 | |
12207 SOAP_FMAC1 | |
12208 const char* | |
12209 SOAP_FMAC2 | |
12210 soap_byte2s(struct soap *soap, char n) | |
12211 { return soap_long2s(soap, (long)n); | |
12212 } | |
12213 #endif | |
12214 | |
12215 /******************************************************************************/ | |
12216 #ifndef PALM_2 | |
12217 SOAP_FMAC1 | |
12218 int | |
12219 SOAP_FMAC2 | |
12220 soap_outbyte(struct soap *soap, const char *tag, int id, const char *p, const char *type, int n) | |
12221 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) | |
12222 || soap_string_out(soap, soap_long2s(soap, (long)*p), 0)) | |
12223 return soap->error; | |
12224 return soap_element_end_out(soap, tag); | |
12225 } | |
12226 #endif | |
12227 | |
12228 /******************************************************************************/ | |
12229 #ifndef PALM_2 | |
12230 SOAP_FMAC1 | |
12231 int | |
12232 SOAP_FMAC2 | |
12233 soap_s2byte(struct soap *soap, const char *s, char *p) | |
12234 { if (s) | |
12235 { long n; | |
12236 char *r; | |
12237 n = soap_strtol(s, &r, 10); | |
12238 if (s == r || *r || n < -128 || n > 127) | |
12239 soap->error = SOAP_TYPE; | |
12240 *p = (char)n; | |
12241 } | |
12242 return soap->error; | |
12243 } | |
12244 #endif | |
12245 | |
12246 /******************************************************************************/ | |
12247 #ifndef PALM_2 | |
12248 SOAP_FMAC1 | |
12249 char * | |
12250 SOAP_FMAC2 | |
12251 soap_inbyte(struct soap *soap, const char *tag, char *p, const char *type, int t) | |
12252 { if (soap_element_begin_in(soap, tag, 0, NULL)) | |
12253 return NULL; | |
12254 #ifndef WITH_LEAN | |
12255 if (*soap->type | |
12256 && soap_match_tag(soap, soap->type, type) | |
12257 && soap_match_tag(soap, soap->type, ":byte")) | |
12258 { soap->error = SOAP_TYPE; | |
12259 soap_revert(soap); | |
12260 return NULL; | |
12261 } | |
12262 #endif | |
12263 p = (char*)soap_id_enter(soap, soap->id, p, t, sizeof(char), 0, NULL, NULL, NULL); | |
12264 if (*soap->href) | |
12265 p = (char*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(char), 0, NULL); | |
12266 else if (p) | |
12267 { if (soap_s2byte(soap, soap_value(soap), p)) | |
12268 return NULL; | |
12269 } | |
12270 if (soap->body && soap_element_end_in(soap, tag)) | |
12271 return NULL; | |
12272 return p; | |
12273 } | |
12274 #endif | |
12275 | |
12276 /******************************************************************************/ | |
12277 #ifndef PALM_2 | |
12278 SOAP_FMAC1 | |
12279 const char* | |
12280 SOAP_FMAC2 | |
12281 soap_short2s(struct soap *soap, short n) | |
12282 { return soap_long2s(soap, (long)n); | |
12283 } | |
12284 #endif | |
12285 | |
12286 /******************************************************************************/ | |
12287 #ifndef PALM_2 | |
12288 SOAP_FMAC1 | |
12289 int | |
12290 SOAP_FMAC2 | |
12291 soap_outshort(struct soap *soap, const char *tag, int id, const short *p, const char *type, int n) | |
12292 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) | |
12293 || soap_string_out(soap, soap_long2s(soap, (long)*p), 0)) | |
12294 return soap->error; | |
12295 return soap_element_end_out(soap, tag); | |
12296 } | |
12297 #endif | |
12298 | |
12299 /******************************************************************************/ | |
12300 #ifndef PALM_2 | |
12301 SOAP_FMAC1 | |
12302 int | |
12303 SOAP_FMAC2 | |
12304 soap_s2short(struct soap *soap, const char *s, short *p) | |
12305 { if (s) | |
12306 { long n; | |
12307 char *r; | |
12308 n = soap_strtol(s, &r, 10); | |
12309 if (s == r || *r || n < -32768 || n > 32767) | |
12310 soap->error = SOAP_TYPE; | |
12311 *p = (short)n; | |
12312 } | |
12313 return soap->error; | |
12314 } | |
12315 #endif | |
12316 | |
12317 /******************************************************************************/ | |
12318 #ifndef PALM_2 | |
12319 SOAP_FMAC1 | |
12320 short * | |
12321 SOAP_FMAC2 | |
12322 soap_inshort(struct soap *soap, const char *tag, short *p, const char *type, int t) | |
12323 { if (soap_element_begin_in(soap, tag, 0, NULL)) | |
12324 return NULL; | |
12325 #ifndef WITH_LEAN | |
12326 if (*soap->type | |
12327 && soap_match_tag(soap, soap->type, type) | |
12328 && soap_match_tag(soap, soap->type, ":short") | |
12329 && soap_match_tag(soap, soap->type, ":byte")) | |
12330 { soap->error = SOAP_TYPE; | |
12331 soap_revert(soap); | |
12332 return NULL; | |
12333 } | |
12334 #endif | |
12335 p = (short*)soap_id_enter(soap, soap->id, p, t, sizeof(short), 0, NULL, NULL, NULL); | |
12336 if (*soap->href) | |
12337 p = (short*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(short), 0, NULL); | |
12338 else if (p) | |
12339 { if (soap_s2short(soap, soap_value(soap), p)) | |
12340 return NULL; | |
12341 } | |
12342 if (soap->body && soap_element_end_in(soap, tag)) | |
12343 return NULL; | |
12344 return p; | |
12345 } | |
12346 #endif | |
12347 | |
12348 /******************************************************************************/ | |
12349 #ifndef PALM_2 | |
12350 SOAP_FMAC1 | |
12351 const char* | |
12352 SOAP_FMAC2 | |
12353 soap_float2s(struct soap *soap, float n) | |
12354 { char *s; | |
12355 if (soap_isnan((double)n)) | |
12356 return "NaN"; | |
12357 if (soap_ispinff(n)) | |
12358 return "INF"; | |
12359 if (soap_isninff(n)) | |
12360 return "-INF"; | |
12361 #if defined(HAVE_SPRINTF_L) | |
12362 # ifdef WIN32 | |
12363 _sprintf_s_l(soap->tmpbuf, _countof(soap->tmpbuf), soap->float_format, soap->c_locale, n); | |
12364 # else | |
12365 sprintf_l(soap->tmpbuf, soap->c_locale, soap->float_format, n); | |
12366 # endif | |
12367 #else | |
12368 # ifdef HAVE_SNPRINTF | |
12369 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), soap->float_format, n); | |
12370 # else | |
12371 sprintf(soap->tmpbuf, soap->float_format, n); | |
12372 # endif | |
12373 s = strchr(soap->tmpbuf, ','); /* convert decimal comma to DP */ | |
12374 if (s) | |
12375 *s = '.'; | |
12376 #endif | |
12377 return soap->tmpbuf; | |
12378 } | |
12379 #endif | |
12380 | |
12381 /******************************************************************************/ | |
12382 #ifndef PALM_2 | |
12383 SOAP_FMAC1 | |
12384 int | |
12385 SOAP_FMAC2 | |
12386 soap_outfloat(struct soap *soap, const char *tag, int id, const float *p, const char *type, int n) | |
12387 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) | |
12388 || soap_string_out(soap, soap_float2s(soap, *p), 0)) | |
12389 return soap->error; | |
12390 return soap_element_end_out(soap, tag); | |
12391 } | |
12392 #endif | |
12393 | |
12394 /******************************************************************************/ | |
12395 #ifndef PALM_2 | |
12396 SOAP_FMAC1 | |
12397 int | |
12398 SOAP_FMAC2 | |
12399 soap_s2float(struct soap *soap, const char *s, float *p) | |
12400 { if (s) | |
12401 { if (!*s) | |
12402 return soap->error = SOAP_TYPE; | |
12403 if (!soap_tag_cmp(s, "INF")) | |
12404 *p = FLT_PINFTY; | |
12405 else if (!soap_tag_cmp(s, "+INF")) | |
12406 *p = FLT_PINFTY; | |
12407 else if (!soap_tag_cmp(s, "-INF")) | |
12408 *p = FLT_NINFTY; | |
12409 else if (!soap_tag_cmp(s, "NaN")) | |
12410 *p = FLT_NAN; | |
12411 else | |
12412 { | |
12413 /* On some systems strtof requires -std=c99 or does not even link: so we try to use strtod first */ | |
12414 #if defined(HAVE_STRTOD_L) | |
12415 char *r; | |
12416 # ifdef WIN32 | |
12417 *p = (float)_strtod_l(s, &r, soap->c_locale); | |
12418 # else | |
12419 *p = (float)strtod_l(s, &r, soap->c_locale); | |
12420 # endif | |
12421 if (*r) | |
12422 #elif defined(HAVE_STRTOD) | |
12423 char *r; | |
12424 *p = (float)strtod(s, &r); | |
12425 if (*r) | |
12426 #elif defined(HAVE_STRTOF_L) | |
12427 char *r; | |
12428 *p = strtof_l((char*)s, &r, soap->c_locale); | |
12429 if (*r) | |
12430 #elif defined(HAVE_STRTOF) | |
12431 char *r; | |
12432 *p = strtof((char*)s, &r); | |
12433 if (*r) | |
12434 #endif | |
12435 { | |
12436 #if defined(HAVE_SSCANF_L) && !defined(HAVE_STRTOF_L) && !defined(HAVE_STRTOD_L) | |
12437 if (sscanf_l(s, soap->c_locale, "%f", p) != 1) | |
12438 soap->error = SOAP_TYPE; | |
12439 #elif defined(HAVE_SSCANF) | |
12440 if (sscanf(s, "%f", p) != 1) | |
12441 soap->error = SOAP_TYPE; | |
12442 #else | |
12443 soap->error = SOAP_TYPE; | |
12444 #endif | |
12445 } | |
12446 } | |
12447 } | |
12448 return soap->error; | |
12449 } | |
12450 #endif | |
12451 | |
12452 /******************************************************************************/ | |
12453 #ifndef WITH_LEAN | |
12454 static int soap_isnumeric(struct soap *soap, const char *type) | |
12455 { if (soap_match_tag(soap, soap->type, type) | |
12456 && soap_match_tag(soap, soap->type, ":float") | |
12457 && soap_match_tag(soap, soap->type, ":double") | |
12458 && soap_match_tag(soap, soap->type, ":decimal") | |
12459 && soap_match_tag(soap, soap->type, ":integer") | |
12460 && soap_match_tag(soap, soap->type, ":positiveInteger") | |
12461 && soap_match_tag(soap, soap->type, ":negativeInteger") | |
12462 && soap_match_tag(soap, soap->type, ":nonPositiveInteger") | |
12463 && soap_match_tag(soap, soap->type, ":nonNegativeInteger") | |
12464 && soap_match_tag(soap, soap->type, ":long") | |
12465 && soap_match_tag(soap, soap->type, ":int") | |
12466 && soap_match_tag(soap, soap->type, ":short") | |
12467 && soap_match_tag(soap, soap->type, ":byte") | |
12468 && soap_match_tag(soap, soap->type, ":unsignedLong") | |
12469 && soap_match_tag(soap, soap->type, ":unsignedInt") | |
12470 && soap_match_tag(soap, soap->type, ":unsignedShort") | |
12471 && soap_match_tag(soap, soap->type, ":unsignedByte")) | |
12472 { soap->error = SOAP_TYPE; | |
12473 soap_revert(soap); | |
12474 return SOAP_ERR; | |
12475 } | |
12476 return SOAP_OK; | |
12477 } | |
12478 #endif | |
12479 | |
12480 /******************************************************************************/ | |
12481 #ifndef PALM_2 | |
12482 SOAP_FMAC1 | |
12483 float * | |
12484 SOAP_FMAC2 | |
12485 soap_infloat(struct soap *soap, const char *tag, float *p, const char *type, int t) | |
12486 { if (soap_element_begin_in(soap, tag, 0, NULL)) | |
12487 return NULL; | |
12488 #ifndef WITH_LEAN | |
12489 if (*soap->type != '\0' && soap_isnumeric(soap, type)) | |
12490 return NULL; | |
12491 #endif | |
12492 p = (float*)soap_id_enter(soap, soap->id, p, t, sizeof(float), 0, NULL, NULL, NULL); | |
12493 if (*soap->href) | |
12494 p = (float*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(float), 0, NULL); | |
12495 else if (p) | |
12496 { if (soap_s2float(soap, soap_value(soap), p)) | |
12497 return NULL; | |
12498 } | |
12499 if (soap->body && soap_element_end_in(soap, tag)) | |
12500 return NULL; | |
12501 return p; | |
12502 } | |
12503 #endif | |
12504 | |
12505 /******************************************************************************/ | |
12506 #ifndef PALM_2 | |
12507 SOAP_FMAC1 | |
12508 const char* | |
12509 SOAP_FMAC2 | |
12510 soap_double2s(struct soap *soap, double n) | |
12511 { char *s; | |
12512 if (soap_isnan(n)) | |
12513 return "NaN"; | |
12514 if (soap_ispinfd(n)) | |
12515 return "INF"; | |
12516 if (soap_isninfd(n)) | |
12517 return "-INF"; | |
12518 #if defined(HAVE_SPRINTF_L) | |
12519 # ifdef WIN32 | |
12520 _sprintf_s_l(soap->tmpbuf, _countof(soap->tmpbuf), soap->double_format, soap->c_locale, n); | |
12521 # else | |
12522 sprintf_l(soap->tmpbuf, soap->c_locale, soap->double_format, n); | |
12523 # endif | |
12524 #else | |
12525 # ifdef HAVE_SNPRINTF | |
12526 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), soap->double_format, n); | |
12527 #else | |
12528 sprintf(soap->tmpbuf, soap->double_format, n); | |
12529 #endif | |
12530 s = strchr(soap->tmpbuf, ','); /* convert decimal comma to DP */ | |
12531 if (s) | |
12532 *s = '.'; | |
12533 #endif | |
12534 return soap->tmpbuf; | |
12535 } | |
12536 #endif | |
12537 | |
12538 /******************************************************************************/ | |
12539 #ifndef PALM_2 | |
12540 SOAP_FMAC1 | |
12541 int | |
12542 SOAP_FMAC2 | |
12543 soap_outdouble(struct soap *soap, const char *tag, int id, const double *p, const char *type, int n) | |
12544 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) | |
12545 || soap_string_out(soap, soap_double2s(soap, *p), 0)) | |
12546 return soap->error; | |
12547 return soap_element_end_out(soap, tag); | |
12548 } | |
12549 #endif | |
12550 | |
12551 /******************************************************************************/ | |
12552 #ifndef PALM_2 | |
12553 SOAP_FMAC1 | |
12554 int | |
12555 SOAP_FMAC2 | |
12556 soap_s2double(struct soap *soap, const char *s, double *p) | |
12557 { if (s) | |
12558 { if (!*s) | |
12559 return soap->error = SOAP_TYPE; | |
12560 if (!soap_tag_cmp(s, "INF")) | |
12561 *p = DBL_PINFTY; | |
12562 else if (!soap_tag_cmp(s, "+INF")) | |
12563 *p = DBL_PINFTY; | |
12564 else if (!soap_tag_cmp(s, "-INF")) | |
12565 *p = DBL_NINFTY; | |
12566 else if (!soap_tag_cmp(s, "NaN")) | |
12567 *p = DBL_NAN; | |
12568 else | |
12569 { | |
12570 #if defined(HAVE_STRTOD_L) | |
12571 char *r; | |
12572 # ifdef WIN32 | |
12573 *p = _strtod_l(s, &r, soap->c_locale); | |
12574 # else | |
12575 *p = strtod_l(s, &r, soap->c_locale); | |
12576 # endif | |
12577 if (*r) | |
12578 #elif defined(HAVE_STRTOD) | |
12579 char *r; | |
12580 *p = strtod(s, &r); | |
12581 if (*r) | |
12582 #endif | |
12583 { | |
12584 #if defined(HAVE_SSCANF_L) && !defined(HAVE_STRTOF_L) && !defined(HAVE_STRTOD_L) | |
12585 if (sscanf_l(s, soap->c_locale, "%lf", p) != 1) | |
12586 soap->error = SOAP_TYPE; | |
12587 #elif defined(HAVE_SSCANF) | |
12588 if (sscanf(s, "%lf", p) != 1) | |
12589 soap->error = SOAP_TYPE; | |
12590 #else | |
12591 soap->error = SOAP_TYPE; | |
12592 #endif | |
12593 } | |
12594 } | |
12595 } | |
12596 return soap->error; | |
12597 } | |
12598 #endif | |
12599 | |
12600 /******************************************************************************/ | |
12601 #ifndef PALM_2 | |
12602 SOAP_FMAC1 | |
12603 double * | |
12604 SOAP_FMAC2 | |
12605 soap_indouble(struct soap *soap, const char *tag, double *p, const char *type, int t) | |
12606 { if (soap_element_begin_in(soap, tag, 0, NULL)) | |
12607 return NULL; | |
12608 #ifndef WITH_LEAN | |
12609 if (*soap->type != '\0' && soap_isnumeric(soap, type)) | |
12610 return NULL; | |
12611 #endif | |
12612 p = (double*)soap_id_enter(soap, soap->id, p, t, sizeof(double), 0, NULL, NULL, NULL); | |
12613 if (*soap->href) | |
12614 p = (double*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(double), 0, NULL); | |
12615 else if (p) | |
12616 { if (soap_s2double(soap, soap_value(soap), p)) | |
12617 return NULL; | |
12618 } | |
12619 if (soap->body && soap_element_end_in(soap, tag)) | |
12620 return NULL; | |
12621 return p; | |
12622 } | |
12623 #endif | |
12624 | |
12625 /******************************************************************************/ | |
12626 #ifndef PALM_2 | |
12627 SOAP_FMAC1 | |
12628 const char* | |
12629 SOAP_FMAC2 | |
12630 soap_unsignedByte2s(struct soap *soap, unsigned char n) | |
12631 { return soap_unsignedLong2s(soap, (unsigned long)n); | |
12632 } | |
12633 #endif | |
12634 | |
12635 /******************************************************************************/ | |
12636 #ifndef PALM_2 | |
12637 SOAP_FMAC1 | |
12638 int | |
12639 SOAP_FMAC2 | |
12640 soap_outunsignedByte(struct soap *soap, const char *tag, int id, const unsigned char *p, const char *type, int n) | |
12641 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) | |
12642 || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0)) | |
12643 return soap->error; | |
12644 return soap_element_end_out(soap, tag); | |
12645 } | |
12646 #endif | |
12647 | |
12648 /******************************************************************************/ | |
12649 #ifndef PALM_2 | |
12650 SOAP_FMAC1 | |
12651 int | |
12652 SOAP_FMAC2 | |
12653 soap_s2unsignedByte(struct soap *soap, const char *s, unsigned char *p) | |
12654 { if (s) | |
12655 { unsigned long n; | |
12656 char *r; | |
12657 n = soap_strtoul(s, &r, 10); | |
12658 if (s == r || *r || n > 255) | |
12659 soap->error = SOAP_TYPE; | |
12660 *p = (unsigned char)n; | |
12661 } | |
12662 return soap->error; | |
12663 } | |
12664 #endif | |
12665 | |
12666 /******************************************************************************/ | |
12667 #ifndef PALM_2 | |
12668 SOAP_FMAC1 | |
12669 unsigned char * | |
12670 SOAP_FMAC2 | |
12671 soap_inunsignedByte(struct soap *soap, const char *tag, unsigned char *p, const char *type, int t) | |
12672 { if (soap_element_begin_in(soap, tag, 0, NULL)) | |
12673 return NULL; | |
12674 #ifndef WITH_LEAN | |
12675 if (*soap->type | |
12676 && soap_match_tag(soap, soap->type, type) | |
12677 && soap_match_tag(soap, soap->type, ":unsignedByte")) | |
12678 { soap->error = SOAP_TYPE; | |
12679 soap_revert(soap); | |
12680 return NULL; | |
12681 } | |
12682 #endif | |
12683 p = (unsigned char*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned char), 0, NULL, NULL, NULL); | |
12684 if (*soap->href) | |
12685 p = (unsigned char*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned char), 0, NULL); | |
12686 else if (p) | |
12687 { if (soap_s2unsignedByte(soap, soap_value(soap), p)) | |
12688 return NULL; | |
12689 } | |
12690 if (soap->body && soap_element_end_in(soap, tag)) | |
12691 return NULL; | |
12692 return p; | |
12693 } | |
12694 #endif | |
12695 | |
12696 /******************************************************************************/ | |
12697 #ifndef PALM_2 | |
12698 SOAP_FMAC1 | |
12699 const char* | |
12700 SOAP_FMAC2 | |
12701 soap_unsignedShort2s(struct soap *soap, unsigned short n) | |
12702 { return soap_unsignedLong2s(soap, (unsigned long)n); | |
12703 } | |
12704 #endif | |
12705 | |
12706 /******************************************************************************/ | |
12707 #ifndef PALM_2 | |
12708 SOAP_FMAC1 | |
12709 int | |
12710 SOAP_FMAC2 | |
12711 soap_outunsignedShort(struct soap *soap, const char *tag, int id, const unsigned short *p, const char *type, int n) | |
12712 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) | |
12713 || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0)) | |
12714 return soap->error; | |
12715 return soap_element_end_out(soap, tag); | |
12716 } | |
12717 #endif | |
12718 | |
12719 /******************************************************************************/ | |
12720 #ifndef PALM_2 | |
12721 SOAP_FMAC1 | |
12722 int | |
12723 SOAP_FMAC2 | |
12724 soap_s2unsignedShort(struct soap *soap, const char *s, unsigned short *p) | |
12725 { if (s) | |
12726 { unsigned long n; | |
12727 char *r; | |
12728 n = soap_strtoul(s, &r, 10); | |
12729 if (s == r || *r || n > 65535) | |
12730 soap->error = SOAP_TYPE; | |
12731 *p = (unsigned short)n; | |
12732 } | |
12733 return soap->error; | |
12734 } | |
12735 #endif | |
12736 | |
12737 /******************************************************************************/ | |
12738 #ifndef PALM_2 | |
12739 SOAP_FMAC1 | |
12740 unsigned short * | |
12741 SOAP_FMAC2 | |
12742 soap_inunsignedShort(struct soap *soap, const char *tag, unsigned short *p, const char *type, int t) | |
12743 { if (soap_element_begin_in(soap, tag, 0, NULL)) | |
12744 return NULL; | |
12745 #ifndef WITH_LEAN | |
12746 if (*soap->type | |
12747 && soap_match_tag(soap, soap->type, type) | |
12748 && soap_match_tag(soap, soap->type, ":unsignedShort") | |
12749 && soap_match_tag(soap, soap->type, ":unsignedByte")) | |
12750 { soap->error = SOAP_TYPE; | |
12751 soap_revert(soap); | |
12752 return NULL; | |
12753 } | |
12754 #endif | |
12755 p = (unsigned short*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned short), 0, NULL, NULL, NULL); | |
12756 if (*soap->href) | |
12757 p = (unsigned short*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned short), 0, NULL); | |
12758 else if (p) | |
12759 { if (soap_s2unsignedShort(soap, soap_value(soap), p)) | |
12760 return NULL; | |
12761 } | |
12762 if (soap->body && soap_element_end_in(soap, tag)) | |
12763 return NULL; | |
12764 return p; | |
12765 } | |
12766 #endif | |
12767 | |
12768 /******************************************************************************/ | |
12769 #ifndef PALM_2 | |
12770 SOAP_FMAC1 | |
12771 const char* | |
12772 SOAP_FMAC2 | |
12773 soap_unsignedInt2s(struct soap *soap, unsigned int n) | |
12774 { return soap_unsignedLong2s(soap, (unsigned long)n); | |
12775 } | |
12776 #endif | |
12777 | |
12778 /******************************************************************************/ | |
12779 #ifndef PALM_2 | |
12780 SOAP_FMAC1 | |
12781 int | |
12782 SOAP_FMAC2 | |
12783 soap_outunsignedInt(struct soap *soap, const char *tag, int id, const unsigned int *p, const char *type, int n) | |
12784 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) | |
12785 || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0)) | |
12786 return soap->error; | |
12787 return soap_element_end_out(soap, tag); | |
12788 } | |
12789 #endif | |
12790 | |
12791 /******************************************************************************/ | |
12792 #ifndef PALM_2 | |
12793 SOAP_FMAC1 | |
12794 int | |
12795 SOAP_FMAC2 | |
12796 soap_s2unsignedInt(struct soap *soap, const char *s, unsigned int *p) | |
12797 { if (s) | |
12798 { char *r; | |
12799 #ifndef WITH_NOIO | |
12800 #ifndef WITH_LEAN | |
12801 soap_reset_errno; | |
12802 #endif | |
12803 #endif | |
12804 *p = (unsigned int)soap_strtoul(s, &r, 10); | |
12805 if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r | |
12806 #ifndef WITH_NOIO | |
12807 #ifndef WITH_LEAN | |
12808 || soap_errno == SOAP_ERANGE | |
12809 #endif | |
12810 #endif | |
12811 ) | |
12812 soap->error = SOAP_TYPE; | |
12813 } | |
12814 return soap->error; | |
12815 } | |
12816 #endif | |
12817 | |
12818 /******************************************************************************/ | |
12819 #ifndef PALM_2 | |
12820 SOAP_FMAC1 | |
12821 unsigned int * | |
12822 SOAP_FMAC2 | |
12823 soap_inunsignedInt(struct soap *soap, const char *tag, unsigned int *p, const char *type, int t) | |
12824 { if (soap_element_begin_in(soap, tag, 0, NULL)) | |
12825 return NULL; | |
12826 #ifndef WITH_LEAN | |
12827 if (*soap->type | |
12828 && soap_match_tag(soap, soap->type, type) | |
12829 && soap_match_tag(soap, soap->type, ":unsignedInt") | |
12830 && soap_match_tag(soap, soap->type, ":unsignedShort") | |
12831 && soap_match_tag(soap, soap->type, ":unsignedByte")) | |
12832 { soap->error = SOAP_TYPE; | |
12833 soap_revert(soap); | |
12834 return NULL; | |
12835 } | |
12836 #endif | |
12837 p = (unsigned int*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned int), 0, NULL, NULL, NULL); | |
12838 if (*soap->href) | |
12839 p = (unsigned int*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned int), 0, NULL); | |
12840 else if (p) | |
12841 { if (soap_s2unsignedInt(soap, soap_value(soap), p)) | |
12842 return NULL; | |
12843 } | |
12844 if (soap->body && soap_element_end_in(soap, tag)) | |
12845 return NULL; | |
12846 return p; | |
12847 } | |
12848 #endif | |
12849 | |
12850 /******************************************************************************/ | |
12851 #ifndef PALM_2 | |
12852 SOAP_FMAC1 | |
12853 const char* | |
12854 SOAP_FMAC2 | |
12855 soap_unsignedLong2s(struct soap *soap, unsigned long n) | |
12856 { | |
12857 #ifdef HAVE_SNPRINTF | |
12858 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%lu", n); | |
12859 #else | |
12860 sprintf(soap->tmpbuf, "%lu", n); | |
12861 #endif | |
12862 return soap->tmpbuf; | |
12863 } | |
12864 #endif | |
12865 | |
12866 /******************************************************************************/ | |
12867 #ifndef PALM_2 | |
12868 SOAP_FMAC1 | |
12869 int | |
12870 SOAP_FMAC2 | |
12871 soap_outunsignedLong(struct soap *soap, const char *tag, int id, const unsigned long *p, const char *type, int n) | |
12872 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) | |
12873 || soap_string_out(soap, soap_unsignedLong2s(soap, *p), 0)) | |
12874 return soap->error; | |
12875 return soap_element_end_out(soap, tag); | |
12876 } | |
12877 #endif | |
12878 | |
12879 /******************************************************************************/ | |
12880 #ifndef PALM_2 | |
12881 SOAP_FMAC1 | |
12882 int | |
12883 SOAP_FMAC2 | |
12884 soap_s2unsignedLong(struct soap *soap, const char *s, unsigned long *p) | |
12885 { if (s) | |
12886 { char *r; | |
12887 #ifndef WITH_NOIO | |
12888 #ifndef WITH_LEAN | |
12889 soap_reset_errno; | |
12890 #endif | |
12891 #endif | |
12892 *p = soap_strtoul(s, &r, 10); | |
12893 if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r | |
12894 #ifndef WITH_NOIO | |
12895 #ifndef WITH_LEAN | |
12896 || soap_errno == SOAP_ERANGE | |
12897 #endif | |
12898 #endif | |
12899 ) | |
12900 soap->error = SOAP_TYPE; | |
12901 } | |
12902 return soap->error; | |
12903 } | |
12904 #endif | |
12905 | |
12906 /******************************************************************************/ | |
12907 #ifndef PALM_2 | |
12908 SOAP_FMAC1 | |
12909 unsigned long * | |
12910 SOAP_FMAC2 | |
12911 soap_inunsignedLong(struct soap *soap, const char *tag, unsigned long *p, const char *type, int t) | |
12912 { if (soap_element_begin_in(soap, tag, 0, NULL)) | |
12913 return NULL; | |
12914 #ifndef WITH_LEAN | |
12915 if (*soap->type | |
12916 && soap_match_tag(soap, soap->type, type) | |
12917 && soap_match_tag(soap, soap->type, ":unsignedInt") | |
12918 && soap_match_tag(soap, soap->type, ":unsignedShort") | |
12919 && soap_match_tag(soap, soap->type, ":unsignedByte")) | |
12920 { soap->error = SOAP_TYPE; | |
12921 soap_revert(soap); | |
12922 return NULL; | |
12923 } | |
12924 #endif | |
12925 p = (unsigned long*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned long), 0, NULL, NULL, NULL); | |
12926 if (*soap->href) | |
12927 p = (unsigned long*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned long), 0, NULL); | |
12928 else if (p) | |
12929 { if (soap_s2unsignedLong(soap, soap_value(soap), p)) | |
12930 return NULL; | |
12931 } | |
12932 if (soap->body && soap_element_end_in(soap, tag)) | |
12933 return NULL; | |
12934 return p; | |
12935 } | |
12936 #endif | |
12937 | |
12938 /******************************************************************************/ | |
12939 #ifndef WITH_LEAN | |
12940 SOAP_FMAC1 | |
12941 const char* | |
12942 SOAP_FMAC2 | |
12943 soap_ULONG642s(struct soap *soap, ULONG64 n) | |
12944 { | |
12945 #ifdef HAVE_SNPRINTF | |
12946 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), SOAP_ULONG_FORMAT, n); | |
12947 #else | |
12948 sprintf(soap->tmpbuf, SOAP_ULONG_FORMAT, n); | |
12949 #endif | |
12950 return soap->tmpbuf; | |
12951 } | |
12952 #endif | |
12953 | |
12954 /******************************************************************************/ | |
12955 #ifndef WITH_LEAN | |
12956 SOAP_FMAC1 | |
12957 int | |
12958 SOAP_FMAC2 | |
12959 soap_outULONG64(struct soap *soap, const char *tag, int id, const ULONG64 *p, const char *type, int n) | |
12960 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) | |
12961 || soap_string_out(soap, soap_ULONG642s(soap, *p), 0)) | |
12962 return soap->error; | |
12963 return soap_element_end_out(soap, tag); | |
12964 } | |
12965 #endif | |
12966 | |
12967 /******************************************************************************/ | |
12968 #ifndef WITH_LEAN | |
12969 SOAP_FMAC1 | |
12970 int | |
12971 SOAP_FMAC2 | |
12972 soap_s2ULONG64(struct soap *soap, const char *s, ULONG64 *p) | |
12973 { if (s) | |
12974 { | |
12975 #ifdef HAVE_STRTOULL | |
12976 char *r; | |
12977 #ifndef WITH_NOIO | |
12978 #ifndef WITH_LEAN | |
12979 soap_reset_errno; | |
12980 #endif | |
12981 #endif | |
12982 *p = soap_strtoull(s, &r, 10); | |
12983 if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r | |
12984 #ifndef WITH_NOIO | |
12985 #ifndef WITH_LEAN | |
12986 || soap_errno == SOAP_ERANGE | |
12987 #endif | |
12988 #endif | |
12989 ) | |
12990 #else | |
12991 #ifdef HAVE_SSCANF | |
12992 if (sscanf(s, SOAP_ULONG_FORMAT, p) != 1) | |
12993 #endif | |
12994 #endif | |
12995 soap->error = SOAP_TYPE; | |
12996 } | |
12997 return soap->error; | |
12998 } | |
12999 #endif | |
13000 | |
13001 /******************************************************************************/ | |
13002 #ifndef WITH_LEAN | |
13003 SOAP_FMAC1 | |
13004 ULONG64 * | |
13005 SOAP_FMAC2 | |
13006 soap_inULONG64(struct soap *soap, const char *tag, ULONG64 *p, const char *type, int t) | |
13007 { if (soap_element_begin_in(soap, tag, 0, NULL)) | |
13008 return NULL; | |
13009 if (*soap->type | |
13010 && soap_match_tag(soap, soap->type, type) | |
13011 && soap_match_tag(soap, soap->type, ":positiveInteger") | |
13012 && soap_match_tag(soap, soap->type, ":nonNegativeInteger") | |
13013 && soap_match_tag(soap, soap->type, ":unsignedLong") | |
13014 && soap_match_tag(soap, soap->type, ":unsignedInt") | |
13015 && soap_match_tag(soap, soap->type, ":unsignedShort") | |
13016 && soap_match_tag(soap, soap->type, ":unsignedByte")) | |
13017 { soap->error = SOAP_TYPE; | |
13018 soap_revert(soap); | |
13019 return NULL; | |
13020 } | |
13021 p = (ULONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(ULONG64), 0, NULL, NULL, NULL); | |
13022 if (*soap->href) | |
13023 p = (ULONG64*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(ULONG64), 0, NULL); | |
13024 else if (p) | |
13025 { if (soap_s2ULONG64(soap, soap_value(soap), p)) | |
13026 return NULL; | |
13027 } | |
13028 if (soap->body && soap_element_end_in(soap, tag)) | |
13029 return NULL; | |
13030 return p; | |
13031 } | |
13032 #endif | |
13033 | |
13034 /******************************************************************************/ | |
13035 #ifndef PALM_2 | |
13036 SOAP_FMAC1 | |
13037 int | |
13038 SOAP_FMAC2 | |
13039 soap_s2string(struct soap *soap, const char *s, char **t, long minlen, long maxlen) | |
13040 { if (s) | |
13041 { long l = (long)strlen(s); | |
13042 if ((maxlen >= 0 && l > maxlen) || l < minlen) | |
13043 return soap->error = SOAP_LENGTH; | |
13044 if (!(*t = soap_strdup(soap, s))) | |
13045 return soap->error = SOAP_EOM; | |
13046 if (!(soap->mode & (SOAP_ENC_LATIN | SOAP_C_UTFSTRING))) | |
13047 { char *r = *t; | |
13048 /* remove non-ASCII chars */ | |
13049 for (s = *t; *s; s++) | |
13050 if (!(*s & 0x80)) | |
13051 *r++ = *s; | |
13052 *r = '\0'; | |
13053 } | |
13054 } | |
13055 return soap->error; | |
13056 } | |
13057 #endif | |
13058 | |
13059 /******************************************************************************/ | |
13060 #ifndef PALM_2 | |
13061 SOAP_FMAC1 | |
13062 int | |
13063 SOAP_FMAC2 | |
13064 soap_s2QName(struct soap *soap, const char *s, char **t, long minlen, long maxlen) | |
13065 { if (s) | |
13066 { long l = (long)strlen(s); | |
13067 if ((maxlen >= 0 && l > maxlen) || l < minlen) | |
13068 return soap->error = SOAP_LENGTH; | |
13069 soap->labidx = 0; | |
13070 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Normalized namespace(s) of QNames '%s'", s)); | |
13071 /* convert (by prefix normalize prefix) all QNames in s */ | |
13072 for (;;) | |
13073 { size_t n; | |
13074 struct soap_nlist *np; | |
13075 register const char *p; | |
13076 /* skip blanks */ | |
13077 while (*s && soap_blank((soap_wchar)*s)) | |
13078 s++; | |
13079 if (!*s) | |
13080 break; | |
13081 /* find next QName */ | |
13082 n = 1; | |
13083 while (s[n] && !soap_blank((soap_wchar)s[n])) | |
13084 n++; | |
13085 np = soap->nlist; | |
13086 /* if there is no namespace stack, or prefix is "#" or "xml" then copy string */ | |
13087 if (!np || *s == '#' || !strncmp(s, "xml:", 4)) | |
13088 { soap_append_lab(soap, s, n); | |
13089 } | |
13090 else /* we normalize the QName by replacing its prefix */ | |
13091 { const char *q; | |
13092 for (p = s; *p && p < s + n; p++) | |
13093 if (*p == ':') | |
13094 break; | |
13095 if (*p == ':') | |
13096 { size_t k = p - s; | |
13097 while (np && (strncmp(np->id, s, k) || np->id[k])) | |
13098 np = np->next; | |
13099 p++; | |
13100 } | |
13101 else | |
13102 { while (np && *np->id) | |
13103 np = np->next; | |
13104 p = s; | |
13105 } | |
13106 /* replace prefix */ | |
13107 if (np) | |
13108 { if (np->index >= 0 && soap->local_namespaces && (q = soap->local_namespaces[np->index].id)) | |
13109 { size_t k = strlen(q); | |
13110 if (q[k-1] != '_') | |
13111 soap_append_lab(soap, q, k); | |
13112 else | |
13113 { soap_append_lab(soap, "\"", 1); | |
13114 soap_append_lab(soap, soap->local_namespaces[np->index].ns, strlen(soap->local_namespaces[np->index].ns)); | |
13115 soap_append_lab(soap, "\"", 1); | |
13116 } | |
13117 } | |
13118 else if (np->ns) | |
13119 { soap_append_lab(soap, "\"", 1); | |
13120 soap_append_lab(soap, np->ns, strlen(np->ns)); | |
13121 soap_append_lab(soap, "\"", 1); | |
13122 } | |
13123 else | |
13124 { 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)); | |
13125 return soap->error = SOAP_NAMESPACE; | |
13126 } | |
13127 } | |
13128 else if (s[n]) /* no namespace, part of string */ | |
13129 { soap_append_lab(soap, s, n); | |
13130 } | |
13131 else /* no namespace: assume "" namespace */ | |
13132 { soap_append_lab(soap, "\"\"", 2); | |
13133 } | |
13134 soap_append_lab(soap, ":", 1); | |
13135 soap_append_lab(soap, p, n - (p-s)); | |
13136 } | |
13137 /* advance to next and add spacing */ | |
13138 s += n; | |
13139 if (*s) | |
13140 soap_append_lab(soap, " ", 1); | |
13141 } | |
13142 soap_append_lab(soap, SOAP_STR_EOS, 1); | |
13143 *t = soap_strdup(soap, soap->labbuf); | |
13144 DBGLOG(TEST, SOAP_MESSAGE(fdebug, " into '%s'\n", *t)); | |
13145 } | |
13146 return soap->error; | |
13147 } | |
13148 #endif | |
13149 | |
13150 /******************************************************************************/ | |
13151 #ifndef PALM_2 | |
13152 SOAP_FMAC1 | |
13153 const char* | |
13154 SOAP_FMAC2 | |
13155 soap_QName2s(struct soap *soap, const char *s) | |
13156 { const char *t = NULL; | |
13157 if (s) | |
13158 { soap->labidx = 0; | |
13159 for (;;) | |
13160 { size_t n; | |
13161 /* skip blanks */ | |
13162 while (*s && soap_blank((soap_wchar)*s)) | |
13163 s++; | |
13164 if (!*s) | |
13165 break; | |
13166 /* find next QName */ | |
13167 n = 1; | |
13168 while (s[n] && !soap_blank((soap_wchar)s[n])) | |
13169 n++; | |
13170 /* normal prefix: pass string as is */ | |
13171 if (*s != '"') | |
13172 { | |
13173 #ifndef WITH_LEAN | |
13174 if ((soap->mode & SOAP_XML_CANONICAL)) | |
13175 soap_utilize_ns(soap, s); | |
13176 if ((soap->mode & SOAP_XML_DEFAULTNS)) | |
13177 { const char *r = strchr(s, ':'); | |
13178 if (r && soap->nlist && !strncmp(soap->nlist->id, s, r-s) && !soap->nlist->id[r-s]) | |
13179 { n -= r-s + 1; | |
13180 s = r + 1; | |
13181 } | |
13182 } | |
13183 #endif | |
13184 soap_append_lab(soap, s, n); | |
13185 } | |
13186 else /* URL-based string prefix */ | |
13187 { const char *q; | |
13188 s++; | |
13189 q = strchr(s, '"'); | |
13190 if (q) | |
13191 { struct Namespace *p = soap->local_namespaces; | |
13192 if (p) | |
13193 { for (; p->id; p++) | |
13194 { if (p->ns) | |
13195 if (!soap_tag_cmp(s, p->ns)) | |
13196 break; | |
13197 if (p->in) | |
13198 if (!soap_tag_cmp(s, p->in)) | |
13199 break; | |
13200 } | |
13201 } | |
13202 /* URL is in the namespace table? */ | |
13203 if (p && p->id) | |
13204 { const char *r = p->id; | |
13205 #ifndef WITH_LEAN | |
13206 if ((soap->mode & SOAP_XML_DEFAULTNS) && soap->nlist && !strcmp(soap->nlist->id, r)) | |
13207 q++; | |
13208 else | |
13209 #endif | |
13210 soap_append_lab(soap, r, strlen(r)); | |
13211 } | |
13212 else /* not in namespace table: create xmlns binding */ | |
13213 { char *r = soap_strdup(soap, s); | |
13214 r[q-s] = '\0'; | |
13215 #ifdef HAVE_SNPRINTF | |
13216 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "xmlns:_%d", soap->idnum++); | |
13217 #else | |
13218 sprintf(soap->tmpbuf, "xmlns:_%d", soap->idnum++); | |
13219 #endif | |
13220 soap_set_attr(soap, soap->tmpbuf, r, 1); | |
13221 soap_append_lab(soap, soap->tmpbuf + 6, strlen(soap->tmpbuf + 6)); | |
13222 } | |
13223 soap_append_lab(soap, q + 1, n - (q-s) - 1); | |
13224 } | |
13225 } | |
13226 /* advance to next and add spacing */ | |
13227 s += n; | |
13228 if (*s) | |
13229 soap_append_lab(soap, " ", 1); | |
13230 } | |
13231 soap_append_lab(soap, SOAP_STR_EOS, 1); | |
13232 t = soap_strdup(soap, soap->labbuf); | |
13233 } | |
13234 return t; | |
13235 } | |
13236 #endif | |
13237 | |
13238 /******************************************************************************/ | |
13239 #ifndef WITH_LEAN | |
13240 SOAP_FMAC1 | |
13241 int | |
13242 SOAP_FMAC2 | |
13243 soap_s2wchar(struct soap *soap, const char *s, wchar_t **t, long minlen, long maxlen) | |
13244 { if (s) | |
13245 { long l; | |
13246 wchar_t *r; | |
13247 *t = r = (wchar_t*)soap_malloc(soap, sizeof(wchar_t) * (strlen(s) + 1)); | |
13248 if (!r) | |
13249 return soap->error = SOAP_EOM; | |
13250 if (soap->mode & SOAP_ENC_LATIN) | |
13251 { while (*s) | |
13252 *r++ = (wchar_t)*s++; | |
13253 } | |
13254 else | |
13255 { /* Convert UTF8 to wchar */ | |
13256 while (*s) | |
13257 { register soap_wchar c, c1, c2, c3, c4; | |
13258 c = (unsigned char)*s++; | |
13259 if (c < 0x80) | |
13260 *r++ = (wchar_t)c; | |
13261 else | |
13262 { c1 = (soap_wchar)*s++ & 0x3F; | |
13263 if (c < 0xE0) | |
13264 *r++ = (wchar_t)(((soap_wchar)(c & 0x1F) << 6) | c1); | |
13265 else | |
13266 { c2 = (soap_wchar)*s++ & 0x3F; | |
13267 if (c < 0xF0) | |
13268 *r++ = (wchar_t)(((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2); | |
13269 else | |
13270 { c3 = (soap_wchar)*s++ & 0x3F; | |
13271 if (c < 0xF8) | |
13272 *r++ = (wchar_t)(((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3); | |
13273 else | |
13274 { c4 = (soap_wchar)*s++ & 0x3F; | |
13275 if (c < 0xFC) | |
13276 *r++ = (wchar_t)(((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4); | |
13277 else | |
13278 *r++ = (wchar_t)(((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(*s++ & 0x3F)); | |
13279 } | |
13280 } | |
13281 } | |
13282 } | |
13283 } | |
13284 } | |
13285 *r = L'\0'; | |
13286 l = (long)(r - *t); | |
13287 if ((maxlen >= 0 && l > maxlen) || l < minlen) | |
13288 return soap->error = SOAP_LENGTH; | |
13289 } | |
13290 return soap->error; | |
13291 } | |
13292 #endif | |
13293 | |
13294 /******************************************************************************/ | |
13295 #ifndef WITH_LEAN | |
13296 SOAP_FMAC1 | |
13297 const char* | |
13298 SOAP_FMAC2 | |
13299 soap_wchar2s(struct soap *soap, const wchar_t *s) | |
13300 { register soap_wchar c; | |
13301 register char *r, *t; | |
13302 const wchar_t *q = s; | |
13303 size_t n = 0; | |
13304 while ((c = *q++)) | |
13305 { if (c > 0 && c < 0x80) | |
13306 n++; | |
13307 else | |
13308 n += 6; | |
13309 } | |
13310 r = t = (char*)soap_malloc(soap, n + 1); | |
13311 if (r) | |
13312 { /* Convert wchar to UTF8 */ | |
13313 while ((c = *s++)) | |
13314 { if (c > 0 && c < 0x80) | |
13315 *t++ = (char)c; | |
13316 else | |
13317 { if (c < 0x0800) | |
13318 *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); | |
13319 else | |
13320 { if (c < 0x010000) | |
13321 *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); | |
13322 else | |
13323 { if (c < 0x200000) | |
13324 *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); | |
13325 else | |
13326 { if (c < 0x04000000) | |
13327 *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); | |
13328 else | |
13329 { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); | |
13330 *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); | |
13331 } | |
13332 *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); | |
13333 } | |
13334 *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); | |
13335 } | |
13336 *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); | |
13337 } | |
13338 *t++ = (char)(0x80 | (c & 0x3F)); | |
13339 } | |
13340 } | |
13341 *t = '\0'; | |
13342 } | |
13343 return r; | |
13344 } | |
13345 #endif | |
13346 | |
13347 /******************************************************************************/ | |
13348 #ifndef PALM_2 | |
13349 SOAP_FMAC1 | |
13350 int | |
13351 SOAP_FMAC2 | |
13352 soap_outstring(struct soap *soap, const char *tag, int id, char *const*p, const char *type, int n) | |
13353 { id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n); | |
13354 if (id < 0) | |
13355 return soap->error; | |
13356 if (!**p && (soap->mode & SOAP_C_NILSTRING)) | |
13357 return soap_element_null(soap, tag, id, type); | |
13358 if (soap_element_begin_out(soap, tag, id, type) | |
13359 || soap_string_out(soap, *p, 0) | |
13360 || soap_element_end_out(soap, tag)) | |
13361 return soap->error; | |
13362 return SOAP_OK; | |
13363 } | |
13364 #endif | |
13365 | |
13366 /******************************************************************************/ | |
13367 #ifndef PALM_2 | |
13368 SOAP_FMAC1 | |
13369 char ** | |
13370 SOAP_FMAC2 | |
13371 soap_instring(struct soap *soap, const char *tag, char **p, const char *type, int t, int flag, long minlen, long maxlen) | |
13372 { (void)type; | |
13373 if (soap_element_begin_in(soap, tag, 1, NULL)) | |
13374 { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG) | |
13375 return NULL; | |
13376 soap->error = SOAP_OK; | |
13377 } | |
13378 if (!p) | |
13379 { if (!(p = (char**)soap_malloc(soap, sizeof(char*)))) | |
13380 return NULL; | |
13381 } | |
13382 if (soap->null) | |
13383 *p = NULL; | |
13384 else if (soap->body) | |
13385 { *p = soap_string_in(soap, flag, minlen, maxlen); | |
13386 if (!*p || !(char*)soap_id_enter(soap, soap->id, *p, t, sizeof(char*), 0, NULL, NULL, NULL)) | |
13387 return NULL; | |
13388 if (!**p && tag && *tag == '-') | |
13389 { soap->error = SOAP_NO_TAG; | |
13390 return NULL; | |
13391 } | |
13392 } | |
13393 else if (tag && *tag == '-') | |
13394 { soap->error = SOAP_NO_TAG; | |
13395 return NULL; | |
13396 } | |
13397 else if (!*soap->href && minlen > 0) | |
13398 { soap->error = SOAP_LENGTH; | |
13399 return NULL; | |
13400 } | |
13401 else | |
13402 *p = soap_strdup(soap, SOAP_STR_EOS); | |
13403 if (*soap->href) | |
13404 p = (char**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(char**), 0); | |
13405 if (soap->body && soap_element_end_in(soap, tag)) | |
13406 return NULL; | |
13407 return p; | |
13408 } | |
13409 #endif | |
13410 | |
13411 /******************************************************************************/ | |
13412 #ifndef WITH_LEANER | |
13413 #ifndef PALM_2 | |
13414 SOAP_FMAC1 | |
13415 int | |
13416 SOAP_FMAC2 | |
13417 soap_outwstring(struct soap *soap, const char *tag, int id, wchar_t *const*p, const char *type, int n) | |
13418 { id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n); | |
13419 if (id < 0) | |
13420 return soap->error; | |
13421 if (!**p && (soap->mode & SOAP_C_NILSTRING)) | |
13422 return soap_element_null(soap, tag, id, type); | |
13423 if (soap_element_begin_out(soap, tag, id, type) | |
13424 || soap_wstring_out(soap, *p, 0) | |
13425 || soap_element_end_out(soap, tag)) | |
13426 return soap->error; | |
13427 return SOAP_OK; | |
13428 } | |
13429 #endif | |
13430 #endif | |
13431 | |
13432 /******************************************************************************/ | |
13433 #ifndef WITH_LEANER | |
13434 #ifndef PALM_2 | |
13435 SOAP_FMAC1 | |
13436 wchar_t ** | |
13437 SOAP_FMAC2 | |
13438 soap_inwstring(struct soap *soap, const char *tag, wchar_t **p, const char *type, int t, long minlen, long maxlen) | |
13439 { (void)type; | |
13440 if (soap_element_begin_in(soap, tag, 1, NULL)) | |
13441 { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG) | |
13442 return NULL; | |
13443 soap->error = SOAP_OK; | |
13444 } | |
13445 if (!p) | |
13446 { if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*)))) | |
13447 return NULL; | |
13448 } | |
13449 if (soap->body) | |
13450 { *p = soap_wstring_in(soap, 1, minlen, maxlen); | |
13451 if (!*p || !(wchar_t*)soap_id_enter(soap, soap->id, *p, t, sizeof(wchar_t*), 0, NULL, NULL, NULL)) | |
13452 return NULL; | |
13453 if (!**p && tag && *tag == '-') | |
13454 { soap->error = SOAP_NO_TAG; | |
13455 return NULL; | |
13456 } | |
13457 } | |
13458 else if (tag && *tag == '-') | |
13459 { soap->error = SOAP_NO_TAG; | |
13460 return NULL; | |
13461 } | |
13462 else if (soap->null) | |
13463 *p = NULL; | |
13464 else | |
13465 *p = soap_wstrdup(soap, (wchar_t*)SOAP_STR_EOS); | |
13466 if (*soap->href) | |
13467 p = (wchar_t**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(wchar_t**), 0); | |
13468 if (soap->body && soap_element_end_in(soap, tag)) | |
13469 return NULL; | |
13470 return p; | |
13471 } | |
13472 #endif | |
13473 #endif | |
13474 | |
13475 /******************************************************************************/ | |
13476 #ifndef WITH_LEAN | |
13477 SOAP_FMAC1 | |
13478 time_t | |
13479 SOAP_FMAC2 | |
13480 soap_timegm(struct tm *T) | |
13481 { | |
13482 #if defined(HAVE_TIMEGM) | |
13483 return timegm(T); | |
13484 #else | |
13485 time_t t, g, z; | |
13486 struct tm tm; | |
13487 t = mktime(T); | |
13488 if (t == (time_t)-1) | |
13489 return (time_t)-1; | |
13490 #ifdef HAVE_GMTIME_R | |
13491 gmtime_r(&t, &tm); | |
13492 #else | |
13493 tm = *gmtime(&t); | |
13494 #endif | |
13495 tm.tm_isdst = 0; | |
13496 g = mktime(&tm); | |
13497 if (g == (time_t)-1) | |
13498 return (time_t)-1; | |
13499 z = g - t; | |
13500 return t - z; | |
13501 #endif | |
13502 } | |
13503 #endif | |
13504 | |
13505 /******************************************************************************/ | |
13506 #ifndef WITH_LEAN | |
13507 SOAP_FMAC1 | |
13508 const char* | |
13509 SOAP_FMAC2 | |
13510 soap_dateTime2s(struct soap *soap, time_t n) | |
13511 { struct tm T, *pT = &T; | |
13512 #if defined(HAVE_GMTIME_R) | |
13513 if (gmtime_r(&n, pT)) | |
13514 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); | |
13515 #elif defined(HAVE_GMTIME) | |
13516 if ((pT = gmtime(&n))) | |
13517 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); | |
13518 #elif defined(HAVE_TM_GMTOFF) || defined(HAVE_STRUCT_TM_TM_GMTOFF) || defined(HAVE_STRUCT_TM___TM_GMTOFF) | |
13519 #if defined(HAVE_LOCALTIME_R) | |
13520 if (localtime_r(&n, pT)) | |
13521 { strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S%z", pT); | |
13522 memmove(soap->tmpbuf + 23, soap->tmpbuf + 22, 3); /* 2000-03-01T02:00:00+0300 */ | |
13523 soap->tmpbuf[22] = ':'; /* 2000-03-01T02:00:00+03:00 */ | |
13524 } | |
13525 #else | |
13526 if ((pT = localtime(&n))) | |
13527 { strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S%z", pT); | |
13528 memmove(soap->tmpbuf + 23, soap->tmpbuf + 22, 3); /* 2000-03-01T02:00:00+0300 */ | |
13529 soap->tmpbuf[22] = ':'; /* 2000-03-01T02:00:00+03:00 */ | |
13530 } | |
13531 #endif | |
13532 #elif defined(HAVE_GETTIMEOFDAY) | |
13533 struct timezone tz; | |
13534 memset((void*)&tz, 0, sizeof(tz)); | |
13535 #if defined(HAVE_LOCALTIME_R) | |
13536 if (localtime_r(&n, pT)) | |
13537 { struct timeval tv; | |
13538 gettimeofday(&tv, &tz); | |
13539 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); | |
13540 #ifdef HAVE_SNPRINTF | |
13541 soap_snprintf(soap->tmpbuf + strlen(soap->tmpbuf), sizeof(soap->tmpbuf) - strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60); | |
13542 #else | |
13543 sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60); | |
13544 #endif | |
13545 } | |
13546 #else | |
13547 if ((pT = localtime(&n))) | |
13548 { struct timeval tv; | |
13549 gettimeofday(&tv, &tz); | |
13550 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); | |
13551 #ifdef HAVE_SNPRINTF | |
13552 soap_snprintf(soap->tmpbuf + strlen(soap->tmpbuf), sizeof(soap->tmpbuf) - strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60); | |
13553 #else | |
13554 sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60); | |
13555 #endif | |
13556 } | |
13557 #endif | |
13558 #elif defined(HAVE_FTIME) | |
13559 struct timeb t; | |
13560 memset((void*)&t, 0, sizeof(t)); | |
13561 #if defined(HAVE_LOCALTIME_R) | |
13562 if (localtime_r(&n, pT)) | |
13563 { | |
13564 #ifdef __BORLANDC__ | |
13565 ::ftime(&t); | |
13566 #else | |
13567 ftime(&t); | |
13568 #endif | |
13569 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); | |
13570 #ifdef HAVE_SNPRINTF | |
13571 soap_snprintf(soap->tmpbuf + strlen(soap->tmpbuf), sizeof(soap->tmpbuf) - strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60); | |
13572 #else | |
13573 sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60); | |
13574 #endif | |
13575 } | |
13576 #else | |
13577 if ((pT = localtime(&n))) | |
13578 { | |
13579 #ifdef __BORLANDC__ | |
13580 ::ftime(&t); | |
13581 #else | |
13582 ftime(&t); | |
13583 #endif | |
13584 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); | |
13585 #ifdef HAVE_SNPRINTF | |
13586 soap_snprintf(soap->tmpbuf + strlen(soap->tmpbuf), sizeof(soap->tmpbuf) - strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60); | |
13587 #else | |
13588 sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60); | |
13589 #endif | |
13590 } | |
13591 #endif | |
13592 #elif defined(HAVE_LOCALTIME_R) | |
13593 if (localtime_r(&n, pT)) | |
13594 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); | |
13595 #else | |
13596 if ((pT = localtime(&n))) | |
13597 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); | |
13598 #endif | |
13599 else | |
13600 strcpy(soap->tmpbuf, "1969-12-31T23:59:59Z"); | |
13601 return soap->tmpbuf; | |
13602 } | |
13603 #endif | |
13604 | |
13605 /******************************************************************************/ | |
13606 #ifndef WITH_LEAN | |
13607 SOAP_FMAC1 | |
13608 int | |
13609 SOAP_FMAC2 | |
13610 soap_outdateTime(struct soap *soap, const char *tag, int id, const time_t *p, const char *type, int n) | |
13611 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) | |
13612 || soap_string_out(soap, soap_dateTime2s(soap, *p), 0)) | |
13613 return soap->error; | |
13614 return soap_element_end_out(soap, tag); | |
13615 } | |
13616 #endif | |
13617 | |
13618 /******************************************************************************/ | |
13619 #ifndef WITH_LEAN | |
13620 SOAP_FMAC1 | |
13621 int | |
13622 SOAP_FMAC2 | |
13623 soap_s2dateTime(struct soap *soap, const char *s, time_t *p) | |
13624 { if (s) | |
13625 { char zone[32]; | |
13626 struct tm T; | |
13627 const char *t; | |
13628 *zone = '\0'; | |
13629 memset((void*)&T, 0, sizeof(T)); | |
13630 if (strchr(s, '-')) | |
13631 t = "%d-%d-%dT%d:%d:%d%31s"; | |
13632 else if (strchr(s, ':')) | |
13633 t = "%4d%2d%2dT%d:%d:%d%31s"; | |
13634 else /* parse non-XSD-standard alternative ISO 8601 format */ | |
13635 t = "%4d%2d%2dT%2d%2d%2d%31s"; | |
13636 if (sscanf(s, t, &T.tm_year, &T.tm_mon, &T.tm_mday, &T.tm_hour, &T.tm_min, &T.tm_sec, zone) < 6) | |
13637 return soap->error = SOAP_TYPE; | |
13638 if (T.tm_year == 1) | |
13639 T.tm_year = 70; | |
13640 else | |
13641 T.tm_year -= 1900; | |
13642 T.tm_mon--; | |
13643 if (*zone == '.') | |
13644 { for (s = zone + 1; *s; s++) | |
13645 if (*s < '0' || *s > '9') | |
13646 break; | |
13647 } | |
13648 else | |
13649 s = zone; | |
13650 if (*s) | |
13651 { | |
13652 #ifndef WITH_NOZONE | |
13653 if (*s == '+' || *s == '-') | |
13654 { int h = 0, m = 0; | |
13655 if (s[3] == ':') | |
13656 { /* +hh:mm */ | |
13657 sscanf(s, "%d:%d", &h, &m); | |
13658 if (h < 0) | |
13659 m = -m; | |
13660 } | |
13661 else /* +hhmm */ | |
13662 { m = (int)soap_strtol(s, NULL, 10); | |
13663 h = m / 100; | |
13664 m = m % 100; | |
13665 } | |
13666 T.tm_min -= m; | |
13667 T.tm_hour -= h; | |
13668 /* put hour and min in range */ | |
13669 T.tm_hour += T.tm_min / 60; | |
13670 T.tm_min %= 60; | |
13671 if (T.tm_min < 0) | |
13672 { T.tm_min += 60; | |
13673 T.tm_hour--; | |
13674 } | |
13675 T.tm_mday += T.tm_hour / 24; | |
13676 T.tm_hour %= 24; | |
13677 if (T.tm_hour < 0) | |
13678 { T.tm_hour += 24; | |
13679 T.tm_mday--; | |
13680 } | |
13681 /* note: day of the month may be out of range, timegm() handles it */ | |
13682 } | |
13683 #endif | |
13684 *p = soap_timegm(&T); | |
13685 } | |
13686 else /* no UTC or timezone, so assume we got a localtime */ | |
13687 { T.tm_isdst = -1; | |
13688 *p = mktime(&T); | |
13689 } | |
13690 } | |
13691 return soap->error; | |
13692 } | |
13693 #endif | |
13694 | |
13695 /******************************************************************************/ | |
13696 #ifndef WITH_LEAN | |
13697 SOAP_FMAC1 | |
13698 time_t * | |
13699 SOAP_FMAC2 | |
13700 soap_indateTime(struct soap *soap, const char *tag, time_t *p, const char *type, int t) | |
13701 { if (soap_element_begin_in(soap, tag, 0, NULL)) | |
13702 return NULL; | |
13703 if (*soap->type | |
13704 && soap_match_tag(soap, soap->type, type) | |
13705 && soap_match_tag(soap, soap->type, ":dateTime")) | |
13706 { soap->error = SOAP_TYPE; | |
13707 soap_revert(soap); | |
13708 return NULL; | |
13709 } | |
13710 p = (time_t*)soap_id_enter(soap, soap->id, p, t, sizeof(time_t), 0, NULL, NULL, NULL); | |
13711 if (*soap->href) | |
13712 p = (time_t*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(time_t), 0, NULL); | |
13713 else if (p) | |
13714 { if (soap_s2dateTime(soap, soap_value(soap), p)) | |
13715 return NULL; | |
13716 } | |
13717 if (soap->body && soap_element_end_in(soap, tag)) | |
13718 return NULL; | |
13719 return p; | |
13720 } | |
13721 #endif | |
13722 | |
13723 /******************************************************************************/ | |
13724 #ifndef PALM_2 | |
13725 SOAP_FMAC1 | |
13726 int | |
13727 SOAP_FMAC2 | |
13728 soap_outliteral(struct soap *soap, const char *tag, char *const*p, const char *type) | |
13729 { int i; | |
13730 const char *t = NULL; | |
13731 if (tag && *tag != '-') | |
13732 { if (soap->local_namespaces && (t = strchr(tag, ':'))) | |
13733 { size_t n = t - tag; | |
13734 if (n >= sizeof(soap->tmpbuf)) | |
13735 n = sizeof(soap->tmpbuf) - 1; | |
13736 strncpy(soap->tmpbuf, tag, n); | |
13737 soap->tmpbuf[n] = '\0'; | |
13738 for (i = 0; soap->local_namespaces[i].id; i++) | |
13739 if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id)) | |
13740 break; | |
13741 t++; | |
13742 if (soap_element(soap, t, 0, type) | |
13743 || soap_attribute(soap, "xmlns", soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS) | |
13744 || soap_element_start_end_out(soap, NULL)) | |
13745 return soap->error; | |
13746 } | |
13747 else | |
13748 { t = tag; | |
13749 if (soap_element_begin_out(soap, t, 0, type)) | |
13750 return soap->error; | |
13751 } | |
13752 } | |
13753 if (p && *p) | |
13754 { if (soap_send(soap, *p)) /* send as-is */ | |
13755 return soap->error; | |
13756 } | |
13757 if (t) | |
13758 return soap_element_end_out(soap, t); | |
13759 return SOAP_OK; | |
13760 } | |
13761 #endif | |
13762 | |
13763 /******************************************************************************/ | |
13764 #ifndef PALM_2 | |
13765 SOAP_FMAC1 | |
13766 char ** | |
13767 SOAP_FMAC2 | |
13768 soap_inliteral(struct soap *soap, const char *tag, char **p) | |
13769 { if (soap_element_begin_in(soap, tag, 1, NULL)) | |
13770 { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT) | |
13771 return NULL; | |
13772 soap->error = SOAP_OK; | |
13773 } | |
13774 if (!p) | |
13775 { if (!(p = (char**)soap_malloc(soap, sizeof(char*)))) | |
13776 return NULL; | |
13777 } | |
13778 if (soap->body || (tag && *tag == '-')) | |
13779 { *p = soap_string_in(soap, 0, -1, -1); | |
13780 if (!*p) | |
13781 return NULL; | |
13782 if (!**p && tag && *tag == '-') | |
13783 { soap->error = SOAP_NO_TAG; | |
13784 return NULL; | |
13785 } | |
13786 } | |
13787 else if (soap->null) | |
13788 *p = NULL; | |
13789 else | |
13790 *p = soap_strdup(soap, SOAP_STR_EOS); | |
13791 if (soap->body && soap_element_end_in(soap, tag)) | |
13792 return NULL; | |
13793 return p; | |
13794 } | |
13795 #endif | |
13796 | |
13797 /******************************************************************************/ | |
13798 #ifndef WITH_LEANER | |
13799 #ifndef PALM_2 | |
13800 SOAP_FMAC1 | |
13801 int | |
13802 SOAP_FMAC2 | |
13803 soap_outwliteral(struct soap *soap, const char *tag, wchar_t *const*p, const char *type) | |
13804 { int i; | |
13805 const char *t = NULL; | |
13806 if (tag && *tag != '-') | |
13807 { if (soap->local_namespaces && (t = strchr(tag, ':'))) | |
13808 { size_t n = t - tag; | |
13809 if (n >= sizeof(soap->tmpbuf)) | |
13810 n = sizeof(soap->tmpbuf) - 1; | |
13811 strncpy(soap->tmpbuf, tag, n); | |
13812 soap->tmpbuf[n] = '\0'; | |
13813 for (i = 0; soap->local_namespaces[i].id; i++) | |
13814 if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id)) | |
13815 break; | |
13816 t++; | |
13817 if (soap_element(soap, t, 0, type) | |
13818 || soap_attribute(soap, "xmlns", soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS) | |
13819 || soap_element_start_end_out(soap, NULL)) | |
13820 return soap->error; | |
13821 } | |
13822 else | |
13823 { t = tag; | |
13824 if (soap_element_begin_out(soap, t, 0, type)) | |
13825 return soap->error; | |
13826 } | |
13827 } | |
13828 if (p) | |
13829 { wchar_t c; | |
13830 const wchar_t *s = *p; | |
13831 while ((c = *s++)) | |
13832 { if (soap_pututf8(soap, (unsigned long)c)) /* send as-is in UTF8 */ | |
13833 return soap->error; | |
13834 } | |
13835 } | |
13836 if (t) | |
13837 return soap_element_end_out(soap, t); | |
13838 return SOAP_OK; | |
13839 } | |
13840 #endif | |
13841 #endif | |
13842 | |
13843 /******************************************************************************/ | |
13844 #ifndef WITH_LEANER | |
13845 #ifndef PALM_2 | |
13846 SOAP_FMAC1 | |
13847 wchar_t ** | |
13848 SOAP_FMAC2 | |
13849 soap_inwliteral(struct soap *soap, const char *tag, wchar_t **p) | |
13850 { if (soap_element_begin_in(soap, tag, 1, NULL)) | |
13851 { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT) | |
13852 return NULL; | |
13853 soap->error = SOAP_OK; | |
13854 } | |
13855 if (!p) | |
13856 { if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*)))) | |
13857 return NULL; | |
13858 } | |
13859 if (soap->body) | |
13860 { *p = soap_wstring_in(soap, 0, -1, -1); | |
13861 if (!*p) | |
13862 return NULL; | |
13863 if (!**p && tag && *tag == '-') | |
13864 { soap->error = SOAP_NO_TAG; | |
13865 return NULL; | |
13866 } | |
13867 } | |
13868 else if (tag && *tag == '-') | |
13869 { soap->error = SOAP_NO_TAG; | |
13870 return NULL; | |
13871 } | |
13872 else if (soap->null) | |
13873 *p = NULL; | |
13874 else | |
13875 *p = soap_wstrdup(soap, (wchar_t*)SOAP_STR_EOS); | |
13876 if (soap->body && soap_element_end_in(soap, tag)) | |
13877 return NULL; | |
13878 return p; | |
13879 } | |
13880 #endif | |
13881 #endif | |
13882 | |
13883 /******************************************************************************/ | |
13884 #ifndef PALM_2 | |
13885 SOAP_FMAC1 | |
13886 const char * | |
13887 SOAP_FMAC2 | |
13888 soap_value(struct soap *soap) | |
13889 { register size_t i; | |
13890 register soap_wchar c = 0; | |
13891 register char *s = soap->tmpbuf; | |
13892 if (!soap->body) | |
13893 return SOAP_STR_EOS; | |
13894 do c = soap_get(soap); | |
13895 while (soap_blank(c)); | |
13896 for (i = 0; i < sizeof(soap->tmpbuf) - 1; i++) | |
13897 { if (c == SOAP_TT || c == SOAP_LT || (int)c == EOF) | |
13898 break; | |
13899 *s++ = (char)c; | |
13900 c = soap_get(soap); | |
13901 } | |
13902 for (s--; i > 0; i--, s--) | |
13903 { if (!soap_blank((soap_wchar)*s)) | |
13904 break; | |
13905 } | |
13906 s[1] = '\0'; | |
13907 soap->tmpbuf[sizeof(soap->tmpbuf) - 1] = '\0'; /* appease */ | |
13908 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element content value='%s'\n", soap->tmpbuf)); | |
13909 if (c == SOAP_TT || c == SOAP_LT || (int)c == EOF) | |
13910 soap_unget(soap, c); | |
13911 else if (soap->mode & SOAP_XML_STRICT) | |
13912 { soap->error = SOAP_LENGTH; | |
13913 return NULL; | |
13914 } | |
13915 #ifdef WITH_DOM | |
13916 if ((soap->mode & SOAP_XML_DOM) && soap->dom) | |
13917 soap->dom->data = soap_strdup(soap, soap->tmpbuf); | |
13918 #endif | |
13919 return soap->tmpbuf; /* return non-null pointer */ | |
13920 } | |
13921 #endif | |
13922 | |
13923 /******************************************************************************/ | |
13924 #if !defined(WITH_LEANER) || !defined(WITH_NOHTTP) | |
13925 #ifndef PALM_2 | |
13926 SOAP_FMAC1 | |
13927 int | |
13928 SOAP_FMAC2 | |
13929 soap_getline(struct soap *soap, char *s, int len) | |
13930 { int i = len; | |
13931 soap_wchar c = 0; | |
13932 for (;;) | |
13933 { while (--i > 0) | |
13934 { c = soap_getchar(soap); | |
13935 if (c == '\r' || c == '\n') | |
13936 break; | |
13937 if ((int)c == EOF) | |
13938 return soap->error = SOAP_CHK_EOF; | |
13939 *s++ = (char)c; | |
13940 } | |
13941 *s = '\0'; | |
13942 if (c != '\n') | |
13943 c = soap_getchar(soap); /* got \r or something else, now get \n */ | |
13944 if (c == '\n') | |
13945 { if (i + 1 == len) /* empty line: end of HTTP/MIME header */ | |
13946 break; | |
13947 c = soap_get0(soap); | |
13948 if (c != ' ' && c != '\t') /* HTTP line continuation? */ | |
13949 break; | |
13950 } | |
13951 else if ((int)c == EOF) | |
13952 return soap->error = SOAP_CHK_EOF; | |
13953 if (i <= 0) | |
13954 return soap->error = SOAP_HDR; | |
13955 } | |
13956 return SOAP_OK; | |
13957 } | |
13958 #endif | |
13959 #endif | |
13960 | |
13961 /******************************************************************************/ | |
13962 #ifndef PALM_1 | |
13963 static size_t | |
13964 soap_count_attachments(struct soap *soap) | |
13965 { | |
13966 #ifndef WITH_LEANER | |
13967 register struct soap_multipart *content; | |
13968 register size_t count = soap->count; | |
13969 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the message size with attachments, current count=%lu\n", (unsigned long)count)); | |
13970 if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) | |
13971 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of DIME attachments\n")); | |
13972 for (content = soap->dime.first; content; content = content->next) | |
13973 { count += 12 + ((content->size+3)&(~3)); | |
13974 if (content->id) | |
13975 count += ((strlen(content->id)+3)&(~3)); | |
13976 if (content->type) | |
13977 count += ((strlen(content->type)+3)&(~3)); | |
13978 if (content->options) | |
13979 count += ((((unsigned char)content->options[2] << 8) | ((unsigned char)content->options[3]))+7)&(~3); | |
13980 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of DIME attachment content is %lu bytes\n", (unsigned long)content->size)); | |
13981 } | |
13982 } | |
13983 if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary) | |
13984 { register size_t n = strlen(soap->mime.boundary); | |
13985 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of MIME attachments\n")); | |
13986 for (content = soap->mime.first; content; content = content->next) | |
13987 { register const char *s; | |
13988 /* count \r\n--boundary\r\n */ | |
13989 count += 6 + n; | |
13990 /* count Content-Type: ...\r\n */ | |
13991 if (content->type) | |
13992 count += 16 + strlen(content->type); | |
13993 /* count Content-Transfer-Encoding: ...\r\n */ | |
13994 s = soap_code_str(mime_codes, content->encoding); | |
13995 if (s) | |
13996 count += 29 + strlen(s); | |
13997 /* count Content-ID: ...\r\n */ | |
13998 if (content->id) | |
13999 count += 14 + strlen(content->id); | |
14000 /* count Content-Location: ...\r\n */ | |
14001 if (content->location) | |
14002 count += 20 + strlen(content->location); | |
14003 /* count Content-Description: ...\r\n */ | |
14004 if (content->description) | |
14005 count += 23 + strlen(content->description); | |
14006 /* count \r\n...content */ | |
14007 count += 2 + content->size; | |
14008 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of MIME attachment content is %lu bytes\n", (unsigned long)content->size)); | |
14009 } | |
14010 /* count \r\n--boundary-- */ | |
14011 count += 6 + n; | |
14012 } | |
14013 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New count=%lu\n", (unsigned long)count)); | |
14014 return count; | |
14015 #else | |
14016 return soap->count; | |
14017 #endif | |
14018 } | |
14019 #endif | |
14020 | |
14021 /******************************************************************************/ | |
14022 #ifndef WITH_LEANER | |
14023 #ifndef PALM_1 | |
14024 static int | |
14025 soap_putdimefield(struct soap *soap, const char *s, size_t n) | |
14026 { if (soap_send_raw(soap, s, n)) | |
14027 return soap->error; | |
14028 return soap_send_raw(soap, SOAP_STR_PADDING, -(long)n&3); | |
14029 } | |
14030 #endif | |
14031 #endif | |
14032 | |
14033 /******************************************************************************/ | |
14034 #ifndef WITH_LEANER | |
14035 #ifndef PALM_1 | |
14036 SOAP_FMAC1 | |
14037 char * | |
14038 SOAP_FMAC2 | |
14039 soap_dime_option(struct soap *soap, unsigned short optype, const char *option) | |
14040 { size_t n; | |
14041 char *s = NULL; | |
14042 if (option) | |
14043 { n = strlen(option); | |
14044 s = (char*)soap_malloc(soap, n + 5); | |
14045 if (s) | |
14046 { s[0] = (char)(optype >> 8); | |
14047 s[1] = (char)(optype & 0xFF); | |
14048 s[2] = (char)(n >> 8); | |
14049 s[3] = (char)(n & 0xFF); | |
14050 strcpy(s + 4, option); | |
14051 } | |
14052 } | |
14053 return s; | |
14054 } | |
14055 #endif | |
14056 #endif | |
14057 | |
14058 /******************************************************************************/ | |
14059 #ifndef WITH_LEANER | |
14060 #ifndef PALM_1 | |
14061 SOAP_FMAC1 | |
14062 int | |
14063 SOAP_FMAC2 | |
14064 soap_putdimehdr(struct soap *soap) | |
14065 { unsigned char tmp[12]; | |
14066 size_t optlen = 0, idlen = 0, typelen = 0; | |
14067 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Put DIME header id='%s'\n", soap->dime.id ? soap->dime.id : SOAP_STR_EOS)); | |
14068 if (soap->dime.options) | |
14069 optlen = (((unsigned char)soap->dime.options[2] << 8) | ((unsigned char)soap->dime.options[3])) + 4; | |
14070 if (soap->dime.id) | |
14071 { idlen = strlen(soap->dime.id); | |
14072 if (idlen > 0x0000FFFF) | |
14073 idlen = 0x0000FFFF; | |
14074 } | |
14075 if (soap->dime.type) | |
14076 { typelen = strlen(soap->dime.type); | |
14077 if (typelen > 0x0000FFFF) | |
14078 typelen = 0x0000FFFF; | |
14079 } | |
14080 tmp[0] = SOAP_DIME_VERSION | (soap->dime.flags & 0x7); | |
14081 tmp[1] = soap->dime.flags & 0xF0; | |
14082 tmp[2] = (char)(optlen >> 8); | |
14083 tmp[3] = (char)(optlen & 0xFF); | |
14084 tmp[4] = (char)(idlen >> 8); | |
14085 tmp[5] = (char)(idlen & 0xFF); | |
14086 tmp[6] = (char)(typelen >> 8); | |
14087 tmp[7] = (char)(typelen & 0xFF); | |
14088 tmp[8] = (char)(soap->dime.size >> 24); | |
14089 tmp[9] = (char)((soap->dime.size >> 16) & 0xFF); | |
14090 tmp[10] = (char)((soap->dime.size >> 8) & 0xFF); | |
14091 tmp[11] = (char)(soap->dime.size & 0xFF); | |
14092 if (soap_send_raw(soap, (char*)tmp, 12) | |
14093 || soap_putdimefield(soap, soap->dime.options, optlen) | |
14094 || soap_putdimefield(soap, soap->dime.id, idlen) | |
14095 || soap_putdimefield(soap, soap->dime.type, typelen)) | |
14096 return soap->error; | |
14097 return SOAP_OK; | |
14098 } | |
14099 #endif | |
14100 #endif | |
14101 | |
14102 /******************************************************************************/ | |
14103 #ifndef WITH_LEANER | |
14104 #ifndef PALM_1 | |
14105 SOAP_FMAC1 | |
14106 int | |
14107 SOAP_FMAC2 | |
14108 soap_putdime(struct soap *soap) | |
14109 { struct soap_multipart *content; | |
14110 if (!(soap->mode & SOAP_ENC_DIME)) | |
14111 return SOAP_OK; | |
14112 for (content = soap->dime.first; content; content = content->next) | |
14113 { void *handle; | |
14114 soap->dime.size = content->size; | |
14115 soap->dime.id = content->id; | |
14116 soap->dime.type = content->type; | |
14117 soap->dime.options = content->options; | |
14118 soap->dime.flags = SOAP_DIME_VERSION | SOAP_DIME_MEDIA; | |
14119 if (soap->fdimereadopen && ((handle = soap->fdimereadopen(soap, (void*)content->ptr, content->id, content->type, content->options)) || soap->error)) | |
14120 { size_t size = content->size; | |
14121 if (!handle) | |
14122 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadopen failed\n")); | |
14123 return soap->error; | |
14124 } | |
14125 if (!size && ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE)) | |
14126 { size_t chunksize = sizeof(soap->tmpbuf); | |
14127 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming DIME\n")); | |
14128 do | |
14129 { size = soap->fdimeread(soap, handle, soap->tmpbuf, chunksize); | |
14130 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread returned %lu bytes\n", (unsigned long)size)); | |
14131 if (size < chunksize) | |
14132 { soap->dime.flags &= ~SOAP_DIME_CF; | |
14133 if (!content->next) | |
14134 soap->dime.flags |= SOAP_DIME_ME; | |
14135 } | |
14136 else | |
14137 soap->dime.flags |= SOAP_DIME_CF; | |
14138 soap->dime.size = size; | |
14139 if (soap_putdimehdr(soap) | |
14140 || soap_putdimefield(soap, soap->tmpbuf, size)) | |
14141 break; | |
14142 if (soap->dime.id) | |
14143 { soap->dime.flags &= ~(SOAP_DIME_MB | SOAP_DIME_MEDIA); | |
14144 soap->dime.id = NULL; | |
14145 soap->dime.type = NULL; | |
14146 soap->dime.options = NULL; | |
14147 } | |
14148 } while (size >= chunksize); | |
14149 } | |
14150 else | |
14151 { if (!content->next) | |
14152 soap->dime.flags |= SOAP_DIME_ME; | |
14153 if (soap_putdimehdr(soap)) | |
14154 return soap->error; | |
14155 do | |
14156 { size_t bufsize; | |
14157 if (size < sizeof(soap->tmpbuf)) | |
14158 bufsize = size; | |
14159 else | |
14160 bufsize = sizeof(soap->tmpbuf); | |
14161 if (!(bufsize = soap->fdimeread(soap, handle, soap->tmpbuf, bufsize))) | |
14162 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size)); | |
14163 soap->error = SOAP_CHK_EOF; | |
14164 break; | |
14165 } | |
14166 if (soap_send_raw(soap, soap->tmpbuf, bufsize)) | |
14167 break; | |
14168 size -= bufsize; | |
14169 } while (size); | |
14170 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n")); | |
14171 soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3); | |
14172 } | |
14173 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n")); | |
14174 if (soap->fdimereadclose) | |
14175 soap->fdimereadclose(soap, handle); | |
14176 } | |
14177 else | |
14178 { if (!content->next) | |
14179 soap->dime.flags |= SOAP_DIME_ME; | |
14180 if (soap_putdimehdr(soap) | |
14181 || soap_putdimefield(soap, (char*)content->ptr, content->size)) | |
14182 return soap->error; | |
14183 } | |
14184 } | |
14185 return SOAP_OK; | |
14186 } | |
14187 #endif | |
14188 #endif | |
14189 | |
14190 /******************************************************************************/ | |
14191 #ifndef WITH_LEANER | |
14192 #ifndef PALM_1 | |
14193 static char * | |
14194 soap_getdimefield(struct soap *soap, size_t n) | |
14195 { register soap_wchar c; | |
14196 register size_t i; | |
14197 register char *s; | |
14198 register char *p = NULL; | |
14199 if (n) | |
14200 { p = (char*)soap_malloc(soap, n + 1); | |
14201 if (p) | |
14202 { s = p; | |
14203 for (i = n; i > 0; i--) | |
14204 { if ((int)(c = soap_get1(soap)) == EOF) | |
14205 { soap->error = SOAP_CHK_EOF; | |
14206 return NULL; | |
14207 } | |
14208 *s++ = (char)c; | |
14209 } | |
14210 *s = '\0'; | |
14211 if ((soap->error = soap_move(soap, (size_t)(-(long)n&3)))) | |
14212 return NULL; | |
14213 } | |
14214 else | |
14215 soap->error = SOAP_EOM; | |
14216 } | |
14217 return p; | |
14218 } | |
14219 #endif | |
14220 #endif | |
14221 | |
14222 /******************************************************************************/ | |
14223 #ifndef WITH_LEANER | |
14224 #ifndef PALM_1 | |
14225 SOAP_FMAC1 | |
14226 int | |
14227 SOAP_FMAC2 | |
14228 soap_getdimehdr(struct soap *soap) | |
14229 { register soap_wchar c; | |
14230 register char *s; | |
14231 register int i; | |
14232 unsigned char tmp[12]; | |
14233 size_t optlen, idlen, typelen; | |
14234 if (!(soap->mode & SOAP_ENC_DIME)) | |
14235 return soap->error = SOAP_DIME_END; | |
14236 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME header\n")); | |
14237 if (soap->dime.buflen || soap->dime.chunksize) | |
14238 { if (soap_move(soap, soap->dime.size - soap_tell(soap))) | |
14239 return soap->error = SOAP_CHK_EOF; | |
14240 soap_unget(soap, soap_getchar(soap)); /* skip padding and get hdr */ | |
14241 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... From chunked\n")); | |
14242 return SOAP_OK; | |
14243 } | |
14244 s = (char*)tmp; | |
14245 for (i = 12; i > 0; i--) | |
14246 { if ((int)(c = soap_getchar(soap)) == EOF) | |
14247 return soap->error = SOAP_CHK_EOF; | |
14248 *s++ = (char)c; | |
14249 } | |
14250 if ((tmp[0] & 0xF8) != SOAP_DIME_VERSION) | |
14251 return soap->error = SOAP_DIME_MISMATCH; | |
14252 soap->dime.flags = (tmp[0] & 0x7) | (tmp[1] & 0xF0); | |
14253 optlen = (tmp[2] << 8) | tmp[3]; | |
14254 idlen = (tmp[4] << 8) | tmp[5]; | |
14255 typelen = (tmp[6] << 8) | tmp[7]; | |
14256 soap->dime.size = ((size_t)tmp[8] << 24) | ((size_t)tmp[9] << 16) | ((size_t)tmp[10] << 8) | ((size_t)tmp[11]); | |
14257 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME size=%lu flags=0x%X\n", (unsigned long)soap->dime.size, soap->dime.flags)); | |
14258 if (!(soap->dime.options = soap_getdimefield(soap, optlen)) && soap->error) | |
14259 return soap->error; | |
14260 if (!(soap->dime.id = soap_getdimefield(soap, idlen)) && soap->error) | |
14261 return soap->error; | |
14262 if (!(soap->dime.type = soap_getdimefield(soap, typelen)) && soap->error) | |
14263 return soap->error; | |
14264 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)); | |
14265 if (soap->dime.flags & SOAP_DIME_ME) | |
14266 soap->mode &= ~SOAP_ENC_DIME; | |
14267 return SOAP_OK; | |
14268 } | |
14269 #endif | |
14270 #endif | |
14271 | |
14272 /******************************************************************************/ | |
14273 #ifndef WITH_LEANER | |
14274 #ifndef PALM_1 | |
14275 SOAP_FMAC1 | |
14276 int | |
14277 SOAP_FMAC2 | |
14278 soap_getdime(struct soap *soap) | |
14279 { while (soap->dime.flags & SOAP_DIME_CF) | |
14280 { if (soap_getdimehdr(soap)) | |
14281 return soap->error; | |
14282 if (soap_move(soap, soap->dime.size)) | |
14283 return soap->error = SOAP_EOF; | |
14284 } | |
14285 if (soap_move(soap, (size_t)(((soap->dime.size+3)&(~3)) - soap_tell(soap)))) | |
14286 return soap->error = SOAP_EOF; | |
14287 for (;;) | |
14288 { register struct soap_multipart *content; | |
14289 if (soap_getdimehdr(soap)) | |
14290 break; | |
14291 if (soap->fdimewriteopen && ((soap->dime.ptr = (char*)soap->fdimewriteopen(soap, soap->dime.id, soap->dime.type, soap->dime.options)) || soap->error)) | |
14292 { const char *id, *type, *options; | |
14293 size_t size, n; | |
14294 if (!soap->dime.ptr) | |
14295 return soap->error; | |
14296 id = soap->dime.id; | |
14297 type = soap->dime.type; | |
14298 options = soap->dime.options; | |
14299 for (;;) | |
14300 { size = soap->dime.size; | |
14301 for (;;) | |
14302 { n = soap->buflen - soap->bufidx; | |
14303 if (size < n) | |
14304 n = size; | |
14305 if ((soap->error = soap->fdimewrite(soap, (void*)soap->dime.ptr, soap->buf + soap->bufidx, n))) | |
14306 break; | |
14307 size -= n; | |
14308 if (!size) | |
14309 { soap->bufidx += n; | |
14310 break; | |
14311 } | |
14312 if (soap_recv(soap)) | |
14313 { soap->error = SOAP_EOF; | |
14314 goto end; | |
14315 } | |
14316 } | |
14317 if (soap_move(soap, (size_t)(-(long)soap->dime.size&3))) | |
14318 { soap->error = SOAP_EOF; | |
14319 break; | |
14320 } | |
14321 if (!(soap->dime.flags & SOAP_DIME_CF)) | |
14322 break; | |
14323 if (soap_getdimehdr(soap)) | |
14324 break; | |
14325 } | |
14326 end: | |
14327 if (soap->fdimewriteclose) | |
14328 soap->fdimewriteclose(soap, (void*)soap->dime.ptr); | |
14329 soap->dime.size = 0; | |
14330 soap->dime.id = id; | |
14331 soap->dime.type = type; | |
14332 soap->dime.options = options; | |
14333 } | |
14334 else if (soap->dime.flags & SOAP_DIME_CF) | |
14335 { const char *id, *type, *options; | |
14336 id = soap->dime.id; | |
14337 type = soap->dime.type; | |
14338 options = soap->dime.options; | |
14339 if (soap_new_block(soap) == NULL) | |
14340 return SOAP_EOM; | |
14341 for (;;) | |
14342 { register soap_wchar c; | |
14343 register size_t i; | |
14344 register char *s; | |
14345 if (soap->dime.size > SOAP_MAXDIMESIZE) | |
14346 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME size=%lu exceeds SOAP_MAXDIMESIZE=%lu\n", (unsigned long)soap->dime.size, (unsigned long)SOAP_MAXDIMESIZE)); | |
14347 return soap->error = SOAP_DIME_ERROR; | |
14348 } | |
14349 s = (char*)soap_push_block(soap, NULL, soap->dime.size); | |
14350 if (!s) | |
14351 return soap->error = SOAP_EOM; | |
14352 for (i = soap->dime.size; i > 0; i--) | |
14353 { if ((int)(c = soap_get1(soap)) == EOF) | |
14354 return soap->error = SOAP_EOF; | |
14355 *s++ = (char)c; | |
14356 } | |
14357 if (soap_move(soap, (size_t)(-(long)soap->dime.size&3))) | |
14358 return soap->error = SOAP_EOF; | |
14359 if (!(soap->dime.flags & SOAP_DIME_CF)) | |
14360 break; | |
14361 if (soap_getdimehdr(soap)) | |
14362 return soap->error; | |
14363 } | |
14364 soap->dime.size = soap->blist->size++; /* allocate one more byte in blist for the terminating '\0' */ | |
14365 if (!(soap->dime.ptr = soap_save_block(soap, NULL, NULL, 0))) | |
14366 return soap->error; | |
14367 soap->dime.ptr[soap->dime.size] = '\0'; /* make 0-terminated */ | |
14368 soap->dime.id = id; | |
14369 soap->dime.type = type; | |
14370 soap->dime.options = options; | |
14371 } | |
14372 else | |
14373 soap->dime.ptr = soap_getdimefield(soap, soap->dime.size); | |
14374 content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, soap->dime.ptr, soap->dime.size); | |
14375 if (!content) | |
14376 return soap->error = SOAP_EOM; | |
14377 content->id = soap->dime.id; | |
14378 content->type = soap->dime.type; | |
14379 content->options = soap->dime.options; | |
14380 if (soap->error) | |
14381 return soap->error; | |
14382 soap_resolve_attachment(soap, content); | |
14383 } | |
14384 if (soap->error != SOAP_DIME_END) | |
14385 return soap->error; | |
14386 return soap->error = SOAP_OK; | |
14387 } | |
14388 #endif | |
14389 #endif | |
14390 | |
14391 /******************************************************************************/ | |
14392 #ifndef WITH_LEANER | |
14393 #ifndef PALM_1 | |
14394 SOAP_FMAC1 | |
14395 int | |
14396 SOAP_FMAC2 | |
14397 soap_getmimehdr(struct soap *soap) | |
14398 { struct soap_multipart *content; | |
14399 do | |
14400 { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) | |
14401 return soap->error; | |
14402 } | |
14403 while (!*soap->msgbuf); | |
14404 if (soap->msgbuf[0] == '-' && soap->msgbuf[1] == '-') | |
14405 { char *s = soap->msgbuf + strlen(soap->msgbuf) - 1; | |
14406 /* remove white space */ | |
14407 while (soap_blank((soap_wchar)*s)) | |
14408 s--; | |
14409 s[1] = '\0'; | |
14410 if (soap->mime.boundary) | |
14411 { if (strcmp(soap->msgbuf + 2, soap->mime.boundary)) | |
14412 return soap->error = SOAP_MIME_ERROR; | |
14413 } | |
14414 else | |
14415 soap->mime.boundary = soap_strdup(soap, soap->msgbuf + 2); | |
14416 if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) | |
14417 return soap->error; | |
14418 } | |
14419 if (soap_set_mime_attachment(soap, NULL, 0, SOAP_MIME_NONE, NULL, NULL, NULL, NULL)) | |
14420 return soap->error = SOAP_EOM; | |
14421 content = soap->mime.last; | |
14422 for (;;) | |
14423 { register char *key = soap->msgbuf; | |
14424 register char *val; | |
14425 if (!*key) | |
14426 break; | |
14427 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "MIME header: %s\n", key)); | |
14428 val = strchr(soap->msgbuf, ':'); | |
14429 if (val) | |
14430 { *val = '\0'; | |
14431 do val++; | |
14432 while (*val && *val <= 32); | |
14433 if (!soap_tag_cmp(key, "Content-ID")) | |
14434 content->id = soap_strdup(soap, val); | |
14435 else if (!soap_tag_cmp(key, "Content-Location")) | |
14436 content->location = soap_strdup(soap, val); | |
14437 else if (!soap_tag_cmp(key, "Content-Disposition")) | |
14438 content->id = soap_strdup(soap, soap_get_header_attribute(soap, val, "name")); | |
14439 else if (!soap_tag_cmp(key, "Content-Type")) | |
14440 content->type = soap_strdup(soap, val); | |
14441 else if (!soap_tag_cmp(key, "Content-Description")) | |
14442 content->description = soap_strdup(soap, val); | |
14443 else if (!soap_tag_cmp(key, "Content-Transfer-Encoding")) | |
14444 content->encoding = (enum soap_mime_encoding)soap_code_int(mime_codes, val, (long)SOAP_MIME_NONE); | |
14445 } | |
14446 if (soap_getline(soap, key, sizeof(soap->msgbuf))) | |
14447 return soap->error; | |
14448 } | |
14449 return SOAP_OK; | |
14450 } | |
14451 #endif | |
14452 #endif | |
14453 | |
14454 /******************************************************************************/ | |
14455 #ifndef WITH_LEANER | |
14456 #ifndef PALM_1 | |
14457 SOAP_FMAC1 | |
14458 int | |
14459 SOAP_FMAC2 | |
14460 soap_getmime(struct soap *soap) | |
14461 { while (soap_get_mime_attachment(soap, NULL)) | |
14462 ; | |
14463 return soap->error; | |
14464 } | |
14465 #endif | |
14466 #endif | |
14467 | |
14468 /******************************************************************************/ | |
14469 #ifndef WITH_LEANER | |
14470 #ifndef PALM_1 | |
14471 SOAP_FMAC1 | |
14472 void | |
14473 SOAP_FMAC2 | |
14474 soap_post_check_mime_attachments(struct soap *soap) | |
14475 { soap->imode |= SOAP_MIME_POSTCHECK; | |
14476 } | |
14477 #endif | |
14478 #endif | |
14479 | |
14480 /******************************************************************************/ | |
14481 #ifndef WITH_LEANER | |
14482 #ifndef PALM_1 | |
14483 SOAP_FMAC1 | |
14484 int | |
14485 SOAP_FMAC2 | |
14486 soap_check_mime_attachments(struct soap *soap) | |
14487 { if (soap->mode & SOAP_MIME_POSTCHECK) | |
14488 return soap_get_mime_attachment(soap, NULL) != NULL; | |
14489 return SOAP_OK; | |
14490 } | |
14491 #endif | |
14492 #endif | |
14493 | |
14494 /******************************************************************************/ | |
14495 #ifndef WITH_LEANER | |
14496 #ifndef PALM_1 | |
14497 SOAP_FMAC1 | |
14498 struct soap_multipart * | |
14499 SOAP_FMAC2 | |
14500 soap_get_mime_attachment(struct soap *soap, void *handle) | |
14501 { register soap_wchar c = 0; | |
14502 register size_t i, m = 0; | |
14503 register char *s, *t = NULL; | |
14504 register struct soap_multipart *content; | |
14505 register short flag = 0; | |
14506 if (!(soap->mode & SOAP_ENC_MIME)) | |
14507 return NULL; | |
14508 content = soap->mime.last; | |
14509 if (!content) | |
14510 { if (soap_getmimehdr(soap)) | |
14511 return NULL; | |
14512 content = soap->mime.last; | |
14513 } | |
14514 else if (content != soap->mime.first) | |
14515 { if (soap->fmimewriteopen && ((content->ptr = (char*)soap->fmimewriteopen(soap, (void*)handle, content->id, content->type, content->description, content->encoding)) || soap->error)) | |
14516 { if (!content->ptr) | |
14517 return NULL; | |
14518 } | |
14519 } | |
14520 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)); | |
14521 if (!content->ptr && soap_new_block(soap) == NULL) | |
14522 { soap->error = SOAP_EOM; | |
14523 return NULL; | |
14524 } | |
14525 for (;;) | |
14526 { if (content->ptr) | |
14527 s = soap->tmpbuf; | |
14528 else if (!(s = (char*)soap_push_block(soap, NULL, sizeof(soap->tmpbuf)))) | |
14529 { soap->error = SOAP_EOM; | |
14530 return NULL; | |
14531 } | |
14532 for (i = 0; i < sizeof(soap->tmpbuf); i++) | |
14533 { if (m > 0) | |
14534 { *s++ = *t++; | |
14535 m--; | |
14536 } | |
14537 else | |
14538 { if (!flag) | |
14539 { c = soap_get1(soap); | |
14540 if ((int)c == EOF) | |
14541 { if (content->ptr && soap->fmimewriteclose) | |
14542 soap->fmimewriteclose(soap, (void*)content->ptr); | |
14543 soap->error = SOAP_CHK_EOF; | |
14544 return NULL; | |
14545 } | |
14546 } | |
14547 if (flag || c == '\r') | |
14548 { t = soap->msgbuf; | |
14549 memset(t, 0, sizeof(soap->msgbuf)); | |
14550 strcpy(t, "\n--"); | |
14551 if (soap->mime.boundary) | |
14552 strncat(t, soap->mime.boundary, sizeof(soap->msgbuf)-4); | |
14553 do c = soap_getchar(soap); | |
14554 while (c == *t++); | |
14555 if ((int)c == EOF) | |
14556 { if (content->ptr && soap->fmimewriteclose) | |
14557 soap->fmimewriteclose(soap, (void*)content->ptr); | |
14558 soap->error = SOAP_CHK_EOF; | |
14559 return NULL; | |
14560 } | |
14561 if (!*--t) | |
14562 goto end; | |
14563 *t = (char)c; | |
14564 flag = (c == '\r'); | |
14565 m = t - soap->msgbuf + 1 - flag; | |
14566 t = soap->msgbuf; | |
14567 c = '\r'; | |
14568 } | |
14569 *s++ = (char)c; | |
14570 } | |
14571 } | |
14572 if (content->ptr && soap->fmimewrite) | |
14573 { if ((soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i))) | |
14574 break; | |
14575 } | |
14576 } | |
14577 end: | |
14578 *s = '\0'; /* make 0-terminated */ | |
14579 if (content->ptr) | |
14580 { if (!soap->error && soap->fmimewrite) | |
14581 soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i); | |
14582 if (soap->fmimewriteclose) | |
14583 soap->fmimewriteclose(soap, (void*)content->ptr); | |
14584 if (soap->error) | |
14585 return NULL; | |
14586 } | |
14587 else | |
14588 { content->size = soap_size_block(soap, NULL, i+1) - 1; /* last block with '\0' */ | |
14589 content->ptr = soap_save_block(soap, NULL, NULL, 0); | |
14590 } | |
14591 soap_resolve_attachment(soap, content); | |
14592 if (c == '-' && soap_getchar(soap) == '-') | |
14593 { soap->mode &= ~SOAP_ENC_MIME; | |
14594 if ((soap->mode & SOAP_MIME_POSTCHECK) && soap_end_recv(soap)) | |
14595 { if (soap->keep_alive < 0) | |
14596 soap->keep_alive = 0; | |
14597 soap_closesock(soap); | |
14598 return NULL; | |
14599 } | |
14600 } | |
14601 else | |
14602 { while (c != '\r' && (int)c != EOF && soap_blank(c)) | |
14603 c = soap_getchar(soap); | |
14604 if (c != '\r' || soap_getchar(soap) != '\n') | |
14605 { soap->error = SOAP_MIME_ERROR; | |
14606 return NULL; | |
14607 } | |
14608 if (soap_getmimehdr(soap)) | |
14609 return NULL; | |
14610 } | |
14611 return content; | |
14612 } | |
14613 #endif | |
14614 #endif | |
14615 | |
14616 /******************************************************************************/ | |
14617 #ifndef WITH_LEANER | |
14618 #ifndef PALM_1 | |
14619 SOAP_FMAC1 | |
14620 int | |
14621 SOAP_FMAC2 | |
14622 soap_match_cid(struct soap *soap, const char *s, const char *t) | |
14623 { register size_t n; | |
14624 if (!s) | |
14625 return 1; | |
14626 if (!strcmp(s, t)) | |
14627 return 0; | |
14628 if (!strncmp(s, "cid:", 4)) | |
14629 s += 4; | |
14630 n = strlen(t); | |
14631 if (*t == '<') | |
14632 { t++; | |
14633 n -= 2; | |
14634 } | |
14635 if (!strncmp(s, t, n) && !s[n]) | |
14636 return 0; | |
14637 soap_decode(soap->tmpbuf, sizeof(soap->tmpbuf), s, SOAP_STR_EOS); | |
14638 if (!strncmp(soap->tmpbuf, t, n) && !soap->tmpbuf[n]) | |
14639 return 0; | |
14640 return 1; | |
14641 } | |
14642 #endif | |
14643 #endif | |
14644 | |
14645 /******************************************************************************/ | |
14646 #ifndef WITH_LEANER | |
14647 #ifndef PALM_1 | |
14648 static void | |
14649 soap_resolve_attachment(struct soap *soap, struct soap_multipart *content) | |
14650 { if (content->id) | |
14651 { register struct soap_xlist **xp = &soap->xlist; | |
14652 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving attachment data for id='%s'\n", content->id)); | |
14653 while (*xp) | |
14654 { register struct soap_xlist *xq = *xp; | |
14655 if (!soap_match_cid(soap, xq->id, content->id)) | |
14656 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Found matching attachment id='%s' for content id='%s'\n", xq->id, content->id)); | |
14657 *xp = xq->next; | |
14658 *xq->ptr = (unsigned char*)content->ptr; | |
14659 *xq->size = (int)content->size; | |
14660 *xq->type = (char*)content->type; | |
14661 if (content->options) | |
14662 *xq->options = (char*)content->options; | |
14663 else | |
14664 *xq->options = (char*)content->description; | |
14665 SOAP_FREE(soap, xq); | |
14666 } | |
14667 else | |
14668 xp = &(*xp)->next; | |
14669 } | |
14670 } | |
14671 } | |
14672 #endif | |
14673 #endif | |
14674 | |
14675 /******************************************************************************/ | |
14676 #ifndef WITH_LEANER | |
14677 #ifndef PALM_1 | |
14678 SOAP_FMAC1 | |
14679 int | |
14680 SOAP_FMAC2 | |
14681 soap_putmimehdr(struct soap *soap, struct soap_multipart *content) | |
14682 { const char *s; | |
14683 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "MIME attachment type='%s'\n", content->type ? content->type : SOAP_STR_EOS)); | |
14684 if (soap_send3(soap, "\r\n--", soap->mime.boundary, "\r\n")) | |
14685 return soap->error; | |
14686 if (content->type && soap_send3(soap, "Content-Type: ", content->type, "\r\n")) | |
14687 return soap->error; | |
14688 s = soap_code_str(mime_codes, content->encoding); | |
14689 if (s && soap_send3(soap, "Content-Transfer-Encoding: ", s, "\r\n")) | |
14690 return soap->error; | |
14691 if (content->id && soap_send3(soap, "Content-ID: ", content->id, "\r\n")) | |
14692 return soap->error; | |
14693 if (content->location && soap_send3(soap, "Content-Location: ", content->location, "\r\n")) | |
14694 return soap->error; | |
14695 if (content->description && soap_send3(soap, "Content-Description: ", content->description, "\r\n")) | |
14696 return soap->error; | |
14697 return soap_send_raw(soap, "\r\n", 2); | |
14698 } | |
14699 #endif | |
14700 #endif | |
14701 | |
14702 /******************************************************************************/ | |
14703 #ifndef WITH_LEANER | |
14704 #ifndef PALM_1 | |
14705 SOAP_FMAC1 | |
14706 int | |
14707 SOAP_FMAC2 | |
14708 soap_putmime(struct soap *soap) | |
14709 { struct soap_multipart *content; | |
14710 if (!(soap->mode & SOAP_ENC_MIME) || !soap->mime.boundary) | |
14711 return SOAP_OK; | |
14712 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending MIME attachments\n")); | |
14713 for (content = soap->mime.first; content; content = content->next) | |
14714 { void *handle; | |
14715 if (soap->fmimereadopen && ((handle = soap->fmimereadopen(soap, (void*)content->ptr, content->id, content->type, content->description)) || soap->error)) | |
14716 { size_t size = content->size; | |
14717 if (!handle) | |
14718 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimereadopen failed\n")); | |
14719 return soap->error; | |
14720 } | |
14721 if (soap_putmimehdr(soap, content)) | |
14722 return soap->error; | |
14723 if (!size) | |
14724 { if ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE) | |
14725 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming MIME\n")); | |
14726 do | |
14727 { size = soap->fmimeread(soap, handle, soap->tmpbuf, sizeof(soap->tmpbuf)); | |
14728 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread returned %lu bytes\n", (unsigned long)size)); | |
14729 if (soap_send_raw(soap, soap->tmpbuf, size)) | |
14730 break; | |
14731 } while (size); | |
14732 } | |
14733 else | |
14734 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error: cannot chunk streaming MIME (no HTTP chunking)\n")); | |
14735 } | |
14736 } | |
14737 else | |
14738 { do | |
14739 { size_t bufsize; | |
14740 if (size < sizeof(soap->tmpbuf)) | |
14741 bufsize = size; | |
14742 else | |
14743 bufsize = sizeof(soap->tmpbuf); | |
14744 if (!(bufsize = soap->fmimeread(soap, handle, soap->tmpbuf, bufsize))) | |
14745 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size)); | |
14746 soap->error = SOAP_EOF; | |
14747 break; | |
14748 } | |
14749 if (soap_send_raw(soap, soap->tmpbuf, bufsize)) | |
14750 break; | |
14751 size -= bufsize; | |
14752 } while (size); | |
14753 } | |
14754 if (soap->fmimereadclose) | |
14755 soap->fmimereadclose(soap, handle); | |
14756 } | |
14757 else | |
14758 { if (soap_putmimehdr(soap, content) | |
14759 || soap_send_raw(soap, content->ptr, content->size)) | |
14760 return soap->error; | |
14761 } | |
14762 } | |
14763 return soap_send3(soap, "\r\n--", soap->mime.boundary, "--"); | |
14764 } | |
14765 #endif | |
14766 #endif | |
14767 | |
14768 /******************************************************************************/ | |
14769 #ifndef WITH_LEANER | |
14770 #ifndef PALM_1 | |
14771 SOAP_FMAC1 | |
14772 void | |
14773 SOAP_FMAC2 | |
14774 soap_set_dime(struct soap *soap) | |
14775 { soap->omode |= SOAP_ENC_DIME; | |
14776 soap->dime.first = NULL; | |
14777 soap->dime.last = NULL; | |
14778 } | |
14779 #endif | |
14780 #endif | |
14781 | |
14782 /******************************************************************************/ | |
14783 #ifndef WITH_LEANER | |
14784 #ifndef PALM_1 | |
14785 SOAP_FMAC1 | |
14786 void | |
14787 SOAP_FMAC2 | |
14788 soap_set_mime(struct soap *soap, const char *boundary, const char *start) | |
14789 { soap->omode |= SOAP_ENC_MIME; | |
14790 soap->mime.first = NULL; | |
14791 soap->mime.last = NULL; | |
14792 soap->mime.boundary = soap_strdup(soap, boundary); | |
14793 soap->mime.start = soap_strdup(soap, start); | |
14794 } | |
14795 #endif | |
14796 #endif | |
14797 | |
14798 /******************************************************************************/ | |
14799 #ifndef WITH_LEANER | |
14800 #ifndef PALM_1 | |
14801 SOAP_FMAC1 | |
14802 void | |
14803 SOAP_FMAC2 | |
14804 soap_clr_dime(struct soap *soap) | |
14805 { soap->omode &= ~SOAP_ENC_DIME; | |
14806 soap->dime.first = NULL; | |
14807 soap->dime.last = NULL; | |
14808 } | |
14809 #endif | |
14810 #endif | |
14811 | |
14812 /******************************************************************************/ | |
14813 #ifndef WITH_LEANER | |
14814 #ifndef PALM_1 | |
14815 SOAP_FMAC1 | |
14816 void | |
14817 SOAP_FMAC2 | |
14818 soap_clr_mime(struct soap *soap) | |
14819 { soap->omode &= ~SOAP_ENC_MIME; | |
14820 soap->mime.first = NULL; | |
14821 soap->mime.last = NULL; | |
14822 soap->mime.boundary = NULL; | |
14823 soap->mime.start = NULL; | |
14824 } | |
14825 #endif | |
14826 #endif | |
14827 | |
14828 /******************************************************************************/ | |
14829 #ifndef WITH_LEANER | |
14830 #ifndef PALM_1 | |
14831 static struct soap_multipart* | |
14832 soap_new_multipart(struct soap *soap, struct soap_multipart **first, struct soap_multipart **last, char *ptr, size_t size) | |
14833 { struct soap_multipart *content; | |
14834 content = (struct soap_multipart*)soap_malloc(soap, sizeof(struct soap_multipart)); | |
14835 if (content) | |
14836 { content->next = NULL; | |
14837 content->ptr = ptr; | |
14838 content->size = size; | |
14839 content->id = NULL; | |
14840 content->type = NULL; | |
14841 content->options = NULL; | |
14842 content->encoding = SOAP_MIME_NONE; | |
14843 content->location = NULL; | |
14844 content->description = NULL; | |
14845 if (!*first) | |
14846 *first = content; | |
14847 if (*last) | |
14848 (*last)->next = content; | |
14849 *last = content; | |
14850 } | |
14851 return content; | |
14852 } | |
14853 #endif | |
14854 #endif | |
14855 | |
14856 /******************************************************************************/ | |
14857 #ifndef WITH_LEANER | |
14858 #ifndef PALM_1 | |
14859 SOAP_FMAC1 | |
14860 int | |
14861 SOAP_FMAC2 | |
14862 soap_set_dime_attachment(struct soap *soap, char *ptr, size_t size, const char *type, const char *id, unsigned short optype, const char *option) | |
14863 { struct soap_multipart *content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, ptr, size); | |
14864 if (!content) | |
14865 return SOAP_EOM; | |
14866 content->id = soap_strdup(soap, id); | |
14867 content->type = soap_strdup(soap, type); | |
14868 content->options = soap_dime_option(soap, optype, option); | |
14869 return SOAP_OK; | |
14870 } | |
14871 #endif | |
14872 #endif | |
14873 | |
14874 /******************************************************************************/ | |
14875 #ifndef WITH_LEANER | |
14876 #ifndef PALM_1 | |
14877 SOAP_FMAC1 | |
14878 int | |
14879 SOAP_FMAC2 | |
14880 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) | |
14881 { struct soap_multipart *content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, ptr, size); | |
14882 if (!content) | |
14883 return SOAP_EOM; | |
14884 content->id = soap_strdup(soap, id); | |
14885 content->type = soap_strdup(soap, type); | |
14886 content->encoding = encoding; | |
14887 content->location = soap_strdup(soap, location); | |
14888 content->description = soap_strdup(soap, description); | |
14889 return SOAP_OK; | |
14890 } | |
14891 #endif | |
14892 #endif | |
14893 | |
14894 /******************************************************************************/ | |
14895 #ifndef WITH_LEANER | |
14896 #ifndef PALM_1 | |
14897 SOAP_FMAC1 | |
14898 struct soap_multipart* | |
14899 SOAP_FMAC2 | |
14900 soap_next_multipart(struct soap_multipart *content) | |
14901 { if (content) | |
14902 return content->next; | |
14903 return NULL; | |
14904 } | |
14905 #endif | |
14906 #endif | |
14907 | |
14908 /******************************************************************************/ | |
14909 #ifndef WITH_LEANER | |
14910 #ifndef PALM_1 | |
14911 static void | |
14912 soap_select_mime_boundary(struct soap *soap) | |
14913 { while (!soap->mime.boundary || soap_valid_mime_boundary(soap)) | |
14914 { register char *s = soap->mime.boundary; | |
14915 register size_t n = 0; | |
14916 if (s) | |
14917 n = strlen(s); | |
14918 if (n < 16) | |
14919 { n = 64; | |
14920 s = soap->mime.boundary = (char*)soap_malloc(soap, n + 1); | |
14921 if (!s) | |
14922 return; | |
14923 } | |
14924 strcpy(s, "=="); | |
14925 s += 2; | |
14926 n -= 4; | |
14927 while (n) | |
14928 { *s++ = soap_base64o[soap_random & 0x3F]; | |
14929 n--; | |
14930 } | |
14931 strcpy(s, "=="); | |
14932 } | |
14933 if (!soap->mime.start) | |
14934 soap->mime.start = "<SOAP-ENV:Envelope>"; | |
14935 } | |
14936 #endif | |
14937 #endif | |
14938 | |
14939 /******************************************************************************/ | |
14940 #ifndef WITH_LEANER | |
14941 #ifndef PALM_1 | |
14942 static int | |
14943 soap_valid_mime_boundary(struct soap *soap) | |
14944 { register struct soap_multipart *content; | |
14945 register size_t k; | |
14946 if (soap->fmimeread) | |
14947 return SOAP_OK; | |
14948 k = strlen(soap->mime.boundary); | |
14949 for (content = soap->mime.first; content; content = content->next) | |
14950 { if (content->ptr && content->size >= k) | |
14951 { register const char *p = (const char*)content->ptr; | |
14952 register size_t i; | |
14953 for (i = 0; i < content->size - k; i++, p++) | |
14954 { if (!strncmp(p, soap->mime.boundary, k)) | |
14955 return SOAP_ERR; | |
14956 } | |
14957 } | |
14958 } | |
14959 return SOAP_OK; | |
14960 } | |
14961 #endif | |
14962 #endif | |
14963 | |
14964 /******************************************************************************/ | |
14965 #ifdef WITH_GZIP | |
14966 #ifndef PALM_1 | |
14967 static int | |
14968 soap_getgziphdr(struct soap *soap) | |
14969 { int i; | |
14970 soap_wchar c = 0, f = 0; | |
14971 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get gzip header\n")); | |
14972 for (i = 0; i < 9; i++) | |
14973 { if ((int)(c = soap_get1(soap) == EOF)) | |
14974 return soap->error = SOAP_ZLIB_ERROR; | |
14975 if (i == 1 && c == 8) | |
14976 soap->z_dict = 0; | |
14977 if (i == 2) | |
14978 f = c; | |
14979 } | |
14980 if (f & 0x04) /* FEXTRA */ | |
14981 { for (i = soap_get1(soap) | (soap_get1(soap) << 8); i; i--) | |
14982 { if ((int)soap_get1(soap) == EOF) | |
14983 return soap->error = SOAP_ZLIB_ERROR; | |
14984 } | |
14985 } | |
14986 if (f & 0x08) /* skip FNAME */ | |
14987 { do | |
14988 c = soap_get1(soap); | |
14989 while (c && (int)c != EOF); | |
14990 } | |
14991 if ((int)c != EOF && (f & 0x10)) /* skip FCOMMENT */ | |
14992 { do | |
14993 c = soap_get1(soap); | |
14994 while (c && (int)c != EOF); | |
14995 } | |
14996 if ((int)c != EOF && (f & 0x02)) /* skip FHCRC (CRC32 is used) */ | |
14997 { if ((int)(c = soap_get1(soap)) != EOF) | |
14998 c = soap_get1(soap); | |
14999 } | |
15000 if ((int)c == EOF) | |
15001 return soap->error = SOAP_ZLIB_ERROR; | |
15002 return SOAP_OK; | |
15003 } | |
15004 #endif | |
15005 #endif | |
15006 | |
15007 /******************************************************************************/ | |
15008 #ifndef PALM_1 | |
15009 SOAP_FMAC1 | |
15010 int | |
15011 SOAP_FMAC2 | |
15012 soap_begin_serve(struct soap *soap) | |
15013 { | |
15014 #ifdef WITH_FASTCGI | |
15015 if (FCGI_Accept() < 0) | |
15016 { soap->error = SOAP_EOF; | |
15017 return soap_send_fault(soap); | |
15018 } | |
15019 #endif | |
15020 soap_begin(soap); | |
15021 if (soap_begin_recv(soap) | |
15022 || soap_envelope_begin_in(soap) | |
15023 || soap_recv_header(soap) | |
15024 || soap_body_begin_in(soap)) | |
15025 { if (soap->error < SOAP_STOP) | |
15026 { | |
15027 #ifdef WITH_FASTCGI | |
15028 soap_send_fault(soap); | |
15029 #else | |
15030 return soap_send_fault(soap); | |
15031 #endif | |
15032 } | |
15033 return soap_closesock(soap); | |
15034 } | |
15035 return SOAP_OK; | |
15036 } | |
15037 #endif | |
15038 | |
15039 /******************************************************************************/ | |
15040 #ifndef PALM_1 | |
15041 SOAP_FMAC1 | |
15042 int | |
15043 SOAP_FMAC2 | |
15044 soap_begin_recv(struct soap *soap) | |
15045 { register soap_wchar c; | |
15046 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing for input from socket=%d/fd=%d\n", soap->socket, soap->recvfd)); | |
15047 soap->error = SOAP_OK; | |
15048 soap->filterstop = SOAP_OK; | |
15049 soap_free_temp(soap); | |
15050 soap_set_local_namespaces(soap); | |
15051 soap->version = 0; /* don't assume we're parsing SOAP content by default */ | |
15052 #ifndef WITH_NOIDREF | |
15053 soap_free_iht(soap); | |
15054 #endif | |
15055 if ((soap->imode & SOAP_IO) == SOAP_IO_CHUNK) | |
15056 soap->omode |= SOAP_IO_CHUNK; | |
15057 soap->imode &= ~(SOAP_IO | SOAP_ENC_MIME); | |
15058 soap->mode = soap->imode; | |
15059 if (!soap->keep_alive) | |
15060 { soap->buflen = 0; | |
15061 soap->bufidx = 0; | |
15062 } | |
15063 if (!(soap->mode & SOAP_IO_KEEPALIVE)) | |
15064 soap->keep_alive = 0; | |
15065 soap->ahead = 0; | |
15066 soap->peeked = 0; | |
15067 soap->level = 0; | |
15068 soap->part = SOAP_BEGIN; | |
15069 soap->alloced = 0; | |
15070 soap->body = 1; | |
15071 soap->count = 0; | |
15072 soap->length = 0; | |
15073 soap->cdata = 0; | |
15074 *soap->endpoint = '\0'; | |
15075 soap->action = NULL; | |
15076 soap->header = NULL; | |
15077 soap->fault = NULL; | |
15078 soap->status = 0; | |
15079 soap->fform = NULL; | |
15080 #ifndef WITH_LEANER | |
15081 soap->dom = NULL; | |
15082 soap->dime.chunksize = 0; | |
15083 soap->dime.buflen = 0; | |
15084 soap->dime.list = NULL; | |
15085 soap->dime.first = NULL; | |
15086 soap->dime.last = NULL; | |
15087 soap->mime.list = NULL; | |
15088 soap->mime.first = NULL; | |
15089 soap->mime.last = NULL; | |
15090 soap->mime.boundary = NULL; | |
15091 soap->mime.start = NULL; | |
15092 #endif | |
15093 #ifdef WIN32 | |
15094 #ifndef UNDER_CE | |
15095 #ifndef WITH_FASTCGI | |
15096 if (!soap_valid_socket(soap->socket) && !soap->is) /* Set win32 stdout or soap->sendfd to BINARY, e.g. to support DIME */ | |
15097 #ifdef __BORLANDC__ | |
15098 setmode(soap->recvfd, _O_BINARY); | |
15099 #else | |
15100 _setmode(soap->recvfd, _O_BINARY); | |
15101 #endif | |
15102 #endif | |
15103 #endif | |
15104 #endif | |
15105 #ifdef WITH_ZLIB | |
15106 soap->mode &= ~SOAP_ENC_ZLIB; | |
15107 soap->zlib_in = SOAP_ZLIB_NONE; | |
15108 soap->zlib_out = SOAP_ZLIB_NONE; | |
15109 soap->d_stream->next_in = Z_NULL; | |
15110 soap->d_stream->avail_in = 0; | |
15111 soap->d_stream->next_out = (Byte*)soap->buf; | |
15112 soap->d_stream->avail_out = SOAP_BUFLEN; | |
15113 soap->z_ratio_in = 1.0; | |
15114 #endif | |
15115 #ifdef WITH_OPENSSL | |
15116 if (soap->ssl) | |
15117 ERR_clear_error(); | |
15118 #endif | |
15119 #ifndef WITH_LEANER | |
15120 if (soap->fprepareinitrecv && (soap->error = soap->fprepareinitrecv(soap))) | |
15121 return soap->error; | |
15122 #endif | |
15123 c = soap_getchar(soap); | |
15124 #ifdef WITH_GZIP | |
15125 if (c == 0x1F) | |
15126 { if (soap_getgziphdr(soap)) | |
15127 return soap->error; | |
15128 if (inflateInit2(soap->d_stream, -MAX_WBITS) != Z_OK) | |
15129 return soap->error = SOAP_ZLIB_ERROR; | |
15130 if (soap->z_dict) | |
15131 { if (inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len) != Z_OK) | |
15132 return soap->error = SOAP_ZLIB_ERROR; | |
15133 } | |
15134 soap->zlib_state = SOAP_ZLIB_INFLATE; | |
15135 soap->mode |= SOAP_ENC_ZLIB; | |
15136 soap->zlib_in = SOAP_ZLIB_GZIP; | |
15137 soap->z_crc = crc32(0L, NULL, 0); | |
15138 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n")); | |
15139 if (!soap->z_buf) | |
15140 soap->z_buf = (char*)SOAP_MALLOC(soap, SOAP_BUFLEN); | |
15141 memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); | |
15142 /* should not chunk over plain transport, so why bother to check? */ | |
15143 /* if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) */ | |
15144 /* soap->z_buflen = soap->bufidx; */ | |
15145 /* else */ | |
15146 soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx); | |
15147 soap->d_stream->avail_in = (unsigned int)(soap->buflen - soap->bufidx); | |
15148 soap->z_buflen = soap->buflen; | |
15149 soap->buflen = soap->bufidx; | |
15150 c = ' '; | |
15151 } | |
15152 #endif | |
15153 while (soap_blank(c)) | |
15154 c = soap_getchar(soap); | |
15155 #ifndef WITH_LEANER | |
15156 if (c == '-' && soap_get0(soap) == '-') | |
15157 soap->mode |= SOAP_ENC_MIME; | |
15158 else if ((c & 0xFFFC) == (SOAP_DIME_VERSION | SOAP_DIME_MB) && (soap_get0(soap) & 0xFFF0) == 0x20) | |
15159 soap->mode |= SOAP_ENC_DIME; | |
15160 else | |
15161 #endif | |
15162 { /* skip BOM */ | |
15163 if (c == 0xEF && soap_get0(soap) == 0xBB) | |
15164 { c = soap_get1(soap); | |
15165 if ((c = soap_get1(soap)) == 0xBF) | |
15166 { soap->mode &= ~SOAP_ENC_LATIN; | |
15167 c = soap_getchar(soap); | |
15168 } | |
15169 else | |
15170 c = (0x0F << 12) | (0xBB << 6) | (c & 0x3F); /* UTF-8 */ | |
15171 } | |
15172 else if ((c == 0xFE && soap_get0(soap) == 0xFF) /* UTF-16 BE */ | |
15173 || (c == 0xFF && soap_get0(soap) == 0xFE)) /* UTF-16 LE */ | |
15174 return soap->error = SOAP_UTF_ERROR; | |
15175 /* skip space */ | |
15176 while (soap_blank(c)) | |
15177 c = soap_getchar(soap); | |
15178 } | |
15179 if ((int)c == EOF) | |
15180 return soap->error = SOAP_CHK_EOF; | |
15181 soap_unget(soap, c); | |
15182 #ifndef WITH_NOHTTP | |
15183 /* if not XML/MIME/DIME/ZLIB, assume HTTP method or status line */ | |
15184 if (((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) && !(soap->mode & (SOAP_ENC_MIME | SOAP_ENC_DIME | SOAP_ENC_ZLIB | SOAP_ENC_XML))) | |
15185 { soap_mode m = soap->imode; | |
15186 soap->mode &= ~SOAP_IO; | |
15187 soap->error = soap->fparse(soap); | |
15188 if (soap->error && soap->error < SOAP_STOP) | |
15189 { soap->keep_alive = 0; /* force close later */ | |
15190 return soap->error; | |
15191 } | |
15192 if (soap->error == SOAP_STOP) | |
15193 { if (soap->fform) | |
15194 { soap->error = soap->fform(soap); | |
15195 if (soap->error == SOAP_OK) | |
15196 soap->error = SOAP_STOP; /* prevents further processing */ | |
15197 } | |
15198 return soap->error; | |
15199 } | |
15200 soap->mode = soap->imode; /* if imode is changed, effectuate */ | |
15201 soap->imode = m; /* restore imode */ | |
15202 #ifdef WITH_ZLIB | |
15203 soap->mode &= ~SOAP_ENC_ZLIB; | |
15204 #endif | |
15205 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) | |
15206 { soap->chunkbuflen = soap->buflen; | |
15207 soap->buflen = soap->bufidx; | |
15208 soap->chunksize = 0; | |
15209 } | |
15210 /* Note: fparse should not use soap_unget to push back last char */ | |
15211 #if 0 | |
15212 if (soap->status > 200 && soap->length == 0 && !(soap->http_content && (!soap->keep_alive || soap->recv_timeout)) && (soap->imode & SOAP_IO) != SOAP_IO_CHUNK) | |
15213 #endif | |
15214 if (soap->status && !soap->body) | |
15215 return soap->error = soap->status; | |
15216 #ifdef WITH_ZLIB | |
15217 if (soap->zlib_in != SOAP_ZLIB_NONE) | |
15218 { | |
15219 #ifdef WITH_GZIP | |
15220 if (soap->zlib_in != SOAP_ZLIB_DEFLATE) | |
15221 { c = soap_get1(soap); | |
15222 if (c == (int)EOF) | |
15223 return soap->error = SOAP_EOF; | |
15224 if (c == 0x1F) | |
15225 { if (soap_getgziphdr(soap)) | |
15226 return soap->error; | |
15227 if (inflateInit2(soap->d_stream, -MAX_WBITS) != Z_OK) | |
15228 return soap->error = SOAP_ZLIB_ERROR; | |
15229 soap->z_crc = crc32(0L, NULL, 0); | |
15230 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n")); | |
15231 } | |
15232 else | |
15233 { soap_revget1(soap); | |
15234 if (inflateInit(soap->d_stream) != Z_OK) | |
15235 return soap->error = SOAP_ZLIB_ERROR; | |
15236 soap->zlib_in = SOAP_ZLIB_DEFLATE; | |
15237 } | |
15238 } | |
15239 else | |
15240 #endif | |
15241 if (inflateInit(soap->d_stream) != Z_OK) | |
15242 return soap->error = SOAP_ZLIB_ERROR; | |
15243 if (soap->z_dict) | |
15244 { if (inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len) != Z_OK) | |
15245 return soap->error = SOAP_ZLIB_ERROR; | |
15246 } | |
15247 soap->zlib_state = SOAP_ZLIB_INFLATE; | |
15248 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate initialized\n")); | |
15249 soap->mode |= SOAP_ENC_ZLIB; | |
15250 if (!soap->z_buf) | |
15251 soap->z_buf = (char*)SOAP_MALLOC(soap, SOAP_BUFLEN); | |
15252 memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); | |
15253 soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx); | |
15254 soap->d_stream->avail_in = (unsigned int)(soap->buflen - soap->bufidx); | |
15255 soap->z_buflen = soap->buflen; | |
15256 soap->buflen = soap->bufidx; | |
15257 } | |
15258 #endif | |
15259 #ifndef WITH_LEANER | |
15260 if (soap->fpreparerecv && (soap->mode & SOAP_IO) != SOAP_IO_CHUNK && soap->buflen > soap->bufidx) | |
15261 { int r; | |
15262 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Invoking fpreparerecv\n")); | |
15263 if ((r = soap->fpreparerecv(soap, soap->buf + soap->bufidx, soap->buflen - soap->bufidx))) | |
15264 return soap->error = r; | |
15265 } | |
15266 #endif | |
15267 if (soap_get0(soap) == (int)EOF) | |
15268 { if (soap->status == 0 || soap->status == 200) | |
15269 return soap->error = SOAP_NO_DATA; /* HTTP OK: always expect data */ | |
15270 return soap->error = soap->status; | |
15271 } | |
15272 if (soap->error) | |
15273 { if (soap->error == SOAP_FORM && soap->fform) | |
15274 { soap->error = soap->fform(soap); | |
15275 if (soap->error == SOAP_OK) | |
15276 soap->error = SOAP_STOP; /* prevents further processing */ | |
15277 } | |
15278 return soap->error; | |
15279 } | |
15280 } | |
15281 #endif | |
15282 #ifndef WITH_LEANER | |
15283 if (soap->mode & SOAP_ENC_MIME) | |
15284 { do /* skip preamble */ | |
15285 { if ((int)(c = soap_getchar(soap)) == EOF) | |
15286 return soap->error = SOAP_CHK_EOF; | |
15287 } while (c != '-' || soap_get0(soap) != '-'); | |
15288 soap_unget(soap, c); | |
15289 if (soap_getmimehdr(soap)) | |
15290 return soap->error; | |
15291 if (soap->mime.start) | |
15292 { do | |
15293 { if (!soap->mime.last->id) | |
15294 break; | |
15295 if (!soap_match_cid(soap, soap->mime.start, soap->mime.last->id)) | |
15296 break; | |
15297 } while (soap_get_mime_attachment(soap, NULL)); | |
15298 } | |
15299 if (soap_get_header_attribute(soap, soap->mime.first->type, "application/dime")) | |
15300 soap->mode |= SOAP_ENC_DIME; | |
15301 } | |
15302 if (soap->mode & SOAP_ENC_DIME) | |
15303 { if (soap_getdimehdr(soap)) | |
15304 return soap->error; | |
15305 if (soap->dime.flags & SOAP_DIME_CF) | |
15306 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked DIME SOAP message\n")); | |
15307 soap->dime.chunksize = soap->dime.size; | |
15308 if (soap->buflen - soap->bufidx >= soap->dime.chunksize) | |
15309 { soap->dime.buflen = soap->buflen; | |
15310 soap->buflen = soap->bufidx + soap->dime.chunksize; | |
15311 } | |
15312 else | |
15313 soap->dime.chunksize -= soap->buflen - soap->bufidx; | |
15314 } | |
15315 soap->count = soap->buflen - soap->bufidx; | |
15316 } | |
15317 #endif | |
15318 return SOAP_OK; | |
15319 } | |
15320 #endif | |
15321 | |
15322 /******************************************************************************/ | |
15323 #ifndef PALM_2 | |
15324 SOAP_FMAC1 | |
15325 int | |
15326 SOAP_FMAC2 | |
15327 soap_envelope_begin_out(struct soap *soap) | |
15328 { | |
15329 #ifndef WITH_LEANER | |
15330 size_t n = 0; | |
15331 if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && soap->mime.start && strlen(soap->mime.boundary) + strlen(soap->mime.start) < sizeof(soap->tmpbuf) - 80 ) | |
15332 { const char *s; | |
15333 if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) | |
15334 s = "application/dime"; | |
15335 else if (soap->version == 2) | |
15336 { if (soap->mode & SOAP_ENC_MTOM) | |
15337 s = "application/xop+xml; charset=utf-8; type=\"application/soap+xml\""; | |
15338 else | |
15339 s = "application/soap+xml; charset=utf-8"; | |
15340 } | |
15341 else if (soap->mode & SOAP_ENC_MTOM) | |
15342 s = "application/xop+xml; charset=utf-8; type=\"text/xml\""; | |
15343 else | |
15344 s = "text/xml; charset=utf-8"; | |
15345 #ifdef HAVE_SNPRINTF | |
15346 soap_snprintf(soap->tmpbuf, sizeof(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); | |
15347 #else | |
15348 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); | |
15349 #endif | |
15350 n = strlen(soap->tmpbuf); | |
15351 if (soap_send_raw(soap, soap->tmpbuf, n)) | |
15352 return soap->error; | |
15353 } | |
15354 if (soap->mode & SOAP_IO_LENGTH) | |
15355 soap->dime.size = soap->count; /* DIME in MIME correction */ | |
15356 if (!(soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME)) | |
15357 { if (soap_putdimehdr(soap)) | |
15358 return soap->error; | |
15359 } | |
15360 #endif | |
15361 if (soap->version == 0) | |
15362 return SOAP_OK; | |
15363 soap->part = SOAP_IN_ENVELOPE; | |
15364 return soap_element_begin_out(soap, "SOAP-ENV:Envelope", 0, NULL); | |
15365 } | |
15366 #endif | |
15367 | |
15368 /******************************************************************************/ | |
15369 #ifndef PALM_2 | |
15370 SOAP_FMAC1 | |
15371 int | |
15372 SOAP_FMAC2 | |
15373 soap_envelope_end_out(struct soap *soap) | |
15374 { if (soap->version == 0) | |
15375 return SOAP_OK; | |
15376 if (soap_element_end_out(soap, "SOAP-ENV:Envelope") | |
15377 || soap_send_raw(soap, "\r\n", 2)) /* 2.8: always emit \r\n */ | |
15378 return soap->error; | |
15379 #ifndef WITH_LEANER | |
15380 if ((soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) | |
15381 { soap->dime.size = soap->count - soap->dime.size; /* DIME in MIME correction */ | |
15382 #ifdef HAVE_SNPRINTF | |
15383 soap_snprintf(soap->id, sizeof(soap->id), soap->dime_id_format, 0); | |
15384 #else | |
15385 sprintf(soap->id, soap->dime_id_format, 0); | |
15386 #endif | |
15387 soap->dime.id = soap->id; | |
15388 if (soap->local_namespaces) | |
15389 { if (soap->local_namespaces[0].out) | |
15390 soap->dime.type = (char*)soap->local_namespaces[0].out; | |
15391 else | |
15392 soap->dime.type = (char*)soap->local_namespaces[0].ns; | |
15393 } | |
15394 soap->dime.options = NULL; | |
15395 soap->dime.flags = SOAP_DIME_MB | SOAP_DIME_ABSURI; | |
15396 if (!soap->dime.first) | |
15397 soap->dime.flags |= SOAP_DIME_ME; | |
15398 soap->count += 12 + ((strlen(soap->dime.id)+3)&(~3)) + (soap->dime.type ? ((strlen(soap->dime.type)+3)&(~3)) : 0); | |
15399 } | |
15400 if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) | |
15401 return soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3); | |
15402 #endif | |
15403 soap->part = SOAP_END_ENVELOPE; | |
15404 return SOAP_OK; | |
15405 } | |
15406 #endif | |
15407 | |
15408 /******************************************************************************/ | |
15409 #ifndef WITH_LEAN | |
15410 #ifndef PALM_1 | |
15411 SOAP_FMAC1 | |
15412 char* | |
15413 SOAP_FMAC2 | |
15414 soap_get_http_body(struct soap *soap, size_t *len) | |
15415 { if (len) | |
15416 *len = 0; | |
15417 #ifndef WITH_LEAN | |
15418 register size_t l = 0, n = 0; | |
15419 register char *s; | |
15420 /* get HTTP body length */ | |
15421 if (!(soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) != SOAP_IO_CHUNK) | |
15422 { n = soap->length; | |
15423 if (!n) | |
15424 return NULL; | |
15425 } | |
15426 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Parsing HTTP body (mode=0x%x,len=%lu)\n", soap->mode, (unsigned long)n)); | |
15427 #ifdef WITH_FAST | |
15428 soap->labidx = 0; /* use look-aside buffer */ | |
15429 #else | |
15430 if (soap_new_block(soap) == NULL) | |
15431 return NULL; | |
15432 #endif | |
15433 for (;;) | |
15434 { | |
15435 #ifdef WITH_FAST | |
15436 register size_t i, k; | |
15437 if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */ | |
15438 return NULL; | |
15439 s = soap->labbuf + soap->labidx; /* space to populate */ | |
15440 k = soap->lablen - soap->labidx; /* number of bytes available */ | |
15441 soap->labidx = soap->lablen; /* claim this space */ | |
15442 #else | |
15443 register size_t i, k = SOAP_BLKLEN; | |
15444 if (!(s = (char*)soap_push_block(soap, NULL, k))) | |
15445 return NULL; | |
15446 #endif | |
15447 for (i = 0; i < k; i++) | |
15448 { register soap_wchar c; | |
15449 l++; | |
15450 if (n > 0 && l > n) | |
15451 goto end; | |
15452 c = soap_get1(soap); | |
15453 if ((int)c == EOF) | |
15454 goto end; | |
15455 *s++ = (char)(c & 0xFF); | |
15456 } | |
15457 } | |
15458 end: | |
15459 *s = '\0'; | |
15460 if (len) | |
15461 *len = l - 1; /* len excludes terminating \0 */ | |
15462 #ifdef WITH_FAST | |
15463 if ((s = (char*)soap_malloc(soap, l))) | |
15464 memcpy(s, soap->labbuf, l); | |
15465 #else | |
15466 soap_size_block(soap, NULL, i+1); | |
15467 s = soap_save_block(soap, NULL, 0); | |
15468 #endif | |
15469 return s; | |
15470 #else | |
15471 return NULL; | |
15472 #endif | |
15473 } | |
15474 #endif | |
15475 #endif | |
15476 | |
15477 /******************************************************************************/ | |
15478 #ifndef PALM_1 | |
15479 SOAP_FMAC1 | |
15480 int | |
15481 SOAP_FMAC2 | |
15482 soap_envelope_begin_in(struct soap *soap) | |
15483 { register struct Namespace *p; | |
15484 soap->part = SOAP_IN_ENVELOPE; | |
15485 if (soap_element_begin_in(soap, "SOAP-ENV:Envelope", 0, NULL)) | |
15486 { if (soap->error == SOAP_TAG_MISMATCH) | |
15487 { if (!soap_element_begin_in(soap, "Envelope", 0, NULL)) | |
15488 soap->error = SOAP_VERSIONMISMATCH; | |
15489 else if (soap->status == 0 || (soap->status >= 200 && soap->status <= 299)) | |
15490 return SOAP_OK; /* allow non-SOAP XML content to be captured */ | |
15491 soap->error = soap->status; | |
15492 } | |
15493 else if (soap->status) | |
15494 soap->error = soap->status; | |
15495 return soap->error; | |
15496 } | |
15497 p = soap->local_namespaces; | |
15498 if (p) | |
15499 { const char *ns = p[0].out; | |
15500 if (!ns) | |
15501 ns = p[0].ns; | |
15502 if (!strcmp(ns, soap_env1)) | |
15503 { soap->version = 1; /* make sure we use SOAP 1.1 */ | |
15504 if (p[1].out) | |
15505 SOAP_FREE(soap, p[1].out); | |
15506 if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc1)))) | |
15507 strcpy(p[1].out, soap_enc1); | |
15508 } | |
15509 else if (!strcmp(ns, soap_env2)) | |
15510 { soap->version = 2; /* make sure we use SOAP 1.2 */ | |
15511 if (p[1].out) | |
15512 SOAP_FREE(soap, p[1].out); | |
15513 if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc2)))) | |
15514 strcpy(p[1].out, soap_enc2); | |
15515 } | |
15516 } | |
15517 return SOAP_OK; | |
15518 } | |
15519 #endif | |
15520 | |
15521 /******************************************************************************/ | |
15522 #ifndef PALM_1 | |
15523 SOAP_FMAC1 | |
15524 int | |
15525 SOAP_FMAC2 | |
15526 soap_envelope_end_in(struct soap *soap) | |
15527 { if (soap->version == 0) | |
15528 return SOAP_OK; | |
15529 soap->part = SOAP_END_ENVELOPE; | |
15530 return soap_element_end_in(soap, "SOAP-ENV:Envelope"); | |
15531 } | |
15532 #endif | |
15533 | |
15534 /******************************************************************************/ | |
15535 #ifndef PALM_2 | |
15536 SOAP_FMAC1 | |
15537 int | |
15538 SOAP_FMAC2 | |
15539 soap_body_begin_out(struct soap *soap) | |
15540 { if (soap->version == 1) | |
15541 soap->encoding = 1; | |
15542 #ifndef WITH_LEAN | |
15543 if ((soap->mode & SOAP_SEC_WSUID) && soap_set_attr(soap, "wsu:Id", "Body", 1)) | |
15544 return soap->error; | |
15545 #endif | |
15546 if (soap->version == 0) | |
15547 return SOAP_OK; | |
15548 soap->part = SOAP_IN_BODY; | |
15549 return soap_element_begin_out(soap, "SOAP-ENV:Body", 0, NULL); | |
15550 } | |
15551 #endif | |
15552 | |
15553 /******************************************************************************/ | |
15554 #ifndef PALM_2 | |
15555 SOAP_FMAC1 | |
15556 int | |
15557 SOAP_FMAC2 | |
15558 soap_body_end_out(struct soap *soap) | |
15559 { if (soap->version == 0) | |
15560 return SOAP_OK; | |
15561 if (soap_element_end_out(soap, "SOAP-ENV:Body")) | |
15562 return soap->error; | |
15563 soap->part = SOAP_END_BODY; | |
15564 return SOAP_OK; | |
15565 } | |
15566 #endif | |
15567 | |
15568 /******************************************************************************/ | |
15569 #ifndef PALM_2 | |
15570 SOAP_FMAC1 | |
15571 int | |
15572 SOAP_FMAC2 | |
15573 soap_body_begin_in(struct soap *soap) | |
15574 { if (soap->version == 0) | |
15575 return SOAP_OK; | |
15576 soap->part = SOAP_IN_BODY; | |
15577 if (soap_element_begin_in(soap, "SOAP-ENV:Body", 0, NULL)) | |
15578 return soap->error; | |
15579 if (!soap->body) | |
15580 soap->part = SOAP_NO_BODY; | |
15581 return SOAP_OK; | |
15582 } | |
15583 #endif | |
15584 | |
15585 /******************************************************************************/ | |
15586 #ifndef PALM_2 | |
15587 SOAP_FMAC1 | |
15588 int | |
15589 SOAP_FMAC2 | |
15590 soap_body_end_in(struct soap *soap) | |
15591 { if (soap->version == 0) | |
15592 return SOAP_OK; | |
15593 if (soap->part == SOAP_NO_BODY) | |
15594 return soap->error = SOAP_OK; | |
15595 soap->part = SOAP_END_BODY; | |
15596 return soap_element_end_in(soap, "SOAP-ENV:Body"); | |
15597 } | |
15598 #endif | |
15599 | |
15600 /******************************************************************************/ | |
15601 #ifndef PALM_2 | |
15602 SOAP_FMAC1 | |
15603 int | |
15604 SOAP_FMAC2 | |
15605 soap_recv_header(struct soap *soap) | |
15606 { if (soap_getheader(soap) && soap->error == SOAP_TAG_MISMATCH) | |
15607 soap->error = SOAP_OK; | |
15608 if (soap->error == SOAP_OK && soap->fheader) | |
15609 soap->error = soap->fheader(soap); | |
15610 return soap->error; | |
15611 } | |
15612 #endif | |
15613 | |
15614 /******************************************************************************/ | |
15615 #ifndef PALM_1 | |
15616 SOAP_FMAC1 | |
15617 void | |
15618 SOAP_FMAC2 | |
15619 soap_set_endpoint(struct soap *soap, const char *endpoint) | |
15620 { register const char *s; | |
15621 register size_t i, n; | |
15622 soap->endpoint[0] = '\0'; | |
15623 soap->host[0] = '\0'; | |
15624 soap->path[0] = '/'; | |
15625 soap->path[1] = '\0'; | |
15626 soap->port = 80; | |
15627 if (!endpoint || !*endpoint) | |
15628 return; | |
15629 #ifdef WITH_OPENSSL | |
15630 if (!soap_tag_cmp(endpoint, "https:*")) | |
15631 soap->port = 443; | |
15632 #endif | |
15633 strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint)); | |
15634 soap->endpoint[sizeof(soap->endpoint) - 1] = '\0'; | |
15635 s = strchr(endpoint, ':'); | |
15636 if (s && s[1] == '/' && s[2] == '/') | |
15637 s += 3; | |
15638 else | |
15639 s = endpoint; | |
15640 n = strlen(s); | |
15641 if (n >= sizeof(soap->host)) | |
15642 n = sizeof(soap->host) - 1; | |
15643 #ifdef WITH_IPV6 | |
15644 if (s[0] == '[') | |
15645 { s++; | |
15646 for (i = 0; i < n; i++) | |
15647 { if (s[i] == ']') | |
15648 { s++; | |
15649 --n; | |
15650 break; | |
15651 } | |
15652 soap->host[i] = s[i]; | |
15653 } | |
15654 } | |
15655 else | |
15656 { for (i = 0; i < n; i++) | |
15657 { soap->host[i] = s[i]; | |
15658 if (s[i] == '/' || s[i] == ':') | |
15659 break; | |
15660 } | |
15661 } | |
15662 #else | |
15663 for (i = 0; i < n; i++) | |
15664 { soap->host[i] = s[i]; | |
15665 if (s[i] == '/' || s[i] == ':') | |
15666 break; | |
15667 } | |
15668 #endif | |
15669 soap->host[i] = '\0'; | |
15670 if (s[i] == ':') | |
15671 { soap->port = (int)soap_strtol(s + i + 1, NULL, 10); | |
15672 for (i++; i < n; i++) | |
15673 if (s[i] == '/') | |
15674 break; | |
15675 } | |
15676 if (i < n && s[i]) | |
15677 { strncpy(soap->path, s + i, sizeof(soap->path)); | |
15678 soap->path[sizeof(soap->path) - 1] = '\0'; | |
15679 } | |
15680 } | |
15681 #endif | |
15682 | |
15683 /******************************************************************************/ | |
15684 #ifndef PALM_1 | |
15685 SOAP_FMAC1 | |
15686 int | |
15687 SOAP_FMAC2 | |
15688 soap_connect(struct soap *soap, const char *endpoint, const char *action) | |
15689 { return soap_connect_command(soap, SOAP_POST, endpoint, action); | |
15690 } | |
15691 #endif | |
15692 | |
15693 /******************************************************************************/ | |
15694 #ifndef PALM_1 | |
15695 SOAP_FMAC1 | |
15696 int | |
15697 SOAP_FMAC2 | |
15698 soap_connect_command(struct soap *soap, int http_command, const char *endpoints, const char *action) | |
15699 { char *endpoint; | |
15700 const char *s; | |
15701 if (endpoints && (s = strchr(endpoints, ' '))) | |
15702 { endpoint = (char*)SOAP_MALLOC(soap, strlen(endpoints) + 1); | |
15703 for (;;) | |
15704 { strncpy(endpoint, endpoints, s - endpoints); | |
15705 endpoint[s - endpoints] = '\0'; | |
15706 if (soap_try_connect_command(soap, http_command, endpoint, action) != SOAP_TCP_ERROR) | |
15707 break; | |
15708 if (!*s) | |
15709 break; | |
15710 soap->error = SOAP_OK; | |
15711 while (*s == ' ') | |
15712 s++; | |
15713 endpoints = s; | |
15714 s = strchr(endpoints, ' '); | |
15715 if (!s) | |
15716 s = endpoints + strlen(endpoints); | |
15717 } | |
15718 SOAP_FREE(soap, endpoint); | |
15719 } | |
15720 else | |
15721 soap_try_connect_command(soap, http_command, endpoints, action); | |
15722 return soap->error; | |
15723 } | |
15724 #endif | |
15725 | |
15726 /******************************************************************************/ | |
15727 #ifndef PALM_1 | |
15728 static int | |
15729 soap_try_connect_command(struct soap *soap, int http_command, const char *endpoint, const char *action) | |
15730 { char host[sizeof(soap->host)]; | |
15731 int port; | |
15732 size_t count; | |
15733 soap->error = SOAP_OK; | |
15734 strcpy(host, soap->host); /* save previous host name: if != then reconnect */ | |
15735 port = soap->port; /* save previous port to compare */ | |
15736 soap->status = http_command; | |
15737 soap_set_endpoint(soap, endpoint); | |
15738 #ifndef WITH_LEANER | |
15739 if (soap->fconnect) | |
15740 { if ((soap->error = soap->fconnect(soap, endpoint, soap->host, soap->port))) | |
15741 return soap->error; | |
15742 } | |
15743 else | |
15744 #endif | |
15745 soap->action = soap_strdup(soap, action); | |
15746 if (soap->fopen && *soap->host) | |
15747 { if (!soap->keep_alive || !soap_valid_socket(soap->socket) || strcmp(soap->host, host) || soap->port != port || !soap->fpoll || soap->fpoll(soap)) | |
15748 { soap->error = SOAP_OK; | |
15749 #ifndef WITH_LEAN | |
15750 if (!strncmp(endpoint, "soap.udp:", 9)) | |
15751 soap->omode |= SOAP_IO_UDP; | |
15752 else | |
15753 #endif | |
15754 { soap->keep_alive = 0; /* to force close */ | |
15755 soap->omode &= ~SOAP_IO_UDP; /* to force close */ | |
15756 } | |
15757 soap_closesock(soap); | |
15758 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Connect/reconnect to '%s' host='%s' path='%s' port=%d\n", endpoint?endpoint:"(null)", soap->host, soap->path, soap->port)); | |
15759 if (!soap->keep_alive || !soap_valid_socket(soap->socket)) | |
15760 { soap->socket = soap->fopen(soap, endpoint, soap->host, soap->port); | |
15761 if (soap->error) | |
15762 return soap->error; | |
15763 soap->keep_alive = ((soap->omode & SOAP_IO_KEEPALIVE) != 0); | |
15764 } | |
15765 } | |
15766 } | |
15767 #ifdef WITH_NTLM | |
15768 if (soap_ntlm_handshake(soap, SOAP_GET, endpoint, soap->host, soap->port)) | |
15769 return soap->error; | |
15770 #endif | |
15771 count = soap_count_attachments(soap); | |
15772 if (soap_begin_send(soap)) | |
15773 return soap->error; | |
15774 if (http_command == SOAP_GET) | |
15775 { soap->mode &= ~SOAP_IO; | |
15776 soap->mode |= SOAP_IO_BUFFER; | |
15777 } | |
15778 #ifndef WITH_NOHTTP | |
15779 if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML) && endpoint) | |
15780 { unsigned int k = soap->mode; | |
15781 soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB); | |
15782 if ((k & SOAP_IO) != SOAP_IO_FLUSH) | |
15783 soap->mode |= SOAP_IO_BUFFER; | |
15784 if ((soap->error = soap->fpost(soap, endpoint, soap->host, soap->port, soap->path, action, count))) | |
15785 return soap->error; | |
15786 #ifndef WITH_LEANER | |
15787 if ((k & SOAP_IO) == SOAP_IO_CHUNK) | |
15788 { if (soap_flush(soap)) | |
15789 return soap->error; | |
15790 } | |
15791 #endif | |
15792 soap->mode = k; | |
15793 } | |
15794 if (http_command == SOAP_GET || http_command == SOAP_DEL) | |
15795 return soap_end_send_flush(soap); | |
15796 #endif | |
15797 return SOAP_OK; | |
15798 } | |
15799 #endif | |
15800 | |
15801 /******************************************************************************/ | |
15802 #ifdef WITH_NTLM | |
15803 #ifndef PALM_1 | |
15804 static int | |
15805 soap_ntlm_handshake(struct soap *soap, int command, const char *endpoint, const char *host, int port) | |
15806 { /* requires libntlm from http://www.nongnu.org/libntlm/ */ | |
15807 const char *userid = (soap->proxy_userid ? soap->proxy_userid : soap->userid); | |
15808 const char *passwd = (soap->proxy_passwd ? soap->proxy_passwd : soap->passwd); | |
15809 struct SOAP_ENV__Header *oldheader; | |
15810 if (soap->ntlm_challenge && userid && passwd && soap->authrealm) | |
15811 { tSmbNtlmAuthRequest req; | |
15812 tSmbNtlmAuthResponse res; | |
15813 tSmbNtlmAuthChallenge ch; | |
15814 short k = soap->keep_alive; | |
15815 size_t l = soap->length; | |
15816 size_t c = soap->count; | |
15817 soap_mode m = soap->mode, o = soap->omode; | |
15818 int s = soap->status; | |
15819 char *a = soap->action; | |
15820 short v = soap->version; | |
15821 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "NTLM '%s'\n", soap->ntlm_challenge)); | |
15822 if (!*soap->ntlm_challenge) | |
15823 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "NTLM S->C Type 1: received NTLM authentication challenge from server\n")); | |
15824 /* S -> C 401 Unauthorized | |
15825 WWW-Authenticate: NTLM | |
15826 */ | |
15827 buildSmbNtlmAuthRequest(&req, userid, soap->authrealm); | |
15828 soap->ntlm_challenge = soap_s2base64(soap, (unsigned char*)&req, NULL, SmbLength(&req)); | |
15829 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "NTLM C->S Type 2: sending NTLM authorization to server\nAuthorization: NTLM %s\n", soap->ntlm_challenge)); | |
15830 /* C -> S GET ... | |
15831 Authorization: NTLM TlRMTVNTUAABAAAAA7IAAAoACgApAAAACQAJACAAAABMSUdIVENJVFlVUlNBLU1JTk9S | |
15832 */ | |
15833 soap->omode = SOAP_IO_BUFFER; | |
15834 if (soap_begin_send(soap)) | |
15835 return soap->error; | |
15836 soap->keep_alive = 1; | |
15837 soap->status = command; | |
15838 if (soap->fpost(soap, endpoint, host, port, soap->path, soap->action, 0) | |
15839 || soap_end_send_flush(soap)) | |
15840 return soap->error; | |
15841 soap->mode = m; | |
15842 soap->keep_alive = k; | |
15843 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "NTLM S->C Type 2: waiting on server NTLM response\n")); | |
15844 oldheader = soap->header; | |
15845 if (soap_begin_recv(soap)) | |
15846 if (soap->error == SOAP_EOF) | |
15847 return soap->error; | |
15848 soap_end_recv(soap); | |
15849 soap->header = oldheader; | |
15850 soap->length = l; | |
15851 if (soap->status != 401 && soap->status != 407) | |
15852 return soap->error = SOAP_NTLM_ERROR; | |
15853 soap->error = SOAP_OK; | |
15854 } | |
15855 /* S -> C 401 Unauthorized | |
15856 WWW-Authenticate: NTLM TlRMTVNTUAACAAAAAAAAACgAAAABggAAU3J2Tm9uY2UAAAAAAAAAAA== | |
15857 */ | |
15858 soap_base642s(soap, soap->ntlm_challenge, (char*)&ch, sizeof(tSmbNtlmAuthChallenge), NULL); | |
15859 buildSmbNtlmAuthResponse(&ch, &res, userid, passwd); | |
15860 soap->ntlm_challenge = soap_s2base64(soap, (unsigned char*)&res, NULL, SmbLength(&res)); | |
15861 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "NTLM C->S Type 3: sending NTLM authorization to server\nAuthorization: NTLM %s\n", soap->ntlm_challenge)); | |
15862 /* C -> S GET ... | |
15863 Authorization: NTLM TlRMTVNTUAADAAAAGAAYAHIAAAAYABgAigAAABQAFABAAAAADAAMAFQAAAASABIAYAAAAAAAAACiAAAAAYIAAFUAUgBTAEEALQBNAEkATgBPAFIAWgBhAHAAaABvAGQATABJAEcASABUAEMASQBUAFkArYfKbe/jRoW5xDxHeoxC1gBmfWiS5+iX4OAN4xBKG/IFPwfH3agtPEia6YnhsADT | |
15864 */ | |
15865 soap->userid = NULL; | |
15866 soap->passwd = NULL; | |
15867 soap->proxy_userid = NULL; | |
15868 soap->proxy_passwd = NULL; | |
15869 soap->keep_alive = k; | |
15870 soap->length = l; | |
15871 soap->count = c; | |
15872 soap->mode = m; | |
15873 soap->omode = o; | |
15874 soap->status = s; | |
15875 soap->action = a; | |
15876 soap->version = v; | |
15877 } | |
15878 return SOAP_OK; | |
15879 } | |
15880 #endif | |
15881 #endif | |
15882 | |
15883 /******************************************************************************/ | |
15884 #ifndef WITH_LEAN | |
15885 SOAP_FMAC1 | |
15886 char* | |
15887 SOAP_FMAC2 | |
15888 soap_s2base64(struct soap *soap, const unsigned char *s, char *t, int n) | |
15889 { register int i; | |
15890 register unsigned long m; | |
15891 register char *p; | |
15892 if (!t) | |
15893 t = (char*)soap_malloc(soap, (n + 2) / 3 * 4 + 1); | |
15894 if (!t) | |
15895 return NULL; | |
15896 p = t; | |
15897 t[0] = '\0'; | |
15898 if (!s) | |
15899 return p; | |
15900 for (; n > 2; n -= 3, s += 3) | |
15901 { m = s[0]; | |
15902 m = (m << 8) | s[1]; | |
15903 m = (m << 8) | s[2]; | |
15904 for (i = 4; i > 0; m >>= 6) | |
15905 t[--i] = soap_base64o[m & 0x3F]; | |
15906 t += 4; | |
15907 } | |
15908 t[0] = '\0'; | |
15909 if (n > 0) /* 0 < n <= 2 implies that t[0..4] is allocated (base64 scaling formula) */ | |
15910 { m = 0; | |
15911 for (i = 0; i < n; i++) | |
15912 m = (m << 8) | *s++; | |
15913 for (; i < 3; i++) | |
15914 m <<= 8; | |
15915 for (i = 4; i > 0; m >>= 6) | |
15916 t[--i] = soap_base64o[m & 0x3F]; | |
15917 for (i = 3; i > n; i--) | |
15918 t[i] = '='; | |
15919 t[4] = '\0'; | |
15920 } | |
15921 return p; | |
15922 } | |
15923 #endif | |
15924 | |
15925 /******************************************************************************/ | |
15926 #ifndef WITH_LEAN | |
15927 SOAP_FMAC1 | |
15928 const char* | |
15929 SOAP_FMAC2 | |
15930 soap_base642s(struct soap *soap, const char *s, char *t, size_t l, int *n) | |
15931 { register size_t i, j; | |
15932 register soap_wchar c; | |
15933 register unsigned long m; | |
15934 register const char *p; | |
15935 if (!s || !*s) | |
15936 { if (n) | |
15937 *n = 0; | |
15938 if (soap->error) | |
15939 return NULL; | |
15940 return SOAP_NON_NULL; | |
15941 } | |
15942 if (!t) | |
15943 { l = (strlen(s) + 3) / 4 * 3 + 1; /* make sure enough space for \0 */ | |
15944 t = (char*)soap_malloc(soap, l); | |
15945 } | |
15946 if (!t) | |
15947 return NULL; | |
15948 p = t; | |
15949 if (n) | |
15950 *n = 0; | |
15951 for (i = 0; ; i += 3, l -= 3) | |
15952 { m = 0; | |
15953 j = 0; | |
15954 while (j < 4) | |
15955 { c = *s++; | |
15956 if (c == '=' || !c) | |
15957 { if (l >= j - 1) | |
15958 { switch (j) | |
15959 { case 2: | |
15960 *t++ = (char)((m >> 4) & 0xFF); | |
15961 i++; | |
15962 l--; | |
15963 break; | |
15964 case 3: | |
15965 *t++ = (char)((m >> 10) & 0xFF); | |
15966 *t++ = (char)((m >> 2) & 0xFF); | |
15967 i += 2; | |
15968 l -= 2; | |
15969 } | |
15970 } | |
15971 if (n) | |
15972 *n = (int)i; | |
15973 if (l) | |
15974 *t = '\0'; | |
15975 return p; | |
15976 } | |
15977 c -= '+'; | |
15978 if (c >= 0 && c <= 79) | |
15979 { int b = soap_base64i[c]; | |
15980 if (b >= 64) | |
15981 { soap->error = SOAP_TYPE; | |
15982 return NULL; | |
15983 } | |
15984 m = (m << 6) + b; | |
15985 j++; | |
15986 } | |
15987 else if (!soap_blank(c + '+')) | |
15988 { soap->error = SOAP_TYPE; | |
15989 return NULL; | |
15990 } | |
15991 } | |
15992 if (l < 3) | |
15993 { if (n) | |
15994 *n = (int)i; | |
15995 if (l) | |
15996 *t = '\0'; | |
15997 return p; | |
15998 } | |
15999 *t++ = (char)((m >> 16) & 0xFF); | |
16000 *t++ = (char)((m >> 8) & 0xFF); | |
16001 *t++ = (char)(m & 0xFF); | |
16002 } | |
16003 } | |
16004 #endif | |
16005 | |
16006 /******************************************************************************/ | |
16007 #ifndef WITH_LEAN | |
16008 SOAP_FMAC1 | |
16009 char* | |
16010 SOAP_FMAC2 | |
16011 soap_s2hex(struct soap *soap, const unsigned char *s, char *t, int n) | |
16012 { register char *p; | |
16013 if (!t) | |
16014 t = (char*)soap_malloc(soap, 2 * n + 1); | |
16015 if (!t) | |
16016 return NULL; | |
16017 p = t; | |
16018 t[0] = '\0'; | |
16019 if (s) | |
16020 { for (; n > 0; n--) | |
16021 { register int m = *s++; | |
16022 *t++ = (char)((m >> 4) + (m > 159 ? 'a' - 10 : '0')); | |
16023 m &= 0x0F; | |
16024 *t++ = (char)(m + (m > 9 ? 'a' - 10 : '0')); | |
16025 } | |
16026 } | |
16027 *t++ = '\0'; | |
16028 return p; | |
16029 } | |
16030 #endif | |
16031 | |
16032 /******************************************************************************/ | |
16033 #ifndef WITH_LEAN | |
16034 SOAP_FMAC1 | |
16035 const char* | |
16036 SOAP_FMAC2 | |
16037 soap_hex2s(struct soap *soap, const char *s, char *t, size_t l, int *n) | |
16038 { register const char *p; | |
16039 if (!s || !*s) | |
16040 { if (n) | |
16041 *n = 0; | |
16042 if (soap->error) | |
16043 return NULL; | |
16044 return SOAP_NON_NULL; | |
16045 } | |
16046 if (!t) | |
16047 { l = strlen(s) / 2 + 1; /* make sure enough space for \0 */ | |
16048 t = (char*)soap_malloc(soap, l); | |
16049 } | |
16050 if (!t) | |
16051 return NULL; | |
16052 p = t; | |
16053 while (l) | |
16054 { register int d1, d2; | |
16055 d1 = *s++; | |
16056 if (!d1) | |
16057 break; | |
16058 d2 = *s++; | |
16059 if (!d2) | |
16060 break; | |
16061 *t++ = (char)(((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0')); | |
16062 l--; | |
16063 } | |
16064 if (n) | |
16065 *n = (int)(t - p); | |
16066 if (l) | |
16067 *t = '\0'; | |
16068 return p; | |
16069 } | |
16070 #endif | |
16071 | |
16072 /******************************************************************************/ | |
16073 #ifndef WITH_NOHTTP | |
16074 #ifndef PALM_1 | |
16075 SOAP_FMAC1 | |
16076 int | |
16077 SOAP_FMAC2 | |
16078 soap_puthttphdr(struct soap *soap, int status, size_t count) | |
16079 { if (soap->status != SOAP_GET && soap->status != SOAP_DEL && soap->status != SOAP_CONNECT) | |
16080 { register const char *s = "text/xml; charset=utf-8"; | |
16081 register int err = SOAP_OK; | |
16082 #ifndef WITH_LEANER | |
16083 register const char *r = NULL; | |
16084 #endif | |
16085 if ((status == SOAP_FILE || soap->status == SOAP_PUT || soap->status == SOAP_POST_FILE) && soap->http_content && !strchr(s, 10) && !strchr(s, 13)) | |
16086 s = soap->http_content; | |
16087 else if (status == SOAP_HTML) | |
16088 s = "text/html; charset=utf-8"; | |
16089 else if (count || ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK)) | |
16090 { if (soap->version == 2) | |
16091 s = "application/soap+xml; charset=utf-8"; | |
16092 } | |
16093 #ifndef WITH_LEANER | |
16094 if (soap->mode & (SOAP_ENC_DIME | SOAP_ENC_MTOM)) | |
16095 { if (soap->mode & SOAP_ENC_MTOM) | |
16096 { if (soap->version == 2) | |
16097 r = "application/soap+xml"; | |
16098 else | |
16099 r = "text/xml"; | |
16100 s = "application/xop+xml"; | |
16101 } | |
16102 else | |
16103 s = "application/dime"; | |
16104 } | |
16105 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) | |
16106 { register const char *t; | |
16107 #ifdef HAVE_SNPRINTF | |
16108 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "multipart/related; charset=utf-8; boundary=\"%s\"; type=\"", soap->mime.boundary); | |
16109 #else | |
16110 sprintf(soap->tmpbuf, "multipart/related; charset=utf-8; boundary=\"%s\"; type=\"", soap->mime.boundary); | |
16111 #endif | |
16112 t = strchr(s, ';'); | |
16113 if (t) | |
16114 strncat(soap->tmpbuf, s, t - s); | |
16115 else | |
16116 strcat(soap->tmpbuf, s); | |
16117 if (soap->mime.start && strlen(soap->tmpbuf) + strlen(soap->mime.start) + 11 < sizeof(soap->tmpbuf)) | |
16118 { strcat(soap->tmpbuf, "\"; start=\""); | |
16119 strcat(soap->tmpbuf, soap->mime.start); | |
16120 } | |
16121 strcat(soap->tmpbuf, "\""); | |
16122 if (r && strlen(soap->tmpbuf) + strlen(r) + 15 < sizeof(soap->tmpbuf)) | |
16123 { strcat(soap->tmpbuf, "; start-info=\""); | |
16124 strcat(soap->tmpbuf, r); | |
16125 strcat(soap->tmpbuf, "\""); | |
16126 } | |
16127 } | |
16128 else | |
16129 strncpy(soap->tmpbuf, s, sizeof(soap->tmpbuf)); | |
16130 soap->tmpbuf[sizeof(soap->tmpbuf) - 1] = '\0'; | |
16131 s = soap->tmpbuf; | |
16132 if (status == SOAP_OK && soap->version == 2 && soap->action && strlen(soap->action) + strlen(s) < sizeof(soap->tmpbuf) - 80) | |
16133 { | |
16134 #ifdef HAVE_SNPRINTF | |
16135 size_t l = strlen(s); | |
16136 soap_snprintf(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, "; action=\"%s\"", soap->action); | |
16137 #else | |
16138 sprintf(soap->tmpbuf + strlen(s), "; action=\"%s\"", soap->action); | |
16139 #endif | |
16140 } | |
16141 #endif | |
16142 if ((err = soap->fposthdr(soap, "Content-Type", s))) | |
16143 return err; | |
16144 #ifdef WITH_ZLIB | |
16145 if ((soap->omode & SOAP_ENC_ZLIB)) | |
16146 { | |
16147 #ifdef WITH_GZIP | |
16148 err = soap->fposthdr(soap, "Content-Encoding", soap->zlib_out == SOAP_ZLIB_DEFLATE ? "deflate" : "gzip"); | |
16149 #else | |
16150 err = soap->fposthdr(soap, "Content-Encoding", "deflate"); | |
16151 #endif | |
16152 if (err) | |
16153 return err; | |
16154 } | |
16155 #endif | |
16156 #ifndef WITH_LEANER | |
16157 if ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK) | |
16158 err = soap->fposthdr(soap, "Transfer-Encoding", "chunked"); | |
16159 else | |
16160 #endif | |
16161 if (s) | |
16162 { | |
16163 #ifdef HAVE_SNPRINTF | |
16164 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%lu", (unsigned long)count); | |
16165 #else | |
16166 sprintf(soap->tmpbuf, "%lu", (unsigned long)count); | |
16167 #endif | |
16168 err = soap->fposthdr(soap, "Content-Length", soap->tmpbuf); | |
16169 } | |
16170 if (err) | |
16171 return err; | |
16172 } | |
16173 return soap->fposthdr(soap, "Connection", soap->keep_alive ? "keep-alive" : "close"); | |
16174 } | |
16175 #endif | |
16176 #endif | |
16177 | |
16178 /******************************************************************************/ | |
16179 #ifndef WITH_LEAN | |
16180 static const char* | |
16181 soap_set_validation_fault(struct soap *soap, const char *s, const char *t) | |
16182 { if (!t) | |
16183 t = SOAP_STR_EOS; | |
16184 if (*soap->tag) | |
16185 { | |
16186 #ifdef HAVE_SNPRINTF | |
16187 soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "Validation constraint violation: %s%s in element '%s'", s, t ? t : SOAP_STR_EOS, soap->tag); | |
16188 #else | |
16189 if (strlen(soap->tag) + strlen(t) < sizeof(soap->msgbuf) - 100) | |
16190 sprintf(soap->msgbuf, "Validation constraint violation: %s%s in element '%s'", s, t, soap->tag); | |
16191 else | |
16192 sprintf(soap->msgbuf, "Validation constraint violation: %s", s); | |
16193 #endif | |
16194 } | |
16195 else | |
16196 { | |
16197 #ifdef HAVE_SNPRINTF | |
16198 soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "Validation constraint violation: %s%s", s, t ? t : SOAP_STR_EOS); | |
16199 #else | |
16200 if (strlen(soap->tag) + strlen(t) < sizeof(soap->msgbuf) - 100) | |
16201 sprintf(soap->msgbuf, "Validation constraint violation: %s%s", s, t); | |
16202 else | |
16203 sprintf(soap->msgbuf, "Validation constraint violation: %s", s); | |
16204 #endif | |
16205 } | |
16206 return soap->msgbuf; | |
16207 } | |
16208 #endif | |
16209 | |
16210 /******************************************************************************/ | |
16211 #ifndef PALM_1 | |
16212 SOAP_FMAC1 | |
16213 void | |
16214 SOAP_FMAC2 | |
16215 soap_set_fault(struct soap *soap) | |
16216 { const char **c = soap_faultcode(soap); | |
16217 const char **s = soap_faultstring(soap); | |
16218 if (soap->fseterror) | |
16219 soap->fseterror(soap, c, s); | |
16220 if (!*c) | |
16221 { if (soap->version == 2) | |
16222 *c = "SOAP-ENV:Sender"; | |
16223 else | |
16224 *c = "SOAP-ENV:Client"; | |
16225 } | |
16226 if (*s) | |
16227 return; | |
16228 switch (soap->error) | |
16229 { | |
16230 #ifndef WITH_LEAN | |
16231 case SOAP_CLI_FAULT: | |
16232 *s = "Client fault"; | |
16233 break; | |
16234 case SOAP_SVR_FAULT: | |
16235 *s = "Server fault"; | |
16236 break; | |
16237 case SOAP_TAG_MISMATCH: | |
16238 *s = soap_set_validation_fault(soap, "tag name or namespace mismatch", NULL); | |
16239 break; | |
16240 case SOAP_TYPE: | |
16241 *s = soap_set_validation_fault(soap, "data type mismatch ", soap->type); | |
16242 break; | |
16243 case SOAP_SYNTAX_ERROR: | |
16244 *s = "Well-formedness violation"; | |
16245 break; | |
16246 case SOAP_NO_TAG: | |
16247 *s = "No tag: no XML root element or missing SOAP message body element"; | |
16248 break; | |
16249 case SOAP_MUSTUNDERSTAND: | |
16250 *c = "SOAP-ENV:MustUnderstand"; | |
16251 #ifdef HAVE_SNPRINTF | |
16252 soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "The data in element '%s' must be understood but cannot be handled", soap->tag); | |
16253 #else | |
16254 strncpy(soap->msgbuf, soap->tag, sizeof(soap->msgbuf)); | |
16255 soap->msgbuf[sizeof(soap->msgbuf) - 1] = '\0'; | |
16256 #endif | |
16257 *s = soap->msgbuf; | |
16258 break; | |
16259 case SOAP_VERSIONMISMATCH: | |
16260 *c = "SOAP-ENV:VersionMismatch"; | |
16261 *s = "Invalid SOAP message or SOAP version mismatch"; | |
16262 break; | |
16263 case SOAP_DATAENCODINGUNKNOWN: | |
16264 *c = "SOAP-ENV:DataEncodingUnknown"; | |
16265 *s = "Unsupported SOAP data encoding"; | |
16266 break; | |
16267 case SOAP_NAMESPACE: | |
16268 *s = soap_set_validation_fault(soap, "namespace error", NULL); | |
16269 break; | |
16270 case SOAP_USER_ERROR: | |
16271 *s = "User data error"; | |
16272 break; | |
16273 case SOAP_FATAL_ERROR: | |
16274 *s = "Fatal error"; | |
16275 break; | |
16276 case SOAP_NO_METHOD: | |
16277 #ifdef HAVE_SNPRINTF | |
16278 soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "Method '%s' not implemented: method name or namespace not recognized", soap->tag); | |
16279 #else | |
16280 sprintf(soap->msgbuf, "Method '%s' not implemented: method name or namespace not recognized", soap->tag); | |
16281 #endif | |
16282 *s = soap->msgbuf; | |
16283 break; | |
16284 case SOAP_NO_DATA: | |
16285 *s = "Data required for operation"; | |
16286 break; | |
16287 case SOAP_GET_METHOD: | |
16288 *s = "HTTP GET method not implemented"; | |
16289 break; | |
16290 case SOAP_PUT_METHOD: | |
16291 *s = "HTTP PUT method not implemented"; | |
16292 break; | |
16293 case SOAP_HTTP_METHOD: | |
16294 *s = "HTTP method not implemented"; | |
16295 break; | |
16296 case SOAP_EOM: | |
16297 *s = "Out of memory"; | |
16298 break; | |
16299 case SOAP_MOE: | |
16300 *s = "Memory overflow or memory corruption error"; | |
16301 break; | |
16302 case SOAP_HDR: | |
16303 *s = "Header line too long"; | |
16304 break; | |
16305 case SOAP_IOB: | |
16306 *s = "Array index out of bounds"; | |
16307 break; | |
16308 case SOAP_NULL: | |
16309 *s = soap_set_validation_fault(soap, "nil not allowed", NULL); | |
16310 break; | |
16311 case SOAP_DUPLICATE_ID: | |
16312 *s = soap_set_validation_fault(soap, "multiple elements (use the SOAP_XML_TREE flag) with duplicate id ", soap->id); | |
16313 if (soap->version == 2) | |
16314 *soap_faultsubcode(soap) = "SOAP-ENC:DuplicateID"; | |
16315 break; | |
16316 case SOAP_MISSING_ID: | |
16317 *s = soap_set_validation_fault(soap, "missing id for ref ", soap->id); | |
16318 if (soap->version == 2) | |
16319 *soap_faultsubcode(soap) = "SOAP-ENC:MissingID"; | |
16320 break; | |
16321 case SOAP_HREF: | |
16322 *s = soap_set_validation_fault(soap, "incompatible object type id-ref ", soap->id); | |
16323 break; | |
16324 case SOAP_FAULT: | |
16325 break; | |
16326 #ifndef WITH_NOIO | |
16327 case SOAP_UDP_ERROR: | |
16328 *s = "Message too large for UDP packet"; | |
16329 break; | |
16330 case SOAP_TCP_ERROR: | |
16331 *s = tcp_error(soap); | |
16332 break; | |
16333 #endif | |
16334 case SOAP_HTTP_ERROR: | |
16335 *s = "An HTTP processing error occurred"; | |
16336 break; | |
16337 case SOAP_NTLM_ERROR: | |
16338 *s = "An HTTP NTLM authentication error occurred"; | |
16339 break; | |
16340 case SOAP_SSL_ERROR: | |
16341 #ifdef WITH_OPENSSL | |
16342 *s = "SSL/TLS error"; | |
16343 #else | |
16344 *s = "OpenSSL not installed: recompile with -DWITH_OPENSSL"; | |
16345 #endif | |
16346 break; | |
16347 case SOAP_PLUGIN_ERROR: | |
16348 *s = "Plugin registry error"; | |
16349 break; | |
16350 case SOAP_DIME_ERROR: | |
16351 *s = "DIME format error or max DIME size exceeds SOAP_MAXDIMESIZE"; | |
16352 break; | |
16353 case SOAP_DIME_HREF: | |
16354 *s = "DIME href to missing attachment"; | |
16355 break; | |
16356 case SOAP_DIME_MISMATCH: | |
16357 *s = "DIME version/transmission error"; | |
16358 break; | |
16359 case SOAP_DIME_END: | |
16360 *s = "End of DIME error"; | |
16361 break; | |
16362 case SOAP_MIME_ERROR: | |
16363 *s = "MIME format error"; | |
16364 break; | |
16365 case SOAP_MIME_HREF: | |
16366 *s = "MIME href to missing attachment"; | |
16367 break; | |
16368 case SOAP_MIME_END: | |
16369 *s = "End of MIME error"; | |
16370 break; | |
16371 case SOAP_ZLIB_ERROR: | |
16372 #ifdef WITH_ZLIB | |
16373 #ifdef HAVE_SNPRINTF | |
16374 soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "Zlib/gzip error: '%s'", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS); | |
16375 #else | |
16376 sprintf(soap->msgbuf, "Zlib/gzip error: '%s'", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS); | |
16377 #endif | |
16378 *s = soap->msgbuf; | |
16379 #else | |
16380 *s = "Zlib/gzip not installed for (de)compression: recompile with -DWITH_GZIP"; | |
16381 #endif | |
16382 break; | |
16383 case SOAP_REQUIRED: | |
16384 *s = soap_set_validation_fault(soap, "missing required attribute", NULL); | |
16385 break; | |
16386 case SOAP_PROHIBITED: | |
16387 *s = soap_set_validation_fault(soap, "prohibited attribute present", NULL); | |
16388 break; | |
16389 case SOAP_OCCURS: | |
16390 *s = soap_set_validation_fault(soap, "occurrence violation", NULL); | |
16391 break; | |
16392 case SOAP_LENGTH: | |
16393 *s = soap_set_validation_fault(soap, "content range or length violation", NULL); | |
16394 break; | |
16395 case SOAP_FD_EXCEEDED: | |
16396 *s = "Maximum number of open connections was reached (no define HAVE_POLL): increase FD_SETSIZE"; | |
16397 break; | |
16398 case SOAP_UTF_ERROR: | |
16399 *s = "UTF content encoding error"; | |
16400 break; | |
16401 case SOAP_STOP: | |
16402 *s = "Stopped: no response sent or received (informative)"; | |
16403 break; | |
16404 #endif | |
16405 case SOAP_EOF: | |
16406 #ifndef WITH_NOIO | |
16407 *s = soap_strerror(soap); /* *s = soap->msgbuf */ | |
16408 #ifndef WITH_LEAN | |
16409 if (strlen(soap->msgbuf) + 25 < sizeof(soap->msgbuf)) | |
16410 { memmove(soap->msgbuf + 25, soap->msgbuf, strlen(soap->msgbuf) + 1); | |
16411 memcpy(soap->msgbuf, "End of file or no input: ", 25); | |
16412 } | |
16413 #endif | |
16414 break; | |
16415 #else | |
16416 *s = "End of file or no input"; | |
16417 break; | |
16418 #endif | |
16419 default: | |
16420 #ifndef WITH_NOHTTP | |
16421 #ifndef WITH_LEAN | |
16422 if (soap->error > 200 && soap->error < 600) | |
16423 { | |
16424 #ifdef HAVE_SNPRINTF | |
16425 soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "HTTP Error: %d %s", soap->error, http_error(soap, soap->error)); | |
16426 #else | |
16427 sprintf(soap->msgbuf, "HTTP Error: %d %s", soap->error, http_error(soap, soap->error)); | |
16428 #endif | |
16429 *s = soap->msgbuf; | |
16430 } | |
16431 else | |
16432 #endif | |
16433 #endif | |
16434 { | |
16435 #ifdef HAVE_SNPRINTF | |
16436 soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "Error %d", soap->error); | |
16437 #else | |
16438 sprintf(soap->msgbuf, "Error %d", soap->error); | |
16439 #endif | |
16440 *s = soap->msgbuf; | |
16441 } | |
16442 } | |
16443 } | |
16444 #endif | |
16445 | |
16446 /******************************************************************************/ | |
16447 #ifndef PALM_1 | |
16448 SOAP_FMAC1 | |
16449 int | |
16450 SOAP_FMAC2 | |
16451 soap_send_fault(struct soap *soap) | |
16452 { register int status = soap->error; | |
16453 if (status == SOAP_OK || status == SOAP_STOP) | |
16454 return soap_closesock(soap); | |
16455 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Sending back fault struct for error code %d\n", soap->error)); | |
16456 soap->keep_alive = 0; /* to terminate connection */ | |
16457 soap_set_fault(soap); | |
16458 if (soap->error < 200 && soap->error != SOAP_FAULT) | |
16459 soap->header = NULL; | |
16460 if (status != SOAP_EOF || (!soap->recv_timeout && !soap->send_timeout)) | |
16461 { register int r = 1; | |
16462 #ifndef WITH_NOIO | |
16463 if (soap->fpoll && soap->fpoll(soap)) | |
16464 r = 0; | |
16465 #ifndef WITH_LEAN | |
16466 else if (soap_valid_socket(soap->socket)) | |
16467 { r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_SND, 0); | |
16468 if (r > 0) | |
16469 { int t; | |
16470 if (!(r & SOAP_TCP_SELECT_SND) | |
16471 || ((r & SOAP_TCP_SELECT_RCV) | |
16472 && recv(soap->socket, (char*)&t, 1, MSG_PEEK) < 0)) | |
16473 r = 0; | |
16474 } | |
16475 } | |
16476 #endif | |
16477 #endif | |
16478 if (r > 0) | |
16479 { soap->error = SOAP_OK; | |
16480 soap->encodingStyle = NULL; /* no encodingStyle in Faults */ | |
16481 soap_serializeheader(soap); | |
16482 soap_serializefault(soap); | |
16483 soap_begin_count(soap); | |
16484 if (soap->mode & SOAP_IO_LENGTH) | |
16485 { soap_envelope_begin_out(soap); | |
16486 soap_putheader(soap); | |
16487 soap_body_begin_out(soap); | |
16488 soap_putfault(soap); | |
16489 soap_body_end_out(soap); | |
16490 soap_envelope_end_out(soap); | |
16491 } | |
16492 soap_end_count(soap); | |
16493 if (soap_response(soap, status) | |
16494 || soap_envelope_begin_out(soap) | |
16495 || soap_putheader(soap) | |
16496 || soap_body_begin_out(soap) | |
16497 || soap_putfault(soap) | |
16498 || soap_body_end_out(soap) | |
16499 || soap_envelope_end_out(soap)) | |
16500 return soap_closesock(soap); | |
16501 soap_end_send(soap); | |
16502 } | |
16503 } | |
16504 soap->error = status; | |
16505 return soap_closesock(soap); | |
16506 } | |
16507 #endif | |
16508 | |
16509 /******************************************************************************/ | |
16510 #ifndef PALM_1 | |
16511 SOAP_FMAC1 | |
16512 int | |
16513 SOAP_FMAC2 | |
16514 soap_recv_fault(struct soap *soap, int check) | |
16515 { register int status = soap->error; | |
16516 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Check if receiving SOAP Fault\n")); | |
16517 if (!check) | |
16518 { /* try getfault when no tag or tag mismatched at level 2, otherwise ret */ | |
16519 if (soap->error != SOAP_NO_TAG | |
16520 && (soap->error != SOAP_TAG_MISMATCH || soap->level != 2)) | |
16521 return soap->error; | |
16522 } | |
16523 else if (soap->version == 0) /* check == 1 but no SOAP: do not parse SOAP Fault */ | |
16524 return SOAP_OK; | |
16525 soap->error = SOAP_OK; | |
16526 if (soap_getfault(soap)) | |
16527 { /* check flag set: check if SOAP Fault is present, if not just return */ | |
16528 if (check && soap->error == SOAP_TAG_MISMATCH && soap->level == 2) | |
16529 return soap->error = SOAP_OK; | |
16530 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Error: soap_get_soapfault() failed at level %u tag '%s'\n", soap->level, soap->tag)); | |
16531 *soap_faultcode(soap) = (soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client"); | |
16532 soap->error = status; | |
16533 soap_set_fault(soap); | |
16534 } | |
16535 else | |
16536 { register const char *s = *soap_faultcode(soap); | |
16537 if (!soap_match_tag(soap, s, "SOAP-ENV:Server") || !soap_match_tag(soap, s, "SOAP-ENV:Receiver")) | |
16538 status = SOAP_SVR_FAULT; | |
16539 else if (!soap_match_tag(soap, s, "SOAP-ENV:Client") || !soap_match_tag(soap, s, "SOAP-ENV:Sender")) | |
16540 status = SOAP_CLI_FAULT; | |
16541 else if (!soap_match_tag(soap, s, "SOAP-ENV:MustUnderstand")) | |
16542 status = SOAP_MUSTUNDERSTAND; | |
16543 else if (!soap_match_tag(soap, s, "SOAP-ENV:VersionMismatch")) | |
16544 status = SOAP_VERSIONMISMATCH; | |
16545 else | |
16546 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Received SOAP Fault code %s\n", s)); | |
16547 status = SOAP_FAULT; | |
16548 } | |
16549 if (!soap_body_end_in(soap)) | |
16550 soap_envelope_end_in(soap); | |
16551 } | |
16552 soap_end_recv(soap); | |
16553 soap->error = status; | |
16554 return soap_closesock(soap); | |
16555 } | |
16556 #endif | |
16557 | |
16558 /******************************************************************************/ | |
16559 #ifndef WITH_NOHTTP | |
16560 #ifndef PALM_1 | |
16561 SOAP_FMAC1 | |
16562 int | |
16563 SOAP_FMAC2 | |
16564 soap_send_empty_response(struct soap *soap, int httpstatuscode) | |
16565 { register soap_mode m = soap->omode; | |
16566 if (!(m & SOAP_IO_UDP)) | |
16567 { soap->count = 0; | |
16568 if ((m & SOAP_IO) == SOAP_IO_CHUNK) | |
16569 soap->omode = (m & ~SOAP_IO) | SOAP_IO_BUFFER; | |
16570 soap_response(soap, httpstatuscode); | |
16571 soap_end_send(soap); /* force end of sends */ | |
16572 soap->error = SOAP_STOP; /* stops the server (from returning a response) */ | |
16573 soap->omode = m; | |
16574 } | |
16575 return soap_closesock(soap); | |
16576 } | |
16577 #endif | |
16578 #endif | |
16579 | |
16580 /******************************************************************************/ | |
16581 #ifndef WITH_NOHTTP | |
16582 #ifndef PALM_1 | |
16583 SOAP_FMAC1 | |
16584 int | |
16585 SOAP_FMAC2 | |
16586 soap_recv_empty_response(struct soap *soap) | |
16587 { if (!(soap->omode & SOAP_IO_UDP)) | |
16588 { if (!soap_begin_recv(soap)) | |
16589 { | |
16590 #ifndef WITH_LEAN | |
16591 if (soap->body) | |
16592 soap_get_http_body(soap, NULL); /* read (empty?) HTTP body and discard */ | |
16593 #endif | |
16594 soap_end_recv(soap); | |
16595 } | |
16596 else if (soap->error == SOAP_NO_DATA || soap->error == 202) | |
16597 soap->error = SOAP_OK; | |
16598 } | |
16599 return soap_closesock(soap); | |
16600 } | |
16601 #endif | |
16602 #endif | |
16603 | |
16604 /******************************************************************************/ | |
16605 #ifndef WITH_NOIO | |
16606 #ifndef PALM_1 | |
16607 static const char* | |
16608 soap_strerror(struct soap *soap) | |
16609 { register int err = soap->errnum; | |
16610 *soap->msgbuf = '\0'; | |
16611 if (err) | |
16612 { | |
16613 #ifndef WIN32 | |
16614 # ifdef HAVE_STRERROR_R | |
16615 # ifdef _GNU_SOURCE | |
16616 return strerror_r(err, soap->msgbuf, sizeof(soap->msgbuf)); /* GNU-specific */ | |
16617 # else | |
16618 strerror_r(err, soap->msgbuf, sizeof(soap->msgbuf)); /* XSI-compliant */ | |
16619 # endif | |
16620 # else | |
16621 return strerror(err); | |
16622 # endif | |
16623 #else | |
16624 #ifndef UNDER_CE | |
16625 DWORD len; | |
16626 *soap->msgbuf = '\0'; | |
16627 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); | |
16628 #else | |
16629 DWORD i, len; | |
16630 *soap->msgbuf = '\0'; | |
16631 len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, 0, (LPTSTR)soap->msgbuf, (DWORD)(sizeof(soap->msgbuf)/sizeof(TCHAR)), NULL); | |
16632 for (i = 0; i <= len; i++) | |
16633 { if (((TCHAR*)soap->msgbuf)[i] < 0x80) | |
16634 soap->msgbuf[i] = (char)((TCHAR*)soap->msgbuf)[i]; | |
16635 else | |
16636 soap->msgbuf[i] = '?'; | |
16637 } | |
16638 #endif | |
16639 #endif | |
16640 } | |
16641 else | |
16642 { char *s = soap->msgbuf; | |
16643 #ifndef WITH_LEAN | |
16644 int rt = soap->recv_timeout, st = soap->send_timeout; | |
16645 int ru = ' ', su = ' '; | |
16646 #endif | |
16647 strcpy(s, "Operation interrupted or timed out"); | |
16648 #ifndef WITH_LEAN | |
16649 if (rt < 0) | |
16650 { rt = -rt; | |
16651 ru = 'u'; | |
16652 } | |
16653 if (st < 0) | |
16654 { st = -st; | |
16655 su = 'u'; | |
16656 } | |
16657 if (rt) | |
16658 { | |
16659 #ifdef HAVE_SNPRINTF | |
16660 size_t l = strlen(s); | |
16661 soap_snprintf(s + l, sizeof(soap->msgbuf) - l, " (%d%cs recv delay)", rt, ru); | |
16662 #else | |
16663 sprintf(s + strlen(s), " (%d%cs recv delay)", rt, ru); | |
16664 #endif | |
16665 } | |
16666 if (st) | |
16667 { | |
16668 #ifdef HAVE_SNPRINTF | |
16669 size_t l = strlen(s); | |
16670 soap_snprintf(s + l, sizeof(soap->msgbuf) - l, " (%d%cs send delay)", st, su); | |
16671 #else | |
16672 sprintf(s + strlen(s), " (%d%cs send delay)", st, su); | |
16673 #endif | |
16674 } | |
16675 #endif | |
16676 } | |
16677 return soap->msgbuf; | |
16678 } | |
16679 #endif | |
16680 #endif | |
16681 | |
16682 /******************************************************************************/ | |
16683 #ifndef PALM_2 | |
16684 static int | |
16685 soap_set_error(struct soap *soap, const char *faultcode, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML, int soaperror) | |
16686 { *soap_faultcode(soap) = faultcode; | |
16687 if (faultsubcodeQName) | |
16688 *soap_faultsubcode(soap) = faultsubcodeQName; | |
16689 *soap_faultstring(soap) = faultstring; | |
16690 if (faultdetailXML && *faultdetailXML) | |
16691 { register const char **s = soap_faultdetail(soap); | |
16692 if (s) | |
16693 *s = faultdetailXML; | |
16694 } | |
16695 return soap->error = soaperror; | |
16696 } | |
16697 #endif | |
16698 | |
16699 /******************************************************************************/ | |
16700 #ifndef PALM_2 | |
16701 SOAP_FMAC1 | |
16702 int | |
16703 SOAP_FMAC2 | |
16704 soap_set_sender_error(struct soap *soap, const char *faultstring, const char *faultdetailXML, int soaperror) | |
16705 { return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", NULL, faultstring, faultdetailXML, soaperror); | |
16706 } | |
16707 #endif | |
16708 | |
16709 /******************************************************************************/ | |
16710 #ifndef PALM_2 | |
16711 SOAP_FMAC1 | |
16712 int | |
16713 SOAP_FMAC2 | |
16714 soap_set_receiver_error(struct soap *soap, const char *faultstring, const char *faultdetailXML, int soaperror) | |
16715 { return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", NULL, faultstring, faultdetailXML, soaperror); | |
16716 } | |
16717 #endif | |
16718 | |
16719 /******************************************************************************/ | |
16720 #ifndef PALM_2 | |
16721 static int | |
16722 soap_copy_fault(struct soap *soap, const char *faultcode, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML) | |
16723 { char *r = NULL, *s = NULL, *t = NULL; | |
16724 if (faultsubcodeQName) | |
16725 r = soap_strdup(soap, faultsubcodeQName); | |
16726 if (faultstring) | |
16727 s = soap_strdup(soap, faultstring); | |
16728 if (faultdetailXML) | |
16729 t = soap_strdup(soap, faultdetailXML); | |
16730 return soap_set_error(soap, faultcode, r, s, t, SOAP_FAULT); | |
16731 } | |
16732 #endif | |
16733 | |
16734 /******************************************************************************/ | |
16735 #ifndef PALM_2 | |
16736 SOAP_FMAC1 | |
16737 int | |
16738 SOAP_FMAC2 | |
16739 soap_sender_fault(struct soap *soap, const char *faultstring, const char *faultdetailXML) | |
16740 { return soap_sender_fault_subcode(soap, NULL, faultstring, faultdetailXML); | |
16741 } | |
16742 #endif | |
16743 | |
16744 /******************************************************************************/ | |
16745 #ifndef PALM_2 | |
16746 SOAP_FMAC1 | |
16747 int | |
16748 SOAP_FMAC2 | |
16749 soap_sender_fault_subcode(struct soap *soap, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML) | |
16750 { return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", faultsubcodeQName, faultstring, faultdetailXML); | |
16751 } | |
16752 #endif | |
16753 | |
16754 /******************************************************************************/ | |
16755 #ifndef PALM_2 | |
16756 SOAP_FMAC1 | |
16757 int | |
16758 SOAP_FMAC2 | |
16759 soap_receiver_fault(struct soap *soap, const char *faultstring, const char *faultdetailXML) | |
16760 { return soap_receiver_fault_subcode(soap, NULL, faultstring, faultdetailXML); | |
16761 } | |
16762 #endif | |
16763 | |
16764 /******************************************************************************/ | |
16765 #ifndef PALM_2 | |
16766 SOAP_FMAC1 | |
16767 int | |
16768 SOAP_FMAC2 | |
16769 soap_receiver_fault_subcode(struct soap *soap, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML) | |
16770 { return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", faultsubcodeQName, faultstring, faultdetailXML); | |
16771 } | |
16772 #endif | |
16773 | |
16774 /******************************************************************************/ | |
16775 #ifndef PALM_2 | |
16776 #ifndef WITH_NOSTDLIB | |
16777 SOAP_FMAC1 | |
16778 void | |
16779 SOAP_FMAC2 | |
16780 soap_print_fault(struct soap *soap, FILE *fd) | |
16781 { if (soap_check_state(soap)) | |
16782 fprintf(fd, "Error: soap struct state not initialized\n"); | |
16783 else if (soap->error) | |
16784 { const char **c, *v = NULL, *s, *d; | |
16785 c = soap_faultcode(soap); | |
16786 if (!*c) | |
16787 soap_set_fault(soap); | |
16788 if (soap->version == 2) | |
16789 v = soap_check_faultsubcode(soap); | |
16790 s = *soap_faultstring(soap); | |
16791 d = soap_check_faultdetail(soap); | |
16792 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 : "[no detail]"); | |
16793 } | |
16794 } | |
16795 #endif | |
16796 #endif | |
16797 | |
16798 /******************************************************************************/ | |
16799 #ifdef __cplusplus | |
16800 #ifndef WITH_LEAN | |
16801 #ifndef WITH_NOSTDLIB | |
16802 #ifndef WITH_COMPAT | |
16803 SOAP_FMAC1 | |
16804 void | |
16805 SOAP_FMAC2 | |
16806 soap_stream_fault(struct soap *soap, std::ostream& os) | |
16807 { if (soap_check_state(soap)) | |
16808 os << "Error: soap struct state not initialized\n"; | |
16809 else if (soap->error) | |
16810 { const char **c, *v = NULL, *s, *d; | |
16811 c = soap_faultcode(soap); | |
16812 if (!*c) | |
16813 soap_set_fault(soap); | |
16814 if (soap->version == 2) | |
16815 v = soap_check_faultsubcode(soap); | |
16816 s = *soap_faultstring(soap); | |
16817 d = soap_check_faultdetail(soap); | |
16818 os << (soap->version ? "SOAP 1." : "Error ") | |
16819 << (soap->version ? (int)soap->version : soap->error) | |
16820 << " fault: " << *c | |
16821 << "[" << (v ? v : "no subcode") << "]" | |
16822 << std::endl | |
16823 << "\"" << (s ? s : "[no reason]") << "\"" | |
16824 << std::endl | |
16825 << "Detail: " << (d ? d : "[no detail]") | |
16826 << std::endl; | |
16827 } | |
16828 } | |
16829 #endif | |
16830 #endif | |
16831 #endif | |
16832 #endif | |
16833 | |
16834 /******************************************************************************/ | |
16835 #ifndef WITH_LEAN | |
16836 #ifndef WITH_NOSTDLIB | |
16837 SOAP_FMAC1 | |
16838 char* | |
16839 SOAP_FMAC2 | |
16840 soap_sprint_fault(struct soap *soap, char *buf, size_t len) | |
16841 { if (soap_check_state(soap)) | |
16842 { strncpy(buf, "Error: soap struct not initialized", len); | |
16843 buf[len - 1] = '\0'; | |
16844 } | |
16845 else if (soap->error) | |
16846 { const char **c, *v = NULL, *s, *d; | |
16847 c = soap_faultcode(soap); | |
16848 if (!*c) | |
16849 soap_set_fault(soap); | |
16850 if (soap->version == 2) | |
16851 v = *soap_faultsubcode(soap); | |
16852 s = *soap_faultstring(soap); | |
16853 d = soap_check_faultdetail(soap); | |
16854 #ifdef HAVE_SNPRINTF | |
16855 soap_snprintf(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 : "[no detail]"); | |
16856 #else | |
16857 if (len > 40 + (v ? strlen(v) : 0) + (s ? strlen(s) : 0) + (d ? strlen(d) : 0)) | |
16858 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 : "[no detail]"); | |
16859 else if (len > 40) | |
16860 sprintf(buf, "%s%d fault: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, *c); | |
16861 else | |
16862 buf[0] = '\0'; | |
16863 #endif | |
16864 } | |
16865 return buf; | |
16866 } | |
16867 #endif | |
16868 #endif | |
16869 | |
16870 /******************************************************************************/ | |
16871 #ifndef PALM_1 | |
16872 #ifndef WITH_NOSTDLIB | |
16873 SOAP_FMAC1 | |
16874 void | |
16875 SOAP_FMAC2 | |
16876 soap_print_fault_location(struct soap *soap, FILE *fd) | |
16877 { | |
16878 #ifndef WITH_LEAN | |
16879 int i, j, c1, c2; | |
16880 if (soap->error && soap->error != SOAP_STOP && soap->bufidx <= soap->buflen && soap->buflen > 0 && soap->buflen <= SOAP_BUFLEN) | |
16881 { i = (int)soap->bufidx - 1; | |
16882 if (i <= 0) | |
16883 i = 0; | |
16884 c1 = soap->buf[i]; | |
16885 soap->buf[i] = '\0'; | |
16886 if ((int)soap->buflen >= i + 1024) | |
16887 j = i + 1023; | |
16888 else | |
16889 j = (int)soap->buflen - 1; | |
16890 c2 = soap->buf[j]; | |
16891 soap->buf[j] = '\0'; | |
16892 fprintf(fd, "%s%c\n<!-- ** HERE ** -->\n", soap->buf, c1); | |
16893 if (soap->bufidx < soap->buflen) | |
16894 fprintf(fd, "%s\n", soap->buf + soap->bufidx); | |
16895 soap->buf[i] = (char)c1; | |
16896 soap->buf[j] = (char)c2; | |
16897 } | |
16898 #endif | |
16899 } | |
16900 #endif | |
16901 #endif | |
16902 | |
16903 /******************************************************************************/ | |
16904 #ifndef PALM_1 | |
16905 SOAP_FMAC1 | |
16906 int | |
16907 SOAP_FMAC2 | |
16908 soap_register_plugin_arg(struct soap *soap, int (*fcreate)(struct soap*, struct soap_plugin*, void*), void *arg) | |
16909 { register struct soap_plugin *p; | |
16910 register int r; | |
16911 if (!(p = (struct soap_plugin*)SOAP_MALLOC(soap, sizeof(struct soap_plugin)))) | |
16912 return soap->error = SOAP_EOM; | |
16913 p->id = NULL; | |
16914 p->data = NULL; | |
16915 p->fcopy = NULL; | |
16916 p->fdelete = NULL; | |
16917 r = fcreate(soap, p, arg); | |
16918 if (!r && p->fdelete) | |
16919 { p->next = soap->plugins; | |
16920 soap->plugins = p; | |
16921 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Registered '%s' plugin\n", p->id)); | |
16922 return SOAP_OK; | |
16923 } | |
16924 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)); | |
16925 SOAP_FREE(soap, p); | |
16926 return r; | |
16927 } | |
16928 #endif | |
16929 | |
16930 /******************************************************************************/ | |
16931 #ifndef PALM_1 | |
16932 static void * | |
16933 fplugin(struct soap *soap, const char *id) | |
16934 { register struct soap_plugin *p; | |
16935 for (p = soap->plugins; p; p = p->next) | |
16936 if (p->id == id || !strcmp(p->id, id)) | |
16937 return p->data; | |
16938 return NULL; | |
16939 } | |
16940 #endif | |
16941 | |
16942 /******************************************************************************/ | |
16943 #ifndef PALM_2 | |
16944 SOAP_FMAC1 | |
16945 void * | |
16946 SOAP_FMAC2 | |
16947 soap_lookup_plugin(struct soap *soap, const char *id) | |
16948 { return soap->fplugin(soap, id); | |
16949 } | |
16950 #endif | |
16951 | |
16952 /******************************************************************************/ | |
16953 #ifdef __cplusplus | |
16954 } | |
16955 #endif | |
16956 | |
16957 /******************************************************************************\ | |
16958 * | |
16959 * C++ soap struct methods | |
16960 * | |
16961 \******************************************************************************/ | |
16962 | |
16963 #ifdef __cplusplus | |
16964 soap::soap() | |
16965 { soap_init(this); | |
16966 } | |
16967 #endif | |
16968 | |
16969 /******************************************************************************/ | |
16970 #ifdef __cplusplus | |
16971 soap::soap(soap_mode m) | |
16972 { soap_init1(this, m); | |
16973 } | |
16974 #endif | |
16975 | |
16976 /******************************************************************************/ | |
16977 #ifdef __cplusplus | |
16978 soap::soap(soap_mode im, soap_mode om) | |
16979 { soap_init2(this, im, om); | |
16980 } | |
16981 #endif | |
16982 | |
16983 /******************************************************************************/ | |
16984 #ifdef __cplusplus | |
16985 soap::soap(const struct soap& soap) | |
16986 { soap_copy_context(this, &soap); | |
16987 } | |
16988 #endif | |
16989 | |
16990 /******************************************************************************/ | |
16991 #ifdef __cplusplus | |
16992 soap::~soap() | |
16993 { soap_destroy(this); | |
16994 soap_end(this); | |
16995 soap_done(this); | |
16996 } | |
16997 #endif | |
16998 | |
16999 /******************************************************************************/ |