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

📄 gopher.c

📁 -
💻 C
📖 第 1 页 / 共 2 页
字号:
			if (port) {			    char *junk;			    port[0] = ':';			    junk = strchr(host, TAB);			    if (junk)				*junk++ = 0;	/* Chop port */			    else {				junk = strchr(host, '\r');				if (junk)				    *junk++ = 0;	/* Chop port */				else {				    junk = strchr(host, '\n');				    if (junk)					*junk++ = 0;	/* Chop port */				}			    }			    if ((port[1] == '0') && (!port[2]))				port[0] = 0;	/* 0 means none */			}			/* escape a selector here */			escaped_selector = xstrdup(rfc1738_escape(selector));			switch (gtype) {			case GOPHER_DIRECTORY:			    icon_url = mimeGetIconURL("internal-menu");			    break;			case GOPHER_FILE:			    icon_url = mimeGetIconURL("internal-text");			    break;			case GOPHER_INDEX:			case GOPHER_CSO:			    icon_url = mimeGetIconURL("internal-index");			    break;			case GOPHER_IMAGE:			case GOPHER_GIF:			case GOPHER_PLUS_IMAGE:			    icon_url = mimeGetIconURL("internal-image");			    break;			case GOPHER_SOUND:			case GOPHER_PLUS_SOUND:			    icon_url = mimeGetIconURL("internal-sound");			    break;			case GOPHER_PLUS_MOVIE:			    icon_url = mimeGetIconURL("internal-movie");			    break;			case GOPHER_TELNET:			case GOPHER_3270:			    icon_url = mimeGetIconURL("internal-telnet");			    break;			case GOPHER_BIN:			case GOPHER_MACBINHEX:			case GOPHER_DOSBIN:			case GOPHER_UUENCODED:			    icon_url = mimeGetIconURL("internal-binary");			    break;			default:			    icon_url = mimeGetIconURL("internal-unknown");			    break;			}			memset(tmpbuf, '\0', TEMP_BUF_SIZE);			if ((gtype == GOPHER_TELNET) || (gtype == GOPHER_3270)) {			    if (strlen(escaped_selector) != 0)				snprintf(tmpbuf, TEMP_BUF_SIZE, "<IMG BORDER=0 SRC=\"%s\"> <A HREF=\"telnet://%s@%s/\">%s</A>\n",				    icon_url, escaped_selector, host, name);			    else				snprintf(tmpbuf, TEMP_BUF_SIZE, "<IMG BORDER=0 SRC=\"%s\"> <A HREF=\"telnet://%s/\">%s</A>\n",				    icon_url, host, name);			} else {			    snprintf(tmpbuf, TEMP_BUF_SIZE, "<IMG BORDER=0 SRC=\"%s\"> <A HREF=\"gopher://%s/%c%s\">%s</A>\n",				icon_url, host, gtype, escaped_selector, name);			}			safe_free(escaped_selector);			strcat(outbuf, tmpbuf);			gopherState->data_in = 1;		    } else {			memset(line, '\0', TEMP_BUF_SIZE);			continue;		    }		} else {		    memset(line, '\0', TEMP_BUF_SIZE);		    continue;		}		break;	    }			/* HTML_DIR, HTML_INDEX_RESULT */	case HTML_CSO_RESULT:{		int t;		int code;		int recno;		LOCAL_ARRAY(char, result, MAX_CSO_RESULT);		tline = line;		if (tline[0] == '-') {		    t = sscanf(tline, "-%d:%d:%[^\n]", &code, &recno, result);		    if (t < 3)			break;		    if (code != 200)			break;		    if (gopherState->cso_recno != recno) {			snprintf(tmpbuf, TEMP_BUF_SIZE, "</PRE><HR><H2>Record# %d<br><i>%s</i></H2>\n<PRE>", recno, result);			gopherState->cso_recno = recno;		    } else {			snprintf(tmpbuf, TEMP_BUF_SIZE, "%s\n", result);		    }		    strcat(outbuf, tmpbuf);		    gopherState->data_in = 1;		    break;		} else {		    /* handle some error codes */		    t = sscanf(tline, "%d:%[^\n]", &code, result);		    if (t < 2)			break;		    switch (code) {		    case 200:{			    /* OK */			    /* Do nothing here */			    break;			}		    case 102:	/* Number of matches */		    case 501:	/* No Match */		    case 502:	/* Too Many Matches */			{			    /* Print the message the server returns */			    snprintf(tmpbuf, TEMP_BUF_SIZE, "</PRE><HR><H2>%s</H2>\n<PRE>", result);			    strcat(outbuf, tmpbuf);			    gopherState->data_in = 1;			    break;			}		    }		}	    }			/* HTML_CSO_RESULT */	default:	    break;		/* do nothing */	}			/* switch */    }				/* while loop */    if ((int) strlen(outbuf) > 0) {	storeAppend(entry, outbuf, strlen(outbuf));	/* now let start sending stuff to client */	storeBufferFlush(entry);    }    return;}static voidgopherTimeout(int fd, void *data){    GopherStateData *gopherState = data;    StoreEntry *entry = gopherState->entry;    debug(10, 4) ("gopherTimeout: FD %d: '%s'\n", fd, storeUrl(entry));    if (entry->store_status == STORE_PENDING) {	if (entry->mem_obj->inmem_hi == 0) {	    fwdFail(gopherState->fwdState,		errorCon(ERR_READ_TIMEOUT, HTTP_GATEWAY_TIMEOUT));	}    }    comm_close(fd);}/* This will be called when data is ready to be read from fd.  Read until * error or connection closed. */static voidgopherReadReply(int fd, void *data){    GopherStateData *gopherState = data;    StoreEntry *entry = gopherState->entry;    char *buf = NULL;    int len;    int clen;    int bin;    size_t read_sz;#if DELAY_POOLS    delay_id delay_id = delayMostBytesAllowed(entry->mem_obj);#endif    if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {	comm_close(fd);	return;    }    errno = 0;    buf = memAllocate(MEM_4K_BUF);    read_sz = 4096 - 1;		/* leave room for termination */#if DELAY_POOLS    read_sz = delayBytesWanted(delay_id, 1, read_sz);#endif    /* leave one space for \0 in gopherToHTML */    Counter.syscalls.sock.reads++;    len = read(fd, buf, read_sz);    if (len > 0) {	fd_bytes(fd, len, FD_READ);#if DELAY_POOLS	delayBytesIn(delay_id, len);#endif	kb_incr(&Counter.server.all.kbytes_in, len);	kb_incr(&Counter.server.other.kbytes_in, len);    }    debug(10, 5) ("gopherReadReply: FD %d read len=%d\n", fd, len);    if (len > 0) {	commSetTimeout(fd, Config.Timeout.read, NULL, NULL);	IOStats.Gopher.reads++;	for (clen = len - 1, bin = 0; clen; bin++)	    clen >>= 1;	IOStats.Gopher.read_hist[bin]++;    }    if (len < 0) {	debug(50, 1) ("gopherReadReply: error reading: %s\n", xstrerror());	if (ignoreErrno(errno)) {	    commSetSelect(fd, COMM_SELECT_READ, gopherReadReply, data, 0);	} else if (entry->mem_obj->inmem_hi == 0) {	    ErrorState *err;	    err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR);	    err->xerrno = errno;	    err->url = xstrdup(storeUrl(entry));	    errorAppendEntry(entry, err);	    comm_close(fd);	} else {	    comm_close(fd);	}    } else if (len == 0 && entry->mem_obj->inmem_hi == 0) {	ErrorState *err;	err = errorCon(ERR_ZERO_SIZE_OBJECT, HTTP_SERVICE_UNAVAILABLE);	err->xerrno = errno;	err->url = xstrdup(gopherState->request);	errorAppendEntry(entry, err);	comm_close(fd);    } else if (len == 0) {	/* Connection closed; retrieval done. */	/* flush the rest of data in temp buf if there is one. */	if (gopherState->conversion != NORMAL)	    gopherEndHTML(data);	storeTimestampsSet(entry);	storeBufferFlush(entry);	fwdComplete(gopherState->fwdState);	comm_close(fd);    } else {	if (gopherState->conversion != NORMAL) {	    gopherToHTML(data, buf, len);	} else {	    storeAppend(entry, buf, len);	}	commSetSelect(fd,	    COMM_SELECT_READ,	    gopherReadReply,	    data, 0);    }    memFree(buf, MEM_4K_BUF);    return;}/* This will be called when request write is complete. Schedule read of * reply. */static voidgopherSendComplete(int fd, char *buf, size_t size, int errflag, void *data){    GopherStateData *gopherState = (GopherStateData *) data;    StoreEntry *entry = gopherState->entry;    debug(10, 5) ("gopherSendComplete: FD %d size: %d errflag: %d\n",	fd, size, errflag);    if (size > 0) {	fd_bytes(fd, size, FD_WRITE);	kb_incr(&Counter.server.all.kbytes_out, size);	kb_incr(&Counter.server.other.kbytes_out, size);    }    if (errflag) {	ErrorState *err;	err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE);	err->xerrno = errno;	err->host = xstrdup(gopherState->host);	err->port = gopherState->port;	err->url = xstrdup(storeUrl(entry));	errorAppendEntry(entry, err);	comm_close(fd);	if (buf)	    memFree(buf, MEM_4K_BUF);	/* Allocated by gopherSendRequest. */	return;    }    /*      * OK. We successfully reach remote site.  Start MIME typing     * stuff.  Do it anyway even though request is not HTML type.     */    gopherMimeCreate(gopherState);    switch (gopherState->type_id) {    case GOPHER_DIRECTORY:	/* we got to convert it first */	storeBuffer(entry);	gopherState->conversion = HTML_DIR;	gopherState->HTML_header_added = 0;	break;    case GOPHER_INDEX:	/* we got to convert it first */	storeBuffer(entry);	gopherState->conversion = HTML_INDEX_RESULT;	gopherState->HTML_header_added = 0;	break;    case GOPHER_CSO:	/* we got to convert it first */	storeBuffer(entry);	gopherState->conversion = HTML_CSO_RESULT;	gopherState->cso_recno = 0;	gopherState->HTML_header_added = 0;	break;    default:	gopherState->conversion = NORMAL;    }    /* Schedule read reply. */    commSetSelect(fd, COMM_SELECT_READ, gopherReadReply, gopherState, 0);    commSetDefer(fd, fwdCheckDeferRead, entry);    if (buf)	memFree(buf, MEM_4K_BUF);	/* Allocated by gopherSendRequest. */}/* This will be called when connect completes. Write request. */static voidgopherSendRequest(int fd, void *data){    GopherStateData *gopherState = data;    LOCAL_ARRAY(char, query, MAX_URL);    char *buf = memAllocate(MEM_4K_BUF);    char *t;    if (gopherState->type_id == GOPHER_CSO) {	sscanf(gopherState->request, "?%s", query);	snprintf(buf, 4096, "query %s\r\nquit\r\n", query);    } else if (gopherState->type_id == GOPHER_INDEX) {	if ((t = strchr(gopherState->request, '?')))	    *t = '\t';	snprintf(buf, 4096, "%s\r\n", gopherState->request);    } else {	snprintf(buf, 4096, "%s\r\n", gopherState->request);    }    debug(10, 5) ("gopherSendRequest: FD %d\n", fd);    comm_write(fd,	buf,	strlen(buf),	gopherSendComplete,	data,	memFree4K);    if (EBIT_TEST(gopherState->entry->flags, ENTRY_CACHABLE))	storeSetPublicKey(gopherState->entry);	/* Make it public */}voidgopherStart(FwdState * fwdState){    int fd = fwdState->server_fd;    StoreEntry *entry = fwdState->entry;    GopherStateData *gopherState = CreateGopherStateData();    storeLockObject(entry);    gopherState->entry = entry;    debug(10, 3) ("gopherStart: %s\n", storeUrl(entry));    Counter.server.all.requests++;    Counter.server.other.requests++;    /* Parse url. */    if (gopher_url_parser(storeUrl(entry), gopherState->host, &gopherState->port,	    &gopherState->type_id, gopherState->request)) {	ErrorState *err;	err = errorCon(ERR_INVALID_URL, HTTP_BAD_REQUEST);	err->url = xstrdup(storeUrl(entry));	errorAppendEntry(entry, err);	gopherStateFree(-1, gopherState);	return;    }    comm_add_close_handler(fd, gopherStateFree, gopherState);    if (((gopherState->type_id == GOPHER_INDEX) || (gopherState->type_id == GOPHER_CSO))	&& (strchr(gopherState->request, '?') == NULL)) {	/* Index URL without query word */	/* We have to generate search page back to client. No need for connection */	gopherMimeCreate(gopherState);	if (gopherState->type_id == GOPHER_INDEX) {	    gopherState->conversion = HTML_INDEX_PAGE;	} else {	    if (gopherState->type_id == GOPHER_CSO) {		gopherState->conversion = HTML_CSO_PAGE;	    } else {		gopherState->conversion = HTML_INDEX_PAGE;	    }	}	gopherToHTML(gopherState, (char *) NULL, 0);	fwdComplete(fwdState);	comm_close(fd);	return;    }    gopherState->fd = fd;    gopherState->fwdState = fwdState;    commSetSelect(fd, COMM_SELECT_WRITE, gopherSendRequest, gopherState, 0);    commSetTimeout(fd, Config.Timeout.read, gopherTimeout, gopherState);}static GopherStateData *CreateGopherStateData(void){    GopherStateData *gd = xcalloc(1, sizeof(GopherStateData));    cbdataAdd(gd, cbdataXfree, 0);    gd->buf = memAllocate(MEM_4K_BUF);    return (gd);}

⌨️ 快捷键说明

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