/* 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
-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,
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
#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
-#include <sys/types.h>
#include <errno.h>
+#include <time.h>
#include "wget.h"
#include "utils.h"
#include "ftp.h"
#include "url.h"
-
-extern FILE *output_stream;
+#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
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");
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... */
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 */
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;
}
+ 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]));
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)
{
if (!cur.name || (cur.type == FT_SYMLINK && !cur.linkto))
error = 1;
- DEBUGP (("\n"));
+ DEBUGP (("%s\n", cur.name ? cur.name : ""));
if (error || ignore)
{
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;
- l->next = (struct fileinfo *)xmalloc (sizeof (struct fileinfo));
+ l->next = xnew (struct fileinfo);
l = l->next;
memcpy (l, &cur, sizeof (cur));
l->next = NULL;
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);
/* 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, "-");
+ if (tok == NULL) continue;
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;
/* 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");
+ 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 . */
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;
}
else
{
+ wgint size;
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;
- DEBUGP(("File, size %ld bytes\n", cur.size));
+ DEBUGP(("File, size %s bytes\n", number_to_static_string (cur.size)));
}
cur.linkto = NULL;
/* 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;
- l->next = (struct fileinfo *)xmalloc (sizeof (struct fileinfo));
+ l->next = xnew (struct fileinfo);
l = l->next;
memcpy (l, &cur, sizeof (cur));
l->next = NULL;
}
- xfree(line);
+ xfree (line);
}
fclose(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);
- if (line)
- xfree (line);
+ xfree_null (line);
/* Skip empty line. */
line = read_whole_line (fp);
- if (line)
- xfree (line);
+ xfree_null (line);
/* 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);
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';
/* 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, "-");
/* 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, " ");
- hour = min = sec = 0;
+ if (tok == NULL) continue;
+ min = sec = 0;
p = tok;
hour = atoi (p);
- for (; *p && *p != ':'; ++p);
+ for (; *p && *p != ':'; ++p)
+ ;
if (*p)
min = atoi (++p);
- for (; *p && *p != ':'; ++p);
+ for (; *p && *p != ':'; ++p)
+ ;
if (*p)
sec = atoi (++p);
/* Skip the fifth column */
tok = strtok(NULL, " ");
+ if (tok == NULL) continue;
/* Sixth column: Permissions */
tok = strtok(NULL, ","); /* Skip the VMS-specific SYSTEM permissons */
+ if (tok == NULL) continue;
tok = strtok(NULL, ")");
if (tok == NULL)
{
/* 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;
- l->next = (struct fileinfo *)xmalloc (sizeof (struct fileinfo));
+ l->next = xnew (struct fileinfo);
l = l->next;
memcpy (l, &cur, sizeof (cur));
l->next = NULL;
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);
}
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);
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);