Annotation of libwww/Library/src/HTFTPDir.c, revision 2.17

2.1       frystyk     1: /*                                                                  HTFTPDir.c
                      2: **     FILE TRANSFER PROTOCOL (FTP) DIRECTORY LISTINGS
                      3: **
                      4: **     (c) COPYRIGHT MIT 1995.
                      5: **     Please first read the full copyright statement in the file COPYRIGH.
2.17    ! frystyk     6: **     @(#) $Id: HTFTPDir.c,v 2.16 1998/02/01 19:04:06 frystyk Exp $
2.1       frystyk     7: **
                      8: ** Authors
                      9: **     HF      Henrik Frystyk <frystyk@w3.org>
                     10: **
                     11: ** History:
                     12: **     Sep 95          Spawned off from HTFTP.c and made a stream
                     13: **
                     14: */
                     15: 
                     16: /* Library include files */
2.17    ! frystyk    17: #include "wwwsys.h"
2.15      frystyk    18: #include "WWWUtil.h"
                     19: #include "WWWCore.h"
                     20: #include "WWWDir.h"
                     21: #include "WWWTrans.h"
2.1       frystyk    22: #include "HTFTPDir.h"                                   /* Implemented here */
                     23: 
                     24: struct _HTStream {
2.12      frystyk    25:     const HTStreamClass *      isa;
2.1       frystyk    26:     HTRequest *                        request;
                     27:     FTPServerType              server;
2.13      frystyk    28:     HTEOLState                 state;
2.1       frystyk    29:     HTDir *                    dir;
                     30:     BOOL                       first;
                     31:     BOOL                       junk;
                     32:     char                       buffer[MAX_FTP_LINE+1];
                     33:     int                                buflen;
                     34: };
                     35: 
                     36: PRIVATE HTDirShow      dir_show = HT_DS_SIZE+HT_DS_DATE+HT_DS_DES+HT_DS_ICON;
                     37: PRIVATE HTDirKey       dir_key = HT_DK_CINS;
                     38: 
                     39: /* ------------------------------------------------------------------------- */
                     40: 
                     41: /*     ParseUnix
                     42: **     ---------
                     43: **     Extract the name, size, and date from an 'ls'. The function expects
                     44: **     the following format of the ls-line:
                     45: **
                     46: **     <permission> <nlink> <owner> [<group>] <size> <date> <filename>
                     47: **
                     48: **     Returns YES if OK, NO on error
                     49: */
                     50: PRIVATE BOOL ParseUnix (HTDir *dir, char * line)
                     51: {
                     52:     int cnt;
                     53:     char *ptr = line;
                     54:     char *column = NULL;
                     55:     char *date = NULL;
                     56:     char sizestr[10];    
                     57:     HTFileMode mode = (*line == 'd') ? HT_IS_DIR : HT_IS_FILE;
                     58: 
                     59:     /* Spool past permission, link, and owner */
                     60:     for (cnt=0; cnt<4; cnt++) {
                     61:        if ((column = HTNextField(&ptr)) == NULL) break;
                     62:     }
                     63:     
                     64:     /*
                     65:     ** This field can either be group or size. We find out by looking at the
                     66:     ** next field. If this is a non-digit then this field is the size.
                     67:     */
2.16      frystyk    68:     while (*ptr && isspace((int) *ptr)) ptr++;
                     69:     if (isdigit((int) *ptr)) {
2.1       frystyk    70:        column = HTNextField(&ptr);
2.16      frystyk    71:        while (*ptr && isspace((int) *ptr)) ptr++;
2.1       frystyk    72:     }
                     73: 
                     74:     if (mode == HT_IS_FILE) {
                     75:        long ls = atol(column);
                     76:        HTNumToStr(ls, sizestr, 10);
                     77:     } else
                     78:        strcpy(sizestr, "-");
                     79: 
                     80:     /* Find date field */
                     81:     date = ptr;
                     82:     ptr += 12;
                     83:     *ptr++ = '\0';
                     84:     date = HTStrip(date);
                     85: 
                     86:     /* Take the reminder as the filename */
2.16      frystyk    87:     while (*ptr && isspace((int) *ptr)) ptr++;
2.1       frystyk    88:     if ((column = strstr(ptr, " -> ")))
                     89:        *column = '\0';                                    /* Strip any '->' */
                     90:     
                     91:     /* Add the element with what we've got */
                     92:     return HTDir_addElement(dir, ptr, date, sizestr, mode);
                     93: }
                     94: 
                     95: 
                     96: /*     ParseVMS
                     97: **     --------
                     98: **      Parse the VMS line and send it to the directory module
                     99: **     Returns YES if OK, NO on error
                    100: */
                    101: PRIVATE BOOL ParseVMS (HTDir *dir, char * line)
                    102: {
                    103:     char *ptr = NULL;
                    104:     char *date = NULL;
                    105:     char *size = NULL;
                    106:     char sizestr[10];
                    107:     HTFileMode mode;
                    108:     
                    109:     /* Valid lines have the semi-colon version number token */
                    110:     if ((ptr = strchr(line, ';')) == NULL)
                    111:        return YES;
                    112:     *ptr++ ='\0';
                    113:     if (HTNextField(&ptr) == NULL) return YES;
                    114: 
                    115:     /* Cast VMS file and directory names to lowercase except .Z and _Z */
                    116:     {
                    117:        char *lp = line;
                    118:        while (*lp) {
                    119:            if (strcmp(lp, ".Z")==0 || strcmp(lp, "_Z")==0) break;
                    120:            *lp = TOLOWER(*lp);
                    121:            lp++;
                    122:        }
                    123:        if ((lp = strstr(line, ".dir"))) {                 /* Strip any .dir */
                    124:            mode = HT_IS_DIR;
                    125:            *lp = '\0';
                    126:        } else
                    127:            mode = HT_IS_FILE;
                    128:     }
                    129: 
                    130:     /* Find the size */
                    131:     if ((size = HTNextField(&ptr))) {
                    132:        if (mode == HT_IS_FILE) {
                    133:            long ls = atol(size) * 512;                     /* Assume blocks */
                    134:            HTNumToStr(ls, sizestr, 10);
                    135:        } else
                    136:            strcpy(sizestr, "-");
                    137:     } else
                    138:        *sizestr = '\0';
                    139:        
                    140:     /* Find the date */
                    141:     {
                    142:        char *end = strchr(ptr, '[');
                    143:        if (end) *end = '\0';
                    144:        date = HTStrip(ptr);
                    145:     }
                    146:     return HTDir_addElement(dir, line, date, sizestr, mode);
                    147: }
                    148: 
                    149: 
                    150: /*     ParseFTPLine
                    151: **     -----------
                    152: **     Determines what to do with a line read from a FTP listing
                    153: **     Returns YES if OK, else NO
                    154: */
                    155: PRIVATE BOOL ParseFTPLine (HTStream *me)
                    156: {
                    157:     if (!me->buflen) return YES;                           /* If empty line */
                    158:     switch (me->server) {
                    159:       case FTP_WINNT:
                    160:       case FTP_UNIX:
                    161:       case FTP_PETER_LEWIS:
                    162:       case FTP_MACHTEN:
                    163:        if (me->first) {
                    164:            if (strncmp(me->buffer, "total ", 6) &&
                    165:                !strstr(me->buffer, "not available"))
                    166:                ParseUnix(me->dir, me->buffer);
                    167:            me->first = NO;
                    168:        } else
                    169:            ParseUnix(me->dir, me->buffer);
                    170:        break;
                    171: 
                    172:       case FTP_VMS:
                    173:        /* Interpret and edit LIST output from VMS server */
                    174:        /* and convert information lines to zero length.  */
                    175:        ParseVMS(me->dir, me->buffer);
                    176:        break;
                    177:        
                    178:       case FTP_NCSA:
                    179:       case FTP_TCPC:
                    180:        /* Directories identified by trailing "/" characters */
                    181:        {
                    182:            HTFileMode mode = (*(me->buffer+me->buflen-1)=='/') ?
                    183:                HT_IS_DIR : HT_IS_FILE;
                    184:            return HTDir_addElement(me->dir, me->buffer, NULL, NULL, mode);
                    185:        }
                    186:        break;
                    187:        
                    188:       default:
2.11      frystyk   189:        return HTDir_addElement(me->dir, me->buffer, NULL, NULL, HT_IS_FILE);
2.1       frystyk   190:        break;
                    191:     }
                    192:     return NO;
                    193: }
                    194: 
                    195: /*
                    196: **     Searches for FTP line until buffer fills up or a CRLF or LF is found
                    197: */
