00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "tool_setup.h"
00023
00024 #ifndef CURL_DISABLE_LIBCURL_OPTION
00025
00026 #define ENABLE_CURLX_PRINTF
00027
00028 #include "curlx.h"
00029
00030 #include "tool_cfgable.h"
00031 #include "tool_easysrc.h"
00032 #include "tool_setopt.h"
00033
00034 #include "memdebug.h"
00035
00036
00037
00038
00039
00040
00041 #define NV(e) {#e, e}
00042 #define NV1(e, v) {#e, (v)}
00043 #define NVEND {NULL, 0}
00044
00045 const NameValue setopt_nv_CURLPROXY[] = {
00046 NV(CURLPROXY_HTTP),
00047 NV(CURLPROXY_HTTP_1_0),
00048 NV(CURLPROXY_HTTPS),
00049 NV(CURLPROXY_SOCKS4),
00050 NV(CURLPROXY_SOCKS5),
00051 NV(CURLPROXY_SOCKS4A),
00052 NV(CURLPROXY_SOCKS5_HOSTNAME),
00053 NVEND,
00054 };
00055
00056 const NameValue setopt_nv_CURL_SOCKS_PROXY[] = {
00057 NV(CURLPROXY_SOCKS4),
00058 NV(CURLPROXY_SOCKS5),
00059 NV(CURLPROXY_SOCKS4A),
00060 NV(CURLPROXY_SOCKS5_HOSTNAME),
00061 NVEND,
00062 };
00063
00064 const NameValueUnsigned setopt_nv_CURLAUTH[] = {
00065 NV(CURLAUTH_ANY),
00066 NV(CURLAUTH_ANYSAFE),
00067 NV(CURLAUTH_BASIC),
00068 NV(CURLAUTH_DIGEST),
00069 NV(CURLAUTH_GSSNEGOTIATE),
00070 NV(CURLAUTH_NTLM),
00071 NV(CURLAUTH_DIGEST_IE),
00072 NV(CURLAUTH_NTLM_WB),
00073 NV(CURLAUTH_ONLY),
00074 NV(CURLAUTH_NONE),
00075 NVEND,
00076 };
00077
00078 const NameValue setopt_nv_CURL_HTTP_VERSION[] = {
00079 NV(CURL_HTTP_VERSION_NONE),
00080 NV(CURL_HTTP_VERSION_1_0),
00081 NV(CURL_HTTP_VERSION_1_1),
00082 NV(CURL_HTTP_VERSION_2_0),
00083 NV(CURL_HTTP_VERSION_2TLS),
00084 NVEND,
00085 };
00086
00087 const NameValue setopt_nv_CURL_SSLVERSION[] = {
00088 NV(CURL_SSLVERSION_DEFAULT),
00089 NV(CURL_SSLVERSION_TLSv1),
00090 NV(CURL_SSLVERSION_SSLv2),
00091 NV(CURL_SSLVERSION_SSLv3),
00092 NV(CURL_SSLVERSION_TLSv1_0),
00093 NV(CURL_SSLVERSION_TLSv1_1),
00094 NV(CURL_SSLVERSION_TLSv1_2),
00095 NV(CURL_SSLVERSION_TLSv1_3),
00096 NVEND,
00097 };
00098
00099 const NameValue setopt_nv_CURL_TIMECOND[] = {
00100 NV(CURL_TIMECOND_IFMODSINCE),
00101 NV(CURL_TIMECOND_IFUNMODSINCE),
00102 NV(CURL_TIMECOND_LASTMOD),
00103 NV(CURL_TIMECOND_NONE),
00104 NVEND,
00105 };
00106
00107 const NameValue setopt_nv_CURLFTPSSL_CCC[] = {
00108 NV(CURLFTPSSL_CCC_NONE),
00109 NV(CURLFTPSSL_CCC_PASSIVE),
00110 NV(CURLFTPSSL_CCC_ACTIVE),
00111 NVEND,
00112 };
00113
00114 const NameValue setopt_nv_CURLUSESSL[] = {
00115 NV(CURLUSESSL_NONE),
00116 NV(CURLUSESSL_TRY),
00117 NV(CURLUSESSL_CONTROL),
00118 NV(CURLUSESSL_ALL),
00119 NVEND,
00120 };
00121
00122 const NameValueUnsigned setopt_nv_CURLSSLOPT[] = {
00123 NV(CURLSSLOPT_ALLOW_BEAST),
00124 NV(CURLSSLOPT_NO_REVOKE),
00125 NVEND,
00126 };
00127
00128 const NameValue setopt_nv_CURL_NETRC[] = {
00129 NV(CURL_NETRC_IGNORED),
00130 NV(CURL_NETRC_OPTIONAL),
00131 NV(CURL_NETRC_REQUIRED),
00132 NVEND,
00133 };
00134
00135
00136
00137 const NameValue setopt_nv_CURLPROTO[] = {
00138 NV(CURLPROTO_ALL),
00139 NV(CURLPROTO_DICT),
00140 NV(CURLPROTO_FILE),
00141 NV(CURLPROTO_FTP),
00142 NV(CURLPROTO_FTPS),
00143 NV(CURLPROTO_GOPHER),
00144 NV(CURLPROTO_HTTP),
00145 NV(CURLPROTO_HTTPS),
00146 NV(CURLPROTO_IMAP),
00147 NV(CURLPROTO_IMAPS),
00148 NV(CURLPROTO_LDAP),
00149 NV(CURLPROTO_LDAPS),
00150 NV(CURLPROTO_POP3),
00151 NV(CURLPROTO_POP3S),
00152 NV(CURLPROTO_RTSP),
00153 NV(CURLPROTO_SCP),
00154 NV(CURLPROTO_SFTP),
00155 NV(CURLPROTO_SMB),
00156 NV(CURLPROTO_SMBS),
00157 NV(CURLPROTO_SMTP),
00158 NV(CURLPROTO_SMTPS),
00159 NV(CURLPROTO_TELNET),
00160 NV(CURLPROTO_TFTP),
00161 NVEND,
00162 };
00163
00164
00165 static const NameValue setopt_nv_CURLNONZERODEFAULTS[] = {
00166 NV1(CURLOPT_SSL_VERIFYPEER, 1),
00167 NV1(CURLOPT_SSL_VERIFYHOST, 1),
00168 NV1(CURLOPT_SSL_ENABLE_NPN, 1),
00169 NV1(CURLOPT_SSL_ENABLE_ALPN, 1),
00170 NV1(CURLOPT_TCP_NODELAY, 1),
00171 NV1(CURLOPT_PROXY_SSL_VERIFYPEER, 1),
00172 NV1(CURLOPT_PROXY_SSL_VERIFYHOST, 1),
00173 NVEND
00174 };
00175
00176
00177 #define ADD(args) do { \
00178 ret = easysrc_add args; \
00179 if(ret) \
00180 goto nomem; \
00181 } WHILE_FALSE
00182 #define ADDF(args) do { \
00183 ret = easysrc_addf args; \
00184 if(ret) \
00185 goto nomem; \
00186 } WHILE_FALSE
00187
00188 #define DECL0(s) ADD((&easysrc_decl, s))
00189 #define DECL1(f,a) ADDF((&easysrc_decl, f,a))
00190
00191 #define DATA0(s) ADD((&easysrc_data, s))
00192 #define DATA1(f,a) ADDF((&easysrc_data, f,a))
00193 #define DATA2(f,a,b) ADDF((&easysrc_data, f,a,b))
00194 #define DATA3(f,a,b,c) ADDF((&easysrc_data, f,a,b,c))
00195
00196 #define CODE0(s) ADD((&easysrc_code, s))
00197 #define CODE1(f,a) ADDF((&easysrc_code, f,a))
00198 #define CODE2(f,a,b) ADDF((&easysrc_code, f,a,b))
00199 #define CODE3(f,a,b,c) ADDF((&easysrc_code, f,a,b,c))
00200
00201 #define CLEAN0(s) ADD((&easysrc_clean, s))
00202 #define CLEAN1(f,a) ADDF((&easysrc_clean, f,a))
00203
00204 #define REM0(s) ADD((&easysrc_toohard, s))
00205 #define REM1(f,a) ADDF((&easysrc_toohard, f,a))
00206 #define REM2(f,a,b) ADDF((&easysrc_toohard, f,a,b))
00207
00208
00209
00210 static char *c_escape(const char *str)
00211 {
00212 size_t len = 0;
00213 const char *s;
00214 unsigned char c;
00215 char *escaped, *e;
00216
00217 len = strlen(str);
00218 escaped = malloc(4 * len + 1);
00219 if(!escaped)
00220 return NULL;
00221
00222 e = escaped;
00223 for(s=str; (c=*s) != '\0'; s++) {
00224 if(c=='\n') {
00225 strcpy(e, "\\n");
00226 e += 2;
00227 }
00228 else if(c=='\r') {
00229 strcpy(e, "\\r");
00230 e += 2;
00231 }
00232 else if(c=='\t') {
00233 strcpy(e, "\\t");
00234 e += 2;
00235 }
00236 else if(c=='\\') {
00237 strcpy(e, "\\\\");
00238 e += 2;
00239 }
00240 else if(c=='"') {
00241 strcpy(e, "\\\"");
00242 e += 2;
00243 }
00244 else if(! isprint(c)) {
00245 snprintf(e, 5, "\\%03o", (unsigned)c);
00246 e += 4;
00247 }
00248 else
00249 *e++ = c;
00250 }
00251 *e = '\0';
00252 return escaped;
00253 }
00254
00255
00256 CURLcode tool_setopt_enum(CURL *curl, struct GlobalConfig *config,
00257 const char *name, CURLoption tag,
00258 const NameValue *nvlist, long lval)
00259 {
00260 CURLcode ret = CURLE_OK;
00261 bool skip = FALSE;
00262
00263 ret = curl_easy_setopt(curl, tag, lval);
00264 if(!lval)
00265 skip = TRUE;
00266
00267 if(config->libcurl && !skip && !ret) {
00268
00269 const NameValue *nv = NULL;
00270 for(nv=nvlist; nv->name; nv++) {
00271 if(nv->value == lval) break;
00272 }
00273 if(! nv->name) {
00274
00275
00276
00277 CODE2("curl_easy_setopt(hnd, %s, %ldL);", name, lval);
00278 }
00279 else {
00280 CODE2("curl_easy_setopt(hnd, %s, (long)%s);", name, nv->name);
00281 }
00282 }
00283
00284 nomem:
00285 return ret;
00286 }
00287
00288
00289 CURLcode tool_setopt_flags(CURL *curl, struct GlobalConfig *config,
00290 const char *name, CURLoption tag,
00291 const NameValue *nvlist, long lval)
00292 {
00293 CURLcode ret = CURLE_OK;
00294 bool skip = FALSE;
00295
00296 ret = curl_easy_setopt(curl, tag, lval);
00297 if(!lval)
00298 skip = TRUE;
00299
00300 if(config->libcurl && !skip && !ret) {
00301
00302 char preamble[80];
00303 long rest = lval;
00304 const NameValue *nv = NULL;
00305 snprintf(preamble, sizeof(preamble),
00306 "curl_easy_setopt(hnd, %s, ", name);
00307 for(nv=nvlist; nv->name; nv++) {
00308 if((nv->value & ~ rest) == 0) {
00309
00310 rest &= ~ nv->value;
00311 CODE3("%s(long)%s%s",
00312 preamble, nv->name, rest ? " |" : ");");
00313 if(!rest)
00314 break;
00315
00316 snprintf(preamble, sizeof(preamble), "%*s", strlen(preamble), "");
00317 }
00318 }
00319
00320
00321
00322 if(rest)
00323 CODE2("%s%ldL);", preamble, rest);
00324 }
00325
00326 nomem:
00327 return ret;
00328 }
00329
00330
00331 CURLcode tool_setopt_bitmask(CURL *curl, struct GlobalConfig *config,
00332 const char *name, CURLoption tag,
00333 const NameValueUnsigned *nvlist,
00334 long lval)
00335 {
00336 CURLcode ret = CURLE_OK;
00337 bool skip = FALSE;
00338
00339 ret = curl_easy_setopt(curl, tag, lval);
00340 if(!lval)
00341 skip = TRUE;
00342
00343 if(config->libcurl && !skip && !ret) {
00344
00345 char preamble[80];
00346 unsigned long rest = (unsigned long)lval;
00347 const NameValueUnsigned *nv = NULL;
00348 snprintf(preamble, sizeof(preamble),
00349 "curl_easy_setopt(hnd, %s, ", name);
00350 for(nv=nvlist; nv->name; nv++) {
00351 if((nv->value & ~ rest) == 0) {
00352
00353 rest &= ~ nv->value;
00354 CODE3("%s(long)%s%s",
00355 preamble, nv->name, rest ? " |" : ");");
00356 if(!rest)
00357 break;
00358
00359 snprintf(preamble, sizeof(preamble), "%*s", strlen(preamble), "");
00360 }
00361 }
00362
00363
00364
00365 if(rest)
00366 CODE2("%s%luUL);", preamble, rest);
00367 }
00368
00369 nomem:
00370 return ret;
00371 }
00372
00373
00374 CURLcode tool_setopt_httppost(CURL *curl, struct GlobalConfig *config,
00375 const char *name, CURLoption tag,
00376 struct curl_httppost *post)
00377 {
00378 CURLcode ret = CURLE_OK;
00379 char *escaped = NULL;
00380 bool skip = FALSE;
00381
00382 ret = curl_easy_setopt(curl, tag, post);
00383 if(!post)
00384 skip = TRUE;
00385
00386 if(config->libcurl && !skip && !ret) {
00387 struct curl_httppost *pp, *p;
00388 int i;
00389
00390 i = ++ easysrc_form_count;
00391 DECL1("struct curl_httppost *post%d;", i);
00392 DATA1("post%d = NULL;", i);
00393 CLEAN1("curl_formfree(post%d);", i);
00394 CLEAN1("post%d = NULL;", i);
00395 if(i == 1)
00396 DECL0("struct curl_httppost *postend;");
00397 DATA0("postend = NULL;");
00398 for(p=post; p; p=p->next) {
00399 DATA1("curl_formadd(&post%d, &postend,", i);
00400 DATA1(" CURLFORM_COPYNAME, \"%s\",", p->name);
00401 for(pp=p; pp; pp=pp->more) {
00402
00403
00404 Curl_safefree(escaped);
00405 escaped = c_escape(pp->contents);
00406 if(!escaped) {
00407 ret = CURLE_OUT_OF_MEMORY;
00408 goto nomem;
00409 }
00410 if(pp->flags & CURL_HTTPPOST_FILENAME) {
00411
00412 DATA1(" CURLFORM_FILE, \"%s\",", escaped);
00413 }
00414 else if(pp->flags & CURL_HTTPPOST_READFILE) {
00415
00416 DATA1(" CURLFORM_FILECONTENT, \"%s\",", escaped);
00417 }
00418 else
00419 DATA1(" CURLFORM_COPYCONTENTS, \"%s\",", escaped);
00420 if(pp->showfilename) {
00421 Curl_safefree(escaped);
00422 escaped = c_escape(pp->showfilename);
00423 if(!escaped) {
00424 ret = CURLE_OUT_OF_MEMORY;
00425 goto nomem;
00426 }
00427 DATA1(" CURLFORM_FILENAME, \"%s\",", escaped);
00428 }
00429 if(pp->contenttype) {
00430 Curl_safefree(escaped);
00431 escaped = c_escape(pp->contenttype);
00432 if(!escaped) {
00433 ret = CURLE_OUT_OF_MEMORY;
00434 goto nomem;
00435 }
00436 DATA1(" CURLFORM_CONTENTTYPE, \"%s\",", escaped);
00437 }
00438 }
00439 DATA0(" CURLFORM_END);");
00440 }
00441 CODE2("curl_easy_setopt(hnd, %s, post%d);", name, i);
00442 }
00443
00444 nomem:
00445 Curl_safefree(escaped);
00446 return ret;
00447 }
00448
00449
00450 CURLcode tool_setopt_slist(CURL *curl, struct GlobalConfig *config,
00451 const char *name, CURLoption tag,
00452 struct curl_slist *list)
00453 {
00454 CURLcode ret = CURLE_OK;
00455 char *escaped = NULL;
00456 bool skip = FALSE;
00457
00458 ret = curl_easy_setopt(curl, tag, list);
00459 if(!list)
00460 skip = TRUE;
00461
00462 if(config->libcurl && !skip && !ret) {
00463 struct curl_slist *s;
00464 int i;
00465
00466 i = ++ easysrc_slist_count;
00467 DECL1("struct curl_slist *slist%d;", i);
00468 DATA1("slist%d = NULL;", i);
00469 CLEAN1("curl_slist_free_all(slist%d);", i);
00470 CLEAN1("slist%d = NULL;", i);
00471 for(s=list; s; s=s->next) {
00472 Curl_safefree(escaped);
00473 escaped = c_escape(s->data);
00474 if(!escaped) {
00475 ret = CURLE_OUT_OF_MEMORY;
00476 goto nomem;
00477 }
00478 DATA3("slist%d = curl_slist_append(slist%d, \"%s\");", i, i, escaped);
00479 }
00480 CODE2("curl_easy_setopt(hnd, %s, slist%d);", name, i);
00481 }
00482
00483 nomem:
00484 Curl_safefree(escaped);
00485 return ret;
00486 }
00487
00488
00489
00490 CURLcode tool_setopt(CURL *curl, bool str, struct GlobalConfig *config,
00491 const char *name, CURLoption tag, ...)
00492 {
00493 va_list arg;
00494 char buf[256];
00495 const char *value = NULL;
00496 bool remark = FALSE;
00497 bool skip = FALSE;
00498 bool escape = FALSE;
00499 char *escaped = NULL;
00500 CURLcode ret = CURLE_OK;
00501
00502 va_start(arg, tag);
00503
00504 if(tag < CURLOPTTYPE_OBJECTPOINT) {
00505
00506 long lval = va_arg(arg, long);
00507 long defval = 0L;
00508 const NameValue *nv = NULL;
00509 for(nv=setopt_nv_CURLNONZERODEFAULTS; nv->name; nv++) {
00510 if(!strcmp(name, nv->name)) {
00511 defval = nv->value;
00512 break;
00513 }
00514 }
00515
00516 snprintf(buf, sizeof(buf), "%ldL", lval);
00517 value = buf;
00518 ret = curl_easy_setopt(curl, tag, lval);
00519 if(lval == defval)
00520 skip = TRUE;
00521 }
00522 else if(tag < CURLOPTTYPE_OFF_T) {
00523
00524 void *pval = va_arg(arg, void *);
00525
00526
00527 if(tag >= CURLOPTTYPE_FUNCTIONPOINT) {
00528 if(pval) {
00529 value = "functionpointer";
00530 remark = TRUE;
00531 }
00532 else
00533 skip = TRUE;
00534 }
00535
00536 else if(pval && str) {
00537 value = (char *)pval;
00538 escape = TRUE;
00539 }
00540 else if(pval) {
00541 value = "objectpointer";
00542 remark = TRUE;
00543 }
00544 else
00545 skip = TRUE;
00546
00547 ret = curl_easy_setopt(curl, tag, pval);
00548
00549 }
00550 else {
00551
00552 curl_off_t oval = va_arg(arg, curl_off_t);
00553 snprintf(buf, sizeof(buf),
00554 "(curl_off_t)%" CURL_FORMAT_CURL_OFF_T, oval);
00555 value = buf;
00556 ret = curl_easy_setopt(curl, tag, oval);
00557
00558 if(!oval)
00559 skip = TRUE;
00560 }
00561
00562 va_end(arg);
00563
00564 if(config->libcurl && !skip && !ret) {
00565
00566
00567 if(remark)
00568 REM2("%s set to a %s", name, value);
00569 else {
00570 if(escape) {
00571 escaped = c_escape(value);
00572 if(!escaped) {
00573 ret = CURLE_OUT_OF_MEMORY;
00574 goto nomem;
00575 }
00576 CODE2("curl_easy_setopt(hnd, %s, \"%s\");", name, escaped);
00577 }
00578 else
00579 CODE2("curl_easy_setopt(hnd, %s, %s);", name, value);
00580 }
00581 }
00582
00583 nomem:
00584 Curl_safefree(escaped);
00585 return ret;
00586 }
00587
00588 #endif