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

📄 htgopher.c

📁 www工具包
💻 C
📖 第 1 页 / 共 2 页
字号:
		    cont = me->CSO ? GopherCSOLine(me, me->buffer) :			GopherMenuLine(me, me->buffer);		    if (cont == NO) return HT_LOADED;		} 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) {		BOOL cont;		*(me->buffer+me->buflen) = '\0';		cont = me->CSO ? GopherCSOLine(me, me->buffer) :		    GopherMenuLine(me, me->buffer);		if (cont == NO) return HT_LOADED;	    } else		me->junk = NO;				   /* back to normal */	    me->buflen = 0;	    me->state = EOL_BEGIN;	} else {	    *(me->buffer+me->buflen++) = *b;	    if (me->buflen >= MAX_GOPHER_LINE) {		HTTRACE(PROT_TRACE, "Gopher...... Line too long - ignored\n");		me->buflen = 0;		me->junk = YES;	    }	}	b++;    }    return HT_OK;}PRIVATE int GopherMenu_put_string (HTStream * me, const char* s){    return GopherMenu_put_block(me, s, (int) strlen(s));}PRIVATE int GopherMenu_put_character (HTStream * me, char c){    return GopherMenu_put_block(me, &c, 1);}PRIVATE int GopherMenu_flush (HTStream * me){        return (*me->target->isa->flush)(me->target);}PRIVATE int GopherMenu_free (HTStream * me){    int status = HT_OK;    GopherBottom(me);    if ((status = (*me->target->isa->_free)(me->target)) == HT_WOULD_BLOCK)	return HT_WOULD_BLOCK;    HT_FREE(me);    return HT_OK;}PRIVATE int GopherMenu_abort (HTStream * me, HTList * e){    (*me->target->isa->abort)(me->target, e);    HT_FREE(me);    HTTRACE(PROT_TRACE, "Gopher...... ABORTING...\n");    return HT_ERROR;}/*	Goper Menu Stream**	-----------------*/PRIVATE const HTStreamClass GopherMenuClass ={		    "GopherMenu",    GopherMenu_flush,    GopherMenu_free,    GopherMenu_abort,    GopherMenu_put_character,    GopherMenu_put_string,    GopherMenu_put_block};/***  Stream for creating a HTML object out of a Gopher Menu object*/PRIVATE HTStream * GopherMenu_new (HTRequest * request, char *url, BOOL CSO){    HTStream * me;    if ((me = (HTStream  *) HT_CALLOC(1, sizeof(HTStream))) == NULL)        HT_OUTOFMEM("GopherMenu_new");    me->isa = &GopherMenuClass;    me->target = HTMLGenerator(request, NULL, WWW_HTML,			       HTRequest_outputFormat(request),			       HTRequest_outputStream(request));    HTAnchor_setFormat(HTRequest_anchor(request), WWW_HTML);    me->request = request;        me->state = EOL_BEGIN;    me->url = url;    me->CSO = CSO;    GopherTitle(me);    return me;}/* ------------------------------------------------------------------------- *//*				GOPHER STATE MACHINE			     *//* ------------------------------------------------------------------------- *//*	GopherCleanup**	-------------**      This function closes the connection and frees memory.**      Returns YES if OK, else NO*/PRIVATE BOOL GopherCleanup (HTRequest * request, int status){    HTNet * net = HTRequest_net(request);    gopher_info * gopher = (gopher_info *) HTNet_context(net);    HTStream * input = HTRequest_inputStream(request);    /* Free stream with data TO network */    if (input) {	if (status == HT_INTERRUPTED)	    (*input->isa->abort)(input, NULL);	else	    (*input->isa->_free)(input);    }    /* Remove the request object and our own context structure for gopher */    HTNet_delete(net, status);    if (gopher) {	HT_FREE(gopher->cmd);	HT_FREE(gopher);    }    return YES;}/*	Display a Gopher Index document**	-------------------------------**	We create a small HTML object as we have no network activity*/PRIVATE void display_index (HTRequest * request){    HTParentAnchor * anchor = HTRequest_anchor(request);    HTStructured *target = HTMLGenerator(request, NULL, WWW_HTML,					 HTRequest_outputFormat(request),					 HTRequest_outputStream(request));    /* Update anchor information */    HTAnchor_setFormat(anchor, WWW_HTML);    HTAnchor_setTitle(anchor, "Searchable Gopher Index");    /* @@@ We don't set Content-Length */    START(HTML_HTML);    START(HTML_HEAD);    START(HTML_TITLE);    PUTS("Searchable Gopher Index");    END(HTML_TITLE);    END(HTML_HEAD);    START(HTML_BODY);    START(HTML_H1);    PUTS("Searchable Gopher Index");    END(HTML_H1);    START(HTML_ISINDEX);    END(HTML_BODY);    END(HTML_HTML);    (*target->isa->_free)(target);}/*      Display a CSO index document**      -------------------------------**	We create a small HTML object as we have no network activity*/PRIVATE void display_cso (HTRequest * request){    HTParentAnchor * anchor = HTRequest_anchor(request);    HTStructured *target = HTMLGenerator(request, NULL, WWW_HTML,					 HTRequest_outputFormat(request),					 HTRequest_outputStream(request));    /* Update anchor information */    HTAnchor_setFormat(anchor, WWW_HTML);    HTAnchor_setTitle(anchor, "Searchable SCO Index");    /* @@@ We don't set Content-Length */    START(HTML_HTML);    START(HTML_HEAD);    START(HTML_TITLE);    PUTS("Searchable Index of a CSO Name Server");    END(HTML_TITLE);    END(HTML_HEAD);    START(HTML_BODY);    START(HTML_H1);    PUTS("Searchable Index of a CSO Name Server");    END(HTML_H1);    PUTS("A CSO Name Server usually provides directory information about people.");    START(HTML_ISINDEX);    END(HTML_BODY);    END(HTML_HTML);    (*target->isa->_free)(target);}/*	HTLoadGopher**	------------**	Given a hypertext address, this routine loads a gopher document**** On entry,**      request		This is the request structure** On Exit**	returns		HT_ERROR	Error has occured in call back**			HT_OK		Call back was OK*/PRIVATE int GopherEvent (SOCKET soc, void * pVoid, HTEventType type);PUBLIC int HTLoadGopher (SOCKET soc, HTRequest * request){    gopher_info * gopher;    HTNet * net = HTRequest_net(request);    HTParentAnchor * anchor = HTRequest_anchor(request);    char * url = HTAnchor_physical(anchor);        /*    ** Initiate a new gopher structure and bind to request structure    ** This is actually state GOPHER_BEGIN, but it can't be in the state    ** machine as we need the structure first.    */    HTTRACE(PROT_TRACE, "Gopher...... Looking for `%s\'\n" _ url);    if ((gopher = (gopher_info *) HT_CALLOC(1, sizeof(gopher_info))) == NULL)	HT_OUTOFMEM("HTLoadGopher");    gopher->type = GT_MENU;    gopher->state = GOPHER_BEGIN;    gopher->net = net;    HTNet_setContext(net, gopher);    HTNet_setEventCallback(net, GopherEvent);    HTNet_setEventParam(net, gopher);  /* callbacks get http* */    return GopherEvent(soc, gopher, HTEvent_BEGIN);		/* get it started - ops is ignored */}PRIVATE int GopherEvent (SOCKET soc, void * pVoid, HTEventType type){    gopher_info * gopher = (gopher_info *)pVoid;    int status = HT_ERROR;    HTNet * net = gopher->net;    HTRequest * request = HTNet_request(net);    HTParentAnchor * anchor = HTRequest_anchor(request);    HTHost * host = HTNet_host(net);    char * url = HTAnchor_physical(anchor);        if (type == HTEvent_CLOSE) {			      /* Interrupted */	GopherCleanup(request, HT_INTERRUPTED);	return HT_OK;    } else	gopher = (gopher_info *) HTNet_context(net);	/* Get existing copy */    /* Now jump into the machine. We know the state from the previous run */    while (1) {	switch (gopher->state) {	  case GOPHER_BEGIN:	     /* Get entity type, and selector string */	    {		char *path = HTParse(url, "", PARSE_PATH);		char *selector = path;		char *query = NULL;		char *separator = NULL;		if (*selector) gopher->type = (HTGopherType) *selector++;		if (gopher->type == GT_INDEX) {		    HTAnchor_setIndex(anchor);			 /* Is index */		    query = strchr(selector, '?');		    /* Display local cover page only if no search requested */		    if (!query || !*(query+1)) {       /* No search required */			display_index(request);			gopher->state = GOPHER_GOT_DATA;			HT_FREE(path);			break;		    } else {			*query++ = 0; 				 /* Skip '?' */			separator = "\t";		    }		} else if (gopher->type == GT_CSO) {		    HTAnchor_setIndex(anchor);		/* Search is allowed */		    query = strchr(selector, '?'); /* Look for search string */		    		    /* Display local cover page only if no search requested */		    if (!query || !*(query+1)) {       /* No search required */			display_cso(request);			gopher->state = GOPHER_GOT_DATA;			HT_FREE(path);			break;		    } else {			*query++ = 0; 				 /* Skip '?' */			*selector = 0;			separator = "query ";		    }		}		/* Now generate the final command */		{		    char crlf[3];		    StrAllocCopy(gopher->cmd, selector);		    if (query) {			char *p;			for (p=query; *p; p++)   /* Remove plus signs 921006 */			    if (*p == '+') *p = ' ';			StrAllocCat(gopher->cmd, separator);			StrAllocCat(gopher->cmd, query);		    }		    HTUnEscape(gopher->cmd);		    HTCleanTelnetString(gopher->cmd);   /* Prevent sec holes */		    *crlf = CR;			       /* Telnet termination */		    *(crlf+1) = LF;		    *(crlf+2) = '\0';		    StrAllocCat(gopher->cmd, crlf);		}		HT_FREE(path);		gopher->state = GOPHER_NEED_CONNECTION;	    }	    break;	  case GOPHER_NEED_CONNECTION:	    status = HTHost_connect(host, net, url, GOPHER_PORT);	    host = HTNet_host(net);	    if (status == HT_OK) {		/*		** Check the protocol class to see if we have connected to a		** the right class of server, in this case HTTP.		*/		{		    HTHost * host = HTNet_host(net);		    char * s_class = HTHost_class(host);		    if (s_class && strcasecomp(s_class, "gopher")) {			HTRequest_addError(request, ERR_FATAL, NO, HTERR_CLASS,					   NULL, 0, "HTLoadGopher");			gopher->state = GOPHER_ERROR;			break;		    }		    HTHost_setClass(host, "gopher");		}		/* 		** Create the stream pipe FROM the channel to the application.		** The target for the input stream pipe is set up using the		** stream stack.		*/		{		    if (gopher->type == GT_MENU || gopher->type == GT_INDEX)			net->readStream = GopherMenu_new(request, url, NO);		    else if (gopher->type == GT_CSO)			net->readStream = GopherMenu_new(request, url, YES);		    else			net->readStream = HTStreamStack(WWW_UNKNOWN,					       HTRequest_outputFormat(request),					       HTRequest_outputStream(request),					       request, NO);		    HTRequest_setOutputConnected(request, YES);		}		/*		** Create the stream pipe TO the channel from the application		** and hook it up to the request object		*/		{		    HTOutputStream * output = HTNet_getOutput(net, NULL, 0);		    HTRequest_setInputStream(request, (HTStream *) output);		}		gopher->state = GOPHER_NEED_REQUEST;	    } else if (status == HT_WOULD_BLOCK)		return HT_OK;	    else		gopher->state = GOPHER_ERROR;	    break;	  case GOPHER_NEED_REQUEST:	    HTTRACE(PROT_TRACE, "Gopher Tx... `%s\'" _ gopher->cmd);	    {			HTStream * input = HTRequest_inputStream(request);		status = (*input->isa->put_block)		    (input, gopher->cmd, strlen(gopher->cmd));		if (status == HT_WOULD_BLOCK)		    return HT_OK;		else if (status == HT_ERROR)		    gopher->state = GOPHER_ERROR;		else		    gopher->state = GOPHER_NEED_RESPONSE;	    }	    break;	  case GOPHER_NEED_RESPONSE:	    status = HTHost_read(net->host, net);	    if (status == HT_WOULD_BLOCK)		return HT_OK;	    else if (status == HT_LOADED || status == HT_CLOSED)		gopher->state = GOPHER_GOT_DATA;	    else		gopher->state = GOPHER_ERROR;	    break;	  case GOPHER_GOT_DATA:	    GopherCleanup(request, HT_LOADED);	    return HT_OK;	    break;	  case GOPHER_NO_DATA:	    GopherCleanup(request, HT_NO_DATA);	    return HT_OK;	    break;	  case GOPHER_ERROR:	    GopherCleanup(request, HT_ERROR);	    return HT_OK;	    break;	}    }  /* while(1) */}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -