tool_setopt.c
Go to the documentation of this file.
00001 /***************************************************************************
00002  *                                  _   _ ____  _
00003  *  Project                     ___| | | |  _ \| |
00004  *                             / __| | | | |_) | |
00005  *                            | (__| |_| |  _ <| |___
00006  *                             \___|\___/|_| \_\_____|
00007  *
00008  * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
00009  *
00010  * This software is licensed as described in the file COPYING, which
00011  * you should have received as part of this distribution. The terms
00012  * are also available at https://curl.haxx.se/docs/copyright.html.
00013  *
00014  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
00015  * copies of the Software, and permit persons to whom the Software is
00016  * furnished to do so, under the terms of the COPYING file.
00017  *
00018  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
00019  * KIND, either express or implied.
00020  *
00021  ***************************************************************************/
00022 #include "tool_setup.h"
00023 
00024 #ifndef CURL_DISABLE_LIBCURL_OPTION
00025 
00026 #define ENABLE_CURLX_PRINTF
00027 /* use our own printf() functions */
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" /* keep this as LAST include */
00035 
00036 /* Lookup tables for converting setopt values back to symbols */
00037 /* For enums, values may be in any order. */
00038 /* For bit masks, put combinations first, then single bits, */
00039 /* and finally any "NONE" value. */
00040 
00041 #define NV(e) {#e, e}
00042 #define NV1(e, v) {#e, (v)}
00043 #define NVEND {NULL, 0}         /* sentinel to mark end of list */
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),             /* combination */
00066   NV(CURLAUTH_ANYSAFE),         /* combination */
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 /* These mappings essentially triplicated - see
00136  * tool_libinfo.c and tool_paramhlp.c */
00137 const NameValue setopt_nv_CURLPROTO[] = {
00138   NV(CURLPROTO_ALL),            /* combination */
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 /* These options have non-zero default values. */
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 /* Format and add code; jump to nomem on malloc error */
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 /* Escape string to C string syntax.  Return NULL if out of memory.
00209  * Is this correct for those wacky EBCDIC guys? */
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   /* Allocate space based on worst-case */
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 /* setopt wrapper for enum types */
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     /* we only use this for real if --libcurl was used */
00269     const NameValue *nv = NULL;
00270     for(nv=nvlist; nv->name; nv++) {
00271       if(nv->value == lval) break; /* found it */
00272     }
00273     if(! nv->name) {
00274       /* If no definition was found, output an explicit value.
00275        * This could happen if new values are defined and used
00276        * but the NameValue list is not updated. */
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 /* setopt wrapper for flags */
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     /* we only use this for real if --libcurl was used */
00302     char preamble[80];          /* should accommodate any symbol name */
00303     long rest = lval;           /* bits not handled yet */
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         /* all value flags contained in rest */
00310         rest &= ~ nv->value;    /* remove bits handled here */
00311         CODE3("%s(long)%s%s",
00312               preamble, nv->name, rest ? " |" : ");");
00313         if(!rest)
00314           break;                /* handled them all */
00315         /* replace with all spaces for continuation line */
00316         snprintf(preamble, sizeof(preamble), "%*s", strlen(preamble), "");
00317       }
00318     }
00319     /* If any bits have no definition, output an explicit value.
00320      * This could happen if new bits are defined and used
00321      * but the NameValue list is not updated. */
00322     if(rest)
00323       CODE2("%s%ldL);", preamble, rest);
00324   }
00325 
00326  nomem:
00327   return ret;
00328 }
00329 
00330 /* setopt wrapper for bitmasks */
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     /* we only use this for real if --libcurl was used */
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         /* all value flags contained in rest */
00353         rest &= ~ nv->value;    /* remove bits handled here */
00354         CODE3("%s(long)%s%s",
00355               preamble, nv->name, rest ? " |" : ");");
00356         if(!rest)
00357           break;                /* handled them all */
00358         /* replace with all spaces for continuation line */
00359         snprintf(preamble, sizeof(preamble), "%*s", strlen(preamble), "");
00360       }
00361     }
00362     /* If any bits have no definition, output an explicit value.
00363      * This could happen if new bits are defined and used
00364      * but the NameValue list is not updated. */
00365     if(rest)
00366       CODE2("%s%luUL);", preamble, rest);
00367   }
00368 
00369  nomem:
00370   return ret;
00371 }
00372 
00373 /* setopt wrapper for CURLOPT_HTTPPOST */
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     /* May use several httppost lists, if multiple POST actions */
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         /* May be several files uploaded for one name;
00403          * these are linked through the 'more' pointer */
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           /* file upload as for -F @filename */
00412           DATA1("             CURLFORM_FILE, \"%s\",", escaped);
00413         }
00414         else if(pp->flags & CURL_HTTPPOST_READFILE) {
00415           /* content from file as for -F <filename */
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 /* setopt wrapper for curl_slist options */
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     /* May need several slist variables, so invent name */
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 /* generic setopt wrapper for all other options.
00489  * Some type information is encoded in the tag value. */
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     /* Value is expected to be a long */
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; /* found it */
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     /* Value is some sort of object pointer */
00524     void *pval = va_arg(arg, void *);
00525 
00526     /* function pointers are never printable */
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     /* Value is expected to be curl_off_t */
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     /* we only use this for real if --libcurl was used */
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 /* CURL_DISABLE_LIBCURL_OPTION */


rc_visard_driver
Author(s): Heiko Hirschmueller , Christian Emmerich , Felix Ruess
autogenerated on Thu Jun 6 2019 20:43:07