0
|
1 /*
|
|
2 stdsoap2.c[pp] 2.8.17r
|
|
3
|
|
4 gSOAP runtime engine
|
|
5
|
|
6 gSOAP XML Web services tools
|
|
7 Copyright (C) 2000-2013, Robert van Engelen, Genivia Inc., All Rights Reserved.
|
|
8 This part of the software is released under ONE of the following licenses:
|
|
9 GPL, or the gSOAP public license, or Genivia's license for commercial use.
|
|
10 --------------------------------------------------------------------------------
|
|
11 Contributors:
|
|
12
|
|
13 Wind River Systems Inc., for the following additions under gSOAP public license:
|
|
14 - vxWorks compatible options
|
|
15 --------------------------------------------------------------------------------
|
|
16 gSOAP public license.
|
|
17
|
|
18 The contents of this file are subject to the gSOAP Public License Version 1.3
|
|
19 (the "License"); you may not use this file except in compliance with the
|
|
20 License. You may obtain a copy of the License at
|
|
21 http://www.cs.fsu.edu/~engelen/soaplicense.html
|
|
22 Software distributed under the License is distributed on an "AS IS" basis,
|
|
23 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
24 for the specific language governing rights and limitations under the License.
|
|
25
|
|
26 The Initial Developer of the Original Code is Robert A. van Engelen.
|
|
27 Copyright (C) 2000-2013, Robert van Engelen, Genivia Inc., All Rights Reserved.
|
|
28 --------------------------------------------------------------------------------
|
|
29 GPL license.
|
|
30
|
|
31 This program is free software; you can redistribute it and/or modify it under
|
|
32 the terms of the GNU General Public License as published by the Free Software
|
|
33 Foundation; either version 2 of the License, or (at your option) any later
|
|
34 version.
|
|
35
|
|
36 This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
37 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
38 PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
39
|
|
40 You should have received a copy of the GNU General Public License along with
|
|
41 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|
42 Place, Suite 330, Boston, MA 02111-1307 USA
|
|
43
|
|
44 Author contact information:
|
|
45 engelen@genivia.com / engelen@acm.org
|
|
46
|
|
47 This program is released under the GPL with the additional exemption that
|
|
48 compiling, linking, and/or using OpenSSL is allowed.
|
|
49 --------------------------------------------------------------------------------
|
|
50 A commercial use license is available from Genivia, Inc., contact@genivia.com
|
|
51 --------------------------------------------------------------------------------
|
|
52 */
|
|
53
|
|
54 #define GSOAP_LIB_VERSION 20817
|
|
55
|
|
56 #ifdef AS400
|
|
57 # pragma convert(819) /* EBCDIC to ASCII */
|
|
58 #endif
|
|
59
|
|
60 #include "stdsoap2.h"
|
|
61 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
|
|
62 #include <ipcom_key_db.h>
|
|
63 #endif
|
|
64 #if GSOAP_VERSION != GSOAP_LIB_VERSION
|
|
65 # error "GSOAP VERSION MISMATCH IN LIBRARY: PLEASE REINSTALL PACKAGE"
|
|
66 #endif
|
|
67
|
|
68 #ifdef __BORLANDC__
|
|
69 # pragma warn -8060
|
|
70 #else
|
|
71 # ifdef WIN32
|
|
72 # ifdef UNDER_CE
|
|
73 # pragma comment(lib, "ws2.lib") /* WinCE */
|
|
74 # else
|
|
75 # pragma comment(lib, "ws2_32.lib")
|
|
76 # endif
|
|
77 # pragma warning(disable : 4996) /* disable deprecation warnings */
|
|
78 # endif
|
|
79 #endif
|
|
80
|
|
81 #ifdef __cplusplus
|
|
82 SOAP_SOURCE_STAMP("@(#) stdsoap2.cpp ver 2.8.17r 2013-12-18 00:00:00 GMT")
|
|
83 extern "C" {
|
|
84 #else
|
|
85 SOAP_SOURCE_STAMP("@(#) stdsoap2.c ver 2.8.17r 2013-12-18 00:00:00 GMT")
|
|
86 #endif
|
|
87
|
|
88 /* 8bit character representing unknown/nonrepresentable character data (e.g. not supported by current locale with multibyte support enabled) */
|
|
89 #ifndef SOAP_UNKNOWN_CHAR
|
|
90 #define SOAP_UNKNOWN_CHAR (127)
|
|
91 #endif
|
|
92
|
|
93 /* EOF=-1 */
|
|
94 #define SOAP_LT (soap_wchar)(-2) /* XML-specific '<' */
|
|
95 #define SOAP_TT (soap_wchar)(-3) /* XML-specific '</' */
|
|
96 #define SOAP_GT (soap_wchar)(-4) /* XML-specific '>' */
|
|
97 #define SOAP_QT (soap_wchar)(-5) /* XML-specific '"' */
|
|
98 #define SOAP_AP (soap_wchar)(-6) /* XML-specific ''' */
|
|
99
|
|
100 #define soap_blank(c) ((c)+1 > 0 && (c) <= 32)
|
|
101 #define soap_notblank(c) ((c) > 32)
|
|
102
|
|
103 #if defined(WIN32) && !defined(UNDER_CE)
|
|
104 #define soap_hash_ptr(p) ((PtrToUlong(p) >> 3) & (SOAP_PTRHASH - 1))
|
|
105 #else
|
|
106 #define soap_hash_ptr(p) ((size_t)(((unsigned long)(p) >> 3) & (SOAP_PTRHASH-1)))
|
|
107 #endif
|
|
108
|
|
109 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
|
|
110 static void soap_init_logs(struct soap*);
|
|
111 #endif
|
|
112 #ifdef SOAP_DEBUG
|
|
113 static void soap_close_logfile(struct soap*, int);
|
|
114 static void soap_set_logfile(struct soap*, int, const char*);
|
|
115 #endif
|
|
116
|
|
117 #ifdef SOAP_MEM_DEBUG
|
|
118 static void soap_init_mht(struct soap*);
|
|
119 static void soap_free_mht(struct soap*);
|
|
120 static void soap_track_unlink(struct soap*, const void*);
|
|
121 #endif
|
|
122
|
|
123 #ifndef PALM_2
|
|
124 static int soap_set_error(struct soap*, const char*, const char*, const char*, const char*, int);
|
|
125 static int soap_copy_fault(struct soap*, const char*, const char*, const char*, const char*);
|
|
126 static int soap_getattrval(struct soap*, char*, size_t, soap_wchar);
|
|
127 #endif
|
|
128
|
|
129 #ifndef PALM_1
|
|
130 static void soap_free_ns(struct soap *soap);
|
|
131 static soap_wchar soap_char(struct soap*);
|
|
132 static soap_wchar soap_get_pi(struct soap*);
|
|
133 static int soap_isxdigit(int);
|
|
134 static void *fplugin(struct soap*, const char*);
|
|
135 static size_t soap_count_attachments(struct soap *soap);
|
|
136 static int soap_try_connect_command(struct soap*, int http_command, const char *endpoint, const char *action);
|
|
137 #ifdef WITH_NTLM
|
|
138 static int soap_ntlm_handshake(struct soap *soap, int command, const char *endpoint, const char *host, int port);
|
|
139 #endif
|
|
140 #ifndef WITH_NOIDREF
|
|
141 static int soap_has_copies(struct soap*, const char*, const char*);
|
|
142 static void soap_init_iht(struct soap*);
|
|
143 static void soap_free_iht(struct soap*);
|
|
144 static void soap_init_pht(struct soap*);
|
|
145 static void soap_free_pht(struct soap*);
|
|
146 #endif
|
|
147 #endif
|
|
148
|
|
149 #ifndef WITH_LEAN
|
|
150 static const char *soap_set_validation_fault(struct soap*, const char*, const char*);
|
|
151 static int soap_isnumeric(struct soap*, const char*);
|
|
152 static struct soap_nlist *soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized);
|
|
153 static void soap_utilize_ns(struct soap *soap, const char *tag);
|
|
154 #endif
|
|
155
|
|
156 #ifndef WITH_LEANER
|
|
157 #ifndef PALM_1
|
|
158 static struct soap_multipart *soap_new_multipart(struct soap*, struct soap_multipart**, struct soap_multipart**, char*, size_t);
|
|
159 static int soap_putdimefield(struct soap*, const char*, size_t);
|
|
160 static char *soap_getdimefield(struct soap*, size_t);
|
|
161 static void soap_select_mime_boundary(struct soap*);
|
|
162 static int soap_valid_mime_boundary(struct soap*);
|
|
163 static void soap_resolve_attachment(struct soap*, struct soap_multipart*);
|
|
164 #endif
|
|
165 #endif
|
|
166
|
|
167 #ifdef WITH_GZIP
|
|
168 static int soap_getgziphdr(struct soap*);
|
|
169 #endif
|
|
170
|
|
171 #ifdef WITH_OPENSSL
|
|
172 # ifndef SOAP_SSL_RSA_BITS
|
|
173 # define SOAP_SSL_RSA_BITS 2048
|
|
174 # endif
|
|
175 static int soap_ssl_init_done = 0;
|
|
176 static int ssl_auth_init(struct soap*);
|
|
177 static int ssl_verify_callback(int, X509_STORE_CTX*);
|
|
178 static int ssl_verify_callback_allow_expired_certificate(int, X509_STORE_CTX*);
|
|
179 static int ssl_password(char*, int, int, void *);
|
|
180 #endif
|
|
181
|
|
182 #ifdef WITH_GNUTLS
|
|
183 # ifndef SOAP_SSL_RSA_BITS
|
|
184 # define SOAP_SSL_RSA_BITS 2048
|
|
185 # endif
|
|
186 static int soap_ssl_init_done = 0;
|
|
187 static const char *ssl_verify(struct soap *soap, const char *host);
|
|
188 # if defined(HAVE_PTHREAD_H)
|
|
189 # include <pthread.h>
|
|
190 /* make GNUTLS thread safe with pthreads */
|
|
191 GCRY_THREAD_OPTION_PTHREAD_IMPL;
|
|
192 # elif defined(HAVE_PTH_H)
|
|
193 #include <pth.h>
|
|
194 /* make GNUTLS thread safe with PTH */
|
|
195 GCRY_THREAD_OPTION_PTH_IMPL;
|
|
196 # endif
|
|
197 #endif
|
|
198
|
|
199 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
|
|
200 #ifndef PALM_1
|
|
201 static const char *soap_decode(char*, size_t, const char*, const char*);
|
|
202 #endif
|
|
203 #endif
|
|
204
|
|
205 #ifndef WITH_NOHTTP
|
|
206 #ifndef PALM_1
|
|
207 static soap_wchar soap_getchunkchar(struct soap*);
|
|
208 static const char *http_error(struct soap*, int);
|
|
209 static int http_get(struct soap*);
|
|
210 static int http_405(struct soap*);
|
|
211 static int http_200(struct soap*);
|
|
212 static int http_post(struct soap*, const char*, const char*, int, const char*, const char*, size_t);
|
|
213 static int http_send_header(struct soap*, const char*);
|
|
214 static int http_post_header(struct soap*, const char*, const char*);
|
|
215 static int http_response(struct soap*, int, size_t);
|
|
216 static int http_parse(struct soap*);
|
|
217 static int http_parse_header(struct soap*, const char*, const char*);
|
|
218 #endif
|
|
219 #endif
|
|
220
|
|
221 #ifndef WITH_NOIO
|
|
222
|
|
223 #ifndef PALM_1
|
|
224 static int fsend(struct soap*, const char*, size_t);
|
|
225 static size_t frecv(struct soap*, char*, size_t);
|
|
226 static int tcp_init(struct soap*);
|
|
227 static const char *tcp_error(struct soap*);
|
|
228 #ifndef WITH_IPV6
|
|
229 static int tcp_gethost(struct soap*, const char *addr, struct in_addr *inaddr);
|
|
230 #endif
|
|
231 static SOAP_SOCKET tcp_connect(struct soap*, const char *endpoint, const char *host, int port);
|
|
232 static SOAP_SOCKET tcp_accept(struct soap*, SOAP_SOCKET, struct sockaddr*, int*);
|
|
233 static int tcp_select(struct soap*, SOAP_SOCKET, int, int);
|
|
234 static int tcp_disconnect(struct soap*);
|
|
235 static int tcp_closesocket(struct soap*, SOAP_SOCKET);
|
|
236 static int tcp_shutdownsocket(struct soap*, SOAP_SOCKET, int);
|
|
237 static const char *soap_strerror(struct soap*);
|
|
238 #endif
|
|
239
|
|
240 #define SOAP_TCP_SELECT_RCV 0x1
|
|
241 #define SOAP_TCP_SELECT_SND 0x2
|
|
242 #define SOAP_TCP_SELECT_ERR 0x4
|
|
243 #define SOAP_TCP_SELECT_ALL 0x7
|
|
244
|
|
245 #if defined(WIN32)
|
|
246 #define SOAP_SOCKBLOCK(fd) \
|
|
247 { u_long blocking = 0; \
|
|
248 ioctlsocket(fd, FIONBIO, &blocking); \
|
|
249 }
|
|
250 #define SOAP_SOCKNONBLOCK(fd) \
|
|
251 { u_long nonblocking = 1; \
|
|
252 ioctlsocket(fd, FIONBIO, &nonblocking); \
|
|
253 }
|
|
254 #elif defined(VXWORKS)
|
|
255 #define SOAP_SOCKBLOCK(fd) \
|
|
256 { u_long blocking = 0; \
|
|
257 ioctl(fd, FIONBIO, (int)(&blocking)); \
|
|
258 }
|
|
259 #define SOAP_SOCKNONBLOCK(fd) \
|
|
260 { u_long nonblocking = 1; \
|
|
261 ioctl(fd, FIONBIO, (int)(&nonblocking)); \
|
|
262 }
|
|
263 #elif defined(__VMS)
|
|
264 #define SOAP_SOCKBLOCK(fd) \
|
|
265 { int blocking = 0; \
|
|
266 ioctl(fd, FIONBIO, &blocking); \
|
|
267 }
|
|
268 #define SOAP_SOCKNONBLOCK(fd) \
|
|
269 { int nonblocking = 1; \
|
|
270 ioctl(fd, FIONBIO, &nonblocking); \
|
|
271 }
|
|
272 #elif defined(PALM)
|
|
273 #define SOAP_SOCKBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)&~O_NONBLOCK);
|
|
274 #define SOAP_SOCKNONBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)|O_NONBLOCK);
|
|
275 #elif defined(SYMBIAN)
|
|
276 #define SOAP_SOCKBLOCK(fd) \
|
|
277 { long blocking = 0; \
|
|
278 ioctl(fd, 0/*FIONBIO*/, &blocking); \
|
|
279 }
|
|
280 #define SOAP_SOCKNONBLOCK(fd) \
|
|
281 { long nonblocking = 1; \
|
|
282 ioctl(fd, 0/*FIONBIO*/, &nonblocking); \
|
|
283 }
|
|
284 #else
|
|
285 #define SOAP_SOCKBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)&~O_NONBLOCK);
|
|
286 #define SOAP_SOCKNONBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)|O_NONBLOCK);
|
|
287 #endif
|
|
288
|
|
289 #endif
|
|
290
|
|
291 #if defined(PALM) && !defined(PALM_2)
|
|
292 unsigned short errno;
|
|
293 #endif
|
|
294
|
|
295 #ifndef PALM_1
|
|
296 static const char soap_env1[42] = "http://schemas.xmlsoap.org/soap/envelope/";
|
|
297 static const char soap_enc1[42] = "http://schemas.xmlsoap.org/soap/encoding/";
|
|
298 static const char soap_env2[40] = "http://www.w3.org/2003/05/soap-envelope";
|
|
299 static const char soap_enc2[40] = "http://www.w3.org/2003/05/soap-encoding";
|
|
300 static const char soap_rpc[35] = "http://www.w3.org/2003/05/soap-rpc";
|
|
301 #endif
|
|
302
|
|
303 #ifndef PALM_1
|
|
304 const union soap_double_nan soap_double_nan = {{0xFFFFFFFF, 0xFFFFFFFF}};
|
|
305 const char soap_base64o[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
306 const char soap_base64i[81] = "\76XXX\77\64\65\66\67\70\71\72\73\74\75XXXXXXX\00\01\02\03\04\05\06\07\10\11\12\13\14\15\16\17\20\21\22\23\24\25\26\27\30\31XXXXXX\32\33\34\35\36\37\40\41\42\43\44\45\46\47\50\51\52\53\54\55\56\57\60\61\62\63";
|
|
307 #endif
|
|
308
|
|
309 #ifndef WITH_LEAN
|
|
310 static const char soap_indent[11] = "\n\t\t\t\t\t\t\t\t\t";
|
|
311 /* Alternative indentation form for SOAP_XML_INDENT:
|
|
312 static const char soap_indent[21] = "\n ";
|
|
313 */
|
|
314 #endif
|
|
315
|
|
316 #ifndef SOAP_CANARY
|
|
317 # define SOAP_CANARY (0xC0DE)
|
|
318 #endif
|
|
319
|
|
320 static const char soap_padding[4] = "\0\0\0";
|
|
321 #define SOAP_STR_PADDING (soap_padding)
|
|
322 #define SOAP_STR_EOS (soap_padding)
|
|
323 #define SOAP_NON_NULL (soap_padding)
|
|
324
|
|
325 #ifndef WITH_LEAN
|
|
326 static const struct soap_code_map html_entity_codes[] = /* entities for XHTML parsing */
|
|
327 { { 160, "nbsp" },
|
|
328 { 161, "iexcl" },
|
|
329 { 162, "cent" },
|
|
330 { 163, "pound" },
|
|
331 { 164, "curren" },
|
|
332 { 165, "yen" },
|
|
333 { 166, "brvbar" },
|
|
334 { 167, "sect" },
|
|
335 { 168, "uml" },
|
|
336 { 169, "copy" },
|
|
337 { 170, "ordf" },
|
|
338 { 171, "laquo" },
|
|
339 { 172, "not" },
|
|
340 { 173, "shy" },
|
|
341 { 174, "reg" },
|
|
342 { 175, "macr" },
|
|
343 { 176, "deg" },
|
|
344 { 177, "plusmn" },
|
|
345 { 178, "sup2" },
|
|
346 { 179, "sup3" },
|
|
347 { 180, "acute" },
|
|
348 { 181, "micro" },
|
|
349 { 182, "para" },
|
|
350 { 183, "middot" },
|
|
351 { 184, "cedil" },
|
|
352 { 185, "sup1" },
|
|
353 { 186, "ordm" },
|
|
354 { 187, "raquo" },
|
|
355 { 188, "frac14" },
|
|
356 { 189, "frac12" },
|
|
357 { 190, "frac34" },
|
|
358 { 191, "iquest" },
|
|
359 { 192, "Agrave" },
|
|
360 { 193, "Aacute" },
|
|
361 { 194, "Acirc" },
|
|
362 { 195, "Atilde" },
|
|
363 { 196, "Auml" },
|
|
364 { 197, "Aring" },
|
|
365 { 198, "AElig" },
|
|
366 { 199, "Ccedil" },
|
|
367 { 200, "Egrave" },
|
|
368 { 201, "Eacute" },
|
|
369 { 202, "Ecirc" },
|
|
370 { 203, "Euml" },
|
|
371 { 204, "Igrave" },
|
|
372 { 205, "Iacute" },
|
|
373 { 206, "Icirc" },
|
|
374 { 207, "Iuml" },
|
|
375 { 208, "ETH" },
|
|
376 { 209, "Ntilde" },
|
|
377 { 210, "Ograve" },
|
|
378 { 211, "Oacute" },
|
|
379 { 212, "Ocirc" },
|
|
380 { 213, "Otilde" },
|
|
381 { 214, "Ouml" },
|
|
382 { 215, "times" },
|
|
383 { 216, "Oslash" },
|
|
384 { 217, "Ugrave" },
|
|
385 { 218, "Uacute" },
|
|
386 { 219, "Ucirc" },
|
|
387 { 220, "Uuml" },
|
|
388 { 221, "Yacute" },
|
|
389 { 222, "THORN" },
|
|
390 { 223, "szlig" },
|
|
391 { 224, "agrave" },
|
|
392 { 225, "aacute" },
|
|
393 { 226, "acirc" },
|
|
394 { 227, "atilde" },
|
|
395 { 228, "auml" },
|
|
396 { 229, "aring" },
|
|
397 { 230, "aelig" },
|
|
398 { 231, "ccedil" },
|
|
399 { 232, "egrave" },
|
|
400 { 233, "eacute" },
|
|
401 { 234, "ecirc" },
|
|
402 { 235, "euml" },
|
|
403 { 236, "igrave" },
|
|
404 { 237, "iacute" },
|
|
405 { 238, "icirc" },
|
|
406 { 239, "iuml" },
|
|
407 { 240, "eth" },
|
|
408 { 241, "ntilde" },
|
|
409 { 242, "ograve" },
|
|
410 { 243, "oacute" },
|
|
411 { 244, "ocirc" },
|
|
412 { 245, "otilde" },
|
|
413 { 246, "ouml" },
|
|
414 { 247, "divide" },
|
|
415 { 248, "oslash" },
|
|
416 { 249, "ugrave" },
|
|
417 { 250, "uacute" },
|
|
418 { 251, "ucirc" },
|
|
419 { 252, "uuml" },
|
|
420 { 253, "yacute" },
|
|
421 { 254, "thorn" },
|
|
422 { 255, "yuml" },
|
|
423 { 0, NULL }
|
|
424 };
|
|
425 #endif
|
|
426
|
|
427 #ifndef WITH_NOIO
|
|
428 #ifndef WITH_LEAN
|
|
429 static const struct soap_code_map h_error_codes[] =
|
|
430 {
|
|
431 #ifdef HOST_NOT_FOUND
|
|
432 { HOST_NOT_FOUND, "Host not found" },
|
|
433 #endif
|
|
434 #ifdef TRY_AGAIN
|
|
435 { TRY_AGAIN, "Try Again" },
|
|
436 #endif
|
|
437 #ifdef NO_RECOVERY
|
|
438 { NO_RECOVERY, "No Recovery" },
|
|
439 #endif
|
|
440 #ifdef NO_DATA
|
|
441 { NO_DATA, "No Data" },
|
|
442 #endif
|
|
443 #ifdef NO_ADDRESS
|
|
444 { NO_ADDRESS, "No Address" },
|
|
445 #endif
|
|
446 { 0, NULL }
|
|
447 };
|
|
448 #endif
|
|
449 #endif
|
|
450
|
|
451 #ifndef WITH_NOHTTP
|
|
452 #ifndef WITH_LEAN
|
|
453 static const struct soap_code_map h_http_error_codes[] =
|
|
454 { { 200, "OK" },
|
|
455 { 201, "Created" },
|
|
456 { 202, "Accepted" },
|
|
457 { 203, "Non-Authoritative Information" },
|
|
458 { 204, "No Content" },
|
|
459 { 205, "Reset Content" },
|
|
460 { 206, "Partial Content" },
|
|
461 { 300, "Multiple Choices" },
|
|
462 { 301, "Moved Permanently" },
|
|
463 { 302, "Found" },
|
|
464 { 303, "See Other" },
|
|
465 { 304, "Not Modified" },
|
|
466 { 305, "Use Proxy" },
|
|
467 { 307, "Temporary Redirect" },
|
|
468 { 400, "Bad Request" },
|
|
469 { 401, "Unauthorized" },
|
|
470 { 402, "Payment Required" },
|
|
471 { 403, "Forbidden" },
|
|
472 { 404, "Not Found" },
|
|
473 { 405, "Method Not Allowed" },
|
|
474 { 406, "Not Acceptable" },
|
|
475 { 407, "Proxy Authentication Required" },
|
|
476 { 408, "Request Time-out" },
|
|
477 { 409, "Conflict" },
|
|
478 { 410, "Gone" },
|
|
479 { 411, "Length Required" },
|
|
480 { 412, "Precondition Failed" },
|
|
481 { 413, "Request Entity Too Large" },
|
|
482 { 414, "Request-URI Too Large" },
|
|
483 { 415, "Unsupported Media Type" },
|
|
484 { 416, "Requested range not satisfiable" },
|
|
485 { 417, "Expectation Failed" },
|
|
486 { 500, "Internal Server Error" },
|
|
487 { 501, "Not Implemented" },
|
|
488 { 502, "Bad Gateway" },
|
|
489 { 503, "Service Unavailable" },
|
|
490 { 504, "Gateway Time-out" },
|
|
491 { 505, "HTTP Version not supported" },
|
|
492 { 0, NULL }
|
|
493 };
|
|
494 #endif
|
|
495 #endif
|
|
496
|
|
497 #ifdef WITH_OPENSSL
|
|
498 static const struct soap_code_map h_ssl_error_codes[] =
|
|
499 {
|
|
500 #define _SSL_ERROR(e) { e, #e }
|
|
501 _SSL_ERROR(SSL_ERROR_SSL),
|
|
502 _SSL_ERROR(SSL_ERROR_ZERO_RETURN),
|
|
503 _SSL_ERROR(SSL_ERROR_WANT_READ),
|
|
504 _SSL_ERROR(SSL_ERROR_WANT_WRITE),
|
|
505 _SSL_ERROR(SSL_ERROR_WANT_CONNECT),
|
|
506 _SSL_ERROR(SSL_ERROR_WANT_X509_LOOKUP),
|
|
507 _SSL_ERROR(SSL_ERROR_SYSCALL),
|
|
508 { 0, NULL }
|
|
509 };
|
|
510 #endif
|
|
511
|
|
512 #ifndef WITH_LEANER
|
|
513 static const struct soap_code_map mime_codes[] =
|
|
514 { { SOAP_MIME_7BIT, "7bit" },
|
|
515 { SOAP_MIME_8BIT, "8bit" },
|
|
516 { SOAP_MIME_BINARY, "binary" },
|
|
517 { SOAP_MIME_QUOTED_PRINTABLE, "quoted-printable" },
|
|
518 { SOAP_MIME_BASE64, "base64" },
|
|
519 { SOAP_MIME_IETF_TOKEN, "ietf-token" },
|
|
520 { SOAP_MIME_X_TOKEN, "x-token" },
|
|
521 { 0, NULL }
|
|
522 };
|
|
523 #endif
|
|
524
|
|
525 #ifdef WIN32
|
|
526 static int tcp_done = 0;
|
|
527 #endif
|
|
528
|
|
529 #if defined(HP_UX) && defined(HAVE_GETHOSTBYNAME_R)
|
|
530 extern int h_errno;
|
|
531 #endif
|
|
532
|
|
533 /******************************************************************************/
|
|
534 #ifndef WITH_NOIO
|
|
535 #ifndef PALM_1
|
|
536 static int
|
|
537 fsend(struct soap *soap, const char *s, size_t n)
|
|
538 { register int nwritten, err;
|
|
539 SOAP_SOCKET sk;
|
|
540 #if defined(__cplusplus) && !defined(WITH_LEAN) && !defined(WITH_COMPAT)
|
|
541 if (soap->os)
|
|
542 { soap->os->write(s, (std::streamsize)n);
|
|
543 if (soap->os->good())
|
|
544 return SOAP_OK;
|
|
545 soap->errnum = 0;
|
|
546 return SOAP_EOF;
|
|
547 }
|
|
548 #endif
|
|
549 sk = soap->sendsk;
|
|
550 if (!soap_valid_socket(sk))
|
|
551 sk = soap->socket;
|
|
552 while (n)
|
|
553 { if (soap_valid_socket(sk))
|
|
554 {
|
|
555 if (soap->send_timeout)
|
|
556 { for (;;)
|
|
557 { register int r;
|
|
558 #ifdef WITH_OPENSSL
|
|
559 if (soap->ssl)
|
|
560 r = tcp_select(soap, sk, SOAP_TCP_SELECT_ALL, soap->send_timeout);
|
|
561 else
|
|
562 #endif
|
|
563 #ifdef WITH_GNUTLS
|
|
564 if (soap->session)
|
|
565 r = tcp_select(soap, sk, SOAP_TCP_SELECT_ALL, soap->send_timeout);
|
|
566 else
|
|
567 #endif
|
|
568 r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->send_timeout);
|
|
569 if (r > 0)
|
|
570 break;
|
|
571 if (!r)
|
|
572 return SOAP_EOF;
|
|
573 err = soap->errnum;
|
|
574 if (!err)
|
|
575 return soap->error;
|
|
576 if (err != SOAP_EAGAIN && err != SOAP_EWOULDBLOCK)
|
|
577 return SOAP_EOF;
|
|
578 }
|
|
579 }
|
|
580 #ifdef WITH_OPENSSL
|
|
581 if (soap->ssl)
|
|
582 nwritten = SSL_write(soap->ssl, s, (int)n);
|
|
583 else if (soap->bio)
|
|
584 nwritten = BIO_write(soap->bio, s, (int)n);
|
|
585 else
|
|
586 #endif
|
|
587 #ifdef WITH_GNUTLS
|
|
588 if (soap->session)
|
|
589 nwritten = gnutls_record_send(soap->session, s, n);
|
|
590 else
|
|
591 #endif
|
|
592 #ifndef WITH_LEAN
|
|
593 if ((soap->omode & SOAP_IO_UDP))
|
|
594 { if (soap->peerlen)
|
|
595 nwritten = sendto(sk, (char*)s, (SOAP_WINSOCKINT)n, soap->socket_flags, (struct sockaddr*)&soap->peer, (SOAP_WINSOCKINT)soap->peerlen);
|
|
596 else
|
|
597 nwritten = send(sk, s, (SOAP_WINSOCKINT)n, soap->socket_flags);
|
|
598 /* retry and back-off algorithm */
|
|
599 /* TODO: this is not very clear from specs so verify and limit conditions under which we should loop (e.g. ENOBUFS) */
|
|
600 if (nwritten < 0)
|
|
601 { int udp_repeat;
|
|
602 int udp_delay;
|
|
603 if ((soap->connect_flags & SO_BROADCAST))
|
|
604 udp_repeat = 2; /* SOAP-over-UDP MULTICAST_UDP_REPEAT - 1 */
|
|
605 else
|
|
606 udp_repeat = 1; /* SOAP-over-UDP UNICAST_UDP_REPEAT - 1 */
|
|
607 udp_delay = ((unsigned int)soap_random % 201) + 50; /* UDP_MIN_DELAY .. UDP_MAX_DELAY */
|
|
608 do
|
|
609 { tcp_select(soap, sk, SOAP_TCP_SELECT_ERR, -1000 * udp_delay);
|
|
610 if (soap->peerlen)
|
|
611 nwritten = sendto(sk, (char*)s, (SOAP_WINSOCKINT)n, soap->socket_flags, (struct sockaddr*)&soap->peer, (SOAP_WINSOCKINT)soap->peerlen);
|
|
612 else
|
|
613 nwritten = send(sk, s, (SOAP_WINSOCKINT)n, soap->socket_flags);
|
|
614 udp_delay <<= 1;
|
|
615 if (udp_delay > 500) /* UDP_UPPER_DELAY */
|
|
616 udp_delay = 500;
|
|
617 }
|
|
618 while (nwritten < 0 && --udp_repeat > 0);
|
|
619 }
|
|
620 if (nwritten < 0)
|
|
621 { err = soap_socket_errno(sk);
|
|
622 if (err && err != SOAP_EINTR)
|
|
623 { soap->errnum = err;
|
|
624 return SOAP_EOF;
|
|
625 }
|
|
626 nwritten = 0; /* and call write() again */
|
|
627 }
|
|
628 }
|
|
629 else
|
|
630 #endif
|
|
631 #if !defined(PALM) && !defined(AS400)
|
|
632 nwritten = send(sk, s, (int)n, soap->socket_flags);
|
|
633 #else
|
|
634 nwritten = send(sk, (void*)s, n, soap->socket_flags);
|
|
635 #endif
|
|
636 if (nwritten <= 0)
|
|
637 {
|
|
638 register int r = 0;
|
|
639 err = soap_socket_errno(sk);
|
|
640 #ifdef WITH_OPENSSL
|
|
641 if (soap->ssl && (r = SSL_get_error(soap->ssl, nwritten)) != SSL_ERROR_NONE && r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE)
|
|
642 { soap->errnum = err;
|
|
643 return SOAP_EOF;
|
|
644 }
|
|
645 #endif
|
|
646 #ifdef WITH_GNUTLS
|
|
647 if (soap->session)
|
|
648 { if (nwritten == GNUTLS_E_INTERRUPTED)
|
|
649 err = SOAP_EINTR;
|
|
650 else if (nwritten == GNUTLS_E_AGAIN)
|
|
651 err = SOAP_EAGAIN;
|
|
652 }
|
|
653 #endif
|
|
654 if (err == SOAP_EWOULDBLOCK || err == SOAP_EAGAIN)
|
|
655 {
|
|
656 #if defined(WITH_OPENSSL)
|
|
657 if (soap->ssl && r == SSL_ERROR_WANT_READ)
|
|
658 r = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->send_timeout ? soap->send_timeout : -10000);
|
|
659 else
|
|
660 #elif defined(WITH_GNUTLS)
|
|
661 if (soap->session && !gnutls_record_get_direction(soap->session))
|
|
662 r = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->send_timeout ? soap->send_timeout : -10000);
|
|
663 else
|
|
664 #endif
|
|
665 r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->send_timeout ? soap->send_timeout : -10000);
|
|
666 if (!r && soap->send_timeout)
|
|
667 return SOAP_EOF;
|
|
668 if (r < 0)
|
|
669 return SOAP_EOF;
|
|
670 }
|
|
671 else if (err && err != SOAP_EINTR)
|
|
672 { soap->errnum = err;
|
|
673 return SOAP_EOF;
|
|
674 }
|
|
675 nwritten = 0; /* and call write() again */
|
|
676 }
|
|
677 }
|
|
678 else
|
|
679 {
|
|
680 #ifdef WITH_FASTCGI
|
|
681 nwritten = fwrite((void*)s, 1, n, stdout);
|
|
682 fflush(stdout);
|
|
683 #else
|
|
684 #ifdef UNDER_CE
|
|
685 nwritten = fwrite(s, 1, n, soap->sendfd);
|
|
686 #else
|
|
687 #ifdef VXWORKS
|
|
688 #ifdef WMW_RPM_IO
|
|
689 if (soap->rpmreqid)
|
|
690 nwritten = (httpBlockPut(soap->rpmreqid, (char*)s, n) == 0) ? n : -1;
|
|
691 else
|
|
692 #endif
|
|
693 nwritten = fwrite(s, sizeof(char), n, fdopen(soap->sendfd, "w"));
|
|
694 #else
|
|
695 #ifdef WIN32
|
|
696 nwritten = _write(soap->sendfd, s, (unsigned int)n);
|
|
697 #else
|
|
698 nwritten = write(soap->sendfd, s, (unsigned int)n);
|
|
699 #endif
|
|
700 #endif
|
|
701 #endif
|
|
702 #endif
|
|
703 if (nwritten <= 0)
|
|
704 {
|
|
705 #ifndef WITH_FASTCGI
|
|
706 err = soap_errno;
|
|
707 #else
|
|
708 err = EOF;
|
|
709 #endif
|
|
710 if (err && err != SOAP_EINTR && err != SOAP_EWOULDBLOCK && err != SOAP_EAGAIN)
|
|
711 { soap->errnum = err;
|
|
712 return SOAP_EOF;
|
|
713 }
|
|
714 nwritten = 0; /* and call write() again */
|
|
715 }
|
|
716 }
|
|
717 n -= nwritten;
|
|
718 s += nwritten;
|
|
719 }
|
|
720 return SOAP_OK;
|
|
721 }
|
|
722 #endif
|
|
723 #endif
|
|
724
|
|
725 /******************************************************************************/
|
|
726 #ifndef PALM_1
|
|
727 SOAP_FMAC1
|
|
728 int
|
|
729 SOAP_FMAC2
|
|
730 soap_send_raw(struct soap *soap, const char *s, size_t n)
|
|
731 { if (!n)
|
|
732 return SOAP_OK;
|
|
733 #ifndef WITH_LEANER
|
|
734 if (soap->fpreparesend && (soap->mode & SOAP_IO) != SOAP_IO_STORE && (soap->mode & SOAP_IO_LENGTH) && (soap->error = soap->fpreparesend(soap, s, n)))
|
|
735 return soap->error;
|
|
736 if (soap->ffiltersend && (soap->error = soap->ffiltersend(soap, &s, &n)))
|
|
737 return soap->error;
|
|
738 #endif
|
|
739 if (soap->mode & SOAP_IO_LENGTH)
|
|
740 soap->count += n;
|
|
741 else if (soap->mode & SOAP_IO)
|
|
742 { register size_t i = SOAP_BUFLEN - soap->bufidx;
|
|
743 while (n >= i)
|
|
744 { memcpy(soap->buf + soap->bufidx, s, i);
|
|
745 soap->bufidx = SOAP_BUFLEN;
|
|
746 if (soap_flush(soap))
|
|
747 return soap->error;
|
|
748 s += i;
|
|
749 n -= i;
|
|
750 i = SOAP_BUFLEN;
|
|
751 }
|
|
752 memcpy(soap->buf + soap->bufidx, s, n);
|
|
753 soap->bufidx += n;
|
|
754 }
|
|
755 else
|
|
756 return soap_flush_raw(soap, s, n);
|
|
757 return SOAP_OK;
|
|
758 }
|
|
759 #endif
|
|
760
|
|
761 /******************************************************************************/
|
|
762 #ifndef PALM_1
|
|
763 SOAP_FMAC1
|
|
764 int
|
|
765 SOAP_FMAC2
|
|
766 soap_flush(struct soap *soap)
|
|
767 { register size_t n = soap->bufidx;
|
|
768 if (n)
|
|
769 {
|
|
770 #ifndef WITH_LEANER
|
|
771 if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
|
|
772 { register int r;
|
|
773 if (soap->fpreparesend && (r = soap->fpreparesend(soap, soap->buf, n)))
|
|
774 return soap->error = r;
|
|
775 }
|
|
776 #endif
|
|
777 soap->bufidx = 0;
|
|
778 #ifdef WITH_ZLIB
|
|
779 if (soap->mode & SOAP_ENC_ZLIB)
|
|
780 { soap->d_stream->next_in = (Byte*)soap->buf;
|
|
781 soap->d_stream->avail_in = (unsigned int)n;
|
|
782 #ifdef WITH_GZIP
|
|
783 soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)n);
|
|
784 #endif
|
|
785 do
|
|
786 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating %u bytes\n", soap->d_stream->avail_in));
|
|
787 if (deflate(soap->d_stream, Z_NO_FLUSH) != Z_OK)
|
|
788 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to deflate: %s\n", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS));
|
|
789 return soap->error = SOAP_ZLIB_ERROR;
|
|
790 }
|
|
791 if (!soap->d_stream->avail_out)
|
|
792 { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN))
|
|
793 return soap->error;
|
|
794 soap->d_stream->next_out = (Byte*)soap->z_buf;
|
|
795 soap->d_stream->avail_out = SOAP_BUFLEN;
|
|
796 }
|
|
797 } while (soap->d_stream->avail_in);
|
|
798 }
|
|
799 else
|
|
800 #endif
|
|
801 return soap_flush_raw(soap, soap->buf, n);
|
|
802 }
|
|
803 return SOAP_OK;
|
|
804 }
|
|
805 #endif
|
|
806
|
|
807 /******************************************************************************/
|
|
808 #ifndef PALM_1
|
|
809 SOAP_FMAC1
|
|
810 int
|
|
811 SOAP_FMAC2
|
|
812 soap_flush_raw(struct soap *soap, const char *s, size_t n)
|
|
813 { if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
|
|
814 { register char *t;
|
|
815 if (!(t = (char*)soap_push_block(soap, NULL, n)))
|
|
816 return soap->error = SOAP_EOM;
|
|
817 memcpy(t, s, n);
|
|
818 return SOAP_OK;
|
|
819 }
|
|
820 #ifndef WITH_LEANER
|
|
821 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
|
|
822 { char t[16];
|
|
823 #ifdef HAVE_SNPRINTF
|
|
824 soap_snprintf(t, sizeof(t), &"\r\n%lX\r\n"[soap->chunksize ? 0 : 2], (unsigned long)n);
|
|
825 #else
|
|
826 sprintf(t, &"\r\n%lX\r\n"[soap->chunksize ? 0 : 2], (unsigned long)n);
|
|
827 #endif
|
|
828 DBGMSG(SENT, t, strlen(t));
|
|
829 if ((soap->error = soap->fsend(soap, t, strlen(t))))
|
|
830 return soap->error;
|
|
831 soap->chunksize += n;
|
|
832 }
|
|
833 DBGMSG(SENT, s, n);
|
|
834 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Send %u bytes to socket=%d/fd=%d\n", (unsigned int)n, soap->socket, soap->sendfd));
|
|
835 #endif
|
|
836 return soap->error = soap->fsend(soap, s, n);
|
|
837 }
|
|
838 #endif
|
|
839
|
|
840 /******************************************************************************/
|
|
841 #ifndef PALM_1
|
|
842 SOAP_FMAC1
|
|
843 int
|
|
844 SOAP_FMAC2
|
|
845 soap_send(struct soap *soap, const char *s)
|
|
846 { if (s)
|
|
847 return soap_send_raw(soap, s, strlen(s));
|
|
848 return SOAP_OK;
|
|
849 }
|
|
850 #endif
|
|
851
|
|
852 /******************************************************************************/
|
|
853 #ifndef WITH_LEANER
|
|
854 #ifndef PALM_1
|
|
855 SOAP_FMAC1
|
|
856 int
|
|
857 SOAP_FMAC2
|
|
858 soap_send2(struct soap *soap, const char *s1, const char *s2)
|
|
859 { if (soap_send(soap, s1))
|
|
860 return soap->error;
|
|
861 return soap_send(soap, s2);
|
|
862 }
|
|
863 #endif
|
|
864 #endif
|
|
865
|
|
866 /******************************************************************************/
|
|
867 #ifndef WITH_LEANER
|
|
868 #ifndef PALM_1
|
|
869 SOAP_FMAC1
|
|
870 int
|
|
871 SOAP_FMAC2
|
|
872 soap_send3(struct soap *soap, const char *s1, const char *s2, const char *s3)
|
|
873 { if (soap_send(soap, s1)
|
|
874 || soap_send(soap, s2))
|
|
875 return soap->error;
|
|
876 return soap_send(soap, s3);
|
|
877 }
|
|
878 #endif
|
|
879 #endif
|
|
880
|
|
881 /******************************************************************************/
|
|
882 #ifndef WITH_NOIO
|
|
883 #ifndef PALM_1
|
|
884 static size_t
|
|
885 frecv(struct soap *soap, char *s, size_t n)
|
|
886 { register int r;
|
|
887 register int retries = 100; /* max 100 retries with non-blocking sockets */
|
|
888 SOAP_SOCKET sk;
|
|
889 soap->errnum = 0;
|
|
890 #if defined(__cplusplus) && !defined(WITH_LEAN) && !defined(WITH_COMPAT)
|
|
891 if (soap->is)
|
|
892 { if (soap->is->good())
|
|
893 return soap->is->read(s, (std::streamsize)n).gcount();
|
|
894 return 0;
|
|
895 }
|
|
896 #endif
|
|
897 sk = soap->recvsk;
|
|
898 if (!soap_valid_socket(sk))
|
|
899 sk = soap->socket;
|
|
900 if (soap_valid_socket(sk))
|
|
901 { for (;;)
|
|
902 {
|
|
903 #ifdef WITH_OPENSSL
|
|
904 register int err = 0;
|
|
905 #endif
|
|
906 #ifdef WITH_OPENSSL
|
|
907 if (soap->recv_timeout && !soap->ssl) /* SSL: sockets are nonblocking */
|
|
908 #else
|
|
909 if (soap->recv_timeout)
|
|
910 #endif
|
|
911 { for (;;)
|
|
912 { r = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->recv_timeout);
|
|
913 if (r > 0)
|
|
914 break;
|
|
915 if (!r)
|
|
916 return 0;
|
|
917 r = soap->errnum;
|
|
918 if (r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
|
|
919 return 0;
|
|
920 }
|
|
921 }
|
|
922 #ifdef WITH_OPENSSL
|
|
923 if (soap->ssl)
|
|
924 { r = SSL_read(soap->ssl, s, (int)n);
|
|
925 if (r > 0)
|
|
926 return (size_t)r;
|
|
927 err = SSL_get_error(soap->ssl, r);
|
|
928 if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
|
|
929 return 0;
|
|
930 }
|
|
931 else if (soap->bio)
|
|
932 { r = BIO_read(soap->bio, s, (int)n);
|
|
933 if (r > 0)
|
|
934 return (size_t)r;
|
|
935 return 0;
|
|
936 }
|
|
937 else
|
|
938 #endif
|
|
939 #ifdef WITH_GNUTLS
|
|
940 if (soap->session)
|
|
941 { r = (int)gnutls_record_recv(soap->session, s, n);
|
|
942 if (r >= 0)
|
|
943 return (size_t)r;
|
|
944 }
|
|
945 else
|
|
946 #endif
|
|
947 {
|
|
948 #ifndef WITH_LEAN
|
|
949 if ((soap->omode & SOAP_IO_UDP))
|
|
950 { SOAP_SOCKLEN_T k = (SOAP_SOCKLEN_T)sizeof(soap->peer);
|
|
951 memset((void*)&soap->peer, 0, sizeof(soap->peer));
|
|
952 r = recvfrom(sk, s, (SOAP_WINSOCKINT)n, soap->socket_flags, (struct sockaddr*)&soap->peer, &k); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
|
|
953 soap->peerlen = (size_t)k;
|
|
954 #ifndef WITH_IPV6
|
|
955 soap->ip = ntohl(soap->peer.sin_addr.s_addr);
|
|
956 #endif
|
|
957 }
|
|
958 else
|
|
959 #endif
|
|
960 r = recv(sk, s, (int)n, soap->socket_flags);
|
|
961 #ifdef PALM
|
|
962 /* CycleSyncDisplay(curStatusMsg); */
|
|
963 #endif
|
|
964 if (r >= 0)
|
|
965 return (size_t)r;
|
|
966 r = soap_socket_errno(sk);
|
|
967 if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
|
|
968 { soap->errnum = r;
|
|
969 return 0;
|
|
970 }
|
|
971 }
|
|
972 #if defined(WITH_OPENSSL)
|
|
973 if (soap->ssl && err == SSL_ERROR_WANT_WRITE)
|
|
974 r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5);
|
|
975 else
|
|
976 #elif defined(WITH_GNUTLS)
|
|
977 if (soap->session && gnutls_record_get_direction(soap->session))
|
|
978 r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5);
|
|
979 else
|
|
980 #endif
|
|
981 r = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5);
|
|
982 if (!r && soap->recv_timeout)
|
|
983 return 0;
|
|
984 if (r < 0)
|
|
985 { r = soap->errnum;
|
|
986 if (r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
|
|
987 return 0;
|
|
988 }
|
|
989 if (retries-- <= 0)
|
|
990 return 0;
|
|
991 #ifdef PALM
|
|
992 r = soap_socket_errno(sk);
|
|
993 if (r != SOAP_EINTR && retries-- <= 0)
|
|
994 { soap->errnum = r;
|
|
995 return 0;
|
|
996 }
|
|
997 #endif
|
|
998 }
|
|
999 }
|
|
1000 #ifdef WITH_FASTCGI
|
|
1001 return fread(s, 1, n, stdin);
|
|
1002 #else
|
|
1003 #ifdef UNDER_CE
|
|
1004 return fread(s, 1, n, soap->recvfd);
|
|
1005 #else
|
|
1006 #ifdef WMW_RPM_IO
|
|
1007 if (soap->rpmreqid)
|
|
1008 r = httpBlockRead(soap->rpmreqid, s, n);
|
|
1009 else
|
|
1010 #endif
|
|
1011 #ifdef WIN32
|
|
1012 r = _read(soap->recvfd, s, (unsigned int)n);
|
|
1013 #else
|
|
1014 r = read(soap->recvfd, s, (unsigned int)n);
|
|
1015 #endif
|
|
1016 if (r >= 0)
|
|
1017 return (size_t)r;
|
|
1018 soap->errnum = soap_errno;
|
|
1019 return 0;
|
|
1020 #endif
|
|
1021 #endif
|
|
1022 }
|
|
1023 #endif
|
|
1024 #endif
|
|
1025
|
|
1026 /******************************************************************************/
|
|
1027 #ifndef WITH_NOHTTP
|
|
1028 #ifndef PALM_1
|
|
1029 static soap_wchar
|
|
1030 soap_getchunkchar(struct soap *soap)
|
|
1031 { if (soap->bufidx < soap->buflen)
|
|
1032 return soap->buf[soap->bufidx++];
|
|
1033 soap->bufidx = 0;
|
|
1034 soap->buflen = soap->chunkbuflen = soap->frecv(soap, soap->buf, SOAP_BUFLEN);
|
|
1035 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket=%d/fd=%d\n", (unsigned int)soap->buflen, soap->socket, soap->recvfd));
|
|
1036 DBGMSG(RECV, soap->buf, soap->buflen);
|
|
1037 if (soap->buflen)
|
|
1038 return soap->buf[soap->bufidx++];
|
|
1039 return EOF;
|
|
1040 }
|
|
1041 #endif
|
|
1042 #endif
|
|
1043
|
|
1044 /******************************************************************************/
|
|
1045 #ifndef PALM_1
|
|
1046 static int
|
|
1047 soap_isxdigit(int c)
|
|
1048 { return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
|
|
1049 }
|
|
1050 #endif
|
|
1051
|
|
1052 /******************************************************************************/
|
|
1053 #ifndef PALM_1
|
|
1054 SOAP_FMAC1
|
|
1055 int
|
|
1056 SOAP_FMAC2
|
|
1057 soap_recv_raw(struct soap *soap)
|
|
1058 { register size_t ret;
|
|
1059 #if !defined(WITH_LEANER) || defined(WITH_ZLIB)
|
|
1060 register int r;
|
|
1061 #endif
|
|
1062 #ifdef WITH_ZLIB
|
|
1063 if (soap->mode & SOAP_ENC_ZLIB)
|
|
1064 { if (soap->d_stream->next_out == Z_NULL)
|
|
1065 { soap->bufidx = soap->buflen = 0;
|
|
1066 return EOF;
|
|
1067 }
|
|
1068 if (soap->d_stream->avail_in || !soap->d_stream->avail_out)
|
|
1069 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflating\n"));
|
|
1070 soap->d_stream->next_out = (Byte*)soap->buf;
|
|
1071 soap->d_stream->avail_out = SOAP_BUFLEN;
|
|
1072 r = inflate(soap->d_stream, Z_NO_FLUSH);
|
|
1073 if (r == Z_NEED_DICT && soap->z_dict)
|
|
1074 r = inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len);
|
|
1075 if (r == Z_OK || r == Z_STREAM_END)
|
|
1076 { soap->bufidx = 0;
|
|
1077 ret = soap->buflen = SOAP_BUFLEN - soap->d_stream->avail_out;
|
|
1078 if (soap->zlib_in == SOAP_ZLIB_GZIP)
|
|
1079 soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)ret);
|
|
1080 if (r == Z_STREAM_END)
|
|
1081 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out));
|
|
1082 soap->z_ratio_in = (float)soap->d_stream->total_in / (float)soap->d_stream->total_out;
|
|
1083 soap->d_stream->next_out = Z_NULL;
|
|
1084 }
|
|
1085 if (ret)
|
|
1086 { soap->count += ret;
|
|
1087 DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- decompressed ----\n"));
|
|
1088 DBGMSG(RECV, soap->buf, ret);
|
|
1089 DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n----\n"));
|
|
1090 #ifndef WITH_LEANER
|
|
1091 if (soap->fpreparerecv && (r = soap->fpreparerecv(soap, soap->buf, ret)))
|
|
1092 return soap->error = r;
|
|
1093 #endif
|
|
1094 return SOAP_OK;
|
|
1095 }
|
|
1096 }
|
|
1097 else if (r != Z_BUF_ERROR)
|
|
1098 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate error: %s\n", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS));
|
|
1099 soap->d_stream->next_out = Z_NULL;
|
|
1100 return soap->error = SOAP_ZLIB_ERROR;
|
|
1101 }
|
|
1102 }
|
|
1103 zlib_again:
|
|
1104 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK && !soap->chunksize)
|
|
1105 { memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN);
|
|
1106 soap->buflen = soap->z_buflen;
|
|
1107 }
|
|
1108 DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- compressed ----\n"));
|
|
1109 }
|
|
1110 #endif
|
|
1111 #ifndef WITH_NOHTTP
|
|
1112 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) /* read HTTP chunked transfer */
|
|
1113 { for (;;)
|
|
1114 { register soap_wchar c;
|
|
1115 char *t, tmp[17];
|
|
1116 if (soap->chunksize)
|
|
1117 { soap->buflen = ret = soap->frecv(soap, soap->buf, soap->chunksize > SOAP_BUFLEN ? SOAP_BUFLEN : soap->chunksize);
|
|
1118 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk: read %u bytes\n", (unsigned int)ret));
|
|
1119 DBGMSG(RECV, soap->buf, ret);
|
|
1120 soap->bufidx = 0;
|
|
1121 soap->chunksize -= ret;
|
|
1122 break;
|
|
1123 }
|
|
1124 t = tmp;
|
|
1125 if (!soap->chunkbuflen)
|
|
1126 { soap->chunkbuflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN);
|
|
1127 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes (chunked) from socket=%d\n", (unsigned int)ret, soap->socket));
|
|
1128 DBGMSG(RECV, soap->buf, ret);
|
|
1129 soap->bufidx = 0;
|
|
1130 if (!ret)
|
|
1131 { soap->ahead = EOF;
|
|
1132 return EOF;
|
|
1133 }
|
|
1134 }
|
|
1135 else
|
|
1136 soap->bufidx = soap->buflen;
|
|
1137 soap->buflen = soap->chunkbuflen;
|
|
1138 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk size (idx=%u len=%u)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen));
|
|
1139 while (!soap_isxdigit((int)(c = soap_getchunkchar(soap))))
|
|
1140 { if ((int)c == EOF)
|
|
1141 { soap->ahead = EOF;
|
|
1142 return EOF;
|
|
1143 }
|
|
1144 }
|
|
1145 do
|
|
1146 *t++ = (char)c;
|
|
1147 while (soap_isxdigit((int)(c = soap_getchunkchar(soap))) && (size_t)(t - tmp) < sizeof(tmp)-1);
|
|
1148 while ((int)c != EOF && c != '\n')
|
|
1149 c = soap_getchunkchar(soap);
|
|
1150 if ((int)c == EOF)
|
|
1151 { soap->ahead = EOF;
|
|
1152 return EOF;
|
|
1153 }
|
|
1154 *t = '\0';
|
|
1155 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunk size = %s (hex)\n", tmp));
|
|
1156 soap->chunksize = (size_t)soap_strtoul(tmp, &t, 16);
|
|
1157 if (!soap->chunksize)
|
|
1158 { soap->bufidx = soap->buflen = soap->chunkbuflen = 0;
|
|
1159 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of chunked message\n"));
|
|
1160 while ((int)c != EOF && c != '\n')
|
|
1161 c = soap_getchunkchar(soap);
|
|
1162 ret = 0;
|
|
1163 soap->ahead = EOF;
|
|
1164 break;
|
|
1165 }
|
|
1166 soap->buflen = soap->bufidx + soap->chunksize;
|
|
1167 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving buf len to idx=%u len=%u (%s)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen, tmp));
|
|
1168 if (soap->buflen > soap->chunkbuflen)
|
|
1169 { soap->buflen = soap->chunkbuflen;
|
|
1170 soap->chunksize -= soap->buflen - soap->bufidx;
|
|
1171 soap->chunkbuflen = 0;
|
|
1172 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Passed end of buffer for chunked HTTP (%u bytes left)\n", (unsigned int)(soap->buflen - soap->bufidx)));
|
|
1173 }
|
|
1174 else if (soap->chunkbuflen)
|
|
1175 soap->chunksize = 0;
|
|
1176 ret = soap->buflen - soap->bufidx;
|
|
1177 if (ret)
|
|
1178 break;
|
|
1179 }
|
|
1180 }
|
|
1181 else
|
|
1182 #endif
|
|
1183 { soap->bufidx = 0;
|
|
1184 soap->buflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN);
|
|
1185 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket=%d/fd=%d\n", (unsigned int)ret, soap->socket, soap->recvfd));
|
|
1186 DBGMSG(RECV, soap->buf, ret);
|
|
1187 }
|
|
1188 #ifdef WITH_ZLIB
|
|
1189 if (soap->mode & SOAP_ENC_ZLIB)
|
|
1190 { memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN);
|
|
1191 soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx);
|
|
1192 soap->d_stream->avail_in = (unsigned int)ret;
|
|
1193 soap->d_stream->next_out = (Byte*)soap->buf;
|
|
1194 soap->d_stream->avail_out = SOAP_BUFLEN;
|
|
1195 r = inflate(soap->d_stream, Z_NO_FLUSH);
|
|
1196 if (r == Z_NEED_DICT && soap->z_dict)
|
|
1197 r = inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len);
|
|
1198 if (r == Z_OK || r == Z_STREAM_END)
|
|
1199 { soap->bufidx = 0;
|
|
1200 soap->z_buflen = soap->buflen;
|
|
1201 soap->buflen = SOAP_BUFLEN - soap->d_stream->avail_out;
|
|
1202 if (soap->zlib_in == SOAP_ZLIB_GZIP)
|
|
1203 soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen);
|
|
1204 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %u bytes\n", (unsigned int)soap->buflen));
|
|
1205 if (ret && !soap->buflen && r != Z_STREAM_END)
|
|
1206 goto zlib_again;
|
|
1207 ret = soap->buflen;
|
|
1208 if (r == Z_STREAM_END)
|
|
1209 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated total %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out));
|
|
1210 soap->z_ratio_in = (float)soap->d_stream->total_in / (float)soap->d_stream->total_out;
|
|
1211 soap->d_stream->next_out = Z_NULL;
|
|
1212 }
|
|
1213 DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- decompressed ----\n"));
|
|
1214 DBGMSG(RECV, soap->buf, ret);
|
|
1215 #ifndef WITH_LEANER
|
|
1216 if (soap->fpreparerecv && (r = soap->fpreparerecv(soap, soap->buf, ret)))
|
|
1217 return soap->error = r;
|
|
1218 #endif
|
|
1219 }
|
|
1220 else
|
|
1221 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to inflate: (%d) %s\n", r, soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS));
|
|
1222 soap->d_stream->next_out = Z_NULL;
|
|
1223 return soap->error = SOAP_ZLIB_ERROR;
|
|
1224 }
|
|
1225 }
|
|
1226 #endif
|
|
1227 #ifndef WITH_LEANER
|
|
1228 if (soap->fpreparerecv
|
|
1229 #ifdef WITH_ZLIB
|
|
1230 && soap->zlib_in == SOAP_ZLIB_NONE
|
|
1231 #endif
|
|
1232 && (r = soap->fpreparerecv(soap, soap->buf + soap->bufidx, ret)))
|
|
1233 return soap->error = r;
|
|
1234 #endif
|
|
1235 soap->count += ret;
|
|
1236 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read count=%lu (+%lu)\n", (unsigned long)soap->count, (unsigned long)ret));
|
|
1237 return !ret;
|
|
1238 }
|
|
1239 #endif
|
|
1240
|
|
1241 /******************************************************************************/
|
|
1242 #ifndef PALM_1
|
|
1243 SOAP_FMAC1
|
|
1244 int
|
|
1245 SOAP_FMAC2
|
|
1246 soap_recv(struct soap *soap)
|
|
1247 {
|
|
1248 #ifndef WITH_LEANER
|
|
1249 if (soap->mode & SOAP_ENC_DIME)
|
|
1250 { if (soap->dime.buflen)
|
|
1251 { char *s;
|
|
1252 int i;
|
|
1253 unsigned char tmp[12];
|
|
1254 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME hdr for chunked DIME is in buffer\n"));
|
|
1255 soap->count += soap->dime.buflen - soap->buflen;
|
|
1256 soap->buflen = soap->dime.buflen;
|
|
1257 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Skip padding (%ld bytes)\n", -(long)soap->dime.size&3));
|
|
1258 for (i = -(long)soap->dime.size&3; i > 0; i--)
|
|
1259 { soap->bufidx++;
|
|
1260 if (soap->bufidx >= soap->buflen)
|
|
1261 if (soap_recv_raw(soap))
|
|
1262 return EOF;
|
|
1263 }
|
|
1264 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME hdr for next chunk\n"));
|
|
1265 s = (char*)tmp;
|
|
1266 for (i = 12; i > 0; i--)
|
|
1267 { *s++ = soap->buf[soap->bufidx++];
|
|
1268 if (soap->bufidx >= soap->buflen)
|
|
1269 if (soap_recv_raw(soap))
|
|
1270 return EOF;
|
|
1271 }
|
|
1272 soap->dime.flags = tmp[0] & 0x7;
|
|
1273 soap->dime.size = ((size_t)tmp[8] << 24) | ((size_t)tmp[9] << 16) | ((size_t)tmp[10] << 8) | ((size_t)tmp[11]);
|
|
1274 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME chunk (%u bytes)\n", (unsigned int)soap->dime.size));
|
|
1275 if (soap->dime.flags & SOAP_DIME_CF)
|
|
1276 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "More chunking\n"));
|
|
1277 soap->dime.chunksize = soap->dime.size;
|
|
1278 if (soap->buflen - soap->bufidx >= soap->dime.size)
|
|
1279 { soap->dime.buflen = soap->buflen;
|
|
1280 soap->buflen = soap->bufidx + soap->dime.chunksize;
|
|
1281 }
|
|
1282 else
|
|
1283 soap->dime.chunksize -= soap->buflen - soap->bufidx;
|
|
1284 }
|
|
1285 else
|
|
1286 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Last chunk\n"));
|
|
1287 soap->dime.buflen = 0;
|
|
1288 soap->dime.chunksize = 0;
|
|
1289 }
|
|
1290 soap->count = soap->buflen - soap->bufidx;
|
|
1291 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%u bytes remaining\n", (unsigned int)soap->count));
|
|
1292 return SOAP_OK;
|
|
1293 }
|
|
1294 if (soap->dime.chunksize)
|
|
1295 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get next DIME hdr for chunked DIME (%u bytes chunk)\n", (unsigned int)soap->dime.chunksize));
|
|
1296 if (soap_recv_raw(soap))
|
|
1297 return EOF;
|
|
1298 if (soap->buflen - soap->bufidx >= soap->dime.chunksize)
|
|
1299 { soap->dime.buflen = soap->buflen;
|
|
1300 soap->count -= soap->buflen - soap->bufidx - soap->dime.chunksize;
|
|
1301 soap->buflen = soap->bufidx + soap->dime.chunksize;
|
|
1302 }
|
|
1303 else
|
|
1304 soap->dime.chunksize -= soap->buflen - soap->bufidx;
|
|
1305 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%lu bytes remaining, count=%lu\n", (unsigned long)(soap->buflen-soap->bufidx), (unsigned long)soap->count));
|
|
1306 return SOAP_OK;
|
|
1307 }
|
|
1308 }
|
|
1309 while (soap->ffilterrecv)
|
|
1310 { int err, last = soap->filterstop;
|
|
1311 if (last)
|
|
1312 soap->bufidx = soap->buflen = 0;
|
|
1313 if ((err = soap->ffilterrecv(soap, soap->buf, &soap->buflen, sizeof(soap->buf))))
|
|
1314 return soap->error = err;
|
|
1315 if (soap->buflen)
|
|
1316 { soap->bufidx = 0;
|
|
1317 soap->filterstop = last;
|
|
1318 return SOAP_OK;
|
|
1319 }
|
|
1320 if (last)
|
|
1321 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Returning postponed error %d\n", last));
|
|
1322 soap->filterstop = SOAP_OK;
|
|
1323 return last;
|
|
1324 }
|
|
1325 soap->filterstop = soap_recv_raw(soap); /* do not call again after EOF */
|
|
1326 }
|
|
1327 #endif
|
|
1328 return soap_recv_raw(soap);
|
|
1329 }
|
|
1330 #endif
|
|
1331
|
|
1332 /******************************************************************************/
|
|
1333 #ifndef PALM_1
|
|
1334 SOAP_FMAC1
|
|
1335 soap_wchar
|
|
1336 SOAP_FMAC2
|
|
1337 soap_getchar(struct soap *soap)
|
|
1338 { register soap_wchar c;
|
|
1339 c = soap->ahead;
|
|
1340 if (c)
|
|
1341 { if (c != EOF)
|
|
1342 soap->ahead = 0;
|
|
1343 return c;
|
|
1344 }
|
|
1345 return soap_get1(soap);
|
|
1346 }
|
|
1347 #endif
|
|
1348
|
|
1349 /******************************************************************************/
|
|
1350 #ifndef PALM_1
|
|
1351 SOAP_FMAC1
|
|
1352 const struct soap_code_map*
|
|
1353 SOAP_FMAC2
|
|
1354 soap_code(const struct soap_code_map *code_map, const char *str)
|
|
1355 { if (code_map && str)
|
|
1356 { while (code_map->string)
|
|
1357 { if (!strcmp(str, code_map->string)) /* case sensitive */
|
|
1358 return code_map;
|
|
1359 code_map++;
|
|
1360 }
|
|
1361 }
|
|
1362 return NULL;
|
|
1363 }
|
|
1364 #endif
|
|
1365
|
|
1366 /******************************************************************************/
|
|
1367 #ifndef PALM_1
|
|
1368 SOAP_FMAC1
|
|
1369 long
|
|
1370 SOAP_FMAC2
|
|
1371 soap_code_int(const struct soap_code_map *code_map, const char *str, long other)
|
|
1372 { if (code_map)
|
|
1373 { while (code_map->string)
|
|
1374 { if (!soap_tag_cmp(str, code_map->string)) /* case insensitive */
|
|
1375 return code_map->code;
|
|
1376 code_map++;
|
|
1377 }
|
|
1378 }
|
|
1379 return other;
|
|
1380 }
|
|
1381 #endif
|
|
1382
|
|
1383 /******************************************************************************/
|
|
1384 #ifndef PALM_1
|
|
1385 SOAP_FMAC1
|
|
1386 const char*
|
|
1387 SOAP_FMAC2
|
|
1388 soap_code_str(const struct soap_code_map *code_map, long code)
|
|
1389 { if (!code_map)
|
|
1390 return NULL;
|
|
1391 while (code_map->code != code && code_map->string)
|
|
1392 code_map++;
|
|
1393 return code_map->string;
|
|
1394 }
|
|
1395 #endif
|
|
1396
|
|
1397 /******************************************************************************/
|
|
1398 #ifndef PALM_1
|
|
1399 SOAP_FMAC1
|
|
1400 long
|
|
1401 SOAP_FMAC2
|
|
1402 soap_code_bits(const struct soap_code_map *code_map, const char *str)
|
|
1403 { register long bits = 0;
|
|
1404 if (code_map)
|
|
1405 { while (str && *str)
|
|
1406 { const struct soap_code_map *p;
|
|
1407 for (p = code_map; p->string; p++)
|
|
1408 { register size_t n = strlen(p->string);
|
|
1409 if (!strncmp(p->string, str, n) && soap_blank((soap_wchar)str[n]))
|
|
1410 { bits |= p->code;
|
|
1411 str += n;
|
|
1412 while (*str > 0 && *str <= 32)
|
|
1413 str++;
|
|
1414 break;
|
|
1415 }
|
|
1416 }
|
|
1417 if (!p->string)
|
|
1418 return 0;
|
|
1419 }
|
|
1420 }
|
|
1421 return bits;
|
|
1422 }
|
|
1423 #endif
|
|
1424
|
|
1425 /******************************************************************************/
|
|
1426 #ifndef PALM_1
|
|
1427 SOAP_FMAC1
|
|
1428 const char*
|
|
1429 SOAP_FMAC2
|
|
1430 soap_code_list(struct soap *soap, const struct soap_code_map *code_map, long code)
|
|
1431 { register char *t = soap->tmpbuf;
|
|
1432 if (code_map)
|
|
1433 { while (code_map->string)
|
|
1434 { if (code_map->code & code)
|
|
1435 { register const char *s = code_map->string;
|
|
1436 if (t != soap->tmpbuf)
|
|
1437 *t++ = ' ';
|
|
1438 while (*s && t < soap->tmpbuf + sizeof(soap->tmpbuf) - 1)
|
|
1439 *t++ = *s++;
|
|
1440 if (t == soap->tmpbuf + sizeof(soap->tmpbuf) - 1)
|
|
1441 break;
|
|
1442 }
|
|
1443 code_map++;
|
|
1444 }
|
|
1445 }
|
|
1446 *t = '\0';
|
|
1447 return soap->tmpbuf;
|
|
1448 }
|
|
1449 #endif
|
|
1450
|
|
1451 /******************************************************************************/
|
|
1452 #ifndef PALM_1
|
|
1453 static soap_wchar
|
|
1454 soap_char(struct soap *soap)
|
|
1455 { char tmp[8];
|
|
1456 register int i;
|
|
1457 register soap_wchar c;
|
|
1458 register char *s = tmp;
|
|
1459 for (i = 0; i < 7; i++)
|
|
1460 { c = soap_get1(soap);
|
|
1461 if (c == ';' || (int)c == EOF)
|
|
1462 break;
|
|
1463 *s++ = (char)c;
|
|
1464 }
|
|
1465 *s = '\0';
|
|
1466 if (*tmp == '#')
|
|
1467 { if (tmp[1] == 'x' || tmp[1] == 'X')
|
|
1468 return (soap_wchar)soap_strtol(tmp + 2, NULL, 16);
|
|
1469 return (soap_wchar)soap_strtol(tmp + 1, NULL, 10);
|
|
1470 }
|
|
1471 if (!strcmp(tmp, "lt"))
|
|
1472 return '<';
|
|
1473 if (!strcmp(tmp, "gt"))
|
|
1474 return '>';
|
|
1475 if (!strcmp(tmp, "amp"))
|
|
1476 return '&';
|
|
1477 if (!strcmp(tmp, "quot"))
|
|
1478 return '"';
|
|
1479 if (!strcmp(tmp, "apos"))
|
|
1480 return '\'';
|
|
1481 #ifndef WITH_LEAN
|
|
1482 return (soap_wchar)soap_code_int(html_entity_codes, tmp, SOAP_UNKNOWN_CHAR);
|
|
1483 #else
|
|
1484 return SOAP_UNKNOWN_CHAR; /* use this to represent unknown code */
|
|
1485 #endif
|
|
1486 }
|
|
1487 #endif
|
|
1488
|
|
1489 /******************************************************************************/
|
|
1490 #ifdef WITH_LEAN
|
|
1491 #ifndef PALM_1
|
|
1492 soap_wchar
|
|
1493 soap_get0(struct soap *soap)
|
|
1494 { if (soap->bufidx >= soap->buflen && soap_recv(soap))
|
|
1495 return EOF;
|
|
1496 return (unsigned char)soap->buf[soap->bufidx];
|
|
1497 }
|
|
1498 #endif
|
|
1499 #endif
|
|
1500
|
|
1501 /******************************************************************************/
|
|
1502 #ifdef WITH_LEAN
|
|
1503 #ifndef PALM_1
|
|
1504 soap_wchar
|
|
1505 soap_get1(struct soap *soap)
|
|
1506 { if (soap->bufidx >= soap->buflen && soap_recv(soap))
|
|
1507 return EOF;
|
|
1508 return (unsigned char)soap->buf[soap->bufidx++];
|
|
1509 }
|
|
1510 #endif
|
|
1511 #endif
|
|
1512
|
|
1513 /******************************************************************************/
|
|
1514 #ifndef PALM_1
|
|
1515 SOAP_FMAC1
|
|
1516 soap_wchar
|
|
1517 SOAP_FMAC2
|
|
1518 soap_get(struct soap *soap)
|
|
1519 { register soap_wchar c;
|
|
1520 c = soap->ahead;
|
|
1521 if (c)
|
|
1522 { if ((int)c != EOF)
|
|
1523 soap->ahead = 0;
|
|
1524 }
|
|
1525 else
|
|
1526 c = soap_get1(soap);
|
|
1527 while ((int)c != EOF)
|
|
1528 { if (soap->cdata)
|
|
1529 { if (c == ']')
|
|
1530 { c = soap_get1(soap);
|
|
1531 if (c == ']')
|
|
1532 { c = soap_get0(soap);
|
|
1533 if (c == '>')
|
|
1534 { soap->cdata = 0;
|
|
1535 c = soap_get1(soap);
|
|
1536 c = soap_get1(soap);
|
|
1537 }
|
|
1538 else
|
|
1539 { soap_unget(soap, ']');
|
|
1540 return ']';
|
|
1541 }
|
|
1542 }
|
|
1543 else
|
|
1544 { soap_revget1(soap);
|
|
1545 return ']';
|
|
1546 }
|
|
1547 }
|
|
1548 else
|
|
1549 return c;
|
|
1550 }
|
|
1551 switch (c)
|
|
1552 { case '<':
|
|
1553 do c = soap_get1(soap);
|
|
1554 while (soap_blank(c));
|
|
1555 if (c == '!' || c == '?' || c == '%')
|
|
1556 { register int k = 1;
|
|
1557 if (c == '!')
|
|
1558 { c = soap_get1(soap);
|
|
1559 if (c == '[')
|
|
1560 { do c = soap_get1(soap);
|
|
1561 while ((int)c != EOF && c != '[');
|
|
1562 if ((int)c == EOF)
|
|
1563 break;
|
|
1564 soap->cdata = 1;
|
|
1565 c = soap_get1(soap);
|
|
1566 continue;
|
|
1567 }
|
|
1568 if (c == '-' && (c = soap_get1(soap)) == '-')
|
|
1569 { do
|
|
1570 { c = soap_get1(soap);
|
|
1571 if (c == '-' && (c = soap_get1(soap)) == '-')
|
|
1572 break;
|
|
1573 } while ((int)c != EOF);
|
|
1574 }
|
|
1575 }
|
|
1576 else if (c == '?')
|
|
1577 c = soap_get_pi(soap);
|
|
1578 while ((int)c != EOF)
|
|
1579 { if (c == '<')
|
|
1580 k++;
|
|
1581 else if (c == '>')
|
|
1582 { if (--k <= 0)
|
|
1583 break;
|
|
1584 }
|
|
1585 c = soap_get1(soap);
|
|
1586 }
|
|
1587 if ((int)c == EOF)
|
|
1588 break;
|
|
1589 c = soap_get1(soap);
|
|
1590 continue;
|
|
1591 }
|
|
1592 if (c == '/')
|
|
1593 return SOAP_TT;
|
|
1594 soap_revget1(soap);
|
|
1595 return SOAP_LT;
|
|
1596 case '>':
|
|
1597 return SOAP_GT;
|
|
1598 case '"':
|
|
1599 return SOAP_QT;
|
|
1600 case '\'':
|
|
1601 return SOAP_AP;
|
|
1602 case '&':
|
|
1603 return soap_char(soap) | 0x80000000;
|
|
1604 }
|
|
1605 break;
|
|
1606 }
|
|
1607 return c;
|
|
1608 }
|
|
1609 #endif
|
|
1610
|
|
1611 /******************************************************************************/
|
|
1612 #ifndef PALM_1
|
|
1613 static soap_wchar
|
|
1614 soap_get_pi(struct soap *soap)
|
|
1615 { char buf[64];
|
|
1616 register char *s = buf;
|
|
1617 register int i = sizeof(buf);
|
|
1618 register soap_wchar c = soap_getchar(soap);
|
|
1619 /* This is a quick way to parse XML PI and we could use a callback instead to
|
|
1620 * enable applications to intercept processing instructions */
|
|
1621 while ((int)c != EOF && c != '?')
|
|
1622 { if (--i > 0)
|
|
1623 { if (soap_blank(c))
|
|
1624 c = ' ';
|
|
1625 *s++ = (char)c;
|
|
1626 }
|
|
1627 c = soap_getchar(soap);
|
|
1628 }
|
|
1629 *s = '\0';
|
|
1630 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "XML PI <?%s?>\n", buf));
|
|
1631 if (!strncmp(buf, "xml ", 4))
|
|
1632 { s = strstr(buf, " encoding=");
|
|
1633 if (s && s[10])
|
|
1634 { if (!soap_tag_cmp(s + 11, "iso-8859-1*")
|
|
1635 || !soap_tag_cmp(s + 11, "latin1*"))
|
|
1636 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to latin1 encoding\n"));
|
|
1637 soap->mode |= SOAP_ENC_LATIN;
|
|
1638 }
|
|
1639 else if (!soap_tag_cmp(s + 11, "utf-8*"))
|
|
1640 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to utf-8 encoding\n"));
|
|
1641 soap->mode &= ~SOAP_ENC_LATIN;
|
|
1642 }
|
|
1643 }
|
|
1644 }
|
|
1645 if ((int)c != EOF)
|
|
1646 c = soap_getchar(soap);
|
|
1647 return c;
|
|
1648 }
|
|
1649 #endif
|
|
1650
|
|
1651 /******************************************************************************/
|
|
1652 #ifndef WITH_LEANER
|
|
1653 #ifndef PALM_1
|
|
1654 SOAP_FMAC1
|
|
1655 int
|
|
1656 SOAP_FMAC2
|
|
1657 soap_move(struct soap *soap, size_t n)
|
|
1658 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving %lu bytes forward\n", (unsigned long)n));
|
|
1659 for (; n; n--)
|
|
1660 if ((int)soap_getchar(soap) == EOF)
|
|
1661 return SOAP_EOF;
|
|
1662 return SOAP_OK;
|
|
1663 }
|
|
1664 #endif
|
|
1665 #endif
|
|
1666
|
|
1667 /******************************************************************************/
|
|
1668 #ifndef WITH_LEANER
|
|
1669 #ifndef PALM_1
|
|
1670 SOAP_FMAC1
|
|
1671 size_t
|
|
1672 SOAP_FMAC2
|
|
1673 soap_tell(struct soap *soap)
|
|
1674 { return soap->count - soap->buflen + soap->bufidx - (soap->ahead != 0);
|
|
1675 }
|
|
1676 #endif
|
|
1677 #endif
|
|
1678
|
|
1679 /******************************************************************************/
|
|
1680 #ifndef PALM_1
|
|
1681 SOAP_FMAC1
|
|
1682 int
|
|
1683 SOAP_FMAC2
|
|
1684 soap_pututf8(struct soap *soap, register unsigned long c)
|
|
1685 { char tmp[16];
|
|
1686 if (c < 0x80 && c > 0)
|
|
1687 { *tmp = (char)c;
|
|
1688 return soap_send_raw(soap, tmp, 1);
|
|
1689 }
|
|
1690 #ifndef WITH_LEAN
|
|
1691 if (c >= 0x80)
|
|
1692 { register char *t = tmp;
|
|
1693 if (c < 0x0800)
|
|
1694 *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
|
|
1695 else
|
|
1696 { if (c < 0x010000)
|
|
1697 *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
|
|
1698 else
|
|
1699 { if (c < 0x200000)
|
|
1700 *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
|
|
1701 else
|
|
1702 { if (c < 0x04000000)
|
|
1703 *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
|
|
1704 else
|
|
1705 { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
|
|
1706 *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
|
|
1707 }
|
|
1708 *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
|
|
1709 }
|
|
1710 *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
|
|
1711 }
|
|
1712 *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
|
|
1713 }
|
|
1714 *t++ = (char)(0x80 | (c & 0x3F));
|
|
1715 *t = '\0';
|
|
1716 }
|
|
1717 else
|
|
1718 #endif
|
|
1719 #ifdef HAVE_SNPRINTF
|
|
1720 soap_snprintf(tmp, sizeof(tmp), "&#%lu;", c);
|
|
1721 #else
|
|
1722 sprintf(tmp, "&#%lu;", c);
|
|
1723 #endif
|
|
1724 return soap_send(soap, tmp);
|
|
1725 }
|
|
1726 #endif
|
|
1727
|
|
1728 /******************************************************************************/
|
|
1729 #ifndef PALM_1
|
|
1730 SOAP_FMAC1
|
|
1731 soap_wchar
|
|
1732 SOAP_FMAC2
|
|
1733 soap_getutf8(struct soap *soap)
|
|
1734 { register soap_wchar c, c1, c2, c3, c4;
|
|
1735 c = soap->ahead;
|
|
1736 if (c >= 0x80)
|
|
1737 soap->ahead = 0;
|
|
1738 else
|
|
1739 c = soap_get(soap);
|
|
1740 if (c < 0x80 || c > 0xFF || (soap->mode & SOAP_ENC_LATIN))
|
|
1741 return c;
|
|
1742 c1 = soap_get1(soap);
|
|
1743 if (c1 < 0x80)
|
|
1744 { soap_revget1(soap); /* doesn't look like this is UTF8 */
|
|
1745 return c;
|
|
1746 }
|
|
1747 c1 &= 0x3F;
|
|
1748 if (c < 0xE0)
|
|
1749 return ((soap_wchar)(c & 0x1F) << 6) | c1;
|
|
1750 c2 = (soap_wchar)soap_get1(soap) & 0x3F;
|
|
1751 if (c < 0xF0)
|
|
1752 return ((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2;
|
|
1753 c3 = (soap_wchar)soap_get1(soap) & 0x3F;
|
|
1754 if (c < 0xF8)
|
|
1755 return ((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3;
|
|
1756 c4 = (soap_wchar)soap_get1(soap) & 0x3F;
|
|
1757 if (c < 0xFC)
|
|
1758 return ((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4;
|
|
1759 return ((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(soap_get1(soap) & 0x3F);
|
|
1760 }
|
|
1761 #endif
|
|
1762
|
|
1763 /******************************************************************************/
|
|
1764 #ifndef PALM_1
|
|
1765 SOAP_FMAC1
|
|
1766 int
|
|
1767 SOAP_FMAC2
|
|
1768 soap_puthex(struct soap *soap, const unsigned char *s, int n)
|
|
1769 { char d[2];
|
|
1770 register int i;
|
|
1771 #ifdef WITH_DOM
|
|
1772 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
|
|
1773 { if (!(soap->dom->data = soap_s2hex(soap, s, NULL, n)))
|
|
1774 return soap->error;
|
|
1775 return SOAP_OK;
|
|
1776 }
|
|
1777 #endif
|
|
1778 for (i = 0; i < n; i++)
|
|
1779 { register int m = *s++;
|
|
1780 d[0] = (char)((m >> 4) + (m > 159 ? '7' : '0'));
|
|
1781 m &= 0x0F;
|
|
1782 d[1] = (char)(m + (m > 9 ? '7' : '0'));
|
|
1783 if (soap_send_raw(soap, d, 2))
|
|
1784 return soap->error;
|
|
1785 }
|
|
1786 return SOAP_OK;
|
|
1787 }
|
|
1788 #endif
|
|
1789
|
|
1790 /******************************************************************************/
|
|
1791 #ifndef PALM_1
|
|
1792 SOAP_FMAC1
|
|
1793 unsigned char*
|
|
1794 SOAP_FMAC2
|
|
1795 soap_gethex(struct soap *soap, int *n)
|
|
1796 {
|
|
1797 #ifdef WITH_DOM
|
|
1798 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
|
|
1799 { soap->dom->data = soap_string_in(soap, 0, -1, -1);
|
|
1800 return (unsigned char*)soap_hex2s(soap, soap->dom->data, NULL, 0, n);
|
|
1801 }
|
|
1802 #endif
|
|
1803 #ifdef WITH_FAST
|
|
1804 soap->labidx = 0;
|
|
1805 for (;;)
|
|
1806 { register char *s;
|
|
1807 register size_t i, k;
|
|
1808 if (soap_append_lab(soap, NULL, 0))
|
|
1809 return NULL;
|
|
1810 s = soap->labbuf + soap->labidx;
|
|
1811 k = soap->lablen - soap->labidx;
|
|
1812 soap->labidx = soap->lablen;
|
|
1813 for (i = 0; i < k; i++)
|
|
1814 { register char d1, d2;
|
|
1815 register soap_wchar c;
|
|
1816 c = soap_get(soap);
|
|
1817 if (soap_isxdigit(c))
|
|
1818 { d1 = (char)c;
|
|
1819 c = soap_get(soap);
|
|
1820 if (soap_isxdigit(c))
|
|
1821 d2 = (char)c;
|
|
1822 else
|
|
1823 { soap->error = SOAP_TYPE;
|
|
1824 return NULL;
|
|
1825 }
|
|
1826 }
|
|
1827 else
|
|
1828 { unsigned char *p;
|
|
1829 soap_unget(soap, c);
|
|
1830 if (n)
|
|
1831 *n = (int)(soap->lablen + i - k);
|
|
1832 p = (unsigned char*)soap_malloc(soap, soap->lablen + i - k);
|
|
1833 if (p)
|
|
1834 memcpy(p, soap->labbuf, soap->lablen + i - k);
|
|
1835 return p;
|
|
1836 }
|
|
1837 *s++ = (char)(((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'));
|
|
1838 }
|
|
1839 }
|
|
1840 #else
|
|
1841 if (soap_new_block(soap) == NULL)
|
|
1842 return NULL;
|
|
1843 for (;;)
|
|
1844 { register int i;
|
|
1845 register char *s = (char*)soap_push_block(soap, NULL, SOAP_BLKLEN);
|
|
1846 if (!s)
|
|
1847 { soap_end_block(soap, NULL);
|
|
1848 return NULL;
|
|
1849 }
|
|
1850 for (i = 0; i < SOAP_BLKLEN; i++)
|
|
1851 { register char d1, d2;
|
|
1852 register soap_wchar c = soap_get(soap);
|
|
1853 if (soap_isxdigit(c))
|
|
1854 { d1 = (char)c;
|
|
1855 c = soap_get(soap);
|
|
1856 if (soap_isxdigit(c))
|
|
1857 d2 = (char)c;
|
|
1858 else
|
|
1859 { soap_end_block(soap, NULL);
|
|
1860 soap->error = SOAP_TYPE;
|
|
1861 return NULL;
|
|
1862 }
|
|
1863 }
|
|
1864 else
|
|
1865 { unsigned char *p;
|
|
1866 soap_unget(soap, c);
|
|
1867 if (n)
|
|
1868 *n = (int)soap_size_block(soap, NULL, i);
|
|
1869 p = (unsigned char*)soap_save_block(soap, NULL, 0);
|
|
1870 return p;
|
|
1871 }
|
|
1872 *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0');
|
|
1873 }
|
|
1874 }
|
|
1875 #endif
|
|
1876 }
|
|
1877 #endif
|
|
1878
|
|
1879 /******************************************************************************/
|
|
1880 #ifndef PALM_1
|
|
1881 SOAP_FMAC1
|
|
1882 int
|
|
1883 SOAP_FMAC2
|
|
1884 soap_putbase64(struct soap *soap, const unsigned char *s, int n)
|
|
1885 { register int i;
|
|
1886 register unsigned long m;
|
|
1887 char d[4];
|
|
1888 if (!s)
|
|
1889 return SOAP_OK;
|
|
1890 #ifdef WITH_DOM
|
|
1891 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
|
|
1892 { if (!(soap->dom->data = soap_s2base64(soap, s, NULL, n)))
|
|
1893 return soap->error;
|
|
1894 return SOAP_OK;
|
|
1895 }
|
|
1896 #endif
|
|
1897 for (; n > 2; n -= 3, s += 3)
|
|
1898 { m = s[0];
|
|
1899 m = (m << 8) | s[1];
|
|
1900 m = (m << 8) | s[2];
|
|
1901 for (i = 4; i > 0; m >>= 6)
|
|
1902 d[--i] = soap_base64o[m & 0x3F];
|
|
1903 if (soap_send_raw(soap, d, 4))
|
|
1904 return soap->error;
|
|
1905 }
|
|
1906 if (n > 0)
|
|
1907 { m = 0;
|
|
1908 for (i = 0; i < n; i++)
|
|
1909 m = (m << 8) | *s++;
|
|
1910 for (; i < 3; i++)
|
|
1911 m <<= 8;
|
|
1912 for (i++; i > 0; m >>= 6)
|
|
1913 d[--i] = soap_base64o[m & 0x3F];
|
|
1914 for (i = 3; i > n; i--)
|
|
1915 d[i] = '=';
|
|
1916 if (soap_send_raw(soap, d, 4))
|
|
1917 return soap->error;
|
|
1918 }
|
|
1919 return SOAP_OK;
|
|
1920 }
|
|
1921 #endif
|
|
1922
|
|
1923 /******************************************************************************/
|
|
1924 #ifndef PALM_1
|
|
1925 SOAP_FMAC1
|
|
1926 unsigned char*
|
|
1927 SOAP_FMAC2
|
|
1928 soap_getbase64(struct soap *soap, int *n, int malloc_flag)
|
|
1929 { (void)malloc_flag;
|
|
1930 #ifdef WITH_DOM
|
|
1931 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
|
|
1932 { soap->dom->data = soap_string_in(soap, 0, -1, -1);
|
|
1933 return (unsigned char*)soap_base642s(soap, soap->dom->data, NULL, 0, n);
|
|
1934 }
|
|
1935 #endif
|
|
1936 #ifdef WITH_FAST
|
|
1937 soap->labidx = 0;
|
|
1938 for (;;)
|
|
1939 { register size_t i, k;
|
|
1940 register char *s;
|
|
1941 if (soap_append_lab(soap, NULL, 2))
|
|
1942 return NULL;
|
|
1943 s = soap->labbuf + soap->labidx;
|
|
1944 k = soap->lablen - soap->labidx;
|
|
1945 soap->labidx = 3 * (soap->lablen / 3);
|
|
1946 if (!s)
|
|
1947 return NULL;
|
|
1948 if (k > 2)
|
|
1949 { for (i = 0; i < k - 2; i += 3)
|
|
1950 { register unsigned long m = 0;
|
|
1951 register int j = 0;
|
|
1952 do
|
|
1953 { register soap_wchar c = soap_get(soap);
|
|
1954 if (c < SOAP_AP)
|
|
1955 c &= 0x7FFFFFFF;
|
|
1956 if (c == '=' || c < 0)
|
|
1957 { unsigned char *p;
|
|
1958 switch (j)
|
|
1959 { case 2:
|
|
1960 *s++ = (char)((m >> 4) & 0xFF);
|
|
1961 i++;
|
|
1962 break;
|
|
1963 case 3:
|
|
1964 *s++ = (char)((m >> 10) & 0xFF);
|
|
1965 *s++ = (char)((m >> 2) & 0xFF);
|
|
1966 i += 2;
|
|
1967 }
|
|
1968 if (n)
|
|
1969 *n = (int)(soap->lablen + i - k);
|
|
1970 p = (unsigned char*)soap_malloc(soap, soap->lablen + i - k);
|
|
1971 if (p)
|
|
1972 memcpy(p, soap->labbuf, soap->lablen + i - k);
|
|
1973 if (c >= 0)
|
|
1974 { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT)
|
|
1975 ;
|
|
1976 }
|
|
1977 soap_unget(soap, c);
|
|
1978 return p;
|
|
1979 }
|
|
1980 c -= '+';
|
|
1981 if (c >= 0 && c <= 79)
|
|
1982 { register int b = soap_base64i[c];
|
|
1983 if (b >= 64)
|
|
1984 { soap->error = SOAP_TYPE;
|
|
1985 return NULL;
|
|
1986 }
|
|
1987 m = (m << 6) + b;
|
|
1988 j++;
|
|
1989 }
|
|
1990 else if (!soap_blank(c + '+'))
|
|
1991 { soap->error = SOAP_TYPE;
|
|
1992 return NULL;
|
|
1993 }
|
|
1994 } while (j < 4);
|
|
1995 *s++ = (char)((m >> 16) & 0xFF);
|
|
1996 *s++ = (char)((m >> 8) & 0xFF);
|
|
1997 *s++ = (char)(m & 0xFF);
|
|
1998 }
|
|
1999 }
|
|
2000 }
|
|
2001 #else
|
|
2002 if (soap_new_block(soap) == NULL)
|
|
2003 return NULL;
|
|
2004 for (;;)
|
|
2005 { register int i;
|
|
2006 register char *s = (char*)soap_push_block(soap, NULL, 3 * SOAP_BLKLEN); /* must be multiple of 3 */
|
|
2007 if (!s)
|
|
2008 { soap_end_block(soap, NULL);
|
|
2009 return NULL;
|
|
2010 }
|
|
2011 for (i = 0; i < SOAP_BLKLEN; i++)
|
|
2012 { register unsigned long m = 0;
|
|
2013 register int j = 0;
|
|
2014 do
|
|
2015 { register soap_wchar c = soap_get(soap);
|
|
2016 if (c == '=' || c < 0)
|
|
2017 { unsigned char *p;
|
|
2018 i *= 3;
|
|
2019 switch (j)
|
|
2020 { case 2:
|
|
2021 *s++ = (char)((m >> 4) & 0xFF);
|
|
2022 i++;
|
|
2023 break;
|
|
2024 case 3:
|
|
2025 *s++ = (char)((m >> 10) & 0xFF);
|
|
2026 *s++ = (char)((m >> 2) & 0xFF);
|
|
2027 i += 2;
|
|
2028 }
|
|
2029 if (n)
|
|
2030 *n = (int)soap_size_block(soap, NULL, i);
|
|
2031 p = (unsigned char*)soap_save_block(soap, NULL, 0);
|
|
2032 if (c >= 0)
|
|
2033 { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT)
|
|
2034 ;
|
|
2035 }
|
|
2036 soap_unget(soap, c);
|
|
2037 return p;
|
|
2038 }
|
|
2039 c -= '+';
|
|
2040 if (c >= 0 && c <= 79)
|
|
2041 { int b = soap_base64i[c];
|
|
2042 if (b >= 64)
|
|
2043 { soap->error = SOAP_TYPE;
|
|
2044 return NULL;
|
|
2045 }
|
|
2046 m = (m << 6) + b;
|
|
2047 j++;
|
|
2048 }
|
|
2049 else if (!soap_blank(c))
|
|
2050 { soap->error = SOAP_TYPE;
|
|
2051 return NULL;
|
|
2052 }
|
|
2053 } while (j < 4);
|
|
2054 *s++ = (char)((m >> 16) & 0xFF);
|
|
2055 *s++ = (char)((m >> 8) & 0xFF);
|
|
2056 *s++ = (char)(m & 0xFF);
|
|
2057 }
|
|
2058 }
|
|
2059 #endif
|
|
2060 }
|
|
2061 #endif
|
|
2062
|
|
2063 /******************************************************************************/
|
|
2064 #ifndef WITH_LEANER
|
|
2065 #ifndef PALM_1
|
|
2066 SOAP_FMAC1
|
|
2067 int
|
|
2068 SOAP_FMAC2
|
|
2069 soap_xop_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options)
|
|
2070 { /* Check MTOM xop:Include element (within hex/base64Binary) */
|
|
2071 /* TODO: this code to be obsoleted with new import/xop.h conventions */
|
|
2072 short body = soap->body; /* should save type too? */
|
|
2073 if (!soap_peek_element(soap))
|
|
2074 { if (!soap_element_begin_in(soap, "xop:Include", 0, NULL))
|
|
2075 { if (soap_dime_forward(soap, ptr, size, id, type, options)
|
|
2076 || (soap->body && soap_element_end_in(soap, "xop:Include")))
|
|
2077 return soap->error;
|
|
2078 }
|
|
2079 }
|
|
2080 soap->body = body;
|
|
2081 return SOAP_OK;
|
|
2082 }
|
|
2083 #endif
|
|
2084 #endif
|
|
2085
|
|
2086 /******************************************************************************/
|
|
2087 #ifndef WITH_LEANER
|
|
2088 #ifndef PALM_1
|
|
2089 SOAP_FMAC1
|
|
2090 int
|
|
2091 SOAP_FMAC2
|
|
2092 soap_dime_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options)
|
|
2093 { struct soap_xlist *xp;
|
|
2094 *ptr = NULL;
|
|
2095 *size = 0;
|
|
2096 *id = NULL;
|
|
2097 *type = NULL;
|
|
2098 *options = NULL;
|
|
2099 if (!*soap->href)
|
|
2100 return SOAP_OK;
|
|
2101 *id = soap_strdup(soap, soap->href);
|
|
2102 xp = (struct soap_xlist*)SOAP_MALLOC(soap, sizeof(struct soap_xlist));
|
|
2103 if (!xp)
|
|
2104 return soap->error = SOAP_EOM;
|
|
2105 xp->next = soap->xlist;
|
|
2106 xp->ptr = ptr;
|
|
2107 xp->size = size;
|
|
2108 xp->id = *id;
|
|
2109 xp->type = type;
|
|
2110 xp->options = options;
|
|
2111 soap->xlist = xp;
|
|
2112 return SOAP_OK;
|
|
2113 }
|
|
2114 #endif
|
|
2115 #endif
|
|
2116
|
|
2117 /******************************************************************************/
|
|
2118 #ifndef PALM_1
|
|
2119 SOAP_FMAC1
|
|
2120 char *
|
|
2121 SOAP_FMAC2
|
|
2122 soap_strdup(struct soap *soap, const char *s)
|
|
2123 { char *t = NULL;
|
|
2124 if (s && (t = (char*)soap_malloc(soap, strlen(s) + 1)))
|
|
2125 strcpy(t, s);
|
|
2126 return t;
|
|
2127 }
|
|
2128 #endif
|
|
2129
|
|
2130 /******************************************************************************/
|
|
2131 #ifndef PALM_1
|
|
2132 SOAP_FMAC1
|
|
2133 wchar_t *
|
|
2134 SOAP_FMAC2
|
|
2135 soap_wstrdup(struct soap *soap, const wchar_t *s)
|
|
2136 { wchar_t *t = NULL;
|
|
2137 if (s)
|
|
2138 { size_t n = 0;
|
|
2139 while (s[n])
|
|
2140 n++;
|
|
2141 if ((t = (wchar_t*)soap_malloc(soap, sizeof(wchar_t)*(n+1))))
|
|
2142 memcpy(t, s, sizeof(wchar_t)*(n+1));
|
|
2143 }
|
|
2144 return t;
|
|
2145 }
|
|
2146 #endif
|
|
2147
|
|
2148 /******************************************************************************/
|
|
2149 #ifndef PALM_1
|
|
2150 SOAP_FMAC1
|
|
2151 struct soap_blist*
|
|
2152 SOAP_FMAC2
|
|
2153 soap_new_block(struct soap *soap)
|
|
2154 { struct soap_blist *p;
|
|
2155 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New block sequence (prev=%p)\n", soap->blist));
|
|
2156 if (!(p = (struct soap_blist*)SOAP_MALLOC(soap, sizeof(struct soap_blist))))
|
|
2157 { soap->error = SOAP_EOM;
|
|
2158 return NULL;
|
|
2159 }
|
|
2160 p->next = soap->blist;
|
|
2161 p->ptr = NULL;
|
|
2162 p->size = 0;
|
|
2163 soap->blist = p;
|
|
2164 return p;
|
|
2165 }
|
|
2166 #endif
|
|
2167
|
|
2168 /******************************************************************************/
|
|
2169 #ifndef PALM_1
|
|
2170 SOAP_FMAC1
|
|
2171 void*
|
|
2172 SOAP_FMAC2
|
|
2173 soap_push_block(struct soap *soap, struct soap_blist *b, size_t n)
|
|
2174 { char *p;
|
|
2175 if (!b)
|
|
2176 b = soap->blist;
|
|
2177 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push block of %u bytes (%u bytes total)\n", (unsigned int)n, (unsigned int)b->size + (unsigned int)n));
|
|
2178 if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(char*) + sizeof(size_t))))
|
|
2179 { soap->error = SOAP_EOM;
|
|
2180 return NULL;
|
|
2181 }
|
|
2182 *(char**)p = b->ptr;
|
|
2183 *(size_t*)(p + sizeof(char*)) = n;
|
|
2184 b->ptr = p;
|
|
2185 b->size += n;
|
|
2186 return p + sizeof(char*) + sizeof(size_t);
|
|
2187 }
|
|
2188 #endif
|
|
2189
|
|
2190 /******************************************************************************/
|
|
2191 #ifndef PALM_1
|
|
2192 SOAP_FMAC1
|
|
2193 void
|
|
2194 SOAP_FMAC2
|
|
2195 soap_pop_block(struct soap *soap, struct soap_blist *b)
|
|
2196 { char *p;
|
|
2197 if (!b)
|
|
2198 b = soap->blist;
|
|
2199 if (!b->ptr)
|
|
2200 return;
|
|
2201 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop block\n"));
|
|
2202 p = b->ptr;
|
|
2203 b->size -= *(size_t*)(p + sizeof(char*));
|
|
2204 b->ptr = *(char**)p;
|
|
2205 SOAP_FREE(soap, p);
|
|
2206 }
|
|
2207 #endif
|
|
2208
|
|
2209 /******************************************************************************/
|
|
2210 #ifndef PALM_1
|
|
2211 SOAP_FMAC1
|
|
2212 void
|
|
2213 SOAP_FMAC2
|
|
2214 soap_update_pointers(struct soap *soap, char *start, char *end, char *p1, char *p2)
|
|
2215 {
|
|
2216 #ifndef WITH_NOIDREF
|
|
2217 int i;
|
|
2218 register struct soap_ilist *ip = NULL;
|
|
2219 register struct soap_flist *fp = NULL;
|
|
2220 #ifndef WITH_LEANER
|
|
2221 register struct soap_xlist *xp = NULL;
|
|
2222 #endif
|
|
2223 register void *p, **q;
|
|
2224 for (i = 0; i < SOAP_IDHASH; i++)
|
|
2225 { for (ip = soap->iht[i]; ip; ip = ip->next)
|
|
2226 { if (ip->ptr && (char*)ip->ptr >= start && (char*)ip->ptr < end)
|
|
2227 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", ip->id, ip->ptr, (char*)ip->ptr + (p1-p2)));
|
|
2228 ip->ptr = (char*)ip->ptr + (p1-p2);
|
|
2229 }
|
|
2230 for (q = &ip->link; q; q = (void**)p)
|
|
2231 { p = *q;
|
|
2232 if (p && (char*)p >= start && (char*)p < end)
|
|
2233 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Link update id='%s' %p\n", ip->id, p));
|
|
2234 *q = (char*)p + (p1-p2);
|
|
2235 }
|
|
2236 }
|
|
2237 for (q = &ip->copy; q; q = (void**)p)
|
|
2238 { p = *q;
|
|
2239 if (p && (char*)p >= start && (char*)p < end)
|
|
2240 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy chain update id='%s' %p\n", ip->id, p));
|
|
2241 *q = (char*)p + (p1-p2);
|
|
2242 }
|
|
2243 }
|
|
2244 for (fp = ip->flist; fp; fp = fp->next)
|
|
2245 { if ((char*)fp->ptr >= start && (char*)fp->ptr < end)
|
|
2246 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy list update id='%s' %p\n", ip->id, fp));
|
|
2247 fp->ptr = (char*)fp->ptr + (p1-p2);
|
|
2248 }
|
|
2249 }
|
|
2250 }
|
|
2251 }
|
|
2252 #ifndef WITH_LEANER
|
|
2253 for (xp = soap->xlist; xp; xp = xp->next)
|
|
2254 { if (xp->ptr && (char*)xp->ptr >= start && (char*)xp->ptr < end)
|
|
2255 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", xp->id ? xp->id : SOAP_STR_EOS, xp->ptr, (char*)xp->ptr + (p1-p2)));
|
|
2256 xp->ptr = (unsigned char**)((char*)xp->ptr + (p1-p2));
|
|
2257 xp->size = (int*)((char*)xp->size + (p1-p2));
|
|
2258 xp->type = (char**)((char*)xp->type + (p1-p2));
|
|
2259 xp->options = (char**)((char*)xp->options + (p1-p2));
|
|
2260 }
|
|
2261 }
|
|
2262 #endif
|
|
2263 #else
|
|
2264 (void)soap; (void)start; (void)end; (void)p1; (void)p2;
|
|
2265 #endif
|
|
2266 }
|
|
2267 #endif
|
|
2268
|
|
2269 /******************************************************************************/
|
|
2270 #ifndef WITH_NOIDREF
|
|
2271 #ifndef PALM_1
|
|
2272 static int
|
|
2273 soap_has_copies(struct soap *soap, register const char *start, register const char *end)
|
|
2274 { register int i;
|
|
2275 register struct soap_ilist *ip = NULL;
|
|
2276 register struct soap_flist *fp = NULL;
|
|
2277 register const char *p;
|
|
2278 for (i = 0; i < SOAP_IDHASH; i++)
|
|
2279 { for (ip = soap->iht[i]; ip; ip = ip->next)
|
|
2280 { for (p = (const char*)ip->copy; p; p = *(const char**)p)
|
|
2281 if (p >= start && p < end)
|
|
2282 return SOAP_ERR;
|
|
2283 for (fp = ip->flist; fp; fp = fp->next)
|
|
2284 if ((const char*)fp->ptr >= start && (const char*)fp->ptr < end)
|
|
2285 return SOAP_ERR;
|
|
2286 }
|
|
2287 }
|
|
2288 return SOAP_OK;
|
|
2289 }
|
|
2290 #endif
|
|
2291 #endif
|
|
2292
|
|
2293 /******************************************************************************/
|
|
2294 #ifndef WITH_NOIDREF
|
|
2295 #ifndef PALM_1
|
|
2296 SOAP_FMAC1
|
|
2297 int
|
|
2298 SOAP_FMAC2
|
|
2299 soap_resolve(struct soap *soap)
|
|
2300 { register int i;
|
|
2301 register struct soap_ilist *ip = NULL;
|
|
2302 register struct soap_flist *fp = NULL;
|
|
2303 short flag;
|
|
2304 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data\n"));
|
|
2305 for (i = 0; i < SOAP_IDHASH; i++)
|
|
2306 { for (ip = soap->iht[i]; ip; ip = ip->next)
|
|
2307 { if (ip->ptr)
|
|
2308 { register void *p, **q, *r;
|
|
2309 q = (void**)ip->link;
|
|
2310 ip->link = NULL;
|
|
2311 r = ip->ptr;
|
|
2312 DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing link chain to resolve id='%s'\n", ip->id));
|
|
2313 while (q)
|
|
2314 { p = *q;
|
|
2315 *q = r;
|
|
2316 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "... link %p -> %p\n", q, r));
|
|
2317 q = (void**)p;
|
|
2318 }
|
|
2319 }
|
|
2320 else if (*ip->id == '#')
|
|
2321 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Missing data for id='%s'\n", ip->id));
|
|
2322 strcpy(soap->id, ip->id + 1);
|
|
2323 return soap->error = SOAP_MISSING_ID;
|
|
2324 }
|
|
2325 }
|
|
2326 }
|
|
2327 do
|
|
2328 { flag = 0;
|
|
2329 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution phase\n"));
|
|
2330 for (i = 0; i < SOAP_IDHASH; i++)
|
|
2331 { for (ip = soap->iht[i]; ip; ip = ip->next)
|
|
2332 { if (ip->ptr && !soap_has_copies(soap, (const char*)ip->ptr, (const char*)ip->ptr + ip->size))
|
|
2333 { if (ip->copy)
|
|
2334 { register void *p, **q = (void**)ip->copy;
|
|
2335 DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing copy chain to resolve id='%s'\n", ip->id));
|
|
2336 ip->copy = NULL;
|
|
2337 do
|
|
2338 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... copy %p -> %p (%u bytes)\n", ip->ptr, q, (unsigned int)ip->size));
|
|
2339 p = *q;
|
|
2340 memcpy(q, ip->ptr, ip->size);
|
|
2341 q = (void**)p;
|
|
2342 } while (q);
|
|
2343 flag = 1;
|
|
2344 }
|
|
2345 for (fp = ip->flist; fp; fp = ip->flist)
|
|
2346 { register unsigned int k = fp->level;
|
|
2347 register void *p = ip->ptr;
|
|
2348 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data type=%d location=%p level=%u,%u id='%s'\n", ip->type, p, ip->level, fp->level, ip->id));
|
|
2349 while (ip->level < k)
|
|
2350 { register void **q = (void**)soap_malloc(soap, sizeof(void*));
|
|
2351 if (!q)
|
|
2352 return soap->error;
|
|
2353 *q = p;
|
|
2354 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level, new location=%p holds=%p...\n", q, *q));
|
|
2355 p = (void*)q;
|
|
2356 k--;
|
|
2357 }
|
|
2358 if (fp->fcopy)
|
|
2359 fp->fcopy(soap, ip->type, fp->type, fp->ptr, fp->len, p, ip->size);
|
|
2360 else
|
|
2361 soap_fcopy(soap, ip->type, fp->type, fp->ptr, fp->len, p, ip->size);
|
|
2362 ip->flist = fp->next;
|
|
2363 SOAP_FREE(soap, fp);
|
|
2364 flag = 1;
|
|
2365 }
|
|
2366 }
|
|
2367 }
|
|
2368 }
|
|
2369 } while (flag);
|
|
2370 #ifdef SOAP_DEBUG
|
|
2371 for (i = 0; i < SOAP_IDHASH; i++)
|
|
2372 { for (ip = soap->iht[i]; ip; ip = ip->next)
|
|
2373 { if (ip->copy || ip->flist)
|
|
2374 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution error: forwarded data for id='%s' could not be propagated, please report this problem to the developers\n", ip->id));
|
|
2375 }
|
|
2376 }
|
|
2377 }
|
|
2378 #endif
|
|
2379 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution done\n"));
|
|
2380 return SOAP_OK;
|
|
2381 }
|
|
2382 #endif
|
|
2383 #endif
|
|
2384
|
|
2385 /******************************************************************************/
|
|
2386 #ifndef PALM_1
|
|
2387 SOAP_FMAC1
|
|
2388 size_t
|
|
2389 SOAP_FMAC2
|
|
2390 soap_size_block(struct soap *soap, struct soap_blist *b, size_t n)
|
|
2391 { if (!b)
|
|
2392 b = soap->blist;
|
|
2393 if (b->ptr)
|
|
2394 { b->size -= *(size_t*)(b->ptr + sizeof(char*)) - n;
|
|
2395 *(size_t*)(b->ptr + sizeof(char*)) = n;
|
|
2396 }
|
|
2397 return b->size;
|
|
2398 }
|
|
2399 #endif
|
|
2400
|
|
2401 /******************************************************************************/
|
|
2402 #ifndef PALM_1
|
|
2403 SOAP_FMAC1
|
|
2404 char*
|
|
2405 SOAP_FMAC2
|
|
2406 soap_first_block(struct soap *soap, struct soap_blist *b)
|
|
2407 { char *p, *q, *r;
|
|
2408 if (!b)
|
|
2409 b = soap->blist;
|
|
2410 p = b->ptr;
|
|
2411 if (!p)
|
|
2412 return NULL;
|
|
2413 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "First block\n"));
|
|
2414 r = NULL;
|
|
2415 do
|
|
2416 { q = *(char**)p;
|
|
2417 *(char**)p = r;
|
|
2418 r = p;
|
|
2419 p = q;
|
|
2420 } while (p);
|
|
2421 b->ptr = r;
|
|
2422 return r + sizeof(char*) + sizeof(size_t);
|
|
2423 }
|
|
2424 #endif
|
|
2425
|
|
2426 /******************************************************************************/
|
|
2427 #ifndef PALM_1
|
|
2428 SOAP_FMAC1
|
|
2429 char*
|
|
2430 SOAP_FMAC2
|
|
2431 soap_next_block(struct soap *soap, struct soap_blist *b)
|
|
2432 { char *p;
|
|
2433 if (!b)
|
|
2434 b = soap->blist;
|
|
2435 p = b->ptr;
|
|
2436 if (p)
|
|
2437 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Next block\n"));
|
|
2438 b->ptr = *(char**)p;
|
|
2439 SOAP_FREE(soap, p);
|
|
2440 if (b->ptr)
|
|
2441 return b->ptr + sizeof(char*) + sizeof(size_t);
|
|
2442 }
|
|
2443 return NULL;
|
|
2444 }
|
|
2445 #endif
|
|
2446
|
|
2447 /******************************************************************************/
|
|
2448 #ifndef PALM_1
|
|
2449 SOAP_FMAC1
|
|
2450 size_t
|
|
2451 SOAP_FMAC2
|
|
2452 soap_block_size(struct soap *soap, struct soap_blist *b)
|
|
2453 { if (!b)
|
|
2454 b = soap->blist;
|
|
2455 return *(size_t*)(b->ptr + sizeof(char*));
|
|
2456 }
|
|
2457 #endif
|
|
2458
|
|
2459 /******************************************************************************/
|
|
2460 #ifndef PALM_1
|
|
2461 SOAP_FMAC1
|
|
2462 void
|
|
2463 SOAP_FMAC2
|
|
2464 soap_end_block(struct soap *soap, struct soap_blist *b)
|
|
2465 { char *p, *q;
|
|
2466 if (!b)
|
|
2467 b = soap->blist;
|
|
2468 if (b)
|
|
2469 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of block sequence, free all remaining blocks\n"));
|
|
2470 for (p = b->ptr; p; p = q)
|
|
2471 { q = *(char**)p;
|
|
2472 SOAP_FREE(soap, p);
|
|
2473 }
|
|
2474 if (soap->blist == b)
|
|
2475 soap->blist = b->next;
|
|
2476 else
|
|
2477 { struct soap_blist *bp;
|
|
2478 for (bp = soap->blist; bp; bp = bp->next)
|
|
2479 { if (bp->next == b)
|
|
2480 { bp->next = b->next;
|
|
2481 break;
|
|
2482 }
|
|
2483 }
|
|
2484 }
|
|
2485 SOAP_FREE(soap, b);
|
|
2486 }
|
|
2487 DBGLOG(TEST, if (soap->blist) SOAP_MESSAGE(fdebug, "Restore previous block sequence\n"));
|
|
2488 }
|
|
2489 #endif
|
|
2490
|
|
2491 /******************************************************************************/
|
|
2492 #ifndef PALM_1
|
|
2493 SOAP_FMAC1
|
|
2494 char*
|
|
2495 SOAP_FMAC2
|
|
2496 soap_save_block(struct soap *soap, struct soap_blist *b, char *p, int flag)
|
|
2497 { register size_t n;
|
|
2498 register char *q, *s;
|
|
2499 if (!b)
|
|
2500 b = soap->blist;
|
|
2501 if (b->size)
|
|
2502 { if (!p)
|
|
2503 p = (char*)soap_malloc(soap, b->size);
|
|
2504 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Save all blocks in contiguous memory space of %u bytes (%p->%p)\n", (unsigned int)b->size, b->ptr, p));
|
|
2505 if (p)
|
|
2506 { for (s = p, q = soap_first_block(soap, b); q; q = soap_next_block(soap, b))
|
|
2507 { n = soap_block_size(soap, b);
|
|
2508 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy %u bytes from %p to %p\n", (unsigned int)n, q, s));
|
|
2509 #ifndef WITH_NOIDREF
|
|
2510 if (flag)
|
|
2511 soap_update_pointers(soap, q, q + n, s, q);
|
|
2512 #endif
|
|
2513 memcpy(s, q, n);
|
|
2514 s += n;
|
|
2515 }
|
|
2516 }
|
|
2517 else
|
|
2518 soap->error = SOAP_EOM;
|
|
2519 }
|
|
2520 soap_end_block(soap, b);
|
|
2521 return p;
|
|
2522 }
|
|
2523 #endif
|
|
2524
|
|
2525 /******************************************************************************/
|
|
2526 #ifndef PALM_2
|
|
2527 SOAP_FMAC1
|
|
2528 char *
|
|
2529 SOAP_FMAC2
|
|
2530 soap_putsize(struct soap *soap, const char *type, int size)
|
|
2531 { return soap_putsizes(soap, type, &size, 1);
|
|
2532 }
|
|
2533 #endif
|
|
2534
|
|
2535 /******************************************************************************/
|
|
2536 #ifndef PALM_2
|
|
2537 SOAP_FMAC1
|
|
2538 char *
|
|
2539 SOAP_FMAC2
|
|
2540 soap_putsizes(struct soap *soap, const char *type, const int *size, int dim)
|
|
2541 { return soap_putsizesoffsets(soap, type, size, NULL, dim);
|
|
2542 }
|
|
2543 #endif
|
|
2544
|
|
2545 /******************************************************************************/
|
|
2546 #ifndef PALM_2
|
|
2547 SOAP_FMAC1
|
|
2548 char *
|
|
2549 SOAP_FMAC2
|
|
2550 soap_putsizesoffsets(struct soap *soap, const char *type, const int *size, const int *offset, int dim)
|
|
2551 { register int i;
|
|
2552 register size_t l;
|
|
2553 if (!type || strlen(type) + 13 > sizeof(soap->type)) /* prevent overruns */
|
|
2554 return NULL;
|
|
2555 if (soap->version == 2)
|
|
2556 {
|
|
2557 #ifdef HAVE_SNPRINTF
|
|
2558 soap_snprintf(soap->type, sizeof(soap->type) - 1, "%s[%d", type, size[0]);
|
|
2559 #else
|
|
2560 sprintf(soap->type, "%s[%d", type, size[0]);
|
|
2561 #endif
|
|
2562 for (i = 1; i < dim; i++)
|
|
2563 {
|
|
2564 #ifdef HAVE_SNPRINTF
|
|
2565 l = strlen(soap->type);
|
|
2566 soap_snprintf(soap->type + l, sizeof(soap->type) - l - 1, " %d", size[i]);
|
|
2567 #else
|
|
2568 if ((l = strlen(soap->type)) + 13 > sizeof(soap->type))
|
|
2569 return NULL;
|
|
2570 sprintf(soap->type + l, " %d", size[i]);
|
|
2571 #endif
|
|
2572 }
|
|
2573 }
|
|
2574 else
|
|
2575 { if (offset)
|
|
2576 {
|
|
2577 #ifdef HAVE_SNPRINTF
|
|
2578 soap_snprintf(soap->type, sizeof(soap->type) - 1, "%s[%d", type, size[0] + offset[0]);
|
|
2579 #else
|
|
2580 sprintf(soap->type, "%s[%d", type, size[0] + offset[0]);
|
|
2581 #endif
|
|
2582 for (i = 1; i < dim; i++)
|
|
2583 {
|
|
2584 #ifdef HAVE_SNPRINTF
|
|
2585 l = strlen(soap->type);
|
|
2586 soap_snprintf(soap->type + l, sizeof(soap->type) - l - 1, ",%d", size[i] + offset[i]);
|
|
2587 #else
|
|
2588 if ((l = strlen(soap->type)) + 13 > sizeof(soap->type))
|
|
2589 return NULL;
|
|
2590 sprintf(soap->type + l, ",%d", size[i] + offset[i]);
|
|
2591 #endif
|
|
2592 }
|
|
2593 }
|
|
2594 else
|
|
2595 {
|
|
2596 #ifdef HAVE_SNPRINTF
|
|
2597 soap_snprintf(soap->type, sizeof(soap->type) - 1, "%s[%d", type, size[0]);
|
|
2598 #else
|
|
2599 sprintf(soap->type, "%s[%d", type, size[0]);
|
|
2600 #endif
|
|
2601 for (i = 1; i < dim; i++)
|
|
2602 {
|
|
2603 #ifdef HAVE_SNPRINTF
|
|
2604 l = strlen(soap->type);
|
|
2605 soap_snprintf(soap->type + l, sizeof(soap->type) - l - 1, ",%d", size[i]);
|
|
2606 #else
|
|
2607 if ((l = strlen(soap->type)) + 13 > sizeof(soap->type))
|
|
2608 return NULL;
|
|
2609 sprintf(soap->type + l, ",%d", size[i]);
|
|
2610 #endif
|
|
2611 }
|
|
2612 }
|
|
2613 }
|
|
2614 strcat(soap->type, "]");
|
|
2615 return soap->type;
|
|
2616 }
|
|
2617 #endif
|
|
2618
|
|
2619 /******************************************************************************/
|
|
2620 #ifndef PALM_2
|
|
2621 SOAP_FMAC1
|
|
2622 char *
|
|
2623 SOAP_FMAC2
|
|
2624 soap_putoffset(struct soap *soap, int offset)
|
|
2625 { return soap_putoffsets(soap, &offset, 1);
|
|
2626 }
|
|
2627 #endif
|
|
2628
|
|
2629 /******************************************************************************/
|
|
2630 #ifndef PALM_2
|
|
2631 SOAP_FMAC1
|
|
2632 char *
|
|
2633 SOAP_FMAC2
|
|
2634 soap_putoffsets(struct soap *soap, const int *offset, int dim)
|
|
2635 { register int i;
|
|
2636 register size_t l;
|
|
2637 #ifdef HAVE_SNPRINTF
|
|
2638 soap_snprintf(soap->arrayOffset, sizeof(soap->arrayOffset) - 1, "[%d", offset[0]);
|
|
2639 #else
|
|
2640 if (sizeof(soap->arrayOffset) < 13) /* prevent overruns */
|
|
2641 return NULL;
|
|
2642 sprintf(soap->arrayOffset, "[%d", offset[0]);
|
|
2643 #endif
|
|
2644 for (i = 1; i < dim; i++)
|
|
2645 {
|
|
2646 #ifdef HAVE_SNPRINTF
|
|
2647 l = strlen(soap->arrayOffset);
|
|
2648 soap_snprintf(soap->arrayOffset + l, sizeof(soap->arrayOffset) - l - 1, ",%d", offset[i]);
|
|
2649 #else
|
|
2650 if ((l = strlen(soap->arrayOffset)) + 13 > sizeof(soap->arrayOffset))
|
|
2651 return NULL;
|
|
2652 sprintf(soap->arrayOffset + l, ",%d", offset[i]);
|
|
2653 #endif
|
|
2654 }
|
|
2655 strcat(soap->arrayOffset, "]");
|
|
2656 return soap->arrayOffset;
|
|
2657 }
|
|
2658 #endif
|
|
2659
|
|
2660 /******************************************************************************/
|
|
2661 #ifndef PALM_2
|
|
2662 SOAP_FMAC1
|
|
2663 int
|
|
2664 SOAP_FMAC2
|
|
2665 soap_size(const int *size, int dim)
|
|
2666 { register int i, n = size[0];
|
|
2667 for (i = 1; i < dim; i++)
|
|
2668 n *= size[i];
|
|
2669 return n;
|
|
2670 }
|
|
2671 #endif
|
|
2672
|
|
2673 /******************************************************************************/
|
|
2674 #ifndef PALM_2
|
|
2675 SOAP_FMAC1
|
|
2676 int
|
|
2677 SOAP_FMAC2
|
|
2678 soap_getoffsets(const char *attr, const int *size, int *offset, int dim)
|
|
2679 { register int i, j = 0;
|
|
2680 if (offset)
|
|
2681 for (i = 0; i < dim && attr && *attr; i++)
|
|
2682 { attr++;
|
|
2683 j *= size[i];
|
|
2684 j += offset[i] = (int)soap_strtol(attr, NULL, 10);
|
|
2685 attr = strchr(attr, ',');
|
|
2686 }
|
|
2687 else
|
|
2688 for (i = 0; i < dim && attr && *attr; i++)
|
|
2689 { attr++;
|
|
2690 j *= size[i];
|
|
2691 j += (int)soap_strtol(attr, NULL, 10);
|
|
2692 attr = strchr(attr, ',');
|
|
2693 }
|
|
2694 return j;
|
|
2695 }
|
|
2696 #endif
|
|
2697
|
|
2698 /******************************************************************************/
|
|
2699 #ifndef PALM_2
|
|
2700 SOAP_FMAC1
|
|
2701 int
|
|
2702 SOAP_FMAC2
|
|
2703 soap_getsize(const char *attr1, const char *attr2, int *j)
|
|
2704 { register int n, k;
|
|
2705 char *s;
|
|
2706 *j = 0;
|
|
2707 if (!*attr1)
|
|
2708 return -1;
|
|
2709 if (*attr1 == '[')
|
|
2710 attr1++;
|
|
2711 n = 1;
|
|
2712 for (;;)
|
|
2713 { k = (int)soap_strtol(attr1, &s, 10);
|
|
2714 n *= k;
|
|
2715 if (k < 0 || n > SOAP_MAXARRAYSIZE || s == attr1)
|
|
2716 return -1;
|
|
2717 attr1 = strchr(s, ',');
|
|
2718 if (!attr1)
|
|
2719 attr1 = strchr(s, ' ');
|
|
2720 if (attr2 && *attr2)
|
|
2721 { attr2++;
|
|
2722 *j *= k;
|
|
2723 k = (int)soap_strtol(attr2, &s, 10);
|
|
2724 *j += k;
|
|
2725 if (k < 0)
|
|
2726 return -1;
|
|
2727 attr2 = s;
|
|
2728 }
|
|
2729 if (!attr1)
|
|
2730 break;
|
|
2731 attr1++;
|
|
2732 }
|
|
2733 return n - *j;
|
|
2734 }
|
|
2735 #endif
|
|
2736
|
|
2737 /******************************************************************************/
|
|
2738 #ifndef PALM_2
|
|
2739 SOAP_FMAC1
|
|
2740 int
|
|
2741 SOAP_FMAC2
|
|
2742 soap_getsizes(const char *attr, int *size, int dim)
|
|
2743 { register int i, k, n;
|
|
2744 if (!*attr)
|
|
2745 return -1;
|
|
2746 i = (int)strlen(attr);
|
|
2747 n = 1;
|
|
2748 do
|
|
2749 { for (i = i-1; i >= 0; i--)
|
|
2750 if (attr[i] == '[' || attr[i] == ',' || attr[i] == ' ')
|
|
2751 break;
|
|
2752 k = (int)soap_strtol(attr + i + 1, NULL, 10);
|
|
2753 n *= size[--dim] = k;
|
|
2754 if (k < 0 || n > SOAP_MAXARRAYSIZE)
|
|
2755 return -1;
|
|
2756 } while (i >= 0 && attr[i] != '[');
|
|
2757 return n;
|
|
2758 }
|
|
2759 #endif
|
|
2760
|
|
2761 /******************************************************************************/
|
|
2762 #ifndef PALM_2
|
|
2763 SOAP_FMAC1
|
|
2764 int
|
|
2765 SOAP_FMAC2
|
|
2766 soap_getposition(const char *attr, int *pos)
|
|
2767 { register int i, n;
|
|
2768 if (!*attr)
|
|
2769 return -1;
|
|
2770 n = 0;
|
|
2771 i = 1;
|
|
2772 do
|
|
2773 { pos[n++] = (int)soap_strtol(attr + i, NULL, 10);
|
|
2774 while (attr[i] && attr[i] != ',' && attr[i] != ']')
|
|
2775 i++;
|
|
2776 if (attr[i] == ',')
|
|
2777 i++;
|
|
2778 } while (n < SOAP_MAXDIMS && attr[i] && attr[i] != ']');
|
|
2779 return n;
|
|
2780 }
|
|
2781 #endif
|
|
2782
|
|
2783 /******************************************************************************/
|
|
2784 #ifndef PALM_2
|
|
2785 SOAP_FMAC1
|
|
2786 struct soap_nlist *
|
|
2787 SOAP_FMAC2
|
|
2788 soap_push_namespace(struct soap *soap, const char *id, const char *ns)
|
|
2789 { register struct soap_nlist *np;
|
|
2790 register struct Namespace *p;
|
|
2791 register short i = -1;
|
|
2792 register size_t n, k;
|
|
2793 n = strlen(id);
|
|
2794 k = strlen(ns) + 1;
|
|
2795 p = soap->local_namespaces;
|
|
2796 if (p)
|
|
2797 { for (i = 0; p->id; p++, i++)
|
|
2798 { if (p->ns && !strcmp(ns, p->ns))
|
|
2799 break;
|
|
2800 if (p->out)
|
|
2801 { if (!strcmp(ns, p->out))
|
|
2802 break;
|
|
2803 }
|
|
2804 else if (p->in)
|
|
2805 { if (!soap_tag_cmp(ns, p->in))
|
|
2806 { if ((p->out = (char*)SOAP_MALLOC(soap, k)))
|
|
2807 strcpy(p->out, ns);
|
|
2808 break;
|
|
2809 }
|
|
2810 }
|
|
2811 }
|
|
2812 if (!p || !p->id)
|
|
2813 i = -1;
|
|
2814 }
|
|
2815 if (i >= 0)
|
|
2816 k = 0;
|
|
2817 np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k);
|
|
2818 if (!np)
|
|
2819 { soap->error = SOAP_EOM;
|
|
2820 return NULL;
|
|
2821 }
|
|
2822 np->next = soap->nlist;
|
|
2823 soap->nlist = np;
|
|
2824 np->level = soap->level;
|
|
2825 np->index = i;
|
|
2826 strcpy((char*)np->id, id);
|
|
2827 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push namespace binding (level=%u) '%s' '%s'\n", soap->level, id, ns));
|
|
2828 if (i < 0)
|
|
2829 { np->ns = strcpy((char*)np->id + n + 1, ns);
|
|
2830 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push NOT OK: no match found for '%s' in namespace mapping table (added to stack anyway)\n", ns));
|
|
2831 }
|
|
2832 else
|
|
2833 { np->ns = NULL;
|
|
2834 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push OK ('%s' matches '%s' in namespace table)\n", id, p->id));
|
|
2835 }
|
|
2836 return np;
|
|
2837 }
|
|
2838 #endif
|
|
2839
|
|
2840 /******************************************************************************/
|
|
2841 #ifndef PALM_2
|
|
2842 SOAP_FMAC1
|
|
2843 void
|
|
2844 SOAP_FMAC2
|
|
2845 soap_pop_namespace(struct soap *soap)
|
|
2846 { register struct soap_nlist *np, *nq;
|
|
2847 for (np = soap->nlist; np && np->level >= soap->level; np = nq)
|
|
2848 { nq = np->next;
|
|
2849 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop namespace binding (level=%u) '%s'\n", soap->level, np->id));
|
|
2850 SOAP_FREE(soap, np);
|
|
2851 }
|
|
2852 soap->nlist = np;
|
|
2853 }
|
|
2854 #endif
|
|
2855
|
|
2856 /******************************************************************************/
|
|
2857 #ifndef PALM_2
|
|
2858 SOAP_FMAC1
|
|
2859 int
|
|
2860 SOAP_FMAC2
|
|
2861 soap_match_namespace(struct soap *soap, const char *id1, const char *id2, size_t n1, size_t n2)
|
|
2862 { register struct soap_nlist *np = soap->nlist;
|
|
2863 const char *s;
|
|
2864 while (np && (strncmp(np->id, id1, n1) || np->id[n1]))
|
|
2865 np = np->next;
|
|
2866 if (np)
|
|
2867 { if (!(soap->mode & SOAP_XML_IGNORENS))
|
|
2868 if (np->index < 0
|
|
2869 || ((s = soap->local_namespaces[np->index].id) && (strncmp(s, id2, n2) || (s[n2] && s[n2] != '_'))))
|
|
2870 return SOAP_NAMESPACE;
|
|
2871 return SOAP_OK;
|
|
2872 }
|
|
2873 if (n1 == 0)
|
|
2874 return (soap->mode & SOAP_XML_IGNORENS) ? SOAP_OK : SOAP_NAMESPACE;
|
|
2875 if ((n1 == 3 && n1 == n2 && !strncmp(id1, "xml", 3) && !strncmp(id1, id2, 3))
|
|
2876 || (soap->mode & SOAP_XML_IGNORENS))
|
|
2877 return SOAP_OK;
|
|
2878 return soap->error = SOAP_SYNTAX_ERROR;
|
|
2879 }
|
|
2880 #endif
|
|
2881
|
|
2882 /******************************************************************************/
|
|
2883 #ifndef PALM_2
|
|
2884 SOAP_FMAC1
|
|
2885 const char*
|
|
2886 SOAP_FMAC2
|
|
2887 soap_current_namespace(struct soap *soap, const char *tag)
|
|
2888 { register struct soap_nlist *np;
|
|
2889 register const char *s;
|
|
2890 if (!tag || !strncmp(tag, "xml", 3))
|
|
2891 return NULL;
|
|
2892 np = soap->nlist;
|
|
2893 if (!(s = strchr(tag, ':')))
|
|
2894 { while (np && *np->id) /* find default namespace, if present */
|
|
2895 np = np->next;
|
|
2896 }
|
|
2897 else
|
|
2898 { while (np && (strncmp(np->id, tag, s - tag) || np->id[s - tag]))
|
|
2899 np = np->next;
|
|
2900 if (!np)
|
|
2901 soap->error = SOAP_NAMESPACE;
|
|
2902 }
|
|
2903 if (np)
|
|
2904 { if (np->index >= 0)
|
|
2905 return soap->namespaces[np->index].ns;
|
|
2906 if (np->ns)
|
|
2907 return soap_strdup(soap, np->ns);
|
|
2908 }
|
|
2909 return NULL;
|
|
2910 }
|
|
2911 #endif
|
|
2912
|
|
2913 /******************************************************************************/
|
|
2914 #ifndef PALM_2
|
|
2915 SOAP_FMAC1
|
|
2916 int
|
|
2917 SOAP_FMAC2
|
|
2918 soap_tag_cmp(const char *s, const char *t)
|
|
2919 { for (;;)
|
|
2920 { register int c1 = *s;
|
|
2921 register int c2 = *t;
|
|
2922 if (!c1 || c1 == '"')
|
|
2923 break;
|
|
2924 if (c2 != '-')
|
|
2925 { if (c1 != c2)
|
|
2926 { if (c1 >= 'A' && c1 <= 'Z')
|
|
2927 c1 += 'a' - 'A';
|
|
2928 if (c2 >= 'A' && c2 <= 'Z')
|
|
2929 c2 += 'a' - 'A';
|
|
2930 }
|
|
2931 if (c1 != c2)
|
|
2932 { if (c2 != '*')
|
|
2933 return 1;
|
|
2934 c2 = *++t;
|
|
2935 if (!c2)
|
|
2936 return 0;
|
|
2937 if (c2 >= 'A' && c2 <= 'Z')
|
|
2938 c2 += 'a' - 'A';
|
|
2939 for (;;)
|
|
2940 { c1 = *s;
|
|
2941 if (!c1 || c1 == '"')
|
|
2942 break;
|
|
2943 if (c1 >= 'A' && c1 <= 'Z')
|
|
2944 c1 += 'a' - 'A';
|
|
2945 if (c1 == c2 && !soap_tag_cmp(s + 1, t + 1))
|
|
2946 return 0;
|
|
2947 s++;
|
|
2948 }
|
|
2949 break;
|
|
2950 }
|
|
2951 }
|
|
2952 s++;
|
|
2953 t++;
|
|
2954 }
|
|
2955 if (*t == '*' && !t[1])
|
|
2956 return 0;
|
|
2957 return *t;
|
|
2958 }
|
|
2959 #endif
|
|
2960
|
|
2961 /******************************************************************************/
|
|
2962 #ifndef PALM_2
|
|
2963 SOAP_FMAC1
|
|
2964 int
|
|
2965 SOAP_FMAC2
|
|
2966 soap_match_tag(struct soap *soap, const char *tag1, const char *tag2)
|
|
2967 { register const char *s, *t;
|
|
2968 register int err;
|
|
2969 if (!tag1 || !tag2 || !*tag2)
|
|
2970 return SOAP_OK;
|
|
2971 s = strchr(tag1, ':');
|
|
2972 t = strchr(tag2, ':');
|
|
2973 if (t)
|
|
2974 { if (s)
|
|
2975 { if (t[1] && SOAP_STRCMP(s + 1, t + 1))
|
|
2976 return SOAP_TAG_MISMATCH;
|
|
2977 if (t != tag2 && (err = soap_match_namespace(soap, tag1, tag2, s - tag1, t - tag2)))
|
|
2978 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2));
|
|
2979 if (err == SOAP_NAMESPACE)
|
|
2980 return SOAP_TAG_MISMATCH;
|
|
2981 return err;
|
|
2982 }
|
|
2983 }
|
|
2984 else if (!t[1])
|
|
2985 { err = soap_match_namespace(soap, tag1, tag2, 0, t - tag2);
|
|
2986 if (err == SOAP_NAMESPACE)
|
|
2987 return SOAP_TAG_MISMATCH;
|
|
2988 }
|
|
2989 else if (SOAP_STRCMP(tag1, t + 1))
|
|
2990 { return SOAP_TAG_MISMATCH;
|
|
2991 }
|
|
2992 else if (t != tag2 && (err = soap_match_namespace(soap, tag1, tag2, 0, t - tag2)))
|
|
2993 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2));
|
|
2994 if (err == SOAP_NAMESPACE)
|
|
2995 return SOAP_TAG_MISMATCH;
|
|
2996 return err;
|
|
2997 }
|
|
2998 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags and (default) namespaces match: '%s' '%s'\n", tag1, tag2));
|
|
2999 return SOAP_OK;
|
|
3000 }
|
|
3001 if (s)
|
|
3002 { if (SOAP_STRCMP(s + 1, tag2))
|
|
3003 return SOAP_TAG_MISMATCH;
|
|
3004 }
|
|
3005 else if (SOAP_STRCMP(tag1, tag2))
|
|
3006 return SOAP_TAG_MISMATCH;
|
|
3007 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags match: '%s' '%s'\n", tag1, tag2));
|
|
3008 return SOAP_OK;
|
|
3009 }
|
|
3010 #endif
|
|
3011
|
|
3012 /******************************************************************************/
|
|
3013 #ifndef PALM_2
|
|
3014 SOAP_FMAC1
|
|
3015 int
|
|
3016 SOAP_FMAC2
|
|
3017 soap_match_array(struct soap *soap, const char *type)
|
|
3018 { if (*soap->arrayType)
|
|
3019 if (soap_match_tag(soap, soap->arrayType, type)
|
|
3020 && soap_match_tag(soap, soap->arrayType, "xsd:anyType")
|
|
3021 && soap_match_tag(soap, soap->arrayType, "xsd:ur-type")
|
|
3022 )
|
|
3023 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array type mismatch: '%s' '%s'\n", soap->arrayType, type));
|
|
3024 return SOAP_TAG_MISMATCH;
|
|
3025 }
|
|
3026 return SOAP_OK;
|
|
3027 }
|
|
3028 #endif
|
|
3029
|
|
3030 /******************************************************************************\
|
|
3031 *
|
|
3032 * SSL/TLS
|
|
3033 *
|
|
3034 \******************************************************************************/
|
|
3035
|
|
3036 /******************************************************************************/
|
|
3037 #ifdef WITH_OPENSSL
|
|
3038 #ifndef PALM_2
|
|
3039 SOAP_FMAC1
|
|
3040 int
|
|
3041 SOAP_FMAC2
|
|
3042 soap_rand()
|
|
3043 { unsigned char buf[4];
|
|
3044 if (!soap_ssl_init_done)
|
|
3045 soap_ssl_init();
|
|
3046 RAND_pseudo_bytes(buf, 4);
|
|
3047 return *(int*)buf;
|
|
3048 }
|
|
3049 #endif
|
|
3050 #endif
|
|
3051
|
|
3052 /******************************************************************************/
|
|
3053 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
|
|
3054 #ifndef PALM_2
|
|
3055 SOAP_FMAC1
|
|
3056 int
|
|
3057 SOAP_FMAC2
|
|
3058 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
|
|
3059 soap_ssl_server_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *keyid, const char *password, const char *cafile, const char *capath, const char *dhfile, const char *randfile, const char *sid)
|
|
3060 #else
|
|
3061 soap_ssl_server_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *password, const char *cafile, const char *capath, const char *dhfile, const char *randfile, const char *sid)
|
|
3062 #endif
|
|
3063 { int err;
|
|
3064 soap->keyfile = keyfile;
|
|
3065 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
|
|
3066 soap->keyid = keyid;
|
|
3067 #endif
|
|
3068 soap->password = password;
|
|
3069 soap->cafile = cafile;
|
|
3070 soap->capath = capath;
|
|
3071 soap->crlfile = NULL;
|
|
3072 #ifdef WITH_OPENSSL
|
|
3073 soap->dhfile = dhfile;
|
|
3074 soap->randfile = randfile;
|
|
3075 #endif
|
|
3076 soap->ssl_flags = flags | (dhfile == NULL ? SOAP_SSL_RSA : 0);
|
|
3077 #ifdef WITH_GNUTLS
|
|
3078 if (dhfile)
|
|
3079 { char *s;
|
|
3080 int n = (int)soap_strtoul(dhfile, &s, 10);
|
|
3081 if (!soap->dh_params)
|
|
3082 gnutls_dh_params_init(&soap->dh_params);
|
|
3083 /* if dhfile is numeric, treat it as a key length to generate DH params which can take a while */
|
|
3084 if (n >= 512 && s && *s == '\0')
|
|
3085 gnutls_dh_params_generate2(soap->dh_params, (unsigned int)n);
|
|
3086 else
|
|
3087 { unsigned int dparams_len;
|
|
3088 unsigned char dparams_buf[1024];
|
|
3089 FILE *fd = fopen(dhfile, "r");
|
|
3090 if (!fd)
|
|
3091 return soap_set_receiver_error(soap, "SSL/TLS error", "Invalid DH file", SOAP_SSL_ERROR);
|
|
3092 dparams_len = (unsigned int)fread(dparams_buf, 1, sizeof(dparams_buf), fd);
|
|
3093 fclose(fd);
|
|
3094 gnutls_datum_t dparams = { dparams_buf, dparams_len };
|
|
3095 if (gnutls_dh_params_import_pkcs3(soap->dh_params, &dparams, GNUTLS_X509_FMT_PEM))
|
|
3096 return soap_set_receiver_error(soap, "SSL/TLS error", "Invalid DH file", SOAP_SSL_ERROR);
|
|
3097 }
|
|
3098 }
|
|
3099 else
|
|
3100 { if (!soap->rsa_params)
|
|
3101 gnutls_rsa_params_init(&soap->rsa_params);
|
|
3102 gnutls_rsa_params_generate2(soap->rsa_params, SOAP_SSL_RSA_BITS);
|
|
3103 }
|
|
3104 if (soap->session)
|
|
3105 { gnutls_deinit(soap->session);
|
|
3106 soap->session = NULL;
|
|
3107 }
|
|
3108 if (soap->xcred)
|
|
3109 { gnutls_certificate_free_credentials(soap->xcred);
|
|
3110 soap->xcred = NULL;
|
|
3111 }
|
|
3112 #endif
|
|
3113 err = soap->fsslauth(soap);
|
|
3114 #ifdef WITH_OPENSSL
|
|
3115 if (!err)
|
|
3116 { if (sid)
|
|
3117 SSL_CTX_set_session_id_context(soap->ctx, (unsigned char*)sid, (unsigned int)strlen(sid));
|
|
3118 else
|
|
3119 SSL_CTX_set_session_cache_mode(soap->ctx, SSL_SESS_CACHE_OFF);
|
|
3120 }
|
|
3121 #endif
|
|
3122 return err;
|
|
3123 }
|
|
3124 #endif
|
|
3125 #endif
|
|
3126
|
|
3127 /******************************************************************************/
|
|
3128 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
|
|
3129 #ifndef PALM_2
|
|
3130 SOAP_FMAC1
|
|
3131 int
|
|
3132 SOAP_FMAC2
|
|
3133 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
|
|
3134 soap_ssl_client_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *keyid, const char *password, const char *cafile, const char *capath, const char *randfile)
|
|
3135 #else
|
|
3136 soap_ssl_client_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *password, const char *cafile, const char *capath, const char *randfile)
|
|
3137 #endif
|
|
3138 { soap->keyfile = keyfile;
|
|
3139 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
|
|
3140 soap->keyid = keyid;
|
|
3141 #endif
|
|
3142 soap->password = password;
|
|
3143 soap->cafile = cafile;
|
|
3144 soap->capath = capath;
|
|
3145 soap->ssl_flags = SOAP_SSL_CLIENT | flags;
|
|
3146 #ifdef WITH_OPENSSL
|
|
3147 soap->dhfile = NULL;
|
|
3148 soap->randfile = randfile;
|
|
3149 soap->fsslverify = (flags & SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE) == 0 ? ssl_verify_callback : ssl_verify_callback_allow_expired_certificate;
|
|
3150 #endif
|
|
3151 #ifdef WITH_GNUTLS
|
|
3152 if (soap->session)
|
|
3153 { gnutls_deinit(soap->session);
|
|
3154 soap->session = NULL;
|
|
3155 }
|
|
3156 if (soap->xcred)
|
|
3157 { gnutls_certificate_free_credentials(soap->xcred);
|
|
3158 soap->xcred = NULL;
|
|
3159 }
|
|
3160 #endif
|
|
3161 return soap->fsslauth(soap);
|
|
3162 }
|
|
3163 #endif
|
|
3164 #endif
|
|
3165
|
|
3166 /******************************************************************************/
|
|
3167 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
|
|
3168 #ifndef PALM_2
|
|
3169 SOAP_FMAC1
|
|
3170 void
|
|
3171 SOAP_FMAC2
|
|
3172 soap_ssl_init()
|
|
3173 { /* Note: for MT systems, the main program MUST call soap_ssl_init() before any threads are started */
|
|
3174 if (!soap_ssl_init_done)
|
|
3175 { soap_ssl_init_done = 1;
|
|
3176 #ifdef WITH_OPENSSL
|
|
3177 SSL_library_init();
|
|
3178 OpenSSL_add_all_algorithms(); /* 2.8.1 change (wsseapi.c) */
|
|
3179 OpenSSL_add_all_digests();
|
|
3180 #ifndef WITH_LEAN
|
|
3181 SSL_load_error_strings();
|
|
3182 #endif
|
|
3183 if (!RAND_load_file("/dev/urandom", 1024))
|
|
3184 { char buf[1024];
|
|
3185 RAND_seed(buf, sizeof(buf));
|
|
3186 while (!RAND_status())
|
|
3187 { int r = rand();
|
|
3188 RAND_seed(&r, sizeof(int));
|
|
3189 }
|
|
3190 }
|
|
3191 #endif
|
|
3192 #ifdef WITH_GNUTLS
|
|
3193 # if defined(HAVE_PTHREAD_H)
|
|
3194 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
|
|
3195 # elif defined(HAVE_PTH_H)
|
|
3196 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth);
|
|
3197 # endif
|
|
3198 gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM, 0);
|
|
3199 gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
|
|
3200 gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); /* libgcrypt init done */
|
|
3201 gnutls_global_init();
|
|
3202 #endif
|
|
3203 }
|
|
3204 }
|
|
3205 #endif
|
|
3206 #endif
|
|
3207
|
|
3208 /******************************************************************************/
|
|
3209 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
|
|
3210 #ifndef PALM_1
|
|
3211 SOAP_FMAC1
|
|
3212 const char *
|
|
3213 SOAP_FMAC2
|
|
3214 soap_ssl_error(struct soap *soap, int ret)
|
|
3215 {
|
|
3216 #ifdef WITH_OPENSSL
|
|
3217 int err = SSL_get_error(soap->ssl, ret);
|
|
3218 const char *msg = soap_code_str(h_ssl_error_codes, err);
|
|
3219 if (msg)
|
|
3220 strcpy(soap->msgbuf, msg);
|
|
3221 else
|
|
3222 return ERR_error_string(err, soap->msgbuf);
|
|
3223 if (ERR_peek_error())
|
|
3224 { unsigned long r;
|
|
3225 strcat(soap->msgbuf, "\n");
|
|
3226 while ((r = ERR_get_error()))
|
|
3227 ERR_error_string_n(r, soap->msgbuf + strlen(soap->msgbuf), sizeof(soap->msgbuf) - strlen(soap->msgbuf));
|
|
3228 }
|
|
3229 else
|
|
3230 { switch (ret)
|
|
3231 { case 0:
|
|
3232 strcpy(soap->msgbuf, "EOF was observed that violates the SSL/TLS protocol. The client probably provided invalid authentication information.");
|
|
3233 break;
|
|
3234 case -1:
|
|
3235 #ifdef HAVE_SNPRINTF
|
|
3236 soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "Error observed by underlying SSL/TLS BIO: %s", strerror(errno));
|
|
3237 #else
|
|
3238 { const char *s = strerror(errno);
|
|
3239 size_t l = strlen(s);
|
|
3240 sprintf(soap->msgbuf, "Error observed by underlying SSL/TLS BIO: %s", l + 44 < sizeof(soap->msgbuf) ? s : SOAP_STR_EOS);
|
|
3241 }
|
|
3242 #endif
|
|
3243 break;
|
|
3244 }
|
|
3245 }
|
|
3246 return soap->msgbuf;
|
|
3247 #endif
|
|
3248 #ifdef WITH_GNUTLS
|
|
3249 return gnutls_strerror(ret);
|
|
3250 #endif
|
|
3251 }
|
|
3252 #endif
|
|
3253 #endif
|
|
3254
|
|
3255 /******************************************************************************/
|
|
3256 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
|
|
3257 #ifndef PALM_1
|
|
3258 static int
|
|
3259 ssl_auth_init(struct soap *soap)
|
|
3260 {
|
|
3261 #ifdef WITH_OPENSSL
|
|
3262 long flags;
|
|
3263 int mode;
|
|
3264 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
|
|
3265 EVP_PKEY* pkey;
|
|
3266 #endif
|
|
3267 if (!soap_ssl_init_done)
|
|
3268 soap_ssl_init();
|
|
3269 ERR_clear_error();
|
|
3270 if (!soap->ctx)
|
|
3271 { if (!(soap->ctx = SSL_CTX_new(SSLv23_method())))
|
|
3272 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't setup context", SOAP_SSL_ERROR);
|
|
3273 /* The following alters the behavior of SSL read/write: */
|
|
3274 #if 0
|
|
3275 SSL_CTX_set_mode(soap->ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY);
|
|
3276 #endif
|
|
3277 }
|
|
3278 if (soap->randfile)
|
|
3279 { if (!RAND_load_file(soap->randfile, -1))
|
|
3280 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't load randomness", SOAP_SSL_ERROR);
|
|
3281 }
|
|
3282 if (soap->cafile || soap->capath)
|
|
3283 { if (!SSL_CTX_load_verify_locations(soap->ctx, soap->cafile, soap->capath))
|
|
3284 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CA file", SOAP_SSL_ERROR);
|
|
3285 if (soap->cafile && (soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
|
|
3286 SSL_CTX_set_client_CA_list(soap->ctx, SSL_load_client_CA_file(soap->cafile));
|
|
3287 }
|
|
3288 if (!(soap->ssl_flags & SOAP_SSL_NO_DEFAULT_CA_PATH))
|
|
3289 { if (!SSL_CTX_set_default_verify_paths(soap->ctx))
|
|
3290 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read default CA file and/or directory", SOAP_SSL_ERROR);
|
|
3291 }
|
|
3292 /* This code assumes a typical scenario, see alternative code below */
|
|
3293 if (soap->keyfile)
|
|
3294 { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile))
|
|
3295 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read certificate key file", SOAP_SSL_ERROR);
|
|
3296 if (soap->password)
|
|
3297 { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password);
|
|
3298 SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password);
|
|
3299 }
|
|
3300 if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM))
|
|
3301 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read key file", SOAP_SSL_ERROR);
|
|
3302 #ifndef WM_SECURE_KEY_STORAGE
|
|
3303 if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM))
|
|
3304 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read key file", SOAP_SSL_ERROR);
|
|
3305 #endif
|
|
3306 }
|
|
3307 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
|
|
3308 if (NULL == (pkey = ipcom_key_db_pkey_get(soap->keyid)))
|
|
3309 return soap_set_receiver_error(soap, "SSL error", "Can't find key", SOAP_SSL_ERROR);
|
|
3310 if (0 == SSL_CTX_use_PrivateKey(soap->ctx, pkey))
|
|
3311 return soap_set_receiver_error(soap, "SSL error", "Can't read key", SOAP_SSL_ERROR);
|
|
3312 #endif
|
|
3313 /* Suggested alternative approach to check the key file for certs (cafile=NULL):*/
|
|
3314 #if 0
|
|
3315 if (soap->password)
|
|
3316 { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password);
|
|
3317 SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password);
|
|
3318 }
|
|
3319 if (!soap->cafile || !SSL_CTX_use_certificate_chain_file(soap->ctx, soap->cafile))
|
|
3320 { if (soap->keyfile)
|
|
3321 { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile))
|
|
3322 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read certificate or key file", SOAP_SSL_ERROR);
|
|
3323 if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM))
|
|
3324 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read key file", SOAP_SSL_ERROR);
|
|
3325 }
|
|
3326 }
|
|
3327 #endif
|
|
3328 if ((soap->ssl_flags & SOAP_SSL_RSA))
|
|
3329 { RSA *rsa = RSA_generate_key(SOAP_SSL_RSA_BITS, RSA_F4, NULL, NULL);
|
|
3330 if (!SSL_CTX_set_tmp_rsa(soap->ctx, rsa))
|
|
3331 { if (rsa)
|
|
3332 RSA_free(rsa);
|
|
3333 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't set RSA key", SOAP_SSL_ERROR);
|
|
3334 }
|
|
3335 RSA_free(rsa);
|
|
3336 }
|
|
3337 else if (soap->dhfile)
|
|
3338 { DH *dh = 0;
|
|
3339 char *s;
|
|
3340 int n = (int)soap_strtoul(soap->dhfile, &s, 10);
|
|
3341 /* if dhfile is numeric, treat it as a key length to generate DH params which can take a while */
|
|
3342 if (n >= 512 && s && *s == '\0')
|
|
3343 #if defined(VXWORKS)
|
|
3344 DH_generate_parameters_ex(dh, n, 2/*or 5*/, NULL);
|
|
3345 #else
|
|
3346 dh = DH_generate_parameters(n, 2/*or 5*/, NULL, NULL);
|
|
3347 #endif
|
|
3348 else
|
|
3349 { BIO *bio;
|
|
3350 bio = BIO_new_file(soap->dhfile, "r");
|
|
3351 if (!bio)
|
|
3352 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read DH file", SOAP_SSL_ERROR);
|
|
3353 dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
|
|
3354 BIO_free(bio);
|
|
3355 }
|
|
3356 if (!dh || DH_check(dh, &n) != 1 || SSL_CTX_set_tmp_dh(soap->ctx, dh) < 0)
|
|
3357 { if (dh)
|
|
3358 DH_free(dh);
|
|
3359 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't set DH parameters", SOAP_SSL_ERROR);
|
|
3360 }
|
|
3361 DH_free(dh);
|
|
3362 }
|
|
3363 flags = (SSL_OP_ALL | SSL_OP_NO_SSLv2); /* disable SSL v2 */
|
|
3364 if ((soap->ssl_flags & SOAP_SSLv3))
|
|
3365 flags |= SSL_OP_NO_TLSv1;
|
|
3366 if ((soap->ssl_flags & SOAP_TLSv1))
|
|
3367 flags |= SSL_OP_NO_SSLv3;
|
|
3368 #ifdef SSL_OP_NO_TICKET
|
|
3369 /* TLS extension is enabled by default in OPENSSL v0.9.8k
|
|
3370 Disable it by adding SSL_OP_NO_TICKET */
|
|
3371 flags |= SSL_OP_NO_TICKET;
|
|
3372 #endif
|
|
3373 SSL_CTX_set_options(soap->ctx, flags);
|
|
3374 if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
|
|
3375 mode = (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
|
|
3376 else if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION))
|
|
3377 mode = SSL_VERIFY_PEER;
|
|
3378 else
|
|
3379 mode = SSL_VERIFY_NONE;
|
|
3380 SSL_CTX_set_verify(soap->ctx, mode, soap->fsslverify);
|
|
3381 #if (OPENSSL_VERSION_NUMBER < 0x00905100L)
|
|
3382 SSL_CTX_set_verify_depth(soap->ctx, 1);
|
|
3383 #else
|
|
3384 SSL_CTX_set_verify_depth(soap->ctx, 9);
|
|
3385 #endif
|
|
3386 #endif
|
|
3387 #ifdef WITH_GNUTLS
|
|
3388 int ret;
|
|
3389 if (!soap_ssl_init_done)
|
|
3390 soap_ssl_init();
|
|
3391 if (!soap->xcred)
|
|
3392 { gnutls_certificate_allocate_credentials(&soap->xcred);
|
|
3393 if (soap->cafile)
|
|
3394 { if (gnutls_certificate_set_x509_trust_file(soap->xcred, soap->cafile, GNUTLS_X509_FMT_PEM) < 0)
|
|
3395 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CA file", SOAP_SSL_ERROR);
|
|
3396 }
|
|
3397 if (soap->crlfile)
|
|
3398 { if (gnutls_certificate_set_x509_crl_file(soap->xcred, soap->crlfile, GNUTLS_X509_FMT_PEM) < 0)
|
|
3399 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CRL file", SOAP_SSL_ERROR);
|
|
3400 }
|
|
3401 if (soap->keyfile)
|
|
3402 { if (gnutls_certificate_set_x509_key_file(soap->xcred, soap->keyfile, soap->keyfile, GNUTLS_X509_FMT_PEM) < 0) /* TODO: GNUTLS need to concat cert and key in single key file */
|
|
3403 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read key file", SOAP_SSL_ERROR);
|
|
3404 }
|
|
3405 }
|
|
3406 if ((soap->ssl_flags & SOAP_SSL_CLIENT))
|
|
3407 { gnutls_init(&soap->session, GNUTLS_CLIENT);
|
|
3408 if (soap->cafile || soap->crlfile || soap->keyfile)
|
|
3409 { ret = gnutls_priority_set_direct(soap->session, "PERFORMANCE", NULL);
|
|
3410 if (ret < 0)
|
|
3411 return soap_set_receiver_error(soap, soap_ssl_error(soap, ret), "SSL/TLS set priority error", SOAP_SSL_ERROR);
|
|
3412 gnutls_credentials_set(soap->session, GNUTLS_CRD_CERTIFICATE, soap->xcred);
|
|
3413 }
|
|
3414 else
|
|
3415 { if (!soap->acred)
|
|
3416 gnutls_anon_allocate_client_credentials(&soap->acred);
|
|
3417 gnutls_init(&soap->session, GNUTLS_CLIENT);
|
|
3418 gnutls_priority_set_direct(soap->session, "PERFORMANCE:+ANON-DH:!ARCFOUR-128", NULL);
|
|
3419 gnutls_credentials_set(soap->session, GNUTLS_CRD_ANON, soap->acred);
|
|
3420 }
|
|
3421 }
|
|
3422 else
|
|
3423 { if (!soap->keyfile)
|
|
3424 return soap_set_receiver_error(soap, "SSL/TLS error", "No key file: anonymous server authentication not supported in this release", SOAP_SSL_ERROR);
|
|
3425 if ((soap->ssl_flags & SOAP_SSL_RSA) && soap->rsa_params)
|
|
3426 gnutls_certificate_set_rsa_export_params(soap->xcred, soap->rsa_params);
|
|
3427 else if (soap->dh_params)
|
|
3428 gnutls_certificate_set_dh_params(soap->xcred, soap->dh_params);
|
|
3429 if (!soap->cache)
|
|
3430 gnutls_priority_init(&soap->cache, "NORMAL", NULL);
|
|
3431 gnutls_init(&soap->session, GNUTLS_SERVER);
|
|
3432 gnutls_priority_set(soap->session, soap->cache);
|
|
3433 gnutls_credentials_set(soap->session, GNUTLS_CRD_CERTIFICATE, soap->xcred);
|
|
3434 if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
|
|
3435 gnutls_certificate_server_set_request(soap->session, GNUTLS_CERT_REQUEST);
|
|
3436 gnutls_session_enable_compatibility_mode(soap->session);
|
|
3437 if ((soap->ssl_flags & SOAP_TLSv1))
|
|
3438 { int protocol_priority[] = { GNUTLS_TLS1_0, 0 };
|
|
3439 if (gnutls_protocol_set_priority(soap->session, protocol_priority) != GNUTLS_E_SUCCESS)
|
|
3440 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't set TLS v1.0 protocol", SOAP_SSL_ERROR);
|
|
3441 }
|
|
3442 }
|
|
3443 #endif
|
|
3444 return SOAP_OK;
|
|
3445 }
|
|
3446 #endif
|
|
3447 #endif
|
|
3448
|
|
3449 /******************************************************************************/
|
|
3450 #ifdef WITH_OPENSSL
|
|
3451 #ifndef PALM_1
|
|
3452 static int
|
|
3453 ssl_password(char *buf, int num, int rwflag, void *userdata)
|
|
3454 { if (num < (int)strlen((char*)userdata) + 1)
|
|
3455 return 0;
|
|
3456 return (int)strlen(strcpy(buf, (char*)userdata));
|
|
3457 }
|
|
3458 #endif
|
|
3459 #endif
|
|
3460
|
|
3461 /******************************************************************************/
|
|
3462 #ifdef WITH_OPENSSL
|
|
3463 #ifndef PALM_1
|
|
3464 static int
|
|
3465 ssl_verify_callback(int ok, X509_STORE_CTX *store)
|
|
3466 {
|
|
3467 #ifdef SOAP_DEBUG
|
|
3468 if (!ok)
|
|
3469 { char buf[1024];
|
|
3470 int err = X509_STORE_CTX_get_error(store);
|
|
3471 X509 *cert = X509_STORE_CTX_get_current_cert(store);
|
|
3472 fprintf(stderr, "SSL verify error or warning with certificate at depth %d: %s\n", X509_STORE_CTX_get_error_depth(store), X509_verify_cert_error_string(err));
|
|
3473 X509_NAME_oneline(X509_get_issuer_name(cert), buf, sizeof(buf));
|
|
3474 fprintf(stderr, "certificate issuer %s\n", buf);
|
|
3475 X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf));
|
|
3476 fprintf(stderr, "certificate subject %s\n", buf);
|
|
3477 /* accept self signed certificates and certificates out of date */
|
|
3478 switch (err)
|
|
3479 { case X509_V_ERR_CERT_NOT_YET_VALID:
|
|
3480 case X509_V_ERR_CERT_HAS_EXPIRED:
|
|
3481 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
|
|
3482 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
|
|
3483 X509_STORE_CTX_set_error(store, X509_V_OK);
|
|
3484 ok = 1;
|
|
3485 }
|
|
3486 }
|
|
3487 #endif
|
|
3488 /* Note: return 1 to continue, but unsafe progress will be terminated by OpenSSL */
|
|
3489 return ok;
|
|
3490 }
|
|
3491 #endif
|
|
3492 #endif
|
|
3493
|
|
3494 /******************************************************************************/
|
|
3495 #ifdef WITH_OPENSSL
|
|
3496 #ifndef PALM_1
|
|
3497 static int
|
|
3498 ssl_verify_callback_allow_expired_certificate(int ok, X509_STORE_CTX *store)
|
|
3499 { ok = ssl_verify_callback(ok, store);
|
|
3500 if (!ok)
|
|
3501 { /* accept self signed certificates and certificates out of date */
|
|
3502 switch (X509_STORE_CTX_get_error(store))
|
|
3503 { case X509_V_ERR_CERT_NOT_YET_VALID:
|
|
3504 case X509_V_ERR_CERT_HAS_EXPIRED:
|
|
3505 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
|
|
3506 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
|
|
3507 X509_STORE_CTX_set_error(store, X509_V_OK);
|
|
3508 ok = 1;
|
|
3509 }
|
|
3510 }
|
|
3511 /* Note: return 1 to continue, but unsafe progress will be terminated by SSL */
|
|
3512 return ok;
|
|
3513 }
|
|
3514 #endif
|
|
3515 #endif
|
|
3516
|
|
3517 /******************************************************************************/
|
|
3518 #ifdef WITH_GNUTLS
|
|
3519 static const char *
|
|
3520 ssl_verify(struct soap *soap, const char *host)
|
|
3521 { unsigned int status;
|
|
3522 const char *err = NULL;
|
|
3523 int r = gnutls_certificate_verify_peers2(soap->session, &status);
|
|
3524 if (r < 0)
|
|
3525 err = "Certificate verify error";
|
|
3526 else if ((status & GNUTLS_CERT_INVALID))
|
|
3527 err = "The certificate is not trusted";
|
|
3528 else if ((status & GNUTLS_CERT_SIGNER_NOT_FOUND))
|
|
3529 err = "The certificate hasn't got a known issuer";
|
|
3530 else if ((status & GNUTLS_CERT_REVOKED))
|
|
3531 err = "The certificate has been revoked";
|
|
3532 else if (gnutls_certificate_type_get(soap->session) == GNUTLS_CRT_X509)
|
|
3533 { gnutls_x509_crt_t cert;
|
|
3534 const gnutls_datum_t *cert_list;
|
|
3535 unsigned int cert_list_size;
|
|
3536 if (gnutls_x509_crt_init(&cert) < 0)
|
|
3537 err = "Could not get X509 certificates";
|
|
3538 else if ((cert_list = gnutls_certificate_get_peers(soap->session, &cert_list_size)) == NULL)
|
|
3539 err = "Could not get X509 certificates";
|
|
3540 else if (gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0)
|
|
3541 err = "Error parsing X509 certificate";
|
|
3542 else if (!(soap->ssl_flags & SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE) && gnutls_x509_crt_get_expiration_time(cert) < time(NULL))
|
|
3543 err = "The certificate has expired";
|
|
3544 else if (!(soap->ssl_flags & SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE) && gnutls_x509_crt_get_activation_time(cert) > time(NULL))
|
|
3545 err = "The certificate is not yet activated";
|
|
3546 else if (host && !(soap->ssl_flags & SOAP_SSL_SKIP_HOST_CHECK))
|
|
3547 { if (!gnutls_x509_crt_check_hostname(cert, host))
|
|
3548 err = "Certificate host name mismatch";
|
|
3549 }
|
|
3550 gnutls_x509_crt_deinit(cert);
|
|
3551 }
|
|
3552 return err;
|
|
3553 }
|
|
3554 #endif
|
|
3555
|
|
3556 /******************************************************************************/
|
|
3557 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
|
|
3558 #ifndef WITH_NOIO
|
|
3559 #ifndef PALM_1
|
|
3560 SOAP_FMAC1
|
|
3561 int
|
|
3562 SOAP_FMAC2
|
|
3563 soap_ssl_accept(struct soap *soap)
|
|
3564 { SOAP_SOCKET sk = soap->socket;
|
|
3565 #ifdef WITH_OPENSSL
|
|
3566 BIO *bio;
|
|
3567 int retries, r, s;
|
|
3568 if (!soap_valid_socket(sk))
|
|
3569 return soap_set_receiver_error(soap, "SSL/TLS error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR);
|
|
3570 soap->ssl_flags &= ~SOAP_SSL_CLIENT;
|
|
3571 if (!soap->ctx && (soap->error = soap->fsslauth(soap)))
|
|
3572 return soap->error;
|
|
3573 if (!soap->ssl)
|
|
3574 { soap->ssl = SSL_new(soap->ctx);
|
|
3575 if (!soap->ssl)
|
|
3576 return soap_set_receiver_error(soap, "SSL/TLS error", "SSL_new() failed in soap_ssl_accept()", SOAP_SSL_ERROR);
|
|
3577 }
|
|
3578 else
|
|
3579 SSL_clear(soap->ssl);
|
|
3580 bio = BIO_new_socket((int)sk, BIO_NOCLOSE);
|
|
3581 SSL_set_bio(soap->ssl, bio, bio);
|
|
3582 /* Set SSL sockets to non-blocking */
|
|
3583 retries = 0;
|
|
3584 if (soap->accept_timeout)
|
|
3585 { SOAP_SOCKNONBLOCK(sk)
|
|
3586 retries = 10*soap->accept_timeout;
|
|
3587 }
|
|
3588 if (retries <= 0)
|
|
3589 retries = 100; /* timeout: 10 sec retries, 100 times 0.1 sec */
|
|
3590 while ((r = SSL_accept(soap->ssl)) <= 0)
|
|
3591 { int err;
|
|
3592 if (retries-- <= 0)
|
|
3593 break;
|
|
3594 err = SSL_get_error(soap->ssl, r);
|
|
3595 if (err == SSL_ERROR_WANT_ACCEPT || err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
|
|
3596 { if (err == SSL_ERROR_WANT_READ)
|
|
3597 s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000);
|
|
3598 else
|
|
3599 s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000);
|
|
3600 if (s < 0)
|
|
3601 break;
|
|
3602 }
|
|
3603 else
|
|
3604 { soap->errnum = soap_socket_errno(sk);
|
|
3605 break;
|
|
3606 }
|
|
3607 }
|
|
3608 if (r <= 0)
|
|
3609 { soap_set_receiver_error(soap, soap_ssl_error(soap, r), "SSL_accept() failed in soap_ssl_accept()", SOAP_SSL_ERROR);
|
|
3610 soap_closesock(soap);
|
|
3611 return SOAP_SSL_ERROR;
|
|
3612 }
|
|
3613 if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
|
|
3614 { X509 *peer;
|
|
3615 int err;
|
|
3616 if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK)
|
|
3617 { soap_closesock(soap);
|
|
3618 return soap_set_sender_error(soap, X509_verify_cert_error_string(err), "SSL certificate presented by peer cannot be verified in soap_ssl_accept()", SOAP_SSL_ERROR);
|
|
3619 }
|
|
3620 peer = SSL_get_peer_certificate(soap->ssl);
|
|
3621 if (!peer)
|
|
3622 { soap_closesock(soap);
|
|
3623 return soap_set_sender_error(soap, "SSL/TLS error", "No SSL certificate was presented by the peer in soap_ssl_accept()", SOAP_SSL_ERROR);
|
|
3624 }
|
|
3625 X509_free(peer);
|
|
3626 }
|
|
3627 #endif
|
|
3628 #ifdef WITH_GNUTLS
|
|
3629 int retries = 0, r;
|
|
3630 if (!soap_valid_socket(sk))
|
|
3631 return soap_set_receiver_error(soap, "SSL/TLS error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR);
|
|
3632 soap->ssl_flags &= ~SOAP_SSL_CLIENT;
|
|
3633 if (!soap->session && (soap->error = soap->fsslauth(soap)))
|
|
3634 { soap_closesock(soap);
|
|
3635 return soap->error;
|
|
3636 }
|
|
3637 gnutls_transport_set_ptr(soap->session, (gnutls_transport_ptr_t)(long)sk);
|
|
3638 /* Set SSL sockets to non-blocking */
|
|
3639 if (soap->accept_timeout)
|
|
3640 { SOAP_SOCKNONBLOCK(sk)
|
|
3641 retries = 10*soap->accept_timeout;
|
|
3642 }
|
|
3643 if (retries <= 0)
|
|
3644 retries = 100; /* timeout: 10 sec retries, 100 times 0.1 sec */
|
|
3645 while ((r = gnutls_handshake(soap->session)))
|
|
3646 { int s;
|
|
3647 /* GNUTLS repeat handhake when GNUTLS_E_AGAIN */
|
|
3648 if (retries-- <= 0)
|
|
3649 break;
|
|
3650 if (r == GNUTLS_E_AGAIN || r == GNUTLS_E_INTERRUPTED)
|
|
3651 { if (!gnutls_record_get_direction(soap->session))
|
|
3652 s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000);
|
|
3653 else
|
|
3654 s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000);
|
|
3655 if (s < 0)
|
|
3656 break;
|
|
3657 }
|
|
3658 else
|
|
3659 { soap->errnum = soap_socket_errno(sk);
|
|
3660 break;
|
|
3661 }
|
|
3662 }
|
|
3663 if (r)
|
|
3664 { soap_closesock(soap);
|
|
3665 return soap_set_receiver_error(soap, soap_ssl_error(soap, r), "SSL/TLS handshake failed", SOAP_SSL_ERROR);
|
|
3666 }
|
|
3667 if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
|
|
3668 { const char *err = ssl_verify(soap, NULL);
|
|
3669 if (err)
|
|
3670 { soap_closesock(soap);
|
|
3671 return soap_set_receiver_error(soap, "SSL/TLS error", err, SOAP_SSL_ERROR);
|
|
3672 }
|
|
3673 }
|
|
3674 #endif
|
|
3675 if (soap->recv_timeout || soap->send_timeout)
|
|
3676 SOAP_SOCKNONBLOCK(sk)
|
|
3677 else
|
|
3678 SOAP_SOCKBLOCK(sk)
|
|
3679 soap->imode |= SOAP_ENC_SSL;
|
|
3680 soap->omode |= SOAP_ENC_SSL;
|
|
3681 return SOAP_OK;
|
|
3682 }
|
|
3683 #endif
|
|
3684 #endif
|
|
3685 #endif
|
|
3686
|
|
3687 /******************************************************************************\
|
|
3688 *
|
|
3689 * TCP/UDP [SSL/TLS] IPv4 and IPv6
|
|
3690 *
|
|
3691 \******************************************************************************/
|
|
3692
|
|
3693 /******************************************************************************/
|
|
3694 #ifndef WITH_NOIO
|
|
3695 #ifndef PALM_1
|
|
3696 static int
|
|
3697 tcp_init(struct soap *soap)
|
|
3698 { soap->errmode = 1;
|
|
3699 #ifdef WIN32
|
|
3700 if (tcp_done)
|
|
3701 return 0;
|
|
3702 else
|
|
3703 { WSADATA w;
|
|
3704 if (WSAStartup(MAKEWORD(1, 1), &w))
|
|
3705 return -1;
|
|
3706 tcp_done = 1;
|
|
3707 }
|
|
3708 #endif
|
|
3709 return 0;
|
|
3710 }
|
|
3711 #endif
|
|
3712 #endif
|
|
3713
|
|
3714 /******************************************************************************/
|
|
3715 #ifndef WITH_NOIO
|
|
3716 #ifndef PALM_1
|
|
3717 static const char*
|
|
3718 tcp_error(struct soap *soap)
|
|
3719 { register const char *msg = NULL;
|
|
3720 switch (soap->errmode)
|
|
3721 { case 0:
|
|
3722 msg = soap_strerror(soap);
|
|
3723 break;
|
|
3724 case 1:
|
|
3725 msg = "WSAStartup failed";
|
|
3726 break;
|
|
3727 case 2:
|
|
3728 {
|
|
3729 #ifndef WITH_LEAN
|
|
3730 msg = soap_code_str(h_error_codes, soap->errnum);
|
|
3731 if (!msg)
|
|
3732 #endif
|
|
3733 {
|
|
3734 #ifdef HAVE_SNPRINTF
|
|
3735 soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "TCP/UDP IP error %d", soap->errnum);
|
|
3736 #else
|
|
3737 sprintf(soap->msgbuf, "TCP/UDP IP error %d", soap->errnum);
|
|
3738 #endif
|
|
3739 msg = soap->msgbuf;
|
|
3740 }
|
|
3741 }
|
|
3742 }
|
|
3743 return msg;
|
|
3744 }
|
|
3745 #endif
|
|
3746 #endif
|
|
3747
|
|
3748 /******************************************************************************/
|
|
3749 #ifndef WITH_IPV6
|
|
3750 #ifndef WITH_NOIO
|
|
3751 #ifndef PALM_1
|
|
3752 static int
|
|
3753 tcp_gethost(struct soap *soap, const char *addr, struct in_addr *inaddr)
|
|
3754 { soap_int32 iadd = -1;
|
|
3755 struct hostent hostent, *host = &hostent;
|
|
3756 #ifdef VXWORKS
|
|
3757 int hostint;
|
|
3758 /* inet_addr(), and hostGetByName() expect "char *"; addr is a "const char *". */
|
|
3759 iadd = inet_addr((char*)addr);
|
|
3760 #else
|
|
3761 #if defined(_AIX43) || ((defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R))
|
|
3762 struct hostent_data ht_data;
|
|
3763 #endif
|
|
3764 #ifdef AS400
|
|
3765 iadd = inet_addr((void*)addr);
|
|
3766 #else
|
|
3767 iadd = inet_addr(addr);
|
|
3768 #endif
|
|
3769 #endif
|
|
3770 if (iadd != -1)
|
|
3771 { memcpy(inaddr, &iadd, sizeof(iadd));
|
|
3772 return SOAP_OK;
|
|
3773 }
|
|
3774 #if defined(__GLIBC__) || (defined(HAVE_GETHOSTBYNAME_R) && (defined(FREEBSD) || defined(__FreeBSD__))) || defined(__ANDROID__)
|
|
3775 if (gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &host, &soap->errnum) < 0)
|
|
3776 host = NULL;
|
|
3777 #elif defined(_AIX43) || ((defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R))
|
|
3778 memset((void*)&ht_data, 0, sizeof(ht_data));
|
|
3779 if (gethostbyname_r(addr, &hostent, &ht_data) < 0)
|
|
3780 { host = NULL;
|
|
3781 soap->errnum = h_errno;
|
|
3782 }
|
|
3783 #elif defined(HAVE_GETHOSTBYNAME_R)
|
|
3784 host = gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &soap->errnum);
|
|
3785 #elif defined(VXWORKS)
|
|
3786 /* If the DNS resolver library resolvLib has been configured in the vxWorks
|
|
3787 * image, a query for the host IP address is sent to the DNS server, if the
|
|
3788 * name was not found in the local host table. */
|
|
3789 hostint = hostGetByName((char*)addr);
|
|
3790 if (hostint == ERROR)
|
|
3791 { host = NULL;
|
|
3792 soap->errnum = soap_errno;
|
|
3793 }
|
|
3794 #else
|
|
3795 #ifdef AS400
|
|
3796 if (!(host = gethostbyname((void*)addr)))
|
|
3797 soap->errnum = h_errno;
|
|
3798 #else
|
|
3799 if (!(host = gethostbyname(addr)))
|
|
3800 soap->errnum = h_errno;
|
|
3801 #endif
|
|
3802 #endif
|
|
3803 if (!host)
|
|
3804 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Host name not found\n"));
|
|
3805 return SOAP_ERR;
|
|
3806 }
|
|
3807 #ifdef VXWORKS
|
|
3808 inaddr->s_addr = hostint;
|
|
3809 #else
|
|
3810 memcpy(inaddr, host->h_addr, host->h_length);
|
|
3811 #endif
|
|
3812 return SOAP_OK;
|
|
3813 }
|
|
3814 #endif
|
|
3815 #endif
|
|
3816 #endif
|
|
3817
|
|
3818 /******************************************************************************/
|
|
3819 #ifndef WITH_NOIO
|
|
3820 #ifndef PALM_1
|
|
3821 static SOAP_SOCKET
|
|
3822 tcp_connect(struct soap *soap, const char *endpoint, const char *host, int port)
|
|
3823 {
|
|
3824 #ifdef WITH_IPV6
|
|
3825 struct addrinfo hints, *res, *ressave;
|
|
3826 #endif
|
|
3827 SOAP_SOCKET sk;
|
|
3828 int err = 0;
|
|
3829 #ifndef WITH_LEAN
|
|
3830 #ifndef WIN32
|
|
3831 int len = SOAP_BUFLEN;
|
|
3832 #else
|
|
3833 int len = SOAP_BUFLEN + 1; /* speeds up windows xfer */
|
|
3834 #endif
|
|
3835 int set = 1;
|
|
3836 #endif
|
|
3837 #if !defined(WITH_LEAN) || defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
|
|
3838 int retries;
|
|
3839 #endif
|
|
3840 if (soap_valid_socket(soap->socket))
|
|
3841 soap->fclosesocket(soap, soap->socket);
|
|
3842 soap->socket = SOAP_INVALID_SOCKET;
|
|
3843 if (tcp_init(soap))
|
|
3844 { soap->errnum = 0;
|
|
3845 soap_set_sender_error(soap, tcp_error(soap), "TCP init failed in tcp_connect()", SOAP_TCP_ERROR);
|
|
3846 return SOAP_INVALID_SOCKET;
|
|
3847 }
|
|
3848 soap->errmode = 0;
|
|
3849 #ifdef WITH_IPV6
|
|
3850 memset((void*)&hints, 0, sizeof(hints));
|
|
3851 hints.ai_family = PF_UNSPEC;
|
|
3852 #ifndef WITH_LEAN
|
|
3853 if ((soap->omode & SOAP_IO_UDP))
|
|
3854 hints.ai_socktype = SOCK_DGRAM;
|
|
3855 else
|
|
3856 #endif
|
|
3857 hints.ai_socktype = SOCK_STREAM;
|
|
3858 soap->errmode = 2;
|
|
3859 if (soap->proxy_host)
|
|
3860 err = getaddrinfo(soap->proxy_host, soap_int2s(soap, soap->proxy_port), &hints, &res);
|
|
3861 else
|
|
3862 err = getaddrinfo(host, soap_int2s(soap, port), &hints, &res);
|
|
3863 if (err)
|
|
3864 { soap_set_sender_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in tcp_connect()", SOAP_TCP_ERROR);
|
|
3865 return SOAP_INVALID_SOCKET;
|
|
3866 }
|
|
3867 ressave = res;
|
|
3868 again:
|
|
3869 sk = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
|
|
3870 soap->errmode = 0;
|
|
3871 #else
|
|
3872 #ifndef WITH_LEAN
|
|
3873 again:
|
|
3874 #endif
|
|
3875 #ifndef WITH_LEAN
|
|
3876 if ((soap->omode & SOAP_IO_UDP))
|
|
3877 sk = socket(AF_INET, SOCK_DGRAM, 0);
|
|
3878 else
|
|
3879 #endif
|
|
3880 sk = socket(AF_INET, SOCK_STREAM, 0);
|
|
3881 #endif
|
|
3882 if (!soap_valid_socket(sk))
|
|
3883 {
|
|
3884 #ifdef WITH_IPV6
|
|
3885 if (res->ai_next)
|
|
3886 { res = res->ai_next;
|
|
3887 goto again;
|
|
3888 }
|
|
3889 #endif
|
|
3890 soap->errnum = soap_socket_errno(sk);
|
|
3891 soap_set_sender_error(soap, tcp_error(soap), "socket failed in tcp_connect()", SOAP_TCP_ERROR);
|
|
3892 #ifdef WITH_IPV6
|
|
3893 freeaddrinfo(ressave);
|
|
3894 #endif
|
|
3895 return SOAP_INVALID_SOCKET;
|
|
3896 }
|
|
3897 #ifdef SOCKET_CLOSE_ON_EXEC
|
|
3898 #ifdef WIN32
|
|
3899 #ifndef UNDER_CE
|
|
3900 SetHandleInformation((HANDLE)sk, HANDLE_FLAG_INHERIT, 0);
|
|
3901 #endif
|
|
3902 #else
|
|
3903 fcntl(sk, F_SETFD, 1);
|
|
3904 #endif
|
|
3905 #endif
|
|
3906 #ifndef WITH_LEAN
|
|
3907 if (soap->connect_flags == SO_LINGER)
|
|
3908 { struct linger linger;
|
|
3909 memset((void*)&linger, 0, sizeof(linger));
|
|
3910 linger.l_onoff = 1;
|
|
3911 linger.l_linger = soap->linger_time;
|
|
3912 if (setsockopt(sk, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger)))
|
|
3913 { soap->errnum = soap_socket_errno(sk);
|
|
3914 soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in tcp_connect()", SOAP_TCP_ERROR);
|
|
3915 soap->fclosesocket(soap, sk);
|
|
3916 #ifdef WITH_IPV6
|
|
3917 freeaddrinfo(ressave);
|
|
3918 #endif
|
|
3919 return SOAP_INVALID_SOCKET;
|
|
3920 }
|
|
3921 }
|
|
3922 else if (soap->connect_flags && setsockopt(sk, SOL_SOCKET, soap->connect_flags, (char*)&set, sizeof(int)))
|
|
3923 { soap->errnum = soap_socket_errno(sk);
|
|
3924 soap_set_sender_error(soap, tcp_error(soap), "setsockopt failed in tcp_connect()", SOAP_TCP_ERROR);
|
|
3925 soap->fclosesocket(soap, sk);
|
|
3926 #ifdef WITH_IPV6
|
|
3927 freeaddrinfo(ressave);
|
|
3928 #endif
|
|
3929 return SOAP_INVALID_SOCKET;
|
|
3930 }
|
|
3931 if ((soap->keep_alive || soap->tcp_keep_alive) && setsockopt(sk, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
|
|
3932 { soap->errnum = soap_socket_errno(sk);
|
|
3933 soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in tcp_connect()", SOAP_TCP_ERROR);
|
|
3934 soap->fclosesocket(soap, sk);
|
|
3935 #ifdef WITH_IPV6
|
|
3936 freeaddrinfo(ressave);
|
|
3937 #endif
|
|
3938 return SOAP_INVALID_SOCKET;
|
|
3939 }
|
|
3940 if (setsockopt(sk, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
|
|
3941 { soap->errnum = soap_socket_errno(sk);
|
|
3942 soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in tcp_connect()", SOAP_TCP_ERROR);
|
|
3943 soap->fclosesocket(soap, sk);
|
|
3944 #ifdef WITH_IPV6
|
|
3945 freeaddrinfo(ressave);
|
|
3946 #endif
|
|
3947 return SOAP_INVALID_SOCKET;
|
|
3948 }
|
|
3949 if (setsockopt(sk, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
|
|
3950 { soap->errnum = soap_socket_errno(sk);
|
|
3951 soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in tcp_connect()", SOAP_TCP_ERROR);
|
|
3952 soap->fclosesocket(soap, sk);
|
|
3953 #ifdef WITH_IPV6
|
|
3954 freeaddrinfo(ressave);
|
|
3955 #endif
|
|
3956 return SOAP_INVALID_SOCKET;
|
|
3957 }
|
|
3958 #ifdef TCP_KEEPIDLE
|
|
3959 if (soap->tcp_keep_idle && setsockopt((SOAP_SOCKET)sk, IPPROTO_TCP, TCP_KEEPIDLE, (char*)&(soap->tcp_keep_idle), sizeof(int)))
|
|
3960 { soap->errnum = soap_socket_errno(sk);
|
|
3961 soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPIDLE failed in tcp_connect()", SOAP_TCP_ERROR);
|
|
3962 soap->fclosesocket(soap, (SOAP_SOCKET)sk);
|
|
3963 #ifdef WITH_IPV6
|
|
3964 freeaddrinfo(ressave);
|
|
3965 #endif
|
|
3966 return SOAP_INVALID_SOCKET;
|
|
3967 }
|
|
3968 #endif
|
|
3969 #ifdef TCP_KEEPINTVL
|
|
3970 if (soap->tcp_keep_intvl && setsockopt((SOAP_SOCKET)sk, IPPROTO_TCP, TCP_KEEPINTVL, (char*)&(soap->tcp_keep_intvl), sizeof(int)))
|
|
3971 { soap->errnum = soap_socket_errno(sk);
|
|
3972 soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPINTVL failed in tcp_connect()", SOAP_TCP_ERROR);
|
|
3973 soap->fclosesocket(soap, (SOAP_SOCKET)sk);
|
|
3974 #ifdef WITH_IPV6
|
|
3975 freeaddrinfo(ressave);
|
|
3976 #endif
|
|
3977 return SOAP_INVALID_SOCKET;
|
|
3978 }
|
|
3979 #endif
|
|
3980 #ifdef TCP_KEEPCNT
|
|
3981 if (soap->tcp_keep_cnt && setsockopt((SOAP_SOCKET)sk, IPPROTO_TCP, TCP_KEEPCNT, (char*)&(soap->tcp_keep_cnt), sizeof(int)))
|
|
3982 { soap->errnum = soap_socket_errno(sk);
|
|
3983 soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPCNT failed in tcp_connect()", SOAP_TCP_ERROR);
|
|
3984 soap->fclosesocket(soap, (SOAP_SOCKET)sk);
|
|
3985 #ifdef WITH_IPV6
|
|
3986 freeaddrinfo(ressave);
|
|
3987 #endif
|
|
3988 return SOAP_INVALID_SOCKET;
|
|
3989 }
|
|
3990 #endif
|
|
3991 #ifdef TCP_NODELAY
|
|
3992 if (!(soap->omode & SOAP_IO_UDP) && setsockopt(sk, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
|
|
3993 { soap->errnum = soap_socket_errno(sk);
|
|
3994 soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in tcp_connect()", SOAP_TCP_ERROR);
|
|
3995 soap->fclosesocket(soap, sk);
|
|
3996 #ifdef WITH_IPV6
|
|
3997 freeaddrinfo(ressave);
|
|
3998 #endif
|
|
3999 return SOAP_INVALID_SOCKET;
|
|
4000 }
|
|
4001 #endif
|
|
4002 #ifdef WITH_IPV6
|
|
4003 if ((soap->omode & SOAP_IO_UDP) && soap->ipv6_multicast_if)
|
|
4004 { struct sockaddr_in6 *in6addr = (struct sockaddr_in6*)res->ai_addr;
|
|
4005 in6addr->sin6_scope_id = soap->ipv6_multicast_if;
|
|
4006 }
|
|
4007 #endif
|
|
4008 #ifdef IP_MULTICAST_TTL
|
|
4009 if ((soap->omode & SOAP_IO_UDP))
|
|
4010 { if (soap->ipv4_multicast_ttl)
|
|
4011 { unsigned char ttl = soap->ipv4_multicast_ttl;
|
|
4012 if (setsockopt(sk, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ttl, sizeof(ttl)))
|
|
4013 { soap->errnum = soap_socket_errno(sk);
|
|
4014 soap_set_sender_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_TTL failed in tcp_connect()", SOAP_TCP_ERROR);
|
|
4015 soap->fclosesocket(soap, sk);
|
|
4016 return SOAP_INVALID_SOCKET;
|
|
4017 }
|
|
4018 }
|
|
4019 if ((soap->omode & SOAP_IO_UDP) && soap->ipv4_multicast_if && !soap->ipv6_multicast_if)
|
|
4020 { if (setsockopt(sk, IPPROTO_IP, IP_MULTICAST_IF, (char*)soap->ipv4_multicast_if, sizeof(struct in_addr)))
|
|
4021 #ifndef WINDOWS
|
|
4022 { soap->errnum = soap_socket_errno(sk);
|
|
4023 soap_set_sender_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR);
|
|
4024 soap->fclosesocket(soap, sk);
|
|
4025 return SOAP_INVALID_SOCKET;
|
|
4026 }
|
|
4027 #else
|
|
4028 #ifndef IP_MULTICAST_IF
|
|
4029 #define IP_MULTICAST_IF 2
|
|
4030 #endif
|
|
4031 if (setsockopt(sk, IPPROTO_IP, IP_MULTICAST_IF, (char*)soap->ipv4_multicast_if, sizeof(struct in_addr)))
|
|
4032 { soap->errnum = soap_socket_errno(sk);
|
|
4033 soap_set_sender_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR);
|
|
4034 soap->fclosesocket(soap, sk);
|
|
4035 return SOAP_INVALID_SOCKET;
|
|
4036 }
|
|
4037 #endif
|
|
4038 }
|
|
4039 }
|
|
4040 #endif
|
|
4041 #endif
|
|
4042 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Opening socket=%d to host='%s' port=%d\n", sk, host, port));
|
|
4043 #ifndef WITH_IPV6
|
|
4044 soap->peerlen = sizeof(soap->peer);
|
|
4045 memset((void*)&soap->peer, 0, sizeof(soap->peer));
|
|
4046 soap->peer.sin_family = AF_INET;
|
|
4047 soap->errmode = 2;
|
|
4048 if (soap->proxy_host)
|
|
4049 { if (soap->fresolve(soap, soap->proxy_host, &soap->peer.sin_addr))
|
|
4050 { soap_set_sender_error(soap, tcp_error(soap), "get proxy host by name failed in tcp_connect()", SOAP_TCP_ERROR);
|
|
4051 soap->fclosesocket(soap, sk);
|
|
4052 return SOAP_INVALID_SOCKET;
|
|
4053 }
|
|
4054 soap->peer.sin_port = htons((short)soap->proxy_port);
|
|
4055 }
|
|
4056 else
|
|
4057 { if (soap->fresolve(soap, host, &soap->peer.sin_addr))
|
|
4058 { soap_set_sender_error(soap, tcp_error(soap), "get host by name failed in tcp_connect()", SOAP_TCP_ERROR);
|
|
4059 soap->fclosesocket(soap, sk);
|
|
4060 return SOAP_INVALID_SOCKET;
|
|
4061 }
|
|
4062 soap->peer.sin_port = htons((short)port);
|
|
4063 }
|
|
4064 soap->errmode = 0;
|
|
4065 #ifndef WITH_LEAN
|
|
4066 if ((soap->omode & SOAP_IO_UDP))
|
|
4067 return sk;
|
|
4068 #endif
|
|
4069 #else
|
|
4070 if ((soap->omode & SOAP_IO_UDP))
|
|
4071 { memcpy(&soap->peer, res->ai_addr, res->ai_addrlen);
|
|
4072 soap->peerlen = res->ai_addrlen;
|
|
4073 freeaddrinfo(ressave);
|
|
4074 return sk;
|
|
4075 }
|
|
4076 #endif
|
|
4077 #ifndef WITH_LEAN
|
|
4078 if (soap->connect_timeout)
|
|
4079 SOAP_SOCKNONBLOCK(sk)
|
|
4080 else
|
|
4081 SOAP_SOCKBLOCK(sk)
|
|
4082 retries = 10;
|
|
4083 #endif
|
|
4084 for (;;)
|
|
4085 {
|
|
4086 #ifdef WITH_IPV6
|
|
4087 if (connect(sk, res->ai_addr, (int)res->ai_addrlen))
|
|
4088 #else
|
|
4089 if (connect(sk, (struct sockaddr*)&soap->peer, sizeof(soap->peer)))
|
|
4090 #endif
|
|
4091 { err = soap_socket_errno(sk);
|
|
4092 #ifndef WITH_LEAN
|
|
4093 if (err == SOAP_EADDRINUSE)
|
|
4094 { soap->fclosesocket(soap, sk);
|
|
4095 if (retries-- > 0)
|
|
4096 goto again;
|
|
4097 }
|
|
4098 else if (soap->connect_timeout && (err == SOAP_EINPROGRESS || err == SOAP_EAGAIN || err == SOAP_EWOULDBLOCK))
|
|
4099 {
|
|
4100 SOAP_SOCKLEN_T k;
|
|
4101 for (;;)
|
|
4102 { register int r;
|
|
4103 r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND, soap->connect_timeout);
|
|
4104 if (r > 0)
|
|
4105 break;
|
|
4106 if (!r)
|
|
4107 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n"));
|
|
4108 soap_set_sender_error(soap, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR);
|
|
4109 soap->fclosesocket(soap, sk);
|
|
4110 #ifdef WITH_IPV6
|
|
4111 freeaddrinfo(ressave);
|
|
4112 #endif
|
|
4113 return SOAP_INVALID_SOCKET;
|
|
4114 }
|
|
4115 r = soap->errnum = soap_socket_errno(sk);
|
|
4116 if (r != SOAP_EINTR)
|
|
4117 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
|
|
4118 soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
|
|
4119 soap->fclosesocket(soap, sk);
|
|
4120 #ifdef WITH_IPV6
|
|
4121 freeaddrinfo(ressave);
|
|
4122 #endif
|
|
4123 return SOAP_INVALID_SOCKET;
|
|
4124 }
|
|
4125 }
|
|
4126 k = (SOAP_SOCKLEN_T)sizeof(soap->errnum);
|
|
4127 if (!getsockopt(sk, SOL_SOCKET, SO_ERROR, (char*)&soap->errnum, &k) && !soap->errnum) /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
|
|
4128 break;
|
|
4129 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
|
|
4130 if (!soap->errnum)
|
|
4131 soap->errnum = soap_socket_errno(sk);
|
|
4132 soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
|
|
4133 soap->fclosesocket(soap, sk);
|
|
4134 #ifdef WITH_IPV6
|
|
4135 freeaddrinfo(ressave);
|
|
4136 #endif
|
|
4137 return SOAP_INVALID_SOCKET;
|
|
4138 }
|
|
4139 #endif
|
|
4140 #ifdef WITH_IPV6
|
|
4141 if (res->ai_next)
|
|
4142 { res = res->ai_next;
|
|
4143 soap->fclosesocket(soap, sk);
|
|
4144 goto again;
|
|
4145 }
|
|
4146 #endif
|
|
4147 if (err && err != SOAP_EINTR)
|
|
4148 { soap->errnum = err;
|
|
4149 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
|
|
4150 soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
|
|
4151 soap->fclosesocket(soap, sk);
|
|
4152 #ifdef WITH_IPV6
|
|
4153 freeaddrinfo(ressave);
|
|
4154 #endif
|
|
4155 return SOAP_INVALID_SOCKET;
|
|
4156 }
|
|
4157 }
|
|
4158 else
|
|
4159 break;
|
|
4160 }
|
|
4161 #ifdef WITH_IPV6
|
|
4162 soap->peerlen = 0; /* IPv6: already connected so use send() */
|
|
4163 freeaddrinfo(ressave);
|
|
4164 #endif
|
|
4165 soap->socket = sk;
|
|
4166 soap->imode &= ~SOAP_ENC_SSL;
|
|
4167 soap->omode &= ~SOAP_ENC_SSL;
|
|
4168 if (!soap_tag_cmp(endpoint, "https:*"))
|
|
4169 {
|
|
4170 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
|
|
4171 #ifdef WITH_OPENSSL
|
|
4172 BIO *bio;
|
|
4173 #endif
|
|
4174 int r;
|
|
4175 if (soap->proxy_host)
|
|
4176 { soap_mode m = soap->mode; /* preserve settings */
|
|
4177 soap_mode om = soap->omode; /* make sure we only parse HTTP */
|
|
4178 size_t n = soap->count; /* save the content length */
|
|
4179 const char *userid, *passwd;
|
|
4180 int status = soap->status; /* save the current status/command */
|
|
4181 short keep_alive = soap->keep_alive; /* save the KA status */
|
|
4182 soap->omode &= ~SOAP_ENC; /* mask IO and ENC */
|
|
4183 soap->omode |= SOAP_IO_BUFFER;
|
|
4184 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connecting to %s proxy server %s for destination endpoint %s\n", soap->proxy_http_version, soap->proxy_host, endpoint));
|
|
4185 #ifdef WITH_NTLM
|
|
4186 if (soap->ntlm_challenge)
|
|
4187 { if (soap_ntlm_handshake(soap, SOAP_CONNECT, endpoint, host, port))
|
|
4188 return soap->error;
|
|
4189 }
|
|
4190 #endif
|
|
4191 if (soap_begin_send(soap))
|
|
4192 { soap->fclosesocket(soap, sk);
|
|
4193 return SOAP_INVALID_SOCKET;
|
|
4194 }
|
|
4195 soap->status = SOAP_CONNECT;
|
|
4196 soap->keep_alive = 1;
|
|
4197 if ((soap->error = soap->fpost(soap, endpoint, host, port, NULL, NULL, 0))
|
|
4198 || soap_end_send_flush(soap))
|
|
4199 { soap->fclosesocket(soap, sk);
|
|
4200 return SOAP_INVALID_SOCKET;
|
|
4201 }
|
|
4202 soap->keep_alive = keep_alive;
|
|
4203 soap->omode = om;
|
|
4204 om = soap->imode;
|
|
4205 soap->imode &= ~SOAP_ENC; /* mask IO and ENC */
|
|
4206 userid = soap->userid; /* preserve */
|
|
4207 passwd = soap->passwd; /* preserve */
|
|
4208 if ((soap->error = soap->fparse(soap)))
|
|
4209 { soap->fclosesocket(soap, sk);
|
|
4210 return SOAP_INVALID_SOCKET;
|
|
4211 }
|
|
4212 soap->status = status; /* restore */
|
|
4213 soap->userid = userid; /* restore */
|
|
4214 soap->passwd = passwd; /* restore */
|
|
4215 soap->imode = om; /* restore */
|
|
4216 soap->count = n; /* restore */
|
|
4217 if (soap_begin_send(soap))
|
|
4218 { soap->fclosesocket(soap, sk);
|
|
4219 return SOAP_INVALID_SOCKET;
|
|
4220 }
|
|
4221 if (endpoint)
|
|
4222 { strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint)); /* restore */
|
|
4223 soap->endpoint[sizeof(soap->endpoint) - 1] = '\0';
|
|
4224 }
|
|
4225 soap->mode = m;
|
|
4226 }
|
|
4227 #ifdef WITH_OPENSSL
|
|
4228 soap->ssl_flags |= SOAP_SSL_CLIENT;
|
|
4229 if (!soap->ctx && (soap->error = soap->fsslauth(soap)))
|
|
4230 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL required, but no ctx set\n"));
|
|
4231 soap->fclosesocket(soap, sk);
|
|
4232 soap->error = SOAP_SSL_ERROR;
|
|
4233 return SOAP_INVALID_SOCKET;
|
|
4234 }
|
|
4235 if (!soap->ssl)
|
|
4236 { soap->ssl = SSL_new(soap->ctx);
|
|
4237 if (!soap->ssl)
|
|
4238 { soap->fclosesocket(soap, sk);
|
|
4239 soap->error = SOAP_SSL_ERROR;
|
|
4240 return SOAP_INVALID_SOCKET;
|
|
4241 }
|
|
4242 }
|
|
4243 else
|
|
4244 SSL_clear(soap->ssl);
|
|
4245 if (soap->session)
|
|
4246 { if (!strcmp(soap->session_host, host) && soap->session_port == port)
|
|
4247 SSL_set_session(soap->ssl, soap->session);
|
|
4248 SSL_SESSION_free(soap->session);
|
|
4249 soap->session = NULL;
|
|
4250 }
|
|
4251 soap->imode |= SOAP_ENC_SSL;
|
|
4252 soap->omode |= SOAP_ENC_SSL;
|
|
4253 bio = BIO_new_socket((int)sk, BIO_NOCLOSE);
|
|
4254 SSL_set_bio(soap->ssl, bio, bio);
|
|
4255 /* Connect timeout: set SSL sockets to non-blocking */
|
|
4256 retries = 0;
|
|
4257 if (soap->connect_timeout)
|
|
4258 { SOAP_SOCKNONBLOCK(sk)
|
|
4259 retries = 10*soap->connect_timeout;
|
|
4260 }
|
|
4261 else
|
|
4262 SOAP_SOCKBLOCK(sk)
|
|
4263 if (retries <= 0)
|
|
4264 retries = 100; /* timeout: 10 sec retries, 100 times 0.1 sec */
|
|
4265 /* Try connecting until success or timeout (when nonblocking) */
|
|
4266 do
|
|
4267 { if ((r = SSL_connect(soap->ssl)) <= 0)
|
|
4268 { int err = SSL_get_error(soap->ssl, r);
|
|
4269 if (err == SSL_ERROR_WANT_CONNECT || err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
|
|
4270 { register int s;
|
|
4271 if (err == SSL_ERROR_WANT_READ)
|
|
4272 s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000);
|
|
4273 else
|
|
4274 s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000);
|
|
4275 if (s < 0)
|
|
4276 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL_connect/select error in tcp_connect\n"));
|
|
4277 soap_set_sender_error(soap, soap_ssl_error(soap, r), "SSL_connect failed in tcp_connect()", SOAP_TCP_ERROR);
|
|
4278 soap->fclosesocket(soap, sk);
|
|
4279 return SOAP_INVALID_SOCKET;
|
|
4280 }
|
|
4281 if (s == 0 && retries-- <= 0)
|
|
4282 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL/TLS connect timeout\n"));
|
|
4283 soap_set_sender_error(soap, "Timeout", "SSL_connect failed in tcp_connect()", SOAP_TCP_ERROR);
|
|
4284 soap->fclosesocket(soap, sk);
|
|
4285 return SOAP_INVALID_SOCKET;
|
|
4286 }
|
|
4287 }
|
|
4288 else
|
|
4289 { soap_set_sender_error(soap, soap_ssl_error(soap, r), "SSL_connect error in tcp_connect()", SOAP_SSL_ERROR);
|
|
4290 soap->fclosesocket(soap, sk);
|
|
4291 return SOAP_INVALID_SOCKET;
|
|
4292 }
|
|
4293 }
|
|
4294 } while (!SSL_is_init_finished(soap->ssl));
|
|
4295 /* Set SSL sockets to nonblocking */
|
|
4296 SOAP_SOCKNONBLOCK(sk)
|
|
4297 /* Check server credentials when required */
|
|
4298 if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION))
|
|
4299 { int err;
|
|
4300 if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK)
|
|
4301 { soap_set_sender_error(soap, X509_verify_cert_error_string(err), "SSL/TLS certificate presented by peer cannot be verified in tcp_connect()", SOAP_SSL_ERROR);
|
|
4302 soap->fclosesocket(soap, sk);
|
|
4303 return SOAP_INVALID_SOCKET;
|
|
4304 }
|
|
4305 if (!(soap->ssl_flags & SOAP_SSL_SKIP_HOST_CHECK))
|
|
4306 { X509_NAME *subj;
|
|
4307 STACK_OF(CONF_VALUE) *val = NULL;
|
|
4308 #if (OPENSSL_VERSION_NUMBER >= 0x0090800fL)
|
|
4309 GENERAL_NAMES *names = NULL;
|
|
4310 #else
|
|
4311 int ext_count;
|
|
4312 #endif
|
|
4313 int ok = 0;
|
|
4314 X509 *peer = SSL_get_peer_certificate(soap->ssl);
|
|
4315 if (!peer)
|
|
4316 { soap_set_sender_error(soap, "SSL/TLS error", "No SSL/TLS certificate was presented by the peer in tcp_connect()", SOAP_SSL_ERROR);
|
|
4317 soap->fclosesocket(soap, sk);
|
|
4318 return SOAP_INVALID_SOCKET;
|
|
4319 }
|
|
4320 #if (OPENSSL_VERSION_NUMBER < 0x0090800fL)
|
|
4321 ext_count = X509_get_ext_count(peer);
|
|
4322 if (ext_count > 0)
|
|
4323 { int i;
|
|
4324 for (i = 0; i < ext_count; i++)
|
|
4325 { X509_EXTENSION *ext = X509_get_ext(peer, i);
|
|
4326 const char *ext_str = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));
|
|
4327 if (ext_str && !strcmp(ext_str, "subjectAltName"))
|
|
4328 { X509V3_EXT_METHOD *meth = (X509V3_EXT_METHOD*)X509V3_EXT_get(ext);
|
|
4329 unsigned char *data;
|
|
4330 if (!meth)
|
|
4331 break;
|
|
4332 data = ext->value->data;
|
|
4333 if (data)
|
|
4334 {
|
|
4335 #if (OPENSSL_VERSION_NUMBER > 0x00907000L)
|
|
4336 void *ext_data;
|
|
4337 if (meth->it)
|
|
4338 ext_data = ASN1_item_d2i(NULL, &data, ext->value->length, ASN1_ITEM_ptr(meth->it));
|
|
4339 else
|
|
4340 { /* OpenSSL is not portable at this point (?):
|
|
4341 Some compilers appear to prefer
|
|
4342 meth->d2i(NULL, (const unsigned char**)&data, ...
|
|
4343 and others prefer
|
|
4344 meth->d2i(NULL, &data, ext->value->length);
|
|
4345 */
|
|
4346 ext_data = meth->d2i(NULL, &data, ext->value->length);
|
|
4347 }
|
|
4348 if (ext_data)
|
|
4349 val = meth->i2v(meth, ext_data, NULL);
|
|
4350 else
|
|
4351 val = NULL;
|
|
4352 if (meth->it)
|
|
4353 ASN1_item_free((ASN1_VALUE*)ext_data, ASN1_ITEM_ptr(meth->it));
|
|
4354 else
|
|
4355 meth->ext_free(ext_data);
|
|
4356 #else
|
|
4357 void *ext_data = meth->d2i(NULL, &data, ext->value->length);
|
|
4358 if (ext_data)
|
|
4359 val = meth->i2v(meth, ext_data, NULL);
|
|
4360 meth->ext_free(ext_data);
|
|
4361 #endif
|
|
4362 if (val)
|
|
4363 { int j;
|
|
4364 for (j = 0; j < sk_CONF_VALUE_num(val); j++)
|
|
4365 { CONF_VALUE *nval = sk_CONF_VALUE_value(val, j);
|
|
4366 if (nval && !strcmp(nval->name, "DNS") && !strcmp(nval->value, host))
|
|
4367 { ok = 1;
|
|
4368 break;
|
|
4369 }
|
|
4370 }
|
|
4371 sk_CONF_VALUE_pop_free(val, X509V3_conf_free);
|
|
4372 }
|
|
4373 }
|
|
4374 }
|
|
4375 if (ok)
|
|
4376 break;
|
|
4377 }
|
|
4378 }
|
|
4379 #else
|
|
4380 names = (GENERAL_NAMES*)X509_get_ext_d2i(peer, NID_subject_alt_name, NULL, NULL);
|
|
4381 if (names)
|
|
4382 { val = i2v_GENERAL_NAMES(NULL, names, val);
|
|
4383 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
|
|
4384 }
|
|
4385 if (val)
|
|
4386 { int j;
|
|
4387 for (j = 0; j < sk_CONF_VALUE_num(val); j++)
|
|
4388 { CONF_VALUE *nval = sk_CONF_VALUE_value(val, j);
|
|
4389 if (nval && !strcmp(nval->name, "DNS") && !strcmp(nval->value, host))
|
|
4390 { ok = 1;
|
|
4391 break;
|
|
4392 }
|
|
4393 }
|
|
4394 sk_CONF_VALUE_pop_free(val, X509V3_conf_free);
|
|
4395 }
|
|
4396 #endif
|
|
4397 if (!ok && (subj = X509_get_subject_name(peer)))
|
|
4398 { int i = -1;
|
|
4399 do
|
|
4400 { ASN1_STRING *name;
|
|
4401 i = X509_NAME_get_index_by_NID(subj, NID_commonName, i);
|
|
4402 if (i == -1)
|
|
4403 break;
|
|
4404 name = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subj, i));
|
|
4405 if (name)
|
|
4406 { if (!soap_tag_cmp(host, (const char*)M_ASN1_STRING_data(name)))
|
|
4407 ok = 1;
|
|
4408 else
|
|
4409 { unsigned char *tmp = NULL;
|
|
4410 ASN1_STRING_to_UTF8(&tmp, name);
|
|
4411 if (tmp)
|
|
4412 { if (!soap_tag_cmp(host, (const char*)tmp))
|
|
4413 ok = 1;
|
|
4414 else if (tmp[0] == '*') /* wildcard domain */
|
|
4415 { const char *t = strchr(host, '.');
|
|
4416 if (t && !soap_tag_cmp(t, (const char*)tmp+1))
|
|
4417 ok = 1;
|
|
4418 }
|
|
4419 OPENSSL_free(tmp);
|
|
4420 }
|
|
4421 }
|
|
4422 }
|
|
4423 } while (!ok);
|
|
4424 }
|
|
4425 X509_free(peer);
|
|
4426 if (!ok)
|
|
4427 { soap_set_sender_error(soap, "SSL/TLS error", "SSL/TLS certificate host name mismatch in tcp_connect()", SOAP_SSL_ERROR);
|
|
4428 soap->fclosesocket(soap, sk);
|
|
4429 return SOAP_INVALID_SOCKET;
|
|
4430 }
|
|
4431 }
|
|
4432 }
|
|
4433 #endif
|
|
4434 #ifdef WITH_GNUTLS
|
|
4435 soap->ssl_flags |= SOAP_SSL_CLIENT;
|
|
4436 if (!soap->session && (soap->error = soap->fsslauth(soap)))
|
|
4437 { soap->fclosesocket(soap, sk);
|
|
4438 return SOAP_INVALID_SOCKET;
|
|
4439 }
|
|
4440 gnutls_transport_set_ptr(soap->session, (gnutls_transport_ptr_t)(long)sk);
|
|
4441 /* Set SSL sockets to non-blocking */
|
|
4442 if (soap->connect_timeout)
|
|
4443 { SOAP_SOCKNONBLOCK(sk)
|
|
4444 retries = 10*soap->connect_timeout;
|
|
4445 }
|
|
4446 else
|
|
4447 SOAP_SOCKBLOCK(sk)
|
|
4448 if (retries <= 0)
|
|
4449 retries = 100; /* timeout: 10 sec retries, 100 times 0.1 sec */
|
|
4450 while ((r = gnutls_handshake(soap->session)))
|
|
4451 { int s;
|
|
4452 /* GNUTLS repeat handhake when GNUTLS_E_AGAIN */
|
|
4453 if (retries-- <= 0)
|
|
4454 break;
|
|
4455 if (r == GNUTLS_E_AGAIN || r == GNUTLS_E_INTERRUPTED)
|
|
4456 { if (!gnutls_record_get_direction(soap->session))
|
|
4457 s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000);
|
|
4458 else
|
|
4459 s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000);
|
|
4460 if (s < 0)
|
|
4461 break;
|
|
4462 }
|
|
4463 else
|
|
4464 { soap->errnum = soap_socket_errno(sk);
|
|
4465 break;
|
|
4466 }
|
|
4467 }
|
|
4468 if (r)
|
|
4469 { soap_set_sender_error(soap, soap_ssl_error(soap, r), "SSL/TLS handshake failed", SOAP_SSL_ERROR);
|
|
4470 soap->fclosesocket(soap, sk);
|
|
4471 return SOAP_INVALID_SOCKET;
|
|
4472 }
|
|
4473 if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION))
|
|
4474 { const char *err = ssl_verify(soap, host);
|
|
4475 if (err)
|
|
4476 { soap->fclosesocket(soap, sk);
|
|
4477 soap->error = soap_set_sender_error(soap, "SSL/TLS error", err, SOAP_SSL_ERROR);
|
|
4478 return SOAP_INVALID_SOCKET;
|
|
4479 }
|
|
4480 }
|
|
4481 #endif
|
|
4482 #else
|
|
4483 soap->fclosesocket(soap, sk);
|
|
4484 soap->error = SOAP_SSL_ERROR;
|
|
4485 return SOAP_INVALID_SOCKET;
|
|
4486 #endif
|
|
4487 }
|
|
4488 if (soap->recv_timeout || soap->send_timeout)
|
|
4489 SOAP_SOCKNONBLOCK(sk)
|
|
4490 else
|
|
4491 SOAP_SOCKBLOCK(sk)
|
|
4492 return sk;
|
|
4493 }
|
|
4494 #endif
|
|
4495 #endif
|
|
4496
|
|
4497 /******************************************************************************/
|
|
4498 #ifndef WITH_NOIO
|
|
4499 #ifndef PALM_1
|
|
4500 static int
|
|
4501 tcp_select(struct soap *soap, SOAP_SOCKET sk, int flags, int timeout)
|
|
4502 { int r;
|
|
4503 struct timeval tv;
|
|
4504 fd_set fd[3], *rfd, *sfd, *efd;
|
|
4505 int retries = 0;
|
|
4506 int eintr = SOAP_MAXEINTR;
|
|
4507 soap->errnum = 0;
|
|
4508 #ifndef WIN32
|
|
4509 #if !defined(FD_SETSIZE) || defined(__QNX__) || defined(QNX)
|
|
4510 /* no FD_SETSIZE or select() is not MT safe on some QNX: always poll */
|
|
4511 if (1)
|
|
4512 #else
|
|
4513 /* if fd max set size exceeded, use poll() */
|
|
4514 if ((int)sk >= (int)FD_SETSIZE)
|
|
4515 #endif
|
|
4516 #ifdef HAVE_POLL
|
|
4517 { struct pollfd pollfd;
|
|
4518 pollfd.fd = (int)sk;
|
|
4519 pollfd.events = 0;
|
|
4520 if (flags & SOAP_TCP_SELECT_RCV)
|
|
4521 pollfd.events |= POLLIN;
|
|
4522 if (flags & SOAP_TCP_SELECT_SND)
|
|
4523 pollfd.events |= POLLOUT;
|
|
4524 if (flags & SOAP_TCP_SELECT_ERR)
|
|
4525 pollfd.events |= POLLERR;
|
|
4526 if (timeout <= 0)
|
|
4527 timeout /= -1000; /* -usec -> ms */
|
|
4528 else
|
|
4529 { retries = timeout - 1;
|
|
4530 timeout = 1000;
|
|
4531 }
|
|
4532 do
|
|
4533 { r = poll(&pollfd, 1, timeout);
|
|
4534 if (r < 0 && (soap->errnum = soap_socket_errno(sk)) == SOAP_EINTR && eintr--)
|
|
4535 continue;
|
|
4536 } while (r == 0 && retries--);
|
|
4537 if (r > 0)
|
|
4538 { r = 0;
|
|
4539 if ((flags & SOAP_TCP_SELECT_RCV) && (pollfd.revents & POLLIN))
|
|
4540 r |= SOAP_TCP_SELECT_RCV;
|
|
4541 if ((flags & SOAP_TCP_SELECT_SND) && (pollfd.revents & POLLOUT))
|
|
4542 r |= SOAP_TCP_SELECT_SND;
|
|
4543 if ((flags & SOAP_TCP_SELECT_ERR) && (pollfd.revents & POLLERR))
|
|
4544 r |= SOAP_TCP_SELECT_ERR;
|
|
4545 }
|
|
4546 return r;
|
|
4547 }
|
|
4548 #else
|
|
4549 { soap->error = SOAP_FD_EXCEEDED;
|
|
4550 return -1;
|
|
4551 }
|
|
4552 #endif
|
|
4553 #endif
|
|
4554 if (timeout > 0)
|
|
4555 retries = timeout - 1;
|
|
4556 do
|
|
4557 { rfd = sfd = efd = NULL;
|
|
4558 if (flags & SOAP_TCP_SELECT_RCV)
|
|
4559 { rfd = &fd[0];
|
|
4560 FD_ZERO(rfd);
|
|
4561 FD_SET(sk, rfd);
|
|
4562 }
|
|
4563 if (flags & SOAP_TCP_SELECT_SND)
|
|
4564 { sfd = &fd[1];
|
|
4565 FD_ZERO(sfd);
|
|
4566 FD_SET(sk, sfd);
|
|
4567 }
|
|
4568 if (flags & SOAP_TCP_SELECT_ERR)
|
|
4569 { efd = &fd[2];
|
|
4570 FD_ZERO(efd);
|
|
4571 FD_SET(sk, efd);
|
|
4572 }
|
|
4573 if (timeout <= 0)
|
|
4574 { tv.tv_sec = -timeout / 1000000;
|
|
4575 tv.tv_usec = -timeout % 1000000;
|
|
4576 }
|
|
4577 else
|
|
4578 { tv.tv_sec = 1;
|
|
4579 tv.tv_usec = 0;
|
|
4580 }
|
|
4581 r = select((int)sk + 1, rfd, sfd, efd, &tv);
|
|
4582 if (r < 0 && (soap->errnum = soap_socket_errno(sk)) == SOAP_EINTR && eintr--)
|
|
4583 continue;
|
|
4584 } while (r == 0 && retries--);
|
|
4585 if (r > 0)
|
|
4586 { r = 0;
|
|
4587 if ((flags & SOAP_TCP_SELECT_RCV) && FD_ISSET(sk, rfd))
|
|
4588 r |= SOAP_TCP_SELECT_RCV;
|
|
4589 if ((flags & SOAP_TCP_SELECT_SND) && FD_ISSET(sk, sfd))
|
|
4590 r |= SOAP_TCP_SELECT_SND;
|
|
4591 if ((flags & SOAP_TCP_SELECT_ERR) && FD_ISSET(sk, efd))
|
|
4592 r |= SOAP_TCP_SELECT_ERR;
|
|
4593 }
|
|
4594 return r;
|
|
4595 }
|
|
4596 #endif
|
|
4597 #endif
|
|
4598
|
|
4599 /******************************************************************************/
|
|
4600 #ifndef WITH_NOIO
|
|
4601 #ifndef PALM_1
|
|
4602 static SOAP_SOCKET
|
|
4603 tcp_accept(struct soap *soap, SOAP_SOCKET s, struct sockaddr *a, int *n)
|
|
4604 { SOAP_SOCKET sk;
|
|
4605 (void)soap;
|
|
4606 sk = accept(s, a, (SOAP_SOCKLEN_T*)n); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
|
|
4607 #ifdef SOCKET_CLOSE_ON_EXEC
|
|
4608 #ifdef WIN32
|
|
4609 #ifndef UNDER_CE
|
|
4610 SetHandleInformation((HANDLE)sk, HANDLE_FLAG_INHERIT, 0);
|
|
4611 #endif
|
|
4612 #else
|
|
4613 fcntl(sk, F_SETFD, FD_CLOEXEC);
|
|
4614 #endif
|
|
4615 #endif
|
|
4616 return sk;
|
|
4617 }
|
|
4618 #endif
|
|
4619 #endif
|
|
4620
|
|
4621 /******************************************************************************/
|
|
4622 #ifndef WITH_NOIO
|
|
4623 #ifndef PALM_1
|
|
4624 static int
|
|
4625 tcp_disconnect(struct soap *soap)
|
|
4626 {
|
|
4627 #ifdef WITH_OPENSSL
|
|
4628 if (soap->ssl)
|
|
4629 { int r, s = 0;
|
|
4630 if (soap->session)
|
|
4631 { SSL_SESSION_free(soap->session);
|
|
4632 soap->session = NULL;
|
|
4633 }
|
|
4634 if (*soap->host)
|
|
4635 { soap->session = SSL_get1_session(soap->ssl);
|
|
4636 if (soap->session)
|
|
4637 { strcpy(soap->session_host, soap->host);
|
|
4638 soap->session_port = soap->port;
|
|
4639 }
|
|
4640 }
|
|
4641 r = SSL_shutdown(soap->ssl);
|
|
4642 /* SSL shutdown does not work when reads are pending, non-blocking */
|
|
4643 if (r == 0)
|
|
4644 { while (SSL_want_read(soap->ssl))
|
|
4645 { if (SSL_read(soap->ssl, NULL, 0)
|
|
4646 || soap_socket_errno(soap->socket) != SOAP_EAGAIN)
|
|
4647 { r = SSL_shutdown(soap->ssl);
|
|
4648 break;
|
|
4649 }
|
|
4650 }
|
|
4651 }
|
|
4652 if (r == 0)
|
|
4653 { if (soap_valid_socket(soap->socket))
|
|
4654 { if (!soap->fshutdownsocket(soap, soap->socket, SOAP_SHUT_WR))
|
|
4655 {
|
|
4656 #if !defined(WITH_LEAN) && !defined(WIN32)
|
|
4657 /*
|
|
4658 wait up to 5 seconds for close_notify to be sent by peer (if peer not
|
|
4659 present, this avoids calling SSL_shutdown() which has a lengthy return
|
|
4660 timeout)
|
|
4661 */
|
|
4662 r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, 5);
|
|
4663 if (r <= 0)
|
|
4664 { soap->errnum = 0;
|
|
4665 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connection lost...\n"));
|
|
4666 soap->fclosesocket(soap, soap->socket);
|
|
4667 soap->socket = SOAP_INVALID_SOCKET;
|
|
4668 ERR_remove_state(0);
|
|
4669 SSL_free(soap->ssl);
|
|
4670 soap->ssl = NULL;
|
|
4671 return SOAP_OK;
|
|
4672 }
|
|
4673 #else
|
|
4674 r = SSL_shutdown(soap->ssl);
|
|
4675 #endif
|
|
4676 }
|
|
4677 }
|
|
4678 }
|
|
4679 if (r != 1)
|
|
4680 { s = ERR_get_error();
|
|
4681 if (s)
|
|
4682 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown failed: %d\n", SSL_get_error(soap->ssl, r)));
|
|
4683 if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP))
|
|
4684 { soap->fclosesocket(soap, soap->socket);
|
|
4685 soap->socket = SOAP_INVALID_SOCKET;
|
|
4686 }
|
|
4687 }
|
|
4688 }
|
|
4689 SSL_free(soap->ssl);
|
|
4690 soap->ssl = NULL;
|
|
4691 if (s)
|
|
4692 return SOAP_SSL_ERROR;
|
|
4693 ERR_remove_state(0);
|
|
4694 }
|
|
4695 #endif
|
|
4696 #ifdef WITH_GNUTLS
|
|
4697 if (soap->session)
|
|
4698 { gnutls_bye(soap->session, GNUTLS_SHUT_RDWR);
|
|
4699 gnutls_deinit(soap->session);
|
|
4700 soap->session = NULL;
|
|
4701 }
|
|
4702 #endif
|
|
4703 if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP))
|
|
4704 { soap->fshutdownsocket(soap, soap->socket, SOAP_SHUT_RDWR);
|
|
4705 soap->fclosesocket(soap, soap->socket);
|
|
4706 soap->socket = SOAP_INVALID_SOCKET;
|
|
4707 }
|
|
4708 return SOAP_OK;
|
|
4709 }
|
|
4710 #endif
|
|
4711 #endif
|
|
4712
|
|
4713 /******************************************************************************/
|
|
4714 #ifndef WITH_NOIO
|
|
4715 #ifndef PALM_1
|
|
4716 static int
|
|
4717 tcp_closesocket(struct soap *soap, SOAP_SOCKET sk)
|
|
4718 { (void)soap;
|
|
4719 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Close socket=%d\n", (int)sk));
|
|
4720 return soap_closesocket(sk);
|
|
4721 }
|
|
4722 #endif
|
|
4723 #endif
|
|
4724
|
|
4725 /******************************************************************************/
|
|
4726 #ifndef WITH_NOIO
|
|
4727 #ifndef PALM_1
|
|
4728 static int
|
|
4729 tcp_shutdownsocket(struct soap *soap, SOAP_SOCKET sk, int how)
|
|
4730 { (void)soap;
|
|
4731 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown socket=%d how=%d\n", (int)sk, how));
|
|
4732 return shutdown(sk, how);
|
|
4733 }
|
|
4734 #endif
|
|
4735 #endif
|
|
4736
|
|
4737 /******************************************************************************/
|
|
4738 #ifndef WITH_NOIO
|
|
4739 #ifndef PALM_1
|
|
4740 SOAP_FMAC1
|
|
4741 SOAP_SOCKET
|
|
4742 SOAP_FMAC2
|
|
4743 soap_bind(struct soap *soap, const char *host, int port, int backlog)
|
|
4744 {
|
|
4745 #ifdef WITH_IPV6
|
|
4746 struct addrinfo *addrinfo = NULL;
|
|
4747 struct addrinfo hints;
|
|
4748 struct addrinfo res;
|
|
4749 int err;
|
|
4750 #ifdef WITH_NO_IPV6_V6ONLY
|
|
4751 int unset = 0;
|
|
4752 #endif
|
|
4753 #endif
|
|
4754 #ifndef WITH_LEAN
|
|
4755 #ifndef WIN32
|
|
4756 int len = SOAP_BUFLEN;
|
|
4757 #else
|
|
4758 int len = SOAP_BUFLEN + 1; /* speeds up windows xfer */
|
|
4759 #endif
|
|
4760 int set = 1;
|
|
4761 #endif
|
|
4762 if (soap_valid_socket(soap->master))
|
|
4763 { soap->fclosesocket(soap, soap->master);
|
|
4764 soap->master = SOAP_INVALID_SOCKET;
|
|
4765 }
|
|
4766 soap->socket = SOAP_INVALID_SOCKET;
|
|
4767 soap->errmode = 1;
|
|
4768 if (tcp_init(soap))
|
|
4769 { soap_set_receiver_error(soap, tcp_error(soap), "TCP init failed in soap_bind()", SOAP_TCP_ERROR);
|
|
4770 return SOAP_INVALID_SOCKET;
|
|
4771 }
|
|
4772 #ifdef WITH_IPV6
|
|
4773 memset((void*)&hints, 0, sizeof(hints));
|
|
4774 hints.ai_family = PF_UNSPEC;
|
|
4775 #ifndef WITH_LEAN
|
|
4776 if ((soap->omode & SOAP_IO_UDP))
|
|
4777 hints.ai_socktype = SOCK_DGRAM;
|
|
4778 else
|
|
4779 #endif
|
|
4780 hints.ai_socktype = SOCK_STREAM;
|
|
4781 hints.ai_flags = AI_PASSIVE;
|
|
4782 soap->errmode = 2;
|
|
4783 err = getaddrinfo(host, soap_int2s(soap, port), &hints, &addrinfo);
|
|
4784 if (err || !addrinfo)
|
|
4785 { soap_set_receiver_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in soap_bind()", SOAP_TCP_ERROR);
|
|
4786 return SOAP_INVALID_SOCKET;
|
|
4787 }
|
|
4788 res = *addrinfo;
|
|
4789 memcpy(&soap->peer, addrinfo->ai_addr, addrinfo->ai_addrlen);
|
|
4790 soap->peerlen = addrinfo->ai_addrlen;
|
|
4791 res.ai_addr = (struct sockaddr*)&soap->peer;
|
|
4792 res.ai_addrlen = soap->peerlen;
|
|
4793 freeaddrinfo(addrinfo);
|
|
4794 soap->master = (int)socket(res.ai_family, res.ai_socktype, res.ai_protocol);
|
|
4795 #else
|
|
4796 #ifndef WITH_LEAN
|
|
4797 if ((soap->omode & SOAP_IO_UDP))
|
|
4798 soap->master = (int)socket(AF_INET, SOCK_DGRAM, 0);
|
|
4799 else
|
|
4800 #endif
|
|
4801 soap->master = (int)socket(AF_INET, SOCK_STREAM, 0);
|
|
4802 #endif
|
|
4803 soap->errmode = 0;
|
|
4804 if (!soap_valid_socket(soap->master))
|
|
4805 { soap->errnum = soap_socket_errno(soap->master);
|
|
4806 soap_set_receiver_error(soap, tcp_error(soap), "socket failed in soap_bind()", SOAP_TCP_ERROR);
|
|
4807 return SOAP_INVALID_SOCKET;
|
|
4808 }
|
|
4809 soap->port = port;
|
|
4810 #ifndef WITH_LEAN
|
|
4811 if ((soap->omode & SOAP_IO_UDP))
|
|
4812 soap->socket = soap->master;
|
|
4813 #endif
|
|
4814 #ifdef SOCKET_CLOSE_ON_EXEC
|
|
4815 #ifdef WIN32
|
|
4816 #ifndef UNDER_CE
|
|
4817 SetHandleInformation((HANDLE)soap->master, HANDLE_FLAG_INHERIT, 0);
|
|
4818 #endif
|
|
4819 #else
|
|
4820 fcntl(soap->master, F_SETFD, 1);
|
|
4821 #endif
|
|
4822 #endif
|
|
4823 #ifndef WITH_LEAN
|
|
4824 if (soap->bind_flags && setsockopt(soap->master, SOL_SOCKET, soap->bind_flags, (char*)&set, sizeof(int)))
|
|
4825 { soap->errnum = soap_socket_errno(soap->master);
|
|
4826 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_bind()", SOAP_TCP_ERROR);
|
|
4827 return SOAP_INVALID_SOCKET;
|
|
4828 }
|
|
4829 if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && (!((soap->imode | soap->omode) & SOAP_IO_UDP)) && setsockopt(soap->master, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
|
|
4830 { soap->errnum = soap_socket_errno(soap->master);
|
|
4831 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_bind()", SOAP_TCP_ERROR);
|
|
4832 return SOAP_INVALID_SOCKET;
|
|
4833 }
|
|
4834 if (setsockopt(soap->master, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
|
|
4835 { soap->errnum = soap_socket_errno(soap->master);
|
|
4836 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_bind()", SOAP_TCP_ERROR);
|
|
4837 return SOAP_INVALID_SOCKET;
|
|
4838 }
|
|
4839 if (setsockopt(soap->master, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
|
|
4840 { soap->errnum = soap_socket_errno(soap->master);
|
|
4841 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_bind()", SOAP_TCP_ERROR);
|
|
4842 return SOAP_INVALID_SOCKET;
|
|
4843 }
|
|
4844 #ifdef TCP_NODELAY
|
|
4845 if (!(soap->omode & SOAP_IO_UDP) && setsockopt(soap->master, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
|
|
4846 { soap->errnum = soap_socket_errno(soap->master);
|
|
4847 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_bind()", SOAP_TCP_ERROR);
|
|
4848 return SOAP_INVALID_SOCKET;
|
|
4849 }
|
|
4850 #endif
|
|
4851 #endif
|
|
4852 #ifdef WITH_IPV6
|
|
4853 #ifdef WITH_IPV6_V6ONLY
|
|
4854 if (setsockopt(soap->master, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&set, sizeof(int)))
|
|
4855 { soap->errnum = soap_socket_errno(soap->master);
|
|
4856 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt set IPV6_V6ONLY failed in soap_bind()", SOAP_TCP_ERROR);
|
|
4857 return SOAP_INVALID_SOCKET;
|
|
4858 }
|
|
4859 #endif
|
|
4860 #ifdef WITH_NO_IPV6_V6ONLY
|
|
4861 if (setsockopt(soap->master, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&unset, sizeof(int)))
|
|
4862 { soap->errnum = soap_socket_errno(soap->master);
|
|
4863 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt unset IPV6_V6ONLY failed in soap_bind()", SOAP_TCP_ERROR);
|
|
4864 return SOAP_INVALID_SOCKET;
|
|
4865 }
|
|
4866 #endif
|
|
4867 soap->errmode = 0;
|
|
4868 if (bind(soap->master, res.ai_addr, (int)res.ai_addrlen))
|
|
4869 { soap->errnum = soap_socket_errno(soap->master);
|
|
4870 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
|
|
4871 soap_closesock(soap);
|
|
4872 soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR);
|
|
4873 return SOAP_INVALID_SOCKET;
|
|
4874 }
|
|
4875 #else
|
|
4876 soap->peerlen = sizeof(soap->peer);
|
|
4877 memset((void*)&soap->peer, 0, sizeof(soap->peer));
|
|
4878 soap->peer.sin_family = AF_INET;
|
|
4879 soap->errmode = 2;
|
|
4880 if (host)
|
|
4881 { if (soap->fresolve(soap, host, &soap->peer.sin_addr))
|
|
4882 { soap_set_receiver_error(soap, tcp_error(soap), "get host by name failed in soap_bind()", SOAP_TCP_ERROR);
|
|
4883 return SOAP_INVALID_SOCKET;
|
|
4884 }
|
|
4885 }
|
|
4886 else
|
|
4887 soap->peer.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
4888 soap->peer.sin_port = htons((short)port);
|
|
4889 soap->errmode = 0;
|
|
4890 if (bind(soap->master, (struct sockaddr*)&soap->peer, (int)soap->peerlen))
|
|
4891 { soap->errnum = soap_socket_errno(soap->master);
|
|
4892 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
|
|
4893 soap_closesock(soap);
|
|
4894 soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR);
|
|
4895 return SOAP_INVALID_SOCKET;
|
|
4896 }
|
|
4897 #endif
|
|
4898 if (!(soap->omode & SOAP_IO_UDP) && listen(soap->master, backlog))
|
|
4899 { soap->errnum = soap_socket_errno(soap->master);
|
|
4900 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
|
|
4901 soap_closesock(soap);
|
|
4902 soap_set_receiver_error(soap, tcp_error(soap), "listen failed in soap_bind()", SOAP_TCP_ERROR);
|
|
4903 return SOAP_INVALID_SOCKET;
|
|
4904 }
|
|
4905 return soap->master;
|
|
4906 }
|
|
4907 #endif
|
|
4908 #endif
|
|
4909
|
|
4910 /******************************************************************************/
|
|
4911 #ifndef WITH_NOIO
|
|
4912 #ifndef PALM_1
|
|
4913 SOAP_FMAC1
|
|
4914 int
|
|
4915 SOAP_FMAC2
|
|
4916 soap_poll(struct soap *soap)
|
|
4917 {
|
|
4918 #ifndef WITH_LEAN
|
|
4919 register int r;
|
|
4920 if (soap_valid_socket(soap->socket))
|
|
4921 { r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_ALL, 0);
|
|
4922 if (r > 0 && (r & SOAP_TCP_SELECT_ERR))
|
|
4923 r = -1;
|
|
4924 }
|
|
4925 else if (soap_valid_socket(soap->master))
|
|
4926 r = tcp_select(soap, soap->master, SOAP_TCP_SELECT_SND, 0);
|
|
4927 else
|
|
4928 return SOAP_OK; /* OK when no socket! */
|
|
4929 if (r > 0)
|
|
4930 {
|
|
4931 #ifdef WITH_OPENSSL
|
|
4932 if (soap->imode & SOAP_ENC_SSL)
|
|
4933 {
|
|
4934 if (soap_valid_socket(soap->socket)
|
|
4935 && (r & SOAP_TCP_SELECT_SND)
|
|
4936 && (!(r & SOAP_TCP_SELECT_RCV)
|
|
4937 || SSL_peek(soap->ssl, soap->tmpbuf, 1) > 0))
|
|
4938 return SOAP_OK;
|
|
4939 }
|
|
4940 else
|
|
4941 #endif
|
|
4942 { int t;
|
|
4943 if (soap_valid_socket(soap->socket)
|
|
4944 && (r & SOAP_TCP_SELECT_SND)
|
|
4945 && (!(r & SOAP_TCP_SELECT_RCV)
|
|
4946 || recv(soap->socket, (char*)&t, 1, MSG_PEEK) > 0))
|
|
4947 return SOAP_OK;
|
|
4948 }
|
|
4949 }
|
|
4950 else if (r < 0)
|
|
4951 { if ((soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) && soap_socket_errno(soap->master) != SOAP_EINTR)
|
|
4952 { soap_set_receiver_error(soap, tcp_error(soap), "select failed in soap_poll()", SOAP_TCP_ERROR);
|
|
4953 return soap->error = SOAP_TCP_ERROR;
|
|
4954 }
|
|
4955 }
|
|
4956 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Polling: other end down on socket=%d select=%d\n", soap->socket, r));
|
|
4957 return SOAP_EOF;
|
|
4958 #else
|
|
4959 return SOAP_OK;
|
|
4960 #endif
|
|
4961 }
|
|
4962 #endif
|
|
4963 #endif
|
|
4964
|
|
4965 /******************************************************************************/
|
|
4966 #ifndef WITH_NOIO
|
|
4967 #ifndef PALM_1
|
|
4968 SOAP_FMAC1
|
|
4969 SOAP_SOCKET
|
|
4970 SOAP_FMAC2
|
|
4971 soap_accept(struct soap *soap)
|
|
4972 { int n = (int)sizeof(soap->peer);
|
|
4973 register int err;
|
|
4974 #ifndef WITH_LEAN
|
|
4975 #ifndef WIN32
|
|
4976 int len = SOAP_BUFLEN;
|
|
4977 #else
|
|
4978 int len = SOAP_BUFLEN + 1; /* speeds up windows xfer */
|
|
4979 #endif
|
|
4980 int set = 1;
|
|
4981 #endif
|
|
4982 soap->error = SOAP_OK;
|
|
4983 memset((void*)&soap->peer, 0, sizeof(soap->peer));
|
|
4984 soap->socket = SOAP_INVALID_SOCKET;
|
|
4985 soap->errmode = 0;
|
|
4986 soap->keep_alive = 0;
|
|
4987 if (!soap_valid_socket(soap->master))
|
|
4988 { soap->errnum = 0;
|
|
4989 soap_set_receiver_error(soap, tcp_error(soap), "no master socket in soap_accept()", SOAP_TCP_ERROR);
|
|
4990 return SOAP_INVALID_SOCKET;
|
|
4991 }
|
|
4992 #ifndef WITH_LEAN
|
|
4993 if ((soap->omode & SOAP_IO_UDP))
|
|
4994 return soap->socket = soap->master;
|
|
4995 #endif
|
|
4996 for (;;)
|
|
4997 { if (soap->accept_timeout || soap->send_timeout || soap->recv_timeout)
|
|
4998 { for (;;)
|
|
4999 { register int r;
|
|
5000 r = tcp_select(soap, soap->master, SOAP_TCP_SELECT_ALL, soap->accept_timeout ? soap->accept_timeout : 60);
|
|
5001 if (r > 0)
|
|
5002 break;
|
|
5003 if (!r && soap->accept_timeout)
|
|
5004 { soap_set_receiver_error(soap, "Timeout", "accept failed in soap_accept()", SOAP_TCP_ERROR);
|
|
5005 return SOAP_INVALID_SOCKET;
|
|
5006 }
|
|
5007 if (r < 0)
|
|
5008 { r = soap->errnum;
|
|
5009 if (r != SOAP_EINTR)
|
|
5010 { soap_closesock(soap);
|
|
5011 soap_set_sender_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR);
|
|
5012 return SOAP_INVALID_SOCKET;
|
|
5013 }
|
|
5014 }
|
|
5015 }
|
|
5016 }
|
|
5017 if (soap->accept_timeout)
|
|
5018 SOAP_SOCKNONBLOCK(soap->master)
|
|
5019 else
|
|
5020 SOAP_SOCKBLOCK(soap->master)
|
|
5021 soap->socket = soap->faccept(soap, soap->master, (struct sockaddr*)&soap->peer, &n);
|
|
5022 soap->peerlen = (size_t)n;
|
|
5023 if (soap_valid_socket(soap->socket))
|
|
5024 {
|
|
5025 #ifdef WITH_IPV6
|
|
5026 unsigned int ip1, ip2, ip3, ip4;
|
|
5027 char port[16];
|
|
5028 getnameinfo((struct sockaddr*)&soap->peer, n, soap->host, sizeof(soap->host), port, 16, NI_NUMERICHOST | NI_NUMERICSERV);
|
|
5029 sscanf(soap->host, "%u.%u.%u.%u", &ip1, &ip2, &ip3, &ip4);
|
|
5030 soap->ip = (unsigned long)ip1 << 24 | (unsigned long)ip2 << 16 | (unsigned long)ip3 << 8 | (unsigned long)ip4;
|
|
5031 soap->port = soap_strtol(port, NULL, 10);
|
|
5032 #else
|
|
5033 soap->ip = ntohl(soap->peer.sin_addr.s_addr);
|
|
5034 #ifdef HAVE_SNPRINTF
|
|
5035 soap_snprintf(soap->host, sizeof(soap->host), "%u.%u.%u.%u", (int)(soap->ip>>24)&0xFF, (int)(soap->ip>>16)&0xFF, (int)(soap->ip>>8)&0xFF, (int)soap->ip&0xFF);
|
|
5036 #else
|
|
5037 sprintf(soap->host, "%u.%u.%u.%u", (int)(soap->ip>>24)&0xFF, (int)(soap->ip>>16)&0xFF, (int)(soap->ip>>8)&0xFF, (int)soap->ip&0xFF);
|
|
5038 #endif
|
|
5039 soap->port = (int)ntohs(soap->peer.sin_port); /* does not return port number on some systems */
|
|
5040 #endif
|
|
5041 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket=%d at port=%d from IP='%s'\n", soap->socket, soap->port, soap->host));
|
|
5042 #ifndef WITH_LEAN
|
|
5043 if (soap->accept_flags == SO_LINGER)
|
|
5044 { struct linger linger;
|
|
5045 memset((void*)&linger, 0, sizeof(linger));
|
|
5046 linger.l_onoff = 1;
|
|
5047 linger.l_linger = soap->linger_time;
|
|
5048 if (setsockopt(soap->socket, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger)))
|
|
5049 { soap->errnum = soap_socket_errno(soap->socket);
|
|
5050 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in soap_accept()", SOAP_TCP_ERROR);
|
|
5051 soap_closesock(soap);
|
|
5052 return SOAP_INVALID_SOCKET;
|
|
5053 }
|
|
5054 }
|
|
5055 else if (soap->accept_flags && setsockopt(soap->socket, SOL_SOCKET, soap->accept_flags, (char*)&set, sizeof(int)))
|
|
5056 { soap->errnum = soap_socket_errno(soap->socket);
|
|
5057 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_accept()", SOAP_TCP_ERROR);
|
|
5058 soap_closesock(soap);
|
|
5059 return SOAP_INVALID_SOCKET;
|
|
5060 }
|
|
5061 if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt(soap->socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
|
|
5062 { soap->errnum = soap_socket_errno(soap->socket);
|
|
5063 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_accept()", SOAP_TCP_ERROR);
|
|
5064 soap_closesock(soap);
|
|
5065 return SOAP_INVALID_SOCKET;
|
|
5066 }
|
|
5067 if (setsockopt(soap->socket, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
|
|
5068 { soap->errnum = soap_socket_errno(soap->socket);
|
|
5069 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_accept()", SOAP_TCP_ERROR);
|
|
5070 soap_closesock(soap);
|
|
5071 return SOAP_INVALID_SOCKET;
|
|
5072 }
|
|
5073 if (setsockopt(soap->socket, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
|
|
5074 { soap->errnum = soap_socket_errno(soap->socket);
|
|
5075 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_accept()", SOAP_TCP_ERROR);
|
|
5076 soap_closesock(soap);
|
|
5077 return SOAP_INVALID_SOCKET;
|
|
5078 }
|
|
5079 #ifdef TCP_NODELAY
|
|
5080 if (setsockopt(soap->socket, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
|
|
5081 { soap->errnum = soap_socket_errno(soap->socket);
|
|
5082 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_accept()", SOAP_TCP_ERROR);
|
|
5083 soap_closesock(soap);
|
|
5084 return SOAP_INVALID_SOCKET;
|
|
5085 }
|
|
5086 #endif
|
|
5087 #endif
|
|
5088 soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0);
|
|
5089 if (soap->send_timeout || soap->recv_timeout)
|
|
5090 SOAP_SOCKNONBLOCK(soap->socket)
|
|
5091 else
|
|
5092 SOAP_SOCKBLOCK(soap->socket)
|
|
5093 return soap->socket;
|
|
5094 }
|
|
5095 err = soap_socket_errno(soap->socket);
|
|
5096 if (err != 0 && err != SOAP_EINTR && err != SOAP_EAGAIN && err != SOAP_EWOULDBLOCK)
|
|
5097 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept failed from %s\n", soap->host));
|
|
5098 soap->errnum = err;
|
|
5099 soap_set_receiver_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR);
|
|
5100 soap_closesock(soap);
|
|
5101 return SOAP_INVALID_SOCKET;
|
|
5102 }
|
|
5103 }
|
|
5104 }
|
|
5105 #endif
|
|
5106 #endif
|
|
5107
|
|
5108 /******************************************************************************/
|
|
5109 #ifndef PALM_1
|
|
5110 SOAP_FMAC1
|
|
5111 int
|
|
5112 SOAP_FMAC2
|
|
5113 soap_closesock(struct soap *soap)
|
|
5114 { register int status = soap->error;
|
|
5115 #ifndef WITH_LEANER
|
|
5116 if (status) /* close on error: attachment state is not to be trusted */
|
|
5117 { soap->mime.first = NULL;
|
|
5118 soap->mime.last = NULL;
|
|
5119 soap->dime.first = NULL;
|
|
5120 soap->dime.last = NULL;
|
|
5121 }
|
|
5122 #endif
|
|
5123 if (soap->fdisconnect && (soap->error = soap->fdisconnect(soap)))
|
|
5124 return soap->error;
|
|
5125 if (status == SOAP_EOF || status == SOAP_TCP_ERROR || status == SOAP_SSL_ERROR || !soap->keep_alive)
|
|
5126 { if (soap->fclose && (soap->error = soap->fclose(soap)))
|
|
5127 return soap->error;
|
|
5128 soap->keep_alive = 0;
|
|
5129 }
|
|
5130 #ifdef WITH_ZLIB
|
|
5131 if (!(soap->mode & SOAP_MIME_POSTCHECK))
|
|
5132 { if (soap->zlib_state == SOAP_ZLIB_DEFLATE)
|
|
5133 deflateEnd(soap->d_stream);
|
|
5134 else if (soap->zlib_state == SOAP_ZLIB_INFLATE)
|
|
5135 inflateEnd(soap->d_stream);
|
|
5136 soap->zlib_state = SOAP_ZLIB_NONE;
|
|
5137 }
|
|
5138 #endif
|
|
5139 return soap->error = status;
|
|
5140 }
|
|
5141 #endif
|
|
5142
|
|
5143 /******************************************************************************/
|
|
5144 #ifndef WITH_NOIO
|
|
5145 #ifndef PALM_1
|
|
5146 SOAP_FMAC1
|
|
5147 int
|
|
5148 SOAP_FMAC2
|
|
5149 soap_force_closesock(struct soap *soap)
|
|
5150 { soap->keep_alive = 0;
|
|
5151 if (soap_valid_socket(soap->socket))
|
|
5152 return soap_closesocket(soap->socket);
|
|
5153 return SOAP_OK;
|
|
5154 }
|
|
5155 #endif
|
|
5156 #endif
|
|
5157
|
|
5158 /******************************************************************************/
|
|
5159 #ifndef WITH_NOIO
|
|
5160 #ifndef PALM_2
|
|
5161 SOAP_FMAC1
|
|
5162 void
|
|
5163 SOAP_FMAC2
|
|
5164 soap_cleanup(struct soap *soap)
|
|
5165 { soap_done(soap);
|
|
5166 #ifdef WIN32
|
|
5167 if (!tcp_done)
|
|
5168 return;
|
|
5169 tcp_done = 0;
|
|
5170 WSACleanup();
|
|
5171 #endif
|
|
5172 }
|
|
5173 #endif
|
|
5174 #endif
|
|
5175
|
|
5176 /******************************************************************************/
|
|
5177 #ifndef PALM_1
|
|
5178 SOAP_FMAC1
|
|
5179 void
|
|
5180 SOAP_FMAC2
|
|
5181 soap_done(struct soap *soap)
|
|
5182 {
|
|
5183 #ifdef SOAP_DEBUG
|
|
5184 int i;
|
|
5185 #endif
|
|
5186 if (soap_check_state(soap))
|
|
5187 return;
|
|
5188 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Done with context%s\n", soap->state == SOAP_COPY ? " copy" : ""));
|
|
5189 soap_free_temp(soap);
|
|
5190 while (soap->clist)
|
|
5191 { struct soap_clist *p = soap->clist->next;
|
|
5192 SOAP_FREE(soap, soap->clist);
|
|
5193 soap->clist = p;
|
|
5194 }
|
|
5195 if (soap->state == SOAP_INIT)
|
|
5196 soap->omode &= ~SOAP_IO_UDP; /* to force close the socket */
|
|
5197 soap->keep_alive = 0; /* to force close the socket */
|
|
5198 if (soap->master == soap->socket) /* do not close twice */
|
|
5199 soap->master = SOAP_INVALID_SOCKET;
|
|
5200 soap_closesock(soap);
|
|
5201 #ifdef WITH_COOKIES
|
|
5202 soap_free_cookies(soap);
|
|
5203 #endif
|
|
5204 while (soap->plugins)
|
|
5205 { register struct soap_plugin *p = soap->plugins->next;
|
|
5206 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Removing plugin '%s'\n", soap->plugins->id));
|
|
5207 if (soap->plugins->fcopy || soap->state == SOAP_INIT)
|
|
5208 soap->plugins->fdelete(soap, soap->plugins);
|
|
5209 SOAP_FREE(soap, soap->plugins);
|
|
5210 soap->plugins = p;
|
|
5211 }
|
|
5212 soap->fplugin = fplugin;
|
|
5213 soap->fmalloc = NULL;
|
|
5214 #ifndef WITH_NOHTTP
|
|
5215 soap->fpost = http_post;
|
|
5216 soap->fget = http_get;
|
|
5217 soap->fput = http_405;
|
|
5218 soap->fdel = http_405;
|
|
5219 soap->fopt = http_200;
|
|
5220 soap->fhead = http_200;
|
|
5221 soap->fform = NULL;
|
|
5222 soap->fposthdr = http_post_header;
|
|
5223 soap->fresponse = http_response;
|
|
5224 soap->fparse = http_parse;
|
|
5225 soap->fparsehdr = http_parse_header;
|
|
5226 #endif
|
|
5227 soap->fheader = NULL;
|
|
5228 #ifndef WITH_NOIO
|
|
5229 #ifndef WITH_IPV6
|
|
5230 soap->fresolve = tcp_gethost;
|
|
5231 #else
|
|
5232 soap->fresolve = NULL;
|
|
5233 #endif
|
|
5234 soap->faccept = tcp_accept;
|
|
5235 soap->fopen = tcp_connect;
|
|
5236 soap->fclose = tcp_disconnect;
|
|
5237 soap->fclosesocket = tcp_closesocket;
|
|
5238 soap->fshutdownsocket = tcp_shutdownsocket;
|
|
5239 soap->fsend = fsend;
|
|
5240 soap->frecv = frecv;
|
|
5241 soap->fpoll = soap_poll;
|
|
5242 #else
|
|
5243 soap->fopen = NULL;
|
|
5244 soap->fclose = NULL;
|
|
5245 soap->fpoll = NULL;
|
|
5246 #endif
|
|
5247 #ifndef WITH_LEANER
|
|
5248 soap->feltbegin = NULL;
|
|
5249 soap->feltendin = NULL;
|
|
5250 soap->feltbegout = NULL;
|
|
5251 soap->feltendout = NULL;
|
|
5252 soap->fprepareinitsend = NULL;
|
|
5253 soap->fprepareinitrecv = NULL;
|
|
5254 soap->fpreparesend = NULL;
|
|
5255 soap->fpreparerecv = NULL;
|
|
5256 soap->fpreparefinalsend = NULL;
|
|
5257 soap->fpreparefinalrecv = NULL;
|
|
5258 soap->ffiltersend = NULL;
|
|
5259 soap->ffilterrecv = NULL;
|
|
5260 #endif
|
|
5261 soap->fseterror = NULL;
|
|
5262 soap->fignore = NULL;
|
|
5263 soap->fserveloop = NULL;
|
|
5264 #ifdef WITH_OPENSSL
|
|
5265 if (soap->session)
|
|
5266 { SSL_SESSION_free(soap->session);
|
|
5267 soap->session = NULL;
|
|
5268 }
|
|
5269 #endif
|
|
5270 if (soap->state == SOAP_INIT)
|
|
5271 { if (soap_valid_socket(soap->master))
|
|
5272 { soap->fclosesocket(soap, soap->master);
|
|
5273 soap->master = SOAP_INVALID_SOCKET;
|
|
5274 }
|
|
5275 }
|
|
5276 #ifdef WITH_OPENSSL
|
|
5277 if (soap->ssl)
|
|
5278 { SSL_free(soap->ssl);
|
|
5279 soap->ssl = NULL;
|
|
5280 }
|
|
5281 if (soap->state == SOAP_INIT)
|
|
5282 { if (soap->ctx)
|
|
5283 { SSL_CTX_free(soap->ctx);
|
|
5284 soap->ctx = NULL;
|
|
5285 }
|
|
5286 }
|
|
5287 ERR_remove_state(0);
|
|
5288 #endif
|
|
5289 #ifdef WITH_GNUTLS
|
|
5290 if (soap->state == SOAP_INIT)
|
|
5291 { if (soap->xcred)
|
|
5292 { gnutls_certificate_free_credentials(soap->xcred);
|
|
5293 soap->xcred = NULL;
|
|
5294 }
|
|
5295 if (soap->acred)
|
|
5296 { gnutls_anon_free_client_credentials(soap->acred);
|
|
5297 soap->acred = NULL;
|
|
5298 }
|
|
5299 if (soap->cache)
|
|
5300 { gnutls_priority_deinit(soap->cache);
|
|
5301 soap->cache = NULL;
|
|
5302 }
|
|
5303 if (soap->dh_params)
|
|
5304 { gnutls_dh_params_deinit(soap->dh_params);
|
|
5305 soap->dh_params = NULL;
|
|
5306 }
|
|
5307 if (soap->rsa_params)
|
|
5308 { gnutls_rsa_params_deinit(soap->rsa_params);
|
|
5309 soap->rsa_params = NULL;
|
|
5310 }
|
|
5311 }
|
|
5312 if (soap->session)
|
|
5313 { gnutls_deinit(soap->session);
|
|
5314 soap->session = NULL;
|
|
5315 }
|
|
5316 #endif
|
|
5317 #ifdef WITH_C_LOCALE
|
|
5318 # ifdef WIN32
|
|
5319 _free_locale(soap->c_locale);
|
|
5320 # else
|
|
5321 freelocale(soap->c_locale);
|
|
5322 # endif
|
|
5323 #endif
|
|
5324 #ifdef WITH_ZLIB
|
|
5325 if (soap->d_stream)
|
|
5326 { SOAP_FREE(soap, (void*)soap->d_stream);
|
|
5327 soap->d_stream = NULL;
|
|
5328 }
|
|
5329 if (soap->z_buf)
|
|
5330 { SOAP_FREE(soap, (void*)soap->z_buf);
|
|
5331 soap->z_buf = NULL;
|
|
5332 }
|
|
5333 #endif
|
|
5334 #ifdef SOAP_DEBUG
|
|
5335 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free logfiles\n"));
|
|
5336 for (i = 0; i < SOAP_MAXLOGS; i++)
|
|
5337 { if (soap->logfile[i])
|
|
5338 { SOAP_FREE(soap, (void*)soap->logfile[i]);
|
|
5339 soap->logfile[i] = NULL;
|
|
5340 }
|
|
5341 soap_close_logfile(soap, i);
|
|
5342 }
|
|
5343 soap->state = SOAP_NONE;
|
|
5344 #endif
|
|
5345 #ifdef SOAP_MEM_DEBUG
|
|
5346 soap_free_mht(soap);
|
|
5347 #endif
|
|
5348 }
|
|
5349 #endif
|
|
5350
|
|
5351 /******************************************************************************\
|
|
5352 *
|
|
5353 * HTTP
|
|
5354 *
|
|
5355 \******************************************************************************/
|
|
5356
|
|
5357 /******************************************************************************/
|
|
5358 #ifndef WITH_NOHTTP
|
|
5359 #ifndef PALM_1
|
|
5360 static int
|
|
5361 http_parse(struct soap *soap)
|
|
5362 { char header[SOAP_HDRLEN], *s;
|
|
5363 unsigned short httpcmd = 0;
|
|
5364 int status = 0;
|
|
5365 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Waiting for HTTP request/response...\n"));
|
|
5366 *soap->endpoint = '\0';
|
|
5367 #ifdef WITH_NTLM
|
|
5368 if (!soap->ntlm_challenge)
|
|
5369 #endif
|
|
5370 { soap->userid = NULL;
|
|
5371 soap->passwd = NULL;
|
|
5372 soap->authrealm = NULL;
|
|
5373 }
|
|
5374 #ifdef WITH_NTLM
|
|
5375 soap->ntlm_challenge = NULL;
|
|
5376 #endif
|
|
5377 soap->proxy_from = NULL;
|
|
5378 do
|
|
5379 { soap->length = 0;
|
|
5380 soap->http_content = NULL;
|
|
5381 soap->action = NULL;
|
|
5382 soap->status = 0;
|
|
5383 soap->body = 1;
|
|
5384 if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
|
|
5385 { if (soap->error == SOAP_EOF)
|
|
5386 return SOAP_EOF;
|
|
5387 return soap->error = 414;
|
|
5388 }
|
|
5389 if ((s = strchr(soap->msgbuf, ' ')))
|
|
5390 { soap->status = (unsigned short)soap_strtoul(s, &s, 10);
|
|
5391 if (!soap_blank((soap_wchar)*s))
|
|
5392 soap->status = 0;
|
|
5393 }
|
|
5394 else
|
|
5395 soap->status = 0;
|
|
5396 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP status: %s\n", soap->msgbuf));
|
|
5397 for (;;)
|
|
5398 { if (soap_getline(soap, header, SOAP_HDRLEN))
|
|
5399 { if (soap->error == SOAP_EOF)
|
|
5400 { soap->error = SOAP_OK;
|
|
5401 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "EOF in HTTP header, continue anyway\n"));
|
|
5402 break;
|
|
5403 }
|
|
5404 return soap->error;
|
|
5405 }
|
|
5406 if (!*header)
|
|
5407 break;
|
|
5408 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP header: %s\n", header));
|
|
5409 s = strchr(header, ':');
|
|
5410 if (s)
|
|
5411 { char *t;
|
|
5412 *s = '\0';
|
|
5413 do s++;
|
|
5414 while (*s && *s <= 32);
|
|
5415 if (*s == '"')
|
|
5416 s++;
|
|
5417 t = s + strlen(s) - 1;
|
|
5418 while (t > s && *t <= 32)
|
|
5419 t--;
|
|
5420 if (t >= s && *t == '"')
|
|
5421 t--;
|
|
5422 t[1] = '\0';
|
|
5423 if ((soap->error = soap->fparsehdr(soap, header, s)))
|
|
5424 { if (soap->error < SOAP_STOP)
|
|
5425 return soap->error;
|
|
5426 status = soap->error;
|
|
5427 soap->error = SOAP_OK;
|
|
5428 }
|
|
5429 }
|
|
5430 }
|
|
5431 } while (soap->status == 100);
|
|
5432 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Finished HTTP header parsing, status = %d\n", soap->status));
|
|
5433 s = strstr(soap->msgbuf, "HTTP/");
|
|
5434 if (s && s[7] != '1')
|
|
5435 { if (soap->keep_alive == 1)
|
|
5436 soap->keep_alive = 0;
|
|
5437 if (soap->status == 0 && (soap->omode & SOAP_IO) == SOAP_IO_CHUNK) /* soap->status == 0 for HTTP request */
|
|
5438 soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE; /* HTTP 1.0 does not support chunked transfers */
|
|
5439 }
|
|
5440 if (soap->keep_alive < 0)
|
|
5441 soap->keep_alive = 1;
|
|
5442 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Keep alive connection = %d\n", soap->keep_alive));
|
|
5443 if (soap->status == 0)
|
|
5444 { size_t l = 0;
|
|
5445 if (s)
|
|
5446 { if (!strncmp(soap->msgbuf, "POST ", l = 5))
|
|
5447 httpcmd = 1;
|
|
5448 else if (!strncmp(soap->msgbuf, "PUT ", l = 4))
|
|
5449 httpcmd = 2;
|
|
5450 else if (!strncmp(soap->msgbuf, "GET ", l = 4))
|
|
5451 httpcmd = 3;
|
|
5452 else if (!strncmp(soap->msgbuf, "DELETE ", l = 7))
|
|
5453 httpcmd = 4;
|
|
5454 else if (!strncmp(soap->msgbuf, "OPTIONS ", l = 8))
|
|
5455 httpcmd = 5;
|
|
5456 else if (!strncmp(soap->msgbuf, "HEAD ", l = 5))
|
|
5457 httpcmd = 6;
|
|
5458 }
|
|
5459 if (s && httpcmd)
|
|
5460 { size_t m = strlen(soap->endpoint);
|
|
5461 size_t n = m + (s - soap->msgbuf) - l - 1;
|
|
5462 size_t k;
|
|
5463 if (n >= sizeof(soap->endpoint))
|
|
5464 n = sizeof(soap->endpoint) - 1;
|
|
5465 if (m > n)
|
|
5466 m = n;
|
|
5467 k = n - m + 1;
|
|
5468 if (k > sizeof(soap->path))
|
|
5469 k = sizeof(soap->path);
|
|
5470 strncpy(soap->path, soap->msgbuf + l, k);
|
|
5471 soap->path[k - 1] = '\0';
|
|
5472 if (*soap->path && *soap->path != '/')
|
|
5473 *soap->endpoint = '\0';
|
|
5474 strcat(soap->endpoint, soap->path);
|
|
5475 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Target endpoint='%s'\n", soap->endpoint));
|
|
5476 if (httpcmd > 1)
|
|
5477 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP %s handler\n", soap->msgbuf));
|
|
5478 switch (httpcmd)
|
|
5479 { case 2: soap->error = soap->fput(soap); break;
|
|
5480 case 3: soap->error = soap->fget(soap); break;
|
|
5481 case 4: soap->error = soap->fdel(soap); break;
|
|
5482 case 5: soap->error = soap->fopt(soap); break;
|
|
5483 case 6: soap->error = soap->fhead(soap); break;
|
|
5484 default: soap->error = 405; break;
|
|
5485 }
|
|
5486 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP handler return = %d\n", soap->error));
|
|
5487 if (soap->error == SOAP_OK)
|
|
5488 soap->error = SOAP_STOP; /* prevents further processing */
|
|
5489 return soap->error;
|
|
5490 }
|
|
5491 if (status)
|
|
5492 return soap->error = status;
|
|
5493 }
|
|
5494 else if (status)
|
|
5495 return soap->error = status;
|
|
5496 else if (s)
|
|
5497 return soap->error = 405;
|
|
5498 return SOAP_OK;
|
|
5499 }
|
|
5500 #if 0
|
|
5501 if (soap->length > 0 || (soap->http_content && (!soap->keep_alive || soap->recv_timeout)) || (soap->imode & SOAP_IO) == SOAP_IO_CHUNK)
|
|
5502 #endif
|
|
5503 if (soap->body)
|
|
5504 { if ((soap->status >= 200 && soap->status <= 299) /* OK, Accepted, etc */
|
|
5505 || soap->status == 400 /* Bad Request */
|
|
5506 || soap->status == 500) /* Internal Server Error */
|
|
5507 return SOAP_OK;
|
|
5508 /* force close afterwards in soap_closesock() */
|
|
5509 soap->keep_alive = 0;
|
|
5510 #ifndef WITH_LEAN
|
|
5511 /* read HTTP body for error details */
|
|
5512 s = soap_get_http_body(soap, NULL);
|
|
5513 if (s)
|
|
5514 return soap_set_receiver_error(soap, soap->msgbuf, s, soap->status);
|
|
5515 #endif
|
|
5516 }
|
|
5517 else if (soap->status >= 200 && soap->status <= 299)
|
|
5518 return soap->error = soap->status;
|
|
5519 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP error %d\n", soap->status));
|
|
5520 return soap_set_receiver_error(soap, "HTTP Error", soap->msgbuf, soap->status);
|
|
5521 }
|
|
5522 #endif
|
|
5523 #endif
|
|
5524
|
|
5525 /******************************************************************************/
|
|
5526 #ifndef WITH_NOHTTP
|
|
5527 #ifndef PALM_1
|
|
5528 static int
|
|
5529 http_parse_header(struct soap *soap, const char *key, const char *val)
|
|
5530 { if (!soap_tag_cmp(key, "Host"))
|
|
5531 {
|
|
5532 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
|
|
5533 if (soap->imode & SOAP_ENC_SSL)
|
|
5534 strcpy(soap->endpoint, "https://");
|
|
5535 else
|
|
5536 #endif
|
|
5537 strcpy(soap->endpoint, "http://");
|
|
5538 strncat(soap->endpoint, val, sizeof(soap->endpoint) - 8);
|
|
5539 }
|
|
5540 #ifndef WITH_LEANER
|
|
5541 else if (!soap_tag_cmp(key, "Content-Type"))
|
|
5542 { const char *action;
|
|
5543 soap->http_content = soap_strdup(soap, val);
|
|
5544 if (soap_get_header_attribute(soap, val, "application/dime"))
|
|
5545 soap->imode |= SOAP_ENC_DIME;
|
|
5546 else if (soap_get_header_attribute(soap, val, "multipart/related")
|
|
5547 || soap_get_header_attribute(soap, val, "multipart/form-data"))
|
|
5548 { soap->mime.boundary = soap_strdup(soap, soap_get_header_attribute(soap, val, "boundary"));
|
|
5549 soap->mime.start = soap_strdup(soap, soap_get_header_attribute(soap, val, "start"));
|
|
5550 soap->imode |= SOAP_ENC_MIME;
|
|
5551 }
|
|
5552 action = soap_get_header_attribute(soap, val, "action");
|
|
5553 if (action)
|
|
5554 { if (*action == '"')
|
|
5555 { soap->action = soap_strdup(soap, action + 1);
|
|
5556 if (*soap->action)
|
|
5557 soap->action[strlen(soap->action) - 1] = '\0';
|
|
5558 }
|
|
5559 else
|
|
5560 soap->action = soap_strdup(soap, action);
|
|
5561 }
|
|
5562 }
|
|
5563 #endif
|
|
5564 else if (!soap_tag_cmp(key, "Content-Length"))
|
|
5565 { soap->length = soap_strtoul(val, NULL, 10);
|
|
5566 if (!soap->length)
|
|
5567 soap->body = 0;
|
|
5568 }
|
|
5569 else if (!soap_tag_cmp(key, "Content-Encoding"))
|
|
5570 { if (!soap_tag_cmp(val, "deflate"))
|
|
5571 #ifdef WITH_ZLIB
|
|
5572 soap->zlib_in = SOAP_ZLIB_DEFLATE;
|
|
5573 #else
|
|
5574 return SOAP_ZLIB_ERROR;
|
|
5575 #endif
|
|
5576 else if (!soap_tag_cmp(val, "gzip"))
|
|
5577 #ifdef WITH_GZIP
|
|
5578 soap->zlib_in = SOAP_ZLIB_GZIP;
|
|
5579 #else
|
|
5580 return SOAP_ZLIB_ERROR;
|
|
5581 #endif
|
|
5582 }
|
|
5583 #ifdef WITH_ZLIB
|
|
5584 else if (!soap_tag_cmp(key, "Accept-Encoding"))
|
|
5585 {
|
|
5586 #ifdef WITH_GZIP
|
|
5587 if (strchr(val, '*') || soap_get_header_attribute(soap, val, "gzip"))
|
|
5588 soap->zlib_out = SOAP_ZLIB_GZIP;
|
|
5589 else
|
|
5590 #endif
|
|
5591 if (strchr(val, '*') || soap_get_header_attribute(soap, val, "deflate"))
|
|
5592 soap->zlib_out = SOAP_ZLIB_DEFLATE;
|
|
5593 else
|
|
5594 soap->zlib_out = SOAP_ZLIB_NONE;
|
|
5595 }
|
|
5596 #endif
|
|
5597 else if (!soap_tag_cmp(key, "Transfer-Encoding"))
|
|
5598 { soap->imode &= ~SOAP_IO;
|
|
5599 if (!soap_tag_cmp(val, "chunked"))
|
|
5600 soap->imode |= SOAP_IO_CHUNK;
|
|
5601 }
|
|
5602 else if (!soap_tag_cmp(key, "Connection"))
|
|
5603 { if (!soap_tag_cmp(val, "keep-alive"))
|
|
5604 soap->keep_alive = -soap->keep_alive;
|
|
5605 else if (!soap_tag_cmp(val, "close"))
|
|
5606 soap->keep_alive = 0;
|
|
5607 }
|
|
5608 #ifndef WITH_LEAN
|
|
5609 else if (!soap_tag_cmp(key, "Authorization") || !soap_tag_cmp(key, "Proxy-Authorization"))
|
|
5610 {
|
|
5611 #ifdef WITH_NTLM
|
|
5612 if (!soap_tag_cmp(val, "NTLM*"))
|
|
5613 soap->ntlm_challenge = soap_strdup(soap, val + 4);
|
|
5614 else
|
|
5615 #endif
|
|
5616 if (!soap_tag_cmp(val, "Basic *"))
|
|
5617 { int n;
|
|
5618 char *s;
|
|
5619 soap_base642s(soap, val + 6, soap->tmpbuf, sizeof(soap->tmpbuf) - 1, &n);
|
|
5620 soap->tmpbuf[n] = '\0';
|
|
5621 if ((s = strchr(soap->tmpbuf, ':')))
|
|
5622 { *s = '\0';
|
|
5623 soap->userid = soap_strdup(soap, soap->tmpbuf);
|
|
5624 soap->passwd = soap_strdup(soap, s + 1);
|
|
5625 }
|
|
5626 }
|
|
5627 }
|
|
5628 else if (!soap_tag_cmp(key, "WWW-Authenticate") || !soap_tag_cmp(key, "Proxy-Authenticate"))
|
|
5629 {
|
|
5630 #ifdef WITH_NTLM
|
|
5631 if (!soap_tag_cmp(val, "NTLM*"))
|
|
5632 soap->ntlm_challenge = soap_strdup(soap, val + 4);
|
|
5633 else
|
|
5634 #endif
|
|
5635 soap->authrealm = soap_strdup(soap, soap_get_header_attribute(soap, val + 6, "realm"));
|
|
5636 }
|
|
5637 else if (!soap_tag_cmp(key, "Expect"))
|
|
5638 { if (!soap_tag_cmp(val, "100-continue"))
|
|
5639 { if ((soap->error = soap->fposthdr(soap, "HTTP/1.1 100 Continue", NULL))
|
|
5640 || (soap->error = soap->fposthdr(soap, NULL, NULL)))
|
|
5641 return soap->error;
|
|
5642 }
|
|
5643 }
|
|
5644 #endif
|
|
5645 else if (!soap_tag_cmp(key, "SOAPAction"))
|
|
5646 { if (*val == '"')
|
|
5647 { soap->action = soap_strdup(soap, val + 1);
|
|
5648 if (*soap->action)
|
|
5649 soap->action[strlen(soap->action) - 1] = '\0';
|
|
5650 }
|
|
5651 else
|
|
5652 soap->action = soap_strdup(soap, val);
|
|
5653 }
|
|
5654 else if (!soap_tag_cmp(key, "Location"))
|
|
5655 { strncpy(soap->endpoint, val, sizeof(soap->endpoint));
|
|
5656 soap->endpoint[sizeof(soap->endpoint) - 1] = '\0';
|
|
5657 }
|
|
5658 else if (!soap_tag_cmp(key, "X-Forwarded-For"))
|
|
5659 { soap->proxy_from = soap_strdup(soap, val);
|
|
5660 }
|
|
5661 #ifdef WITH_COOKIES
|
|
5662 else if (!soap_tag_cmp(key, "Cookie")
|
|
5663 || !soap_tag_cmp(key, "Cookie2")
|
|
5664 || !soap_tag_cmp(key, "Set-Cookie")
|
|
5665 || !soap_tag_cmp(key, "Set-Cookie2"))
|
|
5666 { soap_getcookies(soap, val);
|
|
5667 }
|
|
5668 #endif
|
|
5669 return SOAP_OK;
|
|
5670 }
|
|
5671 #endif
|
|
5672 #endif
|
|
5673
|
|
5674 /******************************************************************************/
|
|
5675 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
|
|
5676 #ifndef PALM_1
|
|
5677 SOAP_FMAC1
|
|
5678 const char*
|
|
5679 SOAP_FMAC2
|
|
5680 soap_get_header_attribute(struct soap *soap, const char *line, const char *key)
|
|
5681 { register const char *s = line;
|
|
5682 if (s)
|
|
5683 { while (*s)
|
|
5684 { register short flag;
|
|
5685 s = soap_decode_key(soap->tmpbuf, sizeof(soap->tmpbuf), s);
|
|
5686 flag = soap_tag_cmp(soap->tmpbuf, key);
|
|
5687 s = soap_decode_val(soap->tmpbuf, sizeof(soap->tmpbuf), s);
|
|
5688 if (!flag)
|
|
5689 return soap->tmpbuf;
|
|
5690 }
|
|
5691 }
|
|
5692 return NULL;
|
|
5693 }
|
|
5694 #endif
|
|
5695 #endif
|
|
5696
|
|
5697 /******************************************************************************/
|
|
5698 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
|
|
5699 #ifndef PALM_1
|
|
5700 SOAP_FMAC1
|
|
5701 const char*
|
|
5702 SOAP_FMAC2
|
|
5703 soap_decode_key(char *buf, size_t len, const char *val)
|
|
5704 { return soap_decode(buf, len, val, "=,;");
|
|
5705 }
|
|
5706 #endif
|
|
5707 #endif
|
|
5708
|
|
5709 /******************************************************************************/
|
|
5710 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
|
|
5711 #ifndef PALM_1
|
|
5712 SOAP_FMAC1
|
|
5713 const char*
|
|
5714 SOAP_FMAC2
|
|
5715 soap_decode_val(char *buf, size_t len, const char *val)
|
|
5716 { if (*val != '=')
|
|
5717 { *buf = '\0';
|
|
5718 return val;
|
|
5719 }
|
|
5720 return soap_decode(buf, len, val + 1, ",;");
|
|
5721 }
|
|
5722 #endif
|
|
5723 #endif
|
|
5724
|
|
5725 /******************************************************************************/
|
|
5726 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
|
|
5727 #ifndef PALM_1
|
|
5728 static const char*
|
|
5729 soap_decode(char *buf, size_t len, const char *val, const char *sep)
|
|
5730 { const char *s;
|
|
5731 char *t = buf;
|
|
5732 size_t i = len;
|
|
5733 for (s = val; *s; s++)
|
|
5734 if (*s != ' ' && *s != '\t' && !strchr(sep, *s))
|
|
5735 break;
|
|
5736 if (len > 0)
|
|
5737 { if (*s == '"')
|
|
5738 { s++;
|
|
5739 while (*s && *s != '"' && --i)
|
|
5740 *t++ = *s++;
|
|
5741 }
|
|
5742 else
|
|
5743 { while (*s && !soap_blank((soap_wchar)*s) && !strchr(sep, *s) && --i)
|
|
5744 { if (*s == '%' && s[1] && s[2])
|
|
5745 { *t++ = ((s[1] >= 'A' ? (s[1] & 0x7) + 9 : s[1] - '0') << 4)
|
|
5746 + (s[2] >= 'A' ? (s[2] & 0x7) + 9 : s[2] - '0');
|
|
5747 s += 3;
|
|
5748 }
|
|
5749 else
|
|
5750 *t++ = *s++;
|
|
5751 }
|
|
5752 }
|
|
5753 buf[len - 1] = '\0'; /* appease */
|
|
5754 }
|
|
5755 *t = '\0';
|
|
5756 while (*s && !strchr(sep, *s))
|
|
5757 s++;
|
|
5758 return s;
|
|
5759 }
|
|
5760 #endif
|
|
5761 #endif
|
|
5762
|
|
5763 /******************************************************************************/
|
|
5764 #ifndef WITH_NOHTTP
|
|
5765 #ifndef PALM_1
|
|
5766 static const char*
|
|
5767 http_error(struct soap *soap, int status)
|
|
5768 { register const char *msg = SOAP_STR_EOS;
|
|
5769 (void)soap;
|
|
5770 #ifndef WITH_LEAN
|
|
5771 msg = soap_code_str(h_http_error_codes, status);
|
|
5772 if (!msg)
|
|
5773 msg = SOAP_STR_EOS;
|
|
5774 #endif
|
|
5775 return msg;
|
|
5776 }
|
|
5777 #endif
|
|
5778 #endif
|
|
5779
|
|
5780 /******************************************************************************/
|
|
5781
|
|
5782 #ifndef WITH_NOHTTP
|
|
5783 #ifndef PALM_1
|
|
5784 static int
|
|
5785 http_get(struct soap *soap)
|
|
5786 { (void)soap;
|
|
5787 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "HTTP GET request\n"));
|
|
5788 return SOAP_GET_METHOD;
|
|
5789 }
|
|
5790 #endif
|
|
5791 #endif
|
|
5792
|
|
5793 /******************************************************************************/
|
|
5794 #ifndef WITH_NOHTTP
|
|
5795 #ifndef PALM_1
|
|
5796 static int
|
|
5797 http_405(struct soap *soap)
|
|
5798 { (void)soap;
|
|
5799 return 405;
|
|
5800 }
|
|
5801 #endif
|
|
5802 #endif
|
|
5803
|
|
5804 /******************************************************************************/
|
|
5805 #ifndef WITH_NOHTTP
|
|
5806 #ifndef PALM_1
|
|
5807 static int
|
|
5808 http_200(struct soap *soap)
|
|
5809 { return soap_send_empty_response(soap, 200);
|
|
5810 }
|
|
5811 #endif
|
|
5812 #endif
|
|
5813
|
|
5814 /******************************************************************************/
|
|
5815 #ifndef WITH_NOHTTP
|
|
5816 #ifndef PALM_1
|
|
5817 static int
|
|
5818 http_post(struct soap *soap, const char *endpoint, const char *host, int port, const char *path, const char *action, size_t count)
|
|
5819 { register const char *s;
|
|
5820 register int err;
|
|
5821 switch (soap->status)
|
|
5822 { case SOAP_GET:
|
|
5823 s = "GET";
|
|
5824 break;
|
|
5825 case SOAP_PUT:
|
|
5826 s = "PUT";
|
|
5827 break;
|
|
5828 case SOAP_DEL:
|
|
5829 s = "DELETE";
|
|
5830 break;
|
|
5831 case SOAP_CONNECT:
|
|
5832 s = "CONNECT";
|
|
5833 break;
|
|
5834 default:
|
|
5835 s = "POST";
|
|
5836 }
|
|
5837 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "HTTP %s to %s\n", s, endpoint ? endpoint : "(null)"));
|
|
5838 #ifdef PALM
|
|
5839 if (!endpoint || (soap_tag_cmp(endpoint, "http:*") && soap_tag_cmp(endpoint, "https:*") && strncmp(endpoint, "httpg:", 6)) && strncmp(endpoint, "_beam:", 6) && strncmp(endpoint, "_local:", 7) && strncmp(endpoint, "_btobex:", 8))
|
|
5840 #else
|
|
5841 if (!endpoint || (soap_tag_cmp(endpoint, "http:*") && soap_tag_cmp(endpoint, "https:*") && strncmp(endpoint, "httpg:", 6)))
|
|
5842 #endif
|
|
5843 return SOAP_OK;
|
|
5844 if (strlen(endpoint) + strlen(soap->http_version) > sizeof(soap->tmpbuf) - 80
|
|
5845 || strlen(host) + strlen(soap->http_version) > sizeof(soap->tmpbuf) - 80)
|
|
5846 return soap->error = SOAP_EOM; /* prevent overrun (note that 'host' and 'soap->host' are substrings of 'endpoint') */
|
|
5847 if (soap->status == SOAP_CONNECT)
|
|
5848 {
|
|
5849 #ifdef HAVE_SNPRINTF
|
|
5850 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%s %s:%d HTTP/%s", s, soap->host, soap->port, soap->http_version);
|
|
5851 #else
|
|
5852 sprintf(soap->tmpbuf, "%s %s:%d HTTP/%s", s, soap->host, soap->port, soap->http_version);
|
|
5853 #endif
|
|
5854 }
|
|
5855 else if (soap->proxy_host && endpoint)
|
|
5856 {
|
|
5857 #ifdef HAVE_SNPRINTF
|
|
5858 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%s %s HTTP/%s", s, endpoint, soap->http_version);
|
|
5859 #else
|
|
5860 sprintf(soap->tmpbuf, "%s %s HTTP/%s", s, endpoint, soap->http_version);
|
|
5861 #endif
|
|
5862 }
|
|
5863 else
|
|
5864 {
|
|
5865 #ifdef HAVE_SNPRINTF
|
|
5866 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%s /%s HTTP/%s", s, (*path == '/' ? path + 1 : path), soap->http_version);
|
|
5867 #else
|
|
5868 sprintf(soap->tmpbuf, "%s /%s HTTP/%s", s, (*path == '/' ? path + 1 : path), soap->http_version);
|
|
5869 #endif
|
|
5870 }
|
|
5871 if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
|
|
5872 return err;
|
|
5873 #ifdef WITH_OPENSSL
|
|
5874 if ((soap->ssl && port != 443) || (!soap->ssl && port != 80))
|
|
5875 #else
|
|
5876 if (port != 80)
|
|
5877 #endif
|
|
5878 {
|
|
5879 #ifdef WITH_IPV6
|
|
5880 if (*host != '[' && strchr(host, ':'))
|
|
5881 {
|
|
5882 #ifdef HAVE_SNPRINTF
|
|
5883 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "[%s]:%d", host, port); /* RFC 2732 */
|
|
5884 #else
|
|
5885 sprintf(soap->tmpbuf, "[%s]:%d", host, port); /* RFC 2732 */
|
|
5886 #endif
|
|
5887 }
|
|
5888 else
|
|
5889 #endif
|
|
5890 {
|
|
5891 #ifdef HAVE_SNPRINTF
|
|
5892 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%s:%d", host, port);
|
|
5893 #else
|
|
5894 sprintf(soap->tmpbuf, "%s:%d", host, port);
|
|
5895 #endif
|
|
5896 }
|
|
5897 }
|
|
5898 else
|
|
5899 {
|
|
5900 #ifdef WITH_IPV6
|
|
5901 if (*host != '[' && strchr(host, ':'))
|
|
5902 {
|
|
5903 #ifdef HAVE_SNPRINTF
|
|
5904 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "[%s]", host); /* RFC 2732 */
|
|
5905 #else
|
|
5906 sprintf(soap->tmpbuf, "[%s]", host); /* RFC 2732 */
|
|
5907 #endif
|
|
5908 }
|
|
5909 else
|
|
5910 #endif
|
|
5911 strcpy(soap->tmpbuf, host);
|
|
5912 }
|
|
5913 if ((err = soap->fposthdr(soap, "Host", soap->tmpbuf)))
|
|
5914 return err;
|
|
5915 if ((err = soap->fposthdr(soap, "User-Agent", "gSOAP/2.8")))
|
|
5916 return err;
|
|
5917 if ((err = soap_puthttphdr(soap, SOAP_OK, count)))
|
|
5918 return err;
|
|
5919 #ifdef WITH_ZLIB
|
|
5920 #ifdef WITH_GZIP
|
|
5921 if ((err = soap->fposthdr(soap, "Accept-Encoding", "gzip, deflate")))
|
|
5922 #else
|
|
5923 if ((err = soap->fposthdr(soap, "Accept-Encoding", "deflate")))
|
|
5924 #endif
|
|
5925 return err;
|
|
5926 #endif
|
|
5927 #ifndef WITH_LEAN
|
|
5928 #ifdef WITH_NTLM
|
|
5929 if (soap->ntlm_challenge && strlen(soap->ntlm_challenge) + 6 < sizeof(soap->tmpbuf))
|
|
5930 { if (*soap->ntlm_challenge)
|
|
5931 {
|
|
5932 #ifdef HAVE_SNPRINTF
|
|
5933 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "NTLM %s", soap->ntlm_challenge);
|
|
5934 #else
|
|
5935 sprintf(soap->tmpbuf, "NTLM %s", soap->ntlm_challenge);
|
|
5936 #endif
|
|
5937 if (soap->proxy_host)
|
|
5938 { if ((err = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf)))
|
|
5939 return err;
|
|
5940 }
|
|
5941 else if ((err = soap->fposthdr(soap, "Authorization", soap->tmpbuf)))
|
|
5942 return err;
|
|
5943 }
|
|
5944 }
|
|
5945 else
|
|
5946 {
|
|
5947 #endif
|
|
5948 if (soap->userid && soap->passwd && strlen(soap->userid) + strlen(soap->passwd) < 761)
|
|
5949 { strcpy(soap->tmpbuf, "Basic ");
|
|
5950 #ifdef HAVE_SNPRINTF
|
|
5951 soap_snprintf(soap->tmpbuf + 262, sizeof(soap->tmpbuf) - 262, "%s:%s", soap->userid, soap->passwd);
|
|
5952 #else
|
|
5953 sprintf(soap->tmpbuf + 262, "%s:%s", soap->userid, soap->passwd);
|
|
5954 #endif
|
|
5955 soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262));
|
|
5956 if ((err = soap->fposthdr(soap, "Authorization", soap->tmpbuf)))
|
|
5957 return err;
|
|
5958 }
|
|
5959 if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761)
|
|
5960 { strcpy(soap->tmpbuf, "Basic ");
|
|
5961 #ifdef HAVE_SNPRINTF
|
|
5962 soap_snprintf(soap->tmpbuf + 262, sizeof(soap->tmpbuf) - 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd);
|
|
5963 #else
|
|
5964 sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd);
|
|
5965 #endif
|
|
5966 soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262));
|
|
5967 if ((err = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf)))
|
|
5968 return err;
|
|
5969 }
|
|
5970 #ifdef WITH_NTLM
|
|
5971 }
|
|
5972 #endif
|
|
5973 #endif
|
|
5974 #ifdef WITH_COOKIES
|
|
5975 #ifdef WITH_OPENSSL
|
|
5976 if (soap_putcookies(soap, host, path, soap->ssl != NULL))
|
|
5977 return soap->error;
|
|
5978 #else
|
|
5979 if (soap_putcookies(soap, host, path, 0))
|
|
5980 return soap->error;
|
|
5981 #endif
|
|
5982 #endif
|
|
5983 if (action && soap->status != SOAP_GET && soap->status != SOAP_DEL)
|
|
5984 {
|
|
5985 #ifdef HAVE_SNPRINTF
|
|
5986 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "\"%s\"", action);
|
|
5987 #else
|
|
5988 sprintf(soap->tmpbuf, "\"%s\"", strlen(action) < sizeof(soap->tmpbuf) - 3 ? action : SOAP_STR_EOS);
|
|
5989 #endif
|
|
5990 if ((err = soap->fposthdr(soap, "SOAPAction", soap->tmpbuf)))
|
|
5991 return err;
|
|
5992 }
|
|
5993 return soap->fposthdr(soap, NULL, NULL);
|
|
5994 }
|
|
5995 #endif
|
|
5996 #endif
|
|
5997
|
|
5998 /******************************************************************************/
|
|
5999 #ifndef WITH_NOHTTP
|
|
6000 #ifndef PALM_1
|
|
6001 static int
|
|
6002 http_send_header(struct soap *soap, const char *s)
|
|
6003 { register const char *t;
|
|
6004 do
|
|
6005 { t = strchr(s, '\n'); /* disallow \n in HTTP headers */
|
|
6006 if (!t)
|
|
6007 t = s + strlen(s);
|
|
6008 if (soap_send_raw(soap, s, t - s))
|
|
6009 return soap->error;
|
|
6010 s = t + 1;
|
|
6011 } while (*t);
|
|
6012 return SOAP_OK;
|
|
6013 }
|
|
6014 #endif
|
|
6015 #endif
|
|
6016
|
|
6017 /******************************************************************************/
|
|
6018 #ifndef WITH_NOHTTP
|
|
6019 #ifndef PALM_1
|
|
6020 static int
|
|
6021 http_post_header(struct soap *soap, const char *key, const char *val)
|
|
6022 { if (key)
|
|
6023 { if (http_send_header(soap, key))
|
|
6024 return soap->error;
|
|
6025 if (val && (soap_send_raw(soap, ": ", 2) || http_send_header(soap, val)))
|
|
6026 return soap->error;
|
|
6027 }
|
|
6028 return soap_send_raw(soap, "\r\n", 2);
|
|
6029 }
|
|
6030 #endif
|
|
6031 #endif
|
|
6032
|
|
6033 /******************************************************************************/
|
|
6034 #ifndef WITH_NOHTTP
|
|
6035 #ifndef PALM_1
|
|
6036 static int
|
|
6037 http_response(struct soap *soap, int status, size_t count)
|
|
6038 { register int err;
|
|
6039 char http[10];
|
|
6040 int code = status;
|
|
6041 const char *line;
|
|
6042 #ifdef WMW_RPM_IO
|
|
6043 if (soap->rpmreqid)
|
|
6044 httpOutputEnable(soap->rpmreqid);
|
|
6045 #endif
|
|
6046 if (!soap->http_version || strlen(soap->http_version) > 4)
|
|
6047 return soap->error = SOAP_EOM;
|
|
6048 #ifdef WMW_RPM_IO
|
|
6049 if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */
|
|
6050 #else
|
|
6051 if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application (socket) or CGI (stdin/out)? */
|
|
6052 #endif
|
|
6053 {
|
|
6054 #ifdef HAVE_SNPRINTF
|
|
6055 soap_snprintf(http, sizeof(http), "HTTP/%s", soap->http_version);
|
|
6056 #else
|
|
6057 sprintf(http, "HTTP/%s", soap->http_version);
|
|
6058 #endif
|
|
6059 }
|
|
6060 else
|
|
6061 strcpy(http, "Status:");
|
|
6062 if (!status || status == SOAP_HTML || status == SOAP_FILE)
|
|
6063 { if (count || ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK))
|
|
6064 code = 200;
|
|
6065 else
|
|
6066 code = 202;
|
|
6067 }
|
|
6068 else if (status < 200 || status >= 600)
|
|
6069 { const char *s = *soap_faultcode(soap);
|
|
6070 if (status >= SOAP_GET_METHOD && status <= SOAP_HTTP_METHOD)
|
|
6071 code = 405;
|
|
6072 else if (soap->version == 2 && (!s || !strcmp(s, "SOAP-ENV:Sender")))
|
|
6073 code = 400;
|
|
6074 else
|
|
6075 code = 500;
|
|
6076 }
|
|
6077 line = http_error(soap, code);
|
|
6078 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "HTTP Status = %d %s\n", code, line));
|
|
6079 #ifdef HAVE_SNPRINTF
|
|
6080 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%s %d %s", http, code, line);
|
|
6081 #else
|
|
6082 sprintf(soap->tmpbuf, "%s %d %s", http, code, line);
|
|
6083 #endif
|
|
6084 if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
|
|
6085 return err;
|
|
6086 #ifndef WITH_LEAN
|
|
6087 if (status == 401)
|
|
6088 {
|
|
6089 #ifdef HAVE_SNPRINTF
|
|
6090 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "Basic realm=\"%s\"", (soap->authrealm && strlen(soap->authrealm) < sizeof(soap->tmpbuf) - 14) ? soap->authrealm : "gSOAP Web Service");
|
|
6091 #else
|
|
6092 sprintf(soap->tmpbuf, "Basic realm=\"%s\"", (soap->authrealm && strlen(soap->authrealm) < sizeof(soap->tmpbuf) - 14) ? soap->authrealm : "gSOAP Web Service");
|
|
6093 #endif
|
|
6094 if ((err = soap->fposthdr(soap, "WWW-Authenticate", soap->tmpbuf)))
|
|
6095 return err;
|
|
6096 }
|
|
6097 else if ((status >= 301 && status <= 303) || status == 307)
|
|
6098 { if ((err = soap->fposthdr(soap, "Location", soap->endpoint)))
|
|
6099 return err;
|
|
6100 }
|
|
6101 #endif
|
|
6102 if ((err = soap->fposthdr(soap, "Server", "gSOAP/2.8"))
|
|
6103 || (err = soap_puthttphdr(soap, status, count)))
|
|
6104 return err;
|
|
6105 #ifdef WITH_COOKIES
|
|
6106 if (soap_putsetcookies(soap))
|
|
6107 return soap->error;
|
|
6108 #endif
|
|
6109 return soap->fposthdr(soap, NULL, NULL);
|
|
6110 }
|
|
6111 #endif
|
|
6112 #endif
|
|
6113
|
|
6114 /******************************************************************************/
|
|
6115 #ifndef PALM_1
|
|
6116 SOAP_FMAC1
|
|
6117 int
|
|
6118 SOAP_FMAC2
|
|
6119 soap_response(struct soap *soap, int status)
|
|
6120 { register size_t count;
|
|
6121 if (!(soap->omode & (SOAP_ENC_XML | SOAP_IO_STORE /* this tests for chunking too */))
|
|
6122 && (status == SOAP_HTML || status == SOAP_FILE))
|
|
6123 soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE;
|
|
6124 soap->status = status;
|
|
6125 count = soap_count_attachments(soap);
|
|
6126 if (soap_begin_send(soap))
|
|
6127 return soap->error;
|
|
6128 #ifndef WITH_NOHTTP
|
|
6129 if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML))
|
|
6130 { register int n = soap->mode;
|
|
6131 soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB);
|
|
6132 if ((n & SOAP_IO) != SOAP_IO_FLUSH)
|
|
6133 soap->mode |= SOAP_IO_BUFFER;
|
|
6134 if ((soap->error = soap->fresponse(soap, status, count)))
|
|
6135 return soap->error;
|
|
6136 #ifndef WITH_LEANER
|
|
6137 if ((n & SOAP_IO) == SOAP_IO_CHUNK)
|
|
6138 { if (soap_flush(soap))
|
|
6139 return soap->error;
|
|
6140 }
|
|
6141 #endif
|
|
6142 soap->mode = n;
|
|
6143 }
|
|
6144 #endif
|
|
6145 return SOAP_OK;
|
|
6146 }
|
|
6147 #endif
|
|
6148
|
|
6149 /******************************************************************************/
|
|
6150 #ifndef PALM_1
|
|
6151 SOAP_FMAC1
|
|
6152 const char*
|
|
6153 SOAP_FMAC2
|
|
6154 soap_url(struct soap *soap, const char *s, const char *t)
|
|
6155 { if (!t || (*t != '/' && *t != '?') || strlen(s) + strlen(t) >= sizeof(soap->msgbuf))
|
|
6156 return s;
|
|
6157 strcpy(soap->msgbuf, s);
|
|
6158 strcat(soap->msgbuf, t);
|
|
6159 return soap->msgbuf;
|
|
6160 }
|
|
6161 #endif
|
|
6162
|
|
6163 /******************************************************************************/
|
|
6164 #ifndef PALM_1
|
|
6165 SOAP_FMAC1
|
|
6166 size_t
|
|
6167 SOAP_FMAC2
|
|
6168 soap_encode_url(const char *s, char *t, size_t len)
|
|
6169 { register int c;
|
|
6170 register size_t n = len;
|
|
6171 while ((c = *s++) && --n > 0)
|
|
6172 { if (c > ' ' && c < 128 && !strchr("()<>@,;:\\\"/[]?={}#!$&'*+", c))
|
|
6173 *t++ = c;
|
|
6174 else if (n > 2)
|
|
6175 { *t++ = '%';
|
|
6176 *t++ = (c >> 4) + (c > 159 ? '7' : '0');
|
|
6177 c &= 0xF;
|
|
6178 *t++ = c + (c > 9 ? '7' : '0');
|
|
6179 n -= 2;
|
|
6180 }
|
|
6181 else
|
|
6182 break;
|
|
6183 }
|
|
6184 *t = '\0';
|
|
6185 return len - n;
|
|
6186 }
|
|
6187 #endif
|
|
6188
|
|
6189 /******************************************************************************/
|
|
6190 #ifndef PALM_1
|
|
6191 SOAP_FMAC1
|
|
6192 const char*
|
|
6193 SOAP_FMAC2
|
|
6194 soap_encode_url_string(struct soap *soap, const char *s)
|
|
6195 { if (s)
|
|
6196 { size_t n = 3*strlen(s)+1;
|
|
6197 char *t = (char*)soap_malloc(soap, n);
|
|
6198 if (t)
|
|
6199 { soap_encode_url(s, t, n);
|
|
6200 return t;
|
|
6201 }
|
|
6202 }
|
|
6203 return SOAP_STR_EOS;
|
|
6204 }
|
|
6205 #endif
|
|
6206
|
|
6207 /******************************************************************************\
|
|
6208 *
|
|
6209 * HTTP Cookies
|
|
6210 *
|
|
6211 \******************************************************************************/
|
|
6212
|
|
6213 #ifdef WITH_COOKIES
|
|
6214 /******************************************************************************/
|
|
6215 SOAP_FMAC1
|
|
6216 struct soap_cookie*
|
|
6217 SOAP_FMAC2
|
|
6218 soap_cookie(struct soap *soap, const char *name, const char *domain, const char *path)
|
|
6219 { struct soap_cookie *p;
|
|
6220 if (!domain)
|
|
6221 domain = soap->cookie_domain;
|
|
6222 if (!path)
|
|
6223 path = soap->cookie_path;
|
|
6224 if (!path)
|
|
6225 path = SOAP_STR_EOS;
|
|
6226 else if (*path == '/')
|
|
6227 path++;
|
|
6228 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Search cookie='%s' domain='%s' path='%s'\n", name, domain ? domain : "(null)", path ? path : "(null)"));
|
|
6229 for (p = soap->cookies; p; p = p->next)
|
|
6230 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie in database: %s='%s' domain='%s' path='%s' env=%hd\n", p->name, p->value ? p->value : "(null)", p->domain ? p->domain : "(null)", p->path ? p->path : "(null)", p->env));
|
|
6231 if (!strcmp(p->name, name)
|
|
6232 && p->domain
|
|
6233 && p->path
|
|
6234 && !strcmp(p->domain, domain)
|
|
6235 && (!*p->path || !strncmp(p->path, path, strlen(p->path))))
|
|
6236 break;
|
|
6237 }
|
|
6238 return p;
|
|
6239 }
|
|
6240
|
|
6241 /******************************************************************************/
|
|
6242 SOAP_FMAC1
|
|
6243 struct soap_cookie*
|
|
6244 SOAP_FMAC2
|
|
6245 soap_set_cookie(struct soap *soap, const char *name, const char *value, const char *domain, const char *path)
|
|
6246 { struct soap_cookie **p, *q;
|
|
6247 int n;
|
|
6248 if (!domain)
|
|
6249 domain = soap->cookie_domain;
|
|
6250 if (!path)
|
|
6251 path = soap->cookie_path;
|
|
6252 if (!path)
|
|
6253 path = SOAP_STR_EOS;
|
|
6254 else if (*path == '/')
|
|
6255 path++;
|
|
6256 q = soap_cookie(soap, name, domain, path);
|
|
6257 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set %scookie: %s='%s' domain='%s' path='%s'\n", q ? SOAP_STR_EOS : "new ", name, value ? value : "(null)", domain ? domain : "(null)", path ? path : "(null)"));
|
|
6258 if (!q)
|
|
6259 { if ((q = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie))))
|
|
6260 { if ((q->name = (char*)SOAP_MALLOC(soap, strlen(name)+1)))
|
|
6261 strcpy(q->name, name);
|
|
6262 q->value = NULL;
|
|
6263 q->domain = NULL;
|
|
6264 q->path = NULL;
|
|
6265 q->expire = 0;
|
|
6266 q->maxage = -1;
|
|
6267 q->version = 1;
|
|
6268 q->secure = 0;
|
|
6269 q->modified = 0;
|
|
6270 for (p = &soap->cookies, n = soap->cookie_max; *p && n; p = &(*p)->next, n--)
|
|
6271 if (!strcmp((*p)->name, name) && (*p)->path && path && strcmp((*p)->path, path) < 0)
|
|
6272 break;
|
|
6273 if (n)
|
|
6274 { q->next = *p;
|
|
6275 *p = q;
|
|
6276 }
|
|
6277 else
|
|
6278 { SOAP_FREE(soap, q->name);
|
|
6279 SOAP_FREE(soap, q);
|
|
6280 q = NULL;
|
|
6281 }
|
|
6282 }
|
|
6283 }
|
|
6284 else
|
|
6285 q->modified = 1;
|
|
6286 if (q)
|
|
6287 { if (q->value)
|
|
6288 { if (!value || strcmp(value, q->value))
|
|
6289 { SOAP_FREE(soap, q->value);
|
|
6290 q->value = NULL;
|
|
6291 }
|
|
6292 }
|
|
6293 if (value && *value && !q->value && (q->value = (char*)SOAP_MALLOC(soap, strlen(value)+1)))
|
|
6294 strcpy(q->value, value);
|
|
6295 if (q->domain)
|
|
6296 { if (!domain || strcmp(domain, q->domain))
|
|
6297 { SOAP_FREE(soap, q->domain);
|
|
6298 q->domain = NULL;
|
|
6299 }
|
|
6300 }
|
|
6301 if (domain && !q->domain && (q->domain = (char*)SOAP_MALLOC(soap, strlen(domain)+1)))
|
|
6302 strcpy(q->domain, domain);
|
|
6303 if (q->path)
|
|
6304 { if (!path || strncmp(path, q->path, strlen(q->path)))
|
|
6305 { SOAP_FREE(soap, q->path);
|
|
6306 q->path = NULL;
|
|
6307 }
|
|
6308 }
|
|
6309 if (path && !q->path && (q->path = (char*)SOAP_MALLOC(soap, strlen(path)+1)))
|
|
6310 strcpy(q->path, path);
|
|
6311 q->session = 1;
|
|
6312 q->env = 0;
|
|
6313 }
|
|
6314 return q;
|
|
6315 }
|
|
6316
|
|
6317 /******************************************************************************/
|
|
6318 SOAP_FMAC1
|
|
6319 void
|
|
6320 SOAP_FMAC2
|
|
6321 soap_clr_cookie(struct soap *soap, const char *name, const char *domain, const char *path)
|
|
6322 { struct soap_cookie **p, *q;
|
|
6323 if (!domain)
|
|
6324 domain = soap->cookie_domain;
|
|
6325 if (!domain)
|
|
6326 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error in clear cookie='%s': cookie domain not set\n", name ? name : "(null)"));
|
|
6327 return;
|
|
6328 }
|
|
6329 if (!path)
|
|
6330 path = soap->cookie_path;
|
|
6331 if (!path)
|
|
6332 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error in clear cookie='%s': cookie path not set\n", name ? name : "(null)"));
|
|
6333 return;
|
|
6334 }
|
|
6335 if (*path == '/')
|
|
6336 path++;
|
|
6337 for (p = &soap->cookies, q = *p; q; q = *p)
|
|
6338 { if (!strcmp(q->name, name) && !strcmp(q->domain, domain) && !strncmp(q->path, path, strlen(q->path)))
|
|
6339 { if (q->value)
|
|
6340 SOAP_FREE(soap, q->value);
|
|
6341 if (q->domain)
|
|
6342 SOAP_FREE(soap, q->domain);
|
|
6343 if (q->path)
|
|
6344 SOAP_FREE(soap, q->path);
|
|
6345 *p = q->next;
|
|
6346 SOAP_FREE(soap, q);
|
|
6347 }
|
|
6348 else
|
|
6349 p = &q->next;
|
|
6350 }
|
|
6351 }
|
|
6352
|
|
6353 /******************************************************************************/
|
|
6354 SOAP_FMAC1
|
|
6355 char *
|
|
6356 SOAP_FMAC2
|
|
6357 soap_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path)
|
|
6358 { struct soap_cookie *p;
|
|
6359 if ((p = soap_cookie(soap, name, domain, path)))
|
|
6360 return p->value;
|
|
6361 return NULL;
|
|
6362 }
|
|
6363
|
|
6364 /******************************************************************************/
|
|
6365 SOAP_FMAC1
|
|
6366 char *
|
|
6367 SOAP_FMAC2
|
|
6368 soap_env_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path)
|
|
6369 { struct soap_cookie *p;
|
|
6370 if ((p = soap_cookie(soap, name, domain, path)) && p->env)
|
|
6371 return p->value;
|
|
6372 return NULL;
|
|
6373 }
|
|
6374
|
|
6375 /******************************************************************************/
|
|
6376 SOAP_FMAC1
|
|
6377 time_t
|
|
6378 SOAP_FMAC2
|
|
6379 soap_cookie_expire(struct soap *soap, const char *name, const char *domain, const char *path)
|
|
6380 { struct soap_cookie *p;
|
|
6381 if ((p = soap_cookie(soap, name, domain, path)))
|
|
6382 return p->expire;
|
|
6383 return -1;
|
|
6384 }
|
|
6385
|
|
6386 /******************************************************************************/
|
|
6387 SOAP_FMAC1
|
|
6388 int
|
|
6389 SOAP_FMAC2
|
|
6390 soap_set_cookie_expire(struct soap *soap, const char *name, long expire, const char *domain, const char *path)
|
|
6391 { struct soap_cookie *p;
|
|
6392 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set cookie expiration max-age=%ld: cookie='%s' domain='%s' path='%s'\n", expire, name, domain ? domain : "(null)", path ? path : "(null)"));
|
|
6393 if ((p = soap_cookie(soap, name, domain, path)))
|
|
6394 { p->maxage = expire;
|
|
6395 p->modified = 1;
|
|
6396 return SOAP_OK;
|
|
6397 }
|
|
6398 return SOAP_ERR;
|
|
6399 }
|
|
6400
|
|
6401 /******************************************************************************/
|
|
6402 SOAP_FMAC1
|
|
6403 int
|
|
6404 SOAP_FMAC2
|
|
6405 soap_set_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path)
|
|
6406 { struct soap_cookie *p;
|
|
6407 if ((p = soap_cookie(soap, name, domain, path)))
|
|
6408 { p->session = 1;
|
|
6409 p->modified = 1;
|
|
6410 return SOAP_OK;
|
|
6411 }
|
|
6412 return SOAP_ERR;
|
|
6413 }
|
|
6414
|
|
6415 /******************************************************************************/
|
|
6416 SOAP_FMAC1
|
|
6417 int
|
|
6418 SOAP_FMAC2
|
|
6419 soap_clr_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path)
|
|
6420 { struct soap_cookie *p;
|
|
6421 if ((p = soap_cookie(soap, name, domain, path)))
|
|
6422 { p->session = 0;
|
|
6423 p->modified = 1;
|
|
6424 return SOAP_OK;
|
|
6425 }
|
|
6426 return SOAP_ERR;
|
|
6427 }
|
|
6428
|
|
6429 /******************************************************************************/
|
|
6430 SOAP_FMAC1
|
|
6431 int
|
|
6432 SOAP_FMAC2
|
|
6433 soap_putsetcookies(struct soap *soap)
|
|
6434 { struct soap_cookie *p;
|
|
6435 char *s, tmp[4096];
|
|
6436 const char *t;
|
|
6437 for (p = soap->cookies; p; p = p->next)
|
|
6438 {
|
|
6439 if (p->modified
|
|
6440 #ifdef WITH_OPENSSL
|
|
6441 || (!p->env && !soap->ssl == !p->secure)
|
|
6442 #endif
|
|
6443 )
|
|
6444 { s = tmp;
|
|
6445 if (p->name)
|
|
6446 s += soap_encode_url(p->name, s, tmp-s+4064);
|
|
6447 if (p->value && *p->value)
|
|
6448 { *s++ = '=';
|
|
6449 s += soap_encode_url(p->value, s, tmp-s+4064);
|
|
6450 }
|
|
6451 if (p->domain && (int)strlen(p->domain) < tmp-s+4064)
|
|
6452 { strcpy(s, ";Domain=");
|
|
6453 strcat(s, p->domain);
|
|
6454 }
|
|
6455 else if (soap->cookie_domain && (int)strlen(soap->cookie_domain) < tmp-s+4064)
|
|
6456 { strcpy(s, ";Domain=");
|
|
6457 strcat(s, soap->cookie_domain);
|
|
6458 }
|
|
6459 strcat(s, ";Path=/");
|
|
6460 s += strlen(s);
|
|
6461 if (p->path)
|
|
6462 t = p->path;
|
|
6463 else
|
|
6464 t = soap->cookie_path;
|
|
6465 if (t)
|
|
6466 { if (*t == '/')
|
|
6467 t++;
|
|
6468 if ((int)strlen(t) < tmp-s+4064)
|
|
6469 { if (strchr(t, '%')) /* already URL encoded? */
|
|
6470 { strcpy(s, t);
|
|
6471 s += strlen(s);
|
|
6472 }
|
|
6473 else
|
|
6474 s += soap_encode_url(t, s, tmp-s+4064);
|
|
6475 }
|
|
6476 }
|
|
6477 if (p->version > 0 && s-tmp < 4060)
|
|
6478 {
|
|
6479 #ifdef HAVE_SNPRINTF
|
|
6480 soap_snprintf(s, 4096 - (s-tmp), ";Version=%u", p->version);
|
|
6481 #else
|
|
6482 sprintf(s, ";Version=%u", p->version);
|
|
6483 #endif
|
|
6484 s += strlen(s);
|
|
6485 }
|
|
6486 if (p->maxage >= 0 && s-tmp < 4060)
|
|
6487 {
|
|
6488 #ifdef HAVE_SNPRINTF
|
|
6489 soap_snprintf(s, 4096 - (s-tmp), ";Max-Age=%ld", p->maxage);
|
|
6490 #else
|
|
6491 sprintf(s, ";Max-Age=%ld", p->maxage);
|
|
6492 #endif
|
|
6493 s += strlen(s);
|
|
6494 }
|
|
6495 if (s-tmp < 4073
|
|
6496 && (p->secure
|
|
6497 #ifdef WITH_OPENSSL
|
|
6498 || soap->ssl
|
|
6499 #endif
|
|
6500 ))
|
|
6501 strcpy(s, ";Secure");
|
|
6502 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set-Cookie: %s\n", tmp));
|
|
6503 if ((soap->error = soap->fposthdr(soap, "Set-Cookie", tmp)))
|
|
6504 return soap->error;
|
|
6505 }
|
|
6506 }
|
|
6507 return SOAP_OK;
|
|
6508 }
|
|
6509
|
|
6510 /******************************************************************************/
|
|
6511 SOAP_FMAC1
|
|
6512 int
|
|
6513 SOAP_FMAC2
|
|
6514 soap_putcookies(struct soap *soap, const char *domain, const char *path, int secure)
|
|
6515 { struct soap_cookie **p, *q;
|
|
6516 unsigned int version = 0;
|
|
6517 time_t now = time(NULL);
|
|
6518 char *s, tmp[4096];
|
|
6519 if (!domain || !path)
|
|
6520 return SOAP_OK;
|
|
6521 s = tmp;
|
|
6522 p = &soap->cookies;
|
|
6523 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending cookies for domain='%s' path='%s'\n", domain, path));
|
|
6524 if (*path == '/')
|
|
6525 path++;
|
|
6526 while ((q = *p))
|
|
6527 { if (q->expire && now > q->expire)
|
|
6528 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie %s expired\n", q->name));
|
|
6529 SOAP_FREE(soap, q->name);
|
|
6530 if (q->value)
|
|
6531 SOAP_FREE(soap, q->value);
|
|
6532 if (q->domain)
|
|
6533 SOAP_FREE(soap, q->domain);
|
|
6534 if (q->path)
|
|
6535 SOAP_FREE(soap, q->path);
|
|
6536 *p = q->next;
|
|
6537 SOAP_FREE(soap, q);
|
|
6538 }
|
|
6539 else
|
|
6540 { int flag;
|
|
6541 char *t = q->domain;
|
|
6542 size_t n = 0;
|
|
6543 if (!t)
|
|
6544 flag = 1;
|
|
6545 else
|
|
6546 { const char *r = strchr(t, ':');
|
|
6547 if (r)
|
|
6548 n = r - t;
|
|
6549 else
|
|
6550 n = strlen(t);
|
|
6551 flag = !strncmp(t, domain, n);
|
|
6552 }
|
|
6553 /* domain-level cookies, cannot compile when WITH_NOIO set */
|
|
6554 #ifndef WITH_NOIO
|
|
6555 if (!flag)
|
|
6556 { struct hostent *hostent = gethostbyname((char*)domain);
|
|
6557 if (hostent)
|
|
6558 { const char *r = strchr(hostent->h_name, '.');
|
|
6559 if (!r)
|
|
6560 r = hostent->h_name;
|
|
6561 flag = !strncmp(t, r, n);
|
|
6562 }
|
|
6563 }
|
|
6564 #endif
|
|
6565 if (flag
|
|
6566 && (!q->path || !strncmp(q->path, path, strlen(q->path)))
|
|
6567 && (!q->secure || secure))
|
|
6568 { size_t n = 12;
|
|
6569 if (q->name)
|
|
6570 n += 3*strlen(q->name);
|
|
6571 if (q->value && *q->value)
|
|
6572 n += 3*strlen(q->value) + 1;
|
|
6573 if (q->path && *q->path)
|
|
6574 n += strlen(q->path) + 9;
|
|
6575 if (q->domain)
|
|
6576 n += strlen(q->domain) + 11;
|
|
6577 if (tmp - s + n > sizeof(tmp))
|
|
6578 { if (s == tmp)
|
|
6579 return SOAP_OK; /* HTTP header size overflow */
|
|
6580 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie: %s\n", tmp));
|
|
6581 if ((soap->error = soap->fposthdr(soap, "Cookie", tmp)))
|
|
6582 return soap->error;
|
|
6583 s = tmp;
|
|
6584 }
|
|
6585 else if (s != tmp)
|
|
6586 { strcat(s, " ");
|
|
6587 s++;
|
|
6588 }
|
|
6589 if (q->version != version && s-tmp < 4060)
|
|
6590 {
|
|
6591 #ifdef HAVE_SNPRINTF
|
|
6592 soap_snprintf(s, 4096 - (s-tmp), "$Version=%u;", q->version);
|
|
6593 #else
|
|
6594 sprintf(s, "$Version=%u;", q->version);
|
|
6595 #endif
|
|
6596 version = q->version;
|
|
6597 s += strlen(s);
|
|
6598 }
|
|
6599 if (q->name)
|
|
6600 s += soap_encode_url(q->name, s, tmp+sizeof(tmp)-s-16);
|
|
6601 if (q->value && *q->value)
|
|
6602 { *s++ = '=';
|
|
6603 s += soap_encode_url(q->value, s, tmp+sizeof(tmp)-s-16);
|
|
6604 }
|
|
6605 if (q->path && (s-tmp) + strlen(q->path) < 4060)
|
|
6606 {
|
|
6607 #ifdef HAVE_SNPRINTF
|
|
6608 soap_snprintf(s, 4096 - (s-tmp), ";$Path=\"/%s\"", (*q->path == '/' ? q->path + 1 : q->path));
|
|
6609 #else
|
|
6610 sprintf(s, ";$Path=\"/%s\"", (*q->path == '/' ? q->path + 1 : q->path));
|
|
6611 #endif
|
|
6612 s += strlen(s);
|
|
6613 }
|
|
6614 if (q->domain && (s-tmp) + strlen(q->domain) < 4060)
|
|
6615 {
|
|
6616 #ifdef HAVE_SNPRINTF
|
|
6617 soap_snprintf(s, 4096 - (s-tmp), ";$Domain=\"%s\"", q->domain);
|
|
6618 #else
|
|
6619 sprintf(s, ";$Domain=\"%s\"", q->domain);
|
|
6620 #endif
|
|
6621 s += strlen(s);
|
|
6622 }
|
|
6623 }
|
|
6624 p = &q->next;
|
|
6625 }
|
|
6626 }
|
|
6627 if (s != tmp)
|
|
6628 if ((soap->error = soap->fposthdr(soap, "Cookie", tmp)))
|
|
6629 return soap->error;
|
|
6630 return SOAP_OK;
|
|
6631 }
|
|
6632
|
|
6633 /******************************************************************************/
|
|
6634 SOAP_FMAC1
|
|
6635 void
|
|
6636 SOAP_FMAC2
|
|
6637 soap_getcookies(struct soap *soap, const char *val)
|
|
6638 { struct soap_cookie *p = NULL, *q;
|
|
6639 const char *s;
|
|
6640 char *t, tmp[4096]; /* cookie size is up to 4096 bytes [RFC2109] */
|
|
6641 char *domain = NULL;
|
|
6642 char *path = NULL;
|
|
6643 unsigned int version = 0;
|
|
6644 time_t now = time(NULL);
|
|
6645 if (!val)
|
|
6646 return;
|
|
6647 s = val;
|
|
6648 while (*s)
|
|
6649 { s = soap_decode_key(tmp, sizeof(tmp), s);
|
|
6650 if (!soap_tag_cmp(tmp, "$Version"))
|
|
6651 { if ((s = soap_decode_val(tmp, sizeof(tmp), s)))
|
|
6652 { if (p)
|
|
6653 p->version = (int)soap_strtol(tmp, NULL, 10);
|
|
6654 else
|
|
6655 version = (int)soap_strtol(tmp, NULL, 10);
|
|
6656 }
|
|
6657 }
|
|
6658 else if (!soap_tag_cmp(tmp, "$Path"))
|
|
6659 { s = soap_decode_val(tmp, sizeof(tmp), s);
|
|
6660 if (*tmp)
|
|
6661 { if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1)))
|
|
6662 strcpy(t, tmp);
|
|
6663 }
|
|
6664 else
|
|
6665 t = NULL;
|
|
6666 if (p)
|
|
6667 { if (p->path)
|
|
6668 SOAP_FREE(soap, p->path);
|
|
6669 p->path = t;
|
|
6670 }
|
|
6671 else
|
|
6672 { if (path)
|
|
6673 SOAP_FREE(soap, path);
|
|
6674 path = t;
|
|
6675 }
|
|
6676 }
|
|
6677 else if (!soap_tag_cmp(tmp, "$Domain"))
|
|
6678 { s = soap_decode_val(tmp, sizeof(tmp), s);
|
|
6679 if (*tmp)
|
|
6680 { if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1)))
|
|
6681 strcpy(t, tmp);
|
|
6682 }
|
|
6683 else
|
|
6684 t = NULL;
|
|
6685 if (p)
|
|
6686 { if (p->domain)
|
|
6687 SOAP_FREE(soap, p->domain);
|
|
6688 p->domain = t;
|
|
6689 }
|
|
6690 else
|
|
6691 { if (domain)
|
|
6692 SOAP_FREE(soap, domain);
|
|
6693 domain = t;
|
|
6694 }
|
|
6695 }
|
|
6696 else if (p && !soap_tag_cmp(tmp, "Path"))
|
|
6697 { if (p->path)
|
|
6698 SOAP_FREE(soap, p->path);
|
|
6699 s = soap_decode_val(tmp, sizeof(tmp), s);
|
|
6700 if (*tmp)
|
|
6701 { if ((p->path = (char*)SOAP_MALLOC(soap, strlen(tmp)+1)))
|
|
6702 strcpy(p->path, tmp);
|
|
6703 }
|
|
6704 else
|
|
6705 p->path = NULL;
|
|
6706 }
|
|
6707 else if (p && !soap_tag_cmp(tmp, "Domain"))
|
|
6708 { if (p->domain)
|
|
6709 SOAP_FREE(soap, p->domain);
|
|
6710 s = soap_decode_val(tmp, sizeof(tmp), s);
|
|
6711 if (*tmp)
|
|
6712 { if ((p->domain = (char*)SOAP_MALLOC(soap, strlen(tmp)+1)))
|
|
6713 strcpy(p->domain, tmp);
|
|
6714 }
|
|
6715 else
|
|
6716 p->domain = NULL;
|
|
6717 }
|
|
6718 else if (p && !soap_tag_cmp(tmp, "Version"))
|
|
6719 { s = soap_decode_val(tmp, sizeof(tmp), s);
|
|
6720 p->version = (unsigned int)soap_strtoul(tmp, NULL, 10);
|
|
6721 }
|
|
6722 else if (p && !soap_tag_cmp(tmp, "Max-Age"))
|
|
6723 { s = soap_decode_val(tmp, sizeof(tmp), s);
|
|
6724 p->expire = now + soap_strtol(tmp, NULL, 10);
|
|
6725 }
|
|
6726 else if (p && !soap_tag_cmp(tmp, "Expires"))
|
|
6727 { struct tm T;
|
|
6728 char a[3];
|
|
6729 static const char mns[] = "anebarprayunulugepctovec";
|
|
6730 s = soap_decode_val(tmp, sizeof(tmp), s);
|
|
6731 if (strlen(tmp) > 20)
|
|
6732 { memset((void*)&T, 0, sizeof(T));
|
|
6733 a[0] = tmp[4];
|
|
6734 a[1] = tmp[5];
|
|
6735 a[2] = '\0';
|
|
6736 T.tm_mday = (int)soap_strtol(a, NULL, 10);
|
|
6737 a[0] = tmp[8];
|
|
6738 a[1] = tmp[9];
|
|
6739 T.tm_mon = (int)(strstr(mns, a) - mns) / 2;
|
|
6740 a[0] = tmp[11];
|
|
6741 a[1] = tmp[12];
|
|
6742 T.tm_year = 100 + (int)soap_strtol(a, NULL, 10);
|
|
6743 a[0] = tmp[13];
|
|
6744 a[1] = tmp[14];
|
|
6745 T.tm_hour = (int)soap_strtol(a, NULL, 10);
|
|
6746 a[0] = tmp[16];
|
|
6747 a[1] = tmp[17];
|
|
6748 T.tm_min = (int)soap_strtol(a, NULL, 10);
|
|
6749 a[0] = tmp[19];
|
|
6750 a[1] = tmp[20];
|
|
6751 T.tm_sec = (int)soap_strtol(a, NULL, 10);
|
|
6752 p->expire = soap_timegm(&T);
|
|
6753 }
|
|
6754 }
|
|
6755 else if (p && !soap_tag_cmp(tmp, "Secure"))
|
|
6756 p->secure = 1;
|
|
6757 else
|
|
6758 { if (p)
|
|
6759 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie='%s' value='%s' domain='%s' path='%s' expire=%ld secure=%d\n", p->name, p->value ? p->value : "(null)", p->domain ? p->domain : "(null)", p->path ? p->path : "(null)", p->expire, p->secure));
|
|
6760 if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path)))
|
|
6761 { q->version = p->version;
|
|
6762 q->expire = p->expire;
|
|
6763 q->secure = p->secure;
|
|
6764 q->env = 1;
|
|
6765 }
|
|
6766 if (p->name)
|
|
6767 SOAP_FREE(soap, p->name);
|
|
6768 if (p->value)
|
|
6769 SOAP_FREE(soap, p->value);
|
|
6770 if (p->domain)
|
|
6771 SOAP_FREE(soap, p->domain);
|
|
6772 if (p->path)
|
|
6773 SOAP_FREE(soap, p->path);
|
|
6774 SOAP_FREE(soap, p);
|
|
6775 }
|
|
6776 if ((p = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie))))
|
|
6777 { p->name = (char*)SOAP_MALLOC(soap, strlen(tmp)+1);
|
|
6778 strcpy(p->name, tmp);
|
|
6779 s = soap_decode_val(tmp, sizeof(tmp), s);
|
|
6780 if (*tmp)
|
|
6781 { p->value = (char*)SOAP_MALLOC(soap, strlen(tmp)+1);
|
|
6782 strcpy(p->value, tmp);
|
|
6783 }
|
|
6784 else
|
|
6785 p->value = NULL;
|
|
6786 if (domain)
|
|
6787 p->domain = domain;
|
|
6788 else if (*soap->host)
|
|
6789 { p->domain = (char*)SOAP_MALLOC(soap, strlen(soap->host)+1);
|
|
6790 strcpy(p->domain, soap->host);
|
|
6791 }
|
|
6792 else
|
|
6793 p->domain = NULL;
|
|
6794 if (path)
|
|
6795 p->path = path;
|
|
6796 else if (soap->path && *soap->path)
|
|
6797 { p->path = (char*)SOAP_MALLOC(soap, strlen(soap->path)+1);
|
|
6798 strcpy(p->path, soap->path);
|
|
6799 }
|
|
6800 else
|
|
6801 { p->path = (char*)SOAP_MALLOC(soap, 2);
|
|
6802 strcpy(p->path, "/");
|
|
6803 }
|
|
6804 p->expire = 0;
|
|
6805 p->secure = 0;
|
|
6806 p->version = version;
|
|
6807 }
|
|
6808 }
|
|
6809 }
|
|
6810 if (p)
|
|
6811 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie='%s' value='%s' domain='%s' path='%s' expire=%ld secure=%d\n", p->name, p->value ? p->value : "(null)", p->domain ? p->domain : "(null)", p->path ? p->path : "(null)", p->expire, p->secure));
|
|
6812 if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path)))
|
|
6813 { q->version = p->version;
|
|
6814 q->expire = p->expire;
|
|
6815 q->secure = p->secure;
|
|
6816 q->env = 1;
|
|
6817 }
|
|
6818 if (p->name)
|
|
6819 SOAP_FREE(soap, p->name);
|
|
6820 if (p->value)
|
|
6821 SOAP_FREE(soap, p->value);
|
|
6822 if (p->domain)
|
|
6823 SOAP_FREE(soap, p->domain);
|
|
6824 if (p->path)
|
|
6825 SOAP_FREE(soap, p->path);
|
|
6826 SOAP_FREE(soap, p);
|
|
6827 }
|
|
6828 if (domain)
|
|
6829 SOAP_FREE(soap, domain);
|
|
6830 if (path)
|
|
6831 SOAP_FREE(soap, path);
|
|
6832 }
|
|
6833
|
|
6834 /******************************************************************************/
|
|
6835 SOAP_FMAC1
|
|
6836 int
|
|
6837 SOAP_FMAC2
|
|
6838 soap_getenv_cookies(struct soap *soap)
|
|
6839 { struct soap_cookie *p;
|
|
6840 const char *s;
|
|
6841 char key[4096], val[4096]; /* cookie size is up to 4096 bytes [RFC2109] */
|
|
6842 if (!(s = getenv("HTTP_COOKIE")))
|
|
6843 return SOAP_ERR;
|
|
6844 do
|
|
6845 { s = soap_decode_key(key, sizeof(key), s);
|
|
6846 s = soap_decode_val(val, sizeof(val), s);
|
|
6847 p = soap_set_cookie(soap, key, val, NULL, NULL);
|
|
6848 if (p)
|
|
6849 p->env = 1;
|
|
6850 } while (*s);
|
|
6851 return SOAP_OK;
|
|
6852 }
|
|
6853
|
|
6854 /******************************************************************************/
|
|
6855 SOAP_FMAC1
|
|
6856 struct soap_cookie*
|
|
6857 SOAP_FMAC2
|
|
6858 soap_copy_cookies(struct soap *copy, const struct soap *soap)
|
|
6859 { struct soap_cookie *p, **q, *r;
|
|
6860 q = &r;
|
|
6861 for (p = soap->cookies; p; p = p->next)
|
|
6862 { if (!(*q = (struct soap_cookie*)SOAP_MALLOC(copy, sizeof(struct soap_cookie))))
|
|
6863 return r;
|
|
6864 **q = *p;
|
|
6865 if (p->name)
|
|
6866 { if (((*q)->name = (char*)SOAP_MALLOC(copy, strlen(p->name)+1)))
|
|
6867 strcpy((*q)->name, p->name);
|
|
6868 }
|
|
6869 if (p->value)
|
|
6870 { if (((*q)->value = (char*)SOAP_MALLOC(copy, strlen(p->value)+1)))
|
|
6871 strcpy((*q)->value, p->value);
|
|
6872 }
|
|
6873 if (p->domain)
|
|
6874 { if (((*q)->domain = (char*)SOAP_MALLOC(copy, strlen(p->domain)+1)))
|
|
6875 strcpy((*q)->domain, p->domain);
|
|
6876 }
|
|
6877 if (p->path)
|
|
6878 { if (((*q)->path = (char*)SOAP_MALLOC(copy, strlen(p->path)+1)))
|
|
6879 strcpy((*q)->path, p->path);
|
|
6880 }
|
|
6881 q = &(*q)->next;
|
|
6882 }
|
|
6883 *q = NULL;
|
|
6884 return r;
|
|
6885 }
|
|
6886
|
|
6887 /******************************************************************************/
|
|
6888 SOAP_FMAC1
|
|
6889 void
|
|
6890 SOAP_FMAC2
|
|
6891 soap_free_cookies(struct soap *soap)
|
|
6892 { struct soap_cookie *p;
|
|
6893 for (p = soap->cookies; p; p = soap->cookies)
|
|
6894 { soap->cookies = p->next;
|
|
6895 SOAP_FREE(soap, p->name);
|
|
6896 if (p->value)
|
|
6897 SOAP_FREE(soap, p->value);
|
|
6898 if (p->domain)
|
|
6899 SOAP_FREE(soap, p->domain);
|
|
6900 if (p->path)
|
|
6901 SOAP_FREE(soap, p->path);
|
|
6902 SOAP_FREE(soap, p);
|
|
6903 }
|
|
6904 }
|
|
6905
|
|
6906 /******************************************************************************/
|
|
6907 #endif /* WITH_COOKIES */
|
|
6908
|
|
6909 /******************************************************************************/
|
|
6910 #ifndef WITH_NOIDREF
|
|
6911 #ifndef PALM_2
|
|
6912 SOAP_FMAC1
|
|
6913 size_t
|
|
6914 SOAP_FMAC2
|
|
6915 soap_hash(register const char *s)
|
|
6916 { register size_t h = 0;
|
|
6917 while (*s)
|
|
6918 h = 65599*h + *s++;
|
|
6919 return h % SOAP_IDHASH;
|
|
6920 }
|
|
6921 #endif
|
|
6922 #endif
|
|
6923
|
|
6924 /******************************************************************************/
|
|
6925 #ifndef WITH_NOIDREF
|
|
6926 #ifndef PALM_1
|
|
6927 static void
|
|
6928 soap_init_pht(struct soap *soap)
|
|
6929 { register int i;
|
|
6930 soap->pblk = NULL;
|
|
6931 soap->pidx = 0;
|
|
6932 for (i = 0; i < (int)SOAP_PTRHASH; i++)
|
|
6933 soap->pht[i] = NULL;
|
|
6934 }
|
|
6935 #endif
|
|
6936 #endif
|
|
6937
|
|
6938 /******************************************************************************/
|
|
6939 #ifndef PALM_1
|
|
6940 SOAP_FMAC1
|
|
6941 struct soap*
|
|
6942 SOAP_FMAC2
|
|
6943 soap_versioning(soap_new)(soap_mode imode, soap_mode omode)
|
|
6944 { struct soap *soap = (struct soap*)malloc(sizeof(struct soap));
|
|
6945 if (soap)
|
|
6946 soap_versioning(soap_init)(soap, imode, omode);
|
|
6947 return soap;
|
|
6948 }
|
|
6949 #endif
|
|
6950
|
|
6951 /******************************************************************************/
|
|
6952 #ifndef PALM_1
|
|
6953 SOAP_FMAC1
|
|
6954 void
|
|
6955 SOAP_FMAC2
|
|
6956 soap_free(struct soap *soap)
|
|
6957 { soap_done(soap);
|
|
6958 free(soap);
|
|
6959 }
|
|
6960 #endif
|
|
6961
|
|
6962 /******************************************************************************/
|
|
6963 #ifndef PALM_1
|
|
6964 SOAP_FMAC1
|
|
6965 void
|
|
6966 SOAP_FMAC2
|
|
6967 soap_del(struct soap *soap)
|
|
6968 { free(soap);
|
|
6969 }
|
|
6970 #endif
|
|
6971
|
|
6972 /******************************************************************************/
|
|
6973 #ifndef WITH_NOIDREF
|
|
6974 #ifndef PALM_1
|
|
6975 static void
|
|
6976 soap_free_pht(struct soap *soap)
|
|
6977 { register struct soap_pblk *pb, *next;
|
|
6978 register int i;
|
|
6979 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free pointer hashtable\n"));
|
|
6980 for (pb = soap->pblk; pb; pb = next)
|
|
6981 { next = pb->next;
|
|
6982 SOAP_FREE(soap, pb);
|
|
6983 }
|
|
6984 soap->pblk = NULL;
|
|
6985 soap->pidx = 0;
|
|
6986 for (i = 0; i < (int)SOAP_PTRHASH; i++)
|
|
6987 soap->pht[i] = NULL;
|
|
6988 }
|
|
6989 #endif
|
|
6990 #endif
|
|
6991
|
|
6992 /******************************************************************************/
|
|
6993 #ifndef WITH_NOIDREF
|
|
6994 #ifndef PALM_2
|
|
6995 SOAP_FMAC1
|
|
6996 int
|
|
6997 SOAP_FMAC2
|
|
6998 soap_embed(struct soap *soap, const void *p, const struct soap_array *a, int n, const char *tag, int type)
|
|
6999 { register int i;
|
|
7000 struct soap_plist *pp;
|
|
7001 (void)soap;
|
|
7002 if (soap->version == 2)
|
|
7003 soap->encoding = 1;
|
|
7004 if (a)
|
|
7005 i = soap_array_pointer_lookup(soap, p, a, n, type, &pp);
|
|
7006 else
|
|
7007 i = soap_pointer_lookup(soap, p, type, &pp);
|
|
7008 if (i)
|
|
7009 { if (soap_is_embedded(soap, pp)
|
|
7010 || soap_is_single(soap, pp))
|
|
7011 return 0;
|
|
7012 soap_set_embedded(soap, pp);
|
|
7013 }
|
|
7014 return i;
|
|
7015 }
|
|
7016 #endif
|
|
7017 #endif
|
|
7018
|
|
7019 /******************************************************************************/
|
|
7020 #ifndef WITH_NOIDREF
|
|
7021 #ifndef PALM_2
|
|
7022 SOAP_FMAC1
|
|
7023 int
|
|
7024 SOAP_FMAC2
|
|
7025 soap_pointer_lookup(struct soap *soap, const void *p, int type, struct soap_plist **ppp)
|
|
7026 { register struct soap_plist *pp;
|
|
7027 *ppp = NULL;
|
|
7028 if (p)
|
|
7029 { for (pp = soap->pht[soap_hash_ptr(p)]; pp; pp = pp->next)
|
|
7030 { if (pp->ptr == p && pp->type == type)
|
|
7031 { *ppp = pp;
|
|
7032 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d id=%d\n", p, type, pp->id));
|
|
7033 return pp->id;
|
|
7034 }
|
|
7035 }
|
|
7036 }
|
|
7037 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d: not found\n", p, type));
|
|
7038 return 0;
|
|
7039 }
|
|
7040 #endif
|
|
7041 #endif
|
|
7042
|
|
7043 /******************************************************************************/
|
|
7044 #ifndef WITH_NOIDREF
|
|
7045 #ifndef PALM_2
|
|
7046 SOAP_FMAC1
|
|
7047 int
|
|
7048 SOAP_FMAC2
|
|
7049 soap_pointer_enter(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp)
|
|
7050 { register size_t h;
|
|
7051 register struct soap_plist *pp;
|
|
7052 (void)n;
|
|
7053 if (!soap->pblk || soap->pidx >= SOAP_PTRBLK)
|
|
7054 { register struct soap_pblk *pb = (struct soap_pblk*)SOAP_MALLOC(soap, sizeof(struct soap_pblk));
|
|
7055 if (!pb)
|
|
7056 { soap->error = SOAP_EOM;
|
|
7057 return 0;
|
|
7058 }
|
|
7059 pb->next = soap->pblk;
|
|
7060 soap->pblk = pb;
|
|
7061 soap->pidx = 0;
|
|
7062 }
|
|
7063 *ppp = pp = &soap->pblk->plist[soap->pidx++];
|
|
7064 if (a)
|
|
7065 h = soap_hash_ptr(a->__ptr);
|
|
7066 else
|
|
7067 h = soap_hash_ptr(p);
|
|
7068 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pointer enter location=%p array=%p size=%d dim=%d type=%d id=%d\n", p, a ? a->__ptr : NULL, a ? a->__size : 0, n, type, soap->idnum+1));
|
|
7069 pp->next = soap->pht[h];
|
|
7070 pp->type = type;
|
|
7071 pp->mark1 = 0;
|
|
7072 pp->mark2 = 0;
|
|
7073 pp->ptr = p;
|
|
7074 pp->array = a;
|
|
7075 soap->pht[h] = pp;
|
|
7076 pp->id = ++soap->idnum;
|
|
7077 return pp->id;
|
|
7078 }
|
|
7079 #endif
|
|
7080 #endif
|
|
7081
|
|
7082 /******************************************************************************/
|
|
7083 #ifndef WITH_NOIDREF
|
|
7084 #ifndef PALM_2
|
|
7085 SOAP_FMAC1
|
|
7086 int
|
|
7087 SOAP_FMAC2
|
|
7088 soap_array_pointer_lookup(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp)
|
|
7089 { register struct soap_plist *pp;
|
|
7090 *ppp = NULL;
|
|
7091 if (!p || !a->__ptr)
|
|
7092 return 0;
|
|
7093 for (pp = soap->pht[soap_hash_ptr(a->__ptr)]; pp; pp = pp->next)
|
|
7094 { if (pp->type == type && pp->array && pp->array->__ptr == a->__ptr)
|
|
7095 { register int i;
|
|
7096 for (i = 0; i < n; i++)
|
|
7097 if (((const int*)&pp->array->__size)[i] != ((const int*)&a->__size)[i])
|
|
7098 break;
|
|
7099 if (i == n)
|
|
7100 { *ppp = pp;
|
|
7101 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d id=%d\n", a->__ptr, type, pp->id));
|
|
7102 return pp->id;
|
|
7103 }
|
|
7104 }
|
|
7105 }
|
|
7106 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d: not found\n", a->__ptr, type));
|
|
7107 return 0;
|
|
7108 }
|
|
7109 #endif
|
|
7110 #endif
|
|
7111
|
|
7112 /******************************************************************************/
|
|
7113 #ifndef PALM_1
|
|
7114 SOAP_FMAC1
|
|
7115 int
|
|
7116 SOAP_FMAC2
|
|
7117 soap_begin_count(struct soap *soap)
|
|
7118 { soap_free_ns(soap);
|
|
7119 #ifndef WITH_LEANER
|
|
7120 if ((soap->mode & SOAP_ENC_DIME) || (soap->omode & SOAP_ENC_DIME))
|
|
7121 soap->mode = soap->omode | SOAP_IO_LENGTH | SOAP_ENC_DIME;
|
|
7122 else
|
|
7123 #endif
|
|
7124 { soap->mode = soap->omode;
|
|
7125 if ((soap->mode & SOAP_IO_UDP))
|
|
7126 soap->mode |= SOAP_ENC_XML;
|
|
7127 if ((soap->mode & SOAP_IO) == SOAP_IO_STORE
|
|
7128 || (((soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_ENC_XML))
|
|
7129 #ifndef WITH_LEANER
|
|
7130 && !soap->fpreparesend
|
|
7131 #endif
|
|
7132 ))
|
|
7133 soap->mode &= ~SOAP_IO_LENGTH;
|
|
7134 else
|
|
7135 soap->mode |= SOAP_IO_LENGTH;
|
|
7136 }
|
|
7137 #ifdef WITH_ZLIB
|
|
7138 if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH)
|
|
7139 { if (!(soap->mode & SOAP_ENC_DIME))
|
|
7140 soap->mode &= ~SOAP_IO_LENGTH;
|
|
7141 if (soap->mode & SOAP_ENC_XML)
|
|
7142 soap->mode |= SOAP_IO_BUFFER;
|
|
7143 else
|
|
7144 soap->mode |= SOAP_IO_STORE;
|
|
7145 }
|
|
7146 #endif
|
|
7147 #ifndef WITH_LEANER
|
|
7148 if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME))
|
|
7149 soap->mode |= SOAP_ENC_MIME;
|
|
7150 else if (!(soap->mode & SOAP_ENC_MIME))
|
|
7151 soap->mode &= ~SOAP_ENC_MTOM;
|
|
7152 if (soap->mode & SOAP_ENC_MIME)
|
|
7153 soap_select_mime_boundary(soap);
|
|
7154 soap->dime.list = soap->dime.last; /* keep track of last DIME attachment */
|
|
7155 #endif
|
|
7156 soap->count = 0;
|
|
7157 soap->ns = 0;
|
|
7158 soap->null = 0;
|
|
7159 soap->position = 0;
|
|
7160 soap->mustUnderstand = 0;
|
|
7161 soap->encoding = 0;
|
|
7162 soap->part = SOAP_BEGIN;
|
|
7163 soap->event = 0;
|
|
7164 soap->evlev = 0;
|
|
7165 soap->idnum = 0;
|
|
7166 soap_clr_attr(soap);
|
|
7167 soap_set_local_namespaces(soap);
|
|
7168 #ifndef WITH_LEANER
|
|
7169 soap->dime.count = 0; /* count # of attachments */
|
|
7170 soap->dime.size = 0; /* accumulate total size of attachments */
|
|
7171 if (soap->fprepareinitsend && (soap->mode & SOAP_IO) != SOAP_IO_STORE && (soap->error = soap->fprepareinitsend(soap)))
|
|
7172 return soap->error;
|
|
7173 #endif
|
|
7174 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin count phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, (unsigned int)soap->mode, (unsigned long)soap->count));
|
|
7175 return SOAP_OK;
|
|
7176 }
|
|
7177 #endif
|
|
7178
|
|
7179 /******************************************************************************/
|
|
7180 #ifndef PALM_1
|
|
7181 SOAP_FMAC1
|
|
7182 int
|
|
7183 SOAP_FMAC2
|
|
7184 soap_end_count(struct soap *soap)
|
|
7185 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of count phase\n"));
|
|
7186 #ifndef WITH_LEANER
|
|
7187 if ((soap->mode & SOAP_IO_LENGTH))
|
|
7188 { if (soap->fpreparefinalsend && (soap->error = soap->fpreparefinalsend(soap)))
|
|
7189 return soap->error;
|
|
7190 }
|
|
7191 #endif
|
|
7192 return SOAP_OK;
|
|
7193 }
|
|
7194 #endif
|
|
7195
|
|
7196 /******************************************************************************/
|
|
7197 #ifndef PALM_1
|
|
7198 SOAP_FMAC1
|
|
7199 int
|
|
7200 SOAP_FMAC2
|
|
7201 soap_begin_send(struct soap *soap)
|
|
7202 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing for output to socket=%d/fd=%d\n", soap->socket, soap->sendfd));
|
|
7203 soap_free_ns(soap);
|
|
7204 soap->error = SOAP_OK;
|
|
7205 soap->mode = soap->omode | (soap->mode & (SOAP_IO_LENGTH | SOAP_ENC_DIME));
|
|
7206 #ifdef WITH_ZLIB
|
|
7207 if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH)
|
|
7208 { if (soap->mode & SOAP_ENC_XML)
|
|
7209 soap->mode |= SOAP_IO_BUFFER;
|
|
7210 else
|
|
7211 soap->mode |= SOAP_IO_STORE;
|
|
7212 }
|
|
7213 #endif
|
|
7214 #ifndef WITH_LEAN
|
|
7215 if ((soap->mode & SOAP_IO_UDP))
|
|
7216 { soap->mode |= SOAP_ENC_XML;
|
|
7217 if (soap->count > SOAP_BUFLEN)
|
|
7218 return soap->error = SOAP_UDP_ERROR;
|
|
7219 }
|
|
7220 #endif
|
|
7221 if ((soap->mode & SOAP_IO) == SOAP_IO_FLUSH && soap_valid_socket(soap->socket))
|
|
7222 { if (soap->count || (soap->mode & SOAP_IO_LENGTH) || (soap->mode & SOAP_ENC_XML))
|
|
7223 soap->mode |= SOAP_IO_BUFFER;
|
|
7224 else
|
|
7225 soap->mode |= SOAP_IO_STORE;
|
|
7226 }
|
|
7227 soap->mode &= ~SOAP_IO_LENGTH;
|
|
7228 if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
|
|
7229 if (soap_new_block(soap) == NULL)
|
|
7230 return soap->error;
|
|
7231 if (!(soap->mode & SOAP_IO_KEEPALIVE))
|
|
7232 soap->keep_alive = 0;
|
|
7233 #ifndef WITH_LEANER
|
|
7234 if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME))
|
|
7235 { soap->mode |= SOAP_ENC_MIME;
|
|
7236 soap->mode &= ~SOAP_ENC_DIME;
|
|
7237 }
|
|
7238 else if (!(soap->mode & SOAP_ENC_MIME))
|
|
7239 soap->mode &= ~SOAP_ENC_MTOM;
|
|
7240 if (soap->mode & SOAP_ENC_MIME)
|
|
7241 soap_select_mime_boundary(soap);
|
|
7242 #ifdef WIN32
|
|
7243 #ifndef UNDER_CE
|
|
7244 #ifndef WITH_FASTCGI
|
|
7245 if (!soap_valid_socket(soap->socket) && !soap->os) /* Set win32 stdout or soap->sendfd to BINARY, e.g. to support DIME */
|
|
7246 #ifdef __BORLANDC__
|
|
7247 setmode(soap->sendfd, _O_BINARY);
|
|
7248 #else
|
|
7249 _setmode(soap->sendfd, _O_BINARY);
|
|
7250 #endif
|
|
7251 #endif
|
|
7252 #endif
|
|
7253 #endif
|
|
7254 #endif
|
|
7255 if (soap->mode & SOAP_IO)
|
|
7256 { soap->bufidx = 0;
|
|
7257 soap->buflen = 0;
|
|
7258 }
|
|
7259 soap->chunksize = 0;
|
|
7260 soap->ns = 0;
|
|
7261 soap->null = 0;
|
|
7262 soap->position = 0;
|
|
7263 soap->mustUnderstand = 0;
|
|
7264 soap->encoding = 0;
|
|
7265 soap->idnum = 0;
|
|
7266 soap->level = 0;
|
|
7267 soap_clr_attr(soap);
|
|
7268 soap_set_local_namespaces(soap);
|
|
7269 #ifdef WITH_ZLIB
|
|
7270 soap->z_ratio_out = 1.0;
|
|
7271 if ((soap->mode & SOAP_ENC_ZLIB) && soap->zlib_state != SOAP_ZLIB_DEFLATE)
|
|
7272 { if (!soap->z_buf)
|
|
7273 soap->z_buf = (char*)SOAP_MALLOC(soap, SOAP_BUFLEN);
|
|
7274 soap->d_stream->next_out = (Byte*)soap->z_buf;
|
|
7275 soap->d_stream->avail_out = SOAP_BUFLEN;
|
|
7276 #ifdef WITH_GZIP
|
|
7277 if (soap->zlib_out != SOAP_ZLIB_DEFLATE)
|
|
7278 { memcpy(soap->z_buf, "\37\213\10\0\0\0\0\0\0\377", 10);
|
|
7279 soap->d_stream->next_out = (Byte*)soap->z_buf + 10;
|
|
7280 soap->d_stream->avail_out = SOAP_BUFLEN - 10;
|
|
7281 soap->z_crc = crc32(0L, NULL, 0);
|
|
7282 soap->zlib_out = SOAP_ZLIB_GZIP;
|
|
7283 if (soap->z_dict)
|
|
7284 *((Byte*)soap->z_buf + 2) = 0xff;
|
|
7285 if (deflateInit2(soap->d_stream, soap->z_level, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY) != Z_OK)
|
|
7286 return soap->error = SOAP_ZLIB_ERROR;
|
|
7287 }
|
|
7288 else
|
|
7289 #endif
|
|
7290 if (deflateInit(soap->d_stream, soap->z_level) != Z_OK)
|
|
7291 return soap->error = SOAP_ZLIB_ERROR;
|
|
7292 if (soap->z_dict)
|
|
7293 { if (deflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len) != Z_OK)
|
|
7294 return soap->error = SOAP_ZLIB_ERROR;
|
|
7295 }
|
|
7296 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflate initialized\n"));
|
|
7297 soap->zlib_state = SOAP_ZLIB_DEFLATE;
|
|
7298 }
|
|
7299 #endif
|
|
7300 #ifdef WITH_OPENSSL
|
|
7301 if (soap->ssl)
|
|
7302 ERR_clear_error();
|
|
7303 #endif
|
|
7304 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin send phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count));
|
|
7305 soap->part = SOAP_BEGIN;
|
|
7306 #ifndef WITH_LEANER
|
|
7307 if (soap->fprepareinitsend && (soap->mode & SOAP_IO) == SOAP_IO_STORE && (soap->error = soap->fprepareinitsend(soap)))
|
|
7308 return soap->error;
|
|
7309 #endif
|
|
7310 return SOAP_OK;
|
|
7311 }
|
|
7312 #endif
|
|
7313
|
|
7314 /******************************************************************************/
|
|
7315 #ifndef WITH_NOIDREF
|
|
7316 #ifndef PALM_2
|
|
7317 SOAP_FMAC1
|
|
7318 void
|
|
7319 SOAP_FMAC2
|
|
7320 soap_embedded(struct soap *soap, const void *p, int t)
|
|
7321 { struct soap_plist *pp;
|
|
7322 if (soap_pointer_lookup(soap, p, t, &pp))
|
|
7323 { pp->mark1 = 1;
|
|
7324 pp->mark2 = 1;
|
|
7325 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded %p type=%d mark set to 1\n", p, t));
|
|
7326 }
|
|
7327 }
|
|
7328 #endif
|
|
7329 #endif
|
|
7330
|
|
7331 /******************************************************************************/
|
|
7332 #ifndef WITH_NOIDREF
|
|
7333 #ifndef PALM_2
|
|
7334 SOAP_FMAC1
|
|
7335 int
|
|
7336 SOAP_FMAC2
|
|
7337 soap_reference(struct soap *soap, const void *p, int t)
|
|
7338 { struct soap_plist *pp;
|
|
7339 if (!p || (!soap->encodingStyle && !(soap->omode & (SOAP_ENC_DIME|SOAP_ENC_MIME|SOAP_ENC_MTOM|SOAP_XML_GRAPH))) || (soap->omode & SOAP_XML_TREE))
|
|
7340 return 1;
|
|
7341 if (soap_pointer_lookup(soap, p, t, &pp))
|
|
7342 { if (pp->mark1 == 0)
|
|
7343 { pp->mark1 = 2;
|
|
7344 pp->mark2 = 2;
|
|
7345 }
|
|
7346 }
|
|
7347 else if (!soap_pointer_enter(soap, p, NULL, 0, t, &pp))
|
|
7348 return 1;
|
|
7349 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reference %p type=%d (%d %d)\n", p, t, (int)pp->mark1, (int)pp->mark2));
|
|
7350 return pp->mark1;
|
|
7351 }
|
|
7352 #endif
|
|
7353 #endif
|
|
7354
|
|
7355 /******************************************************************************/
|
|
7356 #ifndef WITH_NOIDREF
|
|
7357 #ifndef PALM_2
|
|
7358 SOAP_FMAC1
|
|
7359 int
|
|
7360 SOAP_FMAC2
|
|
7361 soap_array_reference(struct soap *soap, const void *p, const struct soap_array *a, int n, int t)
|
|
7362 { struct soap_plist *pp;
|
|
7363 if (!p || !a->__ptr || (!soap->encodingStyle && !(soap->omode & (SOAP_ENC_DIME|SOAP_ENC_MIME|SOAP_ENC_MTOM|SOAP_XML_GRAPH))) || (soap->omode & SOAP_XML_TREE))
|
|
7364 return 1;
|
|
7365 if (soap_array_pointer_lookup(soap, p, a, n, t, &pp))
|
|
7366 { if (pp->mark1 == 0)
|
|
7367 { pp->mark1 = 2;
|
|
7368 pp->mark2 = 2;
|
|
7369 }
|
|
7370 }
|
|
7371 else if (!soap_pointer_enter(soap, p, a, n, t, &pp))
|
|
7372 return 1;
|
|
7373 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array reference %p ptr=%p dim=%d type=%d (%d %d)\n", p, a->__ptr, n, t, (int)pp->mark1, (int)pp->mark2));
|
|
7374 return pp->mark1;
|
|
7375 }
|
|
7376 #endif
|
|
7377 #endif
|
|
7378
|
|
7379 /******************************************************************************/
|
|
7380 #ifndef WITH_NOIDREF
|
|
7381 #ifndef PALM_2
|
|
7382 SOAP_FMAC1
|
|
7383 int
|
|
7384 SOAP_FMAC2
|
|
7385 soap_embedded_id(struct soap *soap, int id, const void *p, int t)
|
|
7386 { struct soap_plist *pp = NULL;
|
|
7387 if (!id || (!soap->encodingStyle && !(soap->omode & SOAP_XML_GRAPH)) || (soap->omode & SOAP_XML_TREE))
|
|
7388 return id;
|
|
7389 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id %p type=%d id=%d\n", p, t, id));
|
|
7390 if (soap->version == 1 && soap->part != SOAP_IN_HEADER)
|
|
7391 { if (id < 0)
|
|
7392 { id = soap_pointer_lookup(soap, p, t, &pp);
|
|
7393 if (id)
|
|
7394 { if (soap->mode & SOAP_IO_LENGTH)
|
|
7395 pp->mark1 = 2;
|
|
7396 else
|
|
7397 pp->mark2 = 2;
|
|
7398 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id multiref id=%d %p type=%d = (%d %d)\n", id, p, t, (int)pp->mark1, (int)pp->mark2));
|
|
7399 }
|
|
7400 return -1;
|
|
7401 }
|
|
7402 return id;
|
|
7403 }
|
|
7404 if (id < 0)
|
|
7405 id = soap_pointer_lookup(soap, p, t, &pp);
|
|
7406 else if (id && !soap_pointer_lookup(soap, p, t, &pp))
|
|
7407 return 0;
|
|
7408 if (id && pp)
|
|
7409 { if (soap->mode & SOAP_IO_LENGTH)
|
|
7410 pp->mark1 = 1;
|
|
7411 else
|
|
7412 pp->mark2 = 1;
|
|
7413 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id embedded ref id=%d %p type=%d = (%d %d)\n", id, p, t, (int)pp->mark1, (int)pp->mark2));
|
|
7414 }
|
|
7415 return id;
|
|
7416 }
|
|
7417 #endif
|
|
7418 #endif
|
|
7419
|
|
7420 /******************************************************************************/
|
|
7421 #ifndef WITH_NOIDREF
|
|
7422 #ifndef PALM_2
|
|
7423 SOAP_FMAC1
|
|
7424 int
|
|
7425 SOAP_FMAC2
|
|
7426 soap_is_embedded(struct soap *soap, struct soap_plist *pp)
|
|
7427 { if (!pp)
|
|
7428 return 0;
|
|
7429 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Is embedded? %d %d\n", (int)pp->mark1, (int)pp->mark2));
|
|
7430 if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER)
|
|
7431 { if (soap->mode & SOAP_IO_LENGTH)
|
|
7432 return pp->mark1 != 0;
|
|
7433 return pp->mark2 != 0;
|
|
7434 }
|
|
7435 if (soap->mode & SOAP_IO_LENGTH)
|
|
7436 return pp->mark1 == 1;
|
|
7437 return pp->mark2 == 1;
|
|
7438 }
|
|
7439 #endif
|
|
7440 #endif
|
|
7441
|
|
7442 /******************************************************************************/
|
|
7443 #ifndef WITH_NOIDREF
|
|
7444 #ifndef PALM_2
|
|
7445 SOAP_FMAC1
|
|
7446 int
|
|
7447 SOAP_FMAC2
|
|
7448 soap_is_single(struct soap *soap, struct soap_plist *pp)
|
|
7449 { if (soap->part == SOAP_IN_HEADER)
|
|
7450 return 1;
|
|
7451 if (!pp)
|
|
7452 return 0;
|
|
7453 if (soap->mode & SOAP_IO_LENGTH)
|
|
7454 return pp->mark1 == 0;
|
|
7455 return pp->mark2 == 0;
|
|
7456 }
|
|
7457 #endif
|
|
7458 #endif
|
|
7459
|
|
7460 /******************************************************************************/
|
|
7461 #ifndef WITH_NOIDREF
|
|
7462 #ifndef PALM_2
|
|
7463 SOAP_FMAC1
|
|
7464 void
|
|
7465 SOAP_FMAC2
|
|
7466 soap_set_embedded(struct soap *soap, struct soap_plist *pp)
|
|
7467 { if (!pp)
|
|
7468 return;
|
|
7469 if (soap->mode & SOAP_IO_LENGTH)
|
|
7470 pp->mark1 = 1;
|
|
7471 else
|
|
7472 pp->mark2 = 1;
|
|
7473 }
|
|
7474 #endif
|
|
7475 #endif
|
|
7476
|
|
7477 /******************************************************************************/
|
|
7478 #ifndef WITH_LEANER
|
|
7479 #ifndef PALM_1
|
|
7480 SOAP_FMAC1
|
|
7481 int
|
|
7482 SOAP_FMAC2
|
|
7483 soap_attachment(struct soap *soap, const char *tag, int id, const void *p, const struct soap_array *a, const char *aid, const char *atype, const char *aoptions, int n, const char *type, int t)
|
|
7484 {
|
|
7485 #ifndef WITH_NOIDREF
|
|
7486 struct soap_plist *pp;
|
|
7487 int i;
|
|
7488 if (!p || !a->__ptr || (!aid && !atype))
|
|
7489 return soap_element_id(soap, tag, id, p, a, n, type, t);
|
|
7490 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attachment tag='%s' id='%s' (%d) type='%s'\n", tag, aid ? aid : SOAP_STR_EOS, id, atype ? atype : SOAP_STR_EOS));
|
|
7491 i = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
|
|
7492 if (!i)
|
|
7493 { i = soap_pointer_enter(soap, p, a, n, t, &pp);
|
|
7494 if (!i)
|
|
7495 { soap->error = SOAP_EOM;
|
|
7496 return -1;
|
|
7497 }
|
|
7498 }
|
|
7499 if (id <= 0)
|
|
7500 id = i;
|
|
7501 if (!aid)
|
|
7502 {
|
|
7503 #ifdef HAVE_SNPRINTF
|
|
7504 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), soap->dime_id_format, id);
|
|
7505 #else
|
|
7506 sprintf(soap->tmpbuf, soap->dime_id_format, id);
|
|
7507 #endif
|
|
7508 aid = soap_strdup(soap, soap->tmpbuf);
|
|
7509 }
|
|
7510 /* Add MTOM xop:Include element when necessary */
|
|
7511 /* TODO: this code to be obsoleted with new import/xop.h conventions */
|
|
7512 if ((soap->mode & SOAP_ENC_MTOM) && strcmp(tag, "xop:Include"))
|
|
7513 { if (soap_element_begin_out(soap, tag, 0, type)
|
|
7514 || soap_element_href(soap, "xop:Include", 0, "xmlns:xop=\"http://www.w3.org/2004/08/xop/include\" href", aid)
|
|
7515 || soap_element_end_out(soap, tag))
|
|
7516 return soap->error;
|
|
7517 }
|
|
7518 else if (soap_element_href(soap, tag, 0, "href", aid))
|
|
7519 return soap->error;
|
|
7520 if (soap->mode & SOAP_IO_LENGTH)
|
|
7521 { if (pp->mark1 != 3)
|
|
7522 { struct soap_multipart *content;
|
|
7523 if (soap->mode & SOAP_ENC_MTOM)
|
|
7524 content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, (char*)a->__ptr, a->__size);
|
|
7525 else
|
|
7526 content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, (char*)a->__ptr, a->__size);
|
|
7527 if (!content)
|
|
7528 { soap->error = SOAP_EOM;
|
|
7529 return -1;
|
|
7530 }
|
|
7531 if (!strncmp(aid, "cid:", 4)) /* RFC 2111 */
|
|
7532 { if (soap->mode & SOAP_ENC_MTOM)
|
|
7533 { char *s = (char*)soap_malloc(soap, strlen(aid) - 1);
|
|
7534 if (s)
|
|
7535 { *s = '<';
|
|
7536 strcpy(s + 1, aid + 4);
|
|
7537 strcat(s, ">");
|
|
7538 content->id = s;
|
|
7539 }
|
|
7540 }
|
|
7541 else
|
|
7542 content->id = aid + 4;
|
|
7543 }
|
|
7544 else
|
|
7545 content->id = aid;
|
|
7546 content->type = atype;
|
|
7547 content->options = aoptions;
|
|
7548 content->encoding = SOAP_MIME_BINARY;
|
|
7549 pp->mark1 = 3;
|
|
7550 }
|
|
7551 }
|
|
7552 else
|
|
7553 pp->mark2 = 3;
|
|
7554 #endif
|
|
7555 return -1;
|
|
7556 }
|
|
7557 #endif
|
|
7558 #endif
|
|
7559
|
|
7560 /******************************************************************************/
|
|
7561 #ifndef WITH_NOIDREF
|
|
7562 #ifndef PALM_1
|
|
7563 static void
|
|
7564 soap_init_iht(struct soap *soap)
|
|
7565 { register int i;
|
|
7566 for (i = 0; i < SOAP_IDHASH; i++)
|
|
7567 soap->iht[i] = NULL;
|
|
7568 }
|
|
7569 #endif
|
|
7570 #endif
|
|
7571
|
|
7572 /******************************************************************************/
|
|
7573 #ifndef WITH_NOIDREF
|
|
7574 #ifndef PALM_1
|
|
7575 static void
|
|
7576 soap_free_iht(struct soap *soap)
|
|
7577 { register int i;
|
|
7578 register struct soap_ilist *ip = NULL, *p = NULL;
|
|
7579 register struct soap_flist *fp = NULL, *fq = NULL;
|
|
7580 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free ID hashtable\n"));
|
|
7581 for (i = 0; i < SOAP_IDHASH; i++)
|
|
7582 { for (ip = soap->iht[i]; ip; ip = p)
|
|
7583 { for (fp = ip->flist; fp; fp = fq)
|
|
7584 { fq = fp->next;
|
|
7585 SOAP_FREE(soap, fp);
|
|
7586 }
|
|
7587 p = ip->next;
|
|
7588 SOAP_FREE(soap, ip);
|
|
7589 }
|
|
7590 soap->iht[i] = NULL;
|
|
7591 }
|
|
7592 }
|
|
7593 #endif
|
|
7594 #endif
|
|
7595
|
|
7596 /******************************************************************************/
|
|
7597 #ifndef WITH_NOIDREF
|
|
7598 #ifndef PALM_2
|
|
7599 SOAP_FMAC1
|
|
7600 struct soap_ilist *
|
|
7601 SOAP_FMAC2
|
|
7602 soap_lookup(struct soap *soap, const char *id)
|
|
7603 { register struct soap_ilist *ip = NULL;
|
|
7604 for (ip = soap->iht[soap_hash(id)]; ip; ip = ip->next)
|
|
7605 if (!strcmp(ip->id, id))
|
|
7606 return ip;
|
|
7607 return NULL;
|
|
7608 }
|
|
7609 #endif
|
|
7610 #endif
|
|
7611
|
|
7612 /******************************************************************************/
|
|
7613 #ifndef WITH_NOIDREF
|
|
7614 #ifndef PALM_2
|
|
7615 SOAP_FMAC1
|
|
7616 struct soap_ilist *
|
|
7617 SOAP_FMAC2
|
|
7618 soap_enter(struct soap *soap, const char *id)
|
|
7619 { register size_t h;
|
|
7620 register struct soap_ilist *ip;
|
|
7621 ip = (struct soap_ilist*)SOAP_MALLOC(soap, sizeof(struct soap_ilist) + strlen(id));
|
|
7622 if (ip)
|
|
7623 { strcpy((char*)ip->id, id);
|
|
7624 h = soap_hash(id); /* h = (HASH(id) % SOAP_IDHASH) so soap->iht[h] is safe */
|
|
7625 ip->next = soap->iht[h];
|
|
7626 soap->iht[h] = ip;
|
|
7627 }
|
|
7628 return ip;
|
|
7629 }
|
|
7630 #endif
|
|
7631 #endif
|
|
7632
|
|
7633 /******************************************************************************/
|
|
7634 #ifndef PALM_2
|
|
7635 SOAP_FMAC1
|
|
7636 void*
|
|
7637 SOAP_FMAC2
|
|
7638 soap_malloc(struct soap *soap, size_t n)
|
|
7639 { register char *p;
|
|
7640 if (!n)
|
|
7641 return (void*)SOAP_NON_NULL;
|
|
7642 if (!soap)
|
|
7643 return SOAP_MALLOC(soap, n);
|
|
7644 if (soap->fmalloc)
|
|
7645 p = (char*)soap->fmalloc(soap, n);
|
|
7646 else
|
|
7647 { n += sizeof(short);
|
|
7648 n += (-(long)n) & (sizeof(void*)-1); /* align at 4-, 8- or 16-byte boundary */
|
|
7649 if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(void*) + sizeof(size_t))))
|
|
7650 { soap->error = SOAP_EOM;
|
|
7651 return NULL;
|
|
7652 }
|
|
7653 /* set the canary to detect corruption */
|
|
7654 *(unsigned short*)(p + n - sizeof(unsigned short)) = (unsigned short)SOAP_CANARY;
|
|
7655 /* keep chain of alloced cells for destruction */
|
|
7656 *(void**)(p + n) = soap->alist;
|
|
7657 *(size_t*)(p + n + sizeof(void*)) = n;
|
|
7658 soap->alist = p + n;
|
|
7659 }
|
|
7660 soap->alloced = 1;
|
|
7661 return p;
|
|
7662 }
|
|
7663 #endif
|
|
7664
|
|
7665 /******************************************************************************/
|
|
7666 #ifdef SOAP_MEM_DEBUG
|
|
7667 static void
|
|
7668 soap_init_mht(struct soap *soap)
|
|
7669 { register int i;
|
|
7670 for (i = 0; i < (int)SOAP_PTRHASH; i++)
|
|
7671 soap->mht[i] = NULL;
|
|
7672 }
|
|
7673 #endif
|
|
7674
|
|
7675 /******************************************************************************/
|
|
7676 #ifdef SOAP_MEM_DEBUG
|
|
7677 static void
|
|
7678 soap_free_mht(struct soap *soap)
|
|
7679 { register int i;
|
|
7680 register struct soap_mlist *mp, *mq;
|
|
7681 for (i = 0; i < (int)SOAP_PTRHASH; i++)
|
|
7682 { for (mp = soap->mht[i]; mp; mp = mq)
|
|
7683 { mq = mp->next;
|
|
7684 if (mp->live)
|
|
7685 fprintf(stderr, "%s(%d): malloc() = %p not freed (memory leak or forgot to call soap_end()?)\n", mp->file, mp->line, mp->ptr);
|
|
7686 free(mp);
|
|
7687 }
|
|
7688 soap->mht[i] = NULL;
|
|
7689 }
|
|
7690 }
|
|
7691 #endif
|
|
7692
|
|
7693 /******************************************************************************/
|
|
7694 #ifdef SOAP_MEM_DEBUG
|
|
7695 SOAP_FMAC1
|
|
7696 void*
|
|
7697 SOAP_FMAC2
|
|
7698 soap_track_malloc(struct soap *soap, const char *file, int line, size_t size)
|
|
7699 { register void *p = malloc(size);
|
|
7700 if (soap)
|
|
7701 { register size_t h = soap_hash_ptr(p);
|
|
7702 register struct soap_mlist *mp = (struct soap_mlist*)malloc(sizeof(struct soap_mlist));
|
|
7703 if (soap->fdebug[SOAP_INDEX_TEST])
|
|
7704 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): malloc(%lu) = %p\n", file, line, (unsigned long)size, p));
|
|
7705 }
|
|
7706 mp->next = soap->mht[h];
|
|
7707 mp->ptr = p;
|
|
7708 mp->file = file;
|
|
7709 mp->line = line;
|
|
7710 mp->live = 1;
|
|
7711 soap->mht[h] = mp;
|
|
7712 }
|
|
7713 return p;
|
|
7714 }
|
|
7715 #endif
|
|
7716
|
|
7717 /******************************************************************************/
|
|
7718 #ifdef SOAP_MEM_DEBUG
|
|
7719 SOAP_FMAC1
|
|
7720 void
|
|
7721 SOAP_FMAC2
|
|
7722 soap_track_free(struct soap *soap, const char *file, int line, void *p)
|
|
7723 { register size_t h = soap_hash_ptr(p);
|
|
7724 register struct soap_mlist *mp;
|
|
7725 for (mp = soap->mht[h]; mp; mp = mp->next)
|
|
7726 if (mp->ptr == p)
|
|
7727 break;
|
|
7728 if (mp)
|
|
7729 { if (mp->live)
|
|
7730 { free(p);
|
|
7731 if (soap->fdebug[SOAP_INDEX_TEST])
|
|
7732 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): free(%p)\n", file, line, p));
|
|
7733 }
|
|
7734 mp->live = 0;
|
|
7735 }
|
|
7736 else
|
|
7737 fprintf(stderr, "%s(%d): free(%p) double free of pointer malloced at %s(%d)\n", file, line, p, mp->file, mp->line);
|
|
7738 }
|
|
7739 else
|
|
7740 fprintf(stderr, "%s(%d): free(%p) pointer not malloced\n", file, line, p);
|
|
7741 }
|
|
7742 #endif
|
|
7743
|
|
7744 /******************************************************************************/
|
|
7745 #ifdef SOAP_MEM_DEBUG
|
|
7746 static void
|
|
7747 soap_track_unlink(struct soap *soap, const void *p)
|
|
7748 { register size_t h = soap_hash_ptr(p);
|
|
7749 register struct soap_mlist *mp;
|
|
7750 for (mp = soap->mht[h]; mp; mp = mp->next)
|
|
7751 if (mp->ptr == p)
|
|
7752 break;
|
|
7753 if (mp)
|
|
7754 mp->live = 0;
|
|
7755 }
|
|
7756 #endif
|
|
7757
|
|
7758 /******************************************************************************/
|
|
7759 #ifndef PALM_2
|
|
7760 SOAP_FMAC1
|
|
7761 void
|
|
7762 SOAP_FMAC2
|
|
7763 soap_dealloc(struct soap *soap, void *p)
|
|
7764 { if (soap_check_state(soap))
|
|
7765 return;
|
|
7766 if (p)
|
|
7767 { register char **q;
|
|
7768 for (q = (char**)&soap->alist; *q; q = *(char***)q)
|
|
7769 {
|
|
7770 if (*(unsigned short*)(char*)(*q - sizeof(unsigned short)) != (unsigned short)SOAP_CANARY)
|
|
7771 {
|
|
7772 #ifdef SOAP_MEM_DEBUG
|
|
7773 fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n");
|
|
7774 #endif
|
|
7775 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n"));
|
|
7776 DBGHEX(TEST, *q - 200, 200);
|
|
7777 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n"));
|
|
7778 soap->error = SOAP_MOE;
|
|
7779 return;
|
|
7780 }
|
|
7781 if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*))))
|
|
7782 { *q = **(char***)q;
|
|
7783 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Freed data at %p\n", p));
|
|
7784 SOAP_FREE(soap, p);
|
|
7785 return;
|
|
7786 }
|
|
7787 }
|
|
7788 soap_delete(soap, p);
|
|
7789 }
|
|
7790 else
|
|
7791 { register char *q;
|
|
7792 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free all soap_malloc() data\n"));
|
|
7793 while (soap->alist)
|
|
7794 { q = (char*)soap->alist;
|
|
7795 if (*(unsigned short*)(char*)(q - sizeof(unsigned short)) != (unsigned short)SOAP_CANARY)
|
|
7796 {
|
|
7797 #ifdef SOAP_MEM_DEBUG
|
|
7798 fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n");
|
|
7799 #endif
|
|
7800 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n"));
|
|
7801 DBGHEX(TEST, q - 200, 200);
|
|
7802 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n"));
|
|
7803 soap->error = SOAP_MOE;
|
|
7804 return;
|
|
7805 }
|
|
7806 soap->alist = *(void**)q;
|
|
7807 q -= *(size_t*)(q + sizeof(void*));
|
|
7808 SOAP_FREE(soap, q);
|
|
7809 }
|
|
7810 /* we must assume these were deallocated: */
|
|
7811 soap->http_content = NULL;
|
|
7812 soap->action = NULL;
|
|
7813 soap->fault = NULL;
|
|
7814 soap->header = NULL;
|
|
7815 soap->userid = NULL;
|
|
7816 soap->passwd = NULL;
|
|
7817 soap->authrealm = NULL;
|
|
7818 #ifdef WITH_NTLM
|
|
7819 soap->ntlm_challenge = NULL;
|
|
7820 #endif
|
|
7821 #ifndef WITH_LEANER
|
|
7822 soap_clr_mime(soap);
|
|
7823 #endif
|
|
7824 }
|
|
7825 }
|
|
7826 #endif
|
|
7827
|
|
7828 /******************************************************************************/
|
|
7829 #ifndef PALM_2
|
|
7830 SOAP_FMAC1
|
|
7831 void
|
|
7832 SOAP_FMAC2
|
|
7833 soap_delete(struct soap *soap, void *p)
|
|
7834 { register struct soap_clist **cp;
|
|
7835 if (soap_check_state(soap))
|
|
7836 return;
|
|
7837 cp = &soap->clist;
|
|
7838 if (p)
|
|
7839 { while (*cp)
|
|
7840 { if (p == (*cp)->ptr)
|
|
7841 { register struct soap_clist *q = *cp;
|
|
7842 *cp = q->next;
|
|
7843 if (q->fdelete(q))
|
|
7844 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: deletion callback failed for object type %d\n", q->ptr, q->type));
|
|
7845 #ifdef SOAP_MEM_DEBUG
|
|
7846 fprintf(stderr, "new(object type = %d) = %p not freed: deletion callback failed\n", q->type, q->ptr);
|
|
7847 #endif
|
|
7848 }
|
|
7849 SOAP_FREE(soap, q);
|
|
7850 return;
|
|
7851 }
|
|
7852 cp = &(*cp)->next;
|
|
7853 }
|
|
7854 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: address not in list\n", p));
|
|
7855 }
|
|
7856 else
|
|
7857 { while (*cp)
|
|
7858 { register struct soap_clist *q = *cp;
|
|
7859 *cp = q->next;
|
|
7860 if (q->fdelete(q))
|
|
7861 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: deletion callback failed for object type %d\n", q->ptr, q->type));
|
|
7862 #ifdef SOAP_MEM_DEBUG
|
|
7863 fprintf(stderr, "new(object type = %d) = %p not freed: deletion callback failed\n", q->type, q->ptr);
|
|
7864 #endif
|
|
7865 }
|
|
7866 SOAP_FREE(soap, q);
|
|
7867 }
|
|
7868 }
|
|
7869 soap->fault = NULL; /* this was possibly deallocated */
|
|
7870 soap->header = NULL; /* this was possibly deallocated */
|
|
7871 }
|
|
7872 #endif
|
|
7873
|
|
7874 /******************************************************************************/
|
|
7875 #ifndef PALM_2
|
|
7876 SOAP_FMAC1
|
|
7877 void
|
|
7878 SOAP_FMAC2
|
|
7879 soap_delegate_deletion(struct soap *soap, struct soap *soap_to)
|
|
7880 { register struct soap_clist *cp;
|
|
7881 register char **q;
|
|
7882 #ifdef SOAP_MEM_DEBUG
|
|
7883 register void *p;
|
|
7884 register struct soap_mlist **mp, *mq;
|
|
7885 size_t h;
|
|
7886 #endif
|
|
7887 for (q = (char**)&soap->alist; *q; q = *(char***)q)
|
|
7888 {
|
|
7889 if (*(unsigned short*)(char*)(*q - sizeof(unsigned short)) != (unsigned short)SOAP_CANARY)
|
|
7890 {
|
|
7891 #ifdef SOAP_MEM_DEBUG
|
|
7892 fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n");
|
|
7893 #endif
|
|
7894 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n"));
|
|
7895 DBGHEX(TEST, *q - 200, 200);
|
|
7896 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n"));
|
|
7897 soap->error = SOAP_MOE;
|
|
7898 return;
|
|
7899 }
|
|
7900 #ifdef SOAP_MEM_DEBUG
|
|
7901 p = (void*)(*q - *(size_t*)(*q + sizeof(void*)));
|
|
7902 h = soap_hash_ptr(p);
|
|
7903 for (mp = &soap->mht[h]; *mp; mp = &(*mp)->next)
|
|
7904 { if ((*mp)->ptr == p)
|
|
7905 { mq = *mp;
|
|
7906 *mp = mq->next;
|
|
7907 mq->next = soap_to->mht[h];
|
|
7908 soap_to->mht[h] = mq;
|
|
7909 break;
|
|
7910 }
|
|
7911 }
|
|
7912 #endif
|
|
7913 }
|
|
7914 *q = (char*)soap_to->alist;
|
|
7915 soap_to->alist = soap->alist;
|
|
7916 soap->alist = NULL;
|
|
7917 #ifdef SOAP_MEM_DEBUG
|
|
7918 cp = soap->clist;
|
|
7919 while (cp)
|
|
7920 { h = soap_hash_ptr(cp);
|
|
7921 for (mp = &soap->mht[h]; *mp; mp = &(*mp)->next)
|
|
7922 { if ((*mp)->ptr == cp)
|
|
7923 { mq = *mp;
|
|
7924 *mp = mq->next;
|
|
7925 mq->next = soap_to->mht[h];
|
|
7926 soap_to->mht[h] = mq;
|
|
7927 break;
|
|
7928 }
|
|
7929 }
|
|
7930 cp = cp->next;
|
|
7931 }
|
|
7932 #endif
|
|
7933 cp = soap_to->clist;
|
|
7934 if (cp)
|
|
7935 { while (cp->next)
|
|
7936 cp = cp->next;
|
|
7937 cp->next = soap->clist;
|
|
7938 }
|
|
7939 else
|
|
7940 soap_to->clist = soap->clist;
|
|
7941 soap->clist = NULL;
|
|
7942 }
|
|
7943 #endif
|
|
7944
|
|
7945 /******************************************************************************/
|
|
7946 #ifndef PALM_2
|
|
7947 SOAP_FMAC1
|
|
7948 struct soap_clist *
|
|
7949 SOAP_FMAC2
|
|
7950 soap_link(struct soap *soap, void *p, int t, int n, int (*fdelete)(struct soap_clist*))
|
|
7951 { register struct soap_clist *cp;
|
|
7952 if ((cp = (struct soap_clist*)SOAP_MALLOC(soap, sizeof(struct soap_clist))))
|
|
7953 { cp->next = soap->clist;
|
|
7954 cp->type = t;
|
|
7955 cp->size = n;
|
|
7956 cp->ptr = p;
|
|
7957 cp->fdelete = fdelete;
|
|
7958 soap->clist = cp;
|
|
7959 }
|
|
7960 return cp;
|
|
7961 }
|
|
7962 #endif
|
|
7963
|
|
7964 /******************************************************************************/
|
|
7965 #ifndef PALM_2
|
|
7966 SOAP_FMAC1
|
|
7967 int
|
|
7968 SOAP_FMAC2
|
|
7969 soap_unlink(struct soap *soap, const void *p)
|
|
7970 { register char **q;
|
|
7971 register struct soap_clist **cp;
|
|
7972 if (soap && p)
|
|
7973 { for (q = (char**)&soap->alist; *q; q = *(char***)q)
|
|
7974 { if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*))))
|
|
7975 { *q = **(char***)q;
|
|
7976 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked data %p\n", p));
|
|
7977 #ifdef SOAP_MEM_DEBUG
|
|
7978 soap_track_unlink(soap, p);
|
|
7979 #endif
|
|
7980 return SOAP_OK; /* found and removed from dealloc chain */
|
|
7981 }
|
|
7982 }
|
|
7983 for (cp = &soap->clist; *cp; cp = &(*cp)->next)
|
|
7984 { if (p == (*cp)->ptr)
|
|
7985 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked class instance %p\n", p));
|
|
7986 q = (char**)*cp;
|
|
7987 *cp = (*cp)->next;
|
|
7988 SOAP_FREE(soap, q);
|
|
7989 return SOAP_OK; /* found and removed from dealloc chain */
|
|
7990 }
|
|
7991 }
|
|
7992 }
|
|
7993 return SOAP_ERR;
|
|
7994 }
|
|
7995 #endif
|
|
7996
|
|
7997 /******************************************************************************/
|
|
7998 #ifndef WITH_NOIDREF
|
|
7999 #ifndef PALM_2
|
|
8000 SOAP_FMAC1
|
|
8001 int
|
|
8002 SOAP_FMAC2
|
|
8003 soap_lookup_type(struct soap *soap, const char *id)
|
|
8004 { register struct soap_ilist *ip;
|
|
8005 if (id && *id)
|
|
8006 { ip = soap_lookup(soap, id);
|
|
8007 if (ip)
|
|
8008 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup id='%s' type=%d\n", id, ip->type));
|
|
8009 return ip->type;
|
|
8010 }
|
|
8011 }
|
|
8012 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "lookup type id='%s' NOT FOUND! Need to get it from xsi:type\n", id));
|
|
8013 return 0;
|
|
8014 }
|
|
8015 #endif
|
|
8016 #endif
|
|
8017
|
|
8018 /******************************************************************************/
|
|
8019 #ifndef WITH_NOIDREF
|
|
8020 #ifndef PALM_2
|
|
8021 SOAP_FMAC1
|
|
8022 void*
|
|
8023 SOAP_FMAC2
|
|
8024 soap_id_lookup(struct soap *soap, const char *id, void **p, int t, size_t n, unsigned int k)
|
|
8025 { struct soap_ilist *ip;
|
|
8026 void **q;
|
|
8027 if (!p || !id || !*id)
|
|
8028 return p;
|
|
8029 ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */
|
|
8030 if (!ip)
|
|
8031 { if (!(ip = soap_enter(soap, id))) /* new hash table entry for string id */
|
|
8032 return NULL;
|
|
8033 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding first href='%s' type=%d %p (%u bytes)\n", id, t, p, (unsigned int)n));
|
|
8034 ip->type = t;
|
|
8035 ip->size = n;
|
|
8036 ip->link = p;
|
|
8037 ip->copy = NULL;
|
|
8038 ip->flist = NULL;
|
|
8039 ip->ptr = NULL;
|
|
8040 ip->level = k;
|
|
8041 *p = NULL;
|
|
8042 }
|
|
8043 else if (ip->ptr)
|
|
8044 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolved href='%s' type=%d location=%p (%u bytes)\n", id, t, ip->ptr, (unsigned int)n));
|
|
8045 if (ip->type != t)
|
|
8046 { strcpy(soap->id, id);
|
|
8047 soap->error = SOAP_HREF;
|
|
8048 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility: href='%s' id-type=%d href-type=%d\n", id, ip->type, t));
|
|
8049 return NULL;
|
|
8050 }
|
|
8051 while (ip->level < k)
|
|
8052 { q = (void**)soap_malloc(soap, sizeof(void*));
|
|
8053 if (!q)
|
|
8054 return NULL;
|
|
8055 *p = (void*)q;
|
|
8056 p = q;
|
|
8057 k--;
|
|
8058 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n"));
|
|
8059 }
|
|
8060 *p = ip->ptr;
|
|
8061 }
|
|
8062 else if (ip->level > k)
|
|
8063 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving level %u pointers to href='%s'\n", ip->level, id));
|
|
8064 while (ip->level > k)
|
|
8065 { void *s, **r = &ip->link;
|
|
8066 q = (void**)ip->link;
|
|
8067 while (q)
|
|
8068 { *r = (void*)soap_malloc(soap, sizeof(void*));
|
|
8069 if (!*r)
|
|
8070 return NULL;
|
|
8071 s = *q;
|
|
8072 *q = *r;
|
|
8073 r = (void**)*r;
|
|
8074 q = (void**)s;
|
|
8075 }
|
|
8076 *r = NULL;
|
|
8077 ip->size = n;
|
|
8078 ip->copy = NULL;
|
|
8079 ip->level = ip->level - 1;
|
|
8080 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n"));
|
|
8081 }
|
|
8082 q = (void**)ip->link;
|
|
8083 ip->link = p;
|
|
8084 *p = (void*)q;
|
|
8085 }
|
|
8086 else
|
|
8087 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarded href='%s' type=%d location=%p (%u bytes)\n", id, t, p, (unsigned int)n));
|
|
8088 while (ip->level < k)
|
|
8089 { q = (void**)soap_malloc(soap, sizeof(void*));
|
|
8090 if (!q)
|
|
8091 return NULL;
|
|
8092 *p = q;
|
|
8093 p = q;
|
|
8094 k--;
|
|
8095 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n"));
|
|
8096 }
|
|
8097 q = (void**)ip->link;
|
|
8098 ip->link = p;
|
|
8099 *p = (void*)q;
|
|
8100 }
|
|
8101 return p;
|
|
8102 }
|
|
8103 #endif
|
|
8104 #endif
|
|
8105
|
|
8106 /******************************************************************************/
|
|
8107 #ifndef WITH_NOIDREF
|
|
8108 #ifndef PALM_2
|
|
8109 SOAP_FMAC1
|
|
8110 void*
|
|
8111 SOAP_FMAC2
|
|
8112 soap_id_forward(struct soap *soap, const char *href, void *p, size_t len, int st, int tt, size_t n, unsigned int k, void (*fcopy)(struct soap*, int, int, void*, size_t, const void*, size_t))
|
|
8113 { struct soap_ilist *ip;
|
|
8114 if (!p || !href || !*href)
|
|
8115 return p;
|
|
8116 ip = soap_lookup(soap, href); /* lookup pointer to hash table entry for string id */
|
|
8117 if (!ip)
|
|
8118 { if (!(ip = soap_enter(soap, href))) /* new hash table entry for string id */
|
|
8119 return NULL;
|
|
8120 ip->type = st;
|
|
8121 ip->size = n;
|
|
8122 ip->link = NULL;
|
|
8123 ip->copy = NULL;
|
|
8124 ip->ptr = NULL;
|
|
8125 ip->level = 0;
|
|
8126 ip->flist = NULL;
|
|
8127 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "New entry href='%s' type=%d size=%lu level=%d location=%p\n", href, st, (unsigned long)n, k, p));
|
|
8128 }
|
|
8129 else if (ip->type != st || (ip->level == k && ip->size != n))
|
|
8130 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n", href, ip->type, (unsigned long)ip->size, k, st, (unsigned long)n));
|
|
8131 strcpy(soap->id, href);
|
|
8132 soap->error = SOAP_HREF;
|
|
8133 return NULL;
|
|
8134 }
|
|
8135 if (fcopy || n < sizeof(void*) || *href != '#')
|
|
8136 { register struct soap_flist *fp = (struct soap_flist*)SOAP_MALLOC(soap, sizeof(struct soap_flist));
|
|
8137 if (!fp)
|
|
8138 { soap->error = SOAP_EOM;
|
|
8139 return NULL;
|
|
8140 }
|
|
8141 fp->next = ip->flist;
|
|
8142 fp->type = tt;
|
|
8143 fp->ptr = p;
|
|
8144 fp->level = k;
|
|
8145 fp->len = len;
|
|
8146 if (fcopy)
|
|
8147 fp->fcopy = fcopy;
|
|
8148 else
|
|
8149 fp->fcopy = soap_fcopy;
|
|
8150 ip->flist = fp;
|
|
8151 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding type=%d (target type=%d) size=%lu location=%p level=%u len=%lu href='%s'\n", st, tt, (unsigned long)n, p, k, (unsigned long)len, href));
|
|
8152 }
|
|
8153 else
|
|
8154 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding copying address %p for type=%d href='%s'\n", p, st, href));
|
|
8155 *(void**)p = ip->copy;
|
|
8156 ip->copy = p;
|
|
8157 }
|
|
8158 return p;
|
|
8159 }
|
|
8160 #endif
|
|
8161 #endif
|
|
8162
|
|
8163 /******************************************************************************/
|
|
8164 #ifndef PALM_2
|
|
8165 SOAP_FMAC1
|
|
8166 void*
|
|
8167 SOAP_FMAC2
|
|
8168 soap_id_enter(struct soap *soap, const char *id, void *p, int t, size_t n, unsigned int k, const char *type, const char *arrayType, void *(*finstantiate)(struct soap*, int, const char*, const char*, size_t*))
|
|
8169 {
|
|
8170 #ifndef WITH_NOIDREF
|
|
8171 struct soap_ilist *ip;
|
|
8172 #endif
|
|
8173 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Enter id='%s' type=%d loc=%p size=%lu level=%u\n", id, t, p, (unsigned long)n, k));
|
|
8174 soap->alloced = 0;
|
|
8175 if (!p)
|
|
8176 { if (finstantiate)
|
|
8177 p = finstantiate(soap, t, type, arrayType, &n);
|
|
8178 else
|
|
8179 p = soap_malloc(soap, n);
|
|
8180 if (p)
|
|
8181 soap->alloced = 1;
|
|
8182 }
|
|
8183 #ifndef WITH_NOIDREF
|
|
8184 if (!id || !*id)
|
|
8185 #endif
|
|
8186 return p;
|
|
8187 #ifndef WITH_NOIDREF
|
|
8188 ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */
|
|
8189 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Lookup entry id='%s for location=%p'\n", id, p));
|
|
8190 if (!ip)
|
|
8191 { if (!(ip = soap_enter(soap, id))) /* new hash table entry for string id */
|
|
8192 return NULL;
|
|
8193 ip->type = t;
|
|
8194 ip->link = NULL;
|
|
8195 ip->copy = NULL;
|
|
8196 ip->flist = NULL;
|
|
8197 ip->size = n;
|
|
8198 ip->ptr = p;
|
|
8199 ip->level = k;
|
|
8200 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "New entry id='%s' type=%d size=%lu level=%u location=%p\n", id, t, (unsigned long)n, k, p));
|
|
8201 }
|
|
8202 else if ((ip->type != t || (ip->level == k && ip->size != n)) && (ip->copy || ip->flist))
|
|
8203 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n", id, ip->type, (unsigned long)ip->size, k, t, (unsigned long)n));
|
|
8204 strcpy(soap->id, id);
|
|
8205 soap->error = SOAP_HREF;
|
|
8206 return NULL;
|
|
8207 }
|
|
8208 else if (ip->ptr)
|
|
8209 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Multiply defined id='%s'\n", id));
|
|
8210 strcpy(soap->id, id);
|
|
8211 soap->error = SOAP_DUPLICATE_ID;
|
|
8212 return NULL;
|
|
8213 }
|
|
8214 else
|
|
8215 { ip->size = n;
|
|
8216 ip->ptr = p;
|
|
8217 ip->level = k;
|
|
8218 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update entry id='%s' type=%d location=%p size=%lu level=%u\n", id, t, p, (unsigned long)n, k));
|
|
8219 }
|
|
8220 return ip->ptr;
|
|
8221 #endif
|
|
8222 }
|
|
8223 #endif
|
|
8224
|
|
8225 /******************************************************************************/
|
|
8226 #ifndef PALM_2
|
|
8227 SOAP_FMAC1
|
|
8228 void
|
|
8229 SOAP_FMAC2
|
|
8230 soap_fcopy(struct soap *soap, int st, int tt, void *p, size_t len, const void *q, size_t n)
|
|
8231 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Copying data type=%d (target type=%d) %p -> %p (%lu bytes)\n", st, tt, q, p, (unsigned long)n));
|
|
8232 memcpy(p, q, n);
|
|
8233 (void)soap; (void)st; (void)tt; (void)len;
|
|
8234 }
|
|
8235 #endif
|
|
8236
|
|
8237 /******************************************************************************/
|
|
8238 #ifndef PALM_1
|
|
8239 SOAP_FMAC1
|
|
8240 int
|
|
8241 SOAP_FMAC2
|
|
8242 soap_end_send(struct soap *soap)
|
|
8243 {
|
|
8244 #ifndef WITH_LEANER
|
|
8245 int err;
|
|
8246 if (soap->dime.list)
|
|
8247 { /* SOAP body referenced attachments must appear first */
|
|
8248 soap->dime.last->next = soap->dime.first;
|
|
8249 soap->dime.first = soap->dime.list->next;
|
|
8250 soap->dime.list->next = NULL;
|
|
8251 soap->dime.last = soap->dime.list;
|
|
8252 }
|
|
8253 if (!(err = soap_putdime(soap)))
|
|
8254 err = soap_putmime(soap);
|
|
8255 soap->mime.list = NULL;
|
|
8256 soap->mime.first = NULL;
|
|
8257 soap->mime.last = NULL;
|
|
8258 soap->dime.list = NULL;
|
|
8259 soap->dime.first = NULL;
|
|
8260 soap->dime.last = NULL;
|
|
8261 if (err)
|
|
8262 return err;
|
|
8263 #endif
|
|
8264 return soap_end_send_flush(soap);
|
|
8265 }
|
|
8266 #endif
|
|
8267
|
|
8268 /******************************************************************************/
|
|
8269 #ifndef PALM_1
|
|
8270 SOAP_FMAC1
|
|
8271 int
|
|
8272 SOAP_FMAC2
|
|
8273 soap_end_send_flush(struct soap *soap)
|
|
8274 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End send mode=0x%x\n", soap->mode));
|
|
8275 if (soap->mode & SOAP_IO) /* need to flush the remaining data in buffer */
|
|
8276 { if (soap_flush(soap))
|
|
8277 #ifdef WITH_ZLIB
|
|
8278 { if (soap->mode & SOAP_ENC_ZLIB && soap->zlib_state == SOAP_ZLIB_DEFLATE)
|
|
8279 { soap->zlib_state = SOAP_ZLIB_NONE;
|
|
8280 deflateEnd(soap->d_stream);
|
|
8281 }
|
|
8282 return soap->error;
|
|
8283 }
|
|
8284 #else
|
|
8285 return soap->error;
|
|
8286 #endif
|
|
8287 #ifdef WITH_ZLIB
|
|
8288 if (soap->mode & SOAP_ENC_ZLIB)
|
|
8289 { int r;
|
|
8290 soap->d_stream->avail_in = 0;
|
|
8291 do
|
|
8292 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating remainder\n"));
|
|
8293 r = deflate(soap->d_stream, Z_FINISH);
|
|
8294 if (soap->d_stream->avail_out != SOAP_BUFLEN)
|
|
8295 { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN - soap->d_stream->avail_out))
|
|
8296 { soap->zlib_state = SOAP_ZLIB_NONE;
|
|
8297 deflateEnd(soap->d_stream);
|
|
8298 return soap->error;
|
|
8299 }
|
|
8300 soap->d_stream->next_out = (Byte*)soap->z_buf;
|
|
8301 soap->d_stream->avail_out = SOAP_BUFLEN;
|
|
8302 }
|
|
8303 } while (r == Z_OK);
|
|
8304 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflated total %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out));
|
|
8305 soap->z_ratio_out = (float)soap->d_stream->total_out / (float)soap->d_stream->total_in;
|
|
8306 soap->mode &= ~SOAP_ENC_ZLIB;
|
|
8307 soap->zlib_state = SOAP_ZLIB_NONE;
|
|
8308 if (deflateEnd(soap->d_stream) != Z_OK || r != Z_STREAM_END)
|
|
8309 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to end deflate: %s\n", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS));
|
|
8310 return soap->error = SOAP_ZLIB_ERROR;
|
|
8311 }
|
|
8312 #ifdef WITH_GZIP
|
|
8313 if (soap->zlib_out != SOAP_ZLIB_DEFLATE)
|
|
8314 { soap->z_buf[0] = soap->z_crc & 0xFF;
|
|
8315 soap->z_buf[1] = (soap->z_crc >> 8) & 0xFF;
|
|
8316 soap->z_buf[2] = (soap->z_crc >> 16) & 0xFF;
|
|
8317 soap->z_buf[3] = (soap->z_crc >> 24) & 0xFF;
|
|
8318 soap->z_buf[4] = soap->d_stream->total_in & 0xFF;
|
|
8319 soap->z_buf[5] = (soap->d_stream->total_in >> 8) & 0xFF;
|
|
8320 soap->z_buf[6] = (soap->d_stream->total_in >> 16) & 0xFF;
|
|
8321 soap->z_buf[7] = (soap->d_stream->total_in >> 24) & 0xFF;
|
|
8322 if (soap_flush_raw(soap, soap->z_buf, 8))
|
|
8323 return soap->error;
|
|
8324 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip crc32=%lu\n", (unsigned long)soap->z_crc));
|
|
8325 }
|
|
8326 #endif
|
|
8327 }
|
|
8328 #endif
|
|
8329 if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
|
|
8330 { char *p;
|
|
8331 #ifndef WITH_NOHTTP
|
|
8332 if (!(soap->mode & SOAP_ENC_XML))
|
|
8333 { soap->mode--;
|
|
8334 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending buffered message of length %u\n", (unsigned int)soap->blist->size));
|
|
8335 if (soap->status >= SOAP_POST)
|
|
8336 soap->error = soap->fpost(soap, soap->endpoint, soap->host, soap->port, soap->path, soap->action, soap->blist->size);
|
|
8337 else if (soap->status != SOAP_STOP)
|
|
8338 soap->error = soap->fresponse(soap, soap->status, soap->blist->size);
|
|
8339 if (soap->error || soap_flush(soap))
|
|
8340 return soap->error;
|
|
8341 soap->mode++;
|
|
8342 }
|
|
8343 #endif
|
|
8344 for (p = soap_first_block(soap, NULL); p; p = soap_next_block(soap, NULL))
|
|
8345 { DBGMSG(SENT, p, soap_block_size(soap, NULL));
|
|
8346 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Send %u bytes to socket=%d/fd=%d\n", (unsigned int)soap_block_size(soap, NULL), soap->socket, soap->sendfd));
|
|
8347 if ((soap->error = soap->fsend(soap, p, soap_block_size(soap, NULL))))
|
|
8348 { soap_end_block(soap, NULL);
|
|
8349 return soap->error;
|
|
8350 }
|
|
8351 }
|
|
8352 soap_end_block(soap, NULL);
|
|
8353 if (soap->fpreparefinalsend && (soap->error = soap->fpreparefinalsend(soap)))
|
|
8354 return soap->error;
|
|
8355 }
|
|
8356 #ifndef WITH_LEANER
|
|
8357 else if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
|
|
8358 { DBGMSG(SENT, "\r\n0\r\n\r\n", 7);
|
|
8359 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Send 7 bytes to socket=%d/fd=%d\n", soap->socket, soap->sendfd));
|
|
8360 if ((soap->error = soap->fsend(soap, "\r\n0\r\n\r\n", 7)))
|
|
8361 return soap->error;
|
|
8362 }
|
|
8363 #endif
|
|
8364 }
|
|
8365 #ifdef WITH_TCPFIN
|
|
8366 #ifdef WITH_OPENSSL
|
|
8367 if (!soap->ssl && soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP))
|
|
8368 soap->fshutdownsocket(soap, soap->socket, SOAP_SHUT_WR); /* Send TCP FIN */
|
|
8369 #else
|
|
8370 if (soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP))
|
|
8371 soap->fshutdownsocket(soap, soap->socket, SOAP_SHUT_WR); /* Send TCP FIN */
|
|
8372 #endif
|
|
8373 #endif
|
|
8374 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of send phase\n"));
|
|
8375 soap->omode &= ~SOAP_SEC_WSUID;
|
|
8376 soap->count = 0;
|
|
8377 soap->part = SOAP_END;
|
|
8378 return SOAP_OK;
|
|
8379 }
|
|
8380 #endif
|
|
8381
|
|
8382 /******************************************************************************/
|
|
8383 #ifndef PALM_1
|
|
8384 SOAP_FMAC1
|
|
8385 int
|
|
8386 SOAP_FMAC2
|
|
8387 soap_end_recv(struct soap *soap)
|
|
8388 { soap->part = SOAP_END;
|
|
8389 #ifndef WITH_LEAN
|
|
8390 soap->wsuid = NULL; /* reset before next send */
|
|
8391 soap->c14nexclude = NULL; /* reset before next send */
|
|
8392 #endif
|
|
8393 #ifndef WITH_LEANER
|
|
8394 soap->ffilterrecv = NULL;
|
|
8395 if ((soap->mode & SOAP_ENC_DIME) && soap_getdime(soap))
|
|
8396 { soap->dime.first = NULL;
|
|
8397 soap->dime.last = NULL;
|
|
8398 return soap->error;
|
|
8399 }
|
|
8400 soap->dime.list = soap->dime.first;
|
|
8401 soap->dime.first = NULL;
|
|
8402 soap->dime.last = NULL;
|
|
8403 /* Check if MIME attachments and mime-post-check flag is set, if so call soap_resolve() and return */
|
|
8404 if (soap->mode & SOAP_ENC_MIME)
|
|
8405 { if (soap->mode & SOAP_MIME_POSTCHECK)
|
|
8406 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Post checking MIME attachments\n"));
|
|
8407 if (!soap->keep_alive)
|
|
8408 soap->keep_alive = -1;
|
|
8409 #ifndef WITH_NOIDREF
|
|
8410 soap_resolve(soap);
|
|
8411 #endif
|
|
8412 return SOAP_OK;
|
|
8413 }
|
|
8414 if (soap_getmime(soap))
|
|
8415 return soap->error;
|
|
8416 }
|
|
8417 soap->mime.list = soap->mime.first;
|
|
8418 soap->mime.first = NULL;
|
|
8419 soap->mime.last = NULL;
|
|
8420 soap->mime.boundary = NULL;
|
|
8421 if (soap->xlist)
|
|
8422 { struct soap_multipart *content;
|
|
8423 for (content = soap->mime.list; content; content = content->next)
|
|
8424 soap_resolve_attachment(soap, content);
|
|
8425 }
|
|
8426 #endif
|
|
8427 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "End of receive message ok\n"));
|
|
8428 #ifdef WITH_ZLIB
|
|
8429 if (soap->mode & SOAP_ENC_ZLIB)
|
|
8430 { /* Make sure end of compressed content is reached */
|
|
8431 while (soap->d_stream->next_out != Z_NULL)
|
|
8432 if ((int)soap_get1(soap) == EOF)
|
|
8433 break;
|
|
8434 soap->mode &= ~SOAP_ENC_ZLIB;
|
|
8435 memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN);
|
|
8436 soap->bufidx = (char*)soap->d_stream->next_in - soap->z_buf;
|
|
8437 soap->buflen = soap->z_buflen;
|
|
8438 soap->zlib_state = SOAP_ZLIB_NONE;
|
|
8439 if (inflateEnd(soap->d_stream) != Z_OK)
|
|
8440 return soap->error = SOAP_ZLIB_ERROR;
|
|
8441 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Inflate end ok\n"));
|
|
8442 #ifdef WITH_GZIP
|
|
8443 if (soap->zlib_in == SOAP_ZLIB_GZIP)
|
|
8444 { soap_wchar c;
|
|
8445 short i;
|
|
8446 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Inflate gzip crc check\n"));
|
|
8447 for (i = 0; i < 8; i++)
|
|
8448 { if ((int)(c = soap_get1(soap)) == EOF)
|
|
8449 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: unable to read crc value\n"));
|
|
8450 return soap->error = SOAP_ZLIB_ERROR;
|
|
8451 }
|
|
8452 soap->z_buf[i] = (char)c;
|
|
8453 }
|
|
8454 if (soap->z_crc != ((uLong)(unsigned char)soap->z_buf[0] | ((uLong)(unsigned char)soap->z_buf[1] << 8) | ((uLong)(unsigned char)soap->z_buf[2] << 16) | ((uLong)(unsigned char)soap->z_buf[3] << 24)))
|
|
8455 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip inflate error: crc check failed, message corrupted? (crc32=%lu)\n", (unsigned long)soap->z_crc));
|
|
8456 return soap->error = SOAP_ZLIB_ERROR;
|
|
8457 }
|
|
8458 if (soap->d_stream->total_out != ((uLong)(unsigned char)soap->z_buf[4] | ((uLong)(unsigned char)soap->z_buf[5] << 8) | ((uLong)(unsigned char)soap->z_buf[6] << 16) | ((uLong)(unsigned char)soap->z_buf[7] << 24)))
|
|
8459 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip inflate error: incorrect message length\n"));
|
|
8460 return soap->error = SOAP_ZLIB_ERROR;
|
|
8461 }
|
|
8462 }
|
|
8463 soap->zlib_in = SOAP_ZLIB_NONE;
|
|
8464 #endif
|
|
8465 }
|
|
8466 #endif
|
|
8467 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
|
|
8468 while (soap->ahead != EOF && !soap_recv_raw(soap))
|
|
8469 ;
|
|
8470 #ifndef WITH_NOIDREF
|
|
8471 if (soap_resolve(soap))
|
|
8472 return soap->error;
|
|
8473 #endif
|
|
8474 #ifndef WITH_LEANER
|
|
8475 if (soap->xlist)
|
|
8476 { if (soap->mode & SOAP_ENC_MTOM)
|
|
8477 return soap->error = SOAP_MIME_HREF;
|
|
8478 return soap->error = SOAP_DIME_HREF;
|
|
8479 }
|
|
8480 #endif
|
|
8481 soap_free_ns(soap);
|
|
8482 #ifndef WITH_LEANER
|
|
8483 if (soap->fpreparefinalrecv)
|
|
8484 return soap->error = soap->fpreparefinalrecv(soap);
|
|
8485 #endif
|
|
8486 return SOAP_OK;
|
|
8487 }
|
|
8488 #endif
|
|
8489
|
|
8490 /******************************************************************************/
|
|
8491 #ifndef PALM_1
|
|
8492 SOAP_FMAC1
|
|
8493 void
|
|
8494 SOAP_FMAC2
|
|
8495 soap_free_temp(struct soap *soap)
|
|
8496 { register struct soap_attribute *tp, *tq;
|
|
8497 register struct Namespace *ns;
|
|
8498 soap_free_ns(soap);
|
|
8499 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free any remaining temp blocks\n"));
|
|
8500 while (soap->blist)
|
|
8501 soap_end_block(soap, NULL);
|
|
8502 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute storage\n"));
|
|
8503 for (tp = soap->attributes; tp; tp = tq)
|
|
8504 { tq = tp->next;
|
|
8505 if (tp->value)
|
|
8506 SOAP_FREE(soap, tp->value);
|
|
8507 SOAP_FREE(soap, tp);
|
|
8508 }
|
|
8509 soap->attributes = NULL;
|
|
8510 #ifdef WITH_FAST
|
|
8511 if (soap->labbuf)
|
|
8512 SOAP_FREE(soap, soap->labbuf);
|
|
8513 soap->labbuf = NULL;
|
|
8514 soap->lablen = 0;
|
|
8515 soap->labidx = 0;
|
|
8516 #endif
|
|
8517 ns = soap->local_namespaces;
|
|
8518 if (ns)
|
|
8519 { for (; ns->id; ns++)
|
|
8520 { if (ns->out)
|
|
8521 { SOAP_FREE(soap, ns->out);
|
|
8522 ns->out = NULL;
|
|
8523 }
|
|
8524 }
|
|
8525 SOAP_FREE(soap, soap->local_namespaces);
|
|
8526 soap->local_namespaces = NULL;
|
|
8527 }
|
|
8528 #ifndef WITH_LEANER
|
|
8529 while (soap->xlist)
|
|
8530 { struct soap_xlist *xp = soap->xlist->next;
|
|
8531 SOAP_FREE(soap, soap->xlist);
|
|
8532 soap->xlist = xp;
|
|
8533 }
|
|
8534 #endif
|
|
8535 #ifndef WITH_NOIDREF
|
|
8536 soap_free_pht(soap);
|
|
8537 soap_free_iht(soap);
|
|
8538 #endif
|
|
8539 }
|
|
8540 #endif
|
|
8541
|
|
8542 /******************************************************************************/
|
|
8543 #ifndef PALM_1
|
|
8544 static void
|
|
8545 soap_free_ns(struct soap *soap)
|
|
8546 { register struct soap_nlist *np, *nq;
|
|
8547 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free namespace stack\n"));
|
|
8548 for (np = soap->nlist; np; np = nq)
|
|
8549 { nq = np->next;
|
|
8550 SOAP_FREE(soap, np);
|
|
8551 }
|
|
8552 soap->nlist = NULL;
|
|
8553 }
|
|
8554 #endif
|
|
8555
|
|
8556 /******************************************************************************/
|
|
8557 #ifndef PALM_1
|
|
8558 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
|
|
8559 static void
|
|
8560 soap_init_logs(struct soap *soap)
|
|
8561 { int i;
|
|
8562 for (i = 0; i < SOAP_MAXLOGS; i++)
|
|
8563 { soap->logfile[i] = NULL;
|
|
8564 soap->fdebug[i] = NULL;
|
|
8565 }
|
|
8566 }
|
|
8567 #endif
|
|
8568 #endif
|
|
8569
|
|
8570 /******************************************************************************/
|
|
8571 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
|
|
8572 SOAP_FMAC1
|
|
8573 void
|
|
8574 SOAP_FMAC2
|
|
8575 soap_open_logfile(struct soap *soap, int i)
|
|
8576 { if (soap->logfile[i])
|
|
8577 soap->fdebug[i] = fopen(soap->logfile[i], i < 2 ? "ab" : "a");
|
|
8578 }
|
|
8579 #endif
|
|
8580
|
|
8581 /******************************************************************************/
|
|
8582 #ifdef SOAP_DEBUG
|
|
8583 static void
|
|
8584 soap_close_logfile(struct soap *soap, int i)
|
|
8585 { if (soap->fdebug[i])
|
|
8586 { fclose(soap->fdebug[i]);
|
|
8587 soap->fdebug[i] = NULL;
|
|
8588 }
|
|
8589 }
|
|
8590 #endif
|
|
8591
|
|
8592 /******************************************************************************/
|
|
8593 #ifdef SOAP_DEBUG
|
|
8594 SOAP_FMAC1
|
|
8595 void
|
|
8596 SOAP_FMAC2
|
|
8597 soap_close_logfiles(struct soap *soap)
|
|
8598 { int i;
|
|
8599 for (i = 0; i < SOAP_MAXLOGS; i++)
|
|
8600 soap_close_logfile(soap, i);
|
|
8601 }
|
|
8602 #endif
|
|
8603
|
|
8604 /******************************************************************************/
|
|
8605 #ifdef SOAP_DEBUG
|
|
8606 static void
|
|
8607 soap_set_logfile(struct soap *soap, int i, const char *logfile)
|
|
8608 { const char *s;
|
|
8609 char *t = NULL;
|
|
8610 soap_close_logfile(soap, i);
|
|
8611 s = soap->logfile[i];
|
|
8612 soap->logfile[i] = logfile;
|
|
8613 if (s)
|
|
8614 SOAP_FREE(soap, (void*)s);
|
|
8615 if (logfile)
|
|
8616 if ((t = (char*)SOAP_MALLOC(soap, strlen(logfile) + 1)))
|
|
8617 strcpy(t, logfile);
|
|
8618 soap->logfile[i] = t;
|
|
8619 }
|
|
8620 #endif
|
|
8621
|
|
8622 /******************************************************************************/
|
|
8623 SOAP_FMAC1
|
|
8624 void
|
|
8625 SOAP_FMAC2
|
|
8626 soap_set_recv_logfile(struct soap *soap, const char *logfile)
|
|
8627 {
|
|
8628 #ifdef SOAP_DEBUG
|
|
8629 soap_set_logfile(soap, SOAP_INDEX_RECV, logfile);
|
|
8630 #endif
|
|
8631 }
|
|
8632
|
|
8633 /******************************************************************************/
|
|
8634 SOAP_FMAC1
|
|
8635 void
|
|
8636 SOAP_FMAC2
|
|
8637 soap_set_sent_logfile(struct soap *soap, const char *logfile)
|
|
8638 {
|
|
8639 #ifdef SOAP_DEBUG
|
|
8640 soap_set_logfile(soap, SOAP_INDEX_SENT, logfile);
|
|
8641 #endif
|
|
8642 }
|
|
8643
|
|
8644 /******************************************************************************/
|
|
8645 SOAP_FMAC1
|
|
8646 void
|
|
8647 SOAP_FMAC2
|
|
8648 soap_set_test_logfile(struct soap *soap, const char *logfile)
|
|
8649 {
|
|
8650 #ifdef SOAP_DEBUG
|
|
8651 soap_set_logfile(soap, SOAP_INDEX_TEST, logfile);
|
|
8652 #endif
|
|
8653 }
|
|
8654
|
|
8655 /******************************************************************************/
|
|
8656 #ifndef PALM_1
|
|
8657 SOAP_FMAC1
|
|
8658 struct soap*
|
|
8659 SOAP_FMAC2
|
|
8660 soap_copy(const struct soap *soap)
|
|
8661 { return soap_copy_context((struct soap*)malloc(sizeof(struct soap)), soap);
|
|
8662 }
|
|
8663 #endif
|
|
8664
|
|
8665 /******************************************************************************/
|
|
8666 #ifndef PALM_1
|
|
8667 SOAP_FMAC1
|
|
8668 struct soap*
|
|
8669 SOAP_FMAC2
|
|
8670 soap_copy_context(struct soap *copy, const struct soap *soap)
|
|
8671 { if (copy == soap)
|
|
8672 return copy;
|
|
8673 if (soap_check_state(soap))
|
|
8674 return NULL;
|
|
8675 if (copy)
|
|
8676 { register struct soap_plugin *p = NULL;
|
|
8677 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying context\n"));
|
|
8678 #ifdef __cplusplus
|
|
8679 *copy = *soap;
|
|
8680 #else
|
|
8681 memcpy(copy, soap, sizeof(struct soap));
|
|
8682 #endif
|
|
8683 copy->state = SOAP_COPY;
|
|
8684 copy->error = SOAP_OK;
|
|
8685 copy->userid = NULL;
|
|
8686 copy->passwd = NULL;
|
|
8687 #ifdef WITH_NTLM
|
|
8688 copy->ntlm_challenge = NULL;
|
|
8689 #endif
|
|
8690 copy->nlist = NULL;
|
|
8691 copy->blist = NULL;
|
|
8692 copy->clist = NULL;
|
|
8693 copy->alist = NULL;
|
|
8694 copy->attributes = NULL;
|
|
8695 copy->labbuf = NULL;
|
|
8696 copy->lablen = 0;
|
|
8697 copy->labidx = 0;
|
|
8698 #ifdef SOAP_MEM_DEBUG
|
|
8699 soap_init_mht(copy);
|
|
8700 #endif
|
|
8701 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
|
|
8702 soap_init_logs(copy);
|
|
8703 #endif
|
|
8704 #ifdef SOAP_DEBUG
|
|
8705 soap_set_test_logfile(copy, soap->logfile[SOAP_INDEX_TEST]);
|
|
8706 soap_set_sent_logfile(copy, soap->logfile[SOAP_INDEX_SENT]);
|
|
8707 soap_set_recv_logfile(copy, soap->logfile[SOAP_INDEX_RECV]);
|
|
8708 #endif
|
|
8709 copy->namespaces = soap->local_namespaces;
|
|
8710 copy->local_namespaces = NULL;
|
|
8711 soap_set_local_namespaces(copy); /* copy content of soap->local_namespaces */
|
|
8712 copy->namespaces = soap->namespaces; /* point to shared read-only namespaces table */
|
|
8713 #ifdef WITH_C_LOCALE
|
|
8714 # ifdef WIN32
|
|
8715 copy->c_locale = _create_locale(LC_ALL, "C");
|
|
8716 # else
|
|
8717 copy->c_locale = duplocale(soap->c_locale);
|
|
8718 # endif
|
|
8719 #else
|
|
8720 copy->c_locale = NULL;
|
|
8721 #endif
|
|
8722 #ifdef WITH_OPENSSL
|
|
8723 copy->bio = NULL;
|
|
8724 copy->ssl = NULL;
|
|
8725 copy->session = NULL;
|
|
8726 #endif
|
|
8727 #ifdef WITH_GNUTLS
|
|
8728 copy->session = NULL;
|
|
8729 #endif
|
|
8730 #ifdef WITH_ZLIB
|
|
8731 copy->d_stream = (z_stream*)SOAP_MALLOC(copy, sizeof(z_stream));
|
|
8732 copy->d_stream->zalloc = Z_NULL;
|
|
8733 copy->d_stream->zfree = Z_NULL;
|
|
8734 copy->d_stream->opaque = Z_NULL;
|
|
8735 copy->z_buf = NULL;
|
|
8736 #endif
|
|
8737 #ifndef WITH_NOIDREF
|
|
8738 soap_init_iht(copy);
|
|
8739 soap_init_pht(copy);
|
|
8740 #endif
|
|
8741 copy->header = NULL;
|
|
8742 copy->fault = NULL;
|
|
8743 copy->action = NULL;
|
|
8744 #ifndef WITH_LEAN
|
|
8745 #ifdef WITH_COOKIES
|
|
8746 copy->cookies = soap_copy_cookies(copy, soap);
|
|
8747 #else
|
|
8748 copy->cookies = NULL;
|
|
8749 #endif
|
|
8750 #endif
|
|
8751 copy->plugins = NULL;
|
|
8752 for (p = soap->plugins; p; p = p->next)
|
|
8753 { register struct soap_plugin *q = (struct soap_plugin*)SOAP_MALLOC(copy, sizeof(struct soap_plugin));
|
|
8754 if (!q)
|
|
8755 return NULL;
|
|
8756 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying plugin '%s'\n", p->id));
|
|
8757 *q = *p;
|
|
8758 if (p->fcopy && p->fcopy(copy, q, p))
|
|
8759 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not copy plugin '%s'\n", p->id));
|
|
8760 SOAP_FREE(copy, q);
|
|
8761 return NULL;
|
|
8762 }
|
|
8763 q->next = copy->plugins;
|
|
8764 copy->plugins = q;
|
|
8765 }
|
|
8766 }
|
|
8767 return copy;
|
|
8768 }
|
|
8769 #endif
|
|
8770
|
|
8771 /******************************************************************************/
|
|
8772 #ifndef PALM_1
|
|
8773 SOAP_FMAC1
|
|
8774 void
|
|
8775 SOAP_FMAC2
|
|
8776 soap_copy_stream(struct soap *copy, struct soap *soap)
|
|
8777 { struct soap_attribute *tp = NULL, *tq;
|
|
8778 if (copy == soap)
|
|
8779 return;
|
|
8780 copy->header = soap->header;
|
|
8781 copy->mode = soap->mode;
|
|
8782 copy->imode = soap->imode;
|
|
8783 copy->omode = soap->omode;
|
|
8784 copy->master = soap->master;
|
|
8785 copy->socket = soap->socket;
|
|
8786 copy->sendsk = soap->sendsk;
|
|
8787 copy->recvsk = soap->recvsk;
|
|
8788 copy->recv_timeout = soap->recv_timeout;
|
|
8789 copy->send_timeout = soap->send_timeout;
|
|
8790 #if defined(__cplusplus) && !defined(WITH_LEAN)
|
|
8791 copy->os = soap->os;
|
|
8792 copy->is = soap->is;
|
|
8793 #endif
|
|
8794 copy->sendfd = soap->sendfd;
|
|
8795 copy->recvfd = soap->recvfd;
|
|
8796 copy->bufidx = soap->bufidx;
|
|
8797 copy->buflen = soap->buflen;
|
|
8798 copy->ahead = soap->ahead;
|
|
8799 copy->cdata = soap->cdata;
|
|
8800 copy->chunksize = soap->chunksize;
|
|
8801 copy->chunkbuflen = soap->chunkbuflen;
|
|
8802 copy->keep_alive = soap->keep_alive;
|
|
8803 copy->tcp_keep_alive = soap->tcp_keep_alive;
|
|
8804 copy->tcp_keep_idle = soap->tcp_keep_idle;
|
|
8805 copy->tcp_keep_intvl = soap->tcp_keep_intvl;
|
|
8806 copy->tcp_keep_cnt = soap->tcp_keep_cnt;
|
|
8807 copy->max_keep_alive = soap->max_keep_alive;
|
|
8808 #ifndef WITH_NOIO
|
|
8809 copy->peer = soap->peer;
|
|
8810 copy->peerlen = soap->peerlen;
|
|
8811 copy->ip = soap->ip;
|
|
8812 copy->port = soap->port;
|
|
8813 memcpy(copy->host, soap->host, sizeof(soap->host));
|
|
8814 memcpy(copy->endpoint, soap->endpoint, sizeof(soap->endpoint));
|
|
8815 #endif
|
|
8816 #ifdef WITH_OPENSSL
|
|
8817 copy->bio = soap->bio;
|
|
8818 copy->ctx = soap->ctx;
|
|
8819 copy->ssl = soap->ssl;
|
|
8820 #endif
|
|
8821 #ifdef WITH_GNUTLS
|
|
8822 copy->session = soap->session;
|
|
8823 #endif
|
|
8824 #ifdef WITH_ZLIB
|
|
8825 copy->zlib_state = soap->zlib_state;
|
|
8826 copy->zlib_in = soap->zlib_in;
|
|
8827 copy->zlib_out = soap->zlib_out;
|
|
8828 if (!copy->d_stream)
|
|
8829 copy->d_stream = (z_stream*)SOAP_MALLOC(copy, sizeof(z_stream));
|
|
8830 if (copy->d_stream)
|
|
8831 memcpy(copy->d_stream, soap->d_stream, sizeof(z_stream));
|
|
8832 copy->z_crc = soap->z_crc;
|
|
8833 copy->z_ratio_in = soap->z_ratio_in;
|
|
8834 copy->z_ratio_out = soap->z_ratio_out;
|
|
8835 copy->z_buf = NULL;
|
|
8836 copy->z_buflen = soap->z_buflen;
|
|
8837 copy->z_level = soap->z_level;
|
|
8838 if (soap->z_buf && soap->zlib_state != SOAP_ZLIB_NONE)
|
|
8839 { copy->z_buf = (char*)SOAP_MALLOC(copy, SOAP_BUFLEN);
|
|
8840 if (copy->z_buf)
|
|
8841 memcpy(copy->z_buf, soap->z_buf, SOAP_BUFLEN);
|
|
8842 }
|
|
8843 copy->z_dict = soap->z_dict;
|
|
8844 copy->z_dict_len = soap->z_dict_len;
|
|
8845 #endif
|
|
8846 memcpy(copy->buf, soap->buf, sizeof(soap->buf));
|
|
8847 /* copy XML parser state */
|
|
8848 soap_free_ns(copy);
|
|
8849 soap_set_local_namespaces(copy);
|
|
8850 copy->version = soap->version;
|
|
8851 if (soap->nlist && soap->local_namespaces)
|
|
8852 { register struct soap_nlist *np = NULL, *nq;
|
|
8853 /* copy reversed nlist */
|
|
8854 for (nq = soap->nlist; nq; nq = nq->next)
|
|
8855 { register struct soap_nlist *nr = np;
|
|
8856 size_t n = sizeof(struct soap_nlist) + strlen(nq->id);
|
|
8857 np = (struct soap_nlist*)SOAP_MALLOC(copy, n);
|
|
8858 if (!np)
|
|
8859 break;
|
|
8860 memcpy(np, nq, n);
|
|
8861 np->next = nr;
|
|
8862 }
|
|
8863 while (np)
|
|
8864 { register const char *s = np->ns;
|
|
8865 copy->level = np->level; /* preserve element nesting level */
|
|
8866 if (!s && np->index >= 0)
|
|
8867 { s = soap->local_namespaces[np->index].out;
|
|
8868 if (!s)
|
|
8869 s = soap->local_namespaces[np->index].ns;
|
|
8870 }
|
|
8871 if (s && soap_push_namespace(copy, np->id, s) == NULL)
|
|
8872 break;
|
|
8873 nq = np;
|
|
8874 np = np->next;
|
|
8875 SOAP_FREE(copy, nq);
|
|
8876 }
|
|
8877 }
|
|
8878 memcpy(copy->tag, soap->tag, sizeof(copy->tag));
|
|
8879 memcpy(copy->id, soap->id, sizeof(copy->id));
|
|
8880 memcpy(copy->href, soap->href, sizeof(copy->href));
|
|
8881 memcpy(copy->type, soap->type, sizeof(copy->type));
|
|
8882 copy->other = soap->other;
|
|
8883 copy->root = soap->root;
|
|
8884 copy->null = soap->null;
|
|
8885 copy->body = soap->body;
|
|
8886 copy->part = soap->part;
|
|
8887 copy->mustUnderstand = soap->mustUnderstand;
|
|
8888 copy->level = soap->level;
|
|
8889 copy->peeked = soap->peeked;
|
|
8890 /* copy attributes */
|
|
8891 for (tq = soap->attributes; tq; tq = tq->next)
|
|
8892 { struct soap_attribute *tr = tp;
|
|
8893 size_t n = sizeof(struct soap_attribute) + strlen(tq->name);
|
|
8894 tp = (struct soap_attribute*)SOAP_MALLOC(copy, n);
|
|
8895 memcpy(tp, tq, n);
|
|
8896 if (tp->size)
|
|
8897 { tp->value = (char*)SOAP_MALLOC(copy, tp->size);
|
|
8898 if (tp->value)
|
|
8899 strcpy(tp->value, tq->value);
|
|
8900 }
|
|
8901 tp->ns = NULL;
|
|
8902 tp->next = tr;
|
|
8903 }
|
|
8904 copy->attributes = tp;
|
|
8905 }
|
|
8906 #endif
|
|
8907
|
|
8908 /******************************************************************************/
|
|
8909 #ifndef PALM_1
|
|
8910 SOAP_FMAC1
|
|
8911 void
|
|
8912 SOAP_FMAC2
|
|
8913 soap_free_stream(struct soap *soap)
|
|
8914 { soap->socket = SOAP_INVALID_SOCKET;
|
|
8915 soap->sendsk = SOAP_INVALID_SOCKET;
|
|
8916 soap->recvsk = SOAP_INVALID_SOCKET;
|
|
8917 #ifdef WITH_OPENSSL
|
|
8918 soap->bio = NULL;
|
|
8919 soap->ctx = NULL;
|
|
8920 soap->ssl = NULL;
|
|
8921 #endif
|
|
8922 #ifdef WITH_GNUTLS
|
|
8923 soap->xcred = NULL;
|
|
8924 soap->acred = NULL;
|
|
8925 soap->cache = NULL;
|
|
8926 soap->session = NULL;
|
|
8927 soap->dh_params = NULL;
|
|
8928 soap->rsa_params = NULL;
|
|
8929 #endif
|
|
8930 #ifdef WITH_ZLIB
|
|
8931 if (soap->z_buf)
|
|
8932 SOAP_FREE(soap, soap->z_buf);
|
|
8933 soap->z_buf = NULL;
|
|
8934 #endif
|
|
8935 }
|
|
8936 #endif
|
|
8937
|
|
8938 /******************************************************************************/
|
|
8939 #ifndef PALM_1
|
|
8940 SOAP_FMAC1
|
|
8941 void
|
|
8942 SOAP_FMAC2
|
|
8943 soap_initialize(struct soap *soap)
|
|
8944 { soap_versioning(soap_init)(soap, SOAP_IO_DEFAULT, SOAP_IO_DEFAULT);
|
|
8945 }
|
|
8946 #endif
|
|
8947
|
|
8948 /******************************************************************************/
|
|
8949 #ifndef PALM_1
|
|
8950 SOAP_FMAC1
|
|
8951 void
|
|
8952 SOAP_FMAC2
|
|
8953 soap_versioning(soap_init)(struct soap *soap, soap_mode imode, soap_mode omode)
|
|
8954 { size_t i;
|
|
8955 soap->state = SOAP_INIT;
|
|
8956 #ifdef SOAP_MEM_DEBUG
|
|
8957 soap_init_mht(soap);
|
|
8958 #endif
|
|
8959 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
|
|
8960 soap_init_logs(soap);
|
|
8961 #endif
|
|
8962 #ifdef SOAP_DEBUG
|
|
8963 #ifdef TANDEM_NONSTOP
|
|
8964 soap_set_test_logfile(soap, "TESTLOG");
|
|
8965 soap_set_sent_logfile(soap, "SENTLOG");
|
|
8966 soap_set_recv_logfile(soap, "RECVLOG");
|
|
8967 #else
|
|
8968 soap_set_test_logfile(soap, "TEST.log");
|
|
8969 soap_set_sent_logfile(soap, "SENT.log");
|
|
8970 soap_set_recv_logfile(soap, "RECV.log");
|
|
8971 #endif
|
|
8972 #endif
|
|
8973 soap->version = 0;
|
|
8974 soap_mode(soap, imode);
|
|
8975 soap_imode(soap, imode);
|
|
8976 soap_omode(soap, omode);
|
|
8977 soap->plugins = NULL;
|
|
8978 soap->user = NULL;
|
|
8979 for (i = 0; i < sizeof(soap->data)/sizeof(*soap->data); i++)
|
|
8980 soap->data[i] = NULL;
|
|
8981 soap->userid = NULL;
|
|
8982 soap->passwd = NULL;
|
|
8983 soap->authrealm = NULL;
|
|
8984 #ifdef WITH_NTLM
|
|
8985 soap->ntlm_challenge = NULL;
|
|
8986 #endif
|
|
8987 #ifndef WITH_NOHTTP
|
|
8988 soap->fpost = http_post;
|
|
8989 soap->fget = http_get;
|
|
8990 soap->fput = http_405;
|
|
8991 soap->fdel = http_405;
|
|
8992 soap->fopt = http_200;
|
|
8993 soap->fhead = http_200;
|
|
8994 soap->fform = NULL;
|
|
8995 soap->fposthdr = http_post_header;
|
|
8996 soap->fresponse = http_response;
|
|
8997 soap->fparse = http_parse;
|
|
8998 soap->fparsehdr = http_parse_header;
|
|
8999 #endif
|
|
9000 soap->fheader = NULL;
|
|
9001 soap->fconnect = NULL;
|
|
9002 soap->fdisconnect = NULL;
|
|
9003 #ifndef WITH_NOIO
|
|
9004 soap->ipv6_multicast_if = 0; /* in_addr_t value */
|
|
9005 soap->ipv4_multicast_if = NULL; /* points to struct in_addr or in_addr_t */
|
|
9006 soap->ipv4_multicast_ttl = 0; /* 0: use default */
|
|
9007 #ifndef WITH_IPV6
|
|
9008 soap->fresolve = tcp_gethost;
|
|
9009 #else
|
|
9010 soap->fresolve = NULL;
|
|
9011 #endif
|
|
9012 soap->faccept = tcp_accept;
|
|
9013 soap->fopen = tcp_connect;
|
|
9014 soap->fclose = tcp_disconnect;
|
|
9015 soap->fclosesocket = tcp_closesocket;
|
|
9016 soap->fshutdownsocket = tcp_shutdownsocket;
|
|
9017 soap->fsend = fsend;
|
|
9018 soap->frecv = frecv;
|
|
9019 soap->fpoll = soap_poll;
|
|
9020 #else
|
|
9021 soap->fopen = NULL;
|
|
9022 soap->fclose = NULL;
|
|
9023 soap->fpoll = NULL;
|
|
9024 #endif
|
|
9025 soap->fseterror = NULL;
|
|
9026 soap->fignore = NULL;
|
|
9027 soap->fserveloop = NULL;
|
|
9028 soap->fplugin = fplugin;
|
|
9029 soap->fmalloc = NULL;
|
|
9030 #ifndef WITH_LEANER
|
|
9031 soap->feltbegin = NULL;
|
|
9032 soap->feltendin = NULL;
|
|
9033 soap->feltbegout = NULL;
|
|
9034 soap->feltendout = NULL;
|
|
9035 soap->fprepareinitsend = NULL;
|
|
9036 soap->fprepareinitrecv = NULL;
|
|
9037 soap->fpreparesend = NULL;
|
|
9038 soap->fpreparerecv = NULL;
|
|
9039 soap->fpreparefinalsend = NULL;
|
|
9040 soap->fpreparefinalrecv = NULL;
|
|
9041 soap->ffiltersend = NULL;
|
|
9042 soap->ffilterrecv = NULL;
|
|
9043 soap->fdimereadopen = NULL;
|
|
9044 soap->fdimewriteopen = NULL;
|
|
9045 soap->fdimereadclose = NULL;
|
|
9046 soap->fdimewriteclose = NULL;
|
|
9047 soap->fdimeread = NULL;
|
|
9048 soap->fdimewrite = NULL;
|
|
9049 soap->fmimereadopen = NULL;
|
|
9050 soap->fmimewriteopen = NULL;
|
|
9051 soap->fmimereadclose = NULL;
|
|
9052 soap->fmimewriteclose = NULL;
|
|
9053 soap->fmimeread = NULL;
|
|
9054 soap->fmimewrite = NULL;
|
|
9055 #endif
|
|
9056 soap->float_format = "%.9G"; /* Alternative: use "%G" */
|
|
9057 soap->double_format = "%.17lG"; /* Alternative: use "%lG" */
|
|
9058 soap->dime_id_format = "cid:id%d"; /* default DIME id format */
|
|
9059 soap->http_version = "1.1";
|
|
9060 soap->proxy_http_version = "1.0";
|
|
9061 soap->http_content = NULL;
|
|
9062 soap->actor = NULL;
|
|
9063 soap->lang = "en";
|
|
9064 soap->keep_alive = 0;
|
|
9065 soap->tcp_keep_alive = 0;
|
|
9066 soap->tcp_keep_idle = 0;
|
|
9067 soap->tcp_keep_intvl = 0;
|
|
9068 soap->tcp_keep_cnt = 0;
|
|
9069 soap->max_keep_alive = SOAP_MAXKEEPALIVE;
|
|
9070 soap->recv_timeout = 0;
|
|
9071 soap->send_timeout = 0;
|
|
9072 soap->connect_timeout = 0;
|
|
9073 soap->accept_timeout = 0;
|
|
9074 soap->socket_flags = 0;
|
|
9075 soap->connect_flags = 0;
|
|
9076 soap->bind_flags = 0;
|
|
9077 soap->accept_flags = 0;
|
|
9078 soap->linger_time = 0;
|
|
9079 soap->ip = 0;
|
|
9080 soap->labbuf = NULL;
|
|
9081 soap->lablen = 0;
|
|
9082 soap->labidx = 0;
|
|
9083 soap->encodingStyle = NULL;
|
|
9084 #ifndef WITH_NONAMESPACES
|
|
9085 soap->namespaces = namespaces;
|
|
9086 #else
|
|
9087 soap->namespaces = NULL;
|
|
9088 #endif
|
|
9089 soap->local_namespaces = NULL;
|
|
9090 soap->nlist = NULL;
|
|
9091 soap->blist = NULL;
|
|
9092 soap->clist = NULL;
|
|
9093 soap->alist = NULL;
|
|
9094 soap->attributes = NULL;
|
|
9095 soap->header = NULL;
|
|
9096 soap->fault = NULL;
|
|
9097 soap->master = SOAP_INVALID_SOCKET;
|
|
9098 soap->socket = SOAP_INVALID_SOCKET;
|
|
9099 soap->sendsk = SOAP_INVALID_SOCKET;
|
|
9100 soap->recvsk = SOAP_INVALID_SOCKET;
|
|
9101 soap->os = NULL;
|
|
9102 soap->is = NULL;
|
|
9103 #ifndef WITH_LEANER
|
|
9104 soap->dom = NULL;
|
|
9105 soap->dime.list = NULL;
|
|
9106 soap->dime.first = NULL;
|
|
9107 soap->dime.last = NULL;
|
|
9108 soap->mime.list = NULL;
|
|
9109 soap->mime.first = NULL;
|
|
9110 soap->mime.last = NULL;
|
|
9111 soap->mime.boundary = NULL;
|
|
9112 soap->mime.start = NULL;
|
|
9113 soap->xlist = NULL;
|
|
9114 #endif
|
|
9115 #ifndef UNDER_CE
|
|
9116 soap->recvfd = 0;
|
|
9117 soap->sendfd = 1;
|
|
9118 #else
|
|
9119 soap->recvfd = stdin;
|
|
9120 soap->sendfd = stdout;
|
|
9121 #endif
|
|
9122 soap->host[0] = '\0';
|
|
9123 soap->port = 0;
|
|
9124 soap->action = NULL;
|
|
9125 soap->proxy_host = NULL;
|
|
9126 soap->proxy_port = 8080;
|
|
9127 soap->proxy_userid = NULL;
|
|
9128 soap->proxy_passwd = NULL;
|
|
9129 soap->prolog = NULL;
|
|
9130 #ifdef WITH_ZLIB
|
|
9131 soap->zlib_state = SOAP_ZLIB_NONE;
|
|
9132 soap->zlib_in = SOAP_ZLIB_NONE;
|
|
9133 soap->zlib_out = SOAP_ZLIB_NONE;
|
|
9134 soap->d_stream = (z_stream*)SOAP_MALLOC(soap, sizeof(z_stream));
|
|
9135 soap->d_stream->zalloc = Z_NULL;
|
|
9136 soap->d_stream->zfree = Z_NULL;
|
|
9137 soap->d_stream->opaque = Z_NULL;
|
|
9138 soap->z_buf = NULL;
|
|
9139 soap->z_level = 6;
|
|
9140 soap->z_dict = NULL;
|
|
9141 soap->z_dict_len = 0;
|
|
9142 #endif
|
|
9143 #ifndef WITH_LEAN
|
|
9144 soap->wsuid = NULL;
|
|
9145 soap->c14nexclude = NULL;
|
|
9146 soap->cookies = NULL;
|
|
9147 soap->cookie_domain = NULL;
|
|
9148 soap->cookie_path = NULL;
|
|
9149 soap->cookie_max = 32;
|
|
9150 #endif
|
|
9151 #ifdef WMW_RPM_IO
|
|
9152 soap->rpmreqid = NULL;
|
|
9153 #endif
|
|
9154 #ifdef PALM
|
|
9155 palmNetLibOpen();
|
|
9156 #endif
|
|
9157 #ifndef WITH_NOIDREF
|
|
9158 soap_init_iht(soap);
|
|
9159 soap_init_pht(soap);
|
|
9160 #endif
|
|
9161 #ifdef WITH_OPENSSL
|
|
9162 if (!soap_ssl_init_done)
|
|
9163 soap_ssl_init();
|
|
9164 soap->fsslauth = ssl_auth_init;
|
|
9165 soap->fsslverify = ssl_verify_callback;
|
|
9166 soap->bio = NULL;
|
|
9167 soap->ssl = NULL;
|
|
9168 soap->ctx = NULL;
|
|
9169 soap->session = NULL;
|
|
9170 soap->ssl_flags = SOAP_SSL_DEFAULT;
|
|
9171 soap->keyfile = NULL;
|
|
9172 soap->keyid = NULL;
|
|
9173 soap->password = NULL;
|
|
9174 soap->cafile = NULL;
|
|
9175 soap->capath = NULL;
|
|
9176 soap->crlfile = NULL;
|
|
9177 soap->dhfile = NULL;
|
|
9178 soap->randfile = NULL;
|
|
9179 #endif
|
|
9180 #ifdef WITH_GNUTLS
|
|
9181 if (!soap_ssl_init_done)
|
|
9182 soap_ssl_init();
|
|
9183 soap->fsslauth = ssl_auth_init;
|
|
9184 soap->fsslverify = NULL;
|
|
9185 soap->xcred = NULL;
|
|
9186 soap->acred = NULL;
|
|
9187 soap->cache = NULL;
|
|
9188 soap->session = NULL;
|
|
9189 soap->ssl_flags = SOAP_SSL_DEFAULT;
|
|
9190 soap->keyfile = NULL;
|
|
9191 soap->keyid = NULL;
|
|
9192 soap->password = NULL;
|
|
9193 soap->cafile = NULL;
|
|
9194 soap->capath = NULL;
|
|
9195 soap->crlfile = NULL;
|
|
9196 soap->dh_params = NULL;
|
|
9197 soap->rsa_params = NULL;
|
|
9198 #endif
|
|
9199 #ifdef WITH_C_LOCALE
|
|
9200 # ifdef WIN32
|
|
9201 soap->c_locale = _create_locale(LC_ALL, "C");
|
|
9202 # else
|
|
9203 soap->c_locale = newlocale(LC_ALL_MASK, "C", NULL);
|
|
9204 # endif
|
|
9205 #else
|
|
9206 soap->c_locale = NULL;
|
|
9207 #endif
|
|
9208 soap->buflen = 0;
|
|
9209 soap->bufidx = 0;
|
|
9210 #ifndef WITH_LEANER
|
|
9211 soap->dime.chunksize = 0;
|
|
9212 soap->dime.buflen = 0;
|
|
9213 #endif
|
|
9214 soap->null = 0;
|
|
9215 soap->position = 0;
|
|
9216 soap->encoding = 0;
|
|
9217 soap->mustUnderstand = 0;
|
|
9218 soap->ns = 0;
|
|
9219 soap->part = SOAP_END;
|
|
9220 soap->event = 0;
|
|
9221 soap->evlev = 0;
|
|
9222 soap->alloced = 0;
|
|
9223 soap->count = 0;
|
|
9224 soap->length = 0;
|
|
9225 soap->cdata = 0;
|
|
9226 soap->peeked = 0;
|
|
9227 soap->ahead = 0;
|
|
9228 soap->idnum = 0;
|
|
9229 soap->level = 0;
|
|
9230 soap->endpoint[0] = '\0';
|
|
9231 soap->error = SOAP_OK;
|
|
9232 }
|
|
9233 #endif
|
|
9234
|
|
9235 /******************************************************************************/
|
|
9236 #ifndef PALM_2
|
|
9237 SOAP_FMAC1
|
|
9238 void
|
|
9239 SOAP_FMAC2
|
|
9240 soap_begin(struct soap *soap)
|
|
9241 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reinitializing context\n"));
|
|
9242 if (!soap->keep_alive)
|
|
9243 { soap->buflen = 0;
|
|
9244 soap->bufidx = 0;
|
|
9245 }
|
|
9246 soap->null = 0;
|
|
9247 soap->position = 0;
|
|
9248 soap->encoding = 0;
|
|
9249 soap->mustUnderstand = 0;
|
|
9250 soap->mode = 0;
|
|
9251 soap->ns = 0;
|
|
9252 soap->part = SOAP_END;
|
|
9253 soap->event = 0;
|
|
9254 soap->evlev = 0;
|
|
9255 soap->alloced = 0;
|
|
9256 soap->count = 0;
|
|
9257 soap->length = 0;
|
|
9258 soap->cdata = 0;
|
|
9259 soap->error = SOAP_OK;
|
|
9260 soap->peeked = 0;
|
|
9261 soap->ahead = 0;
|
|
9262 soap->idnum = 0;
|
|
9263 soap->level = 0;
|
|
9264 soap->endpoint[0] = '\0';
|
|
9265 soap->encodingStyle = SOAP_STR_EOS;
|
|
9266 #ifndef WITH_LEANER
|
|
9267 soap->dime.chunksize = 0;
|
|
9268 soap->dime.buflen = 0;
|
|
9269 #endif
|
|
9270 soap_free_temp(soap);
|
|
9271 }
|
|
9272 #endif
|
|
9273
|
|
9274 /******************************************************************************/
|
|
9275 #ifndef PALM_2
|
|
9276 SOAP_FMAC1
|
|
9277 void
|
|
9278 SOAP_FMAC2
|
|
9279 soap_end(struct soap *soap)
|
|
9280 { if (soap_check_state(soap))
|
|
9281 return;
|
|
9282 soap_free_temp(soap);
|
|
9283 soap_dealloc(soap, NULL);
|
|
9284 while (soap->clist)
|
|
9285 { register struct soap_clist *cp = soap->clist->next;
|
|
9286 SOAP_FREE(soap, soap->clist);
|
|
9287 soap->clist = cp;
|
|
9288 }
|
|
9289 soap_closesock(soap);
|
|
9290 #ifdef SOAP_DEBUG
|
|
9291 soap_close_logfiles(soap);
|
|
9292 #endif
|
|
9293 #ifdef PALM
|
|
9294 palmNetLibClose();
|
|
9295 #endif
|
|
9296 }
|
|
9297 #endif
|
|
9298
|
|
9299 /******************************************************************************/
|
|
9300 #ifndef PALM_1
|
|
9301 SOAP_FMAC1
|
|
9302 void
|
|
9303 SOAP_FMAC2
|
|
9304 soap_set_version(struct soap *soap, short version)
|
|
9305 { soap_set_local_namespaces(soap);
|
|
9306 if (soap->version != version)
|
|
9307 { if (version == 1)
|
|
9308 { soap->local_namespaces[0].ns = soap_env1;
|
|
9309 soap->local_namespaces[1].ns = soap_enc1;
|
|
9310 }
|
|
9311 else if (version == 2)
|
|
9312 { soap->local_namespaces[0].ns = soap_env2;
|
|
9313 soap->local_namespaces[1].ns = soap_enc2;
|
|
9314 }
|
|
9315 soap->version = version;
|
|
9316 }
|
|
9317 }
|
|
9318 #endif
|
|
9319
|
|
9320 /******************************************************************************/
|
|
9321 #ifndef PALM_1
|
|
9322 SOAP_FMAC1
|
|
9323 int
|
|
9324 SOAP_FMAC2
|
|
9325 soap_set_namespaces(struct soap *soap, const struct Namespace *p)
|
|
9326 { register struct Namespace *ns = soap->local_namespaces;
|
|
9327 register struct soap_nlist *np, *nq, *nr;
|
|
9328 register unsigned int level = soap->level;
|
|
9329 soap->namespaces = p;
|
|
9330 soap->local_namespaces = NULL;
|
|
9331 soap_set_local_namespaces(soap);
|
|
9332 /* reverse the namespace list */
|
|
9333 np = soap->nlist;
|
|
9334 soap->nlist = NULL;
|
|
9335 if (np)
|
|
9336 { nq = np->next;
|
|
9337 np->next = NULL;
|
|
9338 while (nq)
|
|
9339 { nr = nq->next;
|
|
9340 nq->next = np;
|
|
9341 np = nq;
|
|
9342 nq = nr;
|
|
9343 }
|
|
9344 }
|
|
9345 /* then push on new stack */
|
|
9346 while (np)
|
|
9347 { register const char *s;
|
|
9348 soap->level = np->level; /* preserve element nesting level */
|
|
9349 s = np->ns;
|
|
9350 if (!s && np->index >= 0 && ns)
|
|
9351 { s = ns[np->index].out;
|
|
9352 if (!s)
|
|
9353 s = ns[np->index].ns;
|
|
9354 }
|
|
9355 if (s && soap_push_namespace(soap, np->id, s) == NULL)
|
|
9356 return soap->error;
|
|
9357 nq = np;
|
|
9358 np = np->next;
|
|
9359 SOAP_FREE(soap, nq);
|
|
9360 }
|
|
9361 if (ns)
|
|
9362 { register int i;
|
|
9363 for (i = 0; ns[i].id; i++)
|
|
9364 { if (ns[i].out)
|
|
9365 { SOAP_FREE(soap, ns[i].out);
|
|
9366 ns[i].out = NULL;
|
|
9367 }
|
|
9368 }
|
|
9369 SOAP_FREE(soap, ns);
|
|
9370 }
|
|
9371 soap->level = level; /* restore level */
|
|
9372 return SOAP_OK;
|
|
9373 }
|
|
9374 #endif
|
|
9375
|
|
9376 /******************************************************************************/
|
|
9377 #ifndef PALM_1
|
|
9378 SOAP_FMAC1
|
|
9379 void
|
|
9380 SOAP_FMAC2
|
|
9381 soap_set_local_namespaces(struct soap *soap)
|
|
9382 { if (soap->namespaces && !soap->local_namespaces)
|
|
9383 { register const struct Namespace *ns1;
|
|
9384 register struct Namespace *ns2;
|
|
9385 register size_t n = 1;
|
|
9386 for (ns1 = soap->namespaces; ns1->id; ns1++)
|
|
9387 n++;
|
|
9388 n *= sizeof(struct Namespace);
|
|
9389 ns2 = (struct Namespace*)SOAP_MALLOC(soap, n);
|
|
9390 if (ns2)
|
|
9391 { memcpy(ns2, soap->namespaces, n);
|
|
9392 if (ns2[0].ns)
|
|
9393 { if (!strcmp(ns2[0].ns, soap_env1))
|
|
9394 soap->version = 1;
|
|
9395 else if (!strcmp(ns2[0].ns, soap_env2))
|
|
9396 soap->version = 2;
|
|
9397 }
|
|
9398 soap->local_namespaces = ns2;
|
|
9399 for (; ns2->id; ns2++)
|
|
9400 ns2->out = NULL;
|
|
9401 }
|
|
9402 }
|
|
9403 }
|
|
9404 #endif
|
|
9405
|
|
9406 /******************************************************************************/
|
|
9407 #ifndef WITH_LEAN
|
|
9408 #ifndef PALM_1
|
|
9409 SOAP_FMAC1
|
|
9410 const char *
|
|
9411 SOAP_FMAC2
|
|
9412 soap_tagsearch(const char *big, const char *little)
|
|
9413 { if (little)
|
|
9414 { register size_t n = strlen(little);
|
|
9415 register const char *s = big;
|
|
9416 while (s)
|
|
9417 { register const char *t = s;
|
|
9418 register size_t i;
|
|
9419 for (i = 0; i < n; i++, t++)
|
|
9420 { if (*t != little[i])
|
|
9421 break;
|
|
9422 }
|
|
9423 if (*t == '\0' || *t == ' ')
|
|
9424 { if (i == n || (i && little[i-1] == ':'))
|
|
9425 return s;
|
|
9426 }
|
|
9427 s = strchr(t, ' ');
|
|
9428 if (s)
|
|
9429 s++;
|
|
9430 }
|
|
9431 }
|
|
9432 return NULL;
|
|
9433 }
|
|
9434 #endif
|
|
9435 #endif
|
|
9436
|
|
9437 /******************************************************************************/
|
|
9438 #ifndef WITH_LEAN
|
|
9439 #ifndef PALM_1
|
|
9440 SOAP_FMAC1
|
|
9441 struct soap_nlist *
|
|
9442 SOAP_FMAC2
|
|
9443 soap_lookup_ns(struct soap *soap, const char *tag, size_t n)
|
|
9444 { register struct soap_nlist *np;
|
|
9445 for (np = soap->nlist; np; np = np->next)
|
|
9446 { if (!strncmp(np->id, tag, n) && !np->id[n])
|
|
9447 return np;
|
|
9448 }
|
|
9449 return NULL;
|
|
9450 }
|
|
9451 #endif
|
|
9452 #endif
|
|
9453
|
|
9454 /******************************************************************************/
|
|
9455 #ifndef WITH_LEAN
|
|
9456 static struct soap_nlist *
|
|
9457 soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized)
|
|
9458 { register struct soap_nlist *np;
|
|
9459 size_t n, k;
|
|
9460 if (soap_tagsearch(soap->c14nexclude, id))
|
|
9461 return NULL;
|
|
9462 if (!utilized)
|
|
9463 { for (np = soap->nlist; np; np = np->next)
|
|
9464 { if (!strcmp(np->id, id) && (!np->ns || !strcmp(np->ns, ns)))
|
|
9465 break;
|
|
9466 }
|
|
9467 if (np)
|
|
9468 { if ((np->level < soap->level || !np->ns) && np->index == 1)
|
|
9469 utilized = 1;
|
|
9470 else
|
|
9471 return NULL;
|
|
9472 }
|
|
9473 }
|
|
9474 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Adding namespace binding (level=%u) '%s' '%s' utilized=%d\n", soap->level, id, ns ? ns : "(null)", utilized));
|
|
9475 n = strlen(id);
|
|
9476 if (ns)
|
|
9477 k = strlen(ns);
|
|
9478 else
|
|
9479 k = 0;
|
|
9480 np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k + 1);
|
|
9481 if (!np)
|
|
9482 { soap->error = SOAP_EOM;
|
|
9483 return NULL;
|
|
9484 }
|
|
9485 np->next = soap->nlist;
|
|
9486 soap->nlist = np;
|
|
9487 strcpy((char*)np->id, id);
|
|
9488 if (ns)
|
|
9489 np->ns = strcpy((char*)np->id + n + 1, ns);
|
|
9490 else
|
|
9491 np->ns = NULL;
|
|
9492 np->level = soap->level;
|
|
9493 np->index = utilized;
|
|
9494 return np;
|
|
9495 }
|
|
9496 #endif
|
|
9497
|
|
9498 /******************************************************************************/
|
|
9499 #ifndef WITH_LEAN
|
|
9500 static void
|
|
9501 soap_utilize_ns(struct soap *soap, const char *tag)
|
|
9502 { register struct soap_nlist *np;
|
|
9503 size_t n = 0;
|
|
9504 const char *t = strchr(tag, ':');
|
|
9505 if (t)
|
|
9506 { n = t - tag;
|
|
9507 if (n >= sizeof(soap->tmpbuf))
|
|
9508 n = sizeof(soap->tmpbuf) - 1;
|
|
9509 }
|
|
9510 np = soap_lookup_ns(soap, tag, n);
|
|
9511 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Utilizing namespace of '%s'\n", tag));
|
|
9512 if (np)
|
|
9513 { if (np->index <= 0)
|
|
9514 soap_push_ns(soap, np->id, np->ns, 1);
|
|
9515 }
|
|
9516 else if (strncmp(tag, "xml", 3))
|
|
9517 { strncpy(soap->tmpbuf, tag, n);
|
|
9518 soap->tmpbuf[n] = '\0';
|
|
9519 soap_push_ns(soap, soap->tmpbuf, NULL, 1);
|
|
9520 }
|
|
9521 }
|
|
9522 #endif
|
|
9523
|
|
9524 /******************************************************************************/
|
|
9525 #ifndef PALM_2
|
|
9526 SOAP_FMAC1
|
|
9527 int
|
|
9528 SOAP_FMAC2
|
|
9529 soap_element(struct soap *soap, const char *tag, int id, const char *type)
|
|
9530 {
|
|
9531 #ifndef WITH_LEAN
|
|
9532 register const char *s;
|
|
9533 #endif
|
|
9534 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element begin tag='%s' level='%u' id='%d' type='%s'\n", tag, soap->level, id, type ? type : SOAP_STR_EOS));
|
|
9535 soap->level++;
|
|
9536 #ifdef WITH_DOM
|
|
9537 #ifndef WITH_LEAN
|
|
9538 if (soap->wsuid && soap_tagsearch(soap->wsuid, tag))
|
|
9539 { size_t i;
|
|
9540 for (s = tag, i = 0; *s && i < sizeof(soap->tag) - 1; s++, i++)
|
|
9541 soap->tag[i] = *s == ':' ? '-' : *s;
|
|
9542 soap->tag[i] = '\0';
|
|
9543 if (soap_set_attr(soap, "wsu:Id", soap->tag, 1))
|
|
9544 return soap->error;
|
|
9545 }
|
|
9546 if ((soap->mode & SOAP_XML_CANONICAL) && !(soap->mode & SOAP_DOM_ASIS))
|
|
9547 { if (soap->evlev >= soap->level)
|
|
9548 soap->evlev = 0;
|
|
9549 if (soap->event == SOAP_SEC_BEGIN && !soap->evlev)
|
|
9550 { register struct soap_nlist *np;
|
|
9551 /* non-nested wsu:Id found: clear xmlns, re-emit them for exc-c14n */
|
|
9552 for (np = soap->nlist; np; np = np->next)
|
|
9553 { if (np->index == 2)
|
|
9554 { struct soap_nlist *np1 = soap_push_ns(soap, np->id, np->ns, 1);
|
|
9555 if (np1)
|
|
9556 np1->index = 0;
|
|
9557 }
|
|
9558 }
|
|
9559 soap->evlev = soap->level;
|
|
9560 }
|
|
9561 }
|
|
9562 #endif
|
|
9563 if (soap->mode & SOAP_XML_DOM)
|
|
9564 { register struct soap_dom_element *elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element));
|
|
9565 if (!elt)
|
|
9566 return soap->error;
|
|
9567 elt->soap = soap;
|
|
9568 elt->next = NULL;
|
|
9569 elt->prnt = soap->dom;
|
|
9570 elt->name = soap_strdup(soap, tag);
|
|
9571 elt->elts = NULL;
|
|
9572 elt->atts = NULL;
|
|
9573 elt->nstr = NULL;
|
|
9574 elt->data = NULL;
|
|
9575 elt->wide = NULL;
|
|
9576 elt->node = NULL;
|
|
9577 elt->type = 0;
|
|
9578 elt->head = NULL;
|
|
9579 elt->tail = NULL;
|
|
9580 if (soap->dom)
|
|
9581 { struct soap_dom_element *p = soap->dom->elts;
|
|
9582 if (p)
|
|
9583 { while (p->next)
|
|
9584 p = p->next;
|
|
9585 p->next = elt;
|
|
9586 }
|
|
9587 else
|
|
9588 soap->dom->elts = elt;
|
|
9589 }
|
|
9590 soap->dom = elt;
|
|
9591 }
|
|
9592 else
|
|
9593 {
|
|
9594 #endif
|
|
9595 #ifndef WITH_LEAN
|
|
9596 if (!soap->ns)
|
|
9597 { if (!(soap->mode & SOAP_XML_CANONICAL)
|
|
9598 && soap_send(soap, soap->prolog ? soap->prolog : "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"))
|
|
9599 return soap->error;
|
|
9600 }
|
|
9601 else if (soap->mode & SOAP_XML_INDENT)
|
|
9602 { if (soap->ns == 1 && soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1))
|
|
9603 return soap->error;
|
|
9604 soap->body = 1;
|
|
9605 }
|
|
9606 if ((soap->mode & SOAP_XML_DEFAULTNS) && (s = strchr(tag, ':')))
|
|
9607 { struct Namespace *ns = soap->local_namespaces;
|
|
9608 size_t n = s - tag;
|
|
9609 if (soap_send_raw(soap, "<", 1)
|
|
9610 || soap_send(soap, s + 1))
|
|
9611 return soap->error;
|
|
9612 if (soap->nlist && !strncmp(soap->nlist->id, tag, n) && !soap->nlist->id[n])
|
|
9613 ns = NULL;
|
|
9614 for (; ns && ns->id; ns++)
|
|
9615 { if (*ns->id && (ns->out || ns->ns) && !strncmp(ns->id, tag, n) && !ns->id[n])
|
|
9616 { soap_push_ns(soap, ns->id, ns->out ? ns->out : ns->ns, 0);
|
|
9617 if (soap_attribute(soap, "xmlns", ns->out ? ns->out : ns->ns))
|
|
9618 return soap->error;
|
|
9619 break;
|
|
9620 }
|
|
9621 }
|
|
9622 }
|
|
9623 else
|
|
9624 #endif
|
|
9625 if (soap_send_raw(soap, "<", 1)
|
|
9626 || soap_send(soap, tag))
|
|
9627 return soap->error;
|
|
9628 #ifdef WITH_DOM
|
|
9629 }
|
|
9630 #endif
|
|
9631 if (!soap->ns)
|
|
9632 { struct Namespace *ns = soap->local_namespaces;
|
|
9633 int k = -1;
|
|
9634 if (ns)
|
|
9635 {
|
|
9636 #ifndef WITH_LEAN
|
|
9637 if ((soap->mode & SOAP_XML_DEFAULTNS))
|
|
9638 { if (soap->version)
|
|
9639 k = 4; /* first four required entries */
|
|
9640 else if (!(soap->mode & SOAP_XML_NOTYPE) || (soap->mode & SOAP_XML_NIL))
|
|
9641 { ns += 2;
|
|
9642 k = 2; /* next two entries */
|
|
9643 }
|
|
9644 else
|
|
9645 k = 0; /* no entries */
|
|
9646 }
|
|
9647 #endif
|
|
9648 while (k-- && ns->id)
|
|
9649 { if (*ns->id && (ns->out || ns->ns))
|
|
9650 {
|
|
9651 #ifdef HAVE_SNPRINTF
|
|
9652 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "xmlns:%s", ns->id);
|
|
9653 #else
|
|
9654 sprintf(soap->tmpbuf, "xmlns:%s", ns->id);
|
|
9655 #endif
|
|
9656 if (soap_attribute(soap, soap->tmpbuf, ns->out ? ns->out : ns->ns))
|
|
9657 return soap->error;
|
|
9658 }
|
|
9659 ns++;
|
|
9660 }
|
|
9661 }
|
|
9662 }
|
|
9663 soap->ns = 1; /* namespace table control: ns = 0 or 2 to start, then 1 to stop dumping the table */
|
|
9664 #ifndef WITH_LEAN
|
|
9665 if (soap->mode & SOAP_XML_CANONICAL)
|
|
9666 soap_utilize_ns(soap, tag);
|
|
9667 #endif
|
|
9668 if (id > 0)
|
|
9669 {
|
|
9670 #ifdef HAVE_SNPRINTF
|
|
9671 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "_%d", id);
|
|
9672 #else
|
|
9673 sprintf(soap->tmpbuf, "_%d", id);
|
|
9674 #endif
|
|
9675 if (soap->version == 2)
|
|
9676 { if (soap_attribute(soap, "SOAP-ENC:id", soap->tmpbuf))
|
|
9677 return soap->error;
|
|
9678 }
|
|
9679 else if (soap_attribute(soap, "id", soap->tmpbuf))
|
|
9680 return soap->error;
|
|
9681 }
|
|
9682 if (type && *type && !(soap->mode & SOAP_XML_NOTYPE) && soap->part != SOAP_IN_HEADER)
|
|
9683 { const char *t = type;
|
|
9684 #ifndef WITH_LEAN
|
|
9685 if (soap->mode & SOAP_XML_DEFAULTNS)
|
|
9686 { t = strchr(type, ':');
|
|
9687 if (t)
|
|
9688 t++;
|
|
9689 else
|
|
9690 t = type;
|
|
9691 }
|
|
9692 #endif
|
|
9693 if (soap->attributes ? soap_set_attr(soap, "xsi:type", t, 1) : soap_attribute(soap, "xsi:type", t))
|
|
9694 return soap->error;
|
|
9695 #ifndef WITH_LEAN
|
|
9696 if (soap->mode & SOAP_XML_CANONICAL)
|
|
9697 soap_utilize_ns(soap, type);
|
|
9698 #endif
|
|
9699 }
|
|
9700 if (soap->null && soap->position > 0)
|
|
9701 { register int i;
|
|
9702 #ifdef HAVE_SNPRINTF
|
|
9703 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf) - 1, "[%d", soap->positions[0]);
|
|
9704 #else
|
|
9705 sprintf(soap->tmpbuf, "[%d", soap->positions[0]);
|
|
9706 #endif
|
|
9707 for (i = 1; i < soap->position; i++)
|
|
9708 { register size_t l = strlen(soap->tmpbuf);
|
|
9709 #ifdef HAVE_SNPRINTF
|
|
9710 soap_snprintf(soap->tmpbuf + l, sizeof(soap->tmpbuf)-l-1, ",%d", soap->positions[i]);
|
|
9711 #else
|
|
9712 if (l + 13 < sizeof(soap->tmpbuf))
|
|
9713 sprintf(soap->tmpbuf + l, ",%d", soap->positions[i]);
|
|
9714 #endif
|
|
9715 }
|
|
9716 strcat(soap->tmpbuf, "]");
|
|
9717 if (soap_attribute(soap, "SOAP-ENC:position", soap->tmpbuf))
|
|
9718 return soap->error;
|
|
9719 }
|
|
9720 if (soap->mustUnderstand)
|
|
9721 { if (soap->actor && *soap->actor)
|
|
9722 { if (soap_attribute(soap, soap->version == 2 ? "SOAP-ENV:role" : "SOAP-ENV:actor", soap->actor))
|
|
9723 return soap->error;
|
|
9724 }
|
|
9725 if (soap_attribute(soap, "SOAP-ENV:mustUnderstand", soap->version == 2 ? "true" : "1"))
|
|
9726 return soap->error;
|
|
9727 soap->mustUnderstand = 0;
|
|
9728 }
|
|
9729 if (soap->encoding)
|
|
9730 { if (soap->encodingStyle && soap->local_namespaces && soap->local_namespaces[0].id && soap->local_namespaces[1].id)
|
|
9731 { if (!*soap->encodingStyle)
|
|
9732 { if (soap->local_namespaces[1].out)
|
|
9733 soap->encodingStyle = soap->local_namespaces[1].out;
|
|
9734 else
|
|
9735 soap->encodingStyle = soap->local_namespaces[1].ns;
|
|
9736 }
|
|
9737 if (soap->encodingStyle && soap_attribute(soap, "SOAP-ENV:encodingStyle", soap->encodingStyle))
|
|
9738 return soap->error;
|
|
9739 }
|
|
9740 else
|
|
9741 soap->encodingStyle = NULL;
|
|
9742 soap->encoding = 0;
|
|
9743 }
|
|
9744 soap->null = 0;
|
|
9745 soap->position = 0;
|
|
9746 if (soap->event == SOAP_SEC_BEGIN)
|
|
9747 soap->event = 0;
|
|
9748 return SOAP_OK;
|
|
9749 }
|
|
9750 #endif
|
|
9751
|
|
9752 /******************************************************************************/
|
|
9753 #ifndef PALM_2
|
|
9754 SOAP_FMAC1
|
|
9755 int
|
|
9756 SOAP_FMAC2
|
|
9757 soap_element_begin_out(struct soap *soap, const char *tag, int id, const char *type)
|
|
9758 { if (*tag == '-')
|
|
9759 return SOAP_OK;
|
|
9760 if (soap_element(soap, tag, id, type))
|
|
9761 return soap->error;
|
|
9762 #ifdef WITH_DOM
|
|
9763 if (soap_element_start_end_out(soap, NULL))
|
|
9764 return soap->error;
|
|
9765 if (soap->feltbegout)
|
|
9766 return soap->error = soap->feltbegout(soap, tag);
|
|
9767 return SOAP_OK;
|
|
9768 #else
|
|
9769 return soap_element_start_end_out(soap, NULL);
|
|
9770 #endif
|
|
9771 }
|
|
9772 #endif
|
|
9773
|
|
9774 /******************************************************************************/
|
|
9775 #ifndef PALM_2
|
|
9776 #ifndef HAVE_STRRCHR
|
|
9777 SOAP_FMAC1
|
|
9778 char*
|
|
9779 SOAP_FMAC2
|
|
9780 soap_strrchr(const char *s, int t)
|
|
9781 { register char *r = NULL;
|
|
9782 while (*s)
|
|
9783 if (*s++ == t)
|
|
9784 r = (char*)s - 1;
|
|
9785 return r;
|
|
9786 }
|
|
9787 #endif
|
|
9788 #endif
|
|
9789
|
|
9790 /******************************************************************************/
|
|
9791 #ifndef PALM_2
|
|
9792 #ifndef HAVE_STRTOL
|
|
9793 SOAP_FMAC1
|
|
9794 long
|
|
9795 SOAP_FMAC2
|
|
9796 soap_strtol(const char *s, char **t, int b)
|
|
9797 { register long n = 0;
|
|
9798 register int c;
|
|
9799 while (*s > 0 && *s <= 32)
|
|
9800 s++;
|
|
9801 if (b == 10)
|
|
9802 { short neg = 0;
|
|
9803 if (*s == '-')
|
|
9804 { s++;
|
|
9805 neg = 1;
|
|
9806 }
|
|
9807 else if (*s == '+')
|
|
9808 s++;
|
|
9809 while ((c = *s) && c >= '0' && c <= '9')
|
|
9810 { if (n >= 214748364 && (n > 214748364 || c >= '8'))
|
|
9811 break;
|
|
9812 n *= 10;
|
|
9813 n += c - '0';
|
|
9814 s++;
|
|
9815 }
|
|
9816 if (neg)
|
|
9817 n = -n;
|
|
9818 }
|
|
9819 else /* assume b == 16 and value is always positive */
|
|
9820 { while ((c = *s))
|
|
9821 { if (c >= '0' && c <= '9')
|
|
9822 c -= '0';
|
|
9823 else if (c >= 'A' && c <= 'F')
|
|
9824 c -= 'A' - 10;
|
|
9825 else if (c >= 'a' && c <= 'f')
|
|
9826 c -= 'a' - 10;
|
|
9827 if (n > 0x07FFFFFF)
|
|
9828 break;
|
|
9829 n <<= 4;
|
|
9830 n += c;
|
|
9831 s++;
|
|
9832 }
|
|
9833 }
|
|
9834 if (t)
|
|
9835 *t = (char*)s;
|
|
9836 return n;
|
|
9837 }
|
|
9838 #endif
|
|
9839 #endif
|
|
9840
|
|
9841 /******************************************************************************/
|
|
9842 #ifndef PALM_2
|
|
9843 #ifndef HAVE_STRTOUL
|
|
9844 SOAP_FMAC1
|
|
9845 unsigned long
|
|
9846 SOAP_FMAC2
|
|
9847 soap_strtoul(const char *s, char **t, int b)
|
|
9848 { unsigned long n = 0;
|
|
9849 register int c;
|
|
9850 while (*s > 0 && *s <= 32)
|
|
9851 s++;
|
|
9852 if (b == 10)
|
|
9853 { if (*s == '+')
|
|
9854 s++;
|
|
9855 while ((c = *s) && c >= '0' && c <= '9')
|
|
9856 { if (n >= 429496729 && (n > 429496729 || c >= '6'))
|
|
9857 break;
|
|
9858 n *= 10;
|
|
9859 n += c - '0';
|
|
9860 s++;
|
|
9861 }
|
|
9862 }
|
|
9863 else /* b == 16 */
|
|
9864 { while ((c = *s))
|
|
9865 { if (c >= '0' && c <= '9')
|
|
9866 c -= '0';
|
|
9867 else if (c >= 'A' && c <= 'F')
|
|
9868 c -= 'A' - 10;
|
|
9869 else if (c >= 'a' && c <= 'f')
|
|
9870 c -= 'a' - 10;
|
|
9871 if (n > 0x0FFFFFFF)
|
|
9872 break;
|
|
9873 n <<= 4;
|
|
9874 n += c;
|
|
9875 s++;
|
|
9876 }
|
|
9877 }
|
|
9878 if (t)
|
|
9879 *t = (char*)s;
|
|
9880 return n;
|
|
9881 }
|
|
9882 #endif
|
|
9883 #endif
|
|
9884
|
|
9885 /******************************************************************************/
|
|
9886 #ifndef PALM_1
|
|
9887 SOAP_FMAC1
|
|
9888 int
|
|
9889 SOAP_FMAC2
|
|
9890 soap_array_begin_out(struct soap *soap, const char *tag, int id, const char *type, const char *offset)
|
|
9891 { if (!type || !*type)
|
|
9892 return soap_element_begin_out(soap, tag, id, NULL);
|
|
9893 if (soap_element(soap, tag, id, "SOAP-ENC:Array"))
|
|
9894 return soap->error;
|
|
9895 if (soap->version == 2)
|
|
9896 { const char *s;
|
|
9897 s = soap_strrchr(type, '[');
|
|
9898 if (s && (size_t)(s - type) < sizeof(soap->tmpbuf))
|
|
9899 { strncpy(soap->tmpbuf, type, s - type);
|
|
9900 soap->tmpbuf[s - type] = '\0';
|
|
9901 if (soap_attribute(soap, "SOAP-ENC:itemType", soap->tmpbuf))
|
|
9902 return soap->error;
|
|
9903 s++;
|
|
9904 if (*s)
|
|
9905 { strncpy(soap->tmpbuf, s, sizeof(soap->tmpbuf));
|
|
9906 soap->tmpbuf[sizeof(soap->tmpbuf) - 1] = '\0';
|
|
9907 soap->tmpbuf[strlen(soap->tmpbuf) - 1] = '\0';
|
|
9908 if (soap_attribute(soap, "SOAP-ENC:arraySize", soap->tmpbuf))
|
|
9909 return soap->error;
|
|
9910 }
|
|
9911 }
|
|
9912 }
|
|
9913 else
|
|
9914 { if (offset && soap_attribute(soap, "SOAP-ENC:offset", offset))
|
|
9915 return soap->error;
|
|
9916 if (soap_attribute(soap, "SOAP-ENC:arrayType", type))
|
|
9917 return soap->error;
|
|
9918 }
|
|
9919 #ifndef WITH_LEAN
|
|
9920 if ((soap->mode & SOAP_XML_CANONICAL))
|
|
9921 soap_utilize_ns(soap, type);
|
|
9922 #endif
|
|
9923 return soap_element_start_end_out(soap, NULL);
|
|
9924 }
|
|
9925 #endif
|
|
9926
|
|
9927 /******************************************************************************/
|
|
9928 #ifndef PALM_1
|
|
9929 SOAP_FMAC1
|
|
9930 int
|
|
9931 SOAP_FMAC2
|
|
9932 soap_element_start_end_out(struct soap *soap, const char *tag)
|
|
9933 { register struct soap_attribute *tp;
|
|
9934 #ifndef WITH_LEAN
|
|
9935 if (soap->mode & SOAP_XML_CANONICAL)
|
|
9936 { struct soap_nlist *np;
|
|
9937 for (tp = soap->attributes; tp; tp = tp->next)
|
|
9938 { if (tp->visible && tp->name)
|
|
9939 soap_utilize_ns(soap, tp->name);
|
|
9940 }
|
|
9941 for (np = soap->nlist; np; np = np->next)
|
|
9942 { if (np->index == 1 && np->ns)
|
|
9943 { if (*(np->id))
|
|
9944 {
|
|
9945 #ifdef HAVE_SNPRINTF
|
|
9946 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "xmlns:%s", np->id);
|
|
9947 #else
|
|
9948 sprintf(soap->tmpbuf, "xmlns:%s", np->id);
|
|
9949 #endif
|
|
9950 }
|
|
9951 else
|
|
9952 strcpy(soap->tmpbuf, "xmlns");
|
|
9953 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enabling utilized binding (level=%u) %s='%s'\n", np->level, soap->tmpbuf, np->ns));
|
|
9954 soap_set_attr(soap, soap->tmpbuf, np->ns, 1);
|
|
9955 np->index = 2;
|
|
9956 }
|
|
9957 }
|
|
9958 }
|
|
9959 #endif
|
|
9960 #ifdef WITH_DOM
|
|
9961 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
|
|
9962 { register struct soap_dom_attribute **att;
|
|
9963 att = &soap->dom->atts;
|
|
9964 for (tp = soap->attributes; tp; tp = tp->next)
|
|
9965 { if (tp->visible)
|
|
9966 { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
|
|
9967 if (!*att)
|
|
9968 return soap->error;
|
|
9969 (*att)->next = NULL;
|
|
9970 (*att)->nstr = NULL;
|
|
9971 (*att)->name = soap_strdup(soap, tp->name);
|
|
9972 (*att)->data = soap_strdup(soap, tp->value);
|
|
9973 (*att)->wide = NULL;
|
|
9974 (*att)->soap = soap;
|
|
9975 att = &(*att)->next;
|
|
9976 tp->visible = 0;
|
|
9977 }
|
|
9978 }
|
|
9979 return SOAP_OK;
|
|
9980 }
|
|
9981 #endif
|
|
9982 for (tp = soap->attributes; tp; tp = tp->next)
|
|
9983 { if (tp->visible)
|
|
9984 {
|
|
9985 #ifndef WITH_LEAN
|
|
9986 const char *s;
|
|
9987 if ((soap->mode & SOAP_XML_DEFAULTNS) && (s = strchr(tp->name, ':')))
|
|
9988 { size_t n = s - tp->name;
|
|
9989 if (soap->nlist && !strncmp(soap->nlist->id, tp->name, n) && !soap->nlist->id[n])
|
|
9990 s++;
|
|
9991 else
|
|
9992 s = tp->name;
|
|
9993 if (soap_send(soap, " ") || soap_send(soap, s))
|
|
9994 return soap->error;
|
|
9995 }
|
|
9996 else
|
|
9997 #endif
|
|
9998 if (soap_send(soap, " ") || soap_send(soap, tp->name))
|
|
9999 return soap->error;
|
|
10000 if (tp->visible == 2 && tp->value)
|
|
10001 if (soap_send_raw(soap, "=\"", 2)
|
|
10002 || soap_string_out(soap, tp->value, tp->flag)
|
|
10003 || soap_send_raw(soap, "\"", 1))
|
|
10004 return soap->error;
|
|
10005 tp->visible = 0;
|
|
10006 }
|
|
10007 }
|
|
10008 if (tag)
|
|
10009 {
|
|
10010 #ifndef WITH_LEAN
|
|
10011 if (soap->mode & SOAP_XML_CANONICAL)
|
|
10012 { if (soap_send_raw(soap, ">", 1)
|
|
10013 || soap_element_end_out(soap, tag))
|
|
10014 return soap->error;
|
|
10015 return SOAP_OK;
|
|
10016 }
|
|
10017 #endif
|
|
10018 soap->level--; /* decrement level just before /> */
|
|
10019 return soap_send_raw(soap, "/>", 2);
|
|
10020 }
|
|
10021 return soap_send_raw(soap, ">", 1);
|
|
10022 }
|
|
10023 #endif
|
|
10024
|
|
10025 /******************************************************************************/
|
|
10026 #ifndef PALM_1
|
|
10027 SOAP_FMAC1
|
|
10028 int
|
|
10029 SOAP_FMAC2
|
|
10030 soap_element_end_out(struct soap *soap, const char *tag)
|
|
10031 {
|
|
10032 #ifndef WITH_LEAN
|
|
10033 const char *s;
|
|
10034 #endif
|
|
10035 if (*tag == '-')
|
|
10036 return SOAP_OK;
|
|
10037 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element ending tag='%s'\n", tag));
|
|
10038 #ifdef WITH_DOM
|
|
10039 if (soap->feltendout && (soap->error = soap->feltendout(soap, tag)))
|
|
10040 return soap->error;
|
|
10041 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
|
|
10042 { if (soap->dom->prnt)
|
|
10043 soap->dom = soap->dom->prnt;
|
|
10044 return SOAP_OK;
|
|
10045 }
|
|
10046 #endif
|
|
10047 #ifndef WITH_LEAN
|
|
10048 if (soap->mode & SOAP_XML_CANONICAL)
|
|
10049 soap_pop_namespace(soap);
|
|
10050 if (soap->mode & SOAP_XML_INDENT)
|
|
10051 { if (!soap->body)
|
|
10052 { if (soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1))
|
|
10053 return soap->error;
|
|
10054 }
|
|
10055 soap->body = 0;
|
|
10056 }
|
|
10057 if ((soap->mode & SOAP_XML_DEFAULTNS) && (s = strchr(tag, ':')))
|
|
10058 { soap_pop_namespace(soap);
|
|
10059 tag = s + 1;
|
|
10060 }
|
|
10061 #endif
|
|
10062 if (soap_send_raw(soap, "</", 2)
|
|
10063 || soap_send(soap, tag))
|
|
10064 return soap->error;
|
|
10065 soap->level--; /* decrement level just before > */
|
|
10066 return soap_send_raw(soap, ">", 1);
|
|
10067 }
|
|
10068 #endif
|
|
10069
|
|
10070 /******************************************************************************/
|
|
10071 #ifndef PALM_1
|
|
10072 SOAP_FMAC1
|
|
10073 int
|
|
10074 SOAP_FMAC2
|
|
10075 soap_element_ref(struct soap *soap, const char *tag, int id, int href)
|
|
10076 { register const char *s = "ref";
|
|
10077 register int n = 1;
|
|
10078 if (soap->version == 1)
|
|
10079 { s = "href";
|
|
10080 n = 0;
|
|
10081 }
|
|
10082 else if (soap->version == 2)
|
|
10083 s = "SOAP-ENC:ref";
|
|
10084 #ifdef HAVE_SNPRINTF
|
|
10085 soap_snprintf(soap->href, sizeof(soap->href), "#_%d", href);
|
|
10086 #else
|
|
10087 sprintf(soap->href, "#_%d", href);
|
|
10088 #endif
|
|
10089 return soap_element_href(soap, tag, id, s, soap->href + n);
|
|
10090 }
|
|
10091 #endif
|
|
10092
|
|
10093 /******************************************************************************/
|
|
10094 #ifndef PALM_1
|
|
10095 SOAP_FMAC1
|
|
10096 int
|
|
10097 SOAP_FMAC2
|
|
10098 soap_element_href(struct soap *soap, const char *tag, int id, const char *ref, const char *val)
|
|
10099 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element '%s' reference %s='%s'\n", tag, ref, val));
|
|
10100 if (soap_element(soap, tag, id, NULL)
|
|
10101 || soap_attribute(soap, ref, val)
|
|
10102 || soap_element_start_end_out(soap, tag))
|
|
10103 return soap->error;
|
|
10104 return SOAP_OK;
|
|
10105 }
|
|
10106 #endif
|
|
10107
|
|
10108 /******************************************************************************/
|
|
10109 #ifndef PALM_1
|
|
10110 SOAP_FMAC1
|
|
10111 int
|
|
10112 SOAP_FMAC2
|
|
10113 soap_element_null(struct soap *soap, const char *tag, int id, const char *type)
|
|
10114 { struct soap_attribute *tp = NULL;
|
|
10115 for (tp = soap->attributes; tp; tp = tp->next)
|
|
10116 if (tp->visible)
|
|
10117 break;
|
|
10118 if (tp || (soap->version == 2 && soap->position > 0) || id > 0 || (soap->mode & SOAP_XML_NIL))
|
|
10119 { if (soap_element(soap, tag, id, type)
|
|
10120 || (!tp && soap_attribute(soap, "xsi:nil", "true")))
|
|
10121 return soap->error;
|
|
10122 return soap_element_start_end_out(soap, tag);
|
|
10123 }
|
|
10124 soap->null = 1;
|
|
10125 soap->position = 0;
|
|
10126 soap->mustUnderstand = 0;
|
|
10127 return SOAP_OK;
|
|
10128 }
|
|
10129 #endif
|
|
10130
|
|
10131 /******************************************************************************/
|
|
10132 #ifndef PALM_1
|
|
10133 SOAP_FMAC1
|
|
10134 int
|
|
10135 SOAP_FMAC2
|
|
10136 soap_element_nil(struct soap *soap, const char *tag)
|
|
10137 { if (soap_element(soap, tag, -1, NULL)
|
|
10138 || ((soap->mode & SOAP_XML_NIL) && soap_attribute(soap, "xsi:nil", "true")))
|
|
10139 return soap->error;
|
|
10140 return soap_element_start_end_out(soap, tag);
|
|
10141 }
|
|
10142 #endif
|
|
10143
|
|
10144 /******************************************************************************/
|
|
10145 #ifndef PALM_1
|
|
10146 SOAP_FMAC1
|
|
10147 int
|
|
10148 SOAP_FMAC2
|
|
10149 soap_element_id(struct soap *soap, const char *tag, int id, const void *p, const struct soap_array *a, int n, const char *type, int t)
|
|
10150 { if (!p)
|
|
10151 { soap->error = soap_element_null(soap, tag, id, type);
|
|
10152 return -1;
|
|
10153 }
|
|
10154 #ifndef WITH_NOIDREF
|
|
10155 if ((!soap->encodingStyle && !(soap->omode & SOAP_XML_GRAPH)) || (soap->omode & SOAP_XML_TREE))
|
|
10156 return 0;
|
|
10157 if (id < 0)
|
|
10158 { struct soap_plist *pp;
|
|
10159 if (a)
|
|
10160 id = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
|
|
10161 else
|
|
10162 id = soap_pointer_lookup(soap, p, t, &pp);
|
|
10163 if (id)
|
|
10164 { if (soap_is_embedded(soap, pp))
|
|
10165 { soap_element_ref(soap, tag, 0, id);
|
|
10166 return -1;
|
|
10167 }
|
|
10168 if (soap_is_single(soap, pp))
|
|
10169 return 0;
|
|
10170 soap_set_embedded(soap, pp);
|
|
10171 }
|
|
10172 }
|
|
10173 return id;
|
|
10174 #else
|
|
10175 return 0;
|
|
10176 #endif
|
|
10177 }
|
|
10178 #endif
|
|
10179
|
|
10180 /******************************************************************************/
|
|
10181 #ifndef PALM_1
|
|
10182 SOAP_FMAC1
|
|
10183 int
|
|
10184 SOAP_FMAC2
|
|
10185 soap_element_result(struct soap *soap, const char *tag)
|
|
10186 { if (soap->version == 2 && soap->encodingStyle)
|
|
10187 { if (soap_element(soap, "SOAP-RPC:result", 0, NULL)
|
|
10188 || soap_attribute(soap, "xmlns:SOAP-RPC", soap_rpc)
|
|
10189 || soap_element_start_end_out(soap, NULL)
|
|
10190 || soap_string_out(soap, tag, 0)
|
|
10191 || soap_element_end_out(soap, "SOAP-RPC:result"))
|
|
10192 return soap->error;
|
|
10193 }
|
|
10194 return SOAP_OK;
|
|
10195 }
|
|
10196 #endif
|
|
10197
|
|
10198 /******************************************************************************/
|
|
10199 #ifndef PALM_1
|
|
10200 SOAP_FMAC1
|
|
10201 void
|
|
10202 SOAP_FMAC2
|
|
10203 soap_check_result(struct soap *soap, const char *tag)
|
|
10204 { if (soap->version == 2 && soap->encodingStyle)
|
|
10205 { soap_instring(soap, ":result", NULL, NULL, 0, 2, -1, -1);
|
|
10206 /* just ignore content for compliance reasons, but should compare tag to element's QName value? */
|
|
10207 }
|
|
10208 (void)tag;
|
|
10209 }
|
|
10210 #endif
|
|
10211
|
|
10212 /******************************************************************************/
|
|
10213 #ifndef PALM_2
|
|
10214 SOAP_FMAC1
|
|
10215 int
|
|
10216 SOAP_FMAC2
|
|
10217 soap_attribute(struct soap *soap, const char *name, const char *value)
|
|
10218 {
|
|
10219 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attribute '%s'='%s'\n", name, value));
|
|
10220 #ifdef WITH_DOM
|
|
10221 if ((soap->mode & SOAP_XML_DOM) && !(soap->mode & SOAP_XML_CANONICAL) && soap->dom)
|
|
10222 { register struct soap_dom_attribute *a = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
|
|
10223 if (!a)
|
|
10224 return soap->error;
|
|
10225 a->next = soap->dom->atts;
|
|
10226 a->nstr = NULL;
|
|
10227 a->name = soap_strdup(soap, name);
|
|
10228 a->data = soap_strdup(soap, value);
|
|
10229 a->wide = NULL;
|
|
10230 a->soap = soap;
|
|
10231 soap->dom->atts = a;
|
|
10232 return SOAP_OK;
|
|
10233 }
|
|
10234 #endif
|
|
10235 #ifndef WITH_LEAN
|
|
10236 if (soap->mode & SOAP_XML_CANONICAL)
|
|
10237 { /* push namespace */
|
|
10238 if (!strncmp(name, "xmlns", 5) && (name[5] == ':' || name[5] == '\0'))
|
|
10239 soap_push_ns(soap, name + 5 + (name[5] == ':'), value, 0);
|
|
10240 else if (soap_set_attr(soap, name, value, 1))
|
|
10241 return soap->error;
|
|
10242 }
|
|
10243 else
|
|
10244 #endif
|
|
10245 { if (soap_send(soap, " ") || soap_send(soap, name))
|
|
10246 return soap->error;
|
|
10247 if (value)
|
|
10248 if (soap_send_raw(soap, "=\"", 2)
|
|
10249 || soap_string_out(soap, value, 1)
|
|
10250 || soap_send_raw(soap, "\"", 1))
|
|
10251 return soap->error;
|
|
10252 }
|
|
10253 return SOAP_OK;
|
|
10254 }
|
|
10255 #endif
|
|
10256
|
|
10257 /******************************************************************************/
|
|
10258 #ifndef PALM_2
|
|
10259 SOAP_FMAC1
|
|
10260 int
|
|
10261 SOAP_FMAC2
|
|
10262 soap_element_begin_in(struct soap *soap, const char *tag, int nillable, const char *type)
|
|
10263 { if (!soap_peek_element(soap))
|
|
10264 { if (soap->other)
|
|
10265 return soap->error = SOAP_TAG_MISMATCH;
|
|
10266 if (tag && *tag == '-')
|
|
10267 return SOAP_OK;
|
|
10268 if (!(soap->error = soap_match_tag(soap, soap->tag, tag)))
|
|
10269 { soap->peeked = 0;
|
|
10270 if (type && *soap->type && soap_match_tag(soap, soap->type, type))
|
|
10271 return soap->error = SOAP_TYPE;
|
|
10272 if (!nillable && soap->null && (soap->mode & SOAP_XML_STRICT))
|
|
10273 return soap->error = SOAP_NULL;
|
|
10274 if (soap->body)
|
|
10275 soap->level++;
|
|
10276 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag ? tag : SOAP_STR_EOS ));
|
|
10277 soap->error = SOAP_OK;
|
|
10278 }
|
|
10279 }
|
|
10280 else if (soap->error == SOAP_NO_TAG && tag && *tag == '-')
|
|
10281 soap->error = SOAP_OK;
|
|
10282 return soap->error;
|
|
10283 }
|
|
10284 #endif
|
|
10285
|
|
10286 /******************************************************************************/
|
|
10287 #ifndef PALM_2
|
|
10288 SOAP_FMAC1
|
|
10289 int
|
|
10290 SOAP_FMAC2
|
|
10291 soap_element_end_in(struct soap *soap, const char *tag)
|
|
10292 { register soap_wchar c;
|
|
10293 register char *s;
|
|
10294 register int n = 0;
|
|
10295 if (tag && *tag == '-')
|
|
10296 return SOAP_OK;
|
|
10297 if (soap->error == SOAP_NO_TAG)
|
|
10298 soap->error = SOAP_OK;
|
|
10299 #ifdef WITH_DOM
|
|
10300 /* this whitespace or mixed content is significant for DOM */
|
|
10301 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
|
|
10302 { if (!soap->peeked && !soap_string_in(soap, 3, -1, -1))
|
|
10303 return soap->error;
|
|
10304 if (soap->dom->prnt)
|
|
10305 soap->dom = soap->dom->prnt;
|
|
10306 }
|
|
10307 #endif
|
|
10308 if (soap->peeked)
|
|
10309 { if (*soap->tag)
|
|
10310 n++;
|
|
10311 soap->peeked = 0;
|
|
10312 }
|
|
10313 do
|
|
10314 { while (((c = soap_get(soap)) != SOAP_TT))
|
|
10315 { if ((int)c == EOF)
|
|
10316 return soap->error = SOAP_CHK_EOF;
|
|
10317 if (c == SOAP_LT)
|
|
10318 n++;
|
|
10319 else if (c == '/')
|
|
10320 { c = soap_get(soap);
|
|
10321 if (c == SOAP_GT)
|
|
10322 n--;
|
|
10323 else
|
|
10324 soap_unget(soap, c);
|
|
10325 }
|
|
10326 }
|
|
10327 } while (n--);
|
|
10328 s = soap->tag;
|
|
10329 n = sizeof(soap->tag);
|
|
10330 while (soap_notblank(c = soap_get(soap)))
|
|
10331 { if (--n > 0)
|
|
10332 *s++ = (char)c;
|
|
10333 }
|
|
10334 *s = '\0';
|
|
10335 if ((int)c == EOF)
|
|
10336 return soap->error = SOAP_CHK_EOF;
|
|
10337 while (soap_blank(c))
|
|
10338 c = soap_get(soap);
|
|
10339 if (c != SOAP_GT)
|
|
10340 return soap->error = SOAP_SYNTAX_ERROR;
|
|
10341 #ifndef WITH_LEAN
|
|
10342 #ifdef WITH_DOM
|
|
10343 if (soap->feltendin)
|
|
10344 { soap->level--;
|
|
10345 return soap->error = soap->feltendin(soap, soap->tag, tag);
|
|
10346 }
|
|
10347 #endif
|
|
10348 if (tag && (soap->mode & SOAP_XML_STRICT))
|
|
10349 { soap_pop_namespace(soap);
|
|
10350 if (soap_match_tag(soap, soap->tag, tag))
|
|
10351 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element tag '%s' does not match '%s'\n", soap->tag, tag ? tag : SOAP_STR_EOS));
|
|
10352 return soap->error = SOAP_SYNTAX_ERROR;
|
|
10353 }
|
|
10354 }
|
|
10355 #endif
|
|
10356 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag ? tag : SOAP_STR_EOS));
|
|
10357 soap->level--;
|
|
10358 return SOAP_OK;
|
|
10359 }
|
|
10360 #endif
|
|
10361
|
|
10362 /******************************************************************************/
|
|
10363 #ifndef PALM_2
|
|
10364 SOAP_FMAC1
|
|
10365 const char *
|
|
10366 SOAP_FMAC2
|
|
10367 soap_attr_value(struct soap *soap, const char *name, int flag)
|
|
10368 { register struct soap_attribute *tp;
|
|
10369 if (*name == '-')
|
|
10370 return SOAP_STR_EOS;
|
|
10371 for (tp = soap->attributes; tp; tp = tp->next)
|
|
10372 { if (tp->visible && !soap_match_tag(soap, tp->name, name))
|
|
10373 break;
|
|
10374 }
|
|
10375 if (tp)
|
|
10376 { if (flag == 2 && (soap->mode & SOAP_XML_STRICT))
|
|
10377 soap->error = SOAP_PROHIBITED;
|
|
10378 else
|
|
10379 return tp->value;
|
|
10380 }
|
|
10381 else if (flag == 1 && (soap->mode & SOAP_XML_STRICT))
|
|
10382 soap->error = SOAP_REQUIRED;
|
|
10383 else
|
|
10384 soap->error = SOAP_OK;
|
|
10385 return NULL;
|
|
10386 }
|
|
10387 #endif
|
|
10388
|
|
10389 /******************************************************************************/
|
|
10390 #ifndef PALM_2
|
|
10391 SOAP_FMAC1
|
|
10392 int
|
|
10393 SOAP_FMAC2
|
|
10394 soap_set_attr(struct soap *soap, const char *name, const char *value, int flag)
|
|
10395 { register struct soap_attribute *tp;
|
|
10396 if (*name == '-')
|
|
10397 return SOAP_OK;
|
|
10398 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set attribute %s='%s'\n", name, value ? value : SOAP_STR_EOS));
|
|
10399 for (tp = soap->attributes; tp; tp = tp->next)
|
|
10400 { if (!strcmp(tp->name, name))
|
|
10401 break;
|
|
10402 }
|
|
10403 if (!tp)
|
|
10404 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute %s\n", name));
|
|
10405 if (!(tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(name))))
|
|
10406 return soap->error = SOAP_EOM;
|
|
10407 tp->ns = NULL;
|
|
10408 #ifndef WITH_LEAN
|
|
10409 if ((soap->mode & SOAP_XML_CANONICAL))
|
|
10410 { struct soap_attribute **tpp = &soap->attributes;
|
|
10411 const char *s = strchr(name, ':');
|
|
10412 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inserting attribute %s for c14n\n", name));
|
|
10413 if (!strncmp(name, "xmlns", 5))
|
|
10414 { for (; *tpp; tpp = &(*tpp)->next)
|
|
10415 if (strncmp((*tpp)->name, "xmlns", 5) || strcmp((*tpp)->name + 5, name + 5) > 0)
|
|
10416 break;
|
|
10417 }
|
|
10418 else if (!s)
|
|
10419 { for (; *tpp; tpp = &(*tpp)->next)
|
|
10420 if (strncmp((*tpp)->name, "xmlns", 5) && ((*tpp)->ns || strcmp((*tpp)->name, name) > 0))
|
|
10421 break;
|
|
10422 }
|
|
10423 else
|
|
10424 { struct soap_nlist *np = soap_lookup_ns(soap, name, s - name);
|
|
10425 if (np)
|
|
10426 tp->ns = np->ns;
|
|
10427 else
|
|
10428 { struct soap_attribute *tq;
|
|
10429 for (tq = soap->attributes; tq; tq = tq->next)
|
|
10430 { if (!strncmp(tq->name, "xmlns:", 6) && !strncmp(tq->name + 6, name, s - name) && !tq->name[6 + s - name])
|
|
10431 { tp->ns = tq->ns;
|
|
10432 break;
|
|
10433 }
|
|
10434 }
|
|
10435 }
|
|
10436 for (; *tpp; tpp = &(*tpp)->next)
|
|
10437 { int k;
|
|
10438 if (strncmp((*tpp)->name, "xmlns", 5) && (*tpp)->ns && tp->ns && ((k = strcmp((*tpp)->ns, tp->ns)) > 0 || (!k && strcmp((*tpp)->name, name) > 0)))
|
|
10439 break;
|
|
10440 }
|
|
10441 }
|
|
10442 tp->next = *tpp;
|
|
10443 *tpp = tp;
|
|
10444 }
|
|
10445 else
|
|
10446 #endif
|
|
10447 { tp->next = soap->attributes;
|
|
10448 soap->attributes = tp;
|
|
10449 }
|
|
10450 strcpy((char*)tp->name, name);
|
|
10451 tp->value = NULL;
|
|
10452 }
|
|
10453 else if (tp->visible)
|
|
10454 { return SOAP_OK;
|
|
10455 }
|
|
10456 else if (value && tp->value && tp->size <= strlen(value))
|
|
10457 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute value of %s (free %p)\n", name, tp->value));
|
|
10458 SOAP_FREE(soap, tp->value);
|
|
10459 tp->value = NULL;
|
|
10460 tp->ns = NULL;
|
|
10461 }
|
|
10462 if (value)
|
|
10463 { if (!tp->value)
|
|
10464 { tp->size = strlen(value) + 1;
|
|
10465 if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size)))
|
|
10466 return soap->error = SOAP_EOM;
|
|
10467 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute value for %s (%p)\n", tp->name, tp->value));
|
|
10468 }
|
|
10469 strcpy(tp->value, value);
|
|
10470 if (!strncmp(tp->name, "xmlns:", 6))
|
|
10471 tp->ns = tp->value;
|
|
10472 tp->visible = 2;
|
|
10473 tp->flag = (short)flag;
|
|
10474 #ifndef WITH_LEAN
|
|
10475 if (!strcmp(name, "wsu:Id"))
|
|
10476 { soap->event = SOAP_SEC_BEGIN;
|
|
10477 strncpy(soap->id, value, sizeof(soap->id));
|
|
10478 soap->id[sizeof(soap->id) - 1] = '\0';
|
|
10479 }
|
|
10480 #endif
|
|
10481 }
|
|
10482 else
|
|
10483 tp->visible = 1;
|
|
10484 return SOAP_OK;
|
|
10485 }
|
|
10486 #endif
|
|
10487
|
|
10488 /******************************************************************************/
|
|
10489 #ifndef PALM_2
|
|
10490 SOAP_FMAC1
|
|
10491 void
|
|
10492 SOAP_FMAC2
|
|
10493 soap_clr_attr(struct soap *soap)
|
|
10494 { register struct soap_attribute *tp;
|
|
10495 #ifndef WITH_LEAN
|
|
10496 if ((soap->mode & SOAP_XML_CANONICAL))
|
|
10497 { while (soap->attributes)
|
|
10498 { tp = soap->attributes->next;
|
|
10499 if (soap->attributes->value)
|
|
10500 SOAP_FREE(soap, soap->attributes->value);
|
|
10501 SOAP_FREE(soap, soap->attributes);
|
|
10502 soap->attributes = tp;
|
|
10503 }
|
|
10504 }
|
|
10505 else
|
|
10506 #endif
|
|
10507 { for (tp = soap->attributes; tp; tp = tp->next)
|
|
10508 tp->visible = 0;
|
|
10509 }
|
|
10510 }
|
|
10511 #endif
|
|
10512
|
|
10513 /******************************************************************************/
|
|
10514 #ifndef PALM_2
|
|
10515 static int
|
|
10516 soap_getattrval(struct soap *soap, char *s, size_t n, soap_wchar d)
|
|
10517 { register size_t i;
|
|
10518 for (i = 0; i < n; i++)
|
|
10519 { register soap_wchar c = soap_get(soap);
|
|
10520 switch (c)
|
|
10521 {
|
|
10522 case SOAP_TT:
|
|
10523 *s++ = '<';
|
|
10524 soap_unget(soap, '/');
|
|
10525 break;
|
|
10526 case SOAP_LT:
|
|
10527 *s++ = '<';
|
|
10528 break;
|
|
10529 case SOAP_GT:
|
|
10530 if (d == ' ')
|
|
10531 { soap_unget(soap, c);
|
|
10532 *s = '\0';
|
|
10533 return SOAP_OK;
|
|
10534 }
|
|
10535 *s++ = '>';
|
|
10536 break;
|
|
10537 case SOAP_QT:
|
|
10538 if (c == d)
|
|
10539 { *s = '\0';
|
|
10540 return SOAP_OK;
|
|
10541 }
|
|
10542 *s++ = '"';
|
|
10543 break;
|
|
10544 case SOAP_AP:
|
|
10545 if (c == d)
|
|
10546 { *s = '\0';
|
|
10547 return SOAP_OK;
|
|
10548 }
|
|
10549 *s++ = '\'';
|
|
10550 break;
|
|
10551 case '\t':
|
|
10552 case '\n':
|
|
10553 case '\r':
|
|
10554 case ' ':
|
|
10555 case '/':
|
|
10556 if (d == ' ')
|
|
10557 { soap_unget(soap, c);
|
|
10558 *s = '\0';
|
|
10559 return SOAP_OK;
|
|
10560 }
|
|
10561 default:
|
|
10562 if ((int)c == EOF)
|
|
10563 { *s = '\0';
|
|
10564 return soap->error = SOAP_CHK_EOF;
|
|
10565 }
|
|
10566 *s++ = (char)c;
|
|
10567 }
|
|
10568 }
|
|
10569 return soap->error = SOAP_EOM;
|
|
10570 }
|
|
10571 #endif
|
|
10572
|
|
10573 /******************************************************************************/
|
|
10574 #ifdef WITH_FAST
|
|
10575 #ifndef PALM_2
|
|
10576 SOAP_FMAC1
|
|
10577 int
|
|
10578 SOAP_FMAC2
|
|
10579 soap_store_lab(struct soap *soap, const char *s, size_t n)
|
|
10580 { soap->labidx = 0;
|
|
10581 return soap_append_lab(soap, s, n);
|
|
10582 }
|
|
10583 #endif
|
|
10584 #endif
|
|
10585
|
|
10586 /******************************************************************************/
|
|
10587 #ifdef WITH_FAST
|
|
10588 #ifndef PALM_2
|
|
10589 SOAP_FMAC1
|
|
10590 int
|
|
10591 SOAP_FMAC2
|
|
10592 soap_append_lab(struct soap *soap, const char *s, size_t n)
|
|
10593 { if (soap->labidx + n >= soap->lablen)
|
|
10594 { register char *t = soap->labbuf;
|
|
10595 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enlarging look-aside buffer to append data, size=%lu\n", (unsigned long)soap->lablen));
|
|
10596 if (soap->lablen == 0)
|
|
10597 soap->lablen = SOAP_LABLEN;
|
|
10598 while (soap->labidx + n >= soap->lablen)
|
|
10599 soap->lablen <<= 1;
|
|
10600 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New look-aside buffer size=%lu\n", (unsigned long)soap->lablen));
|
|
10601 soap->labbuf = (char*)SOAP_MALLOC(soap, soap->lablen);
|
|
10602 if (!soap->labbuf)
|
|
10603 { if (t)
|
|
10604 SOAP_FREE(soap, t);
|
|
10605 return soap->error = SOAP_EOM;
|
|
10606 }
|
|
10607 if (t)
|
|
10608 { memcpy(soap->labbuf, t, soap->labidx);
|
|
10609 SOAP_FREE(soap, t);
|
|
10610 }
|
|
10611 }
|
|
10612 if (s)
|
|
10613 { memcpy(soap->labbuf + soap->labidx, s, n);
|
|
10614 soap->labidx += n;
|
|
10615 }
|
|
10616 return SOAP_OK;
|
|
10617 }
|
|
10618 #endif
|
|
10619 #endif
|
|
10620
|
|
10621 /******************************************************************************/
|
|
10622 #ifndef PALM_2
|
|
10623 SOAP_FMAC1
|
|
10624 int
|
|
10625 SOAP_FMAC2
|
|
10626 soap_peek_element(struct soap *soap)
|
|
10627 {
|
|
10628 #ifdef WITH_DOM
|
|
10629 register struct soap_dom_attribute **att = NULL;
|
|
10630 register char *lead = NULL;
|
|
10631 #endif
|
|
10632 register struct soap_attribute *tp, *tq = NULL;
|
|
10633 register const char *t;
|
|
10634 register char *s;
|
|
10635 register soap_wchar c;
|
|
10636 register int i;
|
|
10637 if (soap->peeked)
|
|
10638 { if (!*soap->tag)
|
|
10639 return soap->error = SOAP_NO_TAG;
|
|
10640 return SOAP_OK;
|
|
10641 }
|
|
10642 soap->peeked = 1;
|
|
10643 soap->id[0] = '\0';
|
|
10644 soap->href[0] = '\0';
|
|
10645 soap->type[0] = '\0';
|
|
10646 soap->arrayType[0] = '\0';
|
|
10647 soap->arraySize[0] = '\0';
|
|
10648 soap->arrayOffset[0] = '\0';
|
|
10649 soap->other = 0;
|
|
10650 soap->root = -1;
|
|
10651 soap->position = 0;
|
|
10652 soap->null = 0;
|
|
10653 soap->mustUnderstand = 0;
|
|
10654 /* UTF-8 BOM? */
|
|
10655 c = soap_getchar(soap);
|
|
10656 if (c == 0xEF && soap_get0(soap) == 0xBB)
|
|
10657 { c = soap_get1(soap);
|
|
10658 if ((c = soap_get1(soap)) == 0xBF)
|
|
10659 soap->mode &= ~SOAP_ENC_LATIN;
|
|
10660 else
|
|
10661 soap_unget(soap, (0x0F << 12) | (0xBB << 6) | (c & 0x3F)); /* UTF-8 */
|
|
10662 }
|
|
10663 else if ((c == 0xFE && soap_get0(soap) == 0xFF) /* UTF-16 BE */
|
|
10664 || (c == 0xFF && soap_get0(soap) == 0xFE)) /* UTF-16 LE */
|
|
10665 return soap->error = SOAP_UTF_ERROR;
|
|
10666 else
|
|
10667 soap_unget(soap, c);
|
|
10668 c = soap_get(soap);
|
|
10669 #ifdef WITH_DOM
|
|
10670 /* whitespace leading to tag is not insignificant for DOM */
|
|
10671 if (soap_blank(c))
|
|
10672 { soap->labidx = 0;
|
|
10673 do
|
|
10674 { if (soap_append_lab(soap, NULL, 0))
|
|
10675 return soap->error;
|
|
10676 s = soap->labbuf + soap->labidx;
|
|
10677 i = soap->lablen - soap->labidx;
|
|
10678 soap->labidx = soap->lablen;
|
|
10679 while (soap_blank(c) && i--)
|
|
10680 { *s++ = c;
|
|
10681 c = soap_get(soap);
|
|
10682 }
|
|
10683 }
|
|
10684 while (soap_blank(c));
|
|
10685 *s = '\0';
|
|
10686 lead = soap->labbuf;
|
|
10687 }
|
|
10688 #else
|
|
10689 /* skip space */
|
|
10690 while (soap_blank(c))
|
|
10691 c = soap_get(soap);
|
|
10692 #endif
|
|
10693 if (c != SOAP_LT)
|
|
10694 { *soap->tag = '\0';
|
|
10695 if ((int)c == EOF)
|
|
10696 return soap->error = SOAP_CHK_EOF;
|
|
10697 soap_unget(soap, c);
|
|
10698 #ifdef WITH_DOM
|
|
10699 /* whitespace leading to end tag is significant for DOM */
|
|
10700 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
|
|
10701 { if (lead && *lead)
|
|
10702 soap->dom->tail = soap_strdup(soap, lead);
|
|
10703 else
|
|
10704 soap->dom->tail = (char*)SOAP_STR_EOS;
|
|
10705 }
|
|
10706 #endif
|
|
10707 return soap->error = SOAP_NO_TAG;
|
|
10708 }
|
|
10709 do c = soap_get1(soap);
|
|
10710 while (soap_blank(c));
|
|
10711 s = soap->tag;
|
|
10712 i = sizeof(soap->tag);
|
|
10713 while (c != '>' && c != '/' && soap_notblank(c) && (int)c != EOF)
|
|
10714 { if (--i > 0)
|
|
10715 *s++ = (char)c;
|
|
10716 c = soap_get1(soap);
|
|
10717 }
|
|
10718 *s = '\0';
|
|
10719 while (soap_blank(c))
|
|
10720 c = soap_get1(soap);
|
|
10721 #ifdef WITH_DOM
|
|
10722 if (soap->mode & SOAP_XML_DOM)
|
|
10723 { register struct soap_dom_element *elt;
|
|
10724 elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element));
|
|
10725 if (!elt)
|
|
10726 return soap->error;
|
|
10727 elt->next = NULL;
|
|
10728 elt->nstr = NULL;
|
|
10729 elt->name = soap_strdup(soap, soap->tag);
|
|
10730 elt->prnt = soap->dom;
|
|
10731 elt->elts = NULL;
|
|
10732 elt->atts = NULL;
|
|
10733 elt->data = NULL;
|
|
10734 elt->wide = NULL;
|
|
10735 elt->type = 0;
|
|
10736 elt->node = NULL;
|
|
10737 elt->head = soap_strdup(soap, lead);
|
|
10738 elt->tail = NULL;
|
|
10739 elt->soap = soap;
|
|
10740 if (soap->dom)
|
|
10741 { struct soap_dom_element *p = soap->dom->elts;
|
|
10742 if (p)
|
|
10743 { while (p->next)
|
|
10744 p = p->next;
|
|
10745 p->next = elt;
|
|
10746 }
|
|
10747 else
|
|
10748 soap->dom->elts = elt;
|
|
10749 }
|
|
10750 soap->dom = elt;
|
|
10751 att = &elt->atts;
|
|
10752 }
|
|
10753 #endif
|
|
10754 soap_pop_namespace(soap);
|
|
10755 for (tp = soap->attributes; tp; tp = tp->next)
|
|
10756 tp->visible = 0;
|
|
10757 while ((int)c != EOF && c != '>' && c != '/')
|
|
10758 { s = soap->tmpbuf;
|
|
10759 i = sizeof(soap->tmpbuf);
|
|
10760 while (c != '=' && c != '>' && c != '/' && soap_notblank(c) && (int)c != EOF)
|
|
10761 { if (--i > 0)
|
|
10762 *s++ = (char)c;
|
|
10763 c = soap_get1(soap);
|
|
10764 }
|
|
10765 *s = '\0';
|
|
10766 if (i == sizeof(soap->tmpbuf))
|
|
10767 return soap->error = SOAP_SYNTAX_ERROR;
|
|
10768 #ifdef WITH_DOM
|
|
10769 /* add attribute name to dom */
|
|
10770 if (att)
|
|
10771 { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
|
|
10772 if (!*att)
|
|
10773 return soap->error;
|
|
10774 (*att)->next = NULL;
|
|
10775 (*att)->nstr = NULL;
|
|
10776 (*att)->name = soap_strdup(soap, soap->tmpbuf);
|
|
10777 (*att)->data = NULL;
|
|
10778 (*att)->wide = NULL;
|
|
10779 (*att)->soap = soap;
|
|
10780 }
|
|
10781 #endif
|
|
10782 if (!strncmp(soap->tmpbuf, "xmlns", 5))
|
|
10783 { if (soap->tmpbuf[5] == ':')
|
|
10784 t = soap->tmpbuf + 6;
|
|
10785 else if (soap->tmpbuf[5])
|
|
10786 t = NULL;
|
|
10787 else
|
|
10788 t = SOAP_STR_EOS;
|
|
10789 }
|
|
10790 else
|
|
10791 t = NULL;
|
|
10792 tq = NULL;
|
|
10793 for (tp = soap->attributes; tp; tq = tp, tp = tp->next)
|
|
10794 { if (!SOAP_STRCMP(tp->name, soap->tmpbuf))
|
|
10795 break;
|
|
10796 }
|
|
10797 if (!tp)
|
|
10798 { tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(soap->tmpbuf));
|
|
10799 if (!tp)
|
|
10800 return soap->error = SOAP_EOM;
|
|
10801 strcpy((char*)tp->name, soap->tmpbuf);
|
|
10802 tp->value = NULL;
|
|
10803 tp->size = 0;
|
|
10804 tp->ns = NULL;
|
|
10805 /* if attribute name is qualified, append it to the end of the list */
|
|
10806 if (tq && strchr(soap->tmpbuf, ':'))
|
|
10807 { tq->next = tp;
|
|
10808 tp->next = NULL;
|
|
10809 }
|
|
10810 else
|
|
10811 { tp->next = soap->attributes;
|
|
10812 soap->attributes = tp;
|
|
10813 }
|
|
10814 }
|
|
10815 while (soap_blank(c))
|
|
10816 c = soap_get1(soap);
|
|
10817 if (c == '=')
|
|
10818 { do c = soap_getutf8(soap);
|
|
10819 while (soap_blank(c));
|
|
10820 if (c != SOAP_QT && c != SOAP_AP)
|
|
10821 { soap_unget(soap, c);
|
|
10822 c = ' '; /* blank delimiter */
|
|
10823 }
|
|
10824 if (soap_getattrval(soap, tp->value, tp->size, c))
|
|
10825 {
|
|
10826 #ifdef WITH_FAST
|
|
10827 if (soap->error != SOAP_EOM)
|
|
10828 return soap->error;
|
|
10829 soap->error = SOAP_OK;
|
|
10830 if (soap_store_lab(soap, tp->value, tp->size))
|
|
10831 return soap->error;
|
|
10832 if (tp->value)
|
|
10833 SOAP_FREE(soap, tp->value);
|
|
10834 tp->value = NULL;
|
|
10835 for (;;)
|
|
10836 { if (soap_getattrval(soap, soap->labbuf + soap->labidx, soap->lablen - soap->labidx, c))
|
|
10837 { if (soap->error != SOAP_EOM)
|
|
10838 return soap->error;
|
|
10839 soap->error = SOAP_OK;
|
|
10840 soap->labidx = soap->lablen;
|
|
10841 if (soap_append_lab(soap, NULL, 0))
|
|
10842 return soap->error;
|
|
10843 }
|
|
10844 else
|
|
10845 break;
|
|
10846 }
|
|
10847 if (soap->labidx)
|
|
10848 tp->size = soap->lablen;
|
|
10849 else
|
|
10850 { tp->size = strlen(soap->labbuf) + 1;
|
|
10851 if (tp->size < SOAP_LABLEN)
|
|
10852 tp->size = SOAP_LABLEN;
|
|
10853 }
|
|
10854 if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size)))
|
|
10855 return soap->error = SOAP_EOM;
|
|
10856 strcpy(tp->value, soap->labbuf);
|
|
10857 #else
|
|
10858 size_t n;
|
|
10859 if (soap->error != SOAP_EOM)
|
|
10860 return soap->error;
|
|
10861 soap->error = SOAP_OK;
|
|
10862 if (soap_new_block(soap) == NULL)
|
|
10863 return soap->error;
|
|
10864 for (;;)
|
|
10865 { if (!(s = (char*)soap_push_block(soap, NULL, SOAP_BLKLEN)))
|
|
10866 return soap->error;
|
|
10867 if (soap_getattrval(soap, s, SOAP_BLKLEN, c))
|
|
10868 { if (soap->error != SOAP_EOM)
|
|
10869 return soap->error;
|
|
10870 soap->error = SOAP_OK;
|
|
10871 }
|
|
10872 else
|
|
10873 break;
|
|
10874 }
|
|
10875 n = tp->size + soap->blist->size;
|
|
10876 if (!(s = (char*)SOAP_MALLOC(soap, n)))
|
|
10877 return soap->error = SOAP_EOM;
|
|
10878 if (tp->value)
|
|
10879 { memcpy(s, tp->value, tp->size);
|
|
10880 SOAP_FREE(soap, tp->value);
|
|
10881 }
|
|
10882 soap_save_block(soap, NULL, s + tp->size, 0);
|
|
10883 tp->value = s;
|
|
10884 tp->size = n;
|
|
10885 #endif
|
|
10886 }
|
|
10887 do c = soap_get1(soap);
|
|
10888 while (soap_blank(c));
|
|
10889 tp->visible = 2; /* seen this attribute w/ value */
|
|
10890 #ifdef WITH_DOM
|
|
10891 if (att)
|
|
10892 (*att)->data = soap_strdup(soap, tp->value);
|
|
10893 #endif
|
|
10894 }
|
|
10895 else
|
|
10896 tp->visible = 1; /* seen this attribute w/o value */
|
|
10897 #ifdef WITH_DOM
|
|
10898 if (att)
|
|
10899 att = &(*att)->next;
|
|
10900 #endif
|
|
10901 if (t && tp->value)
|
|
10902 { if (soap_push_namespace(soap, t, tp->value) == NULL)
|
|
10903 return soap->error;
|
|
10904 }
|
|
10905 }
|
|
10906 #ifdef WITH_DOM
|
|
10907 if (att)
|
|
10908 { soap->dom->nstr = soap_current_namespace(soap, soap->tag);
|
|
10909 for (att = &soap->dom->atts; *att; att = &(*att)->next)
|
|
10910 (*att)->nstr = soap_current_namespace(soap, (*att)->name);
|
|
10911 }
|
|
10912 #endif
|
|
10913 if ((int)c == EOF)
|
|
10914 return soap->error = SOAP_CHK_EOF;
|
|
10915 if (!(soap->body = (c != '/')))
|
|
10916 do c = soap_get1(soap);
|
|
10917 while (soap_blank(c));
|
|
10918 #ifdef WITH_DOM
|
|
10919 if (soap->mode & SOAP_XML_DOM)
|
|
10920 { if (!soap->body && soap->dom->prnt)
|
|
10921 soap->dom = soap->dom->prnt;
|
|
10922 }
|
|
10923 #endif
|
|
10924 for (tp = soap->attributes; tp; tp = tp->next)
|
|
10925 { if (tp->visible && tp->value)
|
|
10926 {
|
|
10927 #ifndef WITH_NOIDREF
|
|
10928 if (!strcmp(tp->name, "id"))
|
|
10929 { if ((soap->version > 0 && !(soap->imode & SOAP_XML_TREE))
|
|
10930 || (soap->mode & SOAP_XML_GRAPH))
|
|
10931 { *soap->id = '#';
|
|
10932 strncpy(soap->id + 1, tp->value, sizeof(soap->id) - 2);
|
|
10933 soap->id[sizeof(soap->id) - 1] = '\0';
|
|
10934 }
|
|
10935 }
|
|
10936 else if (!strcmp(tp->name, "href"))
|
|
10937 { if ((soap->version == 1 && !(soap->imode & SOAP_XML_TREE))
|
|
10938 || (soap->mode & SOAP_XML_GRAPH)
|
|
10939 || (soap->mode & SOAP_ENC_MTOM)
|
|
10940 || (soap->mode & SOAP_ENC_DIME))
|
|
10941 { strncpy(soap->href, tp->value, sizeof(soap->href) - 1);
|
|
10942 soap->href[sizeof(soap->href) - 1] = '\0';
|
|
10943 }
|
|
10944 }
|
|
10945 else if (!strcmp(tp->name, "ref"))
|
|
10946 { if ((soap->version == 2 && !(soap->imode & SOAP_XML_TREE))
|
|
10947 || (soap->mode & SOAP_XML_GRAPH))
|
|
10948 { *soap->href = '#';
|
|
10949 strncpy(soap->href + (*tp->value != '#'), tp->value, sizeof(soap->href) - 2);
|
|
10950 soap->href[sizeof(soap->href) - 1] = '\0';
|
|
10951 }
|
|
10952 }
|
|
10953 else
|
|
10954 #endif
|
|
10955 if (!soap_match_tag(soap, tp->name, "xsi:type"))
|
|
10956 { strncpy(soap->type, tp->value, sizeof(soap->type) - 1);
|
|
10957 soap->type[sizeof(soap->type) - 1] = '\0';
|
|
10958 }
|
|
10959 else if ((!soap_match_tag(soap, tp->name, "xsi:null")
|
|
10960 || !soap_match_tag(soap, tp->name, "xsi:nil"))
|
|
10961 && (!strcmp(tp->value, "1")
|
|
10962 || !strcmp(tp->value, "true")))
|
|
10963 { soap->null = 1;
|
|
10964 }
|
|
10965 else if (soap->version == 1)
|
|
10966 { if (!soap_match_tag(soap, tp->name, "SOAP-ENC:arrayType"))
|
|
10967 { s = soap_strrchr(tp->value, '[');
|
|
10968 if (s && (size_t)(s - tp->value) < sizeof(soap->arrayType))
|
|
10969 { strncpy(soap->arrayType, tp->value, s - tp->value);
|
|
10970 soap->arrayType[s - tp->value] = '\0';
|
|
10971 strncpy(soap->arraySize, s, sizeof(soap->arraySize));
|
|
10972 }
|
|
10973 else
|
|
10974 strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType));
|
|
10975 soap->arraySize[sizeof(soap->arraySize) - 1] = '\0';
|
|
10976 soap->arrayType[sizeof(soap->arrayType) - 1] = '\0';
|
|
10977 }
|
|
10978 else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:offset"))
|
|
10979 strncpy(soap->arrayOffset, tp->value, sizeof(soap->arrayOffset));
|
|
10980 else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:position"))
|
|
10981 soap->position = soap_getposition(tp->value, soap->positions);
|
|
10982 else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:root"))
|
|
10983 soap->root = ((!strcmp(tp->value, "1") || !strcmp(tp->value, "true")));
|
|
10984 else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand")
|
|
10985 && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true")))
|
|
10986 soap->mustUnderstand = 1;
|
|
10987 else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:actor"))
|
|
10988 { if ((!soap->actor || strcmp(soap->actor, tp->value))
|
|
10989 && strcmp(tp->value, "http://schemas.xmlsoap.org/soap/actor/next"))
|
|
10990 soap->other = 1;
|
|
10991 }
|
|
10992 }
|
|
10993 else if (soap->version == 2)
|
|
10994 {
|
|
10995 #ifndef WITH_NOIDREF
|
|
10996 if (!soap_match_tag(soap, tp->name, "SOAP-ENC:id"))
|
|
10997 { *soap->id = '#';
|
|
10998 strncpy(soap->id + 1, tp->value, sizeof(soap->id) - 2);
|
|
10999 soap->id[sizeof(soap->id) - 1] = '\0';
|
|
11000 }
|
|
11001 else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:ref"))
|
|
11002 { *soap->href = '#';
|
|
11003 strncpy(soap->href + (*tp->value != '#'), tp->value, sizeof(soap->href) - 2);
|
|
11004 soap->href[sizeof(soap->href) - 1] = '\0';
|
|
11005 }
|
|
11006 else
|
|
11007 #endif
|
|
11008 if (!soap_match_tag(soap, tp->name, "SOAP-ENC:itemType"))
|
|
11009 strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1);
|
|
11010 else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:arraySize"))
|
|
11011 strncpy(soap->arraySize, tp->value, sizeof(soap->arraySize) - 1);
|
|
11012 else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand")
|
|
11013 && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true")))
|
|
11014 soap->mustUnderstand = 1;
|
|
11015 else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:role"))
|
|
11016 { if ((!soap->actor || strcmp(soap->actor, tp->value))
|
|
11017 && strcmp(tp->value, "http://www.w3.org/2003/05/soap-envelope/role/next"))
|
|
11018 soap->other = 1;
|
|
11019 }
|
|
11020 }
|
|
11021 else
|
|
11022 { if (!soap_match_tag(soap, tp->name, "wsdl:required") && !strcmp(tp->value, "true"))
|
|
11023 soap->mustUnderstand = 1;
|
|
11024 }
|
|
11025 }
|
|
11026 }
|
|
11027 #ifdef WITH_DOM
|
|
11028 if (soap->feltbegin)
|
|
11029 return soap->error = soap->feltbegin(soap, soap->tag);
|
|
11030 #endif
|
|
11031 return soap->error = SOAP_OK;
|
|
11032 }
|
|
11033 #endif
|
|
11034
|
|
11035 /******************************************************************************/
|
|
11036 #ifndef PALM_2
|
|
11037 SOAP_FMAC1
|
|
11038 void
|
|
11039 SOAP_FMAC2
|
|
11040 soap_retry(struct soap *soap)
|
|
11041 { soap->error = SOAP_OK;
|
|
11042 soap_revert(soap);
|
|
11043 }
|
|
11044 #endif
|
|
11045
|
|
11046 /******************************************************************************/
|
|
11047 #ifndef PALM_2
|
|
11048 SOAP_FMAC1
|
|
11049 void
|
|
11050 SOAP_FMAC2
|
|
11051 soap_revert(struct soap *soap)
|
|
11052 { if (!soap->peeked)
|
|
11053 { soap->peeked = 1;
|
|
11054 if (soap->body)
|
|
11055 soap->level--;
|
|
11056 }
|
|
11057 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reverting to last element '%s' (level=%u)\n", soap->tag, soap->level));
|
|
11058 }
|
|
11059 #endif
|
|
11060
|
|
11061 /******************************************************************************/
|
|
11062 #ifndef PALM_2
|
|
11063 SOAP_FMAC1
|
|
11064 int
|
|
11065 SOAP_FMAC2
|
|
11066 soap_string_out(struct soap *soap, const char *s, int flag)
|
|
11067 { register const char *t;
|
|
11068 register soap_wchar c;
|
|
11069 register soap_wchar mask = (soap_wchar)0xFFFFFF80UL;
|
|
11070 #ifdef WITH_DOM
|
|
11071 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
|
|
11072 { soap->dom->data = soap_strdup(soap, s);
|
|
11073 return SOAP_OK;
|
|
11074 }
|
|
11075 #endif
|
|
11076 if (flag == 2 || soap->mode & SOAP_C_UTFSTRING)
|
|
11077 mask = 0;
|
|
11078 t = s;
|
|
11079 while ((c = *t++))
|
|
11080 { switch (c)
|
|
11081 {
|
|
11082 case 0x09:
|
|
11083 if (flag)
|
|
11084 { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "	", 5))
|
|
11085 return soap->error;
|
|
11086 s = t;
|
|
11087 }
|
|
11088 break;
|
|
11089 case 0x0A:
|
|
11090 if (flag || !(soap->mode & SOAP_XML_CANONICAL))
|
|
11091 { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "
", 5))
|
|
11092 return soap->error;
|
|
11093 s = t;
|
|
11094 }
|
|
11095 break;
|
|
11096 case 0x0D:
|
|
11097 if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "
", 5))
|
|
11098 return soap->error;
|
|
11099 s = t;
|
|
11100 break;
|
|
11101 case '&':
|
|
11102 if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&", 5))
|
|
11103 return soap->error;
|
|
11104 s = t;
|
|
11105 break;
|
|
11106 case '<':
|
|
11107 if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "<", 4))
|
|
11108 return soap->error;
|
|
11109 s = t;
|
|
11110 break;
|
|
11111 case '>':
|
|
11112 if (!flag)
|
|
11113 { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, ">", 4))
|
|
11114 return soap->error;
|
|
11115 s = t;
|
|
11116 }
|
|
11117 break;
|
|
11118 case '"':
|
|
11119 if (flag)
|
|
11120 { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, """, 6))
|
|
11121 return soap->error;
|
|
11122 s = t;
|
|
11123 }
|
|
11124 break;
|
|
11125 default:
|
|
11126 #ifndef WITH_LEANER
|
|
11127 #ifdef HAVE_MBTOWC
|
|
11128 if (soap->mode & SOAP_C_MBSTRING)
|
|
11129 { wchar_t wc;
|
|
11130 register int m = mbtowc(&wc, t - 1, MB_CUR_MAX);
|
|
11131 if (m > 0 && !((soap_wchar)wc == c && m == 1 && c < 0x80))
|
|
11132 { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned long)wc))
|
|
11133 return soap->error;
|
|
11134 s = t += m - 1;
|
|
11135 continue;
|
|
11136 }
|
|
11137 }
|
|
11138 #endif
|
|
11139 #endif
|
|
11140 #ifndef WITH_NOSTRINGTOUTF8
|
|
11141 if ((c & mask) || !(c & 0xFFFFFFE0UL))
|
|
11142 { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned char)c))
|
|
11143 return soap->error;
|
|
11144 s = t;
|
|
11145 }
|
|
11146 #endif
|
|
11147 }
|
|
11148 }
|
|
11149 return soap_send_raw(soap, s, t - s - 1);
|
|
11150 }
|
|
11151 #endif
|
|
11152
|
|
11153 /******************************************************************************/
|
|
11154 #ifndef PALM_2
|
|
11155 SOAP_FMAC1
|
|
11156 char *
|
|
11157 SOAP_FMAC2
|
|
11158 soap_string_in(struct soap *soap, int flag, long minlen, long maxlen)
|
|
11159 { register char *s;
|
|
11160 char *t = NULL;
|
|
11161 register size_t i;
|
|
11162 register long l = 0;
|
|
11163 register int n = 0, f = 0, m = 0;
|
|
11164 register soap_wchar c;
|
|
11165 #if !defined(WITH_LEANER) && defined(HAVE_WCTOMB)
|
|
11166 char buf[MB_LEN_MAX > 8 ? MB_LEN_MAX : 8];
|
|
11167 #else
|
|
11168 char buf[8];
|
|
11169 #endif
|
|
11170 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading string content, flag=%d\n", flag));
|
|
11171 if (soap->peeked && *soap->tag)
|
|
11172 {
|
|
11173 #ifndef WITH_LEAN
|
|
11174 struct soap_attribute *tp;
|
|
11175 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String content includes tag '%s' and attributes\n", soap->tag));
|
|
11176 t = soap->tmpbuf;
|
|
11177 *t = '<';
|
|
11178 strncpy(t + 1, soap->tag, sizeof(soap->tmpbuf) - 2);
|
|
11179 t[sizeof(soap->tmpbuf) - 1] = '\0';
|
|
11180 t += strlen(t);
|
|
11181 for (tp = soap->attributes; tp; tp = tp->next)
|
|
11182 { if (tp->visible)
|
|
11183 { if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2)
|
|
11184 break;
|
|
11185 *t++ = ' ';
|
|
11186 strcpy(t, tp->name);
|
|
11187 t += strlen(t);
|
|
11188 if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2)
|
|
11189 break; /* too many or large attribute values */
|
|
11190 if (tp->value)
|
|
11191 { *t++ = '=';
|
|
11192 *t++ = '"';
|
|
11193 strcpy(t, tp->value);
|
|
11194 t += strlen(t);
|
|
11195 *t++ = '"';
|
|
11196 }
|
|
11197 }
|
|
11198 }
|
|
11199 if (!soap->body)
|
|
11200 *t++ = '/';
|
|
11201 *t++ = '>';
|
|
11202 *t = '\0';
|
|
11203 t = soap->tmpbuf;
|
|
11204 m = (int)strlen(soap->tmpbuf);
|
|
11205 #endif
|
|
11206 if (soap->body)
|
|
11207 n = 1;
|
|
11208 f = 1;
|
|
11209 soap->peeked = 0;
|
|
11210 }
|
|
11211 #ifdef WITH_CDATA
|
|
11212 if (!flag)
|
|
11213 { register int state = 0;
|
|
11214 #ifdef WITH_FAST
|
|
11215 soap->labidx = 0; /* use look-aside buffer */
|
|
11216 #else
|
|
11217 if (soap_new_block(soap) == NULL)
|
|
11218 return NULL;
|
|
11219 #endif
|
|
11220 for (;;)
|
|
11221 {
|
|
11222 #ifdef WITH_FAST
|
|
11223 register size_t k;
|
|
11224 if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */
|
|
11225 return NULL;
|
|
11226 s = soap->labbuf + soap->labidx; /* space to populate */
|
|
11227 k = soap->lablen - soap->labidx; /* number of bytes available */
|
|
11228 soap->labidx = soap->lablen; /* claim this space */
|
|
11229 #else
|
|
11230 register size_t k = SOAP_BLKLEN;
|
|
11231 if (!(s = (char*)soap_push_block(soap, NULL, k)))
|
|
11232 return NULL;
|
|
11233 #endif
|
|
11234 for (i = 0; i < k; i++)
|
|
11235 { if (m > 0)
|
|
11236 { *s++ = *t++; /* copy multibyte characters */
|
|
11237 m--;
|
|
11238 continue;
|
|
11239 }
|
|
11240 c = soap_getchar(soap);
|
|
11241 if ((int)c == EOF)
|
|
11242 goto end;
|
|
11243 if ((c >= 0x80 || c < SOAP_AP) && state != 1 && !(soap->mode & SOAP_ENC_LATIN))
|
|
11244 { if ((c & 0x7FFFFFFF) >= 0x80)
|
|
11245 { soap_unget(soap, c);
|
|
11246 c = soap_getutf8(soap);
|
|
11247 }
|
|
11248 if ((c & 0x7FFFFFFF) >= 0x80 && (!flag || (soap->mode & SOAP_C_UTFSTRING)))
|
|
11249 { c &= 0x7FFFFFFF;
|
|
11250 t = buf;
|
|
11251 if (c < 0x0800)
|
|
11252 *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
|
|
11253 else
|
|
11254 { if (c < 0x010000)
|
|
11255 *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
|
|
11256 else
|
|
11257 { if (c < 0x200000)
|
|
11258 *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
|
|
11259 else
|
|
11260 { if (c < 0x04000000)
|
|
11261 *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
|
|
11262 else
|
|
11263 { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
|
|
11264 *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
|
|
11265 }
|
|
11266 *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
|
|
11267 }
|
|
11268 *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
|
|
11269 }
|
|
11270 *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
|
|
11271 }
|
|
11272 *t++ = (char)(0x80 | (c & 0x3F));
|
|
11273 m = (int)(t - buf) - 1;
|
|
11274 t = buf;
|
|
11275 *s++ = *t++;
|
|
11276 continue;
|
|
11277 }
|
|
11278 }
|
|
11279 switch (state)
|
|
11280 { case 1:
|
|
11281 if (c == ']')
|
|
11282 state = 4;
|
|
11283 *s++ = (char)c;
|
|
11284 continue;
|
|
11285 case 2:
|
|
11286 if (c == '-')
|
|
11287 state = 6;
|
|
11288 *s++ = (char)c;
|
|
11289 continue;
|
|
11290 case 3:
|
|
11291 if (c == '?')
|
|
11292 state = 8;
|
|
11293 *s++ = (char)c;
|
|
11294 continue;
|
|
11295 /* CDATA */
|
|
11296 case 4:
|
|
11297 if (c == ']')
|
|
11298 state = 5;
|
|
11299 else
|
|
11300 state = 1;
|
|
11301 *s++ = (char)c;
|
|
11302 continue;
|
|
11303 case 5:
|
|
11304 if (c == '>')
|
|
11305 state = 0;
|
|
11306 else if (c != ']')
|
|
11307 state = 1;
|
|
11308 *s++ = (char)c;
|
|
11309 continue;
|
|
11310 /* comment */
|
|
11311 case 6:
|
|
11312 if (c == '-')
|
|
11313 state = 7;
|
|
11314 else
|
|
11315 state = 2;
|
|
11316 *s++ = (char)c;
|
|
11317 continue;
|
|
11318 case 7:
|
|
11319 if (c == '>')
|
|
11320 state = 0;
|
|
11321 else if (c != '-')
|
|
11322 state = 2;
|
|
11323 *s++ = (char)c;
|
|
11324 continue;
|
|
11325 /* PI */
|
|
11326 case 8:
|
|
11327 if (c == '>')
|
|
11328 state = 0;
|
|
11329 else if (c != '?')
|
|
11330 state = 3;
|
|
11331 *s++ = (char)c;
|
|
11332 continue;
|
|
11333 }
|
|
11334 switch (c)
|
|
11335 {
|
|
11336 case SOAP_TT:
|
|
11337 if (n == 0)
|
|
11338 goto end;
|
|
11339 n--;
|
|
11340 *s++ = '<';
|
|
11341 t = (char*)"/";
|
|
11342 m = 1;
|
|
11343 break;
|
|
11344 case SOAP_LT:
|
|
11345 if (f && n == 0)
|
|
11346 goto end;
|
|
11347 n++;
|
|
11348 *s++ = '<';
|
|
11349 break;
|
|
11350 case SOAP_GT:
|
|
11351 *s++ = '>';
|
|
11352 break;
|
|
11353 case SOAP_QT:
|
|
11354 *s++ = '"';
|
|
11355 break;
|
|
11356 case SOAP_AP:
|
|
11357 *s++ = '\'';
|
|
11358 break;
|
|
11359 case '/':
|
|
11360 if (n > 0)
|
|
11361 { c = soap_getchar(soap);
|
|
11362 if (c == '>')
|
|
11363 n--;
|
|
11364 soap_unget(soap, c);
|
|
11365 }
|
|
11366 *s++ = '/';
|
|
11367 break;
|
|
11368 case '<':
|
|
11369 c = soap_getchar(soap);
|
|
11370 if (c == '/')
|
|
11371 { if (n == 0)
|
|
11372 { c = SOAP_TT;
|
|
11373 goto end;
|
|
11374 }
|
|
11375 n--;
|
|
11376 }
|
|
11377 else if (c == '!')
|
|
11378 { c = soap_getchar(soap);
|
|
11379 if (c == '[')
|
|
11380 { do c = soap_getchar(soap);
|
|
11381 while ((int)c != EOF && c != '[');
|
|
11382 if ((int)c == EOF)
|
|
11383 goto end;
|
|
11384 t = (char*)"![CDATA[";
|
|
11385 m = 8;
|
|
11386 state = 1;
|
|
11387 }
|
|
11388 else if (c == '-')
|
|
11389 { if ((c = soap_getchar(soap)) == '-')
|
|
11390 state = 2;
|
|
11391 t = (char*)"!-";
|
|
11392 m = 2;
|
|
11393 soap_unget(soap, c);
|
|
11394 }
|
|
11395 else
|
|
11396 { t = (char*)"!";
|
|
11397 m = 1;
|
|
11398 soap_unget(soap, c);
|
|
11399 }
|
|
11400 *s++ = '<';
|
|
11401 break;
|
|
11402 }
|
|
11403 else if (c == '?')
|
|
11404 state = 3;
|
|
11405 else if (f && n == 0)
|
|
11406 { soap_revget1(soap);
|
|
11407 c = '<';
|
|
11408 goto end;
|
|
11409 }
|
|
11410 else
|
|
11411 n++;
|
|
11412 soap_unget(soap, c);
|
|
11413 *s++ = '<';
|
|
11414 break;
|
|
11415 case '>':
|
|
11416 *s++ = '>';
|
|
11417 break;
|
|
11418 case '"':
|
|
11419 *s++ = '"';
|
|
11420 break;
|
|
11421 default:
|
|
11422 #ifndef WITH_LEANER
|
|
11423 #ifdef HAVE_WCTOMB
|
|
11424 if (soap->mode & SOAP_C_MBSTRING)
|
|
11425 { m = wctomb(buf, (wchar_t)(c & 0x7FFFFFFF));
|
|
11426 if (m >= 1 && m <= (int)MB_CUR_MAX)
|
|
11427 { t = buf;
|
|
11428 *s++ = *t++;
|
|
11429 m--;
|
|
11430 }
|
|
11431 else
|
|
11432 { *s++ = SOAP_UNKNOWN_CHAR;
|
|
11433 m = 0;
|
|
11434 }
|
|
11435 }
|
|
11436 else
|
|
11437 #endif
|
|
11438 #endif
|
|
11439 *s++ = (char)(c & 0xFF);
|
|
11440 }
|
|
11441 l++;
|
|
11442 if (maxlen >= 0 && l > maxlen)
|
|
11443 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
|
|
11444 soap->error = SOAP_LENGTH;
|
|
11445 return NULL;
|
|
11446 }
|
|
11447 }
|
|
11448 }
|
|
11449 }
|
|
11450 #endif
|
|
11451 #ifdef WITH_FAST
|
|
11452 soap->labidx = 0; /* use look-aside buffer */
|
|
11453 #else
|
|
11454 if (soap_new_block(soap) == NULL)
|
|
11455 return NULL;
|
|
11456 #endif
|
|
11457 for (;;)
|
|
11458 {
|
|
11459 #ifdef WITH_FAST
|
|
11460 register size_t k;
|
|
11461 if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */
|
|
11462 return NULL;
|
|
11463 s = soap->labbuf + soap->labidx; /* space to populate */
|
|
11464 k = soap->lablen - soap->labidx; /* number of bytes available */
|
|
11465 soap->labidx = soap->lablen; /* claim this space */
|
|
11466 #else
|
|
11467 register size_t k = SOAP_BLKLEN;
|
|
11468 if (!(s = (char*)soap_push_block(soap, NULL, k)))
|
|
11469 return NULL;
|
|
11470 #endif
|
|
11471 for (i = 0; i < k; i++)
|
|
11472 { if (m > 0)
|
|
11473 { *s++ = *t++; /* copy multibyte characters */
|
|
11474 m--;
|
|
11475 continue;
|
|
11476 }
|
|
11477 #ifndef WITH_CDATA
|
|
11478 if (!flag)
|
|
11479 c = soap_getchar(soap);
|
|
11480 else
|
|
11481 #endif
|
|
11482 if ((soap->mode & SOAP_C_UTFSTRING))
|
|
11483 { if (((c = soap_get(soap)) & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP)
|
|
11484 { c &= 0x7FFFFFFF;
|
|
11485 t = buf;
|
|
11486 if (c < 0x0800)
|
|
11487 *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
|
|
11488 else
|
|
11489 { if (c < 0x010000)
|
|
11490 *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
|
|
11491 else
|
|
11492 { if (c < 0x200000)
|
|
11493 *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
|
|
11494 else
|
|
11495 { if (c < 0x04000000)
|
|
11496 *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
|
|
11497 else
|
|
11498 { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
|
|
11499 *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
|
|
11500 }
|
|
11501 *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
|
|
11502 }
|
|
11503 *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
|
|
11504 }
|
|
11505 *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
|
|
11506 }
|
|
11507 *t++ = (char)(0x80 | (c & 0x3F));
|
|
11508 m = (int)(t - buf) - 1;
|
|
11509 t = buf;
|
|
11510 *s++ = *t++;
|
|
11511 continue;
|
|
11512 }
|
|
11513 }
|
|
11514 else
|
|
11515 c = soap_getutf8(soap);
|
|
11516 switch (c)
|
|
11517 {
|
|
11518 case SOAP_TT:
|
|
11519 if (n == 0)
|
|
11520 goto end;
|
|
11521 n--;
|
|
11522 *s++ = '<';
|
|
11523 t = (char*)"/";
|
|
11524 m = 1;
|
|
11525 break;
|
|
11526 case SOAP_LT:
|
|
11527 if (f && n == 0)
|
|
11528 goto end;
|
|
11529 n++;
|
|
11530 *s++ = '<';
|
|
11531 break;
|
|
11532 case SOAP_GT:
|
|
11533 *s++ = '>';
|
|
11534 break;
|
|
11535 case SOAP_QT:
|
|
11536 *s++ = '"';
|
|
11537 break;
|
|
11538 case SOAP_AP:
|
|
11539 *s++ = '\'';
|
|
11540 break;
|
|
11541 case '/':
|
|
11542 if (n > 0)
|
|
11543 { if (!flag)
|
|
11544 { c = soap_getchar(soap);
|
|
11545 if (c == '>')
|
|
11546 n--;
|
|
11547 }
|
|
11548 else
|
|
11549 { c = soap_get(soap);
|
|
11550 if (c == SOAP_GT)
|
|
11551 n--;
|
|
11552 }
|
|
11553 soap_unget(soap, c);
|
|
11554 }
|
|
11555 *s++ = '/';
|
|
11556 break;
|
|
11557 case (soap_wchar)('<' | 0x80000000):
|
|
11558 if (flag)
|
|
11559 *s++ = '<';
|
|
11560 else
|
|
11561 { *s++ = '&';
|
|
11562 t = (char*)"lt;";
|
|
11563 m = 3;
|
|
11564 }
|
|
11565 break;
|
|
11566 case (soap_wchar)('>' | 0x80000000):
|
|
11567 if (flag)
|
|
11568 *s++ = '>';
|
|
11569 else
|
|
11570 { *s++ = '&';
|
|
11571 t = (char*)"gt;";
|
|
11572 m = 3;
|
|
11573 }
|
|
11574 break;
|
|
11575 case (soap_wchar)('&' | 0x80000000):
|
|
11576 if (flag)
|
|
11577 *s++ = '&';
|
|
11578 else
|
|
11579 { *s++ = '&';
|
|
11580 t = (char*)"amp;";
|
|
11581 m = 4;
|
|
11582 }
|
|
11583 break;
|
|
11584 case (soap_wchar)('"' | 0x80000000):
|
|
11585 if (flag)
|
|
11586 *s++ = '"';
|
|
11587 else
|
|
11588 { *s++ = '&';
|
|
11589 t = (char*)"quot;";
|
|
11590 m = 5;
|
|
11591 }
|
|
11592 break;
|
|
11593 case (soap_wchar)('\'' | 0x80000000):
|
|
11594 if (flag)
|
|
11595 *s++ = '\'';
|
|
11596 else
|
|
11597 { *s++ = '&';
|
|
11598 t = (char*)"apos;";
|
|
11599 m = 5;
|
|
11600 }
|
|
11601 break;
|
|
11602 default:
|
|
11603 if ((int)c == EOF)
|
|
11604 goto end;
|
|
11605 #ifndef WITH_CDATA
|
|
11606 if (c == '<' && !flag)
|
|
11607 { if (f && n == 0)
|
|
11608 goto end;
|
|
11609 c = soap_getchar(soap);
|
|
11610 soap_unget(soap, c);
|
|
11611 if (c == '/')
|
|
11612 { c = SOAP_TT;
|
|
11613 if (n == 0)
|
|
11614 goto end;
|
|
11615 n--;
|
|
11616 }
|
|
11617 else
|
|
11618 n++;
|
|
11619 *s++ = '<';
|
|
11620 break;
|
|
11621 }
|
|
11622 else
|
|
11623 #endif
|
|
11624 #ifndef WITH_LEANER
|
|
11625 #ifdef HAVE_WCTOMB
|
|
11626 if (soap->mode & SOAP_C_MBSTRING)
|
|
11627 { m = wctomb(buf, (wchar_t)(c & 0x7FFFFFFF));
|
|
11628 if (m >= 1 && m <= (int)MB_CUR_MAX)
|
|
11629 { t = buf;
|
|
11630 *s++ = *t++;
|
|
11631 m--;
|
|
11632 }
|
|
11633 else
|
|
11634 { *s++ = SOAP_UNKNOWN_CHAR;
|
|
11635 m = 0;
|
|
11636 }
|
|
11637 }
|
|
11638 else
|
|
11639 #endif
|
|
11640 #endif
|
|
11641 *s++ = (char)(c & 0xFF);
|
|
11642 }
|
|
11643 l++;
|
|
11644 if (maxlen >= 0 && l > maxlen)
|
|
11645 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
|
|
11646 soap->error = SOAP_LENGTH;
|
|
11647 return NULL;
|
|
11648 }
|
|
11649 }
|
|
11650 }
|
|
11651 end:
|
|
11652 soap_unget(soap, c);
|
|
11653 *s = '\0';
|
|
11654 #ifdef WITH_FAST
|
|
11655 t = soap_strdup(soap, soap->labbuf);
|
|
11656 #else
|
|
11657 soap_size_block(soap, NULL, i + 1);
|
|
11658 t = soap_save_block(soap, NULL, 0);
|
|
11659 #endif
|
|
11660 if (l < minlen)
|
|
11661 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen));
|
|
11662 soap->error = SOAP_LENGTH;
|
|
11663 return NULL;
|
|
11664 }
|
|
11665 #ifdef WITH_DOM
|
|
11666 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
|
|
11667 { if (flag == 3)
|
|
11668 soap->dom->tail = t;
|
|
11669 else
|
|
11670 soap->dom->data = t;
|
|
11671 }
|
|
11672 #endif
|
|
11673 if (flag == 2)
|
|
11674 if (soap_s2QName(soap, t, &t, minlen, maxlen))
|
|
11675 return NULL;
|
|
11676 return t;
|
|
11677 }
|
|
11678 #endif
|
|
11679
|
|
11680 /******************************************************************************/
|
|
11681 #ifndef WITH_LEANER
|
|
11682 #ifndef PALM_2
|
|
11683 SOAP_FMAC1
|
|
11684 int
|
|
11685 SOAP_FMAC2
|
|
11686 soap_wstring_out(struct soap *soap, const wchar_t *s, int flag)
|
|
11687 { const char *t;
|
|
11688 char tmp;
|
|
11689 register soap_wchar c;
|
|
11690 #ifdef WITH_DOM
|
|
11691 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
|
|
11692 { wchar_t *r = (wchar_t*)s;
|
|
11693 int n = 1;
|
|
11694 while (*r++)
|
|
11695 n++;
|
|
11696 soap->dom->wide = r = (wchar_t*)soap_malloc(soap, n * sizeof(wchar_t));
|
|
11697 while (n--)
|
|
11698 *r++ = *s++;
|
|
11699 return SOAP_OK;
|
|
11700 }
|
|
11701 #endif
|
|
11702 while ((c = *s++))
|
|
11703 { switch (c)
|
|
11704 {
|
|
11705 case 0x09:
|
|
11706 if (flag)
|
|
11707 t = "	";
|
|
11708 else
|
|
11709 t = "\t";
|
|
11710 break;
|
|
11711 case 0x0A:
|
|
11712 if (flag || !(soap->mode & SOAP_XML_CANONICAL))
|
|
11713 t = "
";
|
|
11714 else
|
|
11715 t = "\n";
|
|
11716 break;
|
|
11717 case 0x0D:
|
|
11718 t = "
";
|
|
11719 break;
|
|
11720 case '&':
|
|
11721 t = "&";
|
|
11722 break;
|
|
11723 case '<':
|
|
11724 t = "<";
|
|
11725 break;
|
|
11726 case '>':
|
|
11727 if (flag)
|
|
11728 t = ">";
|
|
11729 else
|
|
11730 t = ">";
|
|
11731 break;
|
|
11732 case '"':
|
|
11733 if (flag)
|
|
11734 t = """;
|
|
11735 else
|
|
11736 t = "\"";
|
|
11737 break;
|
|
11738 default:
|
|
11739 if (c >= 0x20 && c < 0x80)
|
|
11740 { tmp = (char)c;
|
|
11741 if (soap_send_raw(soap, &tmp, 1))
|
|
11742 return soap->error;
|
|
11743 }
|
|
11744 else
|
|
11745 { /* check for UTF16 encoding when wchar_t is too small to hold UCS */
|
|
11746 if (sizeof(wchar_t) < 4 && (c & 0xFC00) == 0xD800)
|
|
11747 { register soap_wchar d = *s++;
|
|
11748 if ((d & 0xFC00) == 0xDC00)
|
|
11749 c = ((c - 0xD800) << 10) + (d - 0xDC00) + 0x10000;
|
|
11750 else
|
|
11751 c = 0xFFFD; /* Malformed */
|
|
11752 }
|
|
11753 if (soap_pututf8(soap, (unsigned long)c))
|
|
11754 return soap->error;
|
|
11755 }
|
|
11756 continue;
|
|
11757 }
|
|
11758 if (soap_send(soap, t))
|
|
11759 return soap->error;
|
|
11760 }
|
|
11761 return SOAP_OK;
|
|
11762 }
|
|
11763 #endif
|
|
11764 #endif
|
|
11765
|
|
11766 /******************************************************************************/
|
|
11767 #ifndef WITH_LEANER
|
|
11768 #ifndef PALM_2
|
|
11769 SOAP_FMAC1
|
|
11770 wchar_t *
|
|
11771 SOAP_FMAC2
|
|
11772 soap_wstring_in(struct soap *soap, int flag, long minlen, long maxlen)
|
|
11773 { wchar_t *s;
|
|
11774 register int i, n = 0, f = 0;
|
|
11775 register long l = 0;
|
|
11776 register soap_wchar c;
|
|
11777 char *t = NULL;
|
|
11778 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading wide string content\n"));
|
|
11779 if (soap->peeked)
|
|
11780 { if (*soap->tag)
|
|
11781 {
|
|
11782 #ifndef WITH_LEAN
|
|
11783 struct soap_attribute *tp;
|
|
11784 t = soap->tmpbuf;
|
|
11785 *t = '<';
|
|
11786 strncpy(t + 1, soap->tag, sizeof(soap->tmpbuf) - 2);
|
|
11787 t[sizeof(soap->tmpbuf) - 1] = '\0';
|
|
11788 t += strlen(t);
|
|
11789 for (tp = soap->attributes; tp; tp = tp->next)
|
|
11790 { if (tp->visible)
|
|
11791 { if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2)
|
|
11792 break;
|
|
11793 *t++ = ' ';
|
|
11794 strcpy(t, tp->name);
|
|
11795 t += strlen(t);
|
|
11796 if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2)
|
|
11797 break;
|
|
11798 if (tp->value)
|
|
11799 { *t++ = '=';
|
|
11800 *t++ = '"';
|
|
11801 strcpy(t, tp->value);
|
|
11802 t += strlen(t);
|
|
11803 *t++ = '"';
|
|
11804 }
|
|
11805 }
|
|
11806 }
|
|
11807 if (!soap->body)
|
|
11808 *t++ = '/';
|
|
11809 *t++ = '>';
|
|
11810 *t = '\0';
|
|
11811 t = soap->tmpbuf;
|
|
11812 #endif
|
|
11813 if (soap->body)
|
|
11814 n = 1;
|
|
11815 f = 1;
|
|
11816 soap->peeked = 0;
|
|
11817 }
|
|
11818 }
|
|
11819 if (soap_new_block(soap) == NULL)
|
|
11820 return NULL;
|
|
11821 for (;;)
|
|
11822 { if (!(s = (wchar_t*)soap_push_block(soap, NULL, sizeof(wchar_t)*SOAP_BLKLEN)))
|
|
11823 return NULL;
|
|
11824 for (i = 0; i < SOAP_BLKLEN; i++)
|
|
11825 { if (t)
|
|
11826 { *s++ = (wchar_t)*t++;
|
|
11827 if (!*t)
|
|
11828 t = NULL;
|
|
11829 continue;
|
|
11830 }
|
|
11831 c = soap_getutf8(soap);
|
|
11832 switch (c)
|
|
11833 {
|
|
11834 case SOAP_TT:
|
|
11835 if (n == 0)
|
|
11836 goto end;
|
|
11837 n--;
|
|
11838 *s++ = '<';
|
|
11839 soap_unget(soap, '/');
|
|
11840 break;
|
|
11841 case SOAP_LT:
|
|
11842 if (f && n == 0)
|
|
11843 goto end;
|
|
11844 n++;
|
|
11845 *s++ = '<';
|
|
11846 break;
|
|
11847 case SOAP_GT:
|
|
11848 *s++ = '>';
|
|
11849 break;
|
|
11850 case SOAP_QT:
|
|
11851 *s++ = '"';
|
|
11852 break;
|
|
11853 case SOAP_AP:
|
|
11854 *s++ = '\'';
|
|
11855 break;
|
|
11856 case '/':
|
|
11857 if (n > 0)
|
|
11858 { c = soap_getutf8(soap);
|
|
11859 if (c == SOAP_GT)
|
|
11860 n--;
|
|
11861 soap_unget(soap, c);
|
|
11862 }
|
|
11863 *s++ = '/';
|
|
11864 break;
|
|
11865 case '<':
|
|
11866 if (flag)
|
|
11867 *s++ = (soap_wchar)'<';
|
|
11868 else
|
|
11869 { *s++ = (soap_wchar)'&';
|
|
11870 t = (char*)"lt;";
|
|
11871 }
|
|
11872 break;
|
|
11873 case '>':
|
|
11874 if (flag)
|
|
11875 *s++ = (soap_wchar)'>';
|
|
11876 else
|
|
11877 { *s++ = (soap_wchar)'&';
|
|
11878 t = (char*)"gt;";
|
|
11879 }
|
|
11880 break;
|
|
11881 case '"':
|
|
11882 if (flag)
|
|
11883 *s++ = (soap_wchar)'"';
|
|
11884 else
|
|
11885 { *s++ = (soap_wchar)'&';
|
|
11886 t = (char*)"quot;";
|
|
11887 }
|
|
11888 break;
|
|
11889 default:
|
|
11890 if ((int)c == EOF)
|
|
11891 goto end;
|
|
11892 /* use UTF16 encoding when wchar_t is too small to hold UCS */
|
|
11893 if (sizeof(wchar_t) < 4 && c > 0xFFFF)
|
|
11894 { register soap_wchar c1, c2;
|
|
11895 c1 = 0xD800 - (0x10000 >> 10) + (c >> 10);
|
|
11896 c2 = 0xDC00 + (c & 0x3FF);
|
|
11897 c = c1;
|
|
11898 soap_unget(soap, c2);
|
|
11899 }
|
|
11900 *s++ = (wchar_t)c & 0x7FFFFFFF;
|
|
11901 }
|
|
11902 l++;
|
|
11903 if (maxlen >= 0 && l > maxlen)
|
|
11904 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
|
|
11905 soap->error = SOAP_LENGTH;
|
|
11906 return NULL;
|
|
11907 }
|
|
11908 }
|
|
11909 }
|
|
11910 end:
|
|
11911 soap_unget(soap, c);
|
|
11912 *s = '\0';
|
|
11913 soap_size_block(soap, NULL, sizeof(wchar_t) * (i + 1));
|
|
11914 if (l < minlen)
|
|
11915 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen));
|
|
11916 soap->error = SOAP_LENGTH;
|
|
11917 return NULL;
|
|
11918 }
|
|
11919 s = (wchar_t*)soap_save_block(soap, NULL, NULL, 0);
|
|
11920 #ifdef WITH_DOM
|
|
11921 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
|
|
11922 soap->dom->wide = s;
|
|
11923 #endif
|
|
11924 return s;
|
|
11925 }
|
|
11926 #endif
|
|
11927 #endif
|
|
11928
|
|
11929 /******************************************************************************/
|
|
11930 #ifndef PALM_2
|
|
11931 SOAP_FMAC1
|
|
11932 const char*
|
|
11933 SOAP_FMAC2
|
|
11934 soap_int2s(struct soap *soap, int n)
|
|
11935 { return soap_long2s(soap, (long)n);
|
|
11936 }
|
|
11937 #endif
|
|
11938
|
|
11939 /******************************************************************************/
|
|
11940 #ifndef PALM_2
|
|
11941 SOAP_FMAC1
|
|
11942 int
|
|
11943 SOAP_FMAC2
|
|
11944 soap_outint(struct soap *soap, const char *tag, int id, const int *p, const char *type, int n)
|
|
11945 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
|
|
11946 || soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
|
|
11947 return soap->error;
|
|
11948 return soap_element_end_out(soap, tag);
|
|
11949 }
|
|
11950 #endif
|
|
11951
|
|
11952 /******************************************************************************/
|
|
11953 #ifndef PALM_2
|
|
11954 SOAP_FMAC1
|
|
11955 int
|
|
11956 SOAP_FMAC2
|
|
11957 soap_s2int(struct soap *soap, const char *s, int *p)
|
|
11958 { if (s)
|
|
11959 { long n;
|
|
11960 char *r;
|
|
11961 #ifndef WITH_NOIO
|
|
11962 #ifndef WITH_LEAN
|
|
11963 soap_reset_errno;
|
|
11964 #endif
|
|
11965 #endif
|
|
11966 n = soap_strtol(s, &r, 10);
|
|
11967 if (s == r || *r
|
|
11968 #ifndef WITH_LEAN
|
|
11969 || n != (int)n
|
|
11970 #endif
|
|
11971 #ifndef WITH_NOIO
|
|
11972 #ifndef WITH_LEAN
|
|
11973 || soap_errno == SOAP_ERANGE
|
|
11974 #endif
|
|
11975 #endif
|
|
11976 )
|
|
11977 soap->error = SOAP_TYPE;
|
|
11978 *p = (int)n;
|
|
11979 }
|
|
11980 return soap->error;
|
|
11981 }
|
|
11982 #endif
|
|
11983
|
|
11984 /******************************************************************************/
|
|
11985 #ifndef PALM_2
|
|
11986 SOAP_FMAC1
|
|
11987 int *
|
|
11988 SOAP_FMAC2
|
|
11989 soap_inint(struct soap *soap, const char *tag, int *p, const char *type, int t)
|
|
11990 { if (soap_element_begin_in(soap, tag, 0, NULL))
|
|
11991 return NULL;
|
|
11992 #ifndef WITH_LEAN
|
|
11993 if (*soap->type
|
|
11994 && soap_match_tag(soap, soap->type, type)
|
|
11995 && soap_match_tag(soap, soap->type, ":int")
|
|
11996 && soap_match_tag(soap, soap->type, ":short")
|
|
11997 && soap_match_tag(soap, soap->type, ":byte"))
|
|
11998 { soap->error = SOAP_TYPE;
|
|
11999 soap_revert(soap);
|
|
12000 return NULL;
|
|
12001 }
|
|
12002 #endif
|
|
12003 p = (int*)soap_id_enter(soap, soap->id, p, t, sizeof(int), 0, NULL, NULL, NULL);
|
|
12004 if (*soap->href)
|
|
12005 p = (int*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(int), 0, NULL);
|
|
12006 else if (p)
|
|
12007 { if (soap_s2int(soap, soap_value(soap), p))
|
|
12008 return NULL;
|
|
12009 }
|
|
12010 if (soap->body && soap_element_end_in(soap, tag))
|
|
12011 return NULL;
|
|
12012 return p;
|
|
12013 }
|
|
12014 #endif
|
|
12015
|
|
12016 /******************************************************************************/
|
|
12017 #ifndef PALM_2
|
|
12018 SOAP_FMAC1
|
|
12019 const char*
|
|
12020 SOAP_FMAC2
|
|
12021 soap_long2s(struct soap *soap, long n)
|
|
12022 {
|
|
12023 #ifdef HAVE_SNPRINTF
|
|
12024 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%ld", n);
|
|
12025 #else
|
|
12026 sprintf(soap->tmpbuf, "%ld", n);
|
|
12027 #endif
|
|
12028 return soap->tmpbuf;
|
|
12029 }
|
|
12030 #endif
|
|
12031
|
|
12032 /******************************************************************************/
|
|
12033 #ifndef PALM_2
|
|
12034 SOAP_FMAC1
|
|
12035 int
|
|
12036 SOAP_FMAC2
|
|
12037 soap_outlong(struct soap *soap, const char *tag, int id, const long *p, const char *type, int n)
|
|
12038 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
|
|
12039 || soap_string_out(soap, soap_long2s(soap, *p), 0))
|
|
12040 return soap->error;
|
|
12041 return soap_element_end_out(soap, tag);
|
|
12042 }
|
|
12043 #endif
|
|
12044
|
|
12045 /******************************************************************************/
|
|
12046 #ifndef PALM_2
|
|
12047 SOAP_FMAC1
|
|
12048 int
|
|
12049 SOAP_FMAC2
|
|
12050 soap_s2long(struct soap *soap, const char *s, long *p)
|
|
12051 { if (s)
|
|
12052 { char *r;
|
|
12053 #ifndef WITH_NOIO
|
|
12054 #ifndef WITH_LEAN
|
|
12055 soap_reset_errno;
|
|
12056 #endif
|
|
12057 #endif
|
|
12058 *p = soap_strtol(s, &r, 10);
|
|
12059 if (s == r || *r
|
|
12060 #ifndef WITH_NOIO
|
|
12061 #ifndef WITH_LEAN
|
|
12062 || soap_errno == SOAP_ERANGE
|
|
12063 #endif
|
|
12064 #endif
|
|
12065 )
|
|
12066 soap->error = SOAP_TYPE;
|
|
12067 }
|
|
12068 return soap->error;
|
|
12069 }
|
|
12070 #endif
|
|
12071
|
|
12072 /******************************************************************************/
|
|
12073 #ifndef PALM_2
|
|
12074 SOAP_FMAC1
|
|
12075 long *
|
|
12076 SOAP_FMAC2
|
|
12077 soap_inlong(struct soap *soap, const char *tag, long *p, const char *type, int t)
|
|
12078 { if (soap_element_begin_in(soap, tag, 0, NULL))
|
|
12079 return NULL;
|
|
12080 #ifndef WITH_LEAN
|
|
12081 if (*soap->type
|
|
12082 && soap_match_tag(soap, soap->type, type)
|
|
12083 && soap_match_tag(soap, soap->type, ":int")
|
|
12084 && soap_match_tag(soap, soap->type, ":short")
|
|
12085 && soap_match_tag(soap, soap->type, ":byte"))
|
|
12086 { soap->error = SOAP_TYPE;
|
|
12087 soap_revert(soap);
|
|
12088 return NULL;
|
|
12089 }
|
|
12090 #endif
|
|
12091 p = (long*)soap_id_enter(soap, soap->id, p, t, sizeof(long), 0, NULL, NULL, NULL);
|
|
12092 if (*soap->href)
|
|
12093 p = (long*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(long), 0, NULL);
|
|
12094 else if (p)
|
|
12095 { if (soap_s2long(soap, soap_value(soap), p))
|
|
12096 return NULL;
|
|
12097 }
|
|
12098 if (soap->body && soap_element_end_in(soap, tag))
|
|
12099 return NULL;
|
|
12100 return p;
|
|
12101 }
|
|
12102 #endif
|
|
12103
|
|
12104 /******************************************************************************/
|
|
12105 #ifndef WITH_LEAN
|
|
12106 SOAP_FMAC1
|
|
12107 const char*
|
|
12108 SOAP_FMAC2
|
|
12109 soap_LONG642s(struct soap *soap, LONG64 n)
|
|
12110 {
|
|
12111 #ifdef HAVE_SNPRINTF
|
|
12112 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), SOAP_LONG_FORMAT, n);
|
|
12113 #else
|
|
12114 sprintf(soap->tmpbuf, SOAP_LONG_FORMAT, n);
|
|
12115 #endif
|
|
12116 return soap->tmpbuf;
|
|
12117 }
|
|
12118 #endif
|
|
12119
|
|
12120 /******************************************************************************/
|
|
12121 #ifndef WITH_LEAN
|
|
12122 SOAP_FMAC1
|
|
12123 int
|
|
12124 SOAP_FMAC2
|
|
12125 soap_outLONG64(struct soap *soap, const char *tag, int id, const LONG64 *p, const char *type, int n)
|
|
12126 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
|
|
12127 || soap_string_out(soap, soap_LONG642s(soap, *p), 0))
|
|
12128 return soap->error;
|
|
12129 return soap_element_end_out(soap, tag);
|
|
12130 }
|
|
12131 #endif
|
|
12132
|
|
12133 /******************************************************************************/
|
|
12134 #ifndef WITH_LEAN
|
|
12135 SOAP_FMAC1
|
|
12136 int
|
|
12137 SOAP_FMAC2
|
|
12138 soap_s2LONG64(struct soap *soap, const char *s, LONG64 *p)
|
|
12139 { if (s)
|
|
12140 {
|
|
12141 #ifdef HAVE_STRTOLL
|
|
12142 char *r;
|
|
12143 #ifndef WITH_NOIO
|
|
12144 #ifndef WITH_LEAN
|
|
12145 soap_reset_errno;
|
|
12146 #endif
|
|
12147 #endif
|
|
12148 *p = soap_strtoll(s, &r, 10);
|
|
12149 if (s == r || *r
|
|
12150 #ifndef WITH_NOIO
|
|
12151 #ifndef WITH_LEAN
|
|
12152 || soap_errno == SOAP_ERANGE
|
|
12153 #endif
|
|
12154 #endif
|
|
12155 )
|
|
12156 #else
|
|
12157 # ifdef HAVE_SSCANF
|
|
12158 if (sscanf(s, SOAP_LONG_FORMAT, p) != 1)
|
|
12159 # endif
|
|
12160 #endif
|
|
12161 soap->error = SOAP_TYPE;
|
|
12162 }
|
|
12163 return soap->error;
|
|
12164 }
|
|
12165 #endif
|
|
12166
|
|
12167 /******************************************************************************/
|
|
12168 #ifndef WITH_LEAN
|
|
12169 SOAP_FMAC1
|
|
12170 LONG64 *
|
|
12171 SOAP_FMAC2
|
|
12172 soap_inLONG64(struct soap *soap, const char *tag, LONG64 *p, const char *type, int t)
|
|
12173 { if (soap_element_begin_in(soap, tag, 0, NULL))
|
|
12174 return NULL;
|
|
12175 #ifndef WITH_LEAN
|
|
12176 if (*soap->type
|
|
12177 && soap_match_tag(soap, soap->type, type)
|
|
12178 && soap_match_tag(soap, soap->type, ":integer")
|
|
12179 && soap_match_tag(soap, soap->type, ":positiveInteger")
|
|
12180 && soap_match_tag(soap, soap->type, ":negativeInteger")
|
|
12181 && soap_match_tag(soap, soap->type, ":nonPositiveInteger")
|
|
12182 && soap_match_tag(soap, soap->type, ":nonNegativeInteger")
|
|
12183 && soap_match_tag(soap, soap->type, ":long")
|
|
12184 && soap_match_tag(soap, soap->type, ":int")
|
|
12185 && soap_match_tag(soap, soap->type, ":short")
|
|
12186 && soap_match_tag(soap, soap->type, ":byte"))
|
|
12187 { soap->error = SOAP_TYPE;
|
|
12188 soap_revert(soap);
|
|
12189 return NULL;
|
|
12190 }
|
|
12191 #endif
|
|
12192 p = (LONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(LONG64), 0, NULL, NULL, NULL);
|
|
12193 if (*soap->href)
|
|
12194 p = (LONG64*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(LONG64), 0, NULL);
|
|
12195 else if (p)
|
|
12196 { if (soap_s2LONG64(soap, soap_value(soap), p))
|
|
12197 return NULL;
|
|
12198 }
|
|
12199 if (soap->body && soap_element_end_in(soap, tag))
|
|
12200 return NULL;
|
|
12201 return p;
|
|
12202 }
|
|
12203 #endif
|
|
12204
|
|
12205 /******************************************************************************/
|
|
12206 #ifndef PALM_2
|
|
12207 SOAP_FMAC1
|
|
12208 const char*
|
|
12209 SOAP_FMAC2
|
|
12210 soap_byte2s(struct soap *soap, char n)
|
|
12211 { return soap_long2s(soap, (long)n);
|
|
12212 }
|
|
12213 #endif
|
|
12214
|
|
12215 /******************************************************************************/
|
|
12216 #ifndef PALM_2
|
|
12217 SOAP_FMAC1
|
|
12218 int
|
|
12219 SOAP_FMAC2
|
|
12220 soap_outbyte(struct soap *soap, const char *tag, int id, const char *p, const char *type, int n)
|
|
12221 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
|
|
12222 || soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
|
|
12223 return soap->error;
|
|
12224 return soap_element_end_out(soap, tag);
|
|
12225 }
|
|
12226 #endif
|
|
12227
|
|
12228 /******************************************************************************/
|
|
12229 #ifndef PALM_2
|
|
12230 SOAP_FMAC1
|
|
12231 int
|
|
12232 SOAP_FMAC2
|
|
12233 soap_s2byte(struct soap *soap, const char *s, char *p)
|
|
12234 { if (s)
|
|
12235 { long n;
|
|
12236 char *r;
|
|
12237 n = soap_strtol(s, &r, 10);
|
|
12238 if (s == r || *r || n < -128 || n > 127)
|
|
12239 soap->error = SOAP_TYPE;
|
|
12240 *p = (char)n;
|
|
12241 }
|
|
12242 return soap->error;
|
|
12243 }
|
|
12244 #endif
|
|
12245
|
|
12246 /******************************************************************************/
|
|
12247 #ifndef PALM_2
|
|
12248 SOAP_FMAC1
|
|
12249 char *
|
|
12250 SOAP_FMAC2
|
|
12251 soap_inbyte(struct soap *soap, const char *tag, char *p, const char *type, int t)
|
|
12252 { if (soap_element_begin_in(soap, tag, 0, NULL))
|
|
12253 return NULL;
|
|
12254 #ifndef WITH_LEAN
|
|
12255 if (*soap->type
|
|
12256 && soap_match_tag(soap, soap->type, type)
|
|
12257 && soap_match_tag(soap, soap->type, ":byte"))
|
|
12258 { soap->error = SOAP_TYPE;
|
|
12259 soap_revert(soap);
|
|
12260 return NULL;
|
|
12261 }
|
|
12262 #endif
|
|
12263 p = (char*)soap_id_enter(soap, soap->id, p, t, sizeof(char), 0, NULL, NULL, NULL);
|
|
12264 if (*soap->href)
|
|
12265 p = (char*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(char), 0, NULL);
|
|
12266 else if (p)
|
|
12267 { if (soap_s2byte(soap, soap_value(soap), p))
|
|
12268 return NULL;
|
|
12269 }
|
|
12270 if (soap->body && soap_element_end_in(soap, tag))
|
|
12271 return NULL;
|
|
12272 return p;
|
|
12273 }
|
|
12274 #endif
|
|
12275
|
|
12276 /******************************************************************************/
|
|
12277 #ifndef PALM_2
|
|
12278 SOAP_FMAC1
|
|
12279 const char*
|
|
12280 SOAP_FMAC2
|
|
12281 soap_short2s(struct soap *soap, short n)
|
|
12282 { return soap_long2s(soap, (long)n);
|
|
12283 }
|
|
12284 #endif
|
|
12285
|
|
12286 /******************************************************************************/
|
|
12287 #ifndef PALM_2
|
|
12288 SOAP_FMAC1
|
|
12289 int
|
|
12290 SOAP_FMAC2
|
|
12291 soap_outshort(struct soap *soap, const char *tag, int id, const short *p, const char *type, int n)
|
|
12292 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
|
|
12293 || soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
|
|
12294 return soap->error;
|
|
12295 return soap_element_end_out(soap, tag);
|
|
12296 }
|
|
12297 #endif
|
|
12298
|
|
12299 /******************************************************************************/
|
|
12300 #ifndef PALM_2
|
|
12301 SOAP_FMAC1
|
|
12302 int
|
|
12303 SOAP_FMAC2
|
|
12304 soap_s2short(struct soap *soap, const char *s, short *p)
|
|
12305 { if (s)
|
|
12306 { long n;
|
|
12307 char *r;
|
|
12308 n = soap_strtol(s, &r, 10);
|
|
12309 if (s == r || *r || n < -32768 || n > 32767)
|
|
12310 soap->error = SOAP_TYPE;
|
|
12311 *p = (short)n;
|
|
12312 }
|
|
12313 return soap->error;
|
|
12314 }
|
|
12315 #endif
|
|
12316
|
|
12317 /******************************************************************************/
|
|
12318 #ifndef PALM_2
|
|
12319 SOAP_FMAC1
|
|
12320 short *
|
|
12321 SOAP_FMAC2
|
|
12322 soap_inshort(struct soap *soap, const char *tag, short *p, const char *type, int t)
|
|
12323 { if (soap_element_begin_in(soap, tag, 0, NULL))
|
|
12324 return NULL;
|
|
12325 #ifndef WITH_LEAN
|
|
12326 if (*soap->type
|
|
12327 && soap_match_tag(soap, soap->type, type)
|
|
12328 && soap_match_tag(soap, soap->type, ":short")
|
|
12329 && soap_match_tag(soap, soap->type, ":byte"))
|
|
12330 { soap->error = SOAP_TYPE;
|
|
12331 soap_revert(soap);
|
|
12332 return NULL;
|
|
12333 }
|
|
12334 #endif
|
|
12335 p = (short*)soap_id_enter(soap, soap->id, p, t, sizeof(short), 0, NULL, NULL, NULL);
|
|
12336 if (*soap->href)
|
|
12337 p = (short*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(short), 0, NULL);
|
|
12338 else if (p)
|
|
12339 { if (soap_s2short(soap, soap_value(soap), p))
|
|
12340 return NULL;
|
|
12341 }
|
|
12342 if (soap->body && soap_element_end_in(soap, tag))
|
|
12343 return NULL;
|
|
12344 return p;
|
|
12345 }
|
|
12346 #endif
|
|
12347
|
|
12348 /******************************************************************************/
|
|
12349 #ifndef PALM_2
|
|
12350 SOAP_FMAC1
|
|
12351 const char*
|
|
12352 SOAP_FMAC2
|
|
12353 soap_float2s(struct soap *soap, float n)
|
|
12354 { char *s;
|
|
12355 if (soap_isnan((double)n))
|
|
12356 return "NaN";
|
|
12357 if (soap_ispinff(n))
|
|
12358 return "INF";
|
|
12359 if (soap_isninff(n))
|
|
12360 return "-INF";
|
|
12361 #if defined(HAVE_SPRINTF_L)
|
|
12362 # ifdef WIN32
|
|
12363 _sprintf_s_l(soap->tmpbuf, _countof(soap->tmpbuf), soap->float_format, soap->c_locale, n);
|
|
12364 # else
|
|
12365 sprintf_l(soap->tmpbuf, soap->c_locale, soap->float_format, n);
|
|
12366 # endif
|
|
12367 #else
|
|
12368 # ifdef HAVE_SNPRINTF
|
|
12369 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), soap->float_format, n);
|
|
12370 # else
|
|
12371 sprintf(soap->tmpbuf, soap->float_format, n);
|
|
12372 # endif
|
|
12373 s = strchr(soap->tmpbuf, ','); /* convert decimal comma to DP */
|
|
12374 if (s)
|
|
12375 *s = '.';
|
|
12376 #endif
|
|
12377 return soap->tmpbuf;
|
|
12378 }
|
|
12379 #endif
|
|
12380
|
|
12381 /******************************************************************************/
|
|
12382 #ifndef PALM_2
|
|
12383 SOAP_FMAC1
|
|
12384 int
|
|
12385 SOAP_FMAC2
|
|
12386 soap_outfloat(struct soap *soap, const char *tag, int id, const float *p, const char *type, int n)
|
|
12387 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
|
|
12388 || soap_string_out(soap, soap_float2s(soap, *p), 0))
|
|
12389 return soap->error;
|
|
12390 return soap_element_end_out(soap, tag);
|
|
12391 }
|
|
12392 #endif
|
|
12393
|
|
12394 /******************************************************************************/
|
|
12395 #ifndef PALM_2
|
|
12396 SOAP_FMAC1
|
|
12397 int
|
|
12398 SOAP_FMAC2
|
|
12399 soap_s2float(struct soap *soap, const char *s, float *p)
|
|
12400 { if (s)
|
|
12401 { if (!*s)
|
|
12402 return soap->error = SOAP_TYPE;
|
|
12403 if (!soap_tag_cmp(s, "INF"))
|
|
12404 *p = FLT_PINFTY;
|
|
12405 else if (!soap_tag_cmp(s, "+INF"))
|
|
12406 *p = FLT_PINFTY;
|
|
12407 else if (!soap_tag_cmp(s, "-INF"))
|
|
12408 *p = FLT_NINFTY;
|
|
12409 else if (!soap_tag_cmp(s, "NaN"))
|
|
12410 *p = FLT_NAN;
|
|
12411 else
|
|
12412 {
|
|
12413 /* On some systems strtof requires -std=c99 or does not even link: so we try to use strtod first */
|
|
12414 #if defined(HAVE_STRTOD_L)
|
|
12415 char *r;
|
|
12416 # ifdef WIN32
|
|
12417 *p = (float)_strtod_l(s, &r, soap->c_locale);
|
|
12418 # else
|
|
12419 *p = (float)strtod_l(s, &r, soap->c_locale);
|
|
12420 # endif
|
|
12421 if (*r)
|
|
12422 #elif defined(HAVE_STRTOD)
|
|
12423 char *r;
|
|
12424 *p = (float)strtod(s, &r);
|
|
12425 if (*r)
|
|
12426 #elif defined(HAVE_STRTOF_L)
|
|
12427 char *r;
|
|
12428 *p = strtof_l((char*)s, &r, soap->c_locale);
|
|
12429 if (*r)
|
|
12430 #elif defined(HAVE_STRTOF)
|
|
12431 char *r;
|
|
12432 *p = strtof((char*)s, &r);
|
|
12433 if (*r)
|
|
12434 #endif
|
|
12435 {
|
|
12436 #if defined(HAVE_SSCANF_L) && !defined(HAVE_STRTOF_L) && !defined(HAVE_STRTOD_L)
|
|
12437 if (sscanf_l(s, soap->c_locale, "%f", p) != 1)
|
|
12438 soap->error = SOAP_TYPE;
|
|
12439 #elif defined(HAVE_SSCANF)
|
|
12440 if (sscanf(s, "%f", p) != 1)
|
|
12441 soap->error = SOAP_TYPE;
|
|
12442 #else
|
|
12443 soap->error = SOAP_TYPE;
|
|
12444 #endif
|
|
12445 }
|
|
12446 }
|
|
12447 }
|
|
12448 return soap->error;
|
|
12449 }
|
|
12450 #endif
|
|
12451
|
|
12452 /******************************************************************************/
|
|
12453 #ifndef WITH_LEAN
|
|
12454 static int soap_isnumeric(struct soap *soap, const char *type)
|
|
12455 { if (soap_match_tag(soap, soap->type, type)
|
|
12456 && soap_match_tag(soap, soap->type, ":float")
|
|
12457 && soap_match_tag(soap, soap->type, ":double")
|
|
12458 && soap_match_tag(soap, soap->type, ":decimal")
|
|
12459 && soap_match_tag(soap, soap->type, ":integer")
|
|
12460 && soap_match_tag(soap, soap->type, ":positiveInteger")
|
|
12461 && soap_match_tag(soap, soap->type, ":negativeInteger")
|
|
12462 && soap_match_tag(soap, soap->type, ":nonPositiveInteger")
|
|
12463 && soap_match_tag(soap, soap->type, ":nonNegativeInteger")
|
|
12464 && soap_match_tag(soap, soap->type, ":long")
|
|
12465 && soap_match_tag(soap, soap->type, ":int")
|
|
12466 && soap_match_tag(soap, soap->type, ":short")
|
|
12467 && soap_match_tag(soap, soap->type, ":byte")
|
|
12468 && soap_match_tag(soap, soap->type, ":unsignedLong")
|
|
12469 && soap_match_tag(soap, soap->type, ":unsignedInt")
|
|
12470 && soap_match_tag(soap, soap->type, ":unsignedShort")
|
|
12471 && soap_match_tag(soap, soap->type, ":unsignedByte"))
|
|
12472 { soap->error = SOAP_TYPE;
|
|
12473 soap_revert(soap);
|
|
12474 return SOAP_ERR;
|
|
12475 }
|
|
12476 return SOAP_OK;
|
|
12477 }
|
|
12478 #endif
|
|
12479
|
|
12480 /******************************************************************************/
|
|
12481 #ifndef PALM_2
|
|
12482 SOAP_FMAC1
|
|
12483 float *
|
|
12484 SOAP_FMAC2
|
|
12485 soap_infloat(struct soap *soap, const char *tag, float *p, const char *type, int t)
|
|
12486 { if (soap_element_begin_in(soap, tag, 0, NULL))
|
|
12487 return NULL;
|
|
12488 #ifndef WITH_LEAN
|
|
12489 if (*soap->type != '\0' && soap_isnumeric(soap, type))
|
|
12490 return NULL;
|
|
12491 #endif
|
|
12492 p = (float*)soap_id_enter(soap, soap->id, p, t, sizeof(float), 0, NULL, NULL, NULL);
|
|
12493 if (*soap->href)
|
|
12494 p = (float*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(float), 0, NULL);
|
|
12495 else if (p)
|
|
12496 { if (soap_s2float(soap, soap_value(soap), p))
|
|
12497 return NULL;
|
|
12498 }
|
|
12499 if (soap->body && soap_element_end_in(soap, tag))
|
|
12500 return NULL;
|
|
12501 return p;
|
|
12502 }
|
|
12503 #endif
|
|
12504
|
|
12505 /******************************************************************************/
|
|
12506 #ifndef PALM_2
|
|
12507 SOAP_FMAC1
|
|
12508 const char*
|
|
12509 SOAP_FMAC2
|
|
12510 soap_double2s(struct soap *soap, double n)
|
|
12511 { char *s;
|
|
12512 if (soap_isnan(n))
|
|
12513 return "NaN";
|
|
12514 if (soap_ispinfd(n))
|
|
12515 return "INF";
|
|
12516 if (soap_isninfd(n))
|
|
12517 return "-INF";
|
|
12518 #if defined(HAVE_SPRINTF_L)
|
|
12519 # ifdef WIN32
|
|
12520 _sprintf_s_l(soap->tmpbuf, _countof(soap->tmpbuf), soap->double_format, soap->c_locale, n);
|
|
12521 # else
|
|
12522 sprintf_l(soap->tmpbuf, soap->c_locale, soap->double_format, n);
|
|
12523 # endif
|
|
12524 #else
|
|
12525 # ifdef HAVE_SNPRINTF
|
|
12526 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), soap->double_format, n);
|
|
12527 #else
|
|
12528 sprintf(soap->tmpbuf, soap->double_format, n);
|
|
12529 #endif
|
|
12530 s = strchr(soap->tmpbuf, ','); /* convert decimal comma to DP */
|
|
12531 if (s)
|
|
12532 *s = '.';
|
|
12533 #endif
|
|
12534 return soap->tmpbuf;
|
|
12535 }
|
|
12536 #endif
|
|
12537
|
|
12538 /******************************************************************************/
|
|
12539 #ifndef PALM_2
|
|
12540 SOAP_FMAC1
|
|
12541 int
|
|
12542 SOAP_FMAC2
|
|
12543 soap_outdouble(struct soap *soap, const char *tag, int id, const double *p, const char *type, int n)
|
|
12544 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
|
|
12545 || soap_string_out(soap, soap_double2s(soap, *p), 0))
|
|
12546 return soap->error;
|
|
12547 return soap_element_end_out(soap, tag);
|
|
12548 }
|
|
12549 #endif
|
|
12550
|
|
12551 /******************************************************************************/
|
|
12552 #ifndef PALM_2
|
|
12553 SOAP_FMAC1
|
|
12554 int
|
|
12555 SOAP_FMAC2
|
|
12556 soap_s2double(struct soap *soap, const char *s, double *p)
|
|
12557 { if (s)
|
|
12558 { if (!*s)
|
|
12559 return soap->error = SOAP_TYPE;
|
|
12560 if (!soap_tag_cmp(s, "INF"))
|
|
12561 *p = DBL_PINFTY;
|
|
12562 else if (!soap_tag_cmp(s, "+INF"))
|
|
12563 *p = DBL_PINFTY;
|
|
12564 else if (!soap_tag_cmp(s, "-INF"))
|
|
12565 *p = DBL_NINFTY;
|
|
12566 else if (!soap_tag_cmp(s, "NaN"))
|
|
12567 *p = DBL_NAN;
|
|
12568 else
|
|
12569 {
|
|
12570 #if defined(HAVE_STRTOD_L)
|
|
12571 char *r;
|
|
12572 # ifdef WIN32
|
|
12573 *p = _strtod_l(s, &r, soap->c_locale);
|
|
12574 # else
|
|
12575 *p = strtod_l(s, &r, soap->c_locale);
|
|
12576 # endif
|
|
12577 if (*r)
|
|
12578 #elif defined(HAVE_STRTOD)
|
|
12579 char *r;
|
|
12580 *p = strtod(s, &r);
|
|
12581 if (*r)
|
|
12582 #endif
|
|
12583 {
|
|
12584 #if defined(HAVE_SSCANF_L) && !defined(HAVE_STRTOF_L) && !defined(HAVE_STRTOD_L)
|
|
12585 if (sscanf_l(s, soap->c_locale, "%lf", p) != 1)
|
|
12586 soap->error = SOAP_TYPE;
|
|
12587 #elif defined(HAVE_SSCANF)
|
|
12588 if (sscanf(s, "%lf", p) != 1)
|
|
12589 soap->error = SOAP_TYPE;
|
|
12590 #else
|
|
12591 soap->error = SOAP_TYPE;
|
|
12592 #endif
|
|
12593 }
|
|
12594 }
|
|
12595 }
|
|
12596 return soap->error;
|
|
12597 }
|
|
12598 #endif
|
|
12599
|
|
12600 /******************************************************************************/
|
|
12601 #ifndef PALM_2
|
|
12602 SOAP_FMAC1
|
|
12603 double *
|
|
12604 SOAP_FMAC2
|
|
12605 soap_indouble(struct soap *soap, const char *tag, double *p, const char *type, int t)
|
|
12606 { if (soap_element_begin_in(soap, tag, 0, NULL))
|
|
12607 return NULL;
|
|
12608 #ifndef WITH_LEAN
|
|
12609 if (*soap->type != '\0' && soap_isnumeric(soap, type))
|
|
12610 return NULL;
|
|
12611 #endif
|
|
12612 p = (double*)soap_id_enter(soap, soap->id, p, t, sizeof(double), 0, NULL, NULL, NULL);
|
|
12613 if (*soap->href)
|
|
12614 p = (double*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(double), 0, NULL);
|
|
12615 else if (p)
|
|
12616 { if (soap_s2double(soap, soap_value(soap), p))
|
|
12617 return NULL;
|
|
12618 }
|
|
12619 if (soap->body && soap_element_end_in(soap, tag))
|
|
12620 return NULL;
|
|
12621 return p;
|
|
12622 }
|
|
12623 #endif
|
|
12624
|
|
12625 /******************************************************************************/
|
|
12626 #ifndef PALM_2
|
|
12627 SOAP_FMAC1
|
|
12628 const char*
|
|
12629 SOAP_FMAC2
|
|
12630 soap_unsignedByte2s(struct soap *soap, unsigned char n)
|
|
12631 { return soap_unsignedLong2s(soap, (unsigned long)n);
|
|
12632 }
|
|
12633 #endif
|
|
12634
|
|
12635 /******************************************************************************/
|
|
12636 #ifndef PALM_2
|
|
12637 SOAP_FMAC1
|
|
12638 int
|
|
12639 SOAP_FMAC2
|
|
12640 soap_outunsignedByte(struct soap *soap, const char *tag, int id, const unsigned char *p, const char *type, int n)
|
|
12641 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
|
|
12642 || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0))
|
|
12643 return soap->error;
|
|
12644 return soap_element_end_out(soap, tag);
|
|
12645 }
|
|
12646 #endif
|
|
12647
|
|
12648 /******************************************************************************/
|
|
12649 #ifndef PALM_2
|
|
12650 SOAP_FMAC1
|
|
12651 int
|
|
12652 SOAP_FMAC2
|
|
12653 soap_s2unsignedByte(struct soap *soap, const char *s, unsigned char *p)
|
|
12654 { if (s)
|
|
12655 { unsigned long n;
|
|
12656 char *r;
|
|
12657 n = soap_strtoul(s, &r, 10);
|
|
12658 if (s == r || *r || n > 255)
|
|
12659 soap->error = SOAP_TYPE;
|
|
12660 *p = (unsigned char)n;
|
|
12661 }
|
|
12662 return soap->error;
|
|
12663 }
|
|
12664 #endif
|
|
12665
|
|
12666 /******************************************************************************/
|
|
12667 #ifndef PALM_2
|
|
12668 SOAP_FMAC1
|
|
12669 unsigned char *
|
|
12670 SOAP_FMAC2
|
|
12671 soap_inunsignedByte(struct soap *soap, const char *tag, unsigned char *p, const char *type, int t)
|
|
12672 { if (soap_element_begin_in(soap, tag, 0, NULL))
|
|
12673 return NULL;
|
|
12674 #ifndef WITH_LEAN
|
|
12675 if (*soap->type
|
|
12676 && soap_match_tag(soap, soap->type, type)
|
|
12677 && soap_match_tag(soap, soap->type, ":unsignedByte"))
|
|
12678 { soap->error = SOAP_TYPE;
|
|
12679 soap_revert(soap);
|
|
12680 return NULL;
|
|
12681 }
|
|
12682 #endif
|
|
12683 p = (unsigned char*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned char), 0, NULL, NULL, NULL);
|
|
12684 if (*soap->href)
|
|
12685 p = (unsigned char*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned char), 0, NULL);
|
|
12686 else if (p)
|
|
12687 { if (soap_s2unsignedByte(soap, soap_value(soap), p))
|
|
12688 return NULL;
|
|
12689 }
|
|
12690 if (soap->body && soap_element_end_in(soap, tag))
|
|
12691 return NULL;
|
|
12692 return p;
|
|
12693 }
|
|
12694 #endif
|
|
12695
|
|
12696 /******************************************************************************/
|
|
12697 #ifndef PALM_2
|
|
12698 SOAP_FMAC1
|
|
12699 const char*
|
|
12700 SOAP_FMAC2
|
|
12701 soap_unsignedShort2s(struct soap *soap, unsigned short n)
|
|
12702 { return soap_unsignedLong2s(soap, (unsigned long)n);
|
|
12703 }
|
|
12704 #endif
|
|
12705
|
|
12706 /******************************************************************************/
|
|
12707 #ifndef PALM_2
|
|
12708 SOAP_FMAC1
|
|
12709 int
|
|
12710 SOAP_FMAC2
|
|
12711 soap_outunsignedShort(struct soap *soap, const char *tag, int id, const unsigned short *p, const char *type, int n)
|
|
12712 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
|
|
12713 || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0))
|
|
12714 return soap->error;
|
|
12715 return soap_element_end_out(soap, tag);
|
|
12716 }
|
|
12717 #endif
|
|
12718
|
|
12719 /******************************************************************************/
|
|
12720 #ifndef PALM_2
|
|
12721 SOAP_FMAC1
|
|
12722 int
|
|
12723 SOAP_FMAC2
|
|
12724 soap_s2unsignedShort(struct soap *soap, const char *s, unsigned short *p)
|
|
12725 { if (s)
|
|
12726 { unsigned long n;
|
|
12727 char *r;
|
|
12728 n = soap_strtoul(s, &r, 10);
|
|
12729 if (s == r || *r || n > 65535)
|
|
12730 soap->error = SOAP_TYPE;
|
|
12731 *p = (unsigned short)n;
|
|
12732 }
|
|
12733 return soap->error;
|
|
12734 }
|
|
12735 #endif
|
|
12736
|
|
12737 /******************************************************************************/
|
|
12738 #ifndef PALM_2
|
|
12739 SOAP_FMAC1
|
|
12740 unsigned short *
|
|
12741 SOAP_FMAC2
|
|
12742 soap_inunsignedShort(struct soap *soap, const char *tag, unsigned short *p, const char *type, int t)
|
|
12743 { if (soap_element_begin_in(soap, tag, 0, NULL))
|
|
12744 return NULL;
|
|
12745 #ifndef WITH_LEAN
|
|
12746 if (*soap->type
|
|
12747 && soap_match_tag(soap, soap->type, type)
|
|
12748 && soap_match_tag(soap, soap->type, ":unsignedShort")
|
|
12749 && soap_match_tag(soap, soap->type, ":unsignedByte"))
|
|
12750 { soap->error = SOAP_TYPE;
|
|
12751 soap_revert(soap);
|
|
12752 return NULL;
|
|
12753 }
|
|
12754 #endif
|
|
12755 p = (unsigned short*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned short), 0, NULL, NULL, NULL);
|
|
12756 if (*soap->href)
|
|
12757 p = (unsigned short*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned short), 0, NULL);
|
|
12758 else if (p)
|
|
12759 { if (soap_s2unsignedShort(soap, soap_value(soap), p))
|
|
12760 return NULL;
|
|
12761 }
|
|
12762 if (soap->body && soap_element_end_in(soap, tag))
|
|
12763 return NULL;
|
|
12764 return p;
|
|
12765 }
|
|
12766 #endif
|
|
12767
|
|
12768 /******************************************************************************/
|
|
12769 #ifndef PALM_2
|
|
12770 SOAP_FMAC1
|
|
12771 const char*
|
|
12772 SOAP_FMAC2
|
|
12773 soap_unsignedInt2s(struct soap *soap, unsigned int n)
|
|
12774 { return soap_unsignedLong2s(soap, (unsigned long)n);
|
|
12775 }
|
|
12776 #endif
|
|
12777
|
|
12778 /******************************************************************************/
|
|
12779 #ifndef PALM_2
|
|
12780 SOAP_FMAC1
|
|
12781 int
|
|
12782 SOAP_FMAC2
|
|
12783 soap_outunsignedInt(struct soap *soap, const char *tag, int id, const unsigned int *p, const char *type, int n)
|
|
12784 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
|
|
12785 || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0))
|
|
12786 return soap->error;
|
|
12787 return soap_element_end_out(soap, tag);
|
|
12788 }
|
|
12789 #endif
|
|
12790
|
|
12791 /******************************************************************************/
|
|
12792 #ifndef PALM_2
|
|
12793 SOAP_FMAC1
|
|
12794 int
|
|
12795 SOAP_FMAC2
|
|
12796 soap_s2unsignedInt(struct soap *soap, const char *s, unsigned int *p)
|
|
12797 { if (s)
|
|
12798 { char *r;
|
|
12799 #ifndef WITH_NOIO
|
|
12800 #ifndef WITH_LEAN
|
|
12801 soap_reset_errno;
|
|
12802 #endif
|
|
12803 #endif
|
|
12804 *p = (unsigned int)soap_strtoul(s, &r, 10);
|
|
12805 if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
|
|
12806 #ifndef WITH_NOIO
|
|
12807 #ifndef WITH_LEAN
|
|
12808 || soap_errno == SOAP_ERANGE
|
|
12809 #endif
|
|
12810 #endif
|
|
12811 )
|
|
12812 soap->error = SOAP_TYPE;
|
|
12813 }
|
|
12814 return soap->error;
|
|
12815 }
|
|
12816 #endif
|
|
12817
|
|
12818 /******************************************************************************/
|
|
12819 #ifndef PALM_2
|
|
12820 SOAP_FMAC1
|
|
12821 unsigned int *
|
|
12822 SOAP_FMAC2
|
|
12823 soap_inunsignedInt(struct soap *soap, const char *tag, unsigned int *p, const char *type, int t)
|
|
12824 { if (soap_element_begin_in(soap, tag, 0, NULL))
|
|
12825 return NULL;
|
|
12826 #ifndef WITH_LEAN
|
|
12827 if (*soap->type
|
|
12828 && soap_match_tag(soap, soap->type, type)
|
|
12829 && soap_match_tag(soap, soap->type, ":unsignedInt")
|
|
12830 && soap_match_tag(soap, soap->type, ":unsignedShort")
|
|
12831 && soap_match_tag(soap, soap->type, ":unsignedByte"))
|
|
12832 { soap->error = SOAP_TYPE;
|
|
12833 soap_revert(soap);
|
|
12834 return NULL;
|
|
12835 }
|
|
12836 #endif
|
|
12837 p = (unsigned int*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned int), 0, NULL, NULL, NULL);
|
|
12838 if (*soap->href)
|
|
12839 p = (unsigned int*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned int), 0, NULL);
|
|
12840 else if (p)
|
|
12841 { if (soap_s2unsignedInt(soap, soap_value(soap), p))
|
|
12842 return NULL;
|
|
12843 }
|
|
12844 if (soap->body && soap_element_end_in(soap, tag))
|
|
12845 return NULL;
|
|
12846 return p;
|
|
12847 }
|
|
12848 #endif
|
|
12849
|
|
12850 /******************************************************************************/
|
|
12851 #ifndef PALM_2
|
|
12852 SOAP_FMAC1
|
|
12853 const char*
|
|
12854 SOAP_FMAC2
|
|
12855 soap_unsignedLong2s(struct soap *soap, unsigned long n)
|
|
12856 {
|
|
12857 #ifdef HAVE_SNPRINTF
|
|
12858 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%lu", n);
|
|
12859 #else
|
|
12860 sprintf(soap->tmpbuf, "%lu", n);
|
|
12861 #endif
|
|
12862 return soap->tmpbuf;
|
|
12863 }
|
|
12864 #endif
|
|
12865
|
|
12866 /******************************************************************************/
|
|
12867 #ifndef PALM_2
|
|
12868 SOAP_FMAC1
|
|
12869 int
|
|
12870 SOAP_FMAC2
|
|
12871 soap_outunsignedLong(struct soap *soap, const char *tag, int id, const unsigned long *p, const char *type, int n)
|
|
12872 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
|
|
12873 || soap_string_out(soap, soap_unsignedLong2s(soap, *p), 0))
|
|
12874 return soap->error;
|
|
12875 return soap_element_end_out(soap, tag);
|
|
12876 }
|
|
12877 #endif
|
|
12878
|
|
12879 /******************************************************************************/
|
|
12880 #ifndef PALM_2
|
|
12881 SOAP_FMAC1
|
|
12882 int
|
|
12883 SOAP_FMAC2
|
|
12884 soap_s2unsignedLong(struct soap *soap, const char *s, unsigned long *p)
|
|
12885 { if (s)
|
|
12886 { char *r;
|
|
12887 #ifndef WITH_NOIO
|
|
12888 #ifndef WITH_LEAN
|
|
12889 soap_reset_errno;
|
|
12890 #endif
|
|
12891 #endif
|
|
12892 *p = soap_strtoul(s, &r, 10);
|
|
12893 if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
|
|
12894 #ifndef WITH_NOIO
|
|
12895 #ifndef WITH_LEAN
|
|
12896 || soap_errno == SOAP_ERANGE
|
|
12897 #endif
|
|
12898 #endif
|
|
12899 )
|
|
12900 soap->error = SOAP_TYPE;
|
|
12901 }
|
|
12902 return soap->error;
|
|
12903 }
|
|
12904 #endif
|
|
12905
|
|
12906 /******************************************************************************/
|
|
12907 #ifndef PALM_2
|
|
12908 SOAP_FMAC1
|
|
12909 unsigned long *
|
|
12910 SOAP_FMAC2
|
|
12911 soap_inunsignedLong(struct soap *soap, const char *tag, unsigned long *p, const char *type, int t)
|
|
12912 { if (soap_element_begin_in(soap, tag, 0, NULL))
|
|
12913 return NULL;
|
|
12914 #ifndef WITH_LEAN
|
|
12915 if (*soap->type
|
|
12916 && soap_match_tag(soap, soap->type, type)
|
|
12917 && soap_match_tag(soap, soap->type, ":unsignedInt")
|
|
12918 && soap_match_tag(soap, soap->type, ":unsignedShort")
|
|
12919 && soap_match_tag(soap, soap->type, ":unsignedByte"))
|
|
12920 { soap->error = SOAP_TYPE;
|
|
12921 soap_revert(soap);
|
|
12922 return NULL;
|
|
12923 }
|
|
12924 #endif
|
|
12925 p = (unsigned long*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned long), 0, NULL, NULL, NULL);
|
|
12926 if (*soap->href)
|
|
12927 p = (unsigned long*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned long), 0, NULL);
|
|
12928 else if (p)
|
|
12929 { if (soap_s2unsignedLong(soap, soap_value(soap), p))
|
|
12930 return NULL;
|
|
12931 }
|
|
12932 if (soap->body && soap_element_end_in(soap, tag))
|
|
12933 return NULL;
|
|
12934 return p;
|
|
12935 }
|
|
12936 #endif
|
|
12937
|
|
12938 /******************************************************************************/
|
|
12939 #ifndef WITH_LEAN
|
|
12940 SOAP_FMAC1
|
|
12941 const char*
|
|
12942 SOAP_FMAC2
|
|
12943 soap_ULONG642s(struct soap *soap, ULONG64 n)
|
|
12944 {
|
|
12945 #ifdef HAVE_SNPRINTF
|
|
12946 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), SOAP_ULONG_FORMAT, n);
|
|
12947 #else
|
|
12948 sprintf(soap->tmpbuf, SOAP_ULONG_FORMAT, n);
|
|
12949 #endif
|
|
12950 return soap->tmpbuf;
|
|
12951 }
|
|
12952 #endif
|
|
12953
|
|
12954 /******************************************************************************/
|
|
12955 #ifndef WITH_LEAN
|
|
12956 SOAP_FMAC1
|
|
12957 int
|
|
12958 SOAP_FMAC2
|
|
12959 soap_outULONG64(struct soap *soap, const char *tag, int id, const ULONG64 *p, const char *type, int n)
|
|
12960 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
|
|
12961 || soap_string_out(soap, soap_ULONG642s(soap, *p), 0))
|
|
12962 return soap->error;
|
|
12963 return soap_element_end_out(soap, tag);
|
|
12964 }
|
|
12965 #endif
|
|
12966
|
|
12967 /******************************************************************************/
|
|
12968 #ifndef WITH_LEAN
|
|
12969 SOAP_FMAC1
|
|
12970 int
|
|
12971 SOAP_FMAC2
|
|
12972 soap_s2ULONG64(struct soap *soap, const char *s, ULONG64 *p)
|
|
12973 { if (s)
|
|
12974 {
|
|
12975 #ifdef HAVE_STRTOULL
|
|
12976 char *r;
|
|
12977 #ifndef WITH_NOIO
|
|
12978 #ifndef WITH_LEAN
|
|
12979 soap_reset_errno;
|
|
12980 #endif
|
|
12981 #endif
|
|
12982 *p = soap_strtoull(s, &r, 10);
|
|
12983 if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
|
|
12984 #ifndef WITH_NOIO
|
|
12985 #ifndef WITH_LEAN
|
|
12986 || soap_errno == SOAP_ERANGE
|
|
12987 #endif
|
|
12988 #endif
|
|
12989 )
|
|
12990 #else
|
|
12991 #ifdef HAVE_SSCANF
|
|
12992 if (sscanf(s, SOAP_ULONG_FORMAT, p) != 1)
|
|
12993 #endif
|
|
12994 #endif
|
|
12995 soap->error = SOAP_TYPE;
|
|
12996 }
|
|
12997 return soap->error;
|
|
12998 }
|
|
12999 #endif
|
|
13000
|
|
13001 /******************************************************************************/
|
|
13002 #ifndef WITH_LEAN
|
|
13003 SOAP_FMAC1
|
|
13004 ULONG64 *
|
|
13005 SOAP_FMAC2
|
|
13006 soap_inULONG64(struct soap *soap, const char *tag, ULONG64 *p, const char *type, int t)
|
|
13007 { if (soap_element_begin_in(soap, tag, 0, NULL))
|
|
13008 return NULL;
|
|
13009 if (*soap->type
|
|
13010 && soap_match_tag(soap, soap->type, type)
|
|
13011 && soap_match_tag(soap, soap->type, ":positiveInteger")
|
|
13012 && soap_match_tag(soap, soap->type, ":nonNegativeInteger")
|
|
13013 && soap_match_tag(soap, soap->type, ":unsignedLong")
|
|
13014 && soap_match_tag(soap, soap->type, ":unsignedInt")
|
|
13015 && soap_match_tag(soap, soap->type, ":unsignedShort")
|
|
13016 && soap_match_tag(soap, soap->type, ":unsignedByte"))
|
|
13017 { soap->error = SOAP_TYPE;
|
|
13018 soap_revert(soap);
|
|
13019 return NULL;
|
|
13020 }
|
|
13021 p = (ULONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(ULONG64), 0, NULL, NULL, NULL);
|
|
13022 if (*soap->href)
|
|
13023 p = (ULONG64*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(ULONG64), 0, NULL);
|
|
13024 else if (p)
|
|
13025 { if (soap_s2ULONG64(soap, soap_value(soap), p))
|
|
13026 return NULL;
|
|
13027 }
|
|
13028 if (soap->body && soap_element_end_in(soap, tag))
|
|
13029 return NULL;
|
|
13030 return p;
|
|
13031 }
|
|
13032 #endif
|
|
13033
|
|
13034 /******************************************************************************/
|
|
13035 #ifndef PALM_2
|
|
13036 SOAP_FMAC1
|
|
13037 int
|
|
13038 SOAP_FMAC2
|
|
13039 soap_s2string(struct soap *soap, const char *s, char **t, long minlen, long maxlen)
|
|
13040 { if (s)
|
|
13041 { long l = (long)strlen(s);
|
|
13042 if ((maxlen >= 0 && l > maxlen) || l < minlen)
|
|
13043 return soap->error = SOAP_LENGTH;
|
|
13044 if (!(*t = soap_strdup(soap, s)))
|
|
13045 return soap->error = SOAP_EOM;
|
|
13046 if (!(soap->mode & (SOAP_ENC_LATIN | SOAP_C_UTFSTRING)))
|
|
13047 { char *r = *t;
|
|
13048 /* remove non-ASCII chars */
|
|
13049 for (s = *t; *s; s++)
|
|
13050 if (!(*s & 0x80))
|
|
13051 *r++ = *s;
|
|
13052 *r = '\0';
|
|
13053 }
|
|
13054 }
|
|
13055 return soap->error;
|
|
13056 }
|
|
13057 #endif
|
|
13058
|
|
13059 /******************************************************************************/
|
|
13060 #ifndef PALM_2
|
|
13061 SOAP_FMAC1
|
|
13062 int
|
|
13063 SOAP_FMAC2
|
|
13064 soap_s2QName(struct soap *soap, const char *s, char **t, long minlen, long maxlen)
|
|
13065 { if (s)
|
|
13066 { long l = (long)strlen(s);
|
|
13067 if ((maxlen >= 0 && l > maxlen) || l < minlen)
|
|
13068 return soap->error = SOAP_LENGTH;
|
|
13069 soap->labidx = 0;
|
|
13070 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Normalized namespace(s) of QNames '%s'", s));
|
|
13071 /* convert (by prefix normalize prefix) all QNames in s */
|
|
13072 for (;;)
|
|
13073 { size_t n;
|
|
13074 struct soap_nlist *np;
|
|
13075 register const char *p;
|
|
13076 /* skip blanks */
|
|
13077 while (*s && soap_blank((soap_wchar)*s))
|
|
13078 s++;
|
|
13079 if (!*s)
|
|
13080 break;
|
|
13081 /* find next QName */
|
|
13082 n = 1;
|
|
13083 while (s[n] && !soap_blank((soap_wchar)s[n]))
|
|
13084 n++;
|
|
13085 np = soap->nlist;
|
|
13086 /* if there is no namespace stack, or prefix is "#" or "xml" then copy string */
|
|
13087 if (!np || *s == '#' || !strncmp(s, "xml:", 4))
|
|
13088 { soap_append_lab(soap, s, n);
|
|
13089 }
|
|
13090 else /* we normalize the QName by replacing its prefix */
|
|
13091 { const char *q;
|
|
13092 for (p = s; *p && p < s + n; p++)
|
|
13093 if (*p == ':')
|
|
13094 break;
|
|
13095 if (*p == ':')
|
|
13096 { size_t k = p - s;
|
|
13097 while (np && (strncmp(np->id, s, k) || np->id[k]))
|
|
13098 np = np->next;
|
|
13099 p++;
|
|
13100 }
|
|
13101 else
|
|
13102 { while (np && *np->id)
|
|
13103 np = np->next;
|
|
13104 p = s;
|
|
13105 }
|
|
13106 /* replace prefix */
|
|
13107 if (np)
|
|
13108 { if (np->index >= 0 && soap->local_namespaces && (q = soap->local_namespaces[np->index].id))
|
|
13109 { size_t k = strlen(q);
|
|
13110 if (q[k-1] != '_')
|
|
13111 soap_append_lab(soap, q, k);
|
|
13112 else
|
|
13113 { soap_append_lab(soap, "\"", 1);
|
|
13114 soap_append_lab(soap, soap->local_namespaces[np->index].ns, strlen(soap->local_namespaces[np->index].ns));
|
|
13115 soap_append_lab(soap, "\"", 1);
|
|
13116 }
|
|
13117 }
|
|
13118 else if (np->ns)
|
|
13119 { soap_append_lab(soap, "\"", 1);
|
|
13120 soap_append_lab(soap, np->ns, strlen(np->ns));
|
|
13121 soap_append_lab(soap, "\"", 1);
|
|
13122 }
|
|
13123 else
|
|
13124 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\nNamespace prefix of '%s' not defined (index=%d, URI='%s')\n", s, np->index, np->ns ? np->ns : SOAP_STR_EOS));
|
|
13125 return soap->error = SOAP_NAMESPACE;
|
|
13126 }
|
|
13127 }
|
|
13128 else if (s[n]) /* no namespace, part of string */
|
|
13129 { soap_append_lab(soap, s, n);
|
|
13130 }
|
|
13131 else /* no namespace: assume "" namespace */
|
|
13132 { soap_append_lab(soap, "\"\"", 2);
|
|
13133 }
|
|
13134 soap_append_lab(soap, ":", 1);
|
|
13135 soap_append_lab(soap, p, n - (p-s));
|
|
13136 }
|
|
13137 /* advance to next and add spacing */
|
|
13138 s += n;
|
|
13139 if (*s)
|
|
13140 soap_append_lab(soap, " ", 1);
|
|
13141 }
|
|
13142 soap_append_lab(soap, SOAP_STR_EOS, 1);
|
|
13143 *t = soap_strdup(soap, soap->labbuf);
|
|
13144 DBGLOG(TEST, SOAP_MESSAGE(fdebug, " into '%s'\n", *t));
|
|
13145 }
|
|
13146 return soap->error;
|
|
13147 }
|
|
13148 #endif
|
|
13149
|
|
13150 /******************************************************************************/
|
|
13151 #ifndef PALM_2
|
|
13152 SOAP_FMAC1
|
|
13153 const char*
|
|
13154 SOAP_FMAC2
|
|
13155 soap_QName2s(struct soap *soap, const char *s)
|
|
13156 { const char *t = NULL;
|
|
13157 if (s)
|
|
13158 { soap->labidx = 0;
|
|
13159 for (;;)
|
|
13160 { size_t n;
|
|
13161 /* skip blanks */
|
|
13162 while (*s && soap_blank((soap_wchar)*s))
|
|
13163 s++;
|
|
13164 if (!*s)
|
|
13165 break;
|
|
13166 /* find next QName */
|
|
13167 n = 1;
|
|
13168 while (s[n] && !soap_blank((soap_wchar)s[n]))
|
|
13169 n++;
|
|
13170 /* normal prefix: pass string as is */
|
|
13171 if (*s != '"')
|
|
13172 {
|
|
13173 #ifndef WITH_LEAN
|
|
13174 if ((soap->mode & SOAP_XML_CANONICAL))
|
|
13175 soap_utilize_ns(soap, s);
|
|
13176 if ((soap->mode & SOAP_XML_DEFAULTNS))
|
|
13177 { const char *r = strchr(s, ':');
|
|
13178 if (r && soap->nlist && !strncmp(soap->nlist->id, s, r-s) && !soap->nlist->id[r-s])
|
|
13179 { n -= r-s + 1;
|
|
13180 s = r + 1;
|
|
13181 }
|
|
13182 }
|
|
13183 #endif
|
|
13184 soap_append_lab(soap, s, n);
|
|
13185 }
|
|
13186 else /* URL-based string prefix */
|
|
13187 { const char *q;
|
|
13188 s++;
|
|
13189 q = strchr(s, '"');
|
|
13190 if (q)
|
|
13191 { struct Namespace *p = soap->local_namespaces;
|
|
13192 if (p)
|
|
13193 { for (; p->id; p++)
|
|
13194 { if (p->ns)
|
|
13195 if (!soap_tag_cmp(s, p->ns))
|
|
13196 break;
|
|
13197 if (p->in)
|
|
13198 if (!soap_tag_cmp(s, p->in))
|
|
13199 break;
|
|
13200 }
|
|
13201 }
|
|
13202 /* URL is in the namespace table? */
|
|
13203 if (p && p->id)
|
|
13204 { const char *r = p->id;
|
|
13205 #ifndef WITH_LEAN
|
|
13206 if ((soap->mode & SOAP_XML_DEFAULTNS) && soap->nlist && !strcmp(soap->nlist->id, r))
|
|
13207 q++;
|
|
13208 else
|
|
13209 #endif
|
|
13210 soap_append_lab(soap, r, strlen(r));
|
|
13211 }
|
|
13212 else /* not in namespace table: create xmlns binding */
|
|
13213 { char *r = soap_strdup(soap, s);
|
|
13214 r[q-s] = '\0';
|
|
13215 #ifdef HAVE_SNPRINTF
|
|
13216 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "xmlns:_%d", soap->idnum++);
|
|
13217 #else
|
|
13218 sprintf(soap->tmpbuf, "xmlns:_%d", soap->idnum++);
|
|
13219 #endif
|
|
13220 soap_set_attr(soap, soap->tmpbuf, r, 1);
|
|
13221 soap_append_lab(soap, soap->tmpbuf + 6, strlen(soap->tmpbuf + 6));
|
|
13222 }
|
|
13223 soap_append_lab(soap, q + 1, n - (q-s) - 1);
|
|
13224 }
|
|
13225 }
|
|
13226 /* advance to next and add spacing */
|
|
13227 s += n;
|
|
13228 if (*s)
|
|
13229 soap_append_lab(soap, " ", 1);
|
|
13230 }
|
|
13231 soap_append_lab(soap, SOAP_STR_EOS, 1);
|
|
13232 t = soap_strdup(soap, soap->labbuf);
|
|
13233 }
|
|
13234 return t;
|
|
13235 }
|
|
13236 #endif
|
|
13237
|
|
13238 /******************************************************************************/
|
|
13239 #ifndef WITH_LEAN
|
|
13240 SOAP_FMAC1
|
|
13241 int
|
|
13242 SOAP_FMAC2
|
|
13243 soap_s2wchar(struct soap *soap, const char *s, wchar_t **t, long minlen, long maxlen)
|
|
13244 { if (s)
|
|
13245 { long l;
|
|
13246 wchar_t *r;
|
|
13247 *t = r = (wchar_t*)soap_malloc(soap, sizeof(wchar_t) * (strlen(s) + 1));
|
|
13248 if (!r)
|
|
13249 return soap->error = SOAP_EOM;
|
|
13250 if (soap->mode & SOAP_ENC_LATIN)
|
|
13251 { while (*s)
|
|
13252 *r++ = (wchar_t)*s++;
|
|
13253 }
|
|
13254 else
|
|
13255 { /* Convert UTF8 to wchar */
|
|
13256 while (*s)
|
|
13257 { register soap_wchar c, c1, c2, c3, c4;
|
|
13258 c = (unsigned char)*s++;
|
|
13259 if (c < 0x80)
|
|
13260 *r++ = (wchar_t)c;
|
|
13261 else
|
|
13262 { c1 = (soap_wchar)*s++ & 0x3F;
|
|
13263 if (c < 0xE0)
|
|
13264 *r++ = (wchar_t)(((soap_wchar)(c & 0x1F) << 6) | c1);
|
|
13265 else
|
|
13266 { c2 = (soap_wchar)*s++ & 0x3F;
|
|
13267 if (c < 0xF0)
|
|
13268 *r++ = (wchar_t)(((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2);
|
|
13269 else
|
|
13270 { c3 = (soap_wchar)*s++ & 0x3F;
|
|
13271 if (c < 0xF8)
|
|
13272 *r++ = (wchar_t)(((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3);
|
|
13273 else
|
|
13274 { c4 = (soap_wchar)*s++ & 0x3F;
|
|
13275 if (c < 0xFC)
|
|
13276 *r++ = (wchar_t)(((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4);
|
|
13277 else
|
|
13278 *r++ = (wchar_t)(((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(*s++ & 0x3F));
|
|
13279 }
|
|
13280 }
|
|
13281 }
|
|
13282 }
|
|
13283 }
|
|
13284 }
|
|
13285 *r = L'\0';
|
|
13286 l = (long)(r - *t);
|
|
13287 if ((maxlen >= 0 && l > maxlen) || l < minlen)
|
|
13288 return soap->error = SOAP_LENGTH;
|
|
13289 }
|
|
13290 return soap->error;
|
|
13291 }
|
|
13292 #endif
|
|
13293
|
|
13294 /******************************************************************************/
|
|
13295 #ifndef WITH_LEAN
|
|
13296 SOAP_FMAC1
|
|
13297 const char*
|
|
13298 SOAP_FMAC2
|
|
13299 soap_wchar2s(struct soap *soap, const wchar_t *s)
|
|
13300 { register soap_wchar c;
|
|
13301 register char *r, *t;
|
|
13302 const wchar_t *q = s;
|
|
13303 size_t n = 0;
|
|
13304 while ((c = *q++))
|
|
13305 { if (c > 0 && c < 0x80)
|
|
13306 n++;
|
|
13307 else
|
|
13308 n += 6;
|
|
13309 }
|
|
13310 r = t = (char*)soap_malloc(soap, n + 1);
|
|
13311 if (r)
|
|
13312 { /* Convert wchar to UTF8 */
|
|
13313 while ((c = *s++))
|
|
13314 { if (c > 0 && c < 0x80)
|
|
13315 *t++ = (char)c;
|
|
13316 else
|
|
13317 { if (c < 0x0800)
|
|
13318 *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
|
|
13319 else
|
|
13320 { if (c < 0x010000)
|
|
13321 *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
|
|
13322 else
|
|
13323 { if (c < 0x200000)
|
|
13324 *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
|
|
13325 else
|
|
13326 { if (c < 0x04000000)
|
|
13327 *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
|
|
13328 else
|
|
13329 { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
|
|
13330 *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
|
|
13331 }
|
|
13332 *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
|
|
13333 }
|
|
13334 *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
|
|
13335 }
|
|
13336 *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
|
|
13337 }
|
|
13338 *t++ = (char)(0x80 | (c & 0x3F));
|
|
13339 }
|
|
13340 }
|
|
13341 *t = '\0';
|
|
13342 }
|
|
13343 return r;
|
|
13344 }
|
|
13345 #endif
|
|
13346
|
|
13347 /******************************************************************************/
|
|
13348 #ifndef PALM_2
|
|
13349 SOAP_FMAC1
|
|
13350 int
|
|
13351 SOAP_FMAC2
|
|
13352 soap_outstring(struct soap *soap, const char *tag, int id, char *const*p, const char *type, int n)
|
|
13353 { id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n);
|
|
13354 if (id < 0)
|
|
13355 return soap->error;
|
|
13356 if (!**p && (soap->mode & SOAP_C_NILSTRING))
|
|
13357 return soap_element_null(soap, tag, id, type);
|
|
13358 if (soap_element_begin_out(soap, tag, id, type)
|
|
13359 || soap_string_out(soap, *p, 0)
|
|
13360 || soap_element_end_out(soap, tag))
|
|
13361 return soap->error;
|
|
13362 return SOAP_OK;
|
|
13363 }
|
|
13364 #endif
|
|
13365
|
|
13366 /******************************************************************************/
|
|
13367 #ifndef PALM_2
|
|
13368 SOAP_FMAC1
|
|
13369 char **
|
|
13370 SOAP_FMAC2
|
|
13371 soap_instring(struct soap *soap, const char *tag, char **p, const char *type, int t, int flag, long minlen, long maxlen)
|
|
13372 { (void)type;
|
|
13373 if (soap_element_begin_in(soap, tag, 1, NULL))
|
|
13374 { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG)
|
|
13375 return NULL;
|
|
13376 soap->error = SOAP_OK;
|
|
13377 }
|
|
13378 if (!p)
|
|
13379 { if (!(p = (char**)soap_malloc(soap, sizeof(char*))))
|
|
13380 return NULL;
|
|
13381 }
|
|
13382 if (soap->null)
|
|
13383 *p = NULL;
|
|
13384 else if (soap->body)
|
|
13385 { *p = soap_string_in(soap, flag, minlen, maxlen);
|
|
13386 if (!*p || !(char*)soap_id_enter(soap, soap->id, *p, t, sizeof(char*), 0, NULL, NULL, NULL))
|
|
13387 return NULL;
|
|
13388 if (!**p && tag && *tag == '-')
|
|
13389 { soap->error = SOAP_NO_TAG;
|
|
13390 return NULL;
|
|
13391 }
|
|
13392 }
|
|
13393 else if (tag && *tag == '-')
|
|
13394 { soap->error = SOAP_NO_TAG;
|
|
13395 return NULL;
|
|
13396 }
|
|
13397 else if (!*soap->href && minlen > 0)
|
|
13398 { soap->error = SOAP_LENGTH;
|
|
13399 return NULL;
|
|
13400 }
|
|
13401 else
|
|
13402 *p = soap_strdup(soap, SOAP_STR_EOS);
|
|
13403 if (*soap->href)
|
|
13404 p = (char**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(char**), 0);
|
|
13405 if (soap->body && soap_element_end_in(soap, tag))
|
|
13406 return NULL;
|
|
13407 return p;
|
|
13408 }
|
|
13409 #endif
|
|
13410
|
|
13411 /******************************************************************************/
|
|
13412 #ifndef WITH_LEANER
|
|
13413 #ifndef PALM_2
|
|
13414 SOAP_FMAC1
|
|
13415 int
|
|
13416 SOAP_FMAC2
|
|
13417 soap_outwstring(struct soap *soap, const char *tag, int id, wchar_t *const*p, const char *type, int n)
|
|
13418 { id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n);
|
|
13419 if (id < 0)
|
|
13420 return soap->error;
|
|
13421 if (!**p && (soap->mode & SOAP_C_NILSTRING))
|
|
13422 return soap_element_null(soap, tag, id, type);
|
|
13423 if (soap_element_begin_out(soap, tag, id, type)
|
|
13424 || soap_wstring_out(soap, *p, 0)
|
|
13425 || soap_element_end_out(soap, tag))
|
|
13426 return soap->error;
|
|
13427 return SOAP_OK;
|
|
13428 }
|
|
13429 #endif
|
|
13430 #endif
|
|
13431
|
|
13432 /******************************************************************************/
|
|
13433 #ifndef WITH_LEANER
|
|
13434 #ifndef PALM_2
|
|
13435 SOAP_FMAC1
|
|
13436 wchar_t **
|
|
13437 SOAP_FMAC2
|
|
13438 soap_inwstring(struct soap *soap, const char *tag, wchar_t **p, const char *type, int t, long minlen, long maxlen)
|
|
13439 { (void)type;
|
|
13440 if (soap_element_begin_in(soap, tag, 1, NULL))
|
|
13441 { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG)
|
|
13442 return NULL;
|
|
13443 soap->error = SOAP_OK;
|
|
13444 }
|
|
13445 if (!p)
|
|
13446 { if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*))))
|
|
13447 return NULL;
|
|
13448 }
|
|
13449 if (soap->body)
|
|
13450 { *p = soap_wstring_in(soap, 1, minlen, maxlen);
|
|
13451 if (!*p || !(wchar_t*)soap_id_enter(soap, soap->id, *p, t, sizeof(wchar_t*), 0, NULL, NULL, NULL))
|
|
13452 return NULL;
|
|
13453 if (!**p && tag && *tag == '-')
|
|
13454 { soap->error = SOAP_NO_TAG;
|
|
13455 return NULL;
|
|
13456 }
|
|
13457 }
|
|
13458 else if (tag && *tag == '-')
|
|
13459 { soap->error = SOAP_NO_TAG;
|
|
13460 return NULL;
|
|
13461 }
|
|
13462 else if (soap->null)
|
|
13463 *p = NULL;
|
|
13464 else
|
|
13465 *p = soap_wstrdup(soap, (wchar_t*)SOAP_STR_EOS);
|
|
13466 if (*soap->href)
|
|
13467 p = (wchar_t**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(wchar_t**), 0);
|
|
13468 if (soap->body && soap_element_end_in(soap, tag))
|
|
13469 return NULL;
|
|
13470 return p;
|
|
13471 }
|
|
13472 #endif
|
|
13473 #endif
|
|
13474
|
|
13475 /******************************************************************************/
|
|
13476 #ifndef WITH_LEAN
|
|
13477 SOAP_FMAC1
|
|
13478 time_t
|
|
13479 SOAP_FMAC2
|
|
13480 soap_timegm(struct tm *T)
|
|
13481 {
|
|
13482 #if defined(HAVE_TIMEGM)
|
|
13483 return timegm(T);
|
|
13484 #else
|
|
13485 time_t t, g, z;
|
|
13486 struct tm tm;
|
|
13487 t = mktime(T);
|
|
13488 if (t == (time_t)-1)
|
|
13489 return (time_t)-1;
|
|
13490 #ifdef HAVE_GMTIME_R
|
|
13491 gmtime_r(&t, &tm);
|
|
13492 #else
|
|
13493 tm = *gmtime(&t);
|
|
13494 #endif
|
|
13495 tm.tm_isdst = 0;
|
|
13496 g = mktime(&tm);
|
|
13497 if (g == (time_t)-1)
|
|
13498 return (time_t)-1;
|
|
13499 z = g - t;
|
|
13500 return t - z;
|
|
13501 #endif
|
|
13502 }
|
|
13503 #endif
|
|
13504
|
|
13505 /******************************************************************************/
|
|
13506 #ifndef WITH_LEAN
|
|
13507 SOAP_FMAC1
|
|
13508 const char*
|
|
13509 SOAP_FMAC2
|
|
13510 soap_dateTime2s(struct soap *soap, time_t n)
|
|
13511 { struct tm T, *pT = &T;
|
|
13512 #if defined(HAVE_GMTIME_R)
|
|
13513 if (gmtime_r(&n, pT))
|
|
13514 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT);
|
|
13515 #elif defined(HAVE_GMTIME)
|
|
13516 if ((pT = gmtime(&n)))
|
|
13517 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT);
|
|
13518 #elif defined(HAVE_TM_GMTOFF) || defined(HAVE_STRUCT_TM_TM_GMTOFF) || defined(HAVE_STRUCT_TM___TM_GMTOFF)
|
|
13519 #if defined(HAVE_LOCALTIME_R)
|
|
13520 if (localtime_r(&n, pT))
|
|
13521 { strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S%z", pT);
|
|
13522 memmove(soap->tmpbuf + 23, soap->tmpbuf + 22, 3); /* 2000-03-01T02:00:00+0300 */
|
|
13523 soap->tmpbuf[22] = ':'; /* 2000-03-01T02:00:00+03:00 */
|
|
13524 }
|
|
13525 #else
|
|
13526 if ((pT = localtime(&n)))
|
|
13527 { strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S%z", pT);
|
|
13528 memmove(soap->tmpbuf + 23, soap->tmpbuf + 22, 3); /* 2000-03-01T02:00:00+0300 */
|
|
13529 soap->tmpbuf[22] = ':'; /* 2000-03-01T02:00:00+03:00 */
|
|
13530 }
|
|
13531 #endif
|
|
13532 #elif defined(HAVE_GETTIMEOFDAY)
|
|
13533 struct timezone tz;
|
|
13534 memset((void*)&tz, 0, sizeof(tz));
|
|
13535 #if defined(HAVE_LOCALTIME_R)
|
|
13536 if (localtime_r(&n, pT))
|
|
13537 { struct timeval tv;
|
|
13538 gettimeofday(&tv, &tz);
|
|
13539 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
|
|
13540 #ifdef HAVE_SNPRINTF
|
|
13541 soap_snprintf(soap->tmpbuf + strlen(soap->tmpbuf), sizeof(soap->tmpbuf) - strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60);
|
|
13542 #else
|
|
13543 sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60);
|
|
13544 #endif
|
|
13545 }
|
|
13546 #else
|
|
13547 if ((pT = localtime(&n)))
|
|
13548 { struct timeval tv;
|
|
13549 gettimeofday(&tv, &tz);
|
|
13550 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
|
|
13551 #ifdef HAVE_SNPRINTF
|
|
13552 soap_snprintf(soap->tmpbuf + strlen(soap->tmpbuf), sizeof(soap->tmpbuf) - strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60);
|
|
13553 #else
|
|
13554 sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60);
|
|
13555 #endif
|
|
13556 }
|
|
13557 #endif
|
|
13558 #elif defined(HAVE_FTIME)
|
|
13559 struct timeb t;
|
|
13560 memset((void*)&t, 0, sizeof(t));
|
|
13561 #if defined(HAVE_LOCALTIME_R)
|
|
13562 if (localtime_r(&n, pT))
|
|
13563 {
|
|
13564 #ifdef __BORLANDC__
|
|
13565 ::ftime(&t);
|
|
13566 #else
|
|
13567 ftime(&t);
|
|
13568 #endif
|
|
13569 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
|
|
13570 #ifdef HAVE_SNPRINTF
|
|
13571 soap_snprintf(soap->tmpbuf + strlen(soap->tmpbuf), sizeof(soap->tmpbuf) - strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60);
|
|
13572 #else
|
|
13573 sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60);
|
|
13574 #endif
|
|
13575 }
|
|
13576 #else
|
|
13577 if ((pT = localtime(&n)))
|
|
13578 {
|
|
13579 #ifdef __BORLANDC__
|
|
13580 ::ftime(&t);
|
|
13581 #else
|
|
13582 ftime(&t);
|
|
13583 #endif
|
|
13584 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
|
|
13585 #ifdef HAVE_SNPRINTF
|
|
13586 soap_snprintf(soap->tmpbuf + strlen(soap->tmpbuf), sizeof(soap->tmpbuf) - strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60);
|
|
13587 #else
|
|
13588 sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60);
|
|
13589 #endif
|
|
13590 }
|
|
13591 #endif
|
|
13592 #elif defined(HAVE_LOCALTIME_R)
|
|
13593 if (localtime_r(&n, pT))
|
|
13594 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
|
|
13595 #else
|
|
13596 if ((pT = localtime(&n)))
|
|
13597 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
|
|
13598 #endif
|
|
13599 else
|
|
13600 strcpy(soap->tmpbuf, "1969-12-31T23:59:59Z");
|
|
13601 return soap->tmpbuf;
|
|
13602 }
|
|
13603 #endif
|
|
13604
|
|
13605 /******************************************************************************/
|
|
13606 #ifndef WITH_LEAN
|
|
13607 SOAP_FMAC1
|
|
13608 int
|
|
13609 SOAP_FMAC2
|
|
13610 soap_outdateTime(struct soap *soap, const char *tag, int id, const time_t *p, const char *type, int n)
|
|
13611 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
|
|
13612 || soap_string_out(soap, soap_dateTime2s(soap, *p), 0))
|
|
13613 return soap->error;
|
|
13614 return soap_element_end_out(soap, tag);
|
|
13615 }
|
|
13616 #endif
|
|
13617
|
|
13618 /******************************************************************************/
|
|
13619 #ifndef WITH_LEAN
|
|
13620 SOAP_FMAC1
|
|
13621 int
|
|
13622 SOAP_FMAC2
|
|
13623 soap_s2dateTime(struct soap *soap, const char *s, time_t *p)
|
|
13624 { if (s)
|
|
13625 { char zone[32];
|
|
13626 struct tm T;
|
|
13627 const char *t;
|
|
13628 *zone = '\0';
|
|
13629 memset((void*)&T, 0, sizeof(T));
|
|
13630 if (strchr(s, '-'))
|
|
13631 t = "%d-%d-%dT%d:%d:%d%31s";
|
|
13632 else if (strchr(s, ':'))
|
|
13633 t = "%4d%2d%2dT%d:%d:%d%31s";
|
|
13634 else /* parse non-XSD-standard alternative ISO 8601 format */
|
|
13635 t = "%4d%2d%2dT%2d%2d%2d%31s";
|
|
13636 if (sscanf(s, t, &T.tm_year, &T.tm_mon, &T.tm_mday, &T.tm_hour, &T.tm_min, &T.tm_sec, zone) < 6)
|
|
13637 return soap->error = SOAP_TYPE;
|
|
13638 if (T.tm_year == 1)
|
|
13639 T.tm_year = 70;
|
|
13640 else
|
|
13641 T.tm_year -= 1900;
|
|
13642 T.tm_mon--;
|
|
13643 if (*zone == '.')
|
|
13644 { for (s = zone + 1; *s; s++)
|
|
13645 if (*s < '0' || *s > '9')
|
|
13646 break;
|
|
13647 }
|
|
13648 else
|
|
13649 s = zone;
|
|
13650 if (*s)
|
|
13651 {
|
|
13652 #ifndef WITH_NOZONE
|
|
13653 if (*s == '+' || *s == '-')
|
|
13654 { int h = 0, m = 0;
|
|
13655 if (s[3] == ':')
|
|
13656 { /* +hh:mm */
|
|
13657 sscanf(s, "%d:%d", &h, &m);
|
|
13658 if (h < 0)
|
|
13659 m = -m;
|
|
13660 }
|
|
13661 else /* +hhmm */
|
|
13662 { m = (int)soap_strtol(s, NULL, 10);
|
|
13663 h = m / 100;
|
|
13664 m = m % 100;
|
|
13665 }
|
|
13666 T.tm_min -= m;
|
|
13667 T.tm_hour -= h;
|
|
13668 /* put hour and min in range */
|
|
13669 T.tm_hour += T.tm_min / 60;
|
|
13670 T.tm_min %= 60;
|
|
13671 if (T.tm_min < 0)
|
|
13672 { T.tm_min += 60;
|
|
13673 T.tm_hour--;
|
|
13674 }
|
|
13675 T.tm_mday += T.tm_hour / 24;
|
|
13676 T.tm_hour %= 24;
|
|
13677 if (T.tm_hour < 0)
|
|
13678 { T.tm_hour += 24;
|
|
13679 T.tm_mday--;
|
|
13680 }
|
|
13681 /* note: day of the month may be out of range, timegm() handles it */
|
|
13682 }
|
|
13683 #endif
|
|
13684 *p = soap_timegm(&T);
|
|
13685 }
|
|
13686 else /* no UTC or timezone, so assume we got a localtime */
|
|
13687 { T.tm_isdst = -1;
|
|
13688 *p = mktime(&T);
|
|
13689 }
|
|
13690 }
|
|
13691 return soap->error;
|
|
13692 }
|
|
13693 #endif
|
|
13694
|
|
13695 /******************************************************************************/
|
|
13696 #ifndef WITH_LEAN
|
|
13697 SOAP_FMAC1
|
|
13698 time_t *
|
|
13699 SOAP_FMAC2
|
|
13700 soap_indateTime(struct soap *soap, const char *tag, time_t *p, const char *type, int t)
|
|
13701 { if (soap_element_begin_in(soap, tag, 0, NULL))
|
|
13702 return NULL;
|
|
13703 if (*soap->type
|
|
13704 && soap_match_tag(soap, soap->type, type)
|
|
13705 && soap_match_tag(soap, soap->type, ":dateTime"))
|
|
13706 { soap->error = SOAP_TYPE;
|
|
13707 soap_revert(soap);
|
|
13708 return NULL;
|
|
13709 }
|
|
13710 p = (time_t*)soap_id_enter(soap, soap->id, p, t, sizeof(time_t), 0, NULL, NULL, NULL);
|
|
13711 if (*soap->href)
|
|
13712 p = (time_t*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(time_t), 0, NULL);
|
|
13713 else if (p)
|
|
13714 { if (soap_s2dateTime(soap, soap_value(soap), p))
|
|
13715 return NULL;
|
|
13716 }
|
|
13717 if (soap->body && soap_element_end_in(soap, tag))
|
|
13718 return NULL;
|
|
13719 return p;
|
|
13720 }
|
|
13721 #endif
|
|
13722
|
|
13723 /******************************************************************************/
|
|
13724 #ifndef PALM_2
|
|
13725 SOAP_FMAC1
|
|
13726 int
|
|
13727 SOAP_FMAC2
|
|
13728 soap_outliteral(struct soap *soap, const char *tag, char *const*p, const char *type)
|
|
13729 { int i;
|
|
13730 const char *t = NULL;
|
|
13731 if (tag && *tag != '-')
|
|
13732 { if (soap->local_namespaces && (t = strchr(tag, ':')))
|
|
13733 { size_t n = t - tag;
|
|
13734 if (n >= sizeof(soap->tmpbuf))
|
|
13735 n = sizeof(soap->tmpbuf) - 1;
|
|
13736 strncpy(soap->tmpbuf, tag, n);
|
|
13737 soap->tmpbuf[n] = '\0';
|
|
13738 for (i = 0; soap->local_namespaces[i].id; i++)
|
|
13739 if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id))
|
|
13740 break;
|
|
13741 t++;
|
|
13742 if (soap_element(soap, t, 0, type)
|
|
13743 || soap_attribute(soap, "xmlns", soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS)
|
|
13744 || soap_element_start_end_out(soap, NULL))
|
|
13745 return soap->error;
|
|
13746 }
|
|
13747 else
|
|
13748 { t = tag;
|
|
13749 if (soap_element_begin_out(soap, t, 0, type))
|
|
13750 return soap->error;
|
|
13751 }
|
|
13752 }
|
|
13753 if (p && *p)
|
|
13754 { if (soap_send(soap, *p)) /* send as-is */
|
|
13755 return soap->error;
|
|
13756 }
|
|
13757 if (t)
|
|
13758 return soap_element_end_out(soap, t);
|
|
13759 return SOAP_OK;
|
|
13760 }
|
|
13761 #endif
|
|
13762
|
|
13763 /******************************************************************************/
|
|
13764 #ifndef PALM_2
|
|
13765 SOAP_FMAC1
|
|
13766 char **
|
|
13767 SOAP_FMAC2
|
|
13768 soap_inliteral(struct soap *soap, const char *tag, char **p)
|
|
13769 { if (soap_element_begin_in(soap, tag, 1, NULL))
|
|
13770 { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT)
|
|
13771 return NULL;
|
|
13772 soap->error = SOAP_OK;
|
|
13773 }
|
|
13774 if (!p)
|
|
13775 { if (!(p = (char**)soap_malloc(soap, sizeof(char*))))
|
|
13776 return NULL;
|
|
13777 }
|
|
13778 if (soap->body || (tag && *tag == '-'))
|
|
13779 { *p = soap_string_in(soap, 0, -1, -1);
|
|
13780 if (!*p)
|
|
13781 return NULL;
|
|
13782 if (!**p && tag && *tag == '-')
|
|
13783 { soap->error = SOAP_NO_TAG;
|
|
13784 return NULL;
|
|
13785 }
|
|
13786 }
|
|
13787 else if (soap->null)
|
|
13788 *p = NULL;
|
|
13789 else
|
|
13790 *p = soap_strdup(soap, SOAP_STR_EOS);
|
|
13791 if (soap->body && soap_element_end_in(soap, tag))
|
|
13792 return NULL;
|
|
13793 return p;
|
|
13794 }
|
|
13795 #endif
|
|
13796
|
|
13797 /******************************************************************************/
|
|
13798 #ifndef WITH_LEANER
|
|
13799 #ifndef PALM_2
|
|
13800 SOAP_FMAC1
|
|
13801 int
|
|
13802 SOAP_FMAC2
|
|
13803 soap_outwliteral(struct soap *soap, const char *tag, wchar_t *const*p, const char *type)
|
|
13804 { int i;
|
|
13805 const char *t = NULL;
|
|
13806 if (tag && *tag != '-')
|
|
13807 { if (soap->local_namespaces && (t = strchr(tag, ':')))
|
|
13808 { size_t n = t - tag;
|
|
13809 if (n >= sizeof(soap->tmpbuf))
|
|
13810 n = sizeof(soap->tmpbuf) - 1;
|
|
13811 strncpy(soap->tmpbuf, tag, n);
|
|
13812 soap->tmpbuf[n] = '\0';
|
|
13813 for (i = 0; soap->local_namespaces[i].id; i++)
|
|
13814 if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id))
|
|
13815 break;
|
|
13816 t++;
|
|
13817 if (soap_element(soap, t, 0, type)
|
|
13818 || soap_attribute(soap, "xmlns", soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS)
|
|
13819 || soap_element_start_end_out(soap, NULL))
|
|
13820 return soap->error;
|
|
13821 }
|
|
13822 else
|
|
13823 { t = tag;
|
|
13824 if (soap_element_begin_out(soap, t, 0, type))
|
|
13825 return soap->error;
|
|
13826 }
|
|
13827 }
|
|
13828 if (p)
|
|
13829 { wchar_t c;
|
|
13830 const wchar_t *s = *p;
|
|
13831 while ((c = *s++))
|
|
13832 { if (soap_pututf8(soap, (unsigned long)c)) /* send as-is in UTF8 */
|
|
13833 return soap->error;
|
|
13834 }
|
|
13835 }
|
|
13836 if (t)
|
|
13837 return soap_element_end_out(soap, t);
|
|
13838 return SOAP_OK;
|
|
13839 }
|
|
13840 #endif
|
|
13841 #endif
|
|
13842
|
|
13843 /******************************************************************************/
|
|
13844 #ifndef WITH_LEANER
|
|
13845 #ifndef PALM_2
|
|
13846 SOAP_FMAC1
|
|
13847 wchar_t **
|
|
13848 SOAP_FMAC2
|
|
13849 soap_inwliteral(struct soap *soap, const char *tag, wchar_t **p)
|
|
13850 { if (soap_element_begin_in(soap, tag, 1, NULL))
|
|
13851 { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT)
|
|
13852 return NULL;
|
|
13853 soap->error = SOAP_OK;
|
|
13854 }
|
|
13855 if (!p)
|
|
13856 { if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*))))
|
|
13857 return NULL;
|
|
13858 }
|
|
13859 if (soap->body)
|
|
13860 { *p = soap_wstring_in(soap, 0, -1, -1);
|
|
13861 if (!*p)
|
|
13862 return NULL;
|
|
13863 if (!**p && tag && *tag == '-')
|
|
13864 { soap->error = SOAP_NO_TAG;
|
|
13865 return NULL;
|
|
13866 }
|
|
13867 }
|
|
13868 else if (tag && *tag == '-')
|
|
13869 { soap->error = SOAP_NO_TAG;
|
|
13870 return NULL;
|
|
13871 }
|
|
13872 else if (soap->null)
|
|
13873 *p = NULL;
|
|
13874 else
|
|
13875 *p = soap_wstrdup(soap, (wchar_t*)SOAP_STR_EOS);
|
|
13876 if (soap->body && soap_element_end_in(soap, tag))
|
|
13877 return NULL;
|
|
13878 return p;
|
|
13879 }
|
|
13880 #endif
|
|
13881 #endif
|
|
13882
|
|
13883 /******************************************************************************/
|
|
13884 #ifndef PALM_2
|
|
13885 SOAP_FMAC1
|
|
13886 const char *
|
|
13887 SOAP_FMAC2
|
|
13888 soap_value(struct soap *soap)
|
|
13889 { register size_t i;
|
|
13890 register soap_wchar c = 0;
|
|
13891 register char *s = soap->tmpbuf;
|
|
13892 if (!soap->body)
|
|
13893 return SOAP_STR_EOS;
|
|
13894 do c = soap_get(soap);
|
|
13895 while (soap_blank(c));
|
|
13896 for (i = 0; i < sizeof(soap->tmpbuf) - 1; i++)
|
|
13897 { if (c == SOAP_TT || c == SOAP_LT || (int)c == EOF)
|
|
13898 break;
|
|
13899 *s++ = (char)c;
|
|
13900 c = soap_get(soap);
|
|
13901 }
|
|
13902 for (s--; i > 0; i--, s--)
|
|
13903 { if (!soap_blank((soap_wchar)*s))
|
|
13904 break;
|
|
13905 }
|
|
13906 s[1] = '\0';
|
|
13907 soap->tmpbuf[sizeof(soap->tmpbuf) - 1] = '\0'; /* appease */
|
|
13908 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element content value='%s'\n", soap->tmpbuf));
|
|
13909 if (c == SOAP_TT || c == SOAP_LT || (int)c == EOF)
|
|
13910 soap_unget(soap, c);
|
|
13911 else if (soap->mode & SOAP_XML_STRICT)
|
|
13912 { soap->error = SOAP_LENGTH;
|
|
13913 return NULL;
|
|
13914 }
|
|
13915 #ifdef WITH_DOM
|
|
13916 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
|
|
13917 soap->dom->data = soap_strdup(soap, soap->tmpbuf);
|
|
13918 #endif
|
|
13919 return soap->tmpbuf; /* return non-null pointer */
|
|
13920 }
|
|
13921 #endif
|
|
13922
|
|
13923 /******************************************************************************/
|
|
13924 #if !defined(WITH_LEANER) || !defined(WITH_NOHTTP)
|
|
13925 #ifndef PALM_2
|
|
13926 SOAP_FMAC1
|
|
13927 int
|
|
13928 SOAP_FMAC2
|
|
13929 soap_getline(struct soap *soap, char *s, int len)
|
|
13930 { int i = len;
|
|
13931 soap_wchar c = 0;
|
|
13932 for (;;)
|
|
13933 { while (--i > 0)
|
|
13934 { c = soap_getchar(soap);
|
|
13935 if (c == '\r' || c == '\n')
|
|
13936 break;
|
|
13937 if ((int)c == EOF)
|
|
13938 return soap->error = SOAP_CHK_EOF;
|
|
13939 *s++ = (char)c;
|
|
13940 }
|
|
13941 *s = '\0';
|
|
13942 if (c != '\n')
|
|
13943 c = soap_getchar(soap); /* got \r or something else, now get \n */
|
|
13944 if (c == '\n')
|
|
13945 { if (i + 1 == len) /* empty line: end of HTTP/MIME header */
|
|
13946 break;
|
|
13947 c = soap_get0(soap);
|
|
13948 if (c != ' ' && c != '\t') /* HTTP line continuation? */
|
|
13949 break;
|
|
13950 }
|
|
13951 else if ((int)c == EOF)
|
|
13952 return soap->error = SOAP_CHK_EOF;
|
|
13953 if (i <= 0)
|
|
13954 return soap->error = SOAP_HDR;
|
|
13955 }
|
|
13956 return SOAP_OK;
|
|
13957 }
|
|
13958 #endif
|
|
13959 #endif
|
|
13960
|
|
13961 /******************************************************************************/
|
|
13962 #ifndef PALM_1
|
|
13963 static size_t
|
|
13964 soap_count_attachments(struct soap *soap)
|
|
13965 {
|
|
13966 #ifndef WITH_LEANER
|
|
13967 register struct soap_multipart *content;
|
|
13968 register size_t count = soap->count;
|
|
13969 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the message size with attachments, current count=%lu\n", (unsigned long)count));
|
|
13970 if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
|
|
13971 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of DIME attachments\n"));
|
|
13972 for (content = soap->dime.first; content; content = content->next)
|
|
13973 { count += 12 + ((content->size+3)&(~3));
|
|
13974 if (content->id)
|
|
13975 count += ((strlen(content->id)+3)&(~3));
|
|
13976 if (content->type)
|
|
13977 count += ((strlen(content->type)+3)&(~3));
|
|
13978 if (content->options)
|
|
13979 count += ((((unsigned char)content->options[2] << 8) | ((unsigned char)content->options[3]))+7)&(~3);
|
|
13980 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of DIME attachment content is %lu bytes\n", (unsigned long)content->size));
|
|
13981 }
|
|
13982 }
|
|
13983 if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary)
|
|
13984 { register size_t n = strlen(soap->mime.boundary);
|
|
13985 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of MIME attachments\n"));
|
|
13986 for (content = soap->mime.first; content; content = content->next)
|
|
13987 { register const char *s;
|
|
13988 /* count \r\n--boundary\r\n */
|
|
13989 count += 6 + n;
|
|
13990 /* count Content-Type: ...\r\n */
|
|
13991 if (content->type)
|
|
13992 count += 16 + strlen(content->type);
|
|
13993 /* count Content-Transfer-Encoding: ...\r\n */
|
|
13994 s = soap_code_str(mime_codes, content->encoding);
|
|
13995 if (s)
|
|
13996 count += 29 + strlen(s);
|
|
13997 /* count Content-ID: ...\r\n */
|
|
13998 if (content->id)
|
|
13999 count += 14 + strlen(content->id);
|
|
14000 /* count Content-Location: ...\r\n */
|
|
14001 if (content->location)
|
|
14002 count += 20 + strlen(content->location);
|
|
14003 /* count Content-Description: ...\r\n */
|
|
14004 if (content->description)
|
|
14005 count += 23 + strlen(content->description);
|
|
14006 /* count \r\n...content */
|
|
14007 count += 2 + content->size;
|
|
14008 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of MIME attachment content is %lu bytes\n", (unsigned long)content->size));
|
|
14009 }
|
|
14010 /* count \r\n--boundary-- */
|
|
14011 count += 6 + n;
|
|
14012 }
|
|
14013 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New count=%lu\n", (unsigned long)count));
|
|
14014 return count;
|
|
14015 #else
|
|
14016 return soap->count;
|
|
14017 #endif
|
|
14018 }
|
|
14019 #endif
|
|
14020
|
|
14021 /******************************************************************************/
|
|
14022 #ifndef WITH_LEANER
|
|
14023 #ifndef PALM_1
|
|
14024 static int
|
|
14025 soap_putdimefield(struct soap *soap, const char *s, size_t n)
|
|
14026 { if (soap_send_raw(soap, s, n))
|
|
14027 return soap->error;
|
|
14028 return soap_send_raw(soap, SOAP_STR_PADDING, -(long)n&3);
|
|
14029 }
|
|
14030 #endif
|
|
14031 #endif
|
|
14032
|
|
14033 /******************************************************************************/
|
|
14034 #ifndef WITH_LEANER
|
|
14035 #ifndef PALM_1
|
|
14036 SOAP_FMAC1
|
|
14037 char *
|
|
14038 SOAP_FMAC2
|
|
14039 soap_dime_option(struct soap *soap, unsigned short optype, const char *option)
|
|
14040 { size_t n;
|
|
14041 char *s = NULL;
|
|
14042 if (option)
|
|
14043 { n = strlen(option);
|
|
14044 s = (char*)soap_malloc(soap, n + 5);
|
|
14045 if (s)
|
|
14046 { s[0] = (char)(optype >> 8);
|
|
14047 s[1] = (char)(optype & 0xFF);
|
|
14048 s[2] = (char)(n >> 8);
|
|
14049 s[3] = (char)(n & 0xFF);
|
|
14050 strcpy(s + 4, option);
|
|
14051 }
|
|
14052 }
|
|
14053 return s;
|
|
14054 }
|
|
14055 #endif
|
|
14056 #endif
|
|
14057
|
|
14058 /******************************************************************************/
|
|
14059 #ifndef WITH_LEANER
|
|
14060 #ifndef PALM_1
|
|
14061 SOAP_FMAC1
|
|
14062 int
|
|
14063 SOAP_FMAC2
|
|
14064 soap_putdimehdr(struct soap *soap)
|
|
14065 { unsigned char tmp[12];
|
|
14066 size_t optlen = 0, idlen = 0, typelen = 0;
|
|
14067 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Put DIME header id='%s'\n", soap->dime.id ? soap->dime.id : SOAP_STR_EOS));
|
|
14068 if (soap->dime.options)
|
|
14069 optlen = (((unsigned char)soap->dime.options[2] << 8) | ((unsigned char)soap->dime.options[3])) + 4;
|
|
14070 if (soap->dime.id)
|
|
14071 { idlen = strlen(soap->dime.id);
|
|
14072 if (idlen > 0x0000FFFF)
|
|
14073 idlen = 0x0000FFFF;
|
|
14074 }
|
|
14075 if (soap->dime.type)
|
|
14076 { typelen = strlen(soap->dime.type);
|
|
14077 if (typelen > 0x0000FFFF)
|
|
14078 typelen = 0x0000FFFF;
|
|
14079 }
|
|
14080 tmp[0] = SOAP_DIME_VERSION | (soap->dime.flags & 0x7);
|
|
14081 tmp[1] = soap->dime.flags & 0xF0;
|
|
14082 tmp[2] = (char)(optlen >> 8);
|
|
14083 tmp[3] = (char)(optlen & 0xFF);
|
|
14084 tmp[4] = (char)(idlen >> 8);
|
|
14085 tmp[5] = (char)(idlen & 0xFF);
|
|
14086 tmp[6] = (char)(typelen >> 8);
|
|
14087 tmp[7] = (char)(typelen & 0xFF);
|
|
14088 tmp[8] = (char)(soap->dime.size >> 24);
|
|
14089 tmp[9] = (char)((soap->dime.size >> 16) & 0xFF);
|
|
14090 tmp[10] = (char)((soap->dime.size >> 8) & 0xFF);
|
|
14091 tmp[11] = (char)(soap->dime.size & 0xFF);
|
|
14092 if (soap_send_raw(soap, (char*)tmp, 12)
|
|
14093 || soap_putdimefield(soap, soap->dime.options, optlen)
|
|
14094 || soap_putdimefield(soap, soap->dime.id, idlen)
|
|
14095 || soap_putdimefield(soap, soap->dime.type, typelen))
|
|
14096 return soap->error;
|
|
14097 return SOAP_OK;
|
|
14098 }
|
|
14099 #endif
|
|
14100 #endif
|
|
14101
|
|
14102 /******************************************************************************/
|
|
14103 #ifndef WITH_LEANER
|
|
14104 #ifndef PALM_1
|
|
14105 SOAP_FMAC1
|
|
14106 int
|
|
14107 SOAP_FMAC2
|
|
14108 soap_putdime(struct soap *soap)
|
|
14109 { struct soap_multipart *content;
|
|
14110 if (!(soap->mode & SOAP_ENC_DIME))
|
|
14111 return SOAP_OK;
|
|
14112 for (content = soap->dime.first; content; content = content->next)
|
|
14113 { void *handle;
|
|
14114 soap->dime.size = content->size;
|
|
14115 soap->dime.id = content->id;
|
|
14116 soap->dime.type = content->type;
|
|
14117 soap->dime.options = content->options;
|
|
14118 soap->dime.flags = SOAP_DIME_VERSION | SOAP_DIME_MEDIA;
|
|
14119 if (soap->fdimereadopen && ((handle = soap->fdimereadopen(soap, (void*)content->ptr, content->id, content->type, content->options)) || soap->error))
|
|
14120 { size_t size = content->size;
|
|
14121 if (!handle)
|
|
14122 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadopen failed\n"));
|
|
14123 return soap->error;
|
|
14124 }
|
|
14125 if (!size && ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE))
|
|
14126 { size_t chunksize = sizeof(soap->tmpbuf);
|
|
14127 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming DIME\n"));
|
|
14128 do
|
|
14129 { size = soap->fdimeread(soap, handle, soap->tmpbuf, chunksize);
|
|
14130 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread returned %lu bytes\n", (unsigned long)size));
|
|
14131 if (size < chunksize)
|
|
14132 { soap->dime.flags &= ~SOAP_DIME_CF;
|
|
14133 if (!content->next)
|
|
14134 soap->dime.flags |= SOAP_DIME_ME;
|
|
14135 }
|
|
14136 else
|
|
14137 soap->dime.flags |= SOAP_DIME_CF;
|
|
14138 soap->dime.size = size;
|
|
14139 if (soap_putdimehdr(soap)
|
|
14140 || soap_putdimefield(soap, soap->tmpbuf, size))
|
|
14141 break;
|
|
14142 if (soap->dime.id)
|
|
14143 { soap->dime.flags &= ~(SOAP_DIME_MB | SOAP_DIME_MEDIA);
|
|
14144 soap->dime.id = NULL;
|
|
14145 soap->dime.type = NULL;
|
|
14146 soap->dime.options = NULL;
|
|
14147 }
|
|
14148 } while (size >= chunksize);
|
|
14149 }
|
|
14150 else
|
|
14151 { if (!content->next)
|
|
14152 soap->dime.flags |= SOAP_DIME_ME;
|
|
14153 if (soap_putdimehdr(soap))
|
|
14154 return soap->error;
|
|
14155 do
|
|
14156 { size_t bufsize;
|
|
14157 if (size < sizeof(soap->tmpbuf))
|
|
14158 bufsize = size;
|
|
14159 else
|
|
14160 bufsize = sizeof(soap->tmpbuf);
|
|
14161 if (!(bufsize = soap->fdimeread(soap, handle, soap->tmpbuf, bufsize)))
|
|
14162 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size));
|
|
14163 soap->error = SOAP_CHK_EOF;
|
|
14164 break;
|
|
14165 }
|
|
14166 if (soap_send_raw(soap, soap->tmpbuf, bufsize))
|
|
14167 break;
|
|
14168 size -= bufsize;
|
|
14169 } while (size);
|
|
14170 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n"));
|
|
14171 soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3);
|
|
14172 }
|
|
14173 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n"));
|
|
14174 if (soap->fdimereadclose)
|
|
14175 soap->fdimereadclose(soap, handle);
|
|
14176 }
|
|
14177 else
|
|
14178 { if (!content->next)
|
|
14179 soap->dime.flags |= SOAP_DIME_ME;
|
|
14180 if (soap_putdimehdr(soap)
|
|
14181 || soap_putdimefield(soap, (char*)content->ptr, content->size))
|
|
14182 return soap->error;
|
|
14183 }
|
|
14184 }
|
|
14185 return SOAP_OK;
|
|
14186 }
|
|
14187 #endif
|
|
14188 #endif
|
|
14189
|
|
14190 /******************************************************************************/
|
|
14191 #ifndef WITH_LEANER
|
|
14192 #ifndef PALM_1
|
|
14193 static char *
|
|
14194 soap_getdimefield(struct soap *soap, size_t n)
|
|
14195 { register soap_wchar c;
|
|
14196 register size_t i;
|
|
14197 register char *s;
|
|
14198 register char *p = NULL;
|
|
14199 if (n)
|
|
14200 { p = (char*)soap_malloc(soap, n + 1);
|
|
14201 if (p)
|
|
14202 { s = p;
|
|
14203 for (i = n; i > 0; i--)
|
|
14204 { if ((int)(c = soap_get1(soap)) == EOF)
|
|
14205 { soap->error = SOAP_CHK_EOF;
|
|
14206 return NULL;
|
|
14207 }
|
|
14208 *s++ = (char)c;
|
|
14209 }
|
|
14210 *s = '\0';
|
|
14211 if ((soap->error = soap_move(soap, (size_t)(-(long)n&3))))
|
|
14212 return NULL;
|
|
14213 }
|
|
14214 else
|
|
14215 soap->error = SOAP_EOM;
|
|
14216 }
|
|
14217 return p;
|
|
14218 }
|
|
14219 #endif
|
|
14220 #endif
|
|
14221
|
|
14222 /******************************************************************************/
|
|
14223 #ifndef WITH_LEANER
|
|
14224 #ifndef PALM_1
|
|
14225 SOAP_FMAC1
|
|
14226 int
|
|
14227 SOAP_FMAC2
|
|
14228 soap_getdimehdr(struct soap *soap)
|
|
14229 { register soap_wchar c;
|
|
14230 register char *s;
|
|
14231 register int i;
|
|
14232 unsigned char tmp[12];
|
|
14233 size_t optlen, idlen, typelen;
|
|
14234 if (!(soap->mode & SOAP_ENC_DIME))
|
|
14235 return soap->error = SOAP_DIME_END;
|
|
14236 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME header\n"));
|
|
14237 if (soap->dime.buflen || soap->dime.chunksize)
|
|
14238 { if (soap_move(soap, soap->dime.size - soap_tell(soap)))
|
|
14239 return soap->error = SOAP_CHK_EOF;
|
|
14240 soap_unget(soap, soap_getchar(soap)); /* skip padding and get hdr */
|
|
14241 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... From chunked\n"));
|
|
14242 return SOAP_OK;
|
|
14243 }
|
|
14244 s = (char*)tmp;
|
|
14245 for (i = 12; i > 0; i--)
|
|
14246 { if ((int)(c = soap_getchar(soap)) == EOF)
|
|
14247 return soap->error = SOAP_CHK_EOF;
|
|
14248 *s++ = (char)c;
|
|
14249 }
|
|
14250 if ((tmp[0] & 0xF8) != SOAP_DIME_VERSION)
|
|
14251 return soap->error = SOAP_DIME_MISMATCH;
|
|
14252 soap->dime.flags = (tmp[0] & 0x7) | (tmp[1] & 0xF0);
|
|
14253 optlen = (tmp[2] << 8) | tmp[3];
|
|
14254 idlen = (tmp[4] << 8) | tmp[5];
|
|
14255 typelen = (tmp[6] << 8) | tmp[7];
|
|
14256 soap->dime.size = ((size_t)tmp[8] << 24) | ((size_t)tmp[9] << 16) | ((size_t)tmp[10] << 8) | ((size_t)tmp[11]);
|
|
14257 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME size=%lu flags=0x%X\n", (unsigned long)soap->dime.size, soap->dime.flags));
|
|
14258 if (!(soap->dime.options = soap_getdimefield(soap, optlen)) && soap->error)
|
|
14259 return soap->error;
|
|
14260 if (!(soap->dime.id = soap_getdimefield(soap, idlen)) && soap->error)
|
|
14261 return soap->error;
|
|
14262 if (!(soap->dime.type = soap_getdimefield(soap, typelen)) && soap->error)
|
|
14263 return soap->error;
|
|
14264 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME id='%s', type='%s', options='%s'\n", soap->dime.id ? soap->dime.id : SOAP_STR_EOS, soap->dime.type ? soap->dime.type : "", soap->dime.options ? soap->dime.options+4 : SOAP_STR_EOS));
|
|
14265 if (soap->dime.flags & SOAP_DIME_ME)
|
|
14266 soap->mode &= ~SOAP_ENC_DIME;
|
|
14267 return SOAP_OK;
|
|
14268 }
|
|
14269 #endif
|
|
14270 #endif
|
|
14271
|
|
14272 /******************************************************************************/
|
|
14273 #ifndef WITH_LEANER
|
|
14274 #ifndef PALM_1
|
|
14275 SOAP_FMAC1
|
|
14276 int
|
|
14277 SOAP_FMAC2
|
|
14278 soap_getdime(struct soap *soap)
|
|
14279 { while (soap->dime.flags & SOAP_DIME_CF)
|
|
14280 { if (soap_getdimehdr(soap))
|
|
14281 return soap->error;
|
|
14282 if (soap_move(soap, soap->dime.size))
|
|
14283 return soap->error = SOAP_EOF;
|
|
14284 }
|
|
14285 if (soap_move(soap, (size_t)(((soap->dime.size+3)&(~3)) - soap_tell(soap))))
|
|
14286 return soap->error = SOAP_EOF;
|
|
14287 for (;;)
|
|
14288 { register struct soap_multipart *content;
|
|
14289 if (soap_getdimehdr(soap))
|
|
14290 break;
|
|
14291 if (soap->fdimewriteopen && ((soap->dime.ptr = (char*)soap->fdimewriteopen(soap, soap->dime.id, soap->dime.type, soap->dime.options)) || soap->error))
|
|
14292 { const char *id, *type, *options;
|
|
14293 size_t size, n;
|
|
14294 if (!soap->dime.ptr)
|
|
14295 return soap->error;
|
|
14296 id = soap->dime.id;
|
|
14297 type = soap->dime.type;
|
|
14298 options = soap->dime.options;
|
|
14299 for (;;)
|
|
14300 { size = soap->dime.size;
|
|
14301 for (;;)
|
|
14302 { n = soap->buflen - soap->bufidx;
|
|
14303 if (size < n)
|
|
14304 n = size;
|
|
14305 if ((soap->error = soap->fdimewrite(soap, (void*)soap->dime.ptr, soap->buf + soap->bufidx, n)))
|
|
14306 break;
|
|
14307 size -= n;
|
|
14308 if (!size)
|
|
14309 { soap->bufidx += n;
|
|
14310 break;
|
|
14311 }
|
|
14312 if (soap_recv(soap))
|
|
14313 { soap->error = SOAP_EOF;
|
|
14314 goto end;
|
|
14315 }
|
|
14316 }
|
|
14317 if (soap_move(soap, (size_t)(-(long)soap->dime.size&3)))
|
|
14318 { soap->error = SOAP_EOF;
|
|
14319 break;
|
|
14320 }
|
|
14321 if (!(soap->dime.flags & SOAP_DIME_CF))
|
|
14322 break;
|
|
14323 if (soap_getdimehdr(soap))
|
|
14324 break;
|
|
14325 }
|
|
14326 end:
|
|
14327 if (soap->fdimewriteclose)
|
|
14328 soap->fdimewriteclose(soap, (void*)soap->dime.ptr);
|
|
14329 soap->dime.size = 0;
|
|
14330 soap->dime.id = id;
|
|
14331 soap->dime.type = type;
|
|
14332 soap->dime.options = options;
|
|
14333 }
|
|
14334 else if (soap->dime.flags & SOAP_DIME_CF)
|
|
14335 { const char *id, *type, *options;
|
|
14336 id = soap->dime.id;
|
|
14337 type = soap->dime.type;
|
|
14338 options = soap->dime.options;
|
|
14339 if (soap_new_block(soap) == NULL)
|
|
14340 return SOAP_EOM;
|
|
14341 for (;;)
|
|
14342 { register soap_wchar c;
|
|
14343 register size_t i;
|
|
14344 register char *s;
|
|
14345 if (soap->dime.size > SOAP_MAXDIMESIZE)
|
|
14346 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME size=%lu exceeds SOAP_MAXDIMESIZE=%lu\n", (unsigned long)soap->dime.size, (unsigned long)SOAP_MAXDIMESIZE));
|
|
14347 return soap->error = SOAP_DIME_ERROR;
|
|
14348 }
|
|
14349 s = (char*)soap_push_block(soap, NULL, soap->dime.size);
|
|
14350 if (!s)
|
|
14351 return soap->error = SOAP_EOM;
|
|
14352 for (i = soap->dime.size; i > 0; i--)
|
|
14353 { if ((int)(c = soap_get1(soap)) == EOF)
|
|
14354 return soap->error = SOAP_EOF;
|
|
14355 *s++ = (char)c;
|
|
14356 }
|
|
14357 if (soap_move(soap, (size_t)(-(long)soap->dime.size&3)))
|
|
14358 return soap->error = SOAP_EOF;
|
|
14359 if (!(soap->dime.flags & SOAP_DIME_CF))
|
|
14360 break;
|
|
14361 if (soap_getdimehdr(soap))
|
|
14362 return soap->error;
|
|
14363 }
|
|
14364 soap->dime.size = soap->blist->size++; /* allocate one more byte in blist for the terminating '\0' */
|
|
14365 if (!(soap->dime.ptr = soap_save_block(soap, NULL, NULL, 0)))
|
|
14366 return soap->error;
|
|
14367 soap->dime.ptr[soap->dime.size] = '\0'; /* make 0-terminated */
|
|
14368 soap->dime.id = id;
|
|
14369 soap->dime.type = type;
|
|
14370 soap->dime.options = options;
|
|
14371 }
|
|
14372 else
|
|
14373 soap->dime.ptr = soap_getdimefield(soap, soap->dime.size);
|
|
14374 content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, soap->dime.ptr, soap->dime.size);
|
|
14375 if (!content)
|
|
14376 return soap->error = SOAP_EOM;
|
|
14377 content->id = soap->dime.id;
|
|
14378 content->type = soap->dime.type;
|
|
14379 content->options = soap->dime.options;
|
|
14380 if (soap->error)
|
|
14381 return soap->error;
|
|
14382 soap_resolve_attachment(soap, content);
|
|
14383 }
|
|
14384 if (soap->error != SOAP_DIME_END)
|
|
14385 return soap->error;
|
|
14386 return soap->error = SOAP_OK;
|
|
14387 }
|
|
14388 #endif
|
|
14389 #endif
|
|
14390
|
|
14391 /******************************************************************************/
|
|
14392 #ifndef WITH_LEANER
|
|
14393 #ifndef PALM_1
|
|
14394 SOAP_FMAC1
|
|
14395 int
|
|
14396 SOAP_FMAC2
|
|
14397 soap_getmimehdr(struct soap *soap)
|
|
14398 { struct soap_multipart *content;
|
|
14399 do
|
|
14400 { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
|
|
14401 return soap->error;
|
|
14402 }
|
|
14403 while (!*soap->msgbuf);
|
|
14404 if (soap->msgbuf[0] == '-' && soap->msgbuf[1] == '-')
|
|
14405 { char *s = soap->msgbuf + strlen(soap->msgbuf) - 1;
|
|
14406 /* remove white space */
|
|
14407 while (soap_blank((soap_wchar)*s))
|
|
14408 s--;
|
|
14409 s[1] = '\0';
|
|
14410 if (soap->mime.boundary)
|
|
14411 { if (strcmp(soap->msgbuf + 2, soap->mime.boundary))
|
|
14412 return soap->error = SOAP_MIME_ERROR;
|
|
14413 }
|
|
14414 else
|
|
14415 soap->mime.boundary = soap_strdup(soap, soap->msgbuf + 2);
|
|
14416 if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
|
|
14417 return soap->error;
|
|
14418 }
|
|
14419 if (soap_set_mime_attachment(soap, NULL, 0, SOAP_MIME_NONE, NULL, NULL, NULL, NULL))
|
|
14420 return soap->error = SOAP_EOM;
|
|
14421 content = soap->mime.last;
|
|
14422 for (;;)
|
|
14423 { register char *key = soap->msgbuf;
|
|
14424 register char *val;
|
|
14425 if (!*key)
|
|
14426 break;
|
|
14427 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "MIME header: %s\n", key));
|
|
14428 val = strchr(soap->msgbuf, ':');
|
|
14429 if (val)
|
|
14430 { *val = '\0';
|
|
14431 do val++;
|
|
14432 while (*val && *val <= 32);
|
|
14433 if (!soap_tag_cmp(key, "Content-ID"))
|
|
14434 content->id = soap_strdup(soap, val);
|
|
14435 else if (!soap_tag_cmp(key, "Content-Location"))
|
|
14436 content->location = soap_strdup(soap, val);
|
|
14437 else if (!soap_tag_cmp(key, "Content-Disposition"))
|
|
14438 content->id = soap_strdup(soap, soap_get_header_attribute(soap, val, "name"));
|
|
14439 else if (!soap_tag_cmp(key, "Content-Type"))
|
|
14440 content->type = soap_strdup(soap, val);
|
|
14441 else if (!soap_tag_cmp(key, "Content-Description"))
|
|
14442 content->description = soap_strdup(soap, val);
|
|
14443 else if (!soap_tag_cmp(key, "Content-Transfer-Encoding"))
|
|
14444 content->encoding = (enum soap_mime_encoding)soap_code_int(mime_codes, val, (long)SOAP_MIME_NONE);
|
|
14445 }
|
|
14446 if (soap_getline(soap, key, sizeof(soap->msgbuf)))
|
|
14447 return soap->error;
|
|
14448 }
|
|
14449 return SOAP_OK;
|
|
14450 }
|
|
14451 #endif
|
|
14452 #endif
|
|
14453
|
|
14454 /******************************************************************************/
|
|
14455 #ifndef WITH_LEANER
|
|
14456 #ifndef PALM_1
|
|
14457 SOAP_FMAC1
|
|
14458 int
|
|
14459 SOAP_FMAC2
|
|
14460 soap_getmime(struct soap *soap)
|
|
14461 { while (soap_get_mime_attachment(soap, NULL))
|
|
14462 ;
|
|
14463 return soap->error;
|
|
14464 }
|
|
14465 #endif
|
|
14466 #endif
|
|
14467
|
|
14468 /******************************************************************************/
|
|
14469 #ifndef WITH_LEANER
|
|
14470 #ifndef PALM_1
|
|
14471 SOAP_FMAC1
|
|
14472 void
|
|
14473 SOAP_FMAC2
|
|
14474 soap_post_check_mime_attachments(struct soap *soap)
|
|
14475 { soap->imode |= SOAP_MIME_POSTCHECK;
|
|
14476 }
|
|
14477 #endif
|
|
14478 #endif
|
|
14479
|
|
14480 /******************************************************************************/
|
|
14481 #ifndef WITH_LEANER
|
|
14482 #ifndef PALM_1
|
|
14483 SOAP_FMAC1
|
|
14484 int
|
|
14485 SOAP_FMAC2
|
|
14486 soap_check_mime_attachments(struct soap *soap)
|
|
14487 { if (soap->mode & SOAP_MIME_POSTCHECK)
|
|
14488 return soap_get_mime_attachment(soap, NULL) != NULL;
|
|
14489 return SOAP_OK;
|
|
14490 }
|
|
14491 #endif
|
|
14492 #endif
|
|
14493
|
|
14494 /******************************************************************************/
|
|
14495 #ifndef WITH_LEANER
|
|
14496 #ifndef PALM_1
|
|
14497 SOAP_FMAC1
|
|
14498 struct soap_multipart *
|
|
14499 SOAP_FMAC2
|
|
14500 soap_get_mime_attachment(struct soap *soap, void *handle)
|
|
14501 { register soap_wchar c = 0;
|
|
14502 register size_t i, m = 0;
|
|
14503 register char *s, *t = NULL;
|
|
14504 register struct soap_multipart *content;
|
|
14505 register short flag = 0;
|
|
14506 if (!(soap->mode & SOAP_ENC_MIME))
|
|
14507 return NULL;
|
|
14508 content = soap->mime.last;
|
|
14509 if (!content)
|
|
14510 { if (soap_getmimehdr(soap))
|
|
14511 return NULL;
|
|
14512 content = soap->mime.last;
|
|
14513 }
|
|
14514 else if (content != soap->mime.first)
|
|
14515 { if (soap->fmimewriteopen && ((content->ptr = (char*)soap->fmimewriteopen(soap, (void*)handle, content->id, content->type, content->description, content->encoding)) || soap->error))
|
|
14516 { if (!content->ptr)
|
|
14517 return NULL;
|
|
14518 }
|
|
14519 }
|
|
14520 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Parsing MIME content id='%s' type='%s'\n", content->id ? content->id : SOAP_STR_EOS, content->type ? content->type : SOAP_STR_EOS));
|
|
14521 if (!content->ptr && soap_new_block(soap) == NULL)
|
|
14522 { soap->error = SOAP_EOM;
|
|
14523 return NULL;
|
|
14524 }
|
|
14525 for (;;)
|
|
14526 { if (content->ptr)
|
|
14527 s = soap->tmpbuf;
|
|
14528 else if (!(s = (char*)soap_push_block(soap, NULL, sizeof(soap->tmpbuf))))
|
|
14529 { soap->error = SOAP_EOM;
|
|
14530 return NULL;
|
|
14531 }
|
|
14532 for (i = 0; i < sizeof(soap->tmpbuf); i++)
|
|
14533 { if (m > 0)
|
|
14534 { *s++ = *t++;
|
|
14535 m--;
|
|
14536 }
|
|
14537 else
|
|
14538 { if (!flag)
|
|
14539 { c = soap_get1(soap);
|
|
14540 if ((int)c == EOF)
|
|
14541 { if (content->ptr && soap->fmimewriteclose)
|
|
14542 soap->fmimewriteclose(soap, (void*)content->ptr);
|
|
14543 soap->error = SOAP_CHK_EOF;
|
|
14544 return NULL;
|
|
14545 }
|
|
14546 }
|
|
14547 if (flag || c == '\r')
|
|
14548 { t = soap->msgbuf;
|
|
14549 memset(t, 0, sizeof(soap->msgbuf));
|
|
14550 strcpy(t, "\n--");
|
|
14551 if (soap->mime.boundary)
|
|
14552 strncat(t, soap->mime.boundary, sizeof(soap->msgbuf)-4);
|
|
14553 do c = soap_getchar(soap);
|
|
14554 while (c == *t++);
|
|
14555 if ((int)c == EOF)
|
|
14556 { if (content->ptr && soap->fmimewriteclose)
|
|
14557 soap->fmimewriteclose(soap, (void*)content->ptr);
|
|
14558 soap->error = SOAP_CHK_EOF;
|
|
14559 return NULL;
|
|
14560 }
|
|
14561 if (!*--t)
|
|
14562 goto end;
|
|
14563 *t = (char)c;
|
|
14564 flag = (c == '\r');
|
|
14565 m = t - soap->msgbuf + 1 - flag;
|
|
14566 t = soap->msgbuf;
|
|
14567 c = '\r';
|
|
14568 }
|
|
14569 *s++ = (char)c;
|
|
14570 }
|
|
14571 }
|
|
14572 if (content->ptr && soap->fmimewrite)
|
|
14573 { if ((soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i)))
|
|
14574 break;
|
|
14575 }
|
|
14576 }
|
|
14577 end:
|
|
14578 *s = '\0'; /* make 0-terminated */
|
|
14579 if (content->ptr)
|
|
14580 { if (!soap->error && soap->fmimewrite)
|
|
14581 soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i);
|
|
14582 if (soap->fmimewriteclose)
|
|
14583 soap->fmimewriteclose(soap, (void*)content->ptr);
|
|
14584 if (soap->error)
|
|
14585 return NULL;
|
|
14586 }
|
|
14587 else
|
|
14588 { content->size = soap_size_block(soap, NULL, i+1) - 1; /* last block with '\0' */
|
|
14589 content->ptr = soap_save_block(soap, NULL, NULL, 0);
|
|
14590 }
|
|
14591 soap_resolve_attachment(soap, content);
|
|
14592 if (c == '-' && soap_getchar(soap) == '-')
|
|
14593 { soap->mode &= ~SOAP_ENC_MIME;
|
|
14594 if ((soap->mode & SOAP_MIME_POSTCHECK) && soap_end_recv(soap))
|
|
14595 { if (soap->keep_alive < 0)
|
|
14596 soap->keep_alive = 0;
|
|
14597 soap_closesock(soap);
|
|
14598 return NULL;
|
|
14599 }
|
|
14600 }
|
|
14601 else
|
|
14602 { while (c != '\r' && (int)c != EOF && soap_blank(c))
|
|
14603 c = soap_getchar(soap);
|
|
14604 if (c != '\r' || soap_getchar(soap) != '\n')
|
|
14605 { soap->error = SOAP_MIME_ERROR;
|
|
14606 return NULL;
|
|
14607 }
|
|
14608 if (soap_getmimehdr(soap))
|
|
14609 return NULL;
|
|
14610 }
|
|
14611 return content;
|
|
14612 }
|
|
14613 #endif
|
|
14614 #endif
|
|
14615
|
|
14616 /******************************************************************************/
|
|
14617 #ifndef WITH_LEANER
|
|
14618 #ifndef PALM_1
|
|
14619 SOAP_FMAC1
|
|
14620 int
|
|
14621 SOAP_FMAC2
|
|
14622 soap_match_cid(struct soap *soap, const char *s, const char *t)
|
|
14623 { register size_t n;
|
|
14624 if (!s)
|
|
14625 return 1;
|
|
14626 if (!strcmp(s, t))
|
|
14627 return 0;
|
|
14628 if (!strncmp(s, "cid:", 4))
|
|
14629 s += 4;
|
|
14630 n = strlen(t);
|
|
14631 if (*t == '<')
|
|
14632 { t++;
|
|
14633 n -= 2;
|
|
14634 }
|
|
14635 if (!strncmp(s, t, n) && !s[n])
|
|
14636 return 0;
|
|
14637 soap_decode(soap->tmpbuf, sizeof(soap->tmpbuf), s, SOAP_STR_EOS);
|
|
14638 if (!strncmp(soap->tmpbuf, t, n) && !soap->tmpbuf[n])
|
|
14639 return 0;
|
|
14640 return 1;
|
|
14641 }
|
|
14642 #endif
|
|
14643 #endif
|
|
14644
|
|
14645 /******************************************************************************/
|
|
14646 #ifndef WITH_LEANER
|
|
14647 #ifndef PALM_1
|
|
14648 static void
|
|
14649 soap_resolve_attachment(struct soap *soap, struct soap_multipart *content)
|
|
14650 { if (content->id)
|
|
14651 { register struct soap_xlist **xp = &soap->xlist;
|
|
14652 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving attachment data for id='%s'\n", content->id));
|
|
14653 while (*xp)
|
|
14654 { register struct soap_xlist *xq = *xp;
|
|
14655 if (!soap_match_cid(soap, xq->id, content->id))
|
|
14656 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Found matching attachment id='%s' for content id='%s'\n", xq->id, content->id));
|
|
14657 *xp = xq->next;
|
|
14658 *xq->ptr = (unsigned char*)content->ptr;
|
|
14659 *xq->size = (int)content->size;
|
|
14660 *xq->type = (char*)content->type;
|
|
14661 if (content->options)
|
|
14662 *xq->options = (char*)content->options;
|
|
14663 else
|
|
14664 *xq->options = (char*)content->description;
|
|
14665 SOAP_FREE(soap, xq);
|
|
14666 }
|
|
14667 else
|
|
14668 xp = &(*xp)->next;
|
|
14669 }
|
|
14670 }
|
|
14671 }
|
|
14672 #endif
|
|
14673 #endif
|
|
14674
|
|
14675 /******************************************************************************/
|
|
14676 #ifndef WITH_LEANER
|
|
14677 #ifndef PALM_1
|
|
14678 SOAP_FMAC1
|
|
14679 int
|
|
14680 SOAP_FMAC2
|
|
14681 soap_putmimehdr(struct soap *soap, struct soap_multipart *content)
|
|
14682 { const char *s;
|
|
14683 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "MIME attachment type='%s'\n", content->type ? content->type : SOAP_STR_EOS));
|
|
14684 if (soap_send3(soap, "\r\n--", soap->mime.boundary, "\r\n"))
|
|
14685 return soap->error;
|
|
14686 if (content->type && soap_send3(soap, "Content-Type: ", content->type, "\r\n"))
|
|
14687 return soap->error;
|
|
14688 s = soap_code_str(mime_codes, content->encoding);
|
|
14689 if (s && soap_send3(soap, "Content-Transfer-Encoding: ", s, "\r\n"))
|
|
14690 return soap->error;
|
|
14691 if (content->id && soap_send3(soap, "Content-ID: ", content->id, "\r\n"))
|
|
14692 return soap->error;
|
|
14693 if (content->location && soap_send3(soap, "Content-Location: ", content->location, "\r\n"))
|
|
14694 return soap->error;
|
|
14695 if (content->description && soap_send3(soap, "Content-Description: ", content->description, "\r\n"))
|
|
14696 return soap->error;
|
|
14697 return soap_send_raw(soap, "\r\n", 2);
|
|
14698 }
|
|
14699 #endif
|
|
14700 #endif
|
|
14701
|
|
14702 /******************************************************************************/
|
|
14703 #ifndef WITH_LEANER
|
|
14704 #ifndef PALM_1
|
|
14705 SOAP_FMAC1
|
|
14706 int
|
|
14707 SOAP_FMAC2
|
|
14708 soap_putmime(struct soap *soap)
|
|
14709 { struct soap_multipart *content;
|
|
14710 if (!(soap->mode & SOAP_ENC_MIME) || !soap->mime.boundary)
|
|
14711 return SOAP_OK;
|
|
14712 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending MIME attachments\n"));
|
|
14713 for (content = soap->mime.first; content; content = content->next)
|
|
14714 { void *handle;
|
|
14715 if (soap->fmimereadopen && ((handle = soap->fmimereadopen(soap, (void*)content->ptr, content->id, content->type, content->description)) || soap->error))
|
|
14716 { size_t size = content->size;
|
|
14717 if (!handle)
|
|
14718 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimereadopen failed\n"));
|
|
14719 return soap->error;
|
|
14720 }
|
|
14721 if (soap_putmimehdr(soap, content))
|
|
14722 return soap->error;
|
|
14723 if (!size)
|
|
14724 { if ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE)
|
|
14725 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming MIME\n"));
|
|
14726 do
|
|
14727 { size = soap->fmimeread(soap, handle, soap->tmpbuf, sizeof(soap->tmpbuf));
|
|
14728 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread returned %lu bytes\n", (unsigned long)size));
|
|
14729 if (soap_send_raw(soap, soap->tmpbuf, size))
|
|
14730 break;
|
|
14731 } while (size);
|
|
14732 }
|
|
14733 else
|
|
14734 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error: cannot chunk streaming MIME (no HTTP chunking)\n"));
|
|
14735 }
|
|
14736 }
|
|
14737 else
|
|
14738 { do
|
|
14739 { size_t bufsize;
|
|
14740 if (size < sizeof(soap->tmpbuf))
|
|
14741 bufsize = size;
|
|
14742 else
|
|
14743 bufsize = sizeof(soap->tmpbuf);
|
|
14744 if (!(bufsize = soap->fmimeread(soap, handle, soap->tmpbuf, bufsize)))
|
|
14745 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size));
|
|
14746 soap->error = SOAP_EOF;
|
|
14747 break;
|
|
14748 }
|
|
14749 if (soap_send_raw(soap, soap->tmpbuf, bufsize))
|
|
14750 break;
|
|
14751 size -= bufsize;
|
|
14752 } while (size);
|
|
14753 }
|
|
14754 if (soap->fmimereadclose)
|
|
14755 soap->fmimereadclose(soap, handle);
|
|
14756 }
|
|
14757 else
|
|
14758 { if (soap_putmimehdr(soap, content)
|
|
14759 || soap_send_raw(soap, content->ptr, content->size))
|
|
14760 return soap->error;
|
|
14761 }
|
|
14762 }
|
|
14763 return soap_send3(soap, "\r\n--", soap->mime.boundary, "--");
|
|
14764 }
|
|
14765 #endif
|
|
14766 #endif
|
|
14767
|
|
14768 /******************************************************************************/
|
|
14769 #ifndef WITH_LEANER
|
|
14770 #ifndef PALM_1
|
|
14771 SOAP_FMAC1
|
|
14772 void
|
|
14773 SOAP_FMAC2
|
|
14774 soap_set_dime(struct soap *soap)
|
|
14775 { soap->omode |= SOAP_ENC_DIME;
|
|
14776 soap->dime.first = NULL;
|
|
14777 soap->dime.last = NULL;
|
|
14778 }
|
|
14779 #endif
|
|
14780 #endif
|
|
14781
|
|
14782 /******************************************************************************/
|
|
14783 #ifndef WITH_LEANER
|
|
14784 #ifndef PALM_1
|
|
14785 SOAP_FMAC1
|
|
14786 void
|
|
14787 SOAP_FMAC2
|
|
14788 soap_set_mime(struct soap *soap, const char *boundary, const char *start)
|
|
14789 { soap->omode |= SOAP_ENC_MIME;
|
|
14790 soap->mime.first = NULL;
|
|
14791 soap->mime.last = NULL;
|
|
14792 soap->mime.boundary = soap_strdup(soap, boundary);
|
|
14793 soap->mime.start = soap_strdup(soap, start);
|
|
14794 }
|
|
14795 #endif
|
|
14796 #endif
|
|
14797
|
|
14798 /******************************************************************************/
|
|
14799 #ifndef WITH_LEANER
|
|
14800 #ifndef PALM_1
|
|
14801 SOAP_FMAC1
|
|
14802 void
|
|
14803 SOAP_FMAC2
|
|
14804 soap_clr_dime(struct soap *soap)
|
|
14805 { soap->omode &= ~SOAP_ENC_DIME;
|
|
14806 soap->dime.first = NULL;
|
|
14807 soap->dime.last = NULL;
|
|
14808 }
|
|
14809 #endif
|
|
14810 #endif
|
|
14811
|
|
14812 /******************************************************************************/
|
|
14813 #ifndef WITH_LEANER
|
|
14814 #ifndef PALM_1
|
|
14815 SOAP_FMAC1
|
|
14816 void
|
|
14817 SOAP_FMAC2
|
|
14818 soap_clr_mime(struct soap *soap)
|
|
14819 { soap->omode &= ~SOAP_ENC_MIME;
|
|
14820 soap->mime.first = NULL;
|
|
14821 soap->mime.last = NULL;
|
|
14822 soap->mime.boundary = NULL;
|
|
14823 soap->mime.start = NULL;
|
|
14824 }
|
|
14825 #endif
|
|
14826 #endif
|
|
14827
|
|
14828 /******************************************************************************/
|
|
14829 #ifndef WITH_LEANER
|
|
14830 #ifndef PALM_1
|
|
14831 static struct soap_multipart*
|
|
14832 soap_new_multipart(struct soap *soap, struct soap_multipart **first, struct soap_multipart **last, char *ptr, size_t size)
|
|
14833 { struct soap_multipart *content;
|
|
14834 content = (struct soap_multipart*)soap_malloc(soap, sizeof(struct soap_multipart));
|
|
14835 if (content)
|
|
14836 { content->next = NULL;
|
|
14837 content->ptr = ptr;
|
|
14838 content->size = size;
|
|
14839 content->id = NULL;
|
|
14840 content->type = NULL;
|
|
14841 content->options = NULL;
|
|
14842 content->encoding = SOAP_MIME_NONE;
|
|
14843 content->location = NULL;
|
|
14844 content->description = NULL;
|
|
14845 if (!*first)
|
|
14846 *first = content;
|
|
14847 if (*last)
|
|
14848 (*last)->next = content;
|
|
14849 *last = content;
|
|
14850 }
|
|
14851 return content;
|
|
14852 }
|
|
14853 #endif
|
|
14854 #endif
|
|
14855
|
|
14856 /******************************************************************************/
|
|
14857 #ifndef WITH_LEANER
|
|
14858 #ifndef PALM_1
|
|
14859 SOAP_FMAC1
|
|
14860 int
|
|
14861 SOAP_FMAC2
|
|
14862 soap_set_dime_attachment(struct soap *soap, char *ptr, size_t size, const char *type, const char *id, unsigned short optype, const char *option)
|
|
14863 { struct soap_multipart *content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, ptr, size);
|
|
14864 if (!content)
|
|
14865 return SOAP_EOM;
|
|
14866 content->id = soap_strdup(soap, id);
|
|
14867 content->type = soap_strdup(soap, type);
|
|
14868 content->options = soap_dime_option(soap, optype, option);
|
|
14869 return SOAP_OK;
|
|
14870 }
|
|
14871 #endif
|
|
14872 #endif
|
|
14873
|
|
14874 /******************************************************************************/
|
|
14875 #ifndef WITH_LEANER
|
|
14876 #ifndef PALM_1
|
|
14877 SOAP_FMAC1
|
|
14878 int
|
|
14879 SOAP_FMAC2
|
|
14880 soap_set_mime_attachment(struct soap *soap, char *ptr, size_t size, enum soap_mime_encoding encoding, const char *type, const char *id, const char *location, const char *description)
|
|
14881 { struct soap_multipart *content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, ptr, size);
|
|
14882 if (!content)
|
|
14883 return SOAP_EOM;
|
|
14884 content->id = soap_strdup(soap, id);
|
|
14885 content->type = soap_strdup(soap, type);
|
|
14886 content->encoding = encoding;
|
|
14887 content->location = soap_strdup(soap, location);
|
|
14888 content->description = soap_strdup(soap, description);
|
|
14889 return SOAP_OK;
|
|
14890 }
|
|
14891 #endif
|
|
14892 #endif
|
|
14893
|
|
14894 /******************************************************************************/
|
|
14895 #ifndef WITH_LEANER
|
|
14896 #ifndef PALM_1
|
|
14897 SOAP_FMAC1
|
|
14898 struct soap_multipart*
|
|
14899 SOAP_FMAC2
|
|
14900 soap_next_multipart(struct soap_multipart *content)
|
|
14901 { if (content)
|
|
14902 return content->next;
|
|
14903 return NULL;
|
|
14904 }
|
|
14905 #endif
|
|
14906 #endif
|
|
14907
|
|
14908 /******************************************************************************/
|
|
14909 #ifndef WITH_LEANER
|
|
14910 #ifndef PALM_1
|
|
14911 static void
|
|
14912 soap_select_mime_boundary(struct soap *soap)
|
|
14913 { while (!soap->mime.boundary || soap_valid_mime_boundary(soap))
|
|
14914 { register char *s = soap->mime.boundary;
|
|
14915 register size_t n = 0;
|
|
14916 if (s)
|
|
14917 n = strlen(s);
|
|
14918 if (n < 16)
|
|
14919 { n = 64;
|
|
14920 s = soap->mime.boundary = (char*)soap_malloc(soap, n + 1);
|
|
14921 if (!s)
|
|
14922 return;
|
|
14923 }
|
|
14924 strcpy(s, "==");
|
|
14925 s += 2;
|
|
14926 n -= 4;
|
|
14927 while (n)
|
|
14928 { *s++ = soap_base64o[soap_random & 0x3F];
|
|
14929 n--;
|
|
14930 }
|
|
14931 strcpy(s, "==");
|
|
14932 }
|
|
14933 if (!soap->mime.start)
|
|
14934 soap->mime.start = "<SOAP-ENV:Envelope>";
|
|
14935 }
|
|
14936 #endif
|
|
14937 #endif
|
|
14938
|
|
14939 /******************************************************************************/
|
|
14940 #ifndef WITH_LEANER
|
|
14941 #ifndef PALM_1
|
|
14942 static int
|
|
14943 soap_valid_mime_boundary(struct soap *soap)
|
|
14944 { register struct soap_multipart *content;
|
|
14945 register size_t k;
|
|
14946 if (soap->fmimeread)
|
|
14947 return SOAP_OK;
|
|
14948 k = strlen(soap->mime.boundary);
|
|
14949 for (content = soap->mime.first; content; content = content->next)
|
|
14950 { if (content->ptr && content->size >= k)
|
|
14951 { register const char *p = (const char*)content->ptr;
|
|
14952 register size_t i;
|
|
14953 for (i = 0; i < content->size - k; i++, p++)
|
|
14954 { if (!strncmp(p, soap->mime.boundary, k))
|
|
14955 return SOAP_ERR;
|
|
14956 }
|
|
14957 }
|
|
14958 }
|
|
14959 return SOAP_OK;
|
|
14960 }
|
|
14961 #endif
|
|
14962 #endif
|
|
14963
|
|
14964 /******************************************************************************/
|
|
14965 #ifdef WITH_GZIP
|
|
14966 #ifndef PALM_1
|
|
14967 static int
|
|
14968 soap_getgziphdr(struct soap *soap)
|
|
14969 { int i;
|
|
14970 soap_wchar c = 0, f = 0;
|
|
14971 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get gzip header\n"));
|
|
14972 for (i = 0; i < 9; i++)
|
|
14973 { if ((int)(c = soap_get1(soap) == EOF))
|
|
14974 return soap->error = SOAP_ZLIB_ERROR;
|
|
14975 if (i == 1 && c == 8)
|
|
14976 soap->z_dict = 0;
|
|
14977 if (i == 2)
|
|
14978 f = c;
|
|
14979 }
|
|
14980 if (f & 0x04) /* FEXTRA */
|
|
14981 { for (i = soap_get1(soap) | (soap_get1(soap) << 8); i; i--)
|
|
14982 { if ((int)soap_get1(soap) == EOF)
|
|
14983 return soap->error = SOAP_ZLIB_ERROR;
|
|
14984 }
|
|
14985 }
|
|
14986 if (f & 0x08) /* skip FNAME */
|
|
14987 { do
|
|
14988 c = soap_get1(soap);
|
|
14989 while (c && (int)c != EOF);
|
|
14990 }
|
|
14991 if ((int)c != EOF && (f & 0x10)) /* skip FCOMMENT */
|
|
14992 { do
|
|
14993 c = soap_get1(soap);
|
|
14994 while (c && (int)c != EOF);
|
|
14995 }
|
|
14996 if ((int)c != EOF && (f & 0x02)) /* skip FHCRC (CRC32 is used) */
|
|
14997 { if ((int)(c = soap_get1(soap)) != EOF)
|
|
14998 c = soap_get1(soap);
|
|
14999 }
|
|
15000 if ((int)c == EOF)
|
|
15001 return soap->error = SOAP_ZLIB_ERROR;
|
|
15002 return SOAP_OK;
|
|
15003 }
|
|
15004 #endif
|
|
15005 #endif
|
|
15006
|
|
15007 /******************************************************************************/
|
|
15008 #ifndef PALM_1
|
|
15009 SOAP_FMAC1
|
|
15010 int
|
|
15011 SOAP_FMAC2
|
|
15012 soap_begin_serve(struct soap *soap)
|
|
15013 {
|
|
15014 #ifdef WITH_FASTCGI
|
|
15015 if (FCGI_Accept() < 0)
|
|
15016 { soap->error = SOAP_EOF;
|
|
15017 return soap_send_fault(soap);
|
|
15018 }
|
|
15019 #endif
|
|
15020 soap_begin(soap);
|
|
15021 if (soap_begin_recv(soap)
|
|
15022 || soap_envelope_begin_in(soap)
|
|
15023 || soap_recv_header(soap)
|
|
15024 || soap_body_begin_in(soap))
|
|
15025 { if (soap->error < SOAP_STOP)
|
|
15026 {
|
|
15027 #ifdef WITH_FASTCGI
|
|
15028 soap_send_fault(soap);
|
|
15029 #else
|
|
15030 return soap_send_fault(soap);
|
|
15031 #endif
|
|
15032 }
|
|
15033 return soap_closesock(soap);
|
|
15034 }
|
|
15035 return SOAP_OK;
|
|
15036 }
|
|
15037 #endif
|
|
15038
|
|
15039 /******************************************************************************/
|
|
15040 #ifndef PALM_1
|
|
15041 SOAP_FMAC1
|
|
15042 int
|
|
15043 SOAP_FMAC2
|
|
15044 soap_begin_recv(struct soap *soap)
|
|
15045 { register soap_wchar c;
|
|
15046 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing for input from socket=%d/fd=%d\n", soap->socket, soap->recvfd));
|
|
15047 soap->error = SOAP_OK;
|
|
15048 soap->filterstop = SOAP_OK;
|
|
15049 soap_free_temp(soap);
|
|
15050 soap_set_local_namespaces(soap);
|
|
15051 soap->version = 0; /* don't assume we're parsing SOAP content by default */
|
|
15052 #ifndef WITH_NOIDREF
|
|
15053 soap_free_iht(soap);
|
|
15054 #endif
|
|
15055 if ((soap->imode & SOAP_IO) == SOAP_IO_CHUNK)
|
|
15056 soap->omode |= SOAP_IO_CHUNK;
|
|
15057 soap->imode &= ~(SOAP_IO | SOAP_ENC_MIME);
|
|
15058 soap->mode = soap->imode;
|
|
15059 if (!soap->keep_alive)
|
|
15060 { soap->buflen = 0;
|
|
15061 soap->bufidx = 0;
|
|
15062 }
|
|
15063 if (!(soap->mode & SOAP_IO_KEEPALIVE))
|
|
15064 soap->keep_alive = 0;
|
|
15065 soap->ahead = 0;
|
|
15066 soap->peeked = 0;
|
|
15067 soap->level = 0;
|
|
15068 soap->part = SOAP_BEGIN;
|
|
15069 soap->alloced = 0;
|
|
15070 soap->body = 1;
|
|
15071 soap->count = 0;
|
|
15072 soap->length = 0;
|
|
15073 soap->cdata = 0;
|
|
15074 *soap->endpoint = '\0';
|
|
15075 soap->action = NULL;
|
|
15076 soap->header = NULL;
|
|
15077 soap->fault = NULL;
|
|
15078 soap->status = 0;
|
|
15079 soap->fform = NULL;
|
|
15080 #ifndef WITH_LEANER
|
|
15081 soap->dom = NULL;
|
|
15082 soap->dime.chunksize = 0;
|
|
15083 soap->dime.buflen = 0;
|
|
15084 soap->dime.list = NULL;
|
|
15085 soap->dime.first = NULL;
|
|
15086 soap->dime.last = NULL;
|
|
15087 soap->mime.list = NULL;
|
|
15088 soap->mime.first = NULL;
|
|
15089 soap->mime.last = NULL;
|
|
15090 soap->mime.boundary = NULL;
|
|
15091 soap->mime.start = NULL;
|
|
15092 #endif
|
|
15093 #ifdef WIN32
|
|
15094 #ifndef UNDER_CE
|
|
15095 #ifndef WITH_FASTCGI
|
|
15096 if (!soap_valid_socket(soap->socket) && !soap->is) /* Set win32 stdout or soap->sendfd to BINARY, e.g. to support DIME */
|
|
15097 #ifdef __BORLANDC__
|
|
15098 setmode(soap->recvfd, _O_BINARY);
|
|
15099 #else
|
|
15100 _setmode(soap->recvfd, _O_BINARY);
|
|
15101 #endif
|
|
15102 #endif
|
|
15103 #endif
|
|
15104 #endif
|
|
15105 #ifdef WITH_ZLIB
|
|
15106 soap->mode &= ~SOAP_ENC_ZLIB;
|
|
15107 soap->zlib_in = SOAP_ZLIB_NONE;
|
|
15108 soap->zlib_out = SOAP_ZLIB_NONE;
|
|
15109 soap->d_stream->next_in = Z_NULL;
|
|
15110 soap->d_stream->avail_in = 0;
|
|
15111 soap->d_stream->next_out = (Byte*)soap->buf;
|
|
15112 soap->d_stream->avail_out = SOAP_BUFLEN;
|
|
15113 soap->z_ratio_in = 1.0;
|
|
15114 #endif
|
|
15115 #ifdef WITH_OPENSSL
|
|
15116 if (soap->ssl)
|
|
15117 ERR_clear_error();
|
|
15118 #endif
|
|
15119 #ifndef WITH_LEANER
|
|
15120 if (soap->fprepareinitrecv && (soap->error = soap->fprepareinitrecv(soap)))
|
|
15121 return soap->error;
|
|
15122 #endif
|
|
15123 c = soap_getchar(soap);
|
|
15124 #ifdef WITH_GZIP
|
|
15125 if (c == 0x1F)
|
|
15126 { if (soap_getgziphdr(soap))
|
|
15127 return soap->error;
|
|
15128 if (inflateInit2(soap->d_stream, -MAX_WBITS) != Z_OK)
|
|
15129 return soap->error = SOAP_ZLIB_ERROR;
|
|
15130 if (soap->z_dict)
|
|
15131 { if (inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len) != Z_OK)
|
|
15132 return soap->error = SOAP_ZLIB_ERROR;
|
|
15133 }
|
|
15134 soap->zlib_state = SOAP_ZLIB_INFLATE;
|
|
15135 soap->mode |= SOAP_ENC_ZLIB;
|
|
15136 soap->zlib_in = SOAP_ZLIB_GZIP;
|
|
15137 soap->z_crc = crc32(0L, NULL, 0);
|
|
15138 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n"));
|
|
15139 if (!soap->z_buf)
|
|
15140 soap->z_buf = (char*)SOAP_MALLOC(soap, SOAP_BUFLEN);
|
|
15141 memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN);
|
|
15142 /* should not chunk over plain transport, so why bother to check? */
|
|
15143 /* if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) */
|
|
15144 /* soap->z_buflen = soap->bufidx; */
|
|
15145 /* else */
|
|
15146 soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx);
|
|
15147 soap->d_stream->avail_in = (unsigned int)(soap->buflen - soap->bufidx);
|
|
15148 soap->z_buflen = soap->buflen;
|
|
15149 soap->buflen = soap->bufidx;
|
|
15150 c = ' ';
|
|
15151 }
|
|
15152 #endif
|
|
15153 while (soap_blank(c))
|
|
15154 c = soap_getchar(soap);
|
|
15155 #ifndef WITH_LEANER
|
|
15156 if (c == '-' && soap_get0(soap) == '-')
|
|
15157 soap->mode |= SOAP_ENC_MIME;
|
|
15158 else if ((c & 0xFFFC) == (SOAP_DIME_VERSION | SOAP_DIME_MB) && (soap_get0(soap) & 0xFFF0) == 0x20)
|
|
15159 soap->mode |= SOAP_ENC_DIME;
|
|
15160 else
|
|
15161 #endif
|
|
15162 { /* skip BOM */
|
|
15163 if (c == 0xEF && soap_get0(soap) == 0xBB)
|
|
15164 { c = soap_get1(soap);
|
|
15165 if ((c = soap_get1(soap)) == 0xBF)
|
|
15166 { soap->mode &= ~SOAP_ENC_LATIN;
|
|
15167 c = soap_getchar(soap);
|
|
15168 }
|
|
15169 else
|
|
15170 c = (0x0F << 12) | (0xBB << 6) | (c & 0x3F); /* UTF-8 */
|
|
15171 }
|
|
15172 else if ((c == 0xFE && soap_get0(soap) == 0xFF) /* UTF-16 BE */
|
|
15173 || (c == 0xFF && soap_get0(soap) == 0xFE)) /* UTF-16 LE */
|
|
15174 return soap->error = SOAP_UTF_ERROR;
|
|
15175 /* skip space */
|
|
15176 while (soap_blank(c))
|
|
15177 c = soap_getchar(soap);
|
|
15178 }
|
|
15179 if ((int)c == EOF)
|
|
15180 return soap->error = SOAP_CHK_EOF;
|
|
15181 soap_unget(soap, c);
|
|
15182 #ifndef WITH_NOHTTP
|
|
15183 /* if not XML/MIME/DIME/ZLIB, assume HTTP method or status line */
|
|
15184 if (((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) && !(soap->mode & (SOAP_ENC_MIME | SOAP_ENC_DIME | SOAP_ENC_ZLIB | SOAP_ENC_XML)))
|
|
15185 { soap_mode m = soap->imode;
|
|
15186 soap->mode &= ~SOAP_IO;
|
|
15187 soap->error = soap->fparse(soap);
|
|
15188 if (soap->error && soap->error < SOAP_STOP)
|
|
15189 { soap->keep_alive = 0; /* force close later */
|
|
15190 return soap->error;
|
|
15191 }
|
|
15192 if (soap->error == SOAP_STOP)
|
|
15193 { if (soap->fform)
|
|
15194 { soap->error = soap->fform(soap);
|
|
15195 if (soap->error == SOAP_OK)
|
|
15196 soap->error = SOAP_STOP; /* prevents further processing */
|
|
15197 }
|
|
15198 return soap->error;
|
|
15199 }
|
|
15200 soap->mode = soap->imode; /* if imode is changed, effectuate */
|
|
15201 soap->imode = m; /* restore imode */
|
|
15202 #ifdef WITH_ZLIB
|
|
15203 soap->mode &= ~SOAP_ENC_ZLIB;
|
|
15204 #endif
|
|
15205 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
|
|
15206 { soap->chunkbuflen = soap->buflen;
|
|
15207 soap->buflen = soap->bufidx;
|
|
15208 soap->chunksize = 0;
|
|
15209 }
|
|
15210 /* Note: fparse should not use soap_unget to push back last char */
|
|
15211 #if 0
|
|
15212 if (soap->status > 200 && soap->length == 0 && !(soap->http_content && (!soap->keep_alive || soap->recv_timeout)) && (soap->imode & SOAP_IO) != SOAP_IO_CHUNK)
|
|
15213 #endif
|
|
15214 if (soap->status && !soap->body)
|
|
15215 return soap->error = soap->status;
|
|
15216 #ifdef WITH_ZLIB
|
|
15217 if (soap->zlib_in != SOAP_ZLIB_NONE)
|
|
15218 {
|
|
15219 #ifdef WITH_GZIP
|
|
15220 if (soap->zlib_in != SOAP_ZLIB_DEFLATE)
|
|
15221 { c = soap_get1(soap);
|
|
15222 if (c == (int)EOF)
|
|
15223 return soap->error = SOAP_EOF;
|
|
15224 if (c == 0x1F)
|
|
15225 { if (soap_getgziphdr(soap))
|
|
15226 return soap->error;
|
|
15227 if (inflateInit2(soap->d_stream, -MAX_WBITS) != Z_OK)
|
|
15228 return soap->error = SOAP_ZLIB_ERROR;
|
|
15229 soap->z_crc = crc32(0L, NULL, 0);
|
|
15230 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n"));
|
|
15231 }
|
|
15232 else
|
|
15233 { soap_revget1(soap);
|
|
15234 if (inflateInit(soap->d_stream) != Z_OK)
|
|
15235 return soap->error = SOAP_ZLIB_ERROR;
|
|
15236 soap->zlib_in = SOAP_ZLIB_DEFLATE;
|
|
15237 }
|
|
15238 }
|
|
15239 else
|
|
15240 #endif
|
|
15241 if (inflateInit(soap->d_stream) != Z_OK)
|
|
15242 return soap->error = SOAP_ZLIB_ERROR;
|
|
15243 if (soap->z_dict)
|
|
15244 { if (inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len) != Z_OK)
|
|
15245 return soap->error = SOAP_ZLIB_ERROR;
|
|
15246 }
|
|
15247 soap->zlib_state = SOAP_ZLIB_INFLATE;
|
|
15248 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate initialized\n"));
|
|
15249 soap->mode |= SOAP_ENC_ZLIB;
|
|
15250 if (!soap->z_buf)
|
|
15251 soap->z_buf = (char*)SOAP_MALLOC(soap, SOAP_BUFLEN);
|
|
15252 memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN);
|
|
15253 soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx);
|
|
15254 soap->d_stream->avail_in = (unsigned int)(soap->buflen - soap->bufidx);
|
|
15255 soap->z_buflen = soap->buflen;
|
|
15256 soap->buflen = soap->bufidx;
|
|
15257 }
|
|
15258 #endif
|
|
15259 #ifndef WITH_LEANER
|
|
15260 if (soap->fpreparerecv && (soap->mode & SOAP_IO) != SOAP_IO_CHUNK && soap->buflen > soap->bufidx)
|
|
15261 { int r;
|
|
15262 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Invoking fpreparerecv\n"));
|
|
15263 if ((r = soap->fpreparerecv(soap, soap->buf + soap->bufidx, soap->buflen - soap->bufidx)))
|
|
15264 return soap->error = r;
|
|
15265 }
|
|
15266 #endif
|
|
15267 if (soap_get0(soap) == (int)EOF)
|
|
15268 { if (soap->status == 0 || soap->status == 200)
|
|
15269 return soap->error = SOAP_NO_DATA; /* HTTP OK: always expect data */
|
|
15270 return soap->error = soap->status;
|
|
15271 }
|
|
15272 if (soap->error)
|
|
15273 { if (soap->error == SOAP_FORM && soap->fform)
|
|
15274 { soap->error = soap->fform(soap);
|
|
15275 if (soap->error == SOAP_OK)
|
|
15276 soap->error = SOAP_STOP; /* prevents further processing */
|
|
15277 }
|
|
15278 return soap->error;
|
|
15279 }
|
|
15280 }
|
|
15281 #endif
|
|
15282 #ifndef WITH_LEANER
|
|
15283 if (soap->mode & SOAP_ENC_MIME)
|
|
15284 { do /* skip preamble */
|
|
15285 { if ((int)(c = soap_getchar(soap)) == EOF)
|
|
15286 return soap->error = SOAP_CHK_EOF;
|
|
15287 } while (c != '-' || soap_get0(soap) != '-');
|
|
15288 soap_unget(soap, c);
|
|
15289 if (soap_getmimehdr(soap))
|
|
15290 return soap->error;
|
|
15291 if (soap->mime.start)
|
|
15292 { do
|
|
15293 { if (!soap->mime.last->id)
|
|
15294 break;
|
|
15295 if (!soap_match_cid(soap, soap->mime.start, soap->mime.last->id))
|
|
15296 break;
|
|
15297 } while (soap_get_mime_attachment(soap, NULL));
|
|
15298 }
|
|
15299 if (soap_get_header_attribute(soap, soap->mime.first->type, "application/dime"))
|
|
15300 soap->mode |= SOAP_ENC_DIME;
|
|
15301 }
|
|
15302 if (soap->mode & SOAP_ENC_DIME)
|
|
15303 { if (soap_getdimehdr(soap))
|
|
15304 return soap->error;
|
|
15305 if (soap->dime.flags & SOAP_DIME_CF)
|
|
15306 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked DIME SOAP message\n"));
|
|
15307 soap->dime.chunksize = soap->dime.size;
|
|
15308 if (soap->buflen - soap->bufidx >= soap->dime.chunksize)
|
|
15309 { soap->dime.buflen = soap->buflen;
|
|
15310 soap->buflen = soap->bufidx + soap->dime.chunksize;
|
|
15311 }
|
|
15312 else
|
|
15313 soap->dime.chunksize -= soap->buflen - soap->bufidx;
|
|
15314 }
|
|
15315 soap->count = soap->buflen - soap->bufidx;
|
|
15316 }
|
|
15317 #endif
|
|
15318 return SOAP_OK;
|
|
15319 }
|
|
15320 #endif
|
|
15321
|
|
15322 /******************************************************************************/
|
|
15323 #ifndef PALM_2
|
|
15324 SOAP_FMAC1
|
|
15325 int
|
|
15326 SOAP_FMAC2
|
|
15327 soap_envelope_begin_out(struct soap *soap)
|
|
15328 {
|
|
15329 #ifndef WITH_LEANER
|
|
15330 size_t n = 0;
|
|
15331 if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && soap->mime.start && strlen(soap->mime.boundary) + strlen(soap->mime.start) < sizeof(soap->tmpbuf) - 80 )
|
|
15332 { const char *s;
|
|
15333 if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
|
|
15334 s = "application/dime";
|
|
15335 else if (soap->version == 2)
|
|
15336 { if (soap->mode & SOAP_ENC_MTOM)
|
|
15337 s = "application/xop+xml; charset=utf-8; type=\"application/soap+xml\"";
|
|
15338 else
|
|
15339 s = "application/soap+xml; charset=utf-8";
|
|
15340 }
|
|
15341 else if (soap->mode & SOAP_ENC_MTOM)
|
|
15342 s = "application/xop+xml; charset=utf-8; type=\"text/xml\"";
|
|
15343 else
|
|
15344 s = "text/xml; charset=utf-8";
|
|
15345 #ifdef HAVE_SNPRINTF
|
|
15346 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "--%s\r\nContent-Type: %s\r\nContent-Transfer-Encoding: binary\r\nContent-ID: %s\r\n\r\n", soap->mime.boundary, s, soap->mime.start);
|
|
15347 #else
|
|
15348 sprintf(soap->tmpbuf, "--%s\r\nContent-Type: %s\r\nContent-Transfer-Encoding: binary\r\nContent-ID: %s\r\n\r\n", soap->mime.boundary, s, soap->mime.start);
|
|
15349 #endif
|
|
15350 n = strlen(soap->tmpbuf);
|
|
15351 if (soap_send_raw(soap, soap->tmpbuf, n))
|
|
15352 return soap->error;
|
|
15353 }
|
|
15354 if (soap->mode & SOAP_IO_LENGTH)
|
|
15355 soap->dime.size = soap->count; /* DIME in MIME correction */
|
|
15356 if (!(soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME))
|
|
15357 { if (soap_putdimehdr(soap))
|
|
15358 return soap->error;
|
|
15359 }
|
|
15360 #endif
|
|
15361 if (soap->version == 0)
|
|
15362 return SOAP_OK;
|
|
15363 soap->part = SOAP_IN_ENVELOPE;
|
|
15364 return soap_element_begin_out(soap, "SOAP-ENV:Envelope", 0, NULL);
|
|
15365 }
|
|
15366 #endif
|
|
15367
|
|
15368 /******************************************************************************/
|
|
15369 #ifndef PALM_2
|
|
15370 SOAP_FMAC1
|
|
15371 int
|
|
15372 SOAP_FMAC2
|
|
15373 soap_envelope_end_out(struct soap *soap)
|
|
15374 { if (soap->version == 0)
|
|
15375 return SOAP_OK;
|
|
15376 if (soap_element_end_out(soap, "SOAP-ENV:Envelope")
|
|
15377 || soap_send_raw(soap, "\r\n", 2)) /* 2.8: always emit \r\n */
|
|
15378 return soap->error;
|
|
15379 #ifndef WITH_LEANER
|
|
15380 if ((soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
|
|
15381 { soap->dime.size = soap->count - soap->dime.size; /* DIME in MIME correction */
|
|
15382 #ifdef HAVE_SNPRINTF
|
|
15383 soap_snprintf(soap->id, sizeof(soap->id), soap->dime_id_format, 0);
|
|
15384 #else
|
|
15385 sprintf(soap->id, soap->dime_id_format, 0);
|
|
15386 #endif
|
|
15387 soap->dime.id = soap->id;
|
|
15388 if (soap->local_namespaces)
|
|
15389 { if (soap->local_namespaces[0].out)
|
|
15390 soap->dime.type = (char*)soap->local_namespaces[0].out;
|
|
15391 else
|
|
15392 soap->dime.type = (char*)soap->local_namespaces[0].ns;
|
|
15393 }
|
|
15394 soap->dime.options = NULL;
|
|
15395 soap->dime.flags = SOAP_DIME_MB | SOAP_DIME_ABSURI;
|
|
15396 if (!soap->dime.first)
|
|
15397 soap->dime.flags |= SOAP_DIME_ME;
|
|
15398 soap->count += 12 + ((strlen(soap->dime.id)+3)&(~3)) + (soap->dime.type ? ((strlen(soap->dime.type)+3)&(~3)) : 0);
|
|
15399 }
|
|
15400 if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
|
|
15401 return soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3);
|
|
15402 #endif
|
|
15403 soap->part = SOAP_END_ENVELOPE;
|
|
15404 return SOAP_OK;
|
|
15405 }
|
|
15406 #endif
|
|
15407
|
|
15408 /******************************************************************************/
|
|
15409 #ifndef WITH_LEAN
|
|
15410 #ifndef PALM_1
|
|
15411 SOAP_FMAC1
|
|
15412 char*
|
|
15413 SOAP_FMAC2
|
|
15414 soap_get_http_body(struct soap *soap, size_t *len)
|
|
15415 { if (len)
|
|
15416 *len = 0;
|
|
15417 #ifndef WITH_LEAN
|
|
15418 register size_t l = 0, n = 0;
|
|
15419 register char *s;
|
|
15420 /* get HTTP body length */
|
|
15421 if (!(soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) != SOAP_IO_CHUNK)
|
|
15422 { n = soap->length;
|
|
15423 if (!n)
|
|
15424 return NULL;
|
|
15425 }
|
|
15426 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Parsing HTTP body (mode=0x%x,len=%lu)\n", soap->mode, (unsigned long)n));
|
|
15427 #ifdef WITH_FAST
|
|
15428 soap->labidx = 0; /* use look-aside buffer */
|
|
15429 #else
|
|
15430 if (soap_new_block(soap) == NULL)
|
|
15431 return NULL;
|
|
15432 #endif
|
|
15433 for (;;)
|
|
15434 {
|
|
15435 #ifdef WITH_FAST
|
|
15436 register size_t i, k;
|
|
15437 if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */
|
|
15438 return NULL;
|
|
15439 s = soap->labbuf + soap->labidx; /* space to populate */
|
|
15440 k = soap->lablen - soap->labidx; /* number of bytes available */
|
|
15441 soap->labidx = soap->lablen; /* claim this space */
|
|
15442 #else
|
|
15443 register size_t i, k = SOAP_BLKLEN;
|
|
15444 if (!(s = (char*)soap_push_block(soap, NULL, k)))
|
|
15445 return NULL;
|
|
15446 #endif
|
|
15447 for (i = 0; i < k; i++)
|
|
15448 { register soap_wchar c;
|
|
15449 l++;
|
|
15450 if (n > 0 && l > n)
|
|
15451 goto end;
|
|
15452 c = soap_get1(soap);
|
|
15453 if ((int)c == EOF)
|
|
15454 goto end;
|
|
15455 *s++ = (char)(c & 0xFF);
|
|
15456 }
|
|
15457 }
|
|
15458 end:
|
|
15459 *s = '\0';
|
|
15460 if (len)
|
|
15461 *len = l - 1; /* len excludes terminating \0 */
|
|
15462 #ifdef WITH_FAST
|
|
15463 if ((s = (char*)soap_malloc(soap, l)))
|
|
15464 memcpy(s, soap->labbuf, l);
|
|
15465 #else
|
|
15466 soap_size_block(soap, NULL, i+1);
|
|
15467 s = soap_save_block(soap, NULL, 0);
|
|
15468 #endif
|
|
15469 return s;
|
|
15470 #else
|
|
15471 return NULL;
|
|
15472 #endif
|
|
15473 }
|
|
15474 #endif
|
|
15475 #endif
|
|
15476
|
|
15477 /******************************************************************************/
|
|
15478 #ifndef PALM_1
|
|
15479 SOAP_FMAC1
|
|
15480 int
|
|
15481 SOAP_FMAC2
|
|
15482 soap_envelope_begin_in(struct soap *soap)
|
|
15483 { register struct Namespace *p;
|
|
15484 soap->part = SOAP_IN_ENVELOPE;
|
|
15485 if (soap_element_begin_in(soap, "SOAP-ENV:Envelope", 0, NULL))
|
|
15486 { if (soap->error == SOAP_TAG_MISMATCH)
|
|
15487 { if (!soap_element_begin_in(soap, "Envelope", 0, NULL))
|
|
15488 soap->error = SOAP_VERSIONMISMATCH;
|
|
15489 else if (soap->status == 0 || (soap->status >= 200 && soap->status <= 299))
|
|
15490 return SOAP_OK; /* allow non-SOAP XML content to be captured */
|
|
15491 soap->error = soap->status;
|
|
15492 }
|
|
15493 else if (soap->status)
|
|
15494 soap->error = soap->status;
|
|
15495 return soap->error;
|
|
15496 }
|
|
15497 p = soap->local_namespaces;
|
|
15498 if (p)
|
|
15499 { const char *ns = p[0].out;
|
|
15500 if (!ns)
|
|
15501 ns = p[0].ns;
|
|
15502 if (!strcmp(ns, soap_env1))
|
|
15503 { soap->version = 1; /* make sure we use SOAP 1.1 */
|
|
15504 if (p[1].out)
|
|
15505 SOAP_FREE(soap, p[1].out);
|
|
15506 if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc1))))
|
|
15507 strcpy(p[1].out, soap_enc1);
|
|
15508 }
|
|
15509 else if (!strcmp(ns, soap_env2))
|
|
15510 { soap->version = 2; /* make sure we use SOAP 1.2 */
|
|
15511 if (p[1].out)
|
|
15512 SOAP_FREE(soap, p[1].out);
|
|
15513 if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc2))))
|
|
15514 strcpy(p[1].out, soap_enc2);
|
|
15515 }
|
|
15516 }
|
|
15517 return SOAP_OK;
|
|
15518 }
|
|
15519 #endif
|
|
15520
|
|
15521 /******************************************************************************/
|
|
15522 #ifndef PALM_1
|
|
15523 SOAP_FMAC1
|
|
15524 int
|
|
15525 SOAP_FMAC2
|
|
15526 soap_envelope_end_in(struct soap *soap)
|
|
15527 { if (soap->version == 0)
|
|
15528 return SOAP_OK;
|
|
15529 soap->part = SOAP_END_ENVELOPE;
|
|
15530 return soap_element_end_in(soap, "SOAP-ENV:Envelope");
|
|
15531 }
|
|
15532 #endif
|
|
15533
|
|
15534 /******************************************************************************/
|
|
15535 #ifndef PALM_2
|
|
15536 SOAP_FMAC1
|
|
15537 int
|
|
15538 SOAP_FMAC2
|
|
15539 soap_body_begin_out(struct soap *soap)
|
|
15540 { if (soap->version == 1)
|
|
15541 soap->encoding = 1;
|
|
15542 #ifndef WITH_LEAN
|
|
15543 if ((soap->mode & SOAP_SEC_WSUID) && soap_set_attr(soap, "wsu:Id", "Body", 1))
|
|
15544 return soap->error;
|
|
15545 #endif
|
|
15546 if (soap->version == 0)
|
|
15547 return SOAP_OK;
|
|
15548 soap->part = SOAP_IN_BODY;
|
|
15549 return soap_element_begin_out(soap, "SOAP-ENV:Body", 0, NULL);
|
|
15550 }
|
|
15551 #endif
|
|
15552
|
|
15553 /******************************************************************************/
|
|
15554 #ifndef PALM_2
|
|
15555 SOAP_FMAC1
|
|
15556 int
|
|
15557 SOAP_FMAC2
|
|
15558 soap_body_end_out(struct soap *soap)
|
|
15559 { if (soap->version == 0)
|
|
15560 return SOAP_OK;
|
|
15561 if (soap_element_end_out(soap, "SOAP-ENV:Body"))
|
|
15562 return soap->error;
|
|
15563 soap->part = SOAP_END_BODY;
|
|
15564 return SOAP_OK;
|
|
15565 }
|
|
15566 #endif
|
|
15567
|
|
15568 /******************************************************************************/
|
|
15569 #ifndef PALM_2
|
|
15570 SOAP_FMAC1
|
|
15571 int
|
|
15572 SOAP_FMAC2
|
|
15573 soap_body_begin_in(struct soap *soap)
|
|
15574 { if (soap->version == 0)
|
|
15575 return SOAP_OK;
|
|
15576 soap->part = SOAP_IN_BODY;
|
|
15577 if (soap_element_begin_in(soap, "SOAP-ENV:Body", 0, NULL))
|
|
15578 return soap->error;
|
|
15579 if (!soap->body)
|
|
15580 soap->part = SOAP_NO_BODY;
|
|
15581 return SOAP_OK;
|
|
15582 }
|
|
15583 #endif
|
|
15584
|
|
15585 /******************************************************************************/
|
|
15586 #ifndef PALM_2
|
|
15587 SOAP_FMAC1
|
|
15588 int
|
|
15589 SOAP_FMAC2
|
|
15590 soap_body_end_in(struct soap *soap)
|
|
15591 { if (soap->version == 0)
|
|
15592 return SOAP_OK;
|
|
15593 if (soap->part == SOAP_NO_BODY)
|
|
15594 return soap->error = SOAP_OK;
|
|
15595 soap->part = SOAP_END_BODY;
|
|
15596 return soap_element_end_in(soap, "SOAP-ENV:Body");
|
|
15597 }
|
|
15598 #endif
|
|
15599
|
|
15600 /******************************************************************************/
|
|
15601 #ifndef PALM_2
|
|
15602 SOAP_FMAC1
|
|
15603 int
|
|
15604 SOAP_FMAC2
|
|
15605 soap_recv_header(struct soap *soap)
|
|
15606 { if (soap_getheader(soap) && soap->error == SOAP_TAG_MISMATCH)
|
|
15607 soap->error = SOAP_OK;
|
|
15608 if (soap->error == SOAP_OK && soap->fheader)
|
|
15609 soap->error = soap->fheader(soap);
|
|
15610 return soap->error;
|
|
15611 }
|
|
15612 #endif
|
|
15613
|
|
15614 /******************************************************************************/
|
|
15615 #ifndef PALM_1
|
|
15616 SOAP_FMAC1
|
|
15617 void
|
|
15618 SOAP_FMAC2
|
|
15619 soap_set_endpoint(struct soap *soap, const char *endpoint)
|
|
15620 { register const char *s;
|
|
15621 register size_t i, n;
|
|
15622 soap->endpoint[0] = '\0';
|
|
15623 soap->host[0] = '\0';
|
|
15624 soap->path[0] = '/';
|
|
15625 soap->path[1] = '\0';
|
|
15626 soap->port = 80;
|
|
15627 if (!endpoint || !*endpoint)
|
|
15628 return;
|
|
15629 #ifdef WITH_OPENSSL
|
|
15630 if (!soap_tag_cmp(endpoint, "https:*"))
|
|
15631 soap->port = 443;
|
|
15632 #endif
|
|
15633 strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint));
|
|
15634 soap->endpoint[sizeof(soap->endpoint) - 1] = '\0';
|
|
15635 s = strchr(endpoint, ':');
|
|
15636 if (s && s[1] == '/' && s[2] == '/')
|
|
15637 s += 3;
|
|
15638 else
|
|
15639 s = endpoint;
|
|
15640 n = strlen(s);
|
|
15641 if (n >= sizeof(soap->host))
|
|
15642 n = sizeof(soap->host) - 1;
|
|
15643 #ifdef WITH_IPV6
|
|
15644 if (s[0] == '[')
|
|
15645 { s++;
|
|
15646 for (i = 0; i < n; i++)
|
|
15647 { if (s[i] == ']')
|
|
15648 { s++;
|
|
15649 --n;
|
|
15650 break;
|
|
15651 }
|
|
15652 soap->host[i] = s[i];
|
|
15653 }
|
|
15654 }
|
|
15655 else
|
|
15656 { for (i = 0; i < n; i++)
|
|
15657 { soap->host[i] = s[i];
|
|
15658 if (s[i] == '/' || s[i] == ':')
|
|
15659 break;
|
|
15660 }
|
|
15661 }
|
|
15662 #else
|
|
15663 for (i = 0; i < n; i++)
|
|
15664 { soap->host[i] = s[i];
|
|
15665 if (s[i] == '/' || s[i] == ':')
|
|
15666 break;
|
|
15667 }
|
|
15668 #endif
|
|
15669 soap->host[i] = '\0';
|
|
15670 if (s[i] == ':')
|
|
15671 { soap->port = (int)soap_strtol(s + i + 1, NULL, 10);
|
|
15672 for (i++; i < n; i++)
|
|
15673 if (s[i] == '/')
|
|
15674 break;
|
|
15675 }
|
|
15676 if (i < n && s[i])
|
|
15677 { strncpy(soap->path, s + i, sizeof(soap->path));
|
|
15678 soap->path[sizeof(soap->path) - 1] = '\0';
|
|
15679 }
|
|
15680 }
|
|
15681 #endif
|
|
15682
|
|
15683 /******************************************************************************/
|
|
15684 #ifndef PALM_1
|
|
15685 SOAP_FMAC1
|
|
15686 int
|
|
15687 SOAP_FMAC2
|
|
15688 soap_connect(struct soap *soap, const char *endpoint, const char *action)
|
|
15689 { return soap_connect_command(soap, SOAP_POST, endpoint, action);
|
|
15690 }
|
|
15691 #endif
|
|
15692
|
|
15693 /******************************************************************************/
|
|
15694 #ifndef PALM_1
|
|
15695 SOAP_FMAC1
|
|
15696 int
|
|
15697 SOAP_FMAC2
|
|
15698 soap_connect_command(struct soap *soap, int http_command, const char *endpoints, const char *action)
|
|
15699 { char *endpoint;
|
|
15700 const char *s;
|
|
15701 if (endpoints && (s = strchr(endpoints, ' ')))
|
|
15702 { endpoint = (char*)SOAP_MALLOC(soap, strlen(endpoints) + 1);
|
|
15703 for (;;)
|
|
15704 { strncpy(endpoint, endpoints, s - endpoints);
|
|
15705 endpoint[s - endpoints] = '\0';
|
|
15706 if (soap_try_connect_command(soap, http_command, endpoint, action) != SOAP_TCP_ERROR)
|
|
15707 break;
|
|
15708 if (!*s)
|
|
15709 break;
|
|
15710 soap->error = SOAP_OK;
|
|
15711 while (*s == ' ')
|
|
15712 s++;
|
|
15713 endpoints = s;
|
|
15714 s = strchr(endpoints, ' ');
|
|
15715 if (!s)
|
|
15716 s = endpoints + strlen(endpoints);
|
|
15717 }
|
|
15718 SOAP_FREE(soap, endpoint);
|
|
15719 }
|
|
15720 else
|
|
15721 soap_try_connect_command(soap, http_command, endpoints, action);
|
|
15722 return soap->error;
|
|
15723 }
|
|
15724 #endif
|
|
15725
|
|
15726 /******************************************************************************/
|
|
15727 #ifndef PALM_1
|
|
15728 static int
|
|
15729 soap_try_connect_command(struct soap *soap, int http_command, const char *endpoint, const char *action)
|
|
15730 { char host[sizeof(soap->host)];
|
|
15731 int port;
|
|
15732 size_t count;
|
|
15733 soap->error = SOAP_OK;
|
|
15734 strcpy(host, soap->host); /* save previous host name: if != then reconnect */
|
|
15735 port = soap->port; /* save previous port to compare */
|
|
15736 soap->status = http_command;
|
|
15737 soap_set_endpoint(soap, endpoint);
|
|
15738 #ifndef WITH_LEANER
|
|
15739 if (soap->fconnect)
|
|
15740 { if ((soap->error = soap->fconnect(soap, endpoint, soap->host, soap->port)))
|
|
15741 return soap->error;
|
|
15742 }
|
|
15743 else
|
|
15744 #endif
|
|
15745 soap->action = soap_strdup(soap, action);
|
|
15746 if (soap->fopen && *soap->host)
|
|
15747 { if (!soap->keep_alive || !soap_valid_socket(soap->socket) || strcmp(soap->host, host) || soap->port != port || !soap->fpoll || soap->fpoll(soap))
|
|
15748 { soap->error = SOAP_OK;
|
|
15749 #ifndef WITH_LEAN
|
|
15750 if (!strncmp(endpoint, "soap.udp:", 9))
|
|
15751 soap->omode |= SOAP_IO_UDP;
|
|
15752 else
|
|
15753 #endif
|
|
15754 { soap->keep_alive = 0; /* to force close */
|
|
15755 soap->omode &= ~SOAP_IO_UDP; /* to force close */
|
|
15756 }
|
|
15757 soap_closesock(soap);
|
|
15758 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Connect/reconnect to '%s' host='%s' path='%s' port=%d\n", endpoint?endpoint:"(null)", soap->host, soap->path, soap->port));
|
|
15759 if (!soap->keep_alive || !soap_valid_socket(soap->socket))
|
|
15760 { soap->socket = soap->fopen(soap, endpoint, soap->host, soap->port);
|
|
15761 if (soap->error)
|
|
15762 return soap->error;
|
|
15763 soap->keep_alive = ((soap->omode & SOAP_IO_KEEPALIVE) != 0);
|
|
15764 }
|
|
15765 }
|
|
15766 }
|
|
15767 #ifdef WITH_NTLM
|
|
15768 if (soap_ntlm_handshake(soap, SOAP_GET, endpoint, soap->host, soap->port))
|
|
15769 return soap->error;
|
|
15770 #endif
|
|
15771 count = soap_count_attachments(soap);
|
|
15772 if (soap_begin_send(soap))
|
|
15773 return soap->error;
|
|
15774 if (http_command == SOAP_GET)
|
|
15775 { soap->mode &= ~SOAP_IO;
|
|
15776 soap->mode |= SOAP_IO_BUFFER;
|
|
15777 }
|
|
15778 #ifndef WITH_NOHTTP
|
|
15779 if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML) && endpoint)
|
|
15780 { unsigned int k = soap->mode;
|
|
15781 soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB);
|
|
15782 if ((k & SOAP_IO) != SOAP_IO_FLUSH)
|
|
15783 soap->mode |= SOAP_IO_BUFFER;
|
|
15784 if ((soap->error = soap->fpost(soap, endpoint, soap->host, soap->port, soap->path, action, count)))
|
|
15785 return soap->error;
|
|
15786 #ifndef WITH_LEANER
|
|
15787 if ((k & SOAP_IO) == SOAP_IO_CHUNK)
|
|
15788 { if (soap_flush(soap))
|
|
15789 return soap->error;
|
|
15790 }
|
|
15791 #endif
|
|
15792 soap->mode = k;
|
|
15793 }
|
|
15794 if (http_command == SOAP_GET || http_command == SOAP_DEL)
|
|
15795 return soap_end_send_flush(soap);
|
|
15796 #endif
|
|
15797 return SOAP_OK;
|
|
15798 }
|
|
15799 #endif
|
|
15800
|
|
15801 /******************************************************************************/
|
|
15802 #ifdef WITH_NTLM
|
|
15803 #ifndef PALM_1
|
|
15804 static int
|
|
15805 soap_ntlm_handshake(struct soap *soap, int command, const char *endpoint, const char *host, int port)
|
|
15806 { /* requires libntlm from http://www.nongnu.org/libntlm/ */
|
|
15807 const char *userid = (soap->proxy_userid ? soap->proxy_userid : soap->userid);
|
|
15808 const char *passwd = (soap->proxy_passwd ? soap->proxy_passwd : soap->passwd);
|
|
15809 struct SOAP_ENV__Header *oldheader;
|
|
15810 if (soap->ntlm_challenge && userid && passwd && soap->authrealm)
|
|
15811 { tSmbNtlmAuthRequest req;
|
|
15812 tSmbNtlmAuthResponse res;
|
|
15813 tSmbNtlmAuthChallenge ch;
|
|
15814 short k = soap->keep_alive;
|
|
15815 size_t l = soap->length;
|
|
15816 size_t c = soap->count;
|
|
15817 soap_mode m = soap->mode, o = soap->omode;
|
|
15818 int s = soap->status;
|
|
15819 char *a = soap->action;
|
|
15820 short v = soap->version;
|
|
15821 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "NTLM '%s'\n", soap->ntlm_challenge));
|
|
15822 if (!*soap->ntlm_challenge)
|
|
15823 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "NTLM S->C Type 1: received NTLM authentication challenge from server\n"));
|
|
15824 /* S -> C 401 Unauthorized
|
|
15825 WWW-Authenticate: NTLM
|
|
15826 */
|
|
15827 buildSmbNtlmAuthRequest(&req, userid, soap->authrealm);
|
|
15828 soap->ntlm_challenge = soap_s2base64(soap, (unsigned char*)&req, NULL, SmbLength(&req));
|
|
15829 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "NTLM C->S Type 2: sending NTLM authorization to server\nAuthorization: NTLM %s\n", soap->ntlm_challenge));
|
|
15830 /* C -> S GET ...
|
|
15831 Authorization: NTLM TlRMTVNTUAABAAAAA7IAAAoACgApAAAACQAJACAAAABMSUdIVENJVFlVUlNBLU1JTk9S
|
|
15832 */
|
|
15833 soap->omode = SOAP_IO_BUFFER;
|
|
15834 if (soap_begin_send(soap))
|
|
15835 return soap->error;
|
|
15836 soap->keep_alive = 1;
|
|
15837 soap->status = command;
|
|
15838 if (soap->fpost(soap, endpoint, host, port, soap->path, soap->action, 0)
|
|
15839 || soap_end_send_flush(soap))
|
|
15840 return soap->error;
|
|
15841 soap->mode = m;
|
|
15842 soap->keep_alive = k;
|
|
15843 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "NTLM S->C Type 2: waiting on server NTLM response\n"));
|
|
15844 oldheader = soap->header;
|
|
15845 if (soap_begin_recv(soap))
|
|
15846 if (soap->error == SOAP_EOF)
|
|
15847 return soap->error;
|
|
15848 soap_end_recv(soap);
|
|
15849 soap->header = oldheader;
|
|
15850 soap->length = l;
|
|
15851 if (soap->status != 401 && soap->status != 407)
|
|
15852 return soap->error = SOAP_NTLM_ERROR;
|
|
15853 soap->error = SOAP_OK;
|
|
15854 }
|
|
15855 /* S -> C 401 Unauthorized
|
|
15856 WWW-Authenticate: NTLM TlRMTVNTUAACAAAAAAAAACgAAAABggAAU3J2Tm9uY2UAAAAAAAAAAA==
|
|
15857 */
|
|
15858 soap_base642s(soap, soap->ntlm_challenge, (char*)&ch, sizeof(tSmbNtlmAuthChallenge), NULL);
|
|
15859 buildSmbNtlmAuthResponse(&ch, &res, userid, passwd);
|
|
15860 soap->ntlm_challenge = soap_s2base64(soap, (unsigned char*)&res, NULL, SmbLength(&res));
|
|
15861 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "NTLM C->S Type 3: sending NTLM authorization to server\nAuthorization: NTLM %s\n", soap->ntlm_challenge));
|
|
15862 /* C -> S GET ...
|
|
15863 Authorization: NTLM TlRMTVNTUAADAAAAGAAYAHIAAAAYABgAigAAABQAFABAAAAADAAMAFQAAAASABIAYAAAAAAAAACiAAAAAYIAAFUAUgBTAEEALQBNAEkATgBPAFIAWgBhAHAAaABvAGQATABJAEcASABUAEMASQBUAFkArYfKbe/jRoW5xDxHeoxC1gBmfWiS5+iX4OAN4xBKG/IFPwfH3agtPEia6YnhsADT
|
|
15864 */
|
|
15865 soap->userid = NULL;
|
|
15866 soap->passwd = NULL;
|
|
15867 soap->proxy_userid = NULL;
|
|
15868 soap->proxy_passwd = NULL;
|
|
15869 soap->keep_alive = k;
|
|
15870 soap->length = l;
|
|
15871 soap->count = c;
|
|
15872 soap->mode = m;
|
|
15873 soap->omode = o;
|
|
15874 soap->status = s;
|
|
15875 soap->action = a;
|
|
15876 soap->version = v;
|
|
15877 }
|
|
15878 return SOAP_OK;
|
|
15879 }
|
|
15880 #endif
|
|
15881 #endif
|
|
15882
|
|
15883 /******************************************************************************/
|
|
15884 #ifndef WITH_LEAN
|
|
15885 SOAP_FMAC1
|
|
15886 char*
|
|
15887 SOAP_FMAC2
|
|
15888 soap_s2base64(struct soap *soap, const unsigned char *s, char *t, int n)
|
|
15889 { register int i;
|
|
15890 register unsigned long m;
|
|
15891 register char *p;
|
|
15892 if (!t)
|
|
15893 t = (char*)soap_malloc(soap, (n + 2) / 3 * 4 + 1);
|
|
15894 if (!t)
|
|
15895 return NULL;
|
|
15896 p = t;
|
|
15897 t[0] = '\0';
|
|
15898 if (!s)
|
|
15899 return p;
|
|
15900 for (; n > 2; n -= 3, s += 3)
|
|
15901 { m = s[0];
|
|
15902 m = (m << 8) | s[1];
|
|
15903 m = (m << 8) | s[2];
|
|
15904 for (i = 4; i > 0; m >>= 6)
|
|
15905 t[--i] = soap_base64o[m & 0x3F];
|
|
15906 t += 4;
|
|
15907 }
|
|
15908 t[0] = '\0';
|
|
15909 if (n > 0) /* 0 < n <= 2 implies that t[0..4] is allocated (base64 scaling formula) */
|
|
15910 { m = 0;
|
|
15911 for (i = 0; i < n; i++)
|
|
15912 m = (m << 8) | *s++;
|
|
15913 for (; i < 3; i++)
|
|
15914 m <<= 8;
|
|
15915 for (i = 4; i > 0; m >>= 6)
|
|
15916 t[--i] = soap_base64o[m & 0x3F];
|
|
15917 for (i = 3; i > n; i--)
|
|
15918 t[i] = '=';
|
|
15919 t[4] = '\0';
|
|
15920 }
|
|
15921 return p;
|
|
15922 }
|
|
15923 #endif
|
|
15924
|
|
15925 /******************************************************************************/
|
|
15926 #ifndef WITH_LEAN
|
|
15927 SOAP_FMAC1
|
|
15928 const char*
|
|
15929 SOAP_FMAC2
|
|
15930 soap_base642s(struct soap *soap, const char *s, char *t, size_t l, int *n)
|
|
15931 { register size_t i, j;
|
|
15932 register soap_wchar c;
|
|
15933 register unsigned long m;
|
|
15934 register const char *p;
|
|
15935 if (!s || !*s)
|
|
15936 { if (n)
|
|
15937 *n = 0;
|
|
15938 if (soap->error)
|
|
15939 return NULL;
|
|
15940 return SOAP_NON_NULL;
|
|
15941 }
|
|
15942 if (!t)
|
|
15943 { l = (strlen(s) + 3) / 4 * 3 + 1; /* make sure enough space for \0 */
|
|
15944 t = (char*)soap_malloc(soap, l);
|
|
15945 }
|
|
15946 if (!t)
|
|
15947 return NULL;
|
|
15948 p = t;
|
|
15949 if (n)
|
|
15950 *n = 0;
|
|
15951 for (i = 0; ; i += 3, l -= 3)
|
|
15952 { m = 0;
|
|
15953 j = 0;
|
|
15954 while (j < 4)
|
|
15955 { c = *s++;
|
|
15956 if (c == '=' || !c)
|
|
15957 { if (l >= j - 1)
|
|
15958 { switch (j)
|
|
15959 { case 2:
|
|
15960 *t++ = (char)((m >> 4) & 0xFF);
|
|
15961 i++;
|
|
15962 l--;
|
|
15963 break;
|
|
15964 case 3:
|
|
15965 *t++ = (char)((m >> 10) & 0xFF);
|
|
15966 *t++ = (char)((m >> 2) & 0xFF);
|
|
15967 i += 2;
|
|
15968 l -= 2;
|
|
15969 }
|
|
15970 }
|
|
15971 if (n)
|
|
15972 *n = (int)i;
|
|
15973 if (l)
|
|
15974 *t = '\0';
|
|
15975 return p;
|
|
15976 }
|
|
15977 c -= '+';
|
|
15978 if (c >= 0 && c <= 79)
|
|
15979 { int b = soap_base64i[c];
|
|
15980 if (b >= 64)
|
|
15981 { soap->error = SOAP_TYPE;
|
|
15982 return NULL;
|
|
15983 }
|
|
15984 m = (m << 6) + b;
|
|
15985 j++;
|
|
15986 }
|
|
15987 else if (!soap_blank(c + '+'))
|
|
15988 { soap->error = SOAP_TYPE;
|
|
15989 return NULL;
|
|
15990 }
|
|
15991 }
|
|
15992 if (l < 3)
|
|
15993 { if (n)
|
|
15994 *n = (int)i;
|
|
15995 if (l)
|
|
15996 *t = '\0';
|
|
15997 return p;
|
|
15998 }
|
|
15999 *t++ = (char)((m >> 16) & 0xFF);
|
|
16000 *t++ = (char)((m >> 8) & 0xFF);
|
|
16001 *t++ = (char)(m & 0xFF);
|
|
16002 }
|
|
16003 }
|
|
16004 #endif
|
|
16005
|
|
16006 /******************************************************************************/
|
|
16007 #ifndef WITH_LEAN
|
|
16008 SOAP_FMAC1
|
|
16009 char*
|
|
16010 SOAP_FMAC2
|
|
16011 soap_s2hex(struct soap *soap, const unsigned char *s, char *t, int n)
|
|
16012 { register char *p;
|
|
16013 if (!t)
|
|
16014 t = (char*)soap_malloc(soap, 2 * n + 1);
|
|
16015 if (!t)
|
|
16016 return NULL;
|
|
16017 p = t;
|
|
16018 t[0] = '\0';
|
|
16019 if (s)
|
|
16020 { for (; n > 0; n--)
|
|
16021 { register int m = *s++;
|
|
16022 *t++ = (char)((m >> 4) + (m > 159 ? 'a' - 10 : '0'));
|
|
16023 m &= 0x0F;
|
|
16024 *t++ = (char)(m + (m > 9 ? 'a' - 10 : '0'));
|
|
16025 }
|
|
16026 }
|
|
16027 *t++ = '\0';
|
|
16028 return p;
|
|
16029 }
|
|
16030 #endif
|
|
16031
|
|
16032 /******************************************************************************/
|
|
16033 #ifndef WITH_LEAN
|
|
16034 SOAP_FMAC1
|
|
16035 const char*
|
|
16036 SOAP_FMAC2
|
|
16037 soap_hex2s(struct soap *soap, const char *s, char *t, size_t l, int *n)
|
|
16038 { register const char *p;
|
|
16039 if (!s || !*s)
|
|
16040 { if (n)
|
|
16041 *n = 0;
|
|
16042 if (soap->error)
|
|
16043 return NULL;
|
|
16044 return SOAP_NON_NULL;
|
|
16045 }
|
|
16046 if (!t)
|
|
16047 { l = strlen(s) / 2 + 1; /* make sure enough space for \0 */
|
|
16048 t = (char*)soap_malloc(soap, l);
|
|
16049 }
|
|
16050 if (!t)
|
|
16051 return NULL;
|
|
16052 p = t;
|
|
16053 while (l)
|
|
16054 { register int d1, d2;
|
|
16055 d1 = *s++;
|
|
16056 if (!d1)
|
|
16057 break;
|
|
16058 d2 = *s++;
|
|
16059 if (!d2)
|
|
16060 break;
|
|
16061 *t++ = (char)(((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'));
|
|
16062 l--;
|
|
16063 }
|
|
16064 if (n)
|
|
16065 *n = (int)(t - p);
|
|
16066 if (l)
|
|
16067 *t = '\0';
|
|
16068 return p;
|
|
16069 }
|
|
16070 #endif
|
|
16071
|
|
16072 /******************************************************************************/
|
|
16073 #ifndef WITH_NOHTTP
|
|
16074 #ifndef PALM_1
|
|
16075 SOAP_FMAC1
|
|
16076 int
|
|
16077 SOAP_FMAC2
|
|
16078 soap_puthttphdr(struct soap *soap, int status, size_t count)
|
|
16079 { if (soap->status != SOAP_GET && soap->status != SOAP_DEL && soap->status != SOAP_CONNECT)
|
|
16080 { register const char *s = "text/xml; charset=utf-8";
|
|
16081 register int err = SOAP_OK;
|
|
16082 #ifndef WITH_LEANER
|
|
16083 register const char *r = NULL;
|
|
16084 #endif
|
|
16085 if ((status == SOAP_FILE || soap->status == SOAP_PUT || soap->status == SOAP_POST_FILE) && soap->http_content && !strchr(s, 10) && !strchr(s, 13))
|
|
16086 s = soap->http_content;
|
|
16087 else if (status == SOAP_HTML)
|
|
16088 s = "text/html; charset=utf-8";
|
|
16089 else if (count || ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK))
|
|
16090 { if (soap->version == 2)
|
|
16091 s = "application/soap+xml; charset=utf-8";
|
|
16092 }
|
|
16093 #ifndef WITH_LEANER
|
|
16094 if (soap->mode & (SOAP_ENC_DIME | SOAP_ENC_MTOM))
|
|
16095 { if (soap->mode & SOAP_ENC_MTOM)
|
|
16096 { if (soap->version == 2)
|
|
16097 r = "application/soap+xml";
|
|
16098 else
|
|
16099 r = "text/xml";
|
|
16100 s = "application/xop+xml";
|
|
16101 }
|
|
16102 else
|
|
16103 s = "application/dime";
|
|
16104 }
|
|
16105 if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && strlen(soap->mime.boundary) + strlen(soap->mime.start ? soap->mime.start : SOAP_STR_EOS) < sizeof(soap->tmpbuf) - 80)
|
|
16106 { register const char *t;
|
|
16107 #ifdef HAVE_SNPRINTF
|
|
16108 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "multipart/related; charset=utf-8; boundary=\"%s\"; type=\"", soap->mime.boundary);
|
|
16109 #else
|
|
16110 sprintf(soap->tmpbuf, "multipart/related; charset=utf-8; boundary=\"%s\"; type=\"", soap->mime.boundary);
|
|
16111 #endif
|
|
16112 t = strchr(s, ';');
|
|
16113 if (t)
|
|
16114 strncat(soap->tmpbuf, s, t - s);
|
|
16115 else
|
|
16116 strcat(soap->tmpbuf, s);
|
|
16117 if (soap->mime.start && strlen(soap->tmpbuf) + strlen(soap->mime.start) + 11 < sizeof(soap->tmpbuf))
|
|
16118 { strcat(soap->tmpbuf, "\"; start=\"");
|
|
16119 strcat(soap->tmpbuf, soap->mime.start);
|
|
16120 }
|
|
16121 strcat(soap->tmpbuf, "\"");
|
|
16122 if (r && strlen(soap->tmpbuf) + strlen(r) + 15 < sizeof(soap->tmpbuf))
|
|
16123 { strcat(soap->tmpbuf, "; start-info=\"");
|
|
16124 strcat(soap->tmpbuf, r);
|
|
16125 strcat(soap->tmpbuf, "\"");
|
|
16126 }
|
|
16127 }
|
|
16128 else
|
|
16129 strncpy(soap->tmpbuf, s, sizeof(soap->tmpbuf));
|
|
16130 soap->tmpbuf[sizeof(soap->tmpbuf) - 1] = '\0';
|
|
16131 s = soap->tmpbuf;
|
|
16132 if (status == SOAP_OK && soap->version == 2 && soap->action && strlen(soap->action) + strlen(s) < sizeof(soap->tmpbuf) - 80)
|
|
16133 {
|
|
16134 #ifdef HAVE_SNPRINTF
|
|
16135 size_t l = strlen(s);
|
|
16136 soap_snprintf(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, "; action=\"%s\"", soap->action);
|
|
16137 #else
|
|
16138 sprintf(soap->tmpbuf + strlen(s), "; action=\"%s\"", soap->action);
|
|
16139 #endif
|
|
16140 }
|
|
16141 #endif
|
|
16142 if ((err = soap->fposthdr(soap, "Content-Type", s)))
|
|
16143 return err;
|
|
16144 #ifdef WITH_ZLIB
|
|
16145 if ((soap->omode & SOAP_ENC_ZLIB))
|
|
16146 {
|
|
16147 #ifdef WITH_GZIP
|
|
16148 err = soap->fposthdr(soap, "Content-Encoding", soap->zlib_out == SOAP_ZLIB_DEFLATE ? "deflate" : "gzip");
|
|
16149 #else
|
|
16150 err = soap->fposthdr(soap, "Content-Encoding", "deflate");
|
|
16151 #endif
|
|
16152 if (err)
|
|
16153 return err;
|
|
16154 }
|
|
16155 #endif
|
|
16156 #ifndef WITH_LEANER
|
|
16157 if ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK)
|
|
16158 err = soap->fposthdr(soap, "Transfer-Encoding", "chunked");
|
|
16159 else
|
|
16160 #endif
|
|
16161 if (s)
|
|
16162 {
|
|
16163 #ifdef HAVE_SNPRINTF
|
|
16164 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%lu", (unsigned long)count);
|
|
16165 #else
|
|
16166 sprintf(soap->tmpbuf, "%lu", (unsigned long)count);
|
|
16167 #endif
|
|
16168 err = soap->fposthdr(soap, "Content-Length", soap->tmpbuf);
|
|
16169 }
|
|
16170 if (err)
|
|
16171 return err;
|
|
16172 }
|
|
16173 return soap->fposthdr(soap, "Connection", soap->keep_alive ? "keep-alive" : "close");
|
|
16174 }
|
|
16175 #endif
|
|
16176 #endif
|
|
16177
|
|
16178 /******************************************************************************/
|
|
16179 #ifndef WITH_LEAN
|
|
16180 static const char*
|
|
16181 soap_set_validation_fault(struct soap *soap, const char *s, const char *t)
|
|
16182 { if (!t)
|
|
16183 t = SOAP_STR_EOS;
|
|
16184 if (*soap->tag)
|
|
16185 {
|
|
16186 #ifdef HAVE_SNPRINTF
|
|
16187 soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "Validation constraint violation: %s%s in element '%s'", s, t ? t : SOAP_STR_EOS, soap->tag);
|
|
16188 #else
|
|
16189 if (strlen(soap->tag) + strlen(t) < sizeof(soap->msgbuf) - 100)
|
|
16190 sprintf(soap->msgbuf, "Validation constraint violation: %s%s in element '%s'", s, t, soap->tag);
|
|
16191 else
|
|
16192 sprintf(soap->msgbuf, "Validation constraint violation: %s", s);
|
|
16193 #endif
|
|
16194 }
|
|
16195 else
|
|
16196 {
|
|
16197 #ifdef HAVE_SNPRINTF
|
|
16198 soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "Validation constraint violation: %s%s", s, t ? t : SOAP_STR_EOS);
|
|
16199 #else
|
|
16200 if (strlen(soap->tag) + strlen(t) < sizeof(soap->msgbuf) - 100)
|
|
16201 sprintf(soap->msgbuf, "Validation constraint violation: %s%s", s, t);
|
|
16202 else
|
|
16203 sprintf(soap->msgbuf, "Validation constraint violation: %s", s);
|
|
16204 #endif
|
|
16205 }
|
|
16206 return soap->msgbuf;
|
|
16207 }
|
|
16208 #endif
|
|
16209
|
|
16210 /******************************************************************************/
|
|
16211 #ifndef PALM_1
|
|
16212 SOAP_FMAC1
|
|
16213 void
|
|
16214 SOAP_FMAC2
|
|
16215 soap_set_fault(struct soap *soap)
|
|
16216 { const char **c = soap_faultcode(soap);
|
|
16217 const char **s = soap_faultstring(soap);
|
|
16218 if (soap->fseterror)
|
|
16219 soap->fseterror(soap, c, s);
|
|
16220 if (!*c)
|
|
16221 { if (soap->version == 2)
|
|
16222 *c = "SOAP-ENV:Sender";
|
|
16223 else
|
|
16224 *c = "SOAP-ENV:Client";
|
|
16225 }
|
|
16226 if (*s)
|
|
16227 return;
|
|
16228 switch (soap->error)
|
|
16229 {
|
|
16230 #ifndef WITH_LEAN
|
|
16231 case SOAP_CLI_FAULT:
|
|
16232 *s = "Client fault";
|
|
16233 break;
|
|
16234 case SOAP_SVR_FAULT:
|
|
16235 *s = "Server fault";
|
|
16236 break;
|
|
16237 case SOAP_TAG_MISMATCH:
|
|
16238 *s = soap_set_validation_fault(soap, "tag name or namespace mismatch", NULL);
|
|
16239 break;
|
|
16240 case SOAP_TYPE:
|
|
16241 *s = soap_set_validation_fault(soap, "data type mismatch ", soap->type);
|
|
16242 break;
|
|
16243 case SOAP_SYNTAX_ERROR:
|
|
16244 *s = "Well-formedness violation";
|
|
16245 break;
|
|
16246 case SOAP_NO_TAG:
|
|
16247 *s = "No tag: no XML root element or missing SOAP message body element";
|
|
16248 break;
|
|
16249 case SOAP_MUSTUNDERSTAND:
|
|
16250 *c = "SOAP-ENV:MustUnderstand";
|
|
16251 #ifdef HAVE_SNPRINTF
|
|
16252 soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "The data in element '%s' must be understood but cannot be handled", soap->tag);
|
|
16253 #else
|
|
16254 strncpy(soap->msgbuf, soap->tag, sizeof(soap->msgbuf));
|
|
16255 soap->msgbuf[sizeof(soap->msgbuf) - 1] = '\0';
|
|
16256 #endif
|
|
16257 *s = soap->msgbuf;
|
|
16258 break;
|
|
16259 case SOAP_VERSIONMISMATCH:
|
|
16260 *c = "SOAP-ENV:VersionMismatch";
|
|
16261 *s = "Invalid SOAP message or SOAP version mismatch";
|
|
16262 break;
|
|
16263 case SOAP_DATAENCODINGUNKNOWN:
|
|
16264 *c = "SOAP-ENV:DataEncodingUnknown";
|
|
16265 *s = "Unsupported SOAP data encoding";
|
|
16266 break;
|
|
16267 case SOAP_NAMESPACE:
|
|
16268 *s = soap_set_validation_fault(soap, "namespace error", NULL);
|
|
16269 break;
|
|
16270 case SOAP_USER_ERROR:
|
|
16271 *s = "User data error";
|
|
16272 break;
|
|
16273 case SOAP_FATAL_ERROR:
|
|
16274 *s = "Fatal error";
|
|
16275 break;
|
|
16276 case SOAP_NO_METHOD:
|
|
16277 #ifdef HAVE_SNPRINTF
|
|
16278 soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "Method '%s' not implemented: method name or namespace not recognized", soap->tag);
|
|
16279 #else
|
|
16280 sprintf(soap->msgbuf, "Method '%s' not implemented: method name or namespace not recognized", soap->tag);
|
|
16281 #endif
|
|
16282 *s = soap->msgbuf;
|
|
16283 break;
|
|
16284 case SOAP_NO_DATA:
|
|
16285 *s = "Data required for operation";
|
|
16286 break;
|
|
16287 case SOAP_GET_METHOD:
|
|
16288 *s = "HTTP GET method not implemented";
|
|
16289 break;
|
|
16290 case SOAP_PUT_METHOD:
|
|
16291 *s = "HTTP PUT method not implemented";
|
|
16292 break;
|
|
16293 case SOAP_HTTP_METHOD:
|
|
16294 *s = "HTTP method not implemented";
|
|
16295 break;
|
|
16296 case SOAP_EOM:
|
|
16297 *s = "Out of memory";
|
|
16298 break;
|
|
16299 case SOAP_MOE:
|
|
16300 *s = "Memory overflow or memory corruption error";
|
|
16301 break;
|
|
16302 case SOAP_HDR:
|
|
16303 *s = "Header line too long";
|
|
16304 break;
|
|
16305 case SOAP_IOB:
|
|
16306 *s = "Array index out of bounds";
|
|
16307 break;
|
|
16308 case SOAP_NULL:
|
|
16309 *s = soap_set_validation_fault(soap, "nil not allowed", NULL);
|
|
16310 break;
|
|
16311 case SOAP_DUPLICATE_ID:
|
|
16312 *s = soap_set_validation_fault(soap, "multiple elements (use the SOAP_XML_TREE flag) with duplicate id ", soap->id);
|
|
16313 if (soap->version == 2)
|
|
16314 *soap_faultsubcode(soap) = "SOAP-ENC:DuplicateID";
|
|
16315 break;
|
|
16316 case SOAP_MISSING_ID:
|
|
16317 *s = soap_set_validation_fault(soap, "missing id for ref ", soap->id);
|
|
16318 if (soap->version == 2)
|
|
16319 *soap_faultsubcode(soap) = "SOAP-ENC:MissingID";
|
|
16320 break;
|
|
16321 case SOAP_HREF:
|
|
16322 *s = soap_set_validation_fault(soap, "incompatible object type id-ref ", soap->id);
|
|
16323 break;
|
|
16324 case SOAP_FAULT:
|
|
16325 break;
|
|
16326 #ifndef WITH_NOIO
|
|
16327 case SOAP_UDP_ERROR:
|
|
16328 *s = "Message too large for UDP packet";
|
|
16329 break;
|
|
16330 case SOAP_TCP_ERROR:
|
|
16331 *s = tcp_error(soap);
|
|
16332 break;
|
|
16333 #endif
|
|
16334 case SOAP_HTTP_ERROR:
|
|
16335 *s = "An HTTP processing error occurred";
|
|
16336 break;
|
|
16337 case SOAP_NTLM_ERROR:
|
|
16338 *s = "An HTTP NTLM authentication error occurred";
|
|
16339 break;
|
|
16340 case SOAP_SSL_ERROR:
|
|
16341 #ifdef WITH_OPENSSL
|
|
16342 *s = "SSL/TLS error";
|
|
16343 #else
|
|
16344 *s = "OpenSSL not installed: recompile with -DWITH_OPENSSL";
|
|
16345 #endif
|
|
16346 break;
|
|
16347 case SOAP_PLUGIN_ERROR:
|
|
16348 *s = "Plugin registry error";
|
|
16349 break;
|
|
16350 case SOAP_DIME_ERROR:
|
|
16351 *s = "DIME format error or max DIME size exceeds SOAP_MAXDIMESIZE";
|
|
16352 break;
|
|
16353 case SOAP_DIME_HREF:
|
|
16354 *s = "DIME href to missing attachment";
|
|
16355 break;
|
|
16356 case SOAP_DIME_MISMATCH:
|
|
16357 *s = "DIME version/transmission error";
|
|
16358 break;
|
|
16359 case SOAP_DIME_END:
|
|
16360 *s = "End of DIME error";
|
|
16361 break;
|
|
16362 case SOAP_MIME_ERROR:
|
|
16363 *s = "MIME format error";
|
|
16364 break;
|
|
16365 case SOAP_MIME_HREF:
|
|
16366 *s = "MIME href to missing attachment";
|
|
16367 break;
|
|
16368 case SOAP_MIME_END:
|
|
16369 *s = "End of MIME error";
|
|
16370 break;
|
|
16371 case SOAP_ZLIB_ERROR:
|
|
16372 #ifdef WITH_ZLIB
|
|
16373 #ifdef HAVE_SNPRINTF
|
|
16374 soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "Zlib/gzip error: '%s'", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS);
|
|
16375 #else
|
|
16376 sprintf(soap->msgbuf, "Zlib/gzip error: '%s'", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS);
|
|
16377 #endif
|
|
16378 *s = soap->msgbuf;
|
|
16379 #else
|
|
16380 *s = "Zlib/gzip not installed for (de)compression: recompile with -DWITH_GZIP";
|
|
16381 #endif
|
|
16382 break;
|
|
16383 case SOAP_REQUIRED:
|
|
16384 *s = soap_set_validation_fault(soap, "missing required attribute", NULL);
|
|
16385 break;
|
|
16386 case SOAP_PROHIBITED:
|
|
16387 *s = soap_set_validation_fault(soap, "prohibited attribute present", NULL);
|
|
16388 break;
|
|
16389 case SOAP_OCCURS:
|
|
16390 *s = soap_set_validation_fault(soap, "occurrence violation", NULL);
|
|
16391 break;
|
|
16392 case SOAP_LENGTH:
|
|
16393 *s = soap_set_validation_fault(soap, "content range or length violation", NULL);
|
|
16394 break;
|
|
16395 case SOAP_FD_EXCEEDED:
|
|
16396 *s = "Maximum number of open connections was reached (no define HAVE_POLL): increase FD_SETSIZE";
|
|
16397 break;
|
|
16398 case SOAP_UTF_ERROR:
|
|
16399 *s = "UTF content encoding error";
|
|
16400 break;
|
|
16401 case SOAP_STOP:
|
|
16402 *s = "Stopped: no response sent or received (informative)";
|
|
16403 break;
|
|
16404 #endif
|
|
16405 case SOAP_EOF:
|
|
16406 #ifndef WITH_NOIO
|
|
16407 *s = soap_strerror(soap); /* *s = soap->msgbuf */
|
|
16408 #ifndef WITH_LEAN
|
|
16409 if (strlen(soap->msgbuf) + 25 < sizeof(soap->msgbuf))
|
|
16410 { memmove(soap->msgbuf + 25, soap->msgbuf, strlen(soap->msgbuf) + 1);
|
|
16411 memcpy(soap->msgbuf, "End of file or no input: ", 25);
|
|
16412 }
|
|
16413 #endif
|
|
16414 break;
|
|
16415 #else
|
|
16416 *s = "End of file or no input";
|
|
16417 break;
|
|
16418 #endif
|
|
16419 default:
|
|
16420 #ifndef WITH_NOHTTP
|
|
16421 #ifndef WITH_LEAN
|
|
16422 if (soap->error > 200 && soap->error < 600)
|
|
16423 {
|
|
16424 #ifdef HAVE_SNPRINTF
|
|
16425 soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "HTTP Error: %d %s", soap->error, http_error(soap, soap->error));
|
|
16426 #else
|
|
16427 sprintf(soap->msgbuf, "HTTP Error: %d %s", soap->error, http_error(soap, soap->error));
|
|
16428 #endif
|
|
16429 *s = soap->msgbuf;
|
|
16430 }
|
|
16431 else
|
|
16432 #endif
|
|
16433 #endif
|
|
16434 {
|
|
16435 #ifdef HAVE_SNPRINTF
|
|
16436 soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "Error %d", soap->error);
|
|
16437 #else
|
|
16438 sprintf(soap->msgbuf, "Error %d", soap->error);
|
|
16439 #endif
|
|
16440 *s = soap->msgbuf;
|
|
16441 }
|
|
16442 }
|
|
16443 }
|
|
16444 #endif
|
|
16445
|
|
16446 /******************************************************************************/
|
|
16447 #ifndef PALM_1
|
|
16448 SOAP_FMAC1
|
|
16449 int
|
|
16450 SOAP_FMAC2
|
|
16451 soap_send_fault(struct soap *soap)
|
|
16452 { register int status = soap->error;
|
|
16453 if (status == SOAP_OK || status == SOAP_STOP)
|
|
16454 return soap_closesock(soap);
|
|
16455 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Sending back fault struct for error code %d\n", soap->error));
|
|
16456 soap->keep_alive = 0; /* to terminate connection */
|
|
16457 soap_set_fault(soap);
|
|
16458 if (soap->error < 200 && soap->error != SOAP_FAULT)
|
|
16459 soap->header = NULL;
|
|
16460 if (status != SOAP_EOF || (!soap->recv_timeout && !soap->send_timeout))
|
|
16461 { register int r = 1;
|
|
16462 #ifndef WITH_NOIO
|
|
16463 if (soap->fpoll && soap->fpoll(soap))
|
|
16464 r = 0;
|
|
16465 #ifndef WITH_LEAN
|
|
16466 else if (soap_valid_socket(soap->socket))
|
|
16467 { r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_SND, 0);
|
|
16468 if (r > 0)
|
|
16469 { int t;
|
|
16470 if (!(r & SOAP_TCP_SELECT_SND)
|
|
16471 || ((r & SOAP_TCP_SELECT_RCV)
|
|
16472 && recv(soap->socket, (char*)&t, 1, MSG_PEEK) < 0))
|
|
16473 r = 0;
|
|
16474 }
|
|
16475 }
|
|
16476 #endif
|
|
16477 #endif
|
|
16478 if (r > 0)
|
|
16479 { soap->error = SOAP_OK;
|
|
16480 soap->encodingStyle = NULL; /* no encodingStyle in Faults */
|
|
16481 soap_serializeheader(soap);
|
|
16482 soap_serializefault(soap);
|
|
16483 soap_begin_count(soap);
|
|
16484 if (soap->mode & SOAP_IO_LENGTH)
|
|
16485 { soap_envelope_begin_out(soap);
|
|
16486 soap_putheader(soap);
|
|
16487 soap_body_begin_out(soap);
|
|
16488 soap_putfault(soap);
|
|
16489 soap_body_end_out(soap);
|
|
16490 soap_envelope_end_out(soap);
|
|
16491 }
|
|
16492 soap_end_count(soap);
|
|
16493 if (soap_response(soap, status)
|
|
16494 || soap_envelope_begin_out(soap)
|
|
16495 || soap_putheader(soap)
|
|
16496 || soap_body_begin_out(soap)
|
|
16497 || soap_putfault(soap)
|
|
16498 || soap_body_end_out(soap)
|
|
16499 || soap_envelope_end_out(soap))
|
|
16500 return soap_closesock(soap);
|
|
16501 soap_end_send(soap);
|
|
16502 }
|
|
16503 }
|
|
16504 soap->error = status;
|
|
16505 return soap_closesock(soap);
|
|
16506 }
|
|
16507 #endif
|
|
16508
|
|
16509 /******************************************************************************/
|
|
16510 #ifndef PALM_1
|
|
16511 SOAP_FMAC1
|
|
16512 int
|
|
16513 SOAP_FMAC2
|
|
16514 soap_recv_fault(struct soap *soap, int check)
|
|
16515 { register int status = soap->error;
|
|
16516 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Check if receiving SOAP Fault\n"));
|
|
16517 if (!check)
|
|
16518 { /* try getfault when no tag or tag mismatched at level 2, otherwise ret */
|
|
16519 if (soap->error != SOAP_NO_TAG
|
|
16520 && (soap->error != SOAP_TAG_MISMATCH || soap->level != 2))
|
|
16521 return soap->error;
|
|
16522 }
|
|
16523 else if (soap->version == 0) /* check == 1 but no SOAP: do not parse SOAP Fault */
|
|
16524 return SOAP_OK;
|
|
16525 soap->error = SOAP_OK;
|
|
16526 if (soap_getfault(soap))
|
|
16527 { /* check flag set: check if SOAP Fault is present, if not just return */
|
|
16528 if (check && soap->error == SOAP_TAG_MISMATCH && soap->level == 2)
|
|
16529 return soap->error = SOAP_OK;
|
|
16530 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Error: soap_get_soapfault() failed at level %u tag '%s'\n", soap->level, soap->tag));
|
|
16531 *soap_faultcode(soap) = (soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client");
|
|
16532 soap->error = status;
|
|
16533 soap_set_fault(soap);
|
|
16534 }
|
|
16535 else
|
|
16536 { register const char *s = *soap_faultcode(soap);
|
|
16537 if (!soap_match_tag(soap, s, "SOAP-ENV:Server") || !soap_match_tag(soap, s, "SOAP-ENV:Receiver"))
|
|
16538 status = SOAP_SVR_FAULT;
|
|
16539 else if (!soap_match_tag(soap, s, "SOAP-ENV:Client") || !soap_match_tag(soap, s, "SOAP-ENV:Sender"))
|
|
16540 status = SOAP_CLI_FAULT;
|
|
16541 else if (!soap_match_tag(soap, s, "SOAP-ENV:MustUnderstand"))
|
|
16542 status = SOAP_MUSTUNDERSTAND;
|
|
16543 else if (!soap_match_tag(soap, s, "SOAP-ENV:VersionMismatch"))
|
|
16544 status = SOAP_VERSIONMISMATCH;
|
|
16545 else
|
|
16546 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Received SOAP Fault code %s\n", s));
|
|
16547 status = SOAP_FAULT;
|
|
16548 }
|
|
16549 if (!soap_body_end_in(soap))
|
|
16550 soap_envelope_end_in(soap);
|
|
16551 }
|
|
16552 soap_end_recv(soap);
|
|
16553 soap->error = status;
|
|
16554 return soap_closesock(soap);
|
|
16555 }
|
|
16556 #endif
|
|
16557
|
|
16558 /******************************************************************************/
|
|
16559 #ifndef WITH_NOHTTP
|
|
16560 #ifndef PALM_1
|
|
16561 SOAP_FMAC1
|
|
16562 int
|
|
16563 SOAP_FMAC2
|
|
16564 soap_send_empty_response(struct soap *soap, int httpstatuscode)
|
|
16565 { register soap_mode m = soap->omode;
|
|
16566 if (!(m & SOAP_IO_UDP))
|
|
16567 { soap->count = 0;
|
|
16568 if ((m & SOAP_IO) == SOAP_IO_CHUNK)
|
|
16569 soap->omode = (m & ~SOAP_IO) | SOAP_IO_BUFFER;
|
|
16570 soap_response(soap, httpstatuscode);
|
|
16571 soap_end_send(soap); /* force end of sends */
|
|
16572 soap->error = SOAP_STOP; /* stops the server (from returning a response) */
|
|
16573 soap->omode = m;
|
|
16574 }
|
|
16575 return soap_closesock(soap);
|
|
16576 }
|
|
16577 #endif
|
|
16578 #endif
|
|
16579
|
|
16580 /******************************************************************************/
|
|
16581 #ifndef WITH_NOHTTP
|
|
16582 #ifndef PALM_1
|
|
16583 SOAP_FMAC1
|
|
16584 int
|
|
16585 SOAP_FMAC2
|
|
16586 soap_recv_empty_response(struct soap *soap)
|
|
16587 { if (!(soap->omode & SOAP_IO_UDP))
|
|
16588 { if (!soap_begin_recv(soap))
|
|
16589 {
|
|
16590 #ifndef WITH_LEAN
|
|
16591 if (soap->body)
|
|
16592 soap_get_http_body(soap, NULL); /* read (empty?) HTTP body and discard */
|
|
16593 #endif
|
|
16594 soap_end_recv(soap);
|
|
16595 }
|
|
16596 else if (soap->error == SOAP_NO_DATA || soap->error == 202)
|
|
16597 soap->error = SOAP_OK;
|
|
16598 }
|
|
16599 return soap_closesock(soap);
|
|
16600 }
|
|
16601 #endif
|
|
16602 #endif
|
|
16603
|
|
16604 /******************************************************************************/
|
|
16605 #ifndef WITH_NOIO
|
|
16606 #ifndef PALM_1
|
|
16607 static const char*
|
|
16608 soap_strerror(struct soap *soap)
|
|
16609 { register int err = soap->errnum;
|
|
16610 *soap->msgbuf = '\0';
|
|
16611 if (err)
|
|
16612 {
|
|
16613 #ifndef WIN32
|
|
16614 # ifdef HAVE_STRERROR_R
|
|
16615 # ifdef _GNU_SOURCE
|
|
16616 return strerror_r(err, soap->msgbuf, sizeof(soap->msgbuf)); /* GNU-specific */
|
|
16617 # else
|
|
16618 strerror_r(err, soap->msgbuf, sizeof(soap->msgbuf)); /* XSI-compliant */
|
|
16619 # endif
|
|
16620 # else
|
|
16621 return strerror(err);
|
|
16622 # endif
|
|
16623 #else
|
|
16624 #ifndef UNDER_CE
|
|
16625 DWORD len;
|
|
16626 *soap->msgbuf = '\0';
|
|
16627 len = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)soap->msgbuf, (DWORD)sizeof(soap->msgbuf), NULL);
|
|
16628 #else
|
|
16629 DWORD i, len;
|
|
16630 *soap->msgbuf = '\0';
|
|
16631 len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, 0, (LPTSTR)soap->msgbuf, (DWORD)(sizeof(soap->msgbuf)/sizeof(TCHAR)), NULL);
|
|
16632 for (i = 0; i <= len; i++)
|
|
16633 { if (((TCHAR*)soap->msgbuf)[i] < 0x80)
|
|
16634 soap->msgbuf[i] = (char)((TCHAR*)soap->msgbuf)[i];
|
|
16635 else
|
|
16636 soap->msgbuf[i] = '?';
|
|
16637 }
|
|
16638 #endif
|
|
16639 #endif
|
|
16640 }
|
|
16641 else
|
|
16642 { char *s = soap->msgbuf;
|
|
16643 #ifndef WITH_LEAN
|
|
16644 int rt = soap->recv_timeout, st = soap->send_timeout;
|
|
16645 int ru = ' ', su = ' ';
|
|
16646 #endif
|
|
16647 strcpy(s, "Operation interrupted or timed out");
|
|
16648 #ifndef WITH_LEAN
|
|
16649 if (rt < 0)
|
|
16650 { rt = -rt;
|
|
16651 ru = 'u';
|
|
16652 }
|
|
16653 if (st < 0)
|
|
16654 { st = -st;
|
|
16655 su = 'u';
|
|
16656 }
|
|
16657 if (rt)
|
|
16658 {
|
|
16659 #ifdef HAVE_SNPRINTF
|
|
16660 size_t l = strlen(s);
|
|
16661 soap_snprintf(s + l, sizeof(soap->msgbuf) - l, " (%d%cs recv delay)", rt, ru);
|
|
16662 #else
|
|
16663 sprintf(s + strlen(s), " (%d%cs recv delay)", rt, ru);
|
|
16664 #endif
|
|
16665 }
|
|
16666 if (st)
|
|
16667 {
|
|
16668 #ifdef HAVE_SNPRINTF
|
|
16669 size_t l = strlen(s);
|
|
16670 soap_snprintf(s + l, sizeof(soap->msgbuf) - l, " (%d%cs send delay)", st, su);
|
|
16671 #else
|
|
16672 sprintf(s + strlen(s), " (%d%cs send delay)", st, su);
|
|
16673 #endif
|
|
16674 }
|
|
16675 #endif
|
|
16676 }
|
|
16677 return soap->msgbuf;
|
|
16678 }
|
|
16679 #endif
|
|
16680 #endif
|
|
16681
|
|
16682 /******************************************************************************/
|
|
16683 #ifndef PALM_2
|
|
16684 static int
|
|
16685 soap_set_error(struct soap *soap, const char *faultcode, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML, int soaperror)
|
|
16686 { *soap_faultcode(soap) = faultcode;
|
|
16687 if (faultsubcodeQName)
|
|
16688 *soap_faultsubcode(soap) = faultsubcodeQName;
|
|
16689 *soap_faultstring(soap) = faultstring;
|
|
16690 if (faultdetailXML && *faultdetailXML)
|
|
16691 { register const char **s = soap_faultdetail(soap);
|
|
16692 if (s)
|
|
16693 *s = faultdetailXML;
|
|
16694 }
|
|
16695 return soap->error = soaperror;
|
|
16696 }
|
|
16697 #endif
|
|
16698
|
|
16699 /******************************************************************************/
|
|
16700 #ifndef PALM_2
|
|
16701 SOAP_FMAC1
|
|
16702 int
|
|
16703 SOAP_FMAC2
|
|
16704 soap_set_sender_error(struct soap *soap, const char *faultstring, const char *faultdetailXML, int soaperror)
|
|
16705 { return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", NULL, faultstring, faultdetailXML, soaperror);
|
|
16706 }
|
|
16707 #endif
|
|
16708
|
|
16709 /******************************************************************************/
|
|
16710 #ifndef PALM_2
|
|
16711 SOAP_FMAC1
|
|
16712 int
|
|
16713 SOAP_FMAC2
|
|
16714 soap_set_receiver_error(struct soap *soap, const char *faultstring, const char *faultdetailXML, int soaperror)
|
|
16715 { return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", NULL, faultstring, faultdetailXML, soaperror);
|
|
16716 }
|
|
16717 #endif
|
|
16718
|
|
16719 /******************************************************************************/
|
|
16720 #ifndef PALM_2
|
|
16721 static int
|
|
16722 soap_copy_fault(struct soap *soap, const char *faultcode, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML)
|
|
16723 { char *r = NULL, *s = NULL, *t = NULL;
|
|
16724 if (faultsubcodeQName)
|
|
16725 r = soap_strdup(soap, faultsubcodeQName);
|
|
16726 if (faultstring)
|
|
16727 s = soap_strdup(soap, faultstring);
|
|
16728 if (faultdetailXML)
|
|
16729 t = soap_strdup(soap, faultdetailXML);
|
|
16730 return soap_set_error(soap, faultcode, r, s, t, SOAP_FAULT);
|
|
16731 }
|
|
16732 #endif
|
|
16733
|
|
16734 /******************************************************************************/
|
|
16735 #ifndef PALM_2
|
|
16736 SOAP_FMAC1
|
|
16737 int
|
|
16738 SOAP_FMAC2
|
|
16739 soap_sender_fault(struct soap *soap, const char *faultstring, const char *faultdetailXML)
|
|
16740 { return soap_sender_fault_subcode(soap, NULL, faultstring, faultdetailXML);
|
|
16741 }
|
|
16742 #endif
|
|
16743
|
|
16744 /******************************************************************************/
|
|
16745 #ifndef PALM_2
|
|
16746 SOAP_FMAC1
|
|
16747 int
|
|
16748 SOAP_FMAC2
|
|
16749 soap_sender_fault_subcode(struct soap *soap, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML)
|
|
16750 { return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", faultsubcodeQName, faultstring, faultdetailXML);
|
|
16751 }
|
|
16752 #endif
|
|
16753
|
|
16754 /******************************************************************************/
|
|
16755 #ifndef PALM_2
|
|
16756 SOAP_FMAC1
|
|
16757 int
|
|
16758 SOAP_FMAC2
|
|
16759 soap_receiver_fault(struct soap *soap, const char *faultstring, const char *faultdetailXML)
|
|
16760 { return soap_receiver_fault_subcode(soap, NULL, faultstring, faultdetailXML);
|
|
16761 }
|
|
16762 #endif
|
|
16763
|
|
16764 /******************************************************************************/
|
|
16765 #ifndef PALM_2
|
|
16766 SOAP_FMAC1
|
|
16767 int
|
|
16768 SOAP_FMAC2
|
|
16769 soap_receiver_fault_subcode(struct soap *soap, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML)
|
|
16770 { return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", faultsubcodeQName, faultstring, faultdetailXML);
|
|
16771 }
|
|
16772 #endif
|
|
16773
|
|
16774 /******************************************************************************/
|
|
16775 #ifndef PALM_2
|
|
16776 #ifndef WITH_NOSTDLIB
|
|
16777 SOAP_FMAC1
|
|
16778 void
|
|
16779 SOAP_FMAC2
|
|
16780 soap_print_fault(struct soap *soap, FILE *fd)
|
|
16781 { if (soap_check_state(soap))
|
|
16782 fprintf(fd, "Error: soap struct state not initialized\n");
|
|
16783 else if (soap->error)
|
|
16784 { const char **c, *v = NULL, *s, *d;
|
|
16785 c = soap_faultcode(soap);
|
|
16786 if (!*c)
|
|
16787 soap_set_fault(soap);
|
|
16788 if (soap->version == 2)
|
|
16789 v = soap_check_faultsubcode(soap);
|
|
16790 s = *soap_faultstring(soap);
|
|
16791 d = soap_check_faultdetail(soap);
|
|
16792 fprintf(fd, "%s%d fault: %s [%s]\n\"%s\"\nDetail: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, *c, v ? v : "no subcode", s ? s : "[no reason]", d ? d : "[no detail]");
|
|
16793 }
|
|
16794 }
|
|
16795 #endif
|
|
16796 #endif
|
|
16797
|
|
16798 /******************************************************************************/
|
|
16799 #ifdef __cplusplus
|
|
16800 #ifndef WITH_LEAN
|
|
16801 #ifndef WITH_NOSTDLIB
|
|
16802 #ifndef WITH_COMPAT
|
|
16803 SOAP_FMAC1
|
|
16804 void
|
|
16805 SOAP_FMAC2
|
|
16806 soap_stream_fault(struct soap *soap, std::ostream& os)
|
|
16807 { if (soap_check_state(soap))
|
|
16808 os << "Error: soap struct state not initialized\n";
|
|
16809 else if (soap->error)
|
|
16810 { const char **c, *v = NULL, *s, *d;
|
|
16811 c = soap_faultcode(soap);
|
|
16812 if (!*c)
|
|
16813 soap_set_fault(soap);
|
|
16814 if (soap->version == 2)
|
|
16815 v = soap_check_faultsubcode(soap);
|
|
16816 s = *soap_faultstring(soap);
|
|
16817 d = soap_check_faultdetail(soap);
|
|
16818 os << (soap->version ? "SOAP 1." : "Error ")
|
|
16819 << (soap->version ? (int)soap->version : soap->error)
|
|
16820 << " fault: " << *c
|
|
16821 << "[" << (v ? v : "no subcode") << "]"
|
|
16822 << std::endl
|
|
16823 << "\"" << (s ? s : "[no reason]") << "\""
|
|
16824 << std::endl
|
|
16825 << "Detail: " << (d ? d : "[no detail]")
|
|
16826 << std::endl;
|
|
16827 }
|
|
16828 }
|
|
16829 #endif
|
|
16830 #endif
|
|
16831 #endif
|
|
16832 #endif
|
|
16833
|
|
16834 /******************************************************************************/
|
|
16835 #ifndef WITH_LEAN
|
|
16836 #ifndef WITH_NOSTDLIB
|
|
16837 SOAP_FMAC1
|
|
16838 char*
|
|
16839 SOAP_FMAC2
|
|
16840 soap_sprint_fault(struct soap *soap, char *buf, size_t len)
|
|
16841 { if (soap_check_state(soap))
|
|
16842 { strncpy(buf, "Error: soap struct not initialized", len);
|
|
16843 buf[len - 1] = '\0';
|
|
16844 }
|
|
16845 else if (soap->error)
|
|
16846 { const char **c, *v = NULL, *s, *d;
|
|
16847 c = soap_faultcode(soap);
|
|
16848 if (!*c)
|
|
16849 soap_set_fault(soap);
|
|
16850 if (soap->version == 2)
|
|
16851 v = *soap_faultsubcode(soap);
|
|
16852 s = *soap_faultstring(soap);
|
|
16853 d = soap_check_faultdetail(soap);
|
|
16854 #ifdef HAVE_SNPRINTF
|
|
16855 soap_snprintf(buf, len, "%s%d fault: %s [%s]\n\"%s\"\nDetail: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, *c, v ? v : "no subcode", s ? s : "[no reason]", d ? d : "[no detail]");
|
|
16856 #else
|
|
16857 if (len > 40 + (v ? strlen(v) : 0) + (s ? strlen(s) : 0) + (d ? strlen(d) : 0))
|
|
16858 sprintf(buf, "%s%d fault: %s [%s]\n\"%s\"\nDetail: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, *c, v ? v : "no subcode", s ? s : "[no reason]", d ? d : "[no detail]");
|
|
16859 else if (len > 40)
|
|
16860 sprintf(buf, "%s%d fault: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, *c);
|
|
16861 else
|
|
16862 buf[0] = '\0';
|
|
16863 #endif
|
|
16864 }
|
|
16865 return buf;
|
|
16866 }
|
|
16867 #endif
|
|
16868 #endif
|
|
16869
|
|
16870 /******************************************************************************/
|
|
16871 #ifndef PALM_1
|
|
16872 #ifndef WITH_NOSTDLIB
|
|
16873 SOAP_FMAC1
|
|
16874 void
|
|
16875 SOAP_FMAC2
|
|
16876 soap_print_fault_location(struct soap *soap, FILE *fd)
|
|
16877 {
|
|
16878 #ifndef WITH_LEAN
|
|
16879 int i, j, c1, c2;
|
|
16880 if (soap->error && soap->error != SOAP_STOP && soap->bufidx <= soap->buflen && soap->buflen > 0 && soap->buflen <= SOAP_BUFLEN)
|
|
16881 { i = (int)soap->bufidx - 1;
|
|
16882 if (i <= 0)
|
|
16883 i = 0;
|
|
16884 c1 = soap->buf[i];
|
|
16885 soap->buf[i] = '\0';
|
|
16886 if ((int)soap->buflen >= i + 1024)
|
|
16887 j = i + 1023;
|
|
16888 else
|
|
16889 j = (int)soap->buflen - 1;
|
|
16890 c2 = soap->buf[j];
|
|
16891 soap->buf[j] = '\0';
|
|
16892 fprintf(fd, "%s%c\n<!-- ** HERE ** -->\n", soap->buf, c1);
|
|
16893 if (soap->bufidx < soap->buflen)
|
|
16894 fprintf(fd, "%s\n", soap->buf + soap->bufidx);
|
|
16895 soap->buf[i] = (char)c1;
|
|
16896 soap->buf[j] = (char)c2;
|
|
16897 }
|
|
16898 #endif
|
|
16899 }
|
|
16900 #endif
|
|
16901 #endif
|
|
16902
|
|
16903 /******************************************************************************/
|
|
16904 #ifndef PALM_1
|
|
16905 SOAP_FMAC1
|
|
16906 int
|
|
16907 SOAP_FMAC2
|
|
16908 soap_register_plugin_arg(struct soap *soap, int (*fcreate)(struct soap*, struct soap_plugin*, void*), void *arg)
|
|
16909 { register struct soap_plugin *p;
|
|
16910 register int r;
|
|
16911 if (!(p = (struct soap_plugin*)SOAP_MALLOC(soap, sizeof(struct soap_plugin))))
|
|
16912 return soap->error = SOAP_EOM;
|
|
16913 p->id = NULL;
|
|
16914 p->data = NULL;
|
|
16915 p->fcopy = NULL;
|
|
16916 p->fdelete = NULL;
|
|
16917 r = fcreate(soap, p, arg);
|
|
16918 if (!r && p->fdelete)
|
|
16919 { p->next = soap->plugins;
|
|
16920 soap->plugins = p;
|
|
16921 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Registered '%s' plugin\n", p->id));
|
|
16922 return SOAP_OK;
|
|
16923 }
|
|
16924 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not register plugin '%s': plugin returned error %d (or fdelete callback not set)\n", p->id ? p->id : "?", r));
|
|
16925 SOAP_FREE(soap, p);
|
|
16926 return r;
|
|
16927 }
|
|
16928 #endif
|
|
16929
|
|
16930 /******************************************************************************/
|
|
16931 #ifndef PALM_1
|
|
16932 static void *
|
|
16933 fplugin(struct soap *soap, const char *id)
|
|
16934 { register struct soap_plugin *p;
|
|
16935 for (p = soap->plugins; p; p = p->next)
|
|
16936 if (p->id == id || !strcmp(p->id, id))
|
|
16937 return p->data;
|
|
16938 return NULL;
|
|
16939 }
|
|
16940 #endif
|
|
16941
|
|
16942 /******************************************************************************/
|
|
16943 #ifndef PALM_2
|
|
16944 SOAP_FMAC1
|
|
16945 void *
|
|
16946 SOAP_FMAC2
|
|
16947 soap_lookup_plugin(struct soap *soap, const char *id)
|
|
16948 { return soap->fplugin(soap, id);
|
|
16949 }
|
|
16950 #endif
|
|
16951
|
|
16952 /******************************************************************************/
|
|
16953 #ifdef __cplusplus
|
|
16954 }
|
|
16955 #endif
|
|
16956
|
|
16957 /******************************************************************************\
|
|
16958 *
|
|
16959 * C++ soap struct methods
|
|
16960 *
|
|
16961 \******************************************************************************/
|
|
16962
|
|
16963 #ifdef __cplusplus
|
|
16964 soap::soap()
|
|
16965 { soap_init(this);
|
|
16966 }
|
|
16967 #endif
|
|
16968
|
|
16969 /******************************************************************************/
|
|
16970 #ifdef __cplusplus
|
|
16971 soap::soap(soap_mode m)
|
|
16972 { soap_init1(this, m);
|
|
16973 }
|
|
16974 #endif
|
|
16975
|
|
16976 /******************************************************************************/
|
|
16977 #ifdef __cplusplus
|
|
16978 soap::soap(soap_mode im, soap_mode om)
|
|
16979 { soap_init2(this, im, om);
|
|
16980 }
|
|
16981 #endif
|
|
16982
|
|
16983 /******************************************************************************/
|
|
16984 #ifdef __cplusplus
|
|
16985 soap::soap(const struct soap& soap)
|
|
16986 { soap_copy_context(this, &soap);
|
|
16987 }
|
|
16988 #endif
|
|
16989
|
|
16990 /******************************************************************************/
|
|
16991 #ifdef __cplusplus
|
|
16992 soap::~soap()
|
|
16993 { soap_destroy(this);
|
|
16994 soap_end(this);
|
|
16995 soap_done(this);
|
|
16996 }
|
|
16997 #endif
|
|
16998
|
|
16999 /******************************************************************************/
|