~ubuntu-branches/ubuntu/vivid/curl/vivid

« back to all changes in this revision

Viewing changes to src/main.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Schuldei
  • Date: 2009-04-02 23:35:45 UTC
  • mto: (1.2.1 upstream) (3.2.3 sid)
  • mto: This revision was merged to the branch mainline in revision 38.
  • Revision ID: james.westby@ubuntu.com-20090402233545-geixkwhe3izccjt7
Tags: upstream-7.19.4
ImportĀ upstreamĀ versionĀ 7.19.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
 *                            | (__| |_| |  _ <| |___
6
6
 *                             \___|\___/|_| \_\_____|
7
7
 *
8
 
 * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
 
8
 * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
9
9
 *
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.
20
20
 *
21
 
 * $Id: main.c,v 1.461 2008-06-01 16:01:37 curlvms Exp $
 
21
 * $Id: main.c,v 1.507 2009-02-17 09:09:18 bagder Exp $
22
22
 ***************************************************************************/
23
23
#include "setup.h"
24
24
 
44
44
#ifdef USE_ENVIRONMENT
45
45
#include "writeenv.h"
46
46
#endif
 
47
#include "rawstr.h"
47
48
 
48
49
#define CURLseparator   "--_curl_--"
49
50
 
96
97
#define ENABLE_CURLX_PRINTF
97
98
/* make the curlx header define all printf() functions to use the curlx_*
98
99
   versions instead */
99
 
#include <curlx.h> /* header from the libcurl directory */
 
100
#include "curlx.h" /* header from the libcurl directory */
100
101
 
101
102
#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
102
103
#include <iconv.h>
152
153
#endif
153
154
 
154
155
#ifdef MSDOS
 
156
#define USE_WATT32
155
157
#include <dos.h>
156
158
 
157
 
const char *msdosify(const char *);
158
 
char *rename_if_dos_device_name(char *);
 
159
static const char *msdosify(const char *);
 
160
static char *rename_if_dos_device_name(char *);
159
161
 
160
162
#ifdef DJGPP
161
163
/* we want to glob our own argv[] */
182
184
#define CURL_PROGRESS_STATS 0 /* default progress display */
183
185
#define CURL_PROGRESS_BAR   1
184
186
 
185
 
/**
186
 
 * @def MIN
187
 
 * standard MIN macro
188
 
 */
189
 
#ifndef MIN
190
 
#define MIN(X,Y)        (((X) < (Y)) ? (X) : (Y))
191
 
#endif
192
 
 
193
187
typedef enum {
194
188
  HTTPREQ_UNSPEC,
195
189
  HTTPREQ_GET,
200
194
  HTTPREQ_LAST
201
195
} HttpReq;
202
196
 
203
 
/* Just a set of bits */
204
 
#ifndef CONF_DEFAULT
205
 
#define CONF_DEFAULT  0
206
 
#endif
207
 
 
208
 
#define CONF_ISATTY (1<<0) /* output to tty! */
209
 
#define CONF_AUTO_REFERER (1<<4) /* the automatic referer-system please! */
210
 
#define CONF_HEADER   (1<<8) /* throw the header out too */
211
 
#define CONF_NOPROGRESS (1<<10) /* shut off the progress meter */
212
 
#define CONF_NOBODY   (1<<11) /* get meta-data (headers) about the file
213
 
                                 without transferring the body, use HEAD to
214
 
                                 get http document */
215
 
#define CONF_FAILONERROR (1<<12) /* no output on http error codes >= 300 */
216
 
#define CONF_DIRLISTONLY (1<<16) /* request nonverbose directory listing */
217
 
#define CONF_FTPAPPEND (1<<20) /* Append instead of overwrite on upload! */
218
 
#define CONF_NETRC    (1<<22)  /* read user+password from .netrc */
219
 
#define CONF_FOLLOWLOCATION (1<<23) /* use Location: Luke! */
220
 
#define CONF_GETTEXT  (1<<24) /* use ASCII/text for transfer */
221
 
#define CONF_MUTE     (1<<28) /* force NOPROGRESS */
222
 
 
223
 
#define CONF_NETRC_OPT (1<<29)  /* read user+password from either
224
 
                                 * .netrc or URL*/
225
 
#define CONF_UNRESTRICTED_AUTH (1<<30)
226
 
/* Send authentication (user+password) when following
227
 
 * locations, even when hostname changed */
228
 
 
229
197
#ifdef WIN32
230
198
#include <direct.h>
231
199
#define F_OK 0
236
204
#include "curlmsg_vms.h"
237
205
#endif
238
206
 
239
 
/* Support uploading and resuming of >2GB files
240
 
 */
241
 
#if defined(WIN32) && (SIZEOF_CURL_OFF_T > 4)
242
 
#define lseek(x,y,z) _lseeki64(x, y, z)
243
 
#define struct_stat struct _stati64
244
 
#define stat(file,st) _stati64(file,st)
245
 
#else
246
 
#define struct_stat struct stat
 
207
/*
 
208
 * Large file support (>2Gb) using WIN32 functions.
 
209
 */
 
210
 
 
211
#ifdef USE_WIN32_LARGE_FILES
 
212
#  include <io.h>
 
213
#  include <sys/types.h>
 
214
#  include <sys/stat.h>
 
215
#  define lseek(fdes,offset,whence)  _lseeki64(fdes, offset, whence)
 
216
#  define fstat(fdes,stp)            _fstati64(fdes, stp)
 
217
#  define stat(fname,stp)            _stati64(fname, stp)
 
218
#  define struct_stat                struct _stati64
 
219
#endif
 
220
 
 
221
/*
 
222
 * Small file support (<2Gb) using WIN32 functions.
 
223
 */
 
224
 
 
225
#ifdef USE_WIN32_SMALL_FILES
 
226
#  include <io.h>
 
227
#  include <sys/types.h>
 
228
#  include <sys/stat.h>
 
229
#  define lseek(fdes,offset,whence)  _lseek(fdes, (long)offset, whence)
 
230
#  define fstat(fdes,stp)            _fstat(fdes, stp)
 
231
#  define stat(fname,stp)            _stat(fname, stp)
 
232
#  define struct_stat                struct _stat
 
233
#endif
 
234
 
 
235
#ifndef struct_stat
 
236
#  define struct_stat struct stat
 
237
#endif
 
238
 
 
239
/*
 
240
 * Default sizeof(off_t) in case it hasn't been defined in config file.
 
241
 */
 
242
 
 
243
#ifndef SIZEOF_OFF_T
 
244
#  if defined(__VMS) && (defined(__alpha) || defined(__ia64))
 
245
#    if defined(_LARGEFILE)
 
246
#      define SIZEOF_OFF_T 8
 
247
#    endif
 
248
#  elif defined(__OS400__) && defined(__ILEC400__)
 
249
#    if defined(_LARGE_FILES)
 
250
#      define SIZEOF_OFF_T 8
 
251
#    endif
 
252
#  elif defined(__MVS__) && defined(__IBMC__)
 
253
#    if defined(_LP64) || defined(_LARGE_FILES)
 
254
#      define SIZEOF_OFF_T 8
 
255
#    endif
 
256
#  elif defined(__370__) && defined(__IBMC__)
 
257
#    if defined(_LP64) || defined(_LARGE_FILES)
 
258
#      define SIZEOF_OFF_T 8
 
259
#    endif
 
260
#  endif
 
261
#  ifndef SIZEOF_OFF_T
 
262
#    define SIZEOF_OFF_T 4
 
263
#  endif
247
264
#endif
248
265
 
249
266
#ifdef CURL_DOES_CONVERSIONS
380
397
#endif
381
398
 
382
399
typedef enum {
383
 
    TRACE_BIN,   /* tcpdump inspired look */
384
 
    TRACE_ASCII, /* like *BIN but without the hex output */
385
 
    TRACE_PLAIN  /* -v/--verbose type */
 
400
  TRACE_NONE,  /* no trace/verbose output at all! */
 
401
  TRACE_BIN,   /* tcpdump inspired look */
 
402
  TRACE_ASCII, /* like *BIN but without the hex output */
 
403
  TRACE_PLAIN  /* -v/--verbose type */
386
404
} trace;
387
405
 
388
406
struct OutStruct {
430
448
  char *userpwd;
431
449
  char *proxyuserpwd;
432
450
  char *proxy;
 
451
  int proxyver;     /* set to CURLPROXY_HTTP* define */
 
452
  char *noproxy;
433
453
  bool proxytunnel;
434
 
  long conf;
 
454
  bool ftp_append;         /* APPE on ftp */
 
455
  bool mute;               /* shutup */
 
456
  bool use_ascii;          /* select ascii or text transfer */
 
457
  bool autoreferer;        /* automatically set referer */
 
458
  bool failonerror;        /* fail on (HTTP) errors */
 
459
  bool include_headers;    /* send headers to data output */
 
460
  bool no_body;            /* don't get the body */
 
461
  bool dirlistonly;        /* only get the FTP dir list */
 
462
  bool followlocation;     /* follow http redirects */
 
463
  bool unrestricted_auth;  /* Continue to send authentication (user+password)
 
464
                              when following ocations, even when hostname
 
465
                              changed */
 
466
  bool netrc_opt;
 
467
  bool netrc;
 
468
  bool noprogress;
 
469
  bool isatty;             /* updated internally only if the output is a tty */
435
470
  struct getout *url_list; /* point to the first node */
436
471
  struct getout *url_last; /* point to the last/current node */
437
472
  struct getout *url_get;  /* point to the node to fill in URL */
502
537
 
503
538
  char *socksproxy; /* set to server string */
504
539
  int socksver;     /* set to CURLPROXY_SOCKS* define */
 
540
  char *socks5_gssapi_service;  /* set service name for gssapi principal
 
541
                                 * default rcmd */
 
542
  int socks5_gssapi_nec ;  /* The NEC reference server does not protect
 
543
                            * the encryption type exchange */
505
544
 
506
545
  bool tcp_nodelay;
507
546
  long req_retry;   /* number of retries */
518
557
  char *libcurl; /* output libcurl code to this file name */
519
558
  bool raw;
520
559
  bool post301;
 
560
  bool post302;
521
561
  bool nokeepalive; /* for keepalive needs */
522
562
  long alivetime;
523
563
 
 
564
  int default_node_flags; /* default flags to seach for each 'node', which is
 
565
                             basically each given URL to transfer */
524
566
  struct OutStruct *outs;
525
567
};
526
568
 
529
571
/* produce this text message to the user unless mute was selected */
530
572
static void warnf(struct Configurable *config, const char *fmt, ...)
531
573
{
532
 
  if(!(config->conf & CONF_MUTE)) {
 
574
  if(!config->mute) {
533
575
    va_list ap;
534
576
    int len;
535
577
    char *ptr;
536
578
    char print_buffer[256];
537
579
 
538
580
    va_start(ap, fmt);
539
 
    va_start(ap, fmt);
540
581
    len = vsnprintf(print_buffer, sizeof(print_buffer), fmt, ap);
541
582
    va_end(ap);
542
583
 
579
620
  /* stop stat() wasting time */
580
621
  _djstat_flags |= _STAT_INODE | _STAT_EXEC_MAGIC | _STAT_DIRSIZE;
581
622
#endif
 
623
 
582
624
  return curl_global_init(CURL_GLOBAL_DEFAULT);
583
625
}
584
626
 
659
701
    "Usage: curl [options...] <url>",
660
702
    "Options: (H) means HTTP/HTTPS only, (F) means FTP only",
661
703
    "    --anyauth       Pick \"any\" authentication method (H)",
662
 
    " -a/--append        Append to target file when uploading (F)",
 
704
    " -a/--append        Append to target file when uploading (F/SFTP)",
663
705
    "    --basic         Use HTTP Basic Authentication (H)",
664
706
    "    --cacert <file> CA certificate to verify peer against (SSL)",
665
707
    "    --capath <directory> CA directory to verify peer against (SSL)",
667
709
    "    --cert-type <type> Certificate file type (DER/PEM/ENG) (SSL)",
668
710
    "    --ciphers <list> SSL ciphers to use (SSL)",
669
711
    "    --compressed    Request compressed response (using deflate or gzip)",
670
 
    " -K/--config        Specify which config file to read",
 
712
    " -K/--config <file> Specify which config file to read",
671
713
    "    --connect-timeout <seconds> Maximum time allowed for connection",
672
714
    " -C/--continue-at <offset> Resumed transfer offset",
673
715
    " -b/--cookie <name=string/file> Cookie string or file to read cookies from (H)",
691
733
    " -F/--form <name=content> Specify HTTP multipart POST data (H)",
692
734
    "    --form-string <name=string> Specify HTTP multipart POST data (H)",
693
735
    "    --ftp-account <data> Account data to send when requested by server (F)",
694
 
    "    --ftp-alternative-to-user String to replace \"USER [name]\" (F)",
 
736
    "    --ftp-alternative-to-user <cmd> String to replace \"USER [name]\" (F)",
695
737
    "    --ftp-create-dirs Create the remote dirs if not present (F)",
696
738
    "    --ftp-method [multicwd/nocwd/singlecwd] Control CWD usage (F)",
697
739
    "    --ftp-pasv      Use PASV/EPSV instead of PORT (F)",
719
761
    "    --keepalive-time <seconds> Interval between keepalive probes",
720
762
    "    --key <key>     Private key file name (SSL/SSH)",
721
763
    "    --key-type <type> Private key file type (DER/PEM/ENG) (SSL)",
722
 
    "    --krb <level>   Enable kerberos with specified security level (F)",
 
764
    "    --krb <level>   Enable Kerberos with specified security level (F)",
723
765
    "    --libcurl <file> Dump libcurl equivalent code of this command line",
724
766
    "    --limit-rate <rate> Limit transfer speed to this rate",
725
767
    " -l/--list-only     List only names of an FTP directory (F)",
736
778
    " -N/--no-buffer     Disable buffering of the output stream",
737
779
    "    --no-keepalive  Disable keepalive use on the connection",
738
780
    "    --no-sessionid  Disable SSL session-ID reusing (SSL)",
 
781
    "    --noproxy       Comma-separated list of hosts which do not use proxy",
739
782
    "    --ntlm          Use HTTP NTLM authentication (H)",
740
783
    " -o/--output <file> Write output to <file> instead of stdout",
741
784
    "    --pass  <pass>  Pass phrase for the private key (SSL/SSH)",
742
785
    "    --post301       Do not switch to GET after following a 301 redirect (H)",
 
786
    "    --post302       Do not switch to GET after following a 302 redirect (H)",
743
787
    " -#/--progress-bar  Display transfer progress as a progress bar",
744
788
    " -x/--proxy <host[:port]> Use HTTP proxy on given port",
745
789
    "    --proxy-anyauth Pick \"any\" proxy authentication method (H)",
748
792
    "    --proxy-negotiate Use Negotiate authentication on the proxy (H)",
749
793
    "    --proxy-ntlm    Use NTLM authentication on the proxy (H)",
750
794
    " -U/--proxy-user <user[:password]> Set proxy user and password",
 
795
    "    --proxy1.0 <host[:port]> Use HTTP/1.0 proxy on given port",
751
796
    " -p/--proxytunnel   Operate through a HTTP proxy tunnel (using CONNECT)",
752
797
    "    --pubkey <key>  Public key file name (SSH)",
753
798
    " -Q/--quote <cmd>   Send command(s) to server before file transfer (F/SFTP)",
754
799
    "    --random-file <file> File for reading random data from (SSL)",
755
 
    " -r/--range <range> Retrieve a byte range from a HTTP/1.1 or FTP server",
 
800
    " -r/--range <range> Retrieve only the bytes within a range",
756
801
    "    --raw           Pass HTTP \"raw\", without any transfer decoding (H)",
757
802
    " -e/--referer       Referer URL (H)",
758
803
    " -O/--remote-name   Write output to a file named as the remote file",
 
804
    "    --remote-name-all Use the remote file name for all URLs",
759
805
    " -R/--remote-time   Set the remote file's time on the local output",
760
806
    " -X/--request <command> Specify request command to use",
761
807
    "    --retry <num>   Retry request <num> times if transient problems occur",
767
813
    "    --socks4a <host[:port]> SOCKS4a proxy on given host + port",
768
814
    "    --socks5 <host[:port]> SOCKS5 proxy on given host + port",
769
815
    "    --socks5-hostname <host[:port]> SOCKS5 proxy, pass host name to proxy",
 
816
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
 
817
    "    --socks5-gssapi-service <name> SOCKS5 proxy service name for gssapi",
 
818
    "    --socks5-gssapi-nec  Compatibility with NEC SOCKS5 server",
 
819
#endif
770
820
    " -Y/--speed-limit   Stop transfer if below speed-limit for 'speed-time' secs",
771
821
    " -y/--speed-time    Time needed to trig speed-limit abort. Defaults to 30",
772
822
    " -2/--sslv2         Use SSLv2 (SSL)",
787
837
    " -v/--verbose       Make the operation more talkative",
788
838
    " -V/--version       Show version number and quit",
789
839
 
790
 
#ifdef MSDOS
791
 
    "    --wdebug        Turn on Watt-32 debugging under DJGPP",
 
840
#ifdef USE_WATT32
 
841
    "    --wdebug        Turn on Watt-32 debugging",
792
842
#endif
793
 
    " -w/--write-out [format] What to output after completion",
 
843
    " -w/--write-out <format> What to output after completion",
794
844
    " -q                 If used as the first parameter disables .curlrc",
795
845
    NULL
796
846
  };
818
868
static int create_dir_hierarchy(const char *outfile, FILE *errors);
819
869
 
820
870
static void GetStr(char **string,
821
 
                   char *value)
 
871
                   const char *value)
822
872
{
823
873
  if(*string)
824
874
    free(*string);
863
913
 
864
914
    /* move the last pointer */
865
915
    config->url_last = node;
 
916
 
 
917
    node->flags = config->default_node_flags;
866
918
  }
867
919
  return node;
868
920
}
887
939
  struct multi_files *multi;
