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