1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-06-20 00:15:31 +00:00

- FSP protocol

This commit is contained in:
2006-01-16 11:40:13 +01:00
parent becf3b42ab
commit bb9b4437fa
9 changed files with 396 additions and 0 deletions

View File

@ -114,6 +114,7 @@ CONFIG_EXMODE = @CONFIG_EXMODE@
CONFIG_FASTMEM = @CONFIG_FASTMEM@
CONFIG_FINGER = @CONFIG_FINGER@
CONFIG_FORMHIST = @CONFIG_FORMHIST@
CONFIG_FSP = @CONFIG_FSP@
CONFIG_FTP = @CONFIG_FTP@
CONFIG_GLOBHIST = @CONFIG_GLOBHIST@
CONFIG_GNUTLS = @CONFIG_GNUTLS@

View File

@ -1132,6 +1132,24 @@ EL_ARG_DEPEND(CONFIG_CGI, cgi, [HAVE_SETENV_OR_PUTENV:yes], [Local CGI],
EL_ARG_ENABLE(CONFIG_FINGER, finger, [Finger protocol],
[ --enable-finger enable finger protocol support])
dnl ===================================================================
dnl FSP protocol
dnl ===================================================================
EL_ARG_ENABLE(CONFIG_FSP, fsp, [FSP protocol],
[ --enable-fsp enable FSP protocol support])
if test "x${enable_fsp}" != xno; then
AC_CHECK_HEADERS(fsplib.h, CONFIG_FSP=yes, CONFIG_FSP=no)
if test "$CONFIG_FSP" = yes; then
AC_CHECK_LIB(fsplib, fsp_open_session, CONFIG_FSP=yes, CONFIG_FSP=no)
if test "$CONFIG_FSP" = yes; then
LIBS="$LIBS -lfsplib"
fi
fi
fi
EL_ARG_ENABLE(CONFIG_FTP, ftp, [FTP protocol],
[ --disable-ftp disable ftp protocol support])

View File

@ -297,6 +297,13 @@ CONFIG_DATA=yes
CONFIG_FINGER=no
### FSP protocol
#
# See: http://fsp.sourceforge.net/
#
# Default: disabled
CONFIG_FSP=no
### File Transfer Protocol Support
#

View File

@ -3,6 +3,7 @@ include $(top_builddir)/Makefile.config
SUBDIRS-$(CONFIG_BITTORRENT) += bittorrent
SUBDIRS-$(CONFIG_FINGER) += finger
SUBDIRS-$(CONFIG_FSP) += fsp
SUBDIRS-$(CONFIG_FTP) += ftp
SUBDIRS-$(CONFIG_GOPHER) += gopher
SUBDIRS-$(CONFIG_NNTP) += nntp

View File

@ -0,0 +1,6 @@
top_builddir=../../..
include $(top_builddir)/Makefile.config
OBJS = fsp.o
include $(top_srcdir)/Makefile.lib

341
src/protocol/fsp/fsp.c Normal file
View File

@ -0,0 +1,341 @@
/* 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_SYS_TIME_H
#include <sys/time.h> /* FreeBSD needs this before resource.h */
#endif
#include <sys/types.h> /* FreeBSD needs this before resource.h */
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
#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/protocol.h"
#include "protocol/fsp/fsp.h"
#include "protocol/uri.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 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
);
struct fsp_info {
int init;
};
static void
fsp_error(unsigned char *error)
{
puts(error);
exit(1);
}
static int
compare(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 void
sort_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(fentry),
(int (*)(const void *, const void *)) compare);
for (i = 0; i < size; i++) {
printf("%10d\t<a href=\"%s\">", table[i].size, table[i].name);
if (fentry.type == FSP_RDTYPE_DIR && *dircolor) {
printf("<font color=\"%s\"><b>", dircolor);
}
printf("%s", table[i].name);
if (fentry.type == FSP_RDTYPE_DIR && *dircolor) {
printf("</b></font>");
}
puts("</a>");
}
}
static void
fsp_directory(FSP_SESSION *ses, struct uri *uri)
{
struct string buf;
FSP_DIR *dir;
unsigned char *data = get_uri_string(uri, URI_DATA);
if (!init_string(&buf))
fsp_error("Out of memory");
add_to_string(&buf, "fsp://");
if (uri->passwordlen) {
add_to_string(&buf, "u:");
add_bytes_to_string(&buf, uri->password, uri->passwordlen);
add_char_to_string(&buf, '@');
}
add_bytes_to_string(&buf, uri->host, uri->hostlen);
if (uri->portlen) {
add_char_to_string(&buf, ':');
add_bytes_to_string(&buf, uri->port, uri->portlen);
}
add_char_to_string(&buf, '/');
if (uri->datalen) {
add_bytes_to_string(&buf, uri->data, uri->datalen);
add_char_to_string(&buf, '/');
}
printf("<html><head><title>%s</title><base href=\"%s\">"
"</head><body><pre>", buf.source, 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\">", fentry.size, fentry.name);
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></body></html>");
fsp_close_session(ses);
exit(0);
}
#define READ_SIZE 4096
static void
do_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[4096];
FSP_FILE *file = fsp_fopen(ses, data, "r");
int r;
if (!file)
fsp_error("fsp_fopen error.");
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 void
fsp_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 == 0) {
if (conn->from)
normalize_cache_entry(conn->cached, conn->from);
close_socket(socket);
abort_connection(conn, S_OK);
return;
}
conn->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);
}
#undef READ_SIZE
/* Close all non-terminal file descriptors. */
static void
close_all_non_term_fd(void)
{
int n;
int max = 1024;
#ifdef RLIMIT_NOFILE
struct rlimit lim;
if (!getrlimit(RLIMIT_NOFILE, &lim))
max = lim.rlim_max;
#endif
for (n = 3; n < max; n++)
close(n);
}
void
fsp_protocol_handler(struct connection *conn)
{
int fsp_pipe[2] = { -1, -1 };
int cpid;
struct read_buffer *buf;
if (c_pipe(fsp_pipe)) {
int s_errno = errno;
if (fsp_pipe[0] >= 0) close(fsp_pipe[0]);
if (fsp_pipe[1] >= 0) close(fsp_pipe[1]);
abort_connection(conn, -s_errno);
return;
}
conn->cached = get_cache_entry(conn->uri);
if (!conn->cached) {
abort_connection(conn, S_OUT_OF_MEM);
return;
}
conn->from = 0;
conn->unrestartable = 1;
cpid = fork();
if (cpid == -1) {
int s_errno = errno;
close(fsp_pipe[0]);
close(fsp_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(open("/dev/null", O_RDONLY), 2);
close(fsp_pipe[0]);
close_all_non_term_fd();
do_fsp(conn);
} else {
conn->socket->fd = fsp_pipe[0];
close(fsp_pipe[1]);
buf = alloc_read_buffer(conn->socket);
if (!buf) {
close(fsp_pipe[0]);
abort_connection(conn, S_OUT_OF_MEM);
return;
}
read_from_socket(conn->socket, buf, S_CONN, fsp_got_data);
}
}

16
src/protocol/fsp/fsp.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef EL__PROTOCOL_FSP_FSP_H
#define EL__PROTOCOL_FSP_FSP_H
#include "main/module.h"
#include "protocol/protocol.h"
extern struct module fsp_protocol_module;
#ifdef CONFIG_FSP
extern protocol_handler_T fsp_protocol_handler;
#else
#define fsp_protocol_handler NULL
#endif
#endif

View File

@ -31,6 +31,7 @@
#include "protocol/data.h"
#include "protocol/file/file.h"
#include "protocol/finger/finger.h"
#include "protocol/fsp/fsp.h"
#include "protocol/ftp/ftp.h"
#include "protocol/gopher/gopher.h"
#include "protocol/http/http.h"
@ -57,6 +58,7 @@ static const struct protocol_backend protocol_backends[] = {
{ "data", 0, data_protocol_handler, 0, 0, 1, 0 },
{ "file", 0, file_protocol_handler, 1, 0, 0, 0 },
{ "finger", 79, finger_protocol_handler, 1, 1, 0, 0 },
{ "fsp", 21, fsp_protocol_handler, 1, 1, 0, 0 },
{ "ftp", 21, ftp_protocol_handler, 1, 1, 0, 0 },
{ "gopher", 70, gopher_protocol_handler, 1, 1, 0, 0 },
{ "http", 80, http_protocol_handler, 1, 1, 0, 0 },
@ -276,6 +278,9 @@ static struct module *protocol_submodules[] = {
#ifdef CONFIG_FINGER
&finger_protocol_module,
#endif
#ifdef CONFIG_FSP
&fsp_protocol_module,
#endif
#ifdef CONFIG_FTP
&ftp_protocol_module,
#endif

View File

@ -14,6 +14,7 @@ enum protocol {
PROTOCOL_DATA,
PROTOCOL_FILE,
PROTOCOL_FINGER,
PROTOCOL_FSP,
PROTOCOL_FTP,
PROTOCOL_GOPHER,
PROTOCOL_HTTP,