2.12      frystyk   198: PRIVATE int FTPDir_put_block (HTStream * me, const char * b, int l)
2.1       frystyk   199: {
                    200:     while (l-- > 0) {
                    201:        if (me->state == EOL_FCR) {
                    202:            if (*b == LF && me->buflen) {
                    203:                if (!me->junk) {
                    204:                    *(me->buffer+me->buflen) = '\0';
                    205:                    ParseFTPLine(me);
                    206:                } else
                    207:                    me->junk = NO;                         /* back to normal */
                    208:            }
                    209:            me->buflen = 0;
                    210:            me->state = EOL_BEGIN;
                    211:        } else if (*b == CR) {
                    212:            me->state = EOL_FCR;
                    213:        } else if (*b == LF && me->buflen) {
                    214:            if (!me->junk) {
                    215:                *(me->buffer+me->buflen) = '\0';
                    216:                ParseFTPLine(me);
                    217:            } else
                    218:                me->junk = NO;                             /* back to normal */
                    219:            me->buflen = 0;
                    220:            me->state = EOL_BEGIN;
                    221:        } else {
                    222:            *(me->buffer+me->buflen++) = *b;
                    223:            if (me->buflen >= MAX_FTP_LINE) {
                    224:                if (PROT_TRACE)
2.10      eric      225:                    HTTrace("FTP Dir..... Line too long - ignored\n");
2.1       frystyk   226:                me->buflen = 0;
                    227:                me->junk = YES;
                    228:            }
                    229:        }
                    230:        b++;
                    231:     }
                    232:     return HT_OK;
                    233: }
                    234: 
