tool_paramhlp.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 #include "strcase.h"
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_getparam.h"
00032 #include "tool_getpass.h"
00033 #include "tool_homedir.h"
00034 #include "tool_msgs.h"
00035 #include "tool_paramhlp.h"
00036 #include "tool_version.h"
00037 
00038 #include "memdebug.h" /* keep this as LAST include */
00039 
00040 struct getout *new_getout(struct OperationConfig *config)
00041 {
00042   struct getout *node = calloc(1, sizeof(struct getout));
00043   struct getout *last = config->url_last;
00044   if(node) {
00045     /* append this new node last in the list */
00046     if(last)
00047       last->next = node;
00048     else
00049       config->url_list = node; /* first node */
00050 
00051     /* move the last pointer */
00052     config->url_last = node;
00053 
00054     node->flags = config->default_node_flags;
00055   }
00056   return node;
00057 }
00058 
00059 ParameterError file2string(char **bufp, FILE *file)
00060 {
00061   char buffer[256];
00062   char *ptr;
00063   char *string = NULL;
00064   size_t stringlen = 0;
00065   size_t buflen;
00066 
00067   if(file) {
00068     while(fgets(buffer, sizeof(buffer), file)) {
00069       ptr = strchr(buffer, '\r');
00070       if(ptr)
00071         *ptr = '\0';
00072       ptr = strchr(buffer, '\n');
00073       if(ptr)
00074         *ptr = '\0';
00075       buflen = strlen(buffer);
00076       ptr = realloc(string, stringlen+buflen+1);
00077       if(!ptr) {
00078         Curl_safefree(string);
00079         return PARAM_NO_MEM;
00080       }
00081       string = ptr;
00082       strcpy(string+stringlen, buffer);
00083       stringlen += buflen;
00084     }
00085   }
00086   *bufp = string;
00087   return PARAM_OK;
00088 }
00089 
00090 ParameterError file2memory(char **bufp, size_t *size, FILE *file)
00091 {
00092   char *newbuf;
00093   char *buffer = NULL;
00094   size_t alloc = 512;
00095   size_t nused = 0;
00096   size_t nread;
00097 
00098   if(file) {
00099     do {
00100       if(!buffer || (alloc == nused)) {
00101         /* size_t overflow detection for huge files */
00102         if(alloc+1 > ((size_t)-1)/2) {
00103           Curl_safefree(buffer);
00104           return PARAM_NO_MEM;
00105         }
00106         alloc *= 2;
00107         /* allocate an extra char, reserved space, for null termination */
00108         newbuf = realloc(buffer, alloc+1);
00109         if(!newbuf) {
00110           Curl_safefree(buffer);
00111           return PARAM_NO_MEM;
00112         }
00113         buffer = newbuf;
00114       }
00115       nread = fread(buffer+nused, 1, alloc-nused, file);
00116       nused += nread;
00117     } while(nread);
00118     /* null terminate the buffer in case it's used as a string later */
00119     buffer[nused] = '\0';
00120     /* free trailing slack space, if possible */
00121     if(alloc != nused) {
00122       newbuf = realloc(buffer, nused+1);
00123       if(!newbuf) {
00124         Curl_safefree(buffer);
00125         return PARAM_NO_MEM;
00126       }
00127       buffer = newbuf;
00128     }
00129     /* discard buffer if nothing was read */
00130     if(!nused) {
00131       Curl_safefree(buffer); /* no string */
00132     }
00133   }
00134   *size = nused;
00135   *bufp = buffer;
00136   return PARAM_OK;
00137 }
00138 
00139 void cleanarg(char *str)
00140 {
00141 #ifdef HAVE_WRITABLE_ARGV
00142   /* now that GetStr has copied the contents of nextarg, wipe the next
00143    * argument out so that the username:password isn't displayed in the
00144    * system process list */
00145   if(str) {
00146     size_t len = strlen(str);
00147     memset(str, ' ', len);
00148   }
00149 #else
00150   (void)str;
00151 #endif
00152 }
00153 
00154 /*
00155  * Parse the string and write the long in the given address. Return PARAM_OK
00156  * on success, otherwise a parameter specific error enum.
00157  *
00158  * Since this function gets called with the 'nextarg' pointer from within the
00159  * getparameter a lot, we must check it for NULL before accessing the str
00160  * data.
00161  */
00162 
00163 ParameterError str2num(long *val, const char *str)
00164 {
00165   if(str) {
00166     char *endptr;
00167     long num = strtol(str, &endptr, 10);
00168     if((endptr != str) && (endptr == str + strlen(str))) {
00169       *val = num;
00170       return PARAM_OK;  /* Ok */
00171     }
00172   }
00173   return PARAM_BAD_NUMERIC; /* badness */
00174 }
00175 
00176 /*
00177  * Parse the string and write the long in the given address. Return PARAM_OK
00178  * on success, otherwise a parameter error enum. ONLY ACCEPTS POSITIVE NUMBERS!
00179  *
00180  * Since this function gets called with the 'nextarg' pointer from within the
00181  * getparameter a lot, we must check it for NULL before accessing the str
00182  * data.
00183  */
00184 
00185 ParameterError str2unum(long *val, const char *str)
00186 {
00187   ParameterError result = str2num(val, str);
00188   if(result != PARAM_OK)
00189     return result;
00190   if(*val < 0)
00191     return PARAM_NEGATIVE_NUMERIC;
00192 
00193   return PARAM_OK;
00194 }
00195 
00196 /*
00197  * Parse the string and write the double in the given address. Return PARAM_OK
00198  * on success, otherwise a parameter specific error enum.
00199  *
00200  * Since this function gets called with the 'nextarg' pointer from within the
00201  * getparameter a lot, we must check it for NULL before accessing the str
00202  * data.
00203  */
00204 
00205 ParameterError str2double(double *val, const char *str)
00206 {
00207   if(str) {
00208     char *endptr;
00209     double num = strtod(str, &endptr);
00210     if((endptr != str) && (endptr == str + strlen(str))) {
00211       *val = num;
00212       return PARAM_OK;  /* Ok */
00213     }
00214   }
00215   return PARAM_BAD_NUMERIC; /* badness */
00216 }
00217 
00218 /*
00219  * Parse the string and write the double in the given address. Return PARAM_OK
00220  * on success, otherwise a parameter error enum. ONLY ACCEPTS POSITIVE NUMBERS!
00221  *
00222  * Since this function gets called with the 'nextarg' pointer from within the
00223  * getparameter a lot, we must check it for NULL before accessing the str
00224  * data.
00225  */
00226 
00227 ParameterError str2udouble(double *val, const char *str)
00228 {
00229   ParameterError result = str2double(val, str);
00230   if(result != PARAM_OK)
00231     return result;
00232   if(*val < 0)
00233     return PARAM_NEGATIVE_NUMERIC;
00234 
00235   return PARAM_OK;
00236 }
00237 
00238 /*
00239  * Parse the string and modify the long in the given address. Return
00240  * non-zero on failure, zero on success.
00241  *
00242  * The string is a list of protocols
00243  *
00244  * Since this function gets called with the 'nextarg' pointer from within the
00245  * getparameter a lot, we must check it for NULL before accessing the str
00246  * data.
00247  */
00248 
00249 long proto2num(struct OperationConfig *config, long *val, const char *str)
00250 {
00251   char *buffer;
00252   const char *sep = ",";
00253   char *token;
00254 
00255   static struct sprotos {
00256     const char *name;
00257     long bit;
00258   } const protos[] = {
00259     { "all", CURLPROTO_ALL },
00260     { "http", CURLPROTO_HTTP },
00261     { "https", CURLPROTO_HTTPS },
00262     { "ftp", CURLPROTO_FTP },
00263     { "ftps", CURLPROTO_FTPS },
00264     { "scp", CURLPROTO_SCP },
00265     { "sftp", CURLPROTO_SFTP },
00266     { "telnet", CURLPROTO_TELNET },
00267     { "ldap", CURLPROTO_LDAP },
00268     { "ldaps", CURLPROTO_LDAPS },
00269     { "dict", CURLPROTO_DICT },
00270     { "file", CURLPROTO_FILE },
00271     { "tftp", CURLPROTO_TFTP },
00272     { "imap", CURLPROTO_IMAP },
00273     { "imaps", CURLPROTO_IMAPS },
00274     { "pop3", CURLPROTO_POP3 },
00275     { "pop3s", CURLPROTO_POP3S },
00276     { "smtp", CURLPROTO_SMTP },
00277     { "smtps", CURLPROTO_SMTPS },
00278     { "rtsp", CURLPROTO_RTSP },
00279     { "gopher", CURLPROTO_GOPHER },
00280     { "smb", CURLPROTO_SMB },
00281     { "smbs", CURLPROTO_SMBS },
00282     { NULL, 0 }
00283   };
00284 
00285   if(!str)
00286     return 1;
00287 
00288   buffer = strdup(str); /* because strtok corrupts it */
00289   if(!buffer)
00290     return 1;
00291 
00292   /* Allow strtok() here since this isn't used threaded */
00293   /* !checksrc! disable BANNEDFUNC 2 */
00294   for(token = strtok(buffer, sep);
00295       token;
00296       token = strtok(NULL, sep)) {
00297     enum e_action { allow, deny, set } action = allow;
00298 
00299     struct sprotos const *pp;
00300 
00301     /* Process token modifiers */
00302     while(!ISALNUM(*token)) { /* may be NULL if token is all modifiers */
00303       switch (*token++) {
00304       case '=':
00305         action = set;
00306         break;
00307       case '-':
00308         action = deny;
00309         break;
00310       case '+':
00311         action = allow;
00312         break;
00313       default: /* Includes case of terminating NULL */
00314         Curl_safefree(buffer);
00315         return 1;
00316       }
00317     }
00318 
00319     for(pp=protos; pp->name; pp++) {
00320       if(curl_strequal(token, pp->name)) {
00321         switch(action) {
00322         case deny:
00323           *val &= ~(pp->bit);
00324           break;
00325         case allow:
00326           *val |= pp->bit;
00327           break;
00328         case set:
00329           *val = pp->bit;
00330           break;
00331         }
00332         break;
00333       }
00334     }
00335 
00336     if(!(pp->name)) { /* unknown protocol */
00337       /* If they have specified only this protocol, we say treat it as
00338          if no protocols are allowed */
00339       if(action == set)
00340         *val = 0;
00341       warnf(config->global, "unrecognized protocol '%s'\n", token);
00342     }
00343   }
00344   Curl_safefree(buffer);
00345   return 0;
00346 }
00347 
00356 int check_protocol(const char *str)
00357 {
00358   const char * const *pp;
00359   const curl_version_info_data *curlinfo = curl_version_info(CURLVERSION_NOW);
00360   if(!str)
00361     return PARAM_REQUIRES_PARAMETER;
00362   for(pp = curlinfo->protocols; *pp; pp++) {
00363     if(curl_strequal(*pp, str))
00364       return PARAM_OK;
00365   }
00366   return PARAM_LIBCURL_UNSUPPORTED_PROTOCOL;
00367 }
00368 
00377 ParameterError str2offset(curl_off_t *val, const char *str)
00378 {
00379   char *endptr;
00380   if(str[0] == '-')
00381     /* offsets aren't negative, this indicates weird input */
00382     return PARAM_NEGATIVE_NUMERIC;
00383 
00384 #if(CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG)
00385   *val = curlx_strtoofft(str, &endptr, 0);
00386   if((*val == CURL_OFF_T_MAX || *val == CURL_OFF_T_MIN) && (ERRNO == ERANGE))
00387     return PARAM_BAD_NUMERIC;
00388 #else
00389   *val = strtol(str, &endptr, 0);
00390   if((*val == LONG_MIN || *val == LONG_MAX) && ERRNO == ERANGE)
00391     return PARAM_BAD_NUMERIC;
00392 #endif
00393   if((endptr != str) && (endptr == str + strlen(str)))
00394     return PARAM_OK;
00395 
00396   return PARAM_BAD_NUMERIC;
00397 }
00398 
00399 static CURLcode checkpasswd(const char *kind, /* for what purpose */
00400                             const size_t i,   /* operation index */
00401                             const bool last,  /* TRUE if last operation */
00402                             char **userpwd)   /* pointer to allocated string */
00403 {
00404   char *psep;
00405   char *osep;
00406 
00407   if(!*userpwd)
00408     return CURLE_OK;
00409 
00410   /* Attempt to find the password separator */
00411   psep = strchr(*userpwd, ':');
00412 
00413   /* Attempt to find the options separator */
00414   osep = strchr(*userpwd, ';');
00415 
00416   if(!psep && **userpwd != ';') {
00417     /* no password present, prompt for one */
00418     char passwd[256] = "";
00419     char prompt[256];
00420     size_t passwdlen;
00421     size_t userlen = strlen(*userpwd);
00422     char *passptr;
00423 
00424     if(osep)
00425       *osep = '\0';
00426 
00427     /* build a nice-looking prompt */
00428     if(!i && last)
00429       curlx_msnprintf(prompt, sizeof(prompt),
00430                       "Enter %s password for user '%s':",
00431                       kind, *userpwd);
00432     else
00433       curlx_msnprintf(prompt, sizeof(prompt),
00434                       "Enter %s password for user '%s' on URL #%"
00435                       CURL_FORMAT_CURL_OFF_TU ":",
00436                       kind, *userpwd, (curl_off_t) (i + 1));
00437 
00438     /* get password */
00439     getpass_r(prompt, passwd, sizeof(passwd));
00440     passwdlen = strlen(passwd);
00441 
00442     if(osep)
00443       *osep = ';';
00444 
00445     /* extend the allocated memory area to fit the password too */
00446     passptr = realloc(*userpwd,
00447                       passwdlen + 1 + /* an extra for the colon */
00448                       userlen + 1);   /* an extra for the zero */
00449     if(!passptr)
00450       return CURLE_OUT_OF_MEMORY;
00451 
00452     /* append the password separated with a colon */
00453     passptr[userlen] = ':';
00454     memcpy(&passptr[userlen+1], passwd, passwdlen+1);
00455     *userpwd = passptr;
00456   }
00457 
00458   return CURLE_OK;
00459 }
00460 
00461 ParameterError add2list(struct curl_slist **list, const char *ptr)
00462 {
00463   struct curl_slist *newlist = curl_slist_append(*list, ptr);
00464   if(newlist)
00465     *list = newlist;
00466   else
00467     return PARAM_NO_MEM;
00468 
00469   return PARAM_OK;
00470 }
00471 
00472 int ftpfilemethod(struct OperationConfig *config, const char *str)
00473 {
00474   if(curl_strequal("singlecwd", str))
00475     return CURLFTPMETHOD_SINGLECWD;
00476   if(curl_strequal("nocwd", str))
00477     return CURLFTPMETHOD_NOCWD;
00478   if(curl_strequal("multicwd", str))
00479     return CURLFTPMETHOD_MULTICWD;
00480 
00481   warnf(config->global, "unrecognized ftp file method '%s', using default\n",
00482         str);
00483 
00484   return CURLFTPMETHOD_MULTICWD;
00485 }
00486 
00487 int ftpcccmethod(struct OperationConfig *config, const char *str)
00488 {
00489   if(curl_strequal("passive", str))
00490     return CURLFTPSSL_CCC_PASSIVE;
00491   if(curl_strequal("active", str))
00492     return CURLFTPSSL_CCC_ACTIVE;
00493 
00494   warnf(config->global, "unrecognized ftp CCC method '%s', using default\n",
00495         str);
00496 
00497   return CURLFTPSSL_CCC_PASSIVE;
00498 }
00499 
00500 long delegation(struct OperationConfig *config, char *str)
00501 {
00502   if(curl_strequal("none", str))
00503     return CURLGSSAPI_DELEGATION_NONE;
00504   if(curl_strequal("policy", str))
00505     return CURLGSSAPI_DELEGATION_POLICY_FLAG;
00506   if(curl_strequal("always", str))
00507     return CURLGSSAPI_DELEGATION_FLAG;
00508 
00509   warnf(config->global, "unrecognized delegation method '%s', using none\n",
00510         str);
00511 
00512   return CURLGSSAPI_DELEGATION_NONE;
00513 }
00514 
00515 /*
00516  * my_useragent: returns allocated string with default user agent
00517  */
00518 static char *my_useragent(void)
00519 {
00520   return strdup(CURL_NAME "/" CURL_VERSION);
00521 }
00522 
00523 CURLcode get_args(struct OperationConfig *config, const size_t i)
00524 {
00525   CURLcode result = CURLE_OK;
00526   bool last = (config->next ? FALSE : TRUE);
00527 
00528   /* Check we have a password for the given host user */
00529   if(config->userpwd && !config->oauth_bearer) {
00530     result = checkpasswd("host", i, last, &config->userpwd);
00531     if(result)
00532       return result;
00533   }
00534 
00535   /* Check we have a password for the given proxy user */
00536   if(config->proxyuserpwd) {
00537     result = checkpasswd("proxy", i, last, &config->proxyuserpwd);
00538     if(result)
00539       return result;
00540   }
00541 
00542   /* Check we have a user agent */
00543   if(!config->useragent) {
00544     config->useragent = my_useragent();
00545     if(!config->useragent) {
00546       helpf(config->global->errors, "out of memory\n");
00547       result = CURLE_OUT_OF_MEMORY;
00548     }
00549   }
00550 
00551   return result;
00552 }


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