1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2011, 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 http://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 "setup.h" 23 24#include <curl/curl.h> 25 26#include "rawstr.h" 27 28#define ENABLE_CURLX_PRINTF 29/* use our own printf() functions */ 30#include "curlx.h" 31 32#include "tool_cfgable.h" 33#include "tool_getparam.h" 34#include "tool_getpass.h" 35#include "tool_homedir.h" 36#include "tool_msgs.h" 37#include "tool_paramhlp.h" 38 39#include "memdebug.h" /* keep this as LAST include */ 40 41struct getout *new_getout(struct Configurable *config) 42{ 43 struct getout *node = calloc(1, sizeof(struct getout)); 44 struct getout *last = config->url_last; 45 if(node) { 46 /* append this new node last in the list */ 47 if(last) 48 last->next = node; 49 else 50 config->url_list = node; /* first node */ 51 52 /* move the last pointer */ 53 config->url_last = node; 54 55 node->flags = config->default_node_flags; 56 } 57 return node; 58} 59 60ParameterError file2string(char **bufp, FILE *file) 61{ 62 char buffer[256]; 63 char *ptr; 64 char *string = NULL; 65 size_t stringlen = 0; 66 size_t buflen; 67 68 if(file) { 69 while(fgets(buffer, sizeof(buffer), file)) { 70 if((ptr = strchr(buffer, '\r')) != NULL) 71 *ptr = '\0'; 72 if((ptr = strchr(buffer, '\n')) != NULL) 73 *ptr = '\0'; 74 buflen = strlen(buffer); 75 if((ptr = realloc(string, stringlen+buflen+1)) == NULL) { 76 Curl_safefree(string); 77 return PARAM_NO_MEM; 78 } 79 string = ptr; 80 strcpy(string+stringlen, buffer); 81 stringlen += buflen; 82 } 83 } 84 *bufp = string; 85 return PARAM_OK; 86} 87 88ParameterError file2memory(char **bufp, size_t *size, FILE *file) 89{ 90 char *newbuf; 91 char *buffer = NULL; 92 size_t alloc = 512; 93 size_t nused = 0; 94 size_t nread; 95 96 if(file) { 97 do { 98 if(!buffer || (alloc == nused)) { 99 /* size_t overflow detection for huge files */ 100 if(alloc+1 > ((size_t)-1)/2) { 101 Curl_safefree(buffer); 102 return PARAM_NO_MEM; 103 } 104 alloc *= 2; 105 /* allocate an extra char, reserved space, for null termination */ 106 if((newbuf = realloc(buffer, alloc+1)) == NULL) { 107 Curl_safefree(buffer); 108 return PARAM_NO_MEM; 109 } 110 buffer = newbuf; 111 } 112 nread = fread(buffer+nused, 1, alloc-nused, file); 113 nused += nread; 114 } while(nread); 115 /* null terminate the buffer in case it's used as a string later */ 116 buffer[nused] = '\0'; 117 /* free trailing slack space, if possible */ 118 if(alloc != nused) { 119 if((newbuf = realloc(buffer, nused+1)) == NULL) { 120 Curl_safefree(buffer); 121 return PARAM_NO_MEM; 122 } 123 buffer = newbuf; 124 } 125 /* discard buffer if nothing was read */ 126 if(!nused) { 127 Curl_safefree(buffer); /* no string */ 128 } 129 } 130 *size = nused; 131 *bufp = buffer; 132 return PARAM_OK; 133} 134 135void cleanarg(char *str) 136{ 137#ifdef HAVE_WRITABLE_ARGV 138 /* now that GetStr has copied the contents of nextarg, wipe the next 139 * argument out so that the username:password isn't displayed in the 140 * system process list */ 141 if(str) { 142 size_t len = strlen(str); 143 memset(str, ' ', len); 144 } 145#else 146 (void)str; 147#endif 148} 149 150/* 151 * Parse the string and write the integer in the given address. Return 152 * non-zero on failure, zero on success. 153 * 154 * The string must start with a digit to be valid. 155 * 156 * Since this function gets called with the 'nextarg' pointer from within the 157 * getparameter a lot, we must check it for NULL before accessing the str 158 * data. 159 */ 160 161int str2num(long *val, const char *str) 162{ 163 if(str && ISDIGIT(*str)) { 164 char *endptr; 165 long num = strtol(str, &endptr, 10); 166 if((endptr != str) && (endptr == str + strlen(str))) { 167 *val = num; 168 return 0; /* Ok */ 169 } 170 } 171 return 1; /* badness */ 172} 173 174/* 175 * Parse the string and modify the long in the given address. Return 176 * non-zero on failure, zero on success. 177 * 178 * The string is a list of protocols 179 * 180 * Since this function gets called with the 'nextarg' pointer from within the 181 * getparameter a lot, we must check it for NULL before accessing the str 182 * data. 183 */ 184 185long proto2num(struct Configurable *config, long *val, const char *str) 186{ 187 char *buffer; 188 const char *sep = ","; 189 char *token; 190 191 static struct sprotos { 192 const char *name; 193 long bit; 194 } const protos[] = { 195 { "all", CURLPROTO_ALL }, 196 { "http", CURLPROTO_HTTP }, 197 { "https", CURLPROTO_HTTPS }, 198 { "ftp", CURLPROTO_FTP }, 199 { "ftps", CURLPROTO_FTPS }, 200 { "scp", CURLPROTO_SCP }, 201 { "sftp", CURLPROTO_SFTP }, 202 { "telnet", CURLPROTO_TELNET }, 203 { "ldap", CURLPROTO_LDAP }, 204 { "ldaps", CURLPROTO_LDAPS }, 205 { "dict", CURLPROTO_DICT }, 206 { "file", CURLPROTO_FILE }, 207 { "tftp", CURLPROTO_TFTP }, 208 { "imap", CURLPROTO_IMAP }, 209 { "imaps", CURLPROTO_IMAPS }, 210 { "pop3", CURLPROTO_POP3 }, 211 { "pop3s", CURLPROTO_POP3S }, 212 { "smtp", CURLPROTO_SMTP }, 213 { "smtps", CURLPROTO_SMTPS }, 214 { "rtsp", CURLPROTO_RTSP }, 215 { "gopher", CURLPROTO_GOPHER }, 216 { NULL, 0 } 217 }; 218 219 if(!str) 220 return 1; 221 222 buffer = strdup(str); /* because strtok corrupts it */ 223 if(!buffer) 224 return 1; 225 226 for(token = strtok(buffer, sep); 227 token; 228 token = strtok(NULL, sep)) { 229 enum e_action { allow, deny, set } action = allow; 230 231 struct sprotos const *pp; 232 233 /* Process token modifiers */ 234 while(!ISALNUM(*token)) { /* may be NULL if token is all modifiers */ 235 switch (*token++) { 236 case '=': 237 action = set; 238 break; 239 case '-': 240 action = deny; 241 break; 242 case '+': 243 action = allow; 244 break; 245 default: /* Includes case of terminating NULL */ 246 Curl_safefree(buffer); 247 return 1; 248 } 249 } 250 251 for(pp=protos; pp->name; pp++) { 252 if(curlx_raw_equal(token, pp->name)) { 253 switch (action) { 254 case deny: 255 *val &= ~(pp->bit); 256 break; 257 case allow: 258 *val |= pp->bit; 259 break; 260 case set: 261 *val = pp->bit; 262 break; 263 } 264 break; 265 } 266 } 267 268 if(!(pp->name)) { /* unknown protocol */ 269 /* If they have specified only this protocol, we say treat it as 270 if no protocols are allowed */ 271 if(action == set) 272 *val = 0; 273 warnf(config, "unrecognized protocol '%s'\n", token); 274 } 275 } 276 Curl_safefree(buffer); 277 return 0; 278} 279 280/** 281 * Parses the given string looking for an offset (which may be 282 * a larger-than-integer value). 283 * 284 * @param val the offset to populate 285 * @param str the buffer containing the offset 286 * @return zero if successful, non-zero if failure. 287 */ 288int str2offset(curl_off_t *val, const char *str) 289{ 290#if(CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG) 291 *val = curlx_strtoofft(str, NULL, 0); 292 if((*val == CURL_OFF_T_MAX || *val == CURL_OFF_T_MIN) && (ERRNO == ERANGE)) 293 return 1; 294#else 295 *val = strtol(str, NULL, 0); 296 if((*val == LONG_MIN || *val == LONG_MAX) && ERRNO == ERANGE) 297 return 1; 298#endif 299 return 0; 300} 301 302ParameterError checkpasswd(const char *kind, /* for what purpose */ 303 char **userpwd) /* pointer to allocated string */ 304{ 305 char *ptr; 306 307 if(!*userpwd) 308 return PARAM_OK; 309 310 ptr = strchr(*userpwd, ':'); 311 if(!ptr) { 312 /* no password present, prompt for one */ 313 char passwd[256] = ""; 314 char prompt[256]; 315 size_t passwdlen; 316 size_t userlen = strlen(*userpwd); 317 char *passptr; 318 319 /* build a nice-looking prompt */ 320 curlx_msnprintf(prompt, sizeof(prompt), 321 "Enter %s password for user '%s':", 322 kind, *userpwd); 323 324 /* get password */ 325 getpass_r(prompt, passwd, sizeof(passwd)); 326 passwdlen = strlen(passwd); 327 328 /* extend the allocated memory area to fit the password too */ 329 passptr = realloc(*userpwd, 330 passwdlen + 1 + /* an extra for the colon */ 331 userlen + 1); /* an extra for the zero */ 332 if(!passptr) 333 return PARAM_NO_MEM; 334 335 /* append the password separated with a colon */ 336 passptr[userlen] = ':'; 337 memcpy(&passptr[userlen+1], passwd, passwdlen+1); 338 *userpwd = passptr; 339 } 340 return PARAM_OK; 341} 342 343ParameterError add2list(struct curl_slist **list, const char *ptr) 344{ 345 struct curl_slist *newlist = curl_slist_append(*list, ptr); 346 if(newlist) 347 *list = newlist; 348 else 349 return PARAM_NO_MEM; 350 351 return PARAM_OK; 352} 353 354int ftpfilemethod(struct Configurable *config, const char *str) 355{ 356 if(curlx_raw_equal("singlecwd", str)) 357 return CURLFTPMETHOD_SINGLECWD; 358 if(curlx_raw_equal("nocwd", str)) 359 return CURLFTPMETHOD_NOCWD; 360 if(curlx_raw_equal("multicwd", str)) 361 return CURLFTPMETHOD_MULTICWD; 362 warnf(config, "unrecognized ftp file method '%s', using default\n", str); 363 return CURLFTPMETHOD_MULTICWD; 364} 365 366int ftpcccmethod(struct Configurable *config, const char *str) 367{ 368 if(curlx_raw_equal("passive", str)) 369 return CURLFTPSSL_CCC_PASSIVE; 370 if(curlx_raw_equal("active", str)) 371 return CURLFTPSSL_CCC_ACTIVE; 372 warnf(config, "unrecognized ftp CCC method '%s', using default\n", str); 373 return CURLFTPSSL_CCC_PASSIVE; 374} 375 376long delegation(struct Configurable *config, char *str) 377{ 378 if(curlx_raw_equal("none", str)) 379 return CURLGSSAPI_DELEGATION_NONE; 380 if(curlx_raw_equal("policy", str)) 381 return CURLGSSAPI_DELEGATION_POLICY_FLAG; 382 if(curlx_raw_equal("always", str)) 383 return CURLGSSAPI_DELEGATION_FLAG; 384 warnf(config, "unrecognized delegation method '%s', using none\n", str); 385 return CURLGSSAPI_DELEGATION_NONE; 386} 387 388