tool_setopt.c (20618B)
1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 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.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 * SPDX-License-Identifier: curl 22 * 23 ***************************************************************************/ 24 #include "tool_setup.h" 25 26 #ifndef CURL_DISABLE_LIBCURL_OPTION 27 28 #include "tool_cfgable.h" 29 #include "tool_easysrc.h" 30 #include "tool_setopt.h" 31 #include "tool_msgs.h" 32 #include "memdebug.h" /* keep this as LAST include */ 33 34 /* Lookup tables for converting setopt values back to symbols */ 35 /* For enums, values may be in any order. */ 36 /* For bit masks, put combinations first, then single bits, */ 37 /* and finally any "NONE" value. */ 38 39 #define NV(e) {#e, e} 40 #define NV1(e, v) {#e, (v)} 41 #define NVEND {NULL, 0} /* sentinel to mark end of list */ 42 43 const struct NameValue setopt_nv_CURLPROXY[] = { 44 NV(CURLPROXY_HTTP), 45 NV(CURLPROXY_HTTP_1_0), 46 NV(CURLPROXY_HTTPS), 47 NV(CURLPROXY_SOCKS4), 48 NV(CURLPROXY_SOCKS5), 49 NV(CURLPROXY_SOCKS4A), 50 NV(CURLPROXY_SOCKS5_HOSTNAME), 51 NVEND, 52 }; 53 54 const struct NameValue setopt_nv_CURL_SOCKS_PROXY[] = { 55 NV(CURLPROXY_SOCKS4), 56 NV(CURLPROXY_SOCKS5), 57 NV(CURLPROXY_SOCKS4A), 58 NV(CURLPROXY_SOCKS5_HOSTNAME), 59 NVEND, 60 }; 61 62 const struct NameValueUnsigned setopt_nv_CURLHSTS[] = { 63 NV(CURLHSTS_ENABLE), 64 NVEND, 65 }; 66 67 const struct NameValueUnsigned setopt_nv_CURLAUTH[] = { 68 NV(CURLAUTH_ANY), /* combination */ 69 NV(CURLAUTH_ANYSAFE), /* combination */ 70 NV(CURLAUTH_BASIC), 71 NV(CURLAUTH_DIGEST), 72 NV(CURLAUTH_GSSNEGOTIATE), 73 NV(CURLAUTH_NTLM), 74 NV(CURLAUTH_DIGEST_IE), 75 NV(CURLAUTH_ONLY), 76 NV(CURLAUTH_NONE), 77 NVEND, 78 }; 79 80 const struct NameValue setopt_nv_CURL_HTTP_VERSION[] = { 81 NV(CURL_HTTP_VERSION_NONE), 82 NV(CURL_HTTP_VERSION_1_0), 83 NV(CURL_HTTP_VERSION_1_1), 84 NV(CURL_HTTP_VERSION_2_0), 85 NV(CURL_HTTP_VERSION_2TLS), 86 NV(CURL_HTTP_VERSION_3), 87 NV(CURL_HTTP_VERSION_3ONLY), 88 NVEND, 89 }; 90 91 const struct NameValue setopt_nv_CURL_SSLVERSION[] = { 92 NV(CURL_SSLVERSION_DEFAULT), 93 NV(CURL_SSLVERSION_TLSv1), 94 NV(CURL_SSLVERSION_SSLv2), 95 NV(CURL_SSLVERSION_SSLv3), 96 NV(CURL_SSLVERSION_TLSv1_0), 97 NV(CURL_SSLVERSION_TLSv1_1), 98 NV(CURL_SSLVERSION_TLSv1_2), 99 NV(CURL_SSLVERSION_TLSv1_3), 100 NVEND, 101 }; 102 103 const struct NameValue setopt_nv_CURL_SSLVERSION_MAX[] = { 104 NV(CURL_SSLVERSION_MAX_NONE), 105 NV(CURL_SSLVERSION_MAX_DEFAULT), 106 NV(CURL_SSLVERSION_MAX_TLSv1_0), 107 NV(CURL_SSLVERSION_MAX_TLSv1_1), 108 NV(CURL_SSLVERSION_MAX_TLSv1_2), 109 NV(CURL_SSLVERSION_MAX_TLSv1_3), 110 NVEND, 111 }; 112 113 const struct NameValue setopt_nv_CURL_TIMECOND[] = { 114 NV(CURL_TIMECOND_IFMODSINCE), 115 NV(CURL_TIMECOND_IFUNMODSINCE), 116 NV(CURL_TIMECOND_LASTMOD), 117 NV(CURL_TIMECOND_NONE), 118 NVEND, 119 }; 120 121 const struct NameValue setopt_nv_CURLFTPSSL_CCC[] = { 122 NV(CURLFTPSSL_CCC_NONE), 123 NV(CURLFTPSSL_CCC_PASSIVE), 124 NV(CURLFTPSSL_CCC_ACTIVE), 125 NVEND, 126 }; 127 128 const struct NameValue setopt_nv_CURLUSESSL[] = { 129 NV(CURLUSESSL_NONE), 130 NV(CURLUSESSL_TRY), 131 NV(CURLUSESSL_CONTROL), 132 NV(CURLUSESSL_ALL), 133 NVEND, 134 }; 135 136 const struct NameValueUnsigned setopt_nv_CURLSSLOPT[] = { 137 NV(CURLSSLOPT_ALLOW_BEAST), 138 NV(CURLSSLOPT_NO_REVOKE), 139 NV(CURLSSLOPT_NO_PARTIALCHAIN), 140 NV(CURLSSLOPT_REVOKE_BEST_EFFORT), 141 NV(CURLSSLOPT_NATIVE_CA), 142 NV(CURLSSLOPT_AUTO_CLIENT_CERT), 143 NVEND, 144 }; 145 146 const struct NameValue setopt_nv_CURL_NETRC[] = { 147 NV(CURL_NETRC_IGNORED), 148 NV(CURL_NETRC_OPTIONAL), 149 NV(CURL_NETRC_REQUIRED), 150 NVEND, 151 }; 152 153 /* These options have non-zero default values. */ 154 static const struct NameValue setopt_nv_CURLNONZERODEFAULTS[] = { 155 NV1(CURLOPT_SSL_VERIFYPEER, 1), 156 NV1(CURLOPT_SSL_VERIFYHOST, 1), 157 NV1(CURLOPT_SSL_ENABLE_NPN, 1), 158 NV1(CURLOPT_SSL_ENABLE_ALPN, 1), 159 NV1(CURLOPT_TCP_NODELAY, 1), 160 NV1(CURLOPT_PROXY_SSL_VERIFYPEER, 1), 161 NV1(CURLOPT_PROXY_SSL_VERIFYHOST, 1), 162 NV1(CURLOPT_SOCKS5_AUTH, 1), 163 NV1(CURLOPT_UPLOAD_FLAGS, CURLULFLAG_SEEN), 164 NVEND 165 }; 166 167 /* Escape string to C string syntax. Return NULL if out of memory. */ 168 #define MAX_STRING_LENGTH_OUTPUT 2000 169 #define ZERO_TERMINATED -1 170 171 static char *c_escape(const char *str, curl_off_t len) 172 { 173 const char *s; 174 unsigned int cutoff = 0; 175 CURLcode result; 176 struct dynbuf escaped; 177 178 curlx_dyn_init(&escaped, 4 * MAX_STRING_LENGTH_OUTPUT + 3); 179 180 if(len == ZERO_TERMINATED) 181 len = strlen(str); 182 183 if(len > MAX_STRING_LENGTH_OUTPUT) { 184 /* cap ridiculously long strings */ 185 len = MAX_STRING_LENGTH_OUTPUT; 186 cutoff = 3; 187 } 188 189 result = curlx_dyn_addn(&escaped, STRCONST("")); 190 for(s = str; !result && len; s++, len--) { 191 /* escape question marks as well, to prevent generating accidental 192 trigraphs */ 193 static const char from[] = "\t\r\n?\"\\"; 194 static const char to[] = "\\t\\r\\n\\?\\\"\\\\"; 195 const char *p = strchr(from, *s); 196 197 if(!p && ISPRINT(*s)) 198 continue; 199 200 result = curlx_dyn_addn(&escaped, str, s - str); 201 str = s + 1; 202 203 if(!result) { 204 if(p && *p) 205 result = curlx_dyn_addn(&escaped, to + 2 * (p - from), 2); 206 else { 207 result = curlx_dyn_addf(&escaped, 208 /* Octal escape to avoid >2 digit hex. */ 209 (len > 1 && ISXDIGIT(s[1])) ? 210 "\\%03o" : "\\x%02x", 211 (unsigned int) *(const unsigned char *) s); 212 } 213 } 214 } 215 216 if(!result) 217 result = curlx_dyn_addn(&escaped, str, s - str); 218 219 if(!result) 220 (void) !curlx_dyn_addn(&escaped, "...", cutoff); 221 222 return curlx_dyn_ptr(&escaped); 223 } 224 225 /* setopt wrapper for enum types */ 226 CURLcode tool_setopt_enum(CURL *curl, struct OperationConfig *config, 227 const char *name, CURLoption tag, 228 const struct NameValue *nvlist, long lval) 229 { 230 CURLcode ret = CURLE_OK; 231 bool skip = FALSE; 232 233 ret = curl_easy_setopt(curl, tag, lval); 234 if(!lval) 235 skip = TRUE; 236 237 if(config->global->libcurl && !skip && !ret) { 238 /* we only use this for real if --libcurl was used */ 239 const struct NameValue *nv = NULL; 240 for(nv = nvlist; nv->name; nv++) { 241 if(nv->value == lval) 242 break; /* found it */ 243 } 244 if(!nv->name) { 245 /* If no definition was found, output an explicit value. 246 * This could happen if new values are defined and used 247 * but the NameValue list is not updated. */ 248 ret = easysrc_addf(&easysrc_code, "curl_easy_setopt(hnd, %s, %ldL);", 249 name, lval); 250 } 251 else { 252 ret = easysrc_addf(&easysrc_code, "curl_easy_setopt(hnd, %s, (long)%s);", 253 name, nv->name); 254 } 255 } 256 257 #ifdef DEBUGBUILD 258 if(ret) 259 warnf(config->global, "option %s returned error (%d)", name, (int)ret); 260 #endif 261 return ret; 262 } 263 264 /* setopt wrapper for CURLOPT_SSLVERSION */ 265 CURLcode tool_setopt_SSLVERSION(CURL *curl, struct OperationConfig *config, 266 const char *name, CURLoption tag, 267 long lval) 268 { 269 CURLcode ret = CURLE_OK; 270 bool skip = FALSE; 271 272 ret = curl_easy_setopt(curl, tag, lval); 273 if(!lval) 274 skip = TRUE; 275 276 if(config->global->libcurl && !skip && !ret) { 277 /* we only use this for real if --libcurl was used */ 278 const struct NameValue *nv = NULL; 279 const struct NameValue *nv2 = NULL; 280 for(nv = setopt_nv_CURL_SSLVERSION; nv->name; nv++) { 281 if(nv->value == (lval & 0xffff)) 282 break; /* found it */ 283 } 284 for(nv2 = setopt_nv_CURL_SSLVERSION_MAX; nv2->name; nv2++) { 285 if(nv2->value == (lval & ~0xffff)) 286 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 ret = easysrc_addf(&easysrc_code, "curl_easy_setopt(hnd, %s, %ldL);", 293 name, lval); 294 } 295 else { 296 ret = easysrc_addf(&easysrc_code, 297 "curl_easy_setopt(hnd, %s, (long)(%s | %s));", 298 name, nv->name, nv2->name); 299 } 300 } 301 302 #ifdef DEBUGBUILD 303 if(ret) 304 warnf(config->global, "option %s returned error (%d)", name, (int)ret); 305 #endif 306 return ret; 307 } 308 309 /* setopt wrapper for bitmasks */ 310 CURLcode tool_setopt_bitmask(CURL *curl, struct OperationConfig *config, 311 const char *name, CURLoption tag, 312 const struct NameValueUnsigned *nvlist, 313 long lval) 314 { 315 bool skip = FALSE; 316 CURLcode ret = curl_easy_setopt(curl, tag, lval); 317 if(!lval) 318 skip = TRUE; 319 320 if(config->global->libcurl && !skip && !ret) { 321 /* we only use this for real if --libcurl was used */ 322 char preamble[80]; 323 unsigned long rest = (unsigned long)lval; 324 const struct NameValueUnsigned *nv = NULL; 325 msnprintf(preamble, sizeof(preamble), 326 "curl_easy_setopt(hnd, %s, ", name); 327 for(nv = nvlist; nv->name; nv++) { 328 if((nv->value & ~ rest) == 0) { 329 /* all value flags contained in rest */ 330 rest &= ~ nv->value; /* remove bits handled here */ 331 ret = easysrc_addf(&easysrc_code, "%s(long)%s%s", 332 preamble, nv->name, rest ? " |" : ");"); 333 if(!rest || ret) 334 break; /* handled them all */ 335 /* replace with all spaces for continuation line */ 336 msnprintf(preamble, sizeof(preamble), "%*s", (int)strlen(preamble), 337 ""); 338 } 339 } 340 /* If any bits have no definition, output an explicit value. 341 * This could happen if new bits are defined and used 342 * but the NameValue list is not updated. */ 343 if(rest && !ret) 344 ret = easysrc_addf(&easysrc_code, "%s%luUL);", preamble, rest); 345 } 346 347 return ret; 348 } 349 350 /* Generate code for a struct curl_slist. */ 351 static CURLcode libcurl_generate_slist(struct curl_slist *slist, int *slistno) 352 { 353 CURLcode ret = CURLE_OK; 354 355 /* May need several slist variables, so invent name */ 356 *slistno = ++easysrc_slist_count; 357 358 ret = easysrc_addf(&easysrc_decl, "struct curl_slist *slist%d;", *slistno); 359 if(!ret) 360 ret = easysrc_addf(&easysrc_data, "slist%d = NULL;", *slistno); 361 if(!ret) 362 ret = easysrc_addf(&easysrc_clean, "curl_slist_free_all(slist%d);", 363 *slistno); 364 if(!ret) 365 ret = easysrc_addf(&easysrc_clean, "slist%d = NULL;", *slistno); 366 if(ret) 367 return ret; 368 for(; slist && !ret; slist = slist->next) { 369 char *escaped = c_escape(slist->data, ZERO_TERMINATED); 370 if(!escaped) 371 return CURLE_OUT_OF_MEMORY; 372 ret = easysrc_addf(&easysrc_data, 373 "slist%d = curl_slist_append(slist%d, \"%s\");", 374 *slistno, *slistno, escaped); 375 free(escaped); 376 } 377 378 return ret; 379 } 380 381 static CURLcode libcurl_generate_mime(CURL *curl, 382 struct OperationConfig *config, 383 struct tool_mime *toolmime, 384 int *mimeno); /* Forward. */ 385 386 /* Wrapper to generate source code for a mime part. */ 387 static CURLcode libcurl_generate_mime_part(CURL *curl, 388 struct OperationConfig *config, 389 struct tool_mime *part, 390 int mimeno) 391 { 392 CURLcode ret = CURLE_OK; 393 int submimeno = 0; 394 const char *data = NULL; 395 const char *filename = part->filename; 396 397 /* Parts are linked in reverse order. */ 398 if(part->prev) 399 ret = libcurl_generate_mime_part(curl, config, part->prev, mimeno); 400 401 /* Create the part. */ 402 if(!ret) 403 ret = easysrc_addf(&easysrc_code, "part%d = curl_mime_addpart(mime%d);", 404 mimeno, mimeno); 405 if(ret) 406 return ret; 407 408 switch(part->kind) { 409 case TOOLMIME_PARTS: 410 ret = libcurl_generate_mime(curl, config, part, &submimeno); 411 if(!ret) { 412 ret = easysrc_addf(&easysrc_code, "curl_mime_subparts(part%d, mime%d);", 413 mimeno, submimeno); 414 if(!ret) 415 /* Avoid freeing in CLEAN. */ 416 ret = easysrc_addf(&easysrc_code, 417 "mime%d = NULL;", submimeno); 418 } 419 break; 420 421 case TOOLMIME_DATA: 422 data = part->data; 423 if(!ret) { 424 char *escaped = c_escape(data, ZERO_TERMINATED); 425 ret = 426 easysrc_addf(&easysrc_code, 427 "curl_mime_data(part%d, \"%s\", CURL_ZERO_TERMINATED);", 428 mimeno, escaped); 429 free(escaped); 430 } 431 break; 432 433 case TOOLMIME_FILE: 434 case TOOLMIME_FILEDATA: { 435 char *escaped = c_escape(part->data, ZERO_TERMINATED); 436 ret = easysrc_addf(&easysrc_code, 437 "curl_mime_filedata(part%d, \"%s\");", mimeno, escaped); 438 if(part->kind == TOOLMIME_FILEDATA && !filename && !ret) { 439 ret = easysrc_addf(&easysrc_code, 440 "curl_mime_filename(part%d, NULL);", mimeno); 441 } 442 free(escaped); 443 break; 444 } 445 446 case TOOLMIME_STDIN: 447 if(!filename) 448 filename = "-"; 449 FALLTHROUGH(); 450 case TOOLMIME_STDINDATA: 451 /* Can only be reading stdin in the current context. */ 452 ret = easysrc_addf(&easysrc_code, "curl_mime_data_cb(part%d, -1, " 453 "(curl_read_callback) fread, \\", mimeno); 454 if(!ret) 455 ret = easysrc_addf(&easysrc_code, " " 456 "(curl_seek_callback) fseek, NULL, stdin);"); 457 break; 458 default: 459 /* Other cases not possible in this context. */ 460 break; 461 } 462 463 if(!ret && part->encoder) { 464 char *escaped = c_escape(part->encoder, ZERO_TERMINATED); 465 ret = easysrc_addf(&easysrc_code, "curl_mime_encoder(part%d, \"%s\");", 466 mimeno, escaped); 467 free(escaped); 468 } 469 470 if(!ret && filename) { 471 char *escaped = c_escape(filename, ZERO_TERMINATED); 472 ret = easysrc_addf(&easysrc_code, "curl_mime_filename(part%d, \"%s\");", 473 mimeno, escaped); 474 free(escaped); 475 } 476 477 if(!ret && part->name) { 478 char *escaped = c_escape(part->name, ZERO_TERMINATED); 479 ret = easysrc_addf(&easysrc_code, "curl_mime_name(part%d, \"%s\");", 480 mimeno, escaped); 481 free(escaped); 482 } 483 484 if(!ret && part->type) { 485 char *escaped = c_escape(part->type, ZERO_TERMINATED); 486 ret = easysrc_addf(&easysrc_code, "curl_mime_type(part%d, \"%s\");", 487 mimeno, escaped); 488 free(escaped); 489 } 490 491 if(!ret && part->headers) { 492 int slistno; 493 494 ret = libcurl_generate_slist(part->headers, &slistno); 495 if(!ret) { 496 ret = easysrc_addf(&easysrc_code, 497 "curl_mime_headers(part%d, slist%d, 1);", 498 mimeno, slistno); 499 if(!ret) 500 ret = easysrc_addf(&easysrc_code, 501 "slist%d = NULL;", slistno); /* Prevent CLEANing. */ 502 } 503 } 504 505 return ret; 506 } 507 508 /* Wrapper to generate source code for a mime structure. */ 509 static CURLcode libcurl_generate_mime(CURL *curl, 510 struct OperationConfig *config, 511 struct tool_mime *toolmime, 512 int *mimeno) 513 { 514 CURLcode ret = CURLE_OK; 515 516 /* May need several mime variables, so invent name. */ 517 *mimeno = ++easysrc_mime_count; 518 ret = easysrc_addf(&easysrc_decl, "curl_mime *mime%d;", *mimeno); 519 if(!ret) 520 ret = easysrc_addf(&easysrc_data, "mime%d = NULL;", *mimeno); 521 if(!ret) 522 ret = easysrc_addf(&easysrc_code, "mime%d = curl_mime_init(hnd);", 523 *mimeno); 524 if(!ret) 525 ret = easysrc_addf(&easysrc_clean, "curl_mime_free(mime%d);", *mimeno); 526 if(!ret) 527 ret = easysrc_addf(&easysrc_clean, "mime%d = NULL;", *mimeno); 528 529 if(toolmime->subparts && !ret) { 530 ret = easysrc_addf(&easysrc_decl, "curl_mimepart *part%d;", *mimeno); 531 if(!ret) 532 ret = libcurl_generate_mime_part(curl, config, 533 toolmime->subparts, *mimeno); 534 } 535 536 return ret; 537 } 538 539 /* setopt wrapper for CURLOPT_MIMEPOST */ 540 CURLcode tool_setopt_mimepost(CURL *curl, struct OperationConfig *config, 541 const char *name, CURLoption tag, 542 curl_mime *mimepost) 543 { 544 CURLcode ret = curl_easy_setopt(curl, tag, mimepost); 545 int mimeno = 0; 546 547 if(!ret && config->global->libcurl) { 548 ret = libcurl_generate_mime(curl, config, config->mimeroot, &mimeno); 549 550 if(!ret) 551 ret = easysrc_addf(&easysrc_code, "curl_easy_setopt(hnd, %s, mime%d);", 552 name, mimeno); 553 } 554 555 return ret; 556 } 557 558 /* setopt wrapper for curl_slist options */ 559 CURLcode tool_setopt_slist(CURL *curl, struct OperationConfig *config, 560 const char *name, CURLoption tag, 561 struct curl_slist *list) 562 { 563 CURLcode ret = CURLE_OK; 564 565 ret = curl_easy_setopt(curl, tag, list); 566 567 if(config->global->libcurl && list && !ret) { 568 int i; 569 570 ret = libcurl_generate_slist(list, &i); 571 if(!ret) 572 ret = easysrc_addf(&easysrc_code, "curl_easy_setopt(hnd, %s, slist%d);", 573 name, i); 574 } 575 576 return ret; 577 } 578 579 /* options that set long */ 580 CURLcode tool_setopt_long(CURL *curl, struct OperationConfig *config, 581 const char *name, CURLoption tag, 582 long lval) 583 { 584 long defval = 0L; 585 const struct NameValue *nv = NULL; 586 CURLcode ret = CURLE_OK; 587 DEBUGASSERT(tag < CURLOPTTYPE_OBJECTPOINT); 588 589 for(nv = setopt_nv_CURLNONZERODEFAULTS; nv->name; nv++) { 590 if(!strcmp(name, nv->name)) { 591 defval = nv->value; 592 break; /* found it */ 593 } 594 } 595 596 ret = curl_easy_setopt(curl, tag, lval); 597 if((lval != defval) && config->global->libcurl && !ret) { 598 /* we only use this for real if --libcurl was used */ 599 ret = easysrc_addf(&easysrc_code, "curl_easy_setopt(hnd, %s, %ldL);", 600 name, lval); 601 } 602 return ret; 603 } 604 605 /* options that set curl_off_t */ 606 CURLcode tool_setopt_offt(CURL *curl, struct OperationConfig *config, 607 const char *name, CURLoption tag, 608 curl_off_t lval) 609 { 610 CURLcode ret = CURLE_OK; 611 DEBUGASSERT((tag >= CURLOPTTYPE_OFF_T) && (tag < CURLOPTTYPE_BLOB)); 612 613 ret = curl_easy_setopt(curl, tag, lval); 614 if(config->global->libcurl && !ret && lval) { 615 /* we only use this for real if --libcurl was used */ 616 ret = easysrc_addf(&easysrc_code, "curl_easy_setopt(hnd, %s, (curl_off_t)%" 617 CURL_FORMAT_CURL_OFF_T ");", name, lval); 618 } 619 620 return ret; 621 } 622 623 /* setopt wrapper for setting object and function pointer options */ 624 CURLcode tool_setopt(CURL *curl, bool str, struct OperationConfig *config, 625 const char *name, CURLoption tag, ...) 626 { 627 va_list arg; 628 CURLcode ret = CURLE_OK; 629 void *pval; 630 631 va_start(arg, tag); 632 633 DEBUGASSERT(tag >= CURLOPTTYPE_OBJECTPOINT); 634 DEBUGASSERT((tag < CURLOPTTYPE_OFF_T) || (tag >= CURLOPTTYPE_BLOB)); 635 636 /* we never set _BLOB options in the curl tool */ 637 DEBUGASSERT(tag < CURLOPTTYPE_BLOB); 638 639 /* argument is an object or function pointer */ 640 pval = va_arg(arg, void *); 641 642 ret = curl_easy_setopt(curl, tag, pval); 643 644 va_end(arg); 645 646 if(config->global->libcurl && pval && !ret) { 647 /* we only use this if --libcurl was used */ 648 649 if(!str) { 650 /* function pointers are never printable */ 651 const char *remark = (tag >= CURLOPTTYPE_FUNCTIONPOINT) ? 652 "function" : "object"; 653 ret = easysrc_addf(&easysrc_toohard, 654 "%s was set to a%s %s pointer", name, 655 (*remark == 'o' ? "n" : ""), remark); 656 } 657 else { 658 curl_off_t len = ZERO_TERMINATED; 659 char *escaped; 660 if(tag == CURLOPT_POSTFIELDS) 661 len = curlx_dyn_len(&config->postdata); 662 escaped = c_escape(pval, len); 663 if(escaped) { 664 ret = easysrc_addf(&easysrc_code, "curl_easy_setopt(hnd, %s, \"%s\");", 665 name, escaped); 666 free(escaped); 667 } 668 } 669 } 670 671 return ret; 672 } 673 674 #endif /* CURL_DISABLE_LIBCURL_OPTION */