]> sjero.net Git - wget/blobdiff - src/ftp.c
[svn] Commit my url.c fix (space as unsafe character) and Jan's
[wget] / src / ftp.c
index 3a19d019b6e4c33947e63bbb8ff19aa2ade3af1b..8ce71fd66b89bdf340d882ce118afc4abbba6d68 100644 (file)
--- a/src/ftp.c
+++ b/src/ftp.c
@@ -1,5 +1,5 @@
 /* File Transfer Protocol support.
-   Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc.
 
 This file is part of Wget.
 
@@ -40,7 +40,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "rbuf.h"
 #include "retr.h"
 #include "ftp.h"
-#include "html.h"
 #include "connect.h"
 #include "host.h"
 #include "fnmatch.h"
@@ -58,6 +57,12 @@ extern int h_errno;
 
 extern char ftp_last_respline[];
 
+/* #### Global variables??  These two should be members of struct
+   ccon!  */
+
+static enum stype host_type=ST_UNIX;
+static char *pwd;
+
 /* Look for regexp "( *[0-9]+ *byte" (literal parenthesis) anywhere in
    the string S, and return the number converted to long, if found, 0
    otherwise.  */
@@ -130,7 +135,7 @@ getftp (const struct urlinfo *u, long *len, long restval, ccon *con)
   search_netrc (u->host, (const char **)&user, (const char **)&passwd, 1);
   user = user ? user : opt.ftp_acc;
   if (!opt.ftp_pass)
-    opt.ftp_pass = xstrdup (ftp_getaddress ());
+    opt.ftp_pass = ftp_getaddress ();
   passwd = passwd ? passwd : opt.ftp_pass;
   assert (user && passwd);
 
@@ -241,7 +246,63 @@ Error in server response, closing control connection.\n"));
          exit (1);
          break;
        }
-      /* Third: Set type to Image (binary).  */
+      /* Third: Get the system type */
+      if (!opt.server_response)
+       logprintf (LOG_VERBOSE, "==> SYST ... ");
+      err = ftp_syst (&con->rbuf, &host_type);
+      /* FTPRERR */
+      switch (err)
+       {
+       case FTPRERR:
+         logputs (LOG_VERBOSE, "\n");
+         logputs (LOG_NOTQUIET, _("\
+Error in server response, closing control connection.\n"));
+         CLOSE (csock);
+         rbuf_uninitialize (&con->rbuf);
+         return err;
+         break;
+       case FTPSRVERR:
+         logputs (LOG_VERBOSE, "\n");
+         logputs (LOG_NOTQUIET,
+                  _("Server error, can't determine system type.\n"));
+         break;
+       case FTPOK:
+         /* Everything is OK.  */
+         break;
+       default:
+         abort ();
+         break;
+       }
+      if (!opt.server_response)
+       logputs (LOG_VERBOSE, _("done.    "));
+
+      /* Fourth: Find the initial ftp directory */
+
+      if (!opt.server_response)
+       logprintf (LOG_VERBOSE, "==> PWD ... ");
+      err = ftp_pwd(&con->rbuf, &pwd);
+      /* FTPRERR */
+      switch (err)
+      {
+       case FTPRERR || FTPSRVERR :
+         logputs (LOG_VERBOSE, "\n");
+         logputs (LOG_NOTQUIET, _("\
+Error in server response, closing control connection.\n"));
+         CLOSE (csock);
+         rbuf_uninitialize (&con->rbuf);
+         return err;
+         break;
+       case FTPOK:
+         /* Everything is OK.  */
+         break;
+       default:
+         abort ();
+         break;
+      }
+      if (!opt.server_response)
+       logputs (LOG_VERBOSE, _("done.\n"));
+
+      /* Fifth: Set the FTP type.  */
       if (!opt.server_response)
        logprintf (LOG_VERBOSE, "==> TYPE %c ... ", TOUPPER (u->ftp_type));
       err = ftp_type (&con->rbuf, TOUPPER (u->ftp_type));
