[svn] Commit my url.c fix (space as unsafe character) and Jan's

winnt directory listing parsing.
This commit is contained in:
hniksic 2000-12-05 14:29:47 -08:00
parent 518fe8d06d
commit 7b5ad90acf
6 changed files with 187 additions and 11 deletions

View File

@ -1,3 +1,8 @@
2000-12-05 Hrvoje Niksic <hniksic@arsdigita.com>
* url.c (init_unsafe_char_table): Reinstate space as an unsafe
char.
2000-11-29 John Summerfield <summer@OS2.ami.com.au>
* netrc.c (parse_netrc): Get rid of line ending.

View File

@ -541,7 +541,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 +577,15 @@ 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
*server_type = ST_OTHER;
xfree (respline);
/* All OK. */

View File

@ -76,7 +76,7 @@ symperms (const char *s)
The time stamps are stored in a separate variable, time_t
compatible (I hope). The timezones are ignored. */
static struct fileinfo *
ftp_parse_unix_ls (const char *file)
ftp_parse_unix_ls (const char *file, int ignore_perms)
{
FILE *fp;
static const char *months[] = {
@ -149,10 +149,28 @@ ftp_parse_unix_ls (const char *file)
break;
}
cur.perms = symperms (tok + 1);
DEBUGP (("perms %0o; ", cur.perms));
if (ignore_perms)
{
switch (cur.type)
{
case FT_PLAINFILE:
cur.perms = 420;
break;
case FT_DIRECTORY:
cur.perms = 493;
break;
default:
cur.perms = 1023;
}
DEBUGP (("implicite perms %0o; ", cur.perms));
}
else
{
cur.perms = symperms (tok + 1);
DEBUGP (("perms %0o; ", cur.perms));
}
error = ignore = 0; /* Errnoeous and ignoring entries are
error = ignore = 0; /* Erroneous and ignoring entries are
treated equally for now. */
year = hour = min = sec = 0; /* Silence the compiler. */
month = day = 0;
@ -385,6 +403,133 @@ ftp_parse_unix_ls (const char *file)
return dir;
}
static struct fileinfo *
ftp_parse_winnt_ls (const char *file)
{
FILE *fp;
int len;
int year, month, day; /* for time analysis */
int hour, min, sec;
struct tm timestruct;
char *line, *tok; /* tokenizer */
struct fileinfo *dir, *l, cur; /* list creation */
fp = fopen (file, "rb");
if (!fp)
{
logprintf (LOG_NOTQUIET, "%s: %s\n", file, strerror (errno));
return NULL;
}
dir = l = NULL;
/* Line loop to end of file: */
while ((line = read_whole_line (fp)))
{
DEBUGP (("%s\n", line));
len = strlen (line);
/* Destroy <CR><LF> if present. */
if (len && line[len - 1] == '\n')
line[--len] = '\0';
if (len && line[len - 1] == '\r')
line[--len] = '\0';
/* Extracting name is a bit of black magic and we have to do it
before `strtok' inserted extra \0 characters in the line
string. For the moment let us just suppose that the name starts at
column 39 of the listing. This way we could also recognize
filenames that begin with a series of space characters (but who
really wants to use such filenames anyway?). */
if (len < 40) continue;
tok = line + 39;
cur.name = xstrdup(tok);
DEBUGP(("Name: '%s'\n", cur.name));
/* First column: mm-dd-yy */
tok = strtok(line, "-");
month = atoi(tok);
tok = strtok(NULL, "-");
day = atoi(tok);
tok = strtok(NULL, " ");
year = atoi(tok);
/* Assuming the epoch starting at 1.1.1970 */
if (year <= 70) year += 100;
/* Second column: hh:mm[AP]M */
tok = strtok(NULL, ":");
hour = atoi(tok);
tok = strtok(NULL, "M");
min = atoi(tok);
/* Adjust hour from AM/PM */
tok+=2;
if (*tok == 'P') hour += 12;
/* Listing does not contain value for seconds */
sec = 0;
DEBUGP(("YYYY/MM/DD HH:MM - %d/%02d/%02d %02d:%02d\n",
year+1900, month, day, hour, min));
/* Build the time-stamp (copy & paste from above) */
timestruct.tm_sec = sec;
timestruct.tm_min = min;
timestruct.tm_hour = hour;
timestruct.tm_mday = day;
timestruct.tm_mon = month;
timestruct.tm_year = year;
timestruct.tm_wday = 0;
timestruct.tm_yday = 0;
timestruct.tm_isdst = -1;
cur.tstamp = mktime (&timestruct); /* store the time-stamp */
DEBUGP(("Timestamp: %ld\n", cur.tstamp));
/* Third column: Either file length, or <DIR>. We also set the
permissions (guessed as 0644 for plain files and 0755 for
directories as the listing does not give us a clue) and filetype
here. */
tok = strtok(NULL, " ");
while (*tok == '\0') tok = strtok(NULL, " ");
if (*tok == '<')
{
cur.type = FT_DIRECTORY;
cur.size = 0;
cur.perms = 493; /* my gcc does not like 0755 ?? */
DEBUGP(("Directory\n"));
}
else
{
cur.type = FT_PLAINFILE;
cur.size = atoi(tok);
cur.perms = 420; /* 0664 octal */
DEBUGP(("File, size %ld bytes\n", cur.size));
}
cur.linkto = NULL;
/* And put everything into the linked list */
if (!dir)
{
l = dir = (struct fileinfo *)xmalloc (sizeof (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 = l->next;
memcpy (l, &cur, sizeof (cur));
l->next = NULL;
}
xfree(line);
}
fclose(fp);
return dir;
}
#ifdef HAVE_FTPPARSE
/* This is a "glue function" that connects the ftpparse interface to
@ -477,12 +622,31 @@ ftp_parse_nonunix_ls (const char *file)
struct fileinfo *
ftp_parse_ls (const char *file, const enum stype system_type)
{
if (system_type == ST_UNIX)
switch (system_type)
{
return ftp_parse_unix_ls (file);
case ST_UNIX:
return ftp_parse_unix_ls (file, FALSE);
case ST_WINNT:
{
/* Detect whether the listing is simulating the UNIX format */
FILE *fp;
int c;
fp = fopen (file, "rb");
if (!fp)
{
logprintf (LOG_NOTQUIET, "%s: %s\n", file, strerror (errno));
return NULL;
}
c = fgetc(fp);
fclose(fp);
/* If the first character of the file is '0'-'9', it's WINNT
format. */
if (c >= '0' && c <='9')
return ftp_parse_winnt_ls (file);
else
{
return ftp_parse_unix_ls (file, TRUE);
}
default:
#ifdef HAVE_FTPPARSE
return ftp_parse_nonunix_ls (file);
#else

View File

@ -353,6 +353,7 @@ Error in server response, closing control connection.\n"));
/* 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);
@ -375,6 +376,7 @@ Error in server response, closing control connection.\n"));
}
break;
case ST_UNIX:
case ST_WINNT:
/* pwd_len == 1 means pwd = "/", but u->dir begins with '/'
already */
if (pwd_len > 1)

View File

@ -26,6 +26,7 @@ enum stype
{
ST_UNIX,
ST_VMS,
ST_WINNT,
ST_OTHER
};

View File

@ -176,6 +176,7 @@ init_unsafe_char_table (void)
int i;
for (i = 0; i < 256; i++)
if (i < 32 || i >= 127
|| i == ' '
|| i == '<'
|| i == '>'
|| i == '\"'