X-Git-Url: http://sjero.net/git/?a=blobdiff_plain;f=src%2Fftp-ls.c;h=748bd788a9df591e3388ef49d77bfca09aada6bf;hb=4d7c5e087b2bc82c9f503dff003916d1047903ce;hp=22d1887aaba48ca458321b6e7993b503ce2a81bc;hpb=55587bdee21e6a62df5c85dafaf2303ac9f91e7d;p=wget
diff --git a/src/ftp-ls.c b/src/ftp-ls.c
index 22d1887a..748bd788 100644
--- a/src/ftp-ls.c
+++ b/src/ftp-ls.c
@@ -1,42 +1,48 @@
/* 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 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
+the Free Software Foundation; either version 3 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
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+along with Wget. If not, see .
+
+In addition, as a special exception, the Free Software Foundation
+gives permission to link the code of its release of Wget with the
+OpenSSL project's "OpenSSL" library (or with modified versions of it
+that use the same license as the "OpenSSL" library), and distribute
+the linked executables. You must obey the GNU General Public License
+in all respects for all of the code used other than "OpenSSL". If you
+modify this file, you may extend this exception to your version of the
+file, but you are not obligated to do so. If you do not wish to do
+so, delete this exception statement from your version. */
#include
#include
#include
-#ifdef HAVE_STRING_H
-# include
-#else
-# include
-#endif
+#include
#ifdef HAVE_UNISTD_H
# include
#endif
-#include
#include
+#include
#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
@@ -97,7 +103,7 @@ ftp_parse_unix_ls (const char *file, int ignore_perms)
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");
@@ -109,7 +115,7 @@ ftp_parse_unix_ls (const char *file, int ignore_perms)
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... */
@@ -146,7 +152,7 @@ ftp_parse_unix_ls (const char *file, int ignore_perms)
break;
default:
cur.type = FT_UNKNOWN;
- DEBUGP (("UNKOWN; "));
+ DEBUGP (("UNKNOWN; "));
break;
}
@@ -155,15 +161,16 @@ ftp_parse_unix_ls (const char *file, int ignore_perms)
switch (cur.type)
{
case FT_PLAINFILE:
- cur.perms = 420;
+ cur.perms = 0644;
break;
case FT_DIRECTORY:
- cur.perms = 493;
+ cur.perms = 0755;
break;
default:
- cur.perms = 1023;
+ /*cur.perms = 1023;*/ /* #### What is this? --hniksic */
+ cur.perms = 0644;
}
- DEBUGP (("implicite perms %0o; ", cur.perms));
+ DEBUGP (("implicit perms %0o; ", cur.perms));
}
else
{
@@ -187,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. */
- while ((tok = strtok (NULL, " ")))
+ tok = line;
+ while (ptok = tok,
+ (tok = strtok (NULL, " ")) != NULL)
{
--next;
if (next < 0) /* a month name was not encountered */
@@ -199,17 +208,25 @@ ftp_parse_unix_ls (const char *file, int ignore_perms)
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]));
@@ -309,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' */
- cur.name = (char *)xmalloc (fnlen + 1);
+ cur.name = xmalloc (fnlen + 1);
memcpy (cur.name, tok, fnlen + 1);
if (fnlen)
{
@@ -342,27 +359,27 @@ ftp_parse_unix_ls (const char *file, int ignore_perms)
if (!cur.name || (cur.type == FT_SYMLINK && !cur.linkto))
error = 1;
- DEBUGP (("\n"));
+ DEBUGP (("%s\n", cur.name ? cur.name : ""));
if (error || ignore)
{
DEBUGP (("Skipping.\n"));
- FREE_MAYBE (cur.name);
- FREE_MAYBE (cur.linkto);
+ xfree_null (cur.name);
+ xfree_null (cur.linkto);
xfree (line);
continue;
}
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;
@@ -425,7 +442,7 @@ ftp_parse_winnt_ls (const char *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);
@@ -440,12 +457,17 @@ ftp_parse_winnt_ls (const char *file)
cur.name = xstrdup(tok);
DEBUGP(("Name: '%s'\n", cur.name));
- /* First column: mm-dd-yy */
+ /* First column: mm-dd-yy. Should atoi() on the month fail, january
+ will be assumed. */
tok = strtok(line, "-");
- month = atoi(tok);
+ 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;
@@ -453,12 +475,16 @@ ftp_parse_winnt_ls (const char *file)
/* 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 */
+ /* Adjust hour from AM/PM. Just for the record, the sequence goes
+ 11:00AM, 12:00PM, 01:00PM ... 11:00PM, 12:00AM, 01:00AM . */
tok+=2;
- if (*tok == 'P') hour = (hour + 12) % 24;
+ if (hour == 12) hour = 0;
+ if (*tok == 'P') hour += 12;
DEBUGP(("YYYY/MM/DD HH:MM - %d/%02d/%02d %02d:%02d\n",
year+1900, month, day, hour, min));
@@ -482,20 +508,28 @@ ftp_parse_winnt_ls (const char *file)
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;
cur.size = 0;
- cur.perms = 493; /* my gcc does not like 0755 ?? */
+ cur.perms = 0755;
DEBUGP(("Directory\n"));
}
else
{
+ wgint size;
cur.type = FT_PLAINFILE;
- cur.size = atoi(tok);
- cur.perms = 420; /* 0664 octal */
- DEBUGP(("File, size %ld bytes\n", cur.size));
+ 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 %s bytes\n", number_to_static_string (cur.size)));
}
cur.linkto = NULL;
@@ -503,20 +537,20 @@ ftp_parse_winnt_ls (const char *file)
/* 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);
@@ -561,7 +595,7 @@ ftp_parse_vms_ls (const char *file)
int hour, min, sec;
struct tm timestruct;
- char *line, *tok, *p; /* tokenizer */
+ char *line, *tok; /* tokenizer */
struct fileinfo *dir, *l, cur; /* list creation */
fp = fopen (file, "rb");
@@ -572,18 +606,28 @@ ftp_parse_vms_ls (const char *file)
}
dir = l = NULL;
- /* Empty line */
- read_whole_line (fp);
- /* "Directory PUB$DEVICE[PUB]" */
- read_whole_line (fp);
- /* Empty line */
- read_whole_line (fp);
+ /* Skip empty line. */
+ line = read_whole_line (fp);
+ xfree_null (line);
+
+ /* Skip "Directory PUB$DEVICE[PUB]" */
+ line = read_whole_line (fp);
+ xfree_null (line);
+
+ /* Skip empty line. */
+ line = read_whole_line (fp);
+ 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);
- if (!i) break;
+ if (!i)
+ {
+ xfree (line);
+ break;
+ }
/* First column: Name. A bit of black magic again. The name my be
either ABCD.EXT or ABCD.EXT;NUM and it might be on a separate
@@ -596,7 +640,8 @@ ftp_parse_vms_ls (const char *file)
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';
@@ -640,6 +685,7 @@ ftp_parse_vms_ls (const char *file)
if (!i)
{
DEBUGP(("confusing VMS listing item, leaving listing parser\n"));
+ xfree (line);
break;
}
tok = strtok(line, " ");
@@ -649,6 +695,7 @@ ftp_parse_vms_ls (const char *file)
/* 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, "-");
@@ -659,22 +706,31 @@ ftp_parse_vms_ls (const char *file)
the first strtok(NULL, "-") will return everything until the end
of the line and only the next strtok() call will return NULL. */
DEBUGP(("nonsense in VMS listing, skipping this line\n"));
+ xfree (line);
break;
}
for (i=0; i<12; i++) if (!strcmp(tok,months[i])) break;
/* Uknown months are mapped to January */
- month = (i%12)+1;
- tok = strtok(NULL, " ");
- year = atoi(tok)-1900;
+ 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 = atoi(tok);
- tok = strtok(NULL, ":");
- min = atoi(tok);
- tok = strtok(NULL, " ");
- sec = atoi(tok);
+ /* Fourth/Third column: Time hh:mm[:ss] */
+ tok = strtok (NULL, " ");
+ if (tok == NULL) continue;
+ min = sec = 0;
+ p = tok;
+ hour = atoi (p);
+ for (; *p && *p != ':'; ++p)
+ ;
+ if (*p)
+ min = atoi (++p);
+ for (; *p && *p != ':'; ++p)
+ ;
+ if (*p)
+ sec = atoi (++p);
DEBUGP(("YYYY/MM/DD HH:MM:SS - %d/%02d/%02d %02d:%02d:%02d\n",
year+1900, month, day, hour, min, sec));
@@ -696,14 +752,17 @@ ftp_parse_vms_ls (const char *file)
/* 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)
{
DEBUGP(("confusing VMS permissions, skipping line\n"));
+ xfree (line);
continue;
}
/* Permissons have the format "RWED,RWED,RE" */
@@ -715,14 +774,14 @@ ftp_parse_vms_ls (const char *file)
/* 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;
@@ -748,7 +807,7 @@ ftp_parse_ls (const char *file, const enum stype system_type)
switch (system_type)
{
case ST_UNIX:
- return ftp_parse_unix_ls (file, FALSE);
+ return ftp_parse_unix_ls (file, 0);
case ST_WINNT:
{
/* Detect whether the listing is simulating the UNIX format */
@@ -767,16 +826,16 @@ ftp_parse_ls (const char *file, const enum stype system_type)
if (c >= '0' && c <='9')
return ftp_parse_winnt_ls (file);
else
- return ftp_parse_unix_ls (file, TRUE);
+ return ftp_parse_unix_ls (file, 1);
}
case ST_VMS:
return ftp_parse_vms_ls (file);
case ST_MACOS:
- return ftp_parse_unix_ls (file, TRUE);
+ return ftp_parse_unix_ls (file, 1);
default:
logprintf (LOG_NOTQUIET, _("\
-Usupported listing type, trying Unix listing parser.\n"));
- return ftp_parse_unix_ls (file, FALSE);
+Unsupported listing type, trying Unix listing parser.\n"));
+ return ftp_parse_unix_ls (file, 0);
}
}
@@ -786,13 +845,13 @@ Usupported listing type, trying Unix listing parser.\n"));
directories and files on the appropriate host. The references are
FTP. */
uerr_t
-ftp_index (const char *file, struct urlinfo *u, struct fileinfo *f)
+ftp_index (const char *file, struct url *u, struct fileinfo *f)
{
FILE *fp;
char *upwd;
char *htclfile; /* HTML-clean file name */
- if (!opt.dfp)
+ if (!output_stream)
{
fp = fopen (file, "wb");
if (!fp)
@@ -802,18 +861,19 @@ ftp_index (const char *file, struct urlinfo *u, struct fileinfo *f)
}
}
else
- fp = opt.dfp;
+ fp = output_stream;
if (u->user)
{
char *tmpu, *tmpp; /* temporary, clean user and passwd */
- tmpu = CLEANDUP (u->user);
- tmpp = u->passwd ? CLEANDUP (u->passwd) : NULL;
- upwd = (char *)xmalloc (strlen (tmpu)
- + (tmpp ? (1 + strlen (tmpp)) : 0) + 2);
- sprintf (upwd, "%s%s%s@", tmpu, tmpp ? ":" : "", tmpp ? tmpp : "");
+ tmpu = url_escape (u->user);
+ tmpp = u->passwd ? url_escape (u->passwd) : NULL;
+ if (tmpp)
+ upwd = concat_strings (tmpu, ":", tmpp, "@", (char *) 0);
+ else
+ upwd = concat_strings (tmpu, "@", (char *) 0);
xfree (tmpu);
- FREE_MAYBE (tmpp);
+ xfree_null (tmpp);
}
else
upwd = xstrdup ("");
@@ -828,8 +888,9 @@ ftp_index (const char *file, struct urlinfo *u, struct fileinfo *f)
fprintf (fp, " ");
if (f->tstamp != -1)
{
- /* #### Should we translate the months? */
- static char *months[] = {
+ /* #### Should we translate the months? Or, even better, use
+ ISO 8601 dates? */
+ static const char *months[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
@@ -860,7 +921,7 @@ ftp_index (const char *file, struct urlinfo *u, struct fileinfo *f)
break;
}
htclfile = html_quote_string (f->name);
- fprintf (fp, "host, u->port);
+ fprintf (fp, "host, u->port);
if (*u->dir != '/')
putc ('/', fp);
fprintf (fp, "%s", u->dir);
@@ -874,7 +935,7 @@ ftp_index (const char *file, struct urlinfo *u, struct fileinfo *f)
putc ('/', fp);
fprintf (fp, " ");
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);
@@ -883,7 +944,7 @@ ftp_index (const char *file, struct urlinfo *u, struct fileinfo *f)
}
fprintf (fp, "\n