mirror of
https://github.com/rkd77/elinks.git
synced 2024-12-04 14:46:47 -05:00
[dgi] Experimental DGI support.
Dos Gateway Interface was introduced by Arachne browser. I tested two cases: file/cdplayer.dgi |[7]$ecdplayer.exe $s application/pdf pdf>txt|$epdftotext $1 $2
This commit is contained in:
parent
24c5295a28
commit
443d42608d
@ -1,6 +1,7 @@
|
||||
top_builddir=../../..
|
||||
include $(top_builddir)/Makefile.config
|
||||
|
||||
OBJS-$(CONFIG_DGI) += dgi.o
|
||||
OBJS-$(CONFIG_MAILCAP) += mailcap.o
|
||||
OBJS-$(CONFIG_MIMETYPES) += mimetypes.o
|
||||
|
||||
|
@ -21,11 +21,15 @@
|
||||
/* Backends dynamic area: */
|
||||
|
||||
#include "mime/backend/default.h"
|
||||
#include "mime/backend/dgi.h"
|
||||
#include "mime/backend/mailcap.h"
|
||||
#include "mime/backend/mimetypes.h"
|
||||
|
||||
static const struct mime_backend *const mime_backends[] = {
|
||||
&default_mime_backend,
|
||||
#ifdef CONFIG_DGI
|
||||
&dgi_mime_backend,
|
||||
#endif
|
||||
#ifdef CONFIG_MAILCAP
|
||||
&mailcap_mime_backend,
|
||||
#endif
|
||||
|
460
src/mime/backend/dgi.c
Normal file
460
src/mime/backend/dgi.c
Normal file
@ -0,0 +1,460 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "elinks.h"
|
||||
|
||||
#include "config/options.h"
|
||||
#include "intl/libintl.h"
|
||||
#include "main/module.h"
|
||||
#include "mime/backend/common.h"
|
||||
#include "mime/backend/dgi.h"
|
||||
#include "mime/mime.h"
|
||||
#include "osdep/osdep.h" /* For exe() */
|
||||
#include "session/session.h"
|
||||
#include "util/file.h"
|
||||
#include "util/hash.h"
|
||||
#include "util/lists.h"
|
||||
#include "util/memory.h"
|
||||
#include "util/string.h"
|
||||
|
||||
struct dgi_hash_item {
|
||||
/* The entries associated with the type */
|
||||
LIST_OF(struct dgi_entry) entries;
|
||||
|
||||
/* The content type of all @entries. Must be last! */
|
||||
char type[1];
|
||||
};
|
||||
|
||||
struct dgi_entry {
|
||||
LIST_HEAD(struct dgi_entry);
|
||||
|
||||
char *type;
|
||||
char *inpext;
|
||||
char *outext;
|
||||
|
||||
/* The 'raw' unformatted (view)command from the dgi files. */
|
||||
char command[1];
|
||||
};
|
||||
|
||||
/* State variables */
|
||||
static struct hash *dgi_map = NULL;
|
||||
|
||||
enum dgi_option {
|
||||
DGI_TREE,
|
||||
|
||||
DGI_ENABLE,
|
||||
DGI_MIME_CFG,
|
||||
DGI_ASK
|
||||
};
|
||||
|
||||
static union option_info dgi_options[] = {
|
||||
INIT_OPT_TREE("mime", N_("DGI"),
|
||||
"dgi", OPT_ZERO,
|
||||
N_("Dos gateway interface specific options.")),
|
||||
|
||||
INIT_OPT_BOOL("mime.dgi", N_("Enable"),
|
||||
"enable", OPT_ZERO, 1,
|
||||
N_("Enable DGI support.")),
|
||||
|
||||
INIT_OPT_STRING("mime.dgi", N_("Config filename"),
|
||||
"mime_cfg", OPT_ZERO, "mime.cfg",
|
||||
N_("Filename and location of config file for DGI.")),
|
||||
|
||||
INIT_OPT_BOOL("mime.dgi", N_("Ask before opening"),
|
||||
"ask", OPT_ZERO, 0,
|
||||
N_("Ask before using the handlers defined by DGI.")),
|
||||
|
||||
INIT_OPT_STRING("mime.dgi", N_("Path $a"),
|
||||
"a", OPT_ZERO, "",
|
||||
N_("Path to cache.")),
|
||||
INIT_OPT_STRING("mime.dgi", N_("Path $b"),
|
||||
"b", OPT_ZERO, "",
|
||||
N_("Full name of bookmarks.")),
|
||||
INIT_OPT_STRING("mime.dgi", N_("Path $c"),
|
||||
"c", OPT_ZERO, "",
|
||||
N_("Full name of cache index.")),
|
||||
INIT_OPT_STRING("mime.dgi", N_("Path $d"),
|
||||
"d", OPT_ZERO, "",
|
||||
N_("Document name.")),
|
||||
INIT_OPT_STRING("mime.dgi", N_("Path $e"),
|
||||
"e", OPT_ZERO, "",
|
||||
N_("Path to executable files.")),
|
||||
INIT_OPT_STRING("mime.dgi", N_("Path $f"),
|
||||
"f", OPT_ZERO, "",
|
||||
N_("File browser arguments.")),
|
||||
INIT_OPT_STRING("mime.dgi", N_("Path $g"),
|
||||
"g", OPT_ZERO, "",
|
||||
N_("IP address of 1st gateway.")),
|
||||
INIT_OPT_STRING("mime.dgi", N_("Path $h"),
|
||||
"h", OPT_ZERO, "",
|
||||
N_("Full name of History file.")),
|
||||
INIT_OPT_STRING("mime.dgi", N_("Path $i"),
|
||||
"i", OPT_ZERO, "",
|
||||
N_("Your IP address.")),
|
||||
INIT_OPT_STRING("mime.dgi", N_("Path $j"),
|
||||
"j", OPT_ZERO, "",
|
||||
N_("DJPEG arguments.")),
|
||||
INIT_OPT_STRING("mime.dgi", N_("Path $l"),
|
||||
"l", OPT_ZERO, "",
|
||||
N_("Last visited document.")),
|
||||
INIT_OPT_STRING("mime.dgi", N_("Path $m"),
|
||||
"m", OPT_ZERO, "",
|
||||
N_("Path to mail.")),
|
||||
INIT_OPT_STRING("mime.dgi", N_("Path $n"),
|
||||
"n", OPT_ZERO, "",
|
||||
N_("IP address of 1st nameserver.")),
|
||||
INIT_OPT_STRING("mime.dgi", N_("Path $p"),
|
||||
"p", OPT_ZERO, "",
|
||||
N_("Host.")),
|
||||
INIT_OPT_STRING("mime.dgi", N_("Path $q"),
|
||||
"q", OPT_ZERO, "",
|
||||
N_("Filename of query string (file created only "
|
||||
"when using this macro).")),
|
||||
INIT_OPT_STRING("mime.dgi", N_("Path $r"),
|
||||
"r", OPT_ZERO, "",
|
||||
N_("Horizontal resolution of screen.")),
|
||||
INIT_OPT_STRING("mime.dgi", N_("Path $s"),
|
||||
"s", OPT_ZERO, "",
|
||||
N_("CGI compatible query string.")),
|
||||
INIT_OPT_STRING("mime.dgi", N_("Path $t"),
|
||||
"t", OPT_ZERO, "",
|
||||
N_("Path for temporary files.")),
|
||||
INIT_OPT_STRING("mime.dgi", N_("Path $u"),
|
||||
"u", OPT_ZERO, "",
|
||||
N_("URL of document.")),
|
||||
INIT_OPT_STRING("mime.dgi", N_("Path $w"),
|
||||
"w", OPT_ZERO, "",
|
||||
N_("Download path.")),
|
||||
INIT_OPT_STRING("mime.dgi", N_("Path $x"),
|
||||
"x", OPT_ZERO, "",
|
||||
N_("Netmask.")),
|
||||
NULL_OPTION_INFO,
|
||||
};
|
||||
|
||||
#define get_opt_dgi(which) dgi_options[(which)].option
|
||||
#define get_dgi(which) get_opt_dgi(which).value
|
||||
#define get_dgi_ask() get_dgi(DGI_ASK).number
|
||||
#define get_dgi_enable() get_dgi(DGI_ENABLE).number
|
||||
|
||||
static inline void
|
||||
done_dgi_entry(struct dgi_entry *entry)
|
||||
{
|
||||
if (!entry) return;
|
||||
mem_free_if(entry->type);
|
||||
mem_free_if(entry->inpext);
|
||||
mem_free_if(entry->outext);
|
||||
mem_free(entry);
|
||||
}
|
||||
|
||||
/* Takes care of all initialization of dgi entries.
|
||||
* Clear memory to make freeing it safer later and we get. */
|
||||
static inline struct dgi_entry *
|
||||
init_dgi_entry(char *type, char *inpext, char *outext, char *command)
|
||||
{
|
||||
struct dgi_entry *entry;
|
||||
int commandlen = strlen(command);
|
||||
|
||||
entry = (struct dgi_entry *)mem_calloc(1, sizeof(*entry) + commandlen);
|
||||
if (!entry) return NULL;
|
||||
|
||||
memcpy(entry->command, command, commandlen);
|
||||
entry->type = stracpy(type);
|
||||
|
||||
if (inpext) {
|
||||
entry->inpext = straconcat(".", inpext, NULL);
|
||||
}
|
||||
|
||||
if (outext) {
|
||||
entry->outext = straconcat(".", outext, NULL);
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
static inline void
|
||||
add_dgi_entry(struct dgi_entry *entry, char *type, int typelen)
|
||||
{
|
||||
struct dgi_hash_item *mitem;
|
||||
struct hash_item *item;
|
||||
|
||||
/* Time to get the entry into the dgi_map */
|
||||
/* First check if the type is already checked in */
|
||||
item = get_hash_item(dgi_map, type, typelen);
|
||||
if (!item) {
|
||||
mitem = (struct dgi_hash_item *)mem_alloc(sizeof(*mitem) + typelen);
|
||||
if (!mitem) {
|
||||
done_dgi_entry(entry);
|
||||
return;
|
||||
}
|
||||
|
||||
safe_strncpy(mitem->type, type, typelen + 1);
|
||||
|
||||
init_list(mitem->entries);
|
||||
|
||||
item = add_hash_item(dgi_map, mitem->type, typelen, mitem);
|
||||
if (!item) {
|
||||
mem_free(mitem);
|
||||
done_dgi_entry(entry);
|
||||
return;
|
||||
}
|
||||
} else if (item->value) {
|
||||
mitem = (struct dgi_hash_item *)item->value;
|
||||
} else {
|
||||
done_dgi_entry(entry);
|
||||
return;
|
||||
}
|
||||
|
||||
add_to_list_end(mitem->entries, entry);
|
||||
}
|
||||
|
||||
/* Parses whole mime_cfg file line-by-line adding entries to the map */
|
||||
static void
|
||||
parse_dgi_file(char *filename)
|
||||
{
|
||||
FILE *file = fopen(filename, "rb");
|
||||
char *line = NULL;
|
||||
size_t linelen = MAX_STR_LEN;
|
||||
int lineno = 1;
|
||||
|
||||
if (!file) return;
|
||||
|
||||
while ((line = file_read_line(line, &linelen, file, &lineno))) {
|
||||
struct dgi_entry *entry;
|
||||
char *linepos;
|
||||
char *command;
|
||||
char *basetypeend;
|
||||
char *type;
|
||||
char *inpext, *outext;
|
||||
char *pipe, *greater, *space;
|
||||
int typelen;
|
||||
|
||||
/* Ignore comments */
|
||||
if (*line == ';' || *line == '[') continue;
|
||||
|
||||
linepos = line;
|
||||
|
||||
pipe = strchr(linepos, '|');
|
||||
if (!pipe) continue;
|
||||
|
||||
*pipe = '\0';
|
||||
command = pipe + 1;
|
||||
|
||||
greater = strchr(linepos, '>');
|
||||
|
||||
if (!greater) {
|
||||
outext = NULL;
|
||||
} else {
|
||||
*greater = '\0';
|
||||
outext = greater + 1;
|
||||
}
|
||||
|
||||
space = strrchr(linepos, ' ');
|
||||
if (!space) {
|
||||
inpext = NULL;
|
||||
} else {
|
||||
inpext = space + 1;
|
||||
}
|
||||
|
||||
space = strchr(linepos, ' ');
|
||||
if (!space) continue;
|
||||
*space = '\0';
|
||||
|
||||
type = linepos;
|
||||
if (!*type) continue;
|
||||
|
||||
entry = init_dgi_entry(type, inpext, outext, command);
|
||||
if (!entry) continue;
|
||||
|
||||
basetypeend = strchr(type, '/');
|
||||
typelen = strlen(type);
|
||||
|
||||
if (!basetypeend) {
|
||||
char implicitwild[64];
|
||||
|
||||
if (typelen + 3 > sizeof(implicitwild)) {
|
||||
done_dgi_entry(entry);
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(implicitwild, type, typelen);
|
||||
implicitwild[typelen++] = '/';
|
||||
implicitwild[typelen++] = '*';
|
||||
implicitwild[typelen++] = '\0';
|
||||
add_dgi_entry(entry, implicitwild, typelen);
|
||||
continue;
|
||||
}
|
||||
|
||||
add_dgi_entry(entry, type, typelen);
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
mem_free_if(line); /* Alloced by file_read_line() */
|
||||
}
|
||||
|
||||
static struct hash *
|
||||
init_dgi_map(void)
|
||||
{
|
||||
dgi_map = init_hash8();
|
||||
|
||||
if (!dgi_map) return NULL;
|
||||
|
||||
parse_dgi_file(get_opt_str("mime.dgi.mime_cfg", NULL));
|
||||
|
||||
return dgi_map;
|
||||
}
|
||||
|
||||
static void
|
||||
done_dgi(struct module *module)
|
||||
{
|
||||
struct hash_item *item;
|
||||
int i;
|
||||
|
||||
if (!dgi_map) return;
|
||||
|
||||
foreach_hash_item (item, *dgi_map, i) {
|
||||
struct dgi_hash_item *mitem = (struct dgi_hash_item *)item->value;
|
||||
|
||||
if (!mitem) continue;
|
||||
|
||||
while (!list_empty(mitem->entries)) {
|
||||
struct dgi_entry *entry = (struct dgi_entry *)mitem->entries.next;
|
||||
|
||||
del_from_list(entry);
|
||||
done_dgi_entry(entry);
|
||||
}
|
||||
|
||||
mem_free(mitem);
|
||||
}
|
||||
|
||||
free_hash(&dgi_map);
|
||||
}
|
||||
|
||||
static int
|
||||
change_hook_dgi(struct session *ses, struct option *current, struct option *changed)
|
||||
{
|
||||
if (changed == &get_opt_dgi(DGI_MIME_CFG)
|
||||
|| (changed == &get_opt_dgi(DGI_ENABLE)
|
||||
&& !get_dgi_enable())) {
|
||||
done_dgi(&dgi_mime_module);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
init_dgi(struct module *module)
|
||||
{
|
||||
static const struct change_hook_info mimetypes_change_hooks[] = {
|
||||
{ "mime.dgi.enable", change_hook_dgi },
|
||||
{ "mime.dgi.mime_cfg", change_hook_dgi },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
register_change_hooks(mimetypes_change_hooks);
|
||||
|
||||
if (get_cmd_opt_bool("anonymous"))
|
||||
get_opt_bool("mime.dgi.enable", NULL) = 0;
|
||||
}
|
||||
|
||||
/* Returns first usable dgi_entry from a list where @entry is the head.
|
||||
* Use of @filename is not supported (yet). */
|
||||
static struct dgi_entry *
|
||||
check_entries(struct dgi_hash_item *item)
|
||||
{
|
||||
struct dgi_entry *entry;
|
||||
|
||||
foreach (entry, item->entries) {
|
||||
return entry;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct dgi_entry *
|
||||
get_dgi_entry(char *type)
|
||||
{
|
||||
struct dgi_entry *entry;
|
||||
struct hash_item *item;
|
||||
|
||||
item = get_hash_item(dgi_map, type, strlen(type));
|
||||
|
||||
/* Check list of entries */
|
||||
entry = ((item && item->value) ? check_entries((struct dgi_hash_item *)item->value) : NULL);
|
||||
|
||||
if (!entry) {
|
||||
struct dgi_entry *wildcard = NULL;
|
||||
char *wildpos = strchr(type, '/');
|
||||
|
||||
if (wildpos) {
|
||||
int wildlen = wildpos - type + 1; /* include '/' */
|
||||
char *wildtype = memacpy(type, wildlen + 2);
|
||||
|
||||
if (!wildtype) return NULL;
|
||||
|
||||
wildtype[wildlen++] = '*';
|
||||
wildtype[wildlen] = '\0';
|
||||
|
||||
item = get_hash_item(dgi_map, wildtype, wildlen);
|
||||
mem_free(wildtype);
|
||||
|
||||
if (item && item->value)
|
||||
wildcard = check_entries((struct dgi_hash_item *)item->value);
|
||||
}
|
||||
|
||||
/* Use @wildcard if its priority is better or @entry is NULL */
|
||||
if (wildcard && (!entry))
|
||||
entry = wildcard;
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
struct mime_handler *
|
||||
get_mime_handler_dgi(char *type, int xwin)
|
||||
{
|
||||
struct dgi_entry *entry;
|
||||
struct mime_handler *handler;
|
||||
char *program;
|
||||
|
||||
if (!get_dgi_enable()
|
||||
|| (!dgi_map && !init_dgi_map()))
|
||||
return NULL;
|
||||
|
||||
entry = get_dgi_entry(type);
|
||||
if (!entry) return NULL;
|
||||
|
||||
program = stracpy(entry->command);
|
||||
if (!program) return NULL;
|
||||
|
||||
handler = init_mime_handler(program, NULL,
|
||||
dgi_mime_module.name,
|
||||
get_dgi_ask(), 0);
|
||||
mem_free(program);
|
||||
|
||||
handler->inpext = entry->inpext;
|
||||
handler->outext = entry->outext;
|
||||
handler->dgi = 1;
|
||||
return handler;
|
||||
}
|
||||
|
||||
const struct mime_backend dgi_mime_backend = {
|
||||
/* get_content_type: */ NULL,
|
||||
/* get_mime_handler: */ get_mime_handler_dgi,
|
||||
};
|
||||
|
||||
/* Setup the exported module. */
|
||||
struct module dgi_mime_module = struct_module(
|
||||
/* name: */ N_("DGI mime"),
|
||||
/* options: */ dgi_options,
|
||||
/* hooks: */ NULL,
|
||||
/* submodules: */ NULL,
|
||||
/* data: */ NULL,
|
||||
/* init: */ init_dgi,
|
||||
/* done: */ done_dgi
|
||||
);
|
21
src/mime/backend/dgi.h
Normal file
21
src/mime/backend/dgi.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef EL__MIME_BACKEND_DGI_H
|
||||
#define EL__MIME_BACKEND_DGI_H
|
||||
|
||||
#include "main/module.h"
|
||||
#include "mime/backend/common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern const struct mime_backend dgi_mime_backend;
|
||||
extern struct module dgi_mime_module;
|
||||
|
||||
struct mime_handler *get_mime_handler_dgi(char *type, int xwin);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,3 +1,6 @@
|
||||
if conf_data.get('CONFIG_DGI')
|
||||
srcs += files('dgi.c')
|
||||
endif
|
||||
if conf_data.get('CONFIG_MAILCAP')
|
||||
srcs += files('mailcap.c')
|
||||
endif
|
||||
|
@ -348,11 +348,15 @@ add_mime_filename_to_string(struct string *string, struct uri *uri)
|
||||
/* Backends dynamic area: */
|
||||
|
||||
#include "mime/backend/default.h"
|
||||
#include "mime/backend/dgi.h"
|
||||
#include "mime/backend/mailcap.h"
|
||||
#include "mime/backend/mimetypes.h"
|
||||
|
||||
static struct module *mime_submodules[] = {
|
||||
&default_mime_module,
|
||||
#ifdef CONFIG_DGI
|
||||
&dgi_mime_module,
|
||||
#endif
|
||||
#ifdef CONFIG_MAILCAP
|
||||
&mailcap_mime_module,
|
||||
#endif
|
||||
|
@ -13,9 +13,12 @@ struct uri;
|
||||
struct mime_handler {
|
||||
char *description;
|
||||
const char *backend_name;
|
||||
char *inpext;
|
||||
char *outext;
|
||||
unsigned int ask:1;
|
||||
unsigned int block:1;
|
||||
unsigned int copiousoutput:1;
|
||||
unsigned int dgi:1;
|
||||
char program[1]; /* XXX: Keep last! */
|
||||
};
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "cookies/cookies.h"
|
||||
#include "intl/libintl.h"
|
||||
#include "mime/backend/common.h"
|
||||
#include "mime/backend/dgi.h"
|
||||
#include "network/connection.h"
|
||||
#include "network/progress.h"
|
||||
#include "network/socket.h"
|
||||
@ -38,92 +39,12 @@
|
||||
#include "terminal/terminal.h"
|
||||
#include "util/conv.h"
|
||||
#include "util/env.h"
|
||||
#include "util/qs_parse/qs_parse.h"
|
||||
#include "util/string.h"
|
||||
|
||||
static union option_info dgi_options[] = {
|
||||
INIT_OPT_TREE("protocol.file", N_("DGI"),
|
||||
"dgi", OPT_ZERO,
|
||||
N_("Dos gateway interface specific options.")),
|
||||
INIT_OPT_STRING("protocol.file.dgi", N_("Path $a"),
|
||||
"a", OPT_ZERO, "",
|
||||
N_("Path to cache.")),
|
||||
INIT_OPT_STRING("protocol.file.dgi", N_("Path $b"),
|
||||
"b", OPT_ZERO, "",
|
||||
N_("Full name of bookmarks.")),
|
||||
INIT_OPT_STRING("protocol.file.dgi", N_("Path $c"),
|
||||
"c", OPT_ZERO, "",
|
||||
N_("Full name of cache index.")),
|
||||
INIT_OPT_STRING("protocol.file.dgi", N_("Path $d"),
|
||||
"d", OPT_ZERO, "",
|
||||
N_("Document name.")),
|
||||
INIT_OPT_STRING("protocol.file.dgi", N_("Path $e"),
|
||||
"e", OPT_ZERO, "",
|
||||
N_("Path to executable files.")),
|
||||
INIT_OPT_STRING("protocol.file.dgi", N_("Path $f"),
|
||||
"f", OPT_ZERO, "",
|
||||
N_("File browser arguments.")),
|
||||
INIT_OPT_STRING("protocol.file.dgi", N_("Path $g"),
|
||||
"g", OPT_ZERO, "",
|
||||
N_("IP address of 1st gateway.")),
|
||||
INIT_OPT_STRING("protocol.file.dgi", N_("Path $h"),
|
||||
"h", OPT_ZERO, "",
|
||||
N_("Full name of History file.")),
|
||||
INIT_OPT_STRING("protocol.file.dgi", N_("Path $i"),
|
||||
"i", OPT_ZERO, "",
|
||||
N_("Your IP address.")),
|
||||
INIT_OPT_STRING("protocol.file.dgi", N_("Path $j"),
|
||||
"j", OPT_ZERO, "",
|
||||
N_("DJPEG arguments.")),
|
||||
INIT_OPT_STRING("protocol.file.dgi", N_("Path $l"),
|
||||
"l", OPT_ZERO, "",
|
||||
N_("Last visited document.")),
|
||||
INIT_OPT_STRING("protocol.file.dgi", N_("Path $m"),
|
||||
"m", OPT_ZERO, "",
|
||||
N_("Path to mail.")),
|
||||
INIT_OPT_STRING("protocol.file.dgi", N_("Path $n"),
|
||||
"n", OPT_ZERO, "",
|
||||
N_("IP address of 1st nameserver.")),
|
||||
INIT_OPT_STRING("protocol.file.dgi", N_("Path $p"),
|
||||
"p", OPT_ZERO, "",
|
||||
N_("Host.")),
|
||||
INIT_OPT_STRING("protocol.file.dgi", N_("Path $q"),
|
||||
"q", OPT_ZERO, "",
|
||||
N_("Filename of query string (file created only "
|
||||
"when using this macro).")),
|
||||
INIT_OPT_STRING("protocol.file.dgi", N_("Path $r"),
|
||||
"r", OPT_ZERO, "",
|
||||
N_("Horizontal resolution of screen.")),
|
||||
INIT_OPT_STRING("protocol.file.dgi", N_("Path $s"),
|
||||
"s", OPT_ZERO, "",
|
||||
N_("CGI compatible query string.")),
|
||||
INIT_OPT_STRING("protocol.file.dgi", N_("Path $t"),
|
||||
"t", OPT_ZERO, "",
|
||||
N_("Path for temporary files.")),
|
||||
INIT_OPT_STRING("protocol.file.dgi", N_("Path $u"),
|
||||
"u", OPT_ZERO, "",
|
||||
N_("URL of document.")),
|
||||
INIT_OPT_STRING("protocol.file.dgi", N_("Path $w"),
|
||||
"w", OPT_ZERO, "",
|
||||
N_("Download path.")),
|
||||
INIT_OPT_STRING("protocol.file.dgi", N_("Path $x"),
|
||||
"x", OPT_ZERO, "",
|
||||
N_("Netmask.")),
|
||||
NULL_OPTION_INFO,
|
||||
};
|
||||
|
||||
struct dgi_entry {
|
||||
const char *name;
|
||||
const char *cmdline;
|
||||
};
|
||||
|
||||
struct dgi_entry entries[] = {
|
||||
{ "cdplayer.dgi", "$ecdplayer.exe $s > $2" },
|
||||
NULL
|
||||
};
|
||||
|
||||
struct module dgi_protocol_module = struct_module(
|
||||
/* name: */ N_("Dos Gateway Interface (DGI)"),
|
||||
/* options: */ dgi_options,
|
||||
/* name: */ N_("DGI"),
|
||||
/* options: */ NULL,
|
||||
/* hooks: */ NULL,
|
||||
/* submodules: */ NULL,
|
||||
/* data: */ NULL,
|
||||
@ -131,25 +52,29 @@ struct module dgi_protocol_module = struct_module(
|
||||
/* done: */ NULL
|
||||
);
|
||||
|
||||
static struct dgi_entry *
|
||||
|
||||
static struct mime_handler *
|
||||
find_dgi(const char *name)
|
||||
{
|
||||
const char *last = strrchr(name, '/');
|
||||
struct dgi_entry *entry;
|
||||
struct mime_handler *handler;
|
||||
|
||||
if (last) {
|
||||
name = last + 1;
|
||||
}
|
||||
|
||||
for (entry = entries; entry; entry++) {
|
||||
if (!entry->name) break;
|
||||
struct string dtype;
|
||||
|
||||
if (!strcmp(name, entry->name)) {
|
||||
return entry;
|
||||
}
|
||||
if (!init_string(&dtype)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
add_to_string(&dtype, "file/");
|
||||
add_to_string(&dtype, name);
|
||||
handler = get_mime_handler_dgi(dtype.source, 0);
|
||||
done_string(&dtype);
|
||||
|
||||
return handler;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -175,16 +100,17 @@ write_request_to_file(struct connection *conn, const char *filename)
|
||||
enum dgi_state {
|
||||
NORMAL,
|
||||
DOLAR,
|
||||
PERCENT
|
||||
PERCENT,
|
||||
LEFT_BRACKET
|
||||
};
|
||||
|
||||
static void
|
||||
prepare_command(struct dgi_entry *entry, const char *query, struct string *cmd, char **inp, char **out, char **queryfile)
|
||||
prepare_command(struct mime_handler *handler, const char *query, struct string *cmd, char **inp, char **out, char **queryfile)
|
||||
{
|
||||
const char *ch;
|
||||
enum dgi_state state = NORMAL;
|
||||
|
||||
for (ch = entry->cmdline; *ch; ch++) {
|
||||
for (ch = handler->program; *ch; ch++) {
|
||||
switch (state) {
|
||||
case NORMAL:
|
||||
default:
|
||||
@ -192,78 +118,89 @@ prepare_command(struct dgi_entry *entry, const char *query, struct string *cmd,
|
||||
state = DOLAR;
|
||||
} else if (*ch == '%') {
|
||||
state = PERCENT;
|
||||
} else if (*ch == '[') {
|
||||
state = LEFT_BRACKET;
|
||||
} else {
|
||||
add_char_to_string(cmd, *ch);
|
||||
}
|
||||
break;
|
||||
case LEFT_BRACKET:
|
||||
switch (*ch) {
|
||||
case ']':
|
||||
state = NORMAL;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case DOLAR:
|
||||
case PERCENT:
|
||||
switch(*ch) {
|
||||
switch (*ch) {
|
||||
case 'a':
|
||||
add_to_string(cmd, get_opt_str("protocol.file.dgi.a", NULL));
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.a", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 'b':
|
||||
add_to_string(cmd, get_opt_str("protocol.file.dgi.b", NULL));
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.b", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 'c':
|
||||
add_to_string(cmd, get_opt_str("protocol.file.dgi.c", NULL));
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.c", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 'd':
|
||||
add_to_string(cmd, get_opt_str("protocol.file.dgi.d", NULL));
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.d", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 'e':
|
||||
add_to_string(cmd, get_opt_str("protocol.file.dgi.e", NULL));
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.e", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 'f':
|
||||
add_to_string(cmd, get_opt_str("protocol.file.dgi.f", NULL));
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.f", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 'g':
|
||||
add_to_string(cmd, get_opt_str("protocol.file.dgi.g", NULL));
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.g", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 'h':
|
||||
add_to_string(cmd, get_opt_str("protocol.file.dgi.h", NULL));
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.h", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 'i':
|
||||
add_to_string(cmd, get_opt_str("protocol.file.dgi.i", NULL));
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.i", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 'j':
|
||||
add_to_string(cmd, get_opt_str("protocol.file.dgi.j", NULL));
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.j", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 'l':
|
||||
add_to_string(cmd, get_opt_str("protocol.file.dgi.l", NULL));
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.l", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 'm':
|
||||
add_to_string(cmd, get_opt_str("protocol.file.dgi.m", NULL));
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.m", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 'n':
|
||||
add_to_string(cmd, get_opt_str("protocol.file.dgi.n", NULL));
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.n", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 'p':
|
||||
add_to_string(cmd, get_opt_str("protocol.file.dgi.p", NULL));
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.p", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 'q':
|
||||
*queryfile = tempname(NULL, "elinks", ".txt");
|
||||
*queryfile = tempname(NULL, "elinks", handler->inpext);
|
||||
if (*queryfile) {
|
||||
add_to_string(cmd, *queryfile);
|
||||
}
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 'r':
|
||||
add_to_string(cmd, get_opt_str("protocol.file.dgi.r", NULL));
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.r", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 's':
|
||||
@ -273,30 +210,30 @@ prepare_command(struct dgi_entry *entry, const char *query, struct string *cmd,
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 't':
|
||||
add_to_string(cmd, get_opt_str("protocol.file.dgi.t", NULL));
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.t", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 'u':
|
||||
add_to_string(cmd, get_opt_str("protocol.file.dgi.u", NULL));
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.u", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 'w':
|
||||
add_to_string(cmd, get_opt_str("protocol.file.dgi.w", NULL));
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.w", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 'x':
|
||||
add_to_string(cmd, get_opt_str("protocol.file.dgi.x", NULL));
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.x", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case '1':
|
||||
*inp = tempname(NULL, "elinks", ".txt");
|
||||
*inp = tempname(NULL, "elinks", handler->inpext);
|
||||
if (*inp) {
|
||||
add_to_string(cmd, *inp);
|
||||
}
|
||||
state = NORMAL;
|
||||
break;
|
||||
case '2':
|
||||
*out = tempname(NULL, "elinks", ".htm");
|
||||
*out = tempname(NULL, "elinks", handler->outext);
|
||||
if (*out) {
|
||||
add_to_string(cmd, *out);
|
||||
}
|
||||
@ -312,11 +249,284 @@ prepare_command(struct dgi_entry *entry, const char *query, struct string *cmd,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
prepare_command2(char *program, const char *filename, char *inpext, char *outext, struct string *cmd, char **inp, char **out)
|
||||
{
|
||||
const char *ch;
|
||||
char *query = NULL;
|
||||
enum dgi_state state = NORMAL;
|
||||
|
||||
for (ch = program; *ch; ch++) {
|
||||
switch (state) {
|
||||
case NORMAL:
|
||||
default:
|
||||
if (*ch == '$') {
|
||||
state = DOLAR;
|
||||
} else if (*ch == '%') {
|
||||
state = PERCENT;
|
||||
} else if (*ch == '[') {
|
||||
state = LEFT_BRACKET;
|
||||
} else {
|
||||
add_char_to_string(cmd, *ch);
|
||||
}
|
||||
break;
|
||||
case LEFT_BRACKET:
|
||||
switch (*ch) {
|
||||
case ']':
|
||||
state = NORMAL;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case DOLAR:
|
||||
case PERCENT:
|
||||
switch (*ch) {
|
||||
case 'a':
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.a", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 'b':
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.b", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 'c':
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.c", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 'd':
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.d", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 'e':
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.e", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 'f':
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.f", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 'g':
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.g", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 'h':
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.h", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 'i':
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.i", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 'j':
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.j", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 'l':
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.l", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 'm':
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.m", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 'n':
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.n", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 'p':
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.p", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 'q':
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 'r':
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.r", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 's':
|
||||
if (query) {
|
||||
add_to_string(cmd, query);
|
||||
}
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 't':
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.t", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 'u':
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.u", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 'w':
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.w", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case 'x':
|
||||
add_to_string(cmd, get_opt_str("mime.dgi.x", NULL));
|
||||
state = NORMAL;
|
||||
break;
|
||||
case '1':
|
||||
if (filename) {
|
||||
add_to_string(cmd, filename);
|
||||
}
|
||||
state = NORMAL;
|
||||
break;
|
||||
case '2':
|
||||
*out = tempname(NULL, "elinks", outext);
|
||||
if (*out) {
|
||||
add_to_string(cmd, *out);
|
||||
}
|
||||
state = NORMAL;
|
||||
break;
|
||||
default:
|
||||
add_char_to_string(cmd, *ch);
|
||||
state = NORMAL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dgi_protocol_handler(struct connection *conn)
|
||||
{
|
||||
#define NUMKVPAIRS 16
|
||||
char *ref, *query;
|
||||
struct connection_state state = connection_state(S_OK);
|
||||
int check;
|
||||
|
||||
int i;
|
||||
char *kvpairs[NUMKVPAIRS];
|
||||
char *command=NULL;
|
||||
char *filename=NULL;
|
||||
char *inpext=NULL;
|
||||
char *outext=NULL;
|
||||
char *del = NULL;
|
||||
|
||||
struct string command_str;
|
||||
char *tempfilename = NULL;
|
||||
char *outputfilename = NULL;
|
||||
|
||||
/* security checks */
|
||||
if (!conn->referrer || conn->referrer->protocol != PROTOCOL_DGI) {
|
||||
goto bad;
|
||||
}
|
||||
ref = get_uri_string(conn->referrer, URI_PATH);
|
||||
if (!ref) {
|
||||
goto bad;
|
||||
}
|
||||
check = strcmp(ref, "/");
|
||||
mem_free(ref);
|
||||
if (check) goto bad;
|
||||
|
||||
if (!init_string(&command_str)) {
|
||||
state = connection_state(S_OUT_OF_MEM);
|
||||
abort_connection(conn, state);
|
||||
return;
|
||||
}
|
||||
|
||||
query = get_uri_string(conn->uri, URI_QUERY);
|
||||
|
||||
if (query) {
|
||||
i = qs_parse(query, kvpairs, 16);
|
||||
command = qs_k2v("command", kvpairs, i);
|
||||
filename = qs_k2v("filename", kvpairs, i);
|
||||
inpext = qs_k2v("inpext", kvpairs, i);
|
||||
outext = qs_k2v("outext", kvpairs, i);
|
||||
del = qs_k2v("delete", kvpairs, i);
|
||||
}
|
||||
prepare_command2(command, filename, inpext, outext, &command_str, &tempfilename, &outputfilename);
|
||||
|
||||
system(command_str.source);
|
||||
done_string(&command_str);
|
||||
|
||||
if (del) {
|
||||
unlink(filename);
|
||||
}
|
||||
|
||||
if (tempfilename) {
|
||||
unlink(tempfilename);
|
||||
}
|
||||
|
||||
if (!outputfilename) {
|
||||
state = connection_state(S_OK);
|
||||
abort_connection(conn, state);
|
||||
mem_free_if(query);
|
||||
return;
|
||||
}
|
||||
|
||||
struct string page;
|
||||
struct string name;
|
||||
|
||||
if (!init_string(&name)) {
|
||||
unlink(outputfilename);
|
||||
mem_free_if(query);
|
||||
return;
|
||||
}
|
||||
add_to_string(&name, outputfilename);
|
||||
state = read_encoded_file(&name, &page);
|
||||
unlink(outputfilename);
|
||||
done_string(&name);
|
||||
|
||||
if (is_in_state(state, S_OK)) {
|
||||
struct cache_entry *cached;
|
||||
|
||||
/* Try to add fragment data to the connection cache if either
|
||||
* file reading or directory listing worked out ok. */
|
||||
cached = conn->cached = get_cache_entry(conn->uri);
|
||||
if (!conn->cached) {
|
||||
state = connection_state(S_OUT_OF_MEM);
|
||||
} else {
|
||||
add_fragment(cached, 0, page.source, page.length);
|
||||
conn->from += page.length;
|
||||
|
||||
if (1) {
|
||||
char *head;
|
||||
char *otype = NULL;
|
||||
|
||||
if (outext) {
|
||||
otype = get_extension_content_type(outext);
|
||||
}
|
||||
if (!otype) {
|
||||
otype = stracpy("text/html");
|
||||
}
|
||||
|
||||
/* If the system charset somehow
|
||||
* changes after the directory listing
|
||||
* has been generated, it should be
|
||||
* parsed with the original charset. */
|
||||
head = straconcat("\r\nContent-Type: ", otype, "; charset=",
|
||||
get_cp_mime_name(get_cp_index("System")),
|
||||
"\r\n", (char *) NULL);
|
||||
|
||||
mem_free_if(otype);
|
||||
|
||||
/* Not so gracefully handle failed memory
|
||||
* allocation. */
|
||||
if (!head)
|
||||
state = connection_state(S_OUT_OF_MEM);
|
||||
|
||||
/* Setup directory listing for viewing. */
|
||||
mem_free_set(&cached->head, head);
|
||||
}
|
||||
done_string(&page);
|
||||
}
|
||||
}
|
||||
mem_free_if(query);
|
||||
abort_connection(conn, state);
|
||||
return;
|
||||
bad:
|
||||
abort_connection(conn, connection_state(S_BAD_URL));
|
||||
}
|
||||
|
||||
int
|
||||
execute_dgi(struct connection *conn)
|
||||
{
|
||||
char *script;
|
||||
struct dgi_entry *entry;
|
||||
struct mime_handler *handler;
|
||||
struct string command;
|
||||
char *tempfilename = NULL;
|
||||
char *outputfilename = NULL;
|
||||
@ -335,8 +545,8 @@ execute_dgi(struct connection *conn)
|
||||
return 0;
|
||||
}
|
||||
|
||||
entry = find_dgi(script);
|
||||
if (!entry) {
|
||||
handler = find_dgi(script);
|
||||
if (!handler) {
|
||||
mem_free(script);
|
||||
return 1;
|
||||
}
|
||||
@ -348,7 +558,7 @@ execute_dgi(struct connection *conn)
|
||||
|
||||
char *query = get_uri_string(conn->uri, URI_QUERY);
|
||||
|
||||
prepare_command(entry, query, &command, &tempfilename, &outputfilename, &queryfile);
|
||||
prepare_command(handler, query, &command, &tempfilename, &outputfilename, &queryfile);
|
||||
|
||||
mem_free_if(query);
|
||||
|
||||
@ -363,10 +573,6 @@ execute_dgi(struct connection *conn)
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s\n", command.source);
|
||||
|
||||
|
||||
system(command.source);
|
||||
done_string(&command);
|
||||
mem_free(script);
|
||||
@ -381,6 +587,7 @@ execute_dgi(struct connection *conn)
|
||||
|
||||
|
||||
if (!outputfilename) {
|
||||
mem_free(handler);
|
||||
state = connection_state(S_OK);
|
||||
abort_connection(conn, state);
|
||||
return 0;
|
||||
@ -391,6 +598,7 @@ execute_dgi(struct connection *conn)
|
||||
|
||||
if (!init_string(&name)) {
|
||||
unlink(outputfilename);
|
||||
mem_free(handler);
|
||||
return 0;
|
||||
}
|
||||
add_to_string(&name, outputfilename);
|
||||
@ -412,15 +620,25 @@ execute_dgi(struct connection *conn)
|
||||
|
||||
if (1) {
|
||||
char *head;
|
||||
char *otype = NULL;
|
||||
|
||||
if (handler->outext) {
|
||||
otype = get_extension_content_type(handler->outext);
|
||||
}
|
||||
if (!otype) {
|
||||
otype = stracpy("text/html");
|
||||
}
|
||||
|
||||
/* If the system charset somehow
|
||||
* changes after the directory listing
|
||||
* has been generated, it should be
|
||||
* parsed with the original charset. */
|
||||
head = straconcat("\r\nContent-Type: text/html; charset=",
|
||||
head = straconcat("\r\nContent-Type: ", otype, "; charset=",
|
||||
get_cp_mime_name(get_cp_index("System")),
|
||||
"\r\n", (char *) NULL);
|
||||
|
||||
mem_free_if(otype);
|
||||
|
||||
/* Not so gracefully handle failed memory
|
||||
* allocation. */
|
||||
if (!head)
|
||||
@ -432,6 +650,7 @@ execute_dgi(struct connection *conn)
|
||||
done_string(&page);
|
||||
}
|
||||
}
|
||||
mem_free(handler);
|
||||
abort_connection(conn, state);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,7 +1,9 @@
|
||||
|
||||
#ifndef EL__PROTOCOL_FILE_DGI_H
|
||||
#define EL__PROTOCOL_FILE_DGI_H
|
||||
|
||||
#include "main/module.h"
|
||||
#include "protocol/protocol.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -10,6 +12,7 @@ struct connection;
|
||||
struct module;
|
||||
|
||||
extern struct module dgi_protocol_module;
|
||||
extern protocol_handler_T dgi_protocol_handler;
|
||||
int execute_dgi(struct connection *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -63,6 +63,7 @@ static const struct protocol_backend protocol_backends[] = {
|
||||
{ "bittorrent", 0, bittorrent_protocol_handler, 0, 0, 1, 0, 1 },
|
||||
{ "bittorrent-peer",0,bittorrent_peer_protocol_handler, 1, 1, 0, 0, 1 },
|
||||
{ "data", 0, data_protocol_handler, 0, 0, 1, 0, 1 },
|
||||
{ "dgi", 0, dgi_protocol_handler, 0, 0, 0, 0, 0 },
|
||||
{ "file", 0, file_protocol_handler, 1, 0, 0, 0, 0 },
|
||||
{ "finger", 79, finger_protocol_handler, 1, 1, 0, 0, 1 },
|
||||
{ "fsp", 21, fsp_protocol_handler, 1, 1, 0, 0, 1 },
|
||||
|
@ -17,6 +17,7 @@ enum protocol {
|
||||
PROTOCOL_BITTORRENT,
|
||||
PROTOCOL_BITTORRENT_PEER,
|
||||
PROTOCOL_DATA,
|
||||
PROTOCOL_DGI,
|
||||
PROTOCOL_FILE,
|
||||
PROTOCOL_FINGER,
|
||||
PROTOCOL_FSP,
|
||||
|
@ -156,6 +156,8 @@ abort_download(struct file_download *file_download)
|
||||
if (file_download->delete_) unlink(file_download->file);
|
||||
mem_free(file_download->file);
|
||||
}
|
||||
mem_free_if(file_download->inpext);
|
||||
mem_free_if(file_download->outext);
|
||||
del_from_list(file_download);
|
||||
mem_free(file_download);
|
||||
}
|
||||
@ -355,7 +357,6 @@ do_follow_url_mailcap(struct session *ses, struct uri *uri)
|
||||
ses_goto(ses, uri, NULL, NULL, CACHE_MODE_NORMAL, TASK_FORWARD, 0);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
exec_mailcap_command(void *data)
|
||||
{
|
||||
@ -406,6 +407,71 @@ exec_later(struct session *ses, char *handler, char *file)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
exec_dgi_command(void *data)
|
||||
{
|
||||
struct exec_dgi *exec_dgi = (struct exec_dgi *)data;
|
||||
|
||||
if (exec_dgi) {
|
||||
if (exec_dgi->command) {
|
||||
struct string string;
|
||||
|
||||
if (init_string(&string)) {
|
||||
static char dgi_dgi[] = "dgi://";
|
||||
struct uri *ref = get_uri(dgi_dgi, URI_NONE);
|
||||
struct uri *uri;
|
||||
struct session *ses = exec_dgi->ses;
|
||||
|
||||
add_to_string(&string, "dgi:///dgi?command=");
|
||||
add_to_string(&string, exec_dgi->command);
|
||||
add_to_string(&string, "&filename=");
|
||||
if (exec_dgi->file) {
|
||||
add_to_string(&string, exec_dgi->file);
|
||||
}
|
||||
add_to_string(&string, "&inpext=");
|
||||
if (exec_dgi->inpext) {
|
||||
add_to_string(&string, exec_dgi->inpext);
|
||||
}
|
||||
add_to_string(&string, "&outext=");
|
||||
if (exec_dgi->outext) {
|
||||
add_to_string(&string, exec_dgi->outext);
|
||||
}
|
||||
if (exec_dgi->del) {
|
||||
add_to_string(&string, "&delete=1");
|
||||
}
|
||||
uri = get_uri(string.source, URI_BASE_FRAGMENT);
|
||||
done_string(&string);
|
||||
set_session_referrer(ses, ref);
|
||||
if (ref) done_uri(ref);
|
||||
|
||||
do_follow_url_mailcap(ses, uri);
|
||||
if (uri) done_uri(uri);
|
||||
}
|
||||
mem_free(exec_dgi->command);
|
||||
}
|
||||
mem_free_if(exec_dgi->file);
|
||||
mem_free_if(exec_dgi->inpext);
|
||||
mem_free_if(exec_dgi->outext);
|
||||
mem_free(exec_dgi);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
exec_later_dgi(struct session *ses, char *handler, char *file, char *inpext, char *outext, int del)
|
||||
{
|
||||
struct exec_dgi *exec_dgi = (struct exec_dgi *)mem_calloc(1, sizeof(*exec_dgi));
|
||||
|
||||
if (exec_dgi) {
|
||||
exec_dgi->ses = ses;
|
||||
exec_dgi->command = null_or_stracpy(handler);
|
||||
exec_dgi->file = null_or_stracpy(file);
|
||||
exec_dgi->inpext = null_or_stracpy(inpext);
|
||||
exec_dgi->outext = null_or_stracpy(outext);
|
||||
exec_dgi->del = del;
|
||||
register_bottom_half(exec_dgi_command, exec_dgi);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
download_data_store(struct download *download, struct file_download *file_download)
|
||||
{
|
||||
@ -462,6 +528,12 @@ download_data_store(struct download *download, struct file_download *file_downlo
|
||||
file_download->external_handler, file_download->file);
|
||||
/* Temporary file is deleted by the mailcap_protocol_handler */
|
||||
file_download->delete_ = 0;
|
||||
} else if (file_download->dgi) {
|
||||
exec_later_dgi(file_download->ses,
|
||||
file_download->external_handler, file_download->file,
|
||||
file_download->inpext, file_download->outext, 1);
|
||||
/* Temporary file is deleted by the dgi_protocol_handler */
|
||||
file_download->delete_ = 0;
|
||||
} else {
|
||||
exec_on_terminal(term, file_download->external_handler,
|
||||
file_download->file,
|
||||
@ -1260,7 +1332,17 @@ continue_download_do(struct terminal *term, int fd, void *data,
|
||||
codw_hop->real_file = NULL;
|
||||
fd = -1;
|
||||
|
||||
if (type_query->external_handler) {
|
||||
if (type_query->dgi && type_query->external_handler) {
|
||||
file_download->external_handler = type_query->external_handler;
|
||||
file_download->file = codw_hop->file;
|
||||
file_download->inpext = null_or_stracpy(type_query->inpext);
|
||||
file_download->outext = null_or_stracpy(type_query->outext);
|
||||
file_download->dgi = type_query->dgi;
|
||||
file_download->delete_ = 1;
|
||||
/* change owners a few lines above */
|
||||
codw_hop->file = NULL;
|
||||
type_query->external_handler = NULL;
|
||||
} else if (type_query->external_handler) {
|
||||
file_download->external_handler = subst_file(type_query->external_handler,
|
||||
codw_hop->file,
|
||||
type_query->uri->string);
|
||||
@ -1390,6 +1472,8 @@ done_type_query(struct type_query *type_query)
|
||||
|
||||
object_unlock(type_query->cached);
|
||||
done_uri(type_query->uri);
|
||||
mem_free_if(type_query->inpext);
|
||||
mem_free_if(type_query->outext);
|
||||
mem_free_if(type_query->external_handler);
|
||||
mem_free_if(type_query->target_frame);
|
||||
del_from_list(type_query);
|
||||
@ -1510,6 +1594,17 @@ tp_open(struct type_query *type_query)
|
||||
char *file = get_uri_string(type_query->uri, URI_PATH);
|
||||
char *handler = NULL;
|
||||
|
||||
if (type_query->dgi) {
|
||||
if (file) {
|
||||
decode_uri(file);
|
||||
}
|
||||
exec_later_dgi(type_query->ses, type_query->external_handler, file,
|
||||
type_query->inpext, type_query->outext, 0);
|
||||
mem_free_if(file);
|
||||
done_type_query(type_query);
|
||||
return;
|
||||
}
|
||||
|
||||
if (file) {
|
||||
decode_uri(file);
|
||||
handler = subst_file(type_query->external_handler,
|
||||
@ -1564,6 +1659,9 @@ do_type_query(struct type_query *type_query, char *ct, struct mime_handler *hand
|
||||
if (handler) {
|
||||
type_query->block = handler->block;
|
||||
type_query->copiousoutput = handler->copiousoutput;
|
||||
type_query->dgi = handler->dgi;
|
||||
type_query->inpext = null_or_stracpy(handler->inpext);
|
||||
type_query->outext = null_or_stracpy(handler->outext);
|
||||
if (!handler->ask) {
|
||||
type_query->external_handler = stracpy(handler->program);
|
||||
tp_open(type_query);
|
||||
|
@ -100,6 +100,12 @@ struct type_query {
|
||||
* this frame. This string must be freed with mem_free(). */
|
||||
char *target_frame;
|
||||
|
||||
/** input filename extension */
|
||||
char *inpext;
|
||||
|
||||
/** output filename extension */
|
||||
char *outext;
|
||||
|
||||
/** Command line for an external handler, to be run when the
|
||||
* download finishes. When ELinks displays the type query,
|
||||
* it copies this from mime_handler.program of the default
|
||||
@ -121,6 +127,7 @@ struct type_query {
|
||||
* from a "file" URI that does not refer to a local CGI, then
|
||||
* Elinks need not copy the file. */
|
||||
unsigned int cgi:1;
|
||||
unsigned int dgi:1;
|
||||
|
||||
/** mailcap entry with copiousoutput */
|
||||
unsigned int copiousoutput:1;
|
||||
@ -152,6 +159,12 @@ struct file_download {
|
||||
int notify;
|
||||
struct download download;
|
||||
|
||||
/** input filename extension */
|
||||
char *inpext;
|
||||
|
||||
/** output filename extension */
|
||||
char *outext;
|
||||
|
||||
/** Should the file be deleted when destroying the structure */
|
||||
unsigned int delete_:1;
|
||||
|
||||
@ -161,6 +174,7 @@ struct file_download {
|
||||
/** Whether to block the terminal when running the external handler. */
|
||||
unsigned int block:1;
|
||||
|
||||
unsigned int dgi:1;
|
||||
/** Mailcap entry with copiousoutput */
|
||||
unsigned int copiousoutput:1;
|
||||
|
||||
@ -169,6 +183,15 @@ struct file_download {
|
||||
struct listbox_item *box_item;
|
||||
};
|
||||
|
||||
struct exec_dgi {
|
||||
struct session *ses;
|
||||
char *command;
|
||||
char *file;
|
||||
char *inpext;
|
||||
char *outext;
|
||||
unsigned int del:1;
|
||||
};
|
||||
|
||||
/** Stack of all running downloads */
|
||||
extern LIST_OF(struct file_download) downloads;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user