summaryrefslogtreecommitdiff
path: root/alpine/mailview.c
diff options
context:
space:
mode:
Diffstat (limited to 'alpine/mailview.c')
-rw-r--r--alpine/mailview.c192
1 files changed, 184 insertions, 8 deletions
diff --git a/alpine/mailview.c b/alpine/mailview.c
index 1265b051..5c886c32 100644
--- a/alpine/mailview.c
+++ b/alpine/mailview.c
@@ -1,11 +1,7 @@
-#if !defined(lint) && !defined(DOS)
-static char rcsid[] = "$Id: mailview.c 1266 2009-07-14 18:39:12Z hubert@u.washington.edu $";
-#endif
-
/*
* ========================================================================
* Copyright 2006-2008 University of Washington
- * Copyright 2013-2021 Eduardo Chappa
+ * Copyright 2013-2022 Eduardo Chappa
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -171,6 +167,8 @@ int scroll_handle_column(int, int);
int scroll_handle_index(int, int);
void scroll_handle_set_loc(POSLIST_S **, int, int);
int dot_on_handle(long, int);
+int imgdata_open(HANDLE_S *);
+char *img_handler(HANDLE_S *);
int url_launch(HANDLE_S *);
int url_launch_too_long(int);
char *url_external_handler(HANDLE_S *, int);
@@ -232,7 +230,7 @@ mail_view_screen(struct pine *ps)
int we_cancel = 0, flags, cmd = 0;
int force_prefer = 0;
MESSAGECACHE *mc;
- ENVELOPE *env;
+ ENVELOPE *env = NULL;
BODY *body;
STORE_S *store;
HANDLE_S *handles = NULL;
@@ -837,6 +835,53 @@ scroll_handle_prompt(HANDLE_S *handle, int force)
else
launch_opts[6].ch = -1;
+ if(handle->type == imgData){
+ if(!handle->h.img.tool
+ && !(handle->h.img.tool = img_handler(handle))){
+ /* TRANSLATORS: a question */
+ if(want_to(_("No Image-Viewer application defined. Define now"),
+ 'y', 0, NO_HELP, WT_SEQ_SENSITIVE) == 'y'){
+ /* Prompt for the displayer? */
+ tmp[0] = '\0';
+ while(1){
+ flags = OE_APPEND_CURRENT |
+ OE_SEQ_SENSITIVE |
+ OE_KEEP_TRAILING_SPACE;
+
+ rc = optionally_enter(tmp, -FOOTER_ROWS(ps_global), 0,
+ sizeof(tmp),
+ _("Image Viewer: "),
+ NULL, NO_HELP, &flags);
+ if(rc == 0){
+ if((flags & OE_USER_MODIFIED) && *tmp){
+ if(can_access(tmp, EXECUTE_ACCESS) == 0){
+ set_variable(V_IMAGE_VIEWER, tmp, TRUE, TRUE, Main);
+ handle->h.img.tool = cpystr(tmp);
+ mailcap_free(); /* redo the mailcap list */
+ break;
+ }
+ else{
+ q_status_message1(SM_ORDER | SM_DING, 2, 2,
+ _("Image Viewer Not Found: %s"),
+ error_description(errno));
+ continue;
+ }
+ }
+ else
+ return(0);
+ }
+ else if(rc == 1 || rc == -1){
+ return(0);
+ }
+ else if(rc == 4){
+ if(ps_global->redrawer)
+ (*ps_global->redrawer)();
+ }
+ }
+ }
+ }
+ }
+
if(handle->type == Attach
&& handle->h.attach
&& handle->h.attach->body
@@ -893,7 +938,7 @@ scroll_handle_prompt(HANDLE_S *handle, int force)
}
else
snprintf(prompt, sizeof(prompt), "View selected %s %s%s%s%.*s%s ? ",
- (handle->type == URL) ? "URL" : "Attachment",
+ (handle->type == URL) ? "URL" : ((handle->type == imgData) ? "Image" : "Attachment"),
external > 0 ? "using external viewer " : "",
external > 0 ? (images > 0 ? "including all images" : "including inline images only") : "",
(handle->type == URL) ? "\"" : "",
@@ -1065,6 +1110,18 @@ scroll_handle_launch(HANDLE_S *handle, int force)
DA_FROM_VIEW | DA_DIDPROMPT, handle->h.ical.depth);
break;
+ case imgData:
+ if(handle->h.img.src){
+ if(scroll_handle_prompt(handle, force)){
+ if(imgdata_open(handle)
+ || ps_global->next_screen != SCREEN_FUN_NULL)
+ return(1); /* done with this screen */
+ }
+ else
+ return(-1);
+ }
+ break;
+
case Function :
(*handle->h.func.f)(handle->h.func.args.stream,
handle->h.func.args.msgmap,
@@ -1556,6 +1613,92 @@ do_url_launch(char *toolp, char *url)
return(rv);
}
+int
+imgdata_open(HANDLE_S *handle)
+{
+ return do_imgdata_open(handle->h.img.tool, handle->h.img.src);
+}
+
+int
+do_imgdata_open(char *toolp, char *data)
+{
+ gf_io_t pc, writec, readc;
+ STORE_S *so, *img;
+ char *tmpfile = NULL, *err = NULL, *imgdata, *encoding;
+
+ if(!toolp) return 1;
+
+ encoding = strchr(data, ';');
+ if(encoding) encoding++;
+ imgdata = strchr(data, ',');
+ if(imgdata) imgdata++;
+ tmpfile = temp_nam(NULL, "img-data-"); /* create temporary file */
+
+ img = so_get(CharStar, NULL, EDIT_ACCESS); /* allocate a pointer to save data */
+ so_seek(img, 0L, 0); /* rewind img to start */
+ gf_set_so_writec(&writec, img); /* set method to write to img in writec */
+ gf_set_so_readc(&readc, img); /* set method to read from img in readc */
+
+ if(imgdata
+ && encoding
+ && imgdata
+ && img
+ && gf_puts(imgdata, writec) /* write imgdata to img using writec */
+ && (so = so_get(FileStar, tmpfile, WRITE_ACCESS|OWNER_ONLY)) != NULL){ /* open temporary file */
+
+ so_seek(img, 0L, 0); /* rewind img to start */
+ so_seek(so, 0L, 0); /* rewind so to start */
+ gf_set_so_writec(&pc, so); /* set method to write to so in pc */
+ gf_filter_init(); /* start a filter */
+ if(!struncmp(encoding, "BASE64", 6)) /* link base64 filter */
+ gf_link_filter(gf_b64_binary, NULL);
+
+ err = gf_pipe(readc, pc); /* pass data from imgdata to so, reading from readc and writing with pc */
+
+ gf_clear_so_writec(so); /* disassociate so and pc */
+
+ if(so_give(&so)) /* write tmp to disk and free so */
+ err = "Error writing image to file";
+
+ gf_clear_so_writec(img); /* disassociate img and writec */
+ gf_clear_so_readc(img); /* disassociate img and readc */
+ so_give(&img); /* free img */
+ }
+ else err = "Error creating space for temporary image";
+
+ /* toolp tells us that there is a program to execute, which is
+ * either the image viewer or the mailcap. No matter which, the
+ * information is now in the mailcap structure, so let's use it
+ */
+ if(!err){
+ char *subtype = NULL;
+ if(!struncmp(data, "IMAGE/", 6)){
+ data += 6;
+ for(subtype = data; data && *data != ';'; data++);
+ if(data){
+ *data = '\0';
+ if(mailcap_can_display(TYPEIMAGE, subtype, NULL, 0)){
+ MCAP_CMD_S *mc_cmd;
+
+ mc_cmd = mailcap_build_command(TYPEIMAGE, subtype,
+ NULL, tmpfile, NULL, 0);
+ exec_mailcap_cmd(mc_cmd, tmpfile, 0);
+ }
+ *data = ';';
+ data = subtype - 6;
+ }
+ }
+ }
+ else
+ q_status_message(SM_ORDER, 2, 2,
+ _("\"Image-Viewer\" not defined: Can't open image"));
+
+ if(tmpfile) /* file was deleted by exec_mailcap_cmd */
+ fs_give((void **) &tmpfile);
+
+ return 0;
+}
+
int
url_launch_too_long(int return_value)
@@ -1680,6 +1823,37 @@ get_url_external_handler(char *url, int specific)
return(cmd);
}
+char *
+img_handler(HANDLE_S *handle)
+{
+ char *src = handle && handle->h.img.src ? handle->h.img.src : NULL;
+ char *cmd, *subtype;
+
+ if(!src) return NULL;
+
+ if(ps_global->VAR_IMAGE_VIEWER)
+ cmd = cpystr(ps_global->VAR_IMAGE_VIEWER);
+ else if(!struncmp(src, "IMAGE/", 6)){
+ src += 6;
+ for(subtype = src; src && *src != ';'; src++);
+ if(src){
+ *src = '\0';
+ if(mailcap_can_display(TYPEIMAGE, subtype, NULL, 0)){
+ MCAP_CMD_S *mc_cmd;
+
+ mc_cmd = mailcap_build_command(TYPEIMAGE, subtype,
+ NULL, "_IMG_", NULL, 0);
+ if(mc_cmd){
+ cmd = mc_cmd->command;
+ fs_give((void **)&mc_cmd);
+ }
+ }
+ *src = ';';
+ }
+ }
+
+ return cmd;
+}
url_tool_t
url_local_handler(char *s)
@@ -5023,14 +5197,16 @@ visible_linelen(int line)
switch((i < st->line_lengths[line]) ? st->text_lines[line][i] : 0){
case TAG_HANDLE:
i++;
+ n = 0; /* quell gcc */
/* skip the length byte plus <length> more bytes */
if(i < st->line_lengths[line]){
n = st->text_lines[line][i];
i++;
}
- if(i < st->line_lengths[line] && n > 0)
+ if(i < st->line_lengths[line] && n > 0){
i += n;
+ }
break;