1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
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 http://curl.haxx.se/docs/copyright.html.
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.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ***************************************************************************/
22 #include "tool_setup.h"
24 #ifndef CURL_DISABLE_LIBCURL_OPTION
26 #define ENABLE_CURLX_PRINTF
27 /* use our own printf() functions */
30 #include "tool_cfgable.h"
31 #include "tool_easysrc.h"
32 #include "tool_setopt.h"
34 #include "memdebug.h" /* keep this as LAST include */
36 /* Lookup tables for converting setopt values back to symbols */
37 /* For enums, values may be in any order. */
38 /* For bit masks, put combinations first, then single bits, */
39 /* and finally any "NONE" value. */
42 #define NV1(e, v) {#e, (v)}
43 #define NVEND {NULL, 0} /* sentinel to mark end of list */
45 const NameValue setopt_nv_CURLPROXY[] = {
47 NV(CURLPROXY_HTTP_1_0),
50 NV(CURLPROXY_SOCKS4A),
51 NV(CURLPROXY_SOCKS5_HOSTNAME),
55 const NameValueUnsigned setopt_nv_CURLAUTH[] = {
56 NV(CURLAUTH_ANY), /* combination */
57 NV(CURLAUTH_ANYSAFE), /* combination */
60 NV(CURLAUTH_GSSNEGOTIATE),
62 NV(CURLAUTH_DIGEST_IE),
69 const NameValue setopt_nv_CURL_HTTP_VERSION[] = {
70 NV(CURL_HTTP_VERSION_NONE),
71 NV(CURL_HTTP_VERSION_1_0),
72 NV(CURL_HTTP_VERSION_1_1),
76 const NameValue setopt_nv_CURL_SSLVERSION[] = {
77 NV(CURL_SSLVERSION_DEFAULT),
78 NV(CURL_SSLVERSION_TLSv1),
79 NV(CURL_SSLVERSION_SSLv2),
80 NV(CURL_SSLVERSION_SSLv3),
84 const NameValue setopt_nv_CURL_TIMECOND[] = {
85 NV(CURL_TIMECOND_IFMODSINCE),
86 NV(CURL_TIMECOND_IFUNMODSINCE),
87 NV(CURL_TIMECOND_LASTMOD),
88 NV(CURL_TIMECOND_NONE),
92 const NameValue setopt_nv_CURLFTPSSL_CCC[] = {
93 NV(CURLFTPSSL_CCC_NONE),
94 NV(CURLFTPSSL_CCC_PASSIVE),
95 NV(CURLFTPSSL_CCC_ACTIVE),
99 const NameValue setopt_nv_CURLUSESSL[] = {
102 NV(CURLUSESSL_CONTROL),
107 /* These mappings essentially triplicated - see
108 * tool_libinfo.c and tool_paramhlp.c */
109 const NameValue setopt_nv_CURLPROTO[] = {
110 NV(CURLPROTO_ALL), /* combination */
115 NV(CURLPROTO_GOPHER),
129 NV(CURLPROTO_TELNET),
134 /* These options have non-zero default values. */
135 static const NameValue setopt_nv_CURLNONZERODEFAULTS[] = {
136 NV1(CURLOPT_SSL_VERIFYPEER, 1),
137 NV1(CURLOPT_SSL_VERIFYHOST, 1),
141 /* Format and add code; jump to nomem on malloc error */
142 #define ADD(args) do { \
143 ret = easysrc_add args; \
147 #define ADDF(args) do { \
148 ret = easysrc_addf args; \
153 #define DECL0(s) ADD((&easysrc_decl, s))
154 #define DECL1(f,a) ADDF((&easysrc_decl, f,a))
156 #define DATA0(s) ADD((&easysrc_data, s))
157 #define DATA1(f,a) ADDF((&easysrc_data, f,a))
158 #define DATA2(f,a,b) ADDF((&easysrc_data, f,a,b))
159 #define DATA3(f,a,b,c) ADDF((&easysrc_data, f,a,b,c))
161 #define CODE0(s) ADD((&easysrc_code, s))
162 #define CODE1(f,a) ADDF((&easysrc_code, f,a))
163 #define CODE2(f,a,b) ADDF((&easysrc_code, f,a,b))
164 #define CODE3(f,a,b,c) ADDF((&easysrc_code, f,a,b,c))
166 #define CLEAN0(s) ADD((&easysrc_clean, s))
167 #define CLEAN1(f,a) ADDF((&easysrc_clean, f,a))
169 #define REM0(s) ADD((&easysrc_toohard, s))
170 #define REM1(f,a) ADDF((&easysrc_toohard, f,a))
171 #define REM2(f,a,b) ADDF((&easysrc_toohard, f,a,b))
173 /* Escape string to C string syntax. Return NULL if out of memory.
174 * Is this correct for those wacky EBCDIC guys? */
175 static char *c_escape(const char *str)
181 /* Allocate space based on worst-case */
183 escaped = malloc(4 * len + 1);
188 for(s=str; (c=*s) != '\0'; s++) {
209 else if(! isprint(c)) {
210 snprintf(e, 4, "\\%03o", c);
220 /* setopt wrapper for enum types */
221 CURLcode tool_setopt_enum(CURL *curl, struct Configurable *config,
222 const char *name, CURLoption tag,
223 const NameValue *nvlist, long lval)
225 CURLcode ret = CURLE_OK;
228 ret = curl_easy_setopt(curl, tag, lval);
232 if(config->libcurl && !skip && !ret) {
233 /* we only use this for real if --libcurl was used */
234 const NameValue *nv = NULL;
235 for(nv=nvlist; nv->name; nv++) {
236 if(nv->value == lval) break; /* found it */
239 /* If no definition was found, output an explicit value.
240 * This could happen if new values are defined and used
241 * but the NameValue list is not updated. */
242 CODE2("curl_easy_setopt(hnd, %s, %ldL);", name, lval);
245 CODE2("curl_easy_setopt(hnd, %s, (long)%s);", name, nv->name);
253 /* setopt wrapper for flags */
254 CURLcode tool_setopt_flags(CURL *curl, struct Configurable *config,
255 const char *name, CURLoption tag,
256 const NameValue *nvlist, long lval)
258 CURLcode ret = CURLE_OK;
261 ret = curl_easy_setopt(curl, tag, lval);
265 if(config->libcurl && !skip && !ret) {
266 /* we only use this for real if --libcurl was used */
267 char preamble[80]; /* should accommodate any symbol name */
268 long rest = lval; /* bits not handled yet */
269 const NameValue *nv = NULL;
270 snprintf(preamble, sizeof(preamble),
271 "curl_easy_setopt(hnd, %s, ", name);
272 for(nv=nvlist; nv->name; nv++) {
273 if((nv->value & ~ rest) == 0) {
274 /* all value flags contained in rest */
275 rest &= ~ nv->value; /* remove bits handled here */
276 CODE3("%s(long)%s%s",
277 preamble, nv->name, rest ? " |" : ");");
279 break; /* handled them all */
280 /* replace with all spaces for continuation line */
281 snprintf(preamble, sizeof(preamble), "%*s", strlen(preamble), "");
284 /* If any bits have no definition, output an explicit value.
285 * This could happen if new bits are defined and used
286 * but the NameValue list is not updated. */
288 CODE2("%s%ldL);", preamble, rest);
295 /* setopt wrapper for bitmasks */
296 CURLcode tool_setopt_bitmask(CURL *curl, struct Configurable *config,
297 const char *name, CURLoption tag,
298 const NameValueUnsigned *nvlist,
301 CURLcode ret = CURLE_OK;
304 ret = curl_easy_setopt(curl, tag, lval);
308 if(config->libcurl && !skip && !ret) {
309 /* we only use this for real if --libcurl was used */
311 unsigned long rest = (unsigned long)lval;
312 const NameValueUnsigned *nv = NULL;
313 snprintf(preamble, sizeof(preamble),
314 "curl_easy_setopt(hnd, %s, ", name);
315 for(nv=nvlist; nv->name; nv++) {
316 if((nv->value & ~ rest) == 0) {
317 /* all value flags contained in rest */
318 rest &= ~ nv->value; /* remove bits handled here */
319 CODE3("%s(long)%s%s",
320 preamble, nv->name, rest ? " |" : ");");
322 break; /* handled them all */
323 /* replace with all spaces for continuation line */
324 snprintf(preamble, sizeof(preamble), "%*s", strlen(preamble), "");
327 /* If any bits have no definition, output an explicit value.
328 * This could happen if new bits are defined and used
329 * but the NameValue list is not updated. */
331 CODE2("%s%luUL);", preamble, rest);
338 /* setopt wrapper for CURLOPT_HTTPPOST */
339 CURLcode tool_setopt_httppost(CURL *curl, struct Configurable *config,
340 const char *name, CURLoption tag,
341 struct curl_httppost *post)
343 CURLcode ret = CURLE_OK;
344 char *escaped = NULL;
347 ret = curl_easy_setopt(curl, tag, post);
351 if(config->libcurl && !skip && !ret) {
352 struct curl_httppost *pp, *p;
354 /* May use several httppost lists, if multiple POST actions */
355 i = ++ easysrc_form_count;
356 DECL1("struct curl_httppost *post%d;", i);
357 DATA1("post%d = NULL;", i);
358 CLEAN1("curl_formfree(post%d);", i);
359 CLEAN1("post%d = NULL;", i);
361 DECL0("struct curl_httppost *postend;");
362 DATA0("postend = NULL;");
363 for(p=post; p; p=p->next) {
364 DATA1("curl_formadd(&post%d, &postend,", i);
365 DATA1(" CURLFORM_COPYNAME, \"%s\",", p->name);
366 for(pp=p; pp; pp=pp->more) {
367 /* May be several files uploaded for one name;
368 * these are linked through the 'more' pointer */
369 Curl_safefree(escaped);
370 escaped = c_escape(pp->contents);
372 ret = CURLE_OUT_OF_MEMORY;
375 if(pp->flags & HTTPPOST_FILENAME) {
376 /* file upload as for -F @filename */
377 DATA1(" CURLFORM_FILE, \"%s\",", escaped);
379 else if(pp->flags & HTTPPOST_READFILE) {
380 /* content from file as for -F <filename */
381 DATA1(" CURLFORM_FILECONTENT, \"%s\",", escaped);
384 DATA1(" CURLFORM_COPYCONTENTS, \"%s\",", escaped);
385 if(pp->showfilename) {
386 Curl_safefree(escaped);
387 escaped = c_escape(pp->showfilename);
389 ret = CURLE_OUT_OF_MEMORY;
392 DATA1(" CURLFORM_FILENAME, \"%s\",", escaped);
394 if(pp->contenttype) {
395 Curl_safefree(escaped);
396 escaped = c_escape(pp->contenttype);
398 ret = CURLE_OUT_OF_MEMORY;
401 DATA1(" CURLFORM_CONTENTTYPE, \"%s\",", escaped);
404 DATA0(" CURLFORM_END);");
406 CODE2("curl_easy_setopt(hnd, %s, post%d);", name, i);
410 Curl_safefree(escaped);
414 /* setopt wrapper for curl_slist options */
415 CURLcode tool_setopt_slist(CURL *curl, struct Configurable *config,
416 const char *name, CURLoption tag,
417 struct curl_slist *list)
419 CURLcode ret = CURLE_OK;
420 char *escaped = NULL;
423 ret = curl_easy_setopt(curl, tag, list);
427 if(config->libcurl && !skip && !ret) {
428 struct curl_slist *s;
430 /* May need several slist variables, so invent name */
431 i = ++ easysrc_slist_count;
432 DECL1("struct curl_slist *slist%d;", i);
433 DATA1("slist%d = NULL;", i);
434 CLEAN1("curl_slist_free_all(slist%d);", i);
435 CLEAN1("slist%d = NULL;", i);
436 for(s=list; s; s=s->next) {
437 Curl_safefree(escaped);
438 escaped = c_escape(s->data);
440 ret = CURLE_OUT_OF_MEMORY;
443 DATA3("slist%d = curl_slist_append(slist%d, \"%s\");", i, i, escaped);
445 CODE2("curl_easy_setopt(hnd, %s, slist%d);", name, i);
449 Curl_safefree(escaped);
453 /* generic setopt wrapper for all other options.
454 * Some type information is encoded in the tag value. */
455 CURLcode tool_setopt(CURL *curl, bool str, struct Configurable *config,
456 const char *name, CURLoption tag, ...)
460 const char *value = NULL;
464 char *escaped = NULL;
465 CURLcode ret = CURLE_OK;
469 if(tag < CURLOPTTYPE_OBJECTPOINT) {
470 /* Value is expected to be a long */
471 long lval = va_arg(arg, long);
473 const NameValue *nv = NULL;
474 for(nv=setopt_nv_CURLNONZERODEFAULTS; nv->name; nv++) {
475 if(!strcmp(name, nv->name)) {
477 break; /* found it */
481 snprintf(buf, sizeof(buf), "%ldL", lval);
483 ret = curl_easy_setopt(curl, tag, lval);
487 else if(tag < CURLOPTTYPE_OFF_T) {
488 /* Value is some sort of object pointer */
489 void *pval = va_arg(arg, void *);
491 /* function pointers are never printable */
492 if(tag >= CURLOPTTYPE_FUNCTIONPOINT) {
494 value = "functionpointer";
501 else if(pval && str) {
502 value = (char *)pval;
506 value = "objectpointer";
512 ret = curl_easy_setopt(curl, tag, pval);
516 /* Value is expected to be curl_off_t */
517 curl_off_t oval = va_arg(arg, curl_off_t);
518 snprintf(buf, sizeof(buf),
519 "(curl_off_t)%" CURL_FORMAT_CURL_OFF_T, oval);
521 ret = curl_easy_setopt(curl, tag, oval);
529 if(config->libcurl && !skip && !ret) {
530 /* we only use this for real if --libcurl was used */
533 REM2("%s set to a %s", name, value);
536 escaped = c_escape(value);
538 ret = CURLE_OUT_OF_MEMORY;
541 CODE2("curl_easy_setopt(hnd, %s, \"%s\");", name, escaped);
544 CODE2("curl_easy_setopt(hnd, %s, %s);", name, value);
549 Curl_safefree(escaped);
553 #endif /* CURL_DISABLE_LIBCURL_OPTION */