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