static char rcsid[] = "@(#)$Id: storage.c,v 1.13 2006/05/01 09:18:57 hurtta Exp $";
/******************************************************************************
* The Elm (ME+) Mail System - $Revision: 1.13 $ $State: Exp $
*
* Author: Kari Hurtta <hurtta+elm@posti.FMI.FI> (was hurtta+elm@ozone.FMI.FI)
*****************************************************************************/
#include "def_messages.h"
#include "s_elm.h"
DEBUG_VAR(Debug,__FILE__,"messages");
#if ANSI_C
#define S_(x) static x;
#else
#define S_(x)
#endif
struct mv_storage {
struct current_storage ** the_mailbox;
int mailbox_count;
};
static void mt_make_storage_view P_((struct MailboxView *mailbox));
S_(mt_init_mailbox mt_init_storage)
static void mt_init_storage P_((struct MailboxView *mbx));
static void mt_init_storage(mbx)
struct MailboxView *mbx;
{
mbx->u.storage = safe_malloc(sizeof (* (mbx->u.storage)));
/* bzero is defined hdrs/defs.h */
bzero((void *)mbx->u.storage, sizeof (* (mbx->u.storage)));
mbx->u.storage->the_mailbox = NULL;
mbx->u.storage->mailbox_count = 0;
}
S_(mt_free_mailbox mt_free_storage)
static void mt_free_storage P_((struct MailboxView *mbx));
static void mt_free_storage(mbx)
struct MailboxView *mbx;
{
if (mbx->u.storage->the_mailbox) {
int i;
for (i = 0; i < mbx->u.storage->mailbox_count; i++) {
if (mbx->u.storage->the_mailbox[i])
free_storage (& (mbx->u.storage->the_mailbox[i]));
}
free(mbx->u.storage->the_mailbox);
mbx->u.storage->the_mailbox = NULL;
}
mbx->u.storage->mailbox_count = 0;
free(mbx->u.storage);
mbx->u.storage = NULL;
}
S_(mt_add_mailbox_storage mt_add_storage_storage)
static void mt_add_storage_storage P_((struct MailboxView *mailbox,
struct current_storage *storage));
static void mt_add_storage_storage(mailbox,storage)
struct MailboxView *mailbox;
struct current_storage *storage;
{
mailbox->u.storage->the_mailbox =
safe_realloc(mailbox->u.storage->the_mailbox,
sizeof ( mailbox->u.storage->the_mailbox[0]) *
( mailbox->u.storage->mailbox_count + 1));
mailbox->u.storage->the_mailbox[mailbox->u.storage->mailbox_count] = storage;
mailbox->u.storage->mailbox_count++;
}
/* Return 1 if redraw required */
S_(mt_update_view_mailbox mt_update_view_storage)
/* Return 1 if redraw required */
static int mt_update_view_storage P_((struct MailboxView *mailbox));
static int mt_update_view_storage(mailbox)
struct MailboxView *mailbox;
{
int count = 0;
int hide = 0;
int i,x;
for (i = 0; i < mailbox->u.storage->mailbox_count; i++) {
int j;
count += mailbox->u.storage->the_mailbox[i]->message_count;
/* Count how many messages are hided */
for (j = 0; j < mailbox->u.storage->the_mailbox[i]->message_count;
j++) {
if (mailbox->u.storage->the_mailbox[i]->headers &&
mailbox->u.storage->the_mailbox[i]->headers[j] &&
mailbox->u.storage->the_mailbox[i]->headers[j]->
exit_disposition == HIDE) {
DPRINT(Debug,7,(&Debug,"mt_update_view_storage: ... mailbox %d message %d hidden\n",
i,j));
hide++;
}
}
}
DPRINT(Debug,7,(&Debug,
"mt_update_view_storage: mailbox=%x %d storages, %d mails ( %d hidden) , current view len %d\n",
mailbox,mailbox->u.storage->mailbox_count, count, hide,
mailbox->view_len));
if (count - hide != mailbox->view_len) {
mt_make_storage_view(mailbox);
DPRINT(Debug,7,(&Debug,
"mt_update_view_storage=1 (view len=%d)\n",mailbox->view_len));
return 1;
}
DPRINT(Debug,7,(&Debug,
"mt_update_view_storage=0\n"));
return 0;
}
S_(mt_get_main_mailbox_folder mt_get_main_storage_folder)
static struct folder_info * mt_get_main_storage_folder P_((struct MailboxView *mailbox));
static struct folder_info * mt_get_main_storage_folder(mailbox)
struct MailboxView *mailbox;
{
if (mailbox->u.storage->mailbox_count < 1)
return NULL;
if (! mailbox->u.storage->the_mailbox ||
! mailbox->u.storage->the_mailbox[0]) {
panic("MBX VIEW PANIC",__FILE__,__LINE__,"mt_get_main_storage_folder",
"Mailbox count positive, but no pointer",0);
return NULL;
}
return mailbox->u.storage->the_mailbox[0]->current_folder;
}
/* Can be called from signal handler */
S_(mt_get_mailbox_storage mt_get_storage_storage)
/* Can be called from signal handler */
static struct current_storage * mt_get_storage_storage P_((struct MailboxView *mailbox,
int i));
/* Can be called from signal handler */
static struct current_storage * mt_get_storage_storage(mailbox,i)
struct MailboxView *mailbox;
int i;
{
if (i < 0 || i >= mailbox->u.storage->mailbox_count ||
! mailbox->u.storage->the_mailbox[i]) {
panic("MBX VIEW PANIC",__FILE__,__LINE__,"mt_get_storage_storage",
"Bad index",1);
return NULL;
}
return mailbox->u.storage->the_mailbox[i];
}
/* Can be called from signal handler */
S_(mt_get_mailbox_storage_count mt_get_storage_storage_count)
/* Can be called from signal handler */
static int mt_get_storage_storage_count P_((struct MailboxView *mailbox));
/* Can be called from signal handler */
static int mt_get_storage_storage_count(mailbox)
struct MailboxView *mailbox;
{
return mailbox->u.storage->mailbox_count;
}
S_(mt_give_header_mailbox mt_give_header_storage)
static struct header_rec * mt_give_header_storage P_((struct MailboxView *mailbox,
int index,
struct folder_view *v));
static struct header_rec * mt_give_header_storage(mailbox,index,v)
struct MailboxView *mailbox;
int index;
struct folder_view *v;
{
int mbx,idx;
mbx = v->mailbox_number;
if (mbx < 0 || mbx >= mailbox->u.storage->mailbox_count ||
! mailbox->u.storage->the_mailbox ||
! mailbox->u.storage->the_mailbox[mbx]) {
panic("MBX VIEW PANIC",__FILE__,__LINE__,"mt_give_header_storage",
"bad mailbox number",0);
return NULL;
}
idx = v->index;
if (idx < 0 ||
idx >= mailbox->u.storage->the_mailbox[mbx]->message_count ||
! mailbox->u.storage->the_mailbox[mbx]->headers ||
! mailbox->u.storage->the_mailbox[mbx]->headers[idx]) {
panic("MBX VIEW PANIC",__FILE__,__LINE__,"mt_give_header_storage",
"bad internal index",0);
return NULL;
}
return mailbox->u.storage->the_mailbox[mbx]->headers[idx];
}
S_(sdt_give_header_s sdt_give_header_mbx)
static struct header_rec * sdt_give_header_mbx P_((struct sort_data *s,
struct folder_view *v));
static struct header_rec * sdt_give_header_mbx(s,v)
struct sort_data *s;
struct folder_view *v;
{
return s->u.mbx->headers[v->index];
}
static struct sort_data_type mbx_sort = {
SORTDATATYPE_magic,
sdt_give_header_mbx
};
S_(mt_sort_mailbox_view mt_sort_storage_view)
static void mt_sort_storage_view P_((struct MailboxView *mailbox,
hdr_compare_func *func));
static void mt_sort_storage_view(mailbox,func)
struct MailboxView *mailbox;
hdr_compare_func *func;
{
int i;
struct sort_data * array;
/* Little dirty ... */
typedef int (*compar) P_((const void *, const void *));
compar X = (compar) func;
array = safe_malloc(mailbox->view_len * sizeof (array[0]));
for (i = 0; i < mailbox->view_len; i++) {
int mbx = mailbox->view[i].mailbox_number;
array[i].w = mailbox->view[i];
array[i].t = mailbox->thread_view; /* For thread sorting */
array[i].sort_data_type = &mbx_sort;
array[i].u.mbx = mailbox->u.storage->the_mailbox[mbx];
}
qsort(array,mailbox->view_len,sizeof (array[0]), X);
for (i = 0; i < mailbox->view_len; i++) {
mailbox->view[i] = array[i].w;
}
free(array);
}
S_(mt_give_message_data_mailbox mt_give_message_data_storage)
static int mt_give_message_data_storage P_((struct MailboxView *mailbox,
int index,
struct header_rec **ret_header,
FILE **ret_F,
struct counter_data *counter,
parse_mime_callback *parse_mime,
struct folder_view *v));
static int mt_give_message_data_storage(mailbox,index,ret_header,ret_F,
counter,parse_mime,v)
struct MailboxView *mailbox;
int index;
struct header_rec **ret_header;
FILE **ret_F;
struct counter_data *counter;
parse_mime_callback *parse_mime;
struct folder_view *v;
{
struct header_rec *hdr;
int mbx,idx;
mbx = v->mailbox_number;
if (mbx < 0 || mbx >= mailbox->u.storage->mailbox_count ||
! mailbox->u.storage->the_mailbox ||
! mailbox->u.storage->the_mailbox[mbx]) {
panic("MBX VIEW PANIC",__FILE__,__LINE__,
"mt_give_message_data_storage",
"bad mailbox number",0);
return 0;
}
idx = v->index;
if (idx < 0 ||
idx >= mailbox->u.storage->the_mailbox[mbx]->message_count ||
! mailbox->u.storage->the_mailbox[mbx]->headers ||
! mailbox->u.storage->the_mailbox[mbx]->headers[idx]) {
panic("MBX VIEW PANIC",__FILE__,__LINE__,
"mt_give_message_data_storage",
"bad internal index",0);
return 0;
}
if (! mailbox->u.storage->the_mailbox[mbx]->current_folder)
return 0;
hdr = mailbox->u.storage->the_mailbox[mbx]->headers[idx];
/* hdr is also needed on error messages ... */
if (ret_header)
*ret_header = hdr;
if (!prepare_message_access(mailbox->u.storage->the_mailbox[mbx]->
current_folder,
hdr,parse_header_routine,parse_body_routine,
counter,parse_mime))
return 0;
if (ret_F) {
*ret_F = folder_to_fd(mailbox->u.storage->the_mailbox[mbx]->
current_folder,
hdr->offset);
if (!*ret_F)
return 0;
}
return 1;
}
S_(mt_write_mailbox_info mt_write_storage_info)
static void mt_write_storage_info P_((FILE *fp, struct MailboxView *mailbox,
int s, int cur_idx));
static void mt_write_storage_info(fp,mailbox,s, cur_idx)
FILE *fp;
struct MailboxView *mailbox;
int s;
int cur_idx;
{
int i;
struct current_storage *storage;
if (s < 0 || s >= mailbox->u.storage->mailbox_count)
panic("MBX VIEW PANIC",__FILE__,__LINE__,
"mt_write_storage_info",
"bad storage index",0);
storage = mailbox->u.storage->the_mailbox[s];
if (!storage)
return;
/* write out the pathname of the folder */
write_folder_info(fp,storage->current_folder);
/* write out the folder size and message indices */
fprintf(fp, "N%d\n", storage->message_count);
for (i = 0 ; i < storage->message_count ; ++i) {
if (storage->headers[i] &&
-1 == storage->headers[i]->offset) {
/* Try download tagged messages */
if (((storage->headers[i]->status & TAGGED) ||
( /* OR message is current */
cur_idx == i
)
) && storage->current_folder)
prepare_message_access(storage->current_folder,
storage->headers[i],
parse_header_routine,
parse_body_routine,
NULL,
NO_mime_parse);
}
if (! storage->headers[i] ||
-1 == storage->headers[i]->offset)
fprintf(fp, "I*\n");
else {
fprintf(fp, "I%ld",
storage->headers[i]->offset);
if (-1 != storage->headers[i]->content_length)
fprintf(fp, " %ld",
storage->headers[i]->content_length);
putc('\n',fp);
}
}
}
S_(mt_mailbox_title mt_storage_title)
static struct string * mt_storage_title P_((struct MailboxView *mailbox));
static struct string * mt_storage_title(mailbox)
struct MailboxView *mailbox;
{
int count = 0;
int mbxcount = 0;
int i;
struct current_storage * s = NULL;
for (i = 0; i < mailbox->u.storage->mailbox_count; i++)
if (mailbox->u.storage->the_mailbox[i] &&
mailbox->u.storage->the_mailbox[i]->current_folder) {
count++;
s = mailbox->u.storage->the_mailbox[i];
if (0 != (FOLDER_MBOX & get_folder_mode(s->current_folder)))
mbxcount++;
}
if (1 == count && s->current_folder) {
struct string * folder_string = NULL;
struct string *s1;
if (*hostname && menu_display_host)
folder_string = format_string(FRM("%s:%S"), hostname,
s->current_folder->
cur_folder_disp);
else
folder_string = dup_string(s->current_folder->
cur_folder_disp);
s1 = format_string(CATGETS(elm_msg_cat, ElmSet,
ElmShownMbxTitle1,
"%s is '%S'"),
folder_type(s->current_folder),
folder_string);
free_string(&folder_string);
return s1;
}
if (mbxcount > 0 && *hostname && menu_display_host)
return format_string(CATGETS(elm_msg_cat, ElmSet,
ElmShownMbxTitleMbxOn,
"%d mailboxes on %s"),
count,hostname);
if (mbxcount > 0)
return format_string(CATGETS(elm_msg_cat, ElmSet,
ElmShownMbxTitleMbx,
"%d mailboxes"),
count);
if (*hostname && menu_display_host)
return format_string(CATGETS(elm_msg_cat, ElmSet,
ElmShownMbxTitleFolderOn,
"%d folders on %s"),
count,hostname);
return format_string(CATGETS(elm_msg_cat, ElmSet,
ElmShownMbxTitleFolder,
"%d folders"),
count);
}
S_(mt_make_mailbox_view mt_make_storage_view)
static void mt_make_storage_view (mailbox)
struct MailboxView *mailbox;
{
int count = 0;
int i,x;
for (i = 0; i < mailbox->u.storage->mailbox_count; i++)
count += mailbox->u.storage->the_mailbox[i]->message_count;
if (count < 1) {
if (mailbox->view)
free(mailbox->view);
mailbox->view = NULL;
mailbox->view_len = 0;
return;
}
mailbox->view =
safe_realloc(mailbox->view,
count * (sizeof ( mailbox->view[0])));
for (i = 0, x = 0; i < mailbox->u.storage->mailbox_count; i++) {
int j;
for (j = 0; j < mailbox->u.storage->the_mailbox[i]->message_count;
j++) {
if (x >= count)
panic("MBX VIEW PANIC",__FILE__,__LINE__,
"mt_make_storage_view",
"overflow",0);
if (mailbox->u.storage->the_mailbox[i]->headers &&
mailbox->u.storage->the_mailbox[i]->headers[j] &&
mailbox->u.storage->the_mailbox[i]->headers[j]->
exit_disposition == HIDE) {
DPRINT(Debug,7,(&Debug,"mt_make_storage_view: ... mailbox %d message %d hidden\n",
i,j));
} else {
zero_folder_view(& (mailbox->view[x]));
mailbox->view[x].mailbox_number = i;
mailbox->view[x].index = j;
x++;
}
}
}
mailbox->view_len = x;
}
S_(mt_add_mailbox_digest mt_add_storage_digest)
static void mt_add_storage_digest P_((struct MailboxView *mailbox,
mime_t *list,
time_t received_time,
char *env_from,
FILE *F,
charset_t defcharset
));
static void mt_add_storage_digest(mailbox, list, received_time, env_from, F,
defcharset
)
struct MailboxView *mailbox;
mime_t *list;
time_t received_time;
char *env_from;
FILE *F;
charset_t defcharset;
{
panic("MBX VIEW PANIC",__FILE__,__LINE__,"mt_add_storage_digest",
"mt_add_storage_digest called",0);
}
static struct mailbox_type mt_storage = {
MAILBOXTYPE_magic,
mt_init_storage,
mt_free_storage,
mt_add_storage_storage,
mt_update_view_storage,
mt_get_main_storage_folder,
mt_get_storage_storage,
mt_get_storage_storage_count,
mt_give_header_storage,
mt_sort_storage_view,
mt_give_message_data_storage,
mt_write_storage_info,
mt_storage_title,
mt_make_storage_view,
mt_add_storage_digest
};
void free_storage(storage)
struct current_storage **storage;
{
if ((*storage)->current_folder) {
/* FREE current_folder */
leave_old_folder(& (*storage)->current_folder,CLOSE_NORMAL);
}
if ((*storage)->headers) {
int i;
for (i = 0; i < (*storage)->max_headers; i++) {
if ((*storage)->headers[i])
header_free( & ((*storage)->headers[i]));
}
free((*storage)->headers);
(*storage)->headers = NULL;
}
free(*storage);
*storage = NULL;
}
struct current_storage *new_storage(new_folder)
struct folder_info *new_folder;
{
struct current_storage *result = NULL;
result = safe_malloc( sizeof (*result));
result->current_folder = new_folder;
result->message_count = 0;
result->max_headers = 0;
result->headers = NULL;
return result;
}
struct MailboxView * malloc_mailbox_view(storage)
struct current_storage *storage;
{
struct MailboxView *ret = malloc_view(&mt_storage);
if (storage) {
ret->mailbox_type->mt_add_it_storage(ret,storage);
ret->mailbox_type->mt_make_it_view(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