/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * * Copyright (C) 1998 - 2011, Daniel Stenberg, , 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 #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; }