1 /* |
|
2 |
|
3 stdsoap2.c[pp] 2.7.6b |
|
4 |
|
5 gSOAP runtime |
|
6 |
|
7 gSOAP XML Web services tools |
|
8 Copyright (C) 2000-2005, Robert van Engelen, Genivia Inc., All Rights Reserved. |
|
9 This part of the software is released under one of the following licenses: |
|
10 GPL, the gSOAP public license, or Genivia's license for commercial use. |
|
11 -------------------------------------------------------------------------------- |
|
12 Contributors: |
|
13 |
|
14 Wind River Systems, Inc., for the following additions: |
|
15 - vxWorks compatible |
|
16 -------------------------------------------------------------------------------- |
|
17 gSOAP public license. |
|
18 |
|
19 The contents of this file are subject to the gSOAP Public License Version 1.3 |
|
20 (the "License"); you may not use this file except in compliance with the |
|
21 License. You may obtain a copy of the License at |
|
22 http://www.cs.fsu.edu/~engelen/soaplicense.html |
|
23 Software distributed under the License is distributed on an "AS IS" basis, |
|
24 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
|
25 for the specific language governing rights and limitations under the License. |
|
26 |
|
27 The Initial Developer of the Original Code is Robert A. van Engelen. |
|
28 Copyright (C) 2000-2005, Robert van Engelen, Genivia Inc., All Rights Reserved. |
|
29 -------------------------------------------------------------------------------- |
|
30 GPL license. |
|
31 |
|
32 This program is free software; you can redistribute it and/or modify it under |
|
33 the terms of the GNU General Public License as published by the Free Software |
|
34 Foundation; either version 2 of the License, or (at your option) any later |
|
35 version. |
|
36 |
|
37 This program is distributed in the hope that it will be useful, but WITHOUT ANY |
|
38 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A |
|
39 PARTICULAR PURPOSE. See the GNU General Public License for more details. |
|
40 |
|
41 You should have received a copy of the GNU General Public License along with |
|
42 this program; if not, write to the Free Software Foundation, Inc., 59 Temple |
|
43 Place, Suite 330, Boston, MA 02111-1307 USA |
|
44 |
|
45 Author contact information: |
|
46 engelen@genivia.com / engelen@acm.org |
|
47 -------------------------------------------------------------------------------- |
|
48 A commercial use license is available from Genivia, Inc., contact@genivia.com |
|
49 -------------------------------------------------------------------------------- |
|
50 |
|
51 Installation note: |
|
52 |
|
53 Win32 build needs winsock.dll (Visual C++ "wsock32.lib") |
|
54 To do this in Visual C++ 6.0, go to "Project", "settings", select the "Link" |
|
55 tab (the project file needs to be selected in the file view) and add |
|
56 "wsock32.lib" to the "Object/library modules" entry |
|
57 |
|
58 On Mac OS X with gcc (GCC) 3.1 20020420 (prerelease) you MUST compile with |
|
59 -fstack_check when using -O2 because gcc 3.1 has a bug that smashes the stack |
|
60 when locally allocated data exceeds 64K. |
|
61 |
|
62 */ |
|
63 |
|
64 #include "stdsoap2.h" |
|
65 |
|
66 #ifdef __cplusplus |
|
67 SOAP_SOURCE_STAMP("@(#) stdsoap2.cpp ver 2.7.6b 2005-08-26 12:00:00 GMT") |
|
68 extern "C" { |
|
69 #else |
|
70 SOAP_SOURCE_STAMP("@(#) stdsoap2.c ver 2.7.6b 2005-08-26 12:00:00 GMT") |
|
71 #endif |
|
72 |
|
73 /* 8bit character representing unknown/nonrepresentable character data (e.g. not supported by current locale with multibyte support enabled) */ |
|
74 #ifndef SOAP_UNKNOWN_CHAR |
|
75 #define SOAP_UNKNOWN_CHAR (127) |
|
76 #endif |
|
77 |
|
78 /* EOF=-1 */ |
|
79 #define SOAP_LT (soap_wchar)(-2) /* XML character '<' */ |
|
80 #define SOAP_TT (soap_wchar)(-3) /* XML character '</' */ |
|
81 #define SOAP_GT (soap_wchar)(-4) /* XML character '>' */ |
|
82 #define SOAP_QT (soap_wchar)(-5) /* XML character '"' */ |
|
83 #define SOAP_AP (soap_wchar)(-6) /* XML character ''' */ |
|
84 |
|
85 #define SOAP_BOM (soap_wchar)(0xFEFF) /* UTF BOM is Unicode FEFF */ |
|
86 |
|
87 #define soap_blank(c) ((c) >= 0 && (c) <= 32) |
|
88 #define soap_notblank(c) ((c) > 32) |
|
89 #define soap_hash_ptr(p) (((unsigned long)(p) >> 3) & (SOAP_PTRHASH - 1)) |
|
90 |
|
91 static int soap_isxdigit(int); |
|
92 static soap_wchar soap_char(struct soap*); |
|
93 |
|
94 #ifndef WITH_NOIDREF |
|
95 static void soap_update_ptrs(struct soap*, char*, char*, long); |
|
96 static int soap_has_copies(struct soap*, const char*, const char*); |
|
97 static void soap_init_iht(struct soap*); |
|
98 static void soap_free_iht(struct soap*); |
|
99 static void soap_init_pht(struct soap*); |
|
100 static void soap_free_pht(struct soap*); |
|
101 #endif |
|
102 |
|
103 #ifdef SOAP_DEBUG |
|
104 static void soap_init_logs(struct soap*); |
|
105 static void soap_close_logfile(struct soap*, int); |
|
106 static void soap_set_logfile(struct soap*, int, const char*); |
|
107 static void soap_free_mht(struct soap*); |
|
108 static void soap_track_unlink(struct soap*, const void*); |
|
109 #endif |
|
110 |
|
111 static int soap_set_error(struct soap*, const char*, const char*, const char*, const char*, int); |
|
112 static int soap_copy_fault(struct soap*, const char*, const char*, const char*, const char*); |
|
113 static int soap_getattrval(struct soap*, char*, size_t, soap_wchar); |
|
114 static void *fplugin(struct soap*, const char*); |
|
115 |
|
116 #ifndef WITH_LEAN |
|
117 static const char *soap_set_validation_fault(struct soap*, const char*, const char*); |
|
118 static int soap_isnumeric(struct soap*, const char*); |
|
119 static time_t soap_timegm(struct tm*); |
|
120 static struct soap_nlist *soap_lookup_ns(struct soap *soap, const char *tag, size_t n); |
|
121 static struct soap_nlist *soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized); |
|
122 static void soap_pop_ns(struct soap *soap); |
|
123 static void soap_utilize_ns(struct soap *soap, const char *tag, size_t n); |
|
124 #endif |
|
125 |
|
126 #ifndef WITH_LEANER |
|
127 static struct soap_multipart *soap_new_multipart(struct soap*, struct soap_multipart**, struct soap_multipart**, char*, size_t); |
|
128 static int soap_putdimefield(struct soap*, const char*, size_t); |
|
129 static char *soap_getdimefield(struct soap*, size_t); |
|
130 static void soap_select_mime_boundary(struct soap*); |
|
131 static int soap_valid_mime_boundary(struct soap*); |
|
132 static int soap_match_cid(const char*, const char*); |
|
133 static void soap_resolve_attachment(struct soap*, struct soap_multipart*); |
|
134 #endif |
|
135 |
|
136 #ifdef WITH_GZIP |
|
137 static int soap_getgziphdr(struct soap*); |
|
138 #endif |
|
139 |
|
140 #ifdef WITH_OPENSSL |
|
141 static void ssl_init(); |
|
142 static int ssl_auth_init(struct soap*); |
|
143 static int ssl_verify_callback(int, X509_STORE_CTX*); |
|
144 static int ssl_password(char*, int, int, void *); |
|
145 static const char *ssl_error(struct soap*, int); |
|
146 /* This callback is included for future references. It should not be deleted |
|
147 static DH *ssl_tmp_dh(SSL*, int, int); |
|
148 */ |
|
149 #endif |
|
150 |
|
151 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) |
|
152 static const char *soap_decode(char*, size_t, const char*, const char*); |
|
153 #endif |
|
154 |
|
155 #ifndef WITH_NOHTTP |
|
156 static soap_wchar soap_getchunkchar(struct soap*); |
|
157 static const char *http_error(struct soap*, int); |
|
158 static int http_post(struct soap*, const char*, const char*, int, const char*, const char*, size_t); |
|
159 static int http_get(struct soap*); |
|
160 static int http_send_header(struct soap*, const char*); |
|
161 static int http_post_header(struct soap*, const char*, const char*); |
|
162 static int http_response(struct soap*, int, size_t); |
|
163 static int http_parse(struct soap*); |
|
164 static int http_parse_header(struct soap*, const char*, const char*); |
|
165 #endif |
|
166 |
|
167 #ifndef WITH_NOIO |
|
168 static int fsend(struct soap*, const char*, size_t); |
|
169 static size_t frecv(struct soap*, char*, size_t); |
|
170 static int tcp_init(struct soap*); |
|
171 static const char *tcp_error(struct soap*); |
|
172 #ifndef WITH_IPV6 |
|
173 static int tcp_gethost(struct soap*, const char *addr, struct in_addr *inaddr); |
|
174 #endif |
|
175 static int tcp_connect(struct soap*, const char *endpoint, const char *host, int port); |
|
176 static int tcp_accept(struct soap*, int, struct sockaddr*, int*); |
|
177 static int tcp_disconnect(struct soap*); |
|
178 static int tcp_closesocket(struct soap*, SOAP_SOCKET); |
|
179 static int tcp_shutdownsocket(struct soap*, SOAP_SOCKET, int); |
|
180 static const char *soap_strerror(struct soap*); |
|
181 #endif |
|
182 |
|
183 #ifdef VXWORKS |
|
184 static int vx_nonblocking = TRUE; /* ioctl argument */ |
|
185 #endif |
|
186 |
|
187 #if defined(PALM) && !defined(PALM_2) |
|
188 unsigned short errno; |
|
189 #endif |
|
190 |
|
191 #ifndef PALM_1 |
|
192 static const char soap_env1[42] = "http://schemas.xmlsoap.org/soap/envelope/"; |
|
193 static const char soap_enc1[42] = "http://schemas.xmlsoap.org/soap/encoding/"; |
|
194 static const char soap_env2[40] = "http://www.w3.org/2003/05/soap-envelope"; |
|
195 static const char soap_enc2[40] = "http://www.w3.org/2003/05/soap-encoding"; |
|
196 static const char soap_rpc[35] = "http://www.w3.org/2003/05/soap-rpc"; |
|
197 #endif |
|
198 |
|
199 #ifndef PALM_1 |
|
200 const struct soap_double_nan soap_double_nan = {0xFFFFFFFF, 0xFFFFFFFF}; |
|
201 static const char soap_base64o[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
|
202 static const char soap_base64i[81] = "\76XXX\77\64\65\66\67\70\71\72\73\74\75XXXXXXX\00\01\02\03\04\05\06\07\10\11\12\13\14\15\16\17\20\21\22\23\24\25\26\27\30\31XXXXXX\32\33\34\35\36\37\40\41\42\43\44\45\46\47\50\51\52\53\54\55\56\57\60\61\62\63"; |
|
203 #endif |
|
204 |
|
205 #ifndef WITH_LEAN |
|
206 static const char soap_indent[11] = "\n\t\t\t\t\t\t\t\t\t"; |
|
207 /* Alternative indentation form for SOAP_XML_INDENT: |
|
208 static const char soap_indent[21] = "\n "; |
|
209 */ |
|
210 #endif |
|
211 |
|
212 static const char soap_padding[3] = "\0\0"; |
|
213 #define SOAP_STR_PADDING (soap_padding) |
|
214 #define SOAP_STR_EOS (soap_padding) |
|
215 #define SOAP_NON_NULL (soap_padding) |
|
216 |
|
217 #ifndef WITH_LEAN |
|
218 static const struct soap_code_map html_entity_codes[] = /* entities for XHTML parsing */ |
|
219 { { 160, "nbsp" }, |
|
220 { 161, "iexcl" }, |
|
221 { 162, "cent" }, |
|
222 { 163, "pound" }, |
|
223 { 164, "curren" }, |
|
224 { 165, "yen" }, |
|
225 { 166, "brvbar" }, |
|
226 { 167, "sect" }, |
|
227 { 168, "uml" }, |
|
228 { 169, "copy" }, |
|
229 { 170, "ordf" }, |
|
230 { 171, "laquo" }, |
|
231 { 172, "not" }, |
|
232 { 173, "shy" }, |
|
233 { 174, "reg" }, |
|
234 { 175, "macr" }, |
|
235 { 176, "deg" }, |
|
236 { 177, "plusmn" }, |
|
237 { 178, "sup2" }, |
|
238 { 179, "sup3" }, |
|
239 { 180, "acute" }, |
|
240 { 181, "micro" }, |
|
241 { 182, "para" }, |
|
242 { 183, "middot" }, |
|
243 { 184, "cedil" }, |
|
244 { 185, "sup1" }, |
|
245 { 186, "ordm" }, |
|
246 { 187, "raquo" }, |
|
247 { 188, "frac14" }, |
|
248 { 189, "frac12" }, |
|
249 { 190, "frac34" }, |
|
250 { 191, "iquest" }, |
|
251 { 192, "Agrave" }, |
|
252 { 193, "Aacute" }, |
|
253 { 194, "Acirc" }, |
|
254 { 195, "Atilde" }, |
|
255 { 196, "Auml" }, |
|
256 { 197, "Aring" }, |
|
257 { 198, "AElig" }, |
|
258 { 199, "Ccedil" }, |
|
259 { 200, "Egrave" }, |
|
260 { 201, "Eacute" }, |
|
261 { 202, "Ecirc" }, |
|
262 { 203, "Euml" }, |
|
263 { 204, "Igrave" }, |
|
264 { 205, "Iacute" }, |
|
265 { 206, "Icirc" }, |
|
266 { 207, "Iuml" }, |
|
267 { 208, "ETH" }, |
|
268 { 209, "Ntilde" }, |
|
269 { 210, "Ograve" }, |
|
270 { 211, "Oacute" }, |
|
271 { 212, "Ocirc" }, |
|
272 { 213, "Otilde" }, |
|
273 { 214, "Ouml" }, |
|
274 { 215, "times" }, |
|
275 { 216, "Oslash" }, |
|
276 { 217, "Ugrave" }, |
|
277 { 218, "Uacute" }, |
|
278 { 219, "Ucirc" }, |
|
279 { 220, "Uuml" }, |
|
280 { 221, "Yacute" }, |
|
281 { 222, "THORN" }, |
|
282 { 223, "szlig" }, |
|
283 { 224, "agrave" }, |
|
284 { 225, "aacute" }, |
|
285 { 226, "acirc" }, |
|
286 { 227, "atilde" }, |
|
287 { 228, "auml" }, |
|
288 { 229, "aring" }, |
|
289 { 230, "aelig" }, |
|
290 { 231, "ccedil" }, |
|
291 { 232, "egrave" }, |
|
292 { 233, "eacute" }, |
|
293 { 234, "ecirc" }, |
|
294 { 235, "euml" }, |
|
295 { 236, "igrave" }, |
|
296 { 237, "iacute" }, |
|
297 { 238, "icirc" }, |
|
298 { 239, "iuml" }, |
|
299 { 240, "eth" }, |
|
300 { 241, "ntilde" }, |
|
301 { 242, "ograve" }, |
|
302 { 243, "oacute" }, |
|
303 { 244, "ocirc" }, |
|
304 { 245, "otilde" }, |
|
305 { 246, "ouml" }, |
|
306 { 247, "divide" }, |
|
307 { 248, "oslash" }, |
|
308 { 249, "ugrave" }, |
|
309 { 250, "uacute" }, |
|
310 { 251, "ucirc" }, |
|
311 { 252, "uuml" }, |
|
312 { 253, "yacute" }, |
|
313 { 254, "thorn" }, |
|
314 { 255, "yuml" }, |
|
315 { 0, NULL } |
|
316 }; |
|
317 #endif |
|
318 |
|
319 #ifndef WITH_NOIO |
|
320 #ifndef WITH_LEAN |
|
321 static const struct soap_code_map h_error_codes[] = |
|
322 { |
|
323 #ifdef HOST_NOT_FOUND |
|
324 { HOST_NOT_FOUND, "Host not found" }, |
|
325 #endif |
|
326 #ifdef TRY_AGAIN |
|
327 { TRY_AGAIN, "Try Again" }, |
|
328 #endif |
|
329 #ifdef NO_RECOVERY |
|
330 { NO_RECOVERY, "No Recovery" }, |
|
331 #endif |
|
332 #ifdef NO_DATA |
|
333 { NO_DATA, "No Data" }, |
|
334 #endif |
|
335 #ifdef NO_ADDRESS |
|
336 { NO_ADDRESS, "No Address" }, |
|
337 #endif |
|
338 { 0, NULL } |
|
339 }; |
|
340 #endif |
|
341 #endif |
|
342 |
|
343 #ifndef WITH_NOHTTP |
|
344 #ifndef WITH_LEAN |
|
345 static const struct soap_code_map h_http_error_codes[] = |
|
346 { { 201, "Created" }, |
|
347 { 202, "Accepted" }, |
|
348 { 203, "Non-Authoritative Information" }, |
|
349 { 204, "No Content" }, |
|
350 { 205, "Reset Content" }, |
|
351 { 206, "Partial Content" }, |
|
352 { 300, "Multiple Choices" }, |
|
353 { 301, "Moved Permanently" }, |
|
354 { 302, "Found" }, |
|
355 { 303, "See Other" }, |
|
356 { 304, "Not Modified" }, |
|
357 { 305, "Use Proxy" }, |
|
358 { 307, "Temporary Redirect" }, |
|
359 { 400, "Bad Request" }, |
|
360 { 401, "Unauthorized" }, |
|
361 { 402, "Payment Required" }, |
|
362 { 403, "Forbidden" }, |
|
363 { 404, "Not Found" }, |
|
364 { 405, "Method Not Allowed" }, |
|
365 { 406, "Not Acceptable" }, |
|
366 { 407, "Proxy Authentication Required" }, |
|
367 { 408, "Request Time-out" }, |
|
368 { 409, "Conflict" }, |
|
369 { 410, "Gone" }, |
|
370 { 411, "Length Required" }, |
|
371 { 412, "Precondition Failed" }, |
|
372 { 413, "Request Entity Too Large" }, |
|
373 { 414, "Request-URI Too Large" }, |
|
374 { 415, "Unsupported Media Type" }, |
|
375 { 416, "Requested range not satisfiable" }, |
|
376 { 417, "Expectation Failed" }, |
|
377 { 500, "Internal Server Error" }, |
|
378 { 501, "Not Implemented" }, |
|
379 { 502, "Bad Gateway" }, |
|
380 { 503, "Service Unavailable" }, |
|
381 { 504, "Gateway Time-out" }, |
|
382 { 505, "HTTP Version not supported" }, |
|
383 { 0, NULL } |
|
384 }; |
|
385 #endif |
|
386 #endif |
|
387 |
|
388 #ifdef WITH_OPENSSL |
|
389 static const struct soap_code_map h_ssl_error_codes[] = |
|
390 { |
|
391 #define _SSL_ERROR(e) { e, #e } |
|
392 _SSL_ERROR(SSL_ERROR_SSL), |
|
393 _SSL_ERROR(SSL_ERROR_ZERO_RETURN), |
|
394 _SSL_ERROR(SSL_ERROR_WANT_READ), |
|
395 _SSL_ERROR(SSL_ERROR_WANT_WRITE), |
|
396 _SSL_ERROR(SSL_ERROR_WANT_CONNECT), |
|
397 _SSL_ERROR(SSL_ERROR_WANT_X509_LOOKUP), |
|
398 _SSL_ERROR(SSL_ERROR_SYSCALL), |
|
399 { 0, NULL } |
|
400 }; |
|
401 #endif |
|
402 |
|
403 #ifndef WITH_LEANER |
|
404 static const struct soap_code_map mime_codes[] = |
|
405 { { SOAP_MIME_7BIT, "7bit" }, |
|
406 { SOAP_MIME_8BIT, "8bit" }, |
|
407 { SOAP_MIME_BINARY, "binary" }, |
|
408 { SOAP_MIME_QUOTED_PRINTABLE, "quoted-printable" }, |
|
409 { SOAP_MIME_BASE64, "base64" }, |
|
410 { SOAP_MIME_IETF_TOKEN, "ietf-token" }, |
|
411 { SOAP_MIME_X_TOKEN, "x-token" }, |
|
412 { 0, NULL } |
|
413 }; |
|
414 #endif |
|
415 |
|
416 #ifdef WIN32 |
|
417 static int tcp_done = 0; |
|
418 #endif |
|
419 |
|
420 /******************************************************************************/ |
|
421 #ifndef WITH_NOIO |
|
422 #ifndef PALM_1 |
|
423 static int |
|
424 fsend(struct soap *soap, const char *s, size_t n) |
|
425 { register int nwritten; |
|
426 #if defined(__cplusplus) && !defined(WITH_LEAN) |
|
427 if (soap->os) |
|
428 { soap->os->write(s, n); |
|
429 if (soap->os->good()) |
|
430 return SOAP_OK; |
|
431 return SOAP_EOF; |
|
432 } |
|
433 #endif |
|
434 while (n) |
|
435 { if (soap_valid_socket(soap->socket)) |
|
436 { |
|
437 #ifndef WITH_LEAN |
|
438 if (soap->send_timeout) |
|
439 { struct timeval timeout; |
|
440 fd_set fd; |
|
441 if (soap->send_timeout > 0) |
|
442 { timeout.tv_sec = soap->send_timeout; |
|
443 timeout.tv_usec = 0; |
|
444 } |
|
445 else |
|
446 { timeout.tv_sec = -soap->send_timeout/1000000; |
|
447 timeout.tv_usec = -soap->send_timeout%1000000; |
|
448 } |
|
449 FD_ZERO(&fd); |
|
450 FD_SET((SOAP_SOCKET)soap->socket, &fd); |
|
451 for (;;) |
|
452 { register int r = select((SOAP_SOCKET)(soap->socket + 1), NULL, &fd, &fd, &timeout); |
|
453 if (r > 0) |
|
454 break; |
|
455 if (!r) |
|
456 { soap->errnum = 0; |
|
457 return SOAP_EOF; |
|
458 } |
|
459 if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EAGAIN) |
|
460 { soap->errnum = soap_socket_errno; |
|
461 return SOAP_EOF; |
|
462 } |
|
463 } |
|
464 } |
|
465 #endif |
|
466 #ifdef WITH_OPENSSL |
|
467 if (soap->ssl) |
|
468 nwritten = SSL_write(soap->ssl, s, n); |
|
469 else if (soap->bio) |
|
470 nwritten = BIO_write(soap->bio, s, n); |
|
471 else |
|
472 #endif |
|
473 #ifdef WITH_UDP |
|
474 if ((soap->omode & SOAP_IO_UDP)) |
|
475 { if (soap->peerlen) |
|
476 nwritten = sendto((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags, (struct sockaddr*)&soap->peer, soap->peerlen); |
|
477 else |
|
478 nwritten = send((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags); |
|
479 /* retry and back-off algorithm */ |
|
480 /* TODO: this is not very clear from specs so verify and limit conditions under which we should loop (e.g. ENOBUFS) */ |
|
481 if (nwritten < 0) |
|
482 { struct timeval timeout; |
|
483 fd_set fd; |
|
484 int udp_repeat; |
|
485 int udp_delay; |
|
486 if ((soap->connect_flags & SO_BROADCAST)) |
|
487 udp_repeat = 3; /* SOAP-over-UDP MULTICAST_UDP_REPEAT - 1 */ |
|
488 else |
|
489 udp_repeat = 1; /* SOAP-over-UDP UNICAST_UDP_REPEAT - 1 */ |
|
490 udp_delay = (soap_random % 201) + 50; /* UDP_MIN_DELAY .. UDP_MAX_DELAY */ |
|
491 do |
|
492 { timeout.tv_sec = 0; |
|
493 timeout.tv_usec = 1000 * udp_delay; /* ms */ |
|
494 FD_ZERO(&fd); |
|
495 FD_SET((SOAP_SOCKET)soap->socket, &fd); |
|
496 select((SOAP_SOCKET)(soap->socket + 1), NULL, NULL, &fd, &timeout); |
|
497 if (soap->peerlen) |
|
498 nwritten = sendto((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags, (struct sockaddr*)&soap->peer, soap->peerlen); |
|
499 else |
|
500 nwritten = send((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags); |
|
501 udp_delay <<= 1; |
|
502 if (udp_delay > 500) /* UDP_UPPER_DELAY */ |
|
503 udp_delay = 500; |
|
504 } |
|
505 while (nwritten < 0 && --udp_repeat > 0); |
|
506 } |
|
507 } |
|
508 else |
|
509 #endif |
|
510 #ifndef PALM |
|
511 nwritten = send((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags); |
|
512 #else |
|
513 nwritten = send((SOAP_SOCKET)soap->socket, (void*)s, n, soap->socket_flags); |
|
514 #endif |
|
515 if (nwritten <= 0) |
|
516 { |
|
517 #ifdef WITH_OPENSSL |
|
518 int err; |
|
519 if (soap->ssl && (err = SSL_get_error(soap->ssl, nwritten)) != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) |
|
520 return SOAP_EOF; |
|
521 #endif |
|
522 if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EWOULDBLOCK && soap_socket_errno != SOAP_EAGAIN) |
|
523 { soap->errnum = soap_socket_errno; |
|
524 return SOAP_EOF; |
|
525 } |
|
526 nwritten = 0; /* and call write() again */ |
|
527 } |
|
528 } |
|
529 else |
|
530 { |
|
531 #ifdef WITH_FASTCGI |
|
532 nwritten = fwrite((void*)s, 1, n, stdout); |
|
533 fflush(stdout); |
|
534 #else |
|
535 #ifdef UNDER_CE |
|
536 nwritten = fwrite(s, 1, n, soap->sendfd); |
|
537 #else |
|
538 #ifdef VXWORKS |
|
539 #ifdef WMW_RPM_IO |
|
540 if (soap->rpmreqid) |
|
541 nwritten = (httpBlockPut(soap->rpmreqid, s, n) == 0) ? n : -1; |
|
542 else |
|
543 nwritten = fwrite(s, sizeof(char), n, fdopen(soap->sendfd, "w")); |
|
544 #else |
|
545 nwritten = fwrite(s, sizeof(char), n, fdopen(soap->sendfd, "w")); |
|
546 #endif /* WMW_RPM_IO */ |
|
547 #else |
|
548 nwritten = write((SOAP_SOCKET)soap->sendfd, s, n); |
|
549 #endif |
|
550 #endif |
|
551 #endif |
|
552 if (nwritten <= 0) |
|
553 { if (soap_errno != SOAP_EINTR && soap_errno != SOAP_EWOULDBLOCK && soap_errno != SOAP_EAGAIN) |
|
554 { soap->errnum = soap_errno; |
|
555 return SOAP_EOF; |
|
556 } |
|
557 nwritten = 0; /* and call write() again */ |
|
558 } |
|
559 } |
|
560 n -= nwritten; |
|
561 s += nwritten; |
|
562 } |
|
563 return SOAP_OK; |
|
564 } |
|
565 #endif |
|
566 #endif |
|
567 |
|
568 /******************************************************************************/ |
|
569 #ifndef PALM_1 |
|
570 SOAP_FMAC1 |
|
571 int |
|
572 SOAP_FMAC2 |
|
573 soap_send_raw(struct soap *soap, const char *s, size_t n) |
|
574 { if (!n) |
|
575 return SOAP_OK; |
|
576 if (soap->mode & SOAP_IO_LENGTH) |
|
577 { soap->count += n; |
|
578 #ifndef WITH_LEANER |
|
579 if (soap->fpreparesend && (soap->mode & SOAP_IO) != SOAP_IO_STORE) |
|
580 return soap->error = soap->fpreparesend(soap, s, n); |
|
581 #endif |
|
582 return SOAP_OK; |
|
583 } |
|
584 if (soap->mode & SOAP_IO) |
|
585 { register size_t i = SOAP_BUFLEN - soap->bufidx; |
|
586 while (n >= i) |
|
587 { memcpy(soap->buf + soap->bufidx, s, i); |
|
588 soap->bufidx = SOAP_BUFLEN; |
|
589 if (soap_flush(soap)) |
|
590 return soap->error; |
|
591 s += i; |
|
592 n -= i; |
|
593 i = SOAP_BUFLEN; |
|
594 } |
|
595 memcpy(soap->buf + soap->bufidx, s, n); |
|
596 soap->bufidx += n; |
|
597 return SOAP_OK; |
|
598 } |
|
599 return soap_flush_raw(soap, s, n); |
|
600 } |
|
601 #endif |
|
602 |
|
603 /******************************************************************************/ |
|
604 #ifndef PALM_1 |
|
605 SOAP_FMAC1 |
|
606 int |
|
607 SOAP_FMAC2 |
|
608 soap_flush(struct soap *soap) |
|
609 { register int n = soap->bufidx; |
|
610 if (n) |
|
611 { soap->bufidx = 0; |
|
612 #ifdef WITH_ZLIB |
|
613 if (soap->mode & SOAP_ENC_ZLIB) |
|
614 { soap->d_stream.next_in = (Byte*)soap->buf; |
|
615 soap->d_stream.avail_in = (unsigned int)n; |
|
616 #ifdef WITH_GZIP |
|
617 soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)n); |
|
618 #endif |
|
619 do |
|
620 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating %u bytes\n", soap->d_stream.avail_in)); |
|
621 if (deflate(&soap->d_stream, Z_NO_FLUSH) != Z_OK) |
|
622 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to deflate: %s\n", soap->d_stream.msg?soap->d_stream.msg:"")); |
|
623 return soap->error = SOAP_ZLIB_ERROR; |
|
624 } |
|
625 if (!soap->d_stream.avail_out) |
|
626 { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN)) |
|
627 return soap->error; |
|
628 soap->d_stream.next_out = (Byte*)soap->z_buf; |
|
629 soap->d_stream.avail_out = SOAP_BUFLEN; |
|
630 } |
|
631 } while (soap->d_stream.avail_in); |
|
632 } |
|
633 else |
|
634 #endif |
|
635 return soap_flush_raw(soap, soap->buf, n); |
|
636 } |
|
637 return SOAP_OK; |
|
638 } |
|
639 #endif |
|
640 |
|
641 /******************************************************************************/ |
|
642 #ifndef PALM_1 |
|
643 SOAP_FMAC1 |
|
644 int |
|
645 SOAP_FMAC2 |
|
646 soap_flush_raw(struct soap *soap, const char *s, size_t n) |
|
647 { if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) |
|
648 { register char *t; |
|
649 if (!(t = (char*)soap_push_block(soap, n))) |
|
650 return soap->error = SOAP_EOM; |
|
651 memcpy(t, s, n); |
|
652 #ifndef WITH_LEANER |
|
653 if (soap->fpreparesend) |
|
654 return soap->error = soap->fpreparesend(soap, s, n); |
|
655 #endif |
|
656 return SOAP_OK; |
|
657 } |
|
658 #ifndef WITH_LEANER |
|
659 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) |
|
660 { char t[16]; |
|
661 sprintf(t, "\r\n%lX\r\n" + (soap->chunksize ? 0 : 2), (unsigned long)n); |
|
662 DBGMSG(SENT, t, strlen(t)); |
|
663 if ((soap->error = soap->fsend(soap, t, strlen(t)))) |
|
664 return soap->error; |
|
665 soap->chunksize += n; |
|
666 } |
|
667 DBGMSG(SENT, s, n); |
|
668 #endif |
|
669 return soap->error = soap->fsend(soap, s, n); |
|
670 } |
|
671 #endif |
|
672 |
|
673 /******************************************************************************/ |
|
674 #ifndef PALM_1 |
|
675 SOAP_FMAC1 |
|
676 int |
|
677 SOAP_FMAC2 |
|
678 soap_send(struct soap *soap, const char *s) |
|
679 { if (s) |
|
680 return soap_send_raw(soap, s, strlen(s)); |
|
681 return SOAP_OK; |
|
682 } |
|
683 #endif |
|
684 |
|
685 /******************************************************************************/ |
|
686 #ifndef WITH_LEANER |
|
687 #ifndef PALM_1 |
|
688 SOAP_FMAC1 |
|
689 int |
|
690 SOAP_FMAC2 |
|
691 soap_send2(struct soap *soap, const char *s1, const char *s2) |
|
692 { if (soap_send(soap, s1)) |
|
693 return soap->error; |
|
694 return soap_send(soap, s2); |
|
695 } |
|
696 #endif |
|
697 #endif |
|
698 |
|
699 /******************************************************************************/ |
|
700 #ifndef WITH_LEANER |
|
701 #ifndef PALM_1 |
|
702 SOAP_FMAC1 |
|
703 int |
|
704 SOAP_FMAC2 |
|
705 soap_send3(struct soap *soap, const char *s1, const char *s2, const char *s3) |
|
706 { if (soap_send(soap, s1) |
|
707 || soap_send(soap, s2)) |
|
708 return soap->error; |
|
709 return soap_send(soap, s3); |
|
710 } |
|
711 #endif |
|
712 #endif |
|
713 |
|
714 /******************************************************************************/ |
|
715 #ifndef WITH_NOIO |
|
716 #ifndef PALM_1 |
|
717 static size_t |
|
718 frecv(struct soap *soap, char *s, size_t n) |
|
719 { register int r; |
|
720 soap->errnum = 0; |
|
721 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "frecv\n")); |
|
722 #if defined(__cplusplus) && !defined(WITH_LEAN) |
|
723 if (soap->is) |
|
724 { if (soap->is->good()) |
|
725 return soap->is->read(s, n).gcount(); |
|
726 return 0; |
|
727 } |
|
728 #endif |
|
729 if (soap_valid_socket(soap->socket)) |
|
730 { for (;;) |
|
731 { |
|
732 #ifndef WITH_LEAN |
|
733 if (soap->recv_timeout) |
|
734 { struct timeval timeout; |
|
735 fd_set fd; |
|
736 if (soap->recv_timeout > 0) |
|
737 { timeout.tv_sec = soap->recv_timeout; |
|
738 timeout.tv_usec = 0; |
|
739 } |
|
740 else |
|
741 { timeout.tv_sec = -soap->recv_timeout/1000000; |
|
742 timeout.tv_usec = -soap->recv_timeout%1000000; |
|
743 } |
|
744 FD_ZERO(&fd); |
|
745 FD_SET((SOAP_SOCKET)soap->socket, &fd); |
|
746 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "select\n")); |
|
747 for (;;) |
|
748 { r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout); |
|
749 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "r=%d\n", r)); |
|
750 if (r > 0) |
|
751 break; |
|
752 if (!r) |
|
753 { soap->errnum = 0; |
|
754 return 0; |
|
755 } |
|
756 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Socket err %d\n", soap_socket_errno)); |
|
757 if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EAGAIN) |
|
758 { soap->errnum = soap_socket_errno; |
|
759 return 0; |
|
760 } |
|
761 } |
|
762 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "select end\n")); |
|
763 } |
|
764 #endif |
|
765 #ifdef WITH_OPENSSL |
|
766 if (soap->ssl) |
|
767 { int err; |
|
768 r = SSL_read(soap->ssl, s, n); |
|
769 if (r > 0) |
|
770 return (size_t)r; |
|
771 err = SSL_get_error(soap->ssl, r); |
|
772 if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) |
|
773 return 0; |
|
774 } |
|
775 else if (soap->bio) |
|
776 { r = BIO_read(soap->bio, s, n); |
|
777 if (r > 0) |
|
778 return (size_t)r; |
|
779 return 0; |
|
780 } |
|
781 else |
|
782 #endif |
|
783 { |
|
784 #ifdef WITH_UDP |
|
785 if ((soap->omode & SOAP_IO_UDP)) |
|
786 { SOAP_SOCKLEN_T k = (SOAP_SOCKLEN_T)sizeof(soap->peer); |
|
787 memset((void*)&soap->peer, 0, sizeof(soap->peer)); |
|
788 r = recvfrom((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags, (struct sockaddr*)&soap->peer, &k); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */ |
|
789 soap->peerlen = (size_t)k; |
|
790 #ifndef WITH_IPV6 |
|
791 soap->ip = ntohl(soap->peer.sin_addr.s_addr); |
|
792 soap->port = (int)ntohs(soap->peer.sin_port); |
|
793 #endif |
|
794 } |
|
795 else |
|
796 #endif |
|
797 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "recv\n")); |
|
798 r = recv((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags); |
|
799 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "r=%d\n", r)); |
|
800 if (r >= 0) |
|
801 return (size_t)r; |
|
802 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Socket err %d\n", soap_socket_errno)); |
|
803 if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EAGAIN && soap_socket_errno != SOAP_EWOULDBLOCK) |
|
804 { soap->errnum = soap_socket_errno; |
|
805 return 0; |
|
806 } |
|
807 } |
|
808 #ifndef WITH_LEAN |
|
809 { struct timeval timeout; |
|
810 fd_set fd; |
|
811 timeout.tv_sec = 0; |
|
812 timeout.tv_usec = 10000; |
|
813 FD_ZERO(&fd); |
|
814 FD_SET((SOAP_SOCKET)soap->socket, &fd); |
|
815 #ifdef WITH_OPENSSL |
|
816 if (soap->ssl && SSL_get_error(soap->ssl, r) == SSL_ERROR_WANT_WRITE) |
|
817 r = select((SOAP_SOCKET)(soap->socket + 1), NULL, &fd, &fd, &timeout); |
|
818 else |
|
819 r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout); |
|
820 #else |
|
821 r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout); |
|
822 #endif |
|
823 if (r < 0 && soap_socket_errno != SOAP_EINTR) |
|
824 { soap->errnum = soap_socket_errno; |
|
825 return 0; |
|
826 } |
|
827 } |
|
828 #endif |
|
829 } |
|
830 } |
|
831 #ifdef WITH_FASTCGI |
|
832 return fread(s, 1, n, stdin); |
|
833 #else |
|
834 #ifdef UNDER_CE |
|
835 return fread(s, 1, n, soap->recvfd); |
|
836 #else |
|
837 #ifdef WMW_RPM_IO |
|
838 if (soap->rpmreqid) |
|
839 r = httpBlockRead(soap->rpmreqid, s, n); |
|
840 #endif |
|
841 r = read((SOAP_SOCKET)soap->recvfd, s, n); |
|
842 if (r >= 0) |
|
843 return (size_t)r; |
|
844 soap->errnum = soap_errno; |
|
845 return 0; |
|
846 #endif |
|
847 #endif |
|
848 } |
|
849 #endif |
|
850 #endif |
|
851 |
|
852 /******************************************************************************/ |
|
853 #ifndef WITH_NOHTTP |
|
854 #ifndef PALM_1 |
|
855 static soap_wchar |
|
856 soap_getchunkchar(struct soap *soap) |
|
857 { if (soap->bufidx < soap->buflen) |
|
858 return soap->buf[soap->bufidx++]; |
|
859 soap->bufidx = 0; |
|
860 soap->buflen = soap->chunkbuflen = soap->frecv(soap, soap->buf, SOAP_BUFLEN); |
|
861 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket %d\n", (unsigned int)soap->buflen, soap->socket)); |
|
862 DBGMSG(RECV, soap->buf, soap->buflen); |
|
863 if (soap->buflen) |
|
864 return soap->buf[soap->bufidx++]; |
|
865 return EOF; |
|
866 } |
|
867 #endif |
|
868 #endif |
|
869 |
|
870 /******************************************************************************/ |
|
871 #ifndef PALM_1 |
|
872 static int |
|
873 soap_isxdigit(int c) |
|
874 { return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); |
|
875 } |
|
876 #endif |
|
877 |
|
878 /******************************************************************************/ |
|
879 #ifndef PALM_1 |
|
880 SOAP_FMAC1 |
|
881 int |
|
882 SOAP_FMAC2 |
|
883 soap_recv_raw(struct soap *soap) |
|
884 { register size_t ret; |
|
885 #ifdef WITH_ZLIB |
|
886 if (soap->mode & SOAP_ENC_ZLIB) |
|
887 { if (soap->d_stream.next_out == Z_NULL) |
|
888 return EOF; |
|
889 if (soap->d_stream.avail_in || !soap->d_stream.avail_out) |
|
890 { register int r; |
|
891 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflating\n")); |
|
892 soap->d_stream.next_out = (Byte*)soap->buf; |
|
893 soap->d_stream.avail_out = SOAP_BUFLEN; |
|
894 r = inflate(&soap->d_stream, Z_NO_FLUSH); |
|
895 if (r == Z_OK || r == Z_STREAM_END) |
|
896 { soap->bufidx = 0; |
|
897 soap->buflen = SOAP_BUFLEN - soap->d_stream.avail_out; |
|
898 if (soap->zlib_in == SOAP_ZLIB_GZIP) |
|
899 soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen); |
|
900 if (r == Z_STREAM_END) |
|
901 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out)); |
|
902 soap->z_ratio_in = (float)soap->d_stream.total_in / (float)soap->d_stream.total_out; |
|
903 soap->d_stream.next_out = Z_NULL; |
|
904 } |
|
905 if (soap->buflen) |
|
906 { soap->count += soap->buflen; |
|
907 return SOAP_OK; |
|
908 } |
|
909 } |
|
910 else if (r != Z_BUF_ERROR) |
|
911 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate error: %s\n", soap->d_stream.msg?soap->d_stream.msg:"")); |
|
912 soap->d_stream.next_out = Z_NULL; |
|
913 soap->error = SOAP_ZLIB_ERROR; |
|
914 return EOF; |
|
915 } |
|
916 } |
|
917 zlib_again: |
|
918 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK && !soap->chunksize) |
|
919 { memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN); |
|
920 soap->buflen = soap->z_buflen; |
|
921 } |
|
922 } |
|
923 #endif |
|
924 #ifndef WITH_NOHTTP |
|
925 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) /* read HTTP chunked transfer */ |
|
926 { |
|
927 chunk_again: |
|
928 if (soap->chunksize) |
|
929 { soap->buflen = ret = soap->frecv(soap, soap->buf, soap->chunksize > SOAP_BUFLEN ? SOAP_BUFLEN : soap->chunksize); |
|
930 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk: read %u bytes\n", (unsigned int)ret)); |
|
931 DBGMSG(RECV, soap->buf, ret); |
|
932 soap->bufidx = 0; |
|
933 soap->chunksize -= ret; |
|
934 } |
|
935 else |
|
936 { register soap_wchar c; |
|
937 char *t, tmp[8]; |
|
938 t = tmp; |
|
939 if (!soap->chunkbuflen) |
|
940 { soap->chunkbuflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN); |
|
941 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes (chunked) from socket %d\n", (unsigned int)ret, soap->socket)); |
|
942 DBGMSG(RECV, soap->buf, ret); |
|
943 soap->bufidx = 0; |
|
944 if (!ret) |
|
945 return soap->ahead = EOF; |
|
946 } |
|
947 else |
|
948 soap->bufidx = soap->buflen; |
|
949 soap->buflen = soap->chunkbuflen; |
|
950 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk size (idx=%u len=%u)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen)); |
|
951 while (!soap_isxdigit((int)(c = soap_getchunkchar(soap)))) |
|
952 if ((int)c == EOF) |
|
953 return soap->ahead = EOF; |
|
954 do |
|
955 *t++ = (char)c; |
|
956 while (soap_isxdigit((int)(c = soap_getchunkchar(soap))) && t - tmp < 7); |
|
957 while ((int)c != EOF && c != '\n') |
|
958 c = soap_getchunkchar(soap); |
|
959 if ((int)c == EOF) |
|
960 return soap->ahead = EOF; |
|
961 *t = '\0'; |
|
962 soap->chunksize = soap_strtoul(tmp, &t, 16); |
|
963 if (!soap->chunksize) |
|
964 { soap->chunkbuflen = 0; |
|
965 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of chunked message\n")); |
|
966 while ((int)c != EOF && c != '\n') |
|
967 c = soap_getchunkchar(soap); |
|
968 return soap->ahead = EOF; |
|
969 } |
|
970 soap->buflen = soap->bufidx + soap->chunksize; |
|
971 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving buf len to idx=%u len=%u (%s)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen, tmp)); |
|
972 if (soap->buflen > soap->chunkbuflen) |
|
973 { soap->buflen = soap->chunkbuflen; |
|
974 soap->chunksize -= soap->buflen - soap->bufidx; |
|
975 soap->chunkbuflen = 0; |
|
976 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Passed end of buffer for chunked HTTP (%u bytes left)\n", (unsigned int)(soap->buflen - soap->bufidx))); |
|
977 } |
|
978 else if (soap->chunkbuflen) |
|
979 soap->chunksize = 0; |
|
980 ret = soap->buflen - soap->bufidx; |
|
981 if (!ret) |
|
982 goto chunk_again; |
|
983 } |
|
984 } |
|
985 else |
|
986 #endif |
|
987 { soap->bufidx = 0; |
|
988 soap->buflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN); |
|
989 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket %d\n", (unsigned int)ret, soap->socket)); |
|
990 DBGMSG(RECV, soap->buf, ret); |
|
991 } |
|
992 #ifndef WITH_LEANER |
|
993 if (soap->fpreparerecv && (soap->error = soap->fpreparerecv(soap, soap->buf, ret))) |
|
994 return soap->error; |
|
995 #endif |
|
996 #ifdef WITH_ZLIB |
|
997 if (soap->mode & SOAP_ENC_ZLIB) |
|
998 { register int r; |
|
999 memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); |
|
1000 soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx); |
|
1001 soap->d_stream.avail_in = (unsigned int)ret; |
|
1002 soap->d_stream.next_out = (Byte*)soap->buf; |
|
1003 soap->d_stream.avail_out = SOAP_BUFLEN; |
|
1004 r = inflate(&soap->d_stream, Z_NO_FLUSH); |
|
1005 if (r == Z_OK || r == Z_STREAM_END) |
|
1006 { soap->bufidx = 0; |
|
1007 soap->z_buflen = soap->buflen; |
|
1008 soap->buflen = ret = SOAP_BUFLEN - soap->d_stream.avail_out; |
|
1009 if (soap->zlib_in == SOAP_ZLIB_GZIP) |
|
1010 soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen); |
|
1011 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %u bytes\n", (unsigned int)ret)); |
|
1012 if (!ret) |
|
1013 goto zlib_again; |
|
1014 if (r == Z_STREAM_END) |
|
1015 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out)); |
|
1016 soap->z_ratio_in = (float)soap->d_stream.total_in / (float)soap->d_stream.total_out; |
|
1017 soap->d_stream.next_out = Z_NULL; |
|
1018 } |
|
1019 } |
|
1020 else |
|
1021 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to inflate: (%d) %s\n", r, soap->d_stream.msg?soap->d_stream.msg:"")); |
|
1022 soap->d_stream.next_out = Z_NULL; |
|
1023 soap->error = SOAP_ZLIB_ERROR; |
|
1024 return EOF; |
|
1025 } |
|
1026 } |
|
1027 #endif |
|
1028 soap->count += ret; |
|
1029 return !ret; |
|
1030 } |
|
1031 #endif |
|
1032 |
|
1033 /******************************************************************************/ |
|
1034 #ifndef PALM_1 |
|
1035 SOAP_FMAC1 |
|
1036 int |
|
1037 SOAP_FMAC2 |
|
1038 soap_recv(struct soap *soap) |
|
1039 { |
|
1040 #ifndef WITH_LEANER |
|
1041 if (soap->mode & SOAP_ENC_DIME) |
|
1042 { if (soap->dime.buflen) |
|
1043 { char *s; |
|
1044 int i; |
|
1045 unsigned char tmp[12]; |
|
1046 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME hdr for chunked DIME is in buffer\n")); |
|
1047 soap->count += soap->dime.buflen - soap->buflen; |
|
1048 soap->buflen = soap->dime.buflen; |
|
1049 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Skip padding (%ld bytes)\n", -(long)soap->dime.size&3)); |
|
1050 for (i = -(long)soap->dime.size&3; i > 0; i--) |
|
1051 { soap->bufidx++; |
|
1052 if (soap->bufidx >= soap->buflen) |
|
1053 if (soap_recv_raw(soap)) |
|
1054 return EOF; |
|
1055 } |
|
1056 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME hdr for next chunk\n")); |
|
1057 s = (char*)tmp; |
|
1058 for (i = 12; i > 0; i--) |
|
1059 { *s++ = soap->buf[soap->bufidx++]; |
|
1060 if (soap->bufidx >= soap->buflen) |
|
1061 if (soap_recv_raw(soap)) |
|
1062 return EOF; |
|
1063 } |
|
1064 soap->dime.flags = tmp[0] & 0x7; |
|
1065 soap->dime.size = ((size_t)tmp[8] << 24) | ((size_t)tmp[9] << 16) | ((size_t)tmp[10] << 8) | ((size_t)tmp[11]); |
|
1066 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME chunk (%u bytes)\n", (unsigned int)soap->dime.size)); |
|
1067 if (soap->dime.flags & SOAP_DIME_CF) |
|
1068 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "More chunking\n")); |
|
1069 soap->dime.chunksize = soap->dime.size; |
|
1070 if (soap->buflen - soap->bufidx >= soap->dime.size) |
|
1071 { soap->dime.buflen = soap->buflen; |
|
1072 soap->buflen = soap->bufidx + soap->dime.chunksize; |
|
1073 } |
|
1074 else |
|
1075 soap->dime.chunksize -= soap->buflen - soap->bufidx; |
|
1076 } |
|
1077 else |
|
1078 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Last chunk\n")); |
|
1079 soap->dime.buflen = 0; |
|
1080 soap->dime.chunksize = 0; |
|
1081 } |
|
1082 soap->count = soap->buflen - soap->bufidx; |
|
1083 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%u bytes remaining\n", (unsigned int)soap->count)); |
|
1084 return SOAP_OK; |
|
1085 } |
|
1086 if (soap->dime.chunksize) |
|
1087 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get next DIME hdr for chunked DIME (%u bytes chunk)\n", (unsigned int)soap->dime.chunksize)); |
|
1088 if (soap_recv_raw(soap)) |
|
1089 return EOF; |
|
1090 if (soap->buflen - soap->bufidx >= soap->dime.chunksize) |
|
1091 { soap->dime.buflen = soap->buflen; |
|
1092 soap->count -= soap->buflen - soap->bufidx - soap->dime.chunksize; |
|
1093 soap->buflen = soap->bufidx + soap->dime.chunksize; |
|
1094 } |
|
1095 else |
|
1096 soap->dime.chunksize -= soap->buflen - soap->bufidx; |
|
1097 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%lu bytes remaining, count=%u\n", (unsigned long)(soap->buflen-soap->bufidx), (unsigned int)soap->count)); |
|
1098 return SOAP_OK; |
|
1099 } |
|
1100 } |
|
1101 #endif |
|
1102 return soap_recv_raw(soap); |
|
1103 } |
|
1104 #endif |
|
1105 |
|
1106 /******************************************************************************/ |
|
1107 #ifndef PALM_1 |
|
1108 SOAP_FMAC1 |
|
1109 soap_wchar |
|
1110 SOAP_FMAC2 |
|
1111 soap_getchar(struct soap *soap) |
|
1112 { register soap_wchar c; |
|
1113 c = soap->ahead; |
|
1114 if (c) |
|
1115 { if (c != EOF) |
|
1116 soap->ahead = 0; |
|
1117 return c; |
|
1118 } |
|
1119 return soap_get1(soap); |
|
1120 } |
|
1121 #endif |
|
1122 |
|
1123 /******************************************************************************/ |
|
1124 #ifndef PALM_1 |
|
1125 SOAP_FMAC1 |
|
1126 const struct soap_code_map* |
|
1127 SOAP_FMAC2 |
|
1128 soap_code(const struct soap_code_map *map, const char *str) |
|
1129 { if (str) |
|
1130 { while (map->string) |
|
1131 { if (!strcmp(str, map->string)) /* case sensitive */ |
|
1132 return map; |
|
1133 map++; |
|
1134 } |
|
1135 } |
|
1136 return NULL; |
|
1137 } |
|
1138 #endif |
|
1139 |
|
1140 /******************************************************************************/ |
|
1141 #ifndef PALM_1 |
|
1142 SOAP_FMAC1 |
|
1143 long |
|
1144 SOAP_FMAC2 |
|
1145 soap_int_code(const struct soap_code_map *map, const char *str, long other) |
|
1146 { while (map->string) |
|
1147 { if (!soap_tag_cmp(str, map->string)) /* case insensitive */ |
|
1148 return map->code; |
|
1149 map++; |
|
1150 } |
|
1151 return other; |
|
1152 } |
|
1153 #endif |
|
1154 |
|
1155 /******************************************************************************/ |
|
1156 #ifndef PALM_1 |
|
1157 SOAP_FMAC1 |
|
1158 const char* |
|
1159 SOAP_FMAC2 |
|
1160 soap_str_code(const struct soap_code_map *map, long code) |
|
1161 { while (map->code != code && map->string) |
|
1162 map++; |
|
1163 return map->string; |
|
1164 } |
|
1165 #endif |
|
1166 |
|
1167 /******************************************************************************/ |
|
1168 #ifndef PALM_1 |
|
1169 static soap_wchar |
|
1170 soap_char(struct soap *soap) |
|
1171 { char tmp[8]; |
|
1172 register int i; |
|
1173 register soap_wchar c; |
|
1174 register char *s = tmp; |
|
1175 for (i = 0; i < 7; i++) |
|
1176 { c = soap_get1(soap); |
|
1177 if (c == ';' || (int)c == EOF) |
|
1178 break; |
|
1179 *s++ = (char)c; |
|
1180 } |
|
1181 *s = '\0'; |
|
1182 if (*tmp == '#') |
|
1183 { if (tmp[1] == 'x' || tmp[1] == 'X') |
|
1184 return soap_strtol(tmp + 2, NULL, 16); |
|
1185 return atol(tmp + 1); |
|
1186 } |
|
1187 if (!strcmp(tmp, "lt")) |
|
1188 return '<'; |
|
1189 if (!strcmp(tmp, "gt")) |
|
1190 return '>'; |
|
1191 if (!strcmp(tmp, "amp")) |
|
1192 return '&'; |
|
1193 if (!strcmp(tmp, "quot")) |
|
1194 return '"'; |
|
1195 if (!strcmp(tmp, "apos")) |
|
1196 return '\''; |
|
1197 #ifndef WITH_LEAN |
|
1198 return (soap_wchar)soap_int_code(html_entity_codes, tmp, SOAP_UNKNOWN_CHAR); |
|
1199 #else |
|
1200 return SOAP_UNKNOWN_CHAR; /* use this to represent unknown code */ |
|
1201 #endif |
|
1202 } |
|
1203 #endif |
|
1204 |
|
1205 /******************************************************************************/ |
|
1206 #ifdef WITH_LEAN |
|
1207 soap_wchar |
|
1208 soap_get0(struct soap *soap) |
|
1209 { if (soap->bufidx >= soap->buflen && soap_recv(soap)) |
|
1210 return EOF; |
|
1211 return (unsigned char)soap->buf[soap->bufidx]; |
|
1212 } |
|
1213 #endif |
|
1214 |
|
1215 /******************************************************************************/ |
|
1216 #ifdef WITH_LEAN |
|
1217 soap_wchar |
|
1218 soap_get1(struct soap *soap) |
|
1219 { if (soap->bufidx >= soap->buflen && soap_recv(soap)) |
|
1220 return EOF; |
|
1221 return (unsigned char)soap->buf[soap->bufidx++]; |
|
1222 } |
|
1223 #endif |
|
1224 |
|
1225 /******************************************************************************/ |
|
1226 #ifndef PALM_1 |
|
1227 SOAP_FMAC1 |
|
1228 soap_wchar |
|
1229 SOAP_FMAC2 |
|
1230 soap_get(struct soap *soap) |
|
1231 { register soap_wchar c; |
|
1232 c = soap->ahead; |
|
1233 if (c) |
|
1234 { if (c != EOF) |
|
1235 soap->ahead = 0; |
|
1236 } |
|
1237 else |
|
1238 c = soap_get1(soap); |
|
1239 for (;;) |
|
1240 { if (soap->cdata) |
|
1241 { if (c == ']') |
|
1242 { c = soap_get1(soap); |
|
1243 if (c == ']') |
|
1244 { soap->cdata = 0; |
|
1245 soap_get1(soap); /* skip > */ |
|
1246 c = soap_get1(soap); |
|
1247 } |
|
1248 else |
|
1249 { soap_revget1(soap); |
|
1250 return ']'; |
|
1251 } |
|
1252 } |
|
1253 else |
|
1254 return c; |
|
1255 } |
|
1256 switch (c) |
|
1257 { case '<': |
|
1258 do c = soap_get1(soap); |
|
1259 while (soap_blank(c)); |
|
1260 if (c == '!' || c == '?' || c == '%') |
|
1261 { register int k = 1; |
|
1262 if (c == '!') |
|
1263 { c = soap_get1(soap); |
|
1264 if (c == '[') |
|
1265 { do c = soap_get1(soap); |
|
1266 while ((int)c != EOF && c != '['); |
|
1267 if ((int)c == EOF) |
|
1268 break; |
|
1269 soap->cdata = 1; |
|
1270 c = soap_get1(soap); |
|
1271 continue; |
|
1272 } |
|
1273 if (c == '-' && (c = soap_get1(soap)) == '-') |
|
1274 { do |
|
1275 { c = soap_get1(soap); |
|
1276 if (c == '-' && (c = soap_get1(soap)) == '-') |
|
1277 break; |
|
1278 } while ((int)c != EOF); |
|
1279 } |
|
1280 } |
|
1281 while ((int)c != EOF) |
|
1282 { if (c == '<') |
|
1283 k++; |
|
1284 else if (c == '>') |
|
1285 { if (--k <= 0) |
|
1286 break; |
|
1287 } |
|
1288 c = soap_get1(soap); |
|
1289 } |
|
1290 if ((int)c == EOF) |
|
1291 break; |
|
1292 c = soap_get1(soap); |
|
1293 continue; |
|
1294 } |
|
1295 if (c == '/') |
|
1296 return SOAP_TT; |
|
1297 soap_revget1(soap); |
|
1298 return SOAP_LT; |
|
1299 case '>': |
|
1300 return SOAP_GT; |
|
1301 case '"': |
|
1302 return SOAP_QT; |
|
1303 case '\'': |
|
1304 return SOAP_AP; |
|
1305 case '&': |
|
1306 return soap_char(soap) | 0x80000000; |
|
1307 } |
|
1308 break; |
|
1309 } |
|
1310 return c; |
|
1311 } |
|
1312 #endif |
|
1313 |
|
1314 /******************************************************************************/ |
|
1315 #ifndef WITH_LEANER |
|
1316 #ifndef PALM_1 |
|
1317 SOAP_FMAC1 |
|
1318 int |
|
1319 SOAP_FMAC2 |
|
1320 soap_move(struct soap *soap, long n) |
|
1321 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving %ld bytes forward\n", (long)n)); |
|
1322 for (; n > 0; n--) |
|
1323 if ((int)soap_getchar(soap) == EOF) |
|
1324 return SOAP_EOF; |
|
1325 return SOAP_OK; |
|
1326 } |
|
1327 #endif |
|
1328 #endif |
|
1329 |
|
1330 /******************************************************************************/ |
|
1331 #ifndef WITH_LEANER |
|
1332 #ifndef PALM_1 |
|
1333 SOAP_FMAC1 |
|
1334 size_t |
|
1335 SOAP_FMAC2 |
|
1336 soap_tell(struct soap *soap) |
|
1337 { return soap->count - soap->buflen + soap->bufidx - (soap->ahead != 0); |
|
1338 } |
|
1339 #endif |
|
1340 #endif |
|
1341 |
|
1342 /******************************************************************************/ |
|
1343 #ifndef PALM_1 |
|
1344 SOAP_FMAC1 |
|
1345 int |
|
1346 SOAP_FMAC2 |
|
1347 soap_pututf8(struct soap *soap, register unsigned long c) |
|
1348 { char tmp[16]; |
|
1349 if (c > 0 && c < 0x80) |
|
1350 { *tmp = (char)c; |
|
1351 return soap_send_raw(soap, tmp, 1); |
|
1352 } |
|
1353 #ifndef WITH_LEAN |
|
1354 if (soap->mode & SOAP_XML_CANONICAL) |
|
1355 { register char *t = tmp; |
|
1356 if (c < 0x0800) |
|
1357 *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); |
|
1358 else |
|
1359 { if (c < 0x010000) |
|
1360 *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); |
|
1361 else |
|
1362 { if (c < 0x200000) |
|
1363 *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); |
|
1364 else |
|
1365 { if (c < 0x04000000) |
|
1366 *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); |
|
1367 else |
|
1368 { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); |
|
1369 *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); |
|
1370 } |
|
1371 *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); |
|
1372 } |
|
1373 *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); |
|
1374 } |
|
1375 *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); |
|
1376 } |
|
1377 *t++ = (char)(0x80 | (c & 0x3F)); |
|
1378 *t = '\0'; |
|
1379 } |
|
1380 else |
|
1381 #endif |
|
1382 sprintf(tmp, "&#%lu;", c); |
|
1383 return soap_send(soap, tmp); |
|
1384 } |
|
1385 #endif |
|
1386 |
|
1387 /******************************************************************************/ |
|
1388 #ifndef PALM_1 |
|
1389 SOAP_FMAC1 |
|
1390 soap_wchar |
|
1391 SOAP_FMAC2 |
|
1392 soap_getutf8(struct soap *soap) |
|
1393 { register soap_wchar c, c1, c2, c3, c4; |
|
1394 c = soap_get(soap); |
|
1395 if (c < 0x80 || (soap->mode & SOAP_ENC_LATIN)) |
|
1396 return c; |
|
1397 c1 = soap_get(soap); |
|
1398 if (c1 < 0x80) |
|
1399 { soap_unget(soap, c1); |
|
1400 return c; |
|
1401 } |
|
1402 c1 &= 0x3F; |
|
1403 if (c < 0xE0) |
|
1404 return ((soap_wchar)(c & 0x1F) << 6) | c1; |
|
1405 c2 = (soap_wchar)soap_get1(soap) & 0x3F; |
|
1406 if (c < 0xF0) |
|
1407 return ((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2; |
|
1408 c3 = (soap_wchar)soap_get1(soap) & 0x3F; |
|
1409 if (c < 0xF8) |
|
1410 return ((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3; |
|
1411 c4 = (soap_wchar)soap_get1(soap) & 0x3F; |
|
1412 if (c < 0xFC) |
|
1413 return ((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4; |
|
1414 return ((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(soap_get1(soap) & 0x3F); |
|
1415 } |
|
1416 #endif |
|
1417 |
|
1418 /******************************************************************************/ |
|
1419 #ifndef PALM_1 |
|
1420 SOAP_FMAC1 |
|
1421 int |
|
1422 SOAP_FMAC2 |
|
1423 soap_puthex(struct soap *soap, const unsigned char *s, int n) |
|
1424 { char d[2]; |
|
1425 register int i; |
|
1426 #ifdef WITH_DOM |
|
1427 if ((soap->mode & SOAP_XML_DOM) && soap->dom) |
|
1428 { if (!(soap->dom->data = soap_s2hex(soap, s, NULL, n))) |
|
1429 return soap->error; |
|
1430 return SOAP_OK; |
|
1431 } |
|
1432 #endif |
|
1433 for (i = 0; i < n; i++) |
|
1434 { register int m = *s++; |
|
1435 d[0] = (char)((m >> 4) + (m > 159 ? '7' : '0')); |
|
1436 m &= 0x0F; |
|
1437 d[1] = (char)(m + (m > 9 ? '7' : '0')); |
|
1438 if (soap_send_raw(soap, d, 2)) |
|
1439 return soap->error; |
|
1440 } |
|
1441 return SOAP_OK; |
|
1442 } |
|
1443 #endif |
|
1444 |
|
1445 /******************************************************************************/ |
|
1446 #ifndef PALM_1 |
|
1447 SOAP_FMAC1 |
|
1448 unsigned char* |
|
1449 SOAP_FMAC2 |
|
1450 soap_gethex(struct soap *soap, int *n) |
|
1451 { |
|
1452 #ifdef WITH_DOM |
|
1453 if ((soap->mode & SOAP_XML_DOM) && soap->dom) |
|
1454 { soap->dom->data = soap_string_in(soap, 0, -1, -1); |
|
1455 return (unsigned char*)soap_hex2s(soap, soap->dom->data, NULL, 0, n); |
|
1456 } |
|
1457 #endif |
|
1458 #ifdef WITH_FAST |
|
1459 soap->labidx = 0; |
|
1460 for (;;) |
|
1461 { register char *s; |
|
1462 register int i, k; |
|
1463 if (soap_append_lab(soap, NULL, 0)) |
|
1464 return NULL; |
|
1465 s = soap->labbuf + soap->labidx; |
|
1466 k = soap->lablen - soap->labidx; |
|
1467 soap->labidx = soap->lablen; |
|
1468 for (i = 0; i < k; i++) |
|
1469 { register char d1, d2; |
|
1470 register soap_wchar c; |
|
1471 c = soap_get(soap); |
|
1472 if (soap_isxdigit(c)) |
|
1473 { d1 = (char)c; |
|
1474 c = soap_get(soap); |
|
1475 if (soap_isxdigit(c)) |
|
1476 d2 = (char)c; |
|
1477 else |
|
1478 { soap->error = SOAP_TYPE; |
|
1479 return NULL; |
|
1480 } |
|
1481 } |
|
1482 else |
|
1483 { unsigned char *p; |
|
1484 soap_unget(soap, c); |
|
1485 if (n) |
|
1486 *n = (int)(soap->lablen - k + i); |
|
1487 p = (unsigned char*)soap_malloc(soap, soap->lablen - k + i); |
|
1488 if (p) |
|
1489 memcpy(p, soap->labbuf, soap->lablen - k + i); |
|
1490 return p; |
|
1491 } |
|
1492 *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'); |
|
1493 } |
|
1494 } |
|
1495 #else |
|
1496 if (soap_new_block(soap)) |
|
1497 return NULL; |
|
1498 for (;;) |
|
1499 { register int i; |
|
1500 register char *s = (char*)soap_push_block(soap, SOAP_BLKLEN); |
|
1501 if (!s) |
|
1502 { soap_end_block(soap); |
|
1503 return NULL; |
|
1504 } |
|
1505 for (i = 0; i < SOAP_BLKLEN; i++) |
|
1506 { register char d1, d2; |
|
1507 register soap_wchar c = soap_get(soap); |
|
1508 if (soap_isxdigit(c)) |
|
1509 { d1 = (char)c; |
|
1510 c = soap_get(soap); |
|
1511 if (soap_isxdigit(c)) |
|
1512 d2 = (char)c; |
|
1513 else |
|
1514 { soap_end_block(soap); |
|
1515 soap->error = SOAP_TYPE; |
|
1516 return NULL; |
|
1517 } |
|
1518 } |
|
1519 else |
|
1520 { unsigned char *p; |
|
1521 soap_unget(soap, c); |
|
1522 if (n) |
|
1523 *n = soap_size_block(soap, i); |
|
1524 p = (unsigned char*)soap_save_block(soap, NULL, 0); |
|
1525 return p; |
|
1526 } |
|
1527 *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'); |
|
1528 } |
|
1529 } |
|
1530 #endif |
|
1531 } |
|
1532 #endif |
|
1533 |
|
1534 /******************************************************************************/ |
|
1535 #ifndef PALM_1 |
|
1536 SOAP_FMAC1 |
|
1537 int |
|
1538 SOAP_FMAC2 |
|
1539 soap_putbase64(struct soap *soap, const unsigned char *s, int n) |
|
1540 { register int i; |
|
1541 register unsigned long m; |
|
1542 char d[4]; |
|
1543 if (!s) |
|
1544 return SOAP_OK; |
|
1545 #ifdef WITH_DOM |
|
1546 if ((soap->mode & SOAP_XML_DOM) && soap->dom) |
|
1547 { if (!(soap->dom->data = soap_s2base64(soap, s, NULL, n))) |
|
1548 return soap->error; |
|
1549 return SOAP_OK; |
|
1550 } |
|
1551 #endif |
|
1552 for (; n > 2; n -= 3, s += 3) |
|
1553 { m = s[0]; |
|
1554 m = (m << 8) | s[1]; |
|
1555 m = (m << 8) | s[2]; |
|
1556 for (i = 4; i > 0; m >>= 6) |
|
1557 d[--i] = soap_base64o[m & 0x3F]; |
|
1558 if (soap_send_raw(soap, d, 4)) |
|
1559 return soap->error; |
|
1560 } |
|
1561 if (n > 0) |
|
1562 { m = 0; |
|
1563 for (i = 0; i < n; i++) |
|
1564 m = (m << 8) | *s++; |
|
1565 for (; i < 3; i++) |
|
1566 m <<= 8; |
|
1567 for (i++; i > 0; m >>= 6) |
|
1568 d[--i] = soap_base64o[m & 0x3F]; |
|
1569 for (i = 3; i > n; i--) |
|
1570 d[i] = '='; |
|
1571 if (soap_send_raw(soap, d, 4)) |
|
1572 return soap->error; |
|
1573 } |
|
1574 return SOAP_OK; |
|
1575 } |
|
1576 #endif |
|
1577 |
|
1578 /******************************************************************************/ |
|
1579 #ifndef PALM_1 |
|
1580 SOAP_FMAC1 |
|
1581 unsigned char* |
|
1582 SOAP_FMAC2 |
|
1583 soap_getbase64(struct soap *soap, int *n, int malloc_flag) |
|
1584 { |
|
1585 #ifdef WITH_DOM |
|
1586 if ((soap->mode & SOAP_XML_DOM) && soap->dom) |
|
1587 { soap->dom->data = soap_string_in(soap, 0, -1, -1); |
|
1588 return (unsigned char*)soap_base642s(soap, soap->dom->data, NULL, 0, n); |
|
1589 } |
|
1590 #endif |
|
1591 #ifdef WITH_FAST |
|
1592 soap->labidx = 0; |
|
1593 for (;;) |
|
1594 { register int i, k; |
|
1595 register char *s; |
|
1596 if (soap_append_lab(soap, NULL, 2)) |
|
1597 return NULL; |
|
1598 s = soap->labbuf + soap->labidx; |
|
1599 k = 3 * ((soap->lablen - soap->labidx) / 3); |
|
1600 soap->labidx = 3 * (soap->lablen / 3); |
|
1601 if (!s) |
|
1602 return NULL; |
|
1603 for (i = 0; i < k; i += 3) |
|
1604 { register unsigned long m = 0; |
|
1605 register int j = 0; |
|
1606 do |
|
1607 { register soap_wchar c = soap_get(soap); |
|
1608 if (c == '=' || c < 0) |
|
1609 { unsigned char *p; |
|
1610 switch (j) |
|
1611 { case 2: |
|
1612 *s++ = (char)((m >> 4) & 0xFF); |
|
1613 i++; |
|
1614 break; |
|
1615 case 3: |
|
1616 *s++ = (char)((m >> 10) & 0xFF); |
|
1617 *s++ = (char)((m >> 2) & 0xFF); |
|
1618 i += 2; |
|
1619 } |
|
1620 if (n) |
|
1621 *n = (int)(soap->lablen - k + i - 1); |
|
1622 p = (unsigned char*)soap_malloc(soap, soap->lablen - k + i - 1); |
|
1623 if (p) |
|
1624 memcpy(p, soap->labbuf, soap->lablen - k + i - 1); |
|
1625 if (c >= 0) |
|
1626 { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT) |
|
1627 ; |
|
1628 } |
|
1629 soap_unget(soap, c); |
|
1630 return p; |
|
1631 } |
|
1632 c -= '+'; |
|
1633 if (c >= 0 && c <= 79) |
|
1634 { m = (m << 6) + soap_base64i[c]; |
|
1635 j++; |
|
1636 } |
|
1637 } while (j < 4); |
|
1638 *s++ = (char)((m >> 16) & 0xFF); |
|
1639 *s++ = (char)((m >> 8) & 0xFF); |
|
1640 *s++ = (char)(m & 0xFF); |
|
1641 } |
|
1642 } |
|
1643 #else |
|
1644 if (soap_new_block(soap)) |
|
1645 return NULL; |
|
1646 for (;;) |
|
1647 { register int i; |
|
1648 register char *s = (char*)soap_push_block(soap, 3 * SOAP_BLKLEN); /* must be multiple of 3 */ |
|
1649 if (!s) |
|
1650 { soap_end_block(soap); |
|
1651 return NULL; |
|
1652 } |
|
1653 for (i = 0; i < SOAP_BLKLEN; i++) |
|
1654 { register unsigned long m = 0; |
|
1655 register int j = 0; |
|
1656 do |
|
1657 { register soap_wchar c = soap_get(soap); |
|
1658 if (c == '=' || c < 0) |
|
1659 { unsigned char *p; |
|
1660 i *= 3; |
|
1661 switch (j) |
|
1662 { case 2: |
|
1663 *s++ = (char)((m >> 4) & 0xFF); |
|
1664 i++; |
|
1665 break; |
|
1666 case 3: |
|
1667 *s++ = (char)((m >> 10) & 0xFF); |
|
1668 *s++ = (char)((m >> 2) & 0xFF); |
|
1669 i += 2; |
|
1670 } |
|
1671 if (n) |
|
1672 *n = (int)soap_size_block(soap, i); |
|
1673 p = (unsigned char*)soap_save_block(soap, NULL, 0); |
|
1674 if (c >= 0) |
|
1675 { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT) |
|
1676 ; |
|
1677 } |
|
1678 soap_unget(soap, c); |
|
1679 return p; |
|
1680 } |
|
1681 c -= '+'; |
|
1682 if (c >= 0 && c <= 79) |
|
1683 { m = (m << 6) + soap_base64i[c]; |
|
1684 j++; |
|
1685 } |
|
1686 } while (j < 4); |
|
1687 *s++ = (char)((m >> 16) & 0xFF); |
|
1688 *s++ = (char)((m >> 8) & 0xFF); |
|
1689 *s++ = (char)(m & 0xFF); |
|
1690 } |
|
1691 } |
|
1692 #endif |
|
1693 } |
|
1694 #endif |
|
1695 |
|
1696 /******************************************************************************/ |
|
1697 #ifndef WITH_LEANER |
|
1698 #ifndef PALM_1 |
|
1699 SOAP_FMAC1 |
|
1700 int |
|
1701 SOAP_FMAC2 |
|
1702 soap_xop_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options) |
|
1703 { /* Check MTOM xop:Include element (within hex/base64Binary) */ |
|
1704 /* TODO: this code to be obsoleted with new import/xop.h conventions */ |
|
1705 int body = soap->body; /* should save type too? */ |
|
1706 if (!soap_peek_element(soap)) |
|
1707 { if (!soap_element_begin_in(soap, "xop:Include", 0) && *soap->href) |
|
1708 { if (soap_dime_forward(soap, ptr, size, id, type, options)) |
|
1709 return soap->error; |
|
1710 } |
|
1711 if (soap->body && soap_element_end_in(soap, NULL)) |
|
1712 return soap->error; |
|
1713 } |
|
1714 soap->body = body; |
|
1715 return SOAP_OK; |
|
1716 } |
|
1717 #endif |
|
1718 #endif |
|
1719 |
|
1720 /******************************************************************************/ |
|
1721 #ifndef WITH_LEANER |
|
1722 #ifndef PALM_1 |
|
1723 SOAP_FMAC1 |
|
1724 int |
|
1725 SOAP_FMAC2 |
|
1726 soap_dime_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options) |
|
1727 { struct soap_xlist *xp = (struct soap_xlist*)SOAP_MALLOC(soap, sizeof(struct soap_xlist)); |
|
1728 *ptr = NULL; |
|
1729 *size = 0; |
|
1730 *id = soap_strdup(soap, soap->href); |
|
1731 *type = NULL; |
|
1732 *options = NULL; |
|
1733 if (!xp) |
|
1734 return soap->error = SOAP_EOM; |
|
1735 xp->next = soap->xlist; |
|
1736 xp->ptr = ptr; |
|
1737 xp->size = size; |
|
1738 xp->id = *id; |
|
1739 xp->type = type; |
|
1740 xp->options = options; |
|
1741 soap->xlist = xp; |
|
1742 return SOAP_OK; |
|
1743 } |
|
1744 #endif |
|
1745 #endif |
|
1746 |
|
1747 /******************************************************************************/ |
|
1748 #ifndef PALM_1 |
|
1749 SOAP_FMAC1 |
|
1750 char * |
|
1751 SOAP_FMAC2 |
|
1752 soap_strdup(struct soap *soap, const char *s) |
|
1753 { char *t = NULL; |
|
1754 if (s && (t = (char*)soap_malloc(soap, strlen(s) + 1))) |
|
1755 strcpy(t, s); |
|
1756 return t; |
|
1757 } |
|
1758 #endif |
|
1759 |
|
1760 /******************************************************************************/ |
|
1761 #ifndef PALM_1 |
|
1762 SOAP_FMAC1 |
|
1763 int |
|
1764 SOAP_FMAC2 |
|
1765 soap_new_block(struct soap *soap) |
|
1766 { struct soap_blist *p; |
|
1767 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New block sequence (prev=%p)\n", soap->blist)); |
|
1768 if (!(p = (struct soap_blist*)SOAP_MALLOC(soap, sizeof(struct soap_blist)))) |
|
1769 return SOAP_EOM; |
|
1770 p->next = soap->blist; |
|
1771 p->ptr = NULL; |
|
1772 p->size = 0; |
|
1773 soap->blist = p; |
|
1774 return SOAP_OK; |
|
1775 } |
|
1776 #endif |
|
1777 |
|
1778 /******************************************************************************/ |
|
1779 #ifndef PALM_1 |
|
1780 SOAP_FMAC1 |
|
1781 void* |
|
1782 SOAP_FMAC2 |
|
1783 soap_push_block(struct soap *soap, size_t n) |
|
1784 { char *p; |
|
1785 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push block of %u bytes (%u bytes total)\n", (unsigned int)n, (unsigned int)soap->blist->size + (unsigned int)n)); |
|
1786 if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(char*) + sizeof(size_t)))) |
|
1787 { soap->error = SOAP_EOM; |
|
1788 return NULL; |
|
1789 } |
|
1790 *(char**)p = soap->blist->ptr; |
|
1791 *(size_t*)(p + sizeof(char*)) = n; |
|
1792 soap->blist->ptr = p; |
|
1793 soap->blist->size += n; |
|
1794 return p + sizeof(char*) + sizeof(size_t); |
|
1795 } |
|
1796 #endif |
|
1797 |
|
1798 /******************************************************************************/ |
|
1799 #ifndef PALM_1 |
|
1800 SOAP_FMAC1 |
|
1801 void |
|
1802 SOAP_FMAC2 |
|
1803 soap_pop_block(struct soap *soap) |
|
1804 { char *p; |
|
1805 if (!soap->blist->ptr) |
|
1806 return; |
|
1807 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop block\n")); |
|
1808 p = soap->blist->ptr; |
|
1809 soap->blist->size -= *(size_t*)(p + sizeof(char*)); |
|
1810 soap->blist->ptr = *(char**)p; |
|
1811 SOAP_FREE(soap, p); |
|
1812 } |
|
1813 #endif |
|
1814 |
|
1815 /******************************************************************************/ |
|
1816 #ifndef WITH_NOIDREF |
|
1817 #ifndef PALM_1 |
|
1818 static void |
|
1819 soap_update_ptrs(struct soap *soap, char *start, char *end, long offset) |
|
1820 { int i; |
|
1821 register struct soap_ilist *ip; |
|
1822 register struct soap_flist *fp; |
|
1823 #ifndef WITH_LEANER |
|
1824 register struct soap_xlist *xp; |
|
1825 #endif |
|
1826 register void *p, **q; |
|
1827 for (i = 0; i < SOAP_IDHASH; i++) |
|
1828 { for (ip = soap->iht[i]; ip; ip = ip->next) |
|
1829 { if (ip->ptr && (char*)ip->ptr >= start && (char*)ip->ptr < end) |
|
1830 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", ip->id, ip->ptr, (char*)ip->ptr + offset)); |
|
1831 ip->ptr = (char*)ip->ptr + offset; |
|
1832 } |
|
1833 for (q = &ip->link; q; q = (void**)p) |
|
1834 { p = *q; |
|
1835 if (p && (char*)p >= start && (char*)p < end) |
|
1836 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Link update id='%s' %p\n", ip->id, p)); |
|
1837 *q = (char*)p + offset; |
|
1838 } |
|
1839 } |
|
1840 for (q = &ip->copy; q; q = (void**)p) |
|
1841 { p = *q; |
|
1842 if (p && (char*)p >= start && (char*)p < end) |
|
1843 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy chain update id='%s' %p\n", ip->id, p)); |
|
1844 *q = (char*)p + offset; |
|
1845 } |
|
1846 } |
|
1847 for (fp = ip->flist; fp; fp = fp->next) |
|
1848 { if ((char*)fp->ptr >= start && (char*)fp->ptr < end) |
|
1849 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy list update id='%s' %p\n", ip->id, fp)); |
|
1850 fp->ptr = (char*)fp->ptr + offset; |
|
1851 } |
|
1852 } |
|
1853 } |
|
1854 } |
|
1855 #ifndef WITH_LEANER |
|
1856 for (xp = soap->xlist; xp; xp = xp->next) |
|
1857 { if (xp->ptr && (char*)xp->ptr >= start && (char*)xp->ptr < end) |
|
1858 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", xp->id?xp->id:"", xp->ptr, (char*)xp->ptr + offset)); |
|
1859 xp->ptr = (unsigned char**)((char*)xp->ptr + offset); |
|
1860 xp->size = (int*)((char*)xp->size + offset); |
|
1861 xp->type = (char**)((char*)xp->type + offset); |
|
1862 xp->options = (char**)((char*)xp->options + offset); |
|
1863 } |
|
1864 } |
|
1865 #endif |
|
1866 } |
|
1867 #endif |
|
1868 #endif |
|
1869 |
|
1870 /******************************************************************************/ |
|
1871 #ifndef WITH_NOIDREF |
|
1872 #ifndef PALM_1 |
|
1873 static int |
|
1874 soap_has_copies(struct soap *soap, register const char *start, register const char *end) |
|
1875 { register int i; |
|
1876 register struct soap_ilist *ip; |
|
1877 register struct soap_flist *fp; |
|
1878 register const char *p; |
|
1879 for (i = 0; i < SOAP_IDHASH; i++) |
|
1880 { for (ip = soap->iht[i]; ip; ip = ip->next) |
|
1881 { for (p = (const char*)ip->copy; p; p = *(const char**)p) |
|
1882 if (p >= start && p < end) |
|
1883 return SOAP_ERR; |
|
1884 for (fp = ip->flist; fp; fp = fp->next) |
|
1885 if ((const char*)fp->ptr >= start && (const char*)fp->ptr < end) |
|
1886 return SOAP_ERR; |
|
1887 } |
|
1888 } |
|
1889 return SOAP_OK; |
|
1890 } |
|
1891 #endif |
|
1892 #endif |
|
1893 |
|
1894 /******************************************************************************/ |
|
1895 #ifndef WITH_NOIDREF |
|
1896 #ifndef PALM_1 |
|
1897 SOAP_FMAC1 |
|
1898 int |
|
1899 SOAP_FMAC2 |
|
1900 soap_resolve(struct soap *soap) |
|
1901 { register int i; |
|
1902 register struct soap_ilist *ip; |
|
1903 register struct soap_flist *fp; |
|
1904 short flag; |
|
1905 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data\n")); |
|
1906 for (i = 0; i < SOAP_IDHASH; i++) |
|
1907 { for (ip = soap->iht[i]; ip; ip = ip->next) |
|
1908 { if (ip->ptr) |
|
1909 { register void *p, **q, *r; |
|
1910 q = (void**)ip->link; |
|
1911 ip->link = NULL; |
|
1912 r = ip->ptr; |
|
1913 DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing link chain to resolve id='%s'\n", ip->id)); |
|
1914 while (q) |
|
1915 { p = *q; |
|
1916 *q = r; |
|
1917 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "... link %p -> %p\n", q, r)); |
|
1918 q = (void**)p; |
|
1919 } |
|
1920 } |
|
1921 else if (*ip->id == '#') |
|
1922 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Missing data for id='%s'\n", ip->id)); |
|
1923 strcpy(soap->id, ip->id + 1); |
|
1924 return soap->error = SOAP_MISSING_ID; |
|
1925 } |
|
1926 } |
|
1927 } |
|
1928 do |
|
1929 { flag = 0; |
|
1930 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution phase\n")); |
|
1931 for (i = 0; i < SOAP_IDHASH; i++) |
|
1932 { for (ip = soap->iht[i]; ip; ip = ip->next) |
|
1933 { if (ip->ptr && !soap_has_copies(soap, (const char*)ip->ptr, (const char*)ip->ptr + ip->size)) |
|
1934 { if (ip->copy) |
|
1935 { register void *p, **q = (void**)ip->copy; |
|
1936 DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing copy chain to resolve id='%s'\n", ip->id)); |
|
1937 ip->copy = NULL; |
|
1938 do |
|
1939 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... copy %p -> %p (%u bytes)\n", ip->ptr, q, (unsigned int)ip->size)); |
|
1940 p = *q; |
|
1941 memcpy(q, ip->ptr, ip->size); |
|
1942 q = (void**)p; |
|
1943 } while (q); |
|
1944 flag = 1; |
|
1945 } |
|
1946 for (fp = ip->flist; fp; fp = ip->flist) |
|
1947 { register unsigned int k = fp->level; |
|
1948 register void *p = ip->ptr; |
|
1949 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)); |
|
1950 while (ip->level < k) |
|
1951 { register void **q = (void**)soap_malloc(soap, sizeof(void*)); |
|
1952 if (!q) |
|
1953 return soap->error; |
|
1954 *q = p; |
|
1955 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level, new location=%p holds=%p...\n", q, *q)); |
|
1956 p = (void*)q; |
|
1957 k--; |
|
1958 } |
|
1959 if (fp->fcopy) |
|
1960 fp->fcopy(soap, ip->type, fp->type, fp->ptr, p, ip->size); |
|
1961 else |
|
1962 soap_fcopy(soap, ip->type, fp->type, fp->ptr, p, ip->size); |
|
1963 ip->flist = fp->next; |
|
1964 SOAP_FREE(soap, fp); |
|
1965 flag = 1; |
|
1966 } |
|
1967 } |
|
1968 } |
|
1969 } |
|
1970 } while (flag); |
|
1971 #ifdef SOAP_DEBUG |
|
1972 for (i = 0; i < SOAP_IDHASH; i++) |
|
1973 { for (ip = soap->iht[i]; ip; ip = ip->next) |
|
1974 { if (ip->copy || ip->flist) |
|
1975 { 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)); |
|
1976 } |
|
1977 } |
|
1978 } |
|
1979 #endif |
|
1980 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution done\n")); |
|
1981 return SOAP_OK; |
|
1982 } |
|
1983 #endif |
|
1984 #endif |
|
1985 |
|
1986 /******************************************************************************/ |
|
1987 #ifndef PALM_1 |
|
1988 SOAP_FMAC1 |
|
1989 size_t |
|
1990 SOAP_FMAC2 |
|
1991 soap_size_block(struct soap *soap, size_t n) |
|
1992 { if (soap->blist->ptr) |
|
1993 { soap->blist->size -= *(size_t*)(soap->blist->ptr + sizeof(char*)) - n; |
|
1994 *(size_t*)(soap->blist->ptr + sizeof(char*)) = n; |
|
1995 } |
|
1996 return soap->blist->size; |
|
1997 } |
|
1998 #endif |
|
1999 |
|
2000 /******************************************************************************/ |
|
2001 #ifndef PALM_1 |
|
2002 SOAP_FMAC1 |
|
2003 char* |
|
2004 SOAP_FMAC2 |
|
2005 soap_first_block(struct soap *soap) |
|
2006 { char *p, *q, *r; |
|
2007 p = soap->blist->ptr; |
|
2008 if (!p) |
|
2009 return NULL; |
|
2010 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "First block\n")); |
|
2011 r = NULL; |
|
2012 do |
|
2013 { q = *(char**)p; |
|
2014 *(char**)p = r; |
|
2015 r = p; |
|
2016 p = q; |
|
2017 } while (p); |
|
2018 soap->blist->ptr = r; |
|
2019 return r + sizeof(char*) + sizeof(size_t); |
|
2020 } |
|
2021 #endif |
|
2022 |
|
2023 /******************************************************************************/ |
|
2024 #ifndef PALM_1 |
|
2025 SOAP_FMAC1 |
|
2026 char* |
|
2027 SOAP_FMAC2 |
|
2028 soap_next_block(struct soap *soap) |
|
2029 { char *p; |
|
2030 p = soap->blist->ptr; |
|
2031 if (p) |
|
2032 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Next block\n")); |
|
2033 soap->blist->ptr = *(char**)p; |
|
2034 SOAP_FREE(soap, p); |
|
2035 if (soap->blist->ptr) |
|
2036 return soap->blist->ptr + sizeof(char*) + sizeof(size_t); |
|
2037 } |
|
2038 return NULL; |
|
2039 } |
|
2040 #endif |
|
2041 |
|
2042 /******************************************************************************/ |
|
2043 #ifndef PALM_1 |
|
2044 SOAP_FMAC1 |
|
2045 size_t |
|
2046 SOAP_FMAC2 |
|
2047 soap_block_size(struct soap *soap) |
|
2048 { return *(size_t*)(soap->blist->ptr + sizeof(char*)); |
|
2049 } |
|
2050 #endif |
|
2051 |
|
2052 /******************************************************************************/ |
|
2053 #ifndef PALM_1 |
|
2054 SOAP_FMAC1 |
|
2055 void |
|
2056 SOAP_FMAC2 |
|
2057 soap_end_block(struct soap *soap) |
|
2058 { struct soap_blist *bp; |
|
2059 char *p, *q; |
|
2060 bp = soap->blist; |
|
2061 if (bp) |
|
2062 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of block sequence, free all remaining blocks\n")); |
|
2063 for (p = bp->ptr; p; p = q) |
|
2064 { q = *(char**)p; |
|
2065 SOAP_FREE(soap, p); |
|
2066 } |
|
2067 soap->blist = bp->next; |
|
2068 SOAP_FREE(soap, bp); |
|
2069 } |
|
2070 DBGLOG(TEST, if (soap->blist) SOAP_MESSAGE(fdebug, "Restore previous block sequence\n")); |
|
2071 } |
|
2072 #endif |
|
2073 |
|
2074 /******************************************************************************/ |
|
2075 #ifndef PALM_1 |
|
2076 SOAP_FMAC1 |
|
2077 char* |
|
2078 SOAP_FMAC2 |
|
2079 soap_save_block(struct soap *soap, char *p, int flag) |
|
2080 { register size_t n; |
|
2081 register char *q, *s; |
|
2082 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Save all blocks in contiguous memory space of %u bytes (%p->%p)\n", (unsigned int)soap->blist->size, soap->blist->ptr, p)); |
|
2083 if (soap->blist->size) |
|
2084 { if (!p) |
|
2085 p = (char*)soap_malloc(soap, soap->blist->size); |
|
2086 if (p) |
|
2087 { for (s = p, q = soap_first_block(soap); q; q = soap_next_block(soap)) |
|
2088 { n = soap_block_size(soap); |
|
2089 #ifndef WITH_NOIDREF |
|
2090 if (flag) |
|
2091 soap_update_ptrs(soap, q, q + n, (long)s - (long)q); /* pointers s and q may or may not be related */ |
|
2092 #endif |
|
2093 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy %u bytes from %p to %p\n", (unsigned int)n, q, s)); |
|
2094 memcpy(s, q, n); |
|
2095 s += n; |
|
2096 } |
|
2097 } |
|
2098 else |
|
2099 soap->error = SOAP_EOM; |
|
2100 } |
|
2101 soap_end_block(soap); |
|
2102 return p; |
|
2103 } |
|
2104 #endif |
|
2105 |
|
2106 /******************************************************************************/ |
|
2107 #ifndef PALM_2 |
|
2108 SOAP_FMAC1 |
|
2109 char * |
|
2110 SOAP_FMAC2 |
|
2111 soap_putsize(struct soap *soap, const char *type, int size) |
|
2112 { return soap_putsizes(soap, type, &size, 1); |
|
2113 } |
|
2114 #endif |
|
2115 |
|
2116 /******************************************************************************/ |
|
2117 #ifndef PALM_2 |
|
2118 SOAP_FMAC1 |
|
2119 char * |
|
2120 SOAP_FMAC2 |
|
2121 soap_putsizes(struct soap *soap, const char *type, const int *size, int dim) |
|
2122 { return soap_putsizesoffsets(soap, type, size, NULL, dim); |
|
2123 } |
|
2124 #endif |
|
2125 |
|
2126 /******************************************************************************/ |
|
2127 #ifndef PALM_2 |
|
2128 SOAP_FMAC1 |
|
2129 char * |
|
2130 SOAP_FMAC2 |
|
2131 soap_putsizesoffsets(struct soap *soap, const char *type, const int *size, const int *offset, int dim) |
|
2132 { int i; |
|
2133 if (!type) |
|
2134 return NULL; |
|
2135 if (soap->version == 2) |
|
2136 { sprintf(soap->type, "%s[%d", type, size[0]); |
|
2137 for (i = 1; i < dim; i++) |
|
2138 sprintf(soap->type + strlen(soap->type), " %d", size[i]); |
|
2139 } |
|
2140 else |
|
2141 { if (offset) |
|
2142 { sprintf(soap->type, "%s[%d", type, size[0] + offset[0]); |
|
2143 for (i = 1; i < dim; i++) |
|
2144 sprintf(soap->type + strlen(soap->type), ",%d", size[i] + offset[i]); |
|
2145 } |
|
2146 else |
|
2147 { sprintf(soap->type, "%s[%d", type, size[0]); |
|
2148 for (i = 1; i < dim; i++) |
|
2149 sprintf(soap->type + strlen(soap->type), ",%d", size[i]); |
|
2150 } |
|
2151 strcat(soap->type, "]"); |
|
2152 } |
|
2153 return soap->type; |
|
2154 } |
|
2155 #endif |
|
2156 |
|
2157 /******************************************************************************/ |
|
2158 #ifndef PALM_2 |
|
2159 SOAP_FMAC1 |
|
2160 char * |
|
2161 SOAP_FMAC2 |
|
2162 soap_putoffset(struct soap *soap, int offset) |
|
2163 { return soap_putoffsets(soap, &offset, 1); |
|
2164 } |
|
2165 #endif |
|
2166 |
|
2167 /******************************************************************************/ |
|
2168 #ifndef PALM_2 |
|
2169 SOAP_FMAC1 |
|
2170 char * |
|
2171 SOAP_FMAC2 |
|
2172 soap_putoffsets(struct soap *soap, const int *offset, int dim) |
|
2173 { register int i; |
|
2174 sprintf(soap->arrayOffset, "[%d", offset[0]); |
|
2175 for (i = 1; i < dim; i++) |
|
2176 sprintf(soap->arrayOffset + strlen(soap->arrayOffset), ",%d", offset[i]); |
|
2177 strcat(soap->arrayOffset, "]"); |
|
2178 return soap->arrayOffset; |
|
2179 } |
|
2180 #endif |
|
2181 |
|
2182 /******************************************************************************/ |
|
2183 #ifndef PALM_2 |
|
2184 SOAP_FMAC1 |
|
2185 int |
|
2186 SOAP_FMAC2 |
|
2187 soap_size(const int *size, int dim) |
|
2188 { register int i, n = size[0]; |
|
2189 for (i = 1; i < dim; i++) |
|
2190 n *= size[i]; |
|
2191 return n; |
|
2192 } |
|
2193 #endif |
|
2194 |
|
2195 /******************************************************************************/ |
|
2196 #ifndef PALM_2 |
|
2197 SOAP_FMAC1 |
|
2198 int |
|
2199 SOAP_FMAC2 |
|
2200 soap_getoffsets(const char *attr, const int *size, int *offset, int dim) |
|
2201 { register int i, j = 0; |
|
2202 if (offset) |
|
2203 for (i = 0; i < dim && attr && *attr; i++) |
|
2204 { attr++; |
|
2205 j *= size[i]; |
|
2206 j += offset[i] = (int)atol(attr); |
|
2207 attr = strchr(attr, ','); |
|
2208 } |
|
2209 else |
|
2210 for (i = 0; i < dim && attr && *attr; i++) |
|
2211 { attr++; |
|
2212 j *= size[i]; |
|
2213 j += (int)atol(attr); |
|
2214 attr = strchr(attr, ','); |
|
2215 } |
|
2216 return j; |
|
2217 } |
|
2218 #endif |
|
2219 |
|
2220 /******************************************************************************/ |
|
2221 #ifndef PALM_2 |
|
2222 SOAP_FMAC1 |
|
2223 int |
|
2224 SOAP_FMAC2 |
|
2225 soap_getsize(const char *attr1, const char *attr2, int *j) |
|
2226 { register int n, k; |
|
2227 char *s; |
|
2228 *j = 0; |
|
2229 if (!*attr1) |
|
2230 return -1; |
|
2231 if (*attr1 == '[') |
|
2232 attr1++; |
|
2233 n = 1; |
|
2234 for (;;) |
|
2235 { k = (int)soap_strtol(attr1, &s, 10); |
|
2236 n *= k; |
|
2237 if (k < 0 || n > SOAP_MAXARRAYSIZE || s == attr1) |
|
2238 return -1; |
|
2239 attr1 = strchr(s, ','); |
|
2240 if (!attr1) |
|
2241 attr1 = strchr(s, ' '); |
|
2242 if (attr2 && *attr2) |
|
2243 { attr2++; |
|
2244 *j *= k; |
|
2245 k = (int)soap_strtol(attr2, &s, 10); |
|
2246 *j += k; |
|
2247 if (k < 0) |
|
2248 return -1; |
|
2249 attr2 = s; |
|
2250 } |
|
2251 if (!attr1) |
|
2252 break; |
|
2253 attr1++; |
|
2254 } |
|
2255 return n - *j; |
|
2256 } |
|
2257 #endif |
|
2258 |
|
2259 /******************************************************************************/ |
|
2260 #ifndef PALM_2 |
|
2261 SOAP_FMAC1 |
|
2262 int |
|
2263 SOAP_FMAC2 |
|
2264 soap_getsizes(const char *attr, int *size, int dim) |
|
2265 { register int i, k, n; |
|
2266 if (!*attr) |
|
2267 return -1; |
|
2268 i = strlen(attr); |
|
2269 n = 1; |
|
2270 do |
|
2271 { for (i = i-1; i >= 0; i--) |
|
2272 if (attr[i] == '[' || attr[i] == ',' || attr[i] == ' ') |
|
2273 break; |
|
2274 k = (int)atol(attr + i + 1); |
|
2275 n *= size[--dim] = k; |
|
2276 if (k < 0 || n > SOAP_MAXARRAYSIZE) |
|
2277 return -1; |
|
2278 } while (i >= 0 && attr[i] != '['); |
|
2279 return n; |
|
2280 } |
|
2281 #endif |
|
2282 |
|
2283 /******************************************************************************/ |
|
2284 #ifndef PALM_2 |
|
2285 SOAP_FMAC1 |
|
2286 int |
|
2287 SOAP_FMAC2 |
|
2288 soap_getposition(const char *attr, int *pos) |
|
2289 { register int i, n; |
|
2290 if (!*attr) |
|
2291 return -1; |
|
2292 n = 0; |
|
2293 i = 1; |
|
2294 do |
|
2295 { pos[n++] = (int)atol(attr + i); |
|
2296 while (attr[i] && attr[i] != ',' && attr[i] != ']') |
|
2297 i++; |
|
2298 if (attr[i] == ',') |
|
2299 i++; |
|
2300 } while (n < SOAP_MAXDIMS && attr[i] && attr[i] != ']'); |
|
2301 return n; |
|
2302 } |
|
2303 #endif |
|
2304 |
|
2305 /******************************************************************************/ |
|
2306 #ifndef PALM_2 |
|
2307 SOAP_FMAC1 |
|
2308 int |
|
2309 SOAP_FMAC2 |
|
2310 soap_push_namespace(struct soap *soap, const char *id, const char *ns) |
|
2311 { register struct soap_nlist *np; |
|
2312 register struct Namespace *p; |
|
2313 register short i = -1; |
|
2314 register size_t n, k; |
|
2315 n = strlen(id); |
|
2316 k = strlen(ns) + 1; |
|
2317 p = soap->local_namespaces; |
|
2318 if (p) |
|
2319 { for (i = 0; p->id; p++, i++) |
|
2320 { if (p->ns && !strcmp(ns, p->ns)) |
|
2321 { if (p->out) |
|
2322 { SOAP_FREE(soap, p->out); |
|
2323 p->out = NULL; |
|
2324 } |
|
2325 break; |
|
2326 } |
|
2327 if (p->out) |
|
2328 { if (!strcmp(ns, p->out)) |
|
2329 break; |
|
2330 } |
|
2331 else if (p->in) |
|
2332 { if (!soap_tag_cmp(ns, p->in)) |
|
2333 { if ((p->out = (char*)SOAP_MALLOC(soap, k))) |
|
2334 strcpy(p->out, ns); |
|
2335 break; |
|
2336 } |
|
2337 } |
|
2338 } |
|
2339 if (!p || !p->id) |
|
2340 i = -1; |
|
2341 } |
|
2342 if (i >= 0) |
|
2343 k = 0; |
|
2344 np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k); |
|
2345 if (!np) |
|
2346 return soap->error = SOAP_EOM; |
|
2347 np->next = soap->nlist; |
|
2348 soap->nlist = np; |
|
2349 np->level = soap->level; |
|
2350 np->index = i; |
|
2351 strcpy(np->id, id); |
|
2352 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push namespace binding (level=%u) '%s' '%s'\n", soap->level, id, ns)); |
|
2353 if (i < 0) |
|
2354 { np->ns = np->id + n + 1; |
|
2355 strcpy(np->ns, ns); |
|
2356 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push NOT OK: no match found for '%s' in namespace mapping table (added to stack anyway)\n", ns)); |
|
2357 } |
|
2358 else |
|
2359 { np->ns = NULL; |
|
2360 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push OK ('%s' matches '%s' in namespace table)\n", id, p->id)); |
|
2361 } |
|
2362 return SOAP_OK; |
|
2363 } |
|
2364 #endif |
|
2365 |
|
2366 /******************************************************************************/ |
|
2367 #ifndef PALM_2 |
|
2368 SOAP_FMAC1 |
|
2369 void |
|
2370 SOAP_FMAC2 |
|
2371 soap_pop_namespace(struct soap *soap) |
|
2372 { register struct soap_nlist *np; |
|
2373 while (soap->nlist && soap->nlist->level >= soap->level) |
|
2374 { np = soap->nlist->next; |
|
2375 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Popped namespace binding (level=%u) '%s'\n", soap->level, soap->nlist->id)); |
|
2376 SOAP_FREE(soap, soap->nlist); |
|
2377 soap->nlist = np; |
|
2378 } |
|
2379 } |
|
2380 #endif |
|
2381 |
|
2382 /******************************************************************************/ |
|
2383 #ifndef PALM_2 |
|
2384 SOAP_FMAC1 |
|
2385 int |
|
2386 SOAP_FMAC2 |
|
2387 soap_match_namespace(struct soap *soap, const char *id1, const char *id2, int n1, int n2) |
|
2388 { register struct soap_nlist *np = soap->nlist; |
|
2389 while (np && (strncmp(np->id, id1, n1) || np->id[n1])) |
|
2390 np = np->next; |
|
2391 if (np) |
|
2392 { if (np->index < 0 |
|
2393 || (soap->local_namespaces[np->index].id |
|
2394 && (strncmp(soap->local_namespaces[np->index].id, id2, n2) |
|
2395 || soap->local_namespaces[np->index].id[n2]))) |
|
2396 return SOAP_NAMESPACE; |
|
2397 return SOAP_OK; |
|
2398 } |
|
2399 if (n1 == 3 && n1 == n2 && !strcmp(id1, "xml") && !strcmp(id1, id2)) |
|
2400 return SOAP_OK; |
|
2401 return SOAP_SYNTAX_ERROR; |
|
2402 } |
|
2403 #endif |
|
2404 |
|
2405 /******************************************************************************/ |
|
2406 #ifndef PALM_2 |
|
2407 SOAP_FMAC1 |
|
2408 int |
|
2409 SOAP_FMAC2 |
|
2410 soap_tag_cmp(const char *s, const char *t) |
|
2411 { for (;;) |
|
2412 { register int c1 = *s; |
|
2413 register int c2 = *t; |
|
2414 if (!c1 || c1 == '"') |
|
2415 break; |
|
2416 if (c2 != '-') |
|
2417 { if (c1 != c2) |
|
2418 { if (c1 >= 'A' && c1 <= 'Z') |
|
2419 c1 += 'a' - 'A'; |
|
2420 if (c2 >= 'A' && c2 <= 'Z') |
|
2421 c2 += 'a' - 'A'; |
|
2422 } |
|
2423 if (c1 != c2) |
|
2424 { if (c2 != '*') |
|
2425 return 1; |
|
2426 c2 = *++t; |
|
2427 if (!c2) |
|
2428 return 0; |
|
2429 if (c2 >= 'A' && c2 <= 'Z') |
|
2430 c2 += 'a' - 'A'; |
|
2431 for (;;) |
|
2432 { c1 = *s; |
|
2433 if (!c1 || c1 == '"') |
|
2434 break; |
|
2435 if (c1 >= 'A' && c1 <= 'Z') |
|
2436 c1 += 'a' - 'A'; |
|
2437 if (c1 == c2 && !soap_tag_cmp(s + 1, t + 1)) |
|
2438 return 0; |
|
2439 s++; |
|
2440 } |
|
2441 break; |
|
2442 } |
|
2443 } |
|
2444 s++; |
|
2445 t++; |
|
2446 } |
|
2447 if (*t == '*' && !t[1]) |
|
2448 return 0; |
|
2449 return *t; |
|
2450 } |
|
2451 #endif |
|
2452 |
|
2453 /******************************************************************************/ |
|
2454 #ifndef PALM_2 |
|
2455 SOAP_FMAC1 |
|
2456 int |
|
2457 SOAP_FMAC2 |
|
2458 soap_match_tag(struct soap *soap, const char *tag1, const char *tag2) |
|
2459 { register const char *s, *t; |
|
2460 if (!tag1 || !tag2 || !*tag2) |
|
2461 return SOAP_OK; |
|
2462 s = strchr(tag1, ':'); |
|
2463 t = strchr(tag2, ':'); |
|
2464 if (t) |
|
2465 { if (s) |
|
2466 { if (t[1] && SOAP_STRCMP(s + 1, t + 1)) |
|
2467 return SOAP_TAG_MISMATCH; |
|
2468 if (t != tag2 && soap_match_namespace(soap, tag1, tag2, s - tag1, t - tag2)) |
|
2469 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2)); |
|
2470 return SOAP_TAG_MISMATCH; |
|
2471 } |
|
2472 } |
|
2473 else if (SOAP_STRCMP(tag1, t + 1)) |
|
2474 return SOAP_TAG_MISMATCH; |
|
2475 else if (t != tag2 && soap_match_namespace(soap, tag1, tag2, 0, t - tag2)) |
|
2476 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2)); |
|
2477 return SOAP_TAG_MISMATCH; |
|
2478 } |
|
2479 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags and (default) namespaces match: '%s' '%s'\n", tag1, tag2)); |
|
2480 return SOAP_OK; |
|
2481 } |
|
2482 if (s) |
|
2483 { if (SOAP_STRCMP(s + 1, tag2)) |
|
2484 return SOAP_TAG_MISMATCH; |
|
2485 } |
|
2486 else if (SOAP_STRCMP(tag1, tag2)) |
|
2487 return SOAP_TAG_MISMATCH; |
|
2488 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags match: '%s' '%s'\n", tag1, tag2)); |
|
2489 return SOAP_OK; |
|
2490 } |
|
2491 #endif |
|
2492 |
|
2493 /******************************************************************************/ |
|
2494 #ifndef PALM_2 |
|
2495 SOAP_FMAC1 |
|
2496 int |
|
2497 SOAP_FMAC2 |
|
2498 soap_match_array(struct soap *soap, const char *type) |
|
2499 { if (*soap->arrayType) |
|
2500 if (soap_match_tag(soap, soap->arrayType, type) |
|
2501 && soap_match_tag(soap, soap->arrayType, "xsd:anyType") |
|
2502 && soap_match_tag(soap, soap->arrayType, "xsd:ur-type") |
|
2503 ) |
|
2504 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array type mismatch: '%s' '%s'\n", soap->arrayType, type)); |
|
2505 return SOAP_TAG_MISMATCH; |
|
2506 } |
|
2507 return SOAP_OK; |
|
2508 } |
|
2509 #endif |
|
2510 |
|
2511 /******************************************************************************/ |
|
2512 |
|
2513 #ifdef WITH_OPENSSL |
|
2514 /******************************************************************************/ |
|
2515 #ifndef PALM_2 |
|
2516 SOAP_FMAC1 |
|
2517 int |
|
2518 SOAP_FMAC2 |
|
2519 soap_rand() |
|
2520 { unsigned char buf[4]; |
|
2521 ssl_init(); |
|
2522 RAND_pseudo_bytes(buf, 4); |
|
2523 return *(int*)buf; |
|
2524 } |
|
2525 #endif |
|
2526 |
|
2527 /******************************************************************************/ |
|
2528 #ifndef PALM_2 |
|
2529 SOAP_FMAC1 |
|
2530 int |
|
2531 SOAP_FMAC2 |
|
2532 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) |
|
2533 { int err; |
|
2534 soap->keyfile = keyfile; |
|
2535 soap->password = password; |
|
2536 soap->cafile = cafile; |
|
2537 soap->capath = capath; |
|
2538 if (dhfile) |
|
2539 { soap->dhfile = dhfile; |
|
2540 soap->rsa = 0; |
|
2541 } |
|
2542 else |
|
2543 { soap->dhfile = NULL; |
|
2544 soap->rsa = 1; |
|
2545 } |
|
2546 soap->randfile = randfile; |
|
2547 soap->require_client_auth = (flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION); |
|
2548 if (!(err = soap->fsslauth(soap))) |
|
2549 if (sid) |
|
2550 SSL_CTX_set_session_id_context(soap->ctx, (unsigned char*)sid, strlen(sid)); |
|
2551 return err; |
|
2552 } |
|
2553 #endif |
|
2554 |
|
2555 /******************************************************************************/ |
|
2556 #ifndef PALM_2 |
|
2557 SOAP_FMAC1 |
|
2558 int |
|
2559 SOAP_FMAC2 |
|
2560 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) |
|
2561 { soap->keyfile = keyfile; |
|
2562 soap->password = password; |
|
2563 soap->cafile = cafile; |
|
2564 soap->capath = capath; |
|
2565 soap->dhfile = NULL; |
|
2566 soap->rsa = 0; |
|
2567 soap->randfile = randfile; |
|
2568 soap->require_server_auth = (flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION); |
|
2569 return soap->fsslauth(soap); |
|
2570 } |
|
2571 #endif |
|
2572 |
|
2573 /******************************************************************************/ |
|
2574 #ifndef PALM_2 |
|
2575 static void |
|
2576 ssl_init() |
|
2577 { static int done = 0; |
|
2578 if (!done) |
|
2579 { done = 1; |
|
2580 SSL_library_init(); |
|
2581 #ifndef WITH_LEAN |
|
2582 SSL_load_error_strings(); |
|
2583 #endif |
|
2584 if (!RAND_load_file("/dev/urandom", 1024)) |
|
2585 { char buf[1024]; |
|
2586 RAND_seed(buf, sizeof(buf)); |
|
2587 while (!RAND_status()) |
|
2588 { int r = rand(); |
|
2589 RAND_seed(&r, sizeof(int)); |
|
2590 } |
|
2591 } |
|
2592 } |
|
2593 } |
|
2594 #endif |
|
2595 |
|
2596 /******************************************************************************/ |
|
2597 #ifndef PALM_1 |
|
2598 static const char * |
|
2599 ssl_error(struct soap *soap, int ret) |
|
2600 { int err = SSL_get_error(soap->ssl, ret); |
|
2601 const char *msg = soap_str_code(h_ssl_error_codes, err); |
|
2602 if (msg) |
|
2603 strcpy(soap->msgbuf, msg); |
|
2604 else |
|
2605 return ERR_error_string(err, soap->msgbuf); |
|
2606 if (ERR_peek_error()) |
|
2607 { unsigned long r; |
|
2608 strcat(soap->msgbuf, "\n"); |
|
2609 while ((r = ERR_get_error())) |
|
2610 ERR_error_string_n(r, soap->msgbuf + strlen(soap->msgbuf), sizeof(soap->msgbuf) - strlen(soap->msgbuf)); |
|
2611 } |
|
2612 else |
|
2613 { switch (ret) |
|
2614 { case 0: |
|
2615 strcpy(soap->msgbuf, "EOF was observed that violates the protocol. The client probably provided invalid authentication information."); |
|
2616 break; |
|
2617 case -1: |
|
2618 sprintf(soap->msgbuf, "Error observed by underlying BIO: %s", strerror(errno)); |
|
2619 break; |
|
2620 } |
|
2621 } |
|
2622 return soap->msgbuf; |
|
2623 } |
|
2624 #endif |
|
2625 |
|
2626 /******************************************************************************/ |
|
2627 #ifndef PALM_1 |
|
2628 static int |
|
2629 ssl_password(char *buf, int num, int rwflag, void *userdata) |
|
2630 { if (num < (int)strlen((char*)userdata) + 1) |
|
2631 return 0; |
|
2632 return strlen(strcpy(buf, (char*)userdata)); |
|
2633 } |
|
2634 #endif |
|
2635 |
|
2636 /******************************************************************************/ |
|
2637 /* This callback is included for future references. It should not be deleted |
|
2638 #ifndef PALM_2 |
|
2639 static DH * |
|
2640 ssl_tmp_dh(SSL *ssl, int is_export, int keylength) |
|
2641 { static DH *dh512 = NULL; |
|
2642 static DH *dh1024 = NULL; |
|
2643 DH *dh; |
|
2644 switch (keylength) |
|
2645 { case 512: |
|
2646 if (!dh512) |
|
2647 { BIO *bio = BIO_new_file("dh512.pem", "r"); |
|
2648 if (bio) |
|
2649 { dh512 = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); |
|
2650 BIO_free(bio); |
|
2651 return dh512; |
|
2652 } |
|
2653 } |
|
2654 else |
|
2655 return dh512; |
|
2656 default: |
|
2657 if (!dh1024) |
|
2658 { BIO *bio = BIO_new_file("dh1024.pem", "r"); |
|
2659 if (bio) |
|
2660 { dh1024 = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); |
|
2661 BIO_free(bio); |
|
2662 } |
|
2663 } |
|
2664 dh = dh1024; |
|
2665 } |
|
2666 return dh; |
|
2667 } |
|
2668 #endif |
|
2669 */ |
|
2670 |
|
2671 /******************************************************************************/ |
|
2672 #ifndef PALM_1 |
|
2673 static int |
|
2674 ssl_auth_init(struct soap *soap) |
|
2675 { ssl_init(); |
|
2676 if (!soap->ctx) |
|
2677 { if (!(soap->ctx = SSL_CTX_new(SSLv23_method()))) |
|
2678 return soap_set_receiver_error(soap, "SSL error", "Can't setup context", SOAP_SSL_ERROR); |
|
2679 } |
|
2680 if (soap->randfile) |
|
2681 { if (!RAND_load_file(soap->randfile, -1)) |
|
2682 return soap_set_receiver_error(soap, "SSL error", "Can't load randomness", SOAP_SSL_ERROR); |
|
2683 } |
|
2684 if (soap->cafile || soap->capath) |
|
2685 { if (!SSL_CTX_load_verify_locations(soap->ctx, soap->cafile, soap->capath)) |
|
2686 return soap_set_receiver_error(soap, "SSL error", "Can't read CA file and directory", SOAP_SSL_ERROR); |
|
2687 } |
|
2688 if (!SSL_CTX_set_default_verify_paths(soap->ctx)) |
|
2689 return soap_set_receiver_error(soap, "SSL error", "Can't read default CA file and/or directory", SOAP_SSL_ERROR); |
|
2690 /* See below */ |
|
2691 if (soap->keyfile) |
|
2692 { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile)) |
|
2693 return soap_set_receiver_error(soap, "SSL error", "Can't read certificate key file", SOAP_SSL_ERROR); |
|
2694 if (soap->password) |
|
2695 { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password); |
|
2696 SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password); |
|
2697 } |
|
2698 if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM)) |
|
2699 return soap_set_receiver_error(soap, "SSL error", "Can't read key file", SOAP_SSL_ERROR); |
|
2700 } |
|
2701 /* Suggested alternative approach to check cafile first before the key file: |
|
2702 if (soap->password) |
|
2703 { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password); |
|
2704 SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password); |
|
2705 } |
|
2706 if (!soap->cafile || !SSL_CTX_use_certificate_chain_file(soap->ctx, soap->cafile)) |
|
2707 { if (soap->keyfile) |
|
2708 { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile)) |
|
2709 return soap_set_receiver_error(soap, "SSL error", "Can't read certificate or key file", SOAP_SSL_ERROR); |
|
2710 if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM)) |
|
2711 return soap_set_receiver_error(soap, "SSL error", "Can't read key file", SOAP_SSL_ERROR); |
|
2712 } |
|
2713 } |
|
2714 */ |
|
2715 if (soap->rsa) |
|
2716 { RSA *rsa = RSA_generate_key(512, RSA_F4, NULL, NULL); |
|
2717 if (!SSL_CTX_set_tmp_rsa(soap->ctx, rsa)) |
|
2718 { if (rsa) |
|
2719 RSA_free(rsa); |
|
2720 return soap_set_receiver_error(soap, "SSL error", "Can't set RSA key", SOAP_SSL_ERROR); |
|
2721 } |
|
2722 RSA_free(rsa); |
|
2723 } |
|
2724 else if (soap->dhfile) |
|
2725 { DH *dh = 0; |
|
2726 BIO *bio; |
|
2727 bio = BIO_new_file(soap->dhfile, "r"); |
|
2728 if (!bio) |
|
2729 return soap_set_receiver_error(soap, "SSL error", "Can't read DH file", SOAP_SSL_ERROR); |
|
2730 dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); |
|
2731 BIO_free(bio); |
|
2732 if (SSL_CTX_set_tmp_dh(soap->ctx, dh) < 0) |
|
2733 { if (dh) |
|
2734 DH_free(dh); |
|
2735 return soap_set_receiver_error(soap, "SSL error", "Can't set DH parameters", SOAP_SSL_ERROR); |
|
2736 } |
|
2737 DH_free(dh); |
|
2738 } |
|
2739 SSL_CTX_set_options(soap->ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2); |
|
2740 SSL_CTX_set_verify(soap->ctx, soap->require_client_auth ? (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT) : soap->require_server_auth ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, soap->fsslverify); |
|
2741 #if (OPENSSL_VERSION_NUMBER < 0x00905100L) |
|
2742 SSL_CTX_set_verify_depth(soap->ctx, 1); |
|
2743 #else |
|
2744 SSL_CTX_set_verify_depth(soap->ctx, 9); |
|
2745 #endif |
|
2746 return SOAP_OK; |
|
2747 } |
|
2748 #endif |
|
2749 |
|
2750 /******************************************************************************/ |
|
2751 #ifndef PALM_1 |
|
2752 static int |
|
2753 ssl_verify_callback(int ok, X509_STORE_CTX *store) |
|
2754 { |
|
2755 #ifdef SOAP_DEBUG |
|
2756 if (!ok) |
|
2757 { char data[256]; |
|
2758 X509 *cert = X509_STORE_CTX_get_current_cert(store); |
|
2759 fprintf(stderr, "SSL verify error or warning with certificate at depth %d: %s\n", X509_STORE_CTX_get_error_depth(store), X509_verify_cert_error_string(X509_STORE_CTX_get_error(store))); |
|
2760 X509_NAME_oneline(X509_get_issuer_name(cert), data, sizeof(data)); |
|
2761 fprintf(stderr, "certificate issuer %s\n", data); |
|
2762 X509_NAME_oneline(X509_get_subject_name(cert), data, sizeof(data)); |
|
2763 fprintf(stderr, "certificate subject %s\n", data); |
|
2764 } |
|
2765 #endif |
|
2766 /* Note: return 1 to continue, but unsafe progress will be terminated by SSL */ |
|
2767 return ok; |
|
2768 } |
|
2769 #endif |
|
2770 |
|
2771 /******************************************************************************/ |
|
2772 #ifndef PALM_1 |
|
2773 SOAP_FMAC1 |
|
2774 int |
|
2775 SOAP_FMAC2 |
|
2776 soap_ssl_accept(struct soap *soap) |
|
2777 { BIO *bio; |
|
2778 int i, r; |
|
2779 if (!soap_valid_socket(soap->socket)) |
|
2780 return soap_set_receiver_error(soap, "SSL error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR); |
|
2781 if (!soap->ctx && (soap->error = soap->fsslauth(soap))) |
|
2782 return SOAP_INVALID_SOCKET; |
|
2783 if (!soap->ssl) |
|
2784 { soap->ssl = SSL_new(soap->ctx); |
|
2785 if (!soap->ssl) |
|
2786 return soap_set_receiver_error(soap, "SSL error", "SSL_new() failed in soap_ssl_accept()", SOAP_SSL_ERROR); |
|
2787 } |
|
2788 else |
|
2789 SSL_clear(soap->ssl); |
|
2790 soap->imode |= SOAP_ENC_SSL; |
|
2791 soap->omode |= SOAP_ENC_SSL; |
|
2792 #ifdef WIN32 |
|
2793 { u_long nonblocking = 1; |
|
2794 ioctlsocket((SOAP_SOCKET)soap->socket, FIONBIO, &nonblocking); |
|
2795 } |
|
2796 #else |
|
2797 fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL)|O_NONBLOCK); |
|
2798 #endif |
|
2799 bio = BIO_new_socket((SOAP_SOCKET)soap->socket, BIO_NOCLOSE); |
|
2800 SSL_set_bio(soap->ssl, bio, bio); |
|
2801 i = 100; /* 100 * 0.1 ms retries */ |
|
2802 while ((r = SSL_accept(soap->ssl)) <= 0) |
|
2803 { int err = SSL_get_error(soap->ssl, r); |
|
2804 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) |
|
2805 { struct timeval timeout; |
|
2806 fd_set fd; |
|
2807 if (i-- <= 0) |
|
2808 break; |
|
2809 timeout.tv_sec = 0; |
|
2810 timeout.tv_usec = 100000; |
|
2811 FD_ZERO(&fd); |
|
2812 FD_SET((SOAP_SOCKET)soap->socket, &fd); |
|
2813 r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout); |
|
2814 if (r < 0 && soap_socket_errno != SOAP_EINTR) |
|
2815 { soap->errnum = soap_socket_errno; |
|
2816 return SOAP_EOF; |
|
2817 } |
|
2818 } |
|
2819 else |
|
2820 { soap->errnum = err; |
|
2821 break; |
|
2822 } |
|
2823 } |
|
2824 #ifdef WIN32 |
|
2825 { u_long blocking = 0; |
|
2826 ioctlsocket((SOAP_SOCKET)soap->socket, FIONBIO, &blocking); |
|
2827 } |
|
2828 #else |
|
2829 fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL)&~O_NONBLOCK); |
|
2830 #endif |
|
2831 if (r <= 0) |
|
2832 { soap_set_receiver_error(soap, ssl_error(soap, r), "SSL_accept() failed in soap_ssl_accept()", SOAP_SSL_ERROR); |
|
2833 soap_closesock(soap); |
|
2834 return SOAP_SSL_ERROR; |
|
2835 } |
|
2836 if (soap->require_client_auth) |
|
2837 { X509 *peer; |
|
2838 int err; |
|
2839 if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK) |
|
2840 { soap_closesock(soap); |
|
2841 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); |
|
2842 } |
|
2843 peer = SSL_get_peer_certificate(soap->ssl); |
|
2844 if (!peer) |
|
2845 { soap_closesock(soap); |
|
2846 return soap_set_sender_error(soap, "SSL error", "No SSL certificate was presented by the peer in soap_ssl_accept()", SOAP_SSL_ERROR); |
|
2847 } |
|
2848 X509_free(peer); |
|
2849 } |
|
2850 return SOAP_OK; |
|
2851 } |
|
2852 #endif |
|
2853 |
|
2854 /******************************************************************************/ |
|
2855 #endif /* WITH_OPENSSL */ |
|
2856 |
|
2857 /******************************************************************************/ |
|
2858 #ifndef WITH_NOIO |
|
2859 #ifndef PALM_1 |
|
2860 static int |
|
2861 tcp_init(struct soap *soap) |
|
2862 { soap->errmode = 1; |
|
2863 #ifdef WIN32 |
|
2864 if (tcp_done) |
|
2865 return 0; |
|
2866 else |
|
2867 { WSADATA w; |
|
2868 if (WSAStartup(MAKEWORD(1, 1), &w)) |
|
2869 return -1; |
|
2870 tcp_done = 1; |
|
2871 } |
|
2872 #endif |
|
2873 return 0; |
|
2874 } |
|
2875 #endif |
|
2876 #endif |
|
2877 |
|
2878 /******************************************************************************/ |
|
2879 #ifndef PALM_1 |
|
2880 SOAP_FMAC1 |
|
2881 void |
|
2882 SOAP_FMAC2 |
|
2883 soap_done(struct soap *soap) |
|
2884 { |
|
2885 #ifdef SOAP_DEBUG |
|
2886 int i; |
|
2887 #endif |
|
2888 soap_free(soap); |
|
2889 while (soap->clist) |
|
2890 { struct soap_clist *p = soap->clist->next; |
|
2891 SOAP_FREE(soap, soap->clist); |
|
2892 soap->clist = p; |
|
2893 } |
|
2894 soap->keep_alive = 0; /* to force close the socket */ |
|
2895 soap_closesock(soap); |
|
2896 #ifdef WITH_COOKIES |
|
2897 soap_free_cookies(soap); |
|
2898 #endif |
|
2899 while (soap->plugins) |
|
2900 { register struct soap_plugin *p = soap->plugins->next; |
|
2901 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Removing plugin '%s'\n", soap->plugins->id)); |
|
2902 if (soap->plugins->fcopy || !soap->copy) |
|
2903 soap->plugins->fdelete(soap, soap->plugins); |
|
2904 SOAP_FREE(soap, soap->plugins); |
|
2905 soap->plugins = p; |
|
2906 } |
|
2907 soap->fplugin = fplugin; |
|
2908 #ifndef WITH_NOHTTP |
|
2909 soap->fpost = http_post; |
|
2910 soap->fget = http_get; |
|
2911 soap->fform = NULL; |
|
2912 soap->fposthdr = http_post_header; |
|
2913 soap->fresponse = http_response; |
|
2914 soap->fparse = http_parse; |
|
2915 soap->fparsehdr = http_parse_header; |
|
2916 #endif |
|
2917 #ifndef WITH_NOIO |
|
2918 #ifndef WITH_IPV6 |
|
2919 soap->fresolve = tcp_gethost; |
|
2920 #else |
|
2921 soap->fresolve = NULL; |
|
2922 #endif |
|
2923 soap->faccept = tcp_accept; |
|
2924 soap->fopen = tcp_connect; |
|
2925 soap->fclose = tcp_disconnect; |
|
2926 soap->fclosesocket = tcp_closesocket; |
|
2927 soap->fshutdownsocket = tcp_shutdownsocket; |
|
2928 soap->fsend = fsend; |
|
2929 soap->frecv = frecv; |
|
2930 soap->fpoll = soap_poll; |
|
2931 #else |
|
2932 soap->fopen = NULL; |
|
2933 soap->fclose = NULL; |
|
2934 soap->fpoll = NULL; |
|
2935 #endif |
|
2936 #ifndef WITH_LEANER |
|
2937 soap->fprepareinit = NULL; |
|
2938 soap->fpreparesend = NULL; |
|
2939 soap->fpreparerecv = NULL; |
|
2940 soap->fpreparefinal = NULL; |
|
2941 #endif |
|
2942 soap->fseterror = NULL; |
|
2943 soap->fignore = NULL; |
|
2944 soap->fserveloop = NULL; |
|
2945 #ifdef WITH_OPENSSL |
|
2946 if (soap->session) |
|
2947 { SSL_SESSION_free(soap->session); |
|
2948 soap->session = NULL; |
|
2949 } |
|
2950 #endif |
|
2951 if (!soap->copy) |
|
2952 { if (soap_valid_socket(soap->master)) |
|
2953 { soap->fclosesocket(soap, (SOAP_SOCKET)soap->master); |
|
2954 soap->master = SOAP_INVALID_SOCKET; |
|
2955 } |
|
2956 #ifdef WITH_OPENSSL |
|
2957 if (soap->ctx) |
|
2958 { SSL_CTX_free(soap->ctx); |
|
2959 soap->ctx = NULL; |
|
2960 } |
|
2961 #endif |
|
2962 } |
|
2963 #ifdef SOAP_DEBUG |
|
2964 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free logfiles\n")); |
|
2965 for (i = 0; i < SOAP_MAXLOGS; i++) |
|
2966 { if (soap->logfile[i]) |
|
2967 { SOAP_FREE(soap, (void*)soap->logfile[i]); |
|
2968 soap->logfile[i] = NULL; |
|
2969 } |
|
2970 soap_close_logfile(soap, i); |
|
2971 } |
|
2972 soap_free_mht(soap); |
|
2973 #endif |
|
2974 } |
|
2975 #endif |
|
2976 |
|
2977 /******************************************************************************/ |
|
2978 #ifndef WITH_NOIO |
|
2979 #ifndef PALM_2 |
|
2980 SOAP_FMAC1 |
|
2981 void |
|
2982 SOAP_FMAC2 |
|
2983 soap_cleanup(struct soap *soap) |
|
2984 { soap_done(soap); |
|
2985 #ifdef WIN32 |
|
2986 if (!tcp_done) |
|
2987 return; |
|
2988 tcp_done = 0; |
|
2989 WSACleanup(); |
|
2990 #endif |
|
2991 } |
|
2992 #endif |
|
2993 #endif |
|
2994 |
|
2995 /******************************************************************************/ |
|
2996 #ifndef WITH_NOIO |
|
2997 #ifndef PALM_1 |
|
2998 static const char* |
|
2999 tcp_error(struct soap *soap) |
|
3000 { register const char *msg = NULL; |
|
3001 switch (soap->errmode) |
|
3002 { case 0: |
|
3003 msg = soap_strerror(soap); |
|
3004 break; |
|
3005 case 1: |
|
3006 msg = "WSAStartup failed"; |
|
3007 break; |
|
3008 case 2: |
|
3009 { |
|
3010 #ifndef WITH_LEAN |
|
3011 msg = soap_str_code(h_error_codes, soap->errnum); |
|
3012 if (!msg) |
|
3013 #endif |
|
3014 { sprintf(soap->msgbuf, "TCP/UDP IP error %d", soap->errnum); |
|
3015 msg = soap->msgbuf; |
|
3016 } |
|
3017 } |
|
3018 } |
|
3019 return msg; |
|
3020 } |
|
3021 #endif |
|
3022 #endif |
|
3023 |
|
3024 /******************************************************************************/ |
|
3025 #ifndef WITH_NOHTTP |
|
3026 #ifndef PALM_1 |
|
3027 static const char* |
|
3028 http_error(struct soap *soap, int status) |
|
3029 { register const char *msg = SOAP_STR_EOS; |
|
3030 #ifndef WITH_LEAN |
|
3031 msg = soap_str_code(h_http_error_codes, status); |
|
3032 if (!msg) |
|
3033 msg = SOAP_STR_EOS; |
|
3034 #endif |
|
3035 return msg; |
|
3036 } |
|
3037 #endif |
|
3038 #endif |
|
3039 |
|
3040 /******************************************************************************/ |
|
3041 #ifndef WITH_IPV6 |
|
3042 #ifndef WITH_NOIO |
|
3043 #ifndef PALM_1 |
|
3044 static int |
|
3045 tcp_gethost(struct soap *soap, const char *addr, struct in_addr *inaddr) |
|
3046 { soap_int32 iadd = -1; |
|
3047 struct hostent hostent, *host = &hostent; |
|
3048 #ifdef VXWORKS |
|
3049 int hostint; |
|
3050 char *addrcopy = (char*)SOAP_MALLOC(soap, strlen(addr) + 1); /*copy of addr. */ |
|
3051 /* inet_addr(), and hostGetByName() expect "char *"; addr is a "const char *". */ |
|
3052 strncpy(addrcopy, addr, strlen(addr)+1); |
|
3053 iadd = inet_addr(addrcopy); |
|
3054 #else |
|
3055 #if defined(_AIXVERSION_431) || defined(TRU64) |
|
3056 struct hostent_data ht_data; |
|
3057 #endif |
|
3058 iadd = inet_addr(addr); |
|
3059 #endif |
|
3060 if (iadd != -1) |
|
3061 { memcpy(inaddr, &iadd, sizeof(iadd)); |
|
3062 #ifdef VXWORKS |
|
3063 SOAP_FREE(soap, addrcopy); |
|
3064 #endif |
|
3065 return SOAP_OK; |
|
3066 } |
|
3067 #if defined(__GLIBC__) |
|
3068 if (gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &host, &soap->errnum) < 0) |
|
3069 host = NULL; |
|
3070 #elif defined(_AIXVERSION_431) || defined(TRU64) |
|
3071 memset((void*)&ht_data, 0, sizeof(ht_data)); |
|
3072 if (gethostbyname_r(addr, &hostent, &ht_data) < 0) |
|
3073 { host = NULL; |
|
3074 soap->errnum = h_errno; |
|
3075 } |
|
3076 #elif defined(HAVE_GETHOSTBYNAME_R) |
|
3077 host = gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &soap->errnum); |
|
3078 #elif defined(VXWORKS) |
|
3079 /* If the DNS resolver library resolvLib has been configured in the vxWorks |
|
3080 * image, a query for the host IP address is sent to the DNS server, if the |
|
3081 * name was not found in the local host table. */ |
|
3082 hostint = hostGetByName(addrcopy); |
|
3083 if (hostint == ERROR) |
|
3084 { host = NULL; |
|
3085 soap->errnum = soap_errno; |
|
3086 } |
|
3087 SOAP_FREE(soap, addrcopy); /*free() is placed after the error checking to assure that |
|
3088 * errno captured is that from hostGetByName() */ |
|
3089 #else |
|
3090 if (!(host = gethostbyname(addr))) |
|
3091 soap->errnum = h_errno; |
|
3092 #endif |
|
3093 if (!host) |
|
3094 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Host name not found\n")); |
|
3095 return SOAP_ERR; |
|
3096 } |
|
3097 #ifdef VXWORKS |
|
3098 inaddr->s_addr = hostint; |
|
3099 #else |
|
3100 memcpy(inaddr, host->h_addr, host->h_length); |
|
3101 #endif |
|
3102 return SOAP_OK; |
|
3103 } |
|
3104 #endif |
|
3105 #endif |
|
3106 #endif |
|
3107 |
|
3108 /******************************************************************************/ |
|
3109 #ifndef WITH_NOIO |
|
3110 #ifndef PALM_1 |
|
3111 static int |
|
3112 tcp_connect(struct soap *soap, const char *endpoint, const char *host, int port) |
|
3113 { |
|
3114 #ifdef WITH_IPV6 |
|
3115 struct addrinfo hints, *res, *ressave; |
|
3116 int err; |
|
3117 #endif |
|
3118 register int fd; |
|
3119 #ifndef WITH_LEAN |
|
3120 int len = SOAP_BUFLEN; |
|
3121 int set = 1; |
|
3122 #endif |
|
3123 if (soap_valid_socket(soap->socket)) |
|
3124 soap->fclosesocket(soap, (SOAP_SOCKET)soap->socket); |
|
3125 soap->socket = SOAP_INVALID_SOCKET; |
|
3126 if (tcp_init(soap)) |
|
3127 { soap->errnum = 0; |
|
3128 soap_set_sender_error(soap, tcp_error(soap), "TCP init failed in tcp_connect()", SOAP_TCP_ERROR); |
|
3129 return SOAP_INVALID_SOCKET; |
|
3130 } |
|
3131 soap->errmode = 0; |
|
3132 #ifdef WITH_IPV6 |
|
3133 memset((void*)&hints, 0, sizeof(hints)); |
|
3134 hints.ai_family = PF_UNSPEC; |
|
3135 #ifdef WITH_UDP |
|
3136 if ((soap->omode & SOAP_IO_UDP)) |
|
3137 hints.ai_socktype = SOCK_DGRAM; |
|
3138 else |
|
3139 #endif |
|
3140 hints.ai_socktype = SOCK_STREAM; |
|
3141 soap->errmode = 2; |
|
3142 if (soap->proxy_host) |
|
3143 err = getaddrinfo(soap->proxy_host, soap_int2s(soap, soap->proxy_port), &hints, &res); |
|
3144 else |
|
3145 err = getaddrinfo(host, soap_int2s(soap, port), &hints, &res); |
|
3146 if (err) |
|
3147 { soap_set_sender_error(soap, gai_strerror(err), "getaddrinfo failed in tcp_connect()", SOAP_TCP_ERROR); |
|
3148 return SOAP_INVALID_SOCKET; |
|
3149 } |
|
3150 ressave = res; |
|
3151 again: |
|
3152 fd = (int)socket(res->ai_family, res->ai_socktype, res->ai_protocol); |
|
3153 soap->errmode = 0; |
|
3154 #else |
|
3155 #ifdef WITH_UDP |
|
3156 if ((soap->omode & SOAP_IO_UDP)) |
|
3157 fd = (int)socket(AF_INET, SOCK_DGRAM, 0); |
|
3158 else |
|
3159 #endif |
|
3160 fd = (int)socket(AF_INET, SOCK_STREAM, 0); |
|
3161 #endif |
|
3162 if (fd < 0) |
|
3163 { soap->errnum = soap_socket_errno; |
|
3164 soap_set_sender_error(soap, tcp_error(soap), "socket failed in tcp_connect()", SOAP_TCP_ERROR); |
|
3165 return SOAP_INVALID_SOCKET; |
|
3166 } |
|
3167 #ifdef SOCKET_CLOSE_ON_EXEC |
|
3168 #ifdef WIN32 |
|
3169 #ifndef UNDER_CE |
|
3170 SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0); |
|
3171 #endif |
|
3172 #else |
|
3173 fcntl(fd, F_SETFD, 1); |
|
3174 #endif |
|
3175 #endif |
|
3176 #ifndef WITH_LEAN |
|
3177 if (soap->connect_flags & SO_LINGER) |
|
3178 { struct linger linger; |
|
3179 memset((void*)&linger, 0, sizeof(linger)); |
|
3180 linger.l_onoff = 1; |
|
3181 linger.l_linger = 0; |
|
3182 if (setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger))) |
|
3183 { soap->errnum = soap_socket_errno; |
|
3184 soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in tcp_connect()", SOAP_TCP_ERROR); |
|
3185 soap->fclosesocket(soap, (SOAP_SOCKET)fd); |
|
3186 return SOAP_INVALID_SOCKET; |
|
3187 } |
|
3188 } |
|
3189 if ((soap->connect_flags & ~SO_LINGER) && setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, soap->connect_flags & ~SO_LINGER, (char*)&set, sizeof(int))) |
|
3190 { soap->errnum = soap_socket_errno; |
|
3191 soap_set_sender_error(soap, tcp_error(soap), "setsockopt failed in tcp_connect()", SOAP_TCP_ERROR); |
|
3192 soap->fclosesocket(soap, (SOAP_SOCKET)fd); |
|
3193 return SOAP_INVALID_SOCKET; |
|
3194 } |
|
3195 if (soap->keep_alive && setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) |
|
3196 { soap->errnum = soap_socket_errno; |
|
3197 soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in tcp_connect()", SOAP_TCP_ERROR); |
|
3198 soap->fclosesocket(soap, (SOAP_SOCKET)fd); |
|
3199 return SOAP_INVALID_SOCKET; |
|
3200 } |
|
3201 if (setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) |
|
3202 { soap->errnum = soap_socket_errno; |
|
3203 soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in tcp_connect()", SOAP_TCP_ERROR); |
|
3204 soap->fclosesocket(soap, (SOAP_SOCKET)fd); |
|
3205 return SOAP_INVALID_SOCKET; |
|
3206 } |
|
3207 if (setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) |
|
3208 { soap->errnum = soap_socket_errno; |
|
3209 soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in tcp_connect()", SOAP_TCP_ERROR); |
|
3210 soap->fclosesocket(soap, (SOAP_SOCKET)fd); |
|
3211 return SOAP_INVALID_SOCKET; |
|
3212 } |
|
3213 #ifdef TCP_NODELAY |
|
3214 if (!(soap->omode & SOAP_IO_UDP) && setsockopt((SOAP_SOCKET)fd, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) |
|
3215 { soap->errnum = soap_socket_errno; |
|
3216 soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in tcp_connect()", SOAP_TCP_ERROR); |
|
3217 soap->fclosesocket(soap, (SOAP_SOCKET)fd); |
|
3218 return SOAP_INVALID_SOCKET; |
|
3219 } |
|
3220 #endif |
|
3221 #endif |
|
3222 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Opening socket %d to host='%s' port=%d\n", fd, host, port)); |
|
3223 #ifndef WITH_IPV6 |
|
3224 soap->peerlen = sizeof(soap->peer); |
|
3225 memset((void*)&soap->peer, 0, sizeof(soap->peer)); |
|
3226 soap->peer.sin_family = AF_INET; |
|
3227 soap->errmode = 2; |
|
3228 if (soap->proxy_host) |
|
3229 { if (soap->fresolve(soap, soap->proxy_host, &soap->peer.sin_addr)) |
|
3230 { soap_set_sender_error(soap, tcp_error(soap), "get proxy host by name failed in tcp_connect()", SOAP_TCP_ERROR); |
|
3231 soap->fclosesocket(soap, (SOAP_SOCKET)fd); |
|
3232 return SOAP_INVALID_SOCKET; |
|
3233 } |
|
3234 soap->peer.sin_port = htons((short)soap->proxy_port); |
|
3235 } |
|
3236 else |
|
3237 { if (soap->fresolve(soap, host, &soap->peer.sin_addr)) |
|
3238 { soap_set_sender_error(soap, tcp_error(soap), "get host by name failed in tcp_connect()", SOAP_TCP_ERROR); |
|
3239 soap->fclosesocket(soap, (SOAP_SOCKET)fd); |
|
3240 return SOAP_INVALID_SOCKET; |
|
3241 } |
|
3242 soap->peer.sin_port = htons((short)port); |
|
3243 } |
|
3244 soap->errmode = 0; |
|
3245 if ((soap->omode & SOAP_IO_UDP)) |
|
3246 return fd; |
|
3247 #endif |
|
3248 #ifndef WITH_LEAN |
|
3249 if (soap->connect_timeout) |
|
3250 #if defined(WIN32) |
|
3251 { u_long nonblocking = 1; |
|
3252 ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &nonblocking); |
|
3253 } |
|
3254 #elif defined(VXWORKS) |
|
3255 { vx_nonblocking = TRUE; |
|
3256 ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&vx_nonblocking)); /* modified to use fd */ |
|
3257 } |
|
3258 #else |
|
3259 fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)|O_NONBLOCK); |
|
3260 #endif |
|
3261 else |
|
3262 #if defined(WIN32) |
|
3263 { u_long blocking = 0; |
|
3264 ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &blocking); |
|
3265 } |
|
3266 #elif defined(VXWORKS) |
|
3267 { vx_nonblocking = FALSE; |
|
3268 ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&vx_nonblocking)); /* modified to use fd */ |
|
3269 } |
|
3270 #else |
|
3271 fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)&~O_NONBLOCK); |
|
3272 #endif |
|
3273 #endif |
|
3274 for (;;) |
|
3275 { |
|
3276 #ifdef WITH_IPV6 |
|
3277 if (connect((SOAP_SOCKET)fd, res->ai_addr, res->ai_addrlen)) |
|
3278 #else |
|
3279 if (connect((SOAP_SOCKET)fd, (struct sockaddr*)&soap->peer, sizeof(soap->peer))) |
|
3280 #endif |
|
3281 { |
|
3282 #ifndef WITH_LEAN |
|
3283 if (soap->connect_timeout && (soap_socket_errno == SOAP_EINPROGRESS || soap_socket_errno == SOAP_EWOULDBLOCK)) |
|
3284 { struct timeval timeout; |
|
3285 SOAP_SOCKLEN_T k; |
|
3286 fd_set fds; |
|
3287 if (soap->connect_timeout > 0) |
|
3288 { timeout.tv_sec = soap->connect_timeout; |
|
3289 timeout.tv_usec = 0; |
|
3290 } |
|
3291 else |
|
3292 { timeout.tv_sec = -soap->connect_timeout/1000000; |
|
3293 timeout.tv_usec = -soap->connect_timeout%1000000; |
|
3294 } |
|
3295 FD_ZERO(&fds); |
|
3296 FD_SET((SOAP_SOCKET)fd, &fds); |
|
3297 for (;;) |
|
3298 { int r = select((SOAP_SOCKET)(fd + 1), NULL, &fds, NULL, &timeout); |
|
3299 if (r > 0) |
|
3300 break; |
|
3301 if (!r) |
|
3302 { soap->errnum = 0; |
|
3303 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n")); |
|
3304 soap_set_sender_error(soap, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR); |
|
3305 soap->fclosesocket(soap, (SOAP_SOCKET)fd); |
|
3306 return SOAP_INVALID_SOCKET; |
|
3307 } |
|
3308 if (soap_socket_errno != SOAP_EINTR) |
|
3309 { soap->errnum = soap_socket_errno; |
|
3310 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); |
|
3311 soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR); |
|
3312 soap->fclosesocket(soap, (SOAP_SOCKET)fd); |
|
3313 return SOAP_INVALID_SOCKET; |
|
3314 } |
|
3315 } |
|
3316 k = (SOAP_SOCKLEN_T)sizeof(soap->errnum); |
|
3317 if (!getsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_ERROR, (char*)&soap->errnum, &k) && !soap->errnum) /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */ |
|
3318 break; |
|
3319 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); |
|
3320 soap->errnum = soap_socket_errno; |
|
3321 soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR); |
|
3322 soap->fclosesocket(soap, (SOAP_SOCKET)fd); |
|
3323 return SOAP_INVALID_SOCKET; |
|
3324 } |
|
3325 else |
|
3326 #endif |
|
3327 #ifdef WITH_IPV6 |
|
3328 if (res->ai_next) |
|
3329 { res = res->ai_next; |
|
3330 soap->fclosesocket(soap, (SOAP_SOCKET)fd); |
|
3331 goto again; |
|
3332 } |
|
3333 else |
|
3334 #endif |
|
3335 if (soap_socket_errno != SOAP_EINTR) |
|
3336 { soap->errnum = soap_socket_errno; |
|
3337 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); |
|
3338 soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR); |
|
3339 soap->fclosesocket(soap, (SOAP_SOCKET)fd); |
|
3340 return SOAP_INVALID_SOCKET; |
|
3341 } |
|
3342 } |
|
3343 else |
|
3344 break; |
|
3345 } |
|
3346 #ifdef WITH_IPV6 |
|
3347 soap->peerlen = 0; /* IPv6: already connected so use send() */ |
|
3348 freeaddrinfo(ressave); |
|
3349 #endif |
|
3350 #ifndef WITH_LEAN |
|
3351 if (soap->connect_timeout) |
|
3352 #if defined(WIN32) |
|
3353 { u_long blocking = 0; |
|
3354 ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &blocking); |
|
3355 } |
|
3356 #elif defined(VXWORKS) |
|
3357 { vx_nonblocking = FALSE; |
|
3358 ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&vx_nonblocking)); /* modified to use fd */ |
|
3359 } |
|
3360 #else |
|
3361 fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)&~O_NONBLOCK); |
|
3362 #endif |
|
3363 #endif |
|
3364 soap->socket = fd; |
|
3365 soap->imode &= ~SOAP_ENC_SSL; |
|
3366 soap->omode &= ~SOAP_ENC_SSL; |
|
3367 if (!strncmp(endpoint, "https:", 6)) |
|
3368 { |
|
3369 #ifdef WITH_OPENSSL |
|
3370 BIO *bio; |
|
3371 int r; |
|
3372 if (soap->proxy_host) |
|
3373 { short v; |
|
3374 unsigned int k = soap->omode; /* make sure we only parse HTTP */ |
|
3375 size_t n = soap->count; /* save the content length */ |
|
3376 soap->omode &= ~SOAP_ENC; /* mask IO and ENC */ |
|
3377 soap->omode |= SOAP_IO_BUFFER; |
|
3378 soap_begin_send(soap); |
|
3379 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connecting to proxy server\n")); |
|
3380 sprintf(soap->tmpbuf, "CONNECT %s:%d HTTP/%s", host, port, soap->http_version); |
|
3381 if ((soap->error = soap->fposthdr(soap, soap->tmpbuf, NULL))) |
|
3382 return SOAP_INVALID_SOCKET; |
|
3383 #ifndef WITH_LEAN |
|
3384 if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761) |
|
3385 { sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd); |
|
3386 strcpy(soap->tmpbuf, "Basic "); |
|
3387 soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, strlen(soap->tmpbuf + 262)); |
|
3388 if ((soap->error = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf))) |
|
3389 return soap->error; |
|
3390 } |
|
3391 #endif |
|
3392 if ((soap->error = soap->fposthdr(soap, NULL, NULL)) |
|
3393 || soap_flush(soap)) |
|
3394 return SOAP_INVALID_SOCKET; |
|
3395 soap->omode = k; |
|
3396 k = soap->imode; |
|
3397 soap->imode &= ~SOAP_ENC; /* mask IO and ENC */ |
|
3398 v = soap->version; /* preserve */ |
|
3399 if (soap_begin_recv(soap)) |
|
3400 return SOAP_INVALID_SOCKET; |
|
3401 soap->version = v; /* restore */ |
|
3402 soap->imode = k; /* restore */ |
|
3403 soap->count = n; /* restore */ |
|
3404 soap_begin_send(soap); |
|
3405 } |
|
3406 if (!soap->ctx && (soap->error = soap->fsslauth(soap))) |
|
3407 { soap_set_sender_error(soap, "SSL error", "SSL authentication failed in tcp_connect(): check password, key file, and ca file.", SOAP_SSL_ERROR); |
|
3408 return SOAP_INVALID_SOCKET; |
|
3409 } |
|
3410 soap->ssl = SSL_new(soap->ctx); |
|
3411 if (!soap->ssl) |
|
3412 { soap->error = SOAP_SSL_ERROR; |
|
3413 return SOAP_INVALID_SOCKET; |
|
3414 } |
|
3415 if (soap->session) |
|
3416 { if (!strcmp(soap->session_host, host) && soap->session_port == port) |
|
3417 SSL_set_session(soap->ssl, soap->session); |
|
3418 SSL_SESSION_free(soap->session); |
|
3419 soap->session = NULL; |
|
3420 } |
|
3421 soap->imode |= SOAP_ENC_SSL; |
|
3422 soap->omode |= SOAP_ENC_SSL; |
|
3423 bio = BIO_new_socket((SOAP_SOCKET)fd, BIO_NOCLOSE); |
|
3424 SSL_set_bio(soap->ssl, bio, bio); |
|
3425 #ifndef WITH_LEAN |
|
3426 if (soap->connect_timeout) |
|
3427 #ifdef WIN32 |
|
3428 { u_long nonblocking = 1; |
|
3429 ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &nonblocking); |
|
3430 } |
|
3431 #else |
|
3432 fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)|O_NONBLOCK); |
|
3433 #endif |
|
3434 #endif |
|
3435 for (;;) |
|
3436 { if ((r = SSL_connect(soap->ssl)) <= 0) |
|
3437 { int err = SSL_get_error(soap->ssl, r); |
|
3438 if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) |
|
3439 { soap_set_sender_error(soap, ssl_error(soap, r), "SSL connect failed in tcp_connect()", SOAP_SSL_ERROR); |
|
3440 return SOAP_INVALID_SOCKET; |
|
3441 } |
|
3442 if (soap->connect_timeout) |
|
3443 { struct timeval timeout; |
|
3444 fd_set fds; |
|
3445 if (soap->connect_timeout > 0) |
|
3446 { timeout.tv_sec = soap->connect_timeout; |
|
3447 timeout.tv_usec = 0; |
|
3448 } |
|
3449 else |
|
3450 { timeout.tv_sec = -soap->connect_timeout/1000000; |
|
3451 timeout.tv_usec = -soap->connect_timeout%1000000; |
|
3452 } |
|
3453 FD_ZERO(&fds); |
|
3454 FD_SET((SOAP_SOCKET)soap->socket, &fds); |
|
3455 for (;;) |
|
3456 { int r = select((SOAP_SOCKET)(soap->socket + 1), &fds, NULL, &fds, &timeout); |
|
3457 if (r > 0) |
|
3458 break; |
|
3459 if (!r) |
|
3460 { soap->errnum = 0; |
|
3461 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n")); |
|
3462 soap_set_sender_error(soap, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR); |
|
3463 return SOAP_INVALID_SOCKET; |
|
3464 } |
|
3465 } |
|
3466 continue; |
|
3467 } |
|
3468 } |
|
3469 break; |
|
3470 } |
|
3471 #ifndef WITH_LEAN |
|
3472 if (soap->connect_timeout) |
|
3473 #ifdef WIN32 |
|
3474 { u_long blocking = 0; |
|
3475 ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &blocking); |
|
3476 } |
|
3477 #else |
|
3478 fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)&~O_NONBLOCK); |
|
3479 #endif |
|
3480 #endif |
|
3481 if (soap->require_server_auth) |
|
3482 { X509 *peer; |
|
3483 int err; |
|
3484 if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK) |
|
3485 { soap_set_sender_error(soap, X509_verify_cert_error_string(err), "SSL certificate presented by peer cannot be verified in tcp_connect()", SOAP_SSL_ERROR); |
|
3486 return SOAP_INVALID_SOCKET; |
|
3487 } |
|
3488 peer = SSL_get_peer_certificate(soap->ssl); |
|
3489 if (!peer) |
|
3490 { soap_set_sender_error(soap, "SSL error", "No SSL certificate was presented by the peer in tcp_connect()", SOAP_SSL_ERROR); |
|
3491 return SOAP_INVALID_SOCKET; |
|
3492 } |
|
3493 X509_NAME_get_text_by_NID(X509_get_subject_name(peer), NID_commonName, soap->msgbuf, sizeof(soap->msgbuf)); |
|
3494 X509_free(peer); |
|
3495 if (soap_tag_cmp(soap->msgbuf, host)) |
|
3496 { soap_set_sender_error(soap, "SSL error", "SSL certificate host name mismatch in tcp_connect()", SOAP_SSL_ERROR); |
|
3497 return SOAP_INVALID_SOCKET; |
|
3498 } |
|
3499 } |
|
3500 #else |
|
3501 soap->error = SOAP_SSL_ERROR; |
|
3502 return SOAP_INVALID_SOCKET; |
|
3503 #endif |
|
3504 } |
|
3505 return fd; |
|
3506 } |
|
3507 #endif |
|
3508 #endif |
|
3509 |
|
3510 /******************************************************************************/ |
|
3511 #ifndef WITH_NOIO |
|
3512 #ifndef PALM_1 |
|
3513 SOAP_FMAC1 |
|
3514 int |
|
3515 SOAP_FMAC2 |
|
3516 soap_bind(struct soap *soap, const char *host, int port, int backlog) |
|
3517 { |
|
3518 #ifdef WITH_IPV6 |
|
3519 struct addrinfo *addrinfo; |
|
3520 struct addrinfo hints; |
|
3521 struct addrinfo res; |
|
3522 int err; |
|
3523 #endif |
|
3524 #ifndef WITH_LEAN |
|
3525 int len = SOAP_BUFLEN; |
|
3526 int set = 1; |
|
3527 #endif |
|
3528 if (soap_valid_socket(soap->master)) |
|
3529 { soap->fclosesocket(soap, (SOAP_SOCKET)soap->master); |
|
3530 soap->master = SOAP_INVALID_SOCKET; |
|
3531 } |
|
3532 soap->socket = SOAP_INVALID_SOCKET; |
|
3533 soap->errmode = 1; |
|
3534 if (tcp_init(soap)) |
|
3535 { soap_set_receiver_error(soap, tcp_error(soap), "TCP init failed in soap_bind()", SOAP_TCP_ERROR); |
|
3536 return SOAP_INVALID_SOCKET; |
|
3537 } |
|
3538 #ifdef WITH_IPV6 |
|
3539 memset((void*)&hints, 0, sizeof(hints)); |
|
3540 hints.ai_family = PF_UNSPEC; |
|
3541 #ifdef WITH_UDP |
|
3542 if ((soap->omode & SOAP_IO_UDP)) |
|
3543 hints.ai_socktype = SOCK_DGRAM; |
|
3544 else |
|
3545 #endif |
|
3546 hints.ai_socktype = SOCK_STREAM; |
|
3547 hints.ai_flags = AI_PASSIVE; |
|
3548 soap->errmode = 2; |
|
3549 err = getaddrinfo(host, soap_int2s(soap, port), &hints, &addrinfo); |
|
3550 if (addrinfo) |
|
3551 { res = *addrinfo; |
|
3552 soap->peer = *((struct sockaddr_storage*)addrinfo->ai_addr); |
|
3553 soap->peerlen = addrinfo->ai_addrlen; |
|
3554 res.ai_addr = (struct sockaddr*)&soap->peer; |
|
3555 res.ai_addrlen = soap->peerlen; |
|
3556 freeaddrinfo(addrinfo); |
|
3557 } |
|
3558 if (err) |
|
3559 { soap_set_receiver_error(soap, gai_strerror(err), "getaddrinfo failed in soap_bind()", SOAP_TCP_ERROR); |
|
3560 return SOAP_INVALID_SOCKET; |
|
3561 } |
|
3562 soap->master = socket(res.ai_family, res.ai_socktype, res.ai_protocol); |
|
3563 #else |
|
3564 #ifdef WITH_UDP |
|
3565 if ((soap->omode & SOAP_IO_UDP)) |
|
3566 soap->master = (int)socket(AF_INET, SOCK_DGRAM, 0); |
|
3567 else |
|
3568 #endif |
|
3569 soap->master = (int)socket(AF_INET, SOCK_STREAM, 0); |
|
3570 #endif |
|
3571 soap->errmode = 0; |
|
3572 if (!soap_valid_socket(soap->master)) |
|
3573 { soap->errnum = soap_socket_errno; |
|
3574 soap_set_receiver_error(soap, tcp_error(soap), "socket failed in soap_bind()", SOAP_TCP_ERROR); |
|
3575 return SOAP_INVALID_SOCKET; |
|
3576 } |
|
3577 #ifdef WITH_UDP |
|
3578 if ((soap->omode & SOAP_IO_UDP)) |
|
3579 soap->socket = soap->master; |
|
3580 #endif |
|
3581 #ifdef SOCKET_CLOSE_ON_EXEC |
|
3582 #ifdef WIN32 |
|
3583 #ifndef UNDER_CE |
|
3584 SetHandleInformation((HANDLE)soap->master, HANDLE_FLAG_INHERIT, 0); |
|
3585 #endif |
|
3586 #else |
|
3587 fcntl(soap->master, F_SETFD, 1); |
|
3588 #endif |
|
3589 #endif |
|
3590 #ifndef WITH_LEAN |
|
3591 if (soap->bind_flags && setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, soap->bind_flags, (char*)&set, sizeof(int))) |
|
3592 { soap->errnum = soap_socket_errno; |
|
3593 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_bind()", SOAP_TCP_ERROR); |
|
3594 return SOAP_INVALID_SOCKET; |
|
3595 } |
|
3596 if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) |
|
3597 { soap->errnum = soap_socket_errno; |
|
3598 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_bind()", SOAP_TCP_ERROR); |
|
3599 return SOAP_INVALID_SOCKET; |
|
3600 } |
|
3601 if (setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) |
|
3602 { soap->errnum = soap_socket_errno; |
|
3603 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_bind()", SOAP_TCP_ERROR); |
|
3604 return SOAP_INVALID_SOCKET; |
|
3605 } |
|
3606 if (setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) |
|
3607 { soap->errnum = soap_socket_errno; |
|
3608 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_bind()", SOAP_TCP_ERROR); |
|
3609 return SOAP_INVALID_SOCKET; |
|
3610 } |
|
3611 #ifdef TCP_NODELAY |
|
3612 if (!(soap->omode & SOAP_IO_UDP) && setsockopt((SOAP_SOCKET)soap->master, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) |
|
3613 { soap->errnum = soap_socket_errno; |
|
3614 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_bind()", SOAP_TCP_ERROR); |
|
3615 return SOAP_INVALID_SOCKET; |
|
3616 } |
|
3617 #endif |
|
3618 #endif |
|
3619 #ifdef WITH_IPV6 |
|
3620 soap->errmode = 0; |
|
3621 if (bind((SOAP_SOCKET)soap->master, res.ai_addr, res.ai_addrlen)) |
|
3622 { soap->errnum = soap_socket_errno; |
|
3623 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n")); |
|
3624 soap_closesock(soap); |
|
3625 soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR); |
|
3626 return SOAP_INVALID_SOCKET; |
|
3627 } |
|
3628 #else |
|
3629 soap->peerlen = sizeof(soap->peer); |
|
3630 memset((void*)&soap->peer, 0, sizeof(soap->peer)); |
|
3631 soap->peer.sin_family = AF_INET; |
|
3632 soap->errmode = 2; |
|
3633 if (host) |
|
3634 { if (soap->fresolve(soap, host, &soap->peer.sin_addr)) |
|
3635 { soap_set_receiver_error(soap, tcp_error(soap), "get host by name failed in soap_bind()", SOAP_TCP_ERROR); |
|
3636 return SOAP_INVALID_SOCKET; |
|
3637 } |
|
3638 } |
|
3639 else |
|
3640 soap->peer.sin_addr.s_addr = htonl(INADDR_ANY); |
|
3641 soap->peer.sin_port = htons((short)port); |
|
3642 soap->errmode = 0; |
|
3643 if (bind((SOAP_SOCKET)soap->master, (struct sockaddr*)&soap->peer, soap->peerlen)) |
|
3644 { soap->errnum = soap_socket_errno; |
|
3645 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n")); |
|
3646 soap_closesock(soap); |
|
3647 soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR); |
|
3648 return SOAP_INVALID_SOCKET; |
|
3649 } |
|
3650 #endif |
|
3651 if (!(soap->omode & SOAP_IO_UDP) && listen((SOAP_SOCKET)soap->master, backlog)) |
|
3652 { soap->errnum = soap_socket_errno; |
|
3653 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n")); |
|
3654 soap_closesock(soap); |
|
3655 soap_set_receiver_error(soap, tcp_error(soap), "listen failed in soap_bind()", SOAP_TCP_ERROR); |
|
3656 return SOAP_INVALID_SOCKET; |
|
3657 } |
|
3658 return soap->master; |
|
3659 } |
|
3660 #endif |
|
3661 #endif |
|
3662 |
|
3663 /******************************************************************************/ |
|
3664 #ifndef WITH_NOIO |
|
3665 #ifndef PALM_1 |
|
3666 SOAP_FMAC1 |
|
3667 int |
|
3668 SOAP_FMAC2 |
|
3669 soap_poll(struct soap *soap) |
|
3670 { |
|
3671 #ifndef WITH_LEAN |
|
3672 struct timeval timeout; |
|
3673 fd_set rfd, sfd, xfd; |
|
3674 int r; |
|
3675 timeout.tv_sec = 0; |
|
3676 timeout.tv_usec = 0; |
|
3677 FD_ZERO(&rfd); |
|
3678 FD_ZERO(&sfd); |
|
3679 FD_ZERO(&xfd); |
|
3680 if (soap_valid_socket(soap->socket)) |
|
3681 { FD_SET((SOAP_SOCKET)soap->socket, &rfd); |
|
3682 FD_SET((SOAP_SOCKET)soap->socket, &sfd); |
|
3683 FD_SET((SOAP_SOCKET)soap->socket, &xfd); |
|
3684 r = select((SOAP_SOCKET)(soap->socket + 1), &rfd, &sfd, &xfd, &timeout); |
|
3685 if (r > 0 && FD_ISSET((SOAP_SOCKET)soap->socket, &xfd)) |
|
3686 r = -1; |
|
3687 } |
|
3688 else if (soap_valid_socket(soap->master)) |
|
3689 { FD_SET((SOAP_SOCKET)soap->master, &sfd); |
|
3690 r = select((SOAP_SOCKET)(soap->master + 1), NULL, &sfd, NULL, &timeout); |
|
3691 } |
|
3692 else |
|
3693 return SOAP_OK; |
|
3694 if (r > 0) |
|
3695 { if (soap_valid_socket(soap->socket) |
|
3696 && FD_ISSET((SOAP_SOCKET)soap->socket, &sfd) |
|
3697 && (!FD_ISSET((SOAP_SOCKET)soap->socket, &rfd) |
|
3698 || recv((SOAP_SOCKET)soap->socket, soap->tmpbuf, 1, MSG_PEEK) > 0)) |
|
3699 return SOAP_OK; |
|
3700 } |
|
3701 else if (r < 0) |
|
3702 { soap->errnum = soap_socket_errno; |
|
3703 if ((soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) && soap_socket_errno != SOAP_EINTR) |
|
3704 { soap_set_receiver_error(soap, tcp_error(soap), "select failed in soap_poll()", SOAP_TCP_ERROR); |
|
3705 return soap->error = SOAP_TCP_ERROR; |
|
3706 } |
|
3707 } |
|
3708 else |
|
3709 soap->errnum = 0; |
|
3710 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Polling: other end down on socket=%d select=%d\n", soap->socket, r)); |
|
3711 return SOAP_EOF; |
|
3712 #else |
|
3713 return SOAP_OK; |
|
3714 #endif |
|
3715 } |
|
3716 #endif |
|
3717 #endif |
|
3718 |
|
3719 /******************************************************************************/ |
|
3720 #ifndef WITH_NOIO |
|
3721 #ifndef PALM_1 |
|
3722 static int |
|
3723 tcp_accept(struct soap *soap, int s, struct sockaddr *a, int *n) |
|
3724 { int fd; |
|
3725 fd = (int)accept((SOAP_SOCKET)s, a, (SOAP_SOCKLEN_T*)n); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */ |
|
3726 #ifdef SOCKET_CLOSE_ON_EXEC |
|
3727 #ifdef WIN32 |
|
3728 #ifndef UNDER_CE |
|
3729 SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0); |
|
3730 #endif |
|
3731 #else |
|
3732 fcntl(fd, F_SETFD, FD_CLOEXEC); |
|
3733 #endif |
|
3734 #endif |
|
3735 return fd; |
|
3736 } |
|
3737 #endif |
|
3738 #endif |
|
3739 |
|
3740 /******************************************************************************/ |
|
3741 #ifndef WITH_NOIO |
|
3742 #ifndef PALM_1 |
|
3743 SOAP_FMAC1 |
|
3744 int |
|
3745 SOAP_FMAC2 |
|
3746 soap_accept(struct soap *soap) |
|
3747 { int n = (int)sizeof(soap->peer); |
|
3748 #ifndef WITH_LEAN |
|
3749 int len = SOAP_BUFLEN; |
|
3750 int set = 1; |
|
3751 #endif |
|
3752 soap->error = SOAP_OK; |
|
3753 #ifdef WITH_UDP |
|
3754 if ((soap->omode & SOAP_IO_UDP)) |
|
3755 return soap->socket = soap->master; |
|
3756 #endif |
|
3757 memset((void*)&soap->peer, 0, sizeof(soap->peer)); |
|
3758 soap->socket = SOAP_INVALID_SOCKET; |
|
3759 soap->errmode = 0; |
|
3760 soap->keep_alive = 0; |
|
3761 if (soap_valid_socket(soap->master)) |
|
3762 { for (;;) |
|
3763 { |
|
3764 #ifndef WITH_LEAN |
|
3765 if (soap->accept_timeout) |
|
3766 { struct timeval timeout; |
|
3767 fd_set fd; |
|
3768 if (soap->accept_timeout > 0) |
|
3769 { timeout.tv_sec = soap->accept_timeout; |
|
3770 timeout.tv_usec = 0; |
|
3771 } |
|
3772 else |
|
3773 { timeout.tv_sec = -soap->accept_timeout/1000000; |
|
3774 timeout.tv_usec = -soap->accept_timeout%1000000; |
|
3775 } |
|
3776 FD_ZERO(&fd); |
|
3777 FD_SET((SOAP_SOCKET)soap->master, &fd); |
|
3778 for (;;) |
|
3779 { int r = select((SOAP_SOCKET)(soap->master + 1), &fd, &fd, NULL, &timeout); |
|
3780 if (r > 0) |
|
3781 break; |
|
3782 if (!r) |
|
3783 { soap->errnum = 0; |
|
3784 soap_set_receiver_error(soap, "Timeout", "accept failed in soap_accept()", SOAP_TCP_ERROR); |
|
3785 return SOAP_INVALID_SOCKET; |
|
3786 } |
|
3787 if (soap_socket_errno != SOAP_EINTR) |
|
3788 { soap->errnum = soap_socket_errno; |
|
3789 soap_closesock(soap); |
|
3790 soap_set_sender_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR); |
|
3791 return SOAP_INVALID_SOCKET; |
|
3792 } |
|
3793 } |
|
3794 #if defined(WIN32) |
|
3795 { u_long nonblocking = 1; |
|
3796 ioctlsocket((SOAP_SOCKET)soap->master, FIONBIO, &nonblocking); |
|
3797 } |
|
3798 #elif defined(VXWORKS) |
|
3799 { vx_nonblocking = TRUE; |
|
3800 ioctl((SOAP_SOCKET)soap->master, FIONBIO, (int)(&vx_nonblocking)); |
|
3801 } |
|
3802 #else |
|
3803 fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL)|O_NONBLOCK); |
|
3804 #endif |
|
3805 } |
|
3806 else |
|
3807 #if defined(WIN32) |
|
3808 { u_long blocking = 0; |
|
3809 ioctlsocket((SOAP_SOCKET)soap->master, FIONBIO, &blocking); |
|
3810 } |
|
3811 #elif defined(VXWORKS) |
|
3812 { vx_nonblocking = FALSE; |
|
3813 ioctl((SOAP_SOCKET)soap->master, FIONBIO, (int)(&vx_nonblocking)); |
|
3814 } |
|
3815 #else |
|
3816 fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL)&~O_NONBLOCK); |
|
3817 #endif |
|
3818 #endif |
|
3819 soap->socket = soap->faccept(soap, soap->master, (struct sockaddr*)&soap->peer, &n); |
|
3820 soap->peerlen = (size_t)n; |
|
3821 if (soap_valid_socket(soap->socket)) |
|
3822 { |
|
3823 #ifdef WITH_IPV6 |
|
3824 /* Use soap->host to store the numeric form of the remote host */ |
|
3825 getnameinfo((struct sockaddr*)&soap->peer, n, soap->host, sizeof(soap->host), NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV); |
|
3826 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket %d from %s\n", soap->socket, soap->host)); |
|
3827 soap->ip = 0; /* info stored in soap->peer and soap->host */ |
|
3828 soap->port = 0; /* info stored in soap->peer and soap->host */ |
|
3829 #else |
|
3830 soap->ip = ntohl(soap->peer.sin_addr.s_addr); |
|
3831 soap->port = (int)ntohs(soap->peer.sin_port); /* does not return port number on some systems */ |
|
3832 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket %d at port %d from IP %d.%d.%d.%d\n", soap->socket, soap->port, (int)(soap->ip>>24)&0xFF, (int)(soap->ip>>16)&0xFF, (int)(soap->ip>>8)&0xFF, (int)soap->ip&0xFF)); |
|
3833 #endif |
|
3834 #ifndef WITH_LEAN |
|
3835 if (soap->accept_flags & SO_LINGER) |
|
3836 { struct linger linger; |
|
3837 memset((void*)&linger, 0, sizeof(linger)); |
|
3838 linger.l_onoff = 1; |
|
3839 linger.l_linger = 0; |
|
3840 if (setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger))) |
|
3841 { soap->errnum = soap_socket_errno; |
|
3842 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in soap_accept()", SOAP_TCP_ERROR); |
|
3843 soap_closesock(soap); |
|
3844 return SOAP_INVALID_SOCKET; |
|
3845 } |
|
3846 } |
|
3847 if ((soap->accept_flags & ~SO_LINGER) && setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, soap->accept_flags & ~SO_LINGER, (char*)&set, sizeof(int))) |
|
3848 { soap->errnum = soap_socket_errno; |
|
3849 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_accept()", SOAP_TCP_ERROR); |
|
3850 soap_closesock(soap); |
|
3851 return SOAP_INVALID_SOCKET; |
|
3852 } |
|
3853 if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) |
|
3854 { soap->errnum = soap_socket_errno; |
|
3855 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_accept()", SOAP_TCP_ERROR); |
|
3856 soap_closesock(soap); |
|
3857 return SOAP_INVALID_SOCKET; |
|
3858 } |
|
3859 if (setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) |
|
3860 { soap->errnum = soap_socket_errno; |
|
3861 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_accept()", SOAP_TCP_ERROR); |
|
3862 soap_closesock(soap); |
|
3863 return SOAP_INVALID_SOCKET; |
|
3864 } |
|
3865 if (setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) |
|
3866 { soap->errnum = soap_socket_errno; |
|
3867 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_accept()", SOAP_TCP_ERROR); |
|
3868 soap_closesock(soap); |
|
3869 return SOAP_INVALID_SOCKET; |
|
3870 } |
|
3871 #ifdef TCP_NODELAY |
|
3872 if (!(soap->omode & SOAP_IO_UDP) && setsockopt((SOAP_SOCKET)soap->socket, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) |
|
3873 { soap->errnum = soap_socket_errno; |
|
3874 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_accept()", SOAP_TCP_ERROR); |
|
3875 soap_closesock(soap); |
|
3876 return SOAP_INVALID_SOCKET; |
|
3877 } |
|
3878 #endif |
|
3879 #endif |
|
3880 if (soap->accept_timeout) |
|
3881 { |
|
3882 #if defined(WIN32) |
|
3883 u_long blocking = 0; |
|
3884 ioctlsocket((SOAP_SOCKET)soap->master, FIONBIO, &blocking); |
|
3885 ioctlsocket((SOAP_SOCKET)soap->socket, FIONBIO, &blocking); |
|
3886 #elif defined(VXWORKS) |
|
3887 vx_nonblocking = FALSE; |
|
3888 ioctl((SOAP_SOCKET)soap->master, FIONBIO, (int)(&vx_nonblocking)); |
|
3889 ioctl((SOAP_SOCKET)soap->socket, FIONBIO, (int)(&vx_nonblocking)); |
|
3890 #elif defined(PALM) |
|
3891 fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL,0)&~O_NONBLOCK); |
|
3892 fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL,0)&~O_NONBLOCK); |
|
3893 #elif defined(SYMBIAN) |
|
3894 long blocking = 0; |
|
3895 ioctl((SOAP_SOCKET)soap->master, 0/*FIONBIO*/, &blocking); |
|
3896 #else |
|
3897 fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL)&~O_NONBLOCK); |
|
3898 fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL)&~O_NONBLOCK); |
|
3899 #endif |
|
3900 } |
|
3901 soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0); |
|
3902 return soap->socket; |
|
3903 } |
|
3904 if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EAGAIN) |
|
3905 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept failed from %s\n", soap->host)); |
|
3906 soap->errnum = soap_socket_errno; |
|
3907 soap_set_receiver_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR); |
|
3908 soap_closesock(soap); |
|
3909 return SOAP_INVALID_SOCKET; |
|
3910 } |
|
3911 } |
|
3912 } |
|
3913 else |
|
3914 { soap->errnum = 0; |
|
3915 soap_set_receiver_error(soap, tcp_error(soap), "no master socket in soap_accept()", SOAP_TCP_ERROR); |
|
3916 return SOAP_INVALID_SOCKET; |
|
3917 } |
|
3918 } |
|
3919 #endif |
|
3920 #endif |
|
3921 |
|
3922 /******************************************************************************/ |
|
3923 #ifndef WITH_NOIO |
|
3924 #ifndef PALM_1 |
|
3925 static int |
|
3926 tcp_disconnect(struct soap *soap) |
|
3927 { |
|
3928 #ifdef WITH_OPENSSL |
|
3929 if (soap->ssl) |
|
3930 { int r, s = 0; |
|
3931 if (soap->session) |
|
3932 SSL_SESSION_free(soap->session); |
|
3933 if (*soap->host) |
|
3934 { soap->session = SSL_get1_session(soap->ssl); |
|
3935 if (soap->session) |
|
3936 { strcpy(soap->session_host, soap->host); |
|
3937 soap->session_port = soap->port; |
|
3938 } |
|
3939 } |
|
3940 r = SSL_shutdown(soap->ssl); |
|
3941 if (r != 1) |
|
3942 { s = ERR_get_error(); |
|
3943 if (s) |
|
3944 { if (soap_valid_socket(soap->socket)) |
|
3945 { soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 1); |
|
3946 soap->socket = SOAP_INVALID_SOCKET; |
|
3947 } |
|
3948 r = SSL_shutdown(soap->ssl); |
|
3949 } |
|
3950 } |
|
3951 DBGLOG(TEST, if (s) SOAP_MESSAGE(fdebug, "Shutdown failed: %d\n", SSL_get_error(soap->ssl, r))); |
|
3952 SSL_free(soap->ssl); |
|
3953 soap->ssl = NULL; |
|
3954 if (s) |
|
3955 return SOAP_SSL_ERROR; |
|
3956 ERR_remove_state(0); |
|
3957 } |
|
3958 #endif |
|
3959 if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP)) |
|
3960 { soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 2); |
|
3961 soap->fclosesocket(soap, (SOAP_SOCKET)soap->socket); |
|
3962 soap->socket = SOAP_INVALID_SOCKET; |
|
3963 } |
|
3964 return SOAP_OK; |
|
3965 } |
|
3966 #endif |
|
3967 #endif |
|
3968 |
|
3969 /******************************************************************************/ |
|
3970 #ifndef WITH_NOIO |
|
3971 #ifndef PALM_1 |
|
3972 static int |
|
3973 tcp_closesocket(struct soap *soap, SOAP_SOCKET fd) |
|
3974 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Close socket %d\n", (int)fd)); |
|
3975 return closesocket(fd); |
|
3976 } |
|
3977 #endif |
|
3978 #endif |
|
3979 |
|
3980 /******************************************************************************/ |
|
3981 #ifndef WITH_NOIO |
|
3982 #ifndef PALM_1 |
|
3983 static int |
|
3984 tcp_shutdownsocket(struct soap *soap, SOAP_SOCKET fd, int how) |
|
3985 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown socket %d how=%d\n", (int)fd, how)); |
|
3986 //return shutdown(fd, how); |
|
3987 return how==SD_BOTH?shutdown(fd, how):0; |
|
3988 } |
|
3989 #endif |
|
3990 #endif |
|
3991 |
|
3992 /******************************************************************************/ |
|
3993 #ifndef PALM_1 |
|
3994 SOAP_FMAC1 |
|
3995 int |
|
3996 SOAP_FMAC2 |
|
3997 soap_closesock(struct soap *soap) |
|
3998 { register int status = soap->error; |
|
3999 if (status == SOAP_EOF || status == SOAP_TCP_ERROR || status == SOAP_SSL_ERROR || !soap->keep_alive) |
|
4000 { if (soap->fclose && (soap->error = soap->fclose(soap))) |
|
4001 return soap->error; |
|
4002 soap->keep_alive = 0; |
|
4003 } |
|
4004 #ifdef WITH_ZLIB |
|
4005 if (soap->zlib_state == SOAP_ZLIB_DEFLATE) |
|
4006 deflateEnd(&soap->d_stream); |
|
4007 else if (soap->zlib_state == SOAP_ZLIB_INFLATE) |
|
4008 inflateEnd(&soap->d_stream); |
|
4009 soap->zlib_state = SOAP_ZLIB_NONE; |
|
4010 #endif |
|
4011 return soap->error = status; |
|
4012 } |
|
4013 #endif |
|
4014 |
|
4015 /******************************************************************************/ |
|
4016 #ifndef WITH_NOIDREF |
|
4017 #ifndef PALM_2 |
|
4018 SOAP_FMAC1 |
|
4019 size_t |
|
4020 SOAP_FMAC2 |
|
4021 soap_hash(register const char *s) |
|
4022 { register size_t h = 0; |
|
4023 while (*s) |
|
4024 h = 65599*h + *s++; |
|
4025 return h % SOAP_IDHASH; |
|
4026 } |
|
4027 #endif |
|
4028 #endif |
|
4029 |
|
4030 /******************************************************************************/ |
|
4031 #ifndef WITH_NOIDREF |
|
4032 #ifndef PALM_1 |
|
4033 static void |
|
4034 soap_init_pht(struct soap *soap) |
|
4035 { register int i; |
|
4036 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing pointer hashtable\n")); |
|
4037 soap->pblk = NULL; |
|
4038 soap->pidx = 0; |
|
4039 for (i = 0; i < (int)SOAP_PTRHASH; i++) |
|
4040 soap->pht[i] = NULL; |
|
4041 } |
|
4042 #endif |
|
4043 #endif |
|
4044 |
|
4045 /******************************************************************************/ |
|
4046 #ifndef PALM_1 |
|
4047 SOAP_FMAC1 |
|
4048 struct soap* |
|
4049 SOAP_FMAC2 |
|
4050 soap_new1(soap_mode mode) |
|
4051 { return soap_new2(mode, mode); |
|
4052 } |
|
4053 #endif |
|
4054 |
|
4055 /******************************************************************************/ |
|
4056 #ifndef PALM_1 |
|
4057 SOAP_FMAC1 |
|
4058 struct soap* |
|
4059 SOAP_FMAC2 |
|
4060 soap_new() |
|
4061 { return soap_new2(SOAP_IO_DEFAULT, SOAP_IO_DEFAULT); |
|
4062 } |
|
4063 #endif |
|
4064 |
|
4065 /******************************************************************************/ |
|
4066 #ifndef PALM_1 |
|
4067 SOAP_FMAC1 |
|
4068 struct soap* |
|
4069 SOAP_FMAC2 |
|
4070 soap_new2(soap_mode imode, soap_mode omode) |
|
4071 { struct soap *soap = (struct soap*)malloc(sizeof(struct soap)); |
|
4072 if (soap) |
|
4073 soap_init2(soap, imode, omode); |
|
4074 return soap; |
|
4075 } |
|
4076 #endif |
|
4077 |
|
4078 /******************************************************************************/ |
|
4079 #ifndef WITH_NOIDREF |
|
4080 #ifndef PALM_1 |
|
4081 static void |
|
4082 soap_free_pht(struct soap *soap) |
|
4083 { register struct soap_pblk *pb, *next; |
|
4084 register int i; |
|
4085 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free pointer hashtable\n")); |
|
4086 for (pb = soap->pblk; pb; pb = next) |
|
4087 { next = pb->next; |
|
4088 SOAP_FREE(soap, pb); |
|
4089 } |
|
4090 soap->pblk = NULL; |
|
4091 soap->pidx = 0; |
|
4092 for (i = 0; i < (int)SOAP_PTRHASH; i++) |
|
4093 soap->pht[i] = NULL; |
|
4094 } |
|
4095 #endif |
|
4096 #endif |
|
4097 |
|
4098 /******************************************************************************/ |
|
4099 #ifndef WITH_NOIDREF |
|
4100 #ifndef PALM_2 |
|
4101 SOAP_FMAC1 |
|
4102 int |
|
4103 SOAP_FMAC2 |
|
4104 soap_embed(struct soap *soap, const void *p, const struct soap_array *a, int n, const char *tag, int type) |
|
4105 { register int i; |
|
4106 struct soap_plist *pp; |
|
4107 if (soap->version != 1) |
|
4108 soap->encoding = 1; |
|
4109 if (a) |
|
4110 i = soap_array_pointer_lookup(soap, p, a, n, type, &pp); |
|
4111 else |
|
4112 i = soap_pointer_lookup(soap, p, type, &pp); |
|
4113 if (i) |
|
4114 { if (soap_is_embedded(soap, pp) |
|
4115 || soap_is_single(soap, pp)) |
|
4116 return 0; |
|
4117 soap_set_embedded(soap, pp); |
|
4118 } |
|
4119 return i; |
|
4120 } |
|
4121 #endif |
|
4122 #endif |
|
4123 |
|
4124 /******************************************************************************/ |
|
4125 #ifndef WITH_NOIDREF |
|
4126 #ifndef PALM_2 |
|
4127 SOAP_FMAC1 |
|
4128 int |
|
4129 SOAP_FMAC2 |
|
4130 soap_pointer_lookup(struct soap *soap, const void *p, int type, struct soap_plist **ppp) |
|
4131 { register struct soap_plist *pp; |
|
4132 *ppp = NULL; |
|
4133 if (p) |
|
4134 { for (pp = soap->pht[soap_hash_ptr(p)]; pp; pp = pp->next) |
|
4135 { if (pp->ptr == p && pp->type == type) |
|
4136 { *ppp = pp; |
|
4137 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d id=%d\n", p, type, pp->id)); |
|
4138 return pp->id; |
|
4139 } |
|
4140 } |
|
4141 } |
|
4142 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d: not found\n", p, type)); |
|
4143 return 0; |
|
4144 } |
|
4145 #endif |
|
4146 #endif |
|
4147 |
|
4148 /******************************************************************************/ |
|
4149 #ifndef WITH_NOIDREF |
|
4150 #ifndef PALM_2 |
|
4151 SOAP_FMAC1 |
|
4152 int |
|
4153 SOAP_FMAC2 |
|
4154 soap_pointer_enter(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp) |
|
4155 { register int h; |
|
4156 register struct soap_plist *pp; |
|
4157 if (!soap->pblk || soap->pidx >= SOAP_PTRBLK) |
|
4158 { register struct soap_pblk *pb = (struct soap_pblk*)SOAP_MALLOC(soap, sizeof(struct soap_pblk)); |
|
4159 if (!pb) |
|
4160 { soap->error = SOAP_EOM; |
|
4161 return 0; |
|
4162 } |
|
4163 pb->next = soap->pblk; |
|
4164 soap->pblk = pb; |
|
4165 soap->pidx = 0; |
|
4166 } |
|
4167 *ppp = pp = &soap->pblk->plist[soap->pidx++]; |
|
4168 if (a) |
|
4169 h = soap_hash_ptr(a->__ptr); |
|
4170 else |
|
4171 h = soap_hash_ptr(p); |
|
4172 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)); |
|
4173 pp->next = soap->pht[h]; |
|
4174 pp->type = type; |
|
4175 pp->mark1 = 0; |
|
4176 pp->mark2 = 0; |
|
4177 pp->ptr = p; |
|
4178 pp->array = a; |
|
4179 soap->pht[h] = pp; |
|
4180 pp->id = ++soap->idnum; |
|
4181 return pp->id; |
|
4182 } |
|
4183 #endif |
|
4184 #endif |
|
4185 |
|
4186 /******************************************************************************/ |
|
4187 #ifndef WITH_NOIDREF |
|
4188 #ifndef PALM_2 |
|
4189 SOAP_FMAC1 |
|
4190 int |
|
4191 SOAP_FMAC2 |
|
4192 soap_array_pointer_lookup(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp) |
|
4193 { register struct soap_plist *pp; |
|
4194 *ppp = NULL; |
|
4195 if (!p || !a->__ptr) |
|
4196 return 0; |
|
4197 for (pp = soap->pht[soap_hash_ptr(a->__ptr)]; pp; pp = pp->next) |
|
4198 { if (pp->type == type && pp->array && pp->array->__ptr == a->__ptr) |
|
4199 { register int i; |
|
4200 for (i = 0; i < n; i++) |
|
4201 if (((const int*)&pp->array->__size)[i] != ((const int*)&a->__size)[i]) |
|
4202 break; |
|
4203 if (i == n) |
|
4204 { *ppp = pp; |
|
4205 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d id=%d\n", a->__ptr, type, pp->id)); |
|
4206 return pp->id; |
|
4207 } |
|
4208 } |
|
4209 } |
|
4210 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d: not found\n", a->__ptr, type)); |
|
4211 return 0; |
|
4212 } |
|
4213 #endif |
|
4214 #endif |
|
4215 |
|
4216 /******************************************************************************/ |
|
4217 #ifndef PALM_1 |
|
4218 SOAP_FMAC1 |
|
4219 int |
|
4220 SOAP_FMAC2 |
|
4221 soap_begin_count(struct soap *soap) |
|
4222 { soap_clr_attr(soap); |
|
4223 soap_set_local_namespaces(soap); |
|
4224 #ifndef WITH_LEANER |
|
4225 if ((soap->mode & SOAP_ENC_DIME) || (soap->omode & SOAP_ENC_DIME)) |
|
4226 soap->mode = soap->omode | SOAP_IO_LENGTH | SOAP_ENC_DIME; |
|
4227 else |
|
4228 #endif |
|
4229 { soap->mode = soap->omode; |
|
4230 if ((soap->mode & SOAP_IO) == SOAP_IO_STORE |
|
4231 || (((soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_ENC_XML)) |
|
4232 #ifndef WITH_LEANER |
|
4233 && !soap->fpreparesend |
|
4234 #endif |
|
4235 )) |
|
4236 soap->mode &= ~SOAP_IO_LENGTH; |
|
4237 else |
|
4238 soap->mode |= SOAP_IO_LENGTH; |
|
4239 } |
|
4240 #ifdef WITH_ZLIB |
|
4241 if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH) |
|
4242 { if (!(soap->mode & SOAP_ENC_DIME)) |
|
4243 soap->mode &= ~SOAP_IO_LENGTH; |
|
4244 if (soap->mode & SOAP_ENC_XML) |
|
4245 soap->mode |= SOAP_IO_BUFFER; |
|
4246 else |
|
4247 soap->mode |= SOAP_IO_STORE; |
|
4248 } |
|
4249 #endif |
|
4250 if (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH)) |
|
4251 soap->mode |= SOAP_XML_TREE; |
|
4252 #ifndef WITH_LEANER |
|
4253 if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME)) |
|
4254 soap->mode |= SOAP_ENC_MIME; |
|
4255 else |
|
4256 soap->mode &= ~SOAP_ENC_MTOM; |
|
4257 if (soap->mode & SOAP_ENC_MIME) |
|
4258 soap_select_mime_boundary(soap); |
|
4259 soap->dime.list = soap->dime.last; /* keep track of last DIME attachment */ |
|
4260 #endif |
|
4261 soap->count = 0; |
|
4262 soap->ns = 0; |
|
4263 soap->null = 0; |
|
4264 soap->position = 0; |
|
4265 soap->mustUnderstand = 0; |
|
4266 soap->encoding = 0; |
|
4267 soap->part = SOAP_BEGIN; |
|
4268 soap->idnum = 0; |
|
4269 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin count phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count)); |
|
4270 #ifndef WITH_LEANER |
|
4271 soap->dime.count = 0; /* count # of attachments */ |
|
4272 soap->dime.size = 0; /* accumulate total size of attachments */ |
|
4273 if (soap->fprepareinit && (soap->mode & SOAP_IO) != SOAP_IO_STORE) |
|
4274 return soap->error = soap->fprepareinit(soap); |
|
4275 #endif |
|
4276 return SOAP_OK; |
|
4277 } |
|
4278 #endif |
|
4279 |
|
4280 /******************************************************************************/ |
|
4281 #ifndef PALM_1 |
|
4282 SOAP_FMAC1 |
|
4283 int |
|
4284 SOAP_FMAC2 |
|
4285 soap_end_count(struct soap *soap) |
|
4286 { |
|
4287 #ifndef WITH_LEANER |
|
4288 if (soap->fpreparefinal) |
|
4289 return soap->error = soap->fpreparefinal(soap); |
|
4290 #endif |
|
4291 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of count phase\n")); |
|
4292 return SOAP_OK; |
|
4293 } |
|
4294 #endif |
|
4295 |
|
4296 /******************************************************************************/ |
|
4297 #ifndef PALM_1 |
|
4298 SOAP_FMAC1 |
|
4299 int |
|
4300 SOAP_FMAC2 |
|
4301 soap_begin_send(struct soap *soap) |
|
4302 { soap->error = SOAP_OK; |
|
4303 soap_clr_attr(soap); |
|
4304 soap_set_local_namespaces(soap); |
|
4305 soap->mode = soap->omode | (soap->mode & (SOAP_IO_LENGTH | SOAP_ENC_DIME)); |
|
4306 #ifdef WITH_ZLIB |
|
4307 if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH) |
|
4308 { if (soap->mode & SOAP_ENC_XML) |
|
4309 soap->mode |= SOAP_IO_BUFFER; |
|
4310 else |
|
4311 soap->mode |= SOAP_IO_STORE; |
|
4312 } |
|
4313 #endif |
|
4314 #ifdef WITH_UDP |
|
4315 if ((soap->mode & SOAP_IO_UDP)) |
|
4316 { soap->mode |= SOAP_ENC_XML; |
|
4317 if (soap->count > SOAP_BUFLEN) |
|
4318 return soap->error = SOAP_UDP_ERROR; |
|
4319 } |
|
4320 #endif |
|
4321 if ((soap->mode & SOAP_IO) == SOAP_IO_FLUSH && soap_valid_socket(soap->socket)) |
|
4322 { if (soap->count || (soap->mode & SOAP_IO_LENGTH) || (soap->mode & SOAP_ENC_XML)) |
|
4323 soap->mode |= SOAP_IO_BUFFER; |
|
4324 else |
|
4325 soap->mode |= SOAP_IO_STORE; |
|
4326 } |
|
4327 soap->mode &= ~SOAP_IO_LENGTH; |
|
4328 if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) |
|
4329 soap_new_block(soap); |
|
4330 if (!(soap->mode & SOAP_IO_KEEPALIVE)) |
|
4331 soap->keep_alive = 0; |
|
4332 if (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH)) |
|
4333 soap->mode |= SOAP_XML_TREE; |
|
4334 #ifndef WITH_LEANER |
|
4335 if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME)) |
|
4336 { soap->mode |= SOAP_ENC_MIME; |
|
4337 soap->mode &= ~SOAP_ENC_DIME; |
|
4338 } |
|
4339 else |
|
4340 soap->mode &= ~SOAP_ENC_MTOM; |
|
4341 if (soap->mode & SOAP_ENC_MIME) |
|
4342 soap_select_mime_boundary(soap); |
|
4343 #ifdef WIN32 |
|
4344 #ifndef UNDER_CE |
|
4345 #ifndef WITH_FASTCGI |
|
4346 if (!soap_valid_socket(soap->socket)) /* Set win32 stdout or soap->sendfd to BINARY, e.g. to support DIME */ |
|
4347 #ifdef __BORLANDC__ |
|
4348 setmode((SOAP_SOCKET)soap->sendfd, O_BINARY); |
|
4349 #else |
|
4350 _setmode((SOAP_SOCKET)soap->sendfd, _O_BINARY); |
|
4351 #endif |
|
4352 #endif |
|
4353 #endif |
|
4354 #endif |
|
4355 #endif |
|
4356 if (soap->mode & SOAP_IO) |
|
4357 { soap->bufidx = 0; |
|
4358 soap->buflen = 0; |
|
4359 } |
|
4360 soap->chunksize = 0; |
|
4361 soap->ns = 0; |
|
4362 soap->null = 0; |
|
4363 soap->position = 0; |
|
4364 soap->mustUnderstand = 0; |
|
4365 soap->encoding = 0; |
|
4366 soap->idnum = 0; |
|
4367 soap->level = 0; |
|
4368 #ifdef WITH_ZLIB |
|
4369 soap->z_ratio_out = 1.0; |
|
4370 if ((soap->mode & SOAP_ENC_ZLIB) && soap->zlib_state != SOAP_ZLIB_DEFLATE) |
|
4371 { |
|
4372 #ifdef WITH_GZIP |
|
4373 memcpy(soap->z_buf, "\37\213\10\0\0\0\0\0\0\377", 10); |
|
4374 soap->d_stream.next_out = (Byte*)soap->z_buf + 10; |
|
4375 soap->d_stream.avail_out = SOAP_BUFLEN - 10; |
|
4376 soap->z_crc = crc32(0L, NULL, 0); |
|
4377 if (deflateInit2(&soap->d_stream, soap->z_level, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY) != Z_OK) |
|
4378 #else |
|
4379 soap->d_stream.next_out = (Byte*)soap->z_buf; |
|
4380 soap->d_stream.avail_out = SOAP_BUFLEN; |
|
4381 if (deflateInit(&soap->d_stream, soap->z_level) != Z_OK) |
|
4382 #endif |
|
4383 return soap->error = SOAP_ZLIB_ERROR; |
|
4384 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflate initialized\n")); |
|
4385 soap->zlib_state = SOAP_ZLIB_DEFLATE; |
|
4386 } |
|
4387 #endif |
|
4388 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin send phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count)); |
|
4389 soap->part = SOAP_BEGIN; |
|
4390 #ifndef WITH_LEANER |
|
4391 if (soap->fprepareinit && (soap->mode & SOAP_IO) == SOAP_IO_STORE) |
|
4392 soap->fprepareinit(soap); |
|
4393 #endif |
|
4394 return SOAP_OK; |
|
4395 } |
|
4396 #endif |
|
4397 |
|
4398 /******************************************************************************/ |
|
4399 #ifndef WITH_NOIDREF |
|
4400 #ifndef PALM_2 |
|
4401 SOAP_FMAC1 |
|
4402 void |
|
4403 SOAP_FMAC2 |
|
4404 soap_embedded(struct soap *soap, const void *p, int t) |
|
4405 { struct soap_plist *pp; |
|
4406 if (soap_pointer_lookup(soap, p, t, &pp)) |
|
4407 { pp->mark1 = 1; |
|
4408 pp->mark2 = 1; |
|
4409 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded %p type=%d mark set to 1\n", p, t)); |
|
4410 } |
|
4411 } |
|
4412 #endif |
|
4413 #endif |
|
4414 |
|
4415 /******************************************************************************/ |
|
4416 #ifndef WITH_NOIDREF |
|
4417 #ifndef PALM_2 |
|
4418 SOAP_FMAC1 |
|
4419 int |
|
4420 SOAP_FMAC2 |
|
4421 soap_reference(struct soap *soap, const void *p, int t) |
|
4422 { struct soap_plist *pp; |
|
4423 if (!p || (soap->mode & SOAP_XML_TREE)) |
|
4424 return 1; |
|
4425 if (soap_pointer_lookup(soap, p, t, &pp)) |
|
4426 { if (pp->mark1 == 0) |
|
4427 { pp->mark1 = 2; |
|
4428 pp->mark2 = 2; |
|
4429 } |
|
4430 } |
|
4431 else if (soap_pointer_enter(soap, p, NULL, 0, t, &pp)) |
|
4432 { pp->mark1 = 0; |
|
4433 pp->mark2 = 0; |
|
4434 } |
|
4435 else |
|
4436 return 1; |
|
4437 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reference %p type=%d (%d %d)\n", p, t, (int)pp->mark1, (int)pp->mark2)); |
|
4438 return pp->mark1; |
|
4439 } |
|
4440 #endif |
|
4441 #endif |
|
4442 |
|
4443 /******************************************************************************/ |
|
4444 #ifndef WITH_NOIDREF |
|
4445 #ifndef PALM_2 |
|
4446 SOAP_FMAC1 |
|
4447 int |
|
4448 SOAP_FMAC2 |
|
4449 soap_array_reference(struct soap *soap, const void *p, const struct soap_array *a, int n, int t) |
|
4450 { register int i; |
|
4451 struct soap_plist *pp; |
|
4452 if (!p || !a->__ptr) |
|
4453 return 1; |
|
4454 i = soap_array_pointer_lookup(soap, p, a, n, t, &pp); |
|
4455 if (i) |
|
4456 { if (pp->mark1 == 0) |
|
4457 { pp->mark1 = 2; |
|
4458 pp->mark2 = 2; |
|
4459 } |
|
4460 } |
|
4461 else if (!soap_pointer_enter(soap, p, a, n, t, &pp)) |
|
4462 return 1; |
|
4463 else |
|
4464 { pp->mark1 = 0; |
|
4465 pp->mark2 = 0; |
|
4466 } |
|
4467 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)); |
|
4468 return pp->mark1; |
|
4469 } |
|
4470 #endif |
|
4471 #endif |
|
4472 |
|
4473 /******************************************************************************/ |
|
4474 #ifndef WITH_NOIDREF |
|
4475 #ifndef PALM_2 |
|
4476 SOAP_FMAC1 |
|
4477 int |
|
4478 SOAP_FMAC2 |
|
4479 soap_embedded_id(struct soap *soap, int id, const void *p, int t) |
|
4480 { struct soap_plist *pp; |
|
4481 if (soap->mode & SOAP_XML_TREE) |
|
4482 return id; |
|
4483 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id %p type=%d id=%d\n", p, t, id)); |
|
4484 if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER) |
|
4485 { if (id < 0) |
|
4486 { id = soap_pointer_lookup(soap, p, t, &pp); |
|
4487 if (id) |
|
4488 { if (soap->mode & SOAP_IO_LENGTH) |
|
4489 pp->mark1 = 2; |
|
4490 else |
|
4491 pp->mark2 = 2; |
|
4492 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)); |
|
4493 } |
|
4494 return -1; |
|
4495 } |
|
4496 return id; |
|
4497 } |
|
4498 if (id < 0) |
|
4499 id = soap_pointer_lookup(soap, p, t, &pp); |
|
4500 else if (id && !soap_pointer_lookup(soap, p, t, &pp)) |
|
4501 return 0; |
|
4502 if (id && pp) |
|
4503 { if (soap->mode & SOAP_IO_LENGTH) |
|
4504 pp->mark1 = 1; |
|
4505 else |
|
4506 pp->mark2 = 1; |
|
4507 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)); |
|
4508 } |
|
4509 return id; |
|
4510 } |
|
4511 #endif |
|
4512 #endif |
|
4513 |
|
4514 /******************************************************************************/ |
|
4515 #ifndef WITH_NOIDREF |
|
4516 #ifndef PALM_2 |
|
4517 SOAP_FMAC1 |
|
4518 int |
|
4519 SOAP_FMAC2 |
|
4520 soap_is_embedded(struct soap *soap, struct soap_plist *pp) |
|
4521 { if (!pp) |
|
4522 return 0; |
|
4523 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Is embedded? %d %d\n", (int)pp->mark1, (int)pp->mark2)); |
|
4524 if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER) |
|
4525 { if (soap->mode & SOAP_IO_LENGTH) |
|
4526 return pp->mark1 != 0; |
|
4527 return pp->mark2 != 0; |
|
4528 } |
|
4529 if (soap->mode & SOAP_IO_LENGTH) |
|
4530 return pp->mark1 == 1; |
|
4531 return pp->mark2 == 1; |
|
4532 } |
|
4533 #endif |
|
4534 #endif |
|
4535 |
|
4536 /******************************************************************************/ |
|
4537 #ifndef WITH_NOIDREF |
|
4538 #ifndef PALM_2 |
|
4539 SOAP_FMAC1 |
|
4540 int |
|
4541 SOAP_FMAC2 |
|
4542 soap_is_single(struct soap *soap, struct soap_plist *pp) |
|
4543 { if (soap->part == SOAP_IN_HEADER) |
|
4544 return 1; |
|
4545 if (!pp) |
|
4546 return 0; |
|
4547 if (soap->mode & SOAP_IO_LENGTH) |
|
4548 return pp->mark1 == 0; |
|
4549 return pp->mark2 == 0; |
|
4550 } |
|
4551 #endif |
|
4552 #endif |
|
4553 |
|
4554 /******************************************************************************/ |
|
4555 #ifndef WITH_NOIDREF |
|
4556 #ifndef PALM_2 |
|
4557 SOAP_FMAC1 |
|
4558 void |
|
4559 SOAP_FMAC2 |
|
4560 soap_set_embedded(struct soap *soap, struct soap_plist *pp) |
|
4561 { if (!pp) |
|
4562 return; |
|
4563 if (soap->mode & SOAP_IO_LENGTH) |
|
4564 pp->mark1 = 1; |
|
4565 else |
|
4566 pp->mark2 = 1; |
|
4567 } |
|
4568 #endif |
|
4569 #endif |
|
4570 |
|
4571 /******************************************************************************/ |
|
4572 #ifndef WITH_NOIDREF |
|
4573 #ifndef WITH_LEANER |
|
4574 #ifndef PALM_1 |
|
4575 SOAP_FMAC1 |
|
4576 int |
|
4577 SOAP_FMAC2 |
|
4578 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) |
|
4579 { struct soap_plist *pp; |
|
4580 int i; |
|
4581 if (!p || !a->__ptr || (!aid && !atype)) |
|
4582 return soap_element_id(soap, tag, id, p, a, n, type, t); |
|
4583 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attachment tag='%s' id='%s' (%d) type='%s'\n", tag, aid?aid:"", id, atype?atype:"")); |
|
4584 i = soap_array_pointer_lookup(soap, p, a, n, t, &pp); |
|
4585 if (!i) |
|
4586 { i = soap_pointer_enter(soap, p, a, n, t, &pp); |
|
4587 if (!i) |
|
4588 { soap->error = SOAP_EOM; |
|
4589 return -1; |
|
4590 } |
|
4591 } |
|
4592 if (id < 0) |
|
4593 id = i; |
|
4594 if (!aid) |
|
4595 { sprintf(soap->tmpbuf, soap->dime_id_format, id); |
|
4596 aid = soap_strdup(soap, soap->tmpbuf); |
|
4597 } |
|
4598 /* Add MTOM xop:Include element when necessary */ |
|
4599 /* TODO: this code to be obsoleted with new import/xop.h conventions */ |
|
4600 if ((soap->mode & SOAP_ENC_MTOM) && strcmp(tag, "xop:Include")) |
|
4601 { if (soap_element_begin_out(soap, tag, 0, type) |
|
4602 || soap_element_href(soap, "xop:Include", 0, "href", aid) |
|
4603 || soap_element_end_out(soap, tag)) |
|
4604 return soap->error; |
|
4605 } |
|
4606 else if (soap_element_href(soap, tag, 0, "href", aid)) |
|
4607 return soap->error; |
|
4608 if (soap->mode & SOAP_IO_LENGTH) |
|
4609 { if (pp->mark1 != 3) |
|
4610 { struct soap_multipart *content; |
|
4611 if (soap->mode & SOAP_ENC_MTOM) |
|
4612 content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, (char*)a->__ptr, a->__size); |
|
4613 else |
|
4614 content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, (char*)a->__ptr, a->__size); |
|
4615 if (!content) |
|
4616 { soap->error = SOAP_EOM; |
|
4617 return -1; |
|
4618 } |
|
4619 if (!strncmp(aid, "cid:", 4)) /* RFC 2111 */ |
|
4620 { if (soap->mode & SOAP_ENC_MTOM) |
|
4621 { char *s = (char*)soap_malloc(soap, strlen(aid) - 1); |
|
4622 if (s) |
|
4623 { *s = '<'; |
|
4624 strcpy(s + 1, aid + 4); |
|
4625 strcat(s, ">"); |
|
4626 content->id = s; |
|
4627 } |
|
4628 } |
|
4629 else |
|
4630 content->id = aid + 4; |
|
4631 } |
|
4632 else |
|
4633 content->id = aid; |
|
4634 content->type = atype; |
|
4635 content->options = aoptions; |
|
4636 content->encoding = SOAP_MIME_BINARY; |
|
4637 pp->mark1 = 3; |
|
4638 } |
|
4639 } |
|
4640 else |
|
4641 pp->mark2 = 3; |
|
4642 return -1; |
|
4643 } |
|
4644 #endif |
|
4645 #endif |
|
4646 #endif |
|
4647 |
|
4648 /******************************************************************************/ |
|
4649 #ifndef WITH_NOIDREF |
|
4650 #ifndef PALM_1 |
|
4651 static void |
|
4652 soap_init_iht(struct soap *soap) |
|
4653 { register int i; |
|
4654 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing ID hashtable\n")); |
|
4655 for (i = 0; i < SOAP_IDHASH; i++) |
|
4656 soap->iht[i] = NULL; |
|
4657 } |
|
4658 #endif |
|
4659 #endif |
|
4660 |
|
4661 /******************************************************************************/ |
|
4662 #ifndef WITH_NOIDREF |
|
4663 #ifndef PALM_1 |
|
4664 static void |
|
4665 soap_free_iht(struct soap *soap) |
|
4666 { register int i; |
|
4667 register struct soap_ilist *ip, *p; |
|
4668 register struct soap_flist *fp, *fq; |
|
4669 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free ID hashtable\n")); |
|
4670 for (i = 0; i < SOAP_IDHASH; i++) |
|
4671 { for (ip = soap->iht[i]; ip; ip = p) |
|
4672 { for (fp = ip->flist; fp; fp = fq) |
|
4673 { fq = fp->next; |
|
4674 SOAP_FREE(soap, fp); |
|
4675 } |
|
4676 p = ip->next; |
|
4677 SOAP_FREE(soap, ip); |
|
4678 } |
|
4679 soap->iht[i] = NULL; |
|
4680 } |
|
4681 } |
|
4682 #endif |
|
4683 #endif |
|
4684 |
|
4685 /******************************************************************************/ |
|
4686 #ifndef WITH_NOIDREF |
|
4687 #ifndef PALM_2 |
|
4688 SOAP_FMAC1 |
|
4689 struct soap_ilist * |
|
4690 SOAP_FMAC2 |
|
4691 soap_lookup(struct soap *soap, const char *id) |
|
4692 { register struct soap_ilist *ip; |
|
4693 for (ip = soap->iht[soap_hash(id)]; ip; ip = ip->next) |
|
4694 if (!strcmp(ip->id, id)) |
|
4695 return ip; |
|
4696 return NULL; |
|
4697 } |
|
4698 #endif |
|
4699 #endif |
|
4700 |
|
4701 /******************************************************************************/ |
|
4702 #ifndef WITH_NOIDREF |
|
4703 #ifndef PALM_2 |
|
4704 SOAP_FMAC1 |
|
4705 struct soap_ilist * |
|
4706 SOAP_FMAC2 |
|
4707 soap_enter(struct soap *soap, const char *id) |
|
4708 { register size_t h; |
|
4709 register struct soap_ilist *ip; |
|
4710 ip = (struct soap_ilist*)SOAP_MALLOC(soap, sizeof(struct soap_ilist) + strlen(id)); |
|
4711 if (ip) |
|
4712 { h = soap_hash(id); |
|
4713 strcpy(ip->id, id); |
|
4714 ip->next = soap->iht[h]; |
|
4715 soap->iht[h] = ip; |
|
4716 return ip; |
|
4717 } |
|
4718 return NULL; |
|
4719 } |
|
4720 #endif |
|
4721 #endif |
|
4722 |
|
4723 /******************************************************************************/ |
|
4724 #ifndef PALM_2 |
|
4725 SOAP_FMAC1 |
|
4726 void* |
|
4727 SOAP_FMAC2 |
|
4728 soap_malloc(struct soap *soap, size_t n) |
|
4729 { register char *p; |
|
4730 if (!n) |
|
4731 return (void*)SOAP_NON_NULL; |
|
4732 if (!soap) |
|
4733 return SOAP_MALLOC(soap, n); |
|
4734 n += (-(long)n) & 7; |
|
4735 if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(void*) + sizeof(size_t)))) |
|
4736 { soap->error = SOAP_EOM; |
|
4737 return NULL; |
|
4738 } |
|
4739 /* keep chain of alloced cells for later destruction */ |
|
4740 soap->alloced = 1; |
|
4741 *(void**)(p + n) = soap->alist; |
|
4742 *(size_t*)(p + n + sizeof(void*)) = n; |
|
4743 soap->alist = p + n; |
|
4744 return p; |
|
4745 } |
|
4746 #endif |
|
4747 |
|
4748 /******************************************************************************/ |
|
4749 #ifdef SOAP_DEBUG |
|
4750 static void |
|
4751 soap_init_mht(struct soap *soap) |
|
4752 { register int i; |
|
4753 for (i = 0; i < (int)SOAP_PTRHASH; i++) |
|
4754 soap->mht[i] = NULL; |
|
4755 } |
|
4756 #endif |
|
4757 |
|
4758 /******************************************************************************/ |
|
4759 #ifdef SOAP_DEBUG |
|
4760 static void |
|
4761 soap_free_mht(struct soap *soap) |
|
4762 { register int i; |
|
4763 register struct soap_mlist *mp, *mq; |
|
4764 for (i = 0; i < (int)SOAP_PTRHASH; i++) |
|
4765 { for (mp = soap->mht[i]; mp; mp = mq) |
|
4766 { mq = mp->next; |
|
4767 if (mp->live) |
|
4768 fprintf(stderr, "%s(%d): malloc() = %p not freed (memory leak or forgot to call soap_end()?)\n", mp->file, mp->line, mp->ptr); |
|
4769 free(mp); |
|
4770 } |
|
4771 soap->mht[i] = NULL; |
|
4772 } |
|
4773 } |
|
4774 #endif |
|
4775 |
|
4776 /******************************************************************************/ |
|
4777 #ifdef SOAP_DEBUG |
|
4778 SOAP_FMAC1 |
|
4779 void* |
|
4780 SOAP_FMAC2 |
|
4781 soap_track_malloc(struct soap *soap, const char *file, int line, size_t size) |
|
4782 { register void *p = malloc(size); |
|
4783 if (soap) |
|
4784 { register int h = soap_hash_ptr(p); |
|
4785 register struct soap_mlist *mp = (struct soap_mlist*)malloc(sizeof(struct soap_mlist)); |
|
4786 if (soap->fdebug[SOAP_INDEX_TEST]) |
|
4787 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): malloc(%lu) = %p\n", file, line, (unsigned long)size, p)); |
|
4788 mp->next = soap->mht[h]; |
|
4789 mp->ptr = p; |
|
4790 mp->file = file; |
|
4791 mp->line = line; |
|
4792 mp->live = 1; |
|
4793 soap->mht[h] = mp; |
|
4794 } |
|
4795 return p; |
|
4796 } |
|
4797 #endif |
|
4798 |
|
4799 /******************************************************************************/ |
|
4800 #ifdef SOAP_DEBUG |
|
4801 SOAP_FMAC1 |
|
4802 void |
|
4803 SOAP_FMAC2 |
|
4804 soap_track_free(struct soap *soap, const char *file, int line, void *p) |
|
4805 { register int h = soap_hash_ptr(p); |
|
4806 register struct soap_mlist *mp; |
|
4807 for (mp = soap->mht[h]; mp; mp = mp->next) |
|
4808 if (mp->ptr == p) |
|
4809 break; |
|
4810 if (mp) |
|
4811 { if (mp->live) |
|
4812 { free(p); |
|
4813 if (soap->fdebug[SOAP_INDEX_TEST]) |
|
4814 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): free(%p)\n", file, line, p)); |
|
4815 mp->live = 0; |
|
4816 } |
|
4817 else |
|
4818 fprintf(stderr, "%s(%d): free(%p) double free of pointer malloced at %s(%d)\n", file, line, p, mp->file, mp->line); |
|
4819 } |
|
4820 else |
|
4821 fprintf(stderr, "%s(%d): free(%p) pointer not malloced\n", file, line, p); |
|
4822 } |
|
4823 #endif |
|
4824 |
|
4825 /******************************************************************************/ |
|
4826 #ifdef SOAP_DEBUG |
|
4827 static void |
|
4828 soap_track_unlink(struct soap *soap, const void *p) |
|
4829 { register int h = soap_hash_ptr(p); |
|
4830 register struct soap_mlist *mp; |
|
4831 for (mp = soap->mht[h]; mp; mp = mp->next) |
|
4832 if (mp->ptr == p) |
|
4833 break; |
|
4834 if (mp) |
|
4835 mp->live = 0; |
|
4836 } |
|
4837 #endif |
|
4838 |
|
4839 /******************************************************************************/ |
|
4840 #ifndef PALM_2 |
|
4841 SOAP_FMAC1 |
|
4842 void |
|
4843 SOAP_FMAC2 |
|
4844 soap_dealloc(struct soap *soap, void *p) |
|
4845 { if (!soap) |
|
4846 return; |
|
4847 if (p) |
|
4848 { register char **q; |
|
4849 for (q = (char**)&soap->alist; *q; q = *(char***)q) |
|
4850 { if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*)))) |
|
4851 { *q = **(char***)q; |
|
4852 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Freed data at %p\n", p)); |
|
4853 SOAP_FREE(soap, p); |
|
4854 return; |
|
4855 } |
|
4856 } |
|
4857 soap_delete(soap, p); |
|
4858 } |
|
4859 else |
|
4860 { register char *q; |
|
4861 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free all soap_malloc() data\n")); |
|
4862 while (soap->alist) |
|
4863 { q = (char*)soap->alist; |
|
4864 soap->alist = *(void**)q; |
|
4865 q -= *(size_t*)(q + sizeof(void*)); |
|
4866 SOAP_FREE(soap, q); |
|
4867 } |
|
4868 } |
|
4869 /* we must assume these were deallocated: */ |
|
4870 soap->action = NULL; |
|
4871 soap->fault = NULL; |
|
4872 soap->header = NULL; |
|
4873 soap->userid = NULL; |
|
4874 soap->passwd = NULL; |
|
4875 soap->authrealm = NULL; |
|
4876 #ifndef WITH_LEANER |
|
4877 soap_clr_mime(soap); |
|
4878 #endif |
|
4879 } |
|
4880 #endif |
|
4881 |
|
4882 /******************************************************************************/ |
|
4883 #ifndef PALM_2 |
|
4884 SOAP_FMAC1 |
|
4885 void |
|
4886 SOAP_FMAC2 |
|
4887 soap_delete(struct soap *soap, void *p) |
|
4888 { register struct soap_clist **cp = &soap->clist; |
|
4889 if (p) |
|
4890 { while (*cp) |
|
4891 { if (p == (*cp)->ptr) |
|
4892 { register struct soap_clist *q = *cp; |
|
4893 *cp = q->next; |
|
4894 q->fdelete(q); |
|
4895 SOAP_FREE(soap, q); |
|
4896 return; |
|
4897 } |
|
4898 cp = &(*cp)->next; |
|
4899 } |
|
4900 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: address not in list\n", p)); |
|
4901 } |
|
4902 else |
|
4903 { while (*cp) |
|
4904 { register struct soap_clist *q = *cp; |
|
4905 *cp = q->next; |
|
4906 if (q->ptr == (void*)soap->fault) |
|
4907 soap->fault = NULL; /* this was deallocated */ |
|
4908 else if (q->ptr == (void*)soap->header) |
|
4909 soap->header = NULL; /* this was deallocated */ |
|
4910 q->fdelete(q); |
|
4911 SOAP_FREE(soap, q); |
|
4912 } |
|
4913 } |
|
4914 } |
|
4915 #endif |
|
4916 |
|
4917 /******************************************************************************/ |
|
4918 #ifndef PALM_2 |
|
4919 SOAP_FMAC1 |
|
4920 struct soap_clist * |
|
4921 SOAP_FMAC2 |
|
4922 soap_link(struct soap *soap, void *p, int t, int n, void (*fdelete)(struct soap_clist*)) |
|
4923 { register struct soap_clist *cp; |
|
4924 if ((cp = (struct soap_clist*)SOAP_MALLOC(soap, sizeof(struct soap_clist)))) |
|
4925 { cp->next = soap->clist; |
|
4926 cp->type = t; |
|
4927 cp->size = n; |
|
4928 cp->ptr = p; |
|
4929 cp->fdelete = fdelete; |
|
4930 soap->clist = cp; |
|
4931 } |
|
4932 return cp; |
|
4933 } |
|
4934 #endif |
|
4935 |
|
4936 /******************************************************************************/ |
|
4937 #ifndef PALM_2 |
|
4938 SOAP_FMAC1 |
|
4939 void |
|
4940 SOAP_FMAC2 |
|
4941 soap_unlink(struct soap *soap, const void *p) |
|
4942 { register char **q; |
|
4943 register struct soap_clist **cp; |
|
4944 if (!soap || !p) |
|
4945 return; |
|
4946 for (q = (char**)&soap->alist; *q; q = *(char***)q) |
|
4947 { if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*)))) |
|
4948 { *q = **(char***)q; |
|
4949 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked data %p\n", p)); |
|
4950 #ifdef SOAP_DEBUG |
|
4951 soap_track_unlink(soap, p); |
|
4952 #endif |
|
4953 return; |
|
4954 } |
|
4955 } |
|
4956 for (cp = &soap->clist; *cp; cp = &(*cp)->next) |
|
4957 { if (p == (*cp)->ptr) |
|
4958 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked class instance %p\n", p)); |
|
4959 q = (char**)*cp; |
|
4960 *cp = (*cp)->next; |
|
4961 SOAP_FREE(soap, q); |
|
4962 return; |
|
4963 } |
|
4964 } |
|
4965 } |
|
4966 #endif |
|
4967 |
|
4968 /******************************************************************************/ |
|
4969 #ifndef WITH_NOIDREF |
|
4970 #ifndef PALM_2 |
|
4971 SOAP_FMAC1 |
|
4972 int |
|
4973 SOAP_FMAC2 |
|
4974 soap_lookup_type(struct soap *soap, const char *id) |
|
4975 { register struct soap_ilist *ip; |
|
4976 if (id && *id) |
|
4977 { ip = soap_lookup(soap, id); |
|
4978 if (ip) |
|
4979 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup id='%s' type=%d\n", id, ip->type)); |
|
4980 return ip->type; |
|
4981 } |
|
4982 } |
|
4983 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "lookup type id='%s' NOT FOUND! Need to get it from xsi:type\n", id)); |
|
4984 return 0; |
|
4985 } |
|
4986 #endif |
|
4987 #endif |
|
4988 |
|
4989 /******************************************************************************/ |
|
4990 #ifndef WITH_NOIDREF |
|
4991 #ifndef PALM_2 |
|
4992 SOAP_FMAC1 |
|
4993 void* |
|
4994 SOAP_FMAC2 |
|
4995 soap_id_lookup(struct soap *soap, const char *id, void **p, int t, size_t n, unsigned int k) |
|
4996 { struct soap_ilist *ip; |
|
4997 void **q; |
|
4998 if (!p || !id || !*id) |
|
4999 return p; |
|
5000 ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */ |
|
5001 if (!ip) |
|
5002 { ip = soap_enter(soap, id); /* new hash table entry for string id */ |
|
5003 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding first href='%s' type=%d %p (%u bytes)\n", id, t, p, (unsigned int)n)); |
|
5004 ip->type = t; |
|
5005 ip->size = n; |
|
5006 ip->link = p; |
|
5007 ip->copy = NULL; |
|
5008 ip->flist = NULL; |
|
5009 ip->ptr = NULL; |
|
5010 ip->level = k; |
|
5011 *p = NULL; |
|
5012 } |
|
5013 else if (ip->ptr) |
|
5014 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolved href='%s' type=%d location=%p (%u bytes)\n", id, t, ip->ptr, (unsigned int)n)); |
|
5015 if (ip->type != t) |
|
5016 { strcpy(soap->id, id); |
|
5017 soap->error = SOAP_HREF; |
|
5018 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility: id type=%d href type=%d\n", ip->type, t)); |
|
5019 return NULL; |
|
5020 } |
|
5021 while (ip->level < k) |
|
5022 { q = (void**)soap_malloc(soap, sizeof(void*)); |
|
5023 if (!q) |
|
5024 return NULL; |
|
5025 *p = (void*)q; |
|
5026 p = q; |
|
5027 k--; |
|
5028 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); |
|
5029 } |
|
5030 *p = ip->ptr; |
|
5031 } |
|
5032 else if (ip->level > k) |
|
5033 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving level %u pointers to href='%s'\n", ip->level, id)); |
|
5034 while (ip->level > k) |
|
5035 { void *s, **r = &ip->link; |
|
5036 q = (void**)ip->link; |
|
5037 while (q) |
|
5038 { *r = (void*)soap_malloc(soap, sizeof(void*)); |
|
5039 s = *q; |
|
5040 *q = *r; |
|
5041 r = (void**)*r; |
|
5042 q = (void**)s; |
|
5043 } |
|
5044 *r = NULL; |
|
5045 ip->size = n; |
|
5046 ip->copy = NULL; |
|
5047 ip->level = ip->level - 1; |
|
5048 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); |
|
5049 } |
|
5050 q = (void**)ip->link; |
|
5051 ip->link = p; |
|
5052 *p = (void*)q; |
|
5053 } |
|
5054 else |
|
5055 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarded href='%s' type=%d location=%p (%u bytes)\n", id, t, p, (unsigned int)n)); |
|
5056 while (ip->level < k) |
|
5057 { q = (void**)soap_malloc(soap, sizeof(void*)); |
|
5058 *p = q; |
|
5059 p = q; |
|
5060 k--; |
|
5061 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); |
|
5062 } |
|
5063 q = (void**)ip->link; |
|
5064 ip->link = p; |
|
5065 *p = (void*)q; |
|
5066 } |
|
5067 return p; |
|
5068 } |
|
5069 #endif |
|
5070 #endif |
|
5071 |
|
5072 /******************************************************************************/ |
|
5073 #ifndef WITH_NOIDREF |
|
5074 #ifndef PALM_2 |
|
5075 SOAP_FMAC1 |
|
5076 void* |
|
5077 SOAP_FMAC2 |
|
5078 soap_id_forward(struct soap *soap, const char *href, void *p, int st, int tt, size_t n, unsigned int k, void (*fcopy)(struct soap*, int, int, void*, const void*, size_t)) |
|
5079 { struct soap_ilist *ip; |
|
5080 if (!p || !href || !*href) |
|
5081 return p; |
|
5082 ip = soap_lookup(soap, href); /* lookup pointer to hash table entry for string id */ |
|
5083 if (!ip) |
|
5084 { ip = soap_enter(soap, href); /* new hash table entry for string id */ |
|
5085 ip->type = st; |
|
5086 ip->size = n; |
|
5087 ip->link = NULL; |
|
5088 ip->copy = NULL; |
|
5089 ip->ptr = NULL; |
|
5090 ip->level = 0; |
|
5091 ip->flist = NULL; |
|
5092 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)); |
|
5093 } |
|
5094 else if (ip->type != st || (ip->level == k && ip->size != n)) |
|
5095 { 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)); |
|
5096 strcpy(soap->id, href); |
|
5097 soap->error = SOAP_HREF; |
|
5098 return NULL; |
|
5099 } |
|
5100 if (fcopy || n < sizeof(void*) || *href != '#') |
|
5101 { register struct soap_flist *fp = (struct soap_flist*)SOAP_MALLOC(soap, sizeof(struct soap_flist)); |
|
5102 if (!fp) |
|
5103 { soap->error = SOAP_EOM; |
|
5104 return NULL; |
|
5105 } |
|
5106 fp->next = ip->flist; |
|
5107 fp->type = tt; |
|
5108 fp->ptr = p; |
|
5109 fp->level = k; |
|
5110 if (fcopy) |
|
5111 fp->fcopy = fcopy; |
|
5112 else |
|
5113 fp->fcopy = soap_fcopy; |
|
5114 ip->flist = fp; |
|
5115 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding type=%d (target type=%d) size=%lu location=%p level=%u href='%s'\n", st, tt, (unsigned long)n, p, k, href)); |
|
5116 } |
|
5117 else |
|
5118 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding copying address %p for type=%d href='%s'\n", p, st, href)); |
|
5119 *(void**)p = ip->copy; |
|
5120 ip->copy = p; |
|
5121 } |
|
5122 return p; |
|
5123 } |
|
5124 #endif |
|
5125 #endif |
|
5126 |
|
5127 /******************************************************************************/ |
|
5128 #ifndef PALM_2 |
|
5129 SOAP_FMAC1 |
|
5130 void* |
|
5131 SOAP_FMAC2 |
|
5132 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*)) |
|
5133 { |
|
5134 #ifndef WITH_NOIDREF |
|
5135 struct soap_ilist *ip; |
|
5136 #endif |
|
5137 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Enter id='%s' type=%d loc=%p size=%lu level=%u\n", id, t, p, (unsigned long)n, k)); |
|
5138 soap->alloced = 0; |
|
5139 if (!p) |
|
5140 { if (finstantiate) |
|
5141 p = finstantiate(soap, t, type, arrayType, &n); |
|
5142 else |
|
5143 p = soap_malloc(soap, n); |
|
5144 if (p) |
|
5145 soap->alloced = 1; |
|
5146 } |
|
5147 #ifndef WITH_NOIDREF |
|
5148 if (!id || !*id) |
|
5149 #endif |
|
5150 return p; |
|
5151 #ifndef WITH_NOIDREF |
|
5152 ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */ |
|
5153 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Lookup entry id='%s for location=%p'\n", id, p)); |
|
5154 if (!ip) |
|
5155 { ip = soap_enter(soap, id); /* new hash table entry for string id */ |
|
5156 ip->type = t; |
|
5157 ip->link = NULL; |
|
5158 ip->copy = NULL; |
|
5159 ip->flist = NULL; |
|
5160 ip->size = n; |
|
5161 ip->ptr = p; |
|
5162 ip->level = k; |
|
5163 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)); |
|
5164 } |
|
5165 else if ((ip->type != t || (ip->level == k && ip->size != n)) && (ip->copy || ip->flist)) |
|
5166 { 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)); |
|
5167 strcpy(soap->id, id); |
|
5168 soap->error = SOAP_HREF; |
|
5169 return NULL; |
|
5170 } |
|
5171 else if (ip->ptr) |
|
5172 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Multiply defined id='%s'\n", id)); |
|
5173 strcpy(soap->id, id); |
|
5174 soap->error = SOAP_DUPLICATE_ID; |
|
5175 return NULL; |
|
5176 } |
|
5177 else |
|
5178 { ip->size = n; |
|
5179 ip->ptr = p; |
|
5180 ip->level = k; |
|
5181 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)); |
|
5182 } |
|
5183 return ip->ptr; |
|
5184 #endif |
|
5185 } |
|
5186 #endif |
|
5187 |
|
5188 /******************************************************************************/ |
|
5189 #ifndef PALM_2 |
|
5190 SOAP_FMAC1 |
|
5191 void |
|
5192 SOAP_FMAC2 |
|
5193 soap_fcopy(struct soap *soap, int st, int tt, void *p, const void *q, size_t n) |
|
5194 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Copying data type=%d (target type=%d) %p -> %p (%lu bytes)\n", st, tt, q, p, (unsigned long)n)); |
|
5195 memcpy(p, q, n); |
|
5196 } |
|
5197 #endif |
|
5198 |
|
5199 /******************************************************************************/ |
|
5200 #ifndef PALM_1 |
|
5201 SOAP_FMAC1 |
|
5202 int |
|
5203 SOAP_FMAC2 |
|
5204 soap_end_send(struct soap *soap) |
|
5205 { |
|
5206 #ifndef WITH_LEANER |
|
5207 if (soap->dime.list) |
|
5208 { /* SOAP body referenced attachments must appear first */ |
|
5209 soap->dime.last->next = soap->dime.first; |
|
5210 soap->dime.first = soap->dime.list->next; |
|
5211 soap->dime.list->next = NULL; |
|
5212 soap->dime.last = soap->dime.list; |
|
5213 } |
|
5214 if (soap_putdime(soap) || soap_putmime(soap)) |
|
5215 return soap->error; |
|
5216 soap->mime.list = NULL; |
|
5217 soap->mime.first = NULL; |
|
5218 soap->mime.last = NULL; |
|
5219 soap->dime.list = NULL; |
|
5220 soap->dime.first = NULL; |
|
5221 soap->dime.last = NULL; |
|
5222 #endif |
|
5223 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End send\n")); |
|
5224 if (soap->mode & SOAP_IO) /* need to flush the remaining data in buffer */ |
|
5225 { if (soap_flush(soap)) |
|
5226 #ifdef WITH_ZLIB |
|
5227 { if (soap->mode & SOAP_ENC_ZLIB && soap->zlib_state == SOAP_ZLIB_DEFLATE) |
|
5228 { soap->zlib_state = SOAP_ZLIB_NONE; |
|
5229 deflateEnd(&soap->d_stream); |
|
5230 } |
|
5231 return soap->error; |
|
5232 } |
|
5233 #else |
|
5234 return soap->error; |
|
5235 #endif |
|
5236 #ifdef WITH_ZLIB |
|
5237 if (soap->mode & SOAP_ENC_ZLIB) |
|
5238 { int r; |
|
5239 soap->d_stream.avail_in = 0; |
|
5240 do |
|
5241 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating remainder\n")); |
|
5242 r = deflate(&soap->d_stream, Z_FINISH); |
|
5243 if (soap->d_stream.avail_out != SOAP_BUFLEN) |
|
5244 { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN - soap->d_stream.avail_out)) |
|
5245 { soap->zlib_state = SOAP_ZLIB_NONE; |
|
5246 deflateEnd(&soap->d_stream); |
|
5247 return soap->error; |
|
5248 } |
|
5249 soap->d_stream.next_out = (Byte*)soap->z_buf; |
|
5250 soap->d_stream.avail_out = SOAP_BUFLEN; |
|
5251 } |
|
5252 } while (r == Z_OK); |
|
5253 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out)); |
|
5254 soap->z_ratio_out = (float)soap->d_stream.total_out / (float)soap->d_stream.total_in; |
|
5255 soap->mode &= ~SOAP_ENC_ZLIB; |
|
5256 soap->zlib_state = SOAP_ZLIB_NONE; |
|
5257 if (deflateEnd(&soap->d_stream) != Z_OK || r != Z_STREAM_END) |
|
5258 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to end deflate: %s\n", soap->d_stream.msg?soap->d_stream.msg:"")); |
|
5259 return soap->error = SOAP_ZLIB_ERROR; |
|
5260 } |
|
5261 #ifdef WITH_GZIP |
|
5262 soap->z_buf[0] = soap->z_crc & 0xFF; |
|
5263 soap->z_buf[1] = (soap->z_crc >> 8) & 0xFF; |
|
5264 soap->z_buf[2] = (soap->z_crc >> 16) & 0xFF; |
|
5265 soap->z_buf[3] = (soap->z_crc >> 24) & 0xFF; |
|
5266 soap->z_buf[4] = soap->d_stream.total_in & 0xFF; |
|
5267 soap->z_buf[5] = (soap->d_stream.total_in >> 8) & 0xFF; |
|
5268 soap->z_buf[6] = (soap->d_stream.total_in >> 16) & 0xFF; |
|
5269 soap->z_buf[7] = (soap->d_stream.total_in >> 24) & 0xFF; |
|
5270 if (soap_flush_raw(soap, soap->z_buf, 8)) |
|
5271 return soap->error; |
|
5272 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip crc32=%lu\n", (unsigned long)soap->z_crc)); |
|
5273 #endif |
|
5274 } |
|
5275 #endif |
|
5276 if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) |
|
5277 { char *p; |
|
5278 #ifndef WITH_NOHTTP |
|
5279 if (!(soap->mode & SOAP_ENC_XML)) |
|
5280 { soap->mode--; |
|
5281 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending buffered message of length %u\n", (unsigned int)soap->blist->size)); |
|
5282 if (soap->status >= SOAP_POST) |
|
5283 soap->error = soap->fpost(soap, soap->endpoint, soap->host, soap->port, soap->path, soap->action, soap->blist->size); |
|
5284 else if (soap->status != SOAP_STOP) |
|
5285 soap->error = soap->fresponse(soap, soap->status, soap->blist->size); |
|
5286 if (soap->error || soap_flush(soap)) |
|
5287 return soap->error; |
|
5288 soap->mode++; |
|
5289 } |
|
5290 #endif |
|
5291 for (p = soap_first_block(soap); p; p = soap_next_block(soap)) |
|
5292 { DBGMSG(SENT, p, soap_block_size(soap)); |
|
5293 if ((soap->error = soap->fsend(soap, p, soap_block_size(soap)))) |
|
5294 { soap_end_block(soap); |
|
5295 return soap->error; |
|
5296 } |
|
5297 } |
|
5298 soap_end_block(soap); |
|
5299 } |
|
5300 #ifndef WITH_LEANER |
|
5301 else if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) |
|
5302 { DBGMSG(SENT, "\r\n0\r\n\r\n", 7); |
|
5303 if ((soap->error = soap->fsend(soap, "\r\n0\r\n\r\n", 7))) |
|
5304 return soap->error; |
|
5305 } |
|
5306 #endif |
|
5307 } |
|
5308 #ifdef WITH_OPENSSL |
|
5309 if (!soap->ssl && soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP)) |
|
5310 soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 1); /* Send TCP FIN */ |
|
5311 #else |
|
5312 if (soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP)) |
|
5313 soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 1); /* Send TCP FIN */ |
|
5314 #endif |
|
5315 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of send phase\n")); |
|
5316 soap->omode &= ~SOAP_XML_SEC; |
|
5317 soap->count = 0; |
|
5318 soap->part = SOAP_END; |
|
5319 return SOAP_OK; |
|
5320 } |
|
5321 #endif |
|
5322 |
|
5323 /******************************************************************************/ |
|
5324 #ifndef PALM_1 |
|
5325 SOAP_FMAC1 |
|
5326 int |
|
5327 SOAP_FMAC2 |
|
5328 soap_end_recv(struct soap *soap) |
|
5329 { soap->part = SOAP_END; |
|
5330 #ifndef WITH_LEANER |
|
5331 if ((soap->mode & SOAP_ENC_DIME) && soap_getdime(soap)) |
|
5332 return soap->error; |
|
5333 soap->dime.list = soap->dime.first; |
|
5334 soap->dime.first = NULL; |
|
5335 soap->dime.last = NULL; |
|
5336 if ((soap->mode & SOAP_ENC_MIME) && soap_getmime(soap)) |
|
5337 return soap->error; |
|
5338 soap->mime.list = soap->mime.first; |
|
5339 soap->mime.first = NULL; |
|
5340 soap->mime.last = NULL; |
|
5341 soap->mime.boundary = NULL; |
|
5342 #endif |
|
5343 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "End of receive message ok\n")); |
|
5344 #ifdef WITH_ZLIB |
|
5345 if (soap->mode & SOAP_ENC_ZLIB) |
|
5346 { soap->mode &= ~SOAP_ENC_ZLIB; |
|
5347 memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN); |
|
5348 soap->bufidx = (char*)soap->d_stream.next_in - soap->z_buf; |
|
5349 soap->buflen = soap->z_buflen; |
|
5350 soap->zlib_state = SOAP_ZLIB_NONE; |
|
5351 if (inflateEnd(&soap->d_stream) != Z_OK) |
|
5352 return soap->error = SOAP_ZLIB_ERROR; |
|
5353 #ifdef WITH_GZIP |
|
5354 if (soap->zlib_in == SOAP_ZLIB_GZIP) |
|
5355 { soap_wchar c; |
|
5356 short i; |
|
5357 for (i = 0; i < 8; i++) |
|
5358 { if ((int)(c = soap_getchar(soap)) == EOF) |
|
5359 return soap->error = SOAP_EOF; |
|
5360 soap->z_buf[i] = (char)c; |
|
5361 } |
|
5362 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))) |
|
5363 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: crc check failed, message corrupted? (crc32=%lu)\n", (unsigned long)soap->z_crc)); |
|
5364 return soap->error = SOAP_ZLIB_ERROR; |
|
5365 } |
|
5366 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))) |
|
5367 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: incorrect message length\n")); |
|
5368 return soap->error = SOAP_ZLIB_ERROR; |
|
5369 } |
|
5370 } |
|
5371 #endif |
|
5372 } |
|
5373 #endif |
|
5374 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) |
|
5375 while ((int)soap_getchar(soap) != EOF) /* advance to last chunk */ |
|
5376 ; |
|
5377 if (soap->fdisconnect && (soap->error = soap->fdisconnect(soap))) |
|
5378 return soap->error; |
|
5379 #ifndef WITH_NOIDREF |
|
5380 return soap_resolve(soap); |
|
5381 #else |
|
5382 #ifndef WITH_LEANER |
|
5383 if (soap->xlist) |
|
5384 { if (soap->mode & SOAP_ENC_MTOM) |
|
5385 return soap->error = SOAP_MIME_HREF; |
|
5386 return soap->error = SOAP_DIME_HREF; |
|
5387 } |
|
5388 #endif |
|
5389 return SOAP_OK; |
|
5390 #endif |
|
5391 } |
|
5392 #endif |
|
5393 |
|
5394 /******************************************************************************/ |
|
5395 #ifndef PALM_1 |
|
5396 SOAP_FMAC1 |
|
5397 void |
|
5398 SOAP_FMAC2 |
|
5399 soap_free(struct soap *soap) |
|
5400 { register struct Namespace *ns; |
|
5401 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free namespace stack\n")); |
|
5402 while (soap->nlist) |
|
5403 { register struct soap_nlist *np = soap->nlist->next; |
|
5404 SOAP_FREE(soap, soap->nlist); |
|
5405 soap->nlist = np; |
|
5406 } |
|
5407 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free any remaining temp blocks\n")); |
|
5408 while (soap->blist) |
|
5409 soap_end_block(soap); |
|
5410 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute storage\n")); |
|
5411 while (soap->attributes) |
|
5412 { register struct soap_attribute *tp = soap->attributes->next; |
|
5413 if (soap->attributes->value) |
|
5414 SOAP_FREE(soap, soap->attributes->value); |
|
5415 SOAP_FREE(soap, soap->attributes); |
|
5416 soap->attributes = tp; |
|
5417 } |
|
5418 #ifdef WITH_FAST |
|
5419 if (soap->labbuf) |
|
5420 SOAP_FREE(soap, soap->labbuf); |
|
5421 soap->labbuf = NULL; |
|
5422 soap->lablen = 0; |
|
5423 soap->labidx = 0; |
|
5424 #endif |
|
5425 ns = soap->local_namespaces; |
|
5426 if (ns) |
|
5427 { for (; ns->id; ns++) |
|
5428 { if (ns->out) |
|
5429 { if (soap->encodingStyle == ns->out) |
|
5430 soap->encodingStyle = SOAP_STR_EOS; |
|
5431 SOAP_FREE(soap, ns->out); |
|
5432 ns->out = NULL; |
|
5433 } |
|
5434 if (soap->encodingStyle == ns->ns) |
|
5435 soap->encodingStyle = SOAP_STR_EOS; |
|
5436 } |
|
5437 SOAP_FREE(soap, soap->local_namespaces); |
|
5438 soap->local_namespaces = NULL; |
|
5439 } |
|
5440 #ifndef WITH_LEANER |
|
5441 while (soap->xlist) |
|
5442 { struct soap_xlist *xp = soap->xlist->next; |
|
5443 SOAP_FREE(soap, soap->xlist); |
|
5444 soap->xlist = xp; |
|
5445 } |
|
5446 #endif |
|
5447 #ifndef WITH_NOIDREF |
|
5448 soap_free_pht(soap); |
|
5449 soap_free_iht(soap); |
|
5450 #endif |
|
5451 } |
|
5452 #endif |
|
5453 |
|
5454 /******************************************************************************/ |
|
5455 #ifdef SOAP_DEBUG |
|
5456 static void |
|
5457 soap_init_logs(struct soap *soap) |
|
5458 { int i; |
|
5459 for (i = 0; i < SOAP_MAXLOGS; i++) |
|
5460 { soap->logfile[i] = NULL; |
|
5461 soap->fdebug[i] = NULL; |
|
5462 } |
|
5463 } |
|
5464 #endif |
|
5465 |
|
5466 /******************************************************************************/ |
|
5467 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG) |
|
5468 SOAP_FMAC1 |
|
5469 void |
|
5470 SOAP_FMAC2 |
|
5471 soap_open_logfile(struct soap *soap, int i) |
|
5472 { if (soap->logfile[i]) |
|
5473 soap->fdebug[i] = fopen(soap->logfile[i], i < 2 ? "ab" : "a"); |
|
5474 } |
|
5475 #endif |
|
5476 |
|
5477 /******************************************************************************/ |
|
5478 #ifdef SOAP_DEBUG |
|
5479 static void |
|
5480 soap_close_logfile(struct soap *soap, int i) |
|
5481 { if (soap->fdebug[i]) |
|
5482 { fclose(soap->fdebug[i]); |
|
5483 soap->fdebug[i] = NULL; |
|
5484 } |
|
5485 } |
|
5486 #endif |
|
5487 |
|
5488 /******************************************************************************/ |
|
5489 #ifdef SOAP_DEBUG |
|
5490 SOAP_FMAC1 |
|
5491 void |
|
5492 SOAP_FMAC2 |
|
5493 soap_close_logfiles(struct soap *soap) |
|
5494 { int i; |
|
5495 for (i = 0; i < SOAP_MAXLOGS; i++) |
|
5496 soap_close_logfile(soap, i); |
|
5497 } |
|
5498 #endif |
|
5499 |
|
5500 /******************************************************************************/ |
|
5501 #ifdef SOAP_DEBUG |
|
5502 static void |
|
5503 soap_set_logfile(struct soap *soap, int i, const char *logfile) |
|
5504 { char *s = NULL; |
|
5505 soap_close_logfile(soap, i); |
|
5506 if (soap->logfile[i]) |
|
5507 SOAP_FREE(soap, (void*)soap->logfile[i]); |
|
5508 if (logfile) |
|
5509 if ((s = (char*)SOAP_MALLOC(soap, strlen(logfile) + 1))) |
|
5510 strcpy(s, logfile); |
|
5511 soap->logfile[i] = s; |
|
5512 } |
|
5513 #endif |
|
5514 |
|
5515 /******************************************************************************/ |
|
5516 #ifdef SOAP_DEBUG |
|
5517 SOAP_FMAC1 |
|
5518 void |
|
5519 SOAP_FMAC2 |
|
5520 soap_set_recv_logfile(struct soap *soap, const char *logfile) |
|
5521 { soap_set_logfile(soap, SOAP_INDEX_RECV, logfile); |
|
5522 } |
|
5523 #endif |
|
5524 |
|
5525 /******************************************************************************/ |
|
5526 #ifdef SOAP_DEBUG |
|
5527 SOAP_FMAC1 |
|
5528 void |
|
5529 SOAP_FMAC2 |
|
5530 soap_set_sent_logfile(struct soap *soap, const char *logfile) |
|
5531 { soap_set_logfile(soap, SOAP_INDEX_SENT, logfile); |
|
5532 } |
|
5533 #endif |
|
5534 |
|
5535 /******************************************************************************/ |
|
5536 #ifdef SOAP_DEBUG |
|
5537 SOAP_FMAC1 |
|
5538 void |
|
5539 SOAP_FMAC2 |
|
5540 soap_set_test_logfile(struct soap *soap, const char *logfile) |
|
5541 { soap_set_logfile(soap, SOAP_INDEX_TEST, logfile); |
|
5542 } |
|
5543 #endif |
|
5544 |
|
5545 /******************************************************************************/ |
|
5546 #ifndef PALM_1 |
|
5547 SOAP_FMAC1 |
|
5548 struct soap* |
|
5549 SOAP_FMAC2 |
|
5550 soap_copy(struct soap *soap) |
|
5551 { return soap_copy_context((struct soap*)malloc(sizeof(struct soap)), soap); |
|
5552 } |
|
5553 #endif |
|
5554 |
|
5555 /******************************************************************************/ |
|
5556 #ifndef PALM_1 |
|
5557 SOAP_FMAC1 |
|
5558 struct soap* |
|
5559 SOAP_FMAC2 |
|
5560 soap_copy_context(struct soap *copy, struct soap *soap) |
|
5561 { if (copy) |
|
5562 { register struct soap_plugin *p; |
|
5563 memcpy(copy, soap, sizeof(struct soap)); |
|
5564 copy->copy = 1; |
|
5565 copy->user = NULL; |
|
5566 copy->error = SOAP_OK; |
|
5567 copy->userid = NULL; |
|
5568 copy->passwd = NULL; |
|
5569 copy->nlist = NULL; |
|
5570 copy->blist = NULL; |
|
5571 copy->clist = NULL; |
|
5572 copy->alist = NULL; |
|
5573 copy->attributes = NULL; |
|
5574 #ifdef WITH_FAST |
|
5575 copy->labbuf = NULL; |
|
5576 copy->lablen = 0; |
|
5577 copy->labidx = 0; |
|
5578 #endif |
|
5579 #ifdef SOAP_DEBUG |
|
5580 soap_init_mht(copy); |
|
5581 #endif |
|
5582 copy->local_namespaces = NULL; |
|
5583 #ifndef WITH_NOIDREF |
|
5584 soap_init_iht(copy); |
|
5585 soap_init_pht(copy); |
|
5586 #endif |
|
5587 copy->header = NULL; |
|
5588 copy->fault = NULL; |
|
5589 copy->action = NULL; |
|
5590 *copy->host = '\0'; |
|
5591 #ifndef WITH_LEAN |
|
5592 #ifdef WITH_COOKIES |
|
5593 copy->cookies = soap_copy_cookies(copy); |
|
5594 #else |
|
5595 copy->cookies = NULL; |
|
5596 #endif |
|
5597 #endif |
|
5598 #ifdef SOAP_DEBUG |
|
5599 soap_init_logs(copy); |
|
5600 soap_set_recv_logfile(copy, soap->logfile[SOAP_INDEX_RECV]); |
|
5601 soap_set_sent_logfile(copy, soap->logfile[SOAP_INDEX_SENT]); |
|
5602 soap_set_test_logfile(copy, soap->logfile[SOAP_INDEX_TEST]); |
|
5603 #endif |
|
5604 copy->plugins = NULL; |
|
5605 for (p = soap->plugins; p; p = p->next) |
|
5606 { register struct soap_plugin *q = (struct soap_plugin*)SOAP_MALLOC(copy, sizeof(struct soap_plugin)); |
|
5607 if (!q) |
|
5608 return NULL; |
|
5609 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying plugin '%s'\n", p->id)); |
|
5610 *q = *p; |
|
5611 if (p->fcopy && (soap->error = p->fcopy(copy, q, p))) |
|
5612 { SOAP_FREE(copy, q); |
|
5613 return NULL; |
|
5614 } |
|
5615 q->next = copy->plugins; |
|
5616 copy->plugins = q; |
|
5617 } |
|
5618 } |
|
5619 else |
|
5620 soap->error = SOAP_EOM; |
|
5621 return copy; |
|
5622 } |
|
5623 #endif |
|
5624 |
|
5625 /******************************************************************************/ |
|
5626 #ifndef PALM_1 |
|
5627 SOAP_FMAC1 |
|
5628 void |
|
5629 SOAP_FMAC2 |
|
5630 soap_init(struct soap *soap) |
|
5631 { soap->version = 0; |
|
5632 soap_imode(soap, SOAP_IO_DEFAULT); |
|
5633 soap_omode(soap, SOAP_IO_DEFAULT); |
|
5634 soap->copy = 0; |
|
5635 soap->plugins = NULL; |
|
5636 soap->user = NULL; |
|
5637 soap->userid = NULL; |
|
5638 soap->passwd = NULL; |
|
5639 #ifndef WITH_NOHTTP |
|
5640 soap->fpost = http_post; |
|
5641 soap->fget = http_get; |
|
5642 soap->fform = NULL; |
|
5643 soap->fposthdr = http_post_header; |
|
5644 soap->fresponse = http_response; |
|
5645 soap->fparse = http_parse; |
|
5646 soap->fparsehdr = http_parse_header; |
|
5647 #endif |
|
5648 soap->fconnect = NULL; |
|
5649 soap->fdisconnect = NULL; |
|
5650 #ifndef WITH_NOIO |
|
5651 #ifndef WITH_IPV6 |
|
5652 soap->fresolve = tcp_gethost; |
|
5653 #else |
|
5654 soap->fresolve = NULL; |
|
5655 #endif |
|
5656 soap->faccept = tcp_accept; |
|
5657 soap->fopen = tcp_connect; |
|
5658 soap->fclose = tcp_disconnect; |
|
5659 soap->fclosesocket = tcp_closesocket; |
|
5660 soap->fshutdownsocket = tcp_shutdownsocket; |
|
5661 soap->fsend = fsend; |
|
5662 soap->frecv = frecv; |
|
5663 soap->fpoll = soap_poll; |
|
5664 #else |
|
5665 soap->fopen = NULL; |
|
5666 soap->fclose = NULL; |
|
5667 soap->fpoll = NULL; |
|
5668 #endif |
|
5669 #ifndef WITH_LEANER |
|
5670 soap->fprepareinit = NULL; |
|
5671 soap->fpreparesend = NULL; |
|
5672 soap->fpreparerecv = NULL; |
|
5673 soap->fpreparefinal = NULL; |
|
5674 #endif |
|
5675 soap->fseterror = NULL; |
|
5676 soap->fignore = NULL; |
|
5677 soap->fserveloop = NULL; |
|
5678 soap->fplugin = fplugin; |
|
5679 #ifndef WITH_LEANER |
|
5680 soap->fdimereadopen = NULL; |
|
5681 soap->fdimewriteopen = NULL; |
|
5682 soap->fdimereadclose = NULL; |
|
5683 soap->fdimewriteclose = NULL; |
|
5684 soap->fdimeread = NULL; |
|
5685 soap->fdimewrite = NULL; |
|
5686 #endif |
|
5687 soap->float_format = "%.8g"; /* .8 preserves single FP precision as much as possible, but might not be very efficient */ |
|
5688 soap->double_format = "%.17lg"; /* .17 preserves double FP precision as much as possible, but might not be very efficient */ |
|
5689 soap->dime_id_format = "cid:id%d"; /* default DIME id format */ |
|
5690 soap->http_version = "1.1"; |
|
5691 soap->actor = NULL; |
|
5692 soap->max_keep_alive = SOAP_MAXKEEPALIVE; |
|
5693 soap->keep_alive = 0; |
|
5694 soap->recv_timeout = 0; |
|
5695 soap->send_timeout = 0; |
|
5696 soap->connect_timeout = 0; |
|
5697 soap->accept_timeout = 0; |
|
5698 soap->socket_flags = 0; |
|
5699 soap->connect_flags = 0; |
|
5700 soap->bind_flags = 0; |
|
5701 soap->accept_flags = 0; |
|
5702 soap->ip = 0; |
|
5703 #ifdef WITH_FAST |
|
5704 soap->labbuf = NULL; |
|
5705 soap->lablen = 0; |
|
5706 soap->labidx = 0; |
|
5707 #endif |
|
5708 soap->encodingStyle = SOAP_STR_EOS; |
|
5709 #ifndef WITH_NONAMESPACES |
|
5710 soap->namespaces = namespaces; |
|
5711 #else |
|
5712 soap->namespaces = NULL; |
|
5713 #endif |
|
5714 soap->local_namespaces = NULL; |
|
5715 soap->nlist = NULL; |
|
5716 soap->blist = NULL; |
|
5717 soap->clist = NULL; |
|
5718 soap->alist = NULL; |
|
5719 soap->attributes = NULL; |
|
5720 soap->header = NULL; |
|
5721 soap->fault = NULL; |
|
5722 soap->master = SOAP_INVALID_SOCKET; |
|
5723 soap->socket = SOAP_INVALID_SOCKET; |
|
5724 soap->os = NULL; |
|
5725 soap->is = NULL; |
|
5726 #ifndef WITH_LEANER |
|
5727 soap->dom = NULL; |
|
5728 soap->dime.list = NULL; |
|
5729 soap->dime.first = NULL; |
|
5730 soap->dime.last = NULL; |
|
5731 soap->mime.list = NULL; |
|
5732 soap->mime.first = NULL; |
|
5733 soap->mime.last = NULL; |
|
5734 soap->mime.boundary = NULL; |
|
5735 soap->mime.start = NULL; |
|
5736 soap->xlist = NULL; |
|
5737 #endif |
|
5738 #ifndef UNDER_CE |
|
5739 soap->recvfd = 0; |
|
5740 soap->sendfd = 1; |
|
5741 #else |
|
5742 soap->recvfd = stdin; |
|
5743 soap->sendfd = stdout; |
|
5744 #endif |
|
5745 soap->host[0] = '\0'; |
|
5746 soap->port = 0; |
|
5747 soap->action = NULL; |
|
5748 soap->proxy_host = NULL; |
|
5749 soap->proxy_port = 8080; |
|
5750 soap->proxy_userid = NULL; |
|
5751 soap->proxy_passwd = NULL; |
|
5752 soap->authrealm = NULL; |
|
5753 soap->prolog = NULL; |
|
5754 #ifdef WITH_OPENSSL |
|
5755 soap->fsslauth = ssl_auth_init; |
|
5756 soap->fsslverify = ssl_verify_callback; |
|
5757 soap->bio = NULL; |
|
5758 soap->ssl = NULL; |
|
5759 soap->ctx = NULL; |
|
5760 soap->require_server_auth = 0; |
|
5761 soap->require_client_auth = 0; |
|
5762 soap->rsa = 0; |
|
5763 soap->keyfile = NULL; |
|
5764 soap->password = NULL; |
|
5765 soap->dhfile = NULL; |
|
5766 soap->cafile = NULL; |
|
5767 soap->capath = NULL; |
|
5768 soap->crlfile = NULL; |
|
5769 soap->randfile = NULL; |
|
5770 soap->session = NULL; |
|
5771 #endif |
|
5772 #ifdef WITH_ZLIB |
|
5773 soap->zlib_state = SOAP_ZLIB_NONE; |
|
5774 soap->zlib_in = SOAP_ZLIB_NONE; |
|
5775 soap->zlib_out = SOAP_ZLIB_NONE; |
|
5776 soap->d_stream.zalloc = NULL; |
|
5777 soap->d_stream.zfree = NULL; |
|
5778 soap->d_stream.opaque = NULL; |
|
5779 soap->z_level = 6; |
|
5780 #endif |
|
5781 #ifndef WITH_LEAN |
|
5782 soap->c14ninclude = NULL; |
|
5783 soap->c14nexclude = NULL; |
|
5784 soap->cookies = NULL; |
|
5785 soap->cookie_domain = NULL; |
|
5786 soap->cookie_path = NULL; |
|
5787 soap->cookie_max = 32; |
|
5788 #endif |
|
5789 #ifdef SOAP_DEBUG |
|
5790 soap_init_mht(soap); |
|
5791 soap_init_logs(soap); |
|
5792 soap_set_recv_logfile(soap, "RECV.log"); |
|
5793 soap_set_sent_logfile(soap, "SENT.log"); |
|
5794 soap_set_test_logfile(soap, NULL); |
|
5795 #endif |
|
5796 #ifdef WMW_RPM_IO |
|
5797 soap->rpmreqid = NULL; |
|
5798 #endif /* WMW_RPM_IO */ |
|
5799 #ifdef PALM |
|
5800 palmNetLibOpen(); |
|
5801 #endif |
|
5802 #ifndef WITH_NOIDREF |
|
5803 soap_init_iht(soap); |
|
5804 soap_init_pht(soap); |
|
5805 #endif |
|
5806 soap_begin(soap); |
|
5807 #ifdef SOAP_DEBUG |
|
5808 soap_set_test_logfile(soap, "TEST.log"); |
|
5809 #endif |
|
5810 } |
|
5811 #endif |
|
5812 |
|
5813 /******************************************************************************/ |
|
5814 #ifndef PALM_1 |
|
5815 SOAP_FMAC1 |
|
5816 void |
|
5817 SOAP_FMAC2 |
|
5818 soap_init1(struct soap *soap, soap_mode mode) |
|
5819 { soap_init2(soap, mode, mode); |
|
5820 } |
|
5821 #endif |
|
5822 |
|
5823 /******************************************************************************/ |
|
5824 #ifndef PALM_1 |
|
5825 SOAP_FMAC1 |
|
5826 void |
|
5827 SOAP_FMAC2 |
|
5828 soap_init2(struct soap *soap, soap_mode imode, soap_mode omode) |
|
5829 { soap_init(soap); |
|
5830 soap_imode(soap, imode); |
|
5831 soap_omode(soap, omode); |
|
5832 } |
|
5833 #endif |
|
5834 |
|
5835 /******************************************************************************/ |
|
5836 #ifndef PALM_2 |
|
5837 SOAP_FMAC1 |
|
5838 void |
|
5839 SOAP_FMAC2 |
|
5840 soap_begin(struct soap *soap) |
|
5841 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing\n")); |
|
5842 if (!soap->keep_alive) |
|
5843 { soap->buflen = 0; |
|
5844 soap->bufidx = 0; |
|
5845 } |
|
5846 soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0); |
|
5847 soap->null = 0; |
|
5848 soap->position = 0; |
|
5849 soap->encoding = 0; |
|
5850 soap->mustUnderstand = 0; |
|
5851 soap->mode = 0; |
|
5852 soap->ns = 0; |
|
5853 soap->part = SOAP_END; |
|
5854 soap->alloced = 0; |
|
5855 soap->count = 0; |
|
5856 soap->length = 0; |
|
5857 soap->cdata = 0; |
|
5858 soap->error = SOAP_OK; |
|
5859 soap->peeked = 0; |
|
5860 soap->ahead = 0; |
|
5861 soap->idnum = 0; |
|
5862 soap->level = 0; |
|
5863 soap->endpoint[0] = '\0'; |
|
5864 #ifndef WITH_LEANER |
|
5865 soap->dime.chunksize = 0; |
|
5866 soap->dime.buflen = 0; |
|
5867 #endif |
|
5868 soap_free(soap); |
|
5869 } |
|
5870 #endif |
|
5871 |
|
5872 /******************************************************************************/ |
|
5873 #ifndef PALM_2 |
|
5874 SOAP_FMAC1 |
|
5875 void |
|
5876 SOAP_FMAC2 |
|
5877 soap_end(struct soap *soap) |
|
5878 { register struct soap_clist *cp; |
|
5879 soap_free(soap); |
|
5880 soap_dealloc(soap, NULL); |
|
5881 while (soap->clist) |
|
5882 { cp = soap->clist->next; |
|
5883 SOAP_FREE(soap, soap->clist); |
|
5884 soap->clist = cp; |
|
5885 } |
|
5886 soap_closesock(soap); |
|
5887 #ifdef SOAP_DEBUG |
|
5888 soap_close_logfiles(soap); |
|
5889 #endif |
|
5890 #ifdef PALM |
|
5891 palmNetLibClose(); |
|
5892 #endif |
|
5893 } |
|
5894 #endif |
|
5895 |
|
5896 /******************************************************************************/ |
|
5897 #ifndef PALM_1 |
|
5898 SOAP_FMAC1 |
|
5899 int |
|
5900 SOAP_FMAC2 |
|
5901 soap_set_namespaces(struct soap *soap, struct Namespace *p) |
|
5902 { register struct Namespace *ns = soap->local_namespaces; |
|
5903 register struct soap_nlist *np, *nq, *nr; |
|
5904 register unsigned int level = soap->level; |
|
5905 soap->namespaces = p; |
|
5906 soap->local_namespaces = NULL; |
|
5907 soap_set_local_namespaces(soap); |
|
5908 /* reverse the namespace list */ |
|
5909 np = soap->nlist; |
|
5910 soap->nlist = NULL; |
|
5911 if (np) |
|
5912 { nq = np->next; |
|
5913 np->next = NULL; |
|
5914 while (nq) |
|
5915 { nr = nq->next; |
|
5916 nq->next = np; |
|
5917 np = nq; |
|
5918 nq = nr; |
|
5919 } |
|
5920 } |
|
5921 /* then push on new stack */ |
|
5922 while (np) |
|
5923 { register const char *s; |
|
5924 soap->level = np->level; /* preserve element nesting level */ |
|
5925 s = np->ns; |
|
5926 if (!s && np->index >= 0 && ns) |
|
5927 { s = ns[np->index].out; |
|
5928 if (!s) |
|
5929 s = ns[np->index].ns; |
|
5930 } |
|
5931 if (s && soap_push_namespace(soap, np->id, s)) |
|
5932 return soap->error; |
|
5933 nq = np; |
|
5934 np = np->next; |
|
5935 SOAP_FREE(soap, nq); |
|
5936 } |
|
5937 if (ns) |
|
5938 { register int i; |
|
5939 for (i = 0; ns[i].id; i++) |
|
5940 { if (ns[i].out) |
|
5941 { SOAP_FREE(soap, ns[i].out); |
|
5942 ns[i].out = NULL; |
|
5943 } |
|
5944 } |
|
5945 SOAP_FREE(soap, ns); |
|
5946 } |
|
5947 soap->level = level; /* restore level */ |
|
5948 return SOAP_OK; |
|
5949 } |
|
5950 #endif |
|
5951 |
|
5952 /******************************************************************************/ |
|
5953 #ifndef PALM_1 |
|
5954 SOAP_FMAC1 |
|
5955 void |
|
5956 SOAP_FMAC2 |
|
5957 soap_set_local_namespaces(struct soap *soap) |
|
5958 { if (soap->namespaces && !soap->local_namespaces) |
|
5959 { register const struct Namespace *ns1; |
|
5960 register struct Namespace *ns2; |
|
5961 register size_t n = 1; |
|
5962 for (ns1 = soap->namespaces; ns1->id; ns1++) |
|
5963 n++; |
|
5964 n *= sizeof(struct Namespace); |
|
5965 ns2 = (struct Namespace*)SOAP_MALLOC(soap, n); |
|
5966 if (ns2) |
|
5967 { memcpy(ns2, soap->namespaces, n); |
|
5968 if (ns2[0].ns) |
|
5969 { if (!strcmp(ns2[0].ns, soap_env1)) |
|
5970 soap->version = 1; |
|
5971 else |
|
5972 soap->version = 2; |
|
5973 } |
|
5974 soap->local_namespaces = ns2; |
|
5975 } |
|
5976 } |
|
5977 } |
|
5978 #endif |
|
5979 |
|
5980 /******************************************************************************/ |
|
5981 #ifndef WITH_LEAN |
|
5982 #ifndef PALM_1 |
|
5983 SOAP_FMAC1 |
|
5984 const char * |
|
5985 SOAP_FMAC2 |
|
5986 soap_strsearch(const char *big, const char *little) |
|
5987 { size_t n = strlen(little); |
|
5988 const char *s = big; |
|
5989 while (s) |
|
5990 { if (!strncmp(s, little, n) && (s[n] == '\0' || s[n] == ' ')) |
|
5991 return s; |
|
5992 s = strchr(s, ' '); |
|
5993 if (s) |
|
5994 s++; |
|
5995 } |
|
5996 return NULL; |
|
5997 } |
|
5998 #endif |
|
5999 #endif |
|
6000 |
|
6001 /******************************************************************************/ |
|
6002 #ifndef WITH_LEAN |
|
6003 static struct soap_nlist * |
|
6004 soap_lookup_ns(struct soap *soap, const char *tag, size_t n) |
|
6005 { register struct soap_nlist *np; |
|
6006 for (np = soap->nlist; np; np = np->next) |
|
6007 { if (!strncmp(np->id, tag, n) && !np->id[n]) |
|
6008 return np; |
|
6009 } |
|
6010 return NULL; |
|
6011 } |
|
6012 #endif |
|
6013 |
|
6014 /******************************************************************************/ |
|
6015 #ifndef WITH_LEAN |
|
6016 static struct soap_nlist * |
|
6017 soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized) |
|
6018 { register struct soap_nlist *np; |
|
6019 size_t n, k; |
|
6020 if (soap_strsearch(soap->c14nexclude, id)) |
|
6021 return NULL; |
|
6022 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push namespace binding (level=%u) '%s' '%s'\n", soap->level, id, ns?ns:"")); |
|
6023 if (!utilized) |
|
6024 { for (np = soap->nlist; np; np = np->next) |
|
6025 { if (!strcmp(np->id, id) && (!np->ns || !strcmp(np->ns, ns))) |
|
6026 break; |
|
6027 } |
|
6028 if (np) |
|
6029 { if (np->index == 1) |
|
6030 utilized = np->index; |
|
6031 else |
|
6032 return NULL; |
|
6033 } |
|
6034 } |
|
6035 n = strlen(id); |
|
6036 if (ns) |
|
6037 k = strlen(ns); |
|
6038 else |
|
6039 k = 0; |
|
6040 np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k + 1); |
|
6041 if (!np) |
|
6042 { soap->error = SOAP_EOM; |
|
6043 return NULL; |
|
6044 } |
|
6045 np->next = soap->nlist; |
|
6046 soap->nlist = np; |
|
6047 strcpy(np->id, id); |
|
6048 if (ns) |
|
6049 { np->ns = np->id + n + 1; |
|
6050 strcpy(np->ns, ns); |
|
6051 } |
|
6052 else |
|
6053 np->ns = NULL; |
|
6054 np->level = soap->level; |
|
6055 np->index = utilized; |
|
6056 return np; |
|
6057 } |
|
6058 #endif |
|
6059 |
|
6060 /******************************************************************************/ |
|
6061 #ifndef WITH_LEAN |
|
6062 static void |
|
6063 soap_utilize_ns(struct soap *soap, const char *tag, size_t n) |
|
6064 { register struct soap_nlist *np = soap_lookup_ns(soap, tag, n); |
|
6065 if (np) |
|
6066 { if (np->index == 0) |
|
6067 soap_push_ns(soap, np->id, np->ns, 1); |
|
6068 } |
|
6069 else |
|
6070 { strncpy(soap->tmpbuf, tag, n); |
|
6071 soap->tmpbuf[n] = '\0'; |
|
6072 soap_push_ns(soap, soap->tmpbuf, NULL, 1); |
|
6073 } |
|
6074 } |
|
6075 #endif |
|
6076 |
|
6077 /******************************************************************************/ |
|
6078 #ifndef WITH_LEAN |
|
6079 static void |
|
6080 soap_pop_ns(struct soap *soap) |
|
6081 { soap_pop_namespace(soap); |
|
6082 } |
|
6083 #endif |
|
6084 |
|
6085 /******************************************************************************/ |
|
6086 #ifndef PALM_2 |
|
6087 SOAP_FMAC1 |
|
6088 int |
|
6089 SOAP_FMAC2 |
|
6090 soap_element(struct soap *soap, const char *tag, int id, const char *type) |
|
6091 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element begin tag='%s' id='%d' type='%s'\n", tag, id, type?type:"")); |
|
6092 #ifdef WITH_DOM |
|
6093 if (soap->mode & SOAP_XML_DOM) |
|
6094 { register struct soap_dom_element *elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element)); |
|
6095 if (!elt) |
|
6096 return soap->error = SOAP_EOM; |
|
6097 elt->soap = soap; |
|
6098 elt->next = NULL; |
|
6099 elt->prnt = soap->dom; |
|
6100 elt->name = soap_strdup(soap, tag); |
|
6101 elt->elts = NULL; |
|
6102 elt->atts = NULL; |
|
6103 elt->nstr = NULL; |
|
6104 elt->data = NULL; |
|
6105 elt->wide = NULL; |
|
6106 elt->node = NULL; |
|
6107 elt->type = 0; |
|
6108 elt->head = NULL; |
|
6109 elt->tail = NULL; |
|
6110 if (soap->dom) |
|
6111 { struct soap_dom_element *p = soap->dom->elts; |
|
6112 if (p) |
|
6113 { while (p->next) |
|
6114 p = p->next; |
|
6115 p->next = elt; |
|
6116 } |
|
6117 else |
|
6118 soap->dom->elts = elt; |
|
6119 } |
|
6120 soap->dom = elt; |
|
6121 } |
|
6122 else |
|
6123 { |
|
6124 #endif |
|
6125 soap->level++; |
|
6126 #ifndef WITH_LEAN |
|
6127 if (!soap->ns) |
|
6128 { if (!(soap->mode & SOAP_XML_CANONICAL) |
|
6129 && soap_send(soap, soap->prolog ? soap->prolog : "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")) |
|
6130 return soap->error; |
|
6131 } |
|
6132 else if (soap->mode & SOAP_XML_INDENT) |
|
6133 { if (soap->ns == 1 && soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1)) |
|
6134 return soap->error; |
|
6135 soap->body = 1; |
|
6136 } |
|
6137 #endif |
|
6138 if (soap_send_raw(soap, "<", 1) |
|
6139 || soap_send(soap, tag)) |
|
6140 return soap->error; |
|
6141 #ifdef WITH_DOM |
|
6142 } |
|
6143 #endif |
|
6144 if (!soap->ns) |
|
6145 { struct Namespace *ns; |
|
6146 for (ns = soap->local_namespaces; ns && ns->id; ns++) |
|
6147 { if (*ns->id && (ns->out || ns->ns)) |
|
6148 { sprintf(soap->tmpbuf, "xmlns:%s", ns->id); |
|
6149 if (soap_attribute(soap, soap->tmpbuf, ns->out ? ns->out : ns->ns)) |
|
6150 return soap->error; |
|
6151 } |
|
6152 } |
|
6153 } |
|
6154 soap->ns = 1; /* start with 0 or 2, but should be one to continue */ |
|
6155 #ifndef WITH_LEAN |
|
6156 if (soap->mode & SOAP_XML_CANONICAL) |
|
6157 { const char *s = strchr(tag, ':'); |
|
6158 if (s) |
|
6159 soap_utilize_ns(soap, tag, s - tag); |
|
6160 } |
|
6161 #endif |
|
6162 if (id > 0) |
|
6163 { sprintf(soap->tmpbuf, "_%d", id); |
|
6164 if (soap_attribute(soap, "id", soap->tmpbuf)) |
|
6165 return soap->error; |
|
6166 } |
|
6167 if (type && *type) |
|
6168 { if (soap_attribute(soap, "xsi:type", type)) |
|
6169 return soap->error; |
|
6170 #ifndef WITH_LEAN |
|
6171 if (soap->mode & SOAP_XML_CANONICAL) |
|
6172 { const char *s = strchr(type, ':'); |
|
6173 if (s) |
|
6174 soap_utilize_ns(soap, type, s - type); |
|
6175 } |
|
6176 #endif |
|
6177 } |
|
6178 if (soap->null && soap->position > 0) |
|
6179 { int i; |
|
6180 sprintf(soap->tmpbuf, "[%d", soap->positions[0]); |
|
6181 for (i = 1; i < soap->position; i++) |
|
6182 sprintf(soap->tmpbuf + strlen(soap->tmpbuf), ",%d", soap->positions[i]); |
|
6183 strcat(soap->tmpbuf, "]"); |
|
6184 if (soap_attribute(soap, "SOAP-ENC:position", soap->tmpbuf)) |
|
6185 return soap->error; |
|
6186 } |
|
6187 if (soap->mustUnderstand) |
|
6188 { if (soap->actor && *soap->actor) |
|
6189 { if (soap_attribute(soap, soap->version == 2 ? "SOAP-ENV:role" : "SOAP-ENV:actor", soap->actor)) |
|
6190 return soap->error; |
|
6191 } |
|
6192 if (soap_attribute(soap, "SOAP-ENV:mustUnderstand", soap->version == 2 ? "true" : "1")) |
|
6193 return soap->error; |
|
6194 soap->mustUnderstand = 0; |
|
6195 } |
|
6196 if (soap->encoding) |
|
6197 { if (soap->encodingStyle && soap->local_namespaces) |
|
6198 { if (!*soap->encodingStyle) |
|
6199 { if (soap->local_namespaces[1].out) |
|
6200 soap->encodingStyle = soap->local_namespaces[1].out; |
|
6201 else |
|
6202 soap->encodingStyle = soap->local_namespaces[1].ns; |
|
6203 } |
|
6204 if (soap_attribute(soap, "SOAP-ENV:encodingStyle", soap->encodingStyle)) |
|
6205 return soap->error; |
|
6206 } |
|
6207 soap->encoding = 0; |
|
6208 } |
|
6209 soap->null = 0; |
|
6210 soap->position = 0; |
|
6211 return SOAP_OK; |
|
6212 } |
|
6213 #endif |
|
6214 |
|
6215 /******************************************************************************/ |
|
6216 #ifndef PALM_2 |
|
6217 SOAP_FMAC1 |
|
6218 int |
|
6219 SOAP_FMAC2 |
|
6220 soap_element_begin_out(struct soap *soap, const char *tag, int id, const char *type) |
|
6221 { if (*tag == '-') |
|
6222 return SOAP_OK; |
|
6223 if (soap_element(soap, tag, id, type)) |
|
6224 return soap->error; |
|
6225 return soap_element_start_end_out(soap, NULL); |
|
6226 } |
|
6227 #endif |
|
6228 |
|
6229 /******************************************************************************/ |
|
6230 #ifndef PALM_2 |
|
6231 #ifndef HAVE_STRRCHR |
|
6232 SOAP_FMAC1 |
|
6233 char* |
|
6234 SOAP_FMAC2 |
|
6235 soap_strrchr(const char *s, int t) |
|
6236 { register char *r = NULL; |
|
6237 while (*s) |
|
6238 if (*s++ == t) |
|
6239 r = (char*)s - 1; |
|
6240 return r; |
|
6241 } |
|
6242 #endif |
|
6243 #endif |
|
6244 |
|
6245 /******************************************************************************/ |
|
6246 #ifndef PALM_2 |
|
6247 #ifndef HAVE_STRTOL |
|
6248 SOAP_FMAC1 |
|
6249 long |
|
6250 SOAP_FMAC2 |
|
6251 soap_strtol(const char *s, char **t, int b) |
|
6252 { register long n = 0; |
|
6253 register int c; |
|
6254 while (*s > 0 && *s <= 32) |
|
6255 s++; |
|
6256 if (b == 10) |
|
6257 { short neg = 0; |
|
6258 if (*s == '-') |
|
6259 { s++; |
|
6260 neg = 1; |
|
6261 } |
|
6262 else if (*s == '+') |
|
6263 s++; |
|
6264 while ((c = *s) && c >= '0' && c <= '9') |
|
6265 { if (n >= 214748364 && (n > 214748364 || c >= '8')) |
|
6266 break; |
|
6267 n *= 10; |
|
6268 n += c - '0'; |
|
6269 s++; |
|
6270 } |
|
6271 if (neg) |
|
6272 n = -n; |
|
6273 } |
|
6274 else /* b == 16 and value is always positive */ |
|
6275 { while ((c = *s)) |
|
6276 { if (c >= '0' && c <= '9') |
|
6277 c -= '0'; |
|
6278 else if (c >= 'A' && c <= 'F') |
|
6279 c -= 'A' - 10; |
|
6280 else if (c >= 'a' && c <= 'f') |
|
6281 c -= 'a' - 10; |
|
6282 if (n > 0x07FFFFFF) |
|
6283 break; |
|
6284 n <<= 4; |
|
6285 n += c; |
|
6286 s++; |
|
6287 } |
|
6288 } |
|
6289 if (t) |
|
6290 *t = (char*)s; |
|
6291 return n; |
|
6292 } |
|
6293 #endif |
|
6294 #endif |
|
6295 |
|
6296 /******************************************************************************/ |
|
6297 #ifndef PALM_2 |
|
6298 #ifndef HAVE_STRTOUL |
|
6299 SOAP_FMAC1 |
|
6300 unsigned long |
|
6301 SOAP_FMAC2 |
|
6302 soap_strtoul(const char *s, char **t, int b) |
|
6303 { unsigned long n = 0; |
|
6304 register int c; |
|
6305 while (*s > 0 && *s <= 32) |
|
6306 s++; |
|
6307 if (b == 10) |
|
6308 { if (*s == '+') |
|
6309 s++; |
|
6310 while ((c = *s) && c >= '0' && c <= '9') |
|
6311 { if (n >= 429496729 && (n > 429496729 || c >= '6')) |
|
6312 break; |
|
6313 n *= 10; |
|
6314 n += c - '0'; |
|
6315 s++; |
|
6316 } |
|
6317 } |
|
6318 else /* b == 16 */ |
|
6319 { while ((c = *s)) |
|
6320 { if (c >= '0' && c <= '9') |
|
6321 c -= '0'; |
|
6322 else if (c >= 'A' && c <= 'F') |
|
6323 c -= 'A' - 10; |
|
6324 else if (c >= 'a' && c <= 'f') |
|
6325 c -= 'a' - 10; |
|
6326 if (n > 0x0FFFFFFF) |
|
6327 break; |
|
6328 n <<= 4; |
|
6329 n += c; |
|
6330 s++; |
|
6331 } |
|
6332 } |
|
6333 if (t) |
|
6334 *t = (char*)s; |
|
6335 return n; |
|
6336 } |
|
6337 #endif |
|
6338 #endif |
|
6339 |
|
6340 /******************************************************************************/ |
|
6341 #ifndef PALM_1 |
|
6342 SOAP_FMAC1 |
|
6343 int |
|
6344 SOAP_FMAC2 |
|
6345 soap_array_begin_out(struct soap *soap, const char *tag, int id, const char *type, const char *offset) |
|
6346 { if (soap_element(soap, tag, id, "SOAP-ENC:Array")) |
|
6347 return soap->error; |
|
6348 if (soap->version == 2) |
|
6349 { const char *s; |
|
6350 s = soap_strrchr(type, '['); |
|
6351 if ((size_t)(s - type) < sizeof(soap->tmpbuf)) |
|
6352 { strncpy(soap->tmpbuf, type, s - type); |
|
6353 soap->tmpbuf[s - type] = '\0'; |
|
6354 if (type && *type && (soap_attribute(soap, "SOAP-ENC:itemType", soap->tmpbuf))) |
|
6355 return soap->error; |
|
6356 if (s && (soap_attribute(soap, "SOAP-ENC:arraySize", s + 1))) |
|
6357 return soap->error; |
|
6358 } |
|
6359 } |
|
6360 else |
|
6361 { if (offset && (soap_attribute(soap, "SOAP-ENC:offset", offset))) |
|
6362 return soap->error; |
|
6363 if (type && *type && (soap_attribute(soap, "SOAP-ENC:arrayType", type))) |
|
6364 return soap->error; |
|
6365 } |
|
6366 #ifndef WITH_LEAN |
|
6367 if (type && *type && (soap->mode & SOAP_XML_CANONICAL)) |
|
6368 { const char *s = strchr(type, ':'); |
|
6369 if (s) |
|
6370 soap_utilize_ns(soap, type, s - type); |
|
6371 } |
|
6372 #endif |
|
6373 return soap_element_start_end_out(soap, NULL); |
|
6374 } |
|
6375 #endif |
|
6376 |
|
6377 /******************************************************************************/ |
|
6378 #ifndef PALM_1 |
|
6379 SOAP_FMAC1 |
|
6380 int |
|
6381 SOAP_FMAC2 |
|
6382 soap_element_start_end_out(struct soap *soap, const char *tag) |
|
6383 { register struct soap_attribute *tp; |
|
6384 #ifdef WITH_DOM |
|
6385 register struct soap_dom_attribute **att; |
|
6386 if ((soap->mode & SOAP_XML_DOM) && soap->dom) |
|
6387 { att = &soap->dom->atts; |
|
6388 for (tp = soap->attributes; tp; tp = tp->next) |
|
6389 { if (tp->visible) |
|
6390 { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); |
|
6391 if (!*att) |
|
6392 return soap->error = SOAP_EOM; |
|
6393 (*att)->next = NULL; |
|
6394 (*att)->nstr = NULL; |
|
6395 (*att)->name = soap_strdup(soap, tp->name); |
|
6396 (*att)->data = soap_strdup(soap, tp->value); |
|
6397 (*att)->wide = NULL; |
|
6398 (*att)->soap = soap; |
|
6399 tp->visible = 0; |
|
6400 } |
|
6401 } |
|
6402 return SOAP_OK; |
|
6403 } |
|
6404 #endif |
|
6405 #ifndef WITH_LEAN |
|
6406 if (soap->mode & SOAP_XML_CANONICAL) |
|
6407 { struct soap_nlist *np; |
|
6408 for (tp = soap->attributes; tp; tp = tp->next) |
|
6409 { if (tp->visible && tp->name) |
|
6410 { const char *s = strchr(tp->name, ':'); |
|
6411 if (s) |
|
6412 soap_utilize_ns(soap, tp->name, s - tp->name); |
|
6413 } |
|
6414 } |
|
6415 for (np = soap->nlist; np; np = np->next) |
|
6416 { if (np->index == 1 && np->ns) |
|
6417 { sprintf(soap->tmpbuf, "xmlns:%s", np->id); |
|
6418 soap_set_attr(soap, soap->tmpbuf, np->ns); |
|
6419 np->index = 2; |
|
6420 } |
|
6421 } |
|
6422 } |
|
6423 #endif |
|
6424 for (tp = soap->attributes; tp; tp = tp->next) |
|
6425 { if (tp->visible) |
|
6426 { if (soap_send(soap, " ") || soap_send(soap, tp->name)) |
|
6427 return soap->error; |
|
6428 if (tp->visible == 2 && tp->value) |
|
6429 if (soap_send_raw(soap, "=\"", 2) |
|
6430 || soap_string_out(soap, tp->value, 1) |
|
6431 || soap_send_raw(soap, "\"", 1)) |
|
6432 return soap->error; |
|
6433 tp->visible = 0; |
|
6434 } |
|
6435 } |
|
6436 if (tag) |
|
6437 { |
|
6438 #ifndef WITH_LEAN |
|
6439 if (soap->mode & SOAP_XML_CANONICAL) |
|
6440 { if (soap_send_raw(soap, ">", 1) |
|
6441 || soap_element_end_out(soap, tag)) |
|
6442 return soap->error; |
|
6443 } |
|
6444 else |
|
6445 #endif |
|
6446 soap->level--; /* decrement level just before /> */ |
|
6447 if (soap_send_raw(soap, "/>", 2)) |
|
6448 return soap->error; |
|
6449 return SOAP_OK; |
|
6450 } |
|
6451 return soap_send_raw(soap, ">", 1); |
|
6452 } |
|
6453 #endif |
|
6454 |
|
6455 /******************************************************************************/ |
|
6456 #ifndef PALM_1 |
|
6457 SOAP_FMAC1 |
|
6458 int |
|
6459 SOAP_FMAC2 |
|
6460 soap_element_end_out(struct soap *soap, const char *tag) |
|
6461 { if (*tag == '-') |
|
6462 return SOAP_OK; |
|
6463 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element ending tag='%s'\n", tag)); |
|
6464 #ifdef WITH_DOM |
|
6465 if ((soap->mode & SOAP_XML_DOM) && soap->dom) |
|
6466 { if (soap->dom->prnt) |
|
6467 soap->dom = soap->dom->prnt; |
|
6468 return SOAP_OK; |
|
6469 } |
|
6470 #endif |
|
6471 #ifndef WITH_LEAN |
|
6472 if (soap->mode & SOAP_XML_CANONICAL) |
|
6473 soap_pop_ns(soap); |
|
6474 if (soap->mode & SOAP_XML_INDENT) |
|
6475 { if (!soap->body) |
|
6476 { if (soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1)) |
|
6477 return soap->error; |
|
6478 } |
|
6479 soap->body = 0; |
|
6480 } |
|
6481 #endif |
|
6482 if (soap_send_raw(soap, "</", 2) |
|
6483 || soap_send(soap, tag)) |
|
6484 return soap->error; |
|
6485 soap->level--; /* decrement level just before > */ |
|
6486 return soap_send_raw(soap, ">", 1); |
|
6487 } |
|
6488 #endif |
|
6489 |
|
6490 /******************************************************************************/ |
|
6491 #ifndef PALM_1 |
|
6492 SOAP_FMAC1 |
|
6493 int |
|
6494 SOAP_FMAC2 |
|
6495 soap_element_ref(struct soap *soap, const char *tag, int id, int href) |
|
6496 { register int n = 0; |
|
6497 if (soap->version == 2) |
|
6498 n = 1; |
|
6499 sprintf(soap->href, "#_%d", href); |
|
6500 return soap_element_href(soap, tag, id, "href" + n, soap->href + n); |
|
6501 } |
|
6502 #endif |
|
6503 |
|
6504 /******************************************************************************/ |
|
6505 #ifndef PALM_1 |
|
6506 SOAP_FMAC1 |
|
6507 int |
|
6508 SOAP_FMAC2 |
|
6509 soap_element_href(struct soap *soap, const char *tag, int id, const char *ref, const char *val) |
|
6510 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element '%s' reference %s='%s'\n", tag, ref, val)); |
|
6511 if (soap_element(soap, tag, id, NULL) |
|
6512 || soap_attribute(soap, ref, val) |
|
6513 || soap_element_start_end_out(soap, tag)) |
|
6514 return soap->error; |
|
6515 return SOAP_OK; |
|
6516 } |
|
6517 #endif |
|
6518 |
|
6519 /******************************************************************************/ |
|
6520 #ifndef PALM_1 |
|
6521 SOAP_FMAC1 |
|
6522 int |
|
6523 SOAP_FMAC2 |
|
6524 soap_element_null(struct soap *soap, const char *tag, int id, const char *type) |
|
6525 { struct soap_attribute *tp; |
|
6526 for (tp = soap->attributes; tp; tp = tp->next) |
|
6527 if (tp->visible) |
|
6528 break; |
|
6529 if (tp || (soap->version == 2 && soap->position > 0) || id > 0 || (soap->mode & SOAP_XML_NIL)) |
|
6530 { if (soap_element(soap, tag, id, type)) |
|
6531 return soap->error; |
|
6532 if (soap->part != SOAP_IN_HEADER && soap->encodingStyle) |
|
6533 if (soap_attribute(soap, "xsi:nil", "true")) |
|
6534 return soap->error; |
|
6535 return soap_element_start_end_out(soap, tag); |
|
6536 } |
|
6537 soap->null = 1; |
|
6538 soap->position = 0; |
|
6539 soap->mustUnderstand = 0; |
|
6540 return SOAP_OK; |
|
6541 } |
|
6542 #endif |
|
6543 |
|
6544 /******************************************************************************/ |
|
6545 #ifndef PALM_1 |
|
6546 SOAP_FMAC1 |
|
6547 int |
|
6548 SOAP_FMAC2 |
|
6549 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) |
|
6550 { if (!p || (a && !a->__ptr)) |
|
6551 { soap_element_null(soap, tag, id, type); |
|
6552 return -1; |
|
6553 } |
|
6554 #ifndef WITH_NOIDREF |
|
6555 if (soap->mode & SOAP_XML_TREE) |
|
6556 return 0; |
|
6557 if (id < 0) |
|
6558 { struct soap_plist *pp; |
|
6559 if (a) |
|
6560 id = soap_array_pointer_lookup(soap, p, a, n, t, &pp); |
|
6561 else |
|
6562 id = soap_pointer_lookup(soap, p, t, &pp); |
|
6563 if (id) |
|
6564 { if (soap_is_embedded(soap, pp)) |
|
6565 { soap_element_ref(soap, tag, 0, id); |
|
6566 return -1; |
|
6567 } |
|
6568 if (soap_is_single(soap, pp)) |
|
6569 return 0; |
|
6570 soap_set_embedded(soap, pp); |
|
6571 } |
|
6572 } |
|
6573 return id; |
|
6574 #else |
|
6575 return 0; |
|
6576 #endif |
|
6577 } |
|
6578 #endif |
|
6579 |
|
6580 /******************************************************************************/ |
|
6581 #ifndef PALM_1 |
|
6582 SOAP_FMAC1 |
|
6583 int |
|
6584 SOAP_FMAC2 |
|
6585 soap_element_result(struct soap *soap, const char *tag) |
|
6586 { if (soap->version == 2 && soap->encodingStyle) |
|
6587 if (soap_element(soap, "SOAP-RPC:result", 0, NULL) |
|
6588 || soap_attribute(soap, "xmlns:SOAP-RPC", soap_rpc) |
|
6589 || soap_element_start_end_out(soap, NULL) |
|
6590 || soap_string_out(soap, tag, 0) |
|
6591 || soap_element_end_out(soap, "SOAP-RPC:result")) |
|
6592 return soap->error; |
|
6593 return SOAP_OK; |
|
6594 } |
|
6595 #endif |
|
6596 |
|
6597 /******************************************************************************/ |
|
6598 #ifndef PALM_2 |
|
6599 SOAP_FMAC1 |
|
6600 int |
|
6601 SOAP_FMAC2 |
|
6602 soap_attribute(struct soap *soap, const char *name, const char *value) |
|
6603 { |
|
6604 #ifdef WITH_DOM |
|
6605 if ((soap->mode & SOAP_XML_DOM) && soap->dom) |
|
6606 { register struct soap_dom_attribute *a = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); |
|
6607 a->next = soap->dom->atts; |
|
6608 a->nstr = NULL; |
|
6609 a->name = soap_strdup(soap, name); |
|
6610 a->data = soap_strdup(soap, value); |
|
6611 a->wide = NULL; |
|
6612 a->soap = soap; |
|
6613 soap->dom->atts = a; |
|
6614 return SOAP_OK; |
|
6615 } |
|
6616 #endif |
|
6617 #ifndef WITH_LEAN |
|
6618 if (soap->mode & SOAP_XML_CANONICAL) |
|
6619 { /* TODO: consider using this code to handle default namespace |
|
6620 if (!strncmp(name, "xmlns", 5) && (name[5] == ':' || name[5] == '\0')) |
|
6621 { if (name[5] == ':') |
|
6622 soap_push_ns(soap, name + 6, value, 0); |
|
6623 else |
|
6624 soap_push_ns(soap, "", value, 0); |
|
6625 } |
|
6626 */ |
|
6627 if (!strncmp(name, "xmlns:", 6)) |
|
6628 soap_push_ns(soap, name + 6, value, 0); |
|
6629 else if (soap_set_attr(soap, name, value)) |
|
6630 return soap->error; |
|
6631 } |
|
6632 else |
|
6633 #endif |
|
6634 { if (soap_send(soap, " ") || soap_send(soap, name)) |
|
6635 return soap->error; |
|
6636 if (value) |
|
6637 if (soap_send_raw(soap, "=\"", 2) |
|
6638 || soap_string_out(soap, value, 1) |
|
6639 || soap_send_raw(soap, "\"", 1)) |
|
6640 return soap->error; |
|
6641 } |
|
6642 return SOAP_OK; |
|
6643 } |
|
6644 #endif |
|
6645 |
|
6646 /******************************************************************************/ |
|
6647 #ifndef PALM_2 |
|
6648 SOAP_FMAC1 |
|
6649 int |
|
6650 SOAP_FMAC2 |
|
6651 soap_element_begin_in(struct soap *soap, const char *tag, int nillable) |
|
6652 { if (!soap_peek_element(soap)) |
|
6653 { if (soap->other) |
|
6654 return soap->error = SOAP_TAG_MISMATCH; |
|
6655 if (tag && *tag == '-') |
|
6656 return SOAP_OK; |
|
6657 if (!(soap->error = soap_match_tag(soap, soap->tag, tag))) |
|
6658 { soap->peeked = 0; |
|
6659 if (soap->body) |
|
6660 soap->level++; |
|
6661 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:"" )); |
|
6662 if (!nillable && soap->null && (soap->mode & SOAP_XML_STRICT)) |
|
6663 return soap->error = SOAP_NULL; |
|
6664 } |
|
6665 } |
|
6666 else if (soap->error == SOAP_NO_TAG && tag && *tag == '-') |
|
6667 soap->error = SOAP_OK; |
|
6668 return soap->error; |
|
6669 } |
|
6670 #endif |
|
6671 |
|
6672 /******************************************************************************/ |
|
6673 #ifndef PALM_2 |
|
6674 SOAP_FMAC1 |
|
6675 int |
|
6676 SOAP_FMAC2 |
|
6677 soap_element_end_in(struct soap *soap, const char *tag) |
|
6678 { register soap_wchar c; |
|
6679 register char *s; |
|
6680 register const char *t; |
|
6681 register int n = 0; |
|
6682 if (tag && *tag == '-') |
|
6683 return SOAP_OK; |
|
6684 soap->level--; |
|
6685 soap_pop_namespace(soap); |
|
6686 #ifdef WITH_DOM |
|
6687 /* this whitespace or mixed content is not insignificant for DOM */ |
|
6688 if ((soap->mode & SOAP_XML_DOM) && soap->dom) |
|
6689 { if (!soap->peeked && !soap_string_in(soap, 3, -1, -1)) |
|
6690 return soap->error; |
|
6691 if (soap->dom->prnt) |
|
6692 soap->dom = soap->dom->prnt; |
|
6693 } |
|
6694 #endif |
|
6695 if (soap->peeked) |
|
6696 { if (soap->error == SOAP_NO_TAG) |
|
6697 soap->error = SOAP_OK; |
|
6698 if (*soap->tag) |
|
6699 n++; |
|
6700 soap->peeked = 0; |
|
6701 } |
|
6702 do |
|
6703 { while (((c = soap_get(soap)) != SOAP_TT)) |
|
6704 { if ((int)c == EOF) |
|
6705 return soap->error = SOAP_EOF; |
|
6706 if (c == SOAP_LT) |
|
6707 n++; |
|
6708 else if (c == '/') |
|
6709 { c = soap_get(soap); |
|
6710 if (c == SOAP_GT) |
|
6711 n--; |
|
6712 else |
|
6713 soap_unget(soap, c); |
|
6714 } |
|
6715 } |
|
6716 } while (n--); |
|
6717 s = soap->tag; |
|
6718 while (soap_notblank(c = soap_getutf8(soap))) |
|
6719 *s++ = (char)c; |
|
6720 *s = '\0'; |
|
6721 if ((int)c == EOF) |
|
6722 return soap->error = SOAP_EOF; |
|
6723 while (soap_blank(c)) |
|
6724 c = soap_get(soap); |
|
6725 if (c != SOAP_GT) |
|
6726 return soap->error = SOAP_SYNTAX_ERROR; |
|
6727 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:"")); |
|
6728 if (!tag || !*tag) |
|
6729 return SOAP_OK; |
|
6730 if ((s = strchr(soap->tag, ':'))) |
|
6731 s++; |
|
6732 else |
|
6733 s = soap->tag; |
|
6734 if ((t = strchr(tag, ':'))) |
|
6735 t++; |
|
6736 else |
|
6737 t = tag; |
|
6738 if (!SOAP_STRCMP(s, t)) |
|
6739 return SOAP_OK; |
|
6740 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element tag name does not match\n")); |
|
6741 return soap->error = SOAP_SYNTAX_ERROR; |
|
6742 } |
|
6743 #endif |
|
6744 |
|
6745 /******************************************************************************/ |
|
6746 #ifndef PALM_2 |
|
6747 SOAP_FMAC1 |
|
6748 const char * |
|
6749 SOAP_FMAC2 |
|
6750 soap_attr_value(struct soap *soap, const char *name, int flag) |
|
6751 { register struct soap_attribute *tp; |
|
6752 for (tp = soap->attributes; tp; tp = tp->next) |
|
6753 if (!soap_match_tag(soap, tp->name, name)) |
|
6754 break; |
|
6755 if (tp && tp->visible == 2) |
|
6756 { if (flag == 2 && (soap->mode & SOAP_XML_STRICT)) |
|
6757 soap->error = SOAP_PROHIBITED; |
|
6758 else |
|
6759 return tp->value; |
|
6760 } |
|
6761 else if (flag == 1 && (soap->mode & SOAP_XML_STRICT)) |
|
6762 soap->error = SOAP_REQUIRED; |
|
6763 return NULL; |
|
6764 } |
|
6765 #endif |
|
6766 |
|
6767 /******************************************************************************/ |
|
6768 #ifndef PALM_2 |
|
6769 SOAP_FMAC1 |
|
6770 int |
|
6771 SOAP_FMAC2 |
|
6772 soap_set_attr(struct soap *soap, const char *name, const char *value) |
|
6773 { register struct soap_attribute *tp; |
|
6774 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set attribute %s='%s'\n", name, value?value:"")); |
|
6775 for (tp = soap->attributes; tp; tp = tp->next) |
|
6776 { if (!strcmp(tp->name, name)) |
|
6777 break; |
|
6778 } |
|
6779 if (!tp) |
|
6780 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute %s\n", name)); |
|
6781 if (!(tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(name)))) |
|
6782 return soap->error = SOAP_EOM; |
|
6783 tp->ns = NULL; |
|
6784 #ifndef WITH_LEAN |
|
6785 if (soap->mode & SOAP_XML_CANONICAL) |
|
6786 { struct soap_attribute **tpp = &soap->attributes; |
|
6787 const char *s = strchr(name, ':'); |
|
6788 if (!strncmp(name, "xmlns", 5)) |
|
6789 { for (; *tpp; tpp = &(*tpp)->next) |
|
6790 if (strncmp((*tpp)->name, "xmlns", 5) || strcmp((*tpp)->name + 5, name + 5) > 0) |
|
6791 break; |
|
6792 } |
|
6793 else if (!s) |
|
6794 { for (; *tpp; tpp = &(*tpp)->next) |
|
6795 if (strncmp((*tpp)->name, "xmlns", 5) && ((*tpp)->ns || strcmp((*tpp)->name, name) > 0)) |
|
6796 break; |
|
6797 } |
|
6798 else |
|
6799 { int k; |
|
6800 for (; *tpp; tpp = &(*tpp)->next) |
|
6801 { if (!strncmp((*tpp)->name, "xmlns:", 6) && !strncmp((*tpp)->name + 6, name, s - name) && !(*tpp)->name[6 + s - name]) |
|
6802 { if (!tp->ns) |
|
6803 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Canonicalization: prefix %s=%p(%s)\n", name, (*tpp)->ns, (*tpp)->ns)); |
|
6804 tp->ns = (*tpp)->ns; |
|
6805 } |
|
6806 } |
|
6807 else if (strncmp((*tpp)->name, "xmlns", 5) && (*tpp)->ns && tp->ns && ((k = strcmp((*tpp)->ns, tp->ns)) > 0 || (!k && strcmp((*tpp)->name, name) > 0))) |
|
6808 break; |
|
6809 } |
|
6810 } |
|
6811 tp->next = *tpp; |
|
6812 *tpp = tp; |
|
6813 } |
|
6814 else |
|
6815 #endif |
|
6816 { tp->next = soap->attributes; |
|
6817 soap->attributes = tp; |
|
6818 } |
|
6819 strcpy(tp->name, name); |
|
6820 tp->value = NULL; |
|
6821 } |
|
6822 else if (value && tp->value && tp->size <= strlen(value)) |
|
6823 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute value of %s (free %p)\n", name, tp->value)); |
|
6824 SOAP_FREE(soap, tp->value); |
|
6825 tp->value = NULL; |
|
6826 tp->ns = NULL; |
|
6827 } |
|
6828 if (value) |
|
6829 { if (!tp->value) |
|
6830 { tp->size = strlen(value) + 1; |
|
6831 if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size))) |
|
6832 return soap->error = SOAP_EOM; |
|
6833 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute value of %s (%p)\n", tp->name, tp->value)); |
|
6834 } |
|
6835 strcpy(tp->value, value); |
|
6836 if (!strncmp(tp->name, "xmlns:", 6)) |
|
6837 tp->ns = tp->value; |
|
6838 tp->visible = 2; |
|
6839 #ifndef WITH_LEAN |
|
6840 if (!strcmp(name, "wsu:Id")) |
|
6841 { soap->part = SOAP_BEGIN_SECURITY; |
|
6842 strncpy(soap->id, value, sizeof(soap->id)); |
|
6843 soap->id[sizeof(soap->id)-1] = '\0'; |
|
6844 } |
|
6845 #endif |
|
6846 } |
|
6847 else |
|
6848 tp->visible = 1; |
|
6849 return SOAP_OK; |
|
6850 } |
|
6851 #endif |
|
6852 |
|
6853 /******************************************************************************/ |
|
6854 #ifndef PALM_2 |
|
6855 SOAP_FMAC1 |
|
6856 void |
|
6857 SOAP_FMAC2 |
|
6858 soap_clr_attr(struct soap *soap) |
|
6859 { register struct soap_attribute *tp; |
|
6860 #ifndef WITH_LEAN |
|
6861 if (soap->mode & SOAP_XML_CANONICAL) |
|
6862 { while (soap->attributes) |
|
6863 { tp = soap->attributes->next; |
|
6864 SOAP_FREE(soap, soap->attributes->value); |
|
6865 SOAP_FREE(soap, soap->attributes); |
|
6866 soap->attributes = tp; |
|
6867 } |
|
6868 } |
|
6869 else |
|
6870 #endif |
|
6871 { for (tp = soap->attributes; tp; tp = tp->next) |
|
6872 tp->visible = 0; |
|
6873 } |
|
6874 } |
|
6875 #endif |
|
6876 |
|
6877 /******************************************************************************/ |
|
6878 #ifndef PALM_2 |
|
6879 static int |
|
6880 soap_getattrval(struct soap *soap, char *s, size_t n, soap_wchar d) |
|
6881 { size_t i; |
|
6882 soap_wchar c; |
|
6883 for (i = 0; i < n; i++) |
|
6884 { c = soap_getutf8(soap); |
|
6885 switch (c) |
|
6886 { |
|
6887 case SOAP_TT: |
|
6888 *s++ = '<'; |
|
6889 soap_unget(soap, '/'); |
|
6890 break; |
|
6891 case SOAP_LT: |
|
6892 *s++ = '<'; |
|
6893 break; |
|
6894 case SOAP_GT: |
|
6895 if (d == ' ') |
|
6896 { soap_unget(soap, c); |
|
6897 *s = '\0'; |
|
6898 return SOAP_OK; |
|
6899 } |
|
6900 *s++ = '>'; |
|
6901 break; |
|
6902 case SOAP_QT: |
|
6903 if (c == d) |
|
6904 { *s = '\0'; |
|
6905 return SOAP_OK; |
|
6906 } |
|
6907 *s++ = '"'; |
|
6908 break; |
|
6909 case SOAP_AP: |
|
6910 if (c == d) |
|
6911 { *s = '\0'; |
|
6912 return SOAP_OK; |
|
6913 } |
|
6914 *s++ = '\''; |
|
6915 break; |
|
6916 case '\t': |
|
6917 case '\n': |
|
6918 case '\r': |
|
6919 case ' ': |
|
6920 case '/': |
|
6921 if (d == ' ') |
|
6922 { soap_unget(soap, c); |
|
6923 *s = '\0'; |
|
6924 return SOAP_OK; |
|
6925 } |
|
6926 default: |
|
6927 if ((int)c == EOF) |
|
6928 return soap->error = SOAP_EOF; |
|
6929 *s++ = (char)c; |
|
6930 } |
|
6931 } |
|
6932 return soap->error = SOAP_EOM; |
|
6933 } |
|
6934 #endif |
|
6935 |
|
6936 /******************************************************************************/ |
|
6937 #ifdef WITH_FAST |
|
6938 #ifndef PALM_2 |
|
6939 SOAP_FMAC1 |
|
6940 int |
|
6941 SOAP_FMAC2 |
|
6942 soap_store_lab(struct soap *soap, const char *s, size_t n) |
|
6943 { soap->labidx = 0; |
|
6944 return soap_append_lab(soap, s, n); |
|
6945 } |
|
6946 #endif |
|
6947 #endif |
|
6948 |
|
6949 /******************************************************************************/ |
|
6950 #ifdef WITH_FAST |
|
6951 #ifndef PALM_2 |
|
6952 SOAP_FMAC1 |
|
6953 int |
|
6954 SOAP_FMAC2 |
|
6955 soap_append_lab(struct soap *soap, const char *s, size_t n) |
|
6956 { if (soap->labidx + n >= soap->lablen) |
|
6957 { register char *t = soap->labbuf; |
|
6958 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enlarging look-aside buffer to append data, old size=%lu", (unsigned long)soap->lablen)); |
|
6959 if (soap->lablen == 0) |
|
6960 soap->lablen = SOAP_LABLEN; |
|
6961 while (soap->labidx + n >= soap->lablen) |
|
6962 soap->lablen <<= 1; |
|
6963 DBGLOG(TEST, SOAP_MESSAGE(fdebug, ", new size=%lu\n", (unsigned long)soap->lablen)); |
|
6964 soap->labbuf = (char*)SOAP_MALLOC(soap, soap->lablen); |
|
6965 if (!soap->labbuf) |
|
6966 { if (t) |
|
6967 SOAP_FREE(soap, t); |
|
6968 return soap->error = SOAP_EOM; |
|
6969 } |
|
6970 if (t) |
|
6971 { memcpy(soap->labbuf, t, soap->labidx); |
|
6972 SOAP_FREE(soap, t); |
|
6973 } |
|
6974 } |
|
6975 if (s) |
|
6976 { memcpy(soap->labbuf + soap->labidx, s, n); |
|
6977 soap->labidx += n; |
|
6978 } |
|
6979 return SOAP_OK; |
|
6980 } |
|
6981 #endif |
|
6982 #endif |
|
6983 |
|
6984 /******************************************************************************/ |
|
6985 #ifndef PALM_2 |
|
6986 SOAP_FMAC1 |
|
6987 int |
|
6988 SOAP_FMAC2 |
|
6989 soap_peek_element(struct soap *soap) |
|
6990 { |
|
6991 #ifdef WITH_DOM |
|
6992 register struct soap_dom_attribute **att = NULL; |
|
6993 register char *lead = NULL; |
|
6994 #endif |
|
6995 register struct soap_attribute *tp; |
|
6996 const char *t; |
|
6997 register char *s; |
|
6998 register soap_wchar c; |
|
6999 register int i; |
|
7000 if (soap->peeked) |
|
7001 { if (!*soap->tag) |
|
7002 return soap->error = SOAP_NO_TAG; |
|
7003 return SOAP_OK; |
|
7004 } |
|
7005 soap->peeked = 1; |
|
7006 for (;;) |
|
7007 { c = soap_getutf8(soap); |
|
7008 if (c == SOAP_BOM) |
|
7009 c = soap_get(soap); |
|
7010 #ifdef WITH_DOM |
|
7011 /* whitespace leading to start tag is not insignificant for DOM */ |
|
7012 if (soap_blank(c)) |
|
7013 { soap->labidx = 0; |
|
7014 do |
|
7015 { if (soap_append_lab(soap, NULL, 0)) |
|
7016 return SOAP_EOM; |
|
7017 s = soap->labbuf + soap->labidx; |
|
7018 i = soap->lablen - soap->labidx; |
|
7019 soap->labidx = soap->lablen; |
|
7020 while (soap_blank(c) && i--) |
|
7021 { *s++ = c; |
|
7022 c = soap_get(soap); |
|
7023 } |
|
7024 } |
|
7025 while (soap_blank(c)); |
|
7026 *s = '\0'; |
|
7027 lead = soap_strdup(soap, soap->labbuf); |
|
7028 } |
|
7029 #else |
|
7030 while (soap_blank(c)) |
|
7031 c = soap_get(soap); |
|
7032 #endif |
|
7033 if (c != SOAP_LT) |
|
7034 { *soap->tag = '\0'; |
|
7035 if ((int)c == EOF) |
|
7036 return soap->error = SOAP_EOF; |
|
7037 soap_unget(soap, c); |
|
7038 #ifdef WITH_DOM |
|
7039 /* whitespace leading to end tag is not insignificant for DOM */ |
|
7040 if ((soap->mode & SOAP_XML_DOM) && soap->dom) |
|
7041 soap->dom->tail = soap_strdup(soap, lead); |
|
7042 #endif |
|
7043 return soap->error = SOAP_NO_TAG; |
|
7044 } |
|
7045 s = soap->tag; |
|
7046 do c = soap_getutf8(soap); |
|
7047 while (soap_blank(c)); |
|
7048 i = sizeof(soap->tag); |
|
7049 while (c != '/' && soap_notblank(c)) |
|
7050 { if (--i > 0) |
|
7051 *s++ = (char)c; |
|
7052 c = soap_getutf8(soap); |
|
7053 } |
|
7054 while (soap_blank(c)) |
|
7055 c = soap_get(soap); |
|
7056 *s = '\0'; |
|
7057 if (*soap->tag != '?') |
|
7058 break; |
|
7059 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "XML PI <%s?>\n", soap->tag)); |
|
7060 while ((int)c != EOF && c != SOAP_GT && c != '?') |
|
7061 { s = soap->tmpbuf; |
|
7062 i = sizeof(soap->tmpbuf) - 2; |
|
7063 while (c != '=' && c != SOAP_GT && c != '?' && soap_notblank(c)) |
|
7064 { if (--i > 0) |
|
7065 *s++ = (char)c; |
|
7066 c = soap_get(soap); |
|
7067 } |
|
7068 while (soap_blank(c)) |
|
7069 c = soap_get(soap); |
|
7070 if (c == '=') |
|
7071 { *s++ = '='; |
|
7072 do c = soap_get(soap); |
|
7073 while (soap_blank(c)); |
|
7074 if (c != SOAP_QT && c != SOAP_AP) |
|
7075 { soap_unget(soap, c); |
|
7076 c = ' '; /* blank delimiter */ |
|
7077 } |
|
7078 if (soap_getattrval(soap, s, i, c) == SOAP_EOM) |
|
7079 { while (soap_getattrval(soap, soap->tmpbuf, sizeof(soap->tmpbuf), c) == SOAP_EOM) |
|
7080 ; |
|
7081 } |
|
7082 else if (!strcmp(soap->tag, "?xml") |
|
7083 && (!soap_tag_cmp(soap->tmpbuf, "encoding=iso-8859-1") |
|
7084 || !soap_tag_cmp(soap->tmpbuf, "encoding=latin1"))) |
|
7085 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "XML latin1 encoding\n")); |
|
7086 soap->mode |= SOAP_ENC_LATIN; |
|
7087 } |
|
7088 } |
|
7089 do c = soap_get(soap); |
|
7090 while (soap_blank(c)); |
|
7091 } |
|
7092 } |
|
7093 soap->id[0] = '\0'; |
|
7094 soap->href[0] = '\0'; |
|
7095 soap->type[0] = '\0'; |
|
7096 soap->arrayType[0] = '\0'; |
|
7097 soap->arraySize[0] = '\0'; |
|
7098 soap->arrayOffset[0] = '\0'; |
|
7099 soap->other = 0; |
|
7100 soap->root = -1; |
|
7101 soap->position = 0; |
|
7102 soap->null = 0; |
|
7103 soap->mustUnderstand = 0; |
|
7104 #ifdef WITH_DOM |
|
7105 if (soap->mode & SOAP_XML_DOM) |
|
7106 { register struct soap_dom_element *elt; |
|
7107 elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element)); |
|
7108 if (!elt) |
|
7109 return soap->error = SOAP_EOM; |
|
7110 elt->next = NULL; |
|
7111 elt->nstr = NULL; |
|
7112 elt->name = soap_strdup(soap, soap->tag); |
|
7113 elt->prnt = soap->dom; |
|
7114 elt->elts = NULL; |
|
7115 elt->atts = NULL; |
|
7116 elt->data = NULL; |
|
7117 elt->wide = NULL; |
|
7118 elt->type = 0; |
|
7119 elt->node = NULL; |
|
7120 elt->head = lead; |
|
7121 elt->tail = NULL; |
|
7122 elt->soap = soap; |
|
7123 if (soap->dom) |
|
7124 { struct soap_dom_element *p = soap->dom->elts; |
|
7125 if (p) |
|
7126 { while (p->next) |
|
7127 p = p->next; |
|
7128 p->next = elt; |
|
7129 } |
|
7130 else |
|
7131 soap->dom->elts = elt; |
|
7132 } |
|
7133 soap->dom = elt; |
|
7134 att = &elt->atts; |
|
7135 } |
|
7136 #endif |
|
7137 for (tp = soap->attributes; tp; tp = tp->next) |
|
7138 tp->visible = 0; |
|
7139 while ((int)c != EOF && c != SOAP_GT && c != '/') |
|
7140 { s = soap->tmpbuf; |
|
7141 i = sizeof(soap->tmpbuf); |
|
7142 while (c != '=' && c != '/' && soap_notblank(c)) |
|
7143 { if (--i > 0) |
|
7144 *s++ = (char)c; |
|
7145 c = soap_get(soap); |
|
7146 } |
|
7147 *s = '\0'; |
|
7148 if (i == sizeof(soap->tmpbuf)) |
|
7149 return soap->error = SOAP_SYNTAX_ERROR; |
|
7150 #ifdef WITH_DOM |
|
7151 /* add attribute name to dom */ |
|
7152 if (att) |
|
7153 { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); |
|
7154 if (!*att) |
|
7155 return soap->error = SOAP_EOM; |
|
7156 (*att)->next = NULL; |
|
7157 (*att)->nstr = NULL; |
|
7158 (*att)->name = soap_strdup(soap, soap->tmpbuf); |
|
7159 (*att)->data = NULL; |
|
7160 (*att)->wide = NULL; |
|
7161 (*att)->soap = soap; |
|
7162 } |
|
7163 #endif |
|
7164 if (!strncmp(soap->tmpbuf, "xmlns", 5)) |
|
7165 { if (soap->tmpbuf[5] == ':') |
|
7166 { soap->tmpbuf[5] = '\0'; |
|
7167 t = soap->tmpbuf + 6; |
|
7168 } |
|
7169 else if (soap->tmpbuf[5]) |
|
7170 t = NULL; |
|
7171 else |
|
7172 t = SOAP_STR_EOS; |
|
7173 } |
|
7174 else |
|
7175 t = NULL; |
|
7176 for (tp = soap->attributes; tp; tp = tp->next) |
|
7177 { if (!SOAP_STRCMP(tp->name, soap->tmpbuf)) |
|
7178 break; |
|
7179 } |
|
7180 if (!tp) |
|
7181 { tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(soap->tmpbuf)); |
|
7182 if (!tp) |
|
7183 return soap->error = SOAP_EOM; |
|
7184 strcpy(tp->name, soap->tmpbuf); |
|
7185 tp->value = NULL; |
|
7186 tp->size = 0; |
|
7187 tp->next = soap->attributes; |
|
7188 soap->attributes = tp; |
|
7189 } |
|
7190 while (soap_blank(c)) |
|
7191 c = soap_get(soap); |
|
7192 if (c == '=') |
|
7193 { do c = soap_get(soap); |
|
7194 while (soap_blank(c)); |
|
7195 if (c != SOAP_QT && c != SOAP_AP) |
|
7196 { soap_unget(soap, c); |
|
7197 c = ' '; /* blank delimiter */ |
|
7198 } |
|
7199 if (soap_getattrval(soap, tp->value, tp->size, c)) |
|
7200 { |
|
7201 #ifdef WITH_FAST |
|
7202 if (soap->error != SOAP_EOM) |
|
7203 return soap->error; |
|
7204 soap->error = SOAP_OK; |
|
7205 if (soap_store_lab(soap, tp->value, tp->size)) |
|
7206 return soap->error; |
|
7207 if (tp->value) |
|
7208 SOAP_FREE(soap, tp->value); |
|
7209 for (;;) |
|
7210 { if (soap_getattrval(soap, soap->labbuf + soap->labidx, soap->lablen - soap->labidx, c)) |
|
7211 { if (soap->error != SOAP_EOM) |
|
7212 return soap->error; |
|
7213 soap->error = SOAP_OK; |
|
7214 soap->labidx = soap->lablen; |
|
7215 if (soap_append_lab(soap, NULL, 0)) |
|
7216 return soap->error; |
|
7217 } |
|
7218 else |
|
7219 break; |
|
7220 } |
|
7221 if (soap->labidx) |
|
7222 tp->size = soap->lablen; |
|
7223 else |
|
7224 { tp->size = strlen(soap->labbuf) + 1; |
|
7225 if (tp->size < SOAP_LABLEN) |
|
7226 tp->size = SOAP_LABLEN; |
|
7227 } |
|
7228 if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size))) |
|
7229 return soap->error = SOAP_EOM; |
|
7230 strcpy(tp->value, soap->labbuf); |
|
7231 #else |
|
7232 size_t n; |
|
7233 if (soap->error != SOAP_EOM) |
|
7234 return soap->error; |
|
7235 soap->error = SOAP_OK; |
|
7236 if (soap_new_block(soap)) |
|
7237 return soap->error; |
|
7238 for (;;) |
|
7239 { if (!(s = (char*)soap_push_block(soap, SOAP_BLKLEN))) |
|
7240 return soap->error; |
|
7241 if (soap_getattrval(soap, s, SOAP_BLKLEN, c)) |
|
7242 { if (soap->error != SOAP_EOM) |
|
7243 return soap->error; |
|
7244 soap->error = SOAP_OK; |
|
7245 } |
|
7246 else |
|
7247 break; |
|
7248 } |
|
7249 n = tp->size + soap->blist->size; |
|
7250 if (!(s = (char*)SOAP_MALLOC(soap, n))) |
|
7251 return soap->error = SOAP_EOM; |
|
7252 if (tp->value) |
|
7253 { memcpy(s, tp->value, tp->size); |
|
7254 SOAP_FREE(soap, tp->value); |
|
7255 } |
|
7256 soap_save_block(soap, s + tp->size, 0); |
|
7257 tp->value = s; |
|
7258 tp->size = n; |
|
7259 #endif |
|
7260 } |
|
7261 do c = soap_get(soap); |
|
7262 while (soap_blank(c)); |
|
7263 tp->visible = 2; /* seen this attribute w/ value */ |
|
7264 #ifdef WITH_DOM |
|
7265 if (att) |
|
7266 (*att)->data = soap_strdup(soap, tp->value); |
|
7267 #endif |
|
7268 } |
|
7269 else |
|
7270 tp->visible = 1; /* seen this attribute w/o value */ |
|
7271 #ifdef WITH_DOM |
|
7272 if (att) |
|
7273 att = &(*att)->next; |
|
7274 #endif |
|
7275 if (t && tp->value) |
|
7276 { if (soap_push_namespace(soap, t, tp->value)) |
|
7277 return soap->error; |
|
7278 tp->visible = 0; |
|
7279 } |
|
7280 } |
|
7281 #ifdef WITH_DOM |
|
7282 if (att) |
|
7283 { soap->dom->nstr = soap_dom_current_nstr(soap, soap->tag); |
|
7284 for (att = &soap->dom->atts; *att; att = &(*att)->next) |
|
7285 (*att)->nstr = soap_dom_current_nstr(soap, (*att)->name); |
|
7286 } |
|
7287 #endif |
|
7288 if ((int)c == EOF) |
|
7289 return soap->error = SOAP_EOF; |
|
7290 if (!(soap->body = (c != '/'))) |
|
7291 do c = soap_get(soap); |
|
7292 while (soap_blank(c)); |
|
7293 #ifdef WITH_DOM |
|
7294 if (soap->mode & SOAP_XML_DOM) |
|
7295 { if (!soap->body && soap->dom->prnt) |
|
7296 soap->dom = soap->dom->prnt; |
|
7297 } |
|
7298 #endif |
|
7299 for (tp = soap->attributes; tp; tp = tp->next) |
|
7300 { if (tp->visible && tp->value) |
|
7301 { if (!strcmp(tp->name, "id")) |
|
7302 { *soap->id = '#'; |
|
7303 strncpy(soap->id + 1, tp->value, sizeof(soap->id) - 2); |
|
7304 soap->id[sizeof(soap->id)-1] = '\0'; |
|
7305 } |
|
7306 else if (!strcmp(tp->name, "href")) |
|
7307 { strncpy(soap->href, tp->value, sizeof(soap->href) - 1); |
|
7308 soap->href[sizeof(soap->href)-1] = '\0'; |
|
7309 } |
|
7310 else if ((soap->version == 2 || (soap->mode & SOAP_XML_GRAPH)) && !strcmp(tp->name, "ref")) |
|
7311 { *soap->href = '#'; |
|
7312 strncpy(soap->href + 1, tp->value, sizeof(soap->href) - 2); |
|
7313 soap->href[sizeof(soap->href)-1] = '\0'; |
|
7314 } |
|
7315 else if (!soap_match_tag(soap, tp->name, "xsi:type")) |
|
7316 { strncpy(soap->type, tp->value, sizeof(soap->type) - 1); |
|
7317 soap->type[sizeof(soap->type)-1] = '\0'; |
|
7318 } |
|
7319 else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:arrayType")) |
|
7320 { s = soap_strrchr(tp->value, '['); |
|
7321 if (s && (size_t)(s - tp->value) < sizeof(soap->arrayType)) |
|
7322 { strncpy(soap->arrayType, tp->value, s - tp->value); |
|
7323 soap->arrayType[s - tp->value] = '\0'; |
|
7324 strncpy(soap->arraySize, s, sizeof(soap->arraySize) - 1); |
|
7325 } |
|
7326 else |
|
7327 strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1); |
|
7328 soap->arraySize[sizeof(soap->arrayType)-1] = '\0'; |
|
7329 soap->arrayType[sizeof(soap->arrayType)-1] = '\0'; |
|
7330 } |
|
7331 else if (soap->version == 2 && !soap_match_tag(soap, tp->name, "SOAP-ENC:itemType")) |
|
7332 strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1); |
|
7333 else if (soap->version == 2 && !soap_match_tag(soap, tp->name, "SOAP-ENC:arraySize")) |
|
7334 strncpy(soap->arraySize, tp->value, sizeof(soap->arraySize) - 1); |
|
7335 else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:offset")) |
|
7336 strncpy(soap->arrayOffset, tp->value, sizeof(soap->arrayOffset)); |
|
7337 else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:position")) |
|
7338 soap->position = soap_getposition(tp->value, soap->positions); |
|
7339 else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:root")) |
|
7340 soap->root = ((!strcmp(tp->value, "1") || !strcmp(tp->value, "true"))); |
|
7341 else if ((soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENV:actor")) |
|
7342 || (soap->version == 2 && !soap_match_tag(soap, tp->name, "SOAP-ENV:role"))) |
|
7343 { if ((!soap->actor || strcmp(soap->actor, tp->value)) |
|
7344 && strcmp(tp->value, "http://schemas.xmlsoap.org/soap/actor/next") |
|
7345 && strcmp(tp->value, "http://www.w3.org/2003/05/soap-envelope/role/next")) |
|
7346 soap->other = 1; |
|
7347 } |
|
7348 else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand") |
|
7349 && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true"))) |
|
7350 soap->mustUnderstand = 1; |
|
7351 else if ((!soap_match_tag(soap, tp->name, "xsi:null") |
|
7352 || !soap_match_tag(soap, tp->name, "xsi:nil")) |
|
7353 && (!strcmp(tp->value, "1") |
|
7354 || !strcmp(tp->value, "true"))) |
|
7355 soap->null = 1; |
|
7356 } |
|
7357 } |
|
7358 return soap->error = SOAP_OK; |
|
7359 } |
|
7360 #endif |
|
7361 |
|
7362 /******************************************************************************/ |
|
7363 #ifndef PALM_2 |
|
7364 SOAP_FMAC1 |
|
7365 void |
|
7366 SOAP_FMAC2 |
|
7367 soap_retry(struct soap *soap) |
|
7368 { soap->error = SOAP_OK; |
|
7369 soap_revert(soap); |
|
7370 } |
|
7371 #endif |
|
7372 |
|
7373 /******************************************************************************/ |
|
7374 #ifndef PALM_2 |
|
7375 SOAP_FMAC1 |
|
7376 void |
|
7377 SOAP_FMAC2 |
|
7378 soap_revert(struct soap *soap) |
|
7379 { if (!soap->peeked) |
|
7380 { soap->peeked = 1; |
|
7381 if (soap->body) |
|
7382 soap->level--; |
|
7383 } |
|
7384 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reverting last element (level=%u)\n", soap->level)); |
|
7385 } |
|
7386 #endif |
|
7387 |
|
7388 /******************************************************************************/ |
|
7389 #ifndef PALM_2 |
|
7390 SOAP_FMAC1 |
|
7391 int |
|
7392 SOAP_FMAC2 |
|
7393 soap_string_out(struct soap *soap, const char *s, int flag) |
|
7394 { register const char *t; |
|
7395 register soap_wchar c; |
|
7396 register soap_wchar mask = 0xFFFFFF80UL; |
|
7397 #ifdef WITH_DOM |
|
7398 if ((soap->mode & SOAP_XML_DOM) && soap->dom) |
|
7399 { soap->dom->data = soap_strdup(soap, s); |
|
7400 return SOAP_OK; |
|
7401 } |
|
7402 #endif |
|
7403 if (soap->mode & SOAP_C_UTFSTRING) |
|
7404 mask = 0; |
|
7405 t = s; |
|
7406 while ((c = *t++)) |
|
7407 { switch (c) |
|
7408 { |
|
7409 case 9: |
|
7410 if (flag) |
|
7411 { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "	", 5)) |
|
7412 return soap->error; |
|
7413 s = t; |
|
7414 } |
|
7415 break; |
|
7416 case 10: |
|
7417 if (flag || !(soap->mode & SOAP_XML_CANONICAL)) |
|
7418 { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "
", 5)) |
|
7419 return soap->error; |
|
7420 s = t; |
|
7421 } |
|
7422 break; |
|
7423 case 13: |
|
7424 if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "
", 5)) |
|
7425 return soap->error; |
|
7426 s = t; |
|
7427 break; |
|
7428 case '&': |
|
7429 if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&", 5)) |
|
7430 return soap->error; |
|
7431 s = t; |
|
7432 break; |
|
7433 case '<': |
|
7434 if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "<", 4)) |
|
7435 return soap->error; |
|
7436 s = t; |
|
7437 break; |
|
7438 case '>': |
|
7439 if (!flag) |
|
7440 { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, ">", 4)) |
|
7441 return soap->error; |
|
7442 s = t; |
|
7443 } |
|
7444 break; |
|
7445 case '"': |
|
7446 if (flag) |
|
7447 { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, """, 6)) |
|
7448 return soap->error; |
|
7449 s = t; |
|
7450 } |
|
7451 break; |
|
7452 default: |
|
7453 #ifndef WITH_LEANER |
|
7454 #ifdef HAVE_MBTOWC |
|
7455 if (soap->mode & SOAP_C_MBSTRING) |
|
7456 { wchar_t wc; |
|
7457 register int m = mbtowc(&wc, t - 1, MB_CUR_MAX); |
|
7458 if (m > 0 && wc != c) |
|
7459 { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, wc)) |
|
7460 return soap->error; |
|
7461 s = t += m - 1; |
|
7462 continue; |
|
7463 } |
|
7464 } |
|
7465 #endif |
|
7466 #endif |
|
7467 if (c & mask) |
|
7468 { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned char)c)) |
|
7469 return soap->error; |
|
7470 s = t; |
|
7471 } |
|
7472 } |
|
7473 } |
|
7474 return soap_send_raw(soap, s, t - s - 1); |
|
7475 } |
|
7476 #endif |
|
7477 |
|
7478 /******************************************************************************/ |
|
7479 #ifndef PALM_2 |
|
7480 SOAP_FMAC1 |
|
7481 char * |
|
7482 SOAP_FMAC2 |
|
7483 soap_string_in(struct soap *soap, int flag, long minlen, long maxlen) |
|
7484 { register char *s; |
|
7485 char *t = NULL; |
|
7486 register size_t i; |
|
7487 register long l = 0; |
|
7488 register int n = 0; |
|
7489 register int m = 0; |
|
7490 register soap_wchar c; |
|
7491 #if !defined(WITH_LEANER) && defined(HAVE_WCTOMB) |
|
7492 char buf[MB_LEN_MAX > 8 ? MB_LEN_MAX : 8]; |
|
7493 #else |
|
7494 char buf[8]; |
|
7495 #endif |
|
7496 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading string content\n")); |
|
7497 if (soap->peeked) |
|
7498 { if (!soap->body) |
|
7499 return NULL; |
|
7500 if (*soap->tag) |
|
7501 { n = 1; |
|
7502 soap->peeked = 0; |
|
7503 #ifndef WITH_LEAN |
|
7504 t = soap->tmpbuf; |
|
7505 t[0] = '<'; |
|
7506 strncpy(t + 1, soap->tag, sizeof(soap->tmpbuf) - 1); |
|
7507 strncat(t, ">", sizeof(soap->tmpbuf)); |
|
7508 m = strlen(soap->tag) + 2; |
|
7509 #endif |
|
7510 } |
|
7511 } |
|
7512 #ifdef WITH_CDATA |
|
7513 if (!flag) |
|
7514 { register int state = 0; |
|
7515 #ifdef WITH_FAST |
|
7516 soap->labidx = 0; /* use look-aside buffer */ |
|
7517 #else |
|
7518 if (soap_new_block(soap)) |
|
7519 return NULL; |
|
7520 #endif |
|
7521 for (;;) |
|
7522 { |
|
7523 #ifdef WITH_FAST |
|
7524 register size_t k; |
|
7525 if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */ |
|
7526 return NULL; |
|
7527 s = soap->labbuf + soap->labidx; /* space to populate */ |
|
7528 k = soap->lablen - soap->labidx; /* number of bytes available */ |
|
7529 soap->labidx = soap->lablen; /* claim this space */ |
|
7530 #else |
|
7531 register size_t k = SOAP_BLKLEN; |
|
7532 if (!(s = (char*)soap_push_block(soap, k))) |
|
7533 return NULL; |
|
7534 #endif |
|
7535 for (i = 0; i < k; i++) |
|
7536 { if (m > 0) |
|
7537 { *s++ = *t++; /* copy multibyte characters */ |
|
7538 m--; |
|
7539 continue; |
|
7540 } |
|
7541 c = soap_getchar(soap); |
|
7542 if ((int)c == EOF) |
|
7543 goto end; |
|
7544 if (c >= 0x80 && !(soap->mode & SOAP_ENC_LATIN)) |
|
7545 { soap_unget(soap, c); |
|
7546 c = soap_getutf8(soap); |
|
7547 if (soap->mode & SOAP_C_UTFSTRING) |
|
7548 { if ((c & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP) |
|
7549 { c &= 0x7FFFFFFF; |
|
7550 t = buf; |
|
7551 if (c < 0x0800) |
|
7552 *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); |
|
7553 else |
|
7554 { if (c < 0x010000) |
|
7555 *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); |
|
7556 else |
|
7557 { if (c < 0x200000) |
|
7558 *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); |
|
7559 else |
|
7560 { if (c < 0x04000000) |
|
7561 *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); |
|
7562 else |
|
7563 { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); |
|
7564 *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); |
|
7565 } |
|
7566 *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); |
|
7567 } |
|
7568 *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); |
|
7569 } |
|
7570 *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); |
|
7571 } |
|
7572 *t++ = (char)(0x80 | (c & 0x3F)); |
|
7573 m = (int)(t - buf) - 1; |
|
7574 t = buf; |
|
7575 *s++ = *t++; |
|
7576 continue; |
|
7577 } |
|
7578 } |
|
7579 } |
|
7580 switch (state) |
|
7581 { case 1: |
|
7582 if (c == ']') |
|
7583 state = 4; |
|
7584 *s++ = c; |
|
7585 continue; |
|
7586 case 2: |
|
7587 if (c == '-') |
|
7588 state = 6; |
|
7589 *s++ = c; |
|
7590 continue; |
|
7591 case 3: |
|
7592 if (c == '?') |
|
7593 state = 8; |
|
7594 *s++ = c; |
|
7595 continue; |
|
7596 /* CDATA */ |
|
7597 case 4: |
|
7598 if (c == ']') |
|
7599 state = 5; |
|
7600 else |
|
7601 state = 1; |
|
7602 *s++ = c; |
|
7603 continue; |
|
7604 case 5: |
|
7605 if (c == '>') |
|
7606 state = 0; |
|
7607 else |
|
7608 state = 1; |
|
7609 *s++ = c; |
|
7610 continue; |
|
7611 /* comment */ |
|
7612 case 6: |
|
7613 if (c == '-') |
|
7614 state = 7; |
|
7615 else |
|
7616 state = 2; |
|
7617 *s++ = c; |
|
7618 continue; |
|
7619 case 7: |
|
7620 if (c == '>') |
|
7621 state = 0; |
|
7622 else |
|
7623 state = 2; |
|
7624 *s++ = c; |
|
7625 continue; |
|
7626 /* PI */ |
|
7627 case 8: |
|
7628 if (c == '>') |
|
7629 state = 0; |
|
7630 else |
|
7631 state = 3; |
|
7632 *s++ = c; |
|
7633 continue; |
|
7634 } |
|
7635 switch (c) |
|
7636 { |
|
7637 case '/': |
|
7638 if (n > 0) |
|
7639 { c = soap_getchar(soap); |
|
7640 if (c == '>') |
|
7641 n--; |
|
7642 soap_unget(soap, c); |
|
7643 } |
|
7644 *s++ = '/'; |
|
7645 break; |
|
7646 case '<': |
|
7647 c = soap_getchar(soap); |
|
7648 if (c == '/') |
|
7649 { if (n == 0) |
|
7650 { c = SOAP_TT; |
|
7651 goto end; |
|
7652 } |
|
7653 n--; |
|
7654 } |
|
7655 else if (c == '!') |
|
7656 { c = soap_getchar(soap); |
|
7657 if (c == '[') |
|
7658 { do c = soap_getchar(soap); |
|
7659 while ((int)c != EOF && c != '['); |
|
7660 if ((int)c == EOF) |
|
7661 goto end; |
|
7662 t = (char*)"![CDATA["; |
|
7663 m = 8; |
|
7664 state = 1; |
|
7665 } |
|
7666 else if (c == '-') |
|
7667 { if ((c = soap_getchar(soap)) == '-') |
|
7668 state = 2; |
|
7669 t = (char*)"!-"; |
|
7670 m = 2; |
|
7671 soap_unget(soap, c); |
|
7672 } |
|
7673 else |
|
7674 { t = (char*)"!"; |
|
7675 m = 1; |
|
7676 soap_unget(soap, c); |
|
7677 } |
|
7678 *s++ = '<'; |
|
7679 break; |
|
7680 } |
|
7681 else if (c == '?') |
|
7682 state = 3; |
|
7683 else |
|
7684 n++; |
|
7685 soap_unget(soap, c); |
|
7686 *s++ = '<'; |
|
7687 break; |
|
7688 case '>': |
|
7689 *s++ = '>'; |
|
7690 break; |
|
7691 case '"': |
|
7692 *s++ = '"'; |
|
7693 break; |
|
7694 default: |
|
7695 #ifndef WITH_LEANER |
|
7696 #ifdef HAVE_WCTOMB |
|
7697 if (soap->mode & SOAP_C_MBSTRING) |
|
7698 { m = wctomb(buf, c & 0x7FFFFFFF); |
|
7699 if (m >= 1 && m <= (int)MB_CUR_MAX) |
|
7700 { t = buf; |
|
7701 *s++ = *t++; |
|
7702 m--; |
|
7703 } |
|
7704 else |
|
7705 { *s++ = SOAP_UNKNOWN_CHAR; |
|
7706 m = 0; |
|
7707 } |
|
7708 } |
|
7709 else |
|
7710 #endif |
|
7711 #endif |
|
7712 *s++ = (char)(c & 0xFF); |
|
7713 } |
|
7714 l++; |
|
7715 if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen) |
|
7716 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); |
|
7717 soap->error = SOAP_LENGTH; |
|
7718 return NULL; |
|
7719 } |
|
7720 } |
|
7721 } |
|
7722 } |
|
7723 #endif |
|
7724 #ifdef WITH_FAST |
|
7725 soap->labidx = 0; /* use look-aside buffer */ |
|
7726 #else |
|
7727 if (soap_new_block(soap)) |
|
7728 return NULL; |
|
7729 #endif |
|
7730 for (;;) |
|
7731 { |
|
7732 #ifdef WITH_FAST |
|
7733 register size_t k; |
|
7734 if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */ |
|
7735 return NULL; |
|
7736 s = soap->labbuf + soap->labidx; /* space to populate */ |
|
7737 k = soap->lablen - soap->labidx; /* number of bytes available */ |
|
7738 soap->labidx = soap->lablen; /* claim this space */ |
|
7739 #else |
|
7740 register size_t k = SOAP_BLKLEN; |
|
7741 if (!(s = (char*)soap_push_block(soap, k))) |
|
7742 return NULL; |
|
7743 #endif |
|
7744 for (i = 0; i < k; i++) |
|
7745 { if (m > 0) |
|
7746 { *s++ = *t++; /* copy multibyte characters */ |
|
7747 m--; |
|
7748 continue; |
|
7749 } |
|
7750 if (soap->mode & SOAP_C_UTFSTRING) |
|
7751 { if (((c = soap_get(soap)) & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP) |
|
7752 { c &= 0x7FFFFFFF; |
|
7753 t = buf; |
|
7754 if (c < 0x0800) |
|
7755 *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); |
|
7756 else |
|
7757 { if (c < 0x010000) |
|
7758 *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); |
|
7759 else |
|
7760 { if (c < 0x200000) |
|
7761 *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); |
|
7762 else |
|
7763 { if (c < 0x04000000) |
|
7764 *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); |
|
7765 else |
|
7766 { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); |
|
7767 *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); |
|
7768 } |
|
7769 *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); |
|
7770 } |
|
7771 *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); |
|
7772 } |
|
7773 *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); |
|
7774 } |
|
7775 *t++ = (char)(0x80 | (c & 0x3F)); |
|
7776 m = (int)(t - buf) - 1; |
|
7777 t = buf; |
|
7778 *s++ = *t++; |
|
7779 continue; |
|
7780 } |
|
7781 } |
|
7782 else |
|
7783 c = soap_getutf8(soap); |
|
7784 switch (c) |
|
7785 { |
|
7786 case SOAP_TT: |
|
7787 if (n == 0) |
|
7788 goto end; |
|
7789 n--; |
|
7790 *s++ = '<'; |
|
7791 t = (char*)"/"; |
|
7792 m = 1; |
|
7793 break; |
|
7794 case SOAP_LT: |
|
7795 n++; |
|
7796 *s++ = '<'; |
|
7797 break; |
|
7798 case SOAP_GT: |
|
7799 *s++ = '>'; |
|
7800 break; |
|
7801 case SOAP_QT: |
|
7802 *s++ = '"'; |
|
7803 break; |
|
7804 case SOAP_AP: |
|
7805 *s++ = '\''; |
|
7806 break; |
|
7807 case '/': |
|
7808 if (n > 0) |
|
7809 { c = soap_get(soap); |
|
7810 if (c == SOAP_GT) |
|
7811 n--; |
|
7812 soap_unget(soap, c); |
|
7813 } |
|
7814 *s++ = '/'; |
|
7815 break; |
|
7816 case '<' | 0x80000000: |
|
7817 if (flag) |
|
7818 *s++ = '<'; |
|
7819 else |
|
7820 { *s++ = '&'; |
|
7821 t = (char*)"lt;"; |
|
7822 m = 3; |
|
7823 } |
|
7824 break; |
|
7825 case '>' | 0x80000000: |
|
7826 if (flag) |
|
7827 *s++ = '>'; |
|
7828 else |
|
7829 { *s++ = '&'; |
|
7830 t = (char*)"gt;"; |
|
7831 m = 3; |
|
7832 } |
|
7833 break; |
|
7834 case '&' | 0x80000000: |
|
7835 if (flag) |
|
7836 *s++ = '&'; |
|
7837 else |
|
7838 { *s++ = '&'; |
|
7839 t = (char*)"amp;"; |
|
7840 m = 4; |
|
7841 } |
|
7842 break; |
|
7843 case '"' | 0x80000000: |
|
7844 if (flag) |
|
7845 *s++ = '"'; |
|
7846 else |
|
7847 { *s++ = '&'; |
|
7848 t = (char*)"quot;"; |
|
7849 m = 5; |
|
7850 } |
|
7851 break; |
|
7852 case '\'' | 0x80000000: |
|
7853 if (flag) |
|
7854 *s++ = '\''; |
|
7855 else |
|
7856 { *s++ = '&'; |
|
7857 t = (char*)"apos;"; |
|
7858 m = 5; |
|
7859 } |
|
7860 break; |
|
7861 default: |
|
7862 if ((int)c == EOF) |
|
7863 goto end; |
|
7864 #ifndef WITH_LEANER |
|
7865 #ifdef HAVE_WCTOMB |
|
7866 if (soap->mode & SOAP_C_MBSTRING) |
|
7867 { m = wctomb(buf, c & 0x7FFFFFFF); |
|
7868 if (m >= 1 && m <= (int)MB_CUR_MAX) |
|
7869 { t = buf; |
|
7870 *s++ = *t++; |
|
7871 m--; |
|
7872 } |
|
7873 else |
|
7874 { *s++ = SOAP_UNKNOWN_CHAR; |
|
7875 m = 0; |
|
7876 } |
|
7877 } |
|
7878 else |
|
7879 #endif |
|
7880 #endif |
|
7881 *s++ = (char)(c & 0xFF); |
|
7882 } |
|
7883 l++; |
|
7884 if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen) |
|
7885 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); |
|
7886 soap->error = SOAP_LENGTH; |
|
7887 return NULL; |
|
7888 } |
|
7889 } |
|
7890 } |
|
7891 end: |
|
7892 soap_unget(soap, c); |
|
7893 *s = '\0'; |
|
7894 #ifdef WITH_FAST |
|
7895 t = soap_strdup(soap, soap->labbuf); |
|
7896 #else |
|
7897 soap_size_block(soap, i+1); |
|
7898 t = soap_save_block(soap, NULL, 0); |
|
7899 #endif |
|
7900 if ((soap->mode & SOAP_XML_STRICT) && l < minlen) |
|
7901 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen)); |
|
7902 soap->error = SOAP_LENGTH; |
|
7903 return NULL; |
|
7904 } |
|
7905 #ifdef WITH_DOM |
|
7906 if ((soap->mode & SOAP_XML_DOM) && soap->dom) |
|
7907 { if (flag == 3) |
|
7908 soap->dom->tail = t; |
|
7909 else |
|
7910 soap->dom->data = t; |
|
7911 } |
|
7912 #endif |
|
7913 if (flag == 2) |
|
7914 if (soap_s2QName(soap, t, &t)) |
|
7915 return NULL; |
|
7916 return t; |
|
7917 } |
|
7918 #endif |
|
7919 |
|
7920 /******************************************************************************/ |
|
7921 #ifndef WITH_LEANER |
|
7922 #ifndef PALM_2 |
|
7923 SOAP_FMAC1 |
|
7924 int |
|
7925 SOAP_FMAC2 |
|
7926 soap_wstring_out(struct soap *soap, const wchar_t *s, int flag) |
|
7927 { const char *t; |
|
7928 char tmp; |
|
7929 register soap_wchar c; |
|
7930 #ifdef WITH_DOM |
|
7931 if ((soap->mode & SOAP_XML_DOM) && soap->dom) |
|
7932 { wchar_t *r = (wchar_t*)s; |
|
7933 int n = 1; |
|
7934 while (*r++) |
|
7935 n++; |
|
7936 soap->dom->wide = r = (wchar_t*)soap_malloc(soap, n * sizeof(wchar_t)); |
|
7937 while (n--) |
|
7938 *r++ = *s++; |
|
7939 return SOAP_OK; |
|
7940 } |
|
7941 #endif |
|
7942 while ((c = *s++)) |
|
7943 { switch (c) |
|
7944 { |
|
7945 case 9: |
|
7946 if (flag) |
|
7947 t = "	"; |
|
7948 else |
|
7949 t = "\t"; |
|
7950 break; |
|
7951 case 10: |
|
7952 if (flag || !(soap->mode & SOAP_XML_CANONICAL)) |
|
7953 t = "
"; |
|
7954 else |
|
7955 t = "\n"; |
|
7956 break; |
|
7957 case 13: |
|
7958 t = "
"; |
|
7959 break; |
|
7960 case '&': |
|
7961 t = "&"; |
|
7962 break; |
|
7963 case '<': |
|
7964 t = "<"; |
|
7965 break; |
|
7966 case '>': |
|
7967 if (flag) |
|
7968 t = ">"; |
|
7969 else |
|
7970 t = ">"; |
|
7971 break; |
|
7972 case '"': |
|
7973 if (flag) |
|
7974 t = """; |
|
7975 else |
|
7976 t = "\""; |
|
7977 break; |
|
7978 default: |
|
7979 if (c > 0 && c < 0x80) |
|
7980 { tmp = (char)c; |
|
7981 if (soap_send_raw(soap, &tmp, 1)) |
|
7982 return soap->error; |
|
7983 } |
|
7984 else if (soap_pututf8(soap, (unsigned long)c)) |
|
7985 return soap->error; |
|
7986 continue; |
|
7987 } |
|
7988 if (soap_send(soap, t)) |
|
7989 return soap->error; |
|
7990 } |
|
7991 return SOAP_OK; |
|
7992 } |
|
7993 #endif |
|
7994 #endif |
|
7995 |
|
7996 /******************************************************************************/ |
|
7997 #ifndef WITH_LEANER |
|
7998 #ifndef PALM_2 |
|
7999 SOAP_FMAC1 |
|
8000 wchar_t * |
|
8001 SOAP_FMAC2 |
|
8002 soap_wstring_in(struct soap *soap, int flag, long minlen, long maxlen) |
|
8003 { wchar_t *s; |
|
8004 register int i, n = 0; |
|
8005 register long l = 0; |
|
8006 register soap_wchar c; |
|
8007 const char *t = NULL; |
|
8008 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading wide string content\n")); |
|
8009 if (soap->peeked) |
|
8010 { if (!soap->body) |
|
8011 return NULL; |
|
8012 if (*soap->tag) |
|
8013 { n = 1; |
|
8014 soap->peeked = 0; |
|
8015 } |
|
8016 } |
|
8017 if (soap_new_block(soap)) |
|
8018 return NULL; |
|
8019 for (;;) |
|
8020 { if (!(s = (wchar_t*)soap_push_block(soap, sizeof(wchar_t)*SOAP_BLKLEN))) |
|
8021 return NULL; |
|
8022 for (i = 0; i < SOAP_BLKLEN; i++) |
|
8023 { if (t) |
|
8024 { *s++ = (wchar_t)*t++; |
|
8025 if (!*t) |
|
8026 t = NULL; |
|
8027 continue; |
|
8028 } |
|
8029 c = soap_getutf8(soap); |
|
8030 switch (c) |
|
8031 { |
|
8032 case SOAP_TT: |
|
8033 if (n == 0) |
|
8034 goto end; |
|
8035 n--; |
|
8036 *s++ = '<'; |
|
8037 soap_unget(soap, '/'); |
|
8038 break; |
|
8039 case SOAP_LT: |
|
8040 n++; |
|
8041 *s++ = '<'; |
|
8042 break; |
|
8043 case SOAP_GT: |
|
8044 *s++ = '>'; |
|
8045 break; |
|
8046 case SOAP_QT: |
|
8047 *s++ = '"'; |
|
8048 break; |
|
8049 case SOAP_AP: |
|
8050 *s++ = '\''; |
|
8051 break; |
|
8052 case '/': |
|
8053 if (n > 0) |
|
8054 { c = soap_getutf8(soap); |
|
8055 if (c == SOAP_GT) |
|
8056 n--; |
|
8057 soap_unget(soap, c); |
|
8058 } |
|
8059 *s++ = '/'; |
|
8060 break; |
|
8061 case '<': |
|
8062 if (flag) |
|
8063 *s++ = (soap_wchar)'<'; |
|
8064 else |
|
8065 { *s++ = (soap_wchar)'&'; |
|
8066 t = "lt;"; |
|
8067 } |
|
8068 break; |
|
8069 case '>': |
|
8070 if (flag) |
|
8071 *s++ = (soap_wchar)'>'; |
|
8072 else |
|
8073 { *s++ = (soap_wchar)'&'; |
|
8074 t = "gt;"; |
|
8075 } |
|
8076 break; |
|
8077 case '"': |
|
8078 if (flag) |
|
8079 *s++ = (soap_wchar)'"'; |
|
8080 else |
|
8081 { *s++ = (soap_wchar)'&'; |
|
8082 t = "quot;"; |
|
8083 } |
|
8084 break; |
|
8085 default: |
|
8086 if ((int)c == EOF) |
|
8087 goto end; |
|
8088 *s++ = (wchar_t)c & 0x7FFFFFFF; |
|
8089 } |
|
8090 l++; |
|
8091 if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen) |
|
8092 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); |
|
8093 soap->error = SOAP_LENGTH; |
|
8094 return NULL; |
|
8095 } |
|
8096 } |
|
8097 } |
|
8098 end: |
|
8099 soap_unget(soap, c); |
|
8100 *s = '\0'; |
|
8101 soap_size_block(soap, sizeof(wchar_t) * (i + 1)); |
|
8102 if ((soap->mode & SOAP_XML_STRICT) && l < minlen) |
|
8103 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen)); |
|
8104 soap->error = SOAP_LENGTH; |
|
8105 return NULL; |
|
8106 } |
|
8107 s = (wchar_t*)soap_save_block(soap, NULL, 0); |
|
8108 #ifdef WITH_DOM |
|
8109 if ((soap->mode & SOAP_XML_DOM) && soap->dom) |
|
8110 soap->dom->wide = s; |
|
8111 #endif |
|
8112 return s; |
|
8113 } |
|
8114 #endif |
|
8115 #endif |
|
8116 |
|
8117 /******************************************************************************/ |
|
8118 #ifndef PALM_2 |
|
8119 SOAP_FMAC1 |
|
8120 const char* |
|
8121 SOAP_FMAC2 |
|
8122 soap_int2s(struct soap *soap, int n) |
|
8123 { return soap_long2s(soap, (long)n); |
|
8124 } |
|
8125 #endif |
|
8126 |
|
8127 /******************************************************************************/ |
|
8128 #ifndef PALM_2 |
|
8129 SOAP_FMAC1 |
|
8130 int |
|
8131 SOAP_FMAC2 |
|
8132 soap_outint(struct soap *soap, const char *tag, int id, const int *p, const char *type, int n) |
|
8133 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) |
|
8134 || soap_string_out(soap, soap_long2s(soap, (long)*p), 0)) |
|
8135 return soap->error; |
|
8136 return soap_element_end_out(soap, tag); |
|
8137 } |
|
8138 #endif |
|
8139 |
|
8140 /******************************************************************************/ |
|
8141 #ifndef PALM_2 |
|
8142 SOAP_FMAC1 |
|
8143 int |
|
8144 SOAP_FMAC2 |
|
8145 soap_s2int(struct soap *soap, const char *s, int *p) |
|
8146 { if (s) |
|
8147 { char *r; |
|
8148 *p = (int)soap_strtol(s, &r, 10); |
|
8149 if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r |
|
8150 #ifndef WITH_NOIO |
|
8151 #ifndef WITH_LEAN |
|
8152 || soap_errno == SOAP_ERANGE |
|
8153 #endif |
|
8154 #endif |
|
8155 ) |
|
8156 soap->error = SOAP_TYPE; |
|
8157 } |
|
8158 return soap->error; |
|
8159 } |
|
8160 #endif |
|
8161 |
|
8162 /******************************************************************************/ |
|
8163 #ifndef PALM_2 |
|
8164 SOAP_FMAC1 |
|
8165 int * |
|
8166 SOAP_FMAC2 |
|
8167 soap_inint(struct soap *soap, const char *tag, int *p, const char *type, int t) |
|
8168 { if (soap_element_begin_in(soap, tag, 0)) |
|
8169 return NULL; |
|
8170 #ifndef WITH_LEAN |
|
8171 if (*soap->type |
|
8172 && soap_match_tag(soap, soap->type, type) |
|
8173 && soap_match_tag(soap, soap->type, ":int") |
|
8174 && soap_match_tag(soap, soap->type, ":short") |
|
8175 && soap_match_tag(soap, soap->type, ":byte")) |
|
8176 { soap->error = SOAP_TYPE; |
|
8177 soap_revert(soap); |
|
8178 return NULL; |
|
8179 } |
|
8180 #endif |
|
8181 p = (int*)soap_id_enter(soap, soap->id, p, t, sizeof(int), 0, NULL, NULL, NULL); |
|
8182 if (*soap->href) |
|
8183 p = (int*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(int), 0, NULL); |
|
8184 else if (p) |
|
8185 { if (soap_s2int(soap, soap_value(soap), p)) |
|
8186 return NULL; |
|
8187 } |
|
8188 if (soap->body && soap_element_end_in(soap, tag)) |
|
8189 return NULL; |
|
8190 return p; |
|
8191 } |
|
8192 #endif |
|
8193 |
|
8194 /******************************************************************************/ |
|
8195 #ifndef PALM_2 |
|
8196 SOAP_FMAC1 |
|
8197 const char* |
|
8198 SOAP_FMAC2 |
|
8199 soap_long2s(struct soap *soap, long n) |
|
8200 { sprintf(soap->tmpbuf, "%ld", n); |
|
8201 return soap->tmpbuf; |
|
8202 } |
|
8203 #endif |
|
8204 |
|
8205 /******************************************************************************/ |
|
8206 #ifndef PALM_2 |
|
8207 SOAP_FMAC1 |
|
8208 int |
|
8209 SOAP_FMAC2 |
|
8210 soap_outlong(struct soap *soap, const char *tag, int id, const long *p, const char *type, int n) |
|
8211 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) |
|
8212 || soap_string_out(soap, soap_long2s(soap, *p), 0)) |
|
8213 return soap->error; |
|
8214 return soap_element_end_out(soap, tag); |
|
8215 } |
|
8216 #endif |
|
8217 |
|
8218 /******************************************************************************/ |
|
8219 #ifndef PALM_2 |
|
8220 SOAP_FMAC1 |
|
8221 int |
|
8222 SOAP_FMAC2 |
|
8223 soap_s2long(struct soap *soap, const char *s, long *p) |
|
8224 { if (s) |
|
8225 { char *r; |
|
8226 *p = soap_strtol(s, &r, 10); |
|
8227 if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r |
|
8228 #ifndef WITH_NOIO |
|
8229 #ifndef WITH_LEAN |
|
8230 || soap_errno == SOAP_ERANGE |
|
8231 #endif |
|
8232 #endif |
|
8233 ) |
|
8234 soap->error = SOAP_TYPE; |
|
8235 } |
|
8236 return soap->error; |
|
8237 } |
|
8238 #endif |
|
8239 |
|
8240 /******************************************************************************/ |
|
8241 #ifndef PALM_2 |
|
8242 SOAP_FMAC1 |
|
8243 long * |
|
8244 SOAP_FMAC2 |
|
8245 soap_inlong(struct soap *soap, const char *tag, long *p, const char *type, int t) |
|
8246 { if (soap_element_begin_in(soap, tag, 0)) |
|
8247 return NULL; |
|
8248 #ifndef WITH_LEAN |
|
8249 if (*soap->type |
|
8250 && soap_match_tag(soap, soap->type, type) |
|
8251 && soap_match_tag(soap, soap->type, ":int") |
|
8252 && soap_match_tag(soap, soap->type, ":short") |
|
8253 && soap_match_tag(soap, soap->type, ":byte")) |
|
8254 { soap->error = SOAP_TYPE; |
|
8255 soap_revert(soap); |
|
8256 return NULL; |
|
8257 } |
|
8258 #endif |
|
8259 p = (long*)soap_id_enter(soap, soap->id, p, t, sizeof(long), 0, NULL, NULL, NULL); |
|
8260 if (*soap->href) |
|
8261 p = (long*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(long), 0, NULL); |
|
8262 else if (p) |
|
8263 { if (soap_s2long(soap, soap_value(soap), p)) |
|
8264 return NULL; |
|
8265 } |
|
8266 if (soap->body && soap_element_end_in(soap, tag)) |
|
8267 return NULL; |
|
8268 return p; |
|
8269 } |
|
8270 #endif |
|
8271 |
|
8272 /******************************************************************************/ |
|
8273 #ifndef WITH_LEAN |
|
8274 SOAP_FMAC1 |
|
8275 const char* |
|
8276 SOAP_FMAC2 |
|
8277 soap_LONG642s(struct soap *soap, LONG64 n) |
|
8278 { sprintf(soap->tmpbuf, SOAP_LONG_FORMAT, n); |
|
8279 return soap->tmpbuf; |
|
8280 } |
|
8281 #endif |
|
8282 |
|
8283 /******************************************************************************/ |
|
8284 #ifndef WITH_LEAN |
|
8285 SOAP_FMAC1 |
|
8286 int |
|
8287 SOAP_FMAC2 |
|
8288 soap_outLONG64(struct soap *soap, const char *tag, int id, const LONG64 *p, const char *type, int n) |
|
8289 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) |
|
8290 || soap_string_out(soap, soap_LONG642s(soap, *p), 0)) |
|
8291 return soap->error; |
|
8292 return soap_element_end_out(soap, tag); |
|
8293 } |
|
8294 #endif |
|
8295 |
|
8296 /******************************************************************************/ |
|
8297 #ifndef WITH_LEAN |
|
8298 SOAP_FMAC1 |
|
8299 int |
|
8300 SOAP_FMAC2 |
|
8301 soap_s2LONG64(struct soap *soap, const char *s, LONG64 *p) |
|
8302 { if (s) |
|
8303 { |
|
8304 #ifdef HAVE_STRTOLL |
|
8305 char *r; |
|
8306 *p = strtoll(s, &r, 10); |
|
8307 if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r |
|
8308 #ifndef WITH_NOIO |
|
8309 #ifndef WITH_LEAN |
|
8310 || soap_errno == SOAP_ERANGE |
|
8311 #endif |
|
8312 #endif |
|
8313 ) |
|
8314 #else |
|
8315 # ifdef HAVE_SSCANF |
|
8316 if (sscanf(s, SOAP_LONG_FORMAT, p) != 1) |
|
8317 # endif |
|
8318 #endif |
|
8319 soap->error = SOAP_TYPE; |
|
8320 } |
|
8321 return soap->error; |
|
8322 } |
|
8323 #endif |
|
8324 |
|
8325 /******************************************************************************/ |
|
8326 #ifndef WITH_LEAN |
|
8327 SOAP_FMAC1 |
|
8328 LONG64 * |
|
8329 SOAP_FMAC2 |
|
8330 soap_inLONG64(struct soap *soap, const char *tag, LONG64 *p, const char *type, int t) |
|
8331 { if (soap_element_begin_in(soap, tag, 0)) |
|
8332 return NULL; |
|
8333 #ifndef WITH_LEAN |
|
8334 if (*soap->type |
|
8335 && soap_match_tag(soap, soap->type, type) |
|
8336 && soap_match_tag(soap, soap->type, ":integer") |
|
8337 && soap_match_tag(soap, soap->type, ":positiveInteger") |
|
8338 && soap_match_tag(soap, soap->type, ":negativeInteger") |
|
8339 && soap_match_tag(soap, soap->type, ":nonPositiveInteger") |
|
8340 && soap_match_tag(soap, soap->type, ":nonNegativeInteger") |
|
8341 && soap_match_tag(soap, soap->type, ":long") |
|
8342 && soap_match_tag(soap, soap->type, ":int") |
|
8343 && soap_match_tag(soap, soap->type, ":short") |
|
8344 && soap_match_tag(soap, soap->type, ":byte")) |
|
8345 { soap->error = SOAP_TYPE; |
|
8346 soap_revert(soap); |
|
8347 return NULL; |
|
8348 } |
|
8349 #endif |
|
8350 p = (LONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(LONG64), 0, NULL, NULL, NULL); |
|
8351 if (*soap->href) |
|
8352 p = (LONG64*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(LONG64), 0, NULL); |
|
8353 else if (p) |
|
8354 { if (soap_s2LONG64(soap, soap_value(soap), p)) |
|
8355 return NULL; |
|
8356 } |
|
8357 if (soap->body && soap_element_end_in(soap, tag)) |
|
8358 return NULL; |
|
8359 return p; |
|
8360 } |
|
8361 #endif |
|
8362 |
|
8363 /******************************************************************************/ |
|
8364 #ifndef PALM_2 |
|
8365 SOAP_FMAC1 |
|
8366 const char* |
|
8367 SOAP_FMAC2 |
|
8368 soap_byte2s(struct soap *soap, char n) |
|
8369 { return soap_long2s(soap, (long)n); |
|
8370 } |
|
8371 #endif |
|
8372 |
|
8373 /******************************************************************************/ |
|
8374 #ifndef PALM_2 |
|
8375 SOAP_FMAC1 |
|
8376 int |
|
8377 SOAP_FMAC2 |
|
8378 soap_outbyte(struct soap *soap, const char *tag, int id, const char *p, const char *type, int n) |
|
8379 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) |
|
8380 || soap_string_out(soap, soap_long2s(soap, (long)*p), 0)) |
|
8381 return soap->error; |
|
8382 return soap_element_end_out(soap, tag); |
|
8383 } |
|
8384 #endif |
|
8385 |
|
8386 /******************************************************************************/ |
|
8387 #ifndef PALM_2 |
|
8388 SOAP_FMAC1 |
|
8389 int |
|
8390 SOAP_FMAC2 |
|
8391 soap_s2byte(struct soap *soap, const char *s, char *p) |
|
8392 { if (s) |
|
8393 { long n; |
|
8394 char *r; |
|
8395 n = soap_strtol(s, &r, 10); |
|
8396 if (s == r || *r || n < -128 || n > 127) |
|
8397 soap->error = SOAP_TYPE; |
|
8398 *p = (char)n; |
|
8399 } |
|
8400 return soap->error; |
|
8401 } |
|
8402 #endif |
|
8403 |
|
8404 /******************************************************************************/ |
|
8405 #ifndef PALM_2 |
|
8406 SOAP_FMAC1 |
|
8407 char * |
|
8408 SOAP_FMAC2 |
|
8409 soap_inbyte(struct soap *soap, const char *tag, char *p, const char *type, int t) |
|
8410 { if (soap_element_begin_in(soap, tag, 0)) |
|
8411 return NULL; |
|
8412 #ifndef WITH_LEAN |
|
8413 if (*soap->type |
|
8414 && soap_match_tag(soap, soap->type, type) |
|
8415 && soap_match_tag(soap, soap->type, ":byte")) |
|
8416 { soap->error = SOAP_TYPE; |
|
8417 soap_revert(soap); |
|
8418 return NULL; |
|
8419 } |
|
8420 #endif |
|
8421 p = (char*)soap_id_enter(soap, soap->id, p, t, sizeof(char), 0, NULL, NULL, NULL); |
|
8422 if (*soap->href) |
|
8423 p = (char*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(char), 0, NULL); |
|
8424 else if (p) |
|
8425 { if (soap_s2byte(soap, soap_value(soap), p)) |
|
8426 return NULL; |
|
8427 } |
|
8428 if (soap->body && soap_element_end_in(soap, tag)) |
|
8429 return NULL; |
|
8430 return p; |
|
8431 } |
|
8432 #endif |
|
8433 |
|
8434 /******************************************************************************/ |
|
8435 #ifndef PALM_2 |
|
8436 SOAP_FMAC1 |
|
8437 const char* |
|
8438 SOAP_FMAC2 |
|
8439 soap_short2s(struct soap *soap, short n) |
|
8440 { return soap_long2s(soap, (long)n); |
|
8441 } |
|
8442 #endif |
|
8443 |
|
8444 /******************************************************************************/ |
|
8445 #ifndef PALM_2 |
|
8446 SOAP_FMAC1 |
|
8447 int |
|
8448 SOAP_FMAC2 |
|
8449 soap_outshort(struct soap *soap, const char *tag, int id, const short *p, const char *type, int n) |
|
8450 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) |
|
8451 || soap_string_out(soap, soap_long2s(soap, (long)*p), 0)) |
|
8452 return soap->error; |
|
8453 return soap_element_end_out(soap, tag); |
|
8454 } |
|
8455 #endif |
|
8456 |
|
8457 /******************************************************************************/ |
|
8458 #ifndef PALM_2 |
|
8459 SOAP_FMAC1 |
|
8460 int |
|
8461 SOAP_FMAC2 |
|
8462 soap_s2short(struct soap *soap, const char *s, short *p) |
|
8463 { if (s) |
|
8464 { long n; |
|
8465 char *r; |
|
8466 n = soap_strtol(s, &r, 10); |
|
8467 if (s == r || *r || n < -32768 || n > 32767) |
|
8468 soap->error = SOAP_TYPE; |
|
8469 *p = (short)n; |
|
8470 } |
|
8471 return soap->error; |
|
8472 } |
|
8473 #endif |
|
8474 |
|
8475 /******************************************************************************/ |
|
8476 #ifndef PALM_2 |
|
8477 SOAP_FMAC1 |
|
8478 short * |
|
8479 SOAP_FMAC2 |
|
8480 soap_inshort(struct soap *soap, const char *tag, short *p, const char *type, int t) |
|
8481 { if (soap_element_begin_in(soap, tag, 0)) |
|
8482 return NULL; |
|
8483 #ifndef WITH_LEAN |
|
8484 if (*soap->type |
|
8485 && soap_match_tag(soap, soap->type, type) |
|
8486 && soap_match_tag(soap, soap->type, ":short") |
|
8487 && soap_match_tag(soap, soap->type, ":byte")) |
|
8488 { soap->error = SOAP_TYPE; |
|
8489 soap_revert(soap); |
|
8490 return NULL; |
|
8491 } |
|
8492 #endif |
|
8493 p = (short*)soap_id_enter(soap, soap->id, p, t, sizeof(short), 0, NULL, NULL, NULL); |
|
8494 if (*soap->href) |
|
8495 p = (short*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(short), 0, NULL); |
|
8496 else if (p) |
|
8497 { if (soap_s2short(soap, soap_value(soap), p)) |
|
8498 return NULL; |
|
8499 } |
|
8500 if (soap->body && soap_element_end_in(soap, tag)) |
|
8501 return NULL; |
|
8502 return p; |
|
8503 } |
|
8504 #endif |
|
8505 |
|
8506 /******************************************************************************/ |
|
8507 #ifndef PALM_2 |
|
8508 SOAP_FMAC1 |
|
8509 const char* |
|
8510 SOAP_FMAC2 |
|
8511 soap_float2s(struct soap *soap, float n) |
|
8512 { const char *s; |
|
8513 if (soap_isnan((double)n)) |
|
8514 s = "NaN"; |
|
8515 else if (soap_ispinff(n)) |
|
8516 s = "INF"; |
|
8517 else if (soap_isninff(n)) |
|
8518 s = "-INF"; |
|
8519 else |
|
8520 { sprintf(soap->tmpbuf, soap->float_format, n); |
|
8521 s = soap->tmpbuf; |
|
8522 } |
|
8523 return s; |
|
8524 } |
|
8525 #endif |
|
8526 |
|
8527 /******************************************************************************/ |
|
8528 #ifndef PALM_2 |
|
8529 SOAP_FMAC1 |
|
8530 int |
|
8531 SOAP_FMAC2 |
|
8532 soap_outfloat(struct soap *soap, const char *tag, int id, const float *p, const char *type, int n) |
|
8533 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) |
|
8534 || soap_string_out(soap, soap_float2s(soap, *p), 0)) |
|
8535 return soap->error; |
|
8536 return soap_element_end_out(soap, tag); |
|
8537 } |
|
8538 #endif |
|
8539 |
|
8540 /******************************************************************************/ |
|
8541 #ifndef PALM_2 |
|
8542 SOAP_FMAC1 |
|
8543 int |
|
8544 SOAP_FMAC2 |
|
8545 soap_s2float(struct soap *soap, const char *s, float *p) |
|
8546 { if (s) |
|
8547 { if (!*s) |
|
8548 return soap->error = SOAP_TYPE; |
|
8549 if (!soap_tag_cmp(s, "INF")) |
|
8550 *p = FLT_PINFTY; |
|
8551 else if (!soap_tag_cmp(s, "+INF")) |
|
8552 *p = FLT_PINFTY; |
|
8553 else if (!soap_tag_cmp(s, "-INF")) |
|
8554 *p = FLT_NINFTY; |
|
8555 else if (!soap_tag_cmp(s, "NaN")) |
|
8556 *p = FLT_NAN; |
|
8557 else |
|
8558 { |
|
8559 /* On some systems, strtof appears to be broken or doesn't link: use with caution */ |
|
8560 #if defined(HAVE_STRTOF) |
|
8561 char *r; |
|
8562 *p = strtof((char*)s, &r); |
|
8563 if (*r) |
|
8564 #elif defined(HAVE_STRTOD) |
|
8565 char *r; |
|
8566 *p = (float)strtod(s, &r); |
|
8567 if (*r) |
|
8568 #endif |
|
8569 #ifdef HAVE_SSCANF |
|
8570 if (sscanf(s, "%g", p) != 1) |
|
8571 soap->error = SOAP_TYPE; |
|
8572 #else |
|
8573 soap->error = SOAP_TYPE; |
|
8574 #endif |
|
8575 } |
|
8576 } |
|
8577 return soap->error; |
|
8578 } |
|
8579 #endif |
|
8580 |
|
8581 /******************************************************************************/ |
|
8582 #ifndef WITH_LEAN |
|
8583 static int soap_isnumeric(struct soap *soap, const char *type) |
|
8584 { if (soap_match_tag(soap, soap->type, type) |
|
8585 && soap_match_tag(soap, soap->type, ":float") |
|
8586 && soap_match_tag(soap, soap->type, ":double") |
|
8587 && soap_match_tag(soap, soap->type, ":decimal") |
|
8588 && soap_match_tag(soap, soap->type, ":integer") |
|
8589 && soap_match_tag(soap, soap->type, ":positiveInteger") |
|
8590 && soap_match_tag(soap, soap->type, ":negativeInteger") |
|
8591 && soap_match_tag(soap, soap->type, ":nonPositiveInteger") |
|
8592 && soap_match_tag(soap, soap->type, ":nonNegativeInteger") |
|
8593 && soap_match_tag(soap, soap->type, ":long") |
|
8594 && soap_match_tag(soap, soap->type, ":int") |
|
8595 && soap_match_tag(soap, soap->type, ":short") |
|
8596 && soap_match_tag(soap, soap->type, ":byte") |
|
8597 && soap_match_tag(soap, soap->type, ":unsignedLong") |
|
8598 && soap_match_tag(soap, soap->type, ":unsignedInt") |
|
8599 && soap_match_tag(soap, soap->type, ":unsignedShort") |
|
8600 && soap_match_tag(soap, soap->type, ":unsignedByte")) |
|
8601 { soap->error = SOAP_TYPE; |
|
8602 soap_revert(soap); |
|
8603 return SOAP_ERR; |
|
8604 } |
|
8605 return SOAP_OK; |
|
8606 } |
|
8607 #endif |
|
8608 |
|
8609 /******************************************************************************/ |
|
8610 #ifndef PALM_2 |
|
8611 SOAP_FMAC1 |
|
8612 float * |
|
8613 SOAP_FMAC2 |
|
8614 soap_infloat(struct soap *soap, const char *tag, float *p, const char *type, int t) |
|
8615 { if (soap_element_begin_in(soap, tag, 0)) |
|
8616 return NULL; |
|
8617 #ifndef WITH_LEAN |
|
8618 if (*soap->type != '\0' && soap_isnumeric(soap, type)) |
|
8619 return NULL; |
|
8620 #endif |
|
8621 p = (float*)soap_id_enter(soap, soap->id, p, t, sizeof(float), 0, NULL, NULL, NULL); |
|
8622 if (*soap->href) |
|
8623 p = (float*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(float), 0, NULL); |
|
8624 else if (p) |
|
8625 { if (soap_s2float(soap, soap_value(soap), p)) |
|
8626 return NULL; |
|
8627 } |
|
8628 if (soap->body && soap_element_end_in(soap, tag)) |
|
8629 return NULL; |
|
8630 return p; |
|
8631 } |
|
8632 #endif |
|
8633 |
|
8634 /******************************************************************************/ |
|
8635 #ifndef PALM_2 |
|
8636 SOAP_FMAC1 |
|
8637 const char* |
|
8638 SOAP_FMAC2 |
|
8639 soap_double2s(struct soap *soap, double n) |
|
8640 { const char *s; |
|
8641 if (soap_isnan(n)) |
|
8642 s = "NaN"; |
|
8643 else if (soap_ispinfd(n)) |
|
8644 s = "INF"; |
|
8645 else if (soap_isninfd(n)) |
|
8646 s = "-INF"; |
|
8647 else |
|
8648 { sprintf(soap->tmpbuf, soap->double_format, n); |
|
8649 s = soap->tmpbuf; |
|
8650 } |
|
8651 return s; |
|
8652 } |
|
8653 #endif |
|
8654 |
|
8655 /******************************************************************************/ |
|
8656 #ifndef PALM_2 |
|
8657 SOAP_FMAC1 |
|
8658 int |
|
8659 SOAP_FMAC2 |
|
8660 soap_outdouble(struct soap *soap, const char *tag, int id, const double *p, const char *type, int n) |
|
8661 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) |
|
8662 || soap_string_out(soap, soap_double2s(soap, *p), 0)) |
|
8663 return soap->error; |
|
8664 return soap_element_end_out(soap, tag); |
|
8665 } |
|
8666 #endif |
|
8667 |
|
8668 /******************************************************************************/ |
|
8669 #ifndef PALM_2 |
|
8670 SOAP_FMAC1 |
|
8671 int |
|
8672 SOAP_FMAC2 |
|
8673 soap_s2double(struct soap *soap, const char *s, double *p) |
|
8674 { if (s) |
|
8675 { if (!*s) |
|
8676 return soap->error = SOAP_TYPE; |
|
8677 if (!soap_tag_cmp(s, "INF")) |
|
8678 *p = DBL_PINFTY; |
|
8679 else if (!soap_tag_cmp(s, "+INF")) |
|
8680 *p = DBL_PINFTY; |
|
8681 else if (!soap_tag_cmp(s, "-INF")) |
|
8682 *p = DBL_NINFTY; |
|
8683 else if (!soap_tag_cmp(s, "NaN")) |
|
8684 *p = DBL_NAN; |
|
8685 else |
|
8686 { |
|
8687 #ifdef HAVE_STRTOD |
|
8688 char *r; |
|
8689 *p = strtod(s, &r); |
|
8690 if (*r) |
|
8691 #endif |
|
8692 #ifdef HAVE_SSCANF |
|
8693 if (sscanf(s, "%lg", p) != 1) |
|
8694 soap->error = SOAP_TYPE; |
|
8695 #else |
|
8696 soap->error = SOAP_TYPE; |
|
8697 #endif |
|
8698 } |
|
8699 } |
|
8700 return soap->error; |
|
8701 } |
|
8702 #endif |
|
8703 |
|
8704 /******************************************************************************/ |
|
8705 #ifndef PALM_2 |
|
8706 SOAP_FMAC1 |
|
8707 double * |
|
8708 SOAP_FMAC2 |
|
8709 soap_indouble(struct soap *soap, const char *tag, double *p, const char *type, int t) |
|
8710 { if (soap_element_begin_in(soap, tag, 0)) |
|
8711 return NULL; |
|
8712 #ifndef WITH_LEAN |
|
8713 if (*soap->type != '\0' && soap_isnumeric(soap, type)) |
|
8714 return NULL; |
|
8715 #endif |
|
8716 p = (double*)soap_id_enter(soap, soap->id, p, t, sizeof(double), 0, NULL, NULL, NULL); |
|
8717 if (*soap->href) |
|
8718 p = (double*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(double), 0, NULL); |
|
8719 else if (p) |
|
8720 { if (soap_s2double(soap, soap_value(soap), p)) |
|
8721 return NULL; |
|
8722 } |
|
8723 if (soap->body && soap_element_end_in(soap, tag)) |
|
8724 return NULL; |
|
8725 return p; |
|
8726 } |
|
8727 #endif |
|
8728 |
|
8729 /******************************************************************************/ |
|
8730 #ifndef PALM_2 |
|
8731 SOAP_FMAC1 |
|
8732 const char* |
|
8733 SOAP_FMAC2 |
|
8734 soap_unsignedByte2s(struct soap *soap, unsigned char n) |
|
8735 { return soap_unsignedLong2s(soap, (unsigned long)n); |
|
8736 } |
|
8737 #endif |
|
8738 |
|
8739 /******************************************************************************/ |
|
8740 #ifndef PALM_2 |
|
8741 SOAP_FMAC1 |
|
8742 int |
|
8743 SOAP_FMAC2 |
|
8744 soap_outunsignedByte(struct soap *soap, const char *tag, int id, const unsigned char *p, const char *type, int n) |
|
8745 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) |
|
8746 || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0)) |
|
8747 return soap->error; |
|
8748 return soap_element_end_out(soap, tag); |
|
8749 } |
|
8750 #endif |
|
8751 |
|
8752 /******************************************************************************/ |
|
8753 #ifndef PALM_2 |
|
8754 SOAP_FMAC1 |
|
8755 int |
|
8756 SOAP_FMAC2 |
|
8757 soap_s2unsignedByte(struct soap *soap, const char *s, unsigned char *p) |
|
8758 { if (s) |
|
8759 { unsigned long n; |
|
8760 char *r; |
|
8761 n = soap_strtoul(s, &r, 10); |
|
8762 if (s == r || *r || n > 255) |
|
8763 soap->error = SOAP_TYPE; |
|
8764 *p = (unsigned char)n; |
|
8765 } |
|
8766 return soap->error; |
|
8767 } |
|
8768 #endif |
|
8769 |
|
8770 /******************************************************************************/ |
|
8771 #ifndef PALM_2 |
|
8772 SOAP_FMAC1 |
|
8773 unsigned char * |
|
8774 SOAP_FMAC2 |
|
8775 soap_inunsignedByte(struct soap *soap, const char *tag, unsigned char *p, const char *type, int t) |
|
8776 { if (soap_element_begin_in(soap, tag, 0)) |
|
8777 return NULL; |
|
8778 #ifndef WITH_LEAN |
|
8779 if (*soap->type |
|
8780 && soap_match_tag(soap, soap->type, type) |
|
8781 && soap_match_tag(soap, soap->type, ":unsignedByte")) |
|
8782 { soap->error = SOAP_TYPE; |
|
8783 soap_revert(soap); |
|
8784 return NULL; |
|
8785 } |
|
8786 #endif |
|
8787 p = (unsigned char*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned char), 0, NULL, NULL, NULL); |
|
8788 if (*soap->href) |
|
8789 p = (unsigned char*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(unsigned char), 0, NULL); |
|
8790 else if (p) |
|
8791 { if (soap_s2unsignedByte(soap, soap_value(soap), p)) |
|
8792 return NULL; |
|
8793 } |
|
8794 if (soap->body && soap_element_end_in(soap, tag)) |
|
8795 return NULL; |
|
8796 return p; |
|
8797 } |
|
8798 #endif |
|
8799 |
|
8800 /******************************************************************************/ |
|
8801 #ifndef PALM_2 |
|
8802 SOAP_FMAC1 |
|
8803 const char* |
|
8804 SOAP_FMAC2 |
|
8805 soap_unsignedShort2s(struct soap *soap, unsigned short n) |
|
8806 { return soap_unsignedLong2s(soap, (unsigned long)n); |
|
8807 } |
|
8808 #endif |
|
8809 |
|
8810 /******************************************************************************/ |
|
8811 #ifndef PALM_2 |
|
8812 SOAP_FMAC1 |
|
8813 int |
|
8814 SOAP_FMAC2 |
|
8815 soap_outunsignedShort(struct soap *soap, const char *tag, int id, const unsigned short *p, const char *type, int n) |
|
8816 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) |
|
8817 || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0)) |
|
8818 return soap->error; |
|
8819 return soap_element_end_out(soap, tag); |
|
8820 } |
|
8821 #endif |
|
8822 |
|
8823 /******************************************************************************/ |
|
8824 #ifndef PALM_2 |
|
8825 SOAP_FMAC1 |
|
8826 int |
|
8827 SOAP_FMAC2 |
|
8828 soap_s2unsignedShort(struct soap *soap, const char *s, unsigned short *p) |
|
8829 { if (s) |
|
8830 { unsigned long n; |
|
8831 char *r; |
|
8832 n = soap_strtoul(s, &r, 10); |
|
8833 if (s == r || *r || n > 65535) |
|
8834 soap->error = SOAP_TYPE; |
|
8835 *p = (unsigned short)n; |
|
8836 } |
|
8837 return soap->error; |
|
8838 } |
|
8839 #endif |
|
8840 |
|
8841 /******************************************************************************/ |
|
8842 #ifndef PALM_2 |
|
8843 SOAP_FMAC1 |
|
8844 unsigned short * |
|
8845 SOAP_FMAC2 |
|
8846 soap_inunsignedShort(struct soap *soap, const char *tag, unsigned short *p, const char *type, int t) |
|
8847 { if (soap_element_begin_in(soap, tag, 0)) |
|
8848 return NULL; |
|
8849 #ifndef WITH_LEAN |
|
8850 if (*soap->type |
|
8851 && soap_match_tag(soap, soap->type, type) |
|
8852 && soap_match_tag(soap, soap->type, ":unsignedShort") |
|
8853 && soap_match_tag(soap, soap->type, ":unsignedByte")) |
|
8854 { soap->error = SOAP_TYPE; |
|
8855 soap_revert(soap); |
|
8856 return NULL; |
|
8857 } |
|
8858 #endif |
|
8859 p = (unsigned short*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned short), 0, NULL, NULL, NULL); |
|
8860 if (*soap->href) |
|
8861 p = (unsigned short*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(unsigned short), 0, NULL); |
|
8862 else if (p) |
|
8863 { if (soap_s2unsignedShort(soap, soap_value(soap), p)) |
|
8864 return NULL; |
|
8865 } |
|
8866 if (soap->body && soap_element_end_in(soap, tag)) |
|
8867 return NULL; |
|
8868 return p; |
|
8869 } |
|
8870 #endif |
|
8871 |
|
8872 /******************************************************************************/ |
|
8873 #ifndef PALM_2 |
|
8874 SOAP_FMAC1 |
|
8875 const char* |
|
8876 SOAP_FMAC2 |
|
8877 soap_unsignedInt2s(struct soap *soap, unsigned int n) |
|
8878 { return soap_unsignedLong2s(soap, (unsigned long)n); |
|
8879 } |
|
8880 #endif |
|
8881 |
|
8882 /******************************************************************************/ |
|
8883 #ifndef PALM_2 |
|
8884 SOAP_FMAC1 |
|
8885 int |
|
8886 SOAP_FMAC2 |
|
8887 soap_outunsignedInt(struct soap *soap, const char *tag, int id, const unsigned int *p, const char *type, int n) |
|
8888 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) |
|
8889 || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0)) |
|
8890 return soap->error; |
|
8891 return soap_element_end_out(soap, tag); |
|
8892 } |
|
8893 #endif |
|
8894 |
|
8895 /******************************************************************************/ |
|
8896 #ifndef PALM_2 |
|
8897 SOAP_FMAC1 |
|
8898 int |
|
8899 SOAP_FMAC2 |
|
8900 soap_s2unsignedInt(struct soap *soap, const char *s, unsigned int *p) |
|
8901 { if (s) |
|
8902 { char *r; |
|
8903 *p = (unsigned int)soap_strtoul(s, &r, 10); |
|
8904 if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r |
|
8905 #ifndef WITH_NOIO |
|
8906 #ifndef WITH_LEAN |
|
8907 || soap_errno == SOAP_ERANGE |
|
8908 #endif |
|
8909 #endif |
|
8910 ) |
|
8911 soap->error = SOAP_TYPE; |
|
8912 } |
|
8913 return soap->error; |
|
8914 } |
|
8915 #endif |
|
8916 |
|
8917 /******************************************************************************/ |
|
8918 #ifndef PALM_2 |
|
8919 SOAP_FMAC1 |
|
8920 unsigned int * |
|
8921 SOAP_FMAC2 |
|
8922 soap_inunsignedInt(struct soap *soap, const char *tag, unsigned int *p, const char *type, int t) |
|
8923 { if (soap_element_begin_in(soap, tag, 0)) |
|
8924 return NULL; |
|
8925 #ifndef WITH_LEAN |
|
8926 if (*soap->type |
|
8927 && soap_match_tag(soap, soap->type, type) |
|
8928 && soap_match_tag(soap, soap->type, ":unsignedInt") |
|
8929 && soap_match_tag(soap, soap->type, ":unsignedShort") |
|
8930 && soap_match_tag(soap, soap->type, ":unsignedByte")) |
|
8931 { soap->error = SOAP_TYPE; |
|
8932 soap_revert(soap); |
|
8933 return NULL; |
|
8934 } |
|
8935 #endif |
|
8936 p = (unsigned int*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned int), 0, NULL, NULL, NULL); |
|
8937 if (*soap->href) |
|
8938 p = (unsigned int*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(unsigned int), 0, NULL); |
|
8939 else if (p) |
|
8940 { if (soap_s2unsignedInt(soap, soap_value(soap), p)) |
|
8941 return NULL; |
|
8942 } |
|
8943 if (soap->body && soap_element_end_in(soap, tag)) |
|
8944 return NULL; |
|
8945 return p; |
|
8946 } |
|
8947 #endif |
|
8948 |
|
8949 /******************************************************************************/ |
|
8950 #ifndef PALM_2 |
|
8951 SOAP_FMAC1 |
|
8952 const char* |
|
8953 SOAP_FMAC2 |
|
8954 soap_unsignedLong2s(struct soap *soap, unsigned long n) |
|
8955 { sprintf(soap->tmpbuf, "%lu", n); |
|
8956 return soap->tmpbuf; |
|
8957 } |
|
8958 #endif |
|
8959 |
|
8960 /******************************************************************************/ |
|
8961 #ifndef PALM_2 |
|
8962 SOAP_FMAC1 |
|
8963 int |
|
8964 SOAP_FMAC2 |
|
8965 soap_outunsignedLong(struct soap *soap, const char *tag, int id, const unsigned long *p, const char *type, int n) |
|
8966 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) |
|
8967 || soap_string_out(soap, soap_unsignedLong2s(soap, *p), 0)) |
|
8968 return soap->error; |
|
8969 return soap_element_end_out(soap, tag); |
|
8970 } |
|
8971 #endif |
|
8972 |
|
8973 /******************************************************************************/ |
|
8974 #ifndef PALM_2 |
|
8975 SOAP_FMAC1 |
|
8976 int |
|
8977 SOAP_FMAC2 |
|
8978 soap_s2unsignedLong(struct soap *soap, const char *s, unsigned long *p) |
|
8979 { if (s) |
|
8980 { char *r; |
|
8981 *p = soap_strtoul(s, &r, 10); |
|
8982 if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r |
|
8983 #ifndef WITH_NOIO |
|
8984 #ifndef WITH_LEAN |
|
8985 || soap_errno == SOAP_ERANGE |
|
8986 #endif |
|
8987 #endif |
|
8988 ) |
|
8989 soap->error = SOAP_TYPE; |
|
8990 } |
|
8991 return soap->error; |
|
8992 } |
|
8993 #endif |
|
8994 |
|
8995 /******************************************************************************/ |
|
8996 #ifndef PALM_2 |
|
8997 SOAP_FMAC1 |
|
8998 unsigned long * |
|
8999 SOAP_FMAC2 |
|
9000 soap_inunsignedLong(struct soap *soap, const char *tag, unsigned long *p, const char *type, int t) |
|
9001 { if (soap_element_begin_in(soap, tag, 0)) |
|
9002 return NULL; |
|
9003 #ifndef WITH_LEAN |
|
9004 if (*soap->type |
|
9005 && soap_match_tag(soap, soap->type, type) |
|
9006 && soap_match_tag(soap, soap->type, ":unsignedInt") |
|
9007 && soap_match_tag(soap, soap->type, ":unsignedShort") |
|
9008 && soap_match_tag(soap, soap->type, ":unsignedByte")) |
|
9009 { soap->error = SOAP_TYPE; |
|
9010 soap_revert(soap); |
|
9011 return NULL; |
|
9012 } |
|
9013 #endif |
|
9014 p = (unsigned long*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned long), 0, NULL, NULL, NULL); |
|
9015 if (*soap->href) |
|
9016 p = (unsigned long*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(unsigned long), 0, NULL); |
|
9017 else if (p) |
|
9018 { if (soap_s2unsignedLong(soap, soap_value(soap), p)) |
|
9019 return NULL; |
|
9020 } |
|
9021 if (soap->body && soap_element_end_in(soap, tag)) |
|
9022 return NULL; |
|
9023 return p; |
|
9024 } |
|
9025 #endif |
|
9026 |
|
9027 /******************************************************************************/ |
|
9028 #ifndef WITH_LEAN |
|
9029 SOAP_FMAC1 |
|
9030 const char* |
|
9031 SOAP_FMAC2 |
|
9032 soap_ULONG642s(struct soap *soap, ULONG64 n) |
|
9033 { sprintf(soap->tmpbuf, SOAP_ULONG_FORMAT, n); |
|
9034 return soap->tmpbuf; |
|
9035 } |
|
9036 #endif |
|
9037 |
|
9038 /******************************************************************************/ |
|
9039 #ifndef WITH_LEAN |
|
9040 SOAP_FMAC1 |
|
9041 int |
|
9042 SOAP_FMAC2 |
|
9043 soap_outULONG64(struct soap *soap, const char *tag, int id, const ULONG64 *p, const char *type, int n) |
|
9044 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) |
|
9045 || soap_string_out(soap, soap_ULONG642s(soap, *p), 0)) |
|
9046 return soap->error; |
|
9047 return soap_element_end_out(soap, tag); |
|
9048 } |
|
9049 #endif |
|
9050 |
|
9051 /******************************************************************************/ |
|
9052 #ifndef WITH_LEAN |
|
9053 SOAP_FMAC1 |
|
9054 int |
|
9055 SOAP_FMAC2 |
|
9056 soap_s2ULONG64(struct soap *soap, const char *s, ULONG64 *p) |
|
9057 { if (s) |
|
9058 { |
|
9059 #ifdef HAVE_STRTOULL |
|
9060 char *r; |
|
9061 *p = strtoull(s, &r, 10); |
|
9062 if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r |
|
9063 #ifndef WITH_NOIO |
|
9064 #ifndef WITH_LEAN |
|
9065 || soap_errno == SOAP_ERANGE |
|
9066 #endif |
|
9067 #endif |
|
9068 ) |
|
9069 #else |
|
9070 # ifdef HAVE_SSCANF |
|
9071 if (sscanf(s, SOAP_ULONG_FORMAT, p) != 1) |
|
9072 # endif |
|
9073 #endif |
|
9074 soap->error = SOAP_TYPE; |
|
9075 } |
|
9076 return soap->error; |
|
9077 } |
|
9078 #endif |
|
9079 |
|
9080 /******************************************************************************/ |
|
9081 #ifndef WITH_LEAN |
|
9082 SOAP_FMAC1 |
|
9083 ULONG64 * |
|
9084 SOAP_FMAC2 |
|
9085 soap_inULONG64(struct soap *soap, const char *tag, ULONG64 *p, const char *type, int t) |
|
9086 { if (soap_element_begin_in(soap, tag, 0)) |
|
9087 return NULL; |
|
9088 if (*soap->type |
|
9089 && soap_match_tag(soap, soap->type, type) |
|
9090 && soap_match_tag(soap, soap->type, ":positiveInteger") |
|
9091 && soap_match_tag(soap, soap->type, ":nonNegativeInteger") |
|
9092 && soap_match_tag(soap, soap->type, ":unsignedLong") |
|
9093 && soap_match_tag(soap, soap->type, ":unsignedInt") |
|
9094 && soap_match_tag(soap, soap->type, ":unsignedShort") |
|
9095 && soap_match_tag(soap, soap->type, ":unsignedByte")) |
|
9096 { soap->error = SOAP_TYPE; |
|
9097 soap_revert(soap); |
|
9098 return NULL; |
|
9099 } |
|
9100 p = (ULONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(ULONG64), 0, NULL, NULL, NULL); |
|
9101 if (*soap->href) |
|
9102 p = (ULONG64*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(ULONG64), 0, NULL); |
|
9103 else if (p) |
|
9104 { if (soap_s2ULONG64(soap, soap_value(soap), p)) |
|
9105 return NULL; |
|
9106 } |
|
9107 if (soap->body && soap_element_end_in(soap, tag)) |
|
9108 return NULL; |
|
9109 return p; |
|
9110 } |
|
9111 #endif |
|
9112 |
|
9113 /******************************************************************************/ |
|
9114 #ifndef PALM_2 |
|
9115 SOAP_FMAC1 |
|
9116 int |
|
9117 SOAP_FMAC2 |
|
9118 soap_s2string(struct soap *soap, const char *s, char **t) |
|
9119 { *t = NULL; |
|
9120 if (s && !(*t = soap_strdup(soap, s))) |
|
9121 soap->error = SOAP_EOM; |
|
9122 return soap->error; |
|
9123 } |
|
9124 #endif |
|
9125 |
|
9126 /******************************************************************************/ |
|
9127 #ifndef PALM_2 |
|
9128 SOAP_FMAC1 |
|
9129 int |
|
9130 SOAP_FMAC2 |
|
9131 soap_s2QName(struct soap *soap, const char *s, char **t) |
|
9132 { if (s) |
|
9133 { struct soap_nlist *np; |
|
9134 const char *p; |
|
9135 if (!strncmp(s, "xml:", 4)) |
|
9136 { *t = soap_strdup(soap, s); |
|
9137 return SOAP_OK; |
|
9138 } |
|
9139 np = soap->nlist; |
|
9140 p = strchr(s, ':'); |
|
9141 if (p) |
|
9142 { register int n = p - s; |
|
9143 while (np && (strncmp(np->id, s, n) || np->id[n])) |
|
9144 np = np->next; |
|
9145 p++; |
|
9146 } |
|
9147 else |
|
9148 { while (np && *np->id) |
|
9149 np = np->next; |
|
9150 p = s; |
|
9151 } |
|
9152 if (np) |
|
9153 { if (np->index >= 0 && soap->local_namespaces) |
|
9154 { register const char *q = soap->local_namespaces[np->index].id; |
|
9155 if (q) |
|
9156 { if ((*t = (char*)soap_malloc(soap, strlen(p) + strlen(q) + 2))) |
|
9157 sprintf(*t, "%s:%s", q, p); |
|
9158 return SOAP_OK; |
|
9159 } |
|
9160 } |
|
9161 if (np->ns) |
|
9162 { if ((*t = (char*)soap_malloc(soap, strlen(p) + strlen(np->ns) + 4))) |
|
9163 sprintf(*t, "\"%s\":%s", np->ns, p); |
|
9164 return SOAP_OK; |
|
9165 } |
|
9166 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Namespace prefix of '%s' not defined (index=%d, URI=%s)\n", s, np->index, np->ns?np->ns:"")); |
|
9167 return soap->error = SOAP_NAMESPACE; |
|
9168 } |
|
9169 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Namespace prefix of '%s' not defined, assuming empty namespace\n", s)); |
|
9170 if ((*t = (char*)soap_malloc(soap, strlen(p) + 4))) |
|
9171 sprintf(*t, "\"\":%s", p); |
|
9172 } |
|
9173 return soap->error; |
|
9174 } |
|
9175 #endif |
|
9176 |
|
9177 /******************************************************************************/ |
|
9178 #ifndef PALM_2 |
|
9179 SOAP_FMAC1 |
|
9180 const char* |
|
9181 SOAP_FMAC2 |
|
9182 soap_QName2s(struct soap *soap, const char *s) |
|
9183 { struct Namespace *p; |
|
9184 char *t; |
|
9185 int n; |
|
9186 if (!s || *s != '"') |
|
9187 { |
|
9188 #ifndef WITH_LEAN |
|
9189 if (s && (soap->mode & SOAP_XML_CANONICAL)) |
|
9190 { t = strchr(const_cast<char*>(s), ':'); |
|
9191 if (t) |
|
9192 soap_utilize_ns(soap, s, t - s); |
|
9193 } |
|
9194 #endif |
|
9195 return s; |
|
9196 } |
|
9197 s++; |
|
9198 if ((p = soap->local_namespaces)) |
|
9199 { for (; p->id; p++) |
|
9200 { if (p->ns) |
|
9201 if (!soap_tag_cmp(s, p->ns)) |
|
9202 break; |
|
9203 if (p->in) |
|
9204 if (!soap_tag_cmp(s, p->in)) |
|
9205 break; |
|
9206 } |
|
9207 if (p && p->id) |
|
9208 { s = strchr(s, '"'); |
|
9209 if (s) |
|
9210 { t = (char*)soap_malloc(soap, strlen(p->id) + strlen(s)); |
|
9211 strcpy(t, p->id); |
|
9212 strcat(t, s + 1); |
|
9213 return t; |
|
9214 } |
|
9215 } |
|
9216 } |
|
9217 t = (char*)strchr(s, '"'); |
|
9218 if (t) |
|
9219 n = t - s; |
|
9220 else |
|
9221 n = 0; |
|
9222 t = soap_strdup(soap, s); |
|
9223 t[n] = '\0'; |
|
9224 sprintf(soap->tmpbuf, "xmlns:_%d", soap->idnum++); |
|
9225 soap_set_attr(soap, soap->tmpbuf, t); |
|
9226 s = strchr(s, '"'); |
|
9227 if (s) |
|
9228 { t = (char*)soap_malloc(soap, strlen(soap->tmpbuf) + strlen(s) - 6); |
|
9229 strcpy(t, soap->tmpbuf + 6); |
|
9230 strcat(t, s + 1); |
|
9231 } |
|
9232 return t; |
|
9233 } |
|
9234 #endif |
|
9235 |
|
9236 /******************************************************************************/ |
|
9237 #ifndef PALM_2 |
|
9238 SOAP_FMAC1 |
|
9239 int |
|
9240 SOAP_FMAC2 |
|
9241 soap_outstring(struct soap *soap, const char *tag, int id, char *const*p, const char *type, int n) |
|
9242 { id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n); |
|
9243 if (id < 0 |
|
9244 || soap_element_begin_out(soap, tag, id, type) |
|
9245 || soap_string_out(soap, *p, 0) |
|
9246 || soap_element_end_out(soap, tag)) |
|
9247 return soap->error; |
|
9248 return SOAP_OK; |
|
9249 } |
|
9250 #endif |
|
9251 |
|
9252 /******************************************************************************/ |
|
9253 #ifndef PALM_2 |
|
9254 SOAP_FMAC1 |
|
9255 char ** |
|
9256 SOAP_FMAC2 |
|
9257 soap_instring(struct soap *soap, const char *tag, char **p, const char *type, int t, int flag, long minlen, long maxlen) |
|
9258 { if (soap_element_begin_in(soap, tag, 1)) |
|
9259 { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG) |
|
9260 return NULL; |
|
9261 soap->error = SOAP_OK; |
|
9262 } |
|
9263 if (!p) |
|
9264 if (!(p = (char**)soap_malloc(soap, sizeof(char*)))) |
|
9265 return NULL; |
|
9266 if (soap->body) |
|
9267 { *p = soap_string_in(soap, flag, minlen, maxlen); |
|
9268 if (!*p || !(char*)soap_id_enter(soap, soap->id, *p, t, sizeof(char*), 0, NULL, NULL, NULL)) |
|
9269 return NULL; |
|
9270 } |
|
9271 else |
|
9272 *p = NULL; |
|
9273 if (*soap->href) |
|
9274 p = (char**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(char**), 0); |
|
9275 if (soap->body && soap_element_end_in(soap, tag)) |
|
9276 return NULL; |
|
9277 return p; |
|
9278 } |
|
9279 #endif |
|
9280 |
|
9281 /******************************************************************************/ |
|
9282 #ifndef WITH_LEANER |
|
9283 #ifndef PALM_2 |
|
9284 SOAP_FMAC1 |
|
9285 int |
|
9286 SOAP_FMAC2 |
|
9287 soap_outwstring(struct soap *soap, const char *tag, int id, wchar_t *const*p, const char *type, int n) |
|
9288 { id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n); |
|
9289 if (id < 0 |
|
9290 || soap_element_begin_out(soap, tag, id, type) |
|
9291 || soap_wstring_out(soap, *p, 0) |
|
9292 || soap_element_end_out(soap, tag)) |
|
9293 return soap->error; |
|
9294 return SOAP_OK; |
|
9295 } |
|
9296 #endif |
|
9297 #endif |
|
9298 |
|
9299 /******************************************************************************/ |
|
9300 #ifndef WITH_LEANER |
|
9301 #ifndef PALM_2 |
|
9302 SOAP_FMAC1 |
|
9303 wchar_t ** |
|
9304 SOAP_FMAC2 |
|
9305 soap_inwstring(struct soap *soap, const char *tag, wchar_t **p, const char *type, int t, long minlen, long maxlen) |
|
9306 { if (soap_element_begin_in(soap, tag, 1)) |
|
9307 { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG) |
|
9308 return NULL; |
|
9309 soap->error = SOAP_OK; |
|
9310 } |
|
9311 if (!p) |
|
9312 if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*)))) |
|
9313 return NULL; |
|
9314 if (soap->body) |
|
9315 { *p = soap_wstring_in(soap, 1, minlen, maxlen); |
|
9316 if (!*p || !(wchar_t*)soap_id_enter(soap, soap->id, *p, t, sizeof(wchar_t*), 0, NULL, NULL, NULL)) |
|
9317 return NULL; |
|
9318 } |
|
9319 else |
|
9320 *p = NULL; |
|
9321 if (*soap->href) |
|
9322 p = (wchar_t**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(wchar_t**), 0); |
|
9323 if (soap->body && soap_element_end_in(soap, tag)) |
|
9324 return NULL; |
|
9325 return p; |
|
9326 } |
|
9327 #endif |
|
9328 #endif |
|
9329 |
|
9330 /******************************************************************************/ |
|
9331 #ifndef WITH_LEAN |
|
9332 static time_t |
|
9333 soap_timegm(struct tm *T) |
|
9334 { |
|
9335 #if defined(HAVE_TIMEGM) |
|
9336 return timegm(T); |
|
9337 #else |
|
9338 time_t t, g, z; |
|
9339 #ifdef HAVE_GMTIME_R |
|
9340 struct tm tm, *tmp = &tm; |
|
9341 #else |
|
9342 struct tm *tmp; |
|
9343 #endif |
|
9344 t = mktime(T); |
|
9345 if (t == -1) |
|
9346 return -1; |
|
9347 #ifdef HAVE_GMTIME_R |
|
9348 gmtime_r(&t, tmp); |
|
9349 #else |
|
9350 tmp = gmtime(&t); |
|
9351 #endif |
|
9352 tmp->tm_isdst = 0; |
|
9353 g = mktime(tmp); |
|
9354 if (g == -1) |
|
9355 return -1; |
|
9356 z = g - t; |
|
9357 return t - z; |
|
9358 #endif |
|
9359 } |
|
9360 #endif |
|
9361 |
|
9362 /******************************************************************************/ |
|
9363 #ifndef WITH_LEAN |
|
9364 SOAP_FMAC1 |
|
9365 const char* |
|
9366 SOAP_FMAC2 |
|
9367 soap_dateTime2s(struct soap *soap, time_t n) |
|
9368 { struct tm T, *pT = &T; |
|
9369 #if defined(HAVE_GMTIME_R) |
|
9370 if (gmtime_r(&n, pT)) |
|
9371 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); |
|
9372 /* The following defines were added for VxWorks*/ |
|
9373 #elif defined(HAVE_PGMTIME_R) |
|
9374 if (gmtime_r(&n, pT)) |
|
9375 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); |
|
9376 #elif defined(HAVE_PGMTIME) |
|
9377 if (gmtime(&n, pT)) |
|
9378 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); |
|
9379 #elif defined(HAVE_GMTIME) |
|
9380 if ((pT = gmtime(&n))) |
|
9381 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); |
|
9382 #elif defined(HAVE_GETTIMEOFDAY) |
|
9383 struct timezone tz; |
|
9384 memset((void*)&tz, 0, sizeof(tz)); |
|
9385 # if defined(HAVE_LOCALTIME_R) |
|
9386 if (localtime_r(&n, pT)) |
|
9387 { struct timeval tv; |
|
9388 gettimeofday(&tv, &tz); |
|
9389 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); |
|
9390 sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60); |
|
9391 } |
|
9392 # else |
|
9393 if ((pT = localtime(&n))) |
|
9394 { struct timeval tv; |
|
9395 gettimeofday(&tv, &tz); |
|
9396 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); |
|
9397 sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60); |
|
9398 } |
|
9399 #endif |
|
9400 #elif defined(HAVE_FTIME) |
|
9401 struct timeb t; |
|
9402 memset((void*)&t, 0, sizeof(t)); |
|
9403 # if defined(HAVE_LOCALTIME_R) |
|
9404 if (localtime_r(&n, pT)) |
|
9405 { ftime(&t); |
|
9406 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); |
|
9407 sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60); |
|
9408 } |
|
9409 /* The following defines were added for VxWorks*/ |
|
9410 # elif defined(HAVE_PLOCALTIME_R) |
|
9411 if (localtime_r(&n, pT)) |
|
9412 { strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); |
|
9413 sprintf(soap->tmpbuf+strlen(soap->tmpbuf), "%+03d:%02d", t.timezone/60, abs(t.timezone)%60); |
|
9414 } |
|
9415 # else |
|
9416 if ((pT = localtime(&n))) |
|
9417 { ftime(&t); |
|
9418 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); |
|
9419 sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60); |
|
9420 } |
|
9421 # endif |
|
9422 #elif defined(HAVE_LOCALTIME_R) |
|
9423 if (localtime_r(&n, pT)) |
|
9424 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); |
|
9425 /* The following defines were added for VxWorks*/ |
|
9426 #elif defined(HAVE_PLOCALTIME_R) |
|
9427 if (localtime_r(&n, pT)) |
|
9428 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); |
|
9429 #else |
|
9430 if ((pT = localtime(&n))) |
|
9431 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); |
|
9432 #endif |
|
9433 else |
|
9434 strcpy(soap->tmpbuf, "1969-12-31T23:59:59Z"); |
|
9435 return soap->tmpbuf; |
|
9436 } |
|
9437 #endif |
|
9438 |
|
9439 /******************************************************************************/ |
|
9440 #ifndef WITH_LEAN |
|
9441 SOAP_FMAC1 |
|
9442 int |
|
9443 SOAP_FMAC2 |
|
9444 soap_outdateTime(struct soap *soap, const char *tag, int id, const time_t *p, const char *type, int n) |
|
9445 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) |
|
9446 || soap_string_out(soap, soap_dateTime2s(soap, *p), 0)) |
|
9447 return soap->error; |
|
9448 return soap_element_end_out(soap, tag); |
|
9449 } |
|
9450 #endif |
|
9451 |
|
9452 /******************************************************************************/ |
|
9453 #ifndef WITH_LEAN |
|
9454 SOAP_FMAC1 |
|
9455 int |
|
9456 SOAP_FMAC2 |
|
9457 soap_s2dateTime(struct soap *soap, const char *s, time_t *p) |
|
9458 { if (s) |
|
9459 { struct tm T; |
|
9460 char zone[16]; |
|
9461 const char *t; |
|
9462 memset((void*)&T, 0, sizeof(T)); |
|
9463 zone[sizeof(zone)-1] = '\0'; |
|
9464 if (strchr(s, '-')) |
|
9465 t = "%d-%d-%dT%d:%d:%d%15s"; |
|
9466 else if (strchr(s, ':')) |
|
9467 t = "%4d%2d%2dT%d:%d:%d%15s"; |
|
9468 else /* parse non-XSD-standard alternative ISO 8601 format */ |
|
9469 t = "%4d%2d%2dT%2d%2d%2d%15s"; |
|
9470 sscanf(s, t, &T.tm_year, &T.tm_mon, &T.tm_mday, &T.tm_hour, &T.tm_min, &T.tm_sec, zone); |
|
9471 if (T.tm_year == 1) |
|
9472 T.tm_year = 70; |
|
9473 else |
|
9474 T.tm_year -= 1900; |
|
9475 T.tm_mon--; |
|
9476 if (*zone) |
|
9477 { if (*zone == '.') |
|
9478 { for (s = zone + 1; *s; s++) |
|
9479 if (*s < '0' || *s > '9') |
|
9480 break; |
|
9481 } |
|
9482 else |
|
9483 s = zone; |
|
9484 if (*s == '+' || *s == '-') |
|
9485 { int h = 0, m = 0; |
|
9486 if (s[3] == ':') |
|
9487 { sscanf(s, "%d:%d", &h, &m); |
|
9488 if (h < 0) |
|
9489 m = -m; |
|
9490 } |
|
9491 else |
|
9492 { m = (int)atol(s); |
|
9493 h = m / 100; |
|
9494 m = m % 100; |
|
9495 } |
|
9496 T.tm_hour -= h; |
|
9497 T.tm_min -= m; |
|
9498 } |
|
9499 *p = soap_timegm(&T); |
|
9500 } |
|
9501 else |
|
9502 *p = mktime(&T); /* no time zone: suppose it is localtime? */ |
|
9503 } |
|
9504 return soap->error; |
|
9505 } |
|
9506 #endif |
|
9507 |
|
9508 /******************************************************************************/ |
|
9509 #ifndef WITH_LEAN |
|
9510 SOAP_FMAC1 |
|
9511 time_t * |
|
9512 SOAP_FMAC2 |
|
9513 soap_indateTime(struct soap *soap, const char *tag, time_t *p, const char * type, int t) |
|
9514 { if (soap_element_begin_in(soap, tag, 0)) |
|
9515 return NULL; |
|
9516 if (*soap->type |
|
9517 && soap_match_tag(soap, soap->type, type) |
|
9518 && soap_match_tag(soap, soap->type, ":dateTime")) |
|
9519 { soap->error = SOAP_TYPE; |
|
9520 soap_revert(soap); |
|
9521 return NULL; |
|
9522 } |
|
9523 p = (time_t*)soap_id_enter(soap, soap->id, p, t, sizeof(time_t), 0, NULL, NULL, NULL); |
|
9524 if (*soap->href) |
|
9525 p = (time_t*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(time_t), 0, NULL); |
|
9526 else if (p) |
|
9527 { if (soap_s2dateTime(soap, soap_value(soap), p)) |
|
9528 return NULL; |
|
9529 } |
|
9530 if (soap->body && soap_element_end_in(soap, tag)) |
|
9531 return NULL; |
|
9532 return p; |
|
9533 } |
|
9534 #endif |
|
9535 |
|
9536 /******************************************************************************/ |
|
9537 #ifndef PALM_2 |
|
9538 SOAP_FMAC1 |
|
9539 int |
|
9540 SOAP_FMAC2 |
|
9541 soap_outliteral(struct soap *soap, const char *tag, char *const*p) |
|
9542 { int i; |
|
9543 const char *t = NULL; |
|
9544 if (tag && *tag != '-') |
|
9545 { if (soap->local_namespaces && (t = strchr(tag, ':'))) |
|
9546 { strncpy(soap->tmpbuf, tag, t-tag); |
|
9547 soap->tmpbuf[t-tag] = '\0'; |
|
9548 for (i = 0; soap->local_namespaces[i].id; i++) |
|
9549 if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id)) |
|
9550 break; |
|
9551 t++; |
|
9552 sprintf(soap->tmpbuf, "<%s xmlns=\"%s\">", t, soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS); |
|
9553 } |
|
9554 else |
|
9555 { t = tag; |
|
9556 sprintf(soap->tmpbuf, "<%s>", tag); |
|
9557 } |
|
9558 if (soap_send(soap, soap->tmpbuf)) |
|
9559 return soap->error; |
|
9560 } |
|
9561 if (p && *p) |
|
9562 { if (soap_send(soap, *p)) |
|
9563 return soap->error; |
|
9564 } |
|
9565 if (t) |
|
9566 { sprintf(soap->tmpbuf, "</%s>", t); |
|
9567 return soap_send(soap, soap->tmpbuf); |
|
9568 } |
|
9569 return SOAP_OK; |
|
9570 } |
|
9571 #endif |
|
9572 |
|
9573 /******************************************************************************/ |
|
9574 #ifndef PALM_2 |
|
9575 SOAP_FMAC1 |
|
9576 char ** |
|
9577 SOAP_FMAC2 |
|
9578 soap_inliteral(struct soap *soap, const char *tag, char **p) |
|
9579 { if (soap_element_begin_in(soap, tag, 1)) |
|
9580 { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT) |
|
9581 return NULL; |
|
9582 soap->error = SOAP_OK; |
|
9583 } |
|
9584 if (!p) |
|
9585 if (!(p = (char**)soap_malloc(soap, sizeof(char*)))) |
|
9586 return NULL; |
|
9587 if (soap->null) |
|
9588 *p = NULL; |
|
9589 else |
|
9590 *p = soap_string_in(soap, 0, -1, -1); |
|
9591 if (soap->body && soap_element_end_in(soap, tag)) |
|
9592 return NULL; |
|
9593 return p; |
|
9594 } |
|
9595 #endif |
|
9596 |
|
9597 /******************************************************************************/ |
|
9598 #ifndef WITH_LEANER |
|
9599 #ifndef PALM_2 |
|
9600 SOAP_FMAC1 |
|
9601 int |
|
9602 SOAP_FMAC2 |
|
9603 soap_outwliteral(struct soap *soap, const char *tag, wchar_t *const*p) |
|
9604 { int i; |
|
9605 const char *t = NULL; |
|
9606 wchar_t c; |
|
9607 const wchar_t *s; |
|
9608 if (tag && *tag != '-') |
|
9609 { if (soap->local_namespaces && (t = strchr(tag, ':'))) |
|
9610 { strncpy(soap->tmpbuf, tag, t-tag); |
|
9611 soap->tmpbuf[t-tag] = '\0'; |
|
9612 for (i = 0; soap->local_namespaces[i].id; i++) |
|
9613 if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id)) |
|
9614 break; |
|
9615 t++; |
|
9616 sprintf(soap->tmpbuf, "<%s xmlns=\"%s\">", t, soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS); |
|
9617 } |
|
9618 else |
|
9619 { t = tag; |
|
9620 sprintf(soap->tmpbuf, "<%s>", tag); |
|
9621 } |
|
9622 if (soap_send(soap, soap->tmpbuf)) |
|
9623 return soap->error; |
|
9624 } |
|
9625 if (p) |
|
9626 { s = *p; |
|
9627 while ((c = *s++)) |
|
9628 if (soap_pututf8(soap, (unsigned char)c)) |
|
9629 return soap->error; |
|
9630 } |
|
9631 if (t) |
|
9632 { sprintf(soap->tmpbuf, "</%s>", t); |
|
9633 return soap_send(soap, soap->tmpbuf); |
|
9634 } |
|
9635 return SOAP_OK; |
|
9636 } |
|
9637 #endif |
|
9638 #endif |
|
9639 |
|
9640 /******************************************************************************/ |
|
9641 #ifndef WITH_LEANER |
|
9642 #ifndef PALM_2 |
|
9643 SOAP_FMAC1 |
|
9644 wchar_t ** |
|
9645 SOAP_FMAC2 |
|
9646 soap_inwliteral(struct soap *soap, const char *tag, wchar_t **p) |
|
9647 { if (soap_element_begin_in(soap, tag, 1)) |
|
9648 { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT) |
|
9649 return NULL; |
|
9650 soap->error = SOAP_OK; |
|
9651 } |
|
9652 if (!p) |
|
9653 if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*)))) |
|
9654 return NULL; |
|
9655 if (soap->null) |
|
9656 *p = NULL; |
|
9657 else |
|
9658 *p = soap_wstring_in(soap, 0, -1, -1); |
|
9659 if (soap->body && soap_element_end_in(soap, tag)) |
|
9660 return NULL; |
|
9661 return p; |
|
9662 } |
|
9663 #endif |
|
9664 #endif |
|
9665 |
|
9666 /******************************************************************************/ |
|
9667 #ifndef PALM_2 |
|
9668 SOAP_FMAC1 |
|
9669 const char * |
|
9670 SOAP_FMAC2 |
|
9671 soap_token(struct soap *soap) |
|
9672 { register size_t i; |
|
9673 register soap_wchar c = 0; |
|
9674 register char *s = soap->tmpbuf; |
|
9675 if (!soap->body) |
|
9676 return SOAP_STR_EOS; |
|
9677 do c = soap_get(soap); |
|
9678 while (soap_blank(c)); |
|
9679 for (i = 0; i < sizeof(soap->tmpbuf) - 1; i++) |
|
9680 { if (c == SOAP_TT || (int)c == EOF || soap_blank(c)) |
|
9681 break; |
|
9682 *s++ = (char)c; |
|
9683 c = soap_get(soap); |
|
9684 } |
|
9685 if ((int)c == EOF || c == SOAP_TT) |
|
9686 soap_unget(soap, c); |
|
9687 *s = '\0'; |
|
9688 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element content value='%s'\n", soap->tmpbuf)); |
|
9689 return soap->tmpbuf; /* return non-null pointer */ |
|
9690 } |
|
9691 #endif |
|
9692 |
|
9693 /******************************************************************************/ |
|
9694 #ifndef PALM_2 |
|
9695 SOAP_FMAC1 |
|
9696 const char * |
|
9697 SOAP_FMAC2 |
|
9698 soap_value(struct soap *soap) |
|
9699 { register size_t i; |
|
9700 register soap_wchar c = 0; |
|
9701 register char *s = soap->tmpbuf; |
|
9702 if (!soap->body) |
|
9703 return SOAP_STR_EOS; |
|
9704 do c = soap_get(soap); |
|
9705 while (soap_blank(c)); |
|
9706 for (i = 0; i < sizeof(soap->tmpbuf) - 1; i++) |
|
9707 { if (c == SOAP_TT || (int)c == EOF) |
|
9708 break; |
|
9709 *s++ = (char)c; |
|
9710 c = soap_get(soap); |
|
9711 } |
|
9712 for (s--; i > 0; i--, s--) |
|
9713 if (!soap_blank(*s)) |
|
9714 break; |
|
9715 s[1] = '\0'; |
|
9716 if ((int)c == EOF || c == SOAP_TT) |
|
9717 soap_unget(soap, c); |
|
9718 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element content value='%s'\n", soap->tmpbuf)); |
|
9719 #ifdef WITH_DOM |
|
9720 if ((soap->mode & SOAP_XML_DOM) && soap->dom) |
|
9721 soap->dom->data = soap_strdup(soap, soap->tmpbuf); |
|
9722 #endif |
|
9723 return soap->tmpbuf; /* return non-null pointer */ |
|
9724 } |
|
9725 #endif |
|
9726 |
|
9727 /******************************************************************************/ |
|
9728 #if !defined(WITH_LEANER) || !defined(WITH_NOHTTP) |
|
9729 #ifndef PALM_2 |
|
9730 SOAP_FMAC1 |
|
9731 int |
|
9732 SOAP_FMAC2 |
|
9733 soap_getline(struct soap *soap, char *s, int len) |
|
9734 { int i = len; |
|
9735 soap_wchar c = 0; |
|
9736 for (;;) |
|
9737 { while (--i > 0) |
|
9738 { c = soap_getchar(soap); |
|
9739 if (c == '\r' || c == '\n') |
|
9740 break; |
|
9741 if ((int)c == EOF) |
|
9742 return soap->error = SOAP_EOF; |
|
9743 *s++ = (char)c; |
|
9744 } |
|
9745 if (c != '\n') |
|
9746 c = soap_getchar(soap); /* got \r, now get \n */ |
|
9747 if (c == '\n') |
|
9748 { *s = '\0'; |
|
9749 if (i+1 == len) /* empty line: end of HTTP/MIME header */ |
|
9750 break; |
|
9751 c = soap_unget(soap, soap_getchar(soap)); |
|
9752 if (c != ' ' && c != '\t') /* HTTP line continuation? */ |
|
9753 break; |
|
9754 } |
|
9755 else if ((int)c == EOF) |
|
9756 return soap->error = SOAP_EOF; |
|
9757 } |
|
9758 return SOAP_OK; |
|
9759 } |
|
9760 #endif |
|
9761 #endif |
|
9762 |
|
9763 /******************************************************************************/ |
|
9764 #ifndef PALM_1 |
|
9765 static size_t |
|
9766 soap_count_attachments(struct soap *soap) |
|
9767 { |
|
9768 #ifndef WITH_LEANER |
|
9769 register struct soap_multipart *content; |
|
9770 register size_t count = soap->count; |
|
9771 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the message size with attachments, current count=%lu\n", (unsigned long)count)); |
|
9772 if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) |
|
9773 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of DIME attachments\n")); |
|
9774 for (content = soap->dime.first; content; content = content->next) |
|
9775 { count += 12 + ((content->size+3)&(~3)); |
|
9776 if (content->id) |
|
9777 count += ((strlen(content->id)+3)&(~3)); |
|
9778 if (content->type) |
|
9779 count += ((strlen(content->type)+3)&(~3)); |
|
9780 if (content->options) |
|
9781 count += ((((unsigned char)content->options[2] << 8) | ((unsigned char)content->options[3]))+7)&(~3); |
|
9782 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of DIME attachment content is %lu bytes\n", (unsigned long)content->size)); |
|
9783 } |
|
9784 } |
|
9785 if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary) |
|
9786 { register size_t n = strlen(soap->mime.boundary); |
|
9787 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of MIME attachments\n")); |
|
9788 for (content = soap->mime.first; content; content = content->next) |
|
9789 { register const char *s; |
|
9790 /* count \r\n--boundary\r\n */ |
|
9791 count += 6 + n; |
|
9792 /* count Content-Type: ...\r\n */ |
|
9793 if (content->type) |
|
9794 count += 16 + strlen(content->type); |
|
9795 /* count Content-Transfer-Encoding: ...\r\n */ |
|
9796 s = soap_str_code(mime_codes, content->encoding); |
|
9797 if (s) |
|
9798 count += 29 + strlen(s); |
|
9799 /* count Content-ID: ...\r\n */ |
|
9800 if (content->id) |
|
9801 count += 14 + strlen(content->id); |
|
9802 /* count Content-Location: ...\r\n */ |
|
9803 if (content->location) |
|
9804 count += 20 + strlen(content->location); |
|
9805 /* count Content-Description: ...\r\n */ |
|
9806 if (content->description) |
|
9807 count += 23 + strlen(content->location); |
|
9808 /* count \r\n...content */ |
|
9809 count += 2 + content->size; |
|
9810 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of MIME attachment content is %lu bytes\n", (unsigned long)content->size)); |
|
9811 } |
|
9812 /* count \r\n--boundary-- */ |
|
9813 count += 6 + n; |
|
9814 } |
|
9815 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New count is %lu bytes\n", (unsigned long)count)); |
|
9816 return count; |
|
9817 #else |
|
9818 return soap->count; |
|
9819 #endif |
|
9820 } |
|
9821 #endif |
|
9822 |
|
9823 /******************************************************************************/ |
|
9824 #ifndef WITH_LEANER |
|
9825 #ifndef PALM_1 |
|
9826 static int |
|
9827 soap_putdimefield(struct soap *soap, const char *s, size_t n) |
|
9828 { if (soap_send_raw(soap, s, n)) |
|
9829 return soap->error; |
|
9830 return soap_send_raw(soap, SOAP_STR_PADDING, -(long)n&3); |
|
9831 } |
|
9832 #endif |
|
9833 #endif |
|
9834 |
|
9835 /******************************************************************************/ |
|
9836 #ifndef WITH_LEANER |
|
9837 #ifndef PALM_1 |
|
9838 SOAP_FMAC1 |
|
9839 char * |
|
9840 SOAP_FMAC2 |
|
9841 soap_dime_option(struct soap *soap, unsigned short optype, const char *option) |
|
9842 { size_t n; |
|
9843 char *s = NULL; |
|
9844 if (option) |
|
9845 { n = strlen(option); |
|
9846 s = (char*)soap_malloc(soap, n + 5); |
|
9847 if (s) |
|
9848 { s[0] = optype >> 8; |
|
9849 s[1] = optype & 0xFF; |
|
9850 s[2] = n >> 8; |
|
9851 s[3] = n & 0xFF; |
|
9852 strcpy(s + 4, option); |
|
9853 } |
|
9854 } |
|
9855 return s; |
|
9856 } |
|
9857 #endif |
|
9858 #endif |
|
9859 |
|
9860 /******************************************************************************/ |
|
9861 #ifndef WITH_LEANER |
|
9862 #ifndef PALM_1 |
|
9863 SOAP_FMAC1 |
|
9864 int |
|
9865 SOAP_FMAC2 |
|
9866 soap_putdimehdr(struct soap *soap) |
|
9867 { unsigned char tmp[12]; |
|
9868 size_t optlen = 0, idlen = 0, typelen = 0; |
|
9869 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Put DIME header id='%s'\n", soap->dime.id?soap->dime.id:"")); |
|
9870 if (soap->dime.options) |
|
9871 optlen = (((unsigned char)soap->dime.options[2] << 8) | ((unsigned char)soap->dime.options[3])) + 4; |
|
9872 if (soap->dime.id) |
|
9873 idlen = strlen(soap->dime.id); |
|
9874 if (soap->dime.type) |
|
9875 typelen = strlen(soap->dime.type); |
|
9876 tmp[0] = SOAP_DIME_VERSION | (soap->dime.flags & 0x7); |
|
9877 tmp[1] = soap->dime.flags & 0xF0; |
|
9878 tmp[2] = optlen >> 8; |
|
9879 tmp[3] = optlen & 0xFF; |
|
9880 tmp[4] = idlen >> 8; |
|
9881 tmp[5] = idlen & 0xFF; |
|
9882 tmp[6] = typelen >> 8; |
|
9883 tmp[7] = typelen & 0xFF; |
|
9884 tmp[8] = soap->dime.size >> 24; |
|
9885 tmp[9] = (soap->dime.size >> 16) & 0xFF; |
|
9886 tmp[10] = (soap->dime.size >> 8) & 0xFF; |
|
9887 tmp[11] = soap->dime.size & 0xFF; |
|
9888 if (soap_send_raw(soap, (char*)tmp, 12) |
|
9889 || soap_putdimefield(soap, soap->dime.options, optlen) |
|
9890 || soap_putdimefield(soap, soap->dime.id, idlen) |
|
9891 || soap_putdimefield(soap, soap->dime.type, typelen)) |
|
9892 return soap->error; |
|
9893 return SOAP_OK; |
|
9894 } |
|
9895 #endif |
|
9896 #endif |
|
9897 |
|
9898 /******************************************************************************/ |
|
9899 #ifndef WITH_LEANER |
|
9900 #ifndef PALM_1 |
|
9901 SOAP_FMAC1 |
|
9902 int |
|
9903 SOAP_FMAC2 |
|
9904 soap_putdime(struct soap *soap) |
|
9905 { struct soap_multipart *content; |
|
9906 if (!(soap->mode & SOAP_ENC_DIME)) |
|
9907 return SOAP_OK; |
|
9908 for (content = soap->dime.first; content; content = content->next) |
|
9909 { void *handle; |
|
9910 soap->dime.size = content->size; |
|
9911 soap->dime.id = content->id; |
|
9912 soap->dime.type = content->type; |
|
9913 soap->dime.options = content->options; |
|
9914 soap->dime.flags = SOAP_DIME_VERSION | SOAP_DIME_MEDIA; |
|
9915 if (soap->fdimereadopen && ((handle = soap->fdimereadopen(soap, (void*)content->ptr, content->id, content->type, content->options)) || soap->error)) |
|
9916 { size_t size = content->size; |
|
9917 if (!handle) |
|
9918 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadopen failed\n")); |
|
9919 return soap->error; |
|
9920 } |
|
9921 if (!content->size && ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE)) |
|
9922 { size_t chunksize = sizeof(soap->tmpbuf); |
|
9923 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming DIME\n")); |
|
9924 do |
|
9925 { size = soap->fdimeread(soap, handle, soap->tmpbuf, chunksize); |
|
9926 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread returned %lu bytes\n", (unsigned long)size)); |
|
9927 if (size < chunksize) |
|
9928 { soap->dime.flags &= ~SOAP_DIME_CF; |
|
9929 if (!content->next) |
|
9930 soap->dime.flags |= SOAP_DIME_ME; |
|
9931 } |
|
9932 else |
|
9933 soap->dime.flags |= SOAP_DIME_CF; |
|
9934 soap->dime.size = size; |
|
9935 if (soap_putdimehdr(soap) |
|
9936 || soap_putdimefield(soap, soap->tmpbuf, size)) |
|
9937 break; |
|
9938 if (soap->dime.id) |
|
9939 { soap->dime.flags &= ~(SOAP_DIME_MB | SOAP_DIME_MEDIA); |
|
9940 soap->dime.id = NULL; |
|
9941 soap->dime.type = NULL; |
|
9942 soap->dime.options = NULL; |
|
9943 } |
|
9944 } while (size >= chunksize); |
|
9945 } |
|
9946 else |
|
9947 { if (!content->next) |
|
9948 soap->dime.flags |= SOAP_DIME_ME; |
|
9949 if (soap_putdimehdr(soap)) |
|
9950 return soap->error; |
|
9951 do |
|
9952 { size_t bufsize; |
|
9953 if (size < sizeof(soap->tmpbuf)) |
|
9954 bufsize = size; |
|
9955 else |
|
9956 bufsize = sizeof(soap->tmpbuf); |
|
9957 if (!(bufsize = soap->fdimeread(soap, handle, soap->tmpbuf, bufsize))) |
|
9958 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)soap->dime.size)); |
|
9959 soap->error = SOAP_EOF; |
|
9960 break; |
|
9961 } |
|
9962 if (soap_send_raw(soap, soap->tmpbuf, bufsize)) |
|
9963 break; |
|
9964 size -= bufsize; |
|
9965 } while (size); |
|
9966 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n")); |
|
9967 soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3); |
|
9968 } |
|
9969 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n")); |
|
9970 if (soap->fdimereadclose) |
|
9971 soap->fdimereadclose(soap, handle); |
|
9972 } |
|
9973 else |
|
9974 { if (!content->next) |
|
9975 soap->dime.flags |= SOAP_DIME_ME; |
|
9976 if (soap_putdimehdr(soap) |
|
9977 || soap_putdimefield(soap, (char*)content->ptr, content->size)) |
|
9978 return soap->error; |
|
9979 } |
|
9980 } |
|
9981 return SOAP_OK; |
|
9982 } |
|
9983 #endif |
|
9984 #endif |
|
9985 |
|
9986 /******************************************************************************/ |
|
9987 #ifndef WITH_LEANER |
|
9988 #ifndef PALM_1 |
|
9989 static char * |
|
9990 soap_getdimefield(struct soap *soap, size_t n) |
|
9991 { register soap_wchar c; |
|
9992 register int i; |
|
9993 register char *s; |
|
9994 char *p = NULL; |
|
9995 if (n) |
|
9996 { p = (char*)soap_malloc(soap, n + 1); |
|
9997 if (p) |
|
9998 { s = p; |
|
9999 for (i = n; i > 0; i--) |
|
10000 { if ((int)(c = soap_get1(soap)) == EOF) |
|
10001 { soap->error = SOAP_EOF; |
|
10002 return NULL; |
|
10003 } |
|
10004 *s++ = (char)c; |
|
10005 } |
|
10006 *s = '\0'; |
|
10007 if ((soap->error = soap_move(soap, -(long)n&3))) |
|
10008 return NULL; |
|
10009 } |
|
10010 else |
|
10011 soap->error = SOAP_EOM; |
|
10012 } |
|
10013 return p; |
|
10014 } |
|
10015 #endif |
|
10016 #endif |
|
10017 |
|
10018 /******************************************************************************/ |
|
10019 #ifndef WITH_LEANER |
|
10020 #ifndef PALM_1 |
|
10021 SOAP_FMAC1 |
|
10022 int |
|
10023 SOAP_FMAC2 |
|
10024 soap_getdimehdr(struct soap *soap) |
|
10025 { register soap_wchar c; |
|
10026 register char *s; |
|
10027 register int i; |
|
10028 unsigned char tmp[12]; |
|
10029 size_t optlen, idlen, typelen; |
|
10030 if (!(soap->mode & SOAP_ENC_DIME)) |
|
10031 return soap->error = SOAP_DIME_END; |
|
10032 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME header\n")); |
|
10033 if (soap->dime.buflen || soap->dime.chunksize) |
|
10034 { if (soap_move(soap, (long)(soap->dime.size - soap_tell(soap)))) |
|
10035 return soap->error = SOAP_EOF; |
|
10036 soap_unget(soap, soap_getchar(soap)); /* skip padding and get hdr */ |
|
10037 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... From chunked\n")); |
|
10038 return SOAP_OK; |
|
10039 } |
|
10040 s = (char*)tmp; |
|
10041 for (i = 12; i > 0; i--) |
|
10042 { if ((int)(c = soap_getchar(soap)) == EOF) |
|
10043 return soap->error = SOAP_EOF; |
|
10044 *s++ = (char)c; |
|
10045 } |
|
10046 if ((tmp[0] & 0xF8) != SOAP_DIME_VERSION) |
|
10047 return soap->error = SOAP_DIME_MISMATCH; |
|
10048 soap->dime.flags = (tmp[0] & 0x7) | (tmp[1] & 0xF0); |
|
10049 optlen = (tmp[2] << 8) | tmp[3]; |
|
10050 idlen = (tmp[4] << 8) | tmp[5]; |
|
10051 typelen = (tmp[6] << 8) | tmp[7]; |
|
10052 soap->dime.size = (tmp[8] << 24) | (tmp[9] << 16) | (tmp[10] << 8) | tmp[11]; |
|
10053 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME size=%lu flags=0x%X\n", (unsigned long)soap->dime.size, soap->dime.flags)); |
|
10054 if (!(soap->dime.options = soap_getdimefield(soap, optlen)) && soap->error) |
|
10055 return soap->error; |
|
10056 if (!(soap->dime.id = soap_getdimefield(soap, idlen)) && soap->error) |
|
10057 return soap->error; |
|
10058 if (!(soap->dime.type = soap_getdimefield(soap, typelen)) && soap->error) |
|
10059 return soap->error; |
|
10060 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME id=%s, type=%s, options=%s\n", soap->dime.id?soap->dime.id:"", soap->dime.type?soap->dime.type:"", soap->dime.options?soap->dime.options+4:"")); |
|
10061 if (soap->dime.flags & SOAP_DIME_ME) |
|
10062 soap->mode &= ~SOAP_ENC_DIME; |
|
10063 return SOAP_OK; |
|
10064 } |
|
10065 #endif |
|
10066 #endif |
|
10067 |
|
10068 /******************************************************************************/ |
|
10069 #ifndef WITH_LEANER |
|
10070 #ifndef PALM_1 |
|
10071 SOAP_FMAC1 |
|
10072 int |
|
10073 SOAP_FMAC2 |
|
10074 soap_getdime(struct soap *soap) |
|
10075 { while (soap->dime.flags & SOAP_DIME_CF) |
|
10076 { if (soap_getdimehdr(soap)) |
|
10077 return soap->error; |
|
10078 if (soap_move(soap, soap->dime.size)) |
|
10079 return soap->error = SOAP_EOF; |
|
10080 } |
|
10081 if (soap_move(soap, ((soap->dime.size+3)&(~3))-soap_tell(soap))) |
|
10082 return soap->error = SOAP_EOF; |
|
10083 for (;;) |
|
10084 { register struct soap_multipart *content; |
|
10085 if (soap_getdimehdr(soap)) |
|
10086 break; |
|
10087 if (soap->fdimewriteopen && ((soap->dime.ptr = (char*)soap->fdimewriteopen(soap, soap->dime.id, soap->dime.type, soap->dime.options)) || soap->error)) |
|
10088 { const char *id, *type, *options; |
|
10089 size_t size, n; |
|
10090 if (!soap->dime.ptr) |
|
10091 return soap->error; |
|
10092 id = soap->dime.id; |
|
10093 type = soap->dime.type; |
|
10094 options = soap->dime.options; |
|
10095 for (;;) |
|
10096 { size = soap->dime.size; |
|
10097 for (;;) |
|
10098 { n = soap->buflen - soap->bufidx; |
|
10099 if (size < n) |
|
10100 n = size; |
|
10101 if ((soap->error = soap->fdimewrite(soap, (void*)soap->dime.ptr, soap->buf + soap->bufidx, n))) |
|
10102 break; |
|
10103 size -= n; |
|
10104 if (!size) |
|
10105 { soap->bufidx += n; |
|
10106 break; |
|
10107 } |
|
10108 if (soap_recv(soap)) |
|
10109 { soap->error = SOAP_EOF; |
|
10110 goto end; |
|
10111 } |
|
10112 } |
|
10113 if (soap_move(soap, -(long)soap->dime.size&3)) |
|
10114 { soap->error = SOAP_EOF; |
|
10115 break; |
|
10116 } |
|
10117 if (!(soap->dime.flags & SOAP_DIME_CF)) |
|
10118 break; |
|
10119 if (soap_getdimehdr(soap)) |
|
10120 break; |
|
10121 } |
|
10122 end: |
|
10123 if (soap->fdimewriteclose) |
|
10124 soap->fdimewriteclose(soap, (void*)soap->dime.ptr); |
|
10125 soap->dime.size = 0; |
|
10126 soap->dime.id = id; |
|
10127 soap->dime.type = type; |
|
10128 soap->dime.options = options; |
|
10129 } |
|
10130 else if (soap->dime.flags & SOAP_DIME_CF) |
|
10131 { const char *id, *type, *options; |
|
10132 register soap_wchar c; |
|
10133 register char *s; |
|
10134 register int i; |
|
10135 id = soap->dime.id; |
|
10136 type = soap->dime.type; |
|
10137 options = soap->dime.options; |
|
10138 if (soap_new_block(soap)) |
|
10139 return SOAP_EOM; |
|
10140 for (;;) |
|
10141 { s = (char*)soap_push_block(soap, soap->dime.size); |
|
10142 if (!s) |
|
10143 return soap->error = SOAP_EOM; |
|
10144 for (i = soap->dime.size; i > 0; i--) |
|
10145 { if ((int)(c = soap_get1(soap)) == EOF) |
|
10146 return soap->error = SOAP_EOF; |
|
10147 *s++ = (char)c; |
|
10148 } |
|
10149 if (soap_move(soap, -(long)soap->dime.size&3)) |
|
10150 return soap->error = SOAP_EOF; |
|
10151 if (!(soap->dime.flags & SOAP_DIME_CF)) |
|
10152 break; |
|
10153 if (soap_getdimehdr(soap)) |
|
10154 return soap->error; |
|
10155 } |
|
10156 soap->dime.size = soap->blist->size++; /* allocate one more for '\0' */ |
|
10157 if (!(soap->dime.ptr = soap_save_block(soap, NULL, 0))) |
|
10158 return soap->error; |
|
10159 soap->dime.ptr[soap->dime.size] = '\0'; /* force 0-terminated */ |
|
10160 soap->dime.id = id; |
|
10161 soap->dime.type = type; |
|
10162 soap->dime.options = options; |
|
10163 } |
|
10164 else |
|
10165 soap->dime.ptr = soap_getdimefield(soap, soap->dime.size); |
|
10166 content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, soap->dime.ptr, soap->dime.size); |
|
10167 if (!content) |
|
10168 return soap->error = SOAP_EOM; |
|
10169 content->id = soap->dime.id; |
|
10170 content->type = soap->dime.type; |
|
10171 content->options = soap->dime.options; |
|
10172 soap_resolve_attachment(soap, content); |
|
10173 if (soap->error) |
|
10174 return soap->error; |
|
10175 } |
|
10176 if (soap->error != SOAP_DIME_END) |
|
10177 return soap->error; |
|
10178 return soap->error = SOAP_OK; |
|
10179 } |
|
10180 #endif |
|
10181 #endif |
|
10182 |
|
10183 /******************************************************************************/ |
|
10184 #ifndef WITH_LEANER |
|
10185 #ifndef PALM_1 |
|
10186 SOAP_FMAC1 |
|
10187 int |
|
10188 SOAP_FMAC2 |
|
10189 soap_getmimehdr(struct soap *soap) |
|
10190 { struct soap_multipart *content; |
|
10191 do |
|
10192 { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) |
|
10193 return soap->error; |
|
10194 } |
|
10195 while (!*soap->msgbuf); |
|
10196 if (soap->msgbuf[0] == '-' && soap->msgbuf[1] == '-') |
|
10197 { char *s = soap->msgbuf + strlen(soap->msgbuf) - 1; |
|
10198 /* remove white space */ |
|
10199 while (soap_blank(*s)) |
|
10200 s--; |
|
10201 s[1] = '\0'; |
|
10202 if (soap->mime.boundary) |
|
10203 { if (strcmp(soap->msgbuf + 2, soap->mime.boundary)) |
|
10204 return soap->error = SOAP_MIME_ERROR; |
|
10205 } |
|
10206 else |
|
10207 soap->mime.boundary = soap_strdup(soap, soap->msgbuf + 2); |
|
10208 if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) |
|
10209 return soap->error; |
|
10210 } |
|
10211 if (soap_set_mime_attachment(soap, NULL, 0, SOAP_MIME_NONE, NULL, NULL, NULL, NULL)) |
|
10212 return soap->error = SOAP_EOM; |
|
10213 content = soap->mime.last; |
|
10214 for (;;) |
|
10215 { register char *key = soap->msgbuf; |
|
10216 register char *val; |
|
10217 if (!*key) |
|
10218 break; |
|
10219 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "MIME header: %s\n", key)); |
|
10220 val = strchr(soap->msgbuf, ':'); |
|
10221 if (val) |
|
10222 { *val = '\0'; |
|
10223 do val++; |
|
10224 while (*val && *val <= 32); |
|
10225 if (!soap_tag_cmp(key, "Content-ID")) |
|
10226 content->id = soap_strdup(soap, val); |
|
10227 else if (!soap_tag_cmp(key, "Content-Location")) |
|
10228 content->location = soap_strdup(soap, val); |
|
10229 else if (!soap_tag_cmp(key, "Content-Disposition")) |
|
10230 content->id = soap_strdup(soap, soap_get_header_attribute(soap, val, "name")); |
|
10231 else if (!soap_tag_cmp(key, "Content-Type")) |
|
10232 content->type = soap_strdup(soap, val); |
|
10233 else if (!soap_tag_cmp(key, "Content-Description")) |
|
10234 content->description = soap_strdup(soap, val); |
|
10235 else if (!soap_tag_cmp(key, "Content-Transfer-Encoding")) |
|
10236 content->encoding = (enum soap_mime_encoding)soap_int_code(mime_codes, val, (long)SOAP_MIME_NONE); |
|
10237 } |
|
10238 if (soap_getline(soap, key, sizeof(soap->msgbuf))) |
|
10239 return soap->error; |
|
10240 } |
|
10241 return SOAP_OK; |
|
10242 } |
|
10243 #endif |
|
10244 #endif |
|
10245 |
|
10246 /******************************************************************************/ |
|
10247 #ifndef WITH_LEANER |
|
10248 #ifndef PALM_1 |
|
10249 SOAP_FMAC1 |
|
10250 int |
|
10251 SOAP_FMAC2 |
|
10252 soap_getmime(struct soap *soap) |
|
10253 { register soap_wchar c = 0; |
|
10254 if (!soap->mime.last) |
|
10255 return SOAP_OK; |
|
10256 for (;;) |
|
10257 { register size_t i, m = 0; |
|
10258 register char *s, *t = NULL; |
|
10259 struct soap_multipart *content = soap->mime.last; |
|
10260 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Parsing MIME content id=%s type=%s\n", content->id?content->id:"", content->type?content->type:"")); |
|
10261 if (soap_new_block(soap)) |
|
10262 return soap->error = SOAP_EOM; |
|
10263 for (;;) |
|
10264 { register short flag = 0; |
|
10265 if (!(s = (char*)soap_push_block(soap, SOAP_BLKLEN))) |
|
10266 return soap->error = SOAP_EOM; |
|
10267 for (i = 0; i < SOAP_BLKLEN; i++) |
|
10268 { if (m > 0) |
|
10269 { flag = (*t == '\r'); |
|
10270 *s++ = *t++; |
|
10271 m--; |
|
10272 } |
|
10273 else |
|
10274 { if (!flag) |
|
10275 { c = soap_get1(soap); |
|
10276 if ((int)c == EOF) |
|
10277 return soap->error = SOAP_EOF; |
|
10278 } |
|
10279 if (flag || c == '\r') |
|
10280 { t = soap->tmpbuf; |
|
10281 memset(t, 0, sizeof(soap->tmpbuf)); |
|
10282 strcpy(t, "\n--"); |
|
10283 if (soap->mime.boundary) |
|
10284 strncat(t, soap->mime.boundary, sizeof(soap->tmpbuf)-4); |
|
10285 do c = soap_getchar(soap); |
|
10286 while (c == *t++); |
|
10287 if ((int)c == EOF) |
|
10288 return soap->error = SOAP_EOF; |
|
10289 if (!*--t) |
|
10290 goto end; |
|
10291 *t = (char)c; |
|
10292 m = t - soap->tmpbuf + 1; |
|
10293 t = soap->tmpbuf; |
|
10294 c = '\r'; |
|
10295 } |
|
10296 *s++ = (char)c; |
|
10297 } |
|
10298 } |
|
10299 } |
|
10300 end: |
|
10301 *s = '\0'; /* force 0-terminated */ |
|
10302 content->size = soap_size_block(soap, i+1)-1; |
|
10303 content->ptr = soap_save_block(soap, NULL, 0); |
|
10304 soap_resolve_attachment(soap, content); |
|
10305 if (c == '-' && soap_getchar(soap) == '-') |
|
10306 break; |
|
10307 while (c != '\r' && (int)c != EOF && soap_blank(c)) |
|
10308 c = soap_getchar(soap); |
|
10309 if (c != '\r' || soap_getchar(soap) != '\n') |
|
10310 return soap->error = SOAP_MIME_ERROR; |
|
10311 if (soap_getmimehdr(soap)) |
|
10312 return soap->error; |
|
10313 } |
|
10314 /* |
|
10315 do c = soap_getchar(soap); |
|
10316 while ((int)c != EOF && c != '\r' && c != '\n'); |
|
10317 if ((int)c != '\r' || soap_getchar(soap) != '\n') |
|
10318 return soap->error = SOAP_MIME_ERROR; |
|
10319 */ |
|
10320 return SOAP_OK; |
|
10321 } |
|
10322 #endif |
|
10323 #endif |
|
10324 |
|
10325 /******************************************************************************/ |
|
10326 #ifndef WITH_LEANER |
|
10327 #ifndef PALM_1 |
|
10328 static int |
|
10329 soap_match_cid(const char *s, const char *t) |
|
10330 { register size_t n; |
|
10331 if (!s) |
|
10332 return 1; |
|
10333 if (!strcmp(s, t)) |
|
10334 return 0; |
|
10335 if (!strncmp(s, "cid:", 4)) |
|
10336 s += 4; |
|
10337 n = strlen(t); |
|
10338 if (*t == '<') |
|
10339 { t++; |
|
10340 n -= 2; |
|
10341 } |
|
10342 if (!strncmp(s, t, n) && !s[n]) |
|
10343 return 0; |
|
10344 return 1; |
|
10345 } |
|
10346 #endif |
|
10347 #endif |
|
10348 |
|
10349 /******************************************************************************/ |
|
10350 #ifndef WITH_LEANER |
|
10351 #ifndef PALM_1 |
|
10352 static void |
|
10353 soap_resolve_attachment(struct soap *soap, struct soap_multipart *content) |
|
10354 { if (content->id) |
|
10355 { register struct soap_xlist **xp = &soap->xlist; |
|
10356 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving attachment data for id=%s\n", content->id)); |
|
10357 while (*xp) |
|
10358 { register struct soap_xlist *xq = *xp; |
|
10359 if (!soap_match_cid(xq->id, content->id)) |
|
10360 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Found matching attachment %s for content id=%s\n", xq->id, content->id)); |
|
10361 *xp = xq->next; |
|
10362 *xq->ptr = (unsigned char*)content->ptr; |
|
10363 *xq->size = (int)content->size; |
|
10364 *xq->type = (char*)content->type; |
|
10365 if (content->options) |
|
10366 *xq->options = (char*)content->options; |
|
10367 else |
|
10368 *xq->options = (char*)content->description; |
|
10369 SOAP_FREE(soap, xq); |
|
10370 } |
|
10371 else |
|
10372 xp = &(*xp)->next; |
|
10373 } |
|
10374 } |
|
10375 } |
|
10376 #endif |
|
10377 #endif |
|
10378 |
|
10379 /******************************************************************************/ |
|
10380 #ifndef WITH_LEANER |
|
10381 #ifndef PALM_1 |
|
10382 SOAP_FMAC1 |
|
10383 int |
|
10384 SOAP_FMAC2 |
|
10385 soap_putmimehdr(struct soap *soap, struct soap_multipart *content) |
|
10386 { const char *s; |
|
10387 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "MIME attachment type=%s\n", content->type?content->type:"")); |
|
10388 if (soap_send3(soap, "\r\n--", soap->mime.boundary, "\r\n")) |
|
10389 return soap->error; |
|
10390 if (content->type && soap_send3(soap, "Content-Type: ", content->type, "\r\n")) |
|
10391 return soap->error; |
|
10392 s = soap_str_code(mime_codes, content->encoding); |
|
10393 if (s && soap_send3(soap, "Content-Transfer-Encoding: ", s, "\r\n")) |
|
10394 return soap->error; |
|
10395 if (content->id && soap_send3(soap, "Content-ID: ", content->id, "\r\n")) |
|
10396 return soap->error; |
|
10397 if (content->location && soap_send3(soap, "Content-Location: ", content->location, "\r\n")) |
|
10398 return soap->error; |
|
10399 if (content->description && soap_send3(soap, "Content-Description: ", content->description, "\r\n")) |
|
10400 return soap->error; |
|
10401 return soap_send_raw(soap, "\r\n", 2); |
|
10402 } |
|
10403 #endif |
|
10404 #endif |
|
10405 |
|
10406 /******************************************************************************/ |
|
10407 #ifndef WITH_LEANER |
|
10408 #ifndef PALM_1 |
|
10409 SOAP_FMAC1 |
|
10410 int |
|
10411 SOAP_FMAC2 |
|
10412 soap_putmime(struct soap *soap) |
|
10413 { struct soap_multipart *content; |
|
10414 if (!(soap->mode & SOAP_ENC_MIME) || !soap->mime.boundary) |
|
10415 return SOAP_OK; |
|
10416 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending MIME attachments\n")); |
|
10417 for (content = soap->mime.first; content; content = content->next) |
|
10418 if (soap_putmimehdr(soap, content) |
|
10419 || soap_send_raw(soap, content->ptr, content->size)) |
|
10420 return soap->error; |
|
10421 return soap_send3(soap, "\r\n--", soap->mime.boundary, "--"); |
|
10422 } |
|
10423 #endif |
|
10424 #endif |
|
10425 |
|
10426 /******************************************************************************/ |
|
10427 #ifndef WITH_LEANER |
|
10428 #ifndef PALM_1 |
|
10429 SOAP_FMAC1 |
|
10430 void |
|
10431 SOAP_FMAC2 |
|
10432 soap_set_dime(struct soap *soap) |
|
10433 { soap->omode |= SOAP_ENC_DIME; |
|
10434 soap->dime.first = NULL; |
|
10435 soap->dime.last = NULL; |
|
10436 } |
|
10437 #endif |
|
10438 #endif |
|
10439 |
|
10440 /******************************************************************************/ |
|
10441 #ifndef WITH_LEANER |
|
10442 #ifndef PALM_1 |
|
10443 SOAP_FMAC1 |
|
10444 void |
|
10445 SOAP_FMAC2 |
|
10446 soap_set_mime(struct soap *soap, const char *boundary, const char *start) |
|
10447 { soap->omode |= SOAP_ENC_MIME; |
|
10448 soap->mime.first = NULL; |
|
10449 soap->mime.last = NULL; |
|
10450 soap->mime.boundary = soap_strdup(soap, boundary); |
|
10451 soap->mime.start = soap_strdup(soap, start); |
|
10452 } |
|
10453 #endif |
|
10454 #endif |
|
10455 |
|
10456 /******************************************************************************/ |
|
10457 #ifndef WITH_LEANER |
|
10458 #ifndef PALM_1 |
|
10459 SOAP_FMAC1 |
|
10460 void |
|
10461 SOAP_FMAC2 |
|
10462 soap_clr_dime(struct soap *soap) |
|
10463 { soap->omode &= ~SOAP_ENC_DIME; |
|
10464 soap->dime.first = NULL; |
|
10465 soap->dime.last = NULL; |
|
10466 } |
|
10467 #endif |
|
10468 #endif |
|
10469 |
|
10470 /******************************************************************************/ |
|
10471 #ifndef WITH_LEANER |
|
10472 #ifndef PALM_1 |
|
10473 SOAP_FMAC1 |
|
10474 void |
|
10475 SOAP_FMAC2 |
|
10476 soap_clr_mime(struct soap *soap) |
|
10477 { soap->omode &= ~SOAP_ENC_MIME; |
|
10478 soap->mime.first = NULL; |
|
10479 soap->mime.last = NULL; |
|
10480 soap->mime.boundary = NULL; |
|
10481 soap->mime.start = NULL; |
|
10482 } |
|
10483 #endif |
|
10484 #endif |
|
10485 |
|
10486 /******************************************************************************/ |
|
10487 #ifndef WITH_LEANER |
|
10488 #ifndef PALM_1 |
|
10489 static struct soap_multipart* |
|
10490 soap_new_multipart(struct soap *soap, struct soap_multipart **first, struct soap_multipart **last, char *ptr, size_t size) |
|
10491 { struct soap_multipart *content; |
|
10492 content = (struct soap_multipart*)soap_malloc(soap, sizeof(struct soap_multipart)); |
|
10493 if (content) |
|
10494 { content->next = NULL; |
|
10495 content->ptr = ptr; |
|
10496 content->size = size; |
|
10497 content->id = NULL; |
|
10498 content->type = NULL; |
|
10499 content->options = NULL; |
|
10500 content->encoding = SOAP_MIME_NONE; |
|
10501 content->location = NULL; |
|
10502 content->description = NULL; |
|
10503 if (!*first) |
|
10504 *first = content; |
|
10505 if (*last) |
|
10506 (*last)->next = content; |
|
10507 *last = content; |
|
10508 } |
|
10509 return content; |
|
10510 } |
|
10511 #endif |
|
10512 #endif |
|
10513 |
|
10514 /******************************************************************************/ |
|
10515 #ifndef WITH_LEANER |
|
10516 #ifndef PALM_1 |
|
10517 SOAP_FMAC1 |
|
10518 int |
|
10519 SOAP_FMAC2 |
|
10520 soap_set_dime_attachment(struct soap *soap, char *ptr, size_t size, const char *type, const char *id, unsigned short optype, const char *option) |
|
10521 { struct soap_multipart *content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, ptr, size); |
|
10522 if (!content) |
|
10523 return SOAP_EOM; |
|
10524 content->id = soap_strdup(soap, id); |
|
10525 content->type = soap_strdup(soap, type); |
|
10526 content->options = soap_dime_option(soap, optype, option); |
|
10527 return SOAP_OK; |
|
10528 } |
|
10529 #endif |
|
10530 #endif |
|
10531 |
|
10532 /******************************************************************************/ |
|
10533 #ifndef WITH_LEANER |
|
10534 #ifndef PALM_1 |
|
10535 SOAP_FMAC1 |
|
10536 int |
|
10537 SOAP_FMAC2 |
|
10538 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) |
|
10539 { struct soap_multipart *content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, ptr, size); |
|
10540 if (!content) |
|
10541 return SOAP_EOM; |
|
10542 content->id = soap_strdup(soap, id); |
|
10543 content->type = soap_strdup(soap, type); |
|
10544 content->encoding = encoding; |
|
10545 content->location = soap_strdup(soap, location); |
|
10546 content->description = soap_strdup(soap, description); |
|
10547 return SOAP_OK; |
|
10548 } |
|
10549 #endif |
|
10550 #endif |
|
10551 |
|
10552 /******************************************************************************/ |
|
10553 #ifndef WITH_LEANER |
|
10554 #ifndef PALM_1 |
|
10555 SOAP_FMAC1 |
|
10556 struct soap_multipart* |
|
10557 SOAP_FMAC2 |
|
10558 soap_next_multipart(struct soap_multipart *content) |
|
10559 { if (content) |
|
10560 return content->next; |
|
10561 return NULL; |
|
10562 } |
|
10563 #endif |
|
10564 #endif |
|
10565 |
|
10566 /******************************************************************************/ |
|
10567 #ifndef WITH_LEANER |
|
10568 #ifndef PALM_1 |
|
10569 static void |
|
10570 soap_select_mime_boundary(struct soap *soap) |
|
10571 { while (!soap->mime.boundary || soap_valid_mime_boundary(soap)) |
|
10572 { register char *s = soap->mime.boundary; |
|
10573 register size_t n = 0; |
|
10574 if (s) |
|
10575 n = strlen(s); |
|
10576 if (n < 16) |
|
10577 { n = 72; |
|
10578 s = soap->mime.boundary = (char*)soap_malloc(soap, n + 1); |
|
10579 if (!s) |
|
10580 return; |
|
10581 } |
|
10582 strcpy(s, "<>"); |
|
10583 s += 2; |
|
10584 n -= 4; |
|
10585 while (n) |
|
10586 { *s++ = soap_base64o[soap_random & 0x3F]; |
|
10587 n--; |
|
10588 } |
|
10589 strcpy(s, "<>"); |
|
10590 } |
|
10591 if (!soap->mime.start) |
|
10592 soap->mime.start = "<SOAP-ENV:Envelope>"; |
|
10593 } |
|
10594 #endif |
|
10595 #endif |
|
10596 |
|
10597 /******************************************************************************/ |
|
10598 #ifndef WITH_LEANER |
|
10599 #ifndef PALM_1 |
|
10600 static int |
|
10601 soap_valid_mime_boundary(struct soap *soap) |
|
10602 { register struct soap_multipart *content; |
|
10603 register size_t k = strlen(soap->mime.boundary); |
|
10604 for (content = soap->mime.first; content; content = content->next) |
|
10605 { if (content->ptr && content->size >= k) |
|
10606 { register const char *p = (const char*)content->ptr; |
|
10607 register size_t i; |
|
10608 for (i = 0; i < content->size - k; i++, p++) |
|
10609 if (!strncmp(p, soap->mime.boundary, k)) |
|
10610 return SOAP_ERR; |
|
10611 } |
|
10612 } |
|
10613 return SOAP_OK; |
|
10614 } |
|
10615 #endif |
|
10616 #endif |
|
10617 |
|
10618 /******************************************************************************/ |
|
10619 |
|
10620 #ifdef WITH_COOKIES |
|
10621 /******************************************************************************/ |
|
10622 SOAP_FMAC1 |
|
10623 size_t |
|
10624 SOAP_FMAC2 |
|
10625 soap_encode_cookie(const char *s, char *t, size_t len) |
|
10626 { register int c; |
|
10627 register size_t n = len; |
|
10628 while ((c = *s++) && --n > 0) |
|
10629 { if (c > ' ' && c < 128 && !strchr("()<>@,;:\\\"/[]?={}", c)) |
|
10630 *t++ = c; |
|
10631 else if (n > 2) |
|
10632 { *t++ = '%'; |
|
10633 *t++ = (c >> 4) + (c > 159 ? '7' : '0'); |
|
10634 c &= 0xF; |
|
10635 *t++ = c + (c > 9 ? '7' : '0'); |
|
10636 n -= 2; |
|
10637 } |
|
10638 else |
|
10639 break; |
|
10640 } |
|
10641 *t = '\0'; |
|
10642 return len - n; |
|
10643 } |
|
10644 |
|
10645 /******************************************************************************/ |
|
10646 SOAP_FMAC1 |
|
10647 struct soap_cookie* |
|
10648 SOAP_FMAC2 |
|
10649 soap_cookie(struct soap *soap, const char *name, const char *domain, const char *path) |
|
10650 { struct soap_cookie *p; |
|
10651 size_t n; |
|
10652 if (!domain) |
|
10653 domain = soap->cookie_domain; |
|
10654 if (!path) |
|
10655 path = soap->cookie_path; |
|
10656 if (*path == '/') |
|
10657 path++; |
|
10658 n = strlen(path); |
|
10659 for (p = soap->cookies; p; p = p->next) |
|
10660 if (!strcmp(p->name, name) |
|
10661 && domain |
|
10662 && p->domain |
|
10663 && !strcmp(p->domain, domain) |
|
10664 && !strncmp(p->path, path, n)) |
|
10665 break; |
|
10666 return p; |
|
10667 } |
|
10668 |
|
10669 /******************************************************************************/ |
|
10670 SOAP_FMAC1 |
|
10671 struct soap_cookie* |
|
10672 SOAP_FMAC2 |
|
10673 soap_set_cookie(struct soap *soap, const char *name, const char *value, const char *domain, const char *path) |
|
10674 { struct soap_cookie **p, *q; |
|
10675 int n; |
|
10676 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set cookie: %s=%s domain=%s path=%s\n", name, value?value:"", domain?domain:"", path?path:"")); |
|
10677 if (!domain) |
|
10678 domain = soap->cookie_domain; |
|
10679 if (!path) |
|
10680 path = soap->cookie_path; |
|
10681 if (!path) |
|
10682 { soap_set_receiver_error(soap, "Cookie path not set", NULL, SOAP_HTTP_ERROR); |
|
10683 return NULL; |
|
10684 } |
|
10685 if (*path == '/') |
|
10686 path++; |
|
10687 q = soap_cookie(soap, name, domain, path); |
|
10688 if (!q) |
|
10689 { if ((q = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie)))) |
|
10690 { if ((q->name = (char*)SOAP_MALLOC(soap, strlen(name)+1))) |
|
10691 strcpy(q->name, name); |
|
10692 q->value = NULL; |
|
10693 q->domain = NULL; |
|
10694 q->path = NULL; |
|
10695 q->expire = -1; |
|
10696 q->version = 0; |
|
10697 q->secure = 0; |
|
10698 q->modified = 0; |
|
10699 for (p = &soap->cookies, n = soap->cookie_max; *p && n; p = &(*p)->next, n--) |
|
10700 if (!strcmp((*p)->name, name) && (*p)->path && strcmp((*p)->path, path) < 0) |
|
10701 break; |
|
10702 if (n) |
|
10703 { q->next = *p; |
|
10704 *p = q; |
|
10705 } |
|
10706 else |
|
10707 { SOAP_FREE(soap, q->name); |
|
10708 SOAP_FREE(soap, q); |
|
10709 q = NULL; |
|
10710 } |
|
10711 } |
|
10712 } |
|
10713 else |
|
10714 q->modified = 1; |
|
10715 if (q) |
|
10716 { if (q->value) |
|
10717 { SOAP_FREE(soap, q->value); |
|
10718 q->value = NULL; |
|
10719 } |
|
10720 if (q->domain) |
|
10721 { SOAP_FREE(soap, q->domain); |
|
10722 q->domain = NULL; |
|
10723 } |
|
10724 if (q->path) |
|
10725 { SOAP_FREE(soap, q->path); |
|
10726 q->path = NULL; |
|
10727 } |
|
10728 if (value && *value && (q->value = (char*)SOAP_MALLOC(soap, strlen(value)+1))) |
|
10729 strcpy(q->value, value); |
|
10730 if (domain && *domain && (q->domain = (char*)SOAP_MALLOC(soap, strlen(domain)+1))) |
|
10731 strcpy(q->domain, domain); |
|
10732 if (path && *path && (q->path = (char*)SOAP_MALLOC(soap, strlen(path)+1))) |
|
10733 strcpy(q->path, path); |
|
10734 q->session = 1; |
|
10735 q->env = 0; |
|
10736 } |
|
10737 return q; |
|
10738 } |
|
10739 |
|
10740 /******************************************************************************/ |
|
10741 SOAP_FMAC1 |
|
10742 void |
|
10743 SOAP_FMAC2 |
|
10744 soap_clr_cookie(struct soap *soap, const char *name, const char *domain, const char *path) |
|
10745 { struct soap_cookie **p, *q; |
|
10746 if (!domain) |
|
10747 domain = soap->cookie_domain; |
|
10748 if (!domain) |
|
10749 { soap_set_receiver_error(soap, "Cookie domain not set", NULL, SOAP_HTTP_ERROR); |
|
10750 return; |
|
10751 } |
|
10752 if (!path) |
|
10753 path = soap->cookie_path; |
|
10754 if (!path) |
|
10755 { soap_set_receiver_error(soap, "Cookie path not set", NULL, SOAP_HTTP_ERROR); |
|
10756 return; |
|
10757 } |
|
10758 if (*path == '/') |
|
10759 path++; |
|
10760 for (p = &soap->cookies, q = *p; q; q = *p) |
|
10761 if (!strcmp(q->name, name) && !strcmp(q->domain, domain) && !strncmp(q->path, path, strlen(q->path))) |
|
10762 { if (q->value) |
|
10763 SOAP_FREE(soap, q->value); |
|
10764 if (q->domain) |
|
10765 SOAP_FREE(soap, q->domain); |
|
10766 if (q->path) |
|
10767 SOAP_FREE(soap, q->path); |
|
10768 *p = q->next; |
|
10769 SOAP_FREE(soap, q); |
|
10770 } |
|
10771 else |
|
10772 p = &q->next; |
|
10773 } |
|
10774 |
|
10775 /******************************************************************************/ |
|
10776 SOAP_FMAC1 |
|
10777 char * |
|
10778 SOAP_FMAC2 |
|
10779 soap_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path) |
|
10780 { struct soap_cookie *p; |
|
10781 if ((p = soap_cookie(soap, name, domain, path))) |
|
10782 return p->value; |
|
10783 return NULL; |
|
10784 } |
|
10785 |
|
10786 /******************************************************************************/ |
|
10787 SOAP_FMAC1 |
|
10788 char * |
|
10789 SOAP_FMAC2 |
|
10790 soap_env_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path) |
|
10791 { struct soap_cookie *p; |
|
10792 if ((p = soap_cookie(soap, name, domain, path)) && p->env) |
|
10793 return p->value; |
|
10794 return NULL; |
|
10795 } |
|
10796 |
|
10797 /******************************************************************************/ |
|
10798 SOAP_FMAC1 |
|
10799 long |
|
10800 SOAP_FMAC2 |
|
10801 soap_cookie_expire(struct soap *soap, const char *name, const char *domain, const char *path) |
|
10802 { struct soap_cookie *p; |
|
10803 if ((p = soap_cookie(soap, name, domain, path))) |
|
10804 return p->expire; |
|
10805 return -1; |
|
10806 } |
|
10807 |
|
10808 /******************************************************************************/ |
|
10809 SOAP_FMAC1 |
|
10810 int |
|
10811 SOAP_FMAC2 |
|
10812 soap_set_cookie_expire(struct soap *soap, const char *name, long expire, const char *domain, const char *path) |
|
10813 { struct soap_cookie *p; |
|
10814 if ((p = soap_cookie(soap, name, domain, path))) |
|
10815 { p->expire = expire; |
|
10816 p->modified = 1; |
|
10817 return SOAP_OK; |
|
10818 } |
|
10819 return SOAP_ERR; |
|
10820 } |
|
10821 |
|
10822 /******************************************************************************/ |
|
10823 SOAP_FMAC1 |
|
10824 int |
|
10825 SOAP_FMAC2 |
|
10826 soap_set_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path) |
|
10827 { struct soap_cookie *p; |
|
10828 if ((p = soap_cookie(soap, name, domain, path))) |
|
10829 { p->session = 1; |
|
10830 p->modified = 1; |
|
10831 return SOAP_OK; |
|
10832 } |
|
10833 return SOAP_ERR; |
|
10834 } |
|
10835 |
|
10836 /******************************************************************************/ |
|
10837 SOAP_FMAC1 |
|
10838 int |
|
10839 SOAP_FMAC2 |
|
10840 soap_clr_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path) |
|
10841 { struct soap_cookie *p; |
|
10842 if ((p = soap_cookie(soap, name, domain, path))) |
|
10843 { p->session = 0; |
|
10844 p->modified = 1; |
|
10845 return SOAP_OK; |
|
10846 } |
|
10847 return SOAP_ERR; |
|
10848 } |
|
10849 |
|
10850 /******************************************************************************/ |
|
10851 SOAP_FMAC1 |
|
10852 int |
|
10853 SOAP_FMAC2 |
|
10854 soap_putsetcookies(struct soap *soap) |
|
10855 { struct soap_cookie *p; |
|
10856 char *s, tmp[4096]; |
|
10857 const char *t; |
|
10858 for (p = soap->cookies; p; p = p->next) |
|
10859 { if (p->modified || !p->env) |
|
10860 { s = tmp; |
|
10861 if (p->name) |
|
10862 s += soap_encode_cookie(p->name, s, tmp-s+4064); |
|
10863 if (p->value && *p->value) |
|
10864 { *s++ = '='; |
|
10865 s += soap_encode_cookie(p->value, s, tmp-s+4064); |
|
10866 } |
|
10867 if (p->domain && (int)strlen(p->domain) < tmp-s+4064) |
|
10868 sprintf(s, ";Domain=\"%s\"", p->domain); |
|
10869 else if (soap->cookie_domain && (int)strlen(soap->cookie_domain) < tmp-s+4064) |
|
10870 sprintf(s, ";Domain=\"%s\"", soap->cookie_domain); |
|
10871 strcat(s, ";Path=\"/"); |
|
10872 if (p->path) |
|
10873 t = p->path; |
|
10874 else |
|
10875 t = soap->cookie_path; |
|
10876 if (t) |
|
10877 { if (*t == '/') |
|
10878 t++; |
|
10879 if ((int)strlen(t) < tmp-s+4064) |
|
10880 strcat(s, t); |
|
10881 } |
|
10882 s += strlen(s); |
|
10883 *s++ = '"'; |
|
10884 if (p->version > 0) |
|
10885 sprintf(s, ";Version=%u", p->version); |
|
10886 if (p->expire >= 0) |
|
10887 sprintf(s, ";Max-Age=%ld", p->expire); |
|
10888 if (p->secure) |
|
10889 strcat(s, ";Secure"); |
|
10890 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set-Cookie: %s\n", tmp)); |
|
10891 if ((soap->error = soap->fposthdr(soap, "Set-Cookie", tmp))) |
|
10892 return soap->error; |
|
10893 } |
|
10894 } |
|
10895 return SOAP_OK; |
|
10896 } |
|
10897 |
|
10898 /******************************************************************************/ |
|
10899 SOAP_FMAC1 |
|
10900 int |
|
10901 SOAP_FMAC2 |
|
10902 soap_putcookies(struct soap *soap, const char *domain, const char *path, int secure) |
|
10903 { struct soap_cookie **p, *q; |
|
10904 unsigned int version = 0; |
|
10905 time_t now = time(NULL); |
|
10906 char *s, tmp[4096]; |
|
10907 p = &soap->cookies; |
|
10908 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending cookies for domain=%s path=%s\n", domain, path)); |
|
10909 if (*path == '/') |
|
10910 path++; |
|
10911 while ((q = *p)) |
|
10912 { if (q->expire && now > q->expire) |
|
10913 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie %s expired\n", q->name)); |
|
10914 SOAP_FREE(soap, q->name); |
|
10915 if (q->value) |
|
10916 SOAP_FREE(soap, q->value); |
|
10917 if (q->domain) |
|
10918 SOAP_FREE(soap, q->domain); |
|
10919 if (q->path) |
|
10920 SOAP_FREE(soap, q->path); |
|
10921 *p = q->next; |
|
10922 SOAP_FREE(soap, q); |
|
10923 } |
|
10924 else |
|
10925 { size_t domlen = 0; |
|
10926 if (q->domain) |
|
10927 { const char *s = strchr(q->domain, ':'); |
|
10928 if (s) |
|
10929 domlen = s - q->domain; |
|
10930 else |
|
10931 domlen = strlen(q->domain); |
|
10932 } |
|
10933 if ((!q->domain || !strncmp(q->domain, domain, domlen)) |
|
10934 && (!q->path || !strncmp(q->path, path, strlen(q->path))) |
|
10935 && (!q->secure || secure)) |
|
10936 { s = tmp; |
|
10937 if (q->version != version) |
|
10938 { sprintf(s, "$Version=%u;", q->version); |
|
10939 version = q->version; |
|
10940 } |
|
10941 if (q->name) |
|
10942 s += soap_encode_cookie(q->name, s, tmp-s+4080); |
|
10943 if (q->value && *q->value) |
|
10944 { *s++ = '='; |
|
10945 s += soap_encode_cookie(q->value, s, tmp-s+4080); |
|
10946 } |
|
10947 if (q->path && (int)strlen(q->path) < tmp-s+4080) |
|
10948 { sprintf(s, ";$Path=\"/%s\"", (*q->path == '/' ? q->path + 1 : q->path)); |
|
10949 s += strlen(s); |
|
10950 } |
|
10951 if (q->domain && (int)strlen(q->domain) < tmp-s+4080) |
|
10952 sprintf(s, ";$Domain=\"%s\"", q->domain); |
|
10953 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie: %s\n", tmp)); |
|
10954 if ((soap->error = soap->fposthdr(soap, "Cookie", tmp))) |
|
10955 return soap->error; |
|
10956 } |
|
10957 p = &q->next; |
|
10958 } |
|
10959 } |
|
10960 return SOAP_OK; |
|
10961 } |
|
10962 |
|
10963 /******************************************************************************/ |
|
10964 SOAP_FMAC1 |
|
10965 void |
|
10966 SOAP_FMAC2 |
|
10967 soap_getcookies(struct soap *soap, const char *val) |
|
10968 { struct soap_cookie *p = NULL, *q; |
|
10969 const char *s; |
|
10970 char *t, tmp[4096]; /* cookie size is up to 4096 bytes [RFC2109] */ |
|
10971 char *domain = NULL; |
|
10972 char *path = NULL; |
|
10973 unsigned int version = 0; |
|
10974 time_t now = time(NULL); |
|
10975 if (!val) |
|
10976 return; |
|
10977 s = val; |
|
10978 while (*s) |
|
10979 { s = soap_decode_key(tmp, sizeof(tmp), s); |
|
10980 if (!soap_tag_cmp(tmp, "$Version")) |
|
10981 { if ((s = soap_decode_val(tmp, sizeof(tmp), s))) |
|
10982 { if (p) |
|
10983 p->version = (int)atol(tmp); |
|
10984 else |
|
10985 version = (int)atol(tmp); |
|
10986 } |
|
10987 } |
|
10988 else if (!soap_tag_cmp(tmp, "$Path")) |
|
10989 { s = soap_decode_val(tmp, sizeof(tmp), s); |
|
10990 if (*tmp) |
|
10991 { if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) |
|
10992 strcpy(t, tmp); |
|
10993 } |
|
10994 else |
|
10995 t = NULL; |
|
10996 if (p) |
|
10997 { if (p->path) |
|
10998 SOAP_FREE(soap, p->path); |
|
10999 p->path = t; |
|
11000 } |
|
11001 else |
|
11002 { if (path) |
|
11003 SOAP_FREE(soap, path); |
|
11004 path = t; |
|
11005 } |
|
11006 } |
|
11007 else if (!soap_tag_cmp(tmp, "$Domain")) |
|
11008 { s = soap_decode_val(tmp, sizeof(tmp), s); |
|
11009 if (*tmp) |
|
11010 { if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) |
|
11011 strcpy(t, tmp); |
|
11012 } |
|
11013 else |
|
11014 t = NULL; |
|
11015 if (p) |
|
11016 { if (p->domain) |
|
11017 SOAP_FREE(soap, p->domain); |
|
11018 p->domain = t; |
|
11019 } |
|
11020 else |
|
11021 { if (domain) |
|
11022 SOAP_FREE(soap, domain); |
|
11023 domain = t; |
|
11024 } |
|
11025 } |
|
11026 else if (p && !soap_tag_cmp(tmp, "Path")) |
|
11027 { if (p->path) |
|
11028 SOAP_FREE(soap, p->path); |
|
11029 s = soap_decode_val(tmp, sizeof(tmp), s); |
|
11030 if (*tmp) |
|
11031 { if ((p->path = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) |
|
11032 strcpy(p->path, tmp); |
|
11033 } |
|
11034 else |
|
11035 p->path = NULL; |
|
11036 } |
|
11037 else if (p && !soap_tag_cmp(tmp, "Domain")) |
|
11038 { if (p->domain) |
|
11039 SOAP_FREE(soap, p->domain); |
|
11040 s = soap_decode_val(tmp, sizeof(tmp), s); |
|
11041 if (*tmp) |
|
11042 { if ((p->domain = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) |
|
11043 strcpy(p->domain, tmp); |
|
11044 } |
|
11045 else |
|
11046 p->domain = NULL; |
|
11047 } |
|
11048 else if (p && !soap_tag_cmp(tmp, "Version")) |
|
11049 { s = soap_decode_val(tmp, sizeof(tmp), s); |
|
11050 p->version = (unsigned int)atol(tmp); |
|
11051 } |
|
11052 else if (p && !soap_tag_cmp(tmp, "Max-Age")) |
|
11053 { s = soap_decode_val(tmp, sizeof(tmp), s); |
|
11054 p->expire = now + atol(tmp); |
|
11055 } |
|
11056 else if (p && !soap_tag_cmp(tmp, "Expires")) |
|
11057 { struct tm T; |
|
11058 char a[3]; |
|
11059 static const char mns[] = "anebarprayunulugepctovec"; |
|
11060 s = soap_decode_val(tmp, sizeof(tmp), s); |
|
11061 if (strlen(tmp) > 20) |
|
11062 { memset((void*)&T, 0, sizeof(T)); |
|
11063 a[0] = tmp[4]; |
|
11064 a[1] = tmp[5]; |
|
11065 a[2] = '\0'; |
|
11066 T.tm_mday = (int)atol(a); |
|
11067 a[0] = tmp[8]; |
|
11068 a[1] = tmp[9]; |
|
11069 T.tm_mon = (strstr(mns, a) - mns) / 2; |
|
11070 a[0] = tmp[11]; |
|
11071 a[1] = tmp[12]; |
|
11072 T.tm_year = 100 + (int)atol(a); |
|
11073 a[0] = tmp[13]; |
|
11074 a[1] = tmp[14]; |
|
11075 T.tm_hour = (int)atol(a); |
|
11076 a[0] = tmp[16]; |
|
11077 a[1] = tmp[17]; |
|
11078 T.tm_min = (int)atol(a); |
|
11079 a[0] = tmp[19]; |
|
11080 a[1] = tmp[20]; |
|
11081 T.tm_sec = (int)atol(a); |
|
11082 p->expire = soap_timegm(&T); |
|
11083 } |
|
11084 } |
|
11085 else if (p && !soap_tag_cmp(tmp, "Secure")) |
|
11086 p->secure = 1; |
|
11087 else |
|
11088 { if (p) |
|
11089 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie %s=%s domain=%s path=%s expire=%ld secure=%d\n", p->name, p->value?p->value:"", p->domain?p->domain:"", p->path?p->path:"", p->expire, p->secure)); |
|
11090 if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path))) |
|
11091 { q->version = p->version; |
|
11092 q->expire = p->expire; |
|
11093 q->secure = p->secure; |
|
11094 q->env = 1; |
|
11095 } |
|
11096 if (p->name) |
|
11097 SOAP_FREE(soap, p->name); |
|
11098 if (p->value) |
|
11099 SOAP_FREE(soap, p->value); |
|
11100 if (p->domain) |
|
11101 SOAP_FREE(soap, p->domain); |
|
11102 if (p->path) |
|
11103 SOAP_FREE(soap, p->path); |
|
11104 SOAP_FREE(soap, p); |
|
11105 } |
|
11106 if ((p = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie)))) |
|
11107 { p->name = (char*)SOAP_MALLOC(soap, strlen(tmp)+1); |
|
11108 strcpy(p->name, tmp); |
|
11109 s = soap_decode_val(tmp, sizeof(tmp), s); |
|
11110 if (*tmp) |
|
11111 { p->value = (char*)SOAP_MALLOC(soap, strlen(tmp)+1); |
|
11112 strcpy(p->value, tmp); |
|
11113 } |
|
11114 else |
|
11115 p->value = NULL; |
|
11116 p->domain = domain; |
|
11117 p->path = path; |
|
11118 p->expire = 0; |
|
11119 p->secure = 0; |
|
11120 p->version = version; |
|
11121 } |
|
11122 } |
|
11123 } |
|
11124 if (p) |
|
11125 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie %s=%s domain=%s path=%s expire=%ld secure=%d\n", p->name, p->value?p->value:"", p->domain?p->domain:"", p->path?p->path:"", p->expire, p->secure)); |
|
11126 if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path))) |
|
11127 { q->version = p->version; |
|
11128 q->expire = p->expire; |
|
11129 q->secure = p->secure; |
|
11130 q->env = 1; |
|
11131 } |
|
11132 if (p->name) |
|
11133 SOAP_FREE(soap, p->name); |
|
11134 if (p->value) |
|
11135 SOAP_FREE(soap, p->value); |
|
11136 if (p->domain) |
|
11137 SOAP_FREE(soap, p->domain); |
|
11138 if (p->path) |
|
11139 SOAP_FREE(soap, p->path); |
|
11140 SOAP_FREE(soap, p); |
|
11141 } |
|
11142 if (domain) |
|
11143 SOAP_FREE(soap, domain); |
|
11144 if (path) |
|
11145 SOAP_FREE(soap, path); |
|
11146 } |
|
11147 |
|
11148 /******************************************************************************/ |
|
11149 SOAP_FMAC1 |
|
11150 int |
|
11151 SOAP_FMAC2 |
|
11152 soap_getenv_cookies(struct soap *soap) |
|
11153 { struct soap_cookie *p; |
|
11154 const char *s; |
|
11155 char key[4096], val[4096]; /* cookie size is up to 4096 bytes [RFC2109] */ |
|
11156 if (!(s = getenv("HTTP_COOKIE"))) |
|
11157 return SOAP_ERR; |
|
11158 do |
|
11159 { s = soap_decode_key(key, sizeof(key), s); |
|
11160 s = soap_decode_val(val, sizeof(val), s); |
|
11161 p = soap_set_cookie(soap, key, val, NULL, NULL); |
|
11162 if (p) |
|
11163 p->env = 1; |
|
11164 } while (*s); |
|
11165 return SOAP_OK; |
|
11166 } |
|
11167 |
|
11168 /******************************************************************************/ |
|
11169 SOAP_FMAC1 |
|
11170 struct soap_cookie* |
|
11171 SOAP_FMAC2 |
|
11172 soap_copy_cookies(struct soap *soap) |
|
11173 { struct soap_cookie *p, **q, *r; |
|
11174 q = &r; |
|
11175 for (p = soap->cookies; p; p = p->next) |
|
11176 { if (!(*q = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie)))) |
|
11177 return r; |
|
11178 **q = *p; |
|
11179 if (p->name) |
|
11180 { if (((*q)->name = (char*)SOAP_MALLOC(soap, strlen(p->name)+1))) |
|
11181 strcpy((*q)->name, p->name); |
|
11182 } |
|
11183 if (p->value) |
|
11184 { if (((*q)->value = (char*)SOAP_MALLOC(soap, strlen(p->value)+1))) |
|
11185 strcpy((*q)->value, p->value); |
|
11186 } |
|
11187 if (p->domain) |
|
11188 { if (((*q)->domain = (char*)SOAP_MALLOC(soap, strlen(p->domain)+1))) |
|
11189 strcpy((*q)->domain, p->domain); |
|
11190 } |
|
11191 if (p->path) |
|
11192 { if (((*q)->path = (char*)SOAP_MALLOC(soap, strlen(p->path)+1))) |
|
11193 strcpy((*q)->path, p->path); |
|
11194 } |
|
11195 q = &(*q)->next; |
|
11196 } |
|
11197 *q = NULL; |
|
11198 return r; |
|
11199 } |
|
11200 |
|
11201 /******************************************************************************/ |
|
11202 SOAP_FMAC1 |
|
11203 void |
|
11204 SOAP_FMAC2 |
|
11205 soap_free_cookies(struct soap *soap) |
|
11206 { struct soap_cookie *p; |
|
11207 for (p = soap->cookies; p; p = soap->cookies) |
|
11208 { soap->cookies = p->next; |
|
11209 SOAP_FREE(soap, p->name); |
|
11210 if (p->value) |
|
11211 SOAP_FREE(soap, p->value); |
|
11212 if (p->domain) |
|
11213 SOAP_FREE(soap, p->domain); |
|
11214 if (p->path) |
|
11215 SOAP_FREE(soap, p->path); |
|
11216 SOAP_FREE(soap, p); |
|
11217 } |
|
11218 } |
|
11219 |
|
11220 /******************************************************************************/ |
|
11221 #endif /* WITH_COOKIES */ |
|
11222 |
|
11223 /******************************************************************************/ |
|
11224 #ifdef WITH_GZIP |
|
11225 #ifndef PALM_1 |
|
11226 static int |
|
11227 soap_getgziphdr(struct soap *soap) |
|
11228 { int i; |
|
11229 soap_wchar c, f = 0; |
|
11230 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get gzip header\n")); |
|
11231 for (i = 0; i < 9; i++) |
|
11232 { if ((int)(c = soap_get1(soap) == EOF)) |
|
11233 return soap->error = SOAP_EOF; |
|
11234 if (i == 2) |
|
11235 f = c; |
|
11236 } |
|
11237 if (f & 0x04) /* FEXTRA */ |
|
11238 { for (i = soap_get1(soap) | (soap_get1(soap) << 8); i; i--) |
|
11239 if ((int)soap_get1(soap) == EOF) |
|
11240 return soap->error = SOAP_EOF; |
|
11241 } |
|
11242 if (f & 0x08) /* FNAME */ |
|
11243 do |
|
11244 c = soap_get1(soap); |
|
11245 while (c && (int)c != EOF); |
|
11246 if ((int)c != EOF && (f & 0x10)) /* FCOMMENT */ |
|
11247 do |
|
11248 c = soap_get1(soap); |
|
11249 while (c && (int)f != EOF); |
|
11250 if ((int)c != EOF && (f & 0x01)) /* FHCRC */ |
|
11251 { if ((int)(c = soap_get1(soap)) != EOF) |
|
11252 c = soap_get1(soap); |
|
11253 } |
|
11254 if ((int)c == EOF) |
|
11255 return soap->error = SOAP_EOF; |
|
11256 return SOAP_OK; |
|
11257 } |
|
11258 #endif |
|
11259 #endif |
|
11260 |
|
11261 /******************************************************************************/ |
|
11262 #ifndef PALM_1 |
|
11263 SOAP_FMAC1 |
|
11264 int |
|
11265 SOAP_FMAC2 |
|
11266 soap_begin_recv(struct soap *soap) |
|
11267 { soap_wchar c; |
|
11268 soap->error = SOAP_OK; |
|
11269 soap_free(soap); |
|
11270 soap_set_local_namespaces(soap); |
|
11271 soap->version = 0; /* don't assume we're parsing SOAP content by default */ |
|
11272 #ifndef WITH_NOIDREF |
|
11273 soap_free_iht(soap); |
|
11274 #endif |
|
11275 if ((soap->imode & SOAP_IO) == SOAP_IO_CHUNK) |
|
11276 soap->omode |= SOAP_IO_CHUNK; |
|
11277 soap->imode &= ~SOAP_IO; |
|
11278 soap->mode = soap->imode; |
|
11279 if (!soap->keep_alive) |
|
11280 { soap->buflen = 0; |
|
11281 soap->bufidx = 0; |
|
11282 } |
|
11283 if (!(soap->mode & SOAP_IO_KEEPALIVE)) |
|
11284 soap->keep_alive = 0; |
|
11285 soap->ahead = 0; |
|
11286 soap->peeked = 0; |
|
11287 soap->level = 0; |
|
11288 soap->part = SOAP_BEGIN; |
|
11289 soap->alloced = 0; |
|
11290 soap->count = 0; |
|
11291 soap->length = 0; |
|
11292 soap->cdata = 0; |
|
11293 *soap->endpoint = '\0'; |
|
11294 soap->action = NULL; |
|
11295 #ifndef WITH_LEANER |
|
11296 soap->dom = NULL; |
|
11297 soap->dime.chunksize = 0; |
|
11298 soap->dime.buflen = 0; |
|
11299 soap->dime.list = NULL; |
|
11300 soap->dime.first = NULL; |
|
11301 soap->dime.last = NULL; |
|
11302 soap->mime.list = NULL; |
|
11303 soap->mime.first = NULL; |
|
11304 soap->mime.last = NULL; |
|
11305 soap->mime.boundary = NULL; |
|
11306 soap->mime.start = NULL; |
|
11307 soap->xlist = NULL; |
|
11308 #endif |
|
11309 #ifdef WIN32 |
|
11310 #ifndef UNDER_CE |
|
11311 #ifndef WITH_FASTCGI |
|
11312 if (!soap_valid_socket(soap->socket)) |
|
11313 #ifdef __BORLANDC__ |
|
11314 setmode((SOAP_SOCKET)soap->recvfd, O_BINARY); |
|
11315 #else |
|
11316 _setmode((SOAP_SOCKET)soap->recvfd, _O_BINARY); |
|
11317 #endif |
|
11318 #endif |
|
11319 #endif |
|
11320 #endif |
|
11321 #ifdef WITH_ZLIB |
|
11322 soap->mode &= ~SOAP_ENC_ZLIB; |
|
11323 soap->zlib_in = SOAP_ZLIB_NONE; |
|
11324 soap->zlib_out = SOAP_ZLIB_NONE; |
|
11325 soap->d_stream.next_in = Z_NULL; |
|
11326 soap->d_stream.avail_in = 0; |
|
11327 soap->d_stream.next_out = (Byte*)soap->buf; |
|
11328 soap->d_stream.avail_out = SOAP_BUFLEN; |
|
11329 soap->z_ratio_in = 1.0; |
|
11330 #endif |
|
11331 #ifndef WITH_LEANER |
|
11332 if (soap->fprepareinit) |
|
11333 soap->fprepareinit(soap); |
|
11334 #endif |
|
11335 c = soap_getchar(soap); |
|
11336 #ifdef WITH_GZIP |
|
11337 if (c == 0x1F) |
|
11338 { if (soap_getgziphdr(soap)) |
|
11339 return soap->error; |
|
11340 if (inflateInit2(&soap->d_stream, -MAX_WBITS) != Z_OK) |
|
11341 return soap->error = SOAP_ZLIB_ERROR; |
|
11342 soap->zlib_state = SOAP_ZLIB_INFLATE; |
|
11343 soap->mode |= SOAP_ENC_ZLIB; |
|
11344 soap->zlib_in = SOAP_ZLIB_GZIP; |
|
11345 soap->z_crc = crc32(0L, NULL, 0); |
|
11346 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n")); |
|
11347 memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); |
|
11348 /* should not chunk over plain transport, so why bother to check? */ |
|
11349 /* if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) */ |
|
11350 /* soap->z_buflen = soap->bufidx; */ |
|
11351 /* else */ |
|
11352 soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx); |
|
11353 soap->d_stream.avail_in = soap->buflen - soap->bufidx; |
|
11354 soap->z_buflen = soap->buflen; |
|
11355 soap->buflen = soap->bufidx; |
|
11356 c = soap_getchar(soap); |
|
11357 } |
|
11358 #endif |
|
11359 #ifndef WITH_LEANER |
|
11360 if (c == '-' && soap_get0(soap) == '-') |
|
11361 soap->mode |= SOAP_ENC_MIME; |
|
11362 else if ((c & 0xFFFC) == (SOAP_DIME_VERSION | SOAP_DIME_MB) && (soap_get0(soap) & 0xFFF0) == 0x20) |
|
11363 soap->mode |= SOAP_ENC_DIME; |
|
11364 else |
|
11365 #endif |
|
11366 { while (soap_blank(c)) |
|
11367 c = soap_getchar(soap); |
|
11368 } |
|
11369 if ((int)c == EOF) |
|
11370 return soap->error = SOAP_EOF; |
|
11371 soap_unget(soap, c); |
|
11372 #ifndef WITH_NOHTTP |
|
11373 /* if not XML or (start of)BOM or MIME/DIME/ZLIB, assume HTTP header */ |
|
11374 if (c != '<' && c != 0xEF && !(soap->mode & (SOAP_ENC_MIME | SOAP_ENC_DIME | SOAP_ENC_ZLIB))) |
|
11375 { soap->mode &= ~SOAP_IO; |
|
11376 soap->error = soap->fparse(soap); |
|
11377 if (soap->error && soap->error < SOAP_STOP) |
|
11378 { soap->keep_alive = 0; /* force close later */ |
|
11379 return soap->error; |
|
11380 } |
|
11381 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) |
|
11382 { soap->chunkbuflen = soap->buflen; |
|
11383 soap->buflen = soap->bufidx; |
|
11384 soap->chunksize = 0; |
|
11385 } |
|
11386 #ifndef WITH_LEANER |
|
11387 else if (soap->fpreparerecv && soap->buflen != soap->bufidx) |
|
11388 soap->fpreparerecv(soap, soap->buf + soap->bufidx, soap->buflen - soap->bufidx); |
|
11389 #endif |
|
11390 #ifdef WITH_ZLIB |
|
11391 if (soap->zlib_in != SOAP_ZLIB_NONE) |
|
11392 { /* fparse should not use soap_unget to push back last char */ |
|
11393 #ifdef WITH_GZIP |
|
11394 c = soap_get1(soap); |
|
11395 if (c == 0x1F) |
|
11396 { if (soap_getgziphdr(soap)) |
|
11397 return soap->error; |
|
11398 if (inflateInit2(&soap->d_stream, -MAX_WBITS) != Z_OK) |
|
11399 return soap->error = SOAP_ZLIB_ERROR; |
|
11400 soap->zlib_state = SOAP_ZLIB_INFLATE; |
|
11401 soap->z_crc = crc32(0L, NULL, 0); |
|
11402 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n")); |
|
11403 } |
|
11404 else |
|
11405 { soap_revget1(soap); |
|
11406 #else |
|
11407 { |
|
11408 #endif |
|
11409 if (inflateInit(&soap->d_stream) != Z_OK) |
|
11410 return soap->error = SOAP_ZLIB_ERROR; |
|
11411 soap->zlib_state = SOAP_ZLIB_INFLATE; |
|
11412 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate initialized\n")); |
|
11413 } |
|
11414 soap->mode |= SOAP_ENC_ZLIB; |
|
11415 memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); |
|
11416 soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx); |
|
11417 soap->d_stream.avail_in = soap->buflen - soap->bufidx; |
|
11418 soap->z_buflen = soap->buflen; |
|
11419 soap->buflen = soap->bufidx; |
|
11420 } |
|
11421 #endif |
|
11422 if (soap->error) |
|
11423 { if (soap->error == SOAP_FORM && soap->fform) |
|
11424 { soap->error = soap->fform(soap); |
|
11425 if (soap->error == SOAP_OK) |
|
11426 soap->error = SOAP_STOP; /* prevents further processing */ |
|
11427 } |
|
11428 return soap->error; |
|
11429 } |
|
11430 } |
|
11431 #endif |
|
11432 #ifndef WITH_LEANER |
|
11433 if (soap->mode & SOAP_ENC_MIME) |
|
11434 { if (soap_getmimehdr(soap)) |
|
11435 return soap->error; |
|
11436 if (soap_get_header_attribute(soap, soap->mime.first->type, "application/dime")) |
|
11437 soap->mode |= SOAP_ENC_DIME; |
|
11438 } |
|
11439 if (soap->mode & SOAP_ENC_DIME) |
|
11440 { if (soap_getdimehdr(soap)) |
|
11441 return soap->error; |
|
11442 if (soap->dime.flags & SOAP_DIME_CF) |
|
11443 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked DIME SOAP message\n")); |
|
11444 soap->dime.chunksize = soap->dime.size; |
|
11445 if (soap->buflen - soap->bufidx >= soap->dime.chunksize) |
|
11446 { soap->dime.buflen = soap->buflen; |
|
11447 soap->buflen = soap->bufidx + soap->dime.chunksize; |
|
11448 } |
|
11449 else |
|
11450 soap->dime.chunksize -= soap->buflen - soap->bufidx; |
|
11451 } |
|
11452 soap->count = soap->buflen - soap->bufidx; |
|
11453 } |
|
11454 #endif |
|
11455 return SOAP_OK; |
|
11456 } |
|
11457 #endif |
|
11458 |
|
11459 /******************************************************************************/ |
|
11460 #ifndef WITH_NOHTTP |
|
11461 #ifndef PALM_1 |
|
11462 static int |
|
11463 http_parse(struct soap *soap) |
|
11464 { char header[SOAP_HDRLEN], *s; |
|
11465 unsigned short get = 0, status = 0, k = 0; |
|
11466 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Waiting for HTTP request/response...\n")); |
|
11467 *soap->endpoint = '\0'; |
|
11468 soap->length = 0; |
|
11469 soap->userid = NULL; |
|
11470 soap->passwd = NULL; |
|
11471 soap->action = NULL; |
|
11472 soap->authrealm = NULL; |
|
11473 do |
|
11474 { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) |
|
11475 return soap->error; |
|
11476 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP status: %s\n", soap->msgbuf)); |
|
11477 for (;;) |
|
11478 { if (soap_getline(soap, header, SOAP_HDRLEN)) |
|
11479 { if (soap->error == SOAP_EOF) |
|
11480 { soap->error = SOAP_OK; |
|
11481 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "EOF in HTTP header, continue anyway\n")); |
|
11482 break; |
|
11483 } |
|
11484 return soap->error; |
|
11485 } |
|
11486 if (!*header) |
|
11487 break; |
|
11488 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP header: %s\n", header)); |
|
11489 s = strchr(header, ':'); |
|
11490 if (s) |
|
11491 { *s = '\0'; |
|
11492 do s++; |
|
11493 while (*s && *s <= 32); |
|
11494 if ((soap->error = soap->fparsehdr(soap, header, s))) |
|
11495 { if (soap->error < SOAP_STOP) |
|
11496 return soap->error; |
|
11497 status = soap->error; |
|
11498 soap->error = SOAP_OK; |
|
11499 } |
|
11500 } |
|
11501 } |
|
11502 if ((s = strchr(soap->msgbuf, ' '))) |
|
11503 { k = (unsigned short)soap_strtoul(s, &s, 10); |
|
11504 if (!soap_blank(*s)) |
|
11505 k = 0; |
|
11506 } |
|
11507 else |
|
11508 k = 0; |
|
11509 } while (k == 100); |
|
11510 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Finished HTTP header parsing\n")); |
|
11511 s = strstr(soap->msgbuf, "HTTP/"); |
|
11512 if (s && s[7] != '1') |
|
11513 { if (soap->keep_alive == 1) |
|
11514 soap->keep_alive = 0; |
|
11515 if (k == 0 && (soap->omode & SOAP_IO) == SOAP_IO_CHUNK) /* k == 0 for HTTP request */ |
|
11516 { soap->imode |= SOAP_IO_CHUNK; |
|
11517 soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE; |
|
11518 } |
|
11519 } |
|
11520 if (soap->keep_alive < 0) |
|
11521 soap->keep_alive = 1; |
|
11522 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Keep alive connection = %d\n", soap->keep_alive)); |
|
11523 if (s && (((get = !strncmp(soap->msgbuf, "GET ", 4))) || !strncmp(soap->msgbuf, "POST ", 5))) |
|
11524 { size_t m = strlen(soap->endpoint); |
|
11525 size_t n = m + (s - soap->msgbuf) - 5 - (!get); |
|
11526 if (n >= sizeof(soap->endpoint)) |
|
11527 n = sizeof(soap->endpoint) - 1; |
|
11528 strncpy(soap->path, soap->msgbuf + 4 + (!get), n - m); |
|
11529 soap->path[n - m] = '\0'; |
|
11530 strcat(soap->endpoint, soap->path); |
|
11531 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Target endpoint='%s'\n", soap->endpoint)); |
|
11532 if (get) |
|
11533 { soap->error = soap->fget(soap); |
|
11534 if (soap->error == SOAP_OK) |
|
11535 soap->error = SOAP_STOP; /* prevents further processing */ |
|
11536 return soap->error; |
|
11537 } |
|
11538 if (status) |
|
11539 return soap->error = status; |
|
11540 return SOAP_OK; |
|
11541 } |
|
11542 if (k == 0 || (k >= 200 && k <= 299) || k == 400 || k == 500) |
|
11543 return SOAP_OK; |
|
11544 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP error %d\n", k)); |
|
11545 return soap_set_receiver_error(soap, "HTTP error", soap->msgbuf, k); |
|
11546 } |
|
11547 #endif |
|
11548 #endif |
|
11549 |
|
11550 /******************************************************************************/ |
|
11551 #ifndef WITH_NOHTTP |
|
11552 #ifndef PALM_1 |
|
11553 static int |
|
11554 http_parse_header(struct soap *soap, const char *key, const char *val) |
|
11555 { if (!soap_tag_cmp(key, "Host")) |
|
11556 { |
|
11557 #ifdef WITH_OPENSSL |
|
11558 if (soap->imode & SOAP_ENC_SSL) |
|
11559 strcpy(soap->endpoint, "https://"); |
|
11560 else |
|
11561 #endif |
|
11562 strcpy(soap->endpoint, "http://"); |
|
11563 strncat(soap->endpoint, val, sizeof(soap->endpoint) - 8); |
|
11564 soap->endpoint[sizeof(soap->endpoint) - 1] = '\0'; |
|
11565 } |
|
11566 #ifndef WITH_LEANER |
|
11567 else if (!soap_tag_cmp(key, "Content-Type")) |
|
11568 { if (soap_get_header_attribute(soap, val, "application/dime")) |
|
11569 soap->mode |= SOAP_ENC_DIME; |
|
11570 else if (soap_get_header_attribute(soap, val, "multipart/related") |
|
11571 || soap_get_header_attribute(soap, val, "multipart/form-data")) |
|
11572 { soap->mime.boundary = soap_strdup(soap, soap_get_header_attribute(soap, val, "boundary")); |
|
11573 soap->mime.start = soap_strdup(soap, soap_get_header_attribute(soap, val, "start")); |
|
11574 soap->mode |= SOAP_ENC_MIME; |
|
11575 } |
|
11576 } |
|
11577 #endif |
|
11578 else if (!soap_tag_cmp(key, "Content-Length")) |
|
11579 soap->length = soap_strtoul(val, NULL, 10); |
|
11580 else if (!soap_tag_cmp(key, "Content-Encoding")) |
|
11581 { if (!soap_tag_cmp(val, "deflate")) |
|
11582 #ifdef WITH_ZLIB |
|
11583 soap->zlib_in = SOAP_ZLIB_DEFLATE; |
|
11584 #else |
|
11585 return SOAP_ZLIB_ERROR; |
|
11586 #endif |
|
11587 else if (!soap_tag_cmp(val, "gzip")) |
|
11588 #ifdef WITH_GZIP |
|
11589 soap->zlib_in = SOAP_ZLIB_GZIP; |
|
11590 #else |
|
11591 return SOAP_ZLIB_ERROR; |
|
11592 #endif |
|
11593 } |
|
11594 #ifdef WITH_ZLIB |
|
11595 else if (!soap_tag_cmp(key, "Accept-Encoding")) |
|
11596 { |
|
11597 #ifdef WITH_GZIP |
|
11598 if (strchr(val, '*') || soap_get_header_attribute(soap, val, "gzip")) |
|
11599 soap->zlib_out = SOAP_ZLIB_GZIP; |
|
11600 else |
|
11601 #endif |
|
11602 if (strchr(val, '*') || soap_get_header_attribute(soap, val, "deflate")) |
|
11603 soap->zlib_out = SOAP_ZLIB_DEFLATE; |
|
11604 else |
|
11605 soap->zlib_out = SOAP_ZLIB_NONE; |
|
11606 } |
|
11607 #endif |
|
11608 else if (!soap_tag_cmp(key, "Transfer-Encoding")) |
|
11609 { soap->mode &= ~SOAP_IO; |
|
11610 if (!soap_tag_cmp(val, "chunked")) |
|
11611 soap->mode |= SOAP_IO_CHUNK; |
|
11612 } |
|
11613 else if (!soap_tag_cmp(key, "Connection")) |
|
11614 { if (!soap_tag_cmp(val, "keep-alive")) |
|
11615 soap->keep_alive = -soap->keep_alive; |
|
11616 else if (!soap_tag_cmp(val, "close")) |
|
11617 soap->keep_alive = 0; |
|
11618 } |
|
11619 #ifndef WITH_LEAN |
|
11620 else if (!soap_tag_cmp(key, "Authorization")) |
|
11621 { if (!soap_tag_cmp(val, "Basic *")) |
|
11622 { int n; |
|
11623 char *s; |
|
11624 soap_base642s(soap, val + 6, soap->tmpbuf, sizeof(soap->tmpbuf) - 1, &n); |
|
11625 soap->tmpbuf[n] = '\0'; |
|
11626 if ((s = strchr(soap->tmpbuf, ':'))) |
|
11627 { *s = '\0'; |
|
11628 soap->userid = soap_strdup(soap, soap->tmpbuf); |
|
11629 soap->passwd = soap_strdup(soap, s + 1); |
|
11630 } |
|
11631 } |
|
11632 } |
|
11633 else if (!soap_tag_cmp(key, "WWW-Authenticate")) |
|
11634 soap->authrealm = soap_strdup(soap, soap_get_header_attribute(soap, val + 6, "realm")); |
|
11635 else if (!soap_tag_cmp(key, "Expect")) |
|
11636 { if (!soap_tag_cmp(val, "100-continue")) |
|
11637 { if ((soap->error = soap->fposthdr(soap, "HTTP/1.1 100 Continue", NULL)) |
|
11638 || (soap->error = soap->fposthdr(soap, NULL, NULL))) |
|
11639 return soap->error; |
|
11640 } |
|
11641 } |
|
11642 #endif |
|
11643 else if (!soap_tag_cmp(key, "SOAPAction")) |
|
11644 { if (*val == '"') |
|
11645 { soap->action = soap_strdup(soap, val + 1); |
|
11646 soap->action[strlen(soap->action) - 1] = '\0'; |
|
11647 } |
|
11648 } |
|
11649 else if (!soap_tag_cmp(key, "Location")) |
|
11650 { strncpy(soap->endpoint, val, sizeof(soap->endpoint)); |
|
11651 soap->endpoint[sizeof(soap->endpoint) - 1] = '\0'; |
|
11652 } |
|
11653 #ifdef WITH_COOKIES |
|
11654 else if (!soap_tag_cmp(key, "Cookie") || !soap_tag_cmp(key, "Set-Cookie")) |
|
11655 soap_getcookies(soap, val); |
|
11656 #endif |
|
11657 return SOAP_OK; |
|
11658 } |
|
11659 #endif |
|
11660 #endif |
|
11661 |
|
11662 /******************************************************************************/ |
|
11663 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) |
|
11664 #ifndef PALM_1 |
|
11665 SOAP_FMAC1 |
|
11666 const char* |
|
11667 SOAP_FMAC2 |
|
11668 soap_get_header_attribute(struct soap *soap, const char *line, const char *key) |
|
11669 { register const char *s = line; |
|
11670 if (s) |
|
11671 { while (*s) |
|
11672 { register short flag; |
|
11673 s = soap_decode_key(soap->tmpbuf, sizeof(soap->tmpbuf), s); |
|
11674 flag = soap_tag_cmp(soap->tmpbuf, key); |
|
11675 s = soap_decode_val(soap->tmpbuf, sizeof(soap->tmpbuf), s); |
|
11676 if (!flag) |
|
11677 return soap->tmpbuf; |
|
11678 } |
|
11679 } |
|
11680 return NULL; |
|
11681 } |
|
11682 #endif |
|
11683 #endif |
|
11684 |
|
11685 /******************************************************************************/ |
|
11686 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) |
|
11687 #ifndef PALM_1 |
|
11688 SOAP_FMAC1 |
|
11689 const char* |
|
11690 SOAP_FMAC2 |
|
11691 soap_decode_key(char *buf, size_t len, const char *val) |
|
11692 { return soap_decode(buf, len, val, "=,;"); |
|
11693 } |
|
11694 #endif |
|
11695 #endif |
|
11696 |
|
11697 /******************************************************************************/ |
|
11698 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) |
|
11699 #ifndef PALM_1 |
|
11700 SOAP_FMAC1 |
|
11701 const char* |
|
11702 SOAP_FMAC2 |
|
11703 soap_decode_val(char *buf, size_t len, const char *val) |
|
11704 { if (*val != '=') |
|
11705 { *buf = '\0'; |
|
11706 return val; |
|
11707 } |
|
11708 return soap_decode(buf, len, val + 1, ",;"); |
|
11709 } |
|
11710 #endif |
|
11711 #endif |
|
11712 |
|
11713 /******************************************************************************/ |
|
11714 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) |
|
11715 #ifndef PALM_1 |
|
11716 static const char* |
|
11717 soap_decode(char *buf, size_t len, const char *val, const char *sep) |
|
11718 { const char *s; |
|
11719 char *t = buf; |
|
11720 for (s = val; *s; s++) |
|
11721 if (*s != ' ' && *s != '\t' && !strchr(sep, *s)) |
|
11722 break; |
|
11723 if (*s == '"') |
|
11724 { s++; |
|
11725 while (*s && *s != '"' && --len) |
|
11726 *t++ = *s++; |
|
11727 } |
|
11728 else |
|
11729 { while (soap_notblank(*s) && !strchr(sep, *s) && --len) |
|
11730 { if (*s == '%') |
|
11731 { *t++ = ((s[1] >= 'A' ? (s[1] & 0x7) + 9 : s[1] - '0') << 4) |
|
11732 + (s[2] >= 'A' ? (s[2] & 0x7) + 9 : s[2] - '0'); |
|
11733 s += 3; |
|
11734 } |
|
11735 else |
|
11736 *t++ = *s++; |
|
11737 } |
|
11738 } |
|
11739 *t = '\0'; |
|
11740 while (*s && !strchr(sep, *s)) |
|
11741 s++; |
|
11742 return s; |
|
11743 } |
|
11744 #endif |
|
11745 #endif |
|
11746 |
|
11747 /******************************************************************************/ |
|
11748 #ifndef PALM_2 |
|
11749 SOAP_FMAC1 |
|
11750 int |
|
11751 SOAP_FMAC2 |
|
11752 soap_envelope_begin_out(struct soap *soap) |
|
11753 { |
|
11754 #ifndef WITH_LEANER |
|
11755 size_t n = 0; |
|
11756 if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && soap->mime.start) |
|
11757 { const char *s; |
|
11758 if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) |
|
11759 s = "application/dime"; |
|
11760 else if (soap->version == 2) |
|
11761 s = "application/soap+xml; charset=utf-8"; |
|
11762 else |
|
11763 s = "text/xml; charset=utf-8"; |
|
11764 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); |
|
11765 n = strlen(soap->tmpbuf); |
|
11766 if (soap_send_raw(soap, soap->tmpbuf, n)) |
|
11767 return soap->error; |
|
11768 } |
|
11769 if (soap->mode & SOAP_IO_LENGTH) |
|
11770 soap->dime.size = soap->count; /* DIME in MIME correction */ |
|
11771 if (!(soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME)) |
|
11772 { if (soap_putdimehdr(soap)) |
|
11773 return soap->error; |
|
11774 } |
|
11775 #endif |
|
11776 soap->part = SOAP_IN_ENVELOPE; |
|
11777 return soap_element_begin_out(soap, "SOAP-ENV:Envelope", 0, NULL); |
|
11778 } |
|
11779 #endif |
|
11780 |
|
11781 /******************************************************************************/ |
|
11782 #ifndef PALM_2 |
|
11783 SOAP_FMAC1 |
|
11784 int |
|
11785 SOAP_FMAC2 |
|
11786 soap_envelope_end_out(struct soap *soap) |
|
11787 { if (soap_element_end_out(soap, "SOAP-ENV:Envelope")) |
|
11788 return soap->error; |
|
11789 #ifndef WITH_LEANER |
|
11790 if ((soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) |
|
11791 { soap->dime.size = soap->count - soap->dime.size; /* DIME in MIME correction */ |
|
11792 sprintf(soap->id, soap->dime_id_format, 0); |
|
11793 soap->dime.id = soap->id; |
|
11794 if (soap->local_namespaces) |
|
11795 { if (soap->local_namespaces[0].out) |
|
11796 soap->dime.type = (char*)soap->local_namespaces[0].out; |
|
11797 else |
|
11798 soap->dime.type = (char*)soap->local_namespaces[0].ns; |
|
11799 } |
|
11800 soap->dime.options = NULL; |
|
11801 soap->dime.flags = SOAP_DIME_MB | SOAP_DIME_ABSURI; |
|
11802 if (!soap->dime.first) |
|
11803 soap->dime.flags |= SOAP_DIME_ME; |
|
11804 soap->count += 12 + ((strlen(soap->dime.id)+3)&(~3)) + ((strlen(soap->dime.type)+3)&(~3)); |
|
11805 } |
|
11806 if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) |
|
11807 return soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3); |
|
11808 #endif |
|
11809 soap->part = SOAP_END_ENVELOPE; |
|
11810 return SOAP_OK; |
|
11811 } |
|
11812 #endif |
|
11813 |
|
11814 /******************************************************************************/ |
|
11815 #ifndef PALM_1 |
|
11816 SOAP_FMAC1 |
|
11817 int |
|
11818 SOAP_FMAC2 |
|
11819 soap_envelope_begin_in(struct soap *soap) |
|
11820 { register struct Namespace *p; |
|
11821 soap->part = SOAP_IN_ENVELOPE; |
|
11822 if (soap_element_begin_in(soap, "SOAP-ENV:Envelope", 0)) |
|
11823 return soap->error = SOAP_VERSIONMISMATCH; |
|
11824 p = soap->local_namespaces; |
|
11825 if (p) |
|
11826 { const char *ns = p[0].out; |
|
11827 if (!ns) |
|
11828 ns = p[0].ns; |
|
11829 if (!strcmp(ns, soap_env1)) |
|
11830 { soap->version = 1; /* make sure we use SOAP 1.1 */ |
|
11831 if (p[1].out) |
|
11832 SOAP_FREE(soap, p[1].out); |
|
11833 if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc1)))) |
|
11834 strcpy(p[1].out, soap_enc1); |
|
11835 } |
|
11836 else if (!strcmp(ns, soap_env2)) |
|
11837 { soap->version = 2; /* make sure we use SOAP 1.2 */ |
|
11838 if (p[1].out) |
|
11839 SOAP_FREE(soap, p[1].out); |
|
11840 if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc2)))) |
|
11841 strcpy(p[1].out, soap_enc2); |
|
11842 } |
|
11843 } |
|
11844 return SOAP_OK; |
|
11845 } |
|
11846 #endif |
|
11847 |
|
11848 /******************************************************************************/ |
|
11849 #ifndef PALM_1 |
|
11850 SOAP_FMAC1 |
|
11851 int |
|
11852 SOAP_FMAC2 |
|
11853 soap_envelope_end_in(struct soap *soap) |
|
11854 { soap->part = SOAP_END_ENVELOPE; |
|
11855 return soap_element_end_in(soap, "SOAP-ENV:Envelope"); |
|
11856 } |
|
11857 #endif |
|
11858 |
|
11859 /******************************************************************************/ |
|
11860 #ifndef PALM_2 |
|
11861 SOAP_FMAC1 |
|
11862 int |
|
11863 SOAP_FMAC2 |
|
11864 soap_body_begin_out(struct soap *soap) |
|
11865 { soap->part = SOAP_IN_BODY; |
|
11866 if (soap->version == 1) |
|
11867 soap->encoding = 1; |
|
11868 #ifndef WITH_LEAN |
|
11869 if ((soap->mode & SOAP_XML_SEC) && soap_set_attr(soap, "wsu:Id", "Body")) |
|
11870 return soap->error; |
|
11871 #endif |
|
11872 if (soap_element(soap, "SOAP-ENV:Body", 0, NULL)) |
|
11873 return soap->error; |
|
11874 return soap_element_start_end_out(soap, NULL); |
|
11875 } |
|
11876 #endif |
|
11877 |
|
11878 /******************************************************************************/ |
|
11879 #ifndef PALM_2 |
|
11880 SOAP_FMAC1 |
|
11881 int |
|
11882 SOAP_FMAC2 |
|
11883 soap_body_end_out(struct soap *soap) |
|
11884 { if (soap_element_end_out(soap, "SOAP-ENV:Body")) |
|
11885 return soap->error; |
|
11886 soap->part = SOAP_END_BODY; |
|
11887 return SOAP_OK; |
|
11888 } |
|
11889 #endif |
|
11890 |
|
11891 /******************************************************************************/ |
|
11892 #ifndef PALM_2 |
|
11893 SOAP_FMAC1 |
|
11894 int |
|
11895 SOAP_FMAC2 |
|
11896 soap_body_begin_in(struct soap *soap) |
|
11897 { soap->part = SOAP_IN_BODY; |
|
11898 if (soap_element_begin_in(soap, "SOAP-ENV:Body", 0)) |
|
11899 return soap->error; |
|
11900 if (!soap->body) |
|
11901 soap->part = SOAP_NO_BODY; |
|
11902 return SOAP_OK; |
|
11903 } |
|
11904 #endif |
|
11905 |
|
11906 /******************************************************************************/ |
|
11907 #ifndef PALM_2 |
|
11908 SOAP_FMAC1 |
|
11909 int |
|
11910 SOAP_FMAC2 |
|
11911 soap_body_end_in(struct soap *soap) |
|
11912 { if (soap->part == SOAP_NO_BODY) |
|
11913 return SOAP_OK; |
|
11914 soap->part = SOAP_END_BODY; |
|
11915 return soap_element_end_in(soap, "SOAP-ENV:Body"); |
|
11916 } |
|
11917 #endif |
|
11918 |
|
11919 /******************************************************************************/ |
|
11920 #ifndef PALM_2 |
|
11921 SOAP_FMAC1 |
|
11922 int |
|
11923 SOAP_FMAC2 |
|
11924 soap_recv_header(struct soap *soap) |
|
11925 { if (soap_getheader(soap) && soap->error == SOAP_TAG_MISMATCH) |
|
11926 soap->error = SOAP_OK; |
|
11927 return soap->error; |
|
11928 } |
|
11929 #endif |
|
11930 |
|
11931 /******************************************************************************/ |
|
11932 #ifndef PALM_1 |
|
11933 SOAP_FMAC1 |
|
11934 void |
|
11935 SOAP_FMAC2 |
|
11936 soap_set_endpoint(struct soap *soap, const char *endpoint) |
|
11937 { register const char *s; |
|
11938 register size_t i, n; |
|
11939 soap->endpoint[0] = '\0'; |
|
11940 soap->host[0] = '\0'; |
|
11941 soap->path[0] = '/'; |
|
11942 soap->path[1] = '\0'; |
|
11943 soap->port = 80; |
|
11944 if (!endpoint || !*endpoint) |
|
11945 return; |
|
11946 if (!strncmp(endpoint, "https:", 6)) |
|
11947 soap->port = 443; |
|
11948 strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint) - 1); |
|
11949 s = strchr(endpoint, ':'); |
|
11950 if (s && s[1] == '/' && s[2] == '/') |
|
11951 s += 3; |
|
11952 else |
|
11953 s = endpoint; |
|
11954 n = strlen(s); |
|
11955 if (n >= sizeof(soap->host)) |
|
11956 n = sizeof(soap->host) - 1; |
|
11957 #ifdef WITH_IPV6 |
|
11958 if (s[0] == '[') |
|
11959 { s++; |
|
11960 for (i = 0; i < n; i++) |
|
11961 { soap->host[i] = s[i]; |
|
11962 if (s[i] == ']') |
|
11963 { s++; |
|
11964 break; |
|
11965 } |
|
11966 } |
|
11967 } |
|
11968 else |
|
11969 { for (i = 0; i < n; i++) |
|
11970 { soap->host[i] = s[i]; |
|
11971 if (s[i] == '/' || s[i] == ':') |
|
11972 break; |
|
11973 } |
|
11974 } |
|
11975 #else |
|
11976 for (i = 0; i < n; i++) |
|
11977 { soap->host[i] = s[i]; |
|
11978 if (s[i] == '/' || s[i] == ':') |
|
11979 break; |
|
11980 } |
|
11981 #endif |
|
11982 soap->host[i] = '\0'; |
|
11983 if (s[i] == ':') |
|
11984 { soap->port = (int)atol(s + i + 1); |
|
11985 for (i++; i < n; i++) |
|
11986 if (s[i] == '/') |
|
11987 break; |
|
11988 } |
|
11989 if (s[i]) |
|
11990 { strncpy(soap->path, s + i, sizeof(soap->path)); |
|
11991 soap->path[sizeof(soap->path) - 1] = '\0'; |
|
11992 } |
|
11993 } |
|
11994 #endif |
|
11995 |
|
11996 /******************************************************************************/ |
|
11997 #ifndef PALM_1 |
|
11998 SOAP_FMAC1 |
|
11999 int |
|
12000 SOAP_FMAC2 |
|
12001 soap_connect(struct soap *soap, const char *endpoint, const char *action) |
|
12002 { return soap_connect_command(soap, SOAP_POST, endpoint, action); |
|
12003 } |
|
12004 #endif |
|
12005 |
|
12006 /******************************************************************************/ |
|
12007 #ifndef PALM_1 |
|
12008 SOAP_FMAC1 |
|
12009 int |
|
12010 SOAP_FMAC2 |
|
12011 soap_connect_command(struct soap *soap, int http_command, const char *endpoint, const char *action) |
|
12012 { char host[sizeof(soap->host)]; |
|
12013 int port; |
|
12014 size_t count; |
|
12015 soap->error = SOAP_OK; |
|
12016 strcpy(host, soap->host); /* save to compare */ |
|
12017 port = soap->port; /* save to compare */ |
|
12018 soap_set_endpoint(soap, endpoint); |
|
12019 #ifndef WITH_LEANER |
|
12020 if (soap->fconnect) |
|
12021 { if ((soap->error = soap->fconnect(soap, endpoint, soap->host, soap->port))) |
|
12022 return soap->error; |
|
12023 } |
|
12024 else |
|
12025 #endif |
|
12026 if (soap->fopen && *soap->host) |
|
12027 { soap->status = http_command; |
|
12028 if (!soap->keep_alive || !soap_valid_socket(soap->socket) || strcmp(soap->host, host) || soap->port != port || !soap->fpoll || soap->fpoll(soap)) |
|
12029 { soap->keep_alive = 0; /* to force close */ |
|
12030 soap->omode &= ~SOAP_IO_UDP; /* to force close */ |
|
12031 soap_closesock(soap); |
|
12032 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Connect/reconnect to host='%s' path='%s' port=%d\n", soap->host, soap->path, soap->port)); |
|
12033 #ifdef WITH_UDP |
|
12034 if (!strncmp(endpoint, "soap.udp:", 9)) |
|
12035 soap->omode |= SOAP_IO_UDP; |
|
12036 #endif |
|
12037 soap->socket = soap->fopen(soap, endpoint, soap->host, soap->port); |
|
12038 if (soap->error) |
|
12039 return soap->error; |
|
12040 soap->keep_alive = ((soap->omode & SOAP_IO_KEEPALIVE) != 0); |
|
12041 } |
|
12042 } |
|
12043 count = soap_count_attachments(soap); |
|
12044 if (soap_begin_send(soap)) |
|
12045 return soap->error; |
|
12046 #ifndef WITH_NOHTTP |
|
12047 if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML) && endpoint) |
|
12048 { unsigned int k = soap->mode; |
|
12049 soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB); |
|
12050 if ((k & SOAP_IO) != SOAP_IO_FLUSH) |
|
12051 soap->mode |= SOAP_IO_BUFFER; |
|
12052 if ((soap->error = soap->fpost(soap, endpoint, soap->host, soap->port, soap->path, action, count))) |
|
12053 return soap->error; |
|
12054 #ifndef WITH_LEANER |
|
12055 if ((k & SOAP_IO) == SOAP_IO_CHUNK) |
|
12056 { if (soap_flush(soap)) |
|
12057 return soap->error; |
|
12058 } |
|
12059 #endif |
|
12060 soap->mode = k; |
|
12061 } |
|
12062 else if (action) |
|
12063 soap->action = soap_strdup(soap, action); |
|
12064 if (http_command != SOAP_POST) |
|
12065 return soap_end_send(soap); |
|
12066 #endif |
|
12067 return SOAP_OK; |
|
12068 } |
|
12069 #endif |
|
12070 |
|
12071 /******************************************************************************/ |
|
12072 #ifndef WITH_LEAN |
|
12073 SOAP_FMAC1 |
|
12074 char* |
|
12075 SOAP_FMAC2 |
|
12076 soap_s2base64(struct soap *soap, const unsigned char *s, char *t, int n) |
|
12077 { register int i; |
|
12078 register unsigned long m; |
|
12079 register char *p; |
|
12080 if (!t) |
|
12081 t = (char*)soap_malloc(soap, (n + 2) / 3 * 4 + 1); |
|
12082 if (!t) |
|
12083 { soap->error = SOAP_EOM; |
|
12084 return NULL; |
|
12085 } |
|
12086 p = t; |
|
12087 t[0] = '\0'; |
|
12088 if (!s) |
|
12089 return p; |
|
12090 for (; n > 2; n -= 3, s += 3) |
|
12091 { m = s[0]; |
|
12092 m = (m << 8) | s[1]; |
|
12093 m = (m << 8) | s[2]; |
|
12094 for (i = 4; i > 0; m >>= 6) |
|
12095 t[--i] = soap_base64o[m & 0x3F]; |
|
12096 t += 4; |
|
12097 } |
|
12098 t[0] = '\0'; |
|
12099 if (n > 0) |
|
12100 { m = 0; |
|
12101 for (i = 0; i < n; i++) |
|
12102 m = (m << 8) | *s++; |
|
12103 for (; i < 3; i++) |
|
12104 m <<= 8; |
|
12105 for (i++; i > 0; m >>= 6) |
|
12106 t[--i] = soap_base64o[m & 0x3F]; |
|
12107 for (i = 3; i > n; i--) |
|
12108 t[i] = '='; |
|
12109 t[4] = '\0'; |
|
12110 } |
|
12111 return p; |
|
12112 } |
|
12113 #endif |
|
12114 |
|
12115 /******************************************************************************/ |
|
12116 #ifndef WITH_LEAN |
|
12117 SOAP_FMAC1 |
|
12118 const char* |
|
12119 SOAP_FMAC2 |
|
12120 soap_base642s(struct soap *soap, const char *s, char *t, size_t l, int *n) |
|
12121 { register int i, j, c; |
|
12122 register unsigned long m; |
|
12123 register const char *p; |
|
12124 if (!s || !*s) |
|
12125 { if (n) |
|
12126 *n = 0; |
|
12127 if (soap->error) |
|
12128 return NULL; |
|
12129 return SOAP_NON_NULL; |
|
12130 } |
|
12131 if (!t) |
|
12132 { l = (strlen(s) + 3) / 4 * 3; |
|
12133 t = (char*)soap_malloc(soap, l); |
|
12134 } |
|
12135 if (!t) |
|
12136 { soap->error = SOAP_EOM; |
|
12137 return NULL; |
|
12138 } |
|
12139 p = t; |
|
12140 if (n) |
|
12141 *n = 0; |
|
12142 for (;;) |
|
12143 { for (i = 0; i < SOAP_BLKLEN; i++) |
|
12144 { m = 0; |
|
12145 j = 0; |
|
12146 while (j < 4) |
|
12147 { c = *s++; |
|
12148 if (c == '=' || !c) |
|
12149 { i *= 3; |
|
12150 switch (j) |
|
12151 { case 2: |
|
12152 *t++ = (char)((m >> 4) & 0xFF); |
|
12153 i++; |
|
12154 break; |
|
12155 case 3: |
|
12156 *t++ = (char)((m >> 10) & 0xFF); |
|
12157 *t++ = (char)((m >> 2) & 0xFF); |
|
12158 i += 2; |
|
12159 } |
|
12160 if (n) |
|
12161 *n += i; |
|
12162 return p; |
|
12163 } |
|
12164 c -= '+'; |
|
12165 if (c >= 0 && c <= 79) |
|
12166 { m = (m << 6) + soap_base64i[c]; |
|
12167 j++; |
|
12168 } |
|
12169 } |
|
12170 *t++ = (char)((m >> 16) & 0xFF); |
|
12171 *t++ = (char)((m >> 8) & 0xFF); |
|
12172 *t++ = (char)(m & 0xFF); |
|
12173 if (l < 3) |
|
12174 { if (n) |
|
12175 *n += i; |
|
12176 return p; |
|
12177 } |
|
12178 l -= 3; |
|
12179 } |
|
12180 if (n) |
|
12181 *n += 3 * SOAP_BLKLEN; |
|
12182 } |
|
12183 } |
|
12184 #endif |
|
12185 |
|
12186 /******************************************************************************/ |
|
12187 #ifndef WITH_LEAN |
|
12188 SOAP_FMAC1 |
|
12189 char* |
|
12190 SOAP_FMAC2 |
|
12191 soap_s2hex(struct soap *soap, const unsigned char *s, char *t, int n) |
|
12192 { register char *p; |
|
12193 if (!t) |
|
12194 t = (char*)soap_malloc(soap, 2 * n + 1); |
|
12195 if (!t) |
|
12196 { soap->error = SOAP_EOM; |
|
12197 return NULL; |
|
12198 } |
|
12199 p = t; |
|
12200 t[0] = '\0'; |
|
12201 if (s) |
|
12202 { for (; n > 0; n--) |
|
12203 { register int m = *s++; |
|
12204 *t++ = (char)((m >> 4) + (m > 159 ? 'a' - 10 : '0')); |
|
12205 m &= 0x0F; |
|
12206 *t++ = (char)(m + (m > 9 ? 'a' - 10 : '0')); |
|
12207 } |
|
12208 } |
|
12209 *t++ = '\0'; |
|
12210 return p; |
|
12211 } |
|
12212 #endif |
|
12213 |
|
12214 /******************************************************************************/ |
|
12215 #ifndef WITH_LEAN |
|
12216 SOAP_FMAC1 |
|
12217 const char* |
|
12218 SOAP_FMAC2 |
|
12219 soap_hex2s(struct soap *soap, const char *s, char *t, size_t l, int *n) |
|
12220 { register const char *p; |
|
12221 if (!s || !*s) |
|
12222 { if (n) |
|
12223 *n = 0; |
|
12224 if (soap->error) |
|
12225 return NULL; |
|
12226 return SOAP_NON_NULL; |
|
12227 } |
|
12228 if (!t) |
|
12229 { l = strlen(s) / 2; |
|
12230 t = (char*)soap_malloc(soap, l); |
|
12231 } |
|
12232 if (!t) |
|
12233 { soap->error = SOAP_EOM; |
|
12234 return NULL; |
|
12235 } |
|
12236 p = t; |
|
12237 while (l) |
|
12238 { register int d1, d2; |
|
12239 d1 = *s++; |
|
12240 if (!d1) |
|
12241 break; |
|
12242 d2 = *s++; |
|
12243 if (!d2) |
|
12244 break; |
|
12245 *t++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'); |
|
12246 l--; |
|
12247 } |
|
12248 if (n) |
|
12249 *n = t - p; |
|
12250 return p; |
|
12251 } |
|
12252 #endif |
|
12253 |
|
12254 /******************************************************************************/ |
|
12255 #ifndef WITH_NOHTTP |
|
12256 #ifndef PALM_1 |
|
12257 SOAP_FMAC1 |
|
12258 int |
|
12259 SOAP_FMAC2 |
|
12260 soap_puthttphdr(struct soap *soap, int status, size_t count) |
|
12261 { register const char *s; |
|
12262 #ifndef WITH_LEANER |
|
12263 register const char *r = NULL; |
|
12264 #endif |
|
12265 register int err; |
|
12266 if (status == SOAP_FILE && soap->http_content) |
|
12267 s = soap->http_content; |
|
12268 else if (status == SOAP_HTML) |
|
12269 s = "text/html; charset=utf-8"; |
|
12270 else if (soap->version == 2) |
|
12271 s = "application/soap+xml; charset=utf-8"; |
|
12272 else |
|
12273 s = "text/xml; charset=utf-8"; |
|
12274 #ifndef WITH_LEANER |
|
12275 if (soap->mode & (SOAP_ENC_DIME | SOAP_ENC_MTOM)) |
|
12276 { if (soap->mode & SOAP_ENC_MTOM) |
|
12277 { r = s; |
|
12278 s = "application/xop+xml; charset=utf-8"; |
|
12279 } |
|
12280 else |
|
12281 s = "application/dime"; |
|
12282 } |
|
12283 if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && soap->status != SOAP_GET) |
|
12284 { register const char *t = strchr(s, ';'); |
|
12285 sprintf(soap->tmpbuf, "multipart/related; boundary=\"%s\"; type=\"", soap->mime.boundary); |
|
12286 if (t) |
|
12287 strncat(soap->tmpbuf, s, t - s); |
|
12288 else |
|
12289 strcat(soap->tmpbuf, s); |
|
12290 if (soap->mime.start) |
|
12291 { strcat(soap->tmpbuf, "\"; start=\""); |
|
12292 strcat(soap->tmpbuf, soap->mime.start); |
|
12293 } |
|
12294 strcat(soap->tmpbuf, "\""); |
|
12295 if (r) |
|
12296 { strcat(soap->tmpbuf, "; start-info=\""); |
|
12297 strcat(soap->tmpbuf, r); |
|
12298 strcat(soap->tmpbuf, "\""); |
|
12299 } |
|
12300 s = soap->tmpbuf; |
|
12301 } |
|
12302 #endif |
|
12303 if ((err = soap->fposthdr(soap, "Content-Type", s))) |
|
12304 return err; |
|
12305 #ifdef WITH_ZLIB |
|
12306 if (soap->omode & SOAP_ENC_ZLIB) |
|
12307 { |
|
12308 #ifdef WITH_GZIP |
|
12309 err = soap->fposthdr(soap, "Content-Encoding", "gzip"); |
|
12310 #else |
|
12311 err = soap->fposthdr(soap, "Content-Encoding", "deflate"); |
|
12312 #endif |
|
12313 if (err) |
|
12314 return err; |
|
12315 } |
|
12316 #endif |
|
12317 #ifndef WITH_LEANER |
|
12318 if ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK) |
|
12319 err = soap->fposthdr(soap, "Transfer-Encoding", "chunked"); |
|
12320 else |
|
12321 #endif |
|
12322 if (count > 0) |
|
12323 { sprintf(soap->tmpbuf, "%lu", (unsigned long)count); |
|
12324 err = soap->fposthdr(soap, "Content-Length", soap->tmpbuf); |
|
12325 } |
|
12326 if (err) |
|
12327 return err; |
|
12328 return soap->fposthdr(soap, "Connection", soap->keep_alive ? "keep-alive" : "close"); |
|
12329 } |
|
12330 #endif |
|
12331 #endif |
|
12332 |
|
12333 /******************************************************************************/ |
|
12334 #ifndef WITH_NOHTTP |
|
12335 #ifndef PALM_1 |
|
12336 static int |
|
12337 http_get(struct soap *soap) |
|
12338 { return SOAP_GET_METHOD; |
|
12339 } |
|
12340 #endif |
|
12341 #endif |
|
12342 |
|
12343 /******************************************************************************/ |
|
12344 #ifndef WITH_NOHTTP |
|
12345 #ifndef PALM_1 |
|
12346 static int |
|
12347 http_post(struct soap *soap, const char *endpoint, const char *host, int port, const char *path, const char *action, size_t count) |
|
12348 { register const char *s; |
|
12349 register int err; |
|
12350 if (soap->status == SOAP_GET) |
|
12351 { s = "GET"; |
|
12352 count = 0; |
|
12353 } |
|
12354 else |
|
12355 s = "POST"; |
|
12356 #ifdef PALM |
|
12357 if (!endpoint || (strncmp(endpoint, "http:", 5) && strncmp(endpoint, "https:", 6) && strncmp(endpoint, "httpg:", 6)) && strncmp(endpoint, "_beam:", 6) && strncmp(endpoint, "_local:", 7) && strncmp(endpoint, "_btobex:", 8)) |
|
12358 #else |
|
12359 if (!endpoint || (strncmp(endpoint, "http:", 5) && strncmp(endpoint, "https:", 6) && strncmp(endpoint, "httpg:", 6))) |
|
12360 #endif |
|
12361 return SOAP_OK; |
|
12362 if (soap->proxy_host && strncmp(endpoint, "https:", 6)) |
|
12363 sprintf(soap->tmpbuf, "%s %s HTTP/%s", s, endpoint, soap->http_version); |
|
12364 else |
|
12365 sprintf(soap->tmpbuf, "%s /%s HTTP/%s", s, (*path == '/' ? path + 1 : path), soap->http_version); |
|
12366 if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) |
|
12367 return err; |
|
12368 if (port != 80) |
|
12369 sprintf(soap->tmpbuf, "%s:%d", host, port); |
|
12370 else |
|
12371 strcpy(soap->tmpbuf, host); |
|
12372 if ((err = soap->fposthdr(soap, "Host", soap->tmpbuf)) |
|
12373 || (err = soap->fposthdr(soap, "User-Agent", "gSOAP/2.7")) |
|
12374 || (err = soap_puthttphdr(soap, SOAP_OK, count))) |
|
12375 return err; |
|
12376 #ifdef WITH_ZLIB |
|
12377 #ifdef WITH_GZIP |
|
12378 if ((err = soap->fposthdr(soap, "Accept-Encoding", "gzip, deflate"))) |
|
12379 #else |
|
12380 if ((err = soap->fposthdr(soap, "Accept-Encoding", "deflate"))) |
|
12381 #endif |
|
12382 return err; |
|
12383 #endif |
|
12384 #ifndef WITH_LEAN |
|
12385 if (soap->userid && soap->passwd && strlen(soap->userid) + strlen(soap->passwd) < 761) |
|
12386 { sprintf(soap->tmpbuf + 262, "%s:%s", soap->userid, soap->passwd); |
|
12387 strcpy(soap->tmpbuf, "Basic "); |
|
12388 soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, strlen(soap->tmpbuf + 262)); |
|
12389 if ((err = soap->fposthdr(soap, "Authorization", soap->tmpbuf))) |
|
12390 return err; |
|
12391 } |
|
12392 if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761) |
|
12393 { sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd); |
|
12394 strcpy(soap->tmpbuf, "Basic "); |
|
12395 soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, strlen(soap->tmpbuf + 262)); |
|
12396 if ((err = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf))) |
|
12397 return err; |
|
12398 } |
|
12399 #endif |
|
12400 #ifdef WITH_COOKIES |
|
12401 #ifdef WITH_OPENSSL |
|
12402 if (soap_putcookies(soap, host, path, soap->ssl != NULL)) |
|
12403 return soap->error; |
|
12404 #else |
|
12405 if (soap_putcookies(soap, host, path, 0)) |
|
12406 return soap->error; |
|
12407 #endif |
|
12408 #endif |
|
12409 if (action && soap->version == 1) |
|
12410 { sprintf(soap->tmpbuf, "\"%s\"", action); |
|
12411 if ((err = soap->fposthdr(soap, "SOAPAction", soap->tmpbuf))) |
|
12412 return err; |
|
12413 } |
|
12414 return soap->fposthdr(soap, NULL, NULL); |
|
12415 } |
|
12416 #endif |
|
12417 #endif |
|
12418 |
|
12419 /******************************************************************************/ |
|
12420 #ifndef WITH_NOHTTP |
|
12421 #ifndef PALM_1 |
|
12422 static int |
|
12423 http_send_header(struct soap *soap, const char *s) |
|
12424 { register const char *t; |
|
12425 do |
|
12426 { t = strchr(s, '\n'); /* disallow \n in HTTP headers */ |
|
12427 if (!t) |
|
12428 t = s + strlen(s); |
|
12429 if (soap_send_raw(soap, s, t - s)) |
|
12430 return soap->error; |
|
12431 s = t + 1; |
|
12432 } while (*t); |
|
12433 return SOAP_OK; |
|
12434 } |
|
12435 #endif |
|
12436 #endif |
|
12437 |
|
12438 /******************************************************************************/ |
|
12439 #ifndef WITH_NOHTTP |
|
12440 #ifndef PALM_1 |
|
12441 static int |
|
12442 http_post_header(struct soap *soap, const char *key, const char *val) |
|
12443 { if (key) |
|
12444 { if (http_send_header(soap, key)) |
|
12445 return soap->error; |
|
12446 if (val && (soap_send_raw(soap, ": ", 2) || http_send_header(soap, val))) |
|
12447 return soap->error; |
|
12448 } |
|
12449 return soap_send_raw(soap, "\r\n", 2); |
|
12450 } |
|
12451 #endif |
|
12452 #endif |
|
12453 |
|
12454 /******************************************************************************/ |
|
12455 #ifndef WITH_NOHTTP |
|
12456 #ifndef PALM_1 |
|
12457 static int |
|
12458 http_response(struct soap *soap, int status, size_t count) |
|
12459 { register int err; |
|
12460 #ifdef WMW_RPM_IO |
|
12461 if (soap->rpmreqid) |
|
12462 httpOutputEnable(soap->rpmreqid); |
|
12463 #endif /* WMW_RPM_IO */ |
|
12464 if (!status || status == SOAP_HTML || status == SOAP_FILE) |
|
12465 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "OK 200\n")); |
|
12466 #ifdef WMW_RPM_IO |
|
12467 if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */ |
|
12468 #else |
|
12469 if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application */ |
|
12470 #endif /* WMW_RPM_IO */ |
|
12471 { sprintf(soap->tmpbuf, "HTTP/%s 200 OK", soap->http_version); |
|
12472 if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) |
|
12473 return err; |
|
12474 } |
|
12475 else if ((err = soap->fposthdr(soap, "Status", "200 OK"))) |
|
12476 return err; |
|
12477 } |
|
12478 else if (status > 200 && status < 600) |
|
12479 { sprintf(soap->tmpbuf, "HTTP/%s %d %s", soap->http_version, status, http_error(soap, status)); |
|
12480 if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) |
|
12481 return err; |
|
12482 #ifndef WITH_LEAN |
|
12483 if (status == 401) |
|
12484 { sprintf(soap->tmpbuf, "Basic realm=\"%s\"", soap->authrealm ? soap->authrealm : "gSOAP Web Service"); |
|
12485 if ((err = soap->fposthdr(soap, "WWW-Authenticate", soap->tmpbuf))) |
|
12486 return err; |
|
12487 } |
|
12488 else if ((status >= 301 && status <= 303) || status == 307) |
|
12489 { if ((err = soap->fposthdr(soap, "Location", soap->endpoint))) |
|
12490 return err; |
|
12491 } |
|
12492 #endif |
|
12493 } |
|
12494 else |
|
12495 { const char *s = *soap_faultcode(soap); |
|
12496 if (soap->version == 2 && !strcmp(s, "SOAP-ENV:Sender")) |
|
12497 s = "400 Bad Request"; |
|
12498 else |
|
12499 s = "500 Internal Server Error"; |
|
12500 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error %s (status=%d)\n", s, status)); |
|
12501 #ifdef WMW_RPM_IO |
|
12502 if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */ |
|
12503 #else |
|
12504 if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application */ |
|
12505 #endif /* WMW_RPM_IO */ |
|
12506 { sprintf(soap->tmpbuf, "HTTP/%s %s", soap->http_version, s); |
|
12507 if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) |
|
12508 return err; |
|
12509 } |
|
12510 else if ((err = soap->fposthdr(soap, "Status", s))) |
|
12511 return err; |
|
12512 } |
|
12513 if ((err = soap->fposthdr(soap, "Server", "gSOAP/2.7")) |
|
12514 || (err = soap_puthttphdr(soap, status, count))) |
|
12515 return err; |
|
12516 #ifdef WITH_COOKIES |
|
12517 if (soap_putsetcookies(soap)) |
|
12518 return soap->error; |
|
12519 #endif |
|
12520 return soap->fposthdr(soap, NULL, NULL); |
|
12521 } |
|
12522 #endif |
|
12523 #endif |
|
12524 |
|
12525 /******************************************************************************/ |
|
12526 #ifndef PALM_1 |
|
12527 SOAP_FMAC1 |
|
12528 int |
|
12529 SOAP_FMAC2 |
|
12530 soap_response(struct soap *soap, int status) |
|
12531 { register size_t count; |
|
12532 if (!(soap->omode & (SOAP_ENC_XML | SOAP_IO_STORE /* this tests for chunking too */)) |
|
12533 && (status == SOAP_HTML || status == SOAP_FILE)) |
|
12534 { soap->omode &= ~SOAP_IO; |
|
12535 soap->omode |= SOAP_IO_STORE; |
|
12536 } |
|
12537 soap->status = status; |
|
12538 count = soap_count_attachments(soap); |
|
12539 if (soap_begin_send(soap)) |
|
12540 return soap->error; |
|
12541 #ifndef WITH_NOHTTP |
|
12542 if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML)) |
|
12543 { register int n = soap->mode; |
|
12544 soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB); |
|
12545 if ((n & SOAP_IO) != SOAP_IO_FLUSH) |
|
12546 soap->mode |= SOAP_IO_BUFFER; |
|
12547 if ((soap->error = soap->fresponse(soap, status, count))) |
|
12548 return soap->error; |
|
12549 #ifndef WITH_LEANER |
|
12550 if ((n & SOAP_IO) == SOAP_IO_CHUNK) |
|
12551 { if (soap_flush(soap)) |
|
12552 return soap->error; |
|
12553 } |
|
12554 #endif |
|
12555 soap->mode = n; |
|
12556 } |
|
12557 #endif |
|
12558 return SOAP_OK; |
|
12559 } |
|
12560 #endif |
|
12561 |
|
12562 /******************************************************************************/ |
|
12563 #ifndef WITH_LEAN |
|
12564 static const char* |
|
12565 soap_set_validation_fault(struct soap *soap, const char *s, const char *t) |
|
12566 { if (*soap->tag) |
|
12567 sprintf(soap->msgbuf, "Validation constraint violation: %s%s in element <%s>", s, t?t:SOAP_STR_EOS, soap->tag); |
|
12568 else |
|
12569 sprintf(soap->msgbuf, "Validation constraint violation: %s%s", s, t?t:SOAP_STR_EOS); |
|
12570 return soap->msgbuf; |
|
12571 } |
|
12572 #endif |
|
12573 |
|
12574 /******************************************************************************/ |
|
12575 #ifndef PALM_1 |
|
12576 SOAP_FMAC1 |
|
12577 void |
|
12578 SOAP_FMAC2 |
|
12579 soap_set_fault(struct soap *soap) |
|
12580 { const char **c = soap_faultcode(soap); |
|
12581 const char **s = soap_faultstring(soap); |
|
12582 if (!*c && !*s && soap->fseterror) |
|
12583 soap->fseterror(soap, c, s); |
|
12584 if (!*c) |
|
12585 { if (soap->version == 2) |
|
12586 *c = "SOAP-ENV:Sender"; |
|
12587 else |
|
12588 *c = "SOAP-ENV:Client"; |
|
12589 } |
|
12590 if (*s) |
|
12591 return; |
|
12592 switch (soap->error) |
|
12593 { |
|
12594 #ifndef WITH_LEAN |
|
12595 case SOAP_CLI_FAULT: |
|
12596 *s = "Client fault"; |
|
12597 break; |
|
12598 case SOAP_SVR_FAULT: |
|
12599 *s = "Server fault"; |
|
12600 break; |
|
12601 case SOAP_TAG_MISMATCH: |
|
12602 *s = soap_set_validation_fault(soap, "tag name or namespace mismatch", NULL); |
|
12603 break; |
|
12604 case SOAP_TYPE: |
|
12605 *s = soap_set_validation_fault(soap, "data type mismatch ", soap->type); |
|
12606 break; |
|
12607 case SOAP_SYNTAX_ERROR: |
|
12608 *s = "Well-formedness violation"; |
|
12609 break; |
|
12610 case SOAP_NO_TAG: |
|
12611 *s = "No XML element tag"; |
|
12612 break; |
|
12613 case SOAP_MUSTUNDERSTAND: |
|
12614 *c = "SOAP-ENV:MustUnderstand"; |
|
12615 sprintf(soap->msgbuf, "The data in element '%s' must be understood but cannot be handled", soap->tag); |
|
12616 *s = soap->msgbuf; |
|
12617 break; |
|
12618 case SOAP_VERSIONMISMATCH: |
|
12619 *c = "SOAP-ENV:VersionMismatch"; |
|
12620 *s = "SOAP version mismatch or invalid SOAP message"; |
|
12621 break; |
|
12622 case SOAP_DATAENCODINGUNKNOWN: |
|
12623 *c = "SOAP-ENV:DataEncodingUnknown"; |
|
12624 *s = "Unsupported SOAP data encoding"; |
|
12625 break; |
|
12626 case SOAP_NAMESPACE: |
|
12627 *s = soap_set_validation_fault(soap, "namespace mismatch", NULL); |
|
12628 break; |
|
12629 case SOAP_USER_ERROR: |
|
12630 *s = "User error"; |
|
12631 break; |
|
12632 case SOAP_FATAL_ERROR: |
|
12633 *s = "Fatal error"; |
|
12634 break; |
|
12635 case SOAP_NO_METHOD: |
|
12636 sprintf(soap->msgbuf, "Method '%s' not implemented: method name or namespace not recognized", soap->tag); |
|
12637 *s = soap->msgbuf; |
|
12638 break; |
|
12639 case SOAP_GET_METHOD: |
|
12640 *s = "HTTP GET method not implemented"; |
|
12641 break; |
|
12642 case SOAP_EOM: |
|
12643 *s = "Out of memory"; |
|
12644 break; |
|
12645 case SOAP_IOB: |
|
12646 *s = "Array index out of bounds"; |
|
12647 break; |
|
12648 case SOAP_NULL: |
|
12649 *s = soap_set_validation_fault(soap, "nil not allowed", NULL); |
|
12650 break; |
|
12651 case SOAP_DUPLICATE_ID: |
|
12652 *s = soap_set_validation_fault(soap, "multiple definitions of id ", soap->id); |
|
12653 if (soap->version == 2) |
|
12654 *soap_faultsubcode(soap) = "SOAP-ENC:DuplicateID"; |
|
12655 break; |
|
12656 case SOAP_MISSING_ID: |
|
12657 *s = soap_set_validation_fault(soap, "missing id for ref ", soap->id); |
|
12658 if (soap->version == 2) |
|
12659 *soap_faultsubcode(soap) = "SOAP-ENC:MissingID"; |
|
12660 break; |
|
12661 case SOAP_HREF: |
|
12662 *s = soap_set_validation_fault(soap, "incompatible object ref ", soap->id); |
|
12663 break; |
|
12664 case SOAP_FAULT: |
|
12665 break; |
|
12666 #ifndef WITH_NOIO |
|
12667 case SOAP_UDP_ERROR: |
|
12668 *s = "Message too large for UDP packet"; |
|
12669 break; |
|
12670 case SOAP_TCP_ERROR: |
|
12671 *s = tcp_error(soap); |
|
12672 break; |
|
12673 #endif |
|
12674 case SOAP_HTTP_ERROR: |
|
12675 *s = "HTTP error"; |
|
12676 break; |
|
12677 case SOAP_SSL_ERROR: |
|
12678 #ifdef WITH_OPENSSL |
|
12679 *s = "SSL error"; |
|
12680 #else |
|
12681 *s = "OpenSSL not installed: recompile with -DWITH_OPENSSL"; |
|
12682 #endif |
|
12683 break; |
|
12684 case SOAP_PLUGIN_ERROR: |
|
12685 *s = "Plugin registry error"; |
|
12686 break; |
|
12687 case SOAP_DIME_ERROR: |
|
12688 *s = "DIME format error"; |
|
12689 break; |
|
12690 case SOAP_DIME_HREF: |
|
12691 *s = "DIME href to missing attachment"; |
|
12692 break; |
|
12693 case SOAP_DIME_MISMATCH: |
|
12694 *s = "DIME version/transmission error"; |
|
12695 break; |
|
12696 case SOAP_DIME_END: |
|
12697 *s = "End of DIME error"; |
|
12698 break; |
|
12699 case SOAP_MIME_ERROR: |
|
12700 *s = "MIME format error"; |
|
12701 break; |
|
12702 case SOAP_MIME_HREF: |
|
12703 *s = "MIME href to missing attachment"; |
|
12704 break; |
|
12705 case SOAP_MIME_END: |
|
12706 *s = "End of MIME error"; |
|
12707 break; |
|
12708 case SOAP_ZLIB_ERROR: |
|
12709 #ifdef WITH_ZLIB |
|
12710 sprintf(soap->msgbuf, "Zlib/gzip error: '%s'", soap->d_stream.msg?soap->d_stream.msg:""); |
|
12711 *s = soap->msgbuf; |
|
12712 #else |
|
12713 *s = "Zlib/gzip not installed for (de)compression: recompile with -DWITH_GZIP"; |
|
12714 #endif |
|
12715 break; |
|
12716 case SOAP_REQUIRED: |
|
12717 *s = soap_set_validation_fault(soap, "missing required attribute", NULL); |
|
12718 break; |
|
12719 case SOAP_PROHIBITED: |
|
12720 *s = soap_set_validation_fault(soap, "prohibited attribute present", NULL); |
|
12721 break; |
|
12722 case SOAP_OCCURS: |
|
12723 *s = soap_set_validation_fault(soap, "min/maxOccurs violation", NULL); |
|
12724 break; |
|
12725 case SOAP_LENGTH: |
|
12726 *s = soap_set_validation_fault(soap, "content length violation", NULL); |
|
12727 break; |
|
12728 case SOAP_STOP: |
|
12729 *s = "Stopped: no response sent"; |
|
12730 break; |
|
12731 #endif |
|
12732 case SOAP_EOF: |
|
12733 #ifndef WITH_NOIO |
|
12734 sprintf(soap->msgbuf, "End of file or no input: '%s'", soap_strerror(soap)); |
|
12735 *s = soap->msgbuf; |
|
12736 break; |
|
12737 #else |
|
12738 *s = "End of file or no input"; |
|
12739 break; |
|
12740 #endif |
|
12741 default: |
|
12742 #ifndef WITH_NOHTTP |
|
12743 #ifndef WITH_LEAN |
|
12744 if (soap->error > 200 && soap->error < 600) |
|
12745 { sprintf(soap->msgbuf, "HTTP Error: %d %s", soap->error, http_error(soap, soap->error)); |
|
12746 *s = soap->msgbuf; |
|
12747 } |
|
12748 else |
|
12749 #endif |
|
12750 #endif |
|
12751 { sprintf(soap->msgbuf, "Error %d", soap->error); |
|
12752 *s = soap->msgbuf; |
|
12753 } |
|
12754 } |
|
12755 } |
|
12756 #endif |
|
12757 |
|
12758 /******************************************************************************/ |
|
12759 #ifndef PALM_1 |
|
12760 SOAP_FMAC1 |
|
12761 int |
|
12762 SOAP_FMAC2 |
|
12763 soap_send_fault(struct soap *soap) |
|
12764 { register int status = soap->error; |
|
12765 int r = 1; |
|
12766 if (status == SOAP_STOP) |
|
12767 return status; |
|
12768 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Sending back fault struct for error code %d\n", soap->error)); |
|
12769 soap->keep_alive = 0; /* to terminate connection */ |
|
12770 soap_set_fault(soap); |
|
12771 #ifndef WITH_NOIO |
|
12772 #ifndef WITH_LEAN |
|
12773 if (soap_valid_socket(soap->socket)) |
|
12774 { struct timeval timeout; |
|
12775 fd_set rfd, sfd; |
|
12776 timeout.tv_sec = 0; |
|
12777 timeout.tv_usec = 0; |
|
12778 FD_ZERO(&rfd); |
|
12779 FD_ZERO(&sfd); |
|
12780 FD_SET((SOAP_SOCKET)soap->socket, &rfd); |
|
12781 FD_SET((SOAP_SOCKET)soap->socket, &sfd); |
|
12782 r = select((SOAP_SOCKET)(soap->socket + 1), &rfd, &sfd, NULL, &timeout); |
|
12783 if (r > 0) |
|
12784 { if (!FD_ISSET((SOAP_SOCKET)soap->socket, &sfd) |
|
12785 || (FD_ISSET((SOAP_SOCKET)soap->socket, &rfd) |
|
12786 && recv((SOAP_SOCKET)soap->socket, soap->tmpbuf, 1, MSG_PEEK) < 0)) |
|
12787 r = 0; |
|
12788 } |
|
12789 } |
|
12790 #endif |
|
12791 #endif |
|
12792 if ((status != SOAP_EOF || (!soap->recv_timeout && !soap->send_timeout)) && r > 0) |
|
12793 { soap->error = SOAP_OK; |
|
12794 soap_serializeheader(soap); |
|
12795 soap_serializefault(soap); |
|
12796 soap_begin_count(soap); |
|
12797 if (soap->mode & SOAP_IO_LENGTH) |
|
12798 { soap_envelope_begin_out(soap); |
|
12799 soap_putheader(soap); |
|
12800 soap_body_begin_out(soap); |
|
12801 soap_putfault(soap); |
|
12802 soap_body_end_out(soap); |
|
12803 soap_envelope_end_out(soap); |
|
12804 } |
|
12805 soap_end_count(soap); |
|
12806 if (soap_response(soap, status) |
|
12807 || soap_envelope_begin_out(soap) |
|
12808 || soap_putheader(soap) |
|
12809 || soap_body_begin_out(soap) |
|
12810 || soap_putfault(soap) |
|
12811 || soap_body_end_out(soap) |
|
12812 || soap_envelope_end_out(soap)) |
|
12813 return soap_closesock(soap); |
|
12814 soap_end_send(soap); |
|
12815 } |
|
12816 soap->error = status; |
|
12817 return soap_closesock(soap); |
|
12818 } |
|
12819 #endif |
|
12820 |
|
12821 /******************************************************************************/ |
|
12822 #ifndef PALM_1 |
|
12823 SOAP_FMAC1 |
|
12824 int |
|
12825 SOAP_FMAC2 |
|
12826 soap_recv_fault(struct soap *soap) |
|
12827 { register int status = soap->error; |
|
12828 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Receiving SOAP Fault\n")); |
|
12829 soap->error = SOAP_OK; |
|
12830 if (soap_getfault(soap)) |
|
12831 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Error: soap_get_soapfault() failed. Is this a SOAP message at all?\n")); |
|
12832 *soap_faultcode(soap) = (soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client"); |
|
12833 soap->error = status; |
|
12834 soap_set_fault(soap); |
|
12835 } |
|
12836 else |
|
12837 { register const char *s = *soap_faultcode(soap); |
|
12838 if (!soap_match_tag(soap, s, "SOAP-ENV:Server") || !soap_match_tag(soap, s, "SOAP-ENV:Receiver")) |
|
12839 status = SOAP_SVR_FAULT; |
|
12840 else if (!soap_match_tag(soap, s, "SOAP-ENV:Client") || !soap_match_tag(soap, s, "SOAP-ENV:Sender")) |
|
12841 status = SOAP_CLI_FAULT; |
|
12842 else if (!soap_match_tag(soap, s, "SOAP-ENV:MustUnderstand")) |
|
12843 status = SOAP_MUSTUNDERSTAND; |
|
12844 else if (!soap_match_tag(soap, s, "SOAP-ENV:VersionMismatch")) |
|
12845 status = SOAP_VERSIONMISMATCH; |
|
12846 else |
|
12847 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Fault code %s\n", s)); |
|
12848 status = SOAP_FAULT; |
|
12849 } |
|
12850 if (soap_body_end_in(soap) |
|
12851 || soap_envelope_end_in(soap) |
|
12852 || soap_end_recv(soap)) |
|
12853 return soap_closesock(soap); |
|
12854 soap->error = status; |
|
12855 } |
|
12856 return soap_closesock(soap); |
|
12857 } |
|
12858 #endif |
|
12859 |
|
12860 /******************************************************************************/ |
|
12861 #ifndef WITH_NOHTTP |
|
12862 #ifndef PALM_1 |
|
12863 SOAP_FMAC1 |
|
12864 int |
|
12865 SOAP_FMAC2 |
|
12866 soap_send_empty_response(struct soap *soap) |
|
12867 { soap->count = 0; |
|
12868 if (soap_response(soap, SOAP_OK) || soap_end_send(soap)) |
|
12869 return soap_closesock(soap); |
|
12870 return SOAP_OK; |
|
12871 } |
|
12872 #endif |
|
12873 #endif |
|
12874 |
|
12875 /******************************************************************************/ |
|
12876 #ifndef WITH_NOHTTP |
|
12877 #ifndef PALM_1 |
|
12878 SOAP_FMAC1 |
|
12879 int |
|
12880 SOAP_FMAC2 |
|
12881 soap_recv_empty_response(struct soap *soap) |
|
12882 { if (soap_begin_recv(soap) || soap_end_recv(soap)) |
|
12883 return soap_closesock(soap); |
|
12884 return SOAP_OK; |
|
12885 } |
|
12886 #endif |
|
12887 #endif |
|
12888 |
|
12889 /******************************************************************************/ |
|
12890 #ifndef WITH_NOIO |
|
12891 #ifndef PALM_1 |
|
12892 static const char* |
|
12893 soap_strerror(struct soap *soap) |
|
12894 { register int err = soap->errnum; |
|
12895 if (err) |
|
12896 { |
|
12897 #ifndef WIN32 |
|
12898 return strerror(err); |
|
12899 #else |
|
12900 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, 0, (LPTSTR)&soap->errorstr, sizeof(soap->errorstr), NULL); |
|
12901 return soap->errorstr; |
|
12902 #endif |
|
12903 } |
|
12904 return "Operation interrupted or timed out"; |
|
12905 } |
|
12906 #endif |
|
12907 #endif |
|
12908 |
|
12909 /******************************************************************************/ |
|
12910 #ifndef PALM_2 |
|
12911 static int |
|
12912 soap_set_error(struct soap *soap, const char *faultcode, const char *faultsubcode, const char *faultstring, const char *faultdetail, int soaperror) |
|
12913 { *soap_faultcode(soap) = faultcode; |
|
12914 if (faultsubcode) |
|
12915 *soap_faultsubcode(soap) = faultsubcode; |
|
12916 *soap_faultstring(soap) = faultstring; |
|
12917 if (faultdetail && *faultdetail) |
|
12918 { register const char **s = soap_faultdetail(soap); |
|
12919 if (s) |
|
12920 *s = faultdetail; |
|
12921 } |
|
12922 return soap->error = soaperror; |
|
12923 } |
|
12924 #endif |
|
12925 |
|
12926 /******************************************************************************/ |
|
12927 #ifndef PALM_2 |
|
12928 SOAP_FMAC1 |
|
12929 int |
|
12930 SOAP_FMAC2 |
|
12931 soap_set_sender_error(struct soap *soap, const char *faultstring, const char *faultdetail, int soaperror) |
|
12932 { return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", NULL, faultstring, faultdetail, soaperror); |
|
12933 } |
|
12934 #endif |
|
12935 |
|
12936 /******************************************************************************/ |
|
12937 #ifndef PALM_2 |
|
12938 SOAP_FMAC1 |
|
12939 int |
|
12940 SOAP_FMAC2 |
|
12941 soap_set_receiver_error(struct soap *soap, const char *faultstring, const char *faultdetail, int soaperror) |
|
12942 { return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", NULL, faultstring, faultdetail, soaperror); |
|
12943 } |
|
12944 #endif |
|
12945 |
|
12946 /******************************************************************************/ |
|
12947 #ifndef PALM_2 |
|
12948 static int |
|
12949 soap_copy_fault(struct soap *soap, const char *faultcode, const char *faultsubcode, const char *faultstring, const char *faultdetail) |
|
12950 { char *r = NULL, *s = NULL, *t = NULL; |
|
12951 if (faultsubcode) |
|
12952 r = soap_strdup(soap, faultsubcode); |
|
12953 if (faultstring) |
|
12954 s = soap_strdup(soap, faultstring); |
|
12955 if (faultdetail) |
|
12956 t = soap_strdup(soap, faultdetail); |
|
12957 return soap_set_error(soap, faultcode, r, s, t, SOAP_FAULT); |
|
12958 } |
|
12959 #endif |
|
12960 |
|
12961 /******************************************************************************/ |
|
12962 #ifndef PALM_2 |
|
12963 SOAP_FMAC1 |
|
12964 int |
|
12965 SOAP_FMAC2 |
|
12966 soap_sender_fault(struct soap *soap, const char *faultstring, const char *faultdetail) |
|
12967 { return soap_sender_fault_subcode(soap, NULL, faultstring, faultdetail); |
|
12968 } |
|
12969 #endif |
|
12970 |
|
12971 /******************************************************************************/ |
|
12972 #ifndef PALM_2 |
|
12973 SOAP_FMAC1 |
|
12974 int |
|
12975 SOAP_FMAC2 |
|
12976 soap_sender_fault_subcode(struct soap *soap, const char *faultsubcode, const char *faultstring, const char *faultdetail) |
|
12977 { return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", faultsubcode, faultstring, faultdetail); |
|
12978 } |
|
12979 #endif |
|
12980 |
|
12981 /******************************************************************************/ |
|
12982 #ifndef PALM_2 |
|
12983 SOAP_FMAC1 |
|
12984 int |
|
12985 SOAP_FMAC2 |
|
12986 soap_receiver_fault(struct soap *soap, const char *faultstring, const char *faultdetail) |
|
12987 { return soap_receiver_fault_subcode(soap, NULL, faultstring, faultdetail); |
|
12988 } |
|
12989 #endif |
|
12990 |
|
12991 /******************************************************************************/ |
|
12992 #ifndef PALM_2 |
|
12993 SOAP_FMAC1 |
|
12994 int |
|
12995 SOAP_FMAC2 |
|
12996 soap_receiver_fault_subcode(struct soap *soap, const char *faultsubcode, const char *faultstring, const char *faultdetail) |
|
12997 { return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", faultsubcode, faultstring, faultdetail); |
|
12998 } |
|
12999 #endif |
|
13000 |
|
13001 /******************************************************************************/ |
|
13002 #ifndef PALM_2 |
|
13003 #ifndef WITH_NOSTDLIB |
|
13004 SOAP_FMAC1 |
|
13005 void |
|
13006 SOAP_FMAC2 |
|
13007 soap_print_fault(struct soap *soap, FILE *fd) |
|
13008 { if (soap->error) |
|
13009 { const char *c, *v = NULL, *s, **d; |
|
13010 d = soap_faultcode(soap); |
|
13011 if (!*d) |
|
13012 soap_set_fault(soap); |
|
13013 c = *d; |
|
13014 if (soap->version == 2) |
|
13015 v = *soap_faultsubcode(soap); |
|
13016 s = *soap_faultstring(soap); |
|
13017 d = soap_faultdetail(soap); |
|
13018 fprintf(fd, "%s%d fault: %s [%s]\n\"%s\"\nDetail: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, c, v ? v : "no subcode", s ? s : "[no reason]", d && *d ? *d : "[no detail]"); |
|
13019 } |
|
13020 } |
|
13021 #endif |
|
13022 #endif |
|
13023 |
|
13024 /******************************************************************************/ |
|
13025 #ifndef PALM_1 |
|
13026 #ifndef WITH_NOSTDLIB |
|
13027 SOAP_FMAC1 |
|
13028 void |
|
13029 SOAP_FMAC2 |
|
13030 soap_print_fault_location(struct soap *soap, FILE *fd) |
|
13031 { |
|
13032 #ifndef WITH_LEAN |
|
13033 int i, j, c1, c2; |
|
13034 if (soap->error && soap->buflen > 0) |
|
13035 { i = (int)soap->bufidx - 1; |
|
13036 if (i <= 0) |
|
13037 i = 0; |
|
13038 c1 = soap->buf[i]; |
|
13039 soap->buf[i] = '\0'; |
|
13040 if ((int)soap->buflen >= i + 1024) |
|
13041 j = i + 1023; |
|
13042 else |
|
13043 j = (int)soap->buflen - 1; |
|
13044 c2 = soap->buf[j]; |
|
13045 soap->buf[j] = '\0'; |
|
13046 fprintf(fd, "%s%c\n** HERE **\n", soap->buf, c1); |
|
13047 if (soap->bufidx < soap->buflen) |
|
13048 fprintf(fd, "%s\n", soap->buf + soap->bufidx); |
|
13049 soap->buf[i] = c1; |
|
13050 soap->buf[j] = c2; |
|
13051 } |
|
13052 #endif |
|
13053 } |
|
13054 #endif |
|
13055 #endif |
|
13056 |
|
13057 /******************************************************************************/ |
|
13058 #ifndef PALM_1 |
|
13059 SOAP_FMAC1 |
|
13060 int |
|
13061 SOAP_FMAC2 |
|
13062 soap_register_plugin_arg(struct soap *soap, int (*fcreate)(struct soap*, struct soap_plugin*, void*), void *arg) |
|
13063 { register struct soap_plugin *p; |
|
13064 register int r; |
|
13065 if (!(p = (struct soap_plugin*)SOAP_MALLOC(soap, sizeof(struct soap_plugin)))) |
|
13066 return soap->error = SOAP_EOM; |
|
13067 p->id = NULL; |
|
13068 p->data = NULL; |
|
13069 p->fcopy = NULL; |
|
13070 p->fdelete = NULL; |
|
13071 r = fcreate(soap, p, arg); |
|
13072 if (!r && p->fdelete) |
|
13073 { p->next = soap->plugins; |
|
13074 soap->plugins = p; |
|
13075 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Registered '%s' plugin\n", p->id)); |
|
13076 return SOAP_OK; |
|
13077 } |
|
13078 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)); |
|
13079 SOAP_FREE(soap, p); |
|
13080 return r; |
|
13081 } |
|
13082 #endif |
|
13083 |
|
13084 /******************************************************************************/ |
|
13085 #ifndef PALM_1 |
|
13086 static void * |
|
13087 fplugin(struct soap *soap, const char *id) |
|
13088 { register struct soap_plugin *p; |
|
13089 for (p = soap->plugins; p; p = p->next) |
|
13090 if (p->id == id || !strcmp(p->id, id)) |
|
13091 return p->data; |
|
13092 return NULL; |
|
13093 } |
|
13094 #endif |
|
13095 |
|
13096 /******************************************************************************/ |
|
13097 #ifndef PALM_2 |
|
13098 SOAP_FMAC1 |
|
13099 void * |
|
13100 SOAP_FMAC2 |
|
13101 soap_lookup_plugin(struct soap *soap, const char *id) |
|
13102 { return soap->fplugin(soap, id); |
|
13103 } |
|
13104 #endif |
|
13105 |
|
13106 /******************************************************************************/ |
|
13107 #ifdef __cplusplus |
|
13108 } |
|
13109 #endif |
|
13110 |
|