static char rcsid[] = "@(#)$Id: mpar_rfc822.c,v 1.9 2006/05/07 08:35:31 hurtta Exp $"; /****************************************************************************** * The Elm (ME+) Mail System - $Revision: 1.9 $ $State: Exp $ * * Author: Kari Hurtta (was hurtta+elm@ozone.FMI.FI) * * Some code based on mime_parse.c, which is * initially written by: Michael Elkins , 1995 * -- specially function mpar_rfc822_parse() is based on function * rfc822_parse() * *****************************************************************************/ #include "def_melib.h" #include "mpar_imp.h" #include "s_me.h" DEBUG_VAR(Debug,__FILE__,"mime"); #if ANSI_C #define S_(x) static x; #else #define S_(x) #endif #define MPAR_rfc822_magic 0xFD02 struct mpar_rfc822 { unsigned short magic; /* MPAR_rfc822_magic */ struct mimeinfo X; }; S_(mpar_alloc mpar_rfc822_alloc) static void mpar_rfc822_alloc(D) struct mime_parser_data *D; { D->p.rfc822 = safe_malloc(sizeof (* (D->p.rfc822))); /* bzero is defined on hdrs/defs.h */ bzero((void *)(D->p.rfc822),sizeof (*(D->p.rfc822))); D->p.rfc822->magic = MPAR_rfc822_magic; mime_t_zero( & (D->p.rfc822->X)); } S_(mpar_free mpar_rfc822_free) static void mpar_rfc822_free(D) struct mime_parser_data *D; { if (D->p.rfc822) { if (D->p.rfc822->magic != MPAR_rfc822_magic) panic("MIME PARSER PANIC",__FILE__,__LINE__,"mpar_rfc822_free", "Bad magic number",0); /* mime_t_clear will call mime_parser_free() if needed */ mime_t_clear(& (D->p.rfc822->X)); /* bzero is defined on hdrs/defs.h */ bzero((void *)(D->p.rfc822),sizeof (*(D->p.rfc822))); free(D->p.rfc822); D->p.rfc822 = NULL; } } S_(mpar_parse mpar_rfc822_parse) static int mpar_rfc822_parse(D,s,defcharset,fp,header_error) struct mime_parser_data *D; struct mimeinfo *s; charset_t defcharset; FILE *fp; struct header_errors **header_error; { int ret = 1; /* Always succeed ... */ long part_offset; long body_offset; long end_offset; header_list_ptr headers = NULL, mime_version, content_type; int pre_mime_content_type = 0; if (D->p.rfc822->magic != MPAR_rfc822_magic) panic("MIME PARSER PANIC",__FILE__,__LINE__,"mpar_rfc822_parse", "Bad magic number",0); DPRINT(Debug,9,(&Debug, "mpar_rfc822_parse- (parsing) RFC822\n")); fseek (fp, s->offset, SEEK_SET); part_offset = ftell (fp); if (part_offset != s->offset) { DPRINT(Debug,9,(&Debug, "mpar_rfc822_parse: seek to %ld gives pos %ld\n", (long) s->offset,part_offset)); return 0; } end_offset = part_offset + s->length; DPRINT(Debug,9,(&Debug, "mpar_rfc822_parse --> len=%d\n",s->length)); /* Called to read MESSAGE/RFC822 data. First reads the header of the * message for MIME information, then (when necessary) calls other * functions to determine the content of MULTIPART or MESSAGE/RFC822 * data contained. */ headers = file_read_headers(fp,0); body_offset = ftell(fp); DPRINT(Debug,9,(&Debug, "mpar_rfc822_parse- part_offset=%ld, body_offset=%ld, end_offset=%ld\n", part_offset, body_offset, end_offset)); if (!locate_header_by_name(headers,"From") && !locate_header_by_name(headers,"Subject") && !locate_header_by_name(headers,"To") && !locate_header_by_name(headers,"CC")) { lib_error(CATGETS(elm_msg_cat, MeSet, MeParseRFC822Corrupted, "Seems that message/rfc822 data was corrupted.")); } mime_version = locate_header_by_name(headers,"MIME-Version"); content_type = locate_header_by_name(headers,"Content-Type"); mime_t_clear(& (D->p.rfc822->X)); D->p.rfc822->X.begin_offset = part_offset; D->p.rfc822->X.offset = body_offset; D->p.rfc822->X.length = -1; /* FIXME? update defcharset? */ if (content_type && content_type ->body) pre_mime_content_type = is_pre_mime_content_type(&(D->p.rfc822->X), content_type->body); if (mime_version && pre_mime_content_type) { lib_error(CATGETS(elm_msg_cat, MeSet, MeParseRFC822PreWarn, "Warning: message/rfc822 data with MIME-Version and pre-mime Content-type")); } if (mime_version || (!pre_mime_content_type && req_mime_bodyencoding)) { parse_mime_headers1(& (D->p.rfc822->X), headers,part_offset, body_offset, MIME_MIXED,defcharset, header_error); } DPRINT(Debug,9,(&Debug, "mpar_rfc822_parse: content-type=%s/%s; flags=%d\n", get_major_type_name(D->p.rfc822->X.TYPE), get_subtype_name(D->p.rfc822->X.TYPE), get_type_flags(D->p.rfc822->X.TYPE))); if (D->p.rfc822->X.length < 0) { D->p.rfc822->X.length = end_offset - body_offset; DPRINT(Debug,9,(&Debug, "mpar_rfc822_parse: fixing length=%ld\n", (long) D->p.rfc822->X.length)); } mime_parser_parse(& (D->p.rfc822->X),defcharset,fp,header_error); delete_headers(&headers); /* Make sure the leave the stream at the end of the data! */ fseek (fp, end_offset, SEEK_SET); DPRINT(Debug,9,(&Debug, "mpar_rfc822_parse=%d <-- DONE\n", ret)); return ret; } S_(mpar_subparts mpar_rfc822_subparts) static int mpar_rfc822_subparts(D) struct mime_parser_data *D; { return 1; /* CONSTANT */ } S_(mpar_index mpar_rfc822_index) static struct mimeinfo *mpar_rfc822_index(P,idx) struct mime_parser_data *P; int idx; { if (P->p.rfc822->magic != MPAR_rfc822_magic) panic("MIME PARSER PANIC",__FILE__,__LINE__,"mpar_rfc822_index", "Bad magic number",0); if (idx != 0) panic("MIME PARSER PANIC",__FILE__,__LINE__,"mpar_rfc822_index", "Index out of range",0); return (& (P->p.rfc822->X)); } S_(mpar_copy mpar_rfc822_copy) static void mpar_rfc822_copy(T,S) struct mime_parser_data *T; struct mime_parser_data *S; { if (S->p.rfc822->magic != MPAR_rfc822_magic) panic("MIME PARSER PANIC",__FILE__,__LINE__,"mpar_rfc822_copy", "Bad magic number",0); if (T->p.rfc822->magic != MPAR_rfc822_magic) panic("MIME PARSER PANIC",__FILE__,__LINE__,"mpar_rfc822_copy", "Bad magic number",0); mime_t_copy(& (T->p.rfc822->X), & (S->p.rfc822->X)); } static struct mime_parser RFC822_PARSER = { mpar_rfc822_alloc, mpar_rfc822_free, mpar_rfc822_parse, mpar_rfc822_subparts, mpar_rfc822_index, mpar_rfc822_copy }; #if __GNUC__ #define MTH struct media_type_handle #define PARSER(A) handle_mime_parser, { parser_code: & A } #define CAST1 #else #define MTH struct COMPAT_media_type_handle #define PARSER(A) handle_mime_parser, (void *) & A #define CAST1 ( struct media_type_handle *) #endif static MTH rfc822_parser_1 = { PARSER(RFC822_PARSER) }; void register_rfc822_parser() { register_mt_handler(give_media_type2(MIME_TYPE_MESSAGE,"rfc822",1), CAST1 &rfc822_parser_1); } /* * Local Variables: * mode:c * c-basic-offset:4 * buffer-file-coding-system: iso-8859-1 * End: */