]> sjero.net Git - wget/blobdiff - src/ftp-ls.c
[svn] Merge of fix for bugs 20341 and 20410.
[wget] / src / ftp-ls.c
index d1172de520f9ddf1dc64d7854bd7a5879d43b7f6..748bd788a9df591e3388ef49d77bfca09aada6bf 100644 (file)
@@ -1,12 +1,11 @@
 /* Parsing FTP `ls' output.
 /* Parsing FTP `ls' output.
-   Copyright (C) 1995, 1996, 1997, 2000, 2001
-   Free Software Foundation, Inc. 
+   Copyright (C) 1996-2004 Free Software Foundation, Inc. 
 
 This file is part of GNU Wget.
 
 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
 
 This file is part of GNU Wget.
 
 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
+the Free Software Foundation; either version 3 of the License, or
 (at your option) any later version.
 
 GNU Wget is distributed in the hope that it will be useful,
 (at your option) any later version.
 
 GNU Wget is distributed in the hope that it will be useful,
@@ -15,8 +14,7 @@ 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
 GNU General Public License for more details.
 
 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.
+along with Wget.  If not, see <http://www.gnu.org/licenses/>.
 
 In addition, as a special exception, the Free Software Foundation
 gives permission to link the code of its release of Wget with the
 
 In addition, as a special exception, the Free Software Foundation
 gives permission to link the code of its release of Wget with the
@@ -32,21 +30,19 @@ so, delete this exception statement from your version.  */
 
 #include <stdio.h>
 #include <stdlib.h>
 
 #include <stdio.h>
 #include <stdlib.h>
-#ifdef HAVE_STRING_H
-# include <string.h>
-#else
-# include <strings.h>
-#endif
+#include <string.h>
 #ifdef HAVE_UNISTD_H
 # include <unistd.h>
 #endif
 #ifdef HAVE_UNISTD_H
 # include <unistd.h>
 #endif
-#include <sys/types.h>
 #include <errno.h>
 #include <errno.h>
+#include <time.h>
 
 #include "wget.h"
 #include "utils.h"
 #include "ftp.h"
 #include "url.h"
 
 #include "wget.h"
 #include "utils.h"
 #include "ftp.h"
 #include "url.h"
+#include "convert.h"           /* for html_quote_string prototype */
+#include "retr.h"              /* for output_stream */
 
 /* Converts symbolic permissions to number-style ones, e.g. string
    rwxr-xr-x to 755.  For now, it knows nothing of
 
 /* Converts symbolic permissions to number-style ones, e.g. string
    rwxr-xr-x to 755.  For now, it knows nothing of
@@ -107,7 +103,7 @@ ftp_parse_unix_ls (const char *file, int ignore_perms)
   struct tm timestruct, *tnow;
   time_t timenow;
 
   struct tm timestruct, *tnow;
   time_t timenow;
 
-  char *line, *tok;            /* tokenizer */
+  char *line, *tok, *ptok;     /* tokenizer */
   struct fileinfo *dir, *l, cur; /* list creation */
 
   fp = fopen (file, "rb");
   struct fileinfo *dir, *l, cur; /* list creation */
 
   fp = fopen (file, "rb");
@@ -119,7 +115,7 @@ ftp_parse_unix_ls (const char *file, int ignore_perms)
   dir = l = NULL;
 
   /* Line loop to end of file: */
   dir = l = NULL;
 
   /* Line loop to end of file: */
