/*
** 
** 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_sun_message(struct message *m)
{
  struct data *inbuf;

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

#ifdef DEBUG
  if (edebug)
    fprintf(stderr, "+ (parse_sun_message) Parsing 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 Multipart create a child and run parse_message 
   * on the child.
   */

  if (inbuf->encoding == EMULTI)
    {
      int status;
#ifdef DEBUG
      if (edebug)
	fprintf(stderr, "+ Tried (MAILTOOL) multipart %d at level %d starting at %lu and ending at %lu.\n", 
		inbuf->count,
		m->level,
		inbuf->bodystart,
		inbuf->bodyend);
#endif
      if ((status = parse_sun_multi(m)) == OK)
	{
#ifdef DEBUG
	  if (edebug)
	    fprintf(stderr, "+ Marked up (MAILTOOL) 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, "+ MAILTOOL body part %d at level %d failed.\n", 
		    inbuf->count,
		    m->level);
#endif
	  return(NOK);
      }
    }
  else
    {
      /* Body starts here */
      inbuf->bodystart = inbuf->offset;
      inbuf->linestart = inbuf->loffset;
    }
  if (check_encoding(m) != OK)
    m->sd->encoding = E7BIT;
  if (m->sd->bodyend == 0)
    m->sd->bodyend = m->sd->end;
  return(OK);
}


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

  inbuf = (struct data *)m->sd;
  /* Copy off a child */
  childm = (struct message *)copy_mstruct(m, 0);

  /* Body end is end of data */
  inbuf->bodyend = inbuf->end;
  inbuf->lineend = inbuf->lend;


  /* 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;

  /* Parse child */
  if (parse_sun_siblings(childm) == OK)
    {
      /* Parse successful.
       * Connect child to current part and beware that data
       * now belongs to the children. If the contents was 
       * only one part, fix this here, to reduce the depth 
       * of this part of the structure.
       */

      /* Attach child */
      m->child = childm;
      m->children += 1;
      if (m->level == 0)
	return(OK); /* All data processed */
    }
  else
    {
      /* Erroneous multipart, set type to text instead and
       * run test check below 
       */
      m->sd->encoding = E7BIT;
      m->sd->type = NEWSTR("TEXT");
      check_bits(m->sd);
      return(FAIL);
    }
  return(OK);
}



int
parse_sun_siblings(struct message *m)
{
  struct data *inbuf, *sibbuf;
  struct message *sibm;
  int status;

  inbuf = m->sd;


#ifdef DEBUG
  if (edebug)
    fprintf(stderr, "+   parse_sun_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(SKIP);
    }      

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

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

  /* Find end of bodypart */
  set_end_by_lines(m, m->sd->bodylines);

  parse_sun_message(m);

#ifdef DEBUG
  if (edebug)
    fprintf(stderr, "+ Marked up (MAILTOOL) body part %d at level %d starting at %lu and ending at %lu.\n", 
	    inbuf->count,
	    m->level,
	    inbuf->bodystart,
	    inbuf->bodyend);
#endif

  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 ((status = parse_sun_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
	{
	  if (status == SKIP)
	    return(OK);
	  else
	    return(NOK);
	}
    }
  return(OK);
}



syntax highlighted by Code2HTML, v. 0.9.1