2.12      frystyk   235: PRIVATE int FTPDir_put_string (HTStream * me, const char * s)
2.1       frystyk   236: {
                    237:     return FTPDir_put_block(me, s, (int) strlen(s));
                    238: }
                    239: 
2.3       frystyk   240: PRIVATE int FTPDir_put_character (HTStream * me, char c)
2.1       frystyk   241: {
                    242:     return FTPDir_put_block(me, &c, 1);
                    243: }
                    244: 
2.3       frystyk   245: PRIVATE int FTPDir_flush (HTStream * me)
2.1       frystyk   246: {
                    247:     return HT_OK;
                    248: }
                    249: 
2.3       frystyk   250: PRIVATE int FTPDir_free (HTStream * me)
2.1       frystyk   251: {
                    252:     HTDir_free(me->dir);
2.9       frystyk   253:     HT_FREE(me);
2.1       frystyk   254:     return HT_OK;
                    255: }
                    256: 
2.5       frystyk   257: PRIVATE int FTPDir_abort (HTStream * me, HTList * e)
2.1       frystyk   258: {
2.10      eric      259:     if (PROT_TRACE) HTTrace("FTPDir...... ABORTING...\n");
2.1       frystyk   260:     FTPDir_free(me);
                    261:     return HT_ERROR;
                    262: }
                    263: 
                    264: /*     FTPDir Stream
                    265: **     -----------------
                    266: */
2.12      frystyk   267: PRIVATE const HTStreamClass FTPDirClass =
2.1       frystyk   268: {              
                    269:     "FTPDir",
                    270:     FTPDir_flush,
                    271:     FTPDir_free,
                    272:     FTPDir_abort,
                    273:     FTPDir_put_character,
                    274:     FTPDir_put_string,
                    275:     FTPDir_put_block
                    276: };
                    277: 
                    278: PUBLIC HTStream * HTFTPDir_new (HTRequest *    request,
                    279:                                FTPServerType   server,
                    280:                                char            list)
                    281: {
2.9       frystyk   282:     HTStream * me;
                    283:     if ((me = (HTStream  *) HT_CALLOC(1, sizeof(HTStream))) == NULL)
                    284:         HT_OUTOFMEM("HTFTPDir");
2.1       frystyk   285:     me->isa = &FTPDirClass;
                    286:     me->request = request;    
                    287:     me->server = server;
                    288:     me->state = EOL_BEGIN;
                    289:     me->dir = HTDir_new(request, (list=='L' ? dir_show : 0), dir_key);
                    290:     me->first = YES;
2.7       frystyk   291:     if (me->dir == NULL) {
2.9       frystyk   292:        HT_FREE(me);
2.8       frystyk   293:        return HTErrorStream();
2.7       frystyk   294:     }
2.1       frystyk   295:     return me;
                    296: }

Webmaster