src/utilfuns/ftpparse.c File Reference

#include <ftpparse.h>
Include dependency graph for ftpparse.c:

Go to the source code of this file.

Functions

static int check (char *buf, char *monthname)
int ftpparse (struct ftpparse *fp, char *buf, int len)
static long getlong (char *buf, int len)
static int getmonth (char *buf, int len)
static long guesstai (long month, long mday)
static void initbase (void)
static void initnow (void)
static long totai (long year, long month, long mday)

Variables

static time_t base
static long currentyear
static int flagneedbase = 1
static int flagneedcurrentyear = 1
static char * months [12]
static long now

Function Documentation

static int check ( char *  buf,
char *  monthname 
) [static]

Definition at line 115 of file ftpparse.c.

00116 {
00117   if ((buf[0] != monthname[0]) && (buf[0] != monthname[0] - 32)) return 0;
00118   if ((buf[1] != monthname[1]) && (buf[1] != monthname[1] - 32)) return 0;
00119   if ((buf[2] != monthname[2]) && (buf[2] != monthname[2] - 32)) return 0;
00120   return 1;
00121 }

int ftpparse ( struct ftpparse fp,
char *  buf,
int  len 
)

Definition at line 144 of file ftpparse.c.

00145 {
00146   int i;
00147   int j;
00148   int state;
00149   long size = 0;
00150   long year;
00151   long month = 0;
00152   long mday = 0;
00153   long hour;
00154   long minute;
00155 
00156   fp->name = 0;
00157   fp->namelen = 0;
00158   fp->flagtrycwd = 0;
00159   fp->flagtryretr = 0;
00160   fp->sizetype = FTPPARSE_SIZE_UNKNOWN;
00161   fp->size = 0;
00162   fp->mtimetype = FTPPARSE_MTIME_UNKNOWN;
00163   fp->mtime = 0;
00164   fp->idtype = FTPPARSE_ID_UNKNOWN;
00165   fp->id = 0;
00166   fp->idlen = 0;
00167 
00168   if (len < 2) /* an empty name in EPLF, with no info, could be 2 chars */
00169     return 0;
00170 
00171   switch(*buf) {
00172     /* see http://pobox.com/~djb/proto/eplf.txt */
00173     /* "+i8388621.29609,m824255902,/,\tdev" */
00174     /* "+i8388621.44468,m839956783,r,s10376,\tRFCEPLF" */
00175     case '+':
00176       i = 1;
00177       for (j = 1;j < len;++j) {
00178         if (buf[j] == 9) {
00179           fp->name = buf + j + 1;
00180           fp->namelen = len - j - 1;
00181           return 1;
00182         }
00183         if (buf[j] == ',') {
00184           switch(buf[i]) {
00185             case '/':
00186               fp->flagtrycwd = 1;
00187               break;
00188             case 'r':
00189               fp->flagtryretr = 1;
00190               break;
00191             case 's':
00192               fp->sizetype = FTPPARSE_SIZE_BINARY;
00193               fp->size = getlong(buf + i + 1,j - i - 1);
00194               break;
00195             case 'm':
00196               fp->mtimetype = FTPPARSE_MTIME_LOCAL;
00197               initbase();
00198               fp->mtime = base + getlong(buf + i + 1,j - i - 1);
00199               break;
00200             case 'i':
00201               fp->idtype = FTPPARSE_ID_FULL;
00202               fp->id = buf + i + 1;
00203               fp->idlen = j - i - 1;
00204           }
00205           i = j + 1;
00206         }
00207       }
00208       return 0;
00209     
00210     /* UNIX-style listing, without inum and without blocks */
00211     /* "-rw-r--r--   1 root     other        531 Jan 29 03:26 README" */
00212     /* "dr-xr-xr-x   2 root     other        512 Apr  8  1994 etc" */
00213     /* "dr-xr-xr-x   2 root     512 Apr  8  1994 etc" */
00214     /* "lrwxrwxrwx   1 root     other          7 Jan 25 00:17 bin -> usr/bin" */
00215     /* Also produced by Microsoft's FTP servers for Windows: */
00216     /* "----------   1 owner    group         1803128 Jul 10 10:18 ls-lR.Z" */
00217     /* "d---------   1 owner    group               0 May  9 19:45 Softlib" */
00218     /* Also WFTPD for MSDOS: */
00219     /* "-rwxrwxrwx   1 noone    nogroup      322 Aug 19  1996 message.ftp" */
00220     /* Also NetWare: */
00221     /* "d [R----F--] supervisor            512       Jan 16 18:53    login" */
00222     /* "- [R----F--] rhesus             214059       Oct 20 15:27    cx.exe" */
00223     /* Also NetPresenz for the Mac: */
00224     /* "-------r--         326  1391972  1392298 Nov 22  1995 MegaPhone.sit" */
00225     /* "drwxrwxr-x               folder        2 May 10  1996 network" */
00226     case 'b':
00227     case 'c':
00228     case 'd':
00229     case 'l':
00230     case 'p':
00231     case 's':
00232     case '-':
00233 
00234       if (*buf == 'd') fp->flagtrycwd = 1;
00235       if (*buf == '-') fp->flagtryretr = 1;
00236       if (*buf == 'l') fp->flagtrycwd = fp->flagtryretr = 1;
00237 
00238       state = 1;
00239       i = 0;
00240       for (j = 1;j < len;++j)
00241         if ((buf[j] == ' ') && (buf[j - 1] != ' ')) {
00242           switch(state) {
00243             case 1: /* skipping perm */
00244               state = 2;
00245               break;
00246             case 2: /* skipping nlink */
00247               state = 3;
00248               if ((j - i == 6) && (buf[i] == 'f')) /* for NetPresenz */
00249                 state = 4;
00250               break;
00251             case 3: /* skipping uid */
00252               state = 4;
00253               break;
00254             case 4: /* getting tentative size */
00255               size = getlong(buf + i,j - i);
00256               state = 5;
00257               break;
00258             case 5: /* searching for month, otherwise getting tentative size */
00259               month = getmonth(buf + i,j - i);
00260               if (month >= 0)
00261                 state = 6;
00262               else
00263                 size = getlong(buf + i,j - i);
00264               break;
00265             case 6: /* have size and month */
00266               mday = getlong(buf + i,j - i);
00267               state = 7;
00268               break;
00269             case 7: /* have size, month, mday */
00270               if ((j - i == 4) && (buf[i + 1] == ':')) {
00271                 hour = getlong(buf + i,1);
00272                 minute = getlong(buf + i + 2,2);
00273                 fp->mtimetype = FTPPARSE_MTIME_REMOTEMINUTE;
00274                 initbase();
00275                 fp->mtime = base + guesstai(month,mday) + hour * 3600 + minute * 60;
00276               } else if ((j - i == 5) && (buf[i + 2] == ':')) {
00277                 hour = getlong(buf + i,2);
00278                 minute = getlong(buf + i + 3,2);
00279                 fp->mtimetype = FTPPARSE_MTIME_REMOTEMINUTE;
00280                 initbase();
00281                 fp->mtime = base + guesstai(month,mday) + hour * 3600 + minute * 60;
00282               }
00283               else if (j - i >= 4) {
00284                 year = getlong(buf + i,j - i);
00285                 fp->mtimetype = FTPPARSE_MTIME_REMOTEDAY;
00286                 initbase();
00287                 fp->mtime = base + totai(year,month,mday);
00288               }
00289               else
00290                 return 0;
00291               fp->name = buf + j + 1;
00292               fp->namelen = len - j - 1;
00293               state = 8;
00294               break;
00295             case 8: /* twiddling thumbs */
00296               break;
00297           }
00298           i = j + 1;
00299           while ((i < len) && (buf[i] == ' ')) ++i;
00300         }
00301 
00302       if (state != 8)
00303         return 0;
00304 
00305       fp->size = size;
00306       fp->sizetype = FTPPARSE_SIZE_BINARY;
00307 
00308       if (*buf == 'l')
00309         for (i = 0;i + 3 < fp->namelen;++i)
00310           if (fp->name[i] == ' ')
00311             if (fp->name[i + 1] == '-')
00312               if (fp->name[i + 2] == '>')
00313                 if (fp->name[i + 3] == ' ') {
00314                   fp->namelen = i;
00315                   break;
00316                 }
00317 
00318       /* eliminate extra NetWare spaces */
00319       if ((buf[1] == ' ') || (buf[1] == '['))
00320         if (fp->namelen > 3)
00321           if (fp->name[0] == ' ')
00322             if (fp->name[1] == ' ')
00323               if (fp->name[2] == ' ') {
00324                 fp->name += 3;
00325                 fp->namelen -= 3;
00326               }
00327 
00328       return 1;
00329   }
00330 
00331   /* MultiNet (some spaces removed from examples) */
00332   /* "00README.TXT;1      2 30-DEC-1996 17:44 [SYSTEM] (RWED,RWED,RE,RE)" */
00333   /* "CORE.DIR;1          1  8-SEP-1996 16:09 [SYSTEM] (RWE,RWE,RE,RE)" */
00334   /* and non-MutliNet VMS: */
00335   /* "CII-MANUAL.TEX;1  213/216  29-JAN-1996 03:33:12  [ANONYMOU,ANONYMOUS]   (RWED,RWED,,)" */
00336   for (i = 0;i < len;++i)
00337     if (buf[i] == ';')
00338       break;
00339   if (i < len) {
00340     fp->name = buf;
00341     fp->namelen = i;
00342     if (i > 4)
00343       if (buf[i - 4] == '.')
00344         if (buf[i - 3] == 'D')
00345           if (buf[i - 2] == 'I')
00346             if (buf[i - 1] == 'R') {
00347               fp->namelen -= 4;
00348               fp->flagtrycwd = 1;
00349             }
00350     if (!fp->flagtrycwd)
00351       fp->flagtryretr = 1;
00352     while (buf[i] != ' ') if (++i == len) return 0;
00353     while (buf[i] == ' ') if (++i == len) return 0;
00354     while (buf[i] != ' ') if (++i == len) return 0;
00355     while (buf[i] == ' ') if (++i == len) return 0;
00356     j = i;
00357     while (buf[j] != '-') if (++j == len) return 0;
00358     mday = getlong(buf + i,j - i);
00359     while (buf[j] == '-') if (++j == len) return 0;
00360     i = j;
00361     while (buf[j] != '-') if (++j == len) return 0;
00362     month = getmonth(buf + i,j - i);
00363     if (month < 0) return 0;
00364     while (buf[j] == '-') if (++j == len) return 0;
00365     i = j;
00366     while (buf[j] != ' ') if (++j == len) return 0;
00367     year = getlong(buf + i,j - i);
00368     while (buf[j] == ' ') if (++j == len) return 0;
00369     i = j;
00370     while (buf[j] != ':') if (++j == len) return 0;
00371     hour = getlong(buf + i,j - i);
00372     while (buf[j] == ':') if (++j == len) return 0;
00373     i = j;
00374     while ((buf[j] != ':') && (buf[j] != ' ')) if (++j == len) return 0;
00375     minute = getlong(buf + i,j - i);
00376 
00377     fp->mtimetype = FTPPARSE_MTIME_REMOTEMINUTE;
00378     initbase();
00379     fp->mtime = base + totai(year,month,mday) + hour * 3600 + minute * 60;
00380 
00381     return 1;
00382   }
00383 
00384   /* MSDOS format */
00385   /* 04-27-00  09:09PM       <DIR>          licensed */
00386   /* 07-18-00  10:16AM       <DIR>          pub */
00387   /* 04-14-00  03:47PM                  589 readme.htm */
00388   if ((*buf >= '0') && (*buf <= '9')) {
00389     i = 0;
00390     j = 0;
00391     while (buf[j] != '-') if (++j == len) return 0;
00392     month = getlong(buf + i,j - i) - 1;
00393     while (buf[j] == '-') if (++j == len) return 0;
00394     i = j;
00395     while (buf[j] != '-') if (++j == len) return 0;
00396     mday = getlong(buf + i,j - i);
00397     while (buf[j] == '-') if (++j == len) return 0;
00398     i = j;
00399     while (buf[j] != ' ') if (++j == len) return 0;
00400     year = getlong(buf + i,j - i);
00401     if (year < 50) year += 2000;
00402     if (year < 1000) year += 1900;
00403     while (buf[j] == ' ') if (++j == len) return 0;
00404     i = j;
00405     while (buf[j] != ':') if (++j == len) return 0;
00406     hour = getlong(buf + i,j - i);
00407     while (buf[j] == ':') if (++j == len) return 0;
00408     i = j;
00409     while ((buf[j] != 'A') && (buf[j] != 'P')) if (++j == len) return 0;
00410     minute = getlong(buf + i,j - i);
00411     if (hour == 12) hour = 0;
00412     if (buf[j] == 'A') if (++j == len) return 0;
00413     if (buf[j] == 'P') { hour += 12; if (++j == len) return 0; }
00414     if (buf[j] == 'M') if (++j == len) return 0;
00415 
00416     while (buf[j] == ' ') if (++j == len) return 0;
00417     if (buf[j] == '<') {
00418       fp->flagtrycwd = 1;
00419       while (buf[j] != ' ') if (++j == len) return 0;
00420     }
00421     else {
00422       i = j;
00423       while (buf[j] != ' ') if (++j == len) return 0;
00424       fp->size = getlong(buf + i,j - i);
00425       fp->sizetype = FTPPARSE_SIZE_BINARY;
00426       fp->flagtryretr = 1;
00427     }
00428     while (buf[j] == ' ') if (++j == len) return 0;
00429 
00430     fp->name = buf + j;
00431     fp->namelen = len - j;
00432 
00433     fp->mtimetype = FTPPARSE_MTIME_REMOTEMINUTE;
00434     initbase();
00435     fp->mtime = base + totai(year,month,mday) + hour * 3600 + minute * 60;
00436 
00437     return 1;
00438   }
00439 
00440   /* Some useless lines, safely ignored: */
00441   /* "Total of 11 Files, 10966 Blocks." (VMS) */
00442   /* "total 14786" (UNIX) */
00443   /* "DISK$ANONFTP:[ANONYMOUS]" (VMS) */
00444   /* "Directory DISK$PCSA:[ANONYM]" (VMS) */
00445 
00446   return 0;
00447 }

