/* elmo - ELectronic Mail Operator Copyright (C) 2003, 2004 rzyjontko This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ---------------------------------------------------------------------- attachments viewer */ /**************************************************************************** * IMPLEMENTATION HEADERS ****************************************************************************/ #include #include #include #include #include #include "attach.h" #include "ecurses.h" #include "error.h" #include "mail.h" #include "rmime.h" #include "select.h" #include "xmalloc.h" #include "read.h" #include "cmd.h" #include "gettext.h" #include "wrapbox.h" #include "file.h" #include "ask.h" #include "interface.h" #include "color.h" #include "label.h" #include "folder.h" #include "eprintf.h" #include "run.h" /**************************************************************************** * IMPLEMENTATION PRIVATE DEFINITIONS / ENUMERATIONS / SIMPLE TYPEDEFS ****************************************************************************/ /**************************************************************************** * IMPLEMENTATION PRIVATE CLASS PROTOTYPES / EXTERNAL CLASS REFERENCES ****************************************************************************/ /**************************************************************************** * IMPLEMENTATION PRIVATE STRUCTURES / UTILITY CLASSES ****************************************************************************/ /**************************************************************************** * IMPLEMENTATION REQUIRED EXTERNAL REFERENCES (AVOID) ****************************************************************************/ /**************************************************************************** * IMPLEMENTATION PRIVATE DATA ****************************************************************************/ /* Attachment window consists of select_t object and an optional label. */ static select_t *attach_select = NULL; static elabel_t *label = NULL; static char *attach_fmt = "%020t %040f (%-06s)"; /* These are directories, where user saves his attachments. */ static char *save_dir = NULL; static char *save_all_dir = NULL; /* Color used in attachments window. */ static chtype text_color; /* Used in draw_line. */ static str_t *str_line = NULL; /**************************************************************************** * INTERFACE DATA ****************************************************************************/ /**************************************************************************** * IMPLEMENTATION PRIVATE FUNCTION PROTOTYPES ****************************************************************************/ /* This file is generated by interface.pl script from interface.desc, and inc.in. */ static WINDOW *interface_init (void); #include "attach.inc" /**************************************************************************** * IMPLEMENTATION PRIVATE FUNCTIONS ****************************************************************************/ static mime_t * selected_mime (void) { mail_t *mail = folder_mail_selected (); return mime_nth_leaf (mail->mime, attach_select->bar_pos); } static void draw_line (WINDOW *win, int maxlen, int index, search_t *search) { mail_t *mail = folder_mail_selected (); mime_t *mime = (mail) ? mime_nth_leaf (mail->mime, index) : NULL; if (str_line == NULL) str_line = str_create (); if (mime) { eprintf_mime_str (attach_fmt, mime, str_line); maxlen -= window_addnstr (win, str_line->str, maxlen); } while (maxlen-- > 0) window_addch (win, ' '); } static int count (select_t *nothing) { mail_t *mail = folder_mail_selected (); return (mail) ? mime_leaf_count (mail->mime) : 0; } static void set_focus (void) { if (label){ label_set_focus (label); } cmd_state_push (CMD_ATTACH); attach_refresh (); } static void unset_focus (void) { if (label){ label_unset_focus (label); label_redraw (label); } cmd_state_pop (); } static void save_directory (char **dir, char *str) { char *seek = strrchr (str, '/'); if (seek == NULL) return; if (*dir) xfree (*dir); *seek = '\0'; *dir = xstrdup (str); *seek = '/'; } static int save_file (FILE *fp, mail_t *mail, mime_t *mime) { int ret = 0; str_t *str; str = wrapbox_mail_body (mail, mime, 1); if (str == NULL){ error_ (errno, _("couldn't read attachment, write aborted")); return 1; } if (fwrite (str->str, 1, str->len, fp) != str->len){ error_ (errno, "fwrite"); ret = 1; } fclose (fp); str_destroy (str); return ret; } static FILE * force_open (const char *dir, const char *fname, char *path) { FILE *fp; fp = file_open (path, "w", O_WRONLY | O_CREAT, 0644); if (fp == NULL) error_ (errno, _("couldn't open %s in %s"), fname, dir); xfree (path); return fp; } static FILE * try_open (const char *dir, const char *fname, char *path, int *overwrite) { char *response; str_t *str; FILE *fp; if (*overwrite){ return force_open (dir, fname, path); } fp = file_open (path, "w", O_WRONLY | O_CREAT | O_EXCL, 0644); if (fp == NULL){ if (errno != EEXIST){ error_ (errno, _("couldn't open %s in %s"), fname, dir); xfree (path); return NULL; } str = str_create (); str_sprintf (str, _("File %s already exists, overwrite " "[a/y/N]? "), fname); response = read_argument (str->str, NULL, COMPLETE_NONE, HIDE_NO); str_destroy (str); if (*response == 'a' || *response == 'A') *overwrite = 1; else if (*response != 'y' && *response != 'Y'){ xfree (path); return NULL; } } return force_open (dir, fname, path); } static int save_attach (const char *dir, mail_t *mail, mime_t *mime, int overwrite) { int i; char *path; FILE *fp; if (mime == NULL) return overwrite; if (mime->file_name){ path = file_with_dir (dir, mime->file_name); fp = try_open (dir, mime->file_name, path, & overwrite); if (fp) save_file (fp, mail, mime); return overwrite; } if (mime->parts == NULL) return overwrite; for (i = 0; i < mime->parts->count; i++){ overwrite = save_attach (dir, mail, mime->parts->array[i], overwrite); } return overwrite; } /**************************************************************************** * INTERFACE FUNCTIONS ****************************************************************************/ void attach_init (void) { WINDOW *window; window = interface_init (); attach_select = select_open (window, 0, draw_line, count); window_set_functions (window, attach_show, attach_refresh, set_focus, unset_focus); } void attach_free_resources (void) { if (attach_select) select_close (attach_select); attach_select = NULL; if (label) label_destroy (label); label = NULL; if (str_line) str_destroy (str_line); str_line = NULL; if (save_dir) xfree (save_dir); save_dir = NULL; if (save_all_dir) xfree (save_all_dir); save_all_dir = NULL; } void attach_show (void) { window_show (attach_select->win); select_first (attach_select); attach_refresh (); } void attach_hide (void) { window_hide (attach_select->win); } void attach_refresh (void) { if (label) label_redraw (label); select_redraw (attach_select); } void attach_hit (void) { mail_t *mail = folder_mail_selected (); mime_t *mime = selected_mime (); if (run_mime (mail, mime) == 2) window_hide (attach_select->win); } void attach_prev (void) { select_prev (attach_select); } void attach_next (void) { select_next (attach_select); } void attach_prev_page (void) { select_prev_page (attach_select); } void attach_next_page (void) { select_next_page (attach_select); } void attach_first (void) { select_first (attach_select); } void attach_last (void) { select_last (attach_select); } void attach_save (void) { FILE *fp; char *def; char *file; int ret; mail_t *mail = folder_mail_selected (); mime_t *mime = (mail) ? selected_mime () : NULL; if (mime == NULL) return; def = file_with_dir (save_dir, mime->file_name); file = read_argument (_("File: "), def, COMPLETE_FILES, HIDE_NO); if (file == NULL || *file == '\0' || *file == '\n') return; if (def) xfree (def); save_directory (& save_dir, file); fp = file_open (file, "w", O_WRONLY | O_CREAT | O_EXCL, 0644); if (fp == NULL){ if (errno != EEXIST){ error_ (errno, "%s", file); return; } file = xstrdup (file); ret = ask_if_sure (_("File already exists, overwrite [y/N]? ")); switch (ret){ case -1: case 0: xfree (file); return; case 1: fp = file_open (file, "w", O_WRONLY | O_CREAT | O_TRUNC, 0644); if (fp == NULL){ error_ (errno, "%s", file); xfree (file); return; } xfree (file); } } save_file (fp, mail, selected_mime ()); } void attach_save_all (void) { char *dir; mail_t *mail = folder_mail_selected (); if (mail == NULL || mail->mime == NULL) return; dir = read_argument (_("Directory: "), save_all_dir, COMPLETE_FILES, HIDE_NO); if (dir == NULL || *dir == '\0' || *dir == '\n') return; if (save_all_dir) xfree (save_all_dir); save_all_dir = xstrdup (dir); if (mail->mime->decrypted) save_attach (save_all_dir, mail, mail->mime->decrypted, 0); else save_attach (save_all_dir, mail, mail->mime->mime, 0); } /**************************************************************************** * INTERFACE CLASS BODIES ****************************************************************************/ /**************************************************************************** * * END MODULE attach.c * ****************************************************************************/