Return to HTNewsLs.c CVS log | Up to [Public] / libwww / Library / src |
2.1 frystyk 1: /* HTNewsLs.c
2: ** NEWS (NNTP) GROUP LISTINGS
3: **
4: ** (c) COPYRIGHT MIT 1995.
5: ** Please first read the full copyright statement in the file COPYRIGH.
6: **
7: ** Authors
8: ** FTLO Felix Lo
9: ** HFN Henrik Frystyk <frystyk@w3.org>
10: **
11: ** History:
12: ** Oct 95 HFN Written
13: */
14:
15: /* Library include files */
16: #include "tcp.h"
17: #include "HTUtils.h"
18: #include "HTString.h"
19: #include "HTStream.h"
20: #include "HTFormat.h"
21: #include "HTSocket.h"
22: #include "HTNDir.h"
23: #include "HTNews.h"
24: #include "HTNewsLs.h" /* Implemented here */
25:
26: #define DELIMITER '\t'
27:
28: struct _HTStream {
29: CONST HTStreamClass * isa;
30: HTRequest * request;
31: HTSocketEOL state;
32: HTNewsDir * dir;
33: BOOL group;
34: BOOL junk;
35: char buffer[MAX_NEWS_LINE+1];
36: int buflen;
37: };
38:
39: PRIVATE HTNewsDirKey dir_key = HT_NDK_THREAD;
40:
41: /* ------------------------------------------------------------------------- */
42:
43:
44: /* ParseList
45: ** ---------
46: ** Extract the group name from a LIST listing
47: ** Returns YES if OK, NO on error
48: */
49: PRIVATE BOOL ParseList (HTNewsDir *dir, char * line)
50: {
51: char *ptr = line;
52: while (*ptr && !WHITE(*ptr)) ptr++;
53: *ptr = '\0';
54: return HTNewsDir_addElement(dir, line, 0, NULL, NULL, 0);
55: }
56:
57:
58: /* ParseGroup
59: ** ----------
60: ** Extract the index number, subject etc, from a XOVER command. Expects
61: ** the following format of the line:
62: **
63: ** <index> <subject> <from> <data> <msgid> [*<thread>] ...
64: **
65: ** Returns YES if OK, NO on error
66: */
67: PRIVATE BOOL ParseGroup (HTNewsDir *dir, char * line)
68: {
69: int index;
2.3 frystyk 70: int refcnt=0;
2.1 frystyk 71: char *msgid;
72: char *from;
73: char *ptr;
74: char *subject = line; /* Index */
75: while (*subject && *subject != DELIMITER) subject++;
76: *subject++ = '\0';
77: index = atoi(line);
78: from = subject; /* Subject */
79: while (*from && *from != DELIMITER) from++;
80: *from++ = '\0';
81: ptr = from; /* Date */
82: while (*ptr && *ptr != DELIMITER) ptr++;
83: *ptr++ = '\0';
84: msgid = ptr; /* Msg-ID */
85: while (*msgid && *msgid != DELIMITER) msgid++;
86: *msgid++ = '\0';
87: ptr = msgid; /* Bytes or ref */
88: while (*ptr && *ptr != DELIMITER) ptr++;
89: *ptr++ = '\0';
90: while (!isdigit(*ptr)) {
91: while (*ptr && *ptr != DELIMITER) ptr++;
92: *ptr++ = '\0';
93: refcnt++;
94: }
95: return HTNewsDir_addElement(dir, msgid, index, subject, from, refcnt);
96: }
97:
98: /*
99: ** Searches for News line until buffer fills up or a CRLF or LF is found
100: */
101: PRIVATE int HTNewsList_put_block (HTStream * me, CONST char * b, int l)
102: {
103: while (l-- > 0) {
104: if (me->state == EOL_FCR) {
105: if (*b == LF && me->buflen) {
106: if (!me->junk) {
107: *(me->buffer+me->buflen) = '\0';
108: me->group ? ParseGroup(me->dir, me->buffer) :
109: ParseList(me->dir, me->buffer);
110: } else
111: me->junk = NO; /* back to normal */
112: }
113: me->buflen = 0;
114: me->state = EOL_BEGIN;
115: } else if (*b == CR) {
116: me->state = EOL_FCR;
117: } else if (*b == LF && me->buflen) {
118: if (!me->junk) {
119: *(me->buffer+me->buflen) = '\0';
120: me->group ? ParseGroup(me->dir, me->buffer) :
121: ParseList(me->dir, me->buffer);
122: } else
123: me->junk = NO; /* back to normal */
124: me->buflen = 0;
125: me->state = EOL_BEGIN;
126: } else {
127: *(me->buffer+me->buflen++) = *b;
128: if (me->buflen >= MAX_NEWS_LINE) {
129: if (PROT_TRACE)
2.2 frystyk 130: TTYPrint(TDEST, "News Dir.... Line too long - chopped\n");
2.1 frystyk 131: *(me->buffer+me->buflen) = '\0';
132: me->group ? ParseGroup(me->dir, me->buffer) :
133: ParseList(me->dir, me->buffer);
134: me->buflen = 0;
135: me->junk = YES;
136: }
137: }
138: b++;
139: }
140: return HT_OK;
141: }
142:
143: PRIVATE int HTNewsList_put_character (HTStream * me, char ch)
144: {
145: return HTNewsList_put_block(me, &ch, 1);
146: }
147:
148: PRIVATE int HTNewsList_put_string (HTStream * me, CONST char * s)
149: {
150: return HTNewsList_put_block(me, s, (int) strlen(s));
151: }
152:
153: PRIVATE int HTNewsList_flush (HTStream * me)
154: {
155: return HT_OK;
156: }
157:
158: PRIVATE int HTNewsList_free (HTStream * me)
159: {
160: HTNewsDir_free(me->dir);
161: free(me);
162: return HT_OK;
163: }
164:
2.4 ! frystyk 165: PRIVATE int HTNewsList_abort (HTStream * me, HTList * e)
2.1 frystyk 166: {
2.2 frystyk 167: if (PROT_TRACE) TTYPrint(TDEST, "News Dir.... ABORTING...\n");
2.1 frystyk 168: HTNewsList_free(me);
169: return HT_ERROR;
170: }
171:
172: PRIVATE CONST HTStreamClass HTNewsListClass =
173: {
174: "NewsList",
175: HTNewsList_flush,
176: HTNewsList_free,
177: HTNewsList_abort,
178: HTNewsList_put_character,
179: HTNewsList_put_string,
180: HTNewsList_put_block
181: };
182:
183: PUBLIC HTStream *HTNewsList (HTRequest * request,
184: void * param,
185: HTFormat input_format,
186: HTFormat output_format,
187: HTStream * output_stream)
188: {
189: HTStream *me = (HTStream *) calloc(1, sizeof(HTStream));
190: if (!me) outofmem(__FILE__, "HTNewsList_new");
191: me->isa = &HTNewsListClass;
192: me->request = request;
193: me->state = EOL_BEGIN;
194: me->dir = HTNewsDir_new(request, "Newsgroups", HT_NDK_GROUP);
195: if (me->dir == NULL) FREE(me);
196: return me;
197: }
198:
199: PUBLIC HTStream *HTNewsGroup (HTRequest * request,
200: void * param,
201: HTFormat input_format,
202: HTFormat output_format,
203: HTStream * output_stream)
204: {
205: HTStream *me = (HTStream *) calloc(1, sizeof(HTStream));
206: if (!me) outofmem(__FILE__, "HTNewsList_new");
207: me->isa = &HTNewsListClass;
208: me->request = request;
209: me->state = EOL_BEGIN;
210: me->group = YES;
211: me->dir = HTNewsDir_new(request, "Newsgroup", dir_key);
212: if (me->dir == NULL) FREE(me);
213: return me;
214: }