diff options
Diffstat (limited to 'src/tool_paramhlp.c')
-rw-r--r-- | src/tool_paramhlp.c | 387 |
1 files changed, 387 insertions, 0 deletions
diff --git a/src/tool_paramhlp.c b/src/tool_paramhlp.c new file mode 100644 index 000000000..adb12ce70 --- /dev/null +++ b/src/tool_paramhlp.c @@ -0,0 +1,387 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "setup.h" + +#include <curl/curl.h> + +#include "rawstr.h" + +#define ENABLE_CURLX_PRINTF +/* use our own printf() functions */ +#include "curlx.h" + +#include "tool_cfgable.h" +#include "tool_getparam.h" +#include "tool_getpass.h" +#include "tool_homedir.h" +#include "tool_msgs.h" +#include "tool_paramhlp.h" + +#include "memdebug.h" /* keep this as LAST include */ + +struct getout *new_getout(struct Configurable *config) +{ + struct getout *node = calloc(1, sizeof(struct getout)); + struct getout *last = config->url_last; + if(node) { + /* append this new node last in the list */ + if(last) + last->next = node; + else + config->url_list = node; /* first node */ + + /* move the last pointer */ + config->url_last = node; + + node->flags = config->default_node_flags; + } + return node; +} + +ParameterError file2string(char **bufp, FILE *file) +{ + char buffer[256]; + char *ptr; + char *string = NULL; + size_t stringlen = 0; + size_t buflen; + + if(file) { + while(fgets(buffer, sizeof(buffer), file)) { + if((ptr = strchr(buffer, '\r')) != NULL) + *ptr = '\0'; + if((ptr = strchr(buffer, '\n')) != NULL) + *ptr = '\0'; + buflen = strlen(buffer); + if((ptr = realloc(string, stringlen+buflen+1)) == NULL) { + Curl_safefree(string); + return PARAM_NO_MEM; + } + string = ptr; + strcpy(string+stringlen, buffer); + stringlen += buflen; + } + } + *bufp = string; + return PARAM_OK; +} + +ParameterError file2memory(char **bufp, size_t *size, FILE *file) +{ + char *newbuf; + char *buffer = NULL; + size_t alloc = 512; + size_t nused = 0; + size_t nread; + + if(file) { + do { + if(!buffer || (alloc == nused)) { + /* size_t overflow detection for huge files */ + if(alloc+1 > ((size_t)-1)/2) { + Curl_safefree(buffer); + return PARAM_NO_MEM; + } + alloc *= 2; + /* allocate an extra char, reserved space, for null termination */ + if((newbuf = realloc(buffer, alloc+1)) == NULL) { + Curl_safefree(buffer); + return PARAM_NO_MEM; + } + buffer = newbuf; + } + nread = fread(buffer+nused, 1, alloc-nused, file); + nused += nread; + } while(nread); + /* null terminate the buffer in case it's used as a string later */ + buffer[nused] = '\0'; + /* free trailing slack space, if possible */ + if(alloc != nused) { + if((newbuf = realloc(buffer, nused+1)) == NULL) { + Curl_safefree(buffer); + return PARAM_NO_MEM; + } + buffer = newbuf; + } + /* discard buffer if nothing was read */ + if(!nused) { + Curl_safefree(buffer); /* no string */ + } + } + *size = nused; + *bufp = buffer; + return PARAM_OK; +} + +void cleanarg(char *str) +{ +#ifdef HAVE_WRITABLE_ARGV + /* now that GetStr has copied the contents of nextarg, wipe the next + * argument out so that the username:password isn't displayed in the + * system process list */ + if(str) { + size_t len = strlen(str); + memset(str, ' ', len); + } +#else + (void)str; +#endif +} + +/* + * Parse the string and write the integer in the given address. Return + * non-zero on failure, zero on success. + * + * The string must start with a digit to be valid. + * + * Since this function gets called with the 'nextarg' pointer from within the + * getparameter a lot, we must check it for NULL before accessing the str + * data. + */ + +int str2num(long *val, const char *str) +{ + if(str && ISDIGIT(*str)) { + char *endptr; + long num = strtol(str, &endptr, 10); + if((endptr != str) && (endptr == str + strlen(str))) { + *val = num; + return 0; /* Ok */ + } + } + return 1; /* badness */ +} + +/* + * Parse the string and modify the long in the given address. Return + * non-zero on failure, zero on success. + * + * The string is a list of protocols + * + * Since this function gets called with the 'nextarg' pointer from within the + * getparameter a lot, we must check it for NULL before accessing the str + * data. + */ + +long proto2num(struct Configurable *config, long *val, const char *str) +{ + char *buffer; + const char *sep = ","; + char *token; + + static struct sprotos { + const char *name; + long bit; + } const protos[] = { + { "all", CURLPROTO_ALL }, + { "http", CURLPROTO_HTTP }, + { "https", CURLPROTO_HTTPS }, + { "ftp", CURLPROTO_FTP }, + { "ftps", CURLPROTO_FTPS }, + { "scp", CURLPROTO_SCP }, + { "sftp", CURLPROTO_SFTP }, + { "telnet", CURLPROTO_TELNET }, + { "ldap", CURLPROTO_LDAP }, + { "ldaps", CURLPROTO_LDAPS }, + { "dict", CURLPROTO_DICT }, + { "file", CURLPROTO_FILE }, + { "tftp", CURLPROTO_TFTP }, + { "imap", CURLPROTO_IMAP }, + { "imaps", CURLPROTO_IMAPS }, + { "pop3", CURLPROTO_POP3 }, + { "pop3s", CURLPROTO_POP3S }, + { "smtp", CURLPROTO_SMTP }, + { "smtps", CURLPROTO_SMTPS }, + { "rtsp", CURLPROTO_RTSP }, + { "gopher", CURLPROTO_GOPHER }, + { NULL, 0 } + }; + + if(!str) + return 1; + + buffer = strdup(str); /* because strtok corrupts it */ + if(!buffer) + return 1; + + for(token = strtok(buffer, sep); + token; + token = strtok(NULL, sep)) { + enum e_action { allow, deny, set } action = allow; + + struct sprotos const *pp; + + /* Process token modifiers */ + while(!ISALNUM(*token)) { /* may be NULL if token is all modifiers */ + switch (*token++) { + case '=': + action = set; + break; + case '-': + action = deny; + break; + case '+': + action = allow; + break; + default: /* Includes case of terminating NULL */ + Curl_safefree(buffer); + return 1; + } + } + + for(pp=protos; pp->name; pp++) { + if(curlx_raw_equal(token, pp->name)) { + switch (action) { + case deny: + *val &= ~(pp->bit); + break; + case allow: + *val |= pp->bit; + break; + case set: + *val = pp->bit; + break; + } + break; + } + } + + if(!(pp->name)) { /* unknown protocol */ + /* If they have specified only this protocol, we say treat it as + if no protocols are allowed */ + if(action == set) + *val = 0; + warnf(config, "unrecognized protocol '%s'\n", token); + } + } + Curl_safefree(buffer); + return 0; +} + +/** + * Parses the given string looking for an offset (which may be + * a larger-than-integer value). + * + * @param val the offset to populate + * @param str the buffer containing the offset + * @return zero if successful, non-zero if failure. + */ +int str2offset(curl_off_t *val, const char *str) +{ +#if(CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG) + *val = curlx_strtoofft(str, NULL, 0); + if((*val == CURL_OFF_T_MAX || *val == CURL_OFF_T_MIN) && (ERRNO == ERANGE)) + return 1; +#else + *val = strtol(str, NULL, 0); + if((*val == LONG_MIN || *val == LONG_MAX) && ERRNO == ERANGE) + return 1; +#endif + return 0; +} + +ParameterError checkpasswd(const char *kind, /* for what purpose */ + char **userpwd) /* pointer to allocated string */ +{ + char *ptr; + + if(!*userpwd) + return PARAM_OK; + + ptr = strchr(*userpwd, ':'); + if(!ptr) { + /* no password present, prompt for one */ + char passwd[256] = ""; + char prompt[256]; + size_t passwdlen; + size_t userlen = strlen(*userpwd); + char *passptr; + + /* build a nice-looking prompt */ + curlx_msnprintf(prompt, sizeof(prompt), + "Enter %s password for user '%s':", + kind, *userpwd); + + /* get password */ + getpass_r(prompt, passwd, sizeof(passwd)); + passwdlen = strlen(passwd); + + /* extend the allocated memory area to fit the password too */ + passptr = realloc(*userpwd, + passwdlen + 1 + /* an extra for the colon */ + userlen + 1); /* an extra for the zero */ + if(!passptr) + return PARAM_NO_MEM; + + /* append the password separated with a colon */ + passptr[userlen] = ':'; + memcpy(&passptr[userlen+1], passwd, passwdlen+1); + *userpwd = passptr; + } + return PARAM_OK; +} + +ParameterError add2list(struct curl_slist **list, const char *ptr) +{ + struct curl_slist *newlist = curl_slist_append(*list, ptr); + if(newlist) + *list = newlist; + else + return PARAM_NO_MEM; + + return PARAM_OK; +} + +int ftpfilemethod(struct Configurable *config, const char *str) +{ + if(curlx_raw_equal("singlecwd", str)) + return CURLFTPMETHOD_SINGLECWD; + if(curlx_raw_equal("nocwd", str)) + return CURLFTPMETHOD_NOCWD; + if(curlx_raw_equal("multicwd", str)) + return CURLFTPMETHOD_MULTICWD; + warnf(config, "unrecognized ftp file method '%s', using default\n", str); + return CURLFTPMETHOD_MULTICWD; +} + +int ftpcccmethod(struct Configurable *config, const char *str) +{ + if(curlx_raw_equal("passive", str)) + return CURLFTPSSL_CCC_PASSIVE; + if(curlx_raw_equal("active", str)) + return CURLFTPSSL_CCC_ACTIVE; + warnf(config, "unrecognized ftp CCC method '%s', using default\n", str); + return CURLFTPSSL_CCC_PASSIVE; +} + +long delegation(struct Configurable *config, char *str) +{ + if(curlx_raw_equal("none", str)) + return CURLGSSAPI_DELEGATION_NONE; + if(curlx_raw_equal("policy", str)) + return CURLGSSAPI_DELEGATION_POLICY_FLAG; + if(curlx_raw_equal("always", str)) + return CURLGSSAPI_DELEGATION_FLAG; + warnf(config, "unrecognized delegation method '%s', using none\n", str); + return CURLGSSAPI_DELEGATION_NONE; +} + |