tool_paramhlp.c
Go to the documentation of this file.
1 /***************************************************************************
2  * _ _ ____ _
3  * Project ___| | | | _ \| |
4  * / __| | | | |_) | |
5  * | (__| |_| | _ <| |___
6  * \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2017, 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 #include "strcase.h"
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_getparam.h"
32 #include "tool_getpass.h"
33 #include "tool_homedir.h"
34 #include "tool_msgs.h"
35 #include "tool_paramhlp.h"
36 #include "tool_version.h"
37 
38 #include "memdebug.h" /* keep this as LAST include */
39 
41 {
42  struct getout *node = calloc(1, sizeof(struct getout));
43  struct getout *last = config->url_last;
44  if(node) {
45  /* append this new node last in the list */
46  if(last)
47  last->next = node;
48  else
49  config->url_list = node; /* first node */
50 
51  /* move the last pointer */
52  config->url_last = node;
53 
54  node->flags = config->default_node_flags;
55  }
56  return node;
57 }
58 
59 ParameterError file2string(char **bufp, FILE *file)
60 {
61  char buffer[256];
62  char *ptr;
63  char *string = NULL;
64  size_t stringlen = 0;
65  size_t buflen;
66 
67  if(file) {
68  while(fgets(buffer, sizeof(buffer), file)) {
69  ptr = strchr(buffer, '\r');
70  if(ptr)
71  *ptr = '\0';
72  ptr = strchr(buffer, '\n');
73  if(ptr)
74  *ptr = '\0';
75  buflen = strlen(buffer);
76  ptr = realloc(string, stringlen + buflen + 1);
77  if(!ptr) {
78  Curl_safefree(string);
79  return PARAM_NO_MEM;
80  }
81  string = ptr;
82  strcpy(string + stringlen, buffer);
83  stringlen += buflen;
84  }
85  }
86  *bufp = string;
87  return PARAM_OK;
88 }
89 
90 ParameterError file2memory(char **bufp, size_t *size, FILE *file)
91 {
92  char *newbuf;
93  char *buffer = NULL;
94  size_t alloc = 512;
95  size_t nused = 0;
96  size_t nread;
97 
98  if(file) {
99  do {
100  if(!buffer || (alloc == nused)) {
101  /* size_t overflow detection for huge files */
102  if(alloc + 1 > ((size_t)-1)/2) {
103  Curl_safefree(buffer);
104  return PARAM_NO_MEM;
105  }
106  alloc *= 2;
107  /* allocate an extra char, reserved space, for null termination */
108  newbuf = realloc(buffer, alloc + 1);
109  if(!newbuf) {
110  Curl_safefree(buffer);
111  return PARAM_NO_MEM;
112  }
113  buffer = newbuf;
114  }
115  nread = fread(buffer + nused, 1, alloc-nused, file);
116  nused += nread;
117  } while(nread);
118  /* null terminate the buffer in case it's used as a string later */
119  buffer[nused] = '\0';
120  /* free trailing slack space, if possible */
121  if(alloc != nused) {
122  newbuf = realloc(buffer, nused + 1);
123  if(!newbuf) {
124  Curl_safefree(buffer);
125  return PARAM_NO_MEM;
126  }
127  buffer = newbuf;
128  }
129  /* discard buffer if nothing was read */
130  if(!nused) {
131  Curl_safefree(buffer); /* no string */
132  }
133  }
134  *size = nused;
135  *bufp = buffer;
136  return PARAM_OK;
137 }
138 
139 void cleanarg(char *str)
140 {
141 #ifdef HAVE_WRITABLE_ARGV
142  /* now that GetStr has copied the contents of nextarg, wipe the next
143  * argument out so that the username:password isn't displayed in the
144  * system process list */
145  if(str) {
146  size_t len = strlen(str);
147  memset(str, ' ', len);
148  }
149 #else
150  (void)str;
151 #endif
152 }
153 
154 /*
155  * Parse the string and write the long in the given address. Return PARAM_OK
156  * on success, otherwise a parameter specific error enum.
157  *
158  * Since this function gets called with the 'nextarg' pointer from within the
159  * getparameter a lot, we must check it for NULL before accessing the str
160  * data.
161  */
162 
163 ParameterError str2num(long *val, const char *str)
164 {
165  if(str) {
166  char *endptr;
167  long num;
168  errno = 0;
169  num = strtol(str, &endptr, 10);
170  if(errno == ERANGE)
171  return PARAM_NUMBER_TOO_LARGE;
172  if((endptr != str) && (endptr == str + strlen(str))) {
173  *val = num;
174  return PARAM_OK; /* Ok */
175  }
176  }
177  return PARAM_BAD_NUMERIC; /* badness */
178 }
179 
180 /*
181  * Parse the string and write the long in the given address. Return PARAM_OK
182  * on success, otherwise a parameter error enum. ONLY ACCEPTS POSITIVE NUMBERS!
183  *
184  * Since this function gets called with the 'nextarg' pointer from within the
185  * getparameter a lot, we must check it for NULL before accessing the str
186  * data.
187  */
188 
189 ParameterError str2unum(long *val, const char *str)
190 {
191  ParameterError result = str2num(val, str);
192  if(result != PARAM_OK)
193  return result;
194  if(*val < 0)
195  return PARAM_NEGATIVE_NUMERIC;
196 
197  return PARAM_OK;
198 }
199 
200 /*
201  * Parse the string and write the double in the given address. Return PARAM_OK
202  * on success, otherwise a parameter specific error enum.
203  *
204  * The 'max' argument is the maximum value allowed, as the numbers are often
205  * multiplied when later used.
206  *
207  * Since this function gets called with the 'nextarg' pointer from within the
208  * getparameter a lot, we must check it for NULL before accessing the str
209  * data.
210  */
211 
212 static ParameterError str2double(double *val, const char *str, long max)
213 {
214  if(str) {
215  char *endptr;
216  double num;
217  errno = 0;
218  num = strtod(str, &endptr);
219  if(errno == ERANGE)
220  return PARAM_NUMBER_TOO_LARGE;
221  if(num > max) {
222  /* too large */
223  return PARAM_NUMBER_TOO_LARGE;
224  }
225  if((endptr != str) && (endptr == str + strlen(str))) {
226  *val = num;
227  return PARAM_OK; /* Ok */
228  }
229  }
230  return PARAM_BAD_NUMERIC; /* badness */
231 }
232 
233 /*
234  * Parse the string and write the double in the given address. Return PARAM_OK
235  * on success, otherwise a parameter error enum. ONLY ACCEPTS POSITIVE NUMBERS!
236  *
237  * The 'max' argument is the maximum value allowed, as the numbers are often
238  * multiplied when later used.
239  *
240  * Since this function gets called with the 'nextarg' pointer from within the
241  * getparameter a lot, we must check it for NULL before accessing the str
242  * data.
243  */
244 
245 ParameterError str2udouble(double *valp, const char *str, long max)
246 {
247  double value;
248  ParameterError result = str2double(&value, str, max);
249  if(result != PARAM_OK)
250  return result;
251  if(value < 0)
252  return PARAM_NEGATIVE_NUMERIC;
253 
254  *valp = value;
255  return PARAM_OK;
256 }
257 
258 /*
259  * Parse the string and modify the long in the given address. Return
260  * non-zero on failure, zero on success.
261  *
262  * The string is a list of protocols
263  *
264  * Since this function gets called with the 'nextarg' pointer from within the
265  * getparameter a lot, we must check it for NULL before accessing the str
266  * data.
267  */
268 
269 long proto2num(struct OperationConfig *config, long *val, const char *str)
270 {
271  char *buffer;
272  const char *sep = ",";
273  char *token;
274 
275  static struct sprotos {
276  const char *name;
277  long bit;
278  } const protos[] = {
279  { "all", CURLPROTO_ALL },
280  { "http", CURLPROTO_HTTP },
281  { "https", CURLPROTO_HTTPS },
282  { "ftp", CURLPROTO_FTP },
283  { "ftps", CURLPROTO_FTPS },
284  { "scp", CURLPROTO_SCP },
285  { "sftp", CURLPROTO_SFTP },
286  { "telnet", CURLPROTO_TELNET },
287  { "ldap", CURLPROTO_LDAP },
288  { "ldaps", CURLPROTO_LDAPS },
289  { "dict", CURLPROTO_DICT },
290  { "file", CURLPROTO_FILE },
291  { "tftp", CURLPROTO_TFTP },
292  { "imap", CURLPROTO_IMAP },
293  { "imaps", CURLPROTO_IMAPS },
294  { "pop3", CURLPROTO_POP3 },
295  { "pop3s", CURLPROTO_POP3S },
296  { "smtp", CURLPROTO_SMTP },
297  { "smtps", CURLPROTO_SMTPS },
298  { "rtsp", CURLPROTO_RTSP },
299  { "gopher", CURLPROTO_GOPHER },
300  { "smb", CURLPROTO_SMB },
301  { "smbs", CURLPROTO_SMBS },
302  { NULL, 0 }
303  };
304 
305  if(!str)
306  return 1;
307 
308  buffer = strdup(str); /* because strtok corrupts it */
309  if(!buffer)
310  return 1;
311 
312  /* Allow strtok() here since this isn't used threaded */
313  /* !checksrc! disable BANNEDFUNC 2 */
314  for(token = strtok(buffer, sep);
315  token;
316  token = strtok(NULL, sep)) {
317  enum e_action { allow, deny, set } action = allow;
318 
319  struct sprotos const *pp;
320 
321  /* Process token modifiers */
322  while(!ISALNUM(*token)) { /* may be NULL if token is all modifiers */
323  switch (*token++) {
324  case '=':
325  action = set;
326  break;
327  case '-':
328  action = deny;
329  break;
330  case '+':
331  action = allow;
332  break;
333  default: /* Includes case of terminating NULL */
334  Curl_safefree(buffer);
335  return 1;
336  }
337  }
338 
339  for(pp = protos; pp->name; pp++) {
340  if(curl_strequal(token, pp->name)) {
341  switch(action) {
342  case deny:
343  *val &= ~(pp->bit);
344  break;
345  case allow:
346  *val |= pp->bit;
347  break;
348  case set:
349  *val = pp->bit;
350  break;
351  }
352  break;
353  }
354  }
355 
356  if(!(pp->name)) { /* unknown protocol */
357  /* If they have specified only this protocol, we say treat it as
358  if no protocols are allowed */
359  if(action == set)
360  *val = 0;
361  warnf(config->global, "unrecognized protocol '%s'\n", token);
362  }
363  }
364  Curl_safefree(buffer);
365  return 0;
366 }
367 
376 int check_protocol(const char *str)
377 {
378  const char * const *pp;
380  if(!str)
382  for(pp = curlinfo->protocols; *pp; pp++) {
383  if(curl_strequal(*pp, str))
384  return PARAM_OK;
385  }
387 }
388 
398 {
399  char *endptr;
400  if(str[0] == '-')
401  /* offsets aren't negative, this indicates weird input */
402  return PARAM_NEGATIVE_NUMERIC;
403 
404 #if(SIZEOF_CURL_OFF_T > SIZEOF_LONG)
405  {
406  CURLofft offt = curlx_strtoofft(str, &endptr, 0, val);
407  if(CURL_OFFT_FLOW == offt)
408  return PARAM_NUMBER_TOO_LARGE;
409  else if(CURL_OFFT_INVAL == offt)
410  return PARAM_BAD_NUMERIC;
411  }
412 #else
413  errno = 0;
414  *val = strtol(str, &endptr, 0);
415  if((*val == LONG_MIN || *val == LONG_MAX) && errno == ERANGE)
416  return PARAM_NUMBER_TOO_LARGE;
417 #endif
418  if((endptr != str) && (endptr == str + strlen(str)))
419  return PARAM_OK;
420 
421  return PARAM_BAD_NUMERIC;
422 }
423 
424 static CURLcode checkpasswd(const char *kind, /* for what purpose */
425  const size_t i, /* operation index */
426  const bool last, /* TRUE if last operation */
427  char **userpwd) /* pointer to allocated string */
428 {
429  char *psep;
430  char *osep;
431 
432  if(!*userpwd)
433  return CURLE_OK;
434 
435  /* Attempt to find the password separator */
436  psep = strchr(*userpwd, ':');
437 
438  /* Attempt to find the options separator */
439  osep = strchr(*userpwd, ';');
440 
441  if(!psep && **userpwd != ';') {
442  /* no password present, prompt for one */
443  char passwd[256] = "";
444  char prompt[256];
445  size_t passwdlen;
446  size_t userlen = strlen(*userpwd);
447  char *passptr;
448 
449  if(osep)
450  *osep = '\0';
451 
452  /* build a nice-looking prompt */
453  if(!i && last)
454  curlx_msnprintf(prompt, sizeof(prompt),
455  "Enter %s password for user '%s':",
456  kind, *userpwd);
457  else
458  curlx_msnprintf(prompt, sizeof(prompt),
459  "Enter %s password for user '%s' on URL #%"
461  kind, *userpwd, (curl_off_t) (i + 1));
462 
463  /* get password */
464  getpass_r(prompt, passwd, sizeof(passwd));
465  passwdlen = strlen(passwd);
466 
467  if(osep)
468  *osep = ';';
469 
470  /* extend the allocated memory area to fit the password too */
471  passptr = realloc(*userpwd,
472  passwdlen + 1 + /* an extra for the colon */
473  userlen + 1); /* an extra for the zero */
474  if(!passptr)
475  return CURLE_OUT_OF_MEMORY;
476 
477  /* append the password separated with a colon */
478  passptr[userlen] = ':';
479  memcpy(&passptr[userlen + 1], passwd, passwdlen + 1);
480  *userpwd = passptr;
481  }
482 
483  return CURLE_OK;
484 }
485 
486 ParameterError add2list(struct curl_slist **list, const char *ptr)
487 {
488  struct curl_slist *newlist = curl_slist_append(*list, ptr);
489  if(newlist)
490  *list = newlist;
491  else
492  return PARAM_NO_MEM;
493 
494  return PARAM_OK;
495 }
496 
497 int ftpfilemethod(struct OperationConfig *config, const char *str)
498 {
499  if(curl_strequal("singlecwd", str))
501  if(curl_strequal("nocwd", str))
502  return CURLFTPMETHOD_NOCWD;
503  if(curl_strequal("multicwd", str))
504  return CURLFTPMETHOD_MULTICWD;
505 
506  warnf(config->global, "unrecognized ftp file method '%s', using default\n",
507  str);
508 
509  return CURLFTPMETHOD_MULTICWD;
510 }
511 
512 int ftpcccmethod(struct OperationConfig *config, const char *str)
513 {
514  if(curl_strequal("passive", str))
515  return CURLFTPSSL_CCC_PASSIVE;
516  if(curl_strequal("active", str))
517  return CURLFTPSSL_CCC_ACTIVE;
518 
519  warnf(config->global, "unrecognized ftp CCC method '%s', using default\n",
520  str);
521 
522  return CURLFTPSSL_CCC_PASSIVE;
523 }
524 
525 long delegation(struct OperationConfig *config, char *str)
526 {
527  if(curl_strequal("none", str))
529  if(curl_strequal("policy", str))
531  if(curl_strequal("always", str))
533 
534  warnf(config->global, "unrecognized delegation method '%s', using none\n",
535  str);
536 
538 }
539 
540 /*
541  * my_useragent: returns allocated string with default user agent
542  */
543 static char *my_useragent(void)
544 {
545  return strdup(CURL_NAME "/" CURL_VERSION);
546 }
547 
548 CURLcode get_args(struct OperationConfig *config, const size_t i)
549 {
551  bool last = (config->next ? FALSE : TRUE);
552 
553  /* Check we have a password for the given host user */
554  if(config->userpwd && !config->oauth_bearer) {
555  result = checkpasswd("host", i, last, &config->userpwd);
556  if(result)
557  return result;
558  }
559 
560  /* Check we have a password for the given proxy user */
561  if(config->proxyuserpwd) {
562  result = checkpasswd("proxy", i, last, &config->proxyuserpwd);
563  if(result)
564  return result;
565  }
566 
567  /* Check we have a user agent */
568  if(!config->useragent) {
569  config->useragent = my_useragent();
570  if(!config->useragent) {
571  helpf(config->global->errors, "out of memory\n");
572  result = CURLE_OUT_OF_MEMORY;
573  }
574  }
575 
576  return result;
577 }
578 
579 /*
580  * Parse the string and modify ssl_version in the val argument. Return PARAM_OK
581  * on success, otherwise a parameter error enum. ONLY ACCEPTS POSITIVE NUMBERS!
582  *
583  * Since this function gets called with the 'nextarg' pointer from within the
584  * getparameter a lot, we must check it for NULL before accessing the str
585  * data.
586  */
587 
588 ParameterError str2tls_max(long *val, const char *str)
589 {
590  static struct s_tls_max {
591  const char *tls_max_str;
592  long tls_max;
593  } const tls_max_array[] = {
594  { "default", CURL_SSLVERSION_MAX_DEFAULT },
595  { "1.0", CURL_SSLVERSION_MAX_TLSv1_0 },
596  { "1.1", CURL_SSLVERSION_MAX_TLSv1_1 },
597  { "1.2", CURL_SSLVERSION_MAX_TLSv1_2 },
598  { "1.3", CURL_SSLVERSION_MAX_TLSv1_3 }
599  };
600  size_t i = 0;
601  if(!str)
603  for(i = 0; i < sizeof(tls_max_array)/sizeof(tls_max_array[0]); i++) {
604  if(!strcmp(str, tls_max_array[i].tls_max_str)) {
605  *val = tls_max_array[i].tls_max;
606  return PARAM_OK;
607  }
608  }
609  return PARAM_BAD_USE;
610 }
struct getout * next
Definition: tool_sdecls.h:104
#define CURLPROTO_FTPS
Definition: curl.h:847
#define CURLGSSAPI_DELEGATION_NONE
Definition: curl.h:720
#define CURLPROTO_HTTP
Definition: curl.h:844
#define CURLPROTO_FILE
Definition: curl.h:854
#define CURLPROTO_SCP
Definition: curl.h:848
CURL_EXTERN curl_version_info_data * curl_version_info(CURLversion)
Definition: version.c:342
#define CURLPROTO_ALL
Definition: curl.h:872
int check_protocol(const char *str)
Check if the given string is a protocol supported by libcurl.
#define CURLPROTO_SMB
Definition: curl.h:870
Definition: ws_ssl.c:25
#define CURLPROTO_DICT
Definition: curl.h:853
char * proxyuserpwd
Definition: tool_cfgable.h:90
struct getout * url_last
Definition: tool_cfgable.h:114
curl_version_info_data * curlinfo
Definition: tool_libinfo.c:36
#define CURLPROTO_IMAP
Definition: curl.h:856
void cleanarg(char *str)
#define CURL_FORMAT_CURL_OFF_TU
Definition: system.h:374
#define CURLPROTO_SMBS
Definition: curl.h:871
::std::string string
Definition: gtest-port.h:1129
#define strdup(ptr)
Definition: curl_memory.h:122
UNITTEST_START char * ptr
Definition: unit1330.c:38
#define CURLPROTO_SMTPS
Definition: curl.h:861
CURLcode
Definition: curl.h:454
ParameterError file2memory(char **bufp, size_t *size, FILE *file)
Definition: tool_paramhlp.c:90
#define CURLPROTO_GOPHER
Definition: curl.h:869
#define ISALNUM(x)
#define realloc(ptr, size)
Definition: curl_memory.h:128
struct GlobalConfig * global
Definition: tool_cfgable.h:251
long proto2num(struct OperationConfig *config, long *val, const char *str)
static char * my_useragent(void)
ParameterError file2string(char **bufp, FILE *file)
Definition: tool_paramhlp.c:59
ParameterError str2udouble(double *valp, const char *str, long max)
void helpf(FILE *errors, const char *fmt,...)
Definition: tool_msgs.c:106
UNITTEST_START int result
Definition: unit1304.c:49
#define CURLPROTO_FTP
Definition: curl.h:846
char buffer[]
Definition: unit1308.c:48
unsigned int i
Definition: unit1303.c:79
#define CURL_VERSION
Definition: tool_version.h:28
#define CURLPROTO_SFTP
Definition: curl.h:849
size_t len
Definition: curl_sasl.c:55
memcpy(filename, filename1, strlen(filename1))
struct curl_httppost * last
Definition: unit1308.c:46
ParameterError str2offset(curl_off_t *val, const char *str)
Parses the given string looking for an offset (which may be a larger-than-integer value)...
#define CURLGSSAPI_DELEGATION_POLICY_FLAG
Definition: curl.h:721
#define CURLPROTO_HTTPS
Definition: curl.h:845
int ftpfilemethod(struct OperationConfig *config, const char *str)
#define CURLPROTO_RTSP
Definition: curl.h:862
const char * str
Definition: unit1398.c:33
#define FALSE
#define CURLPROTO_LDAP
Definition: curl.h:851
#define CURLPROTO_LDAPS
Definition: curl.h:852
static ParameterError str2double(double *val, const char *str, long max)
CURL_EXTERN struct curl_slist * curl_slist_append(struct curl_slist *, const char *)
Definition: slist.c:89
CURLofft curlx_strtoofft(const char *str, char **endp, int base, curl_off_t *num)
Definition: strtoofft.c:215
ParameterError
Definition: tool_getparam.h:26
#define CURLPROTO_POP3S
Definition: curl.h:859
#define curlx_msnprintf
Definition: curlx.h:77
#define CURLPROTO_IMAPS
Definition: curl.h:857
static CURLcode checkpasswd(const char *kind, const size_t i, const bool last, char **userpwd)
ParameterError str2num(long *val, const char *str)
CURL_TYPEOF_CURL_OFF_T curl_off_t
Definition: system.h:420
char * getpass_r(const char *prompt, char *password, size_t buflen)
Definition: tool_getpass.c:222
struct OperationConfig * next
Definition: tool_cfgable.h:253
#define CURLPROTO_TFTP
Definition: curl.h:855
Definition: curl.h:455
CURL_EXTERN int curl_strequal(const char *s1, const char *s2)
Definition: strcase.c:170
#define CURLPROTO_TELNET
Definition: curl.h:850
CURLofft
Definition: strtoofft.h:51
#define CURLGSSAPI_DELEGATION_FLAG
Definition: curl.h:722
unsigned int bit
Definition: curl_sasl.c:56
#define Curl_safefree(ptr)
Definition: memdebug.h:170
action
struct getout * url_list
Definition: tool_cfgable.h:113
int flags
Definition: tool_sdecls.h:108
struct getout * new_getout(struct OperationConfig *config)
Definition: tool_paramhlp.c:40
ParameterError str2tls_max(long *val, const char *str)
size_t fread(void *, size_t, size_t, FILE *)
#define CURLPROTO_SMTP
Definition: curl.h:860
int ftpcccmethod(struct OperationConfig *config, const char *str)
#define CURLVERSION_NOW
Definition: curl.h:2603
ParameterError add2list(struct curl_slist **list, const char *ptr)
#define CURL_NAME
Definition: tool_version.h:26
UNITTEST_START int * value
Definition: unit1602.c:51
CURLcode get_args(struct OperationConfig *config, const size_t i)
size_t size
Definition: unit1302.c:52
#define TRUE
#define CURLPROTO_POP3
Definition: curl.h:858
void warnf(struct GlobalConfig *config, const char *fmt,...)
Definition: tool_msgs.c:95
const char * name
Definition: curl_sasl.c:54
long delegation(struct OperationConfig *config, char *str)
ParameterError str2unum(long *val, const char *str)
const char *const * protocols
Definition: curl.h:2615
#define calloc(nbelem, size)
Definition: curl_memory.h:126


rc_tagdetect_client
Author(s): Monika Florek-Jasinska , Raphael Schaller
autogenerated on Sat Feb 13 2021 03:42:16