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. */
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+In addition, as a special exception, the Free Software Foundation
+gives permission to link the code of its release of Wget with the
+OpenSSL project's "OpenSSL" library (or with modified versions of it
+that use the same license as the "OpenSSL" library), and distribute
+the linked executables. You must obey the GNU General Public License
+in all respects for all of the code used other than "OpenSSL". If you
+modify this file, you may extend this exception to your version of the
+file, but you are not obligated to do so. If you do not wish to do
+so, delete this exception statement from your version. */
#include <config.h>
enum stype rs; /* remote system reported by ftp server */
char *id; /* initial directory */
char *target; /* target file name */
+ struct url *proxy; /* FTWK-style proxy */
} ccon;
char type_char;
struct address_list *al;
+ char *host = con->proxy ? con->proxy->host : u->host;
+ int port = con->proxy ? con->proxy->port : u->port;
+ char *logname = user;
+
+ if (con->proxy)
+ {
+ /* If proxy is in use, log in as username@target-site. */
+ logname = xmalloc (strlen (user) + 1 + strlen (u->host) + 1);
+ sprintf (logname, "%s@%s", user, u->host);
+ }
+
/* Login to the server: */
/* First: Establish the control connection. */
- al = lookup_host (u->host, 0);
+ al = lookup_host (host, 0);
if (!al)
return HOSTERR;
- set_connection_host_name (u->host);
- csock = connect_to_many (al, u->port, 0);
+ set_connection_host_name (host);
+ csock = connect_to_many (al, port, 0);
set_connection_host_name (NULL);
address_list_release (al);
if (csock < 0)
- return errno == ECONNREFUSED ? CONREFUSED : CONERROR;
+ return CONNECT_ERROR (errno);
if (cmd & LEAVE_PENDING)
rbuf_initialize (&con->rbuf, csock);
logprintf (LOG_VERBOSE, _("Logging in as %s ... "), user);
if (opt.server_response)
logputs (LOG_ALWAYS, "\n");
- err = ftp_login (&con->rbuf, user, passwd);
+ err = ftp_login (&con->rbuf, logname, passwd);
+
+ if (con->proxy)
+ xfree (logname);
+
/* FTPRERR, FTPSRVERR, WRITEFAILED, FTPLOGREFUSED, FTPLOGINC */
switch (err)
{
/* Change working directory. To change to a non-absolute
Unix directory, we need to prepend initial directory
- (con->id) to it. Absolute directories "just work". */
+ (con->id) to it. Absolute directories "just work".
- if (*target != '/')
+ A relative directory is one that does not begin with '/'
+ and, on non-Unix OS'es, one that doesn't begin with
+ "<letter>:". */
+
+ if (target[0] != '/'
+ && !(con->rs != ST_UNIX
+ && ISALPHA (target[0]) && target[1] == ':'))
{
int idlen = strlen (con->id);
- char *ntarget = (char *)alloca (idlen + 1 + strlen (u->dir) + 1);
- /* idlen == 1 means con->id = "/" */
- sprintf (ntarget, "%s%s%s", con->id, idlen == 1 ? "" : "/",
- target);
+ char *ntarget, *p;
+
+ /* Strip trailing slash(es) from con->id. */
+ while (idlen > 0 && con->id[idlen - 1] == '/')
+ --idlen;
+ p = ntarget = (char *)alloca (idlen + 1 + strlen (u->dir) + 1);
+ memcpy (p, con->id, idlen);
+ p += idlen;
+ *p++ = '/';
+ strcpy (p, target);
+
DEBUGP (("Prepended initial PWD to relative path:\n"));
- DEBUGP ((" old: '%s'\n new: '%s'\n", target, ntarget));
+ DEBUGP ((" pwd: '%s'\n old: '%s'\n new: '%s'\n",
+ con->id, target, ntarget));
target = ntarget;
}
logprintf (LOG_VERBOSE, _("couldn't connect to %s:%hu: %s\n"),
pretty_print_address (&passive_addr), passive_port,
strerror (save_errno));
- return save_errno == ECONNREFUSED ? CONREFUSED : CONERROR;
+ return CONNECT_ERROR (save_errno);
}
pasv_mode_open = 1; /* Flag to avoid accept port */
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 (opt.spider)
+ {
+ CLOSE (csock);
+ closeport (dtsock);
+ rbuf_uninitialize (&con->rbuf);
+ return RETRFINISHED;
+ }
+
if (opt.verbose)
{
if (!opt.server_response)
/* Rewind the output document if the download starts over and if
this is the first download. See gethttp() for a longer
explanation. */
- if (!restval && global_download_count == 0)
+ if (!restval && global_download_count == 0 && opt.dfp != stdout)
{
/* This will silently fail for streams that don't correspond
to regular files, but that's OK. */
static uerr_t
ftp_retrieve_glob (struct url *u, ccon *con, int action)
{
- struct fileinfo *orig, *start;
+ struct fileinfo *f, *orig, *start;
uerr_t res;
con->cmd |= LEAVE_PENDING;
opt.accepts and opt.rejects. */
if (opt.accepts || opt.rejects)
{
- struct fileinfo *f = orig;
-
+ f = orig;
while (f)
{
if (f->type != FT_DIRECTORY && !acceptable (f->name))
f = f->next;
}
}
+ /* Remove all files with possible harmful names */
+ f = orig;
+ while (f)
+ {
+ if (has_insecure_name_p(f->name))
+ {
+ logprintf (LOG_VERBOSE, _("Rejecting `%s'.\n"), f->name);
+ f = delelement (f, &start);
+ }
+ else
+ f = f->next;
+ }
/* 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 == GLOBALL || action == GETONE))
{
int matchres = 0;
- struct fileinfo *f = start;
+ f = start;
while (f)
{
matchres = fnmatch (u->file, f->name, 0);
of URL. Inherently, its capabilities are limited on what can be
encoded into a URL. */
uerr_t
-ftp_loop (struct url *u, int *dt)
+ftp_loop (struct url *u, int *dt, struct url *proxy)
{
ccon con; /* FTP connection */
uerr_t res;
con.st = ON_YOUR_OWN;
con.rs = ST_UNIX;
con.id = NULL;
+ con.proxy = proxy;
res = RETROK; /* in case it's not used */
/* If the file name is empty, the user probably wants a directory