static char rcsid[] = "@(#)$Id: file.c,v 1.52 2006/04/14 21:58:59 hurtta Exp $";
/****************************************************************************
* The Elm (ME+) Mail System - $Revision: 1.52 $ $State: Exp $
*
* Modified by: Kari Hurtta <hurtta+elm@posti.FMI.FI>
* (was hurtta+elm@ozone.FMI.FI)
*****************************************************************************
* The Elm Mail System
*
* Copyright (c) 1988-1992 USENET Community Trust
* Copyright (c) 1986,1987 Dave Taylor
*****************************************************************************/
/** File I/O routines, mostly the save to file command...
**/
#include "def_elm.h"
#ifdef PWDINSYS
# include <sys/pwd.h>
#else
# include <pwd.h>
#endif
#include "s_elm.h"
#include <errno.h>
#ifndef ANSI_C
extern int errno;
#endif
DEBUG_VAR(Debug,__FILE__,"mbox");
#ifndef errno
extern int errno;
#endif
static int save_message P_((int number,
struct folder_browser * XXX,
struct string * name,
WRITE_STATE ptr,
int pause, int appending,
int silently, int delete, int text_only,
struct MailboxView *mailbox,
struct AliasView *aview,
struct menu_context *header_area,
struct menu_context *page));
struct string * prev_fold = NULL; /* name of previous folder */
int save(silently, delete, text_only, mailbox, aview,
page, prompt_area,header_area)
int silently, delete, text_only;
struct MailboxView *mailbox;
struct AliasView *aview;
struct menu_context *page;
struct menu_context *prompt_area;
struct menu_context *header_area;
{
/** Save all tagged messages + current in a folder. If no messages
are tagged, save the current message instead! This routine
will return ZERO if the operation failed.
Pretty reasonable, eh? If "silently" is set,
then don't output the "D" character upon marking for
deletion...
If delete is set, then delete the saved messages, else
we are just copying the messages without deletion.
If text_only is text, message is decoded.
If redraw is needed use
menu_trigger_redraw(page)
**/
int tagged = 0, i, oldstat = -1, appending = 0,
is_ordinary_file, scount = 0;
int mesgnum = 0; /* message whose address is used for save-by-name fn */
int delay_redraw = 0;
struct folder_browser * XXX;
struct string * buffer = NULL;
WRITE_STATE write_ptr = NULL;
int retval = 0;
int fail = 0;
int current = get_current(mailbox);
int mc;
XXX = new_browser(selection_folder);
mc = get_message_count(mailbox);
for (i=0; i < mc; i++) {
if (ison_status_message(mailbox,i,status_basic,TAGGED)) {
if(!tagged)
mesgnum = i; /* first tagged msg - use this one for
* save-by-name folder name */
tagged++;
}
}
if (tagged == 0) {
mesgnum = current-1; /* use this one for save-by-name folder name */
tagged = 1;
/* Remebed old current */
oldstat = setf_status_message(mailbox,current-1,status_basic,
TAGGED);
/* 2 == text_only -- Not envelope information */
if (text_only)
text_only = 2;
}
DPRINT(Debug,4, (&Debug,
"%d message%s tagged for saving (save)\n", tagged,
plural(tagged)));
while (1) {
int code;
struct header_rec * mhdr = give_header(mailbox,mesgnum);
int r = 0;
if (!buffer && save_by_name &&
mhdr && mhdr->from && mhdr->from[0].addr) {
char buffer1[1000];
/** build default filename to save to **/
get_return_name(mhdr->from[0].addr,
buffer1, TRUE, sizeof buffer1);
buffer = format_string(FRM("=%s"), buffer1);
}
/* 2 == text_only -- Not envelope information */
/* XXX gen_browser do not take line !!!
FIXME
FIXME gen_browser should use prompt_area
*/
if (text_only > 0) {
if (tagged == 1)
r = gen_browser(page,
XXX,&buffer,
delete ? word_save : word_copy,
prev_fold,
aview,
CATGETS(elm_msg_cat, ElmSet, ElmSaveTextMesTo,
"%s text of message to: "),
(delete ? cap_save_word : cap_copy_word));
else
r = gen_browser(page,
XXX,&buffer,
delete ? word_save : word_copy,
prev_fold,
aview,
CATGETS(elm_msg_cat, ElmSet, ElmSaveTextMessagesTo,
"%s text messages to: "),
(delete ? cap_save_word : cap_copy_word));
} else {
if (tagged == 1)
r = gen_browser(page,
XXX,&buffer,
delete ? word_save : word_copy,
prev_fold,
aview,
CATGETS(elm_msg_cat, ElmSet, ElmSaveMessageTo,
"%s message to: "),
(delete ? cap_save_word : cap_copy_word));
else
r = gen_browser(page,
XXX,&buffer,
delete ? word_save : word_copy,
prev_fold,
aview,
CATGETS(elm_msg_cat, ElmSet, ElmSaveMessagesTo,
"%s messages to: "),
(delete ? cap_save_word : cap_copy_word));
}
if (!r) {
DPRINT(Debug,4,(&Debug, "Canceled...\n"));
if (oldstat != -1) {
/* BACK! */
if (isoff(oldstat,TAGGED))
clearf_status_message(mailbox,current-1,status_basic,
TAGGED);
}
retval = 0;
goto clean;
}
code = give_dir_flags(XXX);
DPRINT(Debug,4,(&Debug,
"*** %S have flags:%s%s%s%s%s%s%s%s\n",
buffer,
code & BROWSER_NODIR ? " NODIR": "",
code & BROWSER_NOFOLDER ? " NOFOLDER": "",
code & BROWSER_MARKED ? " MARKED": "",
code & BROWSER_MAILFILE ? " MAILFILE": "",
code & BROWSER_SELECTED ? " SELECTED": "",
code & BROWSER_EXIST ? " EXIST" : "",
code & BROWSER_DIRPREFIX ? " DIRPREFIX" : "",
!code ? " none" : ""));
if (0 == code) { /** <return> means 'cancel', right? **/
if (oldstat != -1) {
/* BACK! */
if (isoff(oldstat,TAGGED))
setf_status_message(mailbox,current-1,status_basic,
TAGGED);
}
retval = 0;
goto clean;
}
/* Replace editing buffer with expanded version ... */
if (buffer)
free_string(&buffer);
buffer = selection_name_dir(XXX);
is_ordinary_file = 0 == (code & BROWSER_MAILFILE);
/* 2 == text_only -- Not envelope information */
if (2 == text_only && !is_ordinary_file)
text_only = 1;
if (0 != (code & BROWSER_EXIST)) { /* already there!! */
appending = 1;
if (confirm_append || (confirm_files && is_ordinary_file)) {
int answer = '\0';
again:
if (is_ordinary_file)
answer = prompt_letter(2,"",*def_ans_no,
PROMPT_yesno|PROMPT_redraw_mark|
PROMPT_ctrlL|PROMPT_cancel|
PROMPT_center,
prompt_area,
CATGETS(elm_msg_cat, ElmSet,
ElmConfirmFilesAppend,
"Append to an existing file `%S'? (%c/%c) "),
buffer,
*def_ans_yes,
*def_ans_no);
else
answer = prompt_letter(2,"",*def_ans_no,
PROMPT_yesno|PROMPT_redraw_mark|
PROMPT_ctrlL|PROMPT_cancel|
PROMPT_center,
prompt_area,
CATGETS(elm_msg_cat, ElmSet,
ElmConfirmFolderAppend,
"Append to mail folder `%S'? (%c/%c) "),
buffer,
*def_ans_yes,
*def_ans_no);
if (('L'&31) == answer ||
REDRAW_MARK == answer) {
menu_ClearScreen(page); /* Reset possible redraw flag */
/* Call refresh routines of children */
menu_redraw_children(page);
if (menu_need_redraw(prompt_area))
menu_ClearScreen(prompt_area);
delay_redraw++; /* Can't trigger redraw yet... */
goto again;
}
if (TERMCH_interrupt_char == answer ||
EOF == answer)
goto clean;
if (answer != *def_ans_yes) {
continue; /* RETRY */
}
}
} else {
if (confirm_create || (confirm_folders && !is_ordinary_file)) {
int answer = '\0';
again2:
if (is_ordinary_file)
answer = prompt_letter(2,"",*def_ans_no,
PROMPT_yesno|PROMPT_redraw_mark|
PROMPT_ctrlL|PROMPT_cancel|
PROMPT_center,
prompt_area,
CATGETS(elm_msg_cat, ElmSet,
ElmConfirmFilesCreate,
"Create a new file `%S'? (%c/%c) "),
buffer,
*def_ans_yes,
*def_ans_no);
else
answer = prompt_letter(2,"",*def_ans_no,
PROMPT_yesno|PROMPT_redraw_mark|
PROMPT_ctrlL|PROMPT_cancel|
PROMPT_center,
prompt_area,
CATGETS(elm_msg_cat, ElmSet,
ElmConfirmFolderCreate,
"Create a new mail folder `%S'? (%c/%c) "),
buffer,
*def_ans_yes,
*def_ans_no);
if (('L'&31) == answer ||
REDRAW_MARK == answer) {
menu_ClearScreen(page); /* Reset possible redraw flag */
/* Call refresh routines of children */
menu_redraw_children(page);
if (menu_need_redraw(prompt_area))
menu_ClearScreen(prompt_area);
delay_redraw++; /* Can't trigger redraw yet... */
goto again2;
}
if (TERMCH_interrupt_char == answer)
goto clean;
if (answer != *def_ans_yes) {
continue; /* RETRY */
}
}
/* Create it now ... */
if (!create_selection_dir(XXX))
continue; /* RETRY */
}
if (prepare_write_folder(XXX,&write_ptr)) {
break; /* OK */
}
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmCannotSaveMessage,
"Cannot %s message to folder %S!"),
delete ? save_word:copy_word, buffer);
if (oldstat != -1) {
/* BACK! */
if (isoff(oldstat,TAGGED))
setf_status_message(mailbox,current-1,status_basic,
TAGGED);
}
/* RETRY */
} /* End loop */
/* 2 == text_only -- Not envelope information */
if (2 == text_only && appending)
text_only = 1;
/* save this filename for the next time */
if (2 != text_only) {
if (prev_fold)
free_string(&prev_fold);
prev_fold = dup_string(buffer);
}
/* if we need a redraw that means index screen no longer present
* so whatever silently was, now it's true - we can't show those
* delete markings.
*/
if(delay_redraw || menu_need_redraw(page)) { /* ! ! ! */
silently = TRUE;
delay_redraw = 1;
}
mc = get_message_count(mailbox);
for (i=0; i < mc; i++) { /* save each tagged msg */
if (ison_status_message(mailbox,i,status_basic,TAGGED)) {
struct header_rec * hdr;
if (!save_message(i, XXX, buffer, write_ptr,
(tagged > 1), appending++,
silently, delete, text_only,
mailbox, aview,
header_area,page))
fail++;
if(delay_redraw || menu_need_redraw(page)) { /* ! ! ! */
silently = TRUE;
delay_redraw = 1;
}
scount++;
}
}
if (!end_write_folder(XXX,&write_ptr) || fail) {
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmFailedSaveMessage,
"Failed %s message to folder %S!"),
delete ? save_word:copy_word, buffer);
} else {
if (text_only) {
if (tagged == 1 && !appending)
lib_error(CATGETS(elm_msg_cat, ElmSet,
ElmTextMessageSaved,
"Text of message %s to %S."),
delete ? saved_word: copied_word,
buffer);
else if (tagged > 1)
lib_error(CATGETS(elm_msg_cat, ElmSet,
ElmTextMessagesSaved,
"Text of %d messages %s to %S."),
scount,
delete ? saved_word: copied_word,
buffer);
} else {
if (tagged == 1 && !appending)
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmMessageSaved,
"Message %s to %S."),
delete ? saved_word: copied_word,
buffer);
else if (tagged > 1)
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmMessagesSaved,
"%d messages %s to %S."),
scount,
delete ? saved_word: copied_word,
buffer);
}
retval = 1;
goto clean;
}
clean:
if (XXX)
free_dir(&XXX);
if (buffer)
free_string(&buffer);
DPRINT(Debug,8,(&Debug,
"save=%d delay_redraw=%d\n",
retval,delay_redraw));
if (delay_redraw)
menu_trigger_redraw(page);
else
menu_trigger_redraw(prompt_area);
return retval;
}
static int save_message(number, XXX, name,ptr,
pause, appending, silently,
delete, text_only,
mailbox, aview, header_area,page)
int number, pause, appending, silently, delete;
struct folder_browser * XXX;
struct string * name;
WRITE_STATE ptr;
int text_only;
struct MailboxView *mailbox;
struct AliasView *aview;
struct menu_context *header_area;
struct menu_context *page;
{
int ret = 0;
/** Save an actual message to a folder. This is called by
"save()" only! The parameters are the message number,
and the name and file descriptor of the folder to save to.
If 'pause' is true, a sleep(sleepmsg) will be done after the
saved message appears on the screen...
'appending' is only true if the folder already exists
If 'delete' is true, mark the message for deletion.
If text_only is set then decode_message, if
text_only == 2 no folder envelope will be saved
**/
int save_current, is_new;
int is_tagged = 0;
int delay_redraw = 0;
struct header_rec *hdr;
FILE *infile;
DPRINT(Debug,4,(&Debug,
"\tSaving message %d to folder... (text_only=%d)\n",
number,text_only));
if (!give_message_data(mailbox,number,&hdr,&infile,NULL,
text_only ? mime_parse_routine : NO_mime_parse)) {
DPRINT(Debug,3,(&Debug,
"give_message_data [%d] fails",number));
return 0; /* FAIL */
}
/* change status from NEW before copy and reset to what it was
* so that copy doesn't look new, but we can preserve new status
* of message in this mailfile. This is important because if
* user does a resync, we don't want NEW status to be lost.
* I.e. NEW becomes UNREAD when we "really" leave a mailfile.
*/
if(0 != (is_new = ison(hdr->status, NEW)))
clearit(hdr->status, NEW);
/* Do not save TAGGED flag ... */
if(0 != (is_tagged = ison(hdr->status, TAGGED)))
clearit(hdr->status, TAGGED);
switch(text_only) {
case 2:
ret = copy_message_df(infile,hdr,"",
XXX, ptr,
CM_DECODE | CM_FILT_HDR | CM_REMOVE_ENVELOPE,
system_charset);
break;
case 1:
ret = copy_message_df(infile,hdr,"",
XXX, ptr, CM_DECODE | CM_FILT_HDR,
system_charset);
break;
case 0: default:
ret = copy_message_df(infile,hdr,"",
XXX,ptr, CM_UPDATE_STATUS,
NULL);
break;
}
/* Need redraw -- PGP output ?*/
if (raw_off_called()) {
DPRINT(Debug,9,(&Debug,
"save_message: Raw OFF called\n"));
delay_redraw = TRUE;
silently = TRUE;
}
if(is_new)
setit(hdr->status, NEW);
if (ret) {
if (delete)
setf_status_message(mailbox,number,status_basic,DELETED);
if (text_only) {
if (appending)
lib_transient(CATGETS(elm_msg_cat, ElmSet,
ElmTextMessageAppendedFolder,
"Text of message %d appended to folder %S."),
number+1, name);
else if (2 == text_only)
lib_transient(CATGETS(elm_msg_cat, ElmSet,
ElmTextMessageSavedFile,
"Text of message %d %s to file %S."),
number+1, delete ? saved_word : copied_word,
name);
else
lib_transient(CATGETS(elm_msg_cat, ElmSet,
ElmTextMessageSavedFolder,
"Text of message %d %s to folder %S."),
number+1, delete ? saved_word : copied_word,
name);
} else {
if (appending)
lib_transient(CATGETS(elm_msg_cat, ElmSet,
ElmMessageAppendedFolder,
"Message %d appended to folder %S."),
number+1, name);
else
lib_transient(CATGETS(elm_msg_cat, ElmSet,
ElmMessageSavedFolder,
"Message %d %s to folder %S."),
number+1, delete ? saved_word : copied_word,
name);
}
/* clear also visible tagged flag if different than on header struct */
clearf_status_message(mailbox,number,status_basic,
TAGGED);
} else {
/* save failed -- is still tagged */
if(is_tagged)
setit(hdr->status, TAGGED);
}
if (! silently && header_area) {
struct menu_common MENU;
int vis;
set_mcommon_from_mbxview(&MENU,mailbox);
vis = compute_visible(number+1, &MENU);
menu_header_status_update(header_area,vis-1);
}
DPRINT(Debug,9,(&Debug,
"save_message: delay_redraw=%d\n",delay_redraw));
if (delay_redraw)
menu_trigger_redraw(page);
if (pause && (!silently) && (!appending))
sleep_message();
DPRINT(Debug,9,(&Debug,
"save_message=%d\n",ret));
return ret;
}
/*
* Local Variables:
* mode:c
* c-basic-offset:4
* buffer-file-coding-system: iso-8859-1
* End:
*/
syntax highlighted by Code2HTML, v. 0.9.1