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