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