@@ -289,10 +350,58 @@ Error in server response, closing control connection.\n"));
        logputs (LOG_VERBOSE, _("==> CWD not needed.\n"));
       else
        {
-         /* Change working directory.  */
-         if (!opt.server_response)
-           logprintf (LOG_VERBOSE, "==> CWD %s ... ", u->dir);
-         err = ftp_cwd (&con->rbuf, u->dir);
+         /* Change working directory. If the FTP host runs VMS and
+             the path specified is absolute, we will have to convert
+             it to VMS style as VMS does not like leading slashes */
+         DEBUGP (("changing working directory\n"));
+         if (*(u->dir) == '/')
+           {
+             int pwd_len = strlen (pwd);
+             char *result = (char *)alloca (strlen (u->dir) + pwd_len + 10);
+             *result = '\0';
+             switch (host_type)
+               {
+               case ST_VMS:
+                 {
+                   char *tmp_dir, *tmpp;
+                   STRDUP_ALLOCA (tmp_dir, u->dir);
+                   for (tmpp = tmp_dir; *tmpp; tmpp++)
+                     if (*tmpp=='/')
+                       *tmpp = '.';
+                   strcpy (result, pwd);
+                   /* pwd ends with ']', we have to get rid of it */
+                   result[pwd_len - 1]= '\0';
+                   strcat (result, tmp_dir);
+                   strcat (result, "]");
+                 }
+                 break;
+               case ST_UNIX:
+               case ST_WINNT:
+                 /* pwd_len == 1 means pwd = "/", but u->dir begins with '/'
+                    already */
+                 if (pwd_len > 1)
+                   strcpy (result, pwd);
+                 strcat (result, u->dir);
+                 /* These look like debugging messages to me.  */
+#if 0
+                 logprintf (LOG_VERBOSE, "\npwd=\"%s\"", pwd);
+                 logprintf (LOG_VERBOSE, "\nu->dir=\"%s\"", u->dir);
+#endif
+                 break;
+               default:
+                 abort ();
+                 break;
+               }
+             if (!opt.server_response)
+               logprintf (LOG_VERBOSE, "==> CWD %s ... ", result);
+             err = ftp_cwd (&con->rbuf, result);
+           }
+         else
+           {
+             if (!opt.server_response)
+               logprintf (LOG_VERBOSE, "==> CWD %s ... ", u->dir);
+             err = ftp_cwd (&con->rbuf, u->dir);
+           }
          /* FTPRERR, WRITEFAILED, FTPNSFOD */
          switch (err)
            {
@@ -722,7 +831,7 @@ Error in server response, closing control connection.\n"));
     }
   reset_timer ();
   /* Get the contents of the document.  */
-  res = get_contents (dtsock, fp, len, restval, expected_bytes, &con->rbuf);
+  res = get_contents (dtsock, fp, len, restval, expected_bytes, &con->rbuf, 0);
   con->dltime = elapsed_time ();
   tms = time_str (NULL);
   tmrate = rate (*len - restval, con->dltime);
@@ -764,7 +873,7 @@ Error in server response, closing control connection.\n"));
   rbuf_discard (&con->rbuf);
   if (err != FTPOK)
     {
-      free (respline);
+      xfree (respline);
       /* The control connection is decidedly closed.  Print the time
         only if it hasn't already been printed.  */
       if (res != -1)
@@ -784,13 +893,13 @@ Error in server response, closing control connection.\n"));
      become apparent later.  */
   if (*respline != '2')
     {
-      free (respline);
+      xfree (respline);
       if (res != -1)
        logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
       logputs (LOG_NOTQUIET, _("Data transfer aborted.\n"));
       return FTPRETRINT;
     }
-  free (respline);
+  xfree (respline);
 
   if (res == -1)
     {
@@ -822,7 +931,7 @@ Error in server response, closing control connection.\n"));
          while ((line = read_whole_line (fp)))
            {
              logprintf (LOG_ALWAYS, "%s\n", line);
-             free (line);
+             xfree (line);
            }
          fclose (fp);
        }
@@ -936,7 +1045,7 @@ ftp_loop_internal (struct urlinfo *u, struct fileinfo *f, ccon *con)
 #ifdef WINDOWS
          ws_changetitle (hurl, 1);
 #endif
-         free (hurl);
+         xfree (hurl);
        }
       /* Send getftp the proper length, if fileinfo was provided.  */
       if (f)
@@ -1004,7 +1113,7 @@ ftp_loop_internal (struct urlinfo *u, struct fileinfo *f, ccon *con)
          char *hurl = str_url (u->proxy ? u->proxy : u, 1);
          logprintf (LOG_NONVERBOSE, "%s URL: %s [%ld] -> \"%s\" [%d]\n",
                     tms, hurl, len, locf, count);
-         free (hurl);
+         xfree (hurl);
        }
 
       if ((con->cmd & DO_LIST))
