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

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

Webmaster