HTFTPDir.c
Upload User: zlh9724
Upload Date: 2007-01-04
Package Size: 1991k
Code Size: 7k
Category:

Browser Client

Development Platform:

Unix_Linux

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