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

📄 htgopher.c

📁 elinks下lynx是最重要的二个文本浏览器, 在linux下非常实用, lynx比elinks早的多, 目前好像停止开发, 这是lynx源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/*			GOPHER ACCESS				HTGopher.c**			=============****  History:**	26 Sep 90	Adapted from other accesses (News, HTTP) TBL**	29 Nov 91	Downgraded to C, for portable implementation.**	10 Mar 96	Foteos Macrides (macrides@sci.wfbr.edu).  Added a**			  form-based CSO/PH gateway.  Can be invoked via a**			  "cso://host[:port]/" or "gopher://host:105/2"**			  URL.	If a gopher URL is used with a query token**			  ('?'), the old ISINDEX procedure will be used**			  instead of the form-based gateway.**	15 Mar 96	Foteos Macrides (macrides@sci.wfbr.edu).  Pass**			  port 79, gtype 0 gopher URLs to the finger**			  gateway.*/#include <HTUtils.h>		/* Coding convention macros */#ifndef DISABLE_GOPHER#include <HTAlert.h>#include <HTParse.h>#include <HTTCP.h>#include <HTFinger.h>/***  Implements.*/#include <HTGopher.h>#define GOPHER_PORT 70		/* See protocol spec */#define CSO_PORT 105		/* See protocol spec */#define BIG 1024		/* Bug */#define LINE_LENGTH 256		/* Bug *//***  Gopher entity types.*/#define GOPHER_TEXT		'0'#define GOPHER_MENU		'1'#define GOPHER_CSO		'2'#define GOPHER_ERROR		'3'#define GOPHER_MACBINHEX	'4'#define GOPHER_PCBINARY		'5'#define GOPHER_UUENCODED	'6'#define GOPHER_INDEX		'7'#define GOPHER_TELNET		'8'#define GOPHER_BINARY		'9'#define GOPHER_GIF		'g'#define GOPHER_HTML		'h'		/* HTML */#define GOPHER_CHTML		'H'		/* HTML */#define GOPHER_SOUND		's'#define GOPHER_WWW		'w'		/* W3 address */#define GOPHER_IMAGE		'I'#define GOPHER_TN3270		'T'#define GOPHER_INFO		'i'#define GOPHER_DUPLICATE	'+'#define GOPHER_PLUS_IMAGE	':'		/* Addition from Gopher Plus */#define GOPHER_PLUS_MOVIE	';'#define GOPHER_PLUS_SOUND	'<'#define GOPHER_PLUS_PDF		'P'#include <HTFormat.h>/***  Hypertext object building machinery.*/#include <HTML.h>#include <LYStrings.h>#include <LYUtils.h>#include <LYLeaks.h>#define PUTC(c) (*targetClass.put_character)(target, c)#define PUTS(s) (*targetClass.put_string)(target, s)#define START(e) (*targetClass.start_element)(target, e, 0, 0, -1, 0)#define END(e) (*targetClass.end_element)(target, e, 0)#define FREE_TARGET (*targetClass._free)(target)#define GOPHER_PROGRESS(foo) HTAlert(foo)#define NEXT_CHAR HTGetCharacter()/***  Module-wide variables.*/PRIVATE int s;				/* Socket for gopher or CSO host */struct _HTStructured {	CONST HTStructuredClass * isa;	/* For gopher streams */	/* ... */};PRIVATE HTStructured *target;		/* the new gopher hypertext */PRIVATE HTStructuredClass targetClass;	/* Its action routines */struct _HTStream{  HTStreamClass * isa;			/* For form-based CSO  gateway - FM */};typedef struct _CSOfield_info {		/* For form-based CSO gateway - FM */    struct _CSOfield_info *	next;    char *			name;    char *			attributes;    char *			description;    int				id;    int				lookup;    int				indexed;    int				url;    int				max_size;    int				defreturn;    int				explicit_return;    int				reserved;    int				public;    char			name_buf[16];	/* Avoid malloc if we can */    char			desc_buf[32];	/* Avoid malloc if we can */    char			attr_buf[80];	/* Avoid malloc if we can */} CSOfield_info;PRIVATE CSOfield_info *CSOfields = NULL; /* For form-based CSO gateway - FM */typedef struct _CSOformgen_context {	 /* For form-based CSO gateway - FM */    char *		host;    char *		seek;    CSOfield_info *	fld;    int			port;    int			cur_line;    int			cur_off;    int			rep_line;    int			rep_off;    int			public_override;    int			field_select;} CSOformgen_context;/*	Matrix of allowed characters in filenames**	=========================================*/PRIVATE BOOL acceptable[256];PRIVATE BOOL acceptable_inited = NO;PRIVATE void init_acceptable NOARGS{    unsigned int i;    char * good =      "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./-_$";    for(i = 0; i < 256; i++)	acceptable[i] = NO;    for(; *good; good++)	acceptable[(unsigned int)*good] = YES;    acceptable_inited = YES;}/*	Decode one hex character**	========================*/PRIVATE CONST char hex[17] = "0123456789abcdef";PRIVATE char from_hex ARGS1(char, c){    return (char) (       (c>='0')&&(c<='9') ? c-'0'			: (c>='A')&&(c<='F') ? c-'A'+10			: (c>='a')&&(c<='f') ? c-'a'+10			:		       0);}/*	Paste in an Anchor**	==================****	The title of the destination is set, as there is no way**	of knowing what the title is when we arrive.**** On entry,**	HT	is in append mode.**	text	points to the text to be put into the file, 0 terminated.**	addr	points to the hypertext refernce address 0 terminated.*/PUBLIC BOOLEAN HT_Is_Gopher_URL=FALSE;PRIVATE void write_anchor ARGS2(CONST char *,text, CONST char *,addr){    BOOL present[HTML_A_ATTRIBUTES];    CONST char * value[HTML_A_ATTRIBUTES];    int i;    for (i = 0; i < HTML_A_ATTRIBUTES; i++)	present[i] = 0;    present[HTML_A_HREF] = YES;    ((CONST char **)value)[HTML_A_HREF] = addr;    present[HTML_A_TITLE] = YES;    ((CONST char **)value)[HTML_A_TITLE] = text;    CTRACE((tfp,"HTGopher: adding URL: %s\n",addr));    HT_Is_Gopher_URL = TRUE;  /* tell HTML.c that this is a Gopher URL */    (*targetClass.start_element)(target, HTML_A, present,				 (CONST char **)value, -1, 0);    PUTS(text);    END(HTML_A);}/*	Parse a Gopher Menu document**	============================*/PRIVATE void parse_menu ARGS2(	CONST char *,		arg GCC_UNUSED,	HTParentAnchor *,	anAnchor){    char gtype;    int ich;    char line[BIG];    char *name = NULL, *selector = NULL;	/* Gopher menu fields */    char *host = NULL;    char *port;    char *p = line;    CONST char *title;    int bytes = 0;    int BytesReported = 0;    char buffer[128];#define TAB		'\t'#define HEX_ESCAPE	'%'    START(HTML_HTML);    PUTC('\n');    START(HTML_HEAD);    PUTC('\n');    START(HTML_TITLE);    if ((title = HTAnchor_title(anAnchor)))	PUTS(title);    else	PUTS(GOPHER_MENU_TITLE);    END(HTML_TITLE);    PUTC('\n');    END(HTML_HEAD);    PUTC('\n');    START(HTML_BODY);    PUTC('\n');    START(HTML_H1);    if ((title = HTAnchor_title(anAnchor)))	PUTS(title);    else	PUTS(GOPHER_MENU_TITLE);    END(HTML_H1);    PUTC('\n');    START(HTML_PRE);    while ((ich=NEXT_CHAR) != EOF) {	if (interrupted_in_htgetcharacter) {	    CTRACE((tfp, "HTGopher: Interrupted in HTGetCharacter, apparently.\n"));	    goto end_html;	}	if ((char)ich != LF) {	    *p = (char) ich;    /* Put character in line */	    if (p< &line[BIG-1]) p++;	} else {	    *p++ = '\0';	/* Terminate line */	    bytes += p-line;	/* add size */	    p = line;		/* Scan it to parse it */	    port = 0;		/* Flag "not parsed" */	    CTRACE((tfp, "HTGopher: Menu item: %s\n", line));	    gtype = *p++;	    if (bytes > BytesReported + 1024) {		sprintf(buffer, TRANSFERRED_X_BYTES, bytes);		HTProgress(buffer);		BytesReported = bytes;	    }	    /* Break on line with a dot by itself */	    if ((gtype=='.') && ((*p=='\r') || (*p==0)))		break;	    if (gtype && *p) {		name = p;		selector = strchr(name, TAB);		if (selector) {		    *selector++ = '\0'; /* Terminate name */		    /*		     * Gopher+ Type=0+ objects can be binary, and will		     * have 9 or 5 beginning their selector.  Make sure		     * we don't trash the terminal by treating them as		     * text. - FM		     */		    if (gtype == GOPHER_TEXT && (*selector == GOPHER_BINARY ||						 *selector == GOPHER_PCBINARY))			gtype = *selector;		    host = strchr(selector, TAB);		    if (host) {			*host++ = '\0'; /* Terminate selector */			port = strchr(host, TAB);			if (port) {			    char *junk;			    port[0] = ':';	/* delimit host a la W3 */			    junk = strchr(port, TAB);			    if (junk) *junk++ = '\0';	/* Chop port */			    if ((port[1]=='0') && (!port[2]))				port[0] = '\0'; /* 0 means none */			} /* no port */		    } /* host ok */		} /* selector ok */	    } /* gtype and name ok */	    /* Nameless files are a separator line */	    if (gtype == GOPHER_TEXT) {		int i = strlen(name)-1;		while (name[i] == ' ' && i >= 0)		    name[i--] = '\0';		if (i < 0)		    gtype = GOPHER_INFO;	    }	    if (gtype == GOPHER_WWW) {	/* Gopher pointer to W3 */		PUTS("(HTML) ");		write_anchor(name, selector);	    } else if (gtype == GOPHER_INFO) {	    /* Information or separator line */		PUTS("       ");		PUTS(name);	    } else if (port) {		/* Other types need port */		char *address = 0;		char *format = *selector ? "%s//%s@%s/" : "%s//%s/";		if (gtype == GOPHER_TELNET) {		    PUTS(" (TEL) ");		    HTSprintf0(&address, format, STR_TELNET_URL, selector, host);		}		else if (gtype == GOPHER_TN3270)		{		    PUTS("(3270) ");		    HTSprintf0(&address, format, STR_TN3270_URL, selector, host);		}		else {			/* If parsed ok */		    char *r;		    switch(gtype) {			case GOPHER_TEXT:			    PUTS("(FILE) ");			    break;			case GOPHER_MENU:			    PUTS(" (DIR) ");			    break;			case GOPHER_CSO:			    PUTS(" (CSO) ");			    break;			case GOPHER_PCBINARY:			    PUTS(" (BIN) ");			    break;			case GOPHER_UUENCODED:			    PUTS(" (UUE) ");			    break;			case GOPHER_INDEX:			    PUTS("  (?)  ");			    break;			case GOPHER_BINARY:			    PUTS(" (BIN) ");			    break;			case GOPHER_GIF:			case GOPHER_IMAGE:			case GOPHER_PLUS_IMAGE:			    PUTS(" (IMG) ");			    break;			case GOPHER_SOUND:			case GOPHER_PLUS_SOUND:			    PUTS(" (SND) ");			    break;			case GOPHER_MACBINHEX:			    PUTS(" (HQX) ");			    break;			case GOPHER_HTML:			case GOPHER_CHTML:			    PUTS("(HTML) ");			    break;			case 'm':			    PUTS("(MIME) ");			    break;			case GOPHER_PLUS_MOVIE:			    PUTS(" (MOV) ");			    break;			case GOPHER_PLUS_PDF:			    PUTS(" (PDF) ");			    break;			default:			    PUTS("(UNKN) ");			    break;		    }		    HTSprintf0(&address, "//%s/%c", host, gtype);		    for(r = selector; *r; r++) { /* Encode selector string */			if (acceptable[UCH(*r)]) {			    HTSprintf(&address, "%c", *r);			} else {			    HTSprintf(&address, "%c%c%c",				HEX_ESCAPE,	/* Means hex coming */				hex[(TOASCII(*r)) >> 4],				hex[(TOASCII(*r)) & 15]);			}		    }		}		/* Error response from Gopher doesn't deserve to		   be a hyperlink. */		if (strcmp (address, "gopher://error.host:1/0"))		    write_anchor(name, address);		else		    PUTS(name);		FREE(address);	    } else { /* parse error */		CTRACE((tfp, "HTGopher: Bad menu item.\n"));		PUTS(line);	    } /* parse error */	    PUTC('\n');	    p = line;	/* Start again at beginning of line */	} /* if end of line */    } /* Loop over characters */end_html:    END(HTML_PRE);    PUTC('\n');    END(HTML_BODY);    PUTC('\n');    END(HTML_HTML);    PUTC('\n');    FREE_TARGET;    return;}/*	Parse a Gopher CSO document from an ISINDEX query.**	==================================================****   Accepts an open socket to a CSO server waiting to send us**   data and puts it on the screen in a reasonable manner.****   Perhaps this data can be automatically linked to some**   other source as well???****  Taken from hacking by Lou Montulli@ukanaix.cc.ukans.edu**  on XMosaic-1.1, and put on libwww 2.11 by Arthur Secret,**  secret@dxcern.cern.ch .*/PRIVATE void parse_cso ARGS2(	CONST char *,		arg,	HTParentAnchor *,	anAnchor){    int ich;    char line[BIG];    char *p = line;    char *second_colon, last_char='\0';    CONST char *title;    START(HTML_HEAD);    PUTC('\n');    START(HTML_TITLE);    if ((title = HTAnchor_title(anAnchor)))	PUTS(title);    else	PUTS(GOPHER_CSO_SEARCH_RESULTS);    END(HTML_TITLE);    PUTC('\n');    END(HTML_HEAD);    PUTC('\n');    START(HTML_H1);    if ((title = HTAnchor_title(anAnchor)))	PUTS(title);    else {	PUTS(arg);	PUTS(GOPHER_SEARCH_RESULTS);    }    END(HTML_H1);    PUTC('\n');    START(HTML_PRE);    /*    **	Start grabbing chars from the network.

⌨️ 快捷键说明

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