📄 htnewsls.c
字号:
/* HTNewsLs.c** NEWS (NNTP) GROUP LISTINGS**** (c) COPYRIGHT MIT 1995.** Please first read the full copyright statement in the file COPYRIGH.** @(#) $Id: HTNewsLs.c,v 2.18 1999/02/22 22:10:11 frystyk Exp $**** Authors** FTLO Felix Lo** HFN Henrik Frystyk <frystyk@w3.org>** MP Maciej Puzio <puzio@zodiac1.mimuw.edu.pl>**** History:** Oct 95 HFN Written** Mar 96 MP Modified*//* Library include files */#include "wwwsys.h"#include "WWWUtil.h"#include "WWWCore.h"#include "HTUTree.h"#include "HTNDir.h"#include "HTNews.h"#include "HTNewsLs.h" /* Implemented here */#define DELIMITER '\t'#define ATSIGN '@'#define NEWS_TREE "w3c-news"struct _HTStream { const HTStreamClass * isa; HTRequest * request; HTEOLState state; HTNewsDir * dir; BOOL group; BOOL junk; char buffer[MAX_NEWS_LINE+1]; int buflen;};typedef struct _HTNewsCache { char * host; HTArray * cache;} HTNewsCache;PRIVATE HTNewsDirKey dir_key = HT_NDK_REFTHREAD;PRIVATE HTNewsDirKey list_key = HT_NDK_GROUP; /* Added by MP. *//* ------------------------------------------------------------------------- *//* Helper function added by MP. */PRIVATE char* GetNewsGroupTitle (HTRequest* request){ char * url = HTAnchor_physical(HTRequest_anchor(request)); char * title = NULL; if (strrchr(url, '*')) StrAllocCopy(title, "Newsgroups: "); else StrAllocCopy(title, "Newsgroup: "); if (!strncasecomp(url, "news:", 5)) StrAllocCat(title, url+5); else StrAllocCat(title, HTParse(url, "", PARSE_PATH)); return title;}PRIVATE BOOL ParseList (HTNewsDir * dir, char * line){ char *ptr = line; while (*ptr && !isspace((int) *ptr)) ptr++; *ptr = '\0'; /* Changed by MP */ return (HTNewsDir_addGroupElement(dir, line, NO) != NULL);}/* ParseGroup** ----------** Extract the index number, subject etc, from a XOVER command. Expects** the following format of the line:**** <index> <subject> <from> <data> <msgid> [*<thread>] ...**** Returns YES if OK, NO on error*/PRIVATE BOOL ParseGroup (HTRequest * request, HTNewsDir *dir, char * line){ int index; int refcnt=0; time_t t=0; char *subject = line; char *from; char *date; char *msgid; char *ptr=NULL; HTList* reflist = NULL; /* Added by MP. */ while (*subject && *subject != DELIMITER) subject++; *subject++ = '\0'; /* Index */ index = atoi(line); from = subject; while (*from && *from != DELIMITER) from++; *from++ = '\0'; /* Subject */ date = from; while (*date && *date != DELIMITER) { if (*date=='<' || *date=='(') { ptr = date+1; *date = '\0'; } if (*date=='>' || *date==')') *date = '\0'; date++; } *date++ = '\0'; if (strchr(from, ATSIGN) && ptr) from = ptr; /* From */ msgid = date; while (*msgid && *msgid != DELIMITER) msgid++; *msgid++ = '\0'; /* Date */ if (*msgid=='<') msgid++; t = HTParseTime(date, HTRequest_userProfile(request), YES); ptr = msgid; while (*ptr && *ptr != DELIMITER) { if (*ptr=='>') *ptr = '\0'; ptr++; } *ptr++ = '\0'; /* MsgId */ while (ptr && *ptr && !isdigit((int) *ptr)) { char* refstart = ptr; /* Added by MP. */ char* refcopy = NULL; char* refstop; while (*ptr && *ptr != DELIMITER && *ptr != ' ') ptr++; refstop = ptr - 1; *ptr++ = '\0'; if (strlen(refstart) > 0) /* Added by MP. */ { refcnt++; if (*refstart == '<') refstart++; if (*refstop == '>') *refstop = '\0'; if (reflist == NULL) reflist = HTList_new(); StrAllocCopy (refcopy, refstart); HTList_addObject (reflist, (void*) refcopy); } } /* Changed by MP. */ return (HTNewsDir_addElement(dir, index, subject, from, t, msgid, refcnt, reflist) != NULL);}/* ------------------------------------------------------------------------- *//* NEWS CACHE *//* ------------------------------------------------------------------------- */PRIVATE HTNewsCache * HTNewsCache_new (const char * newshost, HTArray * array){ if (newshost && array) { HTNewsCache * me; if ((me = (HTNewsCache *) HT_CALLOC(1, sizeof(HTNewsCache))) == NULL) HT_OUTOFMEM("HTNewsCache_new"); StrAllocCopy(me->host, newshost); me->cache = array; return me; } return NULL;}/*** Instead of just deleting we could save it to file.*/PRIVATE int HTNewsCache_delete (void * context){ HTNewsCache * me = (HTNewsCache *) context; if (me) { if (me->cache) { void ** data; char * line = (char *) HTArray_firstObject(me->cache, data); while (line) { HT_FREE(line); line = (char *) HTArray_nextObject(me->cache, data); } HTArray_delete(me->cache); } HT_FREE(me->host); HTTRACE(PROT_TRACE, "News Cache.. Deleted cache %p\n" _ me); HT_FREE(me); return YES; } return NO;}/*** Look for cached information for this news server** We store the information in a URL Tree so that we can have multiple** servers stored simultanously*/PRIVATE HTNewsCache * HTNewsCache_find (HTRequest * request, const char * url){ HTUTree * tree = NULL; if (request && url) { char * newshost = NULL; HTNewsCache * element = NULL; if (!strncasecomp(url, "news:", 5)) { HTUserProfile * up = HTRequest_userProfile(request); StrAllocCopy(newshost, HTUserProfile_news(up)); } else if (!strncasecomp(url, "nntp:", 5)) { newshost = HTParse(url, "", PARSE_HOST); } /* If we have a news server then continue to find a URL tree */ if (newshost) { char * colon = strchr(newshost, ':'); int port = NEWS_PORT; if (colon ) { *(colon++) = '\0'; /* Chop off port number */ port = atoi(colon); } tree = HTUTree_find(NEWS_TREE, newshost, port); HT_FREE(newshost); if (!tree) { HTTRACE(PROT_TRACE, "News Cache.. No information for `%s\'\n" _ url); return NULL; } /* Find a cache element (if any) */ element = (HTNewsCache *) HTUTree_findNode(tree, "", "/"); return element; } } return NULL;}PRIVATE BOOL HTNewsCache_update (HTRequest * request, const char * url, HTArray * array){ HTUTree * tree = NULL; if (request && url) { char * newshost = NULL; if (!strncasecomp(url, "news:", 5)) { HTUserProfile * up = HTRequest_userProfile(request); StrAllocCopy(newshost, HTUserProfile_news(up)); } else if (!strncasecomp(url, "nntp:", 5)) { newshost = HTParse(url, "", PARSE_HOST); } /* ** If the news server was found then update the data entry. Otherwise ** create a new entry */ if (newshost) { char * colon = strchr(newshost, ':'); int port = NEWS_PORT; if (colon ) { *(colon++) = '\0'; /* Chop off port number */ port = atoi(colon); } tree = HTUTree_new(NEWS_TREE, newshost, port, HTNewsCache_delete); HT_FREE(newshost); if (!tree) { HTTRACE(PROT_TRACE, "News Cache.. Can't create tree\n"); return NO; } /* Add new cache information to the tree */ { HTNewsCache * element = NULL; BOOL status; if ((element=(HTNewsCache *) HTUTree_findNode(tree, "", "/"))){ element->cache = array; status = YES; } else { element = HTNewsCache_new(url, array); status = HTUTree_addNode(tree, "", "/", element); } return status; } } } return NO;}/*** Before filter: Check whether we have a cache entry for this host*/PUBLIC int HTNewsCache_before (HTRequest * request, void * context, int mode){ char * url = HTAnchor_address((HTAnchor *) HTRequest_anchor(request)); HTNewsCache * element = HTNewsCache_find(request, url); HT_FREE(url); /* ** If we have found a cache object then create a new dir obejct and fill ** it with data from the cache */ if (element) { char * title = GetNewsGroupTitle(request); HTNewsDir * dir = HTNewsDir_new(request, title, list_key, NO); void ** data; char * line = (char *) HTArray_firstObject(element->cache, data); while (line) { HTNewsDir_addGroupElement(dir, line, NO); line = (char *) HTArray_nextObject(element->cache, data); } /* ** After filling the new dir object we write it out and free it again */ HTNewsDir_free(dir); HT_FREE(title); return HT_LOADED; } return HT_OK;}/*** After filter: Update the cache entry for this host*/PUBLIC int HTNewsCache_after (HTRequest * request, HTResponse * response, void * context, int status){ HTArray * array = (HTArray *) context; HTTRACE(PROT_TRACE, "News Cache.. AFTER filter\n"); if (request && array) { char * url = HTAnchor_address((HTAnchor *) HTRequest_anchor(request)); HTNewsCache_update(request, url, array); HT_FREE(url); } return HT_OK;}/* ------------------------------------------------------------------------- *//*** Searches for News line until buffer fills up or a CRLF or LF is found*/PRIVATE int HTNewsList_put_block (HTStream * me, const char * b, int l){ while (l-- > 0) { if (me->state == EOL_FCR) { if (*b == LF && me->buflen) { if (!me->junk) { *(me->buffer+me->buflen) = '\0'; me->group ? ParseGroup(me->request, me->dir, me->buffer) : ParseList(me->dir, me->buffer); } else me->junk = NO; /* back to normal */ } me->buflen = 0; me->state = EOL_BEGIN; } else if (*b == CR) { me->state = EOL_FCR; } else if (*b == LF && me->buflen) { if (!me->junk) { *(me->buffer+me->buflen) = '\0'; me->group ? ParseGroup(me->request, me->dir, me->buffer) : ParseList(me->dir, me->buffer); } else me->junk = NO; /* back to normal */ me->buflen = 0; me->state = EOL_BEGIN; } else { *(me->buffer+me->buflen++) = *b; if (me->buflen >= MAX_NEWS_LINE) { HTTRACE(PROT_TRACE, "News Dir.... Line too long - chopped\n"); *(me->buffer+me->buflen) = '\0'; me->group ? ParseGroup(me->request, me->dir, me->buffer) : ParseList(me->dir, me->buffer); me->buflen = 0; me->junk = YES; } } b++; } return HT_OK;}PRIVATE int HTNewsList_put_character (HTStream * me, char ch){ return HTNewsList_put_block(me, &ch, 1);}PRIVATE int HTNewsList_put_string (HTStream * me, const char * s){ return HTNewsList_put_block(me, s, (int) strlen(s));}PRIVATE int HTNewsList_flush (HTStream * me){ return HT_OK;}PRIVATE int HTNewsList_free (HTStream * me){ HTNewsList_put_character (me, '\n'); /* to flush the last item; added by MP. */ HTNewsDir_free(me->dir); HT_FREE(me); return HT_OK;}PRIVATE int HTNewsList_abort (HTStream * me, HTList * e){ HTTRACE(PROT_TRACE, "News Dir.... ABORTING...\n"); HTNewsList_free(me); return HT_ERROR;}PRIVATE const HTStreamClass HTNewsListClass ={ "NewsList", HTNewsList_flush, HTNewsList_free, HTNewsList_abort, HTNewsList_put_character, HTNewsList_put_string, HTNewsList_put_block};PUBLIC HTStream *HTNewsList (HTRequest * request, void * param, HTFormat input_format, HTFormat output_format, HTStream * output_stream){ HTStream *me; if ((me = (HTStream *) HT_CALLOC(1, sizeof(HTStream))) == NULL) HT_OUTOFMEM("HTNewsList_new"); me->isa = &HTNewsListClass; me->request = request; me->state = EOL_BEGIN; { char * title = GetNewsGroupTitle(request); me->dir = HTNewsDir_new(request, title, list_key,YES); HT_FREE(title); } /* Modified by MP. */ if (me->dir == NULL) HT_FREE(me); return me;}PUBLIC HTStream *HTNewsGroup (HTRequest * request, void * param, HTFormat input_format, HTFormat output_format, HTStream * output_stream){ HTStream * me; if ((me = (HTStream *) HT_CALLOC(1, sizeof(HTStream))) == NULL) HT_OUTOFMEM("HTNewsList_new"); me->isa = &HTNewsListClass; me->request = request; me->state = EOL_BEGIN; me->group = YES; { char * title = GetNewsGroupTitle(request); me->dir = HTNewsDir_new(request, title, dir_key, YES); HT_FREE(title); } /* Modified by MP. */ if (me->dir == NULL) HT_FREE(me); return me;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -