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