00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "tool_setup.h"
00023
00024 #include "strcase.h"
00025
00026 #define ENABLE_CURLX_PRINTF
00027
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"
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
00046 if(last)
00047 last->next = node;
00048 else
00049 config->url_list = node;
00050
00051
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
00102 if(alloc+1 > ((size_t)-1)/2) {
00103 Curl_safefree(buffer);
00104 return PARAM_NO_MEM;
00105 }
00106 alloc *= 2;
00107
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
00119 buffer[nused] = '\0';
00120
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
00130 if(!nused) {
00131 Curl_safefree(buffer);
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
00143
00144
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
00156
00157
00158
00159
00160
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;
00171 }
00172 }
00173 return PARAM_BAD_NUMERIC;
00174 }
00175
00176
00177
00178
00179
00180
00181
00182
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
00198
00199
00200
00201
00202
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;
00213 }
00214 }
00215 return PARAM_BAD_NUMERIC;
00216 }
00217
00218
00219
00220
00221
00222
00223
00224
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
00240
00241
00242
00243
00244
00245
00246
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);
00289 if(!buffer)
00290 return 1;
00291
00292
00293
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
00302 while(!ISALNUM(*token)) {
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:
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)) {
00337
00338
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
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,
00400 const size_t i,
00401 const bool last,
00402 char **userpwd)
00403 {
00404 char *psep;
00405 char *osep;
00406
00407 if(!*userpwd)
00408 return CURLE_OK;
00409
00410
00411 psep = strchr(*userpwd, ':');
00412
00413
00414 osep = strchr(*userpwd, ';');
00415
00416 if(!psep && **userpwd != ';') {
00417
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
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
00439 getpass_r(prompt, passwd, sizeof(passwd));
00440 passwdlen = strlen(passwd);
00441
00442 if(osep)
00443 *osep = ';';
00444
00445
00446 passptr = realloc(*userpwd,
00447 passwdlen + 1 +
00448 userlen + 1);
00449 if(!passptr)
00450 return CURLE_OUT_OF_MEMORY;
00451
00452
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
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
00529 if(config->userpwd && !config->oauth_bearer) {
00530 result = checkpasswd("host", i, last, &config->userpwd);
00531 if(result)
00532 return result;
00533 }
00534
00535
00536 if(config->proxyuserpwd) {
00537 result = checkpasswd("proxy", i, last, &config->proxyuserpwd);
00538 if(result)
00539 return result;
00540 }
00541
00542
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 }