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