]> sjero.net Git - wget/blobdiff - src/ftp-basic.c
[svn] Rewrite parsing and handling of URLs.
[wget] / src / ftp-basic.c
index 1b2680ff89110a37398b5b35a4270607c6537af0..7d36bf267c6f4f3f1ae2a12972dd5a861a10bc4b 100644 (file)
@@ -1,32 +1,33 @@
 /* Basic FTP routines.
    Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc.
 
-This file is part of Wget.
+This file is part of GNU Wget.
 
-This program is free software; you can redistribute it and/or modify
+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
 (at your option) any later version.
 
-This program is distributed in the hope that it will be useful,
+GNU Wget is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 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 this program; if not, write to the Free Software
+along with Wget; if not, write to the Free Software
 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include <config.h>
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <errno.h>
+
 #ifdef HAVE_STRING_H
 # include <string.h>
 #else
 # include <strings.h>
 #endif
-#include <ctype.h>
 #ifdef HAVE_UNISTD_H
 # include <unistd.h>
 #endif
@@ -43,13 +44,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "host.h"
 #include "ftp.h"
 
-#ifndef errno
-extern int errno;
-#endif
-#ifndef h_errno
-extern int h_errno;
-#endif
-
 char ftp_last_respline[128];
 
 \f
@@ -67,33 +61,33 @@ ftp_response (struct rbuf *rbuf, char **line)
   do
     {
       for (i = 0; 1; i++)
-       {
-         int res;
-         if (i > bufsize - 1)
-           *line = (char *)xrealloc (*line, (bufsize <<= 1));
-         res = RBUF_READCHAR (rbuf, *line + i);
-         /* RES is number of bytes read.  */
-         if (res == 1)
-           {
-             if ((*line)[i] == '\n')
-               {
-                 (*line)[i] = '\0';
-                 /* Get rid of \r.  */
-                 if (i > 0 && (*line)[i - 1] == '\r')
-                   (*line)[i - 1] = '\0';
-                 break;
-               }
-           }
-         else
-           return FTPRERR;
-       }
+        {
+          int res;
+          if (i > bufsize - 1)
+            *line = (char *)xrealloc (*line, (bufsize <<= 1));
+          res = RBUF_READCHAR (rbuf, *line + i);
+          /* RES is number of bytes read.  */
+          if (res == 1)
+            {
+              if ((*line)[i] == '\n')
+                {
+                  (*line)[i] = '\0';
+                  /* Get rid of \r.  */
+                  if (i > 0 && (*line)[i - 1] == '\r')
+                    (*line)[i - 1] = '\0';
+                  break;
+                }
+            }
+          else
+            return FTPRERR;
+        }
       if (opt.server_response)
-       logprintf (LOG_ALWAYS, "%s\n", *line);
+        logprintf (LOG_ALWAYS, "%s\n", *line);
       else
-       DEBUGP (("%s\n", *line));
+        DEBUGP (("%s\n", *line));
     }
   while (!(i >= 3 && ISDIGIT (**line) && ISDIGIT ((*line)[1]) &&
-          ISDIGIT ((*line)[2]) && (*line)[3] == ' '));
+           ISDIGIT ((*line)[2]) && (*line)[3] == ' '));
   strncpy (ftp_last_respline, *line, sizeof (ftp_last_respline));
   ftp_last_respline[sizeof (ftp_last_respline) - 1] = '\0';
   return FTPOK;
@@ -106,16 +100,16 @@ static char *
 ftp_request (const char *command, const char *value)
 {
   char *res = (char *)xmalloc (strlen (command)
-                              + (value ? (1 + strlen (value)) : 0)
-                              + 2 + 1);
+                               + (value ? (1 + strlen (value)) : 0)
+                               + 2 + 1);
   sprintf (res, "%s%s%s\r\n", command, value ? " " : "", value ? value : "");
   if (opt.server_response)
     {
       /* Hack: don't print out password.  */
       if (strncmp (res, "PASS", 4) != 0)
-       logprintf (LOG_ALWAYS, "--> %s\n", res);
+        logprintf (LOG_ALWAYS, "--> %s\n", res);
       else
-       logputs (LOG_ALWAYS, "--> PASS Turtle Power!\n");
+        logputs (LOG_ALWAYS, "--> PASS Turtle Power!\n");
     }
   else
     DEBUGP (("\n--> %s\n", res));
@@ -186,31 +180,31 @@ ftp_login (struct rbuf *rbuf, const char *acc, const char *pass)
 
     for (i = 0; i < ARRAY_SIZE (skey_head); i++)
       {
-       if (strncasecmp (skey_head[i], respline, strlen (skey_head[i])) == 0)
-         break;
+        if (strncasecmp (skey_head[i], respline, strlen (skey_head[i])) == 0)
+          break;
       }
     if (i < ARRAY_SIZE (skey_head))
       {
-       const char *cp;
-       int skey_sequence = 0;
-
-       for (cp = respline + strlen (skey_head[i]);
-            '0' <= *cp && *cp <= '9';
-            cp++)
-         {
-           skey_sequence = skey_sequence * 10 + *cp - '0';
-         }
-       if (*cp == ' ')
-         cp++;
-       else
-         {
-         bad:
-           xfree (respline);
-           return FTPLOGREFUSED;
-         }
-       if ((cp = calculate_skey_response (skey_sequence, cp, pass)) == 0)
-         goto bad;
-       pass = cp;
+        const char *cp;
+        int skey_sequence = 0;
+
+        for (cp = respline + strlen (skey_head[i]);
+             '0' <= *cp && *cp <= '9';
+             cp++)
+          {
+            skey_sequence = skey_sequence * 10 + *cp - '0';
+          }
+        if (*cp == ' ')
+          cp++;
+        else
+          {
+          bad:
+            xfree (respline);
+            return FTPLOGREFUSED;
+          }
+        if ((cp = calculate_skey_response (skey_sequence, cp, pass)) == 0)
+          goto bad;
+        pass = cp;
       }
   }
 #endif /* USE_OPIE */
