#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, "+ 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;
      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);
      }
    }
  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);
}

