static char rcsid[] = "@(#)$Id: folder.c,v 1.4 2006/05/30 16:33:21 hurtta Exp $";
/******************************************************************************
* The Elm (ME+) Mail System - $Revision: 1.4 $ $State: Exp $
*
* Author: Kari Hurtta <hurtta+elm@posti.FMI.FI>
* or Kari Hurtta <elm@elmme-mailer.org>
*****************************************************************************/
#include "def_readmsg.h"
DEBUG_VAR(Debug,__FILE__,"readmsg");
#include <errno.h>
#ifndef ANSI_C
extern int errno;
#endif
#if ANSI_C
#define S_(x) static x;
#else
#define S_(x)
#endif
struct folder_data {
struct folder_info *folder_handle;
struct header_rec **headers;
int headers_count;
};
static int parse_header_routine P_((struct folder_info *folder,
READ_STATE read_state_ptr,
struct header_rec *entry,
header_list_ptr parsed_headers ));
static int parse_header_routine(folder,read_state_ptr,entry,parsed_headers)
struct folder_info *folder;
READ_STATE read_state_ptr;
struct header_rec *entry;
header_list_ptr parsed_headers;
{
header_list_ptr tmphdr;
/* copy_envelope_folder() may have set entry->content_length */
/* copy_envelope_folder() have set entry->header_charset */
mime_parse_helper(entry,parsed_headers);
return 1;
}
static int parse_body_routine P_((struct folder_info *folder,
READ_STATE read_state_ptr,
struct header_rec *entry,
header_list_ptr parsed_headers,
struct counter_data *counter
));
static int parse_body_routine(folder,read_state_ptr,entry,parsed_headers,
counter)
struct folder_info *folder;
READ_STATE read_state_ptr;
struct header_rec *entry;
header_list_ptr parsed_headers;
struct counter_data *counter;
{
char * buffer;
int len;
long content_remaining = -1L;
long A1, A2;
content_remaining = entry->content_length;
A1 = copy_fbytes_folder(folder,read_state_ptr);
start_body_helper(entry,A1,parsed_headers);
reset_body:
while (copy_body_folder(folder,read_state_ptr,
&buffer,&len,&content_remaining)) {
if (buffer)
free(buffer);
}
A2 = copy_fbytes_folder(folder,read_state_ptr);
if (!copy_envelope_end_folder(folder,read_state_ptr)) {
if (entry->content_length >= 0L) {
entry->content_length = -1L;
if (copy_envelope_reset_body(folder,read_state_ptr,
&content_remaining))
goto reset_body;
}
DPRINT(Debug,10,(&Debug,
"-- Message parsing FAILED.\n"));
return 0;
}
DPRINT(Debug,10,(&Debug,
"-- Message parsed.\n"));
if (A2-A1 != entry->content_length) {
entry->content_length = A2-A1;
DPRINT(Debug,10,(&Debug,"-- Content-length fixed: %ld\n",
entry->content_length));
}
entry->body_parsed = 1;
return 1;
}
struct header_rec * malloc_header_helper()
{
struct header_rec *entry = safe_malloc(sizeof (* entry));
/* bzero is defined hdrs/defs.h */
bzero((void *)entry,sizeof (* entry));
mime_t_zero (&(entry->mime_rec));
return entry;
}
/* Return 0 on failure, 1 on succeed */
static int read_headers P_((struct folder_handler *H,
struct read_folder_state * read_state_ptr));
static int read_headers(H,read_state_ptr)
struct folder_handler *H;
struct read_folder_state * read_state_ptr;
{
struct folder_data * fol = H->d.normal;
int count = H->num_messages;
int r = 0;
if (count > fol->headers_count)
panic("READMSG PANIC",__FILE__,__LINE__,"read_headers",
"Bad count",0);
while (1) {
if (count >= fol->headers_count) {
int nv = count + 100;
int i;
fol->headers = safe_realloc(fol->headers,
nv * sizeof(fol->headers[0]));
for (i = fol->headers_count; i < nv; i++)
fol->headers[i] = NULL;
fol->headers_count = nv;
}
if (! fol->headers[count])
fol->headers[count] = malloc_header_helper();
r = copy_envelope_folder(fol->folder_handle,read_state_ptr,
fol->headers[count],
parse_header_routine,parse_body_routine,
NULL);
if (r <= 0) {
DPRINT(Debug,10,(&Debug,"[%d] copy_envelope_folder returned %d \n",
count,r));
break;
}
count++;
}
H->num_messages = count;
if (r < 0) {
DPRINT(Debug,10,(&Debug,"read_headers failed.\n"));
return 0;
}
return 1;
}
S_(init_folder_handler_f init_normal_handler)
static void init_normal_handler P_((struct folder_handler *H));
static void init_normal_handler(H)
struct folder_handler *H;
{
H->d.normal = safe_malloc(sizeof (* H->d.normal));
/* bzero is defined hdrs/defs.h */
bzero((void *)H->d.normal,sizeof (* H->d.normal));
H->d.normal->folder_handle = NULL;
H->d.normal->headers = NULL;
H->d.normal->headers_count = 0;
}
void free_header_helper(entry)
struct header_rec **entry;
{
free_rec_mbx_info(*entry);
mime_t_clear(& ((*entry)->mime_rec));
if ((*entry)->header_error)
free_header_errors(& ((*entry)->header_error));
free(*entry); /* LEAKS !!! */
*entry = NULL;
}
S_(free_folder_handler_f free_normal_handler)
static void free_normal_handler P_((struct folder_handler *H));
static void free_normal_handler(H)
struct folder_handler *H;
{
/* leave_old_folder calls close_folder()
so it need not be called separately
*/
if (H->d.normal->folder_handle)
leave_old_folder(& (H->d.normal->folder_handle), CLOSE_NORMAL);
if (H->d.normal->headers) {
int i;
for (i = 0; i < H->d.normal->headers_count; i++) {
/* FIXME -- there is no way to free that -- this leaks ... */
if (H->d.normal->headers[i]) {
free_header_helper(& H->d.normal->headers[i]);
}
}
free(H->d.normal->headers);
H->d.normal->headers = NULL;
}
H->d.normal->headers_count = 0;
}
S_(give_message_from_folder_f give_message_from_normal)
static FILE * give_message_from_normal P_((struct folder_handler *folder,
int idx,
long *content_length,
enum message_error *errret,
int print_separator,
char **env_buffer,
struct header_rec ** entryret
));
static FILE * give_message_from_normal(folder,idx,content_length,errret,
print_separator,env_buffer,entryret)
struct folder_handler *folder;
int idx;
long *content_length;
enum message_error *errret;
int print_separator;
char **env_buffer;
struct header_rec ** entryret;
{
FILE * F;
long ZZ;
struct folder_data * fol = folder->d.normal;
if (idx < 0 || idx >= folder->num_messages ||
idx >= fol->headers_count ||
! fol->headers[idx])
panic("READMSG PANIC",__FILE__,__LINE__,"give_message_from_normal",
"Bad index",0);
if (! prepare_message_access(fol->folder_handle,
fol->headers[idx],
parse_header_routine,
parse_body_routine,
NULL,NO_mime_parse)) {
*errret = error_none; /* Error message already printed ? */
return NULL;
}
if (fol->headers[idx]->header_error)
print_header_errors(fol->headers[idx]->header_error);
*content_length = fol->headers[idx]->content_length;
F = folder_to_fd(fol->folder_handle,
fol->headers[idx]->offset);
if (!F) {
*errret = error_seek;
return NULL;
}
ZZ = separator_helper(NULL,errret,
print_separator,env_buffer,F);
if (-1 == ZZ)
return NULL;
DPRINT(Debug,9,(&Debug,
"give_message_from_folder: beginning of headers=%ld\n",ZZ));
if (fseek(F, ZZ, SEEK_SET) == -1) {
int err = errno;
DPRINT(Debug,1,(&Debug,
"give_message_from_folder: Couldn't seek folder to offset %ld Errno %s (%s)\n",
ZZ,
error_description(err)));
*errret = error_seek;
return NULL;
}
if (entryret)
*entryret = fol->headers[idx];
return F;
}
S_(parse_folder_handler_f parse_folder_normal)
static int parse_folder_normal P_((struct folder_handler *H));
static int parse_folder_normal(H)
struct folder_handler *H;
{
int ret = 0;
struct read_folder_state * read_state_ptr = NULL;
struct folder_data * fol = H->d.normal;
enum prepare_mode mode = PREPARE_NOLOCK;
/* Already called */
if (H->num_messages > 0)
mode = PREPARE_NEW_ONLY_NOLOCK;
if (!prepare_read_folder(fol->folder_handle,mode,&read_state_ptr)) {
DPRINT(Debug,10,(&Debug,"prepare_read_folder failed.\n"));
goto fail;
}
ret = read_headers(H,read_state_ptr);
if (!end_read_folder(fol->folder_handle,&read_state_ptr,0)) {
DPRINT(Debug,10,(&Debug,"end_read_folder failed.\n"));
ret = 0;
}
fail:
return ret;
}
static struct folder_routines NORMAL = {
FOLDER_ROUTINES_magic,
init_normal_handler,
free_normal_handler,
give_message_from_normal,
parse_folder_normal
};
struct folder_handler * open_normal_folder(folder_name)
const char * folder_name;
{
struct folder_handler *ret = NULL;
struct folder_info * f = enter_new_folder(folder_name);
if (!f)
return NULL;
/* Actually open folder
folder_to_fd do not work if SESSIONLOCK_NONE is used
*/
if (!sessionlock_folder(f,SESSIONLOCK_NORMAL)) {
leave_old_folder(& f, CLOSE_NORMAL);
return NULL;
}
ret = malloc_folder_handler(&NORMAL);
ret->d.normal->folder_handle = f;
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