static long getlong ( char *  buf,
int  len 
) [static]

Definition at line 136 of file ftpparse.c.

00137 {
00138   long u = 0;
00139   while (len-- > 0)
00140     u = u * 10 + (*buf++ - '0');
00141   return u;
00142 }

static int getmonth ( char *  buf,
int  len 
) [static]

Definition at line 127 of file ftpparse.c.

00128 {
00129   int i;
00130   if (len == 3)
00131     for (i = 0;i < 12;++i)
00132       if (check(buf,months[i])) return i;
00133   return -1;
00134 }

static long guesstai ( long  month,
long  mday 
) [static]

Definition at line 100 of file ftpparse.c.

00101 {
00102   long year;
00103   long t;
00104 
00105   initnow();
00106 
00107   for (year = currentyear - 1;year < currentyear + 100;++year) {
00108     t = totai(year,month,mday);
00109     if (now - t < 350 * 86400)
00110       return t;
00111   }
00112   return 0;
00113 }

static void initbase ( void   )  [static]

Definition at line 52 of file ftpparse.c.

00053 {
00054   struct tm *t;
00055   if (!flagneedbase) return;
00056 
00057   base = 0;
00058   t = gmtime(&base);
00059   base = -(totai(t->tm_year + 1900,t->tm_mon,t->tm_mday) + t->tm_hour * 3600 + t->tm_min * 60 + t->tm_sec);
00060   /* assumes the right time_t, counting seconds. */
00061   /* base may be slightly off if time_t counts non-leap seconds. */
00062   flagneedbase = 0;
00063 }

