~ubuntu-branches/ubuntu/trusty/wget/trusty-updates

« back to all changes in this revision

Viewing changes to src/ftp-basic.c

  • Committer: Bazaar Package Importer
  • Author(s): Marc Deslauriers
  • Date: 2009-12-12 08:15:59 UTC
  • mfrom: (2.1.5 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091212081559-mvccl4kzdqb138y3
Tags: 1.12-1.1ubuntu1
* Merge from debian testing, remaining changes:
  - Add wget-udeb to ship wget.gnu as alternative to busybox wget
    implementation.
* Keep build dependencies in main:
  - debian/control: remove info2man build-dep
  - debian/patches/00list: disable wget-infopod_generated_manpage.dpatch

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* Basic FTP routines.
2
 
   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
3
 
   2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
 
2
   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 
3
   2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
4
4
 
5
5
This file is part of GNU Wget.
6
6
 
28
28
shall include the source code for the parts of OpenSSL used as well
29
29
as that of the covered work.  */
30
30
 
31
 
#include <config.h>
 
31
#include "wget.h"
32
32
 
33
33
#include <assert.h>
34
34
#include <stdio.h>
39
39
#ifdef HAVE_UNISTD_H
40
40
# include <unistd.h>
41
41
#endif
42
 
 
43
 
#include "wget.h"
44
42
#include "utils.h"
45
43
#include "connect.h"
46
44
#include "host.h"
70
68
        return FTPRERR;
71
69
 
72
70
      /* Strip trailing CRLF before printing the line, so that
73
 
         escnonprint doesn't include bogus \012 and \015. */
 
71
         quotting doesn't include bogus \012 and \015. */
74
72
      p = strchr (line, '\0');
75
73
      if (p > line && p[-1] == '\n')
76
74
        *--p = '\0';
78
76
        *--p = '\0';
79
77
 
80
78
      if (opt.server_response)
81
 
        logprintf (LOG_NOTQUIET, "%s\n", escnonprint (line));
 
79
        logprintf (LOG_NOTQUIET, "%s\n",
 
80
                   quotearg_style (escape_quoting_style, line));
82
81
      else
83
 
        DEBUGP (("%s\n", escnonprint (line)));
 
82
        DEBUGP (("%s\n", quotearg_style (escape_quoting_style, line)));
84
83
 
85
84
      /* The last line of output is the one that begins with "ddd ". */
86
 
      if (ISDIGIT (line[0]) && ISDIGIT (line[1]) && ISDIGIT (line[2])
 
85
      if (c_isdigit (line[0]) && c_isdigit (line[1]) && c_isdigit (line[2])
87
86
          && line[3] == ' ')
88
87
        {
89
88
          strncpy (ftp_last_respline, line, sizeof (ftp_last_respline));
118
117
            if (*p == '\r' || *p == '\n')
119
118
              *p = ' ';
120
119
          DEBUGP (("\nDetected newlines in %s \"%s\"; changing to %s \"%s\"\n",
121
 
                   command, escnonprint (value), command, escnonprint (defanged)));
 
120
                   command, quotearg_style (escape_quoting_style, value),
 
121
                   command, quotearg_style (escape_quoting_style, defanged)));
122
122
          /* Make VALUE point to the defanged copy of the string. */
123
123
          value = defanged;
124
124
        }
189
189
      "331 s/key ",
190
190
      "331 opiekey "
191
191
    };
192
 
    int i;
 
192
    size_t i;
193
193
    const char *seed = NULL;
194
194
 
195
195
    for (i = 0; i < countof (skey_head); i++)
206
206
        int skey_sequence = 0;
207
207
 
208
208
        /* Extract the sequence from SEED.  */
209
 
        for (; ISDIGIT (*seed); seed++)
 
209
        for (; c_isdigit (*seed); seed++)
210
210
          skey_sequence = 10 * skey_sequence + *seed - '0';
211
211
        if (*seed == ' ')
212
212
          ++seed;
246
246
}
247
247
 
248
248
static void
249
 
