⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 htnewsls.c

📁 www工具包. 这是W3C官方支持的www支撑库. 其中提供通用目的的客户端的WebAPI: complete HTTP/1.1 (with caching, pipelining, PUT, POS
💻 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 + -