static char rcsid[] = "@(#)$Id: partial.c,v 1.22 2006/05/07 08:35:31 hurtta Exp $";
/******************************************************************************
* The Elm (ME+) Mail System - $Revision: 1.22 $ $State: Exp $
*
* Author: Kari Hurtta <hurtta+elm@posti.FMI.FI> (was hurtta+elm@ozone.FMI.FI)
*****************************************************************************/
#include "def_messages.h"
#include "s_me.h"
DEBUG_VAR(Debug,__FILE__,"messages");
struct mv_partial {
struct MailboxView * parent_mailbox;
struct composite_vector * composite;
int composite_len;
FILE *F;
char *fname;
};
#if ANSI_C
#define S_(x) static x;
#else
#define S_(x)
#endif
S_(mt_init_mailbox mt_init_partial)
static void mt_init_partial P_((struct MailboxView *mbx));
static void mt_init_partial(mbx)
struct MailboxView *mbx;
{
mbx->u.partial = safe_malloc(sizeof (* (mbx->u.partial)));
/* bzero is defined hdrs/defs.h */
bzero((void *)mbx->u.partial, sizeof (* (mbx->u.partial)));
mbx->u.partial->parent_mailbox = NULL;
mbx->u.partial->composite = NULL;
mbx->u.partial->composite_len = 0;
mbx->u.partial->F = NULL;
mbx->u.partial->fname = NULL;
}
struct composite_vector {
char * id;
int total;
struct header_rec *mss;
struct folder_view * locate_ids ;
int locate_id_count ;
};
static struct header_rec * mt_give_header_partial P_((struct MailboxView
*mailbox,
int index,
struct folder_view *v));
S_(mt_free_mailbox mt_free_partial)
static void mt_free_partial P_((struct MailboxView *mbx));
static void mt_free_partial(mbx)
struct MailboxView *mbx;
{
if (mbx->u.partial->composite) {
int i;
for (i = 0; i < mbx->u.partial->composite_len; i++) {
struct header_rec *X = mbx->u.partial->composite[i].mss;
/* MARK deleted on parent also deleted */
if (X && ison(X->status,DELETED)) {
int j;
for (j = 0;
j < mbx->u.partial->composite[i].locate_id_count;
j++) {
/* locate_ids are shifted so that 0 is our
composite mailbox
*/
struct header_rec * H =
mt_give_header_partial(mbx,-1,
&
mbx->u.partial->composite[i].
locate_ids[j] );
if (H)
setit(H->status,DELETED);
}
}
}
for (i = 0; i < mbx->u.partial->composite_len; i++) {
if (mbx->u.partial->composite[i].mss) {
header_free( & (mbx->u.partial->composite[i].mss));
}
if (mbx->u.partial->composite[i].id) {
free(mbx->u.partial->composite[i].id);
mbx->u.partial->composite[i].id = NULL;
}
if (mbx->u.partial->composite[i].locate_ids) {
free (mbx->u.partial->composite[i].locate_ids);
mbx->u.partial->composite[i].locate_ids = NULL;
}
mbx->u.partial->composite[i].locate_id_count = 0;
}
free(mbx->u.partial->composite);
mbx->u.partial->composite = NULL;
}
mbx->u.partial->composite_len = 0;
if (mbx->u.partial->F) {
fclose(mbx->u.partial->F);
mbx->u.partial->F = NULL;
}
if (mbx->u.partial->fname) {
if (0 == unlink(mbx->u.partial->fname)) {
DPRINT(Debug,7,(&Debug,"%s unlinked\n",
mbx->u.partial->fname));
}
free(mbx->u.partial->fname);
mbx->u.partial->fname = NULL;
}
free(mbx->u.partial);
mbx->u.partial = NULL;
}
S_(mt_add_mailbox_storage mt_add_partial_storage)
static void mt_add_partial_storage P_((struct MailboxView *mailbox,
struct current_storage *storage));
static void mt_add_partial_storage(mailbox,storage)
struct MailboxView *mailbox;
struct current_storage *storage;
{
add_storage(mailbox->u.partial->parent_mailbox,storage);
}
static void mt_make_partial_view P_((struct MailboxView *mailbox));
/* Return 1 if redraw required */
S_(mt_update_view_mailbox mt_update_view_partial)
/* Return 1 if redraw required */
static int mt_update_view_partial P_((struct MailboxView *mailbox));
static int mt_update_view_partial(mailbox)
struct MailboxView *mailbox;
{
struct MailboxView * Z = mailbox->u.partial->parent_mailbox;
int count,i;
int r = update_view(Z);
int hidden = 0;
/* check what parts need NOT be included ... */
for (i = 0; i < Z->view_len; i++) {
struct header_rec *X = give_header(Z,i);
if (X) {
if (X->partial_len)
hidden++;
else if ((X->status & MIME_MESSAGE) &&
(get_type_flags(X->mime_rec.TYPE) & MIME_PARTIAL)) {
/* Try register partial ... */
if (reg_partial(X, & ((X->mime_rec)))) {
DPRINT(Debug,7,(&Debug,
"mt_update_view_partial: Found new fragment\n"));
hidden++;
r = 1;
}
}
}
}
/* check collect messages also for partial */
for (i = 0; i < mailbox->u.partial->composite_len; i++) {
struct header_rec *X = mailbox->u.partial->composite[i].mss;
if (X) {
if (X->partial_len)
hidden++;
else if ((X->status & MIME_MESSAGE) && X->mime_rec.mime_flags &&
(get_type_flags(X->mime_rec.TYPE) & MIME_PARTIAL)) {
/* Try register partial ... */
if (reg_partial(X, & ((X->mime_rec)))) {
DPRINT(Debug,7,(&Debug,
"mt_update_view_partial: Found new fragment from reassembed message\n"));
hidden++;
r = 1;
}
}
}
}
DPRINT(Debug,7,(&Debug,
"mt_update_view_partial: %d parts hidden\n",hidden));
count = Z->view_len + mailbox->u.partial->composite_len - hidden;
if (r || count != mailbox->view_len) {
mt_make_partial_view(mailbox);
DPRINT(Debug,7,(&Debug,
"mt_update_view_partial=1 (view len=%d)\n",
mailbox->view_len));
return 1;
}
DPRINT(Debug,7,(&Debug,
"mt_update_view_partial=0\n"));
return 0;
}
S_(mt_get_main_mailbox_folder mt_get_main_partial_folder)
static struct folder_info * mt_get_main_partial_folder P_((struct MailboxView *mailbox));
static struct folder_info * mt_get_main_partial_folder(mailbox)
struct MailboxView *mailbox;
{
return get_main_folder(mailbox->u.partial->parent_mailbox);
}
/* Can be called from signal handler */
S_(mt_get_mailbox_storage mt_get_partial_storage)
/* Can be called from signal handler */
static struct current_storage * mt_get_partial_storage P_((struct MailboxView *mailbox,
int i));
/* Can be called from signal handler */
static struct current_storage * mt_get_partial_storage(mailbox,i)
struct MailboxView *mailbox;
int i;
{
if (i == 0)
return NULL; /* Not available */
/* Shift by one */
return get_storage(mailbox->u.partial->parent_mailbox,i-1);
}
/* Can be called from signal handler */
S_(mt_get_mailbox_storage_count mt_get_partial_storage_count)
/* Can be called from signal handler */
static int mt_get_partial_storage_count P_((struct MailboxView *mailbox));
/* Can be called from signal handler */
static int mt_get_partial_storage_count(mailbox)
struct MailboxView *mailbox;
{
/* Storage number 0 is internal so add +1 */
return 1 + get_storage_count(mailbox->u.partial->parent_mailbox);
}
static void generate_mail_header P_((struct MailboxView *mailbox,
int composite_index));
S_(mt_give_header_mailbox mt_give_header_partial)
static struct header_rec * mt_give_header_partial(mailbox,index,v)
struct MailboxView *mailbox;
int index;
struct folder_view *v;
{
if (0 == v->mailbox_number) { /* Number 0 is internal */
if (v->index < 0 || v->index >= mailbox->u.partial->composite_len)
return NULL;
if (! mailbox->u.partial->composite[v->index].mss)
generate_mail_header(mailbox,v->index);
return mailbox->u.partial->composite[v->index].mss;
} else {
struct folder_view V;
struct MailboxView *Z = mailbox->u.partial->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_partial",
"Bad type magic number",0);
return Z->mailbox_type->mt_give_header_it(Z,index, &V);
}
}
struct partial_sort {
struct MailboxView *parent_mailbox;
struct composite_vector *composite_record;
};
S_(sdt_give_header_s sdt_give_header_part)
static struct header_rec * sdt_give_header_part P_((struct sort_data *s,
struct folder_view *v));
static struct header_rec * sdt_give_header_part(s,v)
struct sort_data *s;
struct folder_view *v;
{
if (0 == v->mailbox_number) {
return s->u.part->composite_record->mss;
} else {
struct folder_view V;
struct MailboxView *Z = s->u.part->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_part",
"Bad type magic number",0);
return Z->mailbox_type->mt_give_header_it(Z,-1, &V);
}
}
static struct sort_data_type part_sort = {
SORTDATATYPE_magic,
sdt_give_header_part
};
S_(mt_sort_mailbox_view mt_sort_partial_view)
static void mt_sort_partial_view P_((struct MailboxView *mailbox,
hdr_compare_func *func));
static void mt_sort_partial_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 = &part_sort;
array[i].u.part = safe_malloc(sizeof (* array[i].u.part));
array[i].u.part->parent_mailbox = mailbox->u.partial->parent_mailbox;
array[i].u.part->composite_record = NULL;
if (0 == mbx) {
int v = mailbox->view[i].index;
array[i].u.part->composite_record =
& mailbox->u.partial->composite[v];
}
}
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[i].u.part);
array[i].u.part = NULL;
}
free(array);
}
static void generate_mail_data P_((struct MailboxView *mailbox,
int composite_index));
S_(mt_give_message_data_mailbox mt_give_message_data_partial)
static int mt_give_message_data_partial 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_partial(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;
{
if (0 == v->mailbox_number) { /* Number 0 is internal */
if (v->index < 0 || v->index >= mailbox->u.partial->composite_len)
return 0;
if (! mailbox->u.partial->composite[v->index].mss ||
mailbox->u.partial->composite[v->index].mss->offset == -1L)
generate_mail_data(mailbox,v->index);
if (! mailbox->u.partial->composite[v->index].mss ||
mailbox->u.partial->composite[v->index].mss->offset == -1L ||
! mailbox->u.partial->F)
return 0;
if (ret_header)
*ret_header = mailbox->u.partial->composite[v->index].mss;
if (ret_F)
*ret_F = mailbox->u.partial->F;
/* Simulate prepare_message_access */
if (! mailbox->u.partial->composite[v->index].mss->mime_parsed &&
parse_mime == NO_mime_parse) {
DPRINT(Debug,10,(&Debug,
"mt_give_message_data_partial: mime structure not needed\n"));
} else if (! mailbox->u.partial->composite[v->index].mss->
mime_parsed) {
int status;
struct header_rec *entry =
mailbox->u.partial->composite[v->index].mss;
DPRINT(Debug,10,(&Debug,
"mt_give_message_data_partial: Need parsing of mime structure (offset %ld)\n",
entry->offset
));
if (0 != fseek(mailbox->u.partial->F,
entry->offset,
SEEK_SET)) {
DPRINT(Debug,10,(&Debug,
"mt_give_message_data_partial: seek to %ld failed\n",
mailbox->u.partial->composite[v->index].mss->offset));
return 0;
}
status = parse_mime(NULL,entry,mailbox->u.partial->F);
if (status <= 0) {
DPRINT(Debug,10,(&Debug,
"mt_give_message_data_partial: parse_mime callback failed (%d)\n",
status));
}
}
if (0 != fseek(mailbox->u.partial->F,
mailbox->u.partial->composite[v->index].mss->offset,
SEEK_SET)) {
DPRINT(Debug,10,(&Debug,
"mt_give_message_data_partial: seek to %ld failed\n",
mailbox->u.partial->composite[v->index].mss->offset));
return 0;
}
return 1;
} else {
struct folder_view V;
struct MailboxView *Z = mailbox->u.partial->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_partial",
"Bad type magic number",0);
return Z->mailbox_type->mt_give_message_data_it(Z,index,
ret_header,ret_F,
counter,parse_mime,
& V);
}
}
static int check_tempfile P_((struct MailboxView *mailbox));
static int check_tempfile(mailbox)
struct MailboxView *mailbox;
{
if (!mailbox->u.partial->F) {
if (!mailbox->u.partial->fname) {
static int un = 1;
char *tmp;
tmp = give_dt_estr_as_str(&temp_dir_e,"tmpdir");
if (!tmp)
tmp = "/tmp/";
mailbox->u.partial->fname = elm_message(FRM("%selmpartial-%d-%d"),
tmp, getpid (), un++);
DPRINT(Debug,9,(&Debug,
"check_tempfile: temporary folder name is %s\n",
mailbox->u.partial->fname));
}
mailbox->u.partial->F = safeopen_rdwr(mailbox->u.partial->fname);
if (! mailbox->u.partial->F) {
DPRINT(Debug,9,(&Debug,
"check_tempfile: Can't create temporary folder %s\n",
mailbox->u.partial->fname));
lib_error(CATGETS(elm_msg_cat, MeSet, MeDecodeFailedCreate,
"Failed to create file for decoding."));
free(mailbox->u.partial->fname);
mailbox->u.partial->fname = NULL;
return 0;
}
DPRINT(Debug,9,(&Debug,
"check_tempfile: temporary folder %s created\n",
mailbox->u.partial->fname));
}
return 1;
}
S_(mt_write_mailbox_info mt_write_partial_info)
static void mt_write_partial_info P_((FILE *fp, struct MailboxView *mailbox,
int s, int cur_idx));
static void mt_write_partial_info(fp,mailbox,s,cur_idx)
FILE *fp;
struct MailboxView *mailbox;
int s;
int cur_idx;
{
if (0 == s) { /* 0 is internal */
int i;
if (!check_tempfile(mailbox))
return;
/* write out the pathname of the folder */
fprintf(fp,"F%s\n",
mailbox->u.partial->fname);
/* write out the folder size and message indices */
fprintf(fp, "N%d\n", mailbox->u.partial->composite_len);
for (i = 0; i < mailbox->u.partial->composite_len; ++i) {
if (! mailbox->u.partial->composite[i].mss ||
-1 == mailbox->u.partial->composite[i].mss->offset) {
/* Try build tagged messages */
if (mailbox->u.partial->composite[i].mss &&
(mailbox->u.partial->composite[i].mss->status & TAGGED) ||
cur_idx == i)
generate_mail_data(mailbox,i);
}
if (! mailbox->u.partial->composite[i].mss ||
-1 == mailbox->u.partial->composite[i].mss->offset)
fprintf(fp, "I*\n");
else
fprintf(fp, "I%ld\n",mailbox->u.partial->composite[i].mss->offset);
}
} else {
struct MailboxView *Z = mailbox->u.partial->parent_mailbox;
if (Z->mailbox_type->magic != MAILBOXTYPE_magic)
panic("MBX VIEW PANIC",__FILE__,__LINE__,
"mt_write_partial_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_partial_title)
static struct string * mt_partial_title P_((struct MailboxView *mailbox));
static struct string * mt_partial_title(mailbox)
struct MailboxView *mailbox;
{
return mailbox_title(mailbox->u.partial->parent_mailbox);
}
static void add_record P_((struct MailboxView *mailbox, struct folder_view *id,
struct partial_vector *part));
static void add_record (mailbox,id, part)
struct MailboxView *mailbox;
struct folder_view *id;
struct partial_vector *part;
{
int i,j;
for (i = 0; i < mailbox->u.partial->composite_len; i++) {
if (0 == strcmp(mailbox->u.partial->composite[i].id,
part->id))
break; /* FOUND */
}
if (i >= mailbox->u.partial->composite_len) {
i = mailbox->u.partial->composite_len;
/* Add new record */
mailbox->u.partial->composite =
safe_realloc(mailbox->u.partial->composite,
(i+1) * sizeof (mailbox->u.partial->composite[0]));
mailbox->u.partial->composite[i].id = safe_strdup(part->id);
mailbox->u.partial->composite[i].total = part->total;
mailbox->u.partial->composite[i].mss = NULL;
mailbox->u.partial->composite[i].locate_ids = NULL;
mailbox->u.partial->composite[i].locate_id_count = 0;
DPRINT(Debug,9,(&Debug,
"add_record: Added new partial message %s\n",
mailbox->u.partial->composite[i].id));
mailbox->u.partial->composite_len++;
}
/* Check if already added */
for (j = 0; j < mailbox->u.partial->composite[i].locate_id_count; j++) {
if (mailbox->u.partial->composite[i].locate_ids[j].mailbox_number
== id->mailbox_number &&
mailbox->u.partial->composite[i].locate_ids[j].index == id->index)
return; /* Already added */
}
j = mailbox->u.partial->composite[i].locate_id_count;
mailbox->u.partial->composite[i].locate_ids =
safe_realloc(mailbox->u.partial->composite[i].locate_ids,
(j+1) * sizeof (mailbox->u.partial->composite[i].
locate_ids[0]));
mailbox->u.partial->composite[i].locate_ids[j] = *id;
DPRINT(Debug,9,(&Debug,
"add_record: Part %d/%d of message %s is on message %d%d\n",
part->number,part->total,
part->id,
id->mailbox_number,id->index));
mailbox->u.partial->composite[i].locate_id_count++;
}
S_(mt_make_mailbox_view mt_make_partial_view)
static void mt_make_partial_view (mailbox)
struct MailboxView *mailbox;
{
struct MailboxView * Z = mailbox->u.partial->parent_mailbox;
int count = 0;
int i,x;
/* Remove old locations -- they will be recalculated on
rediscovered
*/
for (i = 0; i < mailbox->u.partial->composite_len; i++) {
if (mailbox->u.partial->composite[i].locate_ids) {
free(mailbox->u.partial->composite[i].locate_ids);
mailbox->u.partial->composite[i].locate_ids = NULL;
}
mailbox->u.partial->composite[i].locate_id_count = 0;
}
for (i = 0; i < Z->view_len; i++) {
int z;
struct header_rec *X = give_header(Z,i);
if (X && X->partial_len) {
struct folder_view id;
int j;
give_index_number(Z,i,&id);
/* Shift by one */
id.mailbox_number++;
for (j = 0; j < X->partial_len; j++)
add_record(mailbox,&id,& (X->partial_vector[j]));
}
else
count++;
}
for (i = 0; i < mailbox->u.partial->composite_len; i++) {
struct header_rec *X = mailbox->u.partial->composite[i].mss;
if (X && X->partial_len) {
struct folder_view id;
int j;
id.mailbox_number = 0;
id.index = i;
/* NOTE: This add_record() may increment
mailbox->u.partial->composite_len
*/
for (j = 0; j < X->partial_len; j++)
add_record(mailbox,&id,& (X->partial_vector[j]));
}
else
count++;
}
DPRINT(Debug,9,(&Debug,
"mt_make_partial_view: count = %d, composite_len = %d, parent view len = %d\n",
count, mailbox->u.partial->composite_len,Z->view_len));
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 < Z->view_len; i++) {
struct header_rec *X = give_header(Z,i);
if (!X || ! X->partial_len) {
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_partial_view",
"overflow",0);
mailbox->view[x] = Y;
x++;
}
}
for (i = 0; i < mailbox->u.partial->composite_len; i++) {
struct header_rec *X = mailbox->u.partial->composite[i].mss;
if (!X || !X->partial_len) {
if (x >= count)
panic("MBX VIEW PANIC",__FILE__,__LINE__,
"mt_make_partial_view",
"overflow",0);
zero_folder_view(& (mailbox->view[x]));
mailbox->view[x].mailbox_number = 0;
mailbox->view[x].index = i;
x++;
}
}
mailbox->view_len = x;
}
S_(mt_add_mailbox_digest mt_add_partial_digest)
static void mt_add_partial_digest P_((struct MailboxView *mailbox,
mime_t *list,
time_t received_time,
char *env_from,
FILE *F,
charset_t defcharset));
static void mt_add_partial_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;
{
add_digest(mailbox,list,received_time,env_from,F,defcharset);
}
struct mailbox_type mt_partial = {
MAILBOXTYPE_magic,
mt_init_partial,
mt_free_partial,
mt_add_partial_storage,
mt_update_view_partial,
mt_get_main_partial_folder,
mt_get_partial_storage,
mt_get_partial_storage_count,
mt_give_header_partial,
mt_sort_partial_view,
mt_give_message_data_partial,
mt_write_partial_info,
mt_partial_title,
mt_make_partial_view,
mt_add_partial_digest
};
static struct info_rec {
FILE * F;
struct header_rec * hdr;
struct partial_vector * p;
} * build_info_vector P_((struct MailboxView *mailbox,
int composite_index,
int *vector_len));
static struct info_rec * build_info_vector(mailbox,composite_index,
vector_len)
struct MailboxView *mailbox;
int composite_index;
int *vector_len;
{
struct MailboxView * par = mailbox->u.partial->parent_mailbox;
struct info_rec * ret = NULL;
int i = 0;
int k;
struct composite_vector * Z =
& mailbox->u.partial->composite[composite_index];
int alloced = Z->locate_id_count;
if (!alloced) {
DPRINT(Debug,9,(&Debug,
"build_info_vector: No ids on %d ??? \n",
composite_index));
*vector_len = 0;
return NULL;
}
ret = safe_malloc(alloced * sizeof(ret[0]));
for (k = 0; k < Z->locate_id_count; k++) {
struct folder_view res = Z->locate_ids[k];
struct composite_vector *n1;
if (res.mailbox_number != 0) {
FILE *F;
struct header_rec *hdr;
int n;
res.mailbox_number--; /* Shift by one */
if (! par->mailbox_type->mt_give_message_data_it(par,-1,
&hdr,&F,NULL,
NO_mime_parse,
&res)) {
DPRINT(Debug,9,(&Debug,
"build_info_vector: [%d, %s] Message headers (%d/%d) or data not available on parent mailbox\n",
k,Z->id,
res.mailbox_number,res.index));
continue;
}
for (n = 0; n < hdr->partial_len; n++) {
if (0 == strcmp(hdr->partial_vector[n].id, Z->id)) {
struct partial_vector * p = & hdr->partial_vector[n];
if (alloced <= i) {
alloced = i+1;
ret = safe_realloc(ret,alloced * sizeof(ret[0]));
}
ret[i].F = F;
ret[i].p = p;
ret[i].hdr = hdr;
i++;
}
}
} else if (res.index >= 0 &&
res.index < mailbox->u.partial->composite_len) {
struct header_rec *hdr =
mailbox->u.partial->composite[res.index].mss;
int n;
if (!hdr) {
DPRINT(Debug,9,(&Debug,
"build_info_vector: [%d, %s] Message %d headers not availabel on composite list ???\n",
k,Z->id,
Z->locate_ids[k].index));
continue;
}
if (-1 == hdr->offset || !mailbox->u.partial->F) {
DPRINT(Debug,9,(&Debug,
"build_info_vector: [%d, %s] Message %s data not available (on composite list)??\n",
k,Z->id,
Z->locate_ids[k]));
continue;
}
for (n = 0; n < hdr->partial_len; n++) {
if (0 == strcmp(hdr->partial_vector[n].id, Z->id)) {
struct partial_vector * p = & hdr->partial_vector[n];
if (alloced <= i) {
alloced = i+1;
ret = safe_realloc(ret,alloced * sizeof(ret[0]));
}
ret[i].F = mailbox->u.partial->F;
ret[i].p = p;
ret[i].hdr = hdr;
i++;
}
}
}
}
if (i > Z->locate_id_count) {
DPRINT(Debug,9,(&Debug,
"build_info_vector: [%s] Collected %d when %d expeced??\n",
Z->id,i,Z->locate_id_count));
}
*vector_len = i;
return ret;
}
static int generate_1 P_((struct MailboxView *mailbox, int composite_index,
struct info_rec * vec, int len));
static int generate_1(mailbox,composite_index,vec,len)
struct MailboxView *mailbox;
int composite_index;
struct info_rec * vec;
int len;
{
int i;
struct header_rec *h;
for (i = 0; i < len; i++)
if (1 == vec[i].p->number)
break;
if (i >= len) {
DPRINT(Debug,9,(&Debug,
"generate_1: First part of message %s is not arrived\n",
mailbox->u.partial->composite[composite_index].id));
return i; /* First part is not arrived */
}
if (! mailbox->u.partial->composite[composite_index].mss) {
h = safe_malloc(sizeof (*h));
header_zero(h);
mailbox->u.partial->composite[composite_index].mss = h;
} else
h = mailbox->u.partial->composite[composite_index].mss;
h->offset = -1L; /* Mark that message is not yet collected */
strfcpy(h->env_from,vec[i].hdr->env_from,sizeof h->env_from);
h->header_charset = vec[i].hdr->header_charset;
h->received_time = vec[i].hdr->received_time;
h->content_length = -1; /* not found yet */
h->lines = -1; /* UNKNOWN */
return i;
}
static void generate_mail_header(mailbox,composite_index)
struct MailboxView *mailbox;
int composite_index;
{
int len,i;
struct info_rec * vec = build_info_vector(mailbox,composite_index,&len);
struct header_rec *h;
header_list_ptr parsed_headers = NULL;
if (!vec)
return;
i = generate_1(mailbox,composite_index,vec,len);
h = mailbox->u.partial->composite[composite_index].mss;
if (!h)
goto fail;
/* Assume that first message fragment part includes full headers */
if (0 != fseek(vec[i].F,vec[i].p->reference->offset,SEEK_SET)) {
DPRINT(Debug,3,(&Debug,
"generate_mail_header: seek to %ld failed\n",
h->offset));
goto fail;
}
parsed_headers = file_read_headers(vec[i].F,0);
read_folder_headers_helper(h,parsed_headers);
header_parse_helper(h,parsed_headers);
delete_headers(&parsed_headers);
fail:
free(vec);
}
static void generate_mail_data(mailbox,composite_index)
struct MailboxView *mailbox;
int composite_index;
{
int len,i;
int total_count = -1;
int header_not_full = 0;
int *v1 = NULL;
char * buffer1;
struct header_rec *h;
long written = 0;
int warn = 0;
long content_start;
header_list_ptr parsed_headers = NULL;
struct info_rec * vec = build_info_vector(mailbox,composite_index,&len);
if (!vec)
return;
if (! mailbox->u.partial->composite[composite_index].mss) {
generate_1(mailbox,composite_index,vec,len);
header_not_full++; /* NOT parsed yet */
}
h = mailbox->u.partial->composite[composite_index].mss;
if (!h)
goto fail;
/* read_mailcaps() parses mailcaps only once */
read_mailcaps();
for (i = 0; i < len; i++) {
if (total_count < vec[i].p->total)
total_count = vec[i].p->total;
if (h->received_time < vec[i].hdr->received_time)
h->received_time = vec[i].hdr->received_time;
if (!vec[i].hdr->mime_parsed) {
/* Copy value */
if (vec[i].hdr -> content_length >= 0)
vec[i].hdr->mime_rec.length = vec[i].hdr -> content_length;
if (vec[i].hdr->mime_rec.begin_offset <= 0)
vec[i].hdr->mime_rec.begin_offset =
skip_envelope(vec[i].hdr,vec[i].F);
if (mime_parser_parse(&(vec[i].hdr->mime_rec),
vec[i].hdr->header_charset,vec[i].F,
&(vec[i].hdr->header_error))) {
int tmp = mime_classify_media(&(vec[i].hdr->mime_rec),
vec[i].hdr
);
if (tmp >= 0) {
vec[i].hdr->mime_parsed = 1;
}
}
}
if (0 != strcmp(vec[i].hdr->env_from,
vec[0].hdr->env_from)) {
if (!warn)
lib_error(CATGETS(elm_msg_cat, MeSet, MeFragmentedSender,
"Fragmented message have several different sender addresses"));
warn = 1;
DPRINT(Debug,9,(&Debug,
"generate_mail_data: envelope sender %s <-> %s\n",
vec[i].hdr->env_from,
vec[0].hdr->env_from));
}
}
if (-1 == total_count) {
DPRINT(Debug,9,(&Debug,
"generate_mail_data: number of fragments of message %s is not known\n",
mailbox->u.partial->composite[composite_index].id));
goto fail;
}
if (total_count < 1) {
DPRINT(Debug,9,(&Debug,
"generate_mail_data: Imposible total count %d on %s\n",
total_count,
mailbox->u.partial->composite[composite_index].id));
goto fail;
}
/* Check that all parts are arrived */
v1 = malloc(total_count * sizeof (v1[0]));
for (i = 0; i < total_count; i++) {
v1[i] = -1;
}
for (i = 0; i < total_count; i++) {
int j;
for (j = 0; j < len; j++) {
if (i+1 == vec[j].p->number) {
if (-1 != v1[i]) {
DPRINT(Debug,9,(&Debug,
"generate_mail_data: Part %d on message %s is several times\n" ,
i+1,
mailbox->u.partial->composite[composite_index].id));
goto fail;
}
v1[i] = j;
}
}
}
for (i = 0; i < total_count; i++) {
int j;
if (-1 == v1[i]) {
DPRINT(Debug,9,(&Debug,
"generate_mail_data: Part %d on message %s is missed\n" ,
i+1,
mailbox->u.partial->composite[composite_index].id));
goto fail;
}
j = v1[i];
if (-1 == vec[j].p->reference->offset ||
-1 == vec[j].p->reference->length) {
DPRINT(Debug,9,(&Debug,
"generate_mail_data: Part %d (on message %s) starting offset (%ld) or length (%ld) is mising\n" ,
i+1,
mailbox->u.partial->composite[composite_index].id,
vec[j].p->reference->offset,
vec[j].p->reference->length));
goto fail;
}
}
if (!check_tempfile(mailbox))
goto fail;
if (0 != fseek(mailbox->u.partial->F,0,SEEK_END)) {
DPRINT(Debug,9,(&Debug,
"generate_mail_data: Seek failure on %s\n",
mailbox->u.partial->fname));
goto fail;
}
h->offset = ftell(mailbox->u.partial->F);
buffer1 = ctime(& h->received_time);
fprintf(mailbox->u.partial->F,"From %s %.24s\n",
h->env_from,buffer1);
h->mime_rec.begin_offset = ftell(mailbox->u.partial->F);
/* MIME says: (RFC 2046)
(2) All of the header fields from the initial enclosing
message, except those that start with "Content-" and
the specific header fields "Subject", "Message-ID",
"Encrypted", and "MIME-Version", must be copied, in
order, to the new message.
(3) The header fields in the enclosed message which start
with "Content-", plus the "Subject", "Message-ID",
"Encrypted", and "MIME-Version" fields, must be
appended, in order, to the header fields of the new
message. Any header fields in the enclosed message
which do not start with "Content-" (except for the
"Subject", "Message-ID", "Encrypted", and "MIME-
Version" fields) will be ignored and dropped.
HOWEVER
for now we copy only Received: -headers. Dropping
extra headers from enclosed message makes assembly more
complicated (and dropping of Received: -headers
from enclosed message do not make sense.)
*/
/* Copy some headers from part 1 */
if (skip_envelope(vec[v1[0]].hdr, vec[v1[0]].F) != -1) {
header_list_ptr all_headers = file_read_headers(vec[v1[0]].F,
RHL_CHECK_HEADER|RHL_MARK_FOLDING);
header_list_ptr next_hdr;
for (next_hdr = all_headers;
next_hdr;
next_hdr = next_hdr -> next_header) {
CONST char * hdr_name = give_header_name(next_hdr->header_name);
if (0 == istrcmp(hdr_name,"Received")) {
out_state_t state;
out_state_clear(&state,STATE_out_file);
set_out_state_file(mailbox->u.partial->F,&state);
state.EOLN_is_CRLF = vec[v1[0]].hdr->binary;
state_write_header(&state,next_hdr,0,
vec[v1[0]].hdr->header_charset);
out_state_destroy(&state);
}
}
if (all_headers)
delete_headers(&all_headers);
} else {
DPRINT(Debug,9,(&Debug,
"generate_mail_data: failed seek beginning of part 1 headers\n"));
}
for (i = 0; i < total_count; i++) {
char buf[VERY_LONG_STRING];
int j = v1[i];
int len = vec[j].p->reference->length;
int l;
if (len < 256) {
DPRINT(Debug,9,(&Debug,
"generate_mail_data: Part %d is %d bytes\n",
i+1,len));
}
if (0 != fseek (vec[j].F,vec[j].p->reference->offset, SEEK_SET)) {
DPRINT(Debug,9,(&Debug,
"generate_mail_data: part %d - Seek to %ld failed.\n",
i+1,
vec[j].p->reference->offset));
h->offset = -1L; /* Indicate failure */
goto fail;
}
while (len > 0 &&
0 < (l = mail_gets(buf, sizeof buf, vec[j].F))) {
len -= l;
if (fwrite(buf,1,l,mailbox->u.partial->F) < l) {
DPRINT(Debug,9,(&Debug,
"generate_mail_data: part %d -- incompletet write\n",
i+1));
goto fail2;
}
written += l;
}
if (len > 0) {
DPRINT(Debug,9,(&Debug,
"generate_mail_data: part %d - all data not read\n",
i+1));
h->offset = -1L; /* Indicate failure */
goto fail;
}
}
if (EOF == fflush(mailbox->u.partial->F)) {
DPRINT(Debug,9,(&Debug,
"generate_mail_data: flush failed\n"));
fail2:
h->offset = -1L; /* Indicate failure */
#ifdef FTRUNCATE
if (0== truncate(mailbox->u.partial->fname,
h->offset)) {
DPRINT(Debug,9,(&Debug,
"generate_mail_data: %s truncated to %ld\n",
mailbox->u.partial->fname,h->offset));
}
#endif
goto fail;
}
DPRINT(Debug,9,(&Debug,
"generate_mail_data: %d bytes copied from fragments",
written));
/* written do not include copeid received headers, so recaluclate it */
written = ftell(mailbox->u.partial->F) - h->mime_rec.begin_offset;
DPRINT(Debug,9,(&Debug,", %d total\n",
written));
/* Re-parse headers */
if (0 != fseek(mailbox->u.partial->F,h->mime_rec.begin_offset,SEEK_SET)) {
DPRINT(Debug,3,(&Debug,
"generate_mail_data: seek to %ld failed\n",
h->mime_rec.begin_offset));
goto fail;
}
parsed_headers = file_read_headers(mailbox->u.partial->F,0);
if (!parsed_headers) {
DPRINT(Debug,3,(&Debug,
"generate_mail_data: No headers parsed! \n"));
}
read_folder_headers_helper(h,parsed_headers);
header_parse_helper(h,parsed_headers);
content_start = ftell(mailbox->u.partial->F);
start_body_helper(h,content_start,parsed_headers);
delete_headers(&parsed_headers);
h->body_parsed = 1; /* Mark that data is downloaded */
/* Effectively start_body_helper()
is called
*/
if (-1 != h->content_length) {
DPRINT(Debug,10,(&Debug,
"generate_mail_data: content_length set: %ld\n",
h->content_length
));
}
if (h->content_length != written - (h->mime_rec.offset -
h->mime_rec.begin_offset)) {
h->content_length = written - (h->mime_rec.offset -
h->mime_rec.begin_offset);
DPRINT(Debug,10,(&Debug,
"generate_mail_data: setting content_length: %ld\n",
h->content_length
));
}
h->mime_rec.length = h->content_length;
DPRINT(Debug,10,(&Debug,
"generate_mail_data: {hdr)offset = %ld, {mime} begin_offset = %ld, {mime} offset = %ld\n",
h->offset,
h->mime_rec.begin_offset,
h->mime_rec.offset));
header_not_full = 0;
DPRINT(Debug,5,(&Debug,
"generate_mail_data: Message %s assembled -- %ld bytes - %d parts -- content length %ld\n",
mailbox->u.partial->composite[composite_index].id,
written,total_count,h->content_length
));
fail:
if (header_not_full &&
mailbox->u.partial->composite[composite_index].mss)
header_free(& (mailbox->u.partial->composite[composite_index].mss));
free(vec);
if (v1)
free(v1);
}
struct MailboxView * partial_to_mailbox_view (parent)
struct MailboxView * parent;
{
struct MailboxView *ret = malloc_view(&mt_partial);
if (parent->magic != MAILBOXVIEW_magic)
panic("MBX VIEW PANIC",__FILE__,__LINE__,"partial_to_mailbox_view",
"Bad magic number",0);
if (parent->mailbox_type->magic != MAILBOXTYPE_magic)
panic("MBX VIEW PANIC",__FILE__,__LINE__,"partial_to_mailbox_view",
"Bad type magic number",0);
ret->u.partial->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