Annotation of embedaddon/curl/src/tool_setopt.c, revision 1.1.1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>