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

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

Webmaster