ip_address_to_port_repr (const ip_address *addr, int port, char *buf, 
 
249
ip_address_to_port_repr (const ip_address *addr, int port, char *buf,
250
250
                         size_t buflen)
251
251
{
252
252
  unsigned char *ptr;
322
322
 
323
323
#ifdef ENABLE_IPV6
324
324
static void
325
 
ip_address_to_lprt_repr (const ip_address *addr, int port, char *buf, 
 
325
ip_address_to_lprt_repr (const ip_address *addr, int port, char *buf,
326
326
                         size_t buflen)
327
327
{
328
328
  unsigned char *ptr = IP_INADDR_DATA (addr);
331
331
  assert (buflen >= 21 * 4);
332
332
 
333
333
  /* Construct the argument of LPRT (of the form af,n,h1,h2,...,hn,p1,p2). */
334
 
  switch (addr->family) 
 
334
  switch (addr->family)
335
335
    {
336
 
    case AF_INET: 
337
 
      snprintf (buf, buflen, "%d,%d,%d,%d,%d,%d,%d,%d,%d", 4, 4, 
 
336
    case AF_INET:
 
337
      snprintf (buf, buflen, "%d,%d,%d,%d,%d,%d,%d,%d,%d", 4, 4,
338
338
                ptr[0], ptr[1], ptr[2], ptr[3], 2,
339
339
                (port & 0xff00) >> 8, port & 0xff);
340
340
      break;
341
 
    case AF_INET6: 
 
341
    case AF_INET6:
342
342
      snprintf (buf, buflen,
343
343
                "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
344
344
                6, 16,
345
 
                ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7], 
 
345
                ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7],
346
346
                ptr[8], ptr[9], ptr[10], ptr[11], ptr[12], ptr[13], ptr[14], ptr[15],
347
347
                2, (port & 0xff00) >> 8, port & 0xff);
348
348
      break;
410
410
}
411
411
 
412
412
static void
413
 
ip_address_to_eprt_repr (const ip_address *addr, int port, char *buf, 
 
413
ip_address_to_eprt_repr (const ip_address *addr, int port, char *buf,
414
414
                         size_t buflen)
415
415
{
416
416
  int afnum;
417
417
 
418
 
  /* buf must contain the argument of EPRT (of the form |af|addr|port|). 
419
 
   * 4 chars for the | separators, INET6_ADDRSTRLEN chars for addr  
 
418
  /* buf must contain the argument of EPRT (of the form |af|addr|port|).
 
419
   * 4 chars for the | separators, INET6_ADDRSTRLEN chars for addr
420
420
   * 1 char for af (1-2) and 5 chars for port (0-65535) */
421
 
  assert (buflen >= 4 + INET6_ADDRSTRLEN + 1 + 5); 
 
421
  assert (buflen >= 4 + INET6_ADDRSTRLEN + 1 + 5);
422
422
 
423
423
  /* Construct the argument of EPRT (of the form |af|addr|port|). */
424
424
  afnum = (addr->family == AF_INET ? 1 : 2);
437
437
  ip_address addr;
438
438
  int nwritten;
439
439
  int port;
440
 
  /* Must contain the argument of EPRT (of the form |af|addr|port|). 
441
 
   * 4 chars for the | separators, INET6_ADDRSTRLEN chars for addr  
 
440
  /* Must contain the argument of EPRT (of the form |af|addr|port|).
 
441
   * 4 chars for the | separators, INET6_ADDRSTRLEN chars for addr
442
442
   * 1 char for af (1-2) and 5 chars for port (0-65535) */
443
443
  char bytes[4 + INET6_ADDRSTRLEN + 1 + 5 + 1];
444
444
 
522
522
    }
523
523
  /* Parse the request.  */
524
524
  s = respline;
525
 
  for (s += 4; *s && !ISDIGIT (*s); s++)
 
525
  for (s += 4; *s && !c_isdigit (*s); s++)
526
526
    ;
527
527
  if (!*s)
528
528
    return FTPINVPASV;
529
529
  for (i = 0; i < 6; i++)
530
530
    {
531
531
      tmp[i] = 0;
532
 
      for (; ISDIGIT (*s); s++)
 
532
      for (; c_isdigit (*s); s++)
533
533
        tmp[i] = (*s - '0') + 10 * tmp[i];
534
534
      if (*s == ',')
535
535
        s++;
587
587
    {
588
588
      xfree (respline);
589
589
      return FTPNOPASV;
590
 
    }  
 
590
    }
591
591
 
592
592
  /* Parse the response.  */
593
593
  s = respline;
594
 
  for (s += 4; *s && !ISDIGIT (*s); s++)
 
594
  for (s += 4; *s && !c_isdigit (*s); s++)
595
595
    ;
596
596
  if (!*s)
597
597
    return FTPINVPASV;
598
598
 
599
599
  /* First, get the address family */
600
600
  af = 0;
601
 
  for (; ISDIGIT (*s); s++)
 
601
  for (; c_isdigit (*s); s++)
602
602
    af = (*s - '0') + 10 * af;
603
603
 
604
604
  if (af != 4 && af != 6)
615
615
 
616
616
  /* Then, get the address length */
617
617
  addrlen = 0;
618
 
  for (; ISDIGIT (*s); s++)
 
618
  for (; c_isdigit (*s); s++)
619
619
    addrlen = (*s - '0') + 10 * addrlen;
620
620
 
621
621
  if (!*s || *s++ != ',')
641
641
  for (i = 0; i < addrlen; i++)
642
642
    {
643
643
      tmp[i] = 0;
644
 
      for (; ISDIGIT (*s); s++)
 
644
      for (; c_isdigit (*s); s++)
645
645
        tmp[i] = (*s - '0') + 10 * tmp[i];
646
646
      if (*s == ',')
647
647
        s++;
654
654
 
655
655
  /* Now, get the port length */
656
656
  portlen = 0;
657
 
  for (; ISDIGIT (*s); s++)
 
657
  for (; c_isdigit (*s); s++)
658
658
    portlen = (*s - '0') + 10 * portlen;
659
659
 
660
660
  if (!*s || *s++ != ',')
671
671
 
672
672
  /* Finally, we get the port number */
673
673
  tmpprt[0] = 0;
674
 
  for (; ISDIGIT (*s); s++)
 
674
  for (; c_isdigit (*s); s++)
675
675
    tmpprt[0] = (*s - '0') + 10 * tmpprt[0];
676
676
 
677
677
  if (!*s || *s++ != ',')
681
681
    }
682
682
 
683
683
  tmpprt[1] = 0;
684
 
  for (; ISDIGIT (*s); s++)
 
684
  for (; c_isdigit (*s); s++)
685
685
    tmpprt[1] = (*s - '0') + 10 * tmpprt[1];
686
686
 
687
687
  assert (s != NULL);
750
750
    {
751
751
      xfree (respline);
752
752
      return FTPNOPASV;
753
 
    }  
 
753
    }
754
754
 
755
755
  assert (respline != NULL);
756
756
 
765
765
    {
766
766
      xfree (respline);
767
767
      return FTPINVPASV;
768
 
    }  
 
768
    }
769
769
 
770
770
  /* Skip the first two void fields */
771
771
  s = start + 1;
774
774
    {
775
775
      xfree (respline);
776
776
      return FTPINVPASV;
777
 
    }  
 
777
    }
778
778
 
779
779
  for (i = 0; i < 2; i++)
780
780
    {
781
 
      if (*s++ != delim) 
 
781
      if (*s++ != delim)
782
782
        {
783
783
          xfree (respline);
784
784
        return FTPINVPASV;
785
 
        }  
 
785
        }
786
786
    }
