static char rcsid[] = "@(#)$Id: mparser.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)
 *****************************************************************************/

#include "def_melib.h"
#include "mpar_imp.h"

DEBUG_VAR(Debug,__FILE__,"mime");

#define MPAR_magic              0xFD01

void mime_parser_free(P)
     struct mime_parser_data **P;
{
    
    if ((*P)->magic != MPAR_magic)
	panic("MIME PARSER PANIC",__FILE__,__LINE__,"mime_parser_free",
	      "Bad magic number",0);
	
    if ((*P)->parser_code)
	(*P)->parser_code->free_data(*P);
    (*P)->parser_code = NULL;   /* NOT determined yet */
       
    if ((*P)->p.any) {
	panic("MIME PARSER PANIC",__FILE__,__LINE__,"mime_parser_free",
	      "Parsed data not empty",0);
    }

    /* bzero is defined on hdrs/defs.h */
    bzero((void *)*P,sizeof (**P));

    free(*P);
    *P = NULL;
}

void copy_parser_data(target,source)
     struct mime_parser_data **target;
     struct mime_parser_data *source;				 
{
    struct mime_parser *f;

    if (*target) {

	if ((*target)->magic != MPAR_magic)
	    panic("MIME PARSER PANIC",__FILE__,__LINE__,"copy_parser_data",
		  "Bad magic number",0);

	if ((*target)->parser_code)
	    (*target)->parser_code->free_data((*target));
	(*target)->parser_code = NULL;   /* NOT determined yet */

    } else {
	(*target) = safe_malloc(sizeof (*((*target))));

	/* bzero is defined on hdrs/defs.h */
	bzero((void *)(*target),sizeof (*((*target))));
	
	(*target)->magic = MPAR_magic;
	(*target)->parser_code = NULL;  
	(*target)->p.any       = NULL;

    }

    if (source->magic != MPAR_magic)
	panic("MIME PARSER PANIC",__FILE__,__LINE__,"copy_parser_data",
	      "Bad magic number",0);

    if (! source->parser_code)
	panic("MIME PARSER PANIC",__FILE__,__LINE__,"copy_parser_data",
	      "No parser code",0);

    f = source->parser_code;

    if ((*target)->p.any) {
	panic("MIME PARSER PANIC",__FILE__,__LINE__,"copy_parser_data",
	      "Parsed data not empty",0);
    }

    (*target)->parser_code = f;

    f->alloc_data(*target);
    f->copy_data(*target,source);
}

int  mime_parser_subparts(P)
     struct mime_parser_data *P;
{
    int ret;

    if (P->magic != MPAR_magic)
	panic("MIME PARSER PANIC",__FILE__,__LINE__,"mime_parser_subparts",
	      "Bad magic number",0);

    if (! P->parser_code)
	panic("MIME PARSER PANIC",__FILE__,__LINE__,"mime_parser_subparts",
	      "No parser code",0);

    ret = P->parser_code->count_subparts(P);

    DPRINT(Debug,10,(&Debug,
		    "mime_parser_subparts = %d\n",
		    ret));

    return ret;
}

struct mimeinfo * mime_parser_index(P,idx)
     struct mime_parser_data *P;
     int idx;
{
    struct mimeinfo *ret;

    if (P->magic != MPAR_magic)
	panic("MIME PARSER PANIC",__FILE__,__LINE__,"mime_parser_index",
	      "Bad magic number",0);

    if (! P->parser_code)
	panic("MIME PARSER PANIC",__FILE__,__LINE__,"mime_parser_index",
	      "No parser code",0);

    ret = P->parser_code->index_subpart(P,idx);

    DPRINT(Debug,10,(&Debug,
		    "mime_parser_index[%d] = %p\n",
		    idx,ret));
    
    return ret;
}

static int mime_register_parsers_called = 0;
static void mime_register_parsers P_((void));
static void mime_register_parsers()
{
    register_rfc822_parser();
    register_multipart_parser();
    register_leaf_parser();

    mime_register_parsers_called++;
}

int mime_parser_parse(P,defcharset,fp, header_error)
     struct mimeinfo *P;
     charset_t defcharset;
     FILE *fp;
     struct header_errors **header_error;
{
    struct media_type_handle *H = NULL;
    int is_default = 0;

    if (!mime_register_parsers_called)
	mime_register_parsers();

    if (P->parser_data) {
	/* Already alloced */

	DPRINT(Debug,8,(&Debug,
			 "mime_parser_parse: Reparsing type\n"));

	if (P->parser_data->magic != MPAR_magic)
	    panic("MIME PARSER PANIC",__FILE__,__LINE__,"mime_parser_parse",
		  "Bad magic number",0);

	if (P->parser_data->parser_code)
	    P->parser_data->parser_code->free_data(P->parser_data);
	P->parser_data->parser_code = NULL;   /* NOT determined yet */

    } else {
	P->parser_data = safe_malloc(sizeof (*(P->parser_data)));

	/* bzero is defined on hdrs/defs.h */
	bzero((void *)(P->parser_data),sizeof (*(P->parser_data)));
	
	P->parser_data->magic = MPAR_magic;
	P->parser_data->parser_code = NULL;  
	P->parser_data->p.any       = NULL;
    }

    /* RESET loop variables */
    H = NULL;
    is_default = 0;

    while (walk_mt_handler(P->TYPE,&H,&is_default,handle_mime_parser)) {
	struct mime_parser *f;

	if (H->type != handle_mime_parser)
	    panic("MIME PARSER PANIC",__FILE__,__LINE__,
		  "mime_parser_alloc",
		  "walk_mt_handler returned bad handler type",0);

	if (! H->p.parser_code)
	    panic("MIME PARSER PANIC",__FILE__,__LINE__,
		  "mime_parser_alloc",
		  "walk_mt_handler did not returned parser code",0);

	if (P->parser_data->p.any) {
	    panic("MIME PARSER PANIC",__FILE__,__LINE__,"mime_parser_parse",
		  "Parsed data not empty",0);
	}

	DPRINT(Debug,10,(&Debug,
			 "mime_parser_parse: Traying handler %p (%p) for type %p\n",
			 H,H->p.parser_code,P->TYPE));

	f=H->p.parser_code;
	P->parser_data->parser_code = f;

	f->alloc_data(P->parser_data);

	if (f->parse_data(P->parser_data,P,defcharset,fp, header_error)) {
	    /* SUCCEED */

	    DPRINT(Debug,10,(&Debug,
			     "mime_parser_parse: parse_data succeed\n"));

	    return 1;
	}

	f->free_data(P->parser_data);
	P->parser_data->parser_code = NULL;
    }



    DPRINT(Debug,8,(&Debug,
		    "mime_parser_parse: No one parser succeed for type %p\n",
		    P->TYPE));
    
    if (P->parser_data->p.any) {
	panic("MIME PARSER PANIC",__FILE__,__LINE__,"mime_parser_parse",
	      "Parsed data not empty on failure",0);
    }

    if (P->parser_data) {

	DPRINT(Debug,8,(&Debug,
			"mime_parser_parse: FREEing parser data on failure\n"));

	mime_parser_free( & (P->parser_data) );
    }
    
    /* FAILURE */
    return 0;
}

/*
 * Local Variables:
 *  mode:c
 *  c-basic-offset:4
 *  buffer-file-coding-system: iso-8859-1
 * End:
 */


syntax highlighted by Code2HTML, v. 0.9.1