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 * or Kari Hurtta *****************************************************************************/ #include "def_readmsg.h" DEBUG_VAR(Debug,__FILE__,"readmsg"); #include #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: */