/* 
   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 <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

#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
 *
 ****************************************************************************/


syntax highlighted by Code2HTML, v. 0.9.1