@@ -265,8 +259,8 @@ ftp_port (struct rbuf *rbuf)
   /* Construct the argument of PORT (of the form a,b,c,d,e,f).  */
   bytes = (char *)alloca (6 * 4 + 1);
   sprintf (bytes, "%d,%d,%d,%d,%d,%d", in_addr[0], in_addr[1],
-         in_addr[2], in_addr[3], (unsigned) (port & 0xff00) >> 8,
-         port & 0xff);
+          in_addr[2], in_addr[3], (unsigned) (port & 0xff00) >> 8,
+          port & 0xff);
   /* Send PORT request.  */
   request = ftp_request ("PORT", bytes);
   nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
@@ -333,15 +327,15 @@ ftp_pasv (struct rbuf *rbuf, unsigned char *addr)
     {
       addr[i] = 0;
       for (; ISDIGIT (*s); s++)
-       addr[i] = (*s - '0') + 10 * addr[i];
+        addr[i] = (*s - '0') + 10 * addr[i];
       if (*s == ',')
-       s++;
+        s++;
       else if (i < 5)
-       {
-         /* When on the last number, anything can be a terminator.  */
-         xfree (respline);
-         return FTPINVPASV;
-       }
+        {
+          /* When on the last number, anything can be a terminator.  */
+          xfree (respline);
+          return FTPINVPASV;
+        }
     }
   xfree (respline);
   return FTPOK;
@@ -541,7 +535,7 @@ ftp_list (struct rbuf *rbuf, const char *file)
 
 /* Sends the SYST command to the server. */
 uerr_t
-ftp_syst (struct rbuf *rbuf, enum stype *host_type)
+ftp_syst (struct rbuf *rbuf, enum stype *server_type)
 {
   char *request, *respline;
   int nwritten;
@@ -577,12 +571,18 @@ ftp_syst (struct rbuf *rbuf, enum stype *host_type)
   request = strtok (NULL, " ");
 
   if (!strcasecmp (request, "VMS"))
-    *host_type = ST_VMS;
+    *server_type = ST_VMS;
   else
     if (!strcasecmp (request, "UNIX"))
-      *host_type = ST_UNIX;
+      *server_type = ST_UNIX;
     else
-      *host_type = ST_OTHER;
+      if (!strcasecmp (request, "WINDOWS_NT"))
+        *server_type = ST_WINNT;
+      else
+        if (!strcasecmp (request, "MACOS"))
+          *server_type = ST_MACOS;
+        else
+          *server_type = ST_OTHER;
 
   xfree (respline);
   /* All OK.  */
@@ -633,3 +633,74 @@ ftp_pwd (struct rbuf *rbuf, char **pwd)
   /* All OK.  */
   return FTPOK;
 }
+
+/* Sends the SIZE command to the server, and returns the value in 'size'.
+ * If an error occurs, size is set to zero. */
+uerr_t
+ftp_size (struct rbuf *rbuf, const char *file, long int *size)
+{
+  char *request, *respline;
+  int nwritten;
+  uerr_t err;
+
+  /* Send PWD request.  */
+  request = ftp_request ("SIZE", file);
+  nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
+  if (nwritten < 0)
+    {
+      xfree (request);
+      *size = 0;
+      return WRITEFAILED;
+    }
+  xfree (request);
+  /* Get appropriate response.  */
+  err = ftp_response (rbuf, &respline);
+  if (err != FTPOK)
+    {
+      xfree (respline);
+      *size = 0;
+      return err;
+    }
+  if (*respline == '5')
+    {
+      /* 
+       * Probably means SIZE isn't supported on this server.
+       * Error is nonfatal since SIZE isn't in RFC 959 
+       */
+      xfree (respline);
+      *size = 0;
+      return FTPOK;
+    }
+
+  errno = 0;
+  *size = strtol (respline + 4, NULL, 0);
+  if (errno) 
+    {
+      /* 
+       * Couldn't parse the response for some reason.  On the (few)
+       * tests I've done, the response is 213 <SIZE> with nothing else -
+       * maybe something a bit more resilient is necessary.  It's not a
+       * fatal error, however.
+       */
+      xfree (respline);
+      *size = 0;
+      return FTPOK;
+    }
+
+  xfree (respline);
+  /* All OK.  */
+  return FTPOK;
+}
+
+/* If URL's params are of the form "type=X", return character X.
+   Otherwise, return 'I' (the default type).  */
+char
+ftp_process_type (const char *params)
+{
+  if (params
+      && 0 == strncasecmp (params, "type=", 5)
+      && params[5] != '\0')
+    return TOUPPER (params[5]);
+  else
+    return 'I';
+}