static void initnow ( void   )  [static]

Definition at line 65 of file ftpparse.c.

00066 {
00067   long day;
00068   long year;
00069 
00070   initbase();
00071   now = time((time_t *) 0) - base;
00072 
00073   if (flagneedcurrentyear) {
00074     day = now / 86400;
00075     if ((now % 86400) < 0) --day;
00076     day -= 11017;
00077     year = 5 + day / 146097;
00078     day = day % 146097;
00079     if (day < 0) { day += 146097; --year; }
00080     year *= 4;
00081     if (day == 146096) { year += 3; day = 36524; }
00082     else { year += day / 36524; day %= 36524; }
00083     year *= 25;
00084     year += day / 1461;
00085     day %= 1461;
00086     year *= 4;
00087     if (day == 1460) { year += 3; day = 365; }
00088     else { year += day / 365; day %= 365; }
00089     day *= 10;
00090     if ((day + 5) / 306 >= 10) ++year;
00091     currentyear = year;
00092     flagneedcurrentyear = 0;
00093   }
00094 }

static long totai ( long  year,
long  month,
long  mday 
) [static]

Definition at line 26 of file ftpparse.c.

00027 {
00028   long result;
00029   if (month >= 2) month -= 2;
00030   else { month += 10; --year; }
00031   result = (mday - 1) * 10 + 5 + 306 * month;
00032   result /= 10;
00033   if (result == 365) { year -= 3; result = 1460; }
00034   else result += 365 * (year % 4);
00035   year /= 4;
00036   result += 1461 * (year % 25);
00037   year /= 25;
00038   if (result == 36524) { year -= 3; result = 146096; }
00039   else { result += 36524 * (year % 4); }
00040   year /= 4;
00041   result += 146097 * (year - 5);
00042   result += 11017;
00043   return result * 86400;
00044 }


Variable Documentation

time_t base [static]

Definition at line 47 of file ftpparse.c.

long currentyear [static]

Definition at line 50 of file ftpparse.c.

int flagneedbase = 1 [static]

Definition at line 46 of file ftpparse.c.

int flagneedcurrentyear = 1 [static]

Definition at line 49 of file ftpparse.c.

char* months[12] [static]
Initial value:
 {
  "jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec"
}

Definition at line 123 of file ftpparse.c.

long now [static]

Definition at line 48 of file ftpparse.c.


Generated on 18 Mar 2013 for The SWORD Project by  doxygen 1.6.1