1 | /*************************************************************************** |
2 | * _ _ ____ _ |
3 | * Project ___| | | | _ \| | |
4 | * / __| | | | |_) | | |
5 | * | (__| |_| | _ <| |___ |
6 | * \___|\___/|_| \_\_____| |
7 | * |
8 | * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. |
9 | * |
10 | * This software is licensed as described in the file COPYING, which |
11 | * you should have received as part of this distribution. The terms |
12 | * are also available at https://curl.haxx.se/docs/copyright.html. |
13 | * |
14 | * You may opt to use, copy, modify, merge, publish, distribute and/or sell |
15 | * copies of the Software, and permit persons to whom the Software is |
16 | * furnished to do so, under the terms of the COPYING file. |
17 | * |
18 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
19 | * KIND, either express or implied. |
20 | * |
21 | ***************************************************************************/ |
22 | #include "tool_setup.h" |
23 | |
24 | #ifndef CURL_DISABLE_LIBCURL_OPTION |
25 | |
26 | #define ENABLE_CURLX_PRINTF |
27 | /* use our own printf() functions */ |
28 | #include "curlx.h" |
29 | |
30 | #include "tool_cfgable.h" |
31 | #include "tool_easysrc.h" |
32 | #include "tool_setopt.h" |
33 | #include "tool_convert.h" |
34 | |
35 | #include "memdebug.h" /* keep this as LAST include */ |
36 | |
37 | /* Lookup tables for converting setopt values back to symbols */ |
38 | /* For enums, values may be in any order. */ |
39 | /* For bit masks, put combinations first, then single bits, */ |
40 | /* and finally any "NONE" value. */ |
41 | |
42 | #define NV(e) {#e, e} |
43 | #define NV1(e, v) {#e, (v)} |
44 | #define NVEND {NULL, 0} /* sentinel to mark end of list */ |
45 | |
46 | const NameValue setopt_nv_CURLPROXY[] = { |
47 | NV(CURLPROXY_HTTP), |
48 | NV(CURLPROXY_HTTP_1_0), |
49 | NV(CURLPROXY_HTTPS), |
50 | NV(CURLPROXY_SOCKS4), |
51 | NV(CURLPROXY_SOCKS5), |
52 | NV(CURLPROXY_SOCKS4A), |
53 | NV(CURLPROXY_SOCKS5_HOSTNAME), |
54 | NVEND, |
55 | }; |
56 | |
57 | const NameValue setopt_nv_CURL_SOCKS_PROXY[] = { |
58 | NV(CURLPROXY_SOCKS4), |
59 | NV(CURLPROXY_SOCKS5), |
60 | NV(CURLPROXY_SOCKS4A), |
61 | NV(CURLPROXY_SOCKS5_HOSTNAME), |
62 | NVEND, |
63 | }; |
64 | |
65 | const NameValueUnsigned setopt_nv_CURLAUTH[] = { |
66 | NV(CURLAUTH_ANY), /* combination */ |
67 | NV(CURLAUTH_ANYSAFE), /* combination */ |
68 | NV(CURLAUTH_BASIC), |
69 | NV(CURLAUTH_DIGEST), |
70 | NV(CURLAUTH_GSSNEGOTIATE), |
71 | NV(CURLAUTH_NTLM), |
72 | NV(CURLAUTH_DIGEST_IE), |
73 | NV(CURLAUTH_NTLM_WB), |
74 | NV(CURLAUTH_ONLY), |
75 | NV(CURLAUTH_NONE), |
76 | NVEND, |
77 | }; |
78 | |
79 | const NameValue setopt_nv_CURL_HTTP_VERSION[] = { |
80 | NV(CURL_HTTP_VERSION_NONE), |
81 | NV(CURL_HTTP_VERSION_1_0), |
82 | NV(CURL_HTTP_VERSION_1_1), |
83 | NV(CURL_HTTP_VERSION_2_0), |
84 | NV(CURL_HTTP_VERSION_2TLS), |
85 | NV(CURL_HTTP_VERSION_3), |
86 | NVEND, |
87 | }; |
88 | |
89 | const NameValue setopt_nv_CURL_SSLVERSION[] = { |
90 | NV(CURL_SSLVERSION_DEFAULT), |
91 | NV(CURL_SSLVERSION_TLSv1), |
92 | NV(CURL_SSLVERSION_SSLv2), |
93 | NV(CURL_SSLVERSION_SSLv3), |
94 | NV(CURL_SSLVERSION_TLSv1_0), |
95 | NV(CURL_SSLVERSION_TLSv1_1), |
96 | NV(CURL_SSLVERSION_TLSv1_2), |
97 | NV(CURL_SSLVERSION_TLSv1_3), |
98 | NVEND, |
99 | }; |
100 | |
101 | const NameValue setopt_nv_CURL_TIMECOND[] = { |
102 | NV(CURL_TIMECOND_IFMODSINCE), |
103 | NV(CURL_TIMECOND_IFUNMODSINCE), |
104 | NV(CURL_TIMECOND_LASTMOD), |
105 | NV(CURL_TIMECOND_NONE), |
106 | NVEND, |
107 | }; |
108 | |
109 | const NameValue setopt_nv_CURLFTPSSL_CCC[] = { |
110 | NV(CURLFTPSSL_CCC_NONE), |
111 | NV(CURLFTPSSL_CCC_PASSIVE), |
112 | NV(CURLFTPSSL_CCC_ACTIVE), |
113 | NVEND, |
114 | }; |
115 | |
116 | const NameValue setopt_nv_CURLUSESSL[] = { |
117 | NV(CURLUSESSL_NONE), |
118 | NV(CURLUSESSL_TRY), |
119 | NV(CURLUSESSL_CONTROL), |
120 | NV(CURLUSESSL_ALL), |
121 | NVEND, |
122 | }; |
123 | |
124 | const NameValueUnsigned setopt_nv_CURLSSLOPT[] = { |
125 | NV(CURLSSLOPT_ALLOW_BEAST), |
126 | NV(CURLSSLOPT_NO_REVOKE), |
127 | NVEND, |
128 | }; |
129 | |
130 | const NameValue setopt_nv_CURL_NETRC[] = { |
131 | NV(CURL_NETRC_IGNORED), |
132 | NV(CURL_NETRC_OPTIONAL), |
133 | NV(CURL_NETRC_REQUIRED), |
134 | NVEND, |
135 | }; |
136 | |
137 | /* These mappings essentially triplicated - see |
138 | * tool_libinfo.c and tool_paramhlp.c */ |
139 | const NameValue setopt_nv_CURLPROTO[] = { |
140 | NV(CURLPROTO_ALL), /* combination */ |
141 | NV(CURLPROTO_DICT), |
142 | NV(CURLPROTO_FILE), |
143 | NV(CURLPROTO_FTP), |
144 | NV(CURLPROTO_FTPS), |
145 | NV(CURLPROTO_GOPHER), |
146 | NV(CURLPROTO_HTTP), |
147 | NV(CURLPROTO_HTTPS), |
148 | NV(CURLPROTO_IMAP), |
149 | NV(CURLPROTO_IMAPS), |
150 | NV(CURLPROTO_LDAP), |
151 | NV(CURLPROTO_LDAPS), |
152 | NV(CURLPROTO_POP3), |
153 | NV(CURLPROTO_POP3S), |
154 | NV(CURLPROTO_RTSP), |
155 | NV(CURLPROTO_SCP), |
156 | NV(CURLPROTO_SFTP), |
157 | NV(CURLPROTO_SMB), |
158 | NV(CURLPROTO_SMBS), |
159 | NV(CURLPROTO_SMTP), |
160 | NV(CURLPROTO_SMTPS), |
161 | NV(CURLPROTO_TELNET), |
162 | NV(CURLPROTO_TFTP), |
163 | NVEND, |
164 | }; |
165 | |
166 | /* These options have non-zero default values. */ |
167 | static const NameValue setopt_nv_CURLNONZERODEFAULTS[] = { |
168 | NV1(CURLOPT_SSL_VERIFYPEER, 1), |
169 | NV1(CURLOPT_SSL_VERIFYHOST, 1), |
170 | NV1(CURLOPT_SSL_ENABLE_NPN, 1), |
171 | NV1(CURLOPT_SSL_ENABLE_ALPN, 1), |
172 | NV1(CURLOPT_TCP_NODELAY, 1), |
173 | NV1(CURLOPT_PROXY_SSL_VERIFYPEER, 1), |
174 | NV1(CURLOPT_PROXY_SSL_VERIFYHOST, 1), |
175 | NV1(CURLOPT_SOCKS5_AUTH, 1), |
176 | NVEND |
177 | }; |
178 | |
179 | /* Format and add code; jump to nomem on malloc error */ |
180 | #define ADD(args) do { \ |
181 | ret = easysrc_add args; \ |
182 | if(ret) \ |
183 | goto nomem; \ |
184 | } WHILE_FALSE |
185 | #define ADDF(args) do { \ |
186 | ret = easysrc_addf args; \ |
187 | if(ret) \ |
188 | goto nomem; \ |
189 | } WHILE_FALSE |
190 | #define NULL_CHECK(p) do { \ |
191 | if(!p) { \ |
192 | ret = CURLE_OUT_OF_MEMORY; \ |
193 | goto nomem; \ |
194 | } \ |
195 | } WHILE_FALSE |
196 | |
197 | #define DECL0(s) ADD((&easysrc_decl, s)) |
198 | #define DECL1(f,a) ADDF((&easysrc_decl, f,a)) |
199 | |
200 | #define DATA0(s) ADD((&easysrc_data, s)) |
201 | #define DATA1(f,a) ADDF((&easysrc_data, f,a)) |
202 | #define DATA2(f,a,b) ADDF((&easysrc_data, f,a,b)) |
203 | #define DATA3(f,a,b,c) ADDF((&easysrc_data, f,a,b,c)) |
204 | |
205 | #define CODE0(s) ADD((&easysrc_code, s)) |
206 | #define CODE1(f,a) ADDF((&easysrc_code, f,a)) |
207 | #define CODE2(f,a,b) ADDF((&easysrc_code, f,a,b)) |
208 | #define CODE3(f,a,b,c) ADDF((&easysrc_code, f,a,b,c)) |
209 | |
210 | #define CLEAN0(s) ADD((&easysrc_clean, s)) |
211 | #define CLEAN1(f,a) ADDF((&easysrc_clean, f,a)) |
212 | |
213 | #define REM0(s) ADD((&easysrc_toohard, s)) |
214 | #define REM1(f,a) ADDF((&easysrc_toohard, f,a)) |
215 | #define REM2(f,a,b) ADDF((&easysrc_toohard, f,a,b)) |
216 | |
217 | /* Escape string to C string syntax. Return NULL if out of memory. |
218 | * Is this correct for those wacky EBCDIC guys? */ |
219 | static char *c_escape(const char *str, size_t len) |
220 | { |
221 | const char *s; |
222 | unsigned char c; |
223 | char *escaped, *e; |
224 | |
225 | if(len == CURL_ZERO_TERMINATED) |
226 | len = strlen(str); |
227 | |
228 | /* Check for possible overflow. */ |
229 | if(len > (~(size_t) 0) / 4) |
230 | return NULL; |
231 | |
232 | /* Allocate space based on worst-case */ |
233 | escaped = malloc(4 * len + 1); |
234 | if(!escaped) |
235 | return NULL; |
236 | |
237 | e = escaped; |
238 | for(s = str; (c = *s) != '\0'; s++) { |
239 | if(c == '\n') { |
240 | strcpy(e, "\\n" ); |
241 | e += 2; |
242 | } |
243 | else if(c == '\r') { |
244 | strcpy(e, "\\r" ); |
245 | e += 2; |
246 | } |
247 | else if(c == '\t') { |
248 | strcpy(e, "\\t" ); |
249 | e += 2; |
250 | } |
251 | else if(c == '\\') { |
252 | strcpy(e, "\\\\" ); |
253 | e += 2; |
254 | } |
255 | else if(c == '"') { |
256 | strcpy(e, "\\\"" ); |
257 | e += 2; |
258 | } |
259 | else if(! isprint(c)) { |
260 | msnprintf(e, 5, "\\%03o" , (unsigned)c); |
261 | e += 4; |
262 | } |
263 | else |
264 | *e++ = c; |
265 | } |
266 | *e = '\0'; |
267 | return escaped; |
268 | } |
269 | |
270 | /* setopt wrapper for enum types */ |
271 | CURLcode tool_setopt_enum(CURL *curl, struct GlobalConfig *config, |
272 | const char *name, CURLoption tag, |
273 | const NameValue *nvlist, long lval) |
274 | { |
275 | CURLcode ret = CURLE_OK; |
276 | bool skip = FALSE; |
277 | |
278 | ret = curl_easy_setopt(curl, tag, lval); |
279 | if(!lval) |
280 | skip = TRUE; |
281 | |
282 | if(config->libcurl && !skip && !ret) { |
283 | /* we only use this for real if --libcurl was used */ |
284 | const NameValue *nv = NULL; |
285 | for(nv = nvlist; nv->name; nv++) { |
286 | if(nv->value == lval) break; /* found it */ |
287 | } |
288 | if(! nv->name) { |
289 | /* If no definition was found, output an explicit value. |
290 | * This could happen if new values are defined and used |
291 | * but the NameValue list is not updated. */ |
292 | CODE2("curl_easy_setopt(hnd, %s, %ldL);" , name, lval); |
293 | } |
294 | else { |
295 | CODE2("curl_easy_setopt(hnd, %s, (long)%s);" , name, nv->name); |
296 | } |
297 | } |
298 | |
299 | nomem: |
300 | return ret; |
301 | } |
302 | |
303 | /* setopt wrapper for flags */ |
304 | CURLcode tool_setopt_flags(CURL *curl, struct GlobalConfig *config, |
305 | const char *name, CURLoption tag, |
306 | const NameValue *nvlist, long lval) |
307 | { |
308 | CURLcode ret = CURLE_OK; |
309 | bool skip = FALSE; |
310 | |
311 | ret = curl_easy_setopt(curl, tag, lval); |
312 | if(!lval) |
313 | skip = TRUE; |
314 | |
315 | if(config->libcurl && !skip && !ret) { |
316 | /* we only use this for real if --libcurl was used */ |
317 | char preamble[80]; /* should accommodate any symbol name */ |
318 | long rest = lval; /* bits not handled yet */ |
319 | const NameValue *nv = NULL; |
320 | msnprintf(preamble, sizeof(preamble), |
321 | "curl_easy_setopt(hnd, %s, " , name); |
322 | for(nv = nvlist; nv->name; nv++) { |
323 | if((nv->value & ~ rest) == 0) { |
324 | /* all value flags contained in rest */ |
325 | rest &= ~ nv->value; /* remove bits handled here */ |
326 | CODE3("%s(long)%s%s" , |
327 | preamble, nv->name, rest ? " |" : ");" ); |
328 | if(!rest) |
329 | break; /* handled them all */ |
330 | /* replace with all spaces for continuation line */ |
331 | msnprintf(preamble, sizeof(preamble), "%*s" , strlen(preamble), "" ); |
332 | } |
333 | } |
334 | /* If any bits have no definition, output an explicit value. |
335 | * This could happen if new bits are defined and used |
336 | * but the NameValue list is not updated. */ |
337 | if(rest) |
338 | CODE2("%s%ldL);" , preamble, rest); |
339 | } |
340 | |
341 | nomem: |
342 | return ret; |
343 | } |
344 | |
345 | /* setopt wrapper for bitmasks */ |
346 | CURLcode tool_setopt_bitmask(CURL *curl, struct GlobalConfig *config, |
347 | const char *name, CURLoption tag, |
348 | const NameValueUnsigned *nvlist, |
349 | long lval) |
350 | { |
351 | CURLcode ret = CURLE_OK; |
352 | bool skip = FALSE; |
353 | |
354 | ret = curl_easy_setopt(curl, tag, lval); |
355 | if(!lval) |
356 | skip = TRUE; |
357 | |
358 | if(config->libcurl && !skip && !ret) { |
359 | /* we only use this for real if --libcurl was used */ |
360 | char preamble[80]; |
361 | unsigned long rest = (unsigned long)lval; |
362 | const NameValueUnsigned *nv = NULL; |
363 | msnprintf(preamble, sizeof(preamble), |
364 | "curl_easy_setopt(hnd, %s, " , name); |
365 | for(nv = nvlist; nv->name; nv++) { |
366 | if((nv->value & ~ rest) == 0) { |
367 | /* all value flags contained in rest */ |
368 | rest &= ~ nv->value; /* remove bits handled here */ |
369 | CODE3("%s(long)%s%s" , |
370 | preamble, nv->name, rest ? " |" : ");" ); |
371 | if(!rest) |
372 | break; /* handled them all */ |
373 | /* replace with all spaces for continuation line */ |
374 | msnprintf(preamble, sizeof(preamble), "%*s" , strlen(preamble), "" ); |
375 | } |
376 | } |
377 | /* If any bits have no definition, output an explicit value. |
378 | * This could happen if new bits are defined and used |
379 | * but the NameValue list is not updated. */ |
380 | if(rest) |
381 | CODE2("%s%luUL);" , preamble, rest); |
382 | } |
383 | |
384 | nomem: |
385 | return ret; |
386 | } |
387 | |
388 | /* Generate code for a struct curl_slist. */ |
389 | static CURLcode libcurl_generate_slist(struct curl_slist *slist, int *slistno) |
390 | { |
391 | CURLcode ret = CURLE_OK; |
392 | char *escaped = NULL; |
393 | |
394 | /* May need several slist variables, so invent name */ |
395 | *slistno = ++easysrc_slist_count; |
396 | |
397 | DECL1("struct curl_slist *slist%d;" , *slistno); |
398 | DATA1("slist%d = NULL;" , *slistno); |
399 | CLEAN1("curl_slist_free_all(slist%d);" , *slistno); |
400 | CLEAN1("slist%d = NULL;" , *slistno); |
401 | for(; slist; slist = slist->next) { |
402 | Curl_safefree(escaped); |
403 | escaped = c_escape(slist->data, CURL_ZERO_TERMINATED); |
404 | if(!escaped) |
405 | return CURLE_OUT_OF_MEMORY; |
406 | DATA3("slist%d = curl_slist_append(slist%d, \"%s\");" , |
407 | *slistno, *slistno, escaped); |
408 | } |
409 | |
410 | nomem: |
411 | Curl_safefree(escaped); |
412 | return ret; |
413 | } |
414 | |
415 | static CURLcode libcurl_generate_mime(CURL *curl, |
416 | struct GlobalConfig *config, |
417 | tool_mime *toolmime, |
418 | int *mimeno); /* Forward. */ |
419 | |
420 | /* Wrapper to generate source code for a mime part. */ |
421 | static CURLcode libcurl_generate_mime_part(CURL *curl, |
422 | struct GlobalConfig *config, |
423 | tool_mime *part, |
424 | int mimeno) |
425 | { |
426 | CURLcode ret = CURLE_OK; |
427 | int submimeno = 0; |
428 | char *escaped = NULL; |
429 | const char *data = NULL; |
430 | const char *filename = part->filename; |
431 | |
432 | /* Parts are linked in reverse order. */ |
433 | if(part->prev) { |
434 | ret = libcurl_generate_mime_part(curl, config, part->prev, mimeno); |
435 | if(ret) |
436 | return ret; |
437 | } |
438 | |
439 | /* Create the part. */ |
440 | CODE2("part%d = curl_mime_addpart(mime%d);" , mimeno, mimeno); |
441 | |
442 | switch(part->kind) { |
443 | case TOOLMIME_PARTS: |
444 | ret = libcurl_generate_mime(curl, config, part, &submimeno); |
445 | if(!ret) { |
446 | CODE2("curl_mime_subparts(part%d, mime%d);" , mimeno, submimeno); |
447 | CODE1("mime%d = NULL;" , submimeno); /* Avoid freeing in CLEAN. */ |
448 | } |
449 | break; |
450 | |
451 | case TOOLMIME_DATA: |
452 | #ifdef CURL_DOES_CONVERSIONS |
453 | /* Data will be set in ASCII, thus issue a comment with clear text. */ |
454 | escaped = c_escape(part->data, CURL_ZERO_TERMINATED); |
455 | NULL_CHECK(escaped); |
456 | CODE1("/* \"%s\" */" , escaped); |
457 | |
458 | /* Our data is always textual: convert it to ASCII. */ |
459 | { |
460 | size_t size = strlen(part->data); |
461 | char *cp = malloc(size + 1); |
462 | |
463 | NULL_CHECK(cp); |
464 | memcpy(cp, part->data, size + 1); |
465 | ret = convert_to_network(cp, size); |
466 | data = cp; |
467 | } |
468 | #else |
469 | data = part->data; |
470 | #endif |
471 | if(!ret) { |
472 | Curl_safefree(escaped); |
473 | escaped = c_escape(data, CURL_ZERO_TERMINATED); |
474 | NULL_CHECK(escaped); |
475 | CODE2("curl_mime_data(part%d, \"%s\", CURL_ZERO_TERMINATED);" , |
476 | mimeno, escaped); |
477 | } |
478 | break; |
479 | |
480 | case TOOLMIME_FILE: |
481 | case TOOLMIME_FILEDATA: |
482 | escaped = c_escape(part->data, CURL_ZERO_TERMINATED); |
483 | NULL_CHECK(escaped); |
484 | CODE2("curl_mime_filedata(part%d, \"%s\");" , mimeno, escaped); |
485 | if(part->kind == TOOLMIME_FILEDATA && !filename) { |
486 | CODE1("curl_mime_filename(part%d, NULL);" , mimeno); |
487 | } |
488 | break; |
489 | |
490 | case TOOLMIME_STDIN: |
491 | if(!filename) |
492 | filename = "-" ; |
493 | /* FALLTHROUGH */ |
494 | case TOOLMIME_STDINDATA: |
495 | /* Can only be reading stdin in the current context. */ |
496 | CODE1("curl_mime_data_cb(part%d, -1, (curl_read_callback) fread, \\" , |
497 | mimeno); |
498 | CODE0(" (curl_seek_callback) fseek, NULL, stdin);" ); |
499 | break; |
500 | default: |
501 | /* Other cases not possible in this context. */ |
502 | break; |
503 | } |
504 | |
505 | if(!ret && part->encoder) { |
506 | Curl_safefree(escaped); |
507 | escaped = c_escape(part->encoder, CURL_ZERO_TERMINATED); |
508 | NULL_CHECK(escaped); |
509 | CODE2("curl_mime_encoder(part%d, \"%s\");" , mimeno, escaped); |
510 | } |
511 | |
512 | if(!ret && filename) { |
513 | Curl_safefree(escaped); |
514 | escaped = c_escape(filename, CURL_ZERO_TERMINATED); |
515 | NULL_CHECK(escaped); |
516 | CODE2("curl_mime_filename(part%d, \"%s\");" , mimeno, escaped); |
517 | } |
518 | |
519 | if(!ret && part->name) { |
520 | Curl_safefree(escaped); |
521 | escaped = c_escape(part->name, CURL_ZERO_TERMINATED); |
522 | NULL_CHECK(escaped); |
523 | CODE2("curl_mime_name(part%d, \"%s\");" , mimeno, escaped); |
524 | } |
525 | |
526 | if(!ret && part->type) { |
527 | Curl_safefree(escaped); |
528 | escaped = c_escape(part->type, CURL_ZERO_TERMINATED); |
529 | NULL_CHECK(escaped); |
530 | CODE2("curl_mime_type(part%d, \"%s\");" , mimeno, escaped); |
531 | } |
532 | |
533 | if(!ret && part->headers) { |
534 | int slistno; |
535 | |
536 | ret = libcurl_generate_slist(part->headers, &slistno); |
537 | if(!ret) { |
538 | CODE2("curl_mime_headers(part%d, slist%d, 1);" , mimeno, slistno); |
539 | CODE1("slist%d = NULL;" , slistno); /* Prevent CLEANing. */ |
540 | } |
541 | } |
542 | |
543 | nomem: |
544 | #ifdef CURL_DOES_CONVERSIONS |
545 | if(data) |
546 | free((char *) data); |
547 | #endif |
548 | |
549 | Curl_safefree(escaped); |
550 | return ret; |
551 | } |
552 | |
553 | /* Wrapper to generate source code for a mime structure. */ |
554 | static CURLcode libcurl_generate_mime(CURL *curl, |
555 | struct GlobalConfig *config, |
556 | tool_mime *toolmime, |
557 | int *mimeno) |
558 | { |
559 | CURLcode ret = CURLE_OK; |
560 | |
561 | /* May need several mime variables, so invent name. */ |
562 | *mimeno = ++easysrc_mime_count; |
563 | DECL1("curl_mime *mime%d;" , *mimeno); |
564 | DATA1("mime%d = NULL;" , *mimeno); |
565 | CODE1("mime%d = curl_mime_init(hnd);" , *mimeno); |
566 | CLEAN1("curl_mime_free(mime%d);" , *mimeno); |
567 | CLEAN1("mime%d = NULL;" , *mimeno); |
568 | |
569 | if(toolmime->subparts) { |
570 | DECL1("curl_mimepart *part%d;" , *mimeno); |
571 | ret = libcurl_generate_mime_part(curl, config, |
572 | toolmime->subparts, *mimeno); |
573 | } |
574 | |
575 | nomem: |
576 | return ret; |
577 | } |
578 | |
579 | /* setopt wrapper for CURLOPT_MIMEPOST */ |
580 | CURLcode tool_setopt_mimepost(CURL *curl, struct GlobalConfig *config, |
581 | const char *name, CURLoption tag, |
582 | curl_mime *mimepost) |
583 | { |
584 | CURLcode ret = curl_easy_setopt(curl, tag, mimepost); |
585 | int mimeno = 0; |
586 | |
587 | if(!ret && config->libcurl) { |
588 | ret = libcurl_generate_mime(curl, config, |
589 | config->current->mimeroot, &mimeno); |
590 | |
591 | if(!ret) |
592 | CODE2("curl_easy_setopt(hnd, %s, mime%d);" , name, mimeno); |
593 | } |
594 | |
595 | nomem: |
596 | return ret; |
597 | } |
598 | |
599 | /* setopt wrapper for curl_slist options */ |
600 | CURLcode tool_setopt_slist(CURL *curl, struct GlobalConfig *config, |
601 | const char *name, CURLoption tag, |
602 | struct curl_slist *list) |
603 | { |
604 | CURLcode ret = CURLE_OK; |
605 | |
606 | ret = curl_easy_setopt(curl, tag, list); |
607 | |
608 | if(config->libcurl && list && !ret) { |
609 | int i; |
610 | |
611 | ret = libcurl_generate_slist(list, &i); |
612 | if(!ret) |
613 | CODE2("curl_easy_setopt(hnd, %s, slist%d);" , name, i); |
614 | } |
615 | |
616 | nomem: |
617 | return ret; |
618 | } |
619 | |
620 | /* generic setopt wrapper for all other options. |
621 | * Some type information is encoded in the tag value. */ |
622 | CURLcode tool_setopt(CURL *curl, bool str, struct GlobalConfig *config, |
623 | const char *name, CURLoption tag, ...) |
624 | { |
625 | va_list arg; |
626 | char buf[256]; |
627 | const char *value = NULL; |
628 | bool = FALSE; |
629 | bool skip = FALSE; |
630 | bool escape = FALSE; |
631 | char *escaped = NULL; |
632 | CURLcode ret = CURLE_OK; |
633 | |
634 | va_start(arg, tag); |
635 | |
636 | if(tag < CURLOPTTYPE_OBJECTPOINT) { |
637 | /* Value is expected to be a long */ |
638 | long lval = va_arg(arg, long); |
639 | long defval = 0L; |
640 | const NameValue *nv = NULL; |
641 | for(nv = setopt_nv_CURLNONZERODEFAULTS; nv->name; nv++) { |
642 | if(!strcmp(name, nv->name)) { |
643 | defval = nv->value; |
644 | break; /* found it */ |
645 | } |
646 | } |
647 | |
648 | msnprintf(buf, sizeof(buf), "%ldL" , lval); |
649 | value = buf; |
650 | ret = curl_easy_setopt(curl, tag, lval); |
651 | if(lval == defval) |
652 | skip = TRUE; |
653 | } |
654 | else if(tag < CURLOPTTYPE_OFF_T) { |
655 | /* Value is some sort of object pointer */ |
656 | void *pval = va_arg(arg, void *); |
657 | |
658 | /* function pointers are never printable */ |
659 | if(tag >= CURLOPTTYPE_FUNCTIONPOINT) { |
660 | if(pval) { |
661 | value = "functionpointer" ; |
662 | remark = TRUE; |
663 | } |
664 | else |
665 | skip = TRUE; |
666 | } |
667 | |
668 | else if(pval && str) { |
669 | value = (char *)pval; |
670 | escape = TRUE; |
671 | } |
672 | else if(pval) { |
673 | value = "objectpointer" ; |
674 | remark = TRUE; |
675 | } |
676 | else |
677 | skip = TRUE; |
678 | |
679 | ret = curl_easy_setopt(curl, tag, pval); |
680 | |
681 | } |
682 | else { |
683 | /* Value is expected to be curl_off_t */ |
684 | curl_off_t oval = va_arg(arg, curl_off_t); |
685 | msnprintf(buf, sizeof(buf), |
686 | "(curl_off_t)%" CURL_FORMAT_CURL_OFF_T, oval); |
687 | value = buf; |
688 | ret = curl_easy_setopt(curl, tag, oval); |
689 | |
690 | if(!oval) |
691 | skip = TRUE; |
692 | } |
693 | |
694 | va_end(arg); |
695 | |
696 | if(config->libcurl && !skip && !ret) { |
697 | /* we only use this for real if --libcurl was used */ |
698 | |
699 | if(remark) |
700 | REM2("%s set to a %s" , name, value); |
701 | else { |
702 | if(escape) { |
703 | escaped = c_escape(value, CURL_ZERO_TERMINATED); |
704 | NULL_CHECK(escaped); |
705 | CODE2("curl_easy_setopt(hnd, %s, \"%s\");" , name, escaped); |
706 | } |
707 | else |
708 | CODE2("curl_easy_setopt(hnd, %s, %s);" , name, value); |
709 | } |
710 | } |
711 | |
712 | nomem: |
713 | Curl_safefree(escaped); |
714 | return ret; |
715 | } |
716 | |
717 | #else /* CURL_DISABLE_LIBCURL_OPTION */ |
718 | |
719 | #include "tool_cfgable.h" |
720 | #include "tool_setopt.h" |
721 | |
722 | #endif /* CURL_DISABLE_LIBCURL_OPTION */ |
723 | |
724 | /* |
725 | * tool_setopt_skip() allows the curl tool code to avoid setopt options that |
726 | * are explicitly disabled in the build. |
727 | */ |
728 | bool tool_setopt_skip(CURLoption tag) |
729 | { |
730 | #ifdef CURL_DISABLE_PROXY |
731 | #define USED_TAG |
732 | switch(tag) { |
733 | case CURLOPT_HAPROXYPROTOCOL: |
734 | case CURLOPT_HTTPPROXYTUNNEL: |
735 | case CURLOPT_NOPROXY: |
736 | case CURLOPT_PRE_PROXY: |
737 | case CURLOPT_PROXY: |
738 | case CURLOPT_PROXYAUTH: |
739 | case CURLOPT_PROXY_CAINFO: |
740 | case CURLOPT_PROXY_CAPATH: |
741 | case CURLOPT_PROXY_CRLFILE: |
742 | case CURLOPT_PROXYHEADER: |
743 | case CURLOPT_PROXY_KEYPASSWD: |
744 | case CURLOPT_PROXYPASSWORD: |
745 | case CURLOPT_PROXY_PINNEDPUBLICKEY: |
746 | case CURLOPT_PROXYPORT: |
747 | case CURLOPT_PROXY_SERVICE_NAME: |
748 | case CURLOPT_PROXY_SSLCERT: |
749 | case CURLOPT_PROXY_SSLCERTTYPE: |
750 | case CURLOPT_PROXY_SSL_CIPHER_LIST: |
751 | case CURLOPT_PROXY_SSLKEY: |
752 | case CURLOPT_PROXY_SSLKEYTYPE: |
753 | case CURLOPT_PROXY_SSL_OPTIONS: |
754 | case CURLOPT_PROXY_SSL_VERIFYHOST: |
755 | case CURLOPT_PROXY_SSL_VERIFYPEER: |
756 | case CURLOPT_PROXY_SSLVERSION: |
757 | case CURLOPT_PROXY_TLS13_CIPHERS: |
758 | case CURLOPT_PROXY_TLSAUTH_PASSWORD: |
759 | case CURLOPT_PROXY_TLSAUTH_TYPE: |
760 | case CURLOPT_PROXY_TLSAUTH_USERNAME: |
761 | case CURLOPT_PROXY_TRANSFER_MODE: |
762 | case CURLOPT_PROXYTYPE: |
763 | case CURLOPT_PROXYUSERNAME: |
764 | case CURLOPT_PROXYUSERPWD: |
765 | return TRUE; |
766 | default: |
767 | break; |
768 | } |
769 | #endif |
770 | #ifdef CURL_DISABLE_FTP |
771 | #define USED_TAG |
772 | switch(tag) { |
773 | case CURLOPT_FTPPORT: |
774 | case CURLOPT_FTP_ACCOUNT: |
775 | case CURLOPT_FTP_ALTERNATIVE_TO_USER: |
776 | case CURLOPT_FTP_FILEMETHOD: |
777 | case CURLOPT_FTP_SKIP_PASV_IP: |
778 | case CURLOPT_FTP_USE_EPRT: |
779 | case CURLOPT_FTP_USE_EPSV: |
780 | case CURLOPT_FTP_USE_PRET: |
781 | case CURLOPT_KRBLEVEL: |
782 | return TRUE; |
783 | default: |
784 | break; |
785 | } |
786 | #endif |
787 | #ifdef CURL_DISABLE_RTSP |
788 | #define USED_TAG |
789 | switch(tag) { |
790 | case CURLOPT_INTERLEAVEDATA: |
791 | return TRUE; |
792 | default: |
793 | break; |
794 | } |
795 | #endif |
796 | #if defined(CURL_DISABLE_HTTP) || defined(CURL_DISABLE_COOKIES) |
797 | #define USED_TAG |
798 | switch(tag) { |
799 | case CURLOPT_COOKIE: |
800 | case CURLOPT_COOKIEFILE: |
801 | case CURLOPT_COOKIEJAR: |
802 | case CURLOPT_COOKIESESSION: |
803 | return TRUE; |
804 | default: |
805 | break; |
806 | } |
807 | #endif |
808 | #if defined(CURL_DISABLE_TELNET) |
809 | #define USED_TAG |
810 | switch(tag) { |
811 | case CURLOPT_TELNETOPTIONS: |
812 | return TRUE; |
813 | default: |
814 | break; |
815 | } |
816 | #endif |
817 | #ifdef CURL_DISABLE_TFTP |
818 | #define USED_TAG |
819 | switch(tag) { |
820 | case CURLOPT_TFTP_BLKSIZE: |
821 | case CURLOPT_TFTP_NO_OPTIONS: |
822 | return TRUE; |
823 | default: |
824 | break; |
825 | } |
826 | #endif |
827 | #ifdef CURL_DISABLE_NETRC |
828 | #define USED_TAG |
829 | switch(tag) { |
830 | case CURLOPT_NETRC: |
831 | case CURLOPT_NETRC_FILE: |
832 | return TRUE; |
833 | default: |
834 | break; |
835 | } |
836 | #endif |
837 | |
838 | #ifndef USED_TAG |
839 | (void)tag; |
840 | #endif |
841 | return FALSE; |
842 | } |
843 | |