]> sjero.net Git - wget/blobdiff - src/ftp.c
[svn] Allow match_tail to be case insensitive.
[wget] / src / ftp.c
index c0ded718b718497dac8ca1c3143143bbf08db3cc..ebddf3a06fbfaaf9d8890fbd459452b2ea209bcc 100644 (file)
--- a/src/ftp.c
+++ b/src/ftp.c
@@ -63,6 +63,7 @@ typedef struct
   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;
 
 
@@ -150,15 +151,26 @@ getftp (struct url *u, long *len, long restval, ccon *con)
       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);
 
@@ -178,7 +190,11 @@ getftp (struct url *u, long *len, long restval, ccon *con)
       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)
        {
@@ -367,17 +383,31 @@ Error in server response, closing control connection.\n"));
 
          /* 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;
            }
 
@@ -668,6 +698,18 @@ Error in server response, closing control connection.\n"));
 
   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)
@@ -1629,7 +1671,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)
+ftp_loop (struct url *u, int *dt, struct url *proxy)
 {
   ccon con;                    /* FTP connection */
   uerr_t res;
@@ -1642,6 +1684,7 @@ ftp_loop (struct url *u, int *dt)
   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