]> sjero.net Git - wget/blob - src/ftp.c
Eschew config-post.h.
[wget] / src / ftp.c
1 /* File Transfer Protocol support.
2    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
3    2004, 2005, 2006, 2007 Free Software Foundation, Inc.
4
5 This file is part of GNU Wget.
6
7 GNU Wget is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 GNU Wget is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Wget.  If not, see <http://www.gnu.org/licenses/>.
19
20 In addition, as a special exception, the Free Software Foundation
21 gives permission to link the code of its release of Wget with the
22 OpenSSL project's "OpenSSL" library (or with modified versions of it
23 that use the same license as the "OpenSSL" library), and distribute
24 the linked executables.  You must obey the GNU General Public License
25 in all respects for all of the code used other than "OpenSSL".  If you
26 modify this file, you may extend this exception to your version of the
27 file, but you are not obligated to do so.  If you do not wish to do
28 so, delete this exception statement from your version.  */
29
30 #include "wget.h"
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #ifdef HAVE_UNISTD_H
36 # include <unistd.h>
37 #endif
38 #include <assert.h>
39 #include <errno.h>
40 #include <time.h>
41
42 #include "utils.h"
43 #include "url.h"
44 #include "retr.h"
45 #include "ftp.h"
46 #include "connect.h"
47 #include "host.h"
48 #include "netrc.h"
49 #include "convert.h"            /* for downloaded_file */
50 #include "recur.h"              /* for INFINITE_RECURSION */
51
52 /* File where the "ls -al" listing will be saved.  */
53 #ifdef MSDOS
54 #define LIST_FILENAME "_listing"
55 #else
56 #define LIST_FILENAME ".listing"
57 #endif
58
59 typedef struct
60 {
61   int st;                       /* connection status */
62   int cmd;                      /* command code */
63   int csock;                    /* control connection socket */
64   double dltime;                /* time of the download in msecs */
65   enum stype rs;                /* remote system reported by ftp server */ 
66   char *id;                     /* initial directory */
67   char *target;                 /* target file name */
68   struct url *proxy;            /* FTWK-style proxy */
69 } ccon;
70
71
72 /* Look for regexp "( *[0-9]+ *byte" (literal parenthesis) anywhere in
73    the string S, and return the number converted to wgint, if found, 0
74    otherwise.  */
75 static wgint
76 ftp_expected_bytes (const char *s)
77 {
78   wgint res;
79
80   while (1)
81     {
82       while (*s && *s != '(')
83         ++s;
84       if (!*s)
85         return 0;
86       ++s;                      /* skip the '(' */
87       res = str_to_wgint (s, (char **) &s, 10);
88       if (!*s)
89         return 0;
90       while (*s && c_isspace (*s))
91         ++s;
92       if (!*s)
93         return 0;
94       if (c_tolower (*s) != 'b')
95         continue;
96       if (strncasecmp (s, "byte", 4))
97         continue;
98       else
99         break;
100     }
101   return res;
102 }
103
104 #ifdef ENABLE_IPV6
105 /* 
106  * This function sets up a passive data connection with the FTP server.
107  * It is merely a wrapper around ftp_epsv, ftp_lpsv and ftp_pasv.
108  */
109 static uerr_t
110 ftp_do_pasv (int csock, ip_address *addr, int *port)
111 {
112   uerr_t err;
113
114   /* We need to determine the address family and need to call
115      getpeername, so while we're at it, store the address to ADDR.
116      ftp_pasv and ftp_lpsv can simply override it.  */
117   if (!socket_ip_address (csock, addr, ENDPOINT_PEER))
118     abort ();
119
120   /* If our control connection is over IPv6, then we first try EPSV and then 
121    * LPSV if the former is not supported. If the control connection is over 
122    * IPv4, we simply issue the good old PASV request. */
123   switch (addr->family)
124     {
125     case AF_INET:
126       if (!opt.server_response)
127         logputs (LOG_VERBOSE, "==> PASV ... ");
128       err = ftp_pasv (csock, addr, port);
129       break;
130     case AF_INET6:
131       if (!opt.server_response)
132         logputs (LOG_VERBOSE, "==> EPSV ... ");
133       err = ftp_epsv (csock, addr, port);
134
135       /* If EPSV is not supported try LPSV */
136       if (err == FTPNOPASV)
137         {
138           if (!opt.server_response)
139             logputs (LOG_VERBOSE, "==> LPSV ... ");
140           err = ftp_lpsv (csock, addr, port);
141         }
142       break;
143     default:
144       abort ();
145     }
146
147   return err;
148 }
149
150 /* 
151  * This function sets up an active data connection with the FTP server.
152  * It is merely a wrapper around ftp_eprt, ftp_lprt and ftp_port.
153  */
154 static uerr_t
155 ftp_do_port (int csock, int *local_sock)
156 {
157   uerr_t err;
158   ip_address cip;
159
160   if (!socket_ip_address (csock, &cip, ENDPOINT_PEER))
161     abort ();
162
163   /* If our control connection is over IPv6, then we first try EPRT and then 
164    * LPRT if the former is not supported. If the control connection is over 
165    * IPv4, we simply issue the good old PORT request. */
166   switch (cip.family)
167     {
168     case AF_INET:
169       if (!opt.server_response)
170         logputs (LOG_VERBOSE, "==> PORT ... ");
171       err = ftp_port (csock, local_sock);
172       break;
173     case AF_INET6:
174       if (!opt.server_response)
175         logputs (LOG_VERBOSE, "==> EPRT ... ");
176       err = ftp_eprt (csock, local_sock);
177
178       /* If EPRT is not supported try LPRT */
179       if (err == FTPPORTERR)
180         {
181           if (!opt.server_response)
182             logputs (LOG_VERBOSE, "==> LPRT ... ");
183           err = ftp_lprt (csock, local_sock);
184         }
185       break;
186     default:
187       abort ();
188     }
189   return err;
190 }
191 #else
192
193 static uerr_t
194 ftp_do_pasv (int csock, ip_address *addr, int *port)
195 {
196   if (!opt.server_response)
197     logputs (LOG_VERBOSE, "==> PASV ... ");
198   return ftp_pasv (csock, addr, port);
199 }
200
201 static uerr_t
202 ftp_do_port (int csock, int *local_sock)
203 {
204   if (!opt.server_response)
205     logputs (LOG_VERBOSE, "==> PORT ... ");
206   return ftp_port (csock, local_sock);
207 }
208 #endif
209
210 static void
211 print_length (wgint size, wgint start, bool authoritative)
212 {
213   logprintf (LOG_VERBOSE, _("Length: %s"), number_to_static_string (size));
214   if (size >= 1024)
215     logprintf (LOG_VERBOSE, " (%s)", human_readable (size));
216   if (start > 0)
217     {
218       if (start >= 1024)
219         logprintf (LOG_VERBOSE, _(", %s (%s) remaining"),
220                    number_to_static_string (size - start),
221                    human_readable (size - start));
222       else
223         logprintf (LOG_VERBOSE, _(", %s remaining"),
224                    number_to_static_string (size - start));
225     }
226   logputs (LOG_VERBOSE, !authoritative ? _(" (unauthoritative)\n") : "\n");
227 }
228
229 /* Retrieves a file with denoted parameters through opening an FTP
230    connection to the server.  It always closes the data connection,
231    and closes the control connection in case of error.  */
232 static uerr_t
233 getftp (struct url *u, wgint *len, wgint restval, ccon *con)
234 {
235   int csock, dtsock, local_sock, res;
236   uerr_t err = RETROK;          /* appease the compiler */
237   FILE *fp;
238   char *user, *passwd, *respline;
239   char *tms;
240   const char *tmrate;
241   int cmd = con->cmd;
242   bool pasv_mode_open = false;
243   wgint expected_bytes = 0;
244   bool rest_failed = false;
245   int flags;
246   wgint rd_size;
247
248   assert (con != NULL);
249   assert (con->target != NULL);
250
251   /* Debug-check of the sanity of the request by making sure that LIST
252      and RETR are never both requested (since we can handle only one
253      at a time.  */
254   assert (!((cmd & DO_LIST) && (cmd & DO_RETR)));
255   /* Make sure that at least *something* is requested.  */
256   assert ((cmd & (DO_LIST | DO_CWD | DO_RETR | DO_LOGIN)) != 0);
257
258   user = u->user;
259   passwd = u->passwd;
260   search_netrc (u->host, (const char **)&user, (const char **)&passwd, 1);
261   user = user ? user : (opt.ftp_user ? opt.ftp_user : opt.user);
262   if (!user) user = "anonymous";
263   passwd = passwd ? passwd : (opt.ftp_passwd ? opt.ftp_passwd : opt.passwd);
264   if (!passwd) passwd = "-wget@";
265
266   dtsock = -1;
267   local_sock = -1;
268   con->dltime = 0;
269
270   if (!(cmd & DO_LOGIN))
271     csock = con->csock;
272   else                          /* cmd & DO_LOGIN */
273     {
274       char type_char;
275       char    *host = con->proxy ? con->proxy->host : u->host;
276       int      port = con->proxy ? con->proxy->port : u->port;
277       char *logname = user;
278
279       if (con->proxy)
280         {
281           /* If proxy is in use, log in as username@target-site. */
282           logname = concat_strings (user, "@", u->host, (char *) 0);
283         }
284
285       /* Login to the server: */
286
287       /* First: Establish the control connection.  */
288
289       csock = connect_to_host (host, port);
290       if (csock == E_HOST)
291         return HOSTERR;
292       else if (csock < 0)
293         return (retryable_socket_connect_error (errno)
294                 ? CONERROR : CONIMPOSSIBLE);
295
296       if (cmd & LEAVE_PENDING)
297         con->csock = csock;
298       else
299         con->csock = -1;
300
301       /* Second: Login with proper USER/PASS sequence.  */
302       logprintf (LOG_VERBOSE, _("Logging in as %s ... "), escnonprint (user));
303       if (opt.server_response)
304         logputs (LOG_ALWAYS, "\n");
305       err = ftp_login (csock, logname, passwd);
306
307       if (con->proxy)
308         xfree (logname);
309
310       /* FTPRERR, FTPSRVERR, WRITEFAILED, FTPLOGREFUSED, FTPLOGINC */
311       switch (err)
312         {
313         case FTPRERR:
314           logputs (LOG_VERBOSE, "\n");
315           logputs (LOG_NOTQUIET, _("\
316 Error in server response, closing control connection.\n"));
317           fd_close (csock);
318           con->csock = -1;
319           return err;
320         case FTPSRVERR:
321           logputs (LOG_VERBOSE, "\n");
322           logputs (LOG_NOTQUIET, _("Error in server greeting.\n"));
323           fd_close (csock);
324           con->csock = -1;
325           return err;
326         case WRITEFAILED:
327           logputs (LOG_VERBOSE, "\n");
328           logputs (LOG_NOTQUIET,
329                    _("Write failed, closing control connection.\n"));
330           fd_close (csock);
331           con->csock = -1;
332           return err;
333         case FTPLOGREFUSED:
334           logputs (LOG_VERBOSE, "\n");
335           logputs (LOG_NOTQUIET, _("The server refuses login.\n"));
336           fd_close (csock);
337           con->csock = -1;
338           return FTPLOGREFUSED;
339         case FTPLOGINC:
340           logputs (LOG_VERBOSE, "\n");
341           logputs (LOG_NOTQUIET, _("Login incorrect.\n"));
342           fd_close (csock);
343           con->csock = -1;
344           return FTPLOGINC;
345         case FTPOK:
346           if (!opt.server_response)
347             logputs (LOG_VERBOSE, _("Logged in!\n"));
348           break;
349         default:
350           abort ();
351         }
352       /* Third: Get the system type */
353       if (!opt.server_response)
354         logprintf (LOG_VERBOSE, "==> SYST ... ");
355       err = ftp_syst (csock, &con->rs);
356       /* FTPRERR */
357       switch (err)
358         {
359         case FTPRERR:
360           logputs (LOG_VERBOSE, "\n");
361           logputs (LOG_NOTQUIET, _("\
362 Error in server response, closing control connection.\n"));
363           fd_close (csock);
364           con->csock = -1;
365           return err;
366         case FTPSRVERR:
367           logputs (LOG_VERBOSE, "\n");
368           logputs (LOG_NOTQUIET,
369                    _("Server error, can't determine system type.\n"));
370           break;
371         case FTPOK:
372           /* Everything is OK.  */
373           break;
374         default:
375           abort ();
376         }
377       if (!opt.server_response && err != FTPSRVERR)
378         logputs (LOG_VERBOSE, _("done.    "));
379
380       /* Fourth: Find the initial ftp directory */
381
382       if (!opt.server_response)
383         logprintf (LOG_VERBOSE, "==> PWD ... ");
384       err = ftp_pwd (csock, &con->id);
385       /* FTPRERR */
386       switch (err)
387         {
388         case FTPRERR:
389           logputs (LOG_VERBOSE, "\n");
390           logputs (LOG_NOTQUIET, _("\
391 Error in server response, closing control connection.\n"));
392           fd_close (csock);
393           con->csock = -1;
394           return err;
395         case FTPSRVERR :
396           /* PWD unsupported -- assume "/". */
397           xfree_null (con->id);
398           con->id = xstrdup ("/");
399           break;
400         case FTPOK:
401           /* Everything is OK.  */
402           break;
403         default:
404           abort ();
405         }
406       /* VMS will report something like "PUB$DEVICE:[INITIAL.FOLDER]".
407          Convert it to "/INITIAL/FOLDER" */ 
408       if (con->rs == ST_VMS)
409         {
410           char *path = strchr (con->id, '[');
411           char *pathend = path ? strchr (path + 1, ']') : NULL;
412           if (!path || !pathend)
413             DEBUGP (("Initial VMS directory not in the form [...]!\n"));
414           else
415             {
416               char *idir = con->id;
417               DEBUGP (("Preprocessing the initial VMS directory\n"));
418               DEBUGP (("  old = '%s'\n", con->id));
419               /* We do the conversion in-place by copying the stuff
420                  between [ and ] to the beginning, and changing dots
421                  to slashes at the same time.  */
422               *idir++ = '/';
423               for (++path; path < pathend; path++, idir++)
424                 *idir = *path == '.' ? '/' : *path;
425               *idir = '\0';
426               DEBUGP (("  new = '%s'\n\n", con->id));
427             }
428         }
429       if (!opt.server_response)
430         logputs (LOG_VERBOSE, _("done.\n"));
431
432       /* Fifth: Set the FTP type.  */
433       type_char = ftp_process_type (u->params);
434       if (!opt.server_response)
435         logprintf (LOG_VERBOSE, "==> TYPE %c ... ", type_char);
436       err = ftp_type (csock, type_char);
437       /* FTPRERR, WRITEFAILED, FTPUNKNOWNTYPE */
438       switch (err)
439         {
440         case FTPRERR:
441           logputs (LOG_VERBOSE, "\n");
442           logputs (LOG_NOTQUIET, _("\
443 Error in server response, closing control connection.\n"));
444           fd_close (csock);
445           con->csock = -1;
446           return err;
447         case WRITEFAILED:
448           logputs (LOG_VERBOSE, "\n");
449           logputs (LOG_NOTQUIET,
450                    _("Write failed, closing control connection.\n"));
451           fd_close (csock);
452           con->csock = -1;
453           return err;
454         case FTPUNKNOWNTYPE:
455           logputs (LOG_VERBOSE, "\n");
456           logprintf (LOG_NOTQUIET,
457                      _("Unknown type `%c', closing control connection.\n"),
458                      type_char);
459           fd_close (csock);
460           con->csock = -1;
461           return err;
462         case FTPOK:
463           /* Everything is OK.  */
464           break;
465         default:
466           abort ();
467         }
468       if (!opt.server_response)
469         logputs (LOG_VERBOSE, _("done.  "));
470     } /* do login */
471
472   if (cmd & DO_CWD)
473     {
474       if (!*u->dir)
475         logputs (LOG_VERBOSE, _("==> CWD not needed.\n"));
476       else
477         {
478           char *target = u->dir;
479
480           DEBUGP (("changing working directory\n"));
481
482           /* Change working directory.  To change to a non-absolute
483              Unix directory, we need to prepend initial directory
484              (con->id) to it.  Absolute directories "just work".
485
486              A relative directory is one that does not begin with '/'
487              and, on non-Unix OS'es, one that doesn't begin with
488              "[a-z]:".
489
490              This is not done for OS400, which doesn't use
491              "/"-delimited directories, nor does it support directory
492              hierarchies.  "CWD foo" followed by "CWD bar" leaves us
493              in "bar", not in "foo/bar", as would be customary
494              elsewhere.  */
495
496           if (target[0] != '/'
497               && !(con->rs != ST_UNIX
498                    && c_isalpha (target[0])
499                    && target[1] == ':')
500               && con->rs != ST_OS400)
501             {
502               int idlen = strlen (con->id);
503               char *ntarget, *p;
504
505               /* Strip trailing slash(es) from con->id. */
506               while (idlen > 0 && con->id[idlen - 1] == '/')
507                 --idlen;
508               p = ntarget = (char *)alloca (idlen + 1 + strlen (u->dir) + 1);
509               memcpy (p, con->id, idlen);
510               p += idlen;
511               *p++ = '/';
512               strcpy (p, target);
513
514               DEBUGP (("Prepended initial PWD to relative path:\n"));
515               DEBUGP (("   pwd: '%s'\n   old: '%s'\n  new: '%s'\n",
516                        con->id, target, ntarget));
517               target = ntarget;
518             }
519
520           /* If the FTP host runs VMS, we will have to convert the absolute
521              directory path in UNIX notation to absolute directory path in
522              VMS notation as VMS FTP servers do not like UNIX notation of
523              absolute paths.  "VMS notation" is [dir.subdir.subsubdir]. */
524
525           if (con->rs == ST_VMS)
526             {
527               char *tmpp;
528               char *ntarget = (char *)alloca (strlen (target) + 2);
529               /* We use a converted initial dir, so directories in
530                  TARGET will be separated with slashes, something like
531                  "/INITIAL/FOLDER/DIR/SUBDIR".  Convert that to
532                  "[INITIAL.FOLDER.DIR.SUBDIR]".  */
533               strcpy (ntarget, target);
534               assert (*ntarget == '/');
535               *ntarget = '[';
536               for (tmpp = ntarget + 1; *tmpp; tmpp++)
537                 if (*tmpp == '/')
538                   *tmpp = '.';
539               *tmpp++ = ']';
540               *tmpp = '\0';
541               DEBUGP (("Changed file name to VMS syntax:\n"));
542               DEBUGP (("  Unix: '%s'\n  VMS: '%s'\n", target, ntarget));
543               target = ntarget;
544             }
545
546           if (!opt.server_response)
547             logprintf (LOG_VERBOSE, "==> CWD %s ... ", escnonprint (target));
548           err = ftp_cwd (csock, target);
549           /* FTPRERR, WRITEFAILED, FTPNSFOD */
550           switch (err)
551             {
552             case FTPRERR:
553               logputs (LOG_VERBOSE, "\n");
554               logputs (LOG_NOTQUIET, _("\
555 Error in server response, closing control connection.\n"));
556               fd_close (csock);
557               con->csock = -1;
558               return err;
559             case WRITEFAILED:
560               logputs (LOG_VERBOSE, "\n");
561               logputs (LOG_NOTQUIET,
562                        _("Write failed, closing control connection.\n"));
563               fd_close (csock);
564               con->csock = -1;
565               return err;
566             case FTPNSFOD:
567               logputs (LOG_VERBOSE, "\n");
568               logprintf (LOG_NOTQUIET, _("No such directory `%s'.\n\n"),
569                          escnonprint (u->dir));
570               fd_close (csock);
571               con->csock = -1;
572               return err;
573             case FTPOK:
574               break;
575             default:
576               abort ();
577             }
578           if (!opt.server_response)
579             logputs (LOG_VERBOSE, _("done.\n"));
580         }
581     }
582   else /* do not CWD */
583     logputs (LOG_VERBOSE, _("==> CWD not required.\n"));
584
585   if ((cmd & DO_RETR) && *len == 0)
586     {
587       if (opt.verbose)
588         {
589           if (!opt.server_response)
590             logprintf (LOG_VERBOSE, "==> SIZE %s ... ", escnonprint (u->file));
591         }
592
593       err = ftp_size (csock, u->file, len);
594       /* FTPRERR */
595       switch (err)
596         {
597         case FTPRERR:
598         case FTPSRVERR:
599           logputs (LOG_VERBOSE, "\n");
600           logputs (LOG_NOTQUIET, _("\
601 Error in server response, closing control connection.\n"));
602           fd_close (csock);
603           con->csock = -1;
604           return err;
605         case FTPOK:
606           /* Everything is OK.  */
607           break;
608         default:
609           abort ();
610         }
611         if (!opt.server_response)
612           logprintf (LOG_VERBOSE, *len ? "%s\n" : _("done.\n"),
613                      number_to_static_string (*len));
614     }
615
616   /* If anything is to be retrieved, PORT (or PASV) must be sent.  */
617   if (cmd & (DO_LIST | DO_RETR))
618     {
619       if (opt.ftp_pasv)
620         {
621           ip_address passive_addr;
622           int        passive_port;
623           err = ftp_do_pasv (csock, &passive_addr, &passive_port);
624           /* FTPRERR, WRITEFAILED, FTPNOPASV, FTPINVPASV */
625           switch (err)
626             {
627             case FTPRERR:
628               logputs (LOG_VERBOSE, "\n");
629               logputs (LOG_NOTQUIET, _("\
630 Error in server response, closing control connection.\n"));
631               fd_close (csock);
632               con->csock = -1;
633               return err;
634             case WRITEFAILED:
635               logputs (LOG_VERBOSE, "\n");
636               logputs (LOG_NOTQUIET,
637                        _("Write failed, closing control connection.\n"));
638               fd_close (csock);
639               con->csock = -1;
640               return err;
641             case FTPNOPASV:
642               logputs (LOG_VERBOSE, "\n");
643               logputs (LOG_NOTQUIET, _("Cannot initiate PASV transfer.\n"));
644               break;
645             case FTPINVPASV:
646               logputs (LOG_VERBOSE, "\n");
647               logputs (LOG_NOTQUIET, _("Cannot parse PASV response.\n"));
648               break;
649             case FTPOK:
650               break;
651             default:
652               abort ();
653             }   /* switch (err) */
654           if (err==FTPOK)
655             {
656               DEBUGP (("trying to connect to %s port %d\n", 
657                       print_address (&passive_addr), passive_port));
658               dtsock = connect_to_ip (&passive_addr, passive_port, NULL);
659               if (dtsock < 0)
660                 {
661                   int save_errno = errno;
662                   fd_close (csock);
663                   con->csock = -1;
664                   logprintf (LOG_VERBOSE, _("couldn't connect to %s port %d: %s\n"),
665                              print_address (&passive_addr), passive_port,
666                              strerror (save_errno));
667                   return (retryable_socket_connect_error (save_errno)
668                           ? CONERROR : CONIMPOSSIBLE);
669                 }
670
671               pasv_mode_open = true;  /* Flag to avoid accept port */
672               if (!opt.server_response)
673                 logputs (LOG_VERBOSE, _("done.    "));
674             } /* err==FTP_OK */
675         }
676
677       if (!pasv_mode_open)   /* Try to use a port command if PASV failed */
678         {
679           err = ftp_do_port (csock, &local_sock);
680           /* FTPRERR, WRITEFAILED, bindport (FTPSYSERR), HOSTERR,
681              FTPPORTERR */
682           switch (err)
683             {
684             case FTPRERR:
685               logputs (LOG_VERBOSE, "\n");
686               logputs (LOG_NOTQUIET, _("\
687 Error in server response, closing control connection.\n"));
688               fd_close (csock);
689               con->csock = -1;
690               fd_close (dtsock);
691               fd_close (local_sock);
692               return err;
693             case WRITEFAILED:
694               logputs (LOG_VERBOSE, "\n");
695               logputs (LOG_NOTQUIET,
696                        _("Write failed, closing control connection.\n"));
697               fd_close (csock);
698               con->csock = -1;
699               fd_close (dtsock);
700               fd_close (local_sock);
701               return err;
702             case CONSOCKERR:
703               logputs (LOG_VERBOSE, "\n");
704               logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
705               fd_close (csock);
706               con->csock = -1;
707               fd_close (dtsock);
708               fd_close (local_sock);
709               return err;
710             case FTPSYSERR:
711               logputs (LOG_VERBOSE, "\n");
712               logprintf (LOG_NOTQUIET, _("Bind error (%s).\n"),
713                          strerror (errno));
714               fd_close (dtsock);
715               return err;
716             case FTPPORTERR:
717               logputs (LOG_VERBOSE, "\n");
718               logputs (LOG_NOTQUIET, _("Invalid PORT.\n"));
719               fd_close (csock);
720               con->csock = -1;
721               fd_close (dtsock);
722               fd_close (local_sock);
723               return err;
724             case FTPOK:
725               break;
726             default:
727               abort ();
728             } /* port switch */
729           if (!opt.server_response)
730             logputs (LOG_VERBOSE, _("done.    "));
731         } /* dtsock == -1 */
732     } /* cmd & (DO_LIST | DO_RETR) */
733
734   /* Restart if needed.  */
735   if (restval && (cmd & DO_RETR))
736     {
737       if (!opt.server_response)
738         logprintf (LOG_VERBOSE, "==> REST %s ... ",
739                    number_to_static_string (restval));
740       err = ftp_rest (csock, restval);
741
742       /* FTPRERR, WRITEFAILED, FTPRESTFAIL */
743       switch (err)
744         {
745         case FTPRERR:
746           logputs (LOG_VERBOSE, "\n");
747           logputs (LOG_NOTQUIET, _("\
748 Error in server response, closing control connection.\n"));
749           fd_close (csock);
750           con->csock = -1;
751           fd_close (dtsock);
752           fd_close (local_sock);
753           return err;
754         case WRITEFAILED:
755           logputs (LOG_VERBOSE, "\n");
756           logputs (LOG_NOTQUIET,
757                    _("Write failed, closing control connection.\n"));
758           fd_close (csock);
759           con->csock = -1;
760           fd_close (dtsock);
761           fd_close (local_sock);
762           return err;
763         case FTPRESTFAIL:
764           logputs (LOG_VERBOSE, _("\nREST failed, starting from scratch.\n"));
765           rest_failed = true;
766           break;
767         case FTPOK:
768           break;
769         default:
770           abort ();
771         }
772       if (err != FTPRESTFAIL && !opt.server_response)
773         logputs (LOG_VERBOSE, _("done.    "));
774     } /* restval && cmd & DO_RETR */
775
776   if (cmd & DO_RETR)
777     {
778       /* If we're in spider mode, don't really retrieve anything.  The
779          fact that we got to this point should be proof enough that
780          the file exists, vaguely akin to HTTP's concept of a "HEAD"
781          request.  */
782       if (opt.spider)
783         {
784           fd_close (csock);
785           con->csock = -1;
786           fd_close (dtsock);
787           fd_close (local_sock);
788           return RETRFINISHED;
789         }
790
791       if (opt.verbose)
792         {
793           if (!opt.server_response)
794             {
795               if (restval)
796                 logputs (LOG_VERBOSE, "\n");
797               logprintf (LOG_VERBOSE, "==> RETR %s ... ", escnonprint (u->file));
798             }
799         }
800
801       err = ftp_retr (csock, u->file);
802       /* FTPRERR, WRITEFAILED, FTPNSFOD */
803       switch (err)
804         {
805         case FTPRERR:
806           logputs (LOG_VERBOSE, "\n");
807           logputs (LOG_NOTQUIET, _("\
808 Error in server response, closing control connection.\n"));
809           fd_close (csock);
810           con->csock = -1;
811           fd_close (dtsock);
812           fd_close (local_sock);
813           return err;
814         case WRITEFAILED:
815           logputs (LOG_VERBOSE, "\n");
816           logputs (LOG_NOTQUIET,
817                    _("Write failed, closing control connection.\n"));
818           fd_close (csock);
819           con->csock = -1;
820           fd_close (dtsock);
821           fd_close (local_sock);
822           return err;
823         case FTPNSFOD:
824           logputs (LOG_VERBOSE, "\n");
825           logprintf (LOG_NOTQUIET, _("No such file `%s'.\n\n"),
826                      escnonprint (u->file));
827           fd_close (dtsock);
828           fd_close (local_sock);
829           return err;
830         case FTPOK:
831           break;
832         default:
833           abort ();
834         }
835
836       if (!opt.server_response)
837         logputs (LOG_VERBOSE, _("done.\n"));
838       expected_bytes = ftp_expected_bytes (ftp_last_respline);
839     } /* do retrieve */
840
841   if (cmd & DO_LIST)
842     {
843       if (!opt.server_response)
844         logputs (LOG_VERBOSE, "==> LIST ... ");
845       /* As Maciej W. Rozycki (macro@ds2.pg.gda.pl) says, `LIST'
846          without arguments is better than `LIST .'; confirmed by
847          RFC959.  */
848       err = ftp_list (csock, NULL);
849       /* FTPRERR, WRITEFAILED */
850       switch (err)
851         {
852         case FTPRERR:
853           logputs (LOG_VERBOSE, "\n");
854           logputs (LOG_NOTQUIET, _("\
855 Error in server response, closing control connection.\n"));
856           fd_close (csock);
857           con->csock = -1;
858           fd_close (dtsock);
859           fd_close (local_sock);
860           return err;
861         case WRITEFAILED:
862           logputs (LOG_VERBOSE, "\n");
863           logputs (LOG_NOTQUIET,
864                    _("Write failed, closing control connection.\n"));
865           fd_close (csock);
866           con->csock = -1;
867           fd_close (dtsock);
868           fd_close (local_sock);
869           return err;
870         case FTPNSFOD:
871           logputs (LOG_VERBOSE, "\n");
872           logprintf (LOG_NOTQUIET, _("No such file or directory `%s'.\n\n"),
873                      ".");
874           fd_close (dtsock);
875           fd_close (local_sock);
876           return err;
877         case FTPOK:
878           break;
879         default:
880           abort ();
881         }
882       if (!opt.server_response)
883         logputs (LOG_VERBOSE, _("done.\n"));
884       expected_bytes = ftp_expected_bytes (ftp_last_respline);
885     } /* cmd & DO_LIST */
886
887   if (!(cmd & (DO_LIST | DO_RETR)) || (opt.spider && !(cmd & DO_LIST)))
888     return RETRFINISHED;
889
890   /* Some FTP servers return the total length of file after REST
891      command, others just return the remaining size. */
892   if (*len && restval && expected_bytes
893       && (expected_bytes == *len - restval))
894     {
895       DEBUGP (("Lying FTP server found, adjusting.\n"));
896       expected_bytes = *len;
897     }
898
899   /* If no transmission was required, then everything is OK.  */
900   if (!pasv_mode_open)  /* we are not using pasive mode so we need
901                               to accept */
902     {
903       /* Wait for the server to connect to the address we're waiting
904          at.  */
905       dtsock = accept_connection (local_sock);
906       if (dtsock < 0)
907         {
908           logprintf (LOG_NOTQUIET, "accept: %s\n", strerror (errno));
909           return err;
910         }
911     }
912
913   /* Open the file -- if output_stream is set, use it instead.  */
914   if (!output_stream || con->cmd & DO_LIST)
915     {
916       mkalldirs (con->target);
917       if (opt.backups)
918         rotate_backups (con->target);
919
920       if (restval)
921         fp = fopen (con->target, "ab");
922       else if (opt.noclobber || opt.always_rest || opt.timestamping || opt.dirstruct
923                || opt.output_document)
924         fp = fopen (con->target, "wb");
925       else
926         {
927           fp = fopen_excl (con->target, true);
928           if (!fp && errno == EEXIST)
929             {
930               /* We cannot just invent a new name and use it (which is
931                  what functions like unique_create typically do)
932                  because we told the user we'd use this name.
933                  Instead, return and retry the download.  */
934               logprintf (LOG_NOTQUIET, _("%s has sprung into existence.\n"),
935                          con->target);
936               fd_close (csock);
937               con->csock = -1;
938               fd_close (dtsock);
939               fd_close (local_sock);
940               return FOPEN_EXCL_ERR;
941             }
942         }
943       if (!fp)
944         {
945           logprintf (LOG_NOTQUIET, "%s: %s\n", con->target, strerror (errno));
946           fd_close (csock);
947           con->csock = -1;
948           fd_close (dtsock);
949           fd_close (local_sock);
950           return FOPENERR;
951         }
952     }
953   else
954     fp = output_stream;
955
956   if (*len)
957     {
958       print_length (*len, restval, true);
959       expected_bytes = *len;    /* for fd_read_body's progress bar */
960     }
961   else if (expected_bytes)
962     print_length (expected_bytes, restval, false);
963
964   /* Get the contents of the document.  */
965   flags = 0;
966   if (restval && rest_failed)
967     flags |= rb_skip_startpos;
968   *len = restval;
969   rd_size = 0;
970   res = fd_read_body (dtsock, fp,
971                       expected_bytes ? expected_bytes - restval : 0,
972                       restval, &rd_size, len, &con->dltime, flags);
973
974   tms = datetime_str (time (NULL));
975   tmrate = retr_rate (rd_size, con->dltime);
976   total_download_time += con->dltime;
977
978   fd_close (local_sock);
979   /* Close the local file.  */
980   if (!output_stream || con->cmd & DO_LIST)
981     fclose (fp);
982
983   /* If fd_read_body couldn't write to fp, bail out.  */
984   if (res == -2)
985     {
986       logprintf (LOG_NOTQUIET, _("%s: %s, closing control connection.\n"),
987                  con->target, strerror (errno));
988       fd_close (csock);
989       con->csock = -1;
990       fd_close (dtsock);
991       return FWRITEERR;
992     }
993   else if (res == -1)
994     {
995       logprintf (LOG_NOTQUIET, _("%s (%s) - Data connection: %s; "),
996                  tms, tmrate, fd_errstr (dtsock));
997       if (opt.server_response)
998         logputs (LOG_ALWAYS, "\n");
999     }
1000   fd_close (dtsock);
1001
1002   /* Get the server to tell us if everything is retrieved.  */
1003   err = ftp_response (csock, &respline);
1004   if (err != FTPOK)
1005     {
1006       /* The control connection is decidedly closed.  Print the time
1007          only if it hasn't already been printed.  */
1008       if (res != -1)
1009         logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
1010       logputs (LOG_NOTQUIET, _("Control connection closed.\n"));
1011       /* If there is an error on the control connection, close it, but
1012          return FTPRETRINT, since there is a possibility that the
1013          whole file was retrieved nevertheless (but that is for
1014          ftp_loop_internal to decide).  */
1015       fd_close (csock);
1016       con->csock = -1;
1017       return FTPRETRINT;
1018     } /* err != FTPOK */
1019   /* If retrieval failed for any reason, return FTPRETRINT, but do not
1020      close socket, since the control connection is still alive.  If
1021      there is something wrong with the control connection, it will
1022      become apparent later.  */
1023   if (*respline != '2')
1024     {
1025       xfree (respline);
1026       if (res != -1)
1027         logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
1028       logputs (LOG_NOTQUIET, _("Data transfer aborted.\n"));
1029       return FTPRETRINT;
1030     }
1031   xfree (respline);
1032
1033   if (res == -1)
1034     {
1035       /* What now?  The data connection was erroneous, whereas the
1036          response says everything is OK.  We shall play it safe.  */
1037       return FTPRETRINT;
1038     }
1039
1040   if (!(cmd & LEAVE_PENDING))
1041     {
1042       /* Closing the socket is faster than sending 'QUIT' and the
1043          effect is the same.  */
1044       fd_close (csock);
1045       con->csock = -1;
1046     }
1047   /* If it was a listing, and opt.server_response is true,
1048      print it out.  */
1049   if (opt.server_response && (con->cmd & DO_LIST))
1050     {
1051       mkalldirs (con->target);
1052       fp = fopen (con->target, "r");
1053       if (!fp)
1054         logprintf (LOG_ALWAYS, "%s: %s\n", con->target, strerror (errno));
1055       else
1056         {
1057           char *line;
1058           /* The lines are being read with read_whole_line because of
1059              no-buffering on opt.lfile.  */
1060           while ((line = read_whole_line (fp)) != NULL)
1061             {
1062               char *p = strchr (line, '\0');
1063               while (p > line && (p[-1] == '\n' || p[-1] == '\r'))
1064                 *--p = '\0';
1065               logprintf (LOG_ALWAYS, "%s\n", escnonprint (line));
1066               xfree (line);
1067             }
1068           fclose (fp);
1069         }
1070     } /* con->cmd & DO_LIST && server_response */
1071
1072   return RETRFINISHED;
1073 }
1074
1075 /* A one-file FTP loop.  This is the part where FTP retrieval is
1076    retried, and retried, and retried, and...
1077
1078    This loop either gets commands from con, or (if ON_YOUR_OWN is
1079    set), makes them up to retrieve the file given by the URL.  */
1080 static uerr_t
1081 ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
1082 {
1083   int count, orig_lp;
1084   wgint restval, len = 0;
1085   char *tms, *locf;
1086   const char *tmrate = NULL;
1087   uerr_t err;
1088   struct_stat st;
1089
1090   if (!con->target)
1091     con->target = url_file_name (u);
1092
1093   if (opt.noclobber && file_exists_p (con->target))
1094     {
1095       logprintf (LOG_VERBOSE,
1096                  _("File `%s' already there; not retrieving.\n"), con->target);
1097       /* If the file is there, we suppose it's retrieved OK.  */
1098       return RETROK;
1099     }
1100
1101   /* Remove it if it's a link.  */
1102   remove_link (con->target);
1103   if (!opt.output_document)
1104     locf = con->target;
1105   else
1106     locf = opt.output_document;
1107
1108   count = 0;
1109
1110   if (con->st & ON_YOUR_OWN)
1111     con->st = ON_YOUR_OWN;
1112
1113   orig_lp = con->cmd & LEAVE_PENDING ? 1 : 0;
1114
1115   /* THE loop.  */
1116   do
1117     {
1118       /* Increment the pass counter.  */
1119       ++count;
1120       sleep_between_retrievals (count);
1121       if (con->st & ON_YOUR_OWN)
1122         {
1123           con->cmd = 0;
1124           con->cmd |= (DO_RETR | LEAVE_PENDING);
1125           if (con->csock != -1)
1126             con->cmd &= ~ (DO_LOGIN | DO_CWD);
1127           else
1128             con->cmd |= (DO_LOGIN | DO_CWD);
1129         }
1130       else /* not on your own */
1131         {
1132           if (con->csock != -1)
1133             con->cmd &= ~DO_LOGIN;
1134           else
1135             con->cmd |= DO_LOGIN;
1136           if (con->st & DONE_CWD)
1137             con->cmd &= ~DO_CWD;
1138           else
1139             con->cmd |= DO_CWD;
1140         }
1141
1142       /* Decide whether or not to restart.  */
1143       if (opt.always_rest
1144           && stat (locf, &st) == 0
1145           && S_ISREG (st.st_mode))
1146         /* When -c is used, continue from on-disk size.  (Can't use
1147            hstat.len even if count>1 because we don't want a failed
1148            first attempt to clobber existing data.)  */
1149         restval = st.st_size;
1150       else if (count > 1)
1151         restval = len;          /* start where the previous run left off */
1152       else
1153         restval = 0;
1154
1155       /* Get the current time string.  */
1156       tms = datetime_str (time (NULL));
1157       /* Print fetch message, if opt.verbose.  */
1158       if (opt.verbose)
1159         {
1160           char *hurl = url_string (u, URL_AUTH_HIDE_PASSWD);
1161           char tmp[256];
1162           strcpy (tmp, "        ");
1163           if (count > 1)
1164             sprintf (tmp, _("(try:%2d)"), count);
1165           logprintf (LOG_VERBOSE, "--%s--  %s\n  %s => `%s'\n",
1166                      tms, hurl, tmp, locf);
1167 #ifdef WINDOWS
1168           ws_changetitle (hurl);
1169 #endif
1170           xfree (hurl);
1171         }
1172       /* Send getftp the proper length, if fileinfo was provided.  */
1173       if (f)
1174         len = f->size;
1175       else
1176         len = 0;
1177       err = getftp (u, &len, restval, con);
1178
1179       if (con->csock == -1)
1180         con->st &= ~DONE_CWD;
1181       else
1182         con->st |= DONE_CWD;
1183
1184       switch (err)
1185         {
1186         case HOSTERR: case CONIMPOSSIBLE: case FWRITEERR: case FOPENERR:
1187         case FTPNSFOD: case FTPLOGINC: case FTPNOPASV: case CONTNOTSUPPORTED:
1188           /* Fatal errors, give up.  */
1189           return err;
1190         case CONSOCKERR: case CONERROR: case FTPSRVERR: case FTPRERR:
1191         case WRITEFAILED: case FTPUNKNOWNTYPE: case FTPSYSERR:
1192         case FTPPORTERR: case FTPLOGREFUSED: case FTPINVPASV:
1193         case FOPEN_EXCL_ERR:
1194           printwhat (count, opt.ntry);
1195           /* non-fatal errors */
1196           if (err == FOPEN_EXCL_ERR)
1197             {
1198               /* Re-determine the file name. */
1199               xfree_null (con->target);
1200               con->target = url_file_name (u);
1201               locf = con->target;
1202             }
1203           continue;
1204         case FTPRETRINT:
1205           /* If the control connection was closed, the retrieval
1206              will be considered OK if f->size == len.  */
1207           if (!f || len != f->size)
1208             {
1209               printwhat (count, opt.ntry);
1210               continue;
1211             }
1212           break;
1213         case RETRFINISHED:
1214           /* Great!  */
1215           break;
1216         default:
1217           /* Not as great.  */
1218           abort ();
1219         }
1220       tms = datetime_str (time (NULL));
1221       if (!opt.spider)
1222         tmrate = retr_rate (len - restval, con->dltime);
1223
1224       /* If we get out of the switch above without continue'ing, we've
1225          successfully downloaded a file.  Remember this fact. */
1226       downloaded_file (FILE_DOWNLOADED_NORMALLY, locf);
1227
1228       if (con->st & ON_YOUR_OWN)
1229         {
1230           fd_close (con->csock);
1231           con->csock = -1;
1232         }
1233       if (!opt.spider)
1234         logprintf (LOG_VERBOSE, _("%s (%s) - `%s' saved [%s]\n\n"),
1235                    tms, tmrate, locf, number_to_static_string (len));
1236       if (!opt.verbose && !opt.quiet)
1237         {
1238           /* Need to hide the password from the URL.  The `if' is here
1239              so that we don't do the needless allocation every
1240              time. */
1241           char *hurl = url_string (u, URL_AUTH_HIDE_PASSWD);
1242           logprintf (LOG_NONVERBOSE, "%s URL: %s [%s] -> \"%s\" [%d]\n",
1243                      tms, hurl, number_to_static_string (len), locf, count);
1244           xfree (hurl);
1245         }
1246
1247       if ((con->cmd & DO_LIST))
1248         /* This is a directory listing file. */
1249         {
1250           if (!opt.remove_listing)
1251             /* --dont-remove-listing was specified, so do count this towards the
1252                number of bytes and files downloaded. */
1253             {
1254               total_downloaded_bytes += len;
1255               opt.numurls++;
1256             }
1257
1258           /* Deletion of listing files is not controlled by --delete-after, but
1259              by the more specific option --dont-remove-listing, and the code
1260              to do this deletion is in another function. */
1261         }
1262       else if (!opt.spider)
1263         /* This is not a directory listing file. */
1264         {
1265           /* Unlike directory listing files, don't pretend normal files weren't
1266              downloaded if they're going to be deleted.  People seeding proxies,
1267              for instance, may want to know how many bytes and files they've
1268              downloaded through it. */
1269           total_downloaded_bytes += len;
1270           opt.numurls++;
1271
1272           if (opt.delete_after)
1273             {
1274               DEBUGP (("\
1275 Removing file due to --delete-after in ftp_loop_internal():\n"));
1276               logprintf (LOG_VERBOSE, _("Removing %s.\n"), locf);
1277               if (unlink (locf))
1278                 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1279             }
1280         }
1281
1282       /* Restore the original leave-pendingness.  */
1283       if (orig_lp)
1284         con->cmd |= LEAVE_PENDING;
1285       else
1286         con->cmd &= ~LEAVE_PENDING;
1287       return RETROK;
1288     } while (!opt.ntry || (count < opt.ntry));
1289
1290   if (con->csock != -1 && (con->st & ON_YOUR_OWN))
1291     {
1292       fd_close (con->csock);
1293       con->csock = -1;
1294     }
1295   return TRYLIMEXC;
1296 }
1297
1298 /* Return the directory listing in a reusable format.  The directory
1299    is specifed in u->dir.  */
1300 static uerr_t
1301 ftp_get_listing (struct url *u, ccon *con, struct fileinfo **f)
1302 {
1303   uerr_t err;
1304   char *uf;                     /* url file name */
1305   char *lf;                     /* list file name */
1306   char *old_target = con->target;
1307
1308   con->st &= ~ON_YOUR_OWN;
1309   con->cmd |= (DO_LIST | LEAVE_PENDING);
1310   con->cmd &= ~DO_RETR;
1311
1312   /* Find the listing file name.  We do it by taking the file name of
1313      the URL and replacing the last component with the listing file
1314      name.  */
1315   uf = url_file_name (u);
1316   lf = file_merge (uf, LIST_FILENAME);
1317   xfree (uf);
1318   DEBUGP ((_("Using `%s' as listing tmp file.\n"), lf));
1319
1320   con->target = lf;
1321   err = ftp_loop_internal (u, NULL, con);
1322   con->target = old_target;
1323
1324   if (err == RETROK)
1325     *f = ftp_parse_ls (lf, con->rs);
1326   else
1327     *f = NULL;
1328   if (opt.remove_listing)
1329     {
1330       if (unlink (lf))
1331         logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1332       else
1333         logprintf (LOG_VERBOSE, _("Removed `%s'.\n"), lf);
1334     }
1335   xfree (lf);
1336   con->cmd &= ~DO_LIST;
1337   return err;
1338 }
1339
1340 static uerr_t ftp_retrieve_dirs (struct url *, struct fileinfo *, ccon *);
1341 static uerr_t ftp_retrieve_glob (struct url *, ccon *, int);
1342 static struct fileinfo *delelement (struct fileinfo *, struct fileinfo **);
1343 static void freefileinfo (struct fileinfo *f);
1344
1345 /* Retrieve a list of files given in struct fileinfo linked list.  If
1346    a file is a symbolic link, do not retrieve it, but rather try to
1347    set up a similar link on the local disk, if the symlinks are
1348    supported.
1349
1350    If opt.recursive is set, after all files have been retrieved,
1351    ftp_retrieve_dirs will be called to retrieve the directories.  */
1352 static uerr_t
1353 ftp_retrieve_list (struct url *u, struct fileinfo *f, ccon *con)
1354 {
1355   static int depth = 0;
1356   uerr_t err;
1357   struct fileinfo *orig;
1358   wgint local_size;
1359   time_t tml;
1360   bool dlthis;
1361
1362   /* Increase the depth.  */
1363   ++depth;
1364   if (opt.reclevel != INFINITE_RECURSION && depth > opt.reclevel)
1365     {
1366       DEBUGP ((_("Recursion depth %d exceeded max. depth %d.\n"),
1367                depth, opt.reclevel));
1368       --depth;
1369       return RECLEVELEXC;
1370     }
1371
1372   assert (f != NULL);
1373   orig = f;
1374
1375   con->st &= ~ON_YOUR_OWN;
1376   if (!(con->st & DONE_CWD))
1377     con->cmd |= DO_CWD;
1378   else
1379     con->cmd &= ~DO_CWD;
1380   con->cmd |= (DO_RETR | LEAVE_PENDING);
1381
1382   if (con->csock < 0)
1383     con->cmd |= DO_LOGIN;
1384   else
1385     con->cmd &= ~DO_LOGIN;
1386
1387   err = RETROK;                 /* in case it's not used */
1388
1389   while (f)
1390     {
1391       char *old_target, *ofile;
1392
1393       if (opt.quota && total_downloaded_bytes > opt.quota)
1394         {
1395           --depth;
1396           return QUOTEXC;
1397         }
1398       old_target = con->target;
1399
1400       ofile = xstrdup (u->file);
1401       url_set_file (u, f->name);
1402
1403       con->target = url_file_name (u);
1404       err = RETROK;
1405
1406       dlthis = true;
1407       if (opt.timestamping && f->type == FT_PLAINFILE)
1408         {
1409           struct_stat st;
1410           /* If conversion of HTML files retrieved via FTP is ever implemented,
1411              we'll need to stat() <file>.orig here when -K has been specified.
1412              I'm not implementing it now since files on an FTP server are much
1413              more likely than files on an HTTP server to legitimately have a
1414              .orig suffix. */
1415           if (!stat (con->target, &st))
1416             {
1417               bool eq_size;
1418               bool cor_val;
1419               /* Else, get it from the file.  */
1420               local_size = st.st_size;
1421               tml = st.st_mtime;
1422 #ifdef WINDOWS
1423               /* Modification time granularity is 2 seconds for Windows, so
1424                  increase local time by 1 second for later comparison. */
1425               tml++;
1426 #endif
1427               /* Compare file sizes only for servers that tell us correct
1428                  values. Assume sizes being equal for servers that lie
1429                  about file size.  */
1430               cor_val = (con->rs == ST_UNIX || con->rs == ST_WINNT);
1431               eq_size = cor_val ? (local_size == f->size) : true;
1432               if (f->tstamp <= tml && eq_size)
1433                 {
1434                   /* Remote file is older, file sizes can be compared and
1435                      are both equal. */
1436                   logprintf (LOG_VERBOSE, _("\
1437 Remote file no newer than local file `%s' -- not retrieving.\n"), con->target);
1438                   dlthis = false;
1439                 }
1440               else if (eq_size)
1441                 {
1442                   /* Remote file is newer or sizes cannot be matched */
1443                   logprintf (LOG_VERBOSE, _("\
1444 Remote file is newer than local file `%s' -- retrieving.\n\n"),
1445                              con->target);
1446                 }
1447               else
1448                 {
1449                   /* Sizes do not match */
1450                   logprintf (LOG_VERBOSE, _("\
1451 The sizes do not match (local %s) -- retrieving.\n\n"),
1452                              number_to_static_string (local_size));
1453                 }
1454             }
1455         }       /* opt.timestamping && f->type == FT_PLAINFILE */
1456       switch (f->type)
1457         {
1458         case FT_SYMLINK:
1459           /* If opt.retr_symlinks is defined, we treat symlinks as
1460              if they were normal files.  There is currently no way
1461              to distinguish whether they might be directories, and
1462              follow them.  */
1463           if (!opt.retr_symlinks)
1464             {
1465 #ifdef HAVE_SYMLINK
1466               if (!f->linkto)
1467                 logputs (LOG_NOTQUIET,
1468                          _("Invalid name of the symlink, skipping.\n"));
1469               else
1470                 {
1471                   struct_stat st;
1472                   /* Check whether we already have the correct
1473                      symbolic link.  */
1474                   int rc = lstat (con->target, &st);
1475                   if (rc == 0)
1476                     {
1477                       size_t len = strlen (f->linkto) + 1;
1478                       if (S_ISLNK (st.st_mode))
1479                         {
1480                           char *link_target = (char *)alloca (len);
1481                           size_t n = readlink (con->target, link_target, len);
1482                           if ((n == len - 1)
1483                               && (memcmp (link_target, f->linkto, n) == 0))
1484                             {
1485                               logprintf (LOG_VERBOSE, _("\
1486 Already have correct symlink %s -> %s\n\n"),
1487                                          con->target, escnonprint (f->linkto));
1488                               dlthis = false;
1489                               break;
1490                             }
1491                         }
1492                     }
1493                   logprintf (LOG_VERBOSE, _("Creating symlink %s -> %s\n"),
1494                              con->target, escnonprint (f->linkto));
1495                   /* Unlink before creating symlink!  */
1496                   unlink (con->target);
1497                   if (symlink (f->linkto, con->target) == -1)
1498                     logprintf (LOG_NOTQUIET, "symlink: %s\n", strerror (errno));
1499                   logputs (LOG_VERBOSE, "\n");
1500                 } /* have f->linkto */
1501 #else  /* not HAVE_SYMLINK */
1502               logprintf (LOG_NOTQUIET,
1503                          _("Symlinks not supported, skipping symlink `%s'.\n"),
1504                          con->target);
1505 #endif /* not HAVE_SYMLINK */
1506             }
1507           else                /* opt.retr_symlinks */
1508             {
1509               if (dlthis)
1510                 err = ftp_loop_internal (u, f, con);
1511             } /* opt.retr_symlinks */
1512           break;
1513         case FT_DIRECTORY:
1514           if (!opt.recursive)
1515             logprintf (LOG_NOTQUIET, _("Skipping directory `%s'.\n"),
1516                        escnonprint (f->name));
1517           break;
1518         case FT_PLAINFILE:
1519           /* Call the retrieve loop.  */
1520           if (dlthis)
1521             err = ftp_loop_internal (u, f, con);
1522           break;
1523         case FT_UNKNOWN:
1524           logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),
1525                      escnonprint (f->name));
1526           break;
1527         }       /* switch */
1528
1529       /* Set the time-stamp information to the local file.  Symlinks
1530          are not to be stamped because it sets the stamp on the
1531          original.  :( */
1532       if (!(f->type == FT_SYMLINK && !opt.retr_symlinks)
1533           && f->tstamp != -1
1534           && dlthis
1535           && file_exists_p (con->target))
1536         {
1537           /* #### This code repeats in http.c and ftp.c.  Move it to a
1538              function!  */
1539           const char *fl = NULL;
1540           if (opt.output_document)
1541             {
1542               if (output_stream_regular)
1543                 fl = opt.output_document;
1544             }
1545           else
1546             fl = con->target;
1547           if (fl)
1548             touch (fl, f->tstamp);
1549         }
1550       else if (f->tstamp == -1)
1551         logprintf (LOG_NOTQUIET, _("%s: corrupt time-stamp.\n"), con->target);
1552
1553       if (f->perms && f->type == FT_PLAINFILE && dlthis)
1554         {
1555           if (opt.preserve_perm)
1556             chmod (con->target, f->perms);
1557         }
1558       else
1559         DEBUGP (("Unrecognized permissions for %s.\n", con->target));
1560
1561       xfree (con->target);
1562       con->target = old_target;
1563
1564       url_set_file (u, ofile);
1565       xfree (ofile);
1566
1567       /* Break on fatals.  */
1568       if (err == QUOTEXC || err == HOSTERR || err == FWRITEERR)
1569         break;
1570       con->cmd &= ~ (DO_CWD | DO_LOGIN);
1571       f = f->next;
1572     }
1573
1574   /* We do not want to call ftp_retrieve_dirs here */
1575   if (opt.recursive &&
1576       !(opt.reclevel != INFINITE_RECURSION && depth >= opt.reclevel))
1577     err = ftp_retrieve_dirs (u, orig, con);
1578   else if (opt.recursive)
1579     DEBUGP ((_("Will not retrieve dirs since depth is %d (max %d).\n"),
1580              depth, opt.reclevel));
1581   --depth;
1582   return err;
1583 }
1584
1585 /* Retrieve the directories given in a file list.  This function works
1586    by simply going through the linked list and calling
1587    ftp_retrieve_glob on each directory entry.  The function knows
1588    about excluded directories.  */
1589 static uerr_t
1590 ftp_retrieve_dirs (struct url *u, struct fileinfo *f, ccon *con)
1591 {
1592   char *container = NULL;
1593   int container_size = 0;
1594
1595   for (; f; f = f->next)
1596     {
1597       int size;
1598       char *odir, *newdir;
1599
1600       if (opt.quota && total_downloaded_bytes > opt.quota)
1601         break;
1602       if (f->type != FT_DIRECTORY)
1603         continue;
1604
1605       /* Allocate u->dir off stack, but reallocate only if a larger
1606          string is needed.  It's a pity there's no "realloca" for an
1607          item on the bottom of the stack.  */
1608       size = strlen (u->dir) + 1 + strlen (f->name) + 1;
1609       if (size > container_size)
1610         container = (char *)alloca (size);
1611       newdir = container;
1612
1613       odir = u->dir;
1614       if (*odir == '\0'
1615           || (*odir == '/' && *(odir + 1) == '\0'))
1616         /* If ODIR is empty or just "/", simply append f->name to
1617            ODIR.  (In the former case, to preserve u->dir being
1618            relative; in the latter case, to avoid double slash.)  */
1619         sprintf (newdir, "%s%s", odir, f->name);
1620       else
1621         /* Else, use a separator. */
1622         sprintf (newdir, "%s/%s", odir, f->name);
1623
1624       DEBUGP (("Composing new CWD relative to the initial directory.\n"));
1625       DEBUGP (("  odir = '%s'\n  f->name = '%s'\n  newdir = '%s'\n\n",
1626                odir, f->name, newdir));
1627       if (!accdir (newdir))
1628         {
1629           logprintf (LOG_VERBOSE, _("\
1630 Not descending to `%s' as it is excluded/not-included.\n"),
1631                      escnonprint (newdir));
1632           continue;
1633         }
1634
1635       con->st &= ~DONE_CWD;
1636
1637       odir = xstrdup (u->dir);  /* because url_set_dir will free
1638                                    u->dir. */
1639       url_set_dir (u, newdir);
1640       ftp_retrieve_glob (u, con, GLOB_GETALL);
1641       url_set_dir (u, odir);
1642       xfree (odir);
1643
1644       /* Set the time-stamp?  */
1645     }
1646
1647   if (opt.quota && total_downloaded_bytes > opt.quota)
1648     return QUOTEXC;
1649   else
1650     return RETROK;
1651 }
1652
1653 /* Return true if S has a leading '/'  or contains '../' */
1654 static bool
1655 has_insecure_name_p (const char *s)
1656 {
1657   if (*s == '/')
1658     return true;
1659
1660   if (strstr (s, "../") != 0)
1661     return true;
1662
1663   return false;
1664 }
1665
1666 /* A near-top-level function to retrieve the files in a directory.
1667    The function calls ftp_get_listing, to get a linked list of files.
1668    Then it weeds out the file names that do not match the pattern.
1669    ftp_retrieve_list is called with this updated list as an argument.
1670
1671    If the argument ACTION is GLOB_GETONE, just download the file (but
1672    first get the listing, so that the time-stamp is heeded); if it's
1673    GLOB_GLOBALL, use globbing; if it's GLOB_GETALL, download the whole
1674    directory.  */
1675 static uerr_t
1676 ftp_retrieve_glob (struct url *u, ccon *con, int action)
1677 {
1678   struct fileinfo *f, *start;
1679   uerr_t res;
1680
1681   con->cmd |= LEAVE_PENDING;
1682
1683   res = ftp_get_listing (u, con, &start);
1684   if (res != RETROK)
1685     return res;
1686   /* First: weed out that do not conform the global rules given in
1687      opt.accepts and opt.rejects.  */
1688   if (opt.accepts || opt.rejects)
1689     {
1690       f = start;
1691       while (f)
1692         {
1693           if (f->type != FT_DIRECTORY && !acceptable (f->name))
1694             {
1695               logprintf (LOG_VERBOSE, _("Rejecting `%s'.\n"),
1696                          escnonprint (f->name));
1697               f = delelement (f, &start);
1698             }
1699           else
1700             f = f->next;
1701         }
1702     }
1703   /* Remove all files with possible harmful names */
1704   f = start;
1705   while (f)
1706     {
1707       if (has_insecure_name_p (f->name))
1708         {
1709           logprintf (LOG_VERBOSE, _("Rejecting `%s'.\n"),
1710                      escnonprint (f->name));
1711           f = delelement (f, &start);
1712         }
1713       else
1714         f = f->next;
1715     }
1716   /* Now weed out the files that do not match our globbing pattern.
1717      If we are dealing with a globbing pattern, that is.  */
1718   if (*u->file && (action == GLOB_GLOBALL || action == GLOB_GETONE))
1719     {
1720       int (*matcher) (const char *, const char *, int)
1721         = opt.ignore_case ? fnmatch_nocase : fnmatch;
1722       int matchres = 0;
1723
1724       f = start;
1725       while (f)
1726         {
1727           matchres = matcher (u->file, f->name, 0);
1728           if (matchres == -1)
1729             {
1730               logprintf (LOG_NOTQUIET, "%s: %s\n", con->target,
1731                          strerror (errno));
1732               break;
1733             }
1734           if (matchres == FNM_NOMATCH)
1735             f = delelement (f, &start); /* delete the element from the list */
1736           else
1737             f = f->next;        /* leave the element in the list */
1738         }
1739       if (matchres == -1)
1740         {
1741           freefileinfo (start);
1742           return RETRBADPATTERN;
1743         }
1744     }
1745   if (start)
1746     {
1747       /* Just get everything.  */
1748       ftp_retrieve_list (u, start, con);
1749     }
1750   else if (!start)
1751     {
1752       if (action == GLOB_GLOBALL)
1753         {
1754           /* No luck.  */
1755           /* #### This message SUCKS.  We should see what was the
1756              reason that nothing was retrieved.  */
1757           logprintf (LOG_VERBOSE, _("No matches on pattern `%s'.\n"),
1758                      escnonprint (u->file));
1759         }
1760       else /* GLOB_GETONE or GLOB_GETALL */
1761         {
1762           /* Let's try retrieving it anyway.  */
1763           con->st |= ON_YOUR_OWN;
1764           res = ftp_loop_internal (u, NULL, con);
1765           return res;
1766         }
1767     }
1768   freefileinfo (start);
1769   if (opt.quota && total_downloaded_bytes > opt.quota)
1770     return QUOTEXC;
1771   else
1772     /* #### Should we return `res' here?  */
1773     return RETROK;
1774 }
1775
1776 /* The wrapper that calls an appropriate routine according to contents
1777    of URL.  Inherently, its capabilities are limited on what can be
1778    encoded into a URL.  */
1779 uerr_t
1780 ftp_loop (struct url *u, int *dt, struct url *proxy, bool recursive, bool glob)
1781 {
1782   ccon con;                     /* FTP connection */
1783   uerr_t res;
1784
1785   *dt = 0;
1786
1787   xzero (con);
1788
1789   con.csock = -1;
1790   con.st = ON_YOUR_OWN;
1791   con.rs = ST_UNIX;
1792   con.id = NULL;
1793   con.proxy = proxy;
1794
1795   /* If the file name is empty, the user probably wants a directory
1796      index.  We'll provide one, properly HTML-ized.  Unless
1797      opt.htmlify is 0, of course.  :-) */
1798   if (!*u->file && !recursive)
1799     {
1800       struct fileinfo *f;
1801       res = ftp_get_listing (u, &con, &f);
1802
1803       if (res == RETROK)
1804         {
1805           if (opt.htmlify && !opt.spider)
1806             {
1807               char *filename = (opt.output_document
1808                                 ? xstrdup (opt.output_document)
1809                                 : (con.target ? xstrdup (con.target)
1810                                    : url_file_name (u)));
1811               res = ftp_index (filename, u, f);
1812               if (res == FTPOK && opt.verbose)
1813                 {
1814                   if (!opt.output_document)
1815                     {
1816                       struct_stat st;
1817                       wgint sz;
1818                       if (stat (filename, &st) == 0)
1819                         sz = st.st_size;
1820                       else
1821                         sz = -1;
1822                       logprintf (LOG_NOTQUIET,
1823                                  _("Wrote HTML-ized index to `%s' [%s].\n"),
1824                                  filename, number_to_static_string (sz));
1825                     }
1826                   else
1827                     logprintf (LOG_NOTQUIET,
1828                                _("Wrote HTML-ized index to `%s'.\n"),
1829                                filename);
1830                 }
1831               xfree (filename);
1832             }
1833           freefileinfo (f);
1834         }
1835     }
1836   else
1837     {
1838       bool ispattern = false;
1839       if (glob)
1840         {
1841           /* Treat the URL as a pattern if the file name part of the
1842              URL path contains wildcards.  (Don't check for u->file
1843              because it is unescaped and therefore doesn't leave users
1844              the option to escape literal '*' as %2A.)  */
1845           char *file_part = strrchr (u->path, '/');
1846           if (!file_part)
1847             file_part = u->path;
1848           ispattern = has_wildcards_p (file_part);
1849         }
1850       if (ispattern || recursive || opt.timestamping)
1851         {
1852           /* ftp_retrieve_glob is a catch-all function that gets called
1853              if we need globbing, time-stamping or recursion.  Its
1854              third argument is just what we really need.  */
1855           res = ftp_retrieve_glob (u, &con,
1856                                    ispattern ? GLOB_GLOBALL : GLOB_GETONE);
1857         }
1858       else
1859         res = ftp_loop_internal (u, NULL, &con);
1860     }
1861   if (res == FTPOK)
1862     res = RETROK;
1863   if (res == RETROK)
1864     *dt |= RETROKF;
1865   /* If a connection was left, quench it.  */
1866   if (con.csock != -1)
1867     fd_close (con.csock);
1868   xfree_null (con.id);
1869   con.id = NULL;
1870   xfree_null (con.target);
1871   con.target = NULL;
1872   return res;
1873 }
1874
1875 /* Delete an element from the fileinfo linked list.  Returns the
1876    address of the next element, or NULL if the list is exhausted.  It
1877    can modify the start of the list.  */
1878 static struct fileinfo *
1879 delelement (struct fileinfo *f, struct fileinfo **start)
1880 {
1881   struct fileinfo *prev = f->prev;
1882   struct fileinfo *next = f->next;
1883
1884   xfree (f->name);
1885   xfree_null (f->linkto);
1886   xfree (f);
1887
1888   if (next)
1889     next->prev = prev;
1890   if (prev)
1891     prev->next = next;
1892   else
1893     *start = next;
1894   return next;
1895 }
1896
1897 /* Free the fileinfo linked list of files.  */
1898 static void
1899 freefileinfo (struct fileinfo *f)
1900 {
1901   while (f)
1902     {
1903       struct fileinfo *next = f->next;
1904       xfree (f->name);
1905       if (f->linkto)
1906         xfree (f->linkto);
1907       xfree (f);
1908       f = next;
1909     }
1910 }