X-Git-Url: http://sjero.net/git/?p=wget;a=blobdiff_plain;f=src%2Fftp.c;h=2e32c1f03d04b45e9f723706d8e8d7ac1567925d;hp=fed0597c319d5575c04dab6cbdd8f0e6fb416e13;hb=4d7c5e087b2bc82c9f503dff003916d1047903ce;hpb=e911bc29434b7da90446d2ca5304106724d05680
diff --git a/src/ftp.c b/src/ftp.c
index fed0597c..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
@@ -38,6 +36,7 @@ so, delete this exception statement from your version. */
#endif
#include
#include
+#include
#include "wget.h"
#include "utils.h"
@@ -50,16 +49,9 @@ so, delete this exception statement from your version. */
#include "convert.h" /* for downloaded_file */
#include "recur.h" /* for INFINITE_RECURSION */
-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 */
@@ -124,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);
@@ -167,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);
@@ -212,20 +204,20 @@ 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));
}
logputs (LOG_VERBOSE, !authoritative ? _(" (unauthoritative)\n") : "\n");
}
@@ -240,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;
+ bool pasv_mode_open = false;
wgint expected_bytes = 0;
- int rest_failed = 0;
+ bool rest_failed = false;
int flags;
wgint rd_size;
@@ -585,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)
{
@@ -598,7 +591,7 @@ 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"));
@@ -612,7 +605,8 @@ Error in server response, closing control connection.\n"));
abort ();
}
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. */
@@ -656,8 +650,7 @@ Error in server response, closing control connection.\n"));
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)
{
@@ -665,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 */
@@ -765,7 +758,7 @@ Error in server response, closing control connection.\n"));
return err;
case FTPRESTFAIL:
logputs (LOG_VERBOSE, _("\nREST failed, starting from scratch.\n"));
- rest_failed = 1;
+ rest_failed = true;
break;
case FTPOK:
break;
@@ -927,7 +920,7 @@ Error in server response, closing control connection.\n"));
fp = fopen (con->target, "wb");
else
{
- fp = fopen_excl (con->target, 1);
+ fp = fopen_excl (con->target, true);
if (!fp && errno == EEXIST)
{
/* We cannot just invent a new name and use it (which is
@@ -958,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;
@@ -974,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)
@@ -1071,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);
}
@@ -1092,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;
@@ -1162,11 +1149,11 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
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)
@@ -1185,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;
@@ -1226,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. */
@@ -1247,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);
@@ -1306,7 +1293,7 @@ Removing file due to --delete-after in ftp_loop_internal():\n"));
/* 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;
@@ -1366,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;
@@ -1412,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;
@@ -1423,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;
@@ -1434,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)
{
@@ -1494,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;
}
}
@@ -1633,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"),
@@ -1659,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.
@@ -1726,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,
@@ -1784,7 +1773,7 @@ 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;
@@ -1802,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);
@@ -1842,8 +1831,8 @@ ftp_loop (struct url *u, int *dt, struct url *proxy)
}
else
{
- int ispattern = 0;
- if (opt.ftp_glob)
+ 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
@@ -1854,7 +1843,7 @@ ftp_loop (struct url *u, int *dt, struct url *proxy)
file_part = u->path;
ispattern = has_wildcards_p (file_part);
}
- if (ispattern || opt.recursive || opt.timestamping)
+ 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