/*
 *  decode_simple.c
 *
 *    Decode a multipart MIME message.
 *
 *  Copyright (c) 2003, Sun Microsystems, Inc.  All Rights Reserved.
 */

#include <stdio.h>
#include <string.h>
#include "mtasdk.h"

/*
 *  Inline data for a sample message to decode
 */
static const char message[] = 
  "From: sue@siroe.com\n"
  "Date: 31 Mar 2003 09:32:47 -0800\n"
  "Subject: test message\n"
  "Content-type: multipart/mixed; boundary=BoundaryMarker\n"
  "\n\n"
  "--BoundaryMarker\n"
  "Content-type: text/plain; charset=us-ascii\n"
  "Content-disposition: inline\n"
  "\n"
  "This is a\n"
  "  test message!\n"
  "--BoundaryMarker\n"
  "Content-type: application/postscript\n"
  "Content-disposition: attachment; filename=\"a.ps\"\n"
  "Content-transfer-encoding: base64\n"
  "\n"
  "IyFQUwoxMDAgMTAwIG1vdmV0byAzMDAgMzAwIGxpbmV0byBzdHJva2UKc2hvd3Bh\n"
  "Z2UK\n"
  "--BoundaryMarker--\n";

static mta_decode_read_t decode_read;
static mta_decode_inspect_t decode_inspect;

typedef struct {
     const char *cur_position;
     const char *end_position;
} position_t;

main()
{
     int ires;
     position_t pos;

     /*
      *  Initialize the MTA SDK
      */
     if ((ires = mtaInit(0)))
     {
	  mtaLog("mtaInit() returned %d; %s\n", ires, mtaStrError(ires, 0));
	  return(1);
     }

     /*
      *  For a context to pass to mtaDecodeMessage(), we pass a pointer
      *  to the message data to be parsed.  The decode_read() routine uses
      *  this information when supplying data to mtaDecodeMessage().
      */
     pos.cur_position = message;
     pos.end_position = message + strlen(message);

     /*
      *  Invoke mtaDecodeMessage():
      *    1. Use decode_read() as the input routine to supply the message
      *       to be MIME decoded,
      *    2. Use decode_inspect() as the routine to inspect each MIME decoded
      *       message part,
      *    3. Do not specify an output routine to write the resulting, MIME
      *       message, and
      *    4. Indicate that the input message source uses LF record terminators.
      */
     mtaDecodeMessage((void *)&pos, MTA_DECODE_PROC, (void *)decode_read,
		      0, NULL, decode_inspect, MTA_TERM_LF, 0);
}


/*
 *  decode_read -- Provide message data to mtaDecodeMessage().  We could
 *                 just as easily give mtaDecodeMessage() the entire message
 *                 at once.  However, for illustration purposes, we provide
 *                 the message in 200 byte chunks.
 */
static int decode_read(void *ctx, const char **line, size_t *line_len)
{
     position_t *pos = (position_t *)ctx;

     if (!pos)
	  return(MTA_NO);
     else if (pos->cur_position >= pos->end_position)
	  return(MTA_EOF);
     *line = pos->cur_position;
     *line_len = ((pos->cur_position + 200) < pos->end_position) ?
	  200 : (pos->end_position - pos->cur_position);
     pos->cur_position += *line_len;
     return(MTA_OK);
}


/*
 *  decode_inspect -- Called by mtaDecodeMessage() to output a line of the
 *                    parsed message.  We here merely output the line with
 *                    additional information indicating whether the line comes
 *                    from a header, text part, or binary part.
 */
static int decode_inspect(void *ctx, mta_decode_t *dctx, int data_type,
			  const char *data, size_t data_len)
{
     static const char *types[] = {"N", "H", "T", "B"};

     if (data_type == MTA_DATA_NONE)
	  return(MTA_OK);

     printf("%d%s: %.*s\n",
	    mtaDecodeMessageInfoInt(dctx, MTA_DECODE_PART_NUMBER),
	    types[data_type], data_len, data);

     return(MTA_OK);
}
