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

📄 gopher.c

📁 -
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * $Id: gopher.c,v 1.150 1999/01/31 15:58:54 wessels Exp $ * * DEBUG: section 10    Gopher * AUTHOR: Harvest Derived * * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/ * ---------------------------------------------------------- * *  Squid is the result of efforts by numerous individuals from the *  Internet community.  Development is led by Duane Wessels of the *  National Laboratory for Applied Network Research and funded by the *  National Science Foundation.  Squid is Copyrighted (C) 1998 by *  Duane Wessels and the University of California San Diego.  Please *  see the COPYRIGHT file for full details.  Squid incorporates *  software developed and/or copyrighted by other sources.  Please see *  the CREDITS file for full details. * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. *   *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. *   *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */#include "squid.h"/* gopher type code from rfc. Anawat. */#define GOPHER_FILE         '0'#define GOPHER_DIRECTORY    '1'#define GOPHER_CSO          '2'#define GOPHER_ERROR        '3'#define GOPHER_MACBINHEX    '4'#define GOPHER_DOSBIN       '5'#define GOPHER_UUENCODED    '6'#define GOPHER_INDEX        '7'#define GOPHER_TELNET       '8'#define GOPHER_BIN          '9'#define GOPHER_REDUNT       '+'#define GOPHER_3270         'T'#define GOPHER_GIF          'g'#define GOPHER_IMAGE        'I'#define GOPHER_HTML         'h'	/* HTML */#define GOPHER_INFO         'i'#define GOPHER_WWW          'w'	/* W3 address */#define GOPHER_SOUND        's'#define GOPHER_PLUS_IMAGE   ':'#define GOPHER_PLUS_MOVIE   ';'#define GOPHER_PLUS_SOUND   '<'#define GOPHER_PORT         70#define TAB                 '\t'#define TEMP_BUF_SIZE       4096#define MAX_CSO_RESULT      1024typedef struct gopher_ds {    StoreEntry *entry;    char host[SQUIDHOSTNAMELEN + 1];    enum {	NORMAL,	HTML_DIR,	HTML_INDEX_RESULT,	HTML_CSO_RESULT,	HTML_INDEX_PAGE,	HTML_CSO_PAGE    } conversion;    int HTML_header_added;    int port;    char type_id;    char request[MAX_URL];    int data_in;    int cso_recno;    int len;    char *buf;			/* pts to a 4k page */    int fd;    FwdState *fwdState;} GopherStateData;static PF gopherStateFree;static void gopher_mime_content(MemBuf * mb, const char *name, const char *def);static void gopherMimeCreate(GopherStateData *);static int gopher_url_parser(const char *url,    char *host,    int *port,    char *type_id,    char *request);static void gopherEndHTML(GopherStateData *);static void gopherToHTML(GopherStateData *, char *inbuf, int len);static PF gopherTimeout;static PF gopherReadReply;static CWCB gopherSendComplete;static PF gopherSendRequest;static GopherStateData *CreateGopherStateData(void);static char def_gopher_bin[] = "www/unknown";static char def_gopher_text[] = "text/plain";static voidgopherStateFree(int fdnotused, void *data){    GopherStateData *gopherState = data;    if (gopherState == NULL)	return;    if (gopherState->entry) {	storeUnlockObject(gopherState->entry);    }    memFree(gopherState->buf, MEM_4K_BUF);    gopherState->buf = NULL;    cbdataFree(gopherState);}/* figure out content type from file extension */static voidgopher_mime_content(MemBuf * mb, const char *name, const char *def_ctype){    char *ctype = mimeGetContentType(name);    char *cenc = mimeGetContentEncoding(name);    if (cenc)	memBufPrintf(mb, "Content-Encoding: %s\r\n", cenc);    memBufPrintf(mb, "Content-Type: %s\r\n",	ctype ? ctype : def_ctype);}/* create MIME Header for Gopher Data */static voidgopherMimeCreate(GopherStateData * gopherState){    MemBuf mb;    memBufDefInit(&mb);    memBufPrintf(&mb,	"HTTP/1.0 200 OK Gatewaying\r\n"	"Server: Squid/%s\r\n"	"Date: %s\r\n"	"MIME-version: 1.0\r\n",	version_string, mkrfc1123(squid_curtime));    switch (gopherState->type_id) {    case GOPHER_DIRECTORY:    case GOPHER_INDEX:    case GOPHER_HTML:    case GOPHER_WWW:    case GOPHER_CSO:	memBufPrintf(&mb, "Content-Type: text/html\r\n");	break;    case GOPHER_GIF:    case GOPHER_IMAGE:    case GOPHER_PLUS_IMAGE:	memBufPrintf(&mb, "Content-Type: image/gif\r\n");	break;    case GOPHER_SOUND:    case GOPHER_PLUS_SOUND:	memBufPrintf(&mb, "Content-Type: audio/basic\r\n");	break;    case GOPHER_PLUS_MOVIE:	memBufPrintf(&mb, "Content-Type: video/mpeg\r\n");	break;    case GOPHER_MACBINHEX:    case GOPHER_DOSBIN:    case GOPHER_UUENCODED:    case GOPHER_BIN:	/* Rightnow We have no idea what it is. */	gopher_mime_content(&mb, gopherState->request, def_gopher_bin);	break;    case GOPHER_FILE:    default:	gopher_mime_content(&mb, gopherState->request, def_gopher_text);	break;    }    memBufPrintf(&mb, "\r\n");    EBIT_CLR(gopherState->entry->flags, ENTRY_FWD_HDR_WAIT);    storeAppend(gopherState->entry, mb.buf, mb.size);    memBufClean(&mb);}/* Parse a gopher url into components.  By Anawat. */static intgopher_url_parser(const char *url, char *host, int *port, char *type_id, char *request){    LOCAL_ARRAY(char, proto, MAX_URL);    LOCAL_ARRAY(char, hostbuf, MAX_URL);    int t;    proto[0] = hostbuf[0] = '\0';    host[0] = request[0] = '\0';    (*port) = 0;    (*type_id) = 0;    t = sscanf(url,#if defined(__QNX__)	"%[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]://%[^/]/%c%s",#else	"%[a-zA-Z]://%[^/]/%c%s",#endif	proto, hostbuf, type_id, request);    if ((t < 2) || strcasecmp(proto, "gopher")) {	return -1;    } else if (t == 2) {	(*type_id) = GOPHER_DIRECTORY;	request[0] = '\0';    } else if (t == 3) {	request[0] = '\0';    } else {	/* convert %xx to char */	url_convert_hex(request, 0);    }    host[0] = '\0';    if (sscanf(hostbuf, "%[^:]:%d", host, port) < 2)	(*port) = GOPHER_PORT;    return 0;}intgopherCachable(const char *url){    GopherStateData *gopherState = NULL;    int cachable = 1;    /* use as temp data structure to parse gopher URL */    gopherState = CreateGopherStateData();    /* parse to see type */    gopher_url_parser(url,	gopherState->host,	&gopherState->port,	&gopherState->type_id,	gopherState->request);    switch (gopherState->type_id) {    case GOPHER_INDEX:    case GOPHER_CSO:    case GOPHER_TELNET:    case GOPHER_3270:	cachable = 0;	break;    default:	cachable = 1;    }    gopherStateFree(-1, gopherState);    return cachable;}static voidgopherEndHTML(GopherStateData * gopherState){    if (!gopherState->data_in)	storeAppendPrintf(gopherState->entry,	    "<HTML><HEAD><TITLE>Server Return Nothing.</TITLE>\n"	    "</HEAD><BODY><HR><H1>Server Return Nothing.</H1></BODY></HTML>\n");}/* Convert Gopher to HTML *//* Borrow part of code from libwww2 came with Mosaic distribution */static voidgopherToHTML(GopherStateData * gopherState, char *inbuf, int len){    char *pos = inbuf;    char *lpos = NULL;    char *tline = NULL;    LOCAL_ARRAY(char, line, TEMP_BUF_SIZE);    LOCAL_ARRAY(char, tmpbuf, TEMP_BUF_SIZE);    LOCAL_ARRAY(char, outbuf, TEMP_BUF_SIZE << 4);    char *name = NULL;    char *selector = NULL;    char *host = NULL;    char *port = NULL;    char *escaped_selector = NULL;    char *icon_url = NULL;    char gtype;    StoreEntry *entry = NULL;    memset(outbuf, '\0', TEMP_BUF_SIZE << 4);    memset(tmpbuf, '\0', TEMP_BUF_SIZE);    memset(line, '\0', TEMP_BUF_SIZE);    entry = gopherState->entry;    if (gopherState->conversion == HTML_INDEX_PAGE) {	storeAppendPrintf(entry,	    "<HTML><HEAD><TITLE>Gopher Index %s</TITLE></HEAD>\n"	    "<BODY><H1>%s<BR>Gopher Search</H1>\n"	    "<p>This is a searchable Gopher index. Use the search\n"	    "function of your browser to enter search terms.\n"	    "<ISINDEX></BODY></HTML>\n",	    storeUrl(entry), storeUrl(entry));	/* now let start sending stuff to client */	storeBufferFlush(entry);	gopherState->data_in = 1;	return;    }    if (gopherState->conversion == HTML_CSO_PAGE) {	storeAppendPrintf(entry,	    "<HTML><HEAD><TITLE>CSO Search of %s</TITLE></HEAD>\n"	    "<BODY><H1>%s<BR>CSO Search</H1>\n"	    "<P>A CSO database usually contains a phonebook or\n"	    "directory.  Use the search function of your browser to enter\n"	    "search terms.</P><ISINDEX></BODY></HTML>\n",	    storeUrl(entry), storeUrl(entry));	/* now let start sending stuff to client */	storeBufferFlush(entry);	gopherState->data_in = 1;	return;    }    inbuf[len] = '\0';    if (!gopherState->HTML_header_added) {	if (gopherState->conversion == HTML_CSO_RESULT)	    strcat(outbuf, "<HTML><HEAD><TITLE>CSO Searchs Result</TITLE></HEAD>\n"		"<BODY><H1>CSO Searchs Result</H1>\n<PRE>\n");	else	    strcat(outbuf, "<HTML><HEAD><TITLE>Gopher Menu</TITLE></HEAD>\n"		"<BODY><H1>Gopher Menu</H1>\n<PRE>\n");	gopherState->HTML_header_added = 1;    }    while ((pos != NULL) && (pos < inbuf + len)) {	if (gopherState->len != 0) {	    /* there is something left from last tx. */	    xstrncpy(line, gopherState->buf, gopherState->len);	    lpos = (char *) memccpy(line + gopherState->len, inbuf, '\n', len);	    if (lpos)		*lpos = '\0';	    else {		/* there is no complete line in inbuf */		/* copy it to temp buffer */		if (gopherState->len + len > TEMP_BUF_SIZE) {		    debug(10, 1) ("GopherHTML: Buffer overflow. Lost some data on URL: %s\n",			storeUrl(entry));		    len = TEMP_BUF_SIZE - gopherState->len;		}		xmemcpy(gopherState->buf + gopherState->len, inbuf, len);		gopherState->len += len;		return;	    }	    /* skip one line */	    pos = (char *) memchr(pos, '\n', len);	    if (pos)		pos++;	    /* we're done with the remain from last tx. */	    gopherState->len = 0;	    *(gopherState->buf) = '\0';	} else {	    lpos = (char *) memccpy(line, pos, '\n', len - (pos - inbuf));	    if (lpos)		*lpos = '\0';	    else {		/* there is no complete line in inbuf */		/* copy it to temp buffer */		if ((len - (pos - inbuf)) > TEMP_BUF_SIZE) {		    debug(10, 1) ("GopherHTML: Buffer overflow. Lost some data on URL: %s\n",			storeUrl(entry));		    len = TEMP_BUF_SIZE;		}		if (len > (pos - inbuf)) {		    xmemcpy(gopherState->buf, pos, len - (pos - inbuf));		    gopherState->len = len - (pos - inbuf);		}		break;	    }	    /* skip one line */	    pos = (char *) memchr(pos, '\n', len);	    if (pos)		pos++;	}	/* at this point. We should have one line in buffer to process */	if (*line == '.') {	    /* skip it */	    memset(line, '\0', TEMP_BUF_SIZE);	    continue;	}	switch (gopherState->conversion) {	case HTML_INDEX_RESULT:	case HTML_DIR:{		tline = line;		gtype = *tline++;		name = tline;		selector = strchr(tline, TAB);		if (selector) {		    *selector++ = '\0';		    host = strchr(selector, TAB);		    if (host) {			*host++ = '\0';			port = strchr(host, TAB);

⌨️ 快捷键说明

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