Annotation of libwww/Library/src/HTNewsLs.c, revision 2.7
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"
2.5 frystyk 21: #include "HTParse.h"
2.1 frystyk 22: #include "HTSocket.h"
2.5 frystyk 23: #include "HTReq.h"
2.1 frystyk 24: #include "HTNDir.h"
25: #include "HTNews.h"
26: #include "HTNewsLs.h" /* Implemented here */
27:
28: #define DELIMITER '\t'
2.5 frystyk 29: #define ATSIGN '@'
2.1 frystyk 30:
31: struct _HTStream {
32: CONST HTStreamClass * isa;
33: HTRequest * request;
34: HTSocketEOL state;
35: HTNewsDir * dir;
36: BOOL group;
37: BOOL junk;
38: char buffer[MAX_NEWS_LINE+1];
39: int buflen;
40: };
41:
2.5 frystyk 42: PRIVATE HTNewsDirKey dir_key = HT_NDK_NONE;
2.1 frystyk 43:
44: /* ------------------------------------------------------------------------- */
45:
46:
47: /* ParseList
48: ** ---------
49: ** Extract the group name from a LIST listing
50: ** Returns YES if OK, NO on error
51: */
52: PRIVATE BOOL ParseList (HTNewsDir *dir, char * line)
53: {
54: char *ptr = line;
55: while (*ptr && !WHITE(*ptr)) ptr++;
56: *ptr = '\0';
2.5 frystyk 57: return HTNewsDir_addElement(dir, 0, line, NULL, (time_t) 0, line, 0);
2.1 frystyk 58: }
59:
60:
61: /* ParseGroup
62: ** ----------
63: ** Extract the index number, subject etc, from a XOVER command. Expects
64: ** the following format of the line:
65: **
66: ** <index> <subject> <from> <data> <msgid> [*<thread>] ...
67: **
68: ** Returns YES if OK, NO on error
69: */
70: PRIVATE BOOL ParseGroup (HTNewsDir *dir, char * line)
71: {
72: int index;
2.3 frystyk 73: int refcnt=0;
2.5 frystyk 74: time_t t=0;
75: char *subject = line;
76: char *from;
77: char *date;
2.1 frystyk 78: char *msgid;
2.5 frystyk 79: char *ptr=NULL;
2.1 frystyk 80: while (*subject && *subject != DELIMITER) subject++;
2.5 frystyk 81: *subject++ = '\0'; /* Index */
2.1 frystyk 82: index = atoi(line);
2.5 frystyk 83: from = subject;
2.1 frystyk 84: while (*from && *from != DELIMITER) from++;
2.5 frystyk 85: *from++ = '\0'; /* Subject */
86: date = from;
87: while (*date && *date != DELIMITER) {
88: if (*date=='<' || *date=='(') {
89: ptr = date+1;
90: *date = '\0';
91: }
92: if (*date=='>' || *date==')') *date = '\0';
93: date++;
94: }
95: *date++ = '\0';
96: if (strchr(from, ATSIGN) && ptr) from = ptr; /* From */
97: msgid = date;
2.1 frystyk 98: while (*msgid && *msgid != DELIMITER) msgid++;
2.5 frystyk 99: *msgid++ = '\0'; /* Date */
100: if (*msgid=='<') msgid++;
101: #if 0
102: t = HTParseTime(date);
103: #endif
104: ptr = msgid;
105: while (*ptr && *ptr != DELIMITER) {
106: if (*ptr=='>') *ptr = '\0';
107: ptr++;
108: }
109: *ptr++ = '\0'; /* MsgId */
2.1 frystyk 110: while (!isdigit(*ptr)) {
111: while (*ptr && *ptr != DELIMITER) ptr++;
112: *ptr++ = '\0';
113: refcnt++;
114: }
2.5 frystyk 115: return HTNewsDir_addElement(dir, index, subject, from, t, msgid, refcnt);
2.1 frystyk 116: }
117:
118: /*
119: ** Searches for News line until buffer fills up or a CRLF or LF is found
120: */
121: PRIVATE int HTNewsList_put_block (HTStream * me, CONST char * b, int l)
122: {
123: while (l-- > 0) {
124: if (me->state == EOL_FCR) {
125: if (*b == LF && me->buflen) {
126: if (!me->junk) {
127: *(me->buffer+me->buflen) = '\0';
128: me->group ? ParseGroup(me->dir, me->buffer) :
129: ParseList(me->dir, me->buffer);
130: } else
131: me->junk = NO; /* back to normal */
132: }
133: me->buflen = 0;
134: me->state = EOL_BEGIN;
135: } else if (*b == CR) {
136: me->state = EOL_FCR;
137: } else if (*b == LF && me->buflen) {
138: if (!me->junk) {
139: *(me->buffer+me->buflen) = '\0';
140: me->group ? ParseGroup(me->dir, me->buffer) :
141: ParseList(me->dir, me->buffer);
142: } else
143: me->junk = NO; /* back to normal */
144: me->buflen = 0;
145: me->state = EOL_BEGIN;
146: } else {
147: *(me->buffer+me->buflen++) = *b;
148: if (me->buflen >= MAX_NEWS_LINE) {
149: if (PROT_TRACE)
2.7 ! eric 150: HTTrace("News Dir.... Line too long - chopped\n");
2.1 frystyk 151: *(me->buffer+me->buflen) = '\0';
152: me->group ? ParseGroup(me->dir, me->buffer) :
153: ParseList(me->dir, me->buffer);
154: me->buflen = 0;
155: me->junk = YES;
156: }
157: }
158: b++;
159: }
160: return HT_OK;
161: }
162:
163: PRIVATE int HTNewsList_put_character (HTStream * me, char ch)
164: {
165: return HTNewsList_put_block(me, &ch, 1);
166: }
167:
168: PRIVATE int HTNewsList_put_string (HTStream * me, CONST char * s)
169: {
170: return HTNewsList_put_block(me, s, (int) strlen(s));
171: }
172:
173: PRIVATE int HTNewsList_flush (HTStream * me)
174: {
175: return HT_OK;
176: }
177:
178: PRIVATE int HTNewsList_free (HTStream * me)
179: {
180: HTNewsDir_free(me->dir);
2.6 frystyk 181: HT_FREE(me);
2.1 frystyk 182: return HT_OK;
183: }
184:
2.4 frystyk 185: PRIVATE int HTNewsList_abort (HTStream * me, HTList * e)
2.1 frystyk 186: {
2.7 ! eric 187: if (PROT_TRACE) HTTrace("News Dir.... ABORTING...\n");
2.1 frystyk 188: HTNewsList_free(me);
189: return HT_ERROR;
190: }
191:
192: PRIVATE CONST HTStreamClass HTNewsListClass =
193: {
194: "NewsList",
195: HTNewsList_flush,
196: HTNewsList_free,
197: HTNewsList_abort,
198: HTNewsList_put_character,
199: HTNewsList_put_string,
200: HTNewsList_put_block
201: };
202:
203: PUBLIC HTStream *HTNewsList (HTRequest * request,
204: void * param,
205: HTFormat input_format,
206: HTFormat output_format,
207: HTStream * output_stream)
208: {
2.6 frystyk 209: HTStream *me;
210: if ((me = (HTStream *) HT_CALLOC(1, sizeof(HTStream))) == NULL)
211: HT_OUTOFMEM("HTNewsList_new");
2.1 frystyk 212: me->isa = &HTNewsListClass;
213: me->request = request;
214: me->state = EOL_BEGIN;
215: me->dir = HTNewsDir_new(request, "Newsgroups", HT_NDK_GROUP);
2.6 frystyk 216: if (me->dir == NULL) HT_FREE(me);
2.1 frystyk 217: return me;
218: }
219:
220: PUBLIC HTStream *HTNewsGroup (HTRequest * request,
221: void * param,
222: HTFormat input_format,
223: HTFormat output_format,
224: HTStream * output_stream)
225: {
2.5 frystyk 226: char * url = HTAnchor_physical(HTRequest_anchor(request));
227: char * title = NULL;
2.6 frystyk 228: HTStream *me;
229: if ((me = (HTStream *) HT_CALLOC(1, sizeof(HTStream))) == NULL)
230: HT_OUTOFMEM("HTNewsList_new");
2.5 frystyk 231: StrAllocCopy(title, "Newsgroup: ");
232: if (!strncasecomp(url, "news:", 5))
233: StrAllocCat(title, url+5);
234: else
235: StrAllocCat(title, HTParse(url, "", PARSE_PATH));
2.1 frystyk 236: me->isa = &HTNewsListClass;
237: me->request = request;
238: me->state = EOL_BEGIN;
239: me->group = YES;
2.5 frystyk 240: me->dir = HTNewsDir_new(request, title, dir_key);
2.6 frystyk 241: if (me->dir == NULL) HT_FREE(me);
242: HT_FREE(title);
2.1 frystyk 243: return me;
244: }
Webmaster