/* File Transfer Protocol support.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
- 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+ 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
This file is part of GNU Wget.
shall include the source code for the parts of OpenSSL used as well
as that of the covered work. */
-#include <config.h>
+#include "wget.h"
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h>
-#include "wget.h"
#include "utils.h"
#include "url.h"
#include "retr.h"
#include "recur.h" /* for INFINITE_RECURSION */
/* File where the "ls -al" listing will be saved. */
+#ifdef MSDOS
+#define LIST_FILENAME "_listing"
+#else
#define LIST_FILENAME ".listing"
+#endif
typedef struct
{
struct url *proxy; /* FTWK-style proxy */
} ccon;
+extern int numurls;
/* Look for regexp "( *[0-9]+ *byte" (literal parenthesis) anywhere in
the string S, and return the number converted to wgint, if found, 0
res = str_to_wgint (s, (char **) &s, 10);
if (!*s)
return 0;
- while (*s && ISSPACE (*s))
+ while (*s && c_isspace (*s))
++s;
if (!*s)
return 0;
- if (TOLOWER (*s) != 'b')
+ if (c_tolower (*s) != 'b')
continue;
if (strncasecmp (s, "byte", 4))
continue;
logprintf (LOG_VERBOSE, " (%s)", human_readable (size));
if (start > 0)
{
- if (start >= 1024)
+ if (size - start >= 1024)
logprintf (LOG_VERBOSE, _(", %s (%s) remaining"),
number_to_static_string (size - start),
human_readable (size - start));
logputs (LOG_VERBOSE, !authoritative ? _(" (unauthoritative)\n") : "\n");
}
+static uerr_t ftp_get_listing (struct url *, ccon *, struct fileinfo **);
+
/* Retrieves a file with denoted parameters through opening an FTP
connection to the server. It always closes the data connection,
and closes the control connection in case of error. */
con->csock = -1;
/* Second: Login with proper USER/PASS sequence. */
- logprintf (LOG_VERBOSE, _("Logging in as %s ... "), escnonprint (user));
+ logprintf (LOG_VERBOSE, _("Logging in as %s ... "),
+ quotearg_style (escape_quoting_style, user));
if (opt.server_response)
logputs (LOG_ALWAYS, "\n");
err = ftp_login (csock, logname, passwd);
if (target[0] != '/'
&& !(con->rs != ST_UNIX
- && ISALPHA (target[0])
+ && c_isalpha (target[0])
&& target[1] == ':')
&& con->rs != ST_OS400)
{
}
if (!opt.server_response)
- logprintf (LOG_VERBOSE, "==> CWD %s ... ", escnonprint (target));
+ logprintf (LOG_VERBOSE, "==> CWD %s ... ",
+ quotearg_style (escape_quoting_style, target));
err = ftp_cwd (csock, target);
/* FTPRERR, WRITEFAILED, FTPNSFOD */
switch (err)
return err;
case FTPNSFOD:
logputs (LOG_VERBOSE, "\n");
- logprintf (LOG_NOTQUIET, _("No such directory `%s'.\n\n"),
- escnonprint (u->dir));
+ logprintf (LOG_NOTQUIET, _("No such directory %s.\n\n"),
+ quote (u->dir));
fd_close (csock);
con->csock = -1;
return err;
if (opt.verbose)
{
if (!opt.server_response)
- logprintf (LOG_VERBOSE, "==> SIZE %s ... ", escnonprint (u->file));
+ logprintf (LOG_VERBOSE, "==> SIZE %s ... ",
+ quotearg_style (escape_quoting_style, u->file));
}
err = ftp_size (csock, u->file, len);
if (cmd & DO_RETR)
{
- /* If we're in spider mode, don't really retrieve anything. The
- fact that we got to this point should be proof enough that
- the file exists, vaguely akin to HTTP's concept of a "HEAD"
- request. */
+ /* If we're in spider mode, don't really retrieve anything except
+ the directory listing and verify whether the given "file" exists. */
if (opt.spider)
{
+ bool exists = false;
+ uerr_t res;
+ struct fileinfo *f;
+ res = ftp_get_listing (u, con, &f);
+ /* Set the DO_RETR command flag again, because it gets unset when
+ calling ftp_get_listing() and would otherwise cause an assertion
+ failure earlier on when this function gets repeatedly called
+ (e.g., when recursing). */
+ con->cmd |= DO_RETR;
+ if (res == RETROK)
+ {
+ while (f)
+ {
+ if (!strcmp (f->name, u->file))
+ {
+ exists = true;
+ break;
+ }
+ f = f->next;
+ }
+ if (exists)
+ {
+ logputs (LOG_VERBOSE, "\n");
+ logprintf (LOG_NOTQUIET, _("File %s exists.\n"),
+ quote (u->file));
+ }
+ else
+ {
+ logputs (LOG_VERBOSE, "\n");
+ logprintf (LOG_NOTQUIET, _("No such file %s.\n"),
+ quote (u->file));
+ }
+ }
fd_close (csock);
con->csock = -1;
fd_close (dtsock);
{
if (restval)
logputs (LOG_VERBOSE, "\n");
- logprintf (LOG_VERBOSE, "==> RETR %s ... ", escnonprint (u->file));
+ logprintf (LOG_VERBOSE, "==> RETR %s ... ",
+ quotearg_style (escape_quoting_style, u->file));
}
}
return err;
case FTPNSFOD:
logputs (LOG_VERBOSE, "\n");
- logprintf (LOG_NOTQUIET, _("No such file `%s'.\n\n"),
- escnonprint (u->file));
+ logprintf (LOG_NOTQUIET, _("No such file %s.\n\n"),
+ quote (u->file));
fd_close (dtsock);
fd_close (local_sock);
return err;
return err;
case FTPNSFOD:
logputs (LOG_VERBOSE, "\n");
- logprintf (LOG_NOTQUIET, _("No such file or directory `%s'.\n\n"),
- ".");
+ logprintf (LOG_NOTQUIET, _("No such file or directory %s.\n\n"),
+ quote ("."));
fd_close (dtsock);
fd_close (local_sock);
return err;
if (opt.backups)
rotate_backups (con->target);
- if (restval)
+ if (restval && !(con->cmd & DO_LIST))
fp = fopen (con->target, "ab");
else if (opt.noclobber || opt.always_rest || opt.timestamping || opt.dirstruct
|| opt.output_document)
char *p = strchr (line, '\0');
while (p > line && (p[-1] == '\n' || p[-1] == '\r'))
*--p = '\0';
- logprintf (LOG_ALWAYS, "%s\n", escnonprint (line));
+ logprintf (LOG_ALWAYS, "%s\n",
+ quotearg_style (escape_quoting_style, line));
xfree (line);
}
fclose (fp);
if (!con->target)
con->target = url_file_name (u);
- if (opt.noclobber && file_exists_p (con->target))
+ /* If the output_document was given, then this check was already done and
+ the file didn't exist. Hence the !opt.output_document */
+ if (opt.noclobber && !opt.output_document && file_exists_p (con->target))
{
logprintf (LOG_VERBOSE,
- _("File `%s' already there; not retrieving.\n"), con->target);
+ _("File %s already there; not retrieving.\n"), quote (con->target));
/* If the file is there, we suppose it's retrieved OK. */
return RETROK;
}
}
/* Decide whether or not to restart. */
- if (opt.always_rest
+ if (con->cmd & DO_LIST)
+ restval = 0;
+ else 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
strcpy (tmp, " ");
if (count > 1)
sprintf (tmp, _("(try:%2d)"), count);
- logprintf (LOG_VERBOSE, "--%s-- %s\n %s => `%s'\n",
- tms, hurl, tmp, locf);
+ logprintf (LOG_VERBOSE, "--%s-- %s\n %s => %s\n",
+ tms, hurl, tmp, quote (locf));
#ifdef WINDOWS
ws_changetitle (hurl);
#endif
con->csock = -1;
}
if (!opt.spider)
- logprintf (LOG_VERBOSE, _("%s (%s) - `%s' saved [%s]\n\n"),
- tms, tmrate, locf, number_to_static_string (len));
+ logprintf (LOG_VERBOSE, _("%s (%s) - %s saved [%s]\n\n"),
+ tms, tmrate, quote (locf), number_to_static_string (len));
if (!opt.verbose && !opt.quiet)
{
/* Need to hide the password from the URL. The `if' is here
number of bytes and files downloaded. */
{
total_downloaded_bytes += len;
- opt.numurls++;
+ numurls++;
}
/* Deletion of listing files is not controlled by --delete-after, but
for instance, may want to know how many bytes and files they've
downloaded through it. */
total_downloaded_bytes += len;
- opt.numurls++;
+ numurls++;
if (opt.delete_after)
{
uf = url_file_name (u);
lf = file_merge (uf, LIST_FILENAME);
xfree (uf);
- DEBUGP ((_("Using `%s' as listing tmp file.\n"), lf));
+ DEBUGP ((_("Using %s as listing tmp file.\n"), quote (lf)));
con->target = lf;
err = ftp_loop_internal (u, NULL, con);
con->target = old_target;
if (err == RETROK)
- *f = ftp_parse_ls (lf, con->rs);
- else
- *f = NULL;
- if (opt.remove_listing)
{
- if (unlink (lf))
- logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
- else
- logprintf (LOG_VERBOSE, _("Removed `%s'.\n"), lf);
+ *f = ftp_parse_ls (lf, con->rs);
+ if (opt.remove_listing)
+ {
+ if (unlink (lf))
+ logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
+ else
+ logprintf (LOG_VERBOSE, _("Removed %s.\n"), quote (lf));
+ }
}
+ else
+ *f = NULL;
xfree (lf);
con->cmd &= ~DO_LIST;
return err;
/* 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);
+Remote file no newer than local file %s -- not retrieving.\n"), quote (con->target));
dlthis = false;
}
else if (eq_size)
{
/* Remote file is newer or sizes cannot be matched */
logprintf (LOG_VERBOSE, _("\
-Remote file is newer than local file `%s' -- retrieving.\n\n"),
- con->target);
+Remote file is newer than local file %s -- retrieving.\n\n"),
+ quote (con->target));
}
else
{
{
logprintf (LOG_VERBOSE, _("\
Already have correct symlink %s -> %s\n\n"),
- con->target, escnonprint (f->linkto));
+ quote (con->target),
+ quote (f->linkto));
dlthis = false;
break;
}
}
}
logprintf (LOG_VERBOSE, _("Creating symlink %s -> %s\n"),
- con->target, escnonprint (f->linkto));
+ quote (con->target), quote (f->linkto));
/* Unlink before creating symlink! */
unlink (con->target);
if (symlink (f->linkto, con->target) == -1)
} /* have f->linkto */
#else /* not HAVE_SYMLINK */
logprintf (LOG_NOTQUIET,
- _("Symlinks not supported, skipping symlink `%s'.\n"),
- con->target);
+ _("Symlinks not supported, skipping symlink %s.\n"),
+ quote (con->target));
#endif /* not HAVE_SYMLINK */
}
else /* opt.retr_symlinks */
break;
case FT_DIRECTORY:
if (!opt.recursive)
- logprintf (LOG_NOTQUIET, _("Skipping directory `%s'.\n"),
- escnonprint (f->name));
+ logprintf (LOG_NOTQUIET, _("Skipping directory %s.\n"),
+ quote (f->name));
break;
case FT_PLAINFILE:
/* Call the retrieve loop. */
break;
case FT_UNKNOWN:
logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),
- escnonprint (f->name));
+ quote (f->name));
break;
} /* switch */
if (!accdir (newdir))
{
logprintf (LOG_VERBOSE, _("\
-Not descending to `%s' as it is excluded/not-included.\n"),
- escnonprint (newdir));
+Not descending to %s as it is excluded/not-included.\n"),
+ quote (newdir));
continue;
}
{
if (f->type != FT_DIRECTORY && !acceptable (f->name))
{
- logprintf (LOG_VERBOSE, _("Rejecting `%s'.\n"),
- escnonprint (f->name));
+ logprintf (LOG_VERBOSE, _("Rejecting %s.\n"),
+ quote (f->name));
f = delelement (f, &start);
}
else
{
if (has_insecure_name_p (f->name))
{
- logprintf (LOG_VERBOSE, _("Rejecting `%s'.\n"),
- escnonprint (f->name));
+ logprintf (LOG_VERBOSE, _("Rejecting %s.\n"),
+ quote (f->name));
f = delelement (f, &start);
}
else
}
/* Now weed out the files that do not match our globbing pattern.
If we are dealing with a globbing pattern, that is. */
- if (*u->file && (action == GLOB_GLOBALL || action == GLOB_GETONE))
+ if (*u->file)
{
- int (*matcher) (const char *, const char *, int)
- = opt.ignore_case ? fnmatch_nocase : fnmatch;
- int matchres = 0;
-
- f = start;
- while (f)
+ if (action == GLOB_GLOBALL)
{
- matchres = matcher (u->file, f->name, 0);
+ int (*matcher) (const char *, const char *, int)
+ = opt.ignore_case ? fnmatch_nocase : fnmatch;
+ int matchres = 0;
+
+ f = start;
+ while (f)
+ {
+ matchres = matcher (u->file, f->name, 0);
+ if (matchres == -1)
+ {
+ logprintf (LOG_NOTQUIET, _("Error matching %s against %s: %s\n"),
+ u->file, quotearg_style (escape_quoting_style, f->name),
+ strerror (errno));
+ break;
+ }
+ if (matchres == FNM_NOMATCH)
+ f = delelement (f, &start); /* delete the element from the list */
+ else
+ f = f->next; /* leave the element in the list */
+ }
if (matchres == -1)
{
- logprintf (LOG_NOTQUIET, "%s: %s\n", con->target,
- strerror (errno));
- break;
+ freefileinfo (start);
+ return RETRBADPATTERN;
}
- if (matchres == FNM_NOMATCH)
- f = delelement (f, &start); /* delete the element from the list */
- else
- f = f->next; /* leave the element in the list */
}
- if (matchres == -1)
+ else if (action == GLOB_GETONE)
{
- freefileinfo (start);
- return RETRBADPATTERN;
+ int (*cmp) (const char *, const char *)
+ = opt.ignore_case ? strcasecmp : strcmp;
+ f = start;
+ while (f)
+ {
+ if (0 != cmp(u->file, f->name))
+ f = delelement (f, &start);
+ else
+ f = f->next;
+ }
}
}
if (start)
/* Just get everything. */
ftp_retrieve_list (u, start, con);
}
- else if (!start)
+ else
{
if (action == GLOB_GLOBALL)
{
/* No luck. */
/* #### This message SUCKS. We should see what was the
reason that nothing was retrieved. */
- logprintf (LOG_VERBOSE, _("No matches on pattern `%s'.\n"),
- escnonprint (u->file));
+ logprintf (LOG_VERBOSE, _("No matches on pattern %s.\n"),
+ quote (u->file));
}
else /* GLOB_GETONE or GLOB_GETALL */
{
else
sz = -1;
logprintf (LOG_NOTQUIET,
- _("Wrote HTML-ized index to `%s' [%s].\n"),
- filename, number_to_static_string (sz));
+ _("Wrote HTML-ized index to %s [%s].\n"),
+ quote (filename), number_to_static_string (sz));
}
else
logprintf (LOG_NOTQUIET,
- _("Wrote HTML-ized index to `%s'.\n"),
- filename);
+ _("Wrote HTML-ized index to %s.\n"),
+ quote (filename));
}
xfree (filename);
}