/*
**
** 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_rfc822_message(struct message *m)
{
struct data *inbuf;
int linelen;
int encoding;
static int do_sibling = FALSE;
/* Initialize inbuf */
inbuf = (struct data *)m->sd;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "+ (parse_rfc822_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);
}
/* Body starts here */
inbuf->bodystart = inbuf->offset;
inbuf->linestart = inbuf->loffset;
/* Check for encoding */
if (inbuf->encoding == 0)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "+ No encoding (7bit)\n");
#endif
inbuf->encoding = E7BIT;
}
/* Loop through rest of the message */
while ((linelen = getline(inbuf)) != 0)
{
if (inbuf->bodyend <= inbuf->offset &&
inbuf->lineend <= inbuf->loffset)
/* Either bodyend not set or bodyend reached */
{
if ((encoding = boundary_check(m)) != 0 || do_sibling == TRUE)
{
/* If boundary check successful, create sibling.
*/
struct data *sibbuf;
struct message *sibm;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "+ Boundary check OK.\n");
#endif
do_sibling = FALSE;
/* Allocate siblings data sructure */
sibm = (struct message *)copy_mstruct(m, 0);
sibbuf = sibm->sd;
sibbuf->encoding = encoding;
sibbuf->end = inbuf->end;
sibbuf->lend = inbuf->lend;
sibm->bigsib = m->bigsib;
sibm->level = m->level;
sibm->parent = m->parent;
/* Run Sibling */
if (parse_message(sibm) == OK)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "Child ended at offset %lu\n", sibbuf->offset);
#endif
/* If sibling went successful set end of current
* part and attach sibling to current.
*/
if (m->sd->format != RFC822)
{
m->sibling = sibm;
if (m->parent)
m->parent->children += 1;
}
inbuf->bodyend = inbuf->offset;
inbuf->lineend = inbuf->loffset;
/* Successful return from current part */
return(OK);
}
else
/* parse_message(sibm) failed, data is already rewound
* and sibling remains unattached.
*/
{
inbuf->offset += linelen;
inbuf->loffset += 1;
}
}
else
{
/* boundary_check(m) failed, continue with current */
if (inbuf->bodyend == 0)
/* End not reached because boundary check failed;
* data processing may continue
*/
{
/* Process data.
* If typed data trust types
* and perform boundary checks. If untyped raw rfc822
* data, uuencode or BinHex (who have an explicit
* end), process until that end is found.
*/
if (inbuf->encoding == EBINHEX)
{
if (decode_binhex(m) == NOK)
{
sprintf(ebuf, "WARNING: parse_message: BinHex decode failed :%lu", inbuf->loffset);
#ifdef DEBUG
if (edebug)
fprintf(stderr, "%s\n", ebuf);
#endif
logger(LOG_WARNING, ebuf);
return(NOK);
}
else
{
inbuf->lineend = inbuf->loffset;
inbuf->bodyend = inbuf->offset;
/* return(OK); */
}
}
else
if (inbuf->encoding == EUUENCODE)
{
if (decode_uuencode(m) == NOK)
{
sprintf(ebuf, "WARNING: parse_message: UUdecode failed :%lu", inbuf->loffset);
#ifdef DEBUG
if (edebug)
fprintf(stderr, "%s\n", ebuf);
#endif
logger(LOG_WARNING, ebuf);
return(NOK);
}
else
{
inbuf->lineend = inbuf->loffset;
inbuf->bodyend = inbuf->offset;
/* return(OK); */
}
}
else
/* Trust what we've got and look for boundary */
{
inbuf->offset += linelen;
inbuf->loffset += 1;
}
}
else
/* inbuf->bodyend != 0
* Body end set and reached.
*/
{
do_sibling = TRUE;
}
}
}
else
/* Body end set but not reached, process data */
{
/* Process data.
* If typed data trust types
* and perform boundary checks. If untyped raw rfc822
* data, uuencode or BinHex (who have an explicit
* end), process until that end is found. Done above.
*/
inbuf->offset += linelen;
inbuf->loffset += 1;
}
}
/* End of data */
if (inbuf->bodyend == 0)
inbuf->bodyend = inbuf->offset;
if (inbuf->lineend == 0)
inbuf->lineend = inbuf->loffset;
return(OK);
}
syntax highlighted by Code2HTML, v. 0.9.1