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 <hurtta+elm@posti.FMI.FI>
* or Kari Hurtta <elm@elmme-mailer.org>
*****************************************************************************/
#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:
*/
syntax highlighted by Code2HTML, v. 0.9.1