/*
** 
** Copyright (C) 1993 Swedish University Network (SUNET)
** 
** 
** This program is developed by UDAC, Uppsala University by commission
** of the Swedish University Network (SUNET). 
** 
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
** 
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITTNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
** 
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
** 
** 
**                                           Martin.Wendel@its.uu.se
** 				             Torbjorn.Wictorin@its.uu.se
** 
**                                           ITS	
**                                           P.O. Box 887
**                                           S-751 08 Uppsala
**                                           Sweden
** 
*/
#include "emil.h"
/*
 * int
 * parse_message(inbuf, message)
 *
 * Parse message and divide into a hierarchical structure of message parts.
 *
 */

int
parse_mime_message(struct message *m)
{
  struct data *inbuf;
  static int not_first = 0;

  /* Initialize inbuf */
  inbuf = (struct data *)m->sd;

#ifdef DEBUG
  if (edebug)
    fprintf(stderr, "+ Parsing (MIME) body part %d at level %d and offset %lu.\n", 
	    inbuf->count,
	    m->level,
	    inbuf->offset);
#endif

  /* Exit on empty input */
  if (inbuf->size == 0 || (inbuf->end <= inbuf->offset))
    {
#ifdef DEBUG
      if (edebug)
	fprintf(stderr, "*** Empty input (failed).\n");
#endif
      logger(LOG_ERR, "parse_message: Empty input");
      return(NOK);
    }


  if (not_first)
    {
      /* Check header if possible */
      if (!m->headerdone && (m->sd->format != RFC822 || m->level == 0))
	if (check_header(m) != OK)
	  return(NOK);
    }
  else
    not_first = 1;

  /* Body starts here */
  inbuf->bodystart = inbuf->offset;
  inbuf->linestart = inbuf->loffset;

  /* If Multipart create a child and run parse_message 
   * on the child.
   * If MIME Multipart define the end boundary as end of 
   * current data. If Mailtool Multipart define end according 
   * to the lines field. Else leave end undefined. 
   */

  if (inbuf->encoding == EMULTI)
    {
      int status;
      if ((status = parse_mime_multi(m)) == OK)
	{
#ifdef DEBUG
	  if (edebug)
	    fprintf(stderr, "+ Marked up (MIME) multipart %d at level %d starting at %lu and ending at %lu.\n", 
		    inbuf->count,
		    m->level,
		    inbuf->bodystart,
		    inbuf->bodyend);
#endif
	  return(OK);
	}
      if (status == NOK)
	{
#ifdef DEBUG
	  if (edebug)
	    fprintf(stderr, "+ MIME body part %d at level %d failed.\n", 
		    inbuf->count,
		    m->level);
#endif
	  return(NOK);
      }
    }
  else
    {
      if (m->sd->bodyend == 0)
	m->sd->bodyend = m->sd->end;
    }
  if (check_encoding(m) != OK)
    m->sd->encoding = E7BIT;
  return(OK);
}

int
parse_mime_multi(struct message *m)
{
  struct data *childbuf, *inbuf;
  struct message *childm;

#ifdef DEBUG
  if (edebug)
    fprintf(stderr, "+   parse_mime_multi\n");
#endif
  inbuf = (struct data *)m->sd;
  /* Find end of part if prematured by an end boundary (MIME) */
  if (m->sd->endbound != NULL)
    set_end_by_boundary(m, m->sd->endbound);
  else
    {
      /* Body end is end of data */
      inbuf->bodyend = inbuf->end;
      inbuf->lineend = inbuf->lend;
    }

  /* Copy off a child */
  childm = (struct message *)copy_mstruct(m, 0);

  /* Set more child data */
  childbuf = childm->sd;
  childm->level = m->level + 1;
  childm->parent = m;
  childm->bigsib = childm; /* Loop back */
  childbuf->end = (inbuf->bodyend != 0) ? inbuf->bodyend: inbuf->end;
  childbuf->lend = (inbuf->lineend != 0) ? inbuf->lineend: inbuf->lend;
  childbuf->offset = inbuf->bodystart;
  if (parse_mime_siblings(childm) == OK)
    {
      m->child = childm;
#ifdef DEBUG
      if (edebug)
	fprintf(stderr, "   *parse_mime_multi: success, multipart OK\n");
#endif
      return(OK);
    }
  else
    {
      /* Erroneous multipart, set type to text instead and
       * run test check below 
       */
#ifdef DEBUG
      if (edebug)
	fprintf(stderr, "   *parse_mime_multi: failed, set type to TEXT\n");
#endif
      m->sd->encoding = E7BIT;
      m->sd->type = NEWSTR("TEXT");
      check_bits(m->sd);
      return(FAIL);
    }
}

int
parse_mime_siblings(struct message *m)
{
  struct data *inbuf, *sibbuf;
  struct message *sibm;
  inbuf = m->sd;


#ifdef DEBUG
  if (edebug)
    fprintf(stderr, "+   parse_mime_siblings\n");
#endif
  /* Parse child */
  /* If this is a body part in a multipart with startbound set
   *  find the start of this body part 
   */

  if (m->parent != NULL && m->parent->sd->startbound != NULL)
    {
      if (move_past_boundary(m, m->parent->sd->startbound) != OK)
	return(NOK);
    }      

  /* If multipart, find end of bodypart */
  if (m->parent != NULL && m->parent->sd->startbound != NULL)
    set_end_by_boundary(m, m->parent->sd->startbound);

  parse_mime_message(m);

#ifdef DEBUG
  if (edebug)
    fprintf(stderr, "+ Marked up (MIME) body part %d at level %d starting at %lu and ending at %lu.\n", 
	    inbuf->count,
	    m->level,
	    inbuf->bodystart,
	    inbuf->bodyend);
#endif
  /* FIX */
  if (m->sd->encoding == EMULTI && m->sd->endbound != NULL)
    {
      int tttt;
      move_past_boundary(m, m->sd->endbound);
      for (;;)
      {
        tttt = getline(m->sd);
#ifdef DEBUG
          if (edebug)
            fprintf(stderr," getline = %d\n", tttt);
#endif
        if (tttt == 1)
          {
            inbuf->offset += tttt;
            inbuf->loffset += 1;
            continue;
          }
        if (tttt == 2 && *(m->sd->contents + m->sd->offset) == '\r')
          {
            inbuf->offset += tttt;
            inbuf->loffset += 1;
            continue;
          }
        break;
      }

    }
  else
  /* END_FIX */
    m->sd->offset = m->sd->bodyend;


  if (getline(m->sd) == 0)
    return(OK);
  if (m->sd->offset < m->sd->end)
    {
      /* Allocate siblings data sructure */
      sibm = (struct message *)copy_mstruct(m, 0);
      sibbuf = sibm->sd;
      sibbuf->end = inbuf->end;
      sibbuf->lend = inbuf->lend;
      sibbuf->offset = inbuf->bodyend;
      sibm->bigsib = m->bigsib;
      sibm->level = m->level;
      sibm->parent = m->parent;

  /* Run Sibling */
      if (parse_mime_siblings(sibm) == OK)
	{
#ifdef DEBUG
	  if (edebug)
	    fprintf(stderr, "*  sibling ended at offset %lu\n", sibbuf->offset);
#endif
	  m->sibling = sibm;
	  if (m->parent)
	    m->parent->children += 1;
	  return(OK);
	}
      else
	return(NOK);
      /* Successful return from current part */
      return(OK);
    }
  return(OK);
}




syntax highlighted by Code2HTML, v. 0.9.1