888
940
  struct multi_files *multi_type = NULL;
889
941
  struct multi_files *multi_name = NULL;
890
 
  multi = (struct multi_files *)malloc(sizeof(struct multi_files));
 
942
  multi = malloc(sizeof(struct multi_files));
891
943
  if (multi) {
892
944
    memset(multi, 0, sizeof(struct multi_files));
893
945
    multi->form.option = CURLFORM_FILE;
900
952
    *multi_start = multi;
901
953
 
902
954
  if (type_name) {
903
 
    multi_type = (struct multi_files *)malloc(sizeof(struct multi_files));
 
955
    multi_type = malloc(sizeof(struct multi_files));
904
956
    if (multi_type) {
905
957
      memset(multi_type, 0, sizeof(struct multi_files));
906
958
      multi_type->form.option = CURLFORM_CONTENTTYPE;
915
967
    }
916
968
  }
917
969
  if (show_filename) {
918
 
    multi_name = (struct multi_files *)malloc(sizeof(struct multi_files));
 
970
    multi_name = malloc(sizeof(struct multi_files));
919
971
    if (multi_name) {
920
972
      memset(multi_name, 0, sizeof(struct multi_files));
921
973
      multi_name->form.option = CURLFORM_FILENAME;
967
1019
 *
968
1020
 * formparse()
969
1021
 *
970
 
 * Reads a 'name=value' paramter and builds the appropriate linked list.
 
1022
 * Reads a 'name=value' parameter and builds the appropriate linked list.
971
1023
 *
972
1024
 * Specify files to upload with 'name=@filename'. Supports specified
973
1025
 * given Content-Type of the files. Such as ';type=<content-type>'.
1004
1056
#define FORM_TYPE_SEPARATOR ';'
1005
1057
 
1006
1058
static int formparse(struct Configurable *config,
1007
 
                     char *input,
 
1059
                     const char *input,
1008
1060
                     struct curl_httppost **httppost,
1009
1061
                     struct curl_httppost **last_post,
1010
1062
                     bool literal_value)
1147
1199
          ptr = ptr->next;
1148
1200
          ++count;
1149
1201
        }
1150
 
        forms =
1151
 
          (struct curl_forms *)malloc((count+1)*sizeof(struct curl_forms));
 
1202
        forms = malloc((count+1)*sizeof(struct curl_forms));
1152
1203
        if (!forms)
1153
1204
        {
1154
1205
          fprintf(config->errors, "Error building form post!\n");
1372
1423
 * data.
1373
1424
 */
1374
1425
 
1375
 
static int str2num(long *val, char *str)
 
1426
static int str2num(long *val, const char *str)
1376
1427
{
1377
1428
  int retcode = 0;
1378
1429
  if(str && ISDIGIT(*str))
1390
1441
 * @param str  the buffer containing the offset
1391
1442
 * @return zero if successful, non-zero if failure.
1392
1443
 */
1393
 
static int str2offset(curl_off_t *val, char *str)
 
1444
static int str2offset(curl_off_t *val, const char *str)
1394
1445
{
1395
 
#if SIZEOF_CURL_OFF_T > 4
1396
 
  /* Ugly, but without going through a bunch of rigmarole, we don't have the
1397
 
   * definitions for LLONG_{MIN,MAX} or LONG_LONG_{MIN,MAX}.
1398
 
   */
1399
 
#ifndef LLONG_MAX
1400
 
#if defined(_MSC_VER)
1401
 
#define LLONG_MAX (curl_off_t)0x7FFFFFFFFFFFFFFFi64
1402
 
#define LLONG_MIN (curl_off_t)0x8000000000000000i64
1403
 
#elif defined(_CRAYC)
1404
 
#define LLONG_MAX (curl_off_t)0x7FFFFFFFFFFFFFFF
1405
 
#define LLONG_MIN (curl_off_t)0x8000000000000000
1406
 
#else
1407
 
#define LLONG_MAX (curl_off_t)0x7FFFFFFFFFFFFFFFLL
1408
 
#define LLONG_MIN (curl_off_t)0x8000000000000000LL
1409
 
#endif
1410
 
#endif
1411
 
 
1412
 
  /* this is a duplicate of the function that is also used in libcurl */
 
1446
#if (CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG)
1413
1447
  *val = curlx_strtoofft(str, NULL, 0);
1414
 
 
1415
 
  if ((*val == LLONG_MAX || *val == LLONG_MIN) && ERRNO == ERANGE)
 
1448
  if((*val == CURL_LLONG_MAX || *val == CURL_LLONG_MIN) && (ERRNO == ERANGE))
1416
1449
    return 1;
1417
1450
#else
1418
1451
  *val = strtol(str, NULL, 0);
1462
1495
}
1463
1496
 
1464
1497
static ParameterError add2list(struct curl_slist **list,
1465
 
                               char *ptr)
 
1498
                               const char *ptr)
1466
1499
{
1467
1500
  struct curl_slist *newlist = curl_slist_append(*list, ptr);
1468
1501
  if(newlist)
1473
1506
  return PARAM_OK;
1474
1507
}
1475
1508
 
1476
 
static int ftpfilemethod(struct Configurable *config, char *str)
 
1509
static int ftpfilemethod(struct Configurable *config, const char *str)
1477
1510
{
1478
 
  if(curlx_strequal("singlecwd", str))
 
1511
  if(curlx_raw_equal("singlecwd", str))
1479
1512
    return CURLFTPMETHOD_SINGLECWD;
1480
 
  if(curlx_strequal("nocwd", str))
 
1513
  if(curlx_raw_equal("nocwd", str))
1481
1514
    return CURLFTPMETHOD_NOCWD;
1482
 
  if(curlx_strequal("multicwd", str))
 
1515
  if(curlx_raw_equal("multicwd", str))
1483
1516
    return CURLFTPMETHOD_MULTICWD;
1484
1517
  warnf(config, "unrecognized ftp file method '%s', using default\n", str);
1485
1518
  return CURLFTPMETHOD_MULTICWD;
1486
1519
}
1487
1520
 
1488
 
static int ftpcccmethod(struct Configurable *config, char *str)
 
1521
static int ftpcccmethod(struct Configurable *config, const char *str)
1489
1522
{
1490
 
  if(curlx_strequal("passive", str))
 
1523
  if(curlx_raw_equal("passive", str))
1491
1524
    return CURLFTPSSL_CCC_PASSIVE;
1492
 
  if(curlx_strequal("active", str))
 
1525
  if(curlx_raw_equal("active", str))
1493
1526
    return CURLFTPSSL_CCC_ACTIVE;
1494
1527
  warnf(config, "unrecognized ftp CCC method '%s', using default\n", str);
1495
1528
  return CURLFTPSSL_CCC_PASSIVE;
1562
1595
  bool longopt=FALSE;
1563
1596
  bool singleopt=FALSE; /* when true means '-o foo' used '-ofoo' */
1564
1597
  ParameterError err;
 
1598
  bool toggle=TRUE; /* how to switch boolean options, on or off. Controlled
 
1599
                       by using --OPTION or --no-OPTION */
1565
1600
 
1566
1601
  /* single-letter,
1567
1602
     long-name,
1576
1611
    {"*c", "connect-timeout", TRUE},
1577
1612
    {"*d", "ciphers",    TRUE},
1578
1613
    {"*e", "disable-epsv", FALSE},
 
1614
    {"*E", "epsv", FALSE}, /* made like this to make --no-epsv and --epsv to
 
1615
                              work although --disable-epsv is the documented
 
1616
                              option */
1579
1617
#ifdef USE_ENVIRONMENT
1580
1618
    {"*f", "environment", FALSE},
1581
1619
#endif
1588
1626
    {"*m", "ntlm",       FALSE},
1589
1627
    {"*n", "basic",      FALSE},
1590
1628
    {"*o", "anyauth",    FALSE},
1591
 
#ifdef MSDOS
 
1629
#ifdef USE_WATT32
1592
1630
    {"*p", "wdebug",     FALSE},
1593
1631
#endif
1594
1632
    {"*q", "ftp-create-dirs", FALSE},
1602
1640
    {"*x", "krb4" ,       TRUE}, /* this is the previous name */
1603
1641
    {"*y", "max-filesize", TRUE},
1604
1642
    {"*z", "disable-eprt", FALSE},
 
1643
    {"*Z", "eprt", FALSE}, /* made like this to make --no-eprt and --eprt to
 
1644
                              work although --disable-eprt is the documented
 
1645
                              option */
1605
1646
    {"$a", "ftp-ssl",    FALSE},
1606
1647
    {"$b", "ftp-pasv",   FALSE},
1607
1648
    {"$c", "socks5",   TRUE},
1626
1667
    {"$T", "socks4a",    TRUE},
1627
1668
    {"$u", "ftp-alternative-to-user", TRUE},
1628
1669
    {"$v", "ftp-ssl-reqd", FALSE},
1629
 
    {"$w", "no-sessionid", FALSE},
 
1670
    {"$w", "sessionid", FALSE}, /* listed as --no-sessionid in the help */
1630
1671
    {"$x", "ftp-ssl-control", FALSE},
1631
1672
    {"$y", "ftp-ssl-ccc", FALSE},
1632
1673
    {"$j", "ftp-ssl-ccc-mode", TRUE},
1633
1674
    {"$z", "libcurl",    TRUE},
1634
1675
    {"$#", "raw",        FALSE},
1635
1676
    {"$0", "post301",    FALSE},
1636
 
    {"$1", "no-keepalive",   FALSE},
 
1677
    {"$1", "keepalive",   FALSE}, /* listed as --no-keepalive in the help */
1637
1678
    {"$2", "socks5-hostname", TRUE},
1638
1679
    {"$3", "keepalive-time",  TRUE},
 
1680
    {"$4", "post302",    FALSE},
 
1681
    {"$5", "noproxy",    TRUE},
 
1682
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
 
1683
    {"$6", "socks5-gssapi-service",  TRUE},
 
1684
    {"$7", "socks5-gssapi-nec",  FALSE},
 
1685
#endif
 
1686
    {"$8", "proxy1.0",   TRUE},
1639
1687
 
1640
1688
    {"0", "http1.0",     FALSE},
1641
1689
    {"1", "tlsv1",       FALSE},
1684
1732
    {"M", "manual",      FALSE},
1685
1733
    {"n", "netrc",       FALSE},
1686
1734
    {"no", "netrc-optional", FALSE},
1687
 
    {"N", "no-buffer",   FALSE},
 
1735
    {"N", "buffer",   FALSE}, /* listed as --no-buffer in the help */
1688
1736
    {"o", "output",      TRUE},
1689
 
    {"O", "remote-name", FALSE},
 
1737
    {"O",  "remote-name", FALSE},
 
1738
    {"Oa", "remote-name-all", FALSE},
1690
1739
    {"p", "proxytunnel", FALSE},
1691
1740
    {"P", "ftpport",     TRUE}, /* older version */
1692
1741
    {"P", "ftp-port",    TRUE},
1696
1745
    {"R", "remote-time", FALSE},
1697
1746
    {"s", "silent",      FALSE},
1698
1747
    {"S", "show-error",  FALSE},
1699
 
    {"t", "telnet-options", TRUE},
 
1748
    {"t", "telnet-options", TRUE}, /* this is documented as telnet-option */
1700
1749
    {"T", "upload-file", TRUE},
1701
1750
    {"u", "user",        TRUE},
1702
1751
    {"U", "proxy-user",  TRUE},
1718
1767
    char *word=('-' == flag[0])?flag+2:flag;
1719
1768
    size_t fnam=strlen(word);
1720
1769
    int numhits=0;
 
1770
 
 
1771
    if(!strncmp(word, "no-", 3)) {
 
1772
      /* disable this option but ignore the "no-" part when looking for it */
 
1773
      word += 3;
 
1774
      toggle = FALSE;
 
1775
    }
 
1776
 
1721
1777
    for(j=0; j< sizeof(aliases)/sizeof(aliases[0]); j++) {
1722
1778
      if(curlx_strnequal(aliases[j].lname, word, fnam)) {
1723
1779
        longopt = TRUE;
1724
1780
        numhits++;
1725
 
        if(curlx_strequal(aliases[j].lname, word)) {
 
1781
        if(curlx_raw_equal(aliases[j].lname, word)) {
1726
1782
          parse = aliases[j].letter;
1727
1783
          hit = j;
1728
1784
          numhits = 1; /* a single unique hit */
1775
1831
        return PARAM_OPTION_UNKNOWN;
1776
1832
      }
1777
1833
    }
1778
 
    if(hit < 0) {
1779
 
      return PARAM_OPTION_UNKNOWN;
1780
 
    }
1781
 
    if(!longopt && aliases[hit].extraparam && parse[1]) {
1782
 
      nextarg=(char *)&parse[1]; /* this is the actual extra parameter */
1783
 
      singleopt=TRUE;   /* don't loop anymore after this */
1784
 
    }
1785
 
    else if(!nextarg && aliases[hit].extraparam) {
1786
 
      return PARAM_REQUIRES_PARAMETER;
1787
 
    }
1788
 
    else if(nextarg && aliases[hit].extraparam)
1789
 
      *usedarg = TRUE; /* mark it as used */
 
1834
 
 
1835
    if(aliases[hit].extraparam) {
 
1836
      /* this option requires an extra parameter */
 
1837
      if(!longopt && parse[1]) {
 
1838
        nextarg=(char *)&parse[1]; /* this is the actual extra parameter */
 
1839
        singleopt=TRUE;   /* don't loop anymore after this */
 
1840
      }
 
1841
      else if(!nextarg)
 
1842
        return PARAM_REQUIRES_PARAMETER;
 
1843
      else
 
1844
        *usedarg = TRUE; /* mark it as used */
 
1845
    }
1790
1846
 
1791
1847
    switch(letter) {
1792
1848
    case '*': /* options without a short option */
1805
1861
        GetStr(&config->cipher_list, nextarg);
1806
1862
        break;
1807
1863
      case 'e': /* --disable-epsv */
1808
 
        config->disable_epsv ^= TRUE;
 
1864
        config->disable_epsv = toggle;
 
1865
        break;
 
1866
      case 'E': /* --epsv */
 
1867
        config->disable_epsv = (bool)(!toggle);
1809
1868
        break;
1810
1869
#ifdef USE_ENVIRONMENT
1811
1870
      case 'f':
1812
 
        config->writeenv ^= TRUE;
 
1871
        config->writeenv = toggle;
1813
1872
        break;
1814
1873
#endif
1815
1874
      case 'g': /* --trace */
1863
1922
        break;
1864
1923
 
1865
1924
      case 'j': /* --compressed */
1866
 
        config->encoding ^= TRUE;
 
1925
        config->encoding = toggle;
1867
1926
        break;
1868
1927
 
1869
1928
      case 'k': /* --digest */
1870
 
        config->authtype = CURLAUTH_DIGEST;
 
1929
        if(toggle)
 
1930
          config->authtype |= CURLAUTH_DIGEST;
 
1931
        else
 
1932
          config->authtype &= ~CURLAUTH_DIGEST;
1871
1933
        break;
1872
1934
 
1873
1935
      case 'l': /* --negotiate */
1874
 
        if(curlinfo->features & CURL_VERSION_GSSNEGOTIATE)
1875
 
          config->authtype = CURLAUTH_GSSNEGOTIATE;
 
1936
        if(toggle) {
 
1937
          if(curlinfo->features & CURL_VERSION_GSSNEGOTIATE)
 
1938
            config->authtype |= CURLAUTH_GSSNEGOTIATE;
 
1939
          else
 
1940
            return PARAM_LIBCURL_DOESNT_SUPPORT;
 
1941
        }
1876
1942
        else
1877
 
          return PARAM_LIBCURL_DOESNT_SUPPORT;
 
1943
          config->authtype &= ~CURLAUTH_GSSNEGOTIATE;
1878
1944
        break;
1879
1945
 
1880
1946
      case 'm': /* --ntlm */
1881
 
        if(curlinfo->features & CURL_VERSION_NTLM)
1882
 
          config->authtype = CURLAUTH_NTLM;
 
1947
        if(toggle) {
 
1948
          if(curlinfo->features & CURL_VERSION_NTLM)
 
1949
            config->authtype |= CURLAUTH_NTLM;
 
1950
          else
 
1951
            return PARAM_LIBCURL_DOESNT_SUPPORT;
 
1952
        }
1883
1953
        else
1884
 
          return PARAM_LIBCURL_DOESNT_SUPPORT;
 
1954
          config->authtype &= ~CURLAUTH_NTLM;
1885
1955
        break;
1886
1956
 
1887
1957
      case 'n': /* --basic for completeness */
1888
 
        config->authtype = CURLAUTH_BASIC;
 
1958
        if(toggle)
 
1959
          config->authtype |= CURLAUTH_BASIC;
 
1960
        else
 
1961
          config->authtype &= ~CURLAUTH_BASIC;
1889
1962
        break;
1890
1963
 
1891
1964
      case 'o': /* --anyauth, let libcurl pick it */
1892
 
        config->authtype = CURLAUTH_ANY;
 
1965
        if(toggle)
 
1966
          config->authtype = CURLAUTH_ANY;
 
1967
        /* --no-anyauth simply doesn't touch it */
1893
1968
        break;
1894
1969
 
1895
 
#ifdef MSDOS
 
1970
#ifdef USE_WATT32
1896
1971
      case 'p': /* --wdebug */
1897
1972
        dbug_init();
1898
1973
        break;
1899
1974
#endif
1900
1975
      case 'q': /* --ftp-create-dirs */
1901
 
        config->ftp_create_dirs ^= TRUE;
 
1976
        config->ftp_create_dirs = toggle;
1902
1977
        break;
1903
1978
 
1904
1979
      case 'r': /* --create-dirs */
1913
1988
 
1914
1989
      case 't': /* --proxy-ntlm */
1915
1990
        if(curlinfo->features & CURL_VERSION_NTLM)
1916
 
          config->proxyntlm ^= TRUE;
 
1991
          config->proxyntlm = toggle;
1917
1992
        else
1918
1993
          return PARAM_LIBCURL_DOESNT_SUPPORT;
1919
1994
        break;
1920
1995
 
1921
1996
      case 'u': /* --crlf */
1922
 
        /* LF -> CRLF conversinon? */
 
1997
        /* LF -> CRLF conversion? */
1923
1998
        config->crlf = TRUE;
1924
1999
        break;
1925
2000
 
1929
2004
          if(!newfile)
1930
2005
            warnf(config, "Failed to open %s!\n", nextarg);
1931
2006
          else {
 
2007
            if(config->errors_fopened)
 
2008
              fclose(config->errors);
1932
2009
            config->errors = newfile;
1933
2010
            config->errors_fopened = TRUE;
1934
2011
          }
1953
2030
          return PARAM_BAD_NUMERIC;
1954
2031
        break;
1955
2032
      case 'z': /* --disable-eprt */
1956
 
        config->disable_eprt ^= TRUE;
 
2033
        config->disable_eprt = toggle;
 
2034
        break;
 
2035
      case 'Z': /* --eprt */
 
2036
        config->disable_eprt = (bool)(!toggle);
1957
2037
        break;
1958
2038
 
1959
2039
      default: /* the URL! */
1986
2066
    case '$': /* more options without a short option */
1987
2067
      switch(subletter) {
1988
2068
      case 'a': /* --ftp-ssl */
1989
 
        config->ftp_ssl ^= TRUE;
 
2069
        config->ftp_ssl = toggle;
1990
2070
        break;
1991
2071
      case 'b': /* --ftp-pasv */
1992
2072
        if(config->ftpport)
2012
2092
        config->socksver = CURLPROXY_SOCKS5_HOSTNAME;
2013
2093
        break;
2014
2094
      case 'd': /* --tcp-nodelay option */
2015
 
        config->tcp_nodelay ^= TRUE;
 
2095
        config->tcp_nodelay = toggle;
2016
2096
        break;
2017
2097
      case 'e': /* --proxy-digest */
2018
 
        config->proxydigest ^= TRUE;
 
2098
        config->proxydigest = toggle;
2019
2099
        break;
2020
2100
      case 'f': /* --proxy-basic */
2021
 
        config->proxybasic ^= TRUE;
 
2101
        config->proxybasic = toggle;
2022
2102
        break;
2023
2103
      case 'g': /* --retry */
2024
2104
        if(str2num(&config->req_retry, nextarg))
2035
2115
 
2036
2116
      case 'k': /* --proxy-negotiate */
2037
2117
        if(curlinfo->features & CURL_VERSION_GSSNEGOTIATE)
2038
 
          config->proxynegotiate ^= TRUE;
 
2118
          config->proxynegotiate = toggle;
2039
2119
        else
2040
2120
          return PARAM_LIBCURL_DOESNT_SUPPORT;
2041
2121
        break;
2043
2123
        GetStr(&config->ftp_account, nextarg);
2044
2124
        break;
2045
2125
      case 'n': /* --proxy-anyauth */
2046
 
        config->proxyanyauth ^= TRUE;
 
2126
        config->proxyanyauth = toggle;
2047
2127
        break;
2048
2128
      case 'o': /* --trace-time */
2049
 
        config->tracetime ^= TRUE;
 
2129
        config->tracetime = toggle;
2050
2130
        break;
2051
2131
      case 'p': /* --ignore-content-length */
2052
 
        config->ignorecl ^= TRUE;
 
2132
        config->ignorecl = toggle;
2053
2133
        break;
2054
2134
      case 'q': /* --ftp-skip-pasv-ip */
2055
 
        config->ftp_skip_ip ^= TRUE;
 
2135
        config->ftp_skip_ip = toggle;
2056
2136
        break;
2057
2137
      case 'r': /* --ftp-method (undocumented at this point) */
2058
2138
        config->ftp_filemethod = ftpfilemethod(config, nextarg);
2077
2157
        GetStr(&config->ftp_alternative_to_user, nextarg);
2078
2158
        break;
2079
2159
      case 'v': /* --ftp-ssl-reqd */
2080
 
        config->ftp_ssl_reqd ^= TRUE;
 
2160
        config->ftp_ssl_reqd = toggle;
2081
2161
        break;
2082
2162
      case 'w': /* --no-sessionid */
2083
 
        config->disable_sessionid ^= TRUE;
 
2163
        config->disable_sessionid = (bool)(!toggle);
2084
2164
        break;
2085
2165
      case 'x': /* --ftp-ssl-control */
2086
 
        config->ftp_ssl_control ^= TRUE;
 
2166
        config->ftp_ssl_control = toggle;
2087
2167
        break;
2088
2168
      case 'y': /* --ftp-ssl-ccc */
2089
 
        config->ftp_ssl_ccc ^= TRUE;
 
2169
        config->ftp_ssl_ccc = toggle;
2090
2170
        if(!config->ftp_ssl_ccc_mode)
2091
2171
            config->ftp_ssl_ccc_mode = CURLFTPSSL_CCC_PASSIVE;
2092
2172
        break;
2098
2178
        GetStr(&config->libcurl, nextarg);
2099
2179
        break;
2100
2180
      case '#': /* --raw */
2101
 
        config->raw ^= TRUE;
 
2181
        config->raw = toggle;
2102
2182
        break;
2103
2183
      case '0': /* --post301 */
2104
 
        config->post301 ^= TRUE;
 
2184
        config->post301 = toggle;
2105
2185
        break;
2106
2186
      case '1': /* --no-keepalive */
2107
 
        config->nokeepalive ^= TRUE;
 
2187
        config->nokeepalive = (bool)(!toggle);
2108
2188
        break;
2109
2189
      case '3': /* --keepalive-time */
2110
2190
        if(str2num(&config->alivetime, nextarg))
2111
2191
          return PARAM_BAD_NUMERIC;
2112
2192
        break;
 
2193
      case '4': /* --post302 */
 
2194
        config->post302 = toggle;
 
2195
        break;
 
2196
      case '5': /* --noproxy */
 
2197
        /* This specifies the noproxy list */
 
2198
        GetStr(&config->noproxy, nextarg);
 
2199
        break;
 
2200
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
 
2201
      case '6': /* --socks5-gssapi-service */
 
2202
        GetStr(&config->socks5_gssapi_service, nextarg);
 
2203
        break;
 
2204
      case '7': /* --socks5-gssapi-nec*/
 
2205
        config->socks5_gssapi_nec = TRUE;
 
2206
        break;
 
2207
#endif
 
2208
      case '8': /* --proxy1.0 */
 
2209
        /* http 1.0 proxy */
 
2210
        GetStr(&config->proxy, nextarg);
 
2211
        config->proxyver = CURLPROXY_HTTP_1_0;
 
2212
        break;
2113
2213
      }
2114
2214
      break;
2115
2215
    case '#': /* --progress-bar */
2116
 
      config->progressmode ^= CURL_PROGRESS_BAR;
 
2216
      config->progressmode = toggle?CURL_PROGRESS_BAR:0;
2117
2217
      break;
2118
2218
    case '0':
2119
2219
      /* HTTP version 1.0 */
2141
2241
      break;
2142
2242
    case 'a':
2143
2243
      /* This makes the FTP sessions use APPE instead of STOR */
2144
 
      config->conf ^= CONF_FTPAPPEND;
 
2244
      config->ftp_append = toggle;
2145
2245
      break;
2146
2246
    case 'A':
2147
2247
      /* This specifies the User-Agent name */
2161
2261
      break;
2162
2262
    case 'B':
2163
2263
      /* use ASCII/text when transfering */
2164
 
      config->conf ^= CONF_GETTEXT;
 
2264
      config->use_ascii = toggle;
2165
2265
      break;
2166
2266
    case 'c':
2167
2267
      /* get the file name to dump all cookies in */
2193
2293
           * Case 2: we first load the file using that name and then encode
2194
2294
           * the content.
2195
2295
           */
2196
 
          char *p = strchr(nextarg, '=');
 
2296
          const char *p = strchr(nextarg, '=');
2197
2297
          size_t size = 0;
2198
2298
          size_t nlen;
2199
2299
          char is_file;
2243
2343
          }
2244
2344
          else {
2245
2345
            char *enc = curl_easy_escape(config->easy, postdata, size);
 
2346
            free(postdata); /* no matter if it worked or not */
2246
2347
            if(enc) {
2247
2348
              /* now make a string with the name from above and append the
2248
2349
                 encoded string */
2255
2356
              else
2256
2357
                strcpy(n, enc);
2257
2358
              curl_free(enc);
2258
 
              free(postdata);
2259
2359
              if(n) {
2260
2360
                postdata = n;
2261
2361
              }
2349
2449
        if(ptr) {
2350
2450
          /* Automatic referer requested, this may be combined with a
2351
2451
             set initial one */
2352
 
          config->conf |= CONF_AUTO_REFERER;
 
2452
          config->autoreferer = TRUE;
2353
2453
          *ptr = 0; /* zero terminate here */
2354
2454
        }
 
2455
        else
 
2456
          config->autoreferer = FALSE;
2355
2457
        GetStr(&config->referer, nextarg);
2356
2458
      }
2357
2459
      break;
2376
2478
        break;
2377
2479
      case 'f': /* crypto engine */
2378
2480
        GetStr(&config->engine, nextarg);
2379
 
        if (config->engine && curlx_strequal(config->engine,"list"))
 
2481
        if (config->engine && curlx_raw_equal(config->engine,"list"))
2380
2482
           config->list_engines = TRUE;
2381
2483
        break;
2382
2484
      case 'g': /* CA info PEM file */
2423
2525
      break;
2424
2526
    case 'f':
2425
2527
      /* fail hard on errors  */
2426
 
      config->conf ^= CONF_FAILONERROR;
 
2528
      config->failonerror = toggle;
2427
2529
      break;
2428
2530
    case 'F':
2429
2531
      /* "form data" simulation, this is a little advanced so lets do our best
2439
2541
      break;
2440
2542
 
2441
2543
    case 'g': /* g disables URLglobbing */
2442
 
      config->globoff ^= TRUE;
 
2544
      config->globoff = toggle;
2443
2545
      break;
2444
2546
 
2445
2547
    case 'G': /* HTTP GET */
2447
2549
      break;
2448
2550
 
2449
2551
    case 'h': /* h for help */
2450
 
      help();
2451
 
      return PARAM_HELP_REQUESTED;
 
2552
      if(toggle) {
 
2553
        help();
 
2554
        return PARAM_HELP_REQUESTED;
 
2555
      }
 
2556
      /* we now actually support --no-help too! */
 
2557
      break;
2452
2558
    case 'H':
2453
2559
      /* A custom header to append to a list */
2454
2560
      err = add2list(&config->headers, nextarg);
2456
2562
        return err;
2457
2563
      break;
2458
2564
    case 'i':
2459
 
      config->conf ^= CONF_HEADER; /* include the HTTP header as well */
 
2565
      config->include_headers = toggle; /* include the headers as well in the
 
2566
                                           general output stream */
2460
2567
      break;
2461
2568
    case 'j':
2462
 
      config->cookiesession ^= TRUE;
 
2569
      config->cookiesession = toggle;
2463
2570
      break;
2464
2571
    case 'I':
2465
2572
      /*
2466
 
       * CONF_BODY will imply CONF_HEADER later on
 
2573
       * no_body will imply include_headers later on
2467
2574
       */
2468
 
      config->conf ^= CONF_NOBODY;
 
2575
      config->no_body = toggle;
2469
2576
      if(SetHTTPrequest(config,
2470
 
                        (config->conf & CONF_NOBODY)?HTTPREQ_HEAD:HTTPREQ_GET,
 
2577
                        (config->no_body)?HTTPREQ_HEAD:HTTPREQ_GET,
2471
2578
                        &config->httpreq))
2472
2579
        return PARAM_BAD_USE;
2473
2580
      break;
2474
2581
    case 'k': /* allow insecure SSL connects */
2475
 
      config->insecure_ok ^= TRUE;
 
2582
      config->insecure_ok = toggle;
2476
2583
      break;
2477
2584
    case 'K': /* parse config file */
2478
2585
      if(parseconfig(nextarg, config))
2480
2587
              nextarg);
2481
2588
      break;
2482
2589
    case 'l':
2483
 
      config->conf ^= CONF_DIRLISTONLY; /* only list the names of the FTP dir */
 
2590
      config->dirlistonly = toggle; /* only list the names of the FTP dir */
2484
2591
      break;
2485
2592
    case 'L':
2486
 
      config->conf ^= CONF_FOLLOWLOCATION; /* Follow Location: HTTP headers */
 
2593
      config->followlocation = toggle; /* Follow Location: HTTP headers */
2487
2594
      switch (subletter) {
2488
2595
      case 't':
2489
2596
        /* Continue to send authentication (user+password) when following
2490
2597
         * locations, even when hostname changed */
2491
 
        config->conf ^= CONF_UNRESTRICTED_AUTH;
 
2598
        config->unrestricted_auth = toggle;
2492
2599
        break;
2493
2600
      }
2494
2601
      break;
2498
2605
        return PARAM_BAD_NUMERIC;
2499
2606
      break;
2500
2607
    case 'M': /* M for manual, huge help */
 
2608
      if(toggle) { /* --no-manual shows no manual... */
2501
2609
#ifdef USE_MANUAL
2502
 
      hugehelp();
2503
 
      return PARAM_HELP_REQUESTED;
 
2610
        hugehelp();
 
2611
        return PARAM_HELP_REQUESTED;
2504
2612
#else
2505
 
      warnf(config,
2506
 
            "built-in manual was disabled at build-time!\n");
2507
 
      return PARAM_OPTION_UNKNOWN;
 
2613
        warnf(config,
 
2614
              "built-in manual was disabled at build-time!\n");
 
2615
        return PARAM_OPTION_UNKNOWN;
2508
2616
#endif
 
2617
      }
 
2618
      break;
2509
2619
    case 'n':
2510
2620
      switch(subletter) {
2511
2621
      case 'o': /* CA info PEM file */
2512
2622
        /* use .netrc or URL */
2513
 
        config->conf ^= CONF_NETRC_OPT;
 
2623
        config->netrc_opt = toggle;
2514
2624
        break;
2515
2625
      default:
2516
2626
        /* pick info from .netrc, if this is used for http, curl will
2517
2627
           automatically enfore user+password with the request */
2518
 
        config->conf ^= CONF_NETRC;
 
2628
        config->netrc = toggle;
2519
2629
        break;
2520
2630
      }
2521
2631
      break;
2522
2632
    case 'N':
2523
2633
      /* disable the output I/O buffering */
2524
 
      config->nobuffer ^= 1;
 
2634
      config->nobuffer = (bool)(!toggle);
2525
2635
      break;
2526
 
    case 'o':
2527
 
    case 'O':
 
2636
    case 'O': /* --remote-name */
 
2637
      if(subletter == 'a') { /* --remote-name-all */
 
2638
        config->default_node_flags = toggle?GETOUT_USEREMOTE:0;
 
2639
        break;
 
2640
      }
 
2641
    /* fall-through! */
 
2642
    case 'o': /* --output */
2528
2643
      /* output file */
2529
2644
      {
2530
2645
        struct getout *url;
2546
2661
 
2547
2662
        if(url) {
2548
2663
          /* fill in the outfile */
2549
 
          if('o' == letter)
 
2664
          if('o' == letter) {
2550
2665
            GetStr(&url->outfile, nextarg);
 
2666
            url->flags &= ~GETOUT_USEREMOTE; /* switch off */
 
2667
          }
2551
2668
          else {
2552
2669
            url->outfile=NULL; /* leave it */
2553
 
            url->flags |= GETOUT_USEREMOTE;
 
2670
            if(toggle)
 
2671
              url->flags |= GETOUT_USEREMOTE;  /* switch on */
 
2672
            else
 
2673
              url->flags &= ~GETOUT_USEREMOTE; /* switch off */
2554
2674
          }
2555
2675
          url->flags |= GETOUT_OUTFILE;
2556
2676
        }
2566
2686
      break;
2567
2687
    case 'p':
2568
2688
      /* proxy tunnel for non-http protocols */
2569
 
      config->proxytunnel ^= TRUE;
 
2689
      config->proxytunnel = toggle;
2570
2690
      break;
2571
2691
 
2572
2692
    case 'q': /* if used first, already taken care of, we do it like
2628
2748
      break;
2629
2749
    case 'R':
2630
2750
      /* use remote file's time */
2631
 
      config->remote_time ^= TRUE;
 
2751
      config->remote_time = toggle;
2632
2752
      break;
2633
2753
    case 's':
2634
2754
      /* don't show progress meter, don't show errors : */
2635
 
      config->conf ^= (CONF_MUTE|CONF_NOPROGRESS);
2636
 
      config->showerror ^= TRUE; /* toggle off */
 
2755
      if(toggle)
 
2756
        config->mute = config->noprogress = TRUE;
 
2757
      else
 
2758
        config->mute = config->noprogress = FALSE;
 
2759
      config->showerror = (bool)(!toggle); /* toggle off */
2637
2760
      break;
2638
2761
    case 'S':
2639
2762
      /* show errors */
2640
 
      config->showerror ^= TRUE; /* toggle on if used with -s */
 
2763
      config->showerror = toggle; /* toggle on if used with -s */
2641
2764
      break;
2642
2765
    case 't':
2643
2766
      /* Telnet options */
2689
2812
      checkpasswd("proxy", &config->proxyuserpwd);
2690
2813
      break;
2691
2814
    case 'v':
2692
 
      /* the '%' thing here will cause the trace get sent to stderr */
2693
 
      GetStr(&config->trace_dump, (char *)"%");
2694
 
      if(config->tracetype && (config->tracetype != TRACE_PLAIN))
2695
 
        warnf(config,
2696
 
              "-v/--verbose overrides an earlier trace/verbose option\n");
2697
 
      config->tracetype = TRACE_PLAIN;
 
2815
      if(toggle) {
 
2816
        /* the '%' thing here will cause the trace get sent to stderr */
 
2817
        GetStr(&config->trace_dump, (char *)"%");
 
2818
        if(config->tracetype && (config->tracetype != TRACE_PLAIN))
 
2819
          warnf(config,
 
2820
                "-v/--verbose overrides an earlier trace/verbose option\n");
 
2821
        config->tracetype = TRACE_PLAIN;
 
2822
      }
 
2823
      else
 
2824
        /* verbose is disabled here */
 
2825
        config->tracetype = TRACE_NONE;
2698
2826
      break;
2699
2827
    case 'V':
2700
2828
    {
2701
2829
      const char * const *proto;
2702
2830
 
 
2831
      if(!toggle)
 
2832
        /* --no-version yields no output! */
 
2833
        break;
 
2834
 
2703
2835
      printf(CURL_ID "%s\n", curl_version());
2704
2836
      if (curlinfo->protocols) {
2705
2837
        printf("Protocols: ");
2763
2895
    case 'x':
2764
2896
      /* proxy */
2765
2897
      GetStr(&config->proxy, nextarg);
 
2898
      config->proxyver = CURLPROXY_HTTP;
2766
2899
      break;
2767
2900
    case 'X':
2768
2901
      /* set custom request */
2830
2963
  return PARAM_OK;
2831
2964
}
2832
2965
 
 
2966
/*
 
2967
 * Copies the string from line to the buffer at param, unquoting
 
2968
 * backslash-quoted characters and NUL-terminating the output string.
 
2969
 * Stops at the first non-backslash-quoted double quote character or the
 
2970
 * end of the input string. param must be at least as long as the input
 
2971
 * string.  Returns the pointer after the last handled input character.
 
2972
 */
 
2973
static const char *unslashquote(const char *line, char *param)
 
2974
{
 
2975
  while(*line && (*line != '\"')) {
 
2976
    if(*line == '\\') {
 
2977
      char out;
 
2978
      line++;
 
2979
 
 
2980
      /* default is to output the letter after the backslash */
 
2981
      switch(out = *line) {
 
2982
      case '\0':
 
2983
        continue; /* this'll break out of the loop */
 
2984
      case 't':
 
2985
        out='\t';
 
2986
        break;
 
2987
      case 'n':
 
2988
        out='\n';
 
2989
        break;
 
2990
      case 'r':
 
2991
        out='\r';
 
2992
        break;
 
2993
      case 'v':
 
2994
        out='\v';
 
2995
        break;
 
2996
      }
 
2997
      *param++=out;
 
2998
      line++;
 
2999
    }
 
3000
    else
 
3001
      *param++=*line++;
 
3002
  }
 
3003
  *param=0; /* always zero terminate */
 
3004
  return line;
 
3005
}
 
3006
 
2833
3007
/* return 0 on everything-is-fine, and non-zero otherwise */
2834
3008
static int parseconfig(const char *filename,
2835
3009
                       struct Configurable *config)
2839
3013
  char filebuffer[512];
2840
3014
  bool usedarg;
2841
3015
  char *home;
 
3016
  int rc = 0;
2842
3017
 
2843
3018
  if(!filename || !*filename) {
2844
3019
    /* NULL or no file name attempts to load .curlrc from the homedir! */
2922
3097
      line = aline;
2923
3098
      alloced_param=FALSE;
2924
3099
 
2925
 
      /* lines with # in the fist column is a comment! */
 
3100
      /* line with # in the first non-blank column is a comment! */
2926
3101
      while(*line && ISSPACE(*line))
2927
3102
        line++;
2928
3103
 
2956
3131
 
2957
3132
      /* the parameter starts here (unless quoted) */
2958
3133
      if(*line == '\"') {
2959
 
        char *ptr;
2960
 
        /* quoted parameter, do the qoute dance */
 
3134
        /* quoted parameter, do the quote dance */
2961
3135
        line++;
2962
 
        param=strdup(line); /* parameter */
 
3136
        param=malloc(strlen(line)+1); /* parameter */
 
3137
        if (!param) {
 
3138
          /* out of memory */
 
3139
          free(aline);
 
3140
          rc = 1;
 
3141
          break;
 
3142
        }
2963
3143
        alloced_param=TRUE;
2964
 
 
2965
 
        ptr=param;
2966
 
        while(*line && (*line != '\"')) {
2967
 
          if(*line == '\\') {
2968
 
            char out;
2969
 
            line++;
2970
 
 
2971
 
            /* default is to output the letter after the backslah */
2972
 
            switch(out = *line) {
2973
 
            case '\0':
2974
 
              continue; /* this'll break out of the loop */
2975
 
            case 't':
2976
 
              out='\t';
2977
 
              break;
2978
 
            case 'n':
2979
 
              out='\n';
2980
 
              break;
2981
 
            case 'r':
2982
 
              out='\r';
2983
 
              break;
2984
 
            case 'v':
2985
 
              out='\v';
2986
 
              break;
2987
 
            }
2988
 
            *ptr++=out;
2989
 
            line++;
2990
 
          }
2991
 
          else
2992
 
            *ptr++=*line++;
2993
 
        }
2994
 
        *ptr=0; /* always zero terminate */
2995
 
 
 
3144
        line = (char*) unslashquote(line, param);
2996
3145
      }
2997
3146
      else {
2998
3147
        param=line; /* parameter starts here */
3042
3191
      fclose(file);
3043
3192
  }
3044
3193
  else
3045
 
    return 1; /* couldn't open the file */
3046
 
  return 0;
 
3194
    rc = 1; /* couldn't open the file */
 
3195
  return rc;
3047
3196
}
3048
3197
 
3049
3198
static void go_sleep(long ms)
3116
3265
 
3117
3266
#define MAX_SEEK 2147483647
3118
3267
 
3119
 
#ifndef SIZEOF_OFF_T
3120
 
/* (Jan 11th 2008) this is a reasonably new define in the config.h so there
3121
 
   might be older handicrafted configs that don't define it properly and then
3122
 
   we assume 32bit off_t */
3123
 
#define SIZEOF_OFF_T 4
3124
 
#endif
3125
3268
/*
3126
3269
 * my_seek() is the CURLOPT_SEEKFUNCTION we use
3127
3270
 */
3129
3272
{
3130
3273
  struct InStruct *in=(struct InStruct *)stream;
3131
3274
 
3132
 
#if (SIZEOF_CURL_OFF_T > SIZEOF_OFF_T) && !defined(lseek)
3133
 
  /* The sizeof check following here is only interesting if curl_off_t is
3134
 
     larger than off_t, but also not on windows-like systems for which lseek
3135
 
     is a defined macro that works around the 32bit off_t-problem and thus do
3136
 
     64bit seeks correctly anyway */
 
3275
#if (CURL_SIZEOF_CURL_OFF_T > SIZEOF_OFF_T) && !defined(USE_WIN32_LARGE_FILES)
 
3276
  /* The offset check following here is only interesting if curl_off_t is
 
3277
     larger than off_t and we are not using the WIN32 large file support
 
3278
     macros that provide the support to do 64bit seeks correctly */
3137
3279
 
3138
3280
  if(offset > MAX_SEEK) {
3139
3281
    /* Some precaution code to work around problems with different data sizes
3292
3434
 
3293
3435
 
3294
3436
static
3295
 
void dump(char *timebuf, const char *text,
3296
 
          FILE *stream, unsigned char *ptr, size_t size,
 
3437
void dump(const char *timebuf, const char *text,
 
3438
          FILE *stream, const unsigned char *ptr, size_t size,
3297
3439
          trace tracetype, curl_infotype infotype)
3298
3440
{
3299
3441
  size_t i;
3372
3514
  secs = tv.tv_sec;
3373
3515
  now = localtime(&secs);  /* not multithread safe but we don't care */
3374
3516
  if(config->tracetime)
3375
 
    snprintf(timebuf, sizeof(timebuf), "%02d:%02d:%02d.%06d ",
3376
 
             now->tm_hour, now->tm_min, now->tm_sec, tv.tv_usec);
 
3517
    snprintf(timebuf, sizeof(timebuf), "%02d:%02d:%02d.%06ld ",
 
3518
             now->tm_hour, now->tm_min, now->tm_sec, (long)tv.tv_usec);
3377
3519
  else
3378
3520
    timebuf[0]=0;
3379
3521
 
3383
3525
      config->trace_stream = stdout;
3384
3526
    else if(curlx_strequal("%", config->trace_dump))
3385
3527
      /* Ok, this is somewhat hackish but we do it undocumented for now */
3386
 
      config->trace_stream = stderr;
 
3528
      config->trace_stream = config->errors;  /* aka stderr */
3387
3529
    else {
3388
3530
      config->trace_stream = fopen(config->trace_dump, "w");
3389
3531
      config->trace_fopened = TRUE;
3393
3535
  if(config->trace_stream)
3394
3536
    output = config->trace_stream;
3395
3537
 
 
3538
  if(!output) {
 
3539
    warnf(config, "Failed to create/open output");
 
3540
    return 0;
 
3541
  }
 
3542
 
3396
3543
  if(config->tracetype == TRACE_PLAIN) {
3397
3544
    /*
3398
3545
     * This is the trace look that is similar to what libcurl makes on its
3411
3558
      for(i=0; i<size-1; i++) {
3412
3559
        if(data[i] == '\n') { /* LF */
3413
3560
          if(!newl) {
3414
 
            fprintf(config->trace_stream, "%s%s ",
3415
 
                    timebuf, s_infotype[type]);
 
3561
            fprintf(output, "%s%s ", timebuf, s_infotype[type]);
3416
3562
          }
3417
 
          fwrite(data+st, i-st+1, 1, config->trace_stream);
 
3563
          fwrite(data+st, i-st+1, 1, output);
3418
3564
          st = i+1;
3419
3565
          newl = FALSE;
3420
3566
        }
3421
3567
      }
3422
3568
      if(!newl)
3423
 
        fprintf(config->trace_stream, "%s%s ", timebuf, s_infotype[type]);
3424
 
      fwrite(data+st, i-st+1, 1, config->trace_stream);
 
3569
        fprintf(output, "%s%s ", timebuf, s_infotype[type]);
 
3570
      fwrite(data+st, i-st+1, 1, output);
3425
3571
      newl = (bool)(size && (data[size-1] != '\n'));
3426
3572
      traced_data = FALSE;
3427
3573
      break;
3428
3574
    case CURLINFO_TEXT:
3429
3575
    case CURLINFO_HEADER_IN:
3430
3576
      if(!newl)
3431
 
        fprintf(config->trace_stream, "%s%s ", timebuf, s_infotype[type]);
3432
 
      fwrite(data, size, 1, config->trace_stream);
 
3577
        fprintf(output, "%s%s ", timebuf, s_infotype[type]);
 
3578
      fwrite(data, size, 1, output);
3433
3579
      newl = (bool)(size && (data[size-1] != '\n'));
3434
3580
      traced_data = FALSE;
3435
3581
      break;
3442
3588
           to stderr or stdout, we don't display the alert about the data not
3443
3589
           being shown as the data _is_ shown then just not via this
3444
3590
           function */
3445
 
        if(!(config->conf&CONF_ISATTY) ||
3446
 
           ((config->trace_stream != stderr) &&
3447
 
            (config->trace_stream != stdout))) {
 
3591
        if(!config->isatty ||
 
3592
           ((output != stderr) && (output != stdout))) {
3448
3593
          if(!newl)
3449
 
            fprintf(config->trace_stream, "%s%s ", timebuf, s_infotype[type]);
3450
 
          fprintf(config->trace_stream, "[data not shown]\n");
 
3594
            fprintf(output, "%s%s ", timebuf, s_infotype[type]);
 
3595
          fprintf(output, "[data not shown]\n");
3451
3596
          newl = FALSE;
3452
3597
          traced_data = TRUE;
3453
3598
        }
3532
3677
    free(config->proxy);
3533
3678
  if(config->proxyuserpwd)
3534
3679
    free(config->proxyuserpwd);
 
3680
  if(config->noproxy)
 
3681
    free(config->noproxy);
3535
3682
  if(config->cookie)
3536
3683
    free(config->cookie);
3537
3684
  if(config->cookiefile)
3580
3727
    free(config->pubkey);
3581
3728
  if (config->referer)
3582
3729
    free(config->referer);
 
3730
  if (config->hostpubmd5)
 
3731
    free(config->hostpubmd5);
 
3732
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
 
3733
  if(config->socks5_gssapi_service)
 
3734
    free(config->socks5_gssapi_service);
 
3735
#endif
3583
3736
 
3584
3737
  curl_slist_free_all(config->quote); /* checks for config->quote == NULL */
3585
3738
  curl_slist_free_all(config->prequote);
3610
3763
  if(curlinfo->features & CURL_VERSION_SSL) {
3611
3764
    DWORD buflen;
3612
3765
    char *ptr = NULL;
3613
 
    char *retval = (char *) malloc(sizeof (TCHAR) * (MAX_PATH + 1));
 
3766
    char *retval = malloc(sizeof (TCHAR) * (MAX_PATH + 1));
3614
3767
    if (!retval)
3615
3768
      return;
3616
3769
    retval[0] = '\0';
3642
3795
 
3643
3796
static struct curl_slist *easycode;
3644
3797
 
3645
 
CURLcode _my_setopt(CURL *curl, struct Configurable *config, const char *name,
3646
 
                    CURLoption tag, ...);
 
3798
static CURLcode _my_setopt(CURL *curl, struct Configurable *config,
 
3799
                           const char *name, CURLoption tag, ...);
3647
3800
 
3648
 
CURLcode _my_setopt(CURL *curl, struct Configurable *config, const char *name,
3649
 
                    CURLoption tag, ...)
 
3801
static CURLcode _my_setopt(CURL *curl, struct Configurable *config,
 
3802
                           const char *name, CURLoption tag, ...)
3650
3803
{
3651
3804
  va_list arg;
3652
3805
  CURLcode ret;
3756
3909
        if(!memcmp((char *)c, "[m]", 3)) {
3757
3910
#if defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS > 32)
3758
3911
          fprintf(out, "#define _FILE_OFFSET_BITS %d "
3759
 
                  "/* for curl_off_t magic */\n",
 
3912
                  "/* for pre libcurl 7.19.0 curl_off_t magic */\n",
3760
3913
                  _FILE_OFFSET_BITS);
3761
3914
#endif
3762
3915
        }
3799
3952
  int infilenum;
3800
3953
  char *uploadfile=NULL; /* a single file, never a glob */
3801
3954
 
3802
 
  int infd = STDIN_FILENO;
3803
 
  bool infdopen;
3804
 
  FILE *headerfilep = NULL;
3805
3955
  curl_off_t uploadfilesize; /* -1 means unknown */
3806
3956
  bool stillflags=TRUE;
3807
3957
 
3871
4021
  }
3872
4022
  config->postfieldsize = -1;
3873
4023
  config->showerror=TRUE;
3874
 
  config->conf=CONF_DEFAULT;
3875
4024
  config->use_httpget=FALSE;
3876
4025
  config->create_dirs=FALSE;
3877
4026
  config->lastrecvtime = cutil_tvnow();
3997
4146
      free(config->postfields);
3998
4147
      config->postfields = NULL;
3999
4148
      if(SetHTTPrequest(config,
4000
 
                        (config->conf&CONF_NOBODY?HTTPREQ_HEAD:HTTPREQ_GET),
 
4149
                        (config->no_body?HTTPREQ_HEAD:HTTPREQ_GET),
4001
4150
                        &config->httpreq)) {
4002
4151
        free(httpgetfields);
4003
4152
        return PARAM_BAD_USE;
4036
4185
    /* open file for output: */
4037
4186
    if(strcmp(config->headerfile,"-")) {
4038
4187
      heads.filename = config->headerfile;
4039
 
      headerfilep=NULL;
4040
4188
    }
4041
4189
    else
4042
 
      headerfilep=stdout;
4043
 
    heads.stream = headerfilep;
 
4190
      heads.stream=stdout;
4044
4191
    heads.config = config;
4045
4192
  }
4046
4193
 
4128
4275
      for(i = 0;
4129
4276
          (url = urls?glob_next_url(urls):(i?NULL:strdup(url)));
4130
4277
          i++) {
 
4278
        /* NOTE: In the condition expression in the for() statement above, the
 
4279
           'url' variable is only ever strdup()ed if (i == 0) and thus never
 
4280
           when this loops later on. Further down in this function we call
 
4281
           free(url) and then the code loops. Static code parsers may thus get
 
4282
           tricked into believing that we have a potential access-after-free
 
4283
           here.  I can however not spot any such case. */
 
4284
 
 
4285
        int infd = STDIN_FILENO;
 
4286
        bool infdopen;
4131
4287
        char *outfile;
4132
4288
        struct timeval retrystart;
4133
4289
        outfile = outfiles?strdup(outfiles):NULL;
4164
4320
            {
4165
4321
              /* This is for DOS, and then we do some major replacing of
4166
4322
                 bad characters in the file name before using it */
4167
 
              char file1 [PATH_MAX];
4168
 
 
 
4323
              char file1[PATH_MAX];
 
4324
              if(strlen(outfile) >= PATH_MAX)
 
4325
                outfile[PATH_MAX-1]=0; /* cut it */
4169
4326
              strcpy(file1, msdosify(outfile));
4170
 
              free (outfile);
4171
 
              outfile = strdup (rename_if_dos_device_name(file1));
 
4327
              free(outfile);
 
4328
 
 
4329
              outfile = strdup(rename_if_dos_device_name(file1));
 
4330
              if(!outfile) {
 
4331
                res = CURLE_OUT_OF_MEMORY;
 
4332
                break;
 
4333
              }
4172
4334
            }
4173
4335
#endif /* MSDOS */
4174
4336
          }
4258
4420
            filep = curl_easy_escape(curl, filep, 0 /* use strlen */);
4259
4421
 
4260
4422
            if(filep) {
4261
 
              char *urlbuffer=(char *)malloc(strlen(url) + strlen(filep) + 3);
 
4423
              char *urlbuffer = malloc(strlen(url) + strlen(filep) + 3);
4262
4424
              if(!urlbuffer) {
4263
4425
                helpf(config->errors, "out of memory\n");
4264
4426
                return CURLE_OUT_OF_MEMORY;
4292
4454
           */
4293
4455
 
4294
4456
          infd= open(uploadfile, O_RDONLY | O_BINARY);
4295
 
          if ((infd == -1) || stat(uploadfile, &fileinfo)) {
 
4457
          if ((infd == -1) || fstat(infd, &fileinfo)) {
4296
4458
            helpf(config->errors, "Can't open '%s'!\n", uploadfile);
4297
4459
            if(infd != -1)
4298
4460
              close(infd);
4328
4490
           && outs.stream && isatty(fileno(outs.stream)))
4329
4491
          /* we send the output to a tty, therefore we switch off the progress
4330
4492
             meter */
4331
 
          config->conf |= CONF_NOPROGRESS|CONF_ISATTY;
 
4493
          config->noprogress = config->isatty = TRUE;
4332
4494
 
4333
 
        if (urlnum > 1 && !(config->conf&CONF_MUTE)) {
 
4495
        if (urlnum > 1 && !(config->mute)) {
4334
4496
          fprintf(config->errors, "\n[%d/%d]: %s --> %s\n",
4335
4497
                  i+1, urlnum, url, outfile ? outfile : "<stdout>");
4336
4498
          if (separator)
4359
4521
          /*
4360
4522
           * Then append ? followed by the get fields to the url.
4361
4523
           */
4362
 
          urlbuffer=(char *)malloc(strlen(url) + strlen(httpgetfields) + 3);
 
4524
          urlbuffer = malloc(strlen(url) + strlen(httpgetfields) + 3);
4363
4525
          if(!urlbuffer) {
4364
4526
            helpf(config->errors, "out of memory\n");
4365
4527
            return CURLE_OUT_OF_MEMORY;
4379
4541
        if(!config->errors)
4380
4542
          config->errors = stderr;
4381
4543
 
4382
 
        if(!outfile && !(config->conf & CONF_GETTEXT)) {
 
4544
        if(!outfile && !config->use_ascii) {
4383
4545
          /* We get the output to stdout and we have not got the ASCII/text
4384
4546
             flag, then set stdout to be binary */
4385
4547
          SET_BINMODE(stdout);
4389
4551
          my_setopt(curl, CURLOPT_TCP_NODELAY, 1);
4390
4552
 
4391
4553
        /* where to store */
4392
 
        my_setopt(curl, CURLOPT_WRITEDATA, (FILE *)&outs);
 
4554
        my_setopt(curl, CURLOPT_WRITEDATA, &outs);
4393
4555
        /* what call to write */
4394
4556
        my_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);
4395
4557
 
4414
4576
        my_setopt(curl, CURLOPT_INFILESIZE_LARGE, uploadfilesize);
4415
4577
        my_setopt(curl, CURLOPT_URL, url);     /* what to fetch */
4416
4578
        my_setopt(curl, CURLOPT_PROXY, config->proxy); /* proxy to use */
4417
 
        my_setopt(curl, CURLOPT_NOPROGRESS, config->conf&CONF_NOPROGRESS);
4418
 
        if(config->conf&CONF_NOBODY) {
 
4579
        if(config->proxy)
 
4580
          my_setopt(curl, CURLOPT_PROXYTYPE, config->proxyver);
 
4581
        my_setopt(curl, CURLOPT_NOPROGRESS, config->noprogress);
 
4582
        if(config->no_body) {
4419
4583
          my_setopt(curl, CURLOPT_NOBODY, 1);
4420
4584
          my_setopt(curl, CURLOPT_HEADER, 1);
4421
4585
        }
4422
4586
        else
4423
 
          my_setopt(curl, CURLOPT_HEADER, config->conf&CONF_HEADER);
 
4587
          my_setopt(curl, CURLOPT_HEADER, config->include_headers);
4424
4588
 
4425
 
        my_setopt(curl, CURLOPT_FAILONERROR,
4426
 
                  config->conf&CONF_FAILONERROR);
 
4589
        my_setopt(curl, CURLOPT_FAILONERROR, config->failonerror);
4427
4590
        my_setopt(curl, CURLOPT_UPLOAD, uploadfile?TRUE:FALSE);
4428
 
        my_setopt(curl, CURLOPT_DIRLISTONLY,
4429
 
                  config->conf&CONF_DIRLISTONLY);
4430
 
        my_setopt(curl, CURLOPT_APPEND, config->conf&CONF_FTPAPPEND);
 
4591
        my_setopt(curl, CURLOPT_DIRLISTONLY, config->dirlistonly);
 
4592
        my_setopt(curl, CURLOPT_APPEND, config->ftp_append);
4431
4593
 
4432
 
        if (config->conf&CONF_NETRC_OPT)
 
4594
        if (config->netrc_opt)
4433
4595
          my_setopt(curl, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
4434
 
        else if (config->conf&CONF_NETRC)
 
4596
        else if (config->netrc)
4435
4597
          my_setopt(curl, CURLOPT_NETRC, CURL_NETRC_REQUIRED);
4436
4598
        else
4437
4599
          my_setopt(curl, CURLOPT_NETRC, CURL_NETRC_IGNORED);
4438
4600
 
4439
 
        my_setopt(curl, CURLOPT_FOLLOWLOCATION,
4440
 
                  config->conf&CONF_FOLLOWLOCATION);
4441
 
        my_setopt(curl, CURLOPT_UNRESTRICTED_AUTH,
4442
 
                  config->conf&CONF_UNRESTRICTED_AUTH);
4443
 
        my_setopt(curl, CURLOPT_TRANSFERTEXT, config->conf&CONF_GETTEXT);
 
4601
        my_setopt(curl, CURLOPT_FOLLOWLOCATION, config->followlocation);
 
4602
        my_setopt(curl, CURLOPT_UNRESTRICTED_AUTH, config->unrestricted_auth);
 
4603
        my_setopt(curl, CURLOPT_TRANSFERTEXT, config->use_ascii);
4444
4604
        my_setopt(curl, CURLOPT_USERPWD, config->userpwd);
4445
4605
        my_setopt(curl, CURLOPT_PROXYUSERPWD, config->proxyuserpwd);
 
4606
        my_setopt(curl, CURLOPT_NOPROXY, config->noproxy);
4446
4607
        my_setopt(curl, CURLOPT_RANGE, config->range);
4447
4608
        my_setopt(curl, CURLOPT_ERRORBUFFER, errorbuffer);
4448
4609
        my_setopt(curl, CURLOPT_TIMEOUT, config->timeout);
4459
4620
          break;
4460
4621
        }
4461
4622
        my_setopt(curl, CURLOPT_REFERER, config->referer);
4462
 
        my_setopt(curl, CURLOPT_AUTOREFERER,
4463
 
                  config->conf&CONF_AUTO_REFERER);
 
4623
        my_setopt(curl, CURLOPT_AUTOREFERER, config->autoreferer);
4464
4624
        my_setopt(curl, CURLOPT_USERAGENT, config->useragent);
4465
4625
        my_setopt(curl, CURLOPT_FTPPORT, config->ftpport);
4466
4626
        my_setopt(curl, CURLOPT_LOW_SPEED_LIMIT,
4507
4667
          my_setopt(curl, CURLOPT_SSL_VERIFYHOST, 1);
4508
4668
        }
4509
4669
 
4510
 
        if((config->conf&CONF_NOBODY) ||
4511
 
           config->remote_time) {
 
4670
        if(config->no_body || config->remote_time) {
4512
4671
          /* no body or use remote time */
4513
4672
          my_setopt(curl, CURLOPT_FILETIME, TRUE);
4514
4673
        }
4540
4699
 
4541
4700
        progressbarinit(&progressbar, config);
4542
4701
        if((config->progressmode == CURL_PROGRESS_BAR) &&
4543
 
           !(config->conf&(CONF_NOPROGRESS|CONF_MUTE))) {
 
4702
           !config->noprogress && !config->mute) {
4544
4703
          /* we want the alternative style, then we have to implement it
4545
4704
             ourselves! */
4546
4705
          my_setopt(curl, CURLOPT_PROGRESSFUNCTION, myprogress);
4575
4734
        if(config->authtype)
4576
4735
          my_setopt(curl, CURLOPT_HTTPAUTH, config->authtype);
4577
4736
 
4578
 
        /* new in curl 7.9.7 */
4579
 
        if(config->trace_dump) {
 
4737
        if(config->tracetype != TRACE_NONE) {
4580
4738
          my_setopt(curl, CURLOPT_DEBUGFUNCTION, my_trace);
4581
4739
          my_setopt(curl, CURLOPT_DEBUGDATA, config);
4582
4740
          my_setopt(curl, CURLOPT_VERBOSE, TRUE);
4595
4753
 
4596
4754
        /* new in curl 7.10 */
4597
4755
        my_setopt(curl, CURLOPT_ENCODING,
4598
 
                         (config->encoding) ? "" : NULL);
 
4756
                  (config->encoding) ? "" : NULL);
4599
4757
 
4600
 
        /* new in curl 7.10.7 */
 
4758
        /* new in curl 7.10.7, extended in 7.19.4 but this only sets 0 or 1 */
4601
4759
        my_setopt(curl, CURLOPT_FTP_CREATE_MISSING_DIRS,
4602
 
                         config->ftp_create_dirs);
 
4760
                  config->ftp_create_dirs);
4603
4761
        if(config->proxyanyauth)
4604
4762
          my_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
4605
4763
        else if(config->proxynegotiate)
4645
4803
          my_setopt(curl, CURLOPT_PROXYTYPE, config->socksver);
4646
4804
        }
4647
4805
 
 
4806
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
 
4807
        /* new in curl 7.19.4 */
 
4808
        if(config->socks5_gssapi_service)
 
4809
          my_setopt(curl, CURLOPT_SOCKS5_GSSAPI_SERVICE,
 
4810
                    config->socks5_gssapi_service);
 
4811
 
 
4812
        /* new in curl 7.19.4 */
 
4813
        if(config->socks5_gssapi_nec)
 
4814
          my_setopt(curl, CURLOPT_SOCKS5_GSSAPI_NEC, config->socks5_gssapi_nec);
 
4815
#endif
4648
4816
        /* curl 7.13.0 */
4649
4817
        my_setopt(curl, CURLOPT_FTP_ACCOUNT, config->ftp_account);
4650
4818
 
4678
4846
        }
4679
4847
 
4680
4848
        /* curl 7.17.1 */
4681
 
        my_setopt(curl, CURLOPT_POST301, config->post301);
4682
4849
        if (!config->nokeepalive) {
4683
4850
          my_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockoptcallback);
4684
4851
          my_setopt(curl, CURLOPT_SOCKOPTDATA, config);
4685
4852
        }
4686
4853
 
 
4854
        /* curl 7.19.1 (the 301 version existed in 7.18.2) */
 
4855
        my_setopt(curl, CURLOPT_POSTREDIR, config->post301 |
 
4856
                  (config->post302 ? CURL_REDIR_POST_302 : FALSE));
 
4857
 
4687
4858
        retry_numretries = config->req_retry;
4688
4859
 
4689
4860
        retrystart = cutil_tvnow();
4754
4925
            }
4755
4926
 
4756
4927
            if(retry) {
4757
 
              static const char * const m[]={NULL,
4758
 
                                             "timeout",
4759
 
                                             "HTTP error",
4760
 
                                             "FTP error"
 
4928
              static const char * const m[]={
 
4929
                NULL, "timeout", "HTTP error", "FTP error"
4761
4930
              };
4762
4931
              warnf(config, "Transient problem: %s "
4763
4932
                    "Will retry in %ld seconds. "
4764
4933
                    "%ld retries left.\n",
4765
 
                    m[retry],
4766
 
                    retry_sleep/1000,
4767
 
                    retry_numretries);
 
4934
                    m[retry], retry_sleep/1000, retry_numretries);
4768
4935
 
4769
4936
              go_sleep(retry_sleep);
4770
4937
              retry_numretries--;
4776
4943
              if(outs.bytes && outs.filename) {
4777
4944
                /* We have written data to a output file, we truncate file
4778
4945
                 */
4779
 
                if(!(config->conf&CONF_MUTE))
4780
 
                  fprintf(config->errors, "Throwing away %Od bytes\n", outs.bytes);
 
4946
                if(!config->mute)
 
4947
                  fprintf(config->errors, "Throwing away %Od bytes\n",
 
4948
                          outs.bytes);
4781
4949
                fflush(outs.stream);
4782
4950
                /* truncate file at the position where we started appending */
4783
4951
#ifdef HAVE_FTRUNCATE
4805
4973
        } while(1);
4806
4974
 
4807
4975
        if((config->progressmode == CURL_PROGRESS_BAR) &&
4808
 
           progressbar.calls) {
 
4976
           progressbar.calls)
4809
4977
          /* if the custom progress bar has been displayed, we output a
4810
4978
             newline here */
4811
4979
          fputs("\n", progressbar.out);
4812
 
        }
4813
4980
 
4814
 
        if(config->writeout) {
 
4981
        if(config->writeout)
4815
4982
          ourWriteOut(curl, config->writeout);
4816
 
        }
4817
4983
#ifdef USE_ENVIRONMENT
4818
4984
        if (config->writeenv)
4819
4985
          ourWriteEnv(curl);
4827
4993
        }
4828
4994
#else
4829
4995
        if((res!=CURLE_OK) && config->showerror) {
4830
 
          fprintf(config->errors, "curl: (%d) %s\n", (int)res,
 
4996
          fprintf(config->errors, "curl: (%d) %s\n", res,
4831
4997
                  errorbuffer[0]? errorbuffer:
4832
4998
                  curl_easy_strerror((CURLcode)res));
4833
4999
          if(CURLE_SSL_CACERT == res) {
4834
5000
#define CURL_CA_CERT_ERRORMSG1 \
4835
5001
"More details here: http://curl.haxx.se/docs/sslcerts.html\n\n" \
4836
5002
"curl performs SSL certificate verification by default, using a \"bundle\"\n" \
4837
 
" of Certificate Authority (CA) public keys (CA certs). The default\n" \
4838
 
" bundle is named curl-ca-bundle.crt; you can specify an alternate file\n" \
 
5003
" of Certificate Authority (CA) public keys (CA certs). If the default\n" \
 
5004
" bundle file isn't adequate, you can specify an alternate file\n" \
4839
5005
" using the --cacert option.\n"
4840
5006
 
4841
5007
#define CURL_CA_CERT_ERRORMSG2 \
4881
5047
#endif
4882
5048
 
4883
5049
quit_urls:
4884
 
        if(headerfilep)
4885
 
          fclose(headerfilep);
4886
 
 
4887
5050
        if(url)
4888
5051
          free(url);
4889
5052
 
4942
5105
  if (easycode)
4943
5106
    curl_slist_append(easycode, "curl_easy_cleanup(hnd);");
4944
5107
 
4945
 
  if(config->headerfile && !headerfilep && heads.stream)
 
5108
  if(heads.stream && (heads.stream != stdout))
4946
5109
    fclose(heads.stream);
4947
5110
 
4948
5111
  if(allocuseragent)
4951
5114
  if(config->trace_fopened && config->trace_stream)
4952
5115
    fclose(config->trace_stream);
4953
5116
 
 
5117
  /* Dump the libcurl code if previously enabled.
 
5118
     NOTE: that this function relies on config->errors amongst other things
 
5119
     so not everything can be closed and cleaned before this is called */
 
5120
  dumpeasycode(config);
 
5121
 
4954
5122
  if(config->errors_fopened)
4955
5123
    fclose(config->errors);
4956
5124
 
4957
5125
  main_free(); /* cleanup */
4958
5126
 
4959
 
  dumpeasycode(config);
4960
 
 
4961
5127
  return res;
4962
5128
}
4963
5129
 
5015
5181
#endif
5016
5182
}
5017
5183
 
 
5184
/*
 
5185
 * Reads a line from the given file, ensuring is NUL terminated.
 
5186
 * The pointer must be freed by the caller.
 
5187
 * NULL is returned on an out of memory condition.
 
5188
 */
5018
5189
static char *my_get_line(FILE *fp)
5019
5190
{
5020
5191
   char buf[4096];
5024
5195
   do {
5025
5196
     if (NULL == fgets(buf, sizeof(buf), fp))
5026
5197
       break;
5027
 
     if (NULL == retval)
 
5198
     if (NULL == retval) {
5028
5199
       retval = strdup(buf);
 
5200
       if(!retval)
 
5201
         return NULL;
 
5202
     }
5029
5203
     else {
5030
 
       if (NULL == (retval = realloc(retval,
5031
 
                                     strlen(retval) + strlen(buf) + 1)))
5032
 
         break;
 
5204
       char *ptr;
 
5205
       ptr = realloc(retval, strlen(retval) + strlen(buf) + 1);
 
5206
       if (NULL == ptr) {
 
5207
         free(retval);
 
5208
         return NULL;
 
5209
       }
 
5210
       retval = ptr;
5033
5211
       strcat(retval, buf);
5034
5212
     }
5035
5213
   }
5062
5240
#ifdef ENOSPC
5063
5241
  case ENOSPC:
5064
5242
    fprintf(errors,"No space left on the file system that will "
5065
 
            "contain the directory %s.\n", name);
 
5243
            "contain the directory %s.\n", name);
5066
5244
    break;
5067
5245
#endif
5068
5246
#ifdef EDQUOT
5069
5247
  case EDQUOT:
5070
5248
    fprintf(errors,"Cannot create directory %s because you "
5071
 
            "exceeded your quota.\n", name);
 
5249
            "exceeded your quota.\n", name);
5072
5250
    break;
5073
5251
#endif
5074
5252
  default :
5163
5341
/* The following functions are taken with modification from the DJGPP
5164
5342
 * port of tar 1.12. They use algorithms originally from DJTAR. */
5165
5343
 
5166
 
const char *
 
5344
static const char *
5167
5345
msdosify (const char *file_name)
5168
5346
{
5169
5347
  static char dos_name[PATH_MAX];
5170
 
  static const char illegal_chars_dos[] = ".+, ;=[]|<>\\\":?*";
 
5348
  static const char illegal_chars_dos[] = ".+, ;=[]" /* illegal in DOS */
 
5349
                                       "|<>\\\":?*"; /* illegal in DOS & W95 */
5171
5350
  static const char *illegal_chars_w95 = &illegal_chars_dos[8];
5172
5351
  int idx, dot_idx;
5173
5352
  const char *s = file_name;
5174
5353
  char *d = dos_name;
 
5354
  const char * const dlimit = dos_name + sizeof(dos_name) - 1;
5175
5355
  const char *illegal_aliens = illegal_chars_dos;
5176
5356
  size_t len = sizeof (illegal_chars_dos) - 1;
5177
5357
  int lfn = 0;
5192
5372
    *d++ = *s++;
5193
5373
  }
5194
5374
 
5195
 
  for (idx = 0, dot_idx = -1; *s; s++, d++) {
 
5375
  for (idx = 0, dot_idx = -1; *s && d < dlimit; s++, d++) {
5196
5376
    if (memchr (illegal_aliens, *s, len)) {
5197
5377
      /* Dots are special: DOS doesn't allow them as the leading character,
5198
5378
         and a file name cannot have more than a single dot.  We leave the
5253
5433
  return dos_name;
5254
5434
}
5255
5435
 
5256
 
char *
 
5436
static char *
5257
5437
rename_if_dos_device_name (char *file_name)
5258
5438
{
5259
5439
  /* We could have a file whose name is a device on MS-DOS.  Trying to
5263
5443
  struct stat st_buf;
5264
5444
  char fname[PATH_MAX];
5265
5445
 
5266
 
  strcpy (fname, file_name);
 
5446
  strncpy(fname, file_name, PATH_MAX-1);
 
5447
  fname[PATH_MAX-1] = 0;
5267
5448
  base = basename (fname);
5268
5449
  if (((stat(base, &st_buf)) == 0) && (S_ISCHR(st_buf.st_mode))) {
5269
5450
    size_t blen = strlen (base);
5270
5451
 
 
5452
    if (strlen(fname) >= PATH_MAX-1) {
 
5453
      /* Make room for the '_' */
 
5454
      blen--;
 
5455
      base[blen] = 0;
 
5456
    }
5271
5457
    /* Prepend a '_'.  */
5272
5458
    memmove (base + 1, base, blen + 1);
5273
5459
    base[0] = '_';