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 (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: */