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 <hurtta+elm@posti.FMI.FI> (was hurtta+elm@ozone.FMI.FI)
 *
 *  Some code based on mime_parse.c, which is
 *     initially written by: Michael Elkins <elkins@aero.org>, 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:
 */


syntax highlighted by Code2HTML, v. 0.9.1