@@ -1081,7 +1190,7 @@ ftp_get_listing (struct urlinfo *u, ccon *con)
   err = ftp_loop_internal (u, NULL, con);
   u->local = olocal;
   if (err == RETROK)
-    f = ftp_parse_ls (list_filename);
+    f = ftp_parse_ls (list_filename, host_type);
   else
     f = NULL;
   if (opt.remove_listing)
@@ -1091,7 +1200,7 @@ ftp_get_listing (struct urlinfo *u, ccon *con)
       else
        logprintf (LOG_VERBOSE, _("Removed `%s'.\n"), list_filename);
     }
-  free (list_filename);
+  xfree (list_filename);
   con->cmd &= ~DO_LIST;
   return f;
 }
@@ -1183,8 +1292,17 @@ Server file no newer than local file `%s' -- not retrieving.\n\n"), u->local);
                }
              else if (local_size != f->size)
                {
-                 logprintf (LOG_VERBOSE, _("\
+                 if (host_type == ST_VMS)
+                   {
+                     logprintf (LOG_VERBOSE, _("\
+Cannot compare sizes, remote system is VMS.\n"));
+                     dlthis = 0;
+                   }
+                 else
+                   {
+                     logprintf (LOG_VERBOSE, _("\
 The sizes do not match (local %ld) -- retrieving.\n"), local_size);
+                   }
                }
            }
        }       /* opt.timestamping && f->type == FT_PLAINFILE */
@@ -1281,7 +1399,7 @@ Already have correct symlink %s -> %s\n\n"),
       else
        DEBUGP (("Unrecognized permissions for %s.\n", u->local));
 
-      free (u->local);
+      xfree (u->local);
       u->local = olocal;
       u->file = ofile;
       /* Break on fatals.  */
@@ -1494,7 +1612,7 @@ ftp_loop (struct urlinfo *u, int *dt)
                               _("Wrote HTML-ized index to `%s'.\n"),
                               filename);
                }
-             free (filename);
+             xfree (filename);
            }
          freefileinfo (f);
        }
@@ -1520,6 +1638,8 @@ ftp_loop (struct urlinfo *u, int *dt)
   /* If a connection was left, quench it.  */
   if (rbuf_initialized_p (&con.rbuf))
     CLOSE (RBUF_FD (&con.rbuf));
+  FREE_MAYBE (pwd);
+  pwd = NULL;
   return res;
 }
 
@@ -1532,9 +1652,9 @@ delelement (struct fileinfo *f, struct fileinfo **start)
   struct fileinfo *prev = f->prev;
   struct fileinfo *next = f->next;
 
-  free (f->name);
+  xfree (f->name);
   FREE_MAYBE (f->linkto);
-  free (f);
+  xfree (f);
 
   if (next)
     next->prev = prev;
@@ -1552,10 +1672,10 @@ freefileinfo (struct fileinfo *f)
   while (f)
     {
       struct fileinfo *next = f->next;
-      free (f->name);
+      xfree (f->name);
       if (f->linkto)
-       free (f->linkto);
-      free (f);
+       xfree (f->linkto);
+      xfree (f);
       f = next;
     }
 }