-  while ((line = read_whole_line (fp)))
+  while ((line = read_whole_line (fp)) != NULL)
     {
       len = clean_line (line);
       /* Skip if total...  */
     {
       len = clean_line (line);
       /* Skip if total...  */
@@ -198,7 +194,9 @@ ftp_parse_unix_ls (const char *file, int ignore_perms)
         This tactic is quite dubious when it comes to
         internationalization issues (non-English month names), but it
         works for now.  */
         This tactic is quite dubious when it comes to
         internationalization issues (non-English month names), but it
         works for now.  */
-      while ((tok = strtok (NULL, " ")))
+      tok = line;
+      while (ptok = tok,
+            (tok = strtok (NULL, " ")) != NULL)
        {
          --next;
          if (next < 0)         /* a month name was not encountered */
        {
          --next;
          if (next < 0)         /* a month name was not encountered */
@@ -210,17 +208,25 @@ ftp_parse_unix_ls (const char *file, int ignore_perms)
                 size, and the filename is three tokens away.  */
              if (i != 12)
                {
                 size, and the filename is three tokens away.  */
              if (i != 12)
                {
-                 char *t = tok - 2;
-                 long mul = 1;
+                 wgint size;
 
 
-                 for (cur.size = 0; t > line && ISDIGIT (*t); mul *= 10, t--)
-                   cur.size += mul * (*t - '0');
-                 if (t == line)
+                 /* Parse the previous token with str_to_wgint.  */
+                 if (ptok == line)
                    {
                    {
-                     /* Something is seriously wrong.  */
+                     /* Something has gone wrong during parsing. */
                      error = 1;
                      break;
                    }
                      error = 1;
                      break;
                    }
+                 errno = 0;
+                 size = str_to_wgint (ptok, NULL, 10);
+                 if (size == WGINT_MAX && errno == ERANGE)
+                   /* Out of range -- ignore the size.  #### Should
+                      we refuse to start the download.  */
+                   cur.size = 0;
+                 else
+                   cur.size = size;
+                 DEBUGP (("size: %s; ", number_to_static_string(cur.size)));
+
                  month = i;
                  next = 5;
                  DEBUGP (("month: %s; ", months[month]));
                  month = i;
                  next = 5;
                  DEBUGP (("month: %s; ", months[month]));
@@ -320,7 +326,7 @@ ftp_parse_unix_ls (const char *file, int ignore_perms)
                 default -F output.  I believe these cases are very
                 rare.  */
              fnlen = strlen (tok); /* re-calculate `fnlen' */
                 default -F output.  I believe these cases are very
                 rare.  */
              fnlen = strlen (tok); /* re-calculate `fnlen' */
-             cur.name = (char *)xmalloc (fnlen + 1);
+             cur.name = xmalloc (fnlen + 1);
              memcpy (cur.name, tok, fnlen + 1);
              if (fnlen)
                {
              memcpy (cur.name, tok, fnlen + 1);
              if (fnlen)
                {
@@ -353,7 +359,7 @@ ftp_parse_unix_ls (const char *file, int ignore_perms)
       if (!cur.name || (cur.type == FT_SYMLINK && !cur.linkto))
        error = 1;
 
       if (!cur.name || (cur.type == FT_SYMLINK && !cur.linkto))
        error = 1;
 
-      DEBUGP (("\n"));
+      DEBUGP (("%s\n", cur.name ? cur.name : ""));
 
       if (error || ignore)
        {
 
       if (error || ignore)
        {
@@ -366,14 +372,14 @@ ftp_parse_unix_ls (const char *file, int ignore_perms)
 
       if (!dir)
        {
 
       if (!dir)
        {
-         l = dir = (struct fileinfo *)xmalloc (sizeof (struct fileinfo));
+         l = dir = xnew (struct fileinfo);
          memcpy (l, &cur, sizeof (cur));
          l->prev = l->next = NULL;
        }
       else
        {
          cur.prev = l;
          memcpy (l, &cur, sizeof (cur));
          l->prev = l->next = NULL;
        }
       else
        {
          cur.prev = l;
-         l->next = (struct fileinfo *)xmalloc (sizeof (struct fileinfo));
+         l->next = xnew (struct fileinfo);
          l = l->next;
          memcpy (l, &cur, sizeof (cur));
          l->next = NULL;
          l = l->next;
          memcpy (l, &cur, sizeof (cur));
          l->next = NULL;
@@ -436,7 +442,7 @@ ftp_parse_winnt_ls (const char *file)
   dir = l = NULL;
 
   /* Line loop to end of file: */
   dir = l = NULL;
 
   /* Line loop to end of file: */
-  while ((line = read_whole_line (fp)))
+  while ((line = read_whole_line (fp)) != NULL)
     {
       len = clean_line (line);
 
     {
       len = clean_line (line);
 
@@ -454,11 +460,14 @@ ftp_parse_winnt_ls (const char *file)
       /* First column: mm-dd-yy. Should atoi() on the month fail, january
         will be assumed.  */
       tok = strtok(line, "-");
       /* First column: mm-dd-yy. Should atoi() on the month fail, january
         will be assumed.  */
       tok = strtok(line, "-");
+      if (tok == NULL) continue;
       month = atoi(tok) - 1;
       if (month < 0) month = 0;
       tok = strtok(NULL, "-");
       month = atoi(tok) - 1;
       if (month < 0) month = 0;
       tok = strtok(NULL, "-");
+      if (tok == NULL) continue;
       day = atoi(tok);
       tok = strtok(NULL, " ");
       day = atoi(tok);
       tok = strtok(NULL, " ");
+      if (tok == NULL) continue;
       year = atoi(tok);
       /* Assuming the epoch starting at 1.1.1970 */
       if (year <= 70) year += 100;
       year = atoi(tok);
       /* Assuming the epoch starting at 1.1.1970 */
       if (year <= 70) year += 100;
@@ -466,8 +475,10 @@ ftp_parse_winnt_ls (const char *file)
       /* Second column: hh:mm[AP]M, listing does not contain value for
          seconds */
       tok = strtok(NULL,  ":");
       /* Second column: hh:mm[AP]M, listing does not contain value for
          seconds */
       tok = strtok(NULL,  ":");
+      if (tok == NULL) continue;
       hour = atoi(tok);
       tok = strtok(NULL,  "M");
       hour = atoi(tok);
       tok = strtok(NULL,  "M");
+      if (tok == NULL) continue;
       min = atoi(tok);
       /* Adjust hour from AM/PM. Just for the record, the sequence goes
          11:00AM, 12:00PM, 01:00PM ... 11:00PM, 12:00AM, 01:00AM . */
       min = atoi(tok);
       /* Adjust hour from AM/PM. Just for the record, the sequence goes
          11:00AM, 12:00PM, 01:00PM ... 11:00PM, 12:00AM, 01:00AM . */
@@ -497,7 +508,9 @@ ftp_parse_winnt_ls (const char *file)
          directories as the listing does not give us a clue) and filetype
          here. */
       tok = strtok(NULL, " ");
          directories as the listing does not give us a clue) and filetype
          here. */
       tok = strtok(NULL, " ");
-      while (*tok == '\0')  tok = strtok(NULL, " ");
+      if (tok == NULL) continue;
+      while ((tok != NULL) && (*tok == '\0'))  tok = strtok(NULL, " ");
+      if (tok == NULL) continue;
       if (*tok == '<')
        {
          cur.type  = FT_DIRECTORY;
       if (*tok == '<')
        {
          cur.type  = FT_DIRECTORY;
@@ -507,10 +520,16 @@ ftp_parse_winnt_ls (const char *file)
        }
       else
        {
        }
       else
        {
+         wgint size;
          cur.type  = FT_PLAINFILE;
          cur.type  = FT_PLAINFILE;
-         cur.size  = atoi(tok);
+         errno = 0;
+         size = str_to_wgint (tok, NULL, 10);
+         if (size == WGINT_MAX && errno == ERANGE)
+           cur.size = 0;       /* overflow */
+         else
+           cur.size = size;
          cur.perms = 0644;
          cur.perms = 0644;
-         DEBUGP(("File, size %ld bytes\n", cur.size));
+         DEBUGP(("File, size %s bytes\n", number_to_static_string (cur.size)));
        }
 
       cur.linkto = NULL;
        }
 
       cur.linkto = NULL;
@@ -518,20 +537,20 @@ ftp_parse_winnt_ls (const char *file)
       /* And put everything into the linked list */
       if (!dir)
        {
       /* And put everything into the linked list */
       if (!dir)
        {
-         l = dir = (struct fileinfo *)xmalloc (sizeof (struct fileinfo));
+         l = dir = xnew (struct fileinfo);
          memcpy (l, &cur, sizeof (cur));
          l->prev = l->next = NULL;
        }
       else
        {
          cur.prev = l;
          memcpy (l, &cur, sizeof (cur));
          l->prev = l->next = NULL;
        }
       else
        {
          cur.prev = l;
-         l->next = (struct fileinfo *)xmalloc (sizeof (struct fileinfo));
+         l->next = xnew (struct fileinfo);
          l = l->next;
          memcpy (l, &cur, sizeof (cur));
          l->next = NULL;
        }
 
          l = l->next;
          memcpy (l, &cur, sizeof (cur));
          l->next = NULL;
        }
 
-      xfree(line);
+      xfree (line);
     }
 
   fclose(fp);
     }
 
   fclose(fp);
@@ -589,21 +608,18 @@ ftp_parse_vms_ls (const char *file)
 
   /* Skip empty line. */
   line = read_whole_line (fp);
 
   /* Skip empty line. */
   line = read_whole_line (fp);
-  if (line)
-    xfree (line);
+  xfree_null (line);
 
   /* Skip "Directory PUB$DEVICE[PUB]" */
   line = read_whole_line (fp);
 
   /* Skip "Directory PUB$DEVICE[PUB]" */
   line = read_whole_line (fp);
-  if (line)
-    xfree (line);
+  xfree_null (line);
 
   /* Skip empty line. */
   line = read_whole_line (fp);
 
   /* Skip empty line. */
   line = read_whole_line (fp);
-  if (line)
-    xfree (line);
+  xfree_null (line);
 
   /* Line loop to end of file: */
 
   /* Line loop to end of file: */
-  while ((line = read_whole_line (fp)))
+  while ((line = read_whole_line (fp)) != NULL)
     {
       char *p;
       i = clean_line (line);
     {
       char *p;
       i = clean_line (line);
@@ -624,7 +640,8 @@ ftp_parse_vms_ls (const char *file)
       tok = strtok(line, " ");
       if (tok == NULL) tok = line;
       DEBUGP(("file name: '%s'\n", tok));
       tok = strtok(line, " ");
       if (tok == NULL) tok = line;
       DEBUGP(("file name: '%s'\n", tok));
-      for (p = tok ; *p && *p != ';' ; p++);
+      for (p = tok ; *p && *p != ';' ; p++)
+       ;
       if (*p == ';') *p = '\0';
       p   = tok + strlen(tok) - 4;
       if (!strcmp(p, ".DIR")) *p = '\0';
       if (*p == ';') *p = '\0';
       p   = tok + strlen(tok) - 4;
       if (!strcmp(p, ".DIR")) *p = '\0';
@@ -678,6 +695,7 @@ ftp_parse_vms_ls (const char *file)
       /* Third/Second column: Date DD-MMM-YYYY. */
 
       tok = strtok(NULL, "-");
       /* Third/Second column: Date DD-MMM-YYYY. */
 
       tok = strtok(NULL, "-");
+      if (tok == NULL) continue;
       DEBUGP(("day: '%s'\n",tok));
       day = atoi(tok);
       tok = strtok(NULL, "-");
       DEBUGP(("day: '%s'\n",tok));
       day = atoi(tok);
       tok = strtok(NULL, "-");
@@ -695,18 +713,22 @@ ftp_parse_vms_ls (const char *file)
       /* Uknown months are mapped to January */
       month = i % 12 ; 
       tok = strtok (NULL, " ");
       /* Uknown months are mapped to January */
       month = i % 12 ; 
       tok = strtok (NULL, " ");
+      if (tok == NULL) continue;
       year = atoi (tok) - 1900;
       DEBUGP(("date parsed\n"));
 
       /* Fourth/Third column: Time hh:mm[:ss] */
       tok = strtok (NULL, " ");
       year = atoi (tok) - 1900;
       DEBUGP(("date parsed\n"));
 
       /* Fourth/Third column: Time hh:mm[:ss] */
       tok = strtok (NULL, " ");
-      hour = min = sec = 0;
+      if (tok == NULL) continue;
+      min = sec = 0;
       p = tok;
       hour = atoi (p);
       p = tok;
       hour = atoi (p);
-      for (; *p && *p != ':'; ++p);
+      for (; *p && *p != ':'; ++p)
+       ;
       if (*p)
        min = atoi (++p);
       if (*p)
        min = atoi (++p);
-      for (; *p && *p != ':'; ++p);
+      for (; *p && *p != ':'; ++p)
+       ;
       if (*p)
        sec = atoi (++p);
 
       if (*p)
        sec = atoi (++p);
 
@@ -730,10 +752,12 @@ ftp_parse_vms_ls (const char *file)
       /* Skip the fifth column */
 
       tok = strtok(NULL, " ");
       /* Skip the fifth column */
 
       tok = strtok(NULL, " ");
+      if (tok == NULL) continue;
 
       /* Sixth column: Permissions */
 
       tok = strtok(NULL, ","); /* Skip the VMS-specific SYSTEM permissons */
 
       /* Sixth column: Permissions */
 
       tok = strtok(NULL, ","); /* Skip the VMS-specific SYSTEM permissons */
+      if (tok == NULL) continue;
       tok = strtok(NULL, ")");
       if (tok == NULL)
         {
       tok = strtok(NULL, ")");
       if (tok == NULL)
         {
@@ -750,14 +774,14 @@ ftp_parse_vms_ls (const char *file)
       /* And put everything into the linked list */
       if (!dir)
         {
       /* And put everything into the linked list */
       if (!dir)
         {
-          l = dir = (struct fileinfo *)xmalloc (sizeof (struct fileinfo));
+          l = dir = xnew (struct fileinfo);
           memcpy (l, &cur, sizeof (cur));
           l->prev = l->next = NULL;
         }
       else
         {
           cur.prev = l;
           memcpy (l, &cur, sizeof (cur));
           l->prev = l->next = NULL;
         }
       else
         {
           cur.prev = l;
-          l->next = (struct fileinfo *)xmalloc (sizeof (struct fileinfo));
+          l->next = xnew (struct fileinfo);
           l = l->next;
           memcpy (l, &cur, sizeof (cur));
           l->next = NULL;
           l = l->next;
           memcpy (l, &cur, sizeof (cur));
           l->next = NULL;
@@ -827,7 +851,7 @@ ftp_index (const char *file, struct url *u, struct fileinfo *f)
   char *upwd;
   char *htclfile;              /* HTML-clean file name */
 
   char *upwd;
   char *htclfile;              /* HTML-clean file name */
 
-  if (!opt.dfp)
+  if (!output_stream)
     {
       fp = fopen (file, "wb");
       if (!fp)
     {
       fp = fopen (file, "wb");
       if (!fp)
@@ -837,16 +861,17 @@ ftp_index (const char *file, struct url *u, struct fileinfo *f)
        }
     }
   else
        }
     }
   else
-    fp = opt.dfp;
+    fp = output_stream;
   if (u->user)
     {
       char *tmpu, *tmpp;        /* temporary, clean user and passwd */
 
       tmpu = url_escape (u->user);
       tmpp = u->passwd ? url_escape (u->passwd) : NULL;
   if (u->user)
     {
       char *tmpu, *tmpp;        /* temporary, clean user and passwd */
 
       tmpu = url_escape (u->user);
       tmpp = u->passwd ? url_escape (u->passwd) : NULL;
-      upwd = (char *)xmalloc (strlen (tmpu)
-                            + (tmpp ? (1 + strlen (tmpp)) : 0) + 2);
-      sprintf (upwd, "%s%s%s@", tmpu, tmpp ? ":" : "", tmpp ? tmpp : "");
+      if (tmpp)
+       upwd = concat_strings (tmpu, ":", tmpp, "@", (char *) 0);
+      else
+       upwd = concat_strings (tmpu, "@", (char *) 0);
       xfree (tmpu);
       xfree_null (tmpp);
     }
       xfree (tmpu);
       xfree_null (tmpp);
     }
@@ -865,7 +890,7 @@ ftp_index (const char *file, struct url *u, struct fileinfo *f)
        {
          /* #### Should we translate the months?  Or, even better, use
             ISO 8601 dates?  */
        {
          /* #### Should we translate the months?  Or, even better, use
             ISO 8601 dates?  */
-         static char *months[] = {
+         static const char *months[] = {
            "Jan", "Feb", "Mar", "Apr", "May", "Jun",
            "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
          };
            "Jan", "Feb", "Mar", "Apr", "May", "Jun",
            "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
          };
@@ -896,7 +921,7 @@ ftp_index (const char *file, struct url *u, struct fileinfo *f)
          break;
        }
       htclfile = html_quote_string (f->name);
          break;
        }
       htclfile = html_quote_string (f->name);
-      fprintf (fp, "<a href=\"ftp://%s%s:%hu", upwd, u->host, u->port);
+      fprintf (fp, "<a href=\"ftp://%s%s:%d", upwd, u->host, u->port);
       if (*u->dir != '/')
        putc ('/', fp);
       fprintf (fp, "%s", u->dir);
       if (*u->dir != '/')
        putc ('/', fp);
       fprintf (fp, "%s", u->dir);
@@ -910,7 +935,7 @@ ftp_index (const char *file, struct url *u, struct fileinfo *f)
        putc ('/', fp);
       fprintf (fp, "</a> ");
       if (f->type == FT_PLAINFILE)
        putc ('/', fp);
       fprintf (fp, "</a> ");
       if (f->type == FT_PLAINFILE)
-       fprintf (fp, _(" (%s bytes)"), legible (f->size));
+       fprintf (fp, _(" (%s bytes)"), number_to_static_string (f->size));
       else if (f->type == FT_SYMLINK)
        fprintf (fp, "-> %s", f->linkto ? f->linkto : "(nil)");
       putc ('\n', fp);
       else if (f->type == FT_SYMLINK)
        fprintf (fp, "-> %s", f->linkto ? f->linkto : "(nil)");
       putc ('\n', fp);
@@ -919,7 +944,7 @@ ftp_index (const char *file, struct url *u, struct fileinfo *f)
     }
   fprintf (fp, "</pre>\n</body>\n</html>\n");
   xfree (upwd);
     }
   fprintf (fp, "</pre>\n</body>\n</html>\n");
   xfree (upwd);
-  if (!opt.dfp)
+  if (!output_stream)
     fclose (fp);
   else
     fflush (fp);
     fclose (fp);
   else
     fflush (fp);