X-Git-Url: http://sjero.net/git/?a=blobdiff_plain;f=src%2Fftp.c;h=2e32c1f03d04b45e9f723706d8e8d7ac1567925d;hb=4d7c5e087b2bc82c9f503dff003916d1047903ce;hp=257a0574bb13002e426fbff94acf14e768ad9ab0;hpb=52aafa6d15e539935a19af46ebf091a01ab504af;p=wget
diff --git a/src/ftp.c b/src/ftp.c
index 257a0574..2e32c1f0 100644
--- a/src/ftp.c
+++ b/src/ftp.c
@@ -1,12 +1,11 @@
/* File Transfer Protocol support.
- Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001
- Free Software Foundation, Inc.
+ Copyright (C) 1996-2006 Free Software Foundation, Inc.
This file is part of GNU Wget.
GNU Wget is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
+the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
GNU Wget is distributed in the hope that it will be useful,
@@ -15,8 +14,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with Wget; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+along with Wget. If not, see .
In addition, as a special exception, the Free Software Foundation
gives permission to link the code of its release of Wget with the
@@ -32,17 +30,13 @@ so, delete this exception statement from your version. */
#include
#include
-#ifdef HAVE_STRING_H
-# include
-#else
-# include
-#endif
+#include
#ifdef HAVE_UNISTD_H
# include
#endif
-#include
#include
#include
+#include
#include "wget.h"
#include "utils.h"
@@ -55,20 +49,9 @@ so, delete this exception statement from your version. */
#include "convert.h" /* for downloaded_file */
#include "recur.h" /* for INFINITE_RECURSION */
-#ifndef errno
-extern int errno;
-#endif
-
-extern LARGE_INT total_downloaded_bytes;
-
/* File where the "ls -al" listing will be saved. */
#define LIST_FILENAME ".listing"
-extern char ftp_last_respline[];
-
-extern FILE *output_stream;
-extern int output_stream_regular;
-
typedef struct
{
int st; /* connection status */
@@ -133,14 +116,14 @@ ftp_do_pasv (int csock, ip_address *addr, int *port)
/* If our control connection is over IPv6, then we first try EPSV and then
* LPSV if the former is not supported. If the control connection is over
* IPv4, we simply issue the good old PASV request. */
- switch (addr->type)
+ switch (addr->family)
{
- case IPV4_ADDRESS:
+ case AF_INET:
if (!opt.server_response)
logputs (LOG_VERBOSE, "==> PASV ... ");
err = ftp_pasv (csock, addr, port);
break;
- case IPV6_ADDRESS:
+ case AF_INET6:
if (!opt.server_response)
logputs (LOG_VERBOSE, "==> EPSV ... ");
err = ftp_epsv (csock, addr, port);
@@ -176,14 +159,14 @@ ftp_do_port (int csock, int *local_sock)
/* If our control connection is over IPv6, then we first try EPRT and then
* LPRT if the former is not supported. If the control connection is over
* IPv4, we simply issue the good old PORT request. */
- switch (cip.type)
+ switch (cip.family)
{
- case IPV4_ADDRESS:
+ case AF_INET:
if (!opt.server_response)
logputs (LOG_VERBOSE, "==> PORT ... ");
err = ftp_port (csock, local_sock);
break;
- case IPV6_ADDRESS:
+ case AF_INET6:
if (!opt.server_response)
logputs (LOG_VERBOSE, "==> EPRT ... ");
err = ftp_eprt (csock, local_sock);
@@ -221,23 +204,22 @@ ftp_do_port (int csock, int *local_sock)
#endif
static void
-print_length (wgint size, wgint start, int authoritative)
+print_length (wgint size, wgint start, bool authoritative)
{
- logprintf (LOG_VERBOSE, _("Length: %s"), with_thousand_seps (size));
+ logprintf (LOG_VERBOSE, _("Length: %s"), number_to_static_string (size));
if (size >= 1024)
logprintf (LOG_VERBOSE, " (%s)", human_readable (size));
if (start > 0)
{
if (start >= 1024)
logprintf (LOG_VERBOSE, _(", %s (%s) remaining"),
- with_thousand_seps (size - start),
+ number_to_static_string (size - start),
human_readable (size - start));
else
logprintf (LOG_VERBOSE, _(", %s remaining"),
- with_thousand_seps (size - start));
+ number_to_static_string (size - start));
}
- if (!authoritative)
- logputs (LOG_VERBOSE, _(" (unauthoritative)\n"));
+ logputs (LOG_VERBOSE, !authoritative ? _(" (unauthoritative)\n") : "\n");
}
/* Retrieves a file with denoted parameters through opening an FTP
@@ -250,11 +232,12 @@ getftp (struct url *u, wgint *len, wgint restval, ccon *con)
uerr_t err = RETROK; /* appease the compiler */
FILE *fp;
char *user, *passwd, *respline;
- char *tms, *tmrate;
+ char *tms;
+ const char *tmrate;
int cmd = con->cmd;
- int pasv_mode_open = 0;
- wgint expected_bytes = 0L;
- int rest_failed = 0;
+ bool pasv_mode_open = false;
+ wgint expected_bytes = 0;
+ bool rest_failed = false;
int flags;
wgint rd_size;
@@ -271,9 +254,10 @@ getftp (struct url *u, wgint *len, wgint restval, ccon *con)
user = u->user;
passwd = u->passwd;
search_netrc (u->host, (const char **)&user, (const char **)&passwd, 1);
- user = user ? user : opt.ftp_acc;
- passwd = passwd ? passwd : opt.ftp_pass;
- assert (user && passwd);
+ user = user ? user : (opt.ftp_user ? opt.ftp_user : opt.user);
+ if (!user) user = "anonymous";
+ passwd = passwd ? passwd : (opt.ftp_passwd ? opt.ftp_passwd : opt.passwd);
+ if (!passwd) passwd = "-wget@";
dtsock = -1;
local_sock = -1;
@@ -329,14 +313,12 @@ Error in server response, closing control connection.\n"));
fd_close (csock);
con->csock = -1;
return err;
- break;
case FTPSRVERR:
logputs (LOG_VERBOSE, "\n");
logputs (LOG_NOTQUIET, _("Error in server greeting.\n"));
fd_close (csock);
con->csock = -1;
return err;
- break;
case WRITEFAILED:
logputs (LOG_VERBOSE, "\n");
logputs (LOG_NOTQUIET,
@@ -344,29 +326,24 @@ Error in server response, closing control connection.\n"));
fd_close (csock);
con->csock = -1;
return err;
- break;
case FTPLOGREFUSED:
logputs (LOG_VERBOSE, "\n");
logputs (LOG_NOTQUIET, _("The server refuses login.\n"));
fd_close (csock);
con->csock = -1;
return FTPLOGREFUSED;
- break;
case FTPLOGINC:
logputs (LOG_VERBOSE, "\n");
logputs (LOG_NOTQUIET, _("Login incorrect.\n"));
fd_close (csock);
con->csock = -1;
return FTPLOGINC;
- break;
case FTPOK:
if (!opt.server_response)
logputs (LOG_VERBOSE, _("Logged in!\n"));
break;
default:
abort ();
- exit (1);
- break;
}
/* Third: Get the system type */
if (!opt.server_response)
@@ -382,7 +359,6 @@ Error in server response, closing control connection.\n"));
fd_close (csock);
con->csock = -1;
return err;
- break;
case FTPSRVERR:
logputs (LOG_VERBOSE, "\n");
logputs (LOG_NOTQUIET,
@@ -393,7 +369,6 @@ Error in server response, closing control connection.\n"));
break;
default:
abort ();
- break;
}
if (!opt.server_response && err != FTPSRVERR)
logputs (LOG_VERBOSE, _("done. "));
@@ -413,7 +388,6 @@ Error in server response, closing control connection.\n"));
fd_close (csock);
con->csock = -1;
return err;
- break;
case FTPSRVERR :
/* PWD unsupported -- assume "/". */
xfree_null (con->id);
@@ -424,7 +398,6 @@ Error in server response, closing control connection.\n"));
break;
default:
abort ();
- break;
}
/* VMS will report something like "PUB$DEVICE:[INITIAL.FOLDER]".
Convert it to "/INITIAL/FOLDER" */
@@ -467,7 +440,6 @@ Error in server response, closing control connection.\n"));
fd_close (csock);
con->csock = -1;
return err;
- break;
case WRITEFAILED:
logputs (LOG_VERBOSE, "\n");
logputs (LOG_NOTQUIET,
@@ -475,7 +447,6 @@ Error in server response, closing control connection.\n"));
fd_close (csock);
con->csock = -1;
return err;
- break;
case FTPUNKNOWNTYPE:
logputs (LOG_VERBOSE, "\n");
logprintf (LOG_NOTQUIET,
@@ -489,7 +460,6 @@ Error in server response, closing control connection.\n"));
break;
default:
abort ();
- break;
}
if (!opt.server_response)
logputs (LOG_VERBOSE, _("done. "));
@@ -582,7 +552,6 @@ Error in server response, closing control connection.\n"));
fd_close (csock);
con->csock = -1;
return err;
- break;
case WRITEFAILED:
logputs (LOG_VERBOSE, "\n");
logputs (LOG_NOTQUIET,
@@ -590,7 +559,6 @@ Error in server response, closing control connection.\n"));
fd_close (csock);
con->csock = -1;
return err;
- break;
case FTPNSFOD:
logputs (LOG_VERBOSE, "\n");
logprintf (LOG_NOTQUIET, _("No such directory `%s'.\n\n"),
@@ -598,13 +566,10 @@ Error in server response, closing control connection.\n"));
fd_close (csock);
con->csock = -1;
return err;
- break;
case FTPOK:
- /* fine and dandy */
break;
default:
abort ();
- break;
}
if (!opt.server_response)
logputs (LOG_VERBOSE, _("done.\n"));
@@ -613,7 +578,7 @@ Error in server response, closing control connection.\n"));
else /* do not CWD */
logputs (LOG_VERBOSE, _("==> CWD not required.\n"));
- if ((cmd & DO_RETR) && restval && *len == 0)
+ if ((cmd & DO_RETR) && *len == 0)
{
if (opt.verbose)
{
@@ -626,29 +591,28 @@ Error in server response, closing control connection.\n"));
switch (err)
{
case FTPRERR:
- case FTPSRVERR :
+ case FTPSRVERR:
logputs (LOG_VERBOSE, "\n");
logputs (LOG_NOTQUIET, _("\
Error in server response, closing control connection.\n"));
fd_close (csock);
con->csock = -1;
return err;
- break;
case FTPOK:
/* Everything is OK. */
break;
default:
abort ();
- break;
}
if (!opt.server_response)
- logputs (LOG_VERBOSE, _("done.\n"));
+ logprintf (LOG_VERBOSE, *len ? "%s\n" : _("done.\n"),
+ number_to_static_string (*len));
}
/* If anything is to be retrieved, PORT (or PASV) must be sent. */
if (cmd & (DO_LIST | DO_RETR))
{
- if (opt.ftp_pasv > 0)
+ if (opt.ftp_pasv)
{
ip_address passive_addr;
int passive_port;
@@ -663,7 +627,6 @@ Error in server response, closing control connection.\n"));
fd_close (csock);
con->csock = -1;
return err;
- break;
case WRITEFAILED:
logputs (LOG_VERBOSE, "\n");
logputs (LOG_NOTQUIET,
@@ -671,7 +634,6 @@ Error in server response, closing control connection.\n"));
fd_close (csock);
con->csock = -1;
return err;
- break;
case FTPNOPASV:
logputs (LOG_VERBOSE, "\n");
logputs (LOG_NOTQUIET, _("Cannot initiate PASV transfer.\n"));
@@ -681,17 +643,14 @@ Error in server response, closing control connection.\n"));
logputs (LOG_NOTQUIET, _("Cannot parse PASV response.\n"));
break;
case FTPOK:
- /* fine and dandy */
break;
default:
abort ();
- break;
} /* switch (err) */
if (err==FTPOK)
{
DEBUGP (("trying to connect to %s port %d\n",
- pretty_print_address (&passive_addr),
- passive_port));
+ print_address (&passive_addr), passive_port));
dtsock = connect_to_ip (&passive_addr, passive_port, NULL);
if (dtsock < 0)
{
@@ -699,13 +658,13 @@ Error in server response, closing control connection.\n"));
fd_close (csock);
con->csock = -1;
logprintf (LOG_VERBOSE, _("couldn't connect to %s port %d: %s\n"),
- pretty_print_address (&passive_addr), passive_port,
+ print_address (&passive_addr), passive_port,
strerror (save_errno));
return (retryable_socket_connect_error (save_errno)
? CONERROR : CONIMPOSSIBLE);
}
- pasv_mode_open = 1; /* Flag to avoid accept port */
+ pasv_mode_open = true; /* Flag to avoid accept port */
if (!opt.server_response)
logputs (LOG_VERBOSE, _("done. "));
} /* err==FTP_OK */
@@ -727,7 +686,6 @@ Error in server response, closing control connection.\n"));
fd_close (dtsock);
fd_close (local_sock);
return err;
- break;
case WRITEFAILED:
logputs (LOG_VERBOSE, "\n");
logputs (LOG_NOTQUIET,
@@ -737,7 +695,6 @@ Error in server response, closing control connection.\n"));
fd_close (dtsock);
fd_close (local_sock);
return err;
- break;
case CONSOCKERR:
logputs (LOG_VERBOSE, "\n");
logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
@@ -746,14 +703,12 @@ Error in server response, closing control connection.\n"));
fd_close (dtsock);
fd_close (local_sock);
return err;
- break;
case FTPSYSERR:
logputs (LOG_VERBOSE, "\n");
logprintf (LOG_NOTQUIET, _("Bind error (%s).\n"),
strerror (errno));
fd_close (dtsock);
return err;
- break;
case FTPPORTERR:
logputs (LOG_VERBOSE, "\n");
logputs (LOG_NOTQUIET, _("Invalid PORT.\n"));
@@ -762,13 +717,10 @@ Error in server response, closing control connection.\n"));
fd_close (dtsock);
fd_close (local_sock);
return err;
- break;
case FTPOK:
- /* fine and dandy */
break;
default:
abort ();
- break;
} /* port switch */
if (!opt.server_response)
logputs (LOG_VERBOSE, _("done. "));
@@ -795,7 +747,6 @@ Error in server response, closing control connection.\n"));
fd_close (dtsock);
fd_close (local_sock);
return err;
- break;
case WRITEFAILED:
logputs (LOG_VERBOSE, "\n");
logputs (LOG_NOTQUIET,
@@ -805,17 +756,14 @@ Error in server response, closing control connection.\n"));
fd_close (dtsock);
fd_close (local_sock);
return err;
- break;
case FTPRESTFAIL:
logputs (LOG_VERBOSE, _("\nREST failed, starting from scratch.\n"));
- rest_failed = 1;
+ rest_failed = true;
break;
case FTPOK:
- /* fine and dandy */
break;
default:
abort ();
- break;
}
if (err != FTPRESTFAIL && !opt.server_response)
logputs (LOG_VERBOSE, _("done. "));
@@ -859,7 +807,6 @@ Error in server response, closing control connection.\n"));
fd_close (dtsock);
fd_close (local_sock);
return err;
- break;
case WRITEFAILED:
logputs (LOG_VERBOSE, "\n");
logputs (LOG_NOTQUIET,
@@ -869,7 +816,6 @@ Error in server response, closing control connection.\n"));
fd_close (dtsock);
fd_close (local_sock);
return err;
- break;
case FTPNSFOD:
logputs (LOG_VERBOSE, "\n");
logprintf (LOG_NOTQUIET, _("No such file `%s'.\n\n"),
@@ -877,13 +823,10 @@ Error in server response, closing control connection.\n"));
fd_close (dtsock);
fd_close (local_sock);
return err;
- break;
case FTPOK:
- /* fine and dandy */
break;
default:
abort ();
- break;
}
if (!opt.server_response)
@@ -911,7 +854,6 @@ Error in server response, closing control connection.\n"));
fd_close (dtsock);
fd_close (local_sock);
return err;
- break;
case WRITEFAILED:
logputs (LOG_VERBOSE, "\n");
logputs (LOG_NOTQUIET,
@@ -921,7 +863,6 @@ Error in server response, closing control connection.\n"));
fd_close (dtsock);
fd_close (local_sock);
return err;
- break;
case FTPNSFOD:
logputs (LOG_VERBOSE, "\n");
logprintf (LOG_NOTQUIET, _("No such file or directory `%s'.\n\n"),
@@ -929,13 +870,10 @@ Error in server response, closing control connection.\n"));
fd_close (dtsock);
fd_close (local_sock);
return err;
- break;
case FTPOK:
- /* fine and dandy */
break;
default:
abort ();
- break;
}
if (!opt.server_response)
logputs (LOG_VERBOSE, _("done.\n"));
@@ -982,7 +920,7 @@ Error in server response, closing control connection.\n"));
fp = fopen (con->target, "wb");
else
{
- fp = fopen_excl (con->target, 0);
+ fp = fopen_excl (con->target, true);
if (!fp && errno == EEXIST)
{
/* We cannot just invent a new name and use it (which is
@@ -1013,11 +951,11 @@ Error in server response, closing control connection.\n"));
if (*len)
{
- print_length (*len, restval, 1);
- expected_bytes = *len; /* for get_contents/show_progress */
+ print_length (*len, restval, true);
+ expected_bytes = *len; /* for fd_read_body's progress bar */
}
else if (expected_bytes)
- print_length (expected_bytes, restval, 0);
+ print_length (expected_bytes, restval, false);
/* Get the contents of the document. */
flags = 0;
@@ -1029,47 +967,38 @@ Error in server response, closing control connection.\n"));
expected_bytes ? expected_bytes - restval : 0,
restval, &rd_size, len, &con->dltime, flags);
- tms = time_str (NULL);
- tmrate = retr_rate (rd_size, con->dltime, 0);
- /* Close data connection socket. */
- fd_close (dtsock);
+ tms = time_str (time (NULL));
+ tmrate = retr_rate (rd_size, con->dltime);
+ total_download_time += con->dltime;
+
fd_close (local_sock);
/* Close the local file. */
- {
- /* Close or flush the file. We have to be careful to check for
- error here. Checking the result of fwrite() is not enough --
- errors could go unnoticed! */
- int flush_res;
- if (!output_stream || con->cmd & DO_LIST)
- flush_res = fclose (fp);
- else
- flush_res = fflush (fp);
- if (flush_res == EOF)
- res = -2;
- }
-
- /* If get_contents couldn't write to fp, bail out. */
+ if (!output_stream || con->cmd & DO_LIST)
+ fclose (fp);
+
+ /* If fd_read_body couldn't write to fp, bail out. */
if (res == -2)
{
logprintf (LOG_NOTQUIET, _("%s: %s, closing control connection.\n"),
con->target, strerror (errno));
fd_close (csock);
con->csock = -1;
+ fd_close (dtsock);
return FWRITEERR;
}
else if (res == -1)
{
logprintf (LOG_NOTQUIET, _("%s (%s) - Data connection: %s; "),
- tms, tmrate, strerror (errno));
+ tms, tmrate, fd_errstr (dtsock));
if (opt.server_response)
logputs (LOG_ALWAYS, "\n");
}
+ fd_close (dtsock);
/* Get the server to tell us if everything is retrieved. */
err = ftp_response (csock, &respline);
if (err != FTPOK)
{
- xfree (respline);
/* The control connection is decidedly closed. Print the time
only if it hasn't already been printed. */
if (res != -1)
@@ -1126,6 +1055,9 @@ Error in server response, closing control connection.\n"));
no-buffering on opt.lfile. */
while ((line = read_whole_line (fp)) != NULL)
{
+ char *p = strchr (line, '\0');
+ while (p > line && (p[-1] == '\n' || p[-1] == '\r'))
+ *--p = '\0';
logprintf (LOG_ALWAYS, "%s\n", escnonprint (line));
xfree (line);
}
@@ -1147,7 +1079,7 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
int count, orig_lp;
wgint restval, len = 0;
char *tms, *locf;
- char *tmrate = NULL;
+ const char *tmrate = NULL;
uerr_t err;
struct_stat st;
@@ -1157,7 +1089,7 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
if (opt.noclobber && file_exists_p (con->target))
{
logprintf (LOG_VERBOSE,
- _("File `%s' already there, not retrieving.\n"), con->target);
+ _("File `%s' already there; not retrieving.\n"), con->target);
/* If the file is there, we suppose it's retrieved OK. */
return RETROK;
}
@@ -1204,20 +1136,24 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
}
/* Decide whether or not to restart. */
- restval = 0;
- if (count > 1)
- restval = len; /* start where the previous run left off */
- else if (opt.always_rest
- && stat (locf, &st) == 0
- && S_ISREG (st.st_mode))
+ if (opt.always_rest
+ && stat (locf, &st) == 0
+ && S_ISREG (st.st_mode))
+ /* When -c is used, continue from on-disk size. (Can't use
+ hstat.len even if count>1 because we don't want a failed
+ first attempt to clobber existing data.) */
restval = st.st_size;
+ else if (count > 1)
+ restval = len; /* start where the previous run left off */
+ else
+ restval = 0;
/* Get the current time string. */
- tms = time_str (NULL);
+ tms = time_str (time (NULL));
/* Print fetch message, if opt.verbose. */
if (opt.verbose)
{
- char *hurl = url_string (u, 1);
+ char *hurl = url_string (u, true);
char tmp[256];
strcpy (tmp, " ");
if (count > 1)
@@ -1236,7 +1172,7 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
len = 0;
err = getftp (u, &len, restval, con);
- if (con->csock != -1)
+ if (con->csock == -1)
con->st &= ~DONE_CWD;
else
con->st |= DONE_CWD;
@@ -1247,7 +1183,6 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
case FTPNSFOD: case FTPLOGINC: case FTPNOPASV: case CONTNOTSUPPORTED:
/* Fatal errors, give up. */
return err;
- break;
case CONSOCKERR: case CONERROR: case FTPSRVERR: case FTPRERR:
case WRITEFAILED: case FTPUNKNOWNTYPE: case FTPSYSERR:
case FTPPORTERR: case FTPLOGREFUSED: case FTPINVPASV:
@@ -1262,7 +1197,6 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
locf = con->target;
}
continue;
- break;
case FTPRETRINT:
/* If the control connection was closed, the retrieval
will be considered OK if f->size == len. */
@@ -1279,9 +1213,9 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
/* Not as great. */
abort ();
}
- tms = time_str (NULL);
+ tms = time_str (time (NULL));
if (!opt.spider)
- tmrate = retr_rate (len - restval, con->dltime, 0);
+ tmrate = retr_rate (len - restval, con->dltime);
/* If we get out of the switch above without continue'ing, we've
successfully downloaded a file. Remember this fact. */
@@ -1300,7 +1234,7 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
/* Need to hide the password from the URL. The `if' is here
so that we don't do the needless allocation every
time. */
- char *hurl = url_string (u, 1);
+ char *hurl = url_string (u, true);
logprintf (LOG_NONVERBOSE, "%s URL: %s [%s] -> \"%s\" [%d]\n",
tms, hurl, number_to_static_string (len), locf, count);
xfree (hurl);
@@ -1333,8 +1267,8 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
if (opt.delete_after)
{
- DEBUGP (("Removing file due to --delete-after in"
- " ftp_loop_internal():\n"));
+ DEBUGP (("\
+Removing file due to --delete-after in ftp_loop_internal():\n"));
logprintf (LOG_VERBOSE, _("Removing %s.\n"), locf);
if (unlink (locf))
logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
@@ -1359,7 +1293,7 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
/* Return the directory listing in a reusable format. The directory
is specifed in u->dir. */
-uerr_t
+static uerr_t
ftp_get_listing (struct url *u, ccon *con, struct fileinfo **f)
{
uerr_t err;
@@ -1399,12 +1333,10 @@ ftp_get_listing (struct url *u, ccon *con, struct fileinfo **f)
return err;
}
-static uerr_t ftp_retrieve_dirs PARAMS ((struct url *, struct fileinfo *,
- ccon *));
-static uerr_t ftp_retrieve_glob PARAMS ((struct url *, ccon *, int));
-static struct fileinfo *delelement PARAMS ((struct fileinfo *,
- struct fileinfo **));
-static void freefileinfo PARAMS ((struct fileinfo *f));
+static uerr_t ftp_retrieve_dirs (struct url *, struct fileinfo *, ccon *);
+static uerr_t ftp_retrieve_glob (struct url *, ccon *, int);
+static struct fileinfo *delelement (struct fileinfo *, struct fileinfo **);
+static void freefileinfo (struct fileinfo *f);
/* Retrieve a list of files given in struct fileinfo linked list. If
a file is a symbolic link, do not retrieve it, but rather try to
@@ -1421,7 +1353,7 @@ ftp_retrieve_list (struct url *u, struct fileinfo *f, ccon *con)
struct fileinfo *orig;
wgint local_size;
time_t tml;
- int dlthis;
+ bool dlthis;
/* Increase the depth. */
++depth;
@@ -1467,7 +1399,7 @@ ftp_retrieve_list (struct url *u, struct fileinfo *f, ccon *con)
con->target = url_file_name (u);
err = RETROK;
- dlthis = 1;
+ dlthis = true;
if (opt.timestamping && f->type == FT_PLAINFILE)
{
struct_stat st;
@@ -1478,8 +1410,8 @@ ftp_retrieve_list (struct url *u, struct fileinfo *f, ccon *con)
.orig suffix. */
if (!stat (con->target, &st))
{
- int eq_size;
- int cor_val;
+ bool eq_size;
+ bool cor_val;
/* Else, get it from the file. */
local_size = st.st_size;
tml = st.st_mtime;
@@ -1489,17 +1421,17 @@ ftp_retrieve_list (struct url *u, struct fileinfo *f, ccon *con)
tml++;
#endif
/* Compare file sizes only for servers that tell us correct
- values. Assumme sizes being equal for servers that lie
+ values. Assume sizes being equal for servers that lie
about file size. */
cor_val = (con->rs == ST_UNIX || con->rs == ST_WINNT);
- eq_size = cor_val ? (local_size == f->size) : 1 ;
+ eq_size = cor_val ? (local_size == f->size) : true;
if (f->tstamp <= tml && eq_size)
{
/* Remote file is older, file sizes can be compared and
are both equal. */
logprintf (LOG_VERBOSE, _("\
Remote file no newer than local file `%s' -- not retrieving.\n"), con->target);
- dlthis = 0;
+ dlthis = false;
}
else if (eq_size)
{
@@ -1549,7 +1481,7 @@ The sizes do not match (local %s) -- retrieving.\n\n"),
logprintf (LOG_VERBOSE, _("\
Already have correct symlink %s -> %s\n\n"),
con->target, escnonprint (f->linkto));
- dlthis = 0;
+ dlthis = false;
break;
}
}
@@ -1688,7 +1620,7 @@ ftp_retrieve_dirs (struct url *u, struct fileinfo *f, ccon *con)
DEBUGP (("Composing new CWD relative to the initial directory.\n"));
DEBUGP ((" odir = '%s'\n f->name = '%s'\n newdir = '%s'\n\n",
odir, f->name, newdir));
- if (!accdir (newdir, ALLABS))
+ if (!accdir (newdir))
{
logprintf (LOG_VERBOSE, _("\
Not descending to `%s' as it is excluded/not-included.\n"),
@@ -1714,17 +1646,17 @@ Not descending to `%s' as it is excluded/not-included.\n"),
return RETROK;
}
-/* Return non-zero if S has a leading '/' or contains '../' */
-static int
+/* Return true if S has a leading '/' or contains '../' */
+static bool
has_insecure_name_p (const char *s)
{
if (*s == '/')
- return 1;
+ return true;
if (strstr (s, "../") != 0)
- return 1;
+ return true;
- return 0;
+ return false;
}
/* A near-top-level function to retrieve the files in a directory.
@@ -1781,12 +1713,14 @@ ftp_retrieve_glob (struct url *u, ccon *con, int action)
If we are dealing with a globbing pattern, that is. */
if (*u->file && (action == GLOB_GLOBALL || action == GLOB_GETONE))
{
+ int (*matcher) (const char *, const char *, int)
+ = opt.ignore_case ? fnmatch_nocase : fnmatch;
int matchres = 0;
f = start;
while (f)
{
- matchres = fnmatch (u->file, f->name, 0);
+ matchres = matcher (u->file, f->name, 0);
if (matchres == -1)
{
logprintf (LOG_NOTQUIET, "%s: %s\n", con->target,
@@ -1839,14 +1773,14 @@ ftp_retrieve_glob (struct url *u, ccon *con, int action)
of URL. Inherently, its capabilities are limited on what can be
encoded into a URL. */
uerr_t
-ftp_loop (struct url *u, int *dt, struct url *proxy)
+ftp_loop (struct url *u, int *dt, struct url *proxy, bool recursive, bool glob)
{
ccon con; /* FTP connection */
uerr_t res;
*dt = 0;
- memset (&con, 0, sizeof (con));
+ xzero (con);
con.csock = -1;
con.st = ON_YOUR_OWN;
@@ -1857,7 +1791,7 @@ ftp_loop (struct url *u, int *dt, struct url *proxy)
/* If the file name is empty, the user probably wants a directory
index. We'll provide one, properly HTML-ized. Unless
opt.htmlify is 0, of course. :-) */
- if (!*u->file && !opt.recursive)
+ if (!*u->file && !recursive)
{
struct fileinfo *f;
res = ftp_get_listing (u, &con, &f);
@@ -1897,15 +1831,25 @@ ftp_loop (struct url *u, int *dt, struct url *proxy)
}
else
{
- int wild = has_wildcards_p (u->file);
- if ((opt.ftp_glob && wild) || opt.recursive || opt.timestamping)
+ bool ispattern = false;
+ if (glob)
+ {
+ /* Treat the URL as a pattern if the file name part of the
+ URL path contains wildcards. (Don't check for u->file
+ because it is unescaped and therefore doesn't leave users
+ the option to escape literal '*' as %2A.) */
+ char *file_part = strrchr (u->path, '/');
+ if (!file_part)
+ file_part = u->path;
+ ispattern = has_wildcards_p (file_part);
+ }
+ if (ispattern || recursive || opt.timestamping)
{
/* ftp_retrieve_glob is a catch-all function that gets called
if we need globbing, time-stamping or recursion. Its
third argument is just what we really need. */
res = ftp_retrieve_glob (u, &con,
- (opt.ftp_glob && wild)
- ? GLOB_GLOBALL : GLOB_GETONE);
+ ispattern ? GLOB_GLOBALL : GLOB_GETONE);
}
else
res = ftp_loop_internal (u, NULL, &con);