18
18
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19
19
* KIND, either express or implied.
21
* $Id: main.c,v 1.359 2006-06-08 06:12:31 bagder Exp $
21
* $Id: main.c,v 1.366 2006-07-26 23:20:48 bagder Exp $
22
22
***************************************************************************/
183
183
/* Send authentication (user+password) when following
184
184
* locations, even when hostname changed */
187
/* Ultrix doesn't have strdup(), so make a quick clone: */
188
char *strdup(char *str)
194
newstr = (char *) malloc((len+1)*sizeof(char));
206
187
#include <direct.h>
372
354
struct curl_slist *tp_postquote;
373
355
struct curl_slist *tp_prequote;
374
356
char *ftp_account; /* for ACCT */
357
char *ftp_alternative_to_user; /* send command if USER/PASS fails */
375
358
int ftp_filemethod;
377
360
bool ignorecl; /* --ignore-content-length */
534
517
" --ftp-method [multicwd/nocwd/singlecwd] Control CWD usage (F)",
535
518
" --ftp-pasv Use PASV/EPSV instead of PORT (F)",
536
519
" --ftp-skip-pasv-ip Skip the IP address for PASV (F)\n"
537
" --ftp-ssl Enable SSL/TLS for the ftp transfer (F)",
520
" --ftp-ssl Try SSL/TLS for the ftp transfer (F)",
521
" --ftp-ssl-reqd Require SSL/TLS for the ftp transfer (F)",
538
522
" -F/--form <name=content> Specify HTTP multipart POST data (H)",
539
523
" --form-string <name=string> Specify HTTP multipart POST data (H)",
540
524
" -g/--globoff Disable URL sequences and ranges using {} and []",
633
617
/* global variable to hold info about libcurl */
634
618
static curl_version_info_data *curlinfo;
636
static void parseconfig(const char *filename,
637
struct Configurable *config);
620
static int parseconfig(const char *filename,
621
struct Configurable *config);
638
622
static char *my_get_line(FILE *fp);
639
623
static int create_dir_hierarchy(char *outfile);
1272
1256
static int ftpfilemethod(struct Configurable *config, char *str)
1274
if(strequal("singlecwd", str))
1258
if(curlx_strequal("singlecwd", str))
1275
1259
return CURLFTPMETHOD_SINGLECWD;
1276
if(strequal("nocwd", str))
1260
if(curlx_strequal("nocwd", str))
1277
1261
return CURLFTPMETHOD_NOCWD;
1278
if(strequal("multicwd", str))
1262
if(curlx_strequal("multicwd", str))
1279
1263
return CURLFTPMETHOD_MULTICWD;
1280
1264
warnf(config, "unrecognized ftp file method '%s', using default\n", str);
1281
1265
return CURLFTPMETHOD_MULTICWD;
1359
1343
{"$r", "ftp-method", TRUE},
1360
1344
{"$s", "local-port", TRUE},
1361
1345
{"$t", "socks4", TRUE},
1346
{"$u", "ftp-alternative-to-user", TRUE},
1347
{"$v", "ftp-ssl-reqd", FALSE},
1363
1349
{"0", "http1.0", FALSE},
1364
1350
{"1", "tlsv1", FALSE},
1784
case 'u': /* --ftp-alternative-to-user */
1785
GetStr(&config->ftp_alternative_to_user, nextarg);
1787
case 'v': /* --ftp-ssl-reqd */
1788
config->ftp_ssl_reqd ^= TRUE;
1800
1792
case '#': /* --progress-bar */
2069
2061
config->insecure_ok ^= TRUE;
2071
2063
case 'K': /* parse config file */
2072
parseconfig(nextarg, config);
2064
if(parseconfig(nextarg, config))
2065
warnf(config, "error trying read config from the '%s' file\n",
2075
2069
config->conf ^= CONF_FTPLISTONLY; /* only list the names of the FTP dir */
2301
2295
{"SSL", CURL_VERSION_SSL},
2302
2296
{"SSPI", CURL_VERSION_SSPI},
2303
2297
{"krb4", CURL_VERSION_KERBEROS4},
2304
{"libz", CURL_VERSION_LIBZ}
2298
{"libz", CURL_VERSION_LIBZ},
2299
{"CharConv", CURL_VERSION_CONV}
2306
2301
printf("Features: ");
2307
2302
for(i=0; i<sizeof(feats)/sizeof(feats[0]); i++) {
2402
2397
return PARAM_OK;
2406
static void parseconfig(const char *filename,
2407
struct Configurable *config)
2400
/* return 0 on everything-is-fine, and non-zero otherwise */
2401
static int parseconfig(const char *filename,
2402
struct Configurable *config)
2656
2654
struct OutStruct *out=(struct OutStruct *)stream;
2657
2655
struct Configurable *config = out->config;
2658
curl_off_t size = (curl_off_t)(sz * nmemb); /* typecast to prevent
2659
warnings when converting from
2660
unsigned to signed */
2661
2657
if(out && !out->stream) {
2662
2658
/* open file for writing */
2663
2659
out->stream=fopen(out->filename, "wb");
2677
if(config->recvpersecond) {
2679
* We know when we received data the previous time. We know how much data
2680
* we get now. Make sure that this is not faster than we are told to run.
2681
* If we're faster, sleep a while *before* doing the fwrite() here.
2688
static curl_off_t addit = 0;
2690
now = curlx_tvnow();
2691
timediff = curlx_tvdiff(now, config->lastrecvtime); /* milliseconds */
2693
if((config->recvpersecond > CURL_MAX_WRITE_SIZE) && (timediff < 100) ) {
2694
/* If we allow a rather speedy transfer, add this amount for later
2695
* checking. Also, do not modify the lastrecvtime as we will use a
2696
* longer scope due to this addition. We wait for at least 100 ms to
2697
* pass to get better values to do better math for the sleep. */
2701
size += addit; /* add up the possibly added bonus rounds from the
2702
zero timediff calls */
2703
addit = 0; /* clear the addition pool */
2705
if( size*1000 > config->recvpersecond*timediff) {
2706
/* figure out how many milliseconds to rest */
2707
sleep_time = (long)(size*1000/config->recvpersecond - timediff);
2710
* Make sure we don't sleep for so long that we trigger the speed
2711
* limit. This won't limit the bandwidth quite the way we've been
2712
* asked to, but at least the transfer has a chance.
2714
if (config->low_speed_time > 0)
2715
sleep_time = MIN(sleep_time,(config->low_speed_time * 1000) / 2);
2717
if(sleep_time > 0) {
2718
go_sleep(sleep_time);
2719
now = curlx_tvnow();
2722
config->lastrecvtime = now;
2726
2673
rc = fwrite(buffer, sz, nmemb, out->stream);
2728
2675
if((sz * nmemb) == rc) {
2769
2716
struct InStruct *in=(struct InStruct *)userp;
2770
struct Configurable *config = in->config;
2771
curl_off_t size = (curl_off_t)(sz * nmemb); /* typecast to prevent warnings
2772
when converting from
2773
unsigned to signed */
2775
if(config->sendpersecond) {
2777
* We know when we sent data the previous time. We know how much data
2778
* we sent. Make sure that this was not faster than we are told to run.
2779
* If we're faster, sleep a while *before* doing the fread() here.
2780
* Also, make no larger fread() than should be sent this second!
2787
static curl_off_t addit = 0;
2789
now = curlx_tvnow();
2790
timediff = curlx_tvdiff(now, config->lastsendtime); /* milliseconds */
2792
if((config->sendpersecond > CURL_MAX_WRITE_SIZE) &&
2795
* We allow very fast transfers, then allow at least 100 ms between
2796
* each sleeping mile-stone to create more accurate long-term rates.
2801
/* If 'addit' is non-zero, it contains the total amount of bytes
2802
uploaded during the last 'timediff' milliseconds. If it is zero,
2803
we use the stored previous size. */
2804
curl_off_t xfered = addit?addit:(curl_off_t)config->lastsendsize;
2805
addit = 0; /* clear it for the next round */
2807
if( xfered*1000 > config->sendpersecond*timediff) {
2808
/* figure out how many milliseconds to rest */
2809
sleep_time = (long)(xfered*1000/config->sendpersecond - timediff);
2810
if(sleep_time > 0) {
2811
go_sleep (sleep_time);
2812
now = curlx_tvnow();
2815
config->lastsendtime = now;
2817
if(size > config->sendpersecond) {
2818
/* lower the size to actually read */
2819
nmemb = (size_t)config->sendpersecond;
2824
config->lastsendsize = sz*nmemb;
2827
2718
rc = fread(buffer, sz, nmemb, in->stream);
3885
3776
curl_easy_setopt(curl, CURLOPT_IOCTLDATA, &input);
3886
3777
curl_easy_setopt(curl, CURLOPT_IOCTLFUNCTION, my_ioctl);
3888
if(config->recvpersecond) {
3779
if(config->recvpersecond)
3889
3780
/* tell libcurl to use a smaller sized buffer as it allows us to
3890
3781
make better sleeps! 7.9.9 stuff! */
3891
3782
curl_easy_setopt(curl, CURLOPT_BUFFERSIZE, config->recvpersecond);
3894
3784
/* size of uploaded file: */
3895
3785
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, uploadfilesize);
3939
3829
config->conf&CONF_AUTO_REFERER);
3940
3830
curl_easy_setopt(curl, CURLOPT_USERAGENT, config->useragent);
3941
3831
curl_easy_setopt(curl, CURLOPT_FTPPORT, config->ftpport);
3942
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, config->low_speed_limit);
3832
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT,
3833
config->low_speed_limit);
3943
3834
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, config->low_speed_time);
3835
curl_easy_setopt(curl, CURLOPT_MAX_SEND_SPEED_LARGE,
3836
config->sendpersecond);
3837
curl_easy_setopt(curl, CURLOPT_MAX_RECV_SPEED_LARGE,
3838
config->recvpersecond);
3944
3840
curl_easy_setopt(curl, CURLOPT_RESUME_FROM_LARGE,
3945
3841
config->use_resume?config->resume_from:0);
3946
3842
curl_easy_setopt(curl, CURLOPT_COOKIE, config->cookie);
4085
3981
if(config->ftp_ssl)
4086
3982
curl_easy_setopt(curl, CURLOPT_FTP_SSL, CURLFTPSSL_TRY);
3984
/* new in curl 7.15.5 */
3985
if(config->ftp_ssl_reqd)
3986
curl_easy_setopt(curl, CURLOPT_FTP_SSL, CURLFTPSSL_ALL);
4088
3988
/* new in curl 7.11.1, modified in 7.15.2 */
4089
3989
if(config->socksproxy) {
4090
3990
curl_easy_setopt(curl, CURLOPT_PROXY, config->socksproxy);
4113
4013
curl_easy_setopt(curl, CURLOPT_LOCALPORTRANGE, config->localportrange);
4017
curl_easy_setopt(curl, CURLOPT_FTP_ALTERNATIVE_TO_USER, config->ftp_alternative_to_user);
4116
4019
retry_numretries = config->req_retry;
4118
4021
retrystart = curlx_tvnow();
4138
4041
retry = RETRY_TIMEOUT;
4139
4042
else if(CURLE_OK == res) {
4140
4043
/* Check for HTTP transient errors */
4142
curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &url);
4144
curlx_strnequal(url, "http", 4)) {
4044
char *this_url=NULL;
4045
curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &this_url);
4047
curlx_strnequal(this_url, "http", 4)) {
4145
4048
/* This was HTTP(S) */
4146
4049
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);