1 /* File Transfer Protocol support.
2 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
3 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
5 This file is part of GNU Wget.
7 GNU Wget is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
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.
17 You should have received a copy of the GNU General Public License
18 along with Wget. If not, see <http://www.gnu.org/licenses/>.
20 Additional permission under GNU GPL version 3 section 7
22 If you modify this program, or any covered work, by linking or
23 combining it with the OpenSSL project's OpenSSL library (or a
24 modified version of that library), containing parts covered by the
25 terms of the OpenSSL or SSLeay licenses, the Free Software Foundation
26 grants you additional permission to convey the resulting work.
27 Corresponding Source for a non-source form of such a combination
28 shall include the source code for the parts of OpenSSL used as well
29 as that of the covered work. */
50 #include "convert.h" /* for downloaded_file */
51 #include "recur.h" /* for INFINITE_RECURSION */
55 #endif /* def __VMS */
58 /* File where the "ls -al" listing will be saved. */
60 #define LIST_FILENAME "_listing"
62 #define LIST_FILENAME ".listing"
67 int st; /* connection status */
68 int cmd; /* command code */
69 int csock; /* control connection socket */
70 double dltime; /* time of the download in msecs */
71 enum stype rs; /* remote system reported by ftp server */
72 char *id; /* initial directory */
73 char *target; /* target file name */
74 struct url *proxy; /* FTWK-style proxy */
78 /* Look for regexp "( *[0-9]+ *byte" (literal parenthesis) anywhere in
79 the string S, and return the number converted to wgint, if found, 0
82 ftp_expected_bytes (const char *s)
88 while (*s && *s != '(')
92 ++s; /* skip the '(' */
93 res = str_to_wgint (s, (char **) &s, 10);
96 while (*s && c_isspace (*s))
100 if (c_tolower (*s) != 'b')
102 if (strncasecmp (s, "byte", 4))
112 * This function sets up a passive data connection with the FTP server.
113 * It is merely a wrapper around ftp_epsv, ftp_lpsv and ftp_pasv.
116 ftp_do_pasv (int csock, ip_address *addr, int *port)
120 /* We need to determine the address family and need to call
121 getpeername, so while we're at it, store the address to ADDR.
122 ftp_pasv and ftp_lpsv can simply override it. */
123 if (!socket_ip_address (csock, addr, ENDPOINT_PEER))
126 /* If our control connection is over IPv6, then we first try EPSV and then
127 * LPSV if the former is not supported. If the control connection is over
128 * IPv4, we simply issue the good old PASV request. */
129 switch (addr->family)
132 if (!opt.server_response)
133 logputs (LOG_VERBOSE, "==> PASV ... ");
134 err = ftp_pasv (csock, addr, port);
137 if (!opt.server_response)
138 logputs (LOG_VERBOSE, "==> EPSV ... ");
139 err = ftp_epsv (csock, addr, port);
141 /* If EPSV is not supported try LPSV */
142 if (err == FTPNOPASV)
144 if (!opt.server_response)
145 logputs (LOG_VERBOSE, "==> LPSV ... ");
146 err = ftp_lpsv (csock, addr, port);
157 * This function sets up an active data connection with the FTP server.
158 * It is merely a wrapper around ftp_eprt, ftp_lprt and ftp_port.
161 ftp_do_port (int csock, int *local_sock)
166 if (!socket_ip_address (csock, &cip, ENDPOINT_PEER))
169 /* If our control connection is over IPv6, then we first try EPRT and then
170 * LPRT if the former is not supported. If the control connection is over
171 * IPv4, we simply issue the good old PORT request. */
175 if (!opt.server_response)
176 logputs (LOG_VERBOSE, "==> PORT ... ");
177 err = ftp_port (csock, local_sock);
180 if (!opt.server_response)
181 logputs (LOG_VERBOSE, "==> EPRT ... ");
182 err = ftp_eprt (csock, local_sock);
184 /* If EPRT is not supported try LPRT */
185 if (err == FTPPORTERR)
187 if (!opt.server_response)
188 logputs (LOG_VERBOSE, "==> LPRT ... ");
189 err = ftp_lprt (csock, local_sock);
200 ftp_do_pasv (int csock, ip_address *addr, int *port)
202 if (!opt.server_response)
203 logputs (LOG_VERBOSE, "==> PASV ... ");
204 return ftp_pasv (csock, addr, port);
208 ftp_do_port (int csock, int *local_sock)
210 if (!opt.server_response)
211 logputs (LOG_VERBOSE, "==> PORT ... ");
212 return ftp_port (csock, local_sock);
217 print_length (wgint size, wgint start, bool authoritative)
219 logprintf (LOG_VERBOSE, _("Length: %s"), number_to_static_string (size));
221 logprintf (LOG_VERBOSE, " (%s)", human_readable (size));
225 logprintf (LOG_VERBOSE, _(", %s (%s) remaining"),
226 number_to_static_string (size - start),
227 human_readable (size - start));
229 logprintf (LOG_VERBOSE, _(", %s remaining"),
230 number_to_static_string (size - start));
232 logputs (LOG_VERBOSE, !authoritative ? _(" (unauthoritative)\n") : "\n");
235 /* Retrieves a file with denoted parameters through opening an FTP
236 connection to the server. It always closes the data connection,
237 and closes the control connection in case of error. */
239 getftp (struct url *u, wgint *len, wgint restval, ccon *con)
241 int csock, dtsock, local_sock, res;
242 uerr_t err = RETROK; /* appease the compiler */
244 char *user, *passwd, *respline;
248 bool pasv_mode_open = false;
249 wgint expected_bytes = 0;
250 bool rest_failed = false;
255 assert (con != NULL);
256 assert (con->target != NULL);
258 /* Debug-check of the sanity of the request by making sure that LIST
259 and RETR are never both requested (since we can handle only one
261 assert (!((cmd & DO_LIST) && (cmd & DO_RETR)));
262 /* Make sure that at least *something* is requested. */
263 assert ((cmd & (DO_LIST | DO_CWD | DO_RETR | DO_LOGIN)) != 0);
267 search_netrc (u->host, (const char **)&user, (const char **)&passwd, 1);
268 user = user ? user : (opt.ftp_user ? opt.ftp_user : opt.user);
269 if (!user) user = "anonymous";
270 passwd = passwd ? passwd : (opt.ftp_passwd ? opt.ftp_passwd : opt.passwd);
271 if (!passwd) passwd = "-wget@";
277 if (!(cmd & DO_LOGIN))
279 else /* cmd & DO_LOGIN */
281 char *host = con->proxy ? con->proxy->host : u->host;
282 int port = con->proxy ? con->proxy->port : u->port;
283 char *logname = user;
287 /* If proxy is in use, log in as username@target-site. */
288 logname = concat_strings (user, "@", u->host, (char *) 0);
291 /* Login to the server: */
293 /* First: Establish the control connection. */
295 csock = connect_to_host (host, port);
299 return (retryable_socket_connect_error (errno)
300 ? CONERROR : CONIMPOSSIBLE);
302 if (cmd & LEAVE_PENDING)
307 /* Second: Login with proper USER/PASS sequence. */
308 logprintf (LOG_VERBOSE, _("Logging in as %s ... "), escnonprint (user));
309 if (opt.server_response)
310 logputs (LOG_ALWAYS, "\n");
311 err = ftp_login (csock, logname, passwd);
316 /* FTPRERR, FTPSRVERR, WRITEFAILED, FTPLOGREFUSED, FTPLOGINC */
320 logputs (LOG_VERBOSE, "\n");
321 logputs (LOG_NOTQUIET, _("\
322 Error in server response, closing control connection.\n"));
327 logputs (LOG_VERBOSE, "\n");
328 logputs (LOG_NOTQUIET, _("Error in server greeting.\n"));
333 logputs (LOG_VERBOSE, "\n");
334 logputs (LOG_NOTQUIET,
335 _("Write failed, closing control connection.\n"));
340 logputs (LOG_VERBOSE, "\n");
341 logputs (LOG_NOTQUIET, _("The server refuses login.\n"));
344 return FTPLOGREFUSED;
346 logputs (LOG_VERBOSE, "\n");
347 logputs (LOG_NOTQUIET, _("Login incorrect.\n"));
352 if (!opt.server_response)
353 logputs (LOG_VERBOSE, _("Logged in!\n"));
358 /* Third: Get the system type */
359 if (!opt.server_response)
360 logprintf (LOG_VERBOSE, "==> SYST ... ");
361 err = ftp_syst (csock, &con->rs);
366 logputs (LOG_VERBOSE, "\n");
367 logputs (LOG_NOTQUIET, _("\
368 Error in server response, closing control connection.\n"));
373 logputs (LOG_VERBOSE, "\n");
374 logputs (LOG_NOTQUIET,
375 _("Server error, can't determine system type.\n"));
378 /* Everything is OK. */
383 if (!opt.server_response && err != FTPSRVERR)
384 logputs (LOG_VERBOSE, _("done. "));
386 /* Fourth: Find the initial ftp directory */
388 if (!opt.server_response)
389 logprintf (LOG_VERBOSE, "==> PWD ... ");
390 err = ftp_pwd (csock, &con->id);
395 logputs (LOG_VERBOSE, "\n");
396 logputs (LOG_NOTQUIET, _("\
397 Error in server response, closing control connection.\n"));
402 /* PWD unsupported -- assume "/". */
403 xfree_null (con->id);
404 con->id = xstrdup ("/");
407 /* Everything is OK. */
415 Don't help me out. Please.
416 A reasonably recent VMS FTP server will cope just fine with
417 UNIX file specifications. This code just spoils things.
418 Discarding the device name, for example, is not a wise move.
419 This code was disabled but left in as an example of what not
423 /* VMS will report something like "PUB$DEVICE:[INITIAL.FOLDER]".
424 Convert it to "/INITIAL/FOLDER" */
425 if (con->rs == ST_VMS)
427 char *path = strchr (con->id, '[');
428 char *pathend = path ? strchr (path + 1, ']') : NULL;
429 if (!path || !pathend)
430 DEBUGP (("Initial VMS directory not in the form [...]!\n"));
433 char *idir = con->id;
434 DEBUGP (("Preprocessing the initial VMS directory\n"));
435 DEBUGP ((" old = '%s'\n", con->id));
436 /* We do the conversion in-place by copying the stuff
437 between [ and ] to the beginning, and changing dots
438 to slashes at the same time. */
440 for (++path; path < pathend; path++, idir++)
441 *idir = *path == '.' ? '/' : *path;
443 DEBUGP ((" new = '%s'\n\n", con->id));
448 if (!opt.server_response)
449 logputs (LOG_VERBOSE, _("done.\n"));
451 /* Fifth: Set the FTP type. */
452 type_char = ftp_process_type (u->params);
453 if (!opt.server_response)
454 logprintf (LOG_VERBOSE, "==> TYPE %c ... ", type_char);
455 err = ftp_type (csock, type_char);
456 /* FTPRERR, WRITEFAILED, FTPUNKNOWNTYPE */
460 logputs (LOG_VERBOSE, "\n");
461 logputs (LOG_NOTQUIET, _("\
462 Error in server response, closing control connection.\n"));
467 logputs (LOG_VERBOSE, "\n");
468 logputs (LOG_NOTQUIET,
469 _("Write failed, closing control connection.\n"));
474 logputs (LOG_VERBOSE, "\n");
475 logprintf (LOG_NOTQUIET,
476 _("Unknown type `%c', closing control connection.\n"),
482 /* Everything is OK. */
487 if (!opt.server_response)
488 logputs (LOG_VERBOSE, _("done. "));
494 logputs (LOG_VERBOSE, _("==> CWD not needed.\n"));
502 char *target = u->dir;
504 DEBUGP (("changing working directory\n"));
506 /* Change working directory. To change to a non-absolute
507 Unix directory, we need to prepend initial directory
508 (con->id) to it. Absolute directories "just work".
510 A relative directory is one that does not begin with '/'
511 and, on non-Unix OS'es, one that doesn't begin with
514 This is not done for OS400, which doesn't use
515 "/"-delimited directories, nor does it support directory
516 hierarchies. "CWD foo" followed by "CWD bar" leaves us
517 in "bar", not in "foo/bar", as would be customary
521 Why is this wise even on UNIX? It certainly fouls VMS.
522 See below for a more reliable, more universal method.
526 I'm not crazy about it either. I'm informed it's useful
527 for misconfigured servers that have some dirs in the path
528 with +x but -r, but this method is not RFC-conformant. I
529 understand the need to deal with crappy server
530 configurations, but it's far better to use the canonical
531 method first, and fall back to kludges second.
535 && !(con->rs != ST_UNIX
536 && c_isalpha (target[0])
538 && (con->rs != ST_OS400)
539 && (con->rs != ST_VMS))
541 int idlen = strlen (con->id);
544 /* Strip trailing slash(es) from con->id. */
545 while (idlen > 0 && con->id[idlen - 1] == '/')
547 p = ntarget = (char *)alloca (idlen + 1 + strlen (u->dir) + 1);
548 memcpy (p, con->id, idlen);
553 DEBUGP (("Prepended initial PWD to relative path:\n"));
554 DEBUGP ((" pwd: '%s'\n old: '%s'\n new: '%s'\n",
555 con->id, target, ntarget));
561 Don't help me out. Please.
562 A reasonably recent VMS FTP server will cope just fine with
563 UNIX file specifications. This code just spoils things.
564 Discarding the device name, for example, is not a wise
566 This code was disabled but left in as an example of what
570 /* If the FTP host runs VMS, we will have to convert the absolute
571 directory path in UNIX notation to absolute directory path in
572 VMS notation as VMS FTP servers do not like UNIX notation of
573 absolute paths. "VMS notation" is [dir.subdir.subsubdir]. */
575 if (con->rs == ST_VMS)
578 char *ntarget = (char *)alloca (strlen (target) + 2);
579 /* We use a converted initial dir, so directories in
580 TARGET will be separated with slashes, something like
581 "/INITIAL/FOLDER/DIR/SUBDIR". Convert that to
582 "[INITIAL.FOLDER.DIR.SUBDIR]". */
583 strcpy (ntarget, target);
584 assert (*ntarget == '/');
586 for (tmpp = ntarget + 1; *tmpp; tmpp++)
591 DEBUGP (("Changed file name to VMS syntax:\n"));
592 DEBUGP ((" Unix: '%s'\n VMS: '%s'\n", target, ntarget));
598 A relative directory is relative to the initial directory.
599 Thus, what _is_ useful on VMS (and probably elsewhere) is
600 to CWD to the initial directory (ideally, whatever the
601 server reports, _exactly_, NOT badly UNIX-ixed), and then
602 CWD to the (new) relative directory. This should probably
603 be restructured as a function, called once or twice, but
604 I'm lazy enough to take the badly indented loop short-cut
608 /* Decide on one pass (absolute) or two (relative).
609 The VMS restriction may be relaxed when the squirrely code
612 if ((con->rs == ST_VMS) && (target[0] != '/'))
615 DEBUGP (("Using two-step CWD for relative path.\n"));
619 /* Go straight to the target. */
623 /* At least one VMS FTP server (TCPware V5.6-2) can switch to
624 a UNIX emulation mode when given a UNIX-like directory
625 specification (like "a/b/c"). If allowed to continue this
626 way, LIST interpretation will be confused, because the
627 system type (SYST response) will not be re-checked, and
628 future UNIX-format directory listings (for multiple URLs or
629 "-r") will be horribly misinterpreted.
631 The cheap and nasty work-around is to do a "CWD []" after a
632 UNIX-like directory specification is used. (A single-level
633 directory is harmless.) This puts the TCPware server back
634 into VMS mode, and does no harm on other servers.
636 Unlike the rest of this block, this particular behavior
637 _is_ VMS-specific, so it gets its own VMS test.
639 if ((con->rs == ST_VMS) && (strchr( target, '/') != NULL))
642 DEBUGP (("Using extra \"CWD []\" step for VMS server.\n"));
649 /* 2004-09-20 SMS. */
650 /* Sorry about the deviant indenting. Laziness. */
652 for (cwd_count = cwd_start; cwd_count < cwd_end; cwd_count++)
657 /* Step one (optional): Go to the initial directory,
658 exactly as reported by the server.
664 /* Step two: Go to the target directory. (Absolute or
665 relative will work now.)
671 /* Step three (optional): "CWD []" to restore server
682 if (!opt.server_response)
683 logprintf (LOG_VERBOSE, "==> CWD (%d) %s ... ",
684 cwd_count, escnonprint (target));
685 err = ftp_cwd (csock, targ);
686 /* FTPRERR, WRITEFAILED, FTPNSFOD */
690 logputs (LOG_VERBOSE, "\n");
691 logputs (LOG_NOTQUIET, _("\
692 Error in server response, closing control connection.\n"));
697 logputs (LOG_VERBOSE, "\n");
698 logputs (LOG_NOTQUIET,
699 _("Write failed, closing control connection.\n"));
704 logputs (LOG_VERBOSE, "\n");
705 logprintf (LOG_NOTQUIET, _("No such directory `%s'.\n\n"),
706 escnonprint (u->dir));
715 if (!opt.server_response)
716 logputs (LOG_VERBOSE, _("done.\n"));
720 /* 2004-09-20 SMS. */
721 /* End of deviant indenting. */
725 else /* do not CWD */
726 logputs (LOG_VERBOSE, _("==> CWD not required.\n"));
728 if ((cmd & DO_RETR) && *len == 0)
732 if (!opt.server_response)
733 logprintf (LOG_VERBOSE, "==> SIZE %s ... ", escnonprint (u->file));
736 err = ftp_size (csock, u->file, len);
742 logputs (LOG_VERBOSE, "\n");
743 logputs (LOG_NOTQUIET, _("\
744 Error in server response, closing control connection.\n"));
749 /* Everything is OK. */
754 if (!opt.server_response)
755 logprintf (LOG_VERBOSE, *len ? "%s\n" : _("done.\n"),
756 number_to_static_string (*len));
759 /* If anything is to be retrieved, PORT (or PASV) must be sent. */
760 if (cmd & (DO_LIST | DO_RETR))
764 ip_address passive_addr;
766 err = ftp_do_pasv (csock, &passive_addr, &passive_port);
767 /* FTPRERR, WRITEFAILED, FTPNOPASV, FTPINVPASV */
771 logputs (LOG_VERBOSE, "\n");
772 logputs (LOG_NOTQUIET, _("\
773 Error in server response, closing control connection.\n"));
778 logputs (LOG_VERBOSE, "\n");
779 logputs (LOG_NOTQUIET,
780 _("Write failed, closing control connection.\n"));
785 logputs (LOG_VERBOSE, "\n");
786 logputs (LOG_NOTQUIET, _("Cannot initiate PASV transfer.\n"));
789 logputs (LOG_VERBOSE, "\n");
790 logputs (LOG_NOTQUIET, _("Cannot parse PASV response.\n"));
799 DEBUGP (("trying to connect to %s port %d\n",
800 print_address (&passive_addr), passive_port));
801 dtsock = connect_to_ip (&passive_addr, passive_port, NULL);
804 int save_errno = errno;
807 logprintf (LOG_VERBOSE, _("couldn't connect to %s port %d: %s\n"),
808 print_address (&passive_addr), passive_port,
809 strerror (save_errno));
810 return (retryable_socket_connect_error (save_errno)
811 ? CONERROR : CONIMPOSSIBLE);
814 pasv_mode_open = true; /* Flag to avoid accept port */
815 if (!opt.server_response)
816 logputs (LOG_VERBOSE, _("done. "));
820 if (!pasv_mode_open) /* Try to use a port command if PASV failed */
822 err = ftp_do_port (csock, &local_sock);
823 /* FTPRERR, WRITEFAILED, bindport (FTPSYSERR), HOSTERR,
828 logputs (LOG_VERBOSE, "\n");
829 logputs (LOG_NOTQUIET, _("\
830 Error in server response, closing control connection.\n"));
834 fd_close (local_sock);
837 logputs (LOG_VERBOSE, "\n");
838 logputs (LOG_NOTQUIET,
839 _("Write failed, closing control connection.\n"));
843 fd_close (local_sock);
846 logputs (LOG_VERBOSE, "\n");
847 logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
851 fd_close (local_sock);
854 logputs (LOG_VERBOSE, "\n");
855 logprintf (LOG_NOTQUIET, _("Bind error (%s).\n"),
860 logputs (LOG_VERBOSE, "\n");
861 logputs (LOG_NOTQUIET, _("Invalid PORT.\n"));
865 fd_close (local_sock);
872 if (!opt.server_response)
873 logputs (LOG_VERBOSE, _("done. "));
875 } /* cmd & (DO_LIST | DO_RETR) */
877 /* Restart if needed. */
878 if (restval && (cmd & DO_RETR))
880 if (!opt.server_response)
881 logprintf (LOG_VERBOSE, "==> REST %s ... ",
882 number_to_static_string (restval));
883 err = ftp_rest (csock, restval);
885 /* FTPRERR, WRITEFAILED, FTPRESTFAIL */
889 logputs (LOG_VERBOSE, "\n");
890 logputs (LOG_NOTQUIET, _("\
891 Error in server response, closing control connection.\n"));
895 fd_close (local_sock);
898 logputs (LOG_VERBOSE, "\n");
899 logputs (LOG_NOTQUIET,
900 _("Write failed, closing control connection.\n"));
904 fd_close (local_sock);
907 logputs (LOG_VERBOSE, _("\nREST failed, starting from scratch.\n"));
915 if (err != FTPRESTFAIL && !opt.server_response)
916 logputs (LOG_VERBOSE, _("done. "));
917 } /* restval && cmd & DO_RETR */
921 /* If we're in spider mode, don't really retrieve anything. The
922 fact that we got to this point should be proof enough that
923 the file exists, vaguely akin to HTTP's concept of a "HEAD"
930 fd_close (local_sock);
936 if (!opt.server_response)
939 logputs (LOG_VERBOSE, "\n");
940 logprintf (LOG_VERBOSE, "==> RETR %s ... ", escnonprint (u->file));
944 err = ftp_retr (csock, u->file);
945 /* FTPRERR, WRITEFAILED, FTPNSFOD */
949 logputs (LOG_VERBOSE, "\n");
950 logputs (LOG_NOTQUIET, _("\
951 Error in server response, closing control connection.\n"));
955 fd_close (local_sock);
958 logputs (LOG_VERBOSE, "\n");
959 logputs (LOG_NOTQUIET,
960 _("Write failed, closing control connection.\n"));
964 fd_close (local_sock);
967 logputs (LOG_VERBOSE, "\n");
968 logprintf (LOG_NOTQUIET, _("No such file `%s'.\n\n"),
969 escnonprint (u->file));
971 fd_close (local_sock);
974 if (getenv( "FTP_DELETE") != NULL)
976 err = ftp_dele (csock, u->file);
983 if (!opt.server_response)
984 logputs (LOG_VERBOSE, _("done.\n"));
985 expected_bytes = ftp_expected_bytes (ftp_last_respline);
990 if (!opt.server_response)
991 logputs (LOG_VERBOSE, "==> LIST ... ");
992 /* As Maciej W. Rozycki (macro@ds2.pg.gda.pl) says, `LIST'
993 without arguments is better than `LIST .'; confirmed by
995 err = ftp_list (csock, NULL, con->rs);
996 /* FTPRERR, WRITEFAILED */
1000 logputs (LOG_VERBOSE, "\n");
1001 logputs (LOG_NOTQUIET, _("\
1002 Error in server response, closing control connection.\n"));
1006 fd_close (local_sock);
1009 logputs (LOG_VERBOSE, "\n");
1010 logputs (LOG_NOTQUIET,
1011 _("Write failed, closing control connection.\n"));
1015 fd_close (local_sock);
1018 logputs (LOG_VERBOSE, "\n");
1019 logprintf (LOG_NOTQUIET, _("No such file or directory `%s'.\n\n"),
1022 fd_close (local_sock);
1029 if (!opt.server_response)
1030 logputs (LOG_VERBOSE, _("done.\n"));
1031 expected_bytes = ftp_expected_bytes (ftp_last_respline);
1032 } /* cmd & DO_LIST */
1034 if (!(cmd & (DO_LIST | DO_RETR)) || (opt.spider && !(cmd & DO_LIST)))
1035 return RETRFINISHED;
1037 /* Some FTP servers return the total length of file after REST
1038 command, others just return the remaining size. */
1039 if (*len && restval && expected_bytes
1040 && (expected_bytes == *len - restval))
1042 DEBUGP (("Lying FTP server found, adjusting.\n"));
1043 expected_bytes = *len;
1046 /* If no transmission was required, then everything is OK. */
1047 if (!pasv_mode_open) /* we are not using pasive mode so we need
1050 /* Wait for the server to connect to the address we're waiting
1052 dtsock = accept_connection (local_sock);
1055 logprintf (LOG_NOTQUIET, "accept: %s\n", strerror (errno));
1060 /* Open the file -- if output_stream is set, use it instead. */
1063 Note that having the output_stream ("-O") file opened in main()
1064 (main.c) rather limits the ability in VMS to open the file
1065 differently for ASCII versus binary FTP here. (Of course, doing it
1066 there allows a open failure to be detected immediately, without first
1067 connecting to the server.)
1069 if (!output_stream || con->cmd & DO_LIST)
1071 /* On VMS, alter the name as required. */
1075 targ = ods_conform( con->target);
1076 if (targ != con->target)
1078 xfree( con->target);
1081 #endif /* def __VMS */
1083 mkalldirs (con->target);
1085 rotate_backups (con->target);
1088 For VMS, define common fopen() optional arguments, and a handy macro
1089 for use as a variable "binary" flag.
1090 Elsewhere, define a constant "binary" flag.
1091 Isn't it nice to have distinct text and binary file types?
1093 # define BIN_TYPE_TRANSFER (type_char != 'A')
1095 # define FOPEN_OPT_ARGS "fop=sqo", "acc", acc_cb, &open_id
1096 # define FOPEN_OPT_ARGS_BIN "ctx=bin,stm", "rfm=fix", "mrs=512" FOPEN_OPT_ARGS
1097 # define BIN_TYPE_FILE (BIN_TYPE_TRANSFER && (opt.ftp_stmlf == 0))
1098 #else /* def __VMS */
1099 # define BIN_TYPE_FILE 1
1100 #endif /* def __VMS [else] */
1102 if (restval && !(con->cmd & DO_LIST))
1110 fp = fopen (con->target, "ab", FOPEN_OPT_ARGS_BIN);
1115 fp = fopen (con->target, "a", FOPEN_OPT_ARGS);
1117 #else /* def __VMS */
1118 fp = fopen (con->target, "ab");
1119 #endif /* def __VMS [else] */
1121 else if (opt.noclobber || opt.always_rest || opt.timestamping || opt.dirstruct
1122 || opt.output_document)
1130 fp = fopen (con->target, "wb", FOPEN_OPT_ARGS_BIN);
1135 fp = fopen (con->target, "w", FOPEN_OPT_ARGS);
1137 #else /* def __VMS */
1138 fp = fopen (con->target, "wb");
1139 #endif /* def __VMS [else] */
1143 fp = fopen_excl (con->target, true);
1144 if (!fp && errno == EEXIST)
1146 /* We cannot just invent a new name and use it (which is
1147 what functions like unique_create typically do)
1148 because we told the user we'd use this name.
1149 Instead, return and retry the download. */
1150 logprintf (LOG_NOTQUIET, _("%s has sprung into existence.\n"),
1155 fd_close (local_sock);
1156 return FOPEN_EXCL_ERR;
1161 logprintf (LOG_NOTQUIET, "%s: %s\n", con->target, strerror (errno));
1165 fd_close (local_sock);
1174 print_length (*len, restval, true);
1175 expected_bytes = *len; /* for fd_read_body's progress bar */
1177 else if (expected_bytes)
1178 print_length (expected_bytes, restval, false);
1180 /* Get the contents of the document. */
1182 if (restval && rest_failed)
1183 flags |= rb_skip_startpos;
1186 res = fd_read_body (dtsock, fp,
1187 expected_bytes ? expected_bytes - restval : 0,
1188 restval, &rd_size, len, &con->dltime, flags);
1190 tms = datetime_str (time (NULL));
1191 tmrate = retr_rate (rd_size, con->dltime);
1192 total_download_time += con->dltime;
1194 fd_close (local_sock);
1195 /* Close the local file. */
1196 if (!output_stream || con->cmd & DO_LIST)
1199 /* If fd_read_body couldn't write to fp, bail out. */
1202 logprintf (LOG_NOTQUIET, _("%s: %s, closing control connection.\n"),
1203 con->target, strerror (errno));
1211 logprintf (LOG_NOTQUIET, _("%s (%s) - Data connection: %s; "),
1212 tms, tmrate, fd_errstr (dtsock));
1213 if (opt.server_response)
1214 logputs (LOG_ALWAYS, "\n");
1218 /* Get the server to tell us if everything is retrieved. */
1219 err = ftp_response (csock, &respline);
1222 /* The control connection is decidedly closed. Print the time
1223 only if it hasn't already been printed. */
1225 logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
1226 logputs (LOG_NOTQUIET, _("Control connection closed.\n"));
1227 /* If there is an error on the control connection, close it, but
1228 return FTPRETRINT, since there is a possibility that the
1229 whole file was retrieved nevertheless (but that is for
1230 ftp_loop_internal to decide). */
1234 } /* err != FTPOK */
1235 /* If retrieval failed for any reason, return FTPRETRINT, but do not
1236 close socket, since the control connection is still alive. If
1237 there is something wrong with the control connection, it will
1238 become apparent later. */
1239 if (*respline != '2')
1243 logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
1244 logputs (LOG_NOTQUIET, _("Data transfer aborted.\n"));
1251 /* What now? The data connection was erroneous, whereas the
1252 response says everything is OK. We shall play it safe. */
1256 if (!(cmd & LEAVE_PENDING))
1258 /* Closing the socket is faster than sending 'QUIT' and the
1259 effect is the same. */
1263 /* If it was a listing, and opt.server_response is true,
1265 if (opt.server_response && (con->cmd & DO_LIST))
1268 Much of this work may already have been done, but repeating it should
1269 do no damage beyond wasting time.
1271 /* On VMS, alter the name as required. */
1275 targ = ods_conform( con->target);
1276 if (targ != con->target)
1278 xfree( con->target);
1281 #endif /* def __VMS */
1283 mkalldirs (con->target);
1284 fp = fopen (con->target, "r");
1286 logprintf (LOG_ALWAYS, "%s: %s\n", con->target, strerror (errno));
1290 /* The lines are being read with read_whole_line because of
1291 no-buffering on opt.lfile. */
1292 while ((line = read_whole_line (fp)) != NULL)
1294 char *p = strchr (line, '\0');
1295 while (p > line && (p[-1] == '\n' || p[-1] == '\r'))
1297 logprintf (LOG_ALWAYS, "%s\n", escnonprint (line));
1302 } /* con->cmd & DO_LIST && server_response */
1304 return RETRFINISHED;
1307 /* A one-file FTP loop. This is the part where FTP retrieval is
1308 retried, and retried, and retried, and...
1310 This loop either gets commands from con, or (if ON_YOUR_OWN is
1311 set), makes them up to retrieve the file given by the URL. */
1313 ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
1316 wgint restval, len = 0;
1318 const char *tmrate = NULL;
1322 /* Get the target, and set the name for the message accordingly. */
1323 if ((f == NULL) && (con->target))
1325 /* Explicit file (like ".listing"). */
1330 /* URL-derived file. Consider "-O file" name. */
1331 con->target = url_file_name (u);
1332 if (!opt.output_document)
1335 locf = opt.output_document;
1338 if (opt.noclobber && file_exists_p (con->target))
1340 logprintf (LOG_VERBOSE,
1341 _("File `%s' already there; not retrieving.\n"), con->target);
1342 /* If the file is there, we suppose it's retrieved OK. */
1346 /* Remove it if it's a link. */
1347 remove_link (con->target);
1351 if (con->st & ON_YOUR_OWN)
1352 con->st = ON_YOUR_OWN;
1354 orig_lp = con->cmd & LEAVE_PENDING ? 1 : 0;
1359 /* Increment the pass counter. */
1361 sleep_between_retrievals (count);
1362 if (con->st & ON_YOUR_OWN)
1365 con->cmd |= (DO_RETR | LEAVE_PENDING);
1366 if (con->csock != -1)
1367 con->cmd &= ~ (DO_LOGIN | DO_CWD);
1369 con->cmd |= (DO_LOGIN | DO_CWD);
1371 else /* not on your own */
1373 if (con->csock != -1)
1374 con->cmd &= ~DO_LOGIN;
1376 con->cmd |= DO_LOGIN;
1377 if (con->st & DONE_CWD)
1378 con->cmd &= ~DO_CWD;
1383 /* Decide whether or not to restart. */
1384 if (con->cmd & DO_LIST)
1386 else if (opt.always_rest
1387 && stat (locf, &st) == 0
1388 && S_ISREG (st.st_mode))
1389 /* When -c is used, continue from on-disk size. (Can't use
1390 hstat.len even if count>1 because we don't want a failed
1391 first attempt to clobber existing data.) */
1392 restval = st.st_size;
1394 restval = len; /* start where the previous run left off */
1398 /* Get the current time string. */
1399 tms = datetime_str (time (NULL));
1400 /* Print fetch message, if opt.verbose. */
1403 char *hurl = url_string (u, URL_AUTH_HIDE_PASSWD);
1407 sprintf (tmp, _("(try:%2d)"), count);
1408 logprintf (LOG_VERBOSE, "--%s-- %s\n %s => `%s'\n",
1409 tms, hurl, tmp, locf);
1411 ws_changetitle (hurl);
1415 /* Send getftp the proper length, if fileinfo was provided. */
1420 err = getftp (u, &len, restval, con);
1422 if (con->csock == -1)
1423 con->st &= ~DONE_CWD;
1425 con->st |= DONE_CWD;
1429 case HOSTERR: case CONIMPOSSIBLE: case FWRITEERR: case FOPENERR:
1430 case FTPNSFOD: case FTPLOGINC: case FTPNOPASV: case CONTNOTSUPPORTED:
1431 /* Fatal errors, give up. */
1433 case CONSOCKERR: case CONERROR: case FTPSRVERR: case FTPRERR:
1434 case WRITEFAILED: case FTPUNKNOWNTYPE: case FTPSYSERR:
1435 case FTPPORTERR: case FTPLOGREFUSED: case FTPINVPASV:
1436 case FOPEN_EXCL_ERR:
1437 printwhat (count, opt.ntry);
1438 /* non-fatal errors */
1439 if (err == FOPEN_EXCL_ERR)
1441 /* Re-determine the file name. */
1442 xfree_null (con->target);
1443 con->target = url_file_name (u);
1448 /* If the control connection was closed, the retrieval
1449 will be considered OK if f->size == len. */
1450 if (!f || len != f->size)
1452 printwhat (count, opt.ntry);
1463 tms = datetime_str (time (NULL));
1465 tmrate = retr_rate (len - restval, con->dltime);
1467 /* If we get out of the switch above without continue'ing, we've
1468 successfully downloaded a file. Remember this fact. */
1469 downloaded_file (FILE_DOWNLOADED_NORMALLY, locf);
1471 if (con->st & ON_YOUR_OWN)
1473 fd_close (con->csock);
1477 logprintf (LOG_VERBOSE, _("%s (%s) - `%s' saved [%s]\n\n"),
1478 tms, tmrate, locf, number_to_static_string (len));
1479 if (!opt.verbose && !opt.quiet)
1481 /* Need to hide the password from the URL. The `if' is here
1482 so that we don't do the needless allocation every
1484 char *hurl = url_string (u, URL_AUTH_HIDE_PASSWD);
1485 logprintf (LOG_NONVERBOSE, "%s URL: %s [%s] -> \"%s\" [%d]\n",
1486 tms, hurl, number_to_static_string (len), locf, count);
1490 if ((con->cmd & DO_LIST))
1491 /* This is a directory listing file. */
1493 if (!opt.remove_listing)
1494 /* --dont-remove-listing was specified, so do count this towards the
1495 number of bytes and files downloaded. */
1497 total_downloaded_bytes += len;
1501 /* Deletion of listing files is not controlled by --delete-after, but
1502 by the more specific option --dont-remove-listing, and the code
1503 to do this deletion is in another function. */
1505 else if (!opt.spider)
1506 /* This is not a directory listing file. */
1508 /* Unlike directory listing files, don't pretend normal files weren't
1509 downloaded if they're going to be deleted. People seeding proxies,
1510 for instance, may want to know how many bytes and files they've
1511 downloaded through it. */
1512 total_downloaded_bytes += len;
1515 if (opt.delete_after)
1518 Removing file due to --delete-after in ftp_loop_internal():\n"));
1519 logprintf (LOG_VERBOSE, _("Removing %s.\n"), locf);
1521 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1525 /* Restore the original leave-pendingness. */
1527 con->cmd |= LEAVE_PENDING;
1529 con->cmd &= ~LEAVE_PENDING;
1531 } while (!opt.ntry || (count < opt.ntry));
1533 if (con->csock != -1 && (con->st & ON_YOUR_OWN))
1535 fd_close (con->csock);
1541 /* Return the directory listing in a reusable format. The directory
1542 is specifed in u->dir. */
1544 ftp_get_listing (struct url *u, ccon *con, struct fileinfo **f)
1547 char *uf; /* url file name */
1548 char *lf; /* list file name */
1549 char *old_target = con->target;
1551 con->st &= ~ON_YOUR_OWN;
1552 con->cmd |= (DO_LIST | LEAVE_PENDING);
1553 con->cmd &= ~DO_RETR;
1555 /* Find the listing file name. We do it by taking the file name of
1556 the URL and replacing the last component with the listing file
1558 uf = url_file_name (u);
1559 lf = file_merge (uf, LIST_FILENAME);
1561 DEBUGP ((_("Using `%s' as listing tmp file.\n"), lf));
1564 err = ftp_loop_internal (u, NULL, con);
1565 con->target = old_target;
1568 *f = ftp_parse_ls (lf, con->rs);
1571 if (opt.remove_listing)
1574 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1576 logprintf (LOG_VERBOSE, _("Removed `%s'.\n"), lf);
1579 con->cmd &= ~DO_LIST;
1583 static uerr_t ftp_retrieve_dirs (struct url *, struct fileinfo *, ccon *);
1584 static uerr_t ftp_retrieve_glob (struct url *, ccon *, int);
1585 static struct fileinfo *delelement (struct fileinfo *, struct fileinfo **);
1586 static void freefileinfo (struct fileinfo *f);
1588 /* Retrieve a list of files given in struct fileinfo linked list. If
1589 a file is a symbolic link, do not retrieve it, but rather try to
1590 set up a similar link on the local disk, if the symlinks are
1593 If opt.recursive is set, after all files have been retrieved,
1594 ftp_retrieve_dirs will be called to retrieve the directories. */
1596 ftp_retrieve_list (struct url *u, struct fileinfo *f, ccon *con)
1598 static int depth = 0;
1600 struct fileinfo *orig;
1603 bool dlthis; /* Download this (file). */
1604 const char *actual_target = NULL;
1606 /* Increase the depth. */
1608 if (opt.reclevel != INFINITE_RECURSION && depth > opt.reclevel)
1610 DEBUGP ((_("Recursion depth %d exceeded max. depth %d.\n"),
1611 depth, opt.reclevel));
1619 con->st &= ~ON_YOUR_OWN;
1620 if (!(con->st & DONE_CWD))
1623 con->cmd &= ~DO_CWD;
1624 con->cmd |= (DO_RETR | LEAVE_PENDING);
1627 con->cmd |= DO_LOGIN;
1629 con->cmd &= ~DO_LOGIN;
1631 err = RETROK; /* in case it's not used */
1635 char *old_target, *ofile;
1637 if (opt.quota && total_downloaded_bytes > opt.quota)
1642 old_target = con->target;
1644 ofile = xstrdup (u->file);
1645 url_set_file (u, f->name);
1647 con->target = url_file_name (u);
1651 if (opt.timestamping && f->type == FT_PLAINFILE)
1654 /* If conversion of HTML files retrieved via FTP is ever implemented,
1655 we'll need to stat() <file>.orig here when -K has been specified.
1656 I'm not implementing it now since files on an FTP server are much
1657 more likely than files on an HTTP server to legitimately have a
1659 if (!stat (con->target, &st))
1663 /* Else, get it from the file. */
1664 local_size = st.st_size;
1667 /* Modification time granularity is 2 seconds for Windows, so
1668 increase local time by 1 second for later comparison. */
1671 /* Compare file sizes only for servers that tell us correct
1672 values. Assume sizes being equal for servers that lie
1674 cor_val = (con->rs == ST_UNIX || con->rs == ST_WINNT);
1675 eq_size = cor_val ? (local_size == f->size) : true;
1676 if (f->tstamp <= tml && eq_size)
1678 /* Remote file is older, file sizes can be compared and
1680 logprintf (LOG_VERBOSE, _("\
1681 Remote file no newer than local file `%s' -- not retrieving.\n"), con->target);
1686 /* Remote file is newer or sizes cannot be matched */
1687 logprintf (LOG_VERBOSE, _("\
1688 Remote file is newer than local file `%s' -- retrieving.\n\n"),
1693 /* Sizes do not match */
1694 logprintf (LOG_VERBOSE, _("\
1695 The sizes do not match (local %s) -- retrieving.\n\n"),
1696 number_to_static_string (local_size));
1699 } /* opt.timestamping && f->type == FT_PLAINFILE */
1703 /* If opt.retr_symlinks is defined, we treat symlinks as
1704 if they were normal files. There is currently no way
1705 to distinguish whether they might be directories, and
1707 if (!opt.retr_symlinks)
1711 logputs (LOG_NOTQUIET,
1712 _("Invalid name of the symlink, skipping.\n"));
1716 /* Check whether we already have the correct
1718 int rc = lstat (con->target, &st);
1721 size_t len = strlen (f->linkto) + 1;
1722 if (S_ISLNK (st.st_mode))
1724 char *link_target = (char *)alloca (len);
1725 size_t n = readlink (con->target, link_target, len);
1727 && (memcmp (link_target, f->linkto, n) == 0))
1729 logprintf (LOG_VERBOSE, _("\
1730 Already have correct symlink %s -> %s\n\n"),
1731 con->target, escnonprint (f->linkto));
1737 logprintf (LOG_VERBOSE, _("Creating symlink %s -> %s\n"),
1738 con->target, escnonprint (f->linkto));
1739 /* Unlink before creating symlink! */
1740 unlink (con->target);
1741 if (symlink (f->linkto, con->target) == -1)
1742 logprintf (LOG_NOTQUIET, "symlink: %s\n", strerror (errno));
1743 logputs (LOG_VERBOSE, "\n");
1744 } /* have f->linkto */
1745 #else /* not HAVE_SYMLINK */
1746 logprintf (LOG_NOTQUIET,
1747 _("Symlinks not supported, skipping symlink `%s'.\n"),
1749 #endif /* not HAVE_SYMLINK */
1751 else /* opt.retr_symlinks */
1754 err = ftp_loop_internal (u, f, con);
1755 } /* opt.retr_symlinks */
1759 logprintf (LOG_NOTQUIET, _("Skipping directory `%s'.\n"),
1760 escnonprint (f->name));
1763 /* Call the retrieve loop. */
1765 err = ftp_loop_internal (u, f, con);
1768 logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),
1769 escnonprint (f->name));
1775 * Set permissions _before_ setting the times, as setting the
1776 * permissions changes the modified-time, at least on VMS.
1777 * Also, use the opt.output_document name here, too, as
1778 * appropriate. (Do the test once, and save the result.)
1781 /* #### This code repeats in http.c and ftp.c. Move it to a
1783 actual_target = NULL;
1784 if (opt.output_document)
1786 if (output_stream_regular)
1787 actual_target = opt.output_document;
1790 actual_target = con->target;
1792 /* If downloading a plain file, set valid (non-zero) permissions. */
1793 if (dlthis && (actual_target != NULL) && (f->type == FT_PLAINFILE))
1796 chmod (actual_target, f->perms);
1798 DEBUGP (("Unrecognized permissions for %s.\n", actual_target));
1801 /* Set the time-stamp information to the local file. Symlinks
1802 are not to be stamped because it sets the stamp on the
1805 if (actual_target != NULL)
1807 if (!(f->type == FT_SYMLINK && !opt.retr_symlinks)
1810 && file_exists_p (con->target))
1812 touch (actual_target, f->tstamp);
1814 else if (f->tstamp == -1)
1815 logprintf (LOG_NOTQUIET, _("%s: corrupt time-stamp.\n"),
1819 xfree (con->target);
1820 con->target = old_target;
1822 url_set_file (u, ofile);
1825 /* Break on fatals. */
1826 if (err == QUOTEXC || err == HOSTERR || err == FWRITEERR)
1828 con->cmd &= ~ (DO_CWD | DO_LOGIN);
1832 /* We do not want to call ftp_retrieve_dirs here */
1833 if (opt.recursive &&
1834 !(opt.reclevel != INFINITE_RECURSION && depth >= opt.reclevel))
1835 err = ftp_retrieve_dirs (u, orig, con);
1836 else if (opt.recursive)
1837 DEBUGP ((_("Will not retrieve dirs since depth is %d (max %d).\n"),
1838 depth, opt.reclevel));
1843 /* Retrieve the directories given in a file list. This function works
1844 by simply going through the linked list and calling
1845 ftp_retrieve_glob on each directory entry. The function knows
1846 about excluded directories. */
1848 ftp_retrieve_dirs (struct url *u, struct fileinfo *f, ccon *con)
1850 char *container = NULL;
1851 int container_size = 0;
1853 for (; f; f = f->next)
1856 char *odir, *newdir;
1858 if (opt.quota && total_downloaded_bytes > opt.quota)
1860 if (f->type != FT_DIRECTORY)
1863 /* Allocate u->dir off stack, but reallocate only if a larger
1864 string is needed. It's a pity there's no "realloca" for an
1865 item on the bottom of the stack. */
1866 size = strlen (u->dir) + 1 + strlen (f->name) + 1;
1867 if (size > container_size)
1868 container = (char *)alloca (size);
1873 || (*odir == '/' && *(odir + 1) == '\0'))
1874 /* If ODIR is empty or just "/", simply append f->name to
1875 ODIR. (In the former case, to preserve u->dir being
1876 relative; in the latter case, to avoid double slash.) */
1877 sprintf (newdir, "%s%s", odir, f->name);
1879 /* Else, use a separator. */
1880 sprintf (newdir, "%s/%s", odir, f->name);
1882 DEBUGP (("Composing new CWD relative to the initial directory.\n"));
1883 DEBUGP ((" odir = '%s'\n f->name = '%s'\n newdir = '%s'\n\n",
1884 odir, f->name, newdir));
1885 if (!accdir (newdir))
1887 logprintf (LOG_VERBOSE, _("\
1888 Not descending to `%s' as it is excluded/not-included.\n"),
1889 escnonprint (newdir));
1893 con->st &= ~DONE_CWD;
1895 odir = xstrdup (u->dir); /* because url_set_dir will free
1897 url_set_dir (u, newdir);
1898 ftp_retrieve_glob (u, con, GLOB_GETALL);
1899 url_set_dir (u, odir);
1902 /* Set the time-stamp? */
1905 if (opt.quota && total_downloaded_bytes > opt.quota)
1911 /* Return true if S has a leading '/' or contains '../' */
1913 has_insecure_name_p (const char *s)
1918 if (strstr (s, "../") != 0)
1924 /* A near-top-level function to retrieve the files in a directory.
1925 The function calls ftp_get_listing, to get a linked list of files.
1926 Then it weeds out the file names that do not match the pattern.
1927 ftp_retrieve_list is called with this updated list as an argument.
1929 If the argument ACTION is GLOB_GETONE, just download the file (but
1930 first get the listing, so that the time-stamp is heeded); if it's
1931 GLOB_GLOBALL, use globbing; if it's GLOB_GETALL, download the whole
1934 ftp_retrieve_glob (struct url *u, ccon *con, int action)
1936 struct fileinfo *f, *start;
1939 con->cmd |= LEAVE_PENDING;
1941 res = ftp_get_listing (u, con, &start);
1944 /* First: weed out that do not conform the global rules given in
1945 opt.accepts and opt.rejects. */
1946 if (opt.accepts || opt.rejects)
1951 if (f->type != FT_DIRECTORY && !acceptable (f->name))
1953 logprintf (LOG_VERBOSE, _("Rejecting `%s'.\n"),
1954 escnonprint (f->name));
1955 f = delelement (f, &start);
1961 /* Remove all files with possible harmful names */
1965 if (has_insecure_name_p (f->name))
1967 logprintf (LOG_VERBOSE, _("Rejecting `%s'.\n"),
1968 escnonprint (f->name));
1969 f = delelement (f, &start);
1974 /* Now weed out the files that do not match our globbing pattern.
1975 If we are dealing with a globbing pattern, that is. */
1978 if (action == GLOB_GLOBALL)
1980 int (*matcher) (const char *, const char *, int)
1981 = opt.ignore_case ? fnmatch_nocase : fnmatch;
1987 matchres = matcher (u->file, f->name, 0);
1990 logprintf (LOG_NOTQUIET, _("Error matching %s against %s: %s\n"),
1991 u->file, escnonprint (f->name), strerror (errno));
1994 if (matchres == FNM_NOMATCH)
1995 f = delelement (f, &start); /* delete the element from the list */
1997 f = f->next; /* leave the element in the list */
2001 freefileinfo (start);
2002 return RETRBADPATTERN;
2005 else if (action == GLOB_GETONE)
2007 int (*cmp) (const char *, const char *)
2008 = opt.ignore_case ? strcasecmp : strcmp;
2012 if (0 != cmp(u->file, f->name))
2013 f = delelement (f, &start);
2021 /* Just get everything. */
2022 ftp_retrieve_list (u, start, con);
2026 if (action == GLOB_GLOBALL)
2029 /* #### This message SUCKS. We should see what was the
2030 reason that nothing was retrieved. */
2031 logprintf (LOG_VERBOSE, _("No matches on pattern `%s'.\n"),
2032 escnonprint (u->file));
2034 else if (action == GLOB_GETONE) /* GLOB_GETONE or GLOB_GETALL */
2036 /* Let's try retrieving it anyway. */
2037 con->st |= ON_YOUR_OWN;
2038 res = ftp_loop_internal (u, NULL, con);
2042 /* If action == GLOB_GETALL, and the file list is empty, there's
2043 no point in trying to download anything or in complaining about
2044 it. (An empty directory should not cause complaints.)
2047 freefileinfo (start);
2048 if (opt.quota && total_downloaded_bytes > opt.quota)
2051 /* #### Should we return `res' here? */
2055 /* The wrapper that calls an appropriate routine according to contents
2056 of URL. Inherently, its capabilities are limited on what can be
2057 encoded into a URL. */
2059 ftp_loop (struct url *u, int *dt, struct url *proxy, bool recursive, bool glob)
2061 ccon con; /* FTP connection */
2069 con.st = ON_YOUR_OWN;
2074 /* If the file name is empty, the user probably wants a directory
2075 index. We'll provide one, properly HTML-ized. Unless
2076 opt.htmlify is 0, of course. :-) */
2077 if (!*u->file && !recursive)
2080 res = ftp_get_listing (u, &con, &f);
2084 if (opt.htmlify && !opt.spider)
2086 char *filename = (opt.output_document
2087 ? xstrdup (opt.output_document)
2088 : (con.target ? xstrdup (con.target)
2089 : url_file_name (u)));
2090 res = ftp_index (filename, u, f);
2091 if (res == FTPOK && opt.verbose)
2093 if (!opt.output_document)
2097 if (stat (filename, &st) == 0)
2101 logprintf (LOG_NOTQUIET,
2102 _("Wrote HTML-ized index to `%s' [%s].\n"),
2103 filename, number_to_static_string (sz));
2106 logprintf (LOG_NOTQUIET,
2107 _("Wrote HTML-ized index to `%s'.\n"),
2117 bool ispattern = false;
2120 /* Treat the URL as a pattern if the file name part of the
2121 URL path contains wildcards. (Don't check for u->file
2122 because it is unescaped and therefore doesn't leave users
2123 the option to escape literal '*' as %2A.) */
2124 char *file_part = strrchr (u->path, '/');
2126 file_part = u->path;
2127 ispattern = has_wildcards_p (file_part);
2129 if (ispattern || recursive || opt.timestamping)
2131 /* ftp_retrieve_glob is a catch-all function that gets called
2132 if we need globbing, time-stamping or recursion. Its
2133 third argument is just what we really need. */
2134 res = ftp_retrieve_glob (u, &con,
2135 ispattern ? GLOB_GLOBALL : GLOB_GETONE);
2138 res = ftp_loop_internal (u, NULL, &con);
2144 /* If a connection was left, quench it. */
2145 if (con.csock != -1)
2146 fd_close (con.csock);
2147 xfree_null (con.id);
2149 xfree_null (con.target);
2154 /* Delete an element from the fileinfo linked list. Returns the
2155 address of the next element, or NULL if the list is exhausted. It
2156 can modify the start of the list. */
2157 static struct fileinfo *
2158 delelement (struct fileinfo *f, struct fileinfo **start)
2160 struct fileinfo *prev = f->prev;
2161 struct fileinfo *next = f->next;
2164 xfree_null (f->linkto);
2176 /* Free the fileinfo linked list of files. */
2178 freefileinfo (struct fileinfo *f)
2182 struct fileinfo *next = f->next;