787
787
 
788
788
  /* Finally, get the port number */
789
 
  tport = 0; 
790
 
  for (i = 1; ISDIGIT (*s); s++) 
 
789
  tport = 0;
 
790
  for (i = 1; c_isdigit (*s); s++)
791
791
    {
792
792
      if (i > 5)
793
793
        {
794
794
          xfree (respline);
795
795
          return FTPINVPASV;
796
 
        }  
 
796
        }
797
797
      tport = (*s - '0') + 10 * tport;
798
798
    }
799
799
 
802
802
    {
803
803
      xfree (respline);
804
804
      return FTPINVPASV;
805
 
    }  
 
805
    }
806
806
 
807
807
  if (*s++ != ')')
808
808
    {
809
809
      xfree (respline);
810
810
      return FTPINVPASV;
811
 
    }  
 
811
    }
812
812
 
813
813
  *port = tport;
814
814
 
958
958
/* Sends the LIST command to the server.  If FILE is NULL, send just
959
959
   `LIST' (no space).  */
960
960
uerr_t
961
 
ftp_list (int csock, const char *file)
 
961
ftp_list (int csock, const char *file, enum stype rs)
962
962
{
963
963
  char *request, *respline;
964
964
  int nwritten;
965
965
  uerr_t err;
966
966
  bool ok = false;
967
 
  int i = 0;
 
967
  size_t i = 0;
968
968
  /* Try `LIST -a' first and revert to `LIST' in case of failure.  */
969
 
  const char *list_commands[] = { "LIST -a", 
 
969
  const char *list_commands[] = { "LIST -a",
970
970
                                  "LIST" };
971
971
 
 
972
  /* 2008-01-29  SMS.  For a VMS FTP server, where "LIST -a" may not
 
973
     fail, but will never do what is desired here, skip directly to the
 
974
     simple "LIST" command (assumed to be the last one in the list).
 
975
  */
 
976
  if (rs == ST_VMS)
 
977
    i = countof (list_commands)- 1;
 
978
 
972
979
  do {
973
980
    /* Send request.  */
974
981
    request = ftp_request (list_commands[i], file);
992
999
            err = FTPOK;
993
1000
            ok = true;
994
1001
          }
995
 
        else 
 
1002
        else
996
1003
          {
997
1004
            err = FTPRERR;
998
1005
          }
1000
1007
      }
1001
1008
    ++i;
1002
1009
  } while (i < countof (list_commands) && !ok);
1003
 
  
 
1010
 
1004
1011
  return err;
1005
1012
}
1006
1013
 
1135
1142
    }
1136
1143
  if (*respline == '5')
1137
1144
    {
1138
 
      /* 
 
1145
      /*
1139
1146
       * Probably means SIZE isn't supported on this server.
1140
 
       * Error is nonfatal since SIZE isn't in RFC 959 
 
1147
       * Error is nonfatal since SIZE isn't in RFC 959
1141
1148
       */
1142
1149
      xfree (respline);
1143
1150
      *size = 0;
1148
1155
  *size = str_to_wgint (respline + 4, NULL, 10);
1149
1156
  if (errno)
1150
1157
    {
1151
 
      /* 
 
1158
      /*
1152
1159
       * Couldn't parse the response for some reason.  On the (few)
1153
1160
       * tests I've done, the response is 213 <SIZE> with nothing else -
1154
1161
       * maybe something a bit more resilient is necessary.  It's not a
1172
1179
  if (params
1173
1180
      && 0 == strncasecmp (params, "type=", 5)
1174
1181
      && params[5] != '\0')
1175
 
    return TOUPPER (params[5]);
 
1182
    return c_toupper (params[5]);
1176
1183
  else
1177
1184
    return 'I';
1178
1185
}