Annotation of libwww/Library/src/HTNewsLs.c, revision 2.5
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.2 frystyk 150: TTYPrint(TDEST, "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);
181: free(me);
182: return HT_OK;
183: }
184:
2.4 frystyk 185: PRIVATE int HTNewsList_abort (HTStream * me, HTList * e)
2.1 frystyk 186: {
2.2 frystyk 187: if (PROT_TRACE) TTYPrint(TDEST, "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: {
209: HTStream *me = (HTStream *) calloc(1, sizeof(HTStream));
210: if (!me) outofmem(__FILE__, "HTNewsList_new");
211: me->isa = &HTNewsListClass;
212: me->request = request;
213: me->state = EOL_BEGIN;
214: me->dir = HTNewsDir_new(request, "Newsgroups", HT_NDK_GROUP);
215: if (me->dir == NULL) FREE(me);
216: return me;
217: }
218:
219: PUBLIC HTStream *HTNewsGroup (HTRequest * request,
220: void * param,
221: HTFormat input_format,
222: HTFormat output_format,
223: HTStream * output_stream)
224: {
2.5 ! frystyk 225: char * url = HTAnchor_physical(HTRequest_anchor(request));
! 226: char * title = NULL;
2.1 frystyk 227: HTStream *me = (HTStream *) calloc(1, sizeof(HTStream));
228: if (!me) outofmem(__FILE__, "HTNewsList_new");
2.5 ! frystyk 229: StrAllocCopy(title, "Newsgroup: ");
! 230: if (!strncasecomp(url, "news:", 5))
! 231: StrAllocCat(title, url+5);
! 232: else
! 233: StrAllocCat(title, HTParse(url, "", PARSE_PATH));
2.1 frystyk 234: me->isa = &HTNewsListClass;
235: me->request = request;
236: me->state = EOL_BEGIN;
237: me->group = YES;
2.5 ! frystyk 238: me->dir = HTNewsDir_new(request, title, dir_key);
2.1 frystyk 239: if (me->dir == NULL) FREE(me);
2.5 ! frystyk 240: free(title);
2.1 frystyk 241: return me;
242: }
Webmaster