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