5
5
* | (__| |_| | _ <| |___
6
6
* \___|\___/|_| \_\_____|
8
* Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
8
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
10
10
* This software is licensed as described in the file COPYING, which
11
11
* you should have received as part of this distribution. The terms
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.341 2005/12/05 14:10:48 bagder Exp $
21
* $Id: main.c,v 1.359 2006-06-08 06:12:31 bagder Exp $
22
22
***************************************************************************/
108
104
versions instead */
109
105
#include <curlx.h> /* header from the libcurl directory */
107
#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
109
/* set default codesets for iconv */
110
#ifndef CURL_ICONV_CODESET_OF_NETWORK
111
#define CURL_ICONV_CODESET_OF_NETWORK "ISO8859-1"
113
#endif /* CURL_DOES_CONVERSIONS && HAVE_ICONV */
111
115
/* The last #include file should be: */
113
117
#ifndef CURLTOOLDEBUG
419
434
static void main_free(void)
421
436
curl_global_cleanup();
437
#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
438
/* close iconv conversion descriptor */
439
if (inbound_cd != (iconv_t)-1) {
440
iconv_close(inbound_cd);
442
#endif /* CURL_DOES_CONVERSIONS && HAVE_ICONV */
424
445
static int SetHTTPrequest(struct Configurable *config,
510
531
" --crlf Convert LF to CRLF in upload",
511
532
" -f/--fail Fail silently (no output at all) on HTTP errors (H)",
512
533
" --ftp-create-dirs Create the remote dirs if not present (F)",
534
" --ftp-method [multicwd/nocwd/singlecwd] Control CWD usage (F)",
513
535
" --ftp-pasv Use PASV/EPSV instead of PORT (F)",
514
536
" --ftp-skip-pasv-ip Skip the IP address for PASV (F)\n"
515
537
" --ftp-ssl Enable SSL/TLS for the ftp transfer (F)",
523
545
" -i/--include Include protocol headers in the output (H/F)",
524
546
" -I/--head Show document info only",
525
547
" -j/--junk-session-cookies Ignore session cookies read from file (H)",
526
" --interface <interface> Specify network interface to use",
548
" --interface <interface> Specify network interface/address to use",
527
549
" --krb4 <level> Enable krb4 with specified security level (F)",
528
550
" -k/--insecure Allow connections to SSL sites without certs (H)",
529
551
" -K/--config Specify which config file to read",
530
552
" -l/--list-only List only names of an FTP directory (F)",
531
553
" --limit-rate <rate> Limit transfer speed to this rate",
554
" --local-port <num>[-num] Force use of these local port numbers\n",
532
555
" -L/--location Follow Location: hints (H)",
533
556
" --location-trusted Follow Location: and send authentication even ",
534
557
" to other hostnames (H)",
558
581
" --retry-max-time <seconds> Retry only within this period",
559
582
" -s/--silent Silent mode. Don't output anything",
560
583
" -S/--show-error Show error. With -s, make curl show errors when they occur",
561
" --socks <host[:port]> Use SOCKS5 proxy on given host + port",
584
" --socks4 <host[:port]> Use SOCKS4 proxy on given host + port",
585
" --socks5 <host[:port]> Use SOCKS5 proxy on given host + port",
562
586
" --stderr <file> Where to redirect stderr. - means stdout",
563
587
" -t/--telnet-option <OPT=val> Set telnet option",
564
588
" --trace <file> Write a debug trace to the given file",
1248
1272
static int ftpfilemethod(struct Configurable *config, char *str)
1250
1274
if(strequal("singlecwd", str))
1275
return CURLFTPMETHOD_SINGLECWD;
1252
1276
if(strequal("nocwd", str))
1277
return CURLFTPMETHOD_NOCWD;
1254
1278
if(strequal("multicwd", str))
1279
return CURLFTPMETHOD_MULTICWD;
1256
1280
warnf(config, "unrecognized ftp file method '%s', using default\n", str);
1281
return CURLFTPMETHOD_MULTICWD;
1260
1284
static ParameterError getparameter(char *flag, /* f or -long-flag */
1315
1339
{"$a", "ftp-ssl", FALSE},
1316
1340
{"$b", "ftp-pasv", FALSE},
1317
1341
{"$c", "socks5", TRUE},
1342
{"$c", "socks", TRUE}, /* this is how the option was documented but
1343
we prefer the --socks5 version for explicit
1318
1345
{"$d", "tcp-nodelay",FALSE},
1319
1346
{"$e", "proxy-digest", FALSE},
1320
1347
{"$f", "proxy-basic", FALSE},
1330
1357
{"$p", "ignore-content-length", FALSE},
1331
1358
{"$q", "ftp-skip-pasv-ip", FALSE},
1332
1359
{"$r", "ftp-method", TRUE},
1360
{"$s", "local-port", TRUE},
1361
{"$t", "socks4", TRUE},
1334
1363
{"0", "http1.0", FALSE},
1335
1364
{"1", "tlsv1", FALSE},
1671
1702
free(config->ftpport);
1672
1703
config->ftpport = NULL;
1674
case 'c': /* --socks specifies a socks5 proxy to use */
1675
GetStr(&config->socks5proxy, nextarg);
1705
case 'c': /* --socks5 specifies a socks5 proxy to use */
1706
GetStr(&config->socksproxy, nextarg);
1707
config->socksver = CURLPROXY_SOCKS5;
1709
case 't': /* --socks4 specifies a socks4 proxy to use */
1710
GetStr(&config->socksproxy, nextarg);
1711
config->socksver = CURLPROXY_SOCKS4;
1677
1713
case 'd': /* --tcp-nodelay option */
1678
1714
config->tcp_nodelay ^= TRUE;
1743
1779
case 'r': /* --ftp-method (undocumented at this point) */
1744
1780
config->ftp_filemethod = ftpfilemethod(config, nextarg);
1782
case 's': /* --local-port */
1783
rc = sscanf(nextarg, "%d - %d",
1785
&config->localportrange);
1787
return PARAM_BAD_USE;
1789
config->localportrange = 1; /* default number of ports to try */
1791
config->localportrange -= config->localport;
1792
if(config->localportrange < 1) {
1793
warnf(config, "bad range input\n");
1794
return PARAM_BAD_USE;
1748
1800
case '#': /* --progress-bar */
1861
1913
/* we already have a string, we append this one
1862
1914
with a separating &-letter */
1863
1915
char *oldpost=config->postfields;
1864
config->postfields=aprintf("%s&%s", oldpost, postdata);
1916
size_t newlen = strlen(oldpost) + strlen(postdata) + 2;
1917
config->postfields=malloc(newlen);
1918
if(!config->postfields)
1919
return PARAM_NO_MEM;
1920
snprintf(config->postfields, newlen, "%s&%s", oldpost, postdata);
1866
1922
free(postdata);
2382
2438
/* Get the filename of our executable. GetModuleFileName is
2383
* defined in windows.h, which is #included into libcurl.
2439
* already declared via inclusions done in setup header file.
2384
2440
* We assume that we are using the ASCII version here.
2386
2442
int n = GetModuleFileName(0, filebuffer, sizeof(filebuffer));
2594
2650
curl_off_t init; /* original size (non-zero when appending) */
2597
static int my_fwrite(void *buffer, size_t sz, size_t nmemb, void *stream)
2653
static size_t my_fwrite(void *buffer, size_t sz, size_t nmemb, void *stream)
2600
2656
struct OutStruct *out=(struct OutStruct *)stream;
2601
2657
struct Configurable *config = out->config;
2602
2658
curl_off_t size = (curl_off_t)(sz * nmemb); /* typecast to prevent
2607
2663
out->stream=fopen(out->filename, "wb");
2608
2664
if(!out->stream) {
2609
2665
warnf(config, "Failed to create the file %s\n", out->filename);
2610
return -1; /* failure */
2667
* Once that libcurl has called back my_fwrite() the returned value
2668
* is checked against the amount that was intended to be written, if
2669
* it does not match then it fails with CURLE_WRITE_ERROR. So at this
2670
* point returning a value different from sz*nmemb indicates failure.
2672
rc = (0 == (sz * nmemb)) ? 1 : 0;
2673
return rc; /* failure */
2700
2763
return CURLIOE_OK;
2703
static int my_fread(void *buffer, size_t sz, size_t nmemb, void *userp)
2766
static size_t my_fread(void *buffer, size_t sz, size_t nmemb, void *userp)
2706
2769
struct InStruct *in=(struct InStruct *)userp;
2707
2770
struct Configurable *config = in->config;
2708
2771
curl_off_t size = (curl_off_t)(sz * nmemb); /* typecast to prevent warnings
2764
2827
rc = fread(buffer, sz, nmemb, in->stream);
2766
fprintf(stderr, "CALLBACK returning %d bytes data\n", (int)rc);
2829
if (sizeof(rc) > sizeof(unsigned int))
2830
fprintf(stderr, "CALLBACK returning %lu bytes data\n", rc);
2832
fprintf(stderr, "CALLBACK returning %u bytes data\n", rc);
2879
2945
bar->out = config->errors;
2948
#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
2950
* convert_from_network() is an internal function
2951
* for performing ASCII conversions on non-ASCII platforms.
2954
convert_from_network(char *buffer, size_t length)
2958
/* translate from the network encoding to the host encoding */
2959
char *input_ptr, *output_ptr;
2960
size_t in_bytes, out_bytes;
2962
/* open an iconv conversion descriptor if necessary */
2963
if(inbound_cd == (iconv_t)-1) {
2964
inbound_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
2965
CURL_ICONV_CODESET_OF_NETWORK);
2966
if(inbound_cd == (iconv_t)-1) {
2967
return CURLE_CONV_FAILED;
2971
input_ptr = output_ptr = buffer;
2972
in_bytes = out_bytes = length;
2973
rc = iconv(inbound_cd, &input_ptr, &in_bytes,
2974
&output_ptr, &out_bytes);
2975
if ((rc == -1) || (in_bytes != 0)) {
2976
return CURLE_CONV_FAILED;
2983
char convert_char(curl_infotype infotype, char this_char) {
2984
/* determine how this specific character should be displayed */
2986
case CURLINFO_DATA_IN:
2987
case CURLINFO_DATA_OUT:
2988
case CURLINFO_SSL_DATA_IN:
2989
case CURLINFO_SSL_DATA_OUT:
2990
/* data, treat as ASCII */
2991
if ((this_char >= 0x20) && (this_char < 0x7f)) {
2992
/* printable ASCII hex value: convert to host encoding */
2993
convert_from_network(&this_char, 1);
2995
/* non-printable ASCII, use a replacement character */
2996
return(UNPRINTABLE_CHAR);
2998
/* fall through to default */
3000
/* treat as host encoding */
3001
if (isprint(this_char)
3002
&& (this_char != '\t')
3003
&& (this_char != '\r')
3004
&& (this_char != '\n')) {
3005
/* printable characters excluding tabs and line end characters */
3010
/* non-printable, use a replacement character */
3011
return(UNPRINTABLE_CHAR);
3013
#endif /* CURL_DOES_CONVERSIONS */
2883
3016
void dump(char *timebuf, const char *text,
2884
3017
FILE *stream, unsigned char *ptr, size_t size,
3018
trace tracetype, curl_infotype infotype)
2915
3048
i+=(c+2-width);
3051
#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
3052
/* convert to host encoding and print this character */
3053
fprintf(stream, "%c", convert_char(infotype, ptr[i+c]));
2918
3056
fprintf(stream, "%c",
2919
(ptr[i+c]>=0x20) && (ptr[i+c]<0x80)?ptr[i+c]:'.');
3057
(ptr[i+c]>=0x20) && (ptr[i+c]<0x80)?ptr[i+c]:UNPRINTABLE_CHAR);
3058
#endif /* CURL_DOES_CONVERSIONS && HAVE_ICONV */
2920
3059
/* check again for 0D0A, to avoid an extra \n if it's at width */
2921
3060
if ((tracetype == TRACE_ASCII) &&
2922
3061
(i+c+2 < size) && ptr[i+c+1]==0x0D && ptr[i+c+2]==0x0A) {
2940
3079
struct timeval tv;
2941
3080
struct tm *now;
2942
3081
char timebuf[20];
2944
3084
(void)handle; /* prevent compiler warning */
2946
3086
tv = curlx_tvnow();
2947
now = localtime(&tv.tv_sec); /* not multithread safe but we don't care */
3088
now = localtime(&secs); /* not multithread safe but we don't care */
2948
3089
if(config->tracetime)
2949
3090
snprintf(timebuf, sizeof(timebuf), "%02d:%02d:%02d.%06d ",
2950
3091
now->tm_hour, now->tm_min, now->tm_sec, tv.tv_usec);
3042
dump(timebuf, text, output, data, size, config->tracetype);
3183
dump(timebuf, text, output, data, size, config->tracetype, type);
3101
3242
curl_slist_free_all(config->headers);
3104
#if defined(WIN32) && !defined(__CYGWIN32__)
3245
#if defined(WIN32) && !defined(__CYGWIN__)
3106
3247
/* Function to find CACert bundle on a Win32 platform using SearchPath.
3107
* (SearchPath is defined in windows.h, which is #included into libcurl)
3248
* (SearchPath is already declared via inclusions done in setup header file)
3108
3249
* (Use the ASCII version instead of the unicode one!)
3109
3250
* The order of the directories it searches is:
3110
3251
* 1. application's directory
3944
4085
if(config->ftp_ssl)
3945
4086
curl_easy_setopt(curl, CURLOPT_FTP_SSL, CURLFTPSSL_TRY);
3947
/* new in curl 7.11.1 */
3948
if(config->socks5proxy) {
3949
curl_easy_setopt(curl, CURLOPT_PROXY, config->socks5proxy);
3950
curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
4088
/* new in curl 7.11.1, modified in 7.15.2 */
4089
if(config->socksproxy) {
4090
curl_easy_setopt(curl, CURLOPT_PROXY, config->socksproxy);
4091
curl_easy_setopt(curl, CURLOPT_PROXYTYPE, config->socksver);
3953
4094
/* curl 7.13.0 */
3966
4107
/* curl 7.15.1 */
3967
4108
curl_easy_setopt(curl, CURLOPT_FTP_FILEMETHOD, config->ftp_filemethod);
4111
if(config->localport) {
4112
curl_easy_setopt(curl, CURLOPT_LOCALPORT, config->localport);
4113
curl_easy_setopt(curl, CURLOPT_LOCALPORTRANGE, config->localportrange);
3969
4116
retry_numretries = config->req_retry;
3971
4118
retrystart = curlx_tvnow();
4139
4285
/* Important that we set the time _after_ the file has been
4140
4286
closed, as is done above here */
4141
4287
if(config->remote_time && outs.filename) {
4142
/* as libcurl if we got a time. Pretty please */
4288
/* ask libcurl if we got a time. Pretty please */
4144
4290
curl_easy_getinfo(curl, CURLINFO_FILETIME, &filetime);
4145
4291
if(filetime >= 0) {
4233
static void checkfds(void);
4381
/* Ensure that file descriptors 0, 1 and 2 (stdin, stdout, stderr) are
4382
open before starting to run. Otherwise, the first three network
4383
sockets opened by curl could be used for input sources, downloaded data
4384
or error logs as they will effectively be stdin, stdout and/or stderr.
4235
4386
static void checkfds(void)
4237
4388
#ifdef HAVE_PIPE