mirror of
https://github.com/moparisthebest/wget
synced 2024-07-03 16:38:41 -04:00
[svn] Committed Jan's ftpparse patch with Hrvoje's modifications.
<sxshf518e72.fsf@florida.arsdigita.de>.
This commit is contained in:
parent
d6a57bc2a6
commit
c3d636db03
@ -1,3 +1,31 @@
|
|||||||
|
2000-11-21 Hrvoje Niksic <hniksic@arsdigita.com>
|
||||||
|
|
||||||
|
* ftp.c (getftp): Reformat Jan's code according to GNU coding
|
||||||
|
standards; remove (debugging?) printf's; use '\0' for the ASCII
|
||||||
|
zero character. Use alloca() instead of malloc() for
|
||||||
|
inter-function temporary allocations.
|
||||||
|
|
||||||
|
2000-11-18 Jan Prikryl <prikryl@cg.tuwien.ac.at>
|
||||||
|
|
||||||
|
* ftpparse.c, ftpparse.h: New files.
|
||||||
|
|
||||||
|
* ftp-ls.c (ftp_parse_ls): Use ftp_parse_unix_ls for UNIX servers
|
||||||
|
only. Use ftp_parse_nonunix_ls otherwise.
|
||||||
|
(ftp_parse_nonunix_ls): Stub to the ftpparse library handling all
|
||||||
|
exotic FTP servers.
|
||||||
|
|
||||||
|
* ftp.h (stype): New enum, distinguishes UNIX, VMS, and "other"
|
||||||
|
FTP servers.
|
||||||
|
|
||||||
|
* ftp.c: New static wariables host_type, pwd, and pwd_len.
|
||||||
|
(getftp): Support for VMS. Support for FTP servers that do not
|
||||||
|
place you in the root directory after login.
|
||||||
|
(ftp_retrieve_list): VMS is silent about the real file size, issue
|
||||||
|
a more appropriate message.
|
||||||
|
(ftp_get_listing): Pass host_type to ftp_parse_ls.
|
||||||
|
|
||||||
|
* ftp-basic.c (ftp_pwd, ftp_syst): New functions.
|
||||||
|
|
||||||
2000-11-21 Hrvoje Niksic <hniksic@arsdigita.com>
|
2000-11-21 Hrvoje Niksic <hniksic@arsdigita.com>
|
||||||
|
|
||||||
* hash.c (hash_table_put): Don't overwrite deleted mappings.
|
* hash.c (hash_table_put): Don't overwrite deleted mappings.
|
||||||
|
@ -57,10 +57,10 @@ MD5_OBJ = @MD5_OBJ@
|
|||||||
OPIE_OBJ = @OPIE_OBJ@
|
OPIE_OBJ = @OPIE_OBJ@
|
||||||
|
|
||||||
OBJ = $(ALLOCA) cmpt$o connect$o fnmatch$o ftp$o ftp-basic$o \
|
OBJ = $(ALLOCA) cmpt$o connect$o fnmatch$o ftp$o ftp-basic$o \
|
||||||
ftp-ls$o $(OPIE_OBJ) getopt$o hash$o headers$o host$o \
|
ftp-ls$o $(OPIE_OBJ) ftpparse$o getopt$o hash$o \
|
||||||
html-parse$o html-url$o http$o init$o log$o main$o \
|
headers$o host$o html-parse$o html-url$o http$o init$o \
|
||||||
$(MD5_OBJ) netrc$o rbuf$o recur$o retr$o snprintf$o \
|
log$o main$o $(MD5_OBJ) netrc$o rbuf$o recur$o retr$o \
|
||||||
url$o utils$o version$o
|
snprintf$o url$o utils$o version$o
|
||||||
|
|
||||||
.SUFFIXES:
|
.SUFFIXES:
|
||||||
.SUFFIXES: .c .o ._c ._o
|
.SUFFIXES: .c .o ._c ._o
|
||||||
|
@ -41,6 +41,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||||||
#include "rbuf.h"
|
#include "rbuf.h"
|
||||||
#include "connect.h"
|
#include "connect.h"
|
||||||
#include "host.h"
|
#include "host.h"
|
||||||
|
#include "ftp.h"
|
||||||
|
|
||||||
#ifndef errno
|
#ifndef errno
|
||||||
extern int errno;
|
extern int errno;
|
||||||
@ -537,3 +538,98 @@ ftp_list (struct rbuf *rbuf, const char *file)
|
|||||||
/* All OK. */
|
/* All OK. */
|
||||||
return FTPOK;
|
return FTPOK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Sends the SYST command to the server. */
|
||||||
|
uerr_t
|
||||||
|
ftp_syst (struct rbuf *rbuf, enum stype *host_type)
|
||||||
|
{
|
||||||
|
char *request, *respline;
|
||||||
|
int nwritten;
|
||||||
|
uerr_t err;
|
||||||
|
|
||||||
|
/* Send SYST request. */
|
||||||
|
request = ftp_request ("SYST", NULL);
|
||||||
|
nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
|
||||||
|
if (nwritten < 0)
|
||||||
|
{
|
||||||
|
free (request);
|
||||||
|
return WRITEFAILED;
|
||||||
|
}
|
||||||
|
free (request);
|
||||||
|
/* Get appropriate response. */
|
||||||
|
err = ftp_response (rbuf, &respline);
|
||||||
|
if (err != FTPOK)
|
||||||
|
{
|
||||||
|
free (respline);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
if (*respline == '5')
|
||||||
|
{
|
||||||
|
free (respline);
|
||||||
|
return FTPSRVERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skip the number (215, but 200 (!!!) in case of VMS) */
|
||||||
|
strtok (respline, " ");
|
||||||
|
|
||||||
|
/* Which system type has been reported (we are interested just in the
|
||||||
|
first word of the server response)? */
|
||||||
|
request = strtok (NULL, " ");
|
||||||
|
|
||||||
|
if (!strcasecmp (request, "VMS"))
|
||||||
|
*host_type = ST_VMS;
|
||||||
|
else
|
||||||
|
if (!strcasecmp (request, "UNIX"))
|
||||||
|
*host_type = ST_UNIX;
|
||||||
|
else
|
||||||
|
*host_type = ST_OTHER;
|
||||||
|
|
||||||
|
free (respline);
|
||||||
|
/* All OK. */
|
||||||
|
return FTPOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sends the PWD command to the server. */
|
||||||
|
uerr_t
|
||||||
|
ftp_pwd (struct rbuf *rbuf, char **pwd)
|
||||||
|
{
|
||||||
|
char *request, *respline;
|
||||||
|
int nwritten;
|
||||||
|
uerr_t err;
|
||||||
|
|
||||||
|
/* Send PWD request. */
|
||||||
|
request = ftp_request ("PWD", NULL);
|
||||||
|
nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
|
||||||
|
if (nwritten < 0)
|
||||||
|
{
|
||||||
|
free (request);
|
||||||
|
return WRITEFAILED;
|
||||||
|
}
|
||||||
|
free (request);
|
||||||
|
/* Get appropriate response. */
|
||||||
|
err = ftp_response (rbuf, &respline);
|
||||||
|
if (err != FTPOK)
|
||||||
|
{
|
||||||
|
free (respline);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
if (*respline == '5')
|
||||||
|
{
|
||||||
|
free (respline);
|
||||||
|
return FTPSRVERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skip the number (257), leading citation mark, trailing citation mark
|
||||||
|
and everything following it. */
|
||||||
|
strtok (respline, "\"");
|
||||||
|
request = strtok (NULL, "\"");
|
||||||
|
|
||||||
|
/* Has the `pwd' been already allocated? Free! */
|
||||||
|
if (*pwd) free (*pwd);
|
||||||
|
|
||||||
|
*pwd = xstrdup (request);
|
||||||
|
|
||||||
|
free (respline);
|
||||||
|
/* All OK. */
|
||||||
|
return FTPOK;
|
||||||
|
}
|
||||||
|
124
src/ftp-ls.c
124
src/ftp-ls.c
@ -1,5 +1,5 @@
|
|||||||
/* Parsing FTP `ls' output.
|
/* Parsing FTP `ls' output.
|
||||||
Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
|
Copyright (C) 1995, 1996, 1997, 2000 Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is part of Wget.
|
This file is part of Wget.
|
||||||
|
|
||||||
@ -38,6 +38,15 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||||||
#include "ftp.h"
|
#include "ftp.h"
|
||||||
#include "url.h"
|
#include "url.h"
|
||||||
|
|
||||||
|
/* Undef this if FTPPARSE is not available. In that case, Wget will
|
||||||
|
still work with Unix FTP servers, which covers most cases. */
|
||||||
|
|
||||||
|
#define HAVE_FTPPARSE
|
||||||
|
|
||||||
|
#ifdef HAVE_FTPPARSE
|
||||||
|
#include "ftpparse.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Converts symbolic permissions to number-style ones, e.g. string
|
/* Converts symbolic permissions to number-style ones, e.g. string
|
||||||
rwxr-xr-x to 755. For now, it knows nothing of
|
rwxr-xr-x to 755. For now, it knows nothing of
|
||||||
setuid/setgid/sticky. ACLs are ignored. */
|
setuid/setgid/sticky. ACLs are ignored. */
|
||||||
@ -376,18 +385,111 @@ ftp_parse_unix_ls (const char *file)
|
|||||||
return dir;
|
return dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function is just a stub. It should actually accept some kind
|
#ifdef HAVE_FTPPARSE
|
||||||
of information what system it is running on -- e.g. FPL_UNIX,
|
|
||||||
FPL_DOS, FPL_NT, FPL_VMS, etc. and a "guess-me" value, like
|
|
||||||
FPL_GUESS. Then it would call the appropriate parsers to fill up
|
|
||||||
fileinfos.
|
|
||||||
|
|
||||||
Since we currently support only the Unix FTP servers, this function
|
/* This is a "glue function" that connects the ftpparse interface to
|
||||||
simply returns the result of ftp_parse_unix_ls(). */
|
the interface Wget expects. ftpparse is used to parse listings
|
||||||
struct fileinfo *
|
from servers other than Unix, like those running VMS or NT. */
|
||||||
ftp_parse_ls (const char *file)
|
|
||||||
|
static struct fileinfo *
|
||||||
|
ftp_parse_nonunix_ls (const char *file)
|
||||||
{
|
{
|
||||||
return ftp_parse_unix_ls (file);
|
FILE *fp;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
char *line; /* 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)))
|
||||||
|
{
|
||||||
|
struct ftpparse 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';
|
||||||
|
|
||||||
|
if (ftpparse(&fp, line, len))
|
||||||
|
{
|
||||||
|
cur.size = fp.size;
|
||||||
|
cur.name = (char *)xmalloc (fp.namelen + 1);
|
||||||
|
memcpy (cur.name, fp.name, fp.namelen);
|
||||||
|
cur.name[fp.namelen] = '\0';
|
||||||
|
DEBUGP (("%s\n", cur.name));
|
||||||
|
/* No links on non-UNIX systems */
|
||||||
|
cur.linkto = NULL;
|
||||||
|
/* ftpparse won't tell us correct permisions. So lets just invent
|
||||||
|
something. */
|
||||||
|
if (fp.flagtrycwd)
|
||||||
|
{
|
||||||
|
cur.type = FT_DIRECTORY;
|
||||||
|
cur.perms = 0755;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cur.type = FT_PLAINFILE;
|
||||||
|
cur.perms = 0644;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
l->tstamp = fp.mtime;
|
||||||
|
}
|
||||||
|
|
||||||
|
free (line);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose (fp);
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* This function switches between the correct parsing routine
|
||||||
|
depending on the SYSTEM_TYPE. If system type is ST_UNIX, we use
|
||||||
|
our home-grown ftp_parse_unix_ls; otherwise, we use our interface
|
||||||
|
to ftpparse, also known as ftp_parse_nonunix_ls. The system type
|
||||||
|
should be based on the result of the "SYST" response of the FTP
|
||||||
|
server. */
|
||||||
|
|
||||||
|
struct fileinfo *
|
||||||
|
ftp_parse_ls (const char *file, const enum stype system_type)
|
||||||
|
{
|
||||||
|
if (system_type == ST_UNIX)
|
||||||
|
{
|
||||||
|
return ftp_parse_unix_ls (file);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef HAVE_FTPPARSE
|
||||||
|
return ftp_parse_nonunix_ls (file);
|
||||||
|
#else
|
||||||
|
/* #### Maybe log some warning here? */
|
||||||
|
return ftp_parse_unix_ls (file);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Stuff for creating FTP index. */
|
/* Stuff for creating FTP index. */
|
||||||
|
131
src/ftp.c
131
src/ftp.c
@ -57,6 +57,10 @@ extern int h_errno;
|
|||||||
|
|
||||||
extern char ftp_last_respline[];
|
extern char ftp_last_respline[];
|
||||||
|
|
||||||
|
static enum stype host_type=ST_UNIX;
|
||||||
|
static char *pwd;
|
||||||
|
static int pwd_len;
|
||||||
|
|
||||||
/* Look for regexp "( *[0-9]+ *byte" (literal parenthesis) anywhere in
|
/* Look for regexp "( *[0-9]+ *byte" (literal parenthesis) anywhere in
|
||||||
the string S, and return the number converted to long, if found, 0
|
the string S, and return the number converted to long, if found, 0
|
||||||
otherwise. */
|
otherwise. */
|
||||||
@ -240,7 +244,64 @@ Error in server response, closing control connection.\n"));
|
|||||||
exit (1);
|
exit (1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* Third: Set type to Image (binary). */
|
/* Third: Get the system type */
|
||||||
|
if (!opt.server_response)
|
||||||
|
logprintf (LOG_VERBOSE, "==> SYST ... ");
|
||||||
|
err = ftp_syst (&con->rbuf, &host_type);
|
||||||
|
/* FTPRERR */
|
||||||
|
switch (err)
|
||||||
|
{
|
||||||
|
case FTPRERR:
|
||||||
|
logputs (LOG_VERBOSE, "\n");
|
||||||
|
logputs (LOG_NOTQUIET, _("\
|
||||||
|
Error in server response, closing control connection.\n"));
|
||||||
|
CLOSE (csock);
|
||||||
|
rbuf_uninitialize (&con->rbuf);
|
||||||
|
return err;
|
||||||
|
break;
|
||||||
|
case FTPSRVERR:
|
||||||
|
logputs (LOG_VERBOSE, "\n");
|
||||||
|
logputs (LOG_NOTQUIET,
|
||||||
|
_("Server error, can't determine system type.\n"));
|
||||||
|
break;
|
||||||
|
case FTPOK:
|
||||||
|
/* Everything is OK. */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!opt.server_response)
|
||||||
|
logputs (LOG_VERBOSE, _("done. "));
|
||||||
|
|
||||||
|
/* Fourth: Find the initial ftp directory */
|
||||||
|
|
||||||
|
if (!opt.server_response)
|
||||||
|
logprintf (LOG_VERBOSE, "==> PWD ... ");
|
||||||
|
err = ftp_pwd(&con->rbuf, &pwd);
|
||||||
|
pwd_len = strlen(pwd);
|
||||||
|
/* FTPRERR */
|
||||||
|
switch (err)
|
||||||
|
{
|
||||||
|
case FTPRERR || FTPSRVERR :
|
||||||
|
logputs (LOG_VERBOSE, "\n");
|
||||||
|
logputs (LOG_NOTQUIET, _("\
|
||||||
|
Error in server response, closing control connection.\n"));
|
||||||
|
CLOSE (csock);
|
||||||
|
rbuf_uninitialize (&con->rbuf);
|
||||||
|
return err;
|
||||||
|
break;
|
||||||
|
case FTPOK:
|
||||||
|
/* Everything is OK. */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!opt.server_response)
|
||||||
|
logputs (LOG_VERBOSE, _("done.\n"));
|
||||||
|
|
||||||
|
/* Fifth: Set the FTP type. */
|
||||||
if (!opt.server_response)
|
if (!opt.server_response)
|
||||||
logprintf (LOG_VERBOSE, "==> TYPE %c ... ", TOUPPER (u->ftp_type));
|
logprintf (LOG_VERBOSE, "==> TYPE %c ... ", TOUPPER (u->ftp_type));
|
||||||
err = ftp_type (&con->rbuf, TOUPPER (u->ftp_type));
|
err = ftp_type (&con->rbuf, TOUPPER (u->ftp_type));
|
||||||
@ -288,10 +349,55 @@ Error in server response, closing control connection.\n"));
|
|||||||
logputs (LOG_VERBOSE, _("==> CWD not needed.\n"));
|
logputs (LOG_VERBOSE, _("==> CWD not needed.\n"));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Change working directory. */
|
/* Change working directory. If the FTP host runs VMS and
|
||||||
if (!opt.server_response)
|
the path specified is absolute, we will have to convert
|
||||||
logprintf (LOG_VERBOSE, "==> CWD %s ... ", u->dir);
|
it to VMS style as VMS does not like leading slashes */
|
||||||
err = ftp_cwd (&con->rbuf, u->dir);
|
if (*(u->dir) == '/')
|
||||||
|
{
|
||||||
|
char *result = (char *)alloca (strlen (u->dir) + pwd_len + 10);
|
||||||
|
*result = '\0';
|
||||||
|
switch (host_type)
|
||||||
|
{
|
||||||
|
case ST_VMS:
|
||||||
|
{
|
||||||
|
char *tmp_dir, *tmpp;
|
||||||
|
STRDUP_ALLOCA (tmp_dir, u->dir);
|
||||||
|
for (tmpp = tmp_dir; *tmpp; tmpp++)
|
||||||
|
if (*tmpp=='/')
|
||||||
|
*tmpp = '.';
|
||||||
|
strcpy (result, pwd);
|
||||||
|
/* pwd ends with ']', we have to get rid of it */
|
||||||
|
result[pwd_len - 1]= '\0';
|
||||||
|
strcat (result, tmp_dir);
|
||||||
|
strcat (result, "]");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ST_UNIX:
|
||||||
|
/* pwd_len == 1 means pwd = "/", but u->dir begins with '/'
|
||||||
|
already */
|
||||||
|
if (pwd_len > 1)
|
||||||
|
strcpy (result, pwd);
|
||||||
|
strcat (result, u->dir);
|
||||||
|
/* These look like debugging messages to me. */
|
||||||
|
#if 0
|
||||||
|
logprintf (LOG_VERBOSE, "\npwd=\"%s\"", pwd);
|
||||||
|
logprintf (LOG_VERBOSE, "\nu->dir=\"%s\"", u->dir);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!opt.server_response)
|
||||||
|
logprintf (LOG_VERBOSE, "==> CWD %s ... ", result);
|
||||||
|
err = ftp_cwd (&con->rbuf, result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!opt.server_response)
|
||||||
|
logprintf (LOG_VERBOSE, "==> CWD %s ... ", u->dir);
|
||||||
|
err = ftp_cwd (&con->rbuf, u->dir);
|
||||||
|
}
|
||||||
/* FTPRERR, WRITEFAILED, FTPNSFOD */
|
/* FTPRERR, WRITEFAILED, FTPNSFOD */
|
||||||
switch (err)
|
switch (err)
|
||||||
{
|
{
|
||||||
@ -1080,7 +1186,7 @@ ftp_get_listing (struct urlinfo *u, ccon *con)
|
|||||||
err = ftp_loop_internal (u, NULL, con);
|
err = ftp_loop_internal (u, NULL, con);
|
||||||
u->local = olocal;
|
u->local = olocal;
|
||||||
if (err == RETROK)
|
if (err == RETROK)
|
||||||
f = ftp_parse_ls (list_filename);
|
f = ftp_parse_ls (list_filename, host_type);
|
||||||
else
|
else
|
||||||
f = NULL;
|
f = NULL;
|
||||||
if (opt.remove_listing)
|
if (opt.remove_listing)
|
||||||
@ -1177,13 +1283,22 @@ ftp_retrieve_list (struct urlinfo *u, struct fileinfo *f, ccon *con)
|
|||||||
if (local_size == f->size && tml >= f->tstamp)
|
if (local_size == f->size && tml >= f->tstamp)
|
||||||
{
|
{
|
||||||
logprintf (LOG_VERBOSE, _("\
|
logprintf (LOG_VERBOSE, _("\
|
||||||
Server file no newer than local file `%s' -- not retrieving.\n\n"), u->local);
|
Server file not newer than local file `%s' -- not retrieving.\n\n"), u->local);
|
||||||
dlthis = 0;
|
dlthis = 0;
|
||||||
}
|
}
|
||||||
else if (local_size != f->size)
|
else if (local_size != f->size)
|
||||||
{
|
{
|
||||||
logprintf (LOG_VERBOSE, _("\
|
if (host_type == ST_VMS)
|
||||||
|
{
|
||||||
|
logprintf (LOG_VERBOSE, _("\
|
||||||
|
Cannot compare sizes, remote system is VMS.\n"));
|
||||||
|
dlthis = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logprintf (LOG_VERBOSE, _("\
|
||||||
The sizes do not match (local %ld) -- retrieving.\n"), local_size);
|
The sizes do not match (local %ld) -- retrieving.\n"), local_size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} /* opt.timestamping && f->type == FT_PLAINFILE */
|
} /* opt.timestamping && f->type == FT_PLAINFILE */
|
||||||
|
14
src/ftp.h
14
src/ftp.h
@ -1,5 +1,5 @@
|
|||||||
/* Declarations for FTP support.
|
/* Declarations for FTP support.
|
||||||
Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
|
Copyright (C) 1995, 1996, 1997, 2000 Free Software Foundation, Inc.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -21,6 +21,14 @@
|
|||||||
/* Need it for struct rbuf. */
|
/* Need it for struct rbuf. */
|
||||||
#include "rbuf.h"
|
#include "rbuf.h"
|
||||||
|
|
||||||
|
/* System types. */
|
||||||
|
enum stype
|
||||||
|
{
|
||||||
|
ST_UNIX,
|
||||||
|
ST_VMS,
|
||||||
|
ST_OTHER
|
||||||
|
};
|
||||||
|
|
||||||
uerr_t ftp_response PARAMS ((struct rbuf *, char **));
|
uerr_t ftp_response PARAMS ((struct rbuf *, char **));
|
||||||
uerr_t ftp_login PARAMS ((struct rbuf *, const char *, const char *));
|
uerr_t ftp_login PARAMS ((struct rbuf *, const char *, const char *));
|
||||||
uerr_t ftp_port PARAMS ((struct rbuf *));
|
uerr_t ftp_port PARAMS ((struct rbuf *));
|
||||||
@ -30,6 +38,8 @@ uerr_t ftp_cwd PARAMS ((struct rbuf *, const char *));
|
|||||||
uerr_t ftp_retr PARAMS ((struct rbuf *, const char *));
|
uerr_t ftp_retr PARAMS ((struct rbuf *, const char *));
|
||||||
uerr_t ftp_rest PARAMS ((struct rbuf *, long));
|
uerr_t ftp_rest PARAMS ((struct rbuf *, long));
|
||||||
uerr_t ftp_list PARAMS ((struct rbuf *, const char *));
|
uerr_t ftp_list PARAMS ((struct rbuf *, const char *));
|
||||||
|
uerr_t ftp_syst PARAMS ((struct rbuf *, enum stype *));
|
||||||
|
uerr_t ftp_pwd PARAMS ((struct rbuf *, char **));
|
||||||
|
|
||||||
struct urlinfo;
|
struct urlinfo;
|
||||||
|
|
||||||
@ -89,7 +99,7 @@ typedef struct
|
|||||||
long dltime; /* time of the download */
|
long dltime; /* time of the download */
|
||||||
} ccon;
|
} ccon;
|
||||||
|
|
||||||
struct fileinfo *ftp_parse_ls PARAMS ((const char *));
|
struct fileinfo *ftp_parse_ls PARAMS ((const char *, enum stype));
|
||||||
uerr_t ftp_loop PARAMS ((struct urlinfo *, int *));
|
uerr_t ftp_loop PARAMS ((struct urlinfo *, int *));
|
||||||
|
|
||||||
uerr_t ftp_index (const char *, struct urlinfo *, struct fileinfo *);
|
uerr_t ftp_index (const char *, struct urlinfo *, struct fileinfo *);
|
||||||
|
411
src/ftpparse.c
Normal file
411
src/ftpparse.c
Normal file
@ -0,0 +1,411 @@
|
|||||||
|
/* This file is not part of Wget proper, but is included here with the
|
||||||
|
permission of the author. If you wish to use Wget without
|
||||||
|
ftpparse, undefine HAVE_FTPPARSE in ftp-ls.c. */
|
||||||
|
|
||||||
|
/* ftpparse.c, ftpparse.h: library for parsing FTP LIST responses
|
||||||
|
D. J. Bernstein, djb@pobox.com
|
||||||
|
19970712 (doc updated 19970810)
|
||||||
|
Commercial use is fine, if you let me know what programs you're using this in.
|
||||||
|
|
||||||
|
Currently covered:
|
||||||
|
EPLF.
|
||||||
|
UNIX ls, with or without gid.
|
||||||
|
Microsoft FTP Service.
|
||||||
|
Windows NT FTP Server.
|
||||||
|
VMS.
|
||||||
|
WFTPD (DOS).
|
||||||
|
NetPresenz (Mac).
|
||||||
|
NetWare.
|
||||||
|
|
||||||
|
Definitely not covered:
|
||||||
|
Long VMS filenames, with information split across two lines.
|
||||||
|
NCSA Telnet FTP server. Has LIST = NLST (and bad NLST for directories).
|
||||||
|
|
||||||
|
Written for maximum portability, but tested only under UNIX so far. */
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
#include "ftpparse.h"
|
||||||
|
|
||||||
|
static long totai(year,month,mday)
|
||||||
|
long year;
|
||||||
|
long month;
|
||||||
|
long mday;
|
||||||
|
{
|
||||||
|
/* adapted from datetime_untai() */
|
||||||
|
/* about 100x faster than typical mktime() */
|
||||||
|
long result;
|
||||||
|
if (month >= 2) month -= 2;
|
||||||
|
else { month += 10; --year; }
|
||||||
|
result = (mday - 1) * 10 + 5 + 306 * month;
|
||||||
|
result /= 10;
|
||||||
|
if (result == 365) { year -= 3; result = 1460; }
|
||||||
|
else result += 365 * (year % 4);
|
||||||
|
year /= 4;
|
||||||
|
result += 1461 * (year % 25);
|
||||||
|
year /= 25;
|
||||||
|
if (result == 36524) { year -= 3; result = 146096; }
|
||||||
|
else { result += 36524 * (year % 4); }
|
||||||
|
year /= 4;
|
||||||
|
result += 146097 * (year - 5);
|
||||||
|
result += 11017;
|
||||||
|
return result * 86400;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flagneedbase = 1;
|
||||||
|
static time_t base; /* time() value on this OS at the beginning of 1970 TAI */
|
||||||
|
static long now; /* current time */
|
||||||
|
static int flagneedcurrentyear = 1;
|
||||||
|
static long currentyear; /* approximation to current year */
|
||||||
|
|
||||||
|
static void initbase()
|
||||||
|
{
|
||||||
|
struct tm *t;
|
||||||
|
if (!flagneedbase) return;
|
||||||
|
|
||||||
|
base = 0;
|
||||||
|
t = gmtime(&base);
|
||||||
|
base = -(totai(t->tm_year + 1900,t->tm_mon,t->tm_mday) + t->tm_hour * 3600 + t->tm_min * 60 + t->tm_sec);
|
||||||
|
/* time_t is assumed to be measured in TAI seconds. */
|
||||||
|
/* base may be slightly off if time_t is measured in UTC seconds. */
|
||||||
|
/* Typical software naively claims to use UTC but actually uses TAI. */
|
||||||
|
flagneedbase = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void initnow()
|
||||||
|
{
|
||||||
|
long day;
|
||||||
|
long year;
|
||||||
|
|
||||||
|
initbase();
|
||||||
|
now = time((time_t *) 0) - base;
|
||||||
|
|
||||||
|
if (flagneedcurrentyear) {
|
||||||
|
/* adapted from datetime_tai() */
|
||||||
|
day = now / 86400;
|
||||||
|
if ((now % 86400) < 0) --day;
|
||||||
|
day -= 11017;
|
||||||
|
year = 5 + day / 146097;
|
||||||
|
day = day % 146097;
|
||||||
|
if (day < 0) { day += 146097; --year; }
|
||||||
|
year *= 4;
|
||||||
|
if (day == 146096) { year += 3; day = 36524; }
|
||||||
|
else { year += day / 36524; day %= 36524; }
|
||||||
|
year *= 25;
|
||||||
|
year += day / 1461;
|
||||||
|
day %= 1461;
|
||||||
|
year *= 4;
|
||||||
|
if (day == 1460) { year += 3; day = 365; }
|
||||||
|
else { year += day / 365; day %= 365; }
|
||||||
|
day *= 10;
|
||||||
|
if ((day + 5) / 306 >= 10) ++year;
|
||||||
|
currentyear = year;
|
||||||
|
flagneedcurrentyear = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* UNIX ls does not show the year for dates in the last six months. */
|
||||||
|
/* So we have to guess the year. */
|
||||||
|
/* Apparently NetWare uses ``twelve months'' instead of ``six months''; ugh. */
|
||||||
|
/* Some versions of ls also fail to show the year for future dates. */
|
||||||
|
static long guesstai(month,mday)
|
||||||
|
long month;
|
||||||
|
long mday;
|
||||||
|
{
|
||||||
|
long year;
|
||||||
|
long t;
|
||||||
|
|
||||||
|
initnow();
|
||||||
|
|
||||||
|
for (year = currentyear - 1;year < currentyear + 100;++year) {
|
||||||
|
t = totai(year,month,mday);
|
||||||
|
if (now - t < 350 * 86400)
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int check(buf,monthname)
|
||||||
|
char *buf;
|
||||||
|
char *monthname;
|
||||||
|
{
|
||||||
|
if ((buf[0] != monthname[0]) && (buf[0] != monthname[0] - 32)) return 0;
|
||||||
|
if ((buf[1] != monthname[1]) && (buf[1] != monthname[1] - 32)) return 0;
|
||||||
|
if ((buf[2] != monthname[2]) && (buf[2] != monthname[2] - 32)) return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *months[12] = {
|
||||||
|
"jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec"
|
||||||
|
} ;
|
||||||
|
|
||||||
|
static int getmonth(buf,len)
|
||||||
|
char *buf;
|
||||||
|
int len;
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
if (len == 3)
|
||||||
|
for (i = 0;i < 12;++i)
|
||||||
|
if (check(buf,months[i])) return i;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long getlong(buf,len)
|
||||||
|
char *buf;
|
||||||
|
int len;
|
||||||
|
{
|
||||||
|
long u = 0;
|
||||||
|
while (len-- > 0)
|
||||||
|
u = u * 10 + (*buf++ - '0');
|
||||||
|
return u;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ftpparse(fp,buf,len)
|
||||||
|
struct ftpparse *fp;
|
||||||
|
char *buf;
|
||||||
|
int len;
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int j;
|
||||||
|
int state;
|
||||||
|
long size;
|
||||||
|
long year;
|
||||||
|
long month;
|
||||||
|
long mday;
|
||||||
|
long hour;
|
||||||
|
long minute;
|
||||||
|
|
||||||
|
fp->name = 0;
|
||||||
|
fp->namelen = 0;
|
||||||
|
fp->flagtrycwd = 0;
|
||||||
|
fp->flagtryretr = 0;
|
||||||
|
fp->sizetype = FTPPARSE_SIZE_UNKNOWN;
|
||||||
|
fp->size = 0;
|
||||||
|
fp->mtimetype = FTPPARSE_MTIME_UNKNOWN;
|
||||||
|
fp->mtime = 0;
|
||||||
|
fp->idtype = FTPPARSE_ID_UNKNOWN;
|
||||||
|
fp->id = 0;
|
||||||
|
fp->idlen = 0;
|
||||||
|
|
||||||
|
if (len < 2) /* an empty name in EPLF, with no info, could be 2 chars */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
switch(*buf) {
|
||||||
|
/* see http://pobox.com/~djb/proto/eplf.txt */
|
||||||
|
/* "+i8388621.29609,m824255902,/,\tdev" */
|
||||||
|
/* "+i8388621.44468,m839956783,r,s10376,\tRFCEPLF" */
|
||||||
|
case '+':
|
||||||
|
i = 1;
|
||||||
|
for (j = 1;j < len;++j) {
|
||||||
|
if (buf[j] == 9) {
|
||||||
|
fp->name = buf + j + 1;
|
||||||
|
fp->namelen = len - j - 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (buf[j] == ',') {
|
||||||
|
switch(buf[i]) {
|
||||||
|
case '/':
|
||||||
|
fp->flagtrycwd = 1;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
fp->flagtryretr = 1;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
fp->sizetype = FTPPARSE_SIZE_BINARY;
|
||||||
|
fp->size = getlong(buf + i + 1,j - i - 1);
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
fp->mtimetype = FTPPARSE_MTIME_LOCAL;
|
||||||
|
initbase();
|
||||||
|
fp->mtime = base + getlong(buf + i + 1,j - i - 1);
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
fp->idtype = FTPPARSE_ID_FULL;
|
||||||
|
fp->id = buf + i + 1;
|
||||||
|
fp->idlen = j - i - 1;
|
||||||
|
}
|
||||||
|
i = j + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* UNIX-style listing, without inum and without blocks */
|
||||||
|
/* "-rw-r--r-- 1 root other 531 Jan 29 03:26 README" */
|
||||||
|
/* "dr-xr-xr-x 2 root other 512 Apr 8 1994 etc" */
|
||||||
|
/* "dr-xr-xr-x 2 root 512 Apr 8 1994 etc" */
|
||||||
|
/* "lrwxrwxrwx 1 root other 7 Jan 25 00:17 bin -> usr/bin" */
|
||||||
|
/* Also produced by Microsoft's FTP servers for Windows: */
|
||||||
|
/* "---------- 1 owner group 1803128 Jul 10 10:18 ls-lR.Z" */
|
||||||
|
/* "d--------- 1 owner group 0 May 9 19:45 Softlib" */
|
||||||
|
/* Also WFTPD for MSDOS: */
|
||||||
|
/* "-rwxrwxrwx 1 noone nogroup 322 Aug 19 1996 message.ftp" */
|
||||||
|
/* Also NetWare: */
|
||||||
|
/* "d [R----F--] supervisor 512 Jan 16 18:53 login" */
|
||||||
|
/* "- [R----F--] rhesus 214059 Oct 20 15:27 cx.exe" */
|
||||||
|
/* Also NetPresenz for the Mac: */
|
||||||
|
/* "-------r-- 326 1391972 1392298 Nov 22 1995 MegaPhone.sit" */
|
||||||
|
/* "drwxrwxr-x folder 2 May 10 1996 network" */
|
||||||
|
case 'b':
|
||||||
|
case 'c':
|
||||||
|
case 'd':
|
||||||
|
case 'l':
|
||||||
|
case 'p':
|
||||||
|
case 's':
|
||||||
|
case '-':
|
||||||
|
|
||||||
|
if (*buf == 'd') fp->flagtrycwd = 1;
|
||||||
|
if (*buf == '-') fp->flagtryretr = 1;
|
||||||
|
if (*buf == 'l') fp->flagtrycwd = fp->flagtryretr = 1;
|
||||||
|
|
||||||
|
state = 1;
|
||||||
|
i = 0;
|
||||||
|
for (j = 1;j < len;++j)
|
||||||
|
if ((buf[j] == ' ') && (buf[j - 1] != ' ')) {
|
||||||
|
switch(state) {
|
||||||
|
case 1: /* skipping perm */
|
||||||
|
state = 2;
|
||||||
|
break;
|
||||||
|
case 2: /* skipping nlink */
|
||||||
|
state = 3;
|
||||||
|
if ((j - i == 6) && (buf[i] == 'f')) /* for NetPresenz */
|
||||||
|
state = 4;
|
||||||
|
break;
|
||||||
|
case 3: /* skipping uid */
|
||||||
|
state = 4;
|
||||||
|
break;
|
||||||
|
case 4: /* getting tentative size */
|
||||||
|
size = getlong(buf + i,j - i);
|
||||||
|
state = 5;
|
||||||
|
break;
|
||||||
|
case 5: /* searching for month, otherwise getting tentative size */
|
||||||
|
month = getmonth(buf + i,j - i);
|
||||||
|
if (month >= 0)
|
||||||
|
state = 6;
|
||||||
|
else
|
||||||
|
size = getlong(buf + i,j - i);
|
||||||
|
break;
|
||||||
|
case 6: /* have size and month */
|
||||||
|
mday = getlong(buf + i,j - i);
|
||||||
|
state = 7;
|
||||||
|
break;
|
||||||
|
case 7: /* have size, month, mday */
|
||||||
|
if ((j - i == 4) && (buf[i + 1] == ':')) {
|
||||||
|
hour = getlong(buf + i,1);
|
||||||
|
minute = getlong(buf + i + 2,2);
|
||||||
|
fp->mtimetype = FTPPARSE_MTIME_REMOTEMINUTE;
|
||||||
|
initbase();
|
||||||
|
fp->mtime = base + guesstai(month,mday) + hour * 3600 + minute * 60;
|
||||||
|
} else if ((j - i == 5) && (buf[i + 2] == ':')) {
|
||||||
|
hour = getlong(buf + i,2);
|
||||||
|
minute = getlong(buf + i + 3,2);
|
||||||
|
fp->mtimetype = FTPPARSE_MTIME_REMOTEMINUTE;
|
||||||
|
initbase();
|
||||||
|
fp->mtime = base + guesstai(month,mday) + hour * 3600 + minute * 60;
|
||||||
|
}
|
||||||
|
else if (j - i >= 4) {
|
||||||
|
year = getlong(buf + i,j - i);
|
||||||
|
fp->mtimetype = FTPPARSE_MTIME_REMOTEDAY;
|
||||||
|
initbase();
|
||||||
|
fp->mtime = base + totai(year,month,mday);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
fp->name = buf + j + 1;
|
||||||
|
fp->namelen = len - j - 1;
|
||||||
|
state = 8;
|
||||||
|
break;
|
||||||
|
case 8: /* twiddling thumbs */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i = j + 1;
|
||||||
|
while ((i < len) && (buf[i] == ' ')) ++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state != 8)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fp->size = size;
|
||||||
|
fp->sizetype = FTPPARSE_SIZE_ASCII;
|
||||||
|
|
||||||
|
if (*buf == 'l')
|
||||||
|
for (i = 0;i + 3 < fp->namelen;++i)
|
||||||
|
if (fp->name[i] == ' ')
|
||||||
|
if (fp->name[i + 1] == '-')
|
||||||
|
if (fp->name[i + 2] == '>')
|
||||||
|
if (fp->name[i + 3] == ' ') {
|
||||||
|
fp->namelen = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* eliminate extra NetWare spaces */
|
||||||
|
if ((buf[1] == ' ') || (buf[1] == '['))
|
||||||
|
if (fp->namelen > 3)
|
||||||
|
if (fp->name[0] == ' ')
|
||||||
|
if (fp->name[1] == ' ')
|
||||||
|
if (fp->name[2] == ' ') {
|
||||||
|
fp->name += 3;
|
||||||
|
fp->namelen -= 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* MultiNet (some spaces removed from examples) */
|
||||||
|
/* "00README.TXT;1 2 30-DEC-1996 17:44 [SYSTEM] (RWED,RWED,RE,RE)" */
|
||||||
|
/* "CORE.DIR;1 1 8-SEP-1996 16:09 [SYSTEM] (RWE,RWE,RE,RE)" */
|
||||||
|
/* and non-MutliNet VMS: */
|
||||||
|
/* "CII-MANUAL.TEX;1 213/216 29-JAN-1996 03:33:12 [ANONYMOU,ANONYMOUS] (RWED,RWED,,)" */
|
||||||
|
for (i = 0;i < len;++i)
|
||||||
|
if (buf[i] == ';')
|
||||||
|
break;
|
||||||
|
if (i < len) {
|
||||||
|
fp->name = buf;
|
||||||
|
fp->namelen = i;
|
||||||
|
if (i > 4)
|
||||||
|
if (buf[i - 4] == '.')
|
||||||
|
if (buf[i - 3] == 'D')
|
||||||
|
if (buf[i - 2] == 'I')
|
||||||
|
if (buf[i - 1] == 'R') {
|
||||||
|
fp->namelen -= 4;
|
||||||
|
fp->flagtrycwd = 1;
|
||||||
|
}
|
||||||
|
if (!fp->flagtrycwd)
|
||||||
|
fp->flagtryretr = 1;
|
||||||
|
while (buf[i] != ' ') if (++i == len) return 0;
|
||||||
|
while (buf[i] == ' ') if (++i == len) return 0;
|
||||||
|
while (buf[i] != ' ') if (++i == len) return 0;
|
||||||
|
while (buf[i] == ' ') if (++i == len) return 0;
|
||||||
|
j = i;
|
||||||
|
while (buf[j] != '-') if (++j == len) return 0;
|
||||||
|
mday = getlong(buf + i,j - i);
|
||||||
|
while (buf[j] == '-') if (++j == len) return 0;
|
||||||
|
i = j;
|
||||||
|
while (buf[j] != '-') if (++j == len) return 0;
|
||||||
|
month = getmonth(buf + i,j - i);
|
||||||
|
if (month < 0) return 0;
|
||||||
|
while (buf[j] == '-') if (++j == len) return 0;
|
||||||
|
i = j;
|
||||||
|
while (buf[j] != ' ') if (++j == len) return 0;
|
||||||
|
year = getlong(buf + i,j - i);
|
||||||
|
while (buf[j] == ' ') if (++j == len) return 0;
|
||||||
|
i = j;
|
||||||
|
while (buf[j] != ':') if (++j == len) return 0;
|
||||||
|
hour = getlong(buf + i,j - i);
|
||||||
|
while (buf[j] == ':') if (++j == len) return 0;
|
||||||
|
i = j;
|
||||||
|
while ((buf[j] != ':') && (buf[j] != ' ')) if (++j == len) return 0;
|
||||||
|
minute = getlong(buf + i,j - i);
|
||||||
|
|
||||||
|
fp->mtimetype = FTPPARSE_MTIME_REMOTEMINUTE;
|
||||||
|
initbase();
|
||||||
|
fp->mtime = base + totai(year,month,mday) + hour * 3600 + minute * 60;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Some useless lines, safely ignored: */
|
||||||
|
/* "Total of 11 Files, 10966 Blocks." (VMS) */
|
||||||
|
/* "total 14786" (UNIX) */
|
||||||
|
/* "DISK$ANONFTP:[ANONYMOUS]" (VMS) */
|
||||||
|
/* "Directory DISK$PCSA:[ANONYM]" (VMS) */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
51
src/ftpparse.h
Normal file
51
src/ftpparse.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#ifndef FTPPARSE_H
|
||||||
|
#define FTPPARSE_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
ftpparse(&fp,buf,len) tries to parse one line of LIST output.
|
||||||
|
|
||||||
|
The line is an array of len characters stored in buf.
|
||||||
|
It should not include the terminating CR LF; so buf[len] is typically CR.
|
||||||
|
|
||||||
|
If ftpparse() can't find a filename, it returns 0.
|
||||||
|
|
||||||
|
If ftpparse() can find a filename, it fills in fp and returns 1.
|
||||||
|
fp is a struct ftpparse, defined below.
|
||||||
|
The name is an array of fp.namelen characters stored in fp.name;
|
||||||
|
fp.name points somewhere within buf.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct ftpparse {
|
||||||
|
char *name; /* not necessarily 0-terminated */
|
||||||
|
int namelen;
|
||||||
|
int flagtrycwd; /* 0 if cwd is definitely pointless, 1 otherwise */
|
||||||
|
int flagtryretr; /* 0 if retr is definitely pointless, 1 otherwise */
|
||||||
|
int sizetype;
|
||||||
|
long size; /* number of octets */
|
||||||
|
int mtimetype;
|
||||||
|
time_t mtime; /* modification time */
|
||||||
|
int idtype;
|
||||||
|
char *id; /* not necessarily 0-terminated */
|
||||||
|
int idlen;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
#define FTPPARSE_SIZE_UNKNOWN 0
|
||||||
|
#define FTPPARSE_SIZE_BINARY 1 /* size is the number of octets in TYPE I */
|
||||||
|
#define FTPPARSE_SIZE_ASCII 2 /* size is the number of octets in TYPE A */
|
||||||
|
|
||||||
|
#define FTPPARSE_MTIME_UNKNOWN 0
|
||||||
|
#define FTPPARSE_MTIME_LOCAL 1 /* time is correct */
|
||||||
|
#define FTPPARSE_MTIME_REMOTEMINUTE 2 /* time zone and secs are unknown */
|
||||||
|
#define FTPPARSE_MTIME_REMOTEDAY 3 /* time zone and time of day are unknown */
|
||||||
|
/*
|
||||||
|
When a time zone is unknown, it is assumed to be GMT. You may want
|
||||||
|
to use localtime() for LOCAL times, along with an indication that the
|
||||||
|
time is correct in the local time zone, and gmtime() for REMOTE* times.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FTPPARSE_ID_UNKNOWN 0
|
||||||
|
#define FTPPARSE_ID_FULL 1 /* unique identifier for files on this FTP server */
|
||||||
|
|
||||||
|
extern int ftpparse();
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user