/*
 *  decode_complex.c
 *
 *    Remove non-text message parts from a multipart message, writing the
 *    result to stdout.
 *
 *  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_write_t decode_write;
static mta_decode_inspect_t decode_inspect;

main()
{
     int eof, ires;

     /*
      *  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 an end-of-file
      *  flag.  The decode_read() routine uses this flag to know if it has
      *  been called.
      */
     eof = 0;

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


/*
 *  decode_read -- Provide message data to mtaDecodeMessage().  The entire
 *                 message is passed on the first cal to decode_read().  Any
 *                 subsequent calls to decode_read() returns an MTA_EOF status.
 */
static int decode_read(void *ctx, const char **line, size_t *line_len)
{
     int *eof = (int *)ctx;

     if (!eof)
	  return(MTA_NO);
     else if (*eof)
	  return(MTA_EOF);
     *line = message;
     *line_len = strlen(message);
     *eof = 1;
     return(MTA_OK);
}


/*
 *  decode_write -- Called by mtaDecodeMessage() to output a message.  In this
 *                  example we perform the output by writing to stdout.
 */
static int decode_write(void *ctx, mta_decode_t *dctx, const char *line,
			size_t line_len)
{
     /*
      *  Note that the line may not be NULL terminated!
      */
     printf("%.*s\n", line_len, line);
     return(MTA_OK);
}


/*
 *  decode_inspect -- Called by mtaDecodeMessage() to inspect a message 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);

     if (strcmp("text",
		mtaDecodeMessageInfoString(dctx, MTA_DECODE_CTYPE, NULL, NULL)))
	  /*
	   *  Non text / * part; delete it
	   */
	  return(mtaDecodeMessagePartDelete(dctx, 0));
     else
	  /*
	   *  text / * part; keep it
	   */
	  return(mtaDecodeMessagePartCopy(dctx, 0));
}
