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

📄 fsp.c

📁 elinks下lynx是最重要的二个文本浏览器, 在linux下非常实用, elinks也是gentoo安装过程中默认使用的浏览器, 这是elinks源代码
💻 C
字号:
/* Internal FSP protocol implementation */#ifndef _GNU_SOURCE#define _GNU_SOURCE /* Needed for asprintf() */#endif#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <errno.h>#include <fsplib.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#ifdef HAVE_FCNTL_H#include <fcntl.h> /* OS/2 needs this after sys/types.h */#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#include "elinks.h"#include "cache/cache.h"#include "config/options.h"#include "intl/gettext/libintl.h"#include "main/module.h"#include "main/select.h"#include "network/connection.h"#include "network/socket.h"#include "osdep/osdep.h"#include "protocol/common.h"#include "protocol/protocol.h"#include "protocol/fsp/fsp.h"#include "protocol/uri.h"#include "util/conv.h"#include "util/memory.h"#include "util/snprintf.h"#include "util/string.h"struct option_info fsp_options[] = {	INIT_OPT_TREE("protocol", N_("FSP"),		"fsp", 0,		N_("FSP specific options.")),	INIT_OPT_BOOL("protocol.fsp", N_("Sort entries"),		"sort", 0, 1,		N_("Whether to sort entries in directory listings.")),	NULL_OPTION_INFO,};struct module fsp_protocol_module = struct_module(	/* name: */		N_("FSP"),	/* options: */		fsp_options,	/* hooks: */		NULL,	/* submodules: */	NULL,	/* data: */		NULL,	/* init: */		NULL,	/* done: */		NULL);static voidfsp_error(unsigned char *error){	fprintf(stderr, "text/plain");	puts(error);	exit(1);}static intcompare(FSP_RDENTRY *a, FSP_RDENTRY *b){	int res = ((b->type == FSP_RDTYPE_DIR) - (a->type == FSP_RDTYPE_DIR));	if (res)		return res;	return strcmp(a->name, b->name);}static voidsort_and_display_entries(FSP_DIR *dir){	FSP_RDENTRY fentry, *fresult, *table = NULL;	int size = 0;	int i;	unsigned char dircolor[8];	if (get_opt_bool("document.browse.links.color_dirs")) {		color_to_string(get_opt_color("document.colors.dirs"),			(unsigned char *) &dircolor);	} else {		dircolor[0] = 0;	}	while (!fsp_readdir_native(dir, &fentry, &fresult)) {		FSP_RDENTRY *new_table;		if (!fresult) break;		if (!strcmp(fentry.name, "."))			continue;		new_table = mem_realloc(table, (size + 1) * sizeof(*table));		if (!new_table)			continue;		table = new_table;		memcpy(&table[size], &fentry, sizeof(fentry));		size++;	}	qsort(table, size, sizeof(*table),	 (int (*)(const void *, const void *)) compare);	for (i = 0; i < size; i++) {		printf("%10d\t<a href=\"%s%s\">", table[i].size, table[i].name,			table[i].type == FSP_RDTYPE_DIR ? "/" : "");		if (table[i].type == FSP_RDTYPE_DIR && *dircolor)			printf("<font color=\"%s\"><b>", dircolor);		printf("%s", table[i].name);		if (table[i].type == FSP_RDTYPE_DIR && *dircolor)			printf("</b></font>");		puts("</a>");	}}static voidfsp_directory(FSP_SESSION *ses, struct uri *uri){	struct string buf;	FSP_DIR *dir;	unsigned char *uristring = get_uri_string(uri, URI_PUBLIC);	unsigned char *data = get_uri_string(uri, URI_DATA);	if (!uristring || !data || !init_string(&buf))		fsp_error("Out of memory");	fprintf(stderr, "text/html");	fclose(stderr);	add_html_to_string(&buf, uristring, strlen(uristring));	printf("<html><head><title>%s</title><base href=\"%s\">"	       "</head><body><h2>FSP directory %s</h2><pre>",	       buf.source, uristring, buf.source);	dir = fsp_opendir(ses, data);	if (!dir) goto end;	if (get_opt_bool("protocol.fsp.sort")) {		sort_and_display_entries(dir);	} else {		FSP_RDENTRY fentry, *fresult;		unsigned char dircolor[8];		if (get_opt_bool("document.browse.links.color_dirs")) {			color_to_string(get_opt_color("document.colors.dirs"),				(unsigned char *) &dircolor);		} else {			dircolor[0] = 0;		}		while (!fsp_readdir_native(dir, &fentry, &fresult)) {			if (!fresult) break;			printf("%10d\t<a href=\"%s%s\">", fentry.size,			 fentry.name, fentry.type == FSP_RDTYPE_DIR ? "/" : "");			if (fentry.type == FSP_RDTYPE_DIR && *dircolor)				printf("<font color=\"%s\"><b>", dircolor);			printf("%s", fentry.name);			if (fentry.type == FSP_RDTYPE_DIR && *dircolor)				printf("</b></font>");			puts("</a>");		}		fsp_closedir(dir);	}end:	puts("</pre><hr></body></html>");	fsp_close_session(ses);	exit(0);}#define READ_SIZE	4096static voiddo_fsp(struct connection *conn){	struct stat sb;	struct uri *uri = conn->uri;	unsigned char *host = get_uri_string(uri, URI_HOST);	unsigned char *password = get_uri_string(uri, URI_PASSWORD);	unsigned char *data = get_uri_string(uri, URI_DATA);	unsigned short port = (unsigned short)get_uri_port(uri);	FSP_SESSION *ses = fsp_open_session(host, port, password);	if (!ses)		fsp_error("Session initialization failed.");	if (fsp_stat(ses, data, &sb))		fsp_error("File not found.");	if (S_ISDIR(sb.st_mode))		fsp_directory(ses, uri);	else { /* regular file */		char buf[READ_SIZE];		FSP_FILE *file = fsp_fopen(ses, data, "r");		int r;		if (!file)			fsp_error("fsp_fopen error.");		/* Use the default way to find the MIME type, so write an		 * 'empty' name, since something needs to be written in order		 * to avoid socket errors. */		fprintf(stderr, "%c", '\0');		fclose(stderr);		while ((r = fsp_fread(buf, 1, READ_SIZE, file)) > 0)			fwrite(buf, 1, r, stdout);		fsp_fclose(file);		fsp_close_session(ses);		exit(0);	}}static voidfsp_got_data(struct socket *socket, struct read_buffer *rb){	int len = rb->length;	struct connection *conn = socket->conn;	if (len < 0) {		abort_connection(conn, -errno);		return;	}	if (!len) {		if (conn->from)			normalize_cache_entry(conn->cached, conn->from);		abort_connection(conn, S_OK);		return;	}	socket->state = SOCKET_END_ONCLOSE;	conn->received += len;	if (add_fragment(conn->cached, conn->from, rb->data, len) == 1)		conn->tries = 0;	conn->from += len;	kill_buffer_data(rb, len);	read_from_socket(socket, rb, S_TRANS, fsp_got_data);}static voidfsp_got_header(struct socket *socket, struct read_buffer *rb){	struct connection *conn = socket->conn;	struct read_buffer *buf;	conn->cached = get_cache_entry(conn->uri);	if (!conn->cached) {		close(socket->fd);		close(conn->data_socket->fd);		abort_connection(conn, S_OUT_OF_MEM);		return;	}	socket->state = SOCKET_END_ONCLOSE;	if (rb->length > 0) {		unsigned char *ctype = memacpy(rb->data, rb->length);		if (ctype && *ctype)			mem_free_set(&conn->cached->content_type, ctype);		else			mem_free_if(ctype);	}	buf = alloc_read_buffer(conn->data_socket);	if (!buf) {		close(socket->fd);		close(conn->data_socket->fd);		abort_connection(conn, S_OUT_OF_MEM);		return;	}	read_from_socket(conn->data_socket, buf, S_CONN, fsp_got_data); }#undef READ_SIZEvoidfsp_protocol_handler(struct connection *conn){	int fsp_pipe[2] = { -1, -1 };	int header_pipe[2] = { -1, -1 };	pid_t cpid;	if (c_pipe(fsp_pipe) || c_pipe(header_pipe)) {		int s_errno = errno;		if (fsp_pipe[0] >= 0) close(fsp_pipe[0]);		if (fsp_pipe[1] >= 0) close(fsp_pipe[1]);		if (header_pipe[0] >= 0) close(header_pipe[0]);		if (header_pipe[1] >= 0) close(header_pipe[1]);		abort_connection(conn, -s_errno);		return;	}	conn->from = 0;	conn->unrestartable = 1;	cpid = fork();	if (cpid == -1) {		int s_errno = errno;		close(fsp_pipe[0]);		close(fsp_pipe[1]);		close(header_pipe[0]);		close(header_pipe[1]);		retry_connection(conn, -s_errno);		return;	}	if (!cpid) {		close(1);		dup2(fsp_pipe[1], 1);		close(0);		dup2(open("/dev/null", O_RDONLY), 0);		close(2);		dup2(header_pipe[1], 2);		close(fsp_pipe[0]);		close(header_pipe[0]);		close_all_non_term_fd();		do_fsp(conn);	} else {		struct read_buffer *buf2;		conn->data_socket->fd = fsp_pipe[0];		conn->socket->fd = header_pipe[0];		close(fsp_pipe[1]);		close(header_pipe[1]);		buf2 = alloc_read_buffer(conn->socket);		if (!buf2) {			close(fsp_pipe[0]);			close(header_pipe[0]);			abort_connection(conn, S_OUT_OF_MEM);			return;		}		read_from_socket(conn->socket, buf2, S_CONN, fsp_got_header);	}}

⌨️ 快捷键说明

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