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