From 7dfb20d11fbfa7937169432deeb317aff4184d1a Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Sat, 24 Jul 2010 17:07:18 +0200 Subject: [PATCH] Handle mailcap's copiousoutput without an external pager. I tested it only on local PDFs. I don't know if temporary files are deleted or not. --- src/mime/backend/mailcap.c | 19 +------- src/mime/mime.h | 1 + src/protocol/file/Makefile | 2 +- src/protocol/http/blacklist.c | 7 ++- src/protocol/protocol.c | 2 + src/protocol/protocol.h | 1 + src/session/download.c | 102 +++++++++++++++++++++++++++++++++++++++--- src/session/download.h | 5 +++ 8 files changed, 112 insertions(+), 27 deletions(-) diff --git a/src/mime/backend/mailcap.c b/src/mime/backend/mailcap.c index 7f56a61d..4c13c184 100644 --- a/src/mime/backend/mailcap.c +++ b/src/mime/backend/mailcap.c @@ -547,24 +547,6 @@ format_command(unsigned char *command, unsigned char *type, int copiousoutput) break; } } - - if (copiousoutput) { - unsigned char *pager = getenv("PAGER"); - - if (!pager && file_exists(DEFAULT_PAGER_PATH)) { - pager = DEFAULT_PAGER_PATH; - } else if (!pager && file_exists(DEFAULT_LESS_PATH)) { - pager = DEFAULT_LESS_PATH; - } else if (!pager && file_exists(DEFAULT_MORE_PATH)) { - pager = DEFAULT_MORE_PATH; - } - - if (pager) { - add_char_to_string(&cmd, '|'); - add_to_string(&cmd, pager); - } - } - return cmd.source; } @@ -772,6 +754,7 @@ get_mime_handler_mailcap(unsigned char *type, int xwin) get_mailcap_ask(), block); mem_free(program); + handler->copiousoutput = entry->copiousoutput; return handler; } diff --git a/src/mime/mime.h b/src/mime/mime.h index 779ed3b8..01524fdd 100644 --- a/src/mime/mime.h +++ b/src/mime/mime.h @@ -11,6 +11,7 @@ struct mime_handler { unsigned char *backend_name; unsigned int ask:1; unsigned int block:1; + unsigned int copiousoutput:1; unsigned char program[1]; /* XXX: Keep last! */ }; diff --git a/src/protocol/file/Makefile b/src/protocol/file/Makefile index 3d27a63b..99e51b9a 100644 --- a/src/protocol/file/Makefile +++ b/src/protocol/file/Makefile @@ -3,6 +3,6 @@ include $(top_builddir)/Makefile.config OBJS-$(CONFIG_CGI) += cgi.o -OBJS = file.o +OBJS = file.o mailcap.o include $(top_srcdir)/Makefile.lib diff --git a/src/protocol/http/blacklist.c b/src/protocol/http/blacklist.c index 2b9e7ea4..ec2a4638 100644 --- a/src/protocol/http/blacklist.c +++ b/src/protocol/http/blacklist.c @@ -9,6 +9,7 @@ #include "elinks.h" #include "protocol/http/blacklist.h" +#include "protocol/protocol.h" #include "protocol/uri.h" #include "util/lists.h" #include "util/memory.h" @@ -30,8 +31,10 @@ get_blacklist_entry(struct uri *uri) { struct blacklist_entry *entry; - assert(uri && uri->hostlen > 0); - if_assert_failed return NULL; + if (uri->protocol != PROTOCOL_MAILCAP) { + assert(uri && uri->hostlen > 0); + if_assert_failed return NULL; + } foreach (entry, blacklist) if (!c_strlcasecmp(entry->host, -1, uri->host, uri->hostlen)) diff --git a/src/protocol/protocol.c b/src/protocol/protocol.c index 02743c32..433cc0fa 100644 --- a/src/protocol/protocol.c +++ b/src/protocol/protocol.c @@ -32,6 +32,7 @@ #include "protocol/data.h" #include "protocol/file/cgi.h" #include "protocol/file/file.h" +#include "protocol/file/mailcap.h" #include "protocol/finger/finger.h" #include "protocol/fsp/fsp.h" #include "protocol/ftp/ftp.h" @@ -68,6 +69,7 @@ static const struct protocol_backend protocol_backends[] = { { "http", 80, http_protocol_handler, 1, 1, 0, 0, 1 }, { "https", 443, https_protocol_handler, 1, 1, 0, 1, 1 }, { "javascript", 0, NULL, 0, 0, 1, 0, 1 }, + { "mailcap", 0, execute_mailcap, 0, 0, 1, 0, 0 }, { "news", 0, news_protocol_handler, 0, 0, 1, 0, 1 }, { "nntp", 119, nntp_protocol_handler, 1, 1, 0, 0, 0 }, { "nntps", 563, nntp_protocol_handler, 1, 1, 0, 1, 0 }, diff --git a/src/protocol/protocol.h b/src/protocol/protocol.h index d009bc0c..aa994172 100644 --- a/src/protocol/protocol.h +++ b/src/protocol/protocol.h @@ -21,6 +21,7 @@ enum protocol { PROTOCOL_HTTP, PROTOCOL_HTTPS, PROTOCOL_JAVASCRIPT, + PROTOCOL_MAILCAP, PROTOCOL_NEWS, PROTOCOL_NNTP, PROTOCOL_NNTPS, diff --git a/src/session/download.c b/src/session/download.c index 90d7d3e6..dada4ddf 100644 --- a/src/session/download.c +++ b/src/session/download.c @@ -32,6 +32,7 @@ #include "dialogs/menu.h" #include "intl/gettext/libintl.h" #include "main/object.h" +#include "main/select.h" #include "mime/mime.h" #include "network/connection.h" #include "network/progress.h" @@ -326,6 +327,83 @@ abort_download_and_beep(struct file_download *file_download, struct terminal *te abort_download(file_download); } +struct exec_mailcap { + struct session *ses; + unsigned char *command; + unsigned char *file; +}; + +static void +do_follow_url_mailcap(struct session *ses, struct uri *uri) +{ + if (!uri) { + print_error_dialog(ses, connection_state(S_BAD_URL), uri, PRI_CANCEL); + return; + } + + ses->reloadlevel = CACHE_MODE_NORMAL; + + if (ses->task.type == TASK_FORWARD) { + if (compare_uri(ses->loading_uri, uri, 0)) { + /* We're already loading the URL. */ + return; + } + } + + abort_loading(ses, 0); + + ses_goto(ses, uri, NULL, NULL, CACHE_MODE_NORMAL, TASK_FORWARD, 0); +} + + +static void +exec_mailcap_command(void *data) +{ + struct exec_mailcap *exec_mailcap = data; + + if (exec_mailcap) { + if (exec_mailcap->command) { + int length = strlen(exec_mailcap->command) + + sizeof("mailcap:"); + unsigned char *buf = malloc(length); + + if (buf) { + struct uri *ref = get_uri("mailcap:elmailcap", 0); + struct uri *uri; + struct session *ses = exec_mailcap->ses; + + memcpy(buf, "mailcap:", 8); + memcpy(buf + 8, exec_mailcap->command, length - 9); + buf[length - 1] = '\0'; + + uri = get_uri(buf, 0); + mem_free(buf); + set_session_referrer(ses, ref); + if (ref) done_uri(ref); + + do_follow_url_mailcap(ses, uri); + if (uri) done_uri(uri); + } + mem_free(exec_mailcap->command); + } + mem_free_if(exec_mailcap->file); + mem_free(exec_mailcap); + } +} + +static void +exec_later(struct session *ses, unsigned char *handler, unsigned char *file) +{ + struct exec_mailcap *exec_mailcap = calloc(1, sizeof(*exec_mailcap)); + + if (exec_mailcap) { + exec_mailcap->ses = ses; + exec_mailcap->command = null_or_stracpy(handler); + exec_mailcap->file = null_or_stracpy(file); + register_bottom_half(exec_mailcap_command, exec_mailcap); + } +} + static void download_data_store(struct download *download, struct file_download *file_download) { @@ -377,9 +455,15 @@ download_data_store(struct download *download, struct file_download *file_downlo prealloc_truncate(file_download->handle, file_download->seek); close(file_download->handle); file_download->handle = -1; - exec_on_terminal(term, file_download->external_handler, - file_download->file, - file_download->block ? TERM_EXEC_FG : TERM_EXEC_BG); + if (file_download->copiousoutput) { + exec_later(file_download->ses, + file_download->external_handler, NULL); + } else { + exec_on_terminal(term, file_download->external_handler, + file_download->file, + file_download->block ? TERM_EXEC_FG : + TERM_EXEC_BG); + } file_download->delete = 0; abort_download_and_beep(file_download, term); return; @@ -1157,6 +1241,7 @@ continue_download_do(struct terminal *term, int fd, void *data, file_download->external_handler = subst_file(type_query->external_handler, codw_hop->file); file_download->delete = 1; + file_download->copiousoutput = type_query->copiousoutput; mem_free(codw_hop->file); mem_free_set(&type_query->external_handler, NULL); } @@ -1407,9 +1492,13 @@ tp_open(struct type_query *type_query) } if (handler) { - exec_on_terminal(type_query->ses->tab->term, - handler, "", - type_query->block ? TERM_EXEC_FG : TERM_EXEC_BG); + if (type_query->copiousoutput) { + exec_later(type_query->ses, handler, NULL); + } else { + exec_on_terminal(type_query->ses->tab->term, + handler, "", type_query->block ? + TERM_EXEC_FG : TERM_EXEC_BG); + } mem_free(handler); } @@ -1448,6 +1537,7 @@ do_type_query(struct type_query *type_query, unsigned char *ct, struct mime_hand if (handler) { type_query->block = handler->block; + type_query->copiousoutput = handler->copiousoutput; if (!handler->ask) { type_query->external_handler = stracpy(handler->program); tp_open(type_query); diff --git a/src/session/download.h b/src/session/download.h index baec17d5..f1c33345 100644 --- a/src/session/download.h +++ b/src/session/download.h @@ -111,6 +111,8 @@ struct type_query { * Elinks need not copy the file. */ unsigned int cgi:1; + /** mailcap entry with copiousoutput */ + unsigned int copiousoutput:1; /* int frame; */ }; @@ -148,6 +150,9 @@ struct file_download { /** Whether to block the terminal when running the external handler. */ unsigned int block:1; + /** Mailcap entry with copiousoutput */ + unsigned int copiousoutput:1; + /** The current dialog for this download. Can be NULL. */ struct dialog_data *dlg_data; struct listbox_item *box_item; -- 2.11.4.GIT