static char rcsid[] = "@(#)$Id: duplicate.c,v 1.10 2006/04/20 05:42:15 hurtta Exp $"; /****************************************************************************** * The Elm (ME+) Mail System - $Revision: 1.10 $ $State: Exp $ * * Author: Kari Hurtta * or Kari Hurtta *****************************************************************************/ #include "def_messages.h" #include "s_me.h" DEBUG_VAR(Debug,__FILE__,"messages"); #if ANSI_C #define S_(x) static x; #else #define S_(x) #endif #define DUPL_MSGID_magic 0xF506 static struct msg_id_data { unsigned short magic; /* DUPL_MSGID_magic */ char * message_id; struct msg_id_data * smaller; /* LEFT */ struct msg_id_data * bigger; /* RIGHT */ struct instance_chain * chain; } * give_message_id_data P_((struct msg_id_data **root, const char * message_id)); /* This is essentially same than give_uidl() on lib/mbox/pop.c */ static struct msg_id_data *give_message_id_data(root,message_id) struct msg_id_data **root; CONST char * message_id; { struct msg_id_data *ptr = *root; int r; if (!ptr) { ptr = safe_malloc(sizeof(*ptr)); bzero((void *)ptr, sizeof(*ptr)); ptr->magic = DUPL_MSGID_magic; ptr->message_id = safe_strdup(message_id); ptr->smaller = NULL; ptr->bigger = NULL; ptr->chain = NULL; *root = ptr; return ptr; } if (ptr->magic != DUPL_MSGID_magic) panic("MBX VIEW PANIC",__FILE__,__LINE__,"give_message_id_data", "Bad magic number",0); r = strcmp(message_id,ptr->message_id); if (0 == r) { return ptr; } else if (0 < r) { return give_message_id_data(& (ptr->bigger), message_id); } else { return give_message_id_data(& (ptr->smaller), message_id); } } static void free_message_ids P_((struct msg_id_data **root)); static void free_message_ids(root) struct msg_id_data **root; { struct msg_id_data *ptr = *root; if (ptr->magic != DUPL_MSGID_magic) panic("MBX VIEW PANIC",__FILE__,__LINE__,"free_message_ids", "Bad magic number",0); if (ptr->smaller) free_message_ids(& (ptr->smaller)); if (ptr->bigger) free_message_ids(& (ptr->bigger)); if (ptr->message_id) { free(ptr->message_id); ptr->message_id = NULL; } ptr->chain = NULL; ptr->magic = 0; /* Invalidate */ free(ptr); *root = NULL; } #define MV_INSTANCE_magic 0xF507 struct instance_chain { unsigned short magic; /* MV_INSTANCE_magic */ struct instance_chain * next; struct header_rec *mss; struct folder_view *locs; int loc_len; }; #define MV_DUPLICATE_magic 0xF505 struct mv_duplicate { unsigned short magic; /* MV_DUPLICATE_magic */ struct MailboxView * parent_mailbox; struct msg_id_data * learn_ids; struct instance_chain ** collected; int collected_len; }; static struct instance_chain * add_to_chain P_((struct mv_duplicate *mv, struct msg_id_data *id)); static struct instance_chain * add_to_chain(mv,id) struct mv_duplicate *mv; struct msg_id_data *id; { struct instance_chain * ret; if (MV_DUPLICATE_magic != mv->magic) panic("MBX VIEW PANIC",__FILE__,__LINE__,"add_to_chain", "Bad magic number",0); if (DUPL_MSGID_magic != id->magic) panic("MBX VIEW PANIC",__FILE__,__LINE__,"add_to_chain", "Bad magic number",0); ret = safe_malloc(sizeof (*ret)); bzero((void *)ret, sizeof(*ret)); ret->magic = MV_INSTANCE_magic; ret->mss = NULL; ret->locs = NULL; ret->loc_len = 0; ret->next = id->chain; id->chain = ret; mv->collected = safe_realloc(mv->collected, (mv->collected_len +1) * sizeof (mv->collected+1)); mv->collected[mv->collected_len] = ret; mv->collected_len++; return ret; } static void free_chain_item P_((struct instance_chain ** item)); static void free_chain_item(item) struct instance_chain ** item; { if ((*item)->magic != MV_INSTANCE_magic) panic("MBX VIEW PANIC",__FILE__,__LINE__,"add_to_chain", "Bad magic number",0); if ((*item)->mss) header_free(& ((*item)->mss) ); if ((*item)->locs) { free((*item)->locs); (*item)->locs = NULL; } (*item)->loc_len = 0; (*item)->magic = 0; /* Invalidate */ free((*item)); *item = NULL; } S_(mt_init_mailbox mt_init_duplicate) static void mt_init_duplicate P_((struct MailboxView *mbx)); static void mt_init_duplicate(mbx) struct MailboxView *mbx; { mbx->u.duplicate = safe_malloc(sizeof (* (mbx->u.duplicate))); /* bzero is defined hdrs/defs.h */ bzero((void *)mbx->u.duplicate, sizeof (* (mbx->u.duplicate))); mbx->u.duplicate->parent_mailbox = NULL; mbx->u.duplicate->magic = MV_DUPLICATE_magic; mbx->u.duplicate->learn_ids = NULL; mbx->u.duplicate->collected = NULL; mbx->u.duplicate->collected_len = 0; } S_(mt_free_mailbox mt_free_duplicate) static void mt_free_duplicate P_((struct MailboxView *mbx)); static void mt_free_duplicate(mbx) struct MailboxView *mbx; { if (mbx->u.duplicate->magic != MV_DUPLICATE_magic) panic("MBX VIEW PANIC",__FILE__,__LINE__,"mt_free_duplicate", "Bad magic number",0); if (mbx->u.duplicate->learn_ids) free_message_ids( &(mbx->u.duplicate->learn_ids)); if (mbx->u.duplicate->collected) { int i; for (i = 0; i < mbx->u.duplicate->collected_len; i++) { if (mbx->u.duplicate->collected[i]) free_chain_item(& (mbx->u.duplicate->collected[i])); } free(mbx->u.duplicate->collected); mbx->u.duplicate->collected = NULL; } mbx->u.duplicate->collected_len = 0; mbx->u.duplicate->magic = 0; /* Invalidate */ free(mbx->u.duplicate); mbx->u.duplicate = NULL; } S_(mt_add_mailbox_storage mt_add_duplicate_storage) static void mt_add_duplicate_storage P_((struct MailboxView *bx, struct current_storage *storage)); static void mt_add_duplicate_storage(mbx,storage) struct MailboxView *mbx; struct current_storage *storage; { if (mbx->u.duplicate->magic != MV_DUPLICATE_magic) panic("MBX VIEW PANIC",__FILE__,__LINE__,"mt_add_duplicate_storage", "Bad magic number",0); add_storage(mbx->u.duplicate->parent_mailbox,storage); } static void mt_make_duplicate_view P_((struct MailboxView *mailbox)); static struct addr_item * dup_addr_items P_((struct addr_item *src)); static struct addr_item * dup_addr_items(src) struct addr_item *src; { struct addr_item *ret = NULL; append_addr_items(&ret,src); return ret; } static int addr_is_same P_((struct addr_item *a1, struct addr_item *a2)); static int addr_is_same(a1,a2) struct addr_item *a1; struct addr_item *a2; { while(1) { if (! a1->addr && ! a1->fullname && ! a2->addr && ! a2->fullname) return 1; if (! a1->addr || ! a1->fullname || ! a2->addr || ! a2->fullname) return 0; if (0 != strcmp(a1->addr,a2->addr)) return 0; if (0 != string_cmp(a1->fullname, a2->fullname, 99)) return 0; if (a1->comment && a2->comment) { if (0 != string_cmp(a1->comment, a2->comment, 99)) return 0; } else if (a1->comment || a2->comment) return 0; a1++; a2++; } /* NOT REACHED */ } static struct header_rec *copy_header P_((struct header_rec *X, int idx)); static struct header_rec *copy_header(X,idx) struct header_rec *X; int idx; { struct header_rec * ret = safe_malloc(sizeof (*ret)); /* Only save headers which are used on compare and status headers ... others are not used */ header_zero(ret); ret->index_number_X = idx; /* NOT USED */ /* May be used on sorting */ ret->lines = X->lines; ret->status = X->status; ret->status1 = X->status1; strfcpy(ret->env_from, X->env_from, sizeof (ret->env_from)); if (X->from) ret->from = dup_addr_items(X->from); if (X->to) ret->to = dup_addr_items(X->to); if (X->cc) ret->cc = dup_addr_items(X->cc); if (X->subject) ret->subject = dup_string(X->subject); strfcpy(ret->messageid, X->messageid, sizeof (ret->messageid)); strfcpy(ret->time_zone, X->time_zone, sizeof (ret->time_zone)); ret->time_sent = X->time_sent; ret->tz_offset = X->tz_offset; /* -> list_info is not supported */ return ret; } static int cmp_headers_ok P_((struct header_rec * h1, struct header_rec *h2)); static int cmp_headers_ok(h1,h2) struct header_rec * h1; struct header_rec * h2; { /* Do NOT compare lines -- * * it includes headers and mail with different number of * Received: -headers are OK */ /* Do NOT compare content_length --- * * Unix mailboxes may use LF as end of line, but * on IMAP and POP we use CR LF as end of line * So these give different length .... * * Also some routes may re-encode 8bit mail with * quoted-printable or base64 * */ if (0 != strcmp(h1->env_from, h2->env_from)) return 0; if (h1->from && h2->from) { if ( ! addr_is_same(h1->from,h2->from) ) return 0; } else if (h1->from || h2->from) return 0; if (h1->to && h2->to) { if ( ! addr_is_same(h1->to,h2->to) ) return 0; } else if (h1->to || h2->to) return 0; if (h1->cc && h2->cc) { if ( ! addr_is_same(h1->cc,h2->cc) ) return 0; } else if (h1->cc || h2->cc) return 0; if (0 != strcmp(h1->messageid, h2->messageid)) return 0; if (0 != string_cmp(h1->subject, h2->subject, 99)) return 0; /* FIXME: Mailing list headers are not currently supported */ if (h1->list_info || h2->list_info) return 0; if (0 != strcmp(h1->time_zone, h2->time_zone)) return 0; if (h1->time_sent != h2->time_sent) return 0; if (h1->tz_offset != h2->tz_offset) return 0; return 1; } static void update_header P_((struct header_rec * trg, struct header_rec *src)); static void update_header(trg,src) struct header_rec * trg; struct header_rec * src; { trg->status |= src->status; /* Not necessary correct */ trg->status1 |= src->status1; /* Not necessary correct */ /* May be used on sorting */ if (src->lines >= 0 && src->lines < trg->lines) trg->lines = src->lines; if (isoff(src->status,UNREAD)) clearit(trg->status,UNREAD); } /* Return 1 if redraw required */ S_(mt_update_view_mailbox mt_update_view_duplicate) /* Return 1 if redraw required */ static int mt_update_view_duplicate P_((struct MailboxView *mbx)); static int mt_update_view_duplicate(mbx) struct MailboxView *mbx; { struct MailboxView * Z; int hidden = 0; int r,i; int count = 0; if (mbx->u.duplicate->magic != MV_DUPLICATE_magic) panic("MBX VIEW PANIC",__FILE__,__LINE__,"mt_update_view_duplicate", "Bad magic number",0); Z = mbx->u.duplicate->parent_mailbox; r = update_view(Z); if (!r) { /* OPTIMIZE: Do not check is no changes on parent !! */ int c = get_message_count(Z); if (c && Z->view_len) { DPRINT(Debug,7,(&Debug, "mt_update_view_duplicate=0: parent len = %d, view len = %d\n", c,Z->view_len)); return 0; } } for (i = 0; i < Z->view_len; i++) { int z; struct header_rec *X = give_header(Z,i); if (X) { /* FIXME: Mailing list headers are not currently supported */ if (X->list_info) count++; else if (X->messageid[0]) { struct msg_id_data * I = give_message_id_data( & (mbx->u.duplicate->learn_ids), X->messageid ); struct instance_chain * C; for (C = I->chain; C; C = C->next) if ( cmp_headers_ok(C->mss,X)) break; if (!C) { r = 1; C = add_to_chain(mbx->u.duplicate,I); C->mss = copy_header(X,mbx->u.duplicate->collected_len); } update_header(C->mss,X); } else count++; } else count++; } count += mbx->u.duplicate->collected_len; if (r || count != mbx->view_len ) { mt_make_duplicate_view(mbx); DPRINT(Debug,7,(&Debug, "mt_update_view_duplicate=1 (view len=%d)\n", mbx->view_len)); return 1; } DPRINT(Debug,7,(&Debug, "mt_update_view_duplicate=0\n")); return 0; } S_(mt_get_main_mailbox_folder mt_get_main_duplicate_folder) static struct folder_info * mt_get_main_duplicate_folder P_((struct MailboxView *mbx)); static struct folder_info * mt_get_main_duplicate_folder(mbx) struct MailboxView *mbx; { if (mbx->u.duplicate->magic != MV_DUPLICATE_magic) panic("MBX VIEW PANIC",__FILE__,__LINE__, "mt_get_main_duplicate_folder", "Bad magic number",0); return get_main_folder(mbx->u.duplicate->parent_mailbox); } /* Can be called from signal handler */ S_(mt_get_mailbox_storage mt_get_duplicate_storage) /* Can be called from signal handler */ static struct current_storage * mt_get_duplicate_storage P_((struct MailboxView *mbx, int i)); /* Can be called from signal handler */ static struct current_storage * mt_get_duplicate_storage(mbx,i) struct MailboxView *mbx; int i; { if (mbx->u.duplicate->magic != MV_DUPLICATE_magic) panic("MBX VIEW PANIC",__FILE__,__LINE__, "mt_get_duplicate_storage", "Bad magic number",0); if (i == 0) return NULL; /* Not available */ /* Shift by one */ return get_storage(mbx->u.duplicate->parent_mailbox,i-1); } /* Can be called from signal handler */ S_(mt_get_mailbox_storage_count mt_get_duplicate_storage_count) /* Can be called from signal handler */ static int mt_get_duplicate_storage_count P_((struct MailboxView *mbx)); /* Can be called from signal handler */ static int mt_get_duplicate_storage_count(mbx) struct MailboxView *mbx; { if (mbx->u.duplicate->magic != MV_DUPLICATE_magic) panic("MBX VIEW PANIC",__FILE__,__LINE__, "mt_get_duplicate_storage_count", "Bad magic number",0); /* Storage number 0 is internal so add +1 */ return 1 + get_storage_count(mbx->u.duplicate->parent_mailbox); } S_(mt_give_header_mailbox mt_give_header_duplicate) static struct header_rec * mt_give_header_duplicate(mbx,index,v) struct MailboxView *mbx; int index; struct folder_view *v; { if (mbx->u.duplicate->magic != MV_DUPLICATE_magic) panic("MBX VIEW PANIC",__FILE__,__LINE__, "mt_give_header_duplicate", "Bad magic number",0); if (0 == v->mailbox_number) { /* Number 0 is internal */ int j; struct instance_chain *E; struct MailboxView *Z = mbx->u.duplicate->parent_mailbox; if (Z->mailbox_type->magic != MAILBOXTYPE_magic) panic("MBX VIEW PANIC",__FILE__,__LINE__, "mt_give_header_duplicate", "Bad type magic number",0); if (v->index < 0 || v->index >= mbx->u.duplicate->collected_len) return NULL; E = mbx->u.duplicate->collected[v->index]; if (MV_INSTANCE_magic != E->magic) panic("MBX VIEW PANIC",__FILE__,__LINE__, "mt_give_header_duplicate", "Bad magic number",0); /* FIXME -- is it better to return header struct just from instance chain ? */ for (j = 0; j < E->loc_len; j++) { struct header_rec * H = Z->mailbox_type->mt_give_header_it(Z,index, & (E->locs[j])); if (H) { /* Hack -- hide ! from status */ if (E->mss) E->mss->body_parsed = H->body_parsed; return H; } } return E->mss; } else { struct folder_view V; struct MailboxView *Z = mbx->u.duplicate->parent_mailbox; /* Shift by one */ V.mailbox_number = v->mailbox_number-1; V.index = v->index; if (Z->mailbox_type->magic != MAILBOXTYPE_magic) panic("MBX VIEW PANIC",__FILE__,__LINE__, "mt_give_header_duplicate", "Bad type magic number",0); return Z->mailbox_type->mt_give_header_it(Z,index, &V); } } struct duplicate_sort { struct MailboxView *parent_mailbox; struct instance_chain * duplicate_record; }; S_(sdt_give_header_s sdt_give_header_dup) static struct header_rec * sdt_give_header_dup P_((struct sort_data *s, struct folder_view *v)); static struct header_rec * sdt_give_header_dup(s,v) struct sort_data *s; struct folder_view *v; { if (0 == v->mailbox_number) { /* FIXME: not necessary correct .... */ return s->u.dup->duplicate_record->mss; } else { struct folder_view V; struct MailboxView *Z = s->u.dup->parent_mailbox; /* Shift by one */ V.mailbox_number = v->mailbox_number-1; V.index = v->index; if (Z->mailbox_type->magic != MAILBOXTYPE_magic) panic("MBX VIEW PANIC",__FILE__,__LINE__,"sdt_give_header_dup", "Bad type magic number",0); return Z->mailbox_type->mt_give_header_it(Z,-1, &V); } } static struct sort_data_type dup_sort = { SORTDATATYPE_magic, sdt_give_header_dup }; S_(mt_sort_mailbox_view mt_sort_duplicate_view) static void mt_sort_duplicate_view P_((struct MailboxView *mbx, hdr_compare_func *func)); static void mt_sort_duplicate_view(mbx,func) struct MailboxView *mbx; hdr_compare_func *func; { int i; struct sort_data * array; /* Little dirty ... */ typedef int (*compar) P_((const void *, const void *)); compar X = (compar) func; if (mbx->u.duplicate->magic != MV_DUPLICATE_magic) panic("MBX VIEW PANIC",__FILE__,__LINE__, "mt_sort_duplicate_view", "Bad magic number",0); array = safe_malloc(mbx->view_len * sizeof (array[0])); for (i = 0; i < mbx->view_len; i++) { int mbxnum = mbx->view[i].mailbox_number; array[i].w = mbx->view[i]; array[i].t = mbx->thread_view; /* For thread sorting */ array[i].sort_data_type = &dup_sort; array[i].u.dup = safe_malloc(sizeof (* array[i].u.dup)); array[i].u.dup->parent_mailbox = mbx->u.duplicate->parent_mailbox; array[i].u.dup->duplicate_record = NULL; if (0 == mbxnum) { int v = mbx->view[i].index; array[i].u.dup->duplicate_record = mbx->u.duplicate->collected[v]; } } qsort(array,mbx->view_len,sizeof (array[0]), X); for (i = 0; i < mbx->view_len; i++) { mbx->view[i] = array[i].w; free(array[i].u.dup); array[i].u.dup = NULL; } free(array); } S_(mt_give_message_data_mailbox mt_give_message_data_duplicate) static int mt_give_message_data_duplicate P_((struct MailboxView *mbx, 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_duplicate(mbx,index,ret_header,ret_F, counter,parse_mime,v) struct MailboxView *mbx; int index; struct header_rec **ret_header; FILE **ret_F; struct counter_data *counter; parse_mime_callback *parse_mime; struct folder_view *v; { if (mbx->u.duplicate->magic != MV_DUPLICATE_magic) panic("MBX VIEW PANIC",__FILE__,__LINE__, "mt_give_message_data_duplicate", "Bad magic number",0); if (0 == v->mailbox_number) { /* Number 0 is internal */ int j; struct instance_chain *E; struct MailboxView *Z = mbx->u.duplicate->parent_mailbox; if (Z->mailbox_type->magic != MAILBOXTYPE_magic) panic("MBX VIEW PANIC",__FILE__,__LINE__, "mt_give_header_duplicate", "Bad type magic number",0); if (v->index < 0 || v->index >= mbx->u.duplicate->collected_len) return 0; E = mbx->u.duplicate->collected[v->index]; if (MV_INSTANCE_magic != E->magic) panic("MBX VIEW PANIC",__FILE__,__LINE__, "mt_give_header_duplicate", "Bad magic number",0); /* We have better to return same header that is data */ for (j = 0; j < E->loc_len; j++) { if (Z->mailbox_type->mt_give_message_data_it(Z,index, ret_header,ret_F, counter,parse_mime, & (E->locs[j]))) { /* Hack -- hide ! from status */ if (E->mss && ret_header && *ret_header) E->mss->body_parsed = (*ret_header)->body_parsed; return 1; } } return 0; } else { struct folder_view V; struct MailboxView *Z = mbx->u.duplicate->parent_mailbox; /* Shift by one */ V.mailbox_number = v->mailbox_number-1; V.index = v->index; if (Z->mailbox_type->magic != MAILBOXTYPE_magic) panic("MBX VIEW PANIC",__FILE__,__LINE__, "mt_give_message_data_duplicate", "Bad type magic number",0); return Z->mailbox_type->mt_give_message_data_it(Z,index, ret_header,ret_F, counter,parse_mime, & V); } } S_(mt_write_mailbox_info mt_write_duplicate_info) static void mt_write_duplicate_info P_((FILE *fp, struct MailboxView *mbx, int s, int cur_idx)); static void mt_write_duplicate_info(fp,mbx,s,cur_idx) FILE *fp; struct MailboxView *mbx; int s; int cur_idx; { if (mbx->u.duplicate->magic != MV_DUPLICATE_magic) panic("MBX VIEW PANIC",__FILE__,__LINE__, "mt_write_duplicate_info", "Bad magic number",0); if (0 == s) { /* 0 is internal */ /* FIXME: -- is not supported */ } else { struct MailboxView *Z = mbx->u.duplicate->parent_mailbox; if (Z->mailbox_type->magic != MAILBOXTYPE_magic) panic("MBX VIEW PANIC",__FILE__,__LINE__, "mt_write_duplicate_info", "Bad type magic number",0); /* Shift by one */ Z->mailbox_type->mt_write_it_info(fp,Z,s-1,cur_idx); } } S_(mt_mailbox_title mt_duplicate_title) static struct string * mt_duplicate_title P_((struct MailboxView *mbx)); static struct string * mt_duplicate_title(mbx) struct MailboxView *mbx; { if (mbx->u.duplicate->magic != MV_DUPLICATE_magic) panic("MBX VIEW PANIC",__FILE__,__LINE__, "mt_duplicate_title", "Bad magic number",0); return mailbox_title(mbx->u.duplicate->parent_mailbox); } S_(mt_make_mailbox_view mt_make_duplicate_view) static void mt_make_duplicate_view (mbx) struct MailboxView *mbx; { struct MailboxView * Z; int count = 0; int i,x = 0; if (mbx->u.duplicate->magic != MV_DUPLICATE_magic) panic("MBX VIEW PANIC",__FILE__,__LINE__, "mt_make_duplicate_view", "Bad magic number",0); Z = mbx->u.duplicate->parent_mailbox; /* Remove old locations -- they will be recalculated on rediscovered */ for (i = 0; i < mbx->u.duplicate->collected_len; i++) { if (mbx->u.duplicate->collected[i]) { if (mbx->u.duplicate->collected[i]->locs) { free(mbx->u.duplicate->collected[i]->locs); mbx->u.duplicate->collected[i]->locs = 0; } mbx->u.duplicate->collected[i]->loc_len = 0; } } for (i = 0; i < Z->view_len; i++) { int z; struct header_rec *X = give_header(Z,i); if (X) { /* FIXME: Mailing list headers are not currently supported */ if (X->list_info) count++; else if (X->messageid[0]) { struct msg_id_data * I = give_message_id_data( & (mbx->u.duplicate->learn_ids), X->messageid ); struct instance_chain * C; for (C = I->chain; C; C = C->next) if ( cmp_headers_ok(C->mss,X)) break; if (!C) { C = add_to_chain(mbx->u.duplicate,I); C->mss = copy_header(X,mbx->u.duplicate->collected_len); } update_header(C->mss,X); C->locs = safe_realloc(C->locs, (C->loc_len +1 ) * sizeof (C->locs[0])); C->locs[C->loc_len] = Z->view[i]; C->loc_len++; } else count++; } else count++; } count += mbx->u.duplicate->collected_len; DPRINT(Debug,9,(&Debug, "mt_make_duplicate_view: count = %d, collected len = %d, parent view len = %d\n", count, mbx->u.duplicate->collected_len, Z->view_len)); if (count < 1) { if (mbx->view) free(mbx->view); mbx->view = NULL; mbx->view_len = 0; return; } mbx->view = safe_realloc(mbx->view, count * (sizeof ( mbx->view[0]))); for (i = 0, x = 0; i < Z->view_len; i++) { struct header_rec *X = give_header(Z,i); if (!X || X->list_info || ! X->messageid[0]) { struct folder_view Y; give_index_number(Z,i,&Y); Y.mailbox_number ++; /* Shift by one! */ if (x >= count) panic("MBX VIEW PANIC",__FILE__,__LINE__, "mt_make_duplicate_view", "overflow",0); mbx->view[x] = Y; x++; } } for (i = 0; i < mbx->u.duplicate->collected_len; i++) { struct instance_chain *E = mbx->u.duplicate->collected[i]; if (x >= count) panic("MBX VIEW PANIC",__FILE__,__LINE__, "mt_make_duplicate_view", "overflow",0); if (MV_INSTANCE_magic != E->magic) panic("MBX VIEW PANIC",__FILE__,__LINE__, "mt_make_duplicate_view", "Bad magic number",0); /* If exactly one mail, do not use duplicate record */ if (1 == E->loc_len) { struct folder_view Y = E->locs[0]; Y.mailbox_number ++; /* Shift by one! */ mbx->view[x] = Y; } else { zero_folder_view(& (mbx->view[x])); mbx->view[x].mailbox_number = 0; mbx->view[x].index = i; } x++; } mbx->view_len = x; } S_(mt_add_mailbox_digest mt_add_duplicate_digest) static void mt_add_duplicate_digest P_((struct MailboxView *mbx, mime_t *list, time_t received_time, char *env_from, FILE *F, charset_t defcharset)); static void mt_add_duplicate_digest(mbx, list, received_time, env_from, F, defcharset) struct MailboxView *mbx; mime_t *list; time_t received_time; char *env_from; FILE *F; charset_t defcharset; { if (mbx->u.duplicate->magic != MV_DUPLICATE_magic) panic("MBX VIEW PANIC",__FILE__,__LINE__, "mt_add_duplicate_digest", "Bad magic number",0); add_digest(mbx,list,received_time,env_from,F,defcharset); } static struct mailbox_type mt_duplicate = { MAILBOXTYPE_magic, mt_init_duplicate, mt_free_duplicate, mt_add_duplicate_storage, mt_update_view_duplicate, mt_get_main_duplicate_folder, mt_get_duplicate_storage, mt_get_duplicate_storage_count, mt_give_header_duplicate, mt_sort_duplicate_view, mt_give_message_data_duplicate, mt_write_duplicate_info, mt_duplicate_title, mt_make_duplicate_view, mt_add_duplicate_digest }; S_(mt_show_status_message mt_show_status_duplicate) static char * mt_show_status_duplicate P_((struct MailboxView *mailbox, int index, struct folder_view *v)); static char * mt_show_status_duplicate(mailbox,index,v) struct MailboxView *mailbox; int index; struct folder_view *v; { if (mailbox->u.duplicate->magic != MV_DUPLICATE_magic) panic("MBX VIEW PANIC",__FILE__,__LINE__, "mt_show_status_duplicate", "Bad magic number",0); if (0 == v->mailbox_number) { /* Number 0 is internal */ struct instance_chain *E; struct header_rec *hdr; if (v->index < 0 || v->index >= mailbox->u.duplicate->collected_len) return NULL; E = mailbox->u.duplicate->collected[v->index]; if (MV_INSTANCE_magic != E->magic) panic("MBX VIEW PANIC",__FILE__,__LINE__, "mt_show_status_duplicate", "Bad magic number",0); hdr = E->mss; if (!hdr) return NULL; return show_message_status(hdr); } else { struct folder_view V; struct MailboxView *Z = mailbox->u.duplicate->parent_mailbox; /* Shift by one */ V.mailbox_number = v->mailbox_number-1; V.index = v->index; if (Z->status_type->magic != STATUSTYPE_magic) panic("MBX VIEW PANIC",__FILE__,__LINE__, "mt_show_status_duplicate", "Bad type magic number",0); return Z->status_type->mt_show_status_it(Z,index,&V); } } S_(mt_ison_status_message mt_ison_status_duplicate) static int mt_ison_status_duplicate P_((struct MailboxView *mailbox, int index, struct folder_view *v, enum status_x t, int mask)); static int mt_ison_status_duplicate(mailbox,index,v,t,mask) struct MailboxView *mailbox; int index; struct folder_view *v; enum status_x t; int mask; { struct header_rec *hdr; int r = 0; if (mailbox->u.duplicate->magic != MV_DUPLICATE_magic) panic("MBX VIEW PANIC",__FILE__,__LINE__, "mt_ison_status_duplicate", "Bad magic number",0); if (0 == v->mailbox_number) { /* Number 0 is internal */ struct instance_chain *E; struct header_rec *hdr; if (v->index < 0 || v->index >= mailbox->u.duplicate->collected_len) return 0; E = mailbox->u.duplicate->collected[v->index]; if (MV_INSTANCE_magic != E->magic) panic("MBX VIEW PANIC",__FILE__,__LINE__, "mt_show_status_duplicate", "Bad magic number",0); hdr = E->mss; if (hdr) { switch (t) { case status_basic: r = ison(hdr->status,mask); break; case status_1: r = ison(hdr->status1,mask); break; default: panic("MBX VIEW PANIC",__FILE__,__LINE__, "mt_ison_status_duplicate", "bad status type",0); } } } else { struct folder_view V; struct MailboxView *Z = mailbox->u.duplicate->parent_mailbox; /* Shift by one */ V.mailbox_number = v->mailbox_number-1; V.index = v->index; if (Z->status_type->magic != STATUSTYPE_magic) panic("MBX VIEW PANIC",__FILE__,__LINE__, "mt_ison_status_duplicate", "Bad type magic number",0); r = Z->status_type->mt_ison_status_it(Z,index,&V,t,mask); } return r; } S_(mt_setf_status_message mt_setf_status_duplicate) static int mt_setf_status_duplicate P_((struct MailboxView *mailbox, int index, struct folder_view *v, enum status_x t, int mask)); static int mt_setf_status_duplicate(mailbox,index,v,t,mask) struct MailboxView *mailbox; int index; struct folder_view *v; enum status_x t; int mask; { struct header_rec *hdr; int r = 0; if (mailbox->u.duplicate->magic != MV_DUPLICATE_magic) panic("MBX VIEW PANIC",__FILE__,__LINE__, "mt_setf_status_duplicate", "Bad magic number",0); if (0 == v->mailbox_number) { /* Number 0 is internal */ struct instance_chain *E; struct header_rec *hdr; struct MailboxView *Z = mailbox->u.duplicate->parent_mailbox; int j; if (v->index < 0 || v->index >= mailbox->u.duplicate->collected_len) return 0; E = mailbox->u.duplicate->collected[v->index]; if (MV_INSTANCE_magic != E->magic) panic("MBX VIEW PANIC",__FILE__,__LINE__, "mt_setf_status_duplicate", "Bad magic number",0); hdr = E->mss; if (hdr) { switch (t) { case status_basic: setit(hdr->status,mask); r = hdr->status; break; case status_1: setit(hdr->status1,mask); r = hdr->status1; break; default: panic("MBX VIEW PANIC",__FILE__,__LINE__, "mt_setf_status_duplicate", "bad status type",0); } /* TODO: What status codes should cause flagging??? */ hdr->status_chgd = TRUE; } if (Z->status_type->magic != STATUSTYPE_magic) panic("MBX VIEW PANIC",__FILE__,__LINE__, "mt_setf_status_duplicate", "Bad type magic number",0); /* change status of all duplicates ... */ for (j = 0; j < E->loc_len; j++) { Z->status_type->mt_setf_status_it(Z,index,& (E->locs[j]), t,mask); } } else { struct folder_view V; struct MailboxView *Z = mailbox->u.duplicate->parent_mailbox; /* Shift by one */ V.mailbox_number = v->mailbox_number-1; V.index = v->index; if (Z->status_type->magic != STATUSTYPE_magic) panic("MBX VIEW PANIC",__FILE__,__LINE__, "mt_setf_status_duplicate", "Bad type magic number",0); r = Z->status_type->mt_setf_status_it(Z,index,&V,t,mask); } return r; } S_(mt_clearf_status_message mt_clearf_status_duplicate) static int mt_clearf_status_duplicate P_((struct MailboxView *mailbox, int index, struct folder_view *v, enum status_x t, int mask)); static int mt_clearf_status_duplicate(mailbox,index,v,t,mask) struct MailboxView *mailbox; int index; struct folder_view *v; enum status_x t; int mask; { struct header_rec *hdr; int r = 0; if (mailbox->u.duplicate->magic != MV_DUPLICATE_magic) panic("MBX VIEW PANIC",__FILE__,__LINE__, "mt_clearf_status_duplicate", "Bad magic number",0); if (0 == v->mailbox_number) { /* Number 0 is internal */ struct instance_chain *E; struct header_rec *hdr; struct MailboxView *Z = mailbox->u.duplicate->parent_mailbox; int j; if (v->index < 0 || v->index >= mailbox->u.duplicate->collected_len) return 0; E = mailbox->u.duplicate->collected[v->index]; if (MV_INSTANCE_magic != E->magic) panic("MBX VIEW PANIC",__FILE__,__LINE__, "mt_clearf_status_duplicate", "Bad magic number",0); hdr = E->mss; if (hdr) { switch (t) { case status_basic: clearit(hdr->status,mask); r = hdr->status; break; case status_1: clearit(hdr->status1,mask); r = hdr->status1; break; default: panic("MBX VIEW PANIC",__FILE__,__LINE__, "mt_clearf_status_duplicate", "bad status type",0); } /* TODO: What statuses should cause flagging??? */ hdr->status_chgd = TRUE; } if (Z->status_type->magic != STATUSTYPE_magic) panic("MBX VIEW PANIC",__FILE__,__LINE__, "mt_clearf_status_duplicate", "Bad type magic number",0); /* change status of all duplicates ... */ for (j = 0; j < E->loc_len; j++) { Z->status_type->mt_clearf_status_it(Z,index,& (E->locs[j]), t,mask); } } else { struct folder_view V; struct MailboxView *Z = mailbox->u.duplicate->parent_mailbox; /* Shift by one */ V.mailbox_number = v->mailbox_number-1; V.index = v->index; if (Z->status_type->magic != STATUSTYPE_magic) panic("MBX VIEW PANIC",__FILE__,__LINE__, "mt_clearf_status_duplicate", "Bad type magic number",0); r = Z->status_type->mt_clearf_status_it(Z,index,&V,t,mask); } return r; } static struct status_type status_duplicate = { STATUSTYPE_magic, mt_show_status_duplicate, mt_ison_status_duplicate, mt_setf_status_duplicate, mt_clearf_status_duplicate }; struct MailboxView * duplicate_to_mailbox_view (parent) struct MailboxView * parent; { struct MailboxView *ret = malloc_view(&mt_duplicate); if (parent->magic != MAILBOXVIEW_magic) panic("MBX VIEW PANIC",__FILE__,__LINE__,"duplicate_to_mailbox_view", "Bad magic number",0); if (parent->mailbox_type->magic != MAILBOXTYPE_magic) panic("MBX VIEW PANIC",__FILE__,__LINE__,"duplicate_to_mailbox_view", "Bad type magic number",0); /* Override default status handling */ ret->status_type = &status_duplicate; ret->u.duplicate->parent_mailbox = parent; 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: */