/*
**
** 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"
#define HQUOTE -1
/* Function definitions */
void process_header_line(struct header *, char *);
void save_header(struct message *, struct data *, short, int);
void clear_end(struct data *);
void add_header_item();
void add_header_delimiter();
static void code_header(struct header *);
static void code_hvalue(struct hprs *, struct data *);
int isheader(char *);
/*
*
*/
int
load_header(struct message *m)
{
struct data *line_buf;
struct data *indata;
int linelen;
long startoffset;
long startline;
char *buf;
indata = m->sd;
line_buf = (struct data *)Yalloc(sizeof (struct data));
/*
* Make sure there is data to process, else exit.
*/
if (indata->end <= indata->offset)
return(OK);
startoffset = indata->offset;
startline = indata->loffset;
/*
* If current header is not empty, look for folded header lines.
*/
while (1)
{
buf = indata->contents + indata->offset;
if ((linelen = getline(indata)) == 0)
{
/* End of data, illegal header */
indata->offset = startoffset; /* Rewind */
indata->loffset = startline; /* Rewind */
m->h = NULL;
return(NOK);
}
#ifdef DEBUG
if (edebug)
{
fprintf(stderr, "Read: ");
fwrite(indata->contents + indata->offset, 1, linelen, stderr);
}
#endif
indata->loffset += 1;
if ((*buf == ' ' || *buf == '\t') && line_buf->end != 0)
{
/* Unfold header line and append to previos line */
/* clear_end(line_buf); */
append_data(line_buf, buf, linelen, HEAD_BUF);
}
else
/* Not folded yet */
{
if (line_buf->end != 0)
/* If no header line yet, append header line */
/* Already got header line */
{
if (strncasecmp(line_buf->contents, "from ", 5) == 0 ||
strncasecmp(line_buf->contents,">from ", 6) == 0)
{
/* Process folded UNIX from line */
save_header(m, line_buf, (short) UNIXFROM, RFC822);
line_buf->end = 0;
*(line_buf->contents) = '\0';
}
else
{
if (isheader(line_buf->contents))
{
save_header(m, line_buf, (short) EMHEADER, m->sd->format);
line_buf->end = 0;
*(line_buf->contents) = '\0';
}
else
{
/* Syntax error or end of header */
indata->offset = startoffset; /* Rewind */
sprintf(ebuf, "load_header: illegal end of header: %s", line_buf->contents);
logger(LOG_ERR, ebuf);
m->h = NULL;
return(NOK);
}
}
}
}
if((linelen == 1 && *buf == '\n') || (linelen == 2 && *buf == '\r'))
{
/* End of header */
indata->offset++;
return(OK);
}
if (line_buf->end == 0)
{
append_data(line_buf, buf, linelen, HEAD_BUF);
}
indata->offset += linelen;
}
/* Not reached */
}
/*
*
*/
void
clear_end(struct data *d)
{
if (*(d->contents + d->end - 1) == '\n')
{
if (*(d->contents + d->end - 2) == '\r')
{
*(d->contents + d->end - 2) = '\0';
d->end -= 2;
}
else
{
*(d->contents + d->end - 1) = '\0';
d->end -= 1;
}
}
}
/*
* save_header()
*
* Save the header field and header value in a list of header structures.
*
*/
void
save_header(struct message *mess, struct data *line, short type, int format)
{
struct header *hdr, *thdr;
char *value;
hdr = (struct header *)Yalloc(sizeof(struct header));
hdr->type = type;
hdr->format = format;
clear_end(line);
#ifdef DEBUG
if (edebug)
fprintf(stderr, "+ Save header: %s\n", line->contents);
#endif
hdr->field = (struct data *)Yalloc(sizeof(struct data ));
if (type == UNIXFROM)
append_data(hdr->field, line->contents, line->end, HEAD_BUF);
else
{
hdr->value = (struct data *)Yalloc(sizeof(struct data ));
value = index(line->contents, ':'); assert(value);
*value = '\0';
value++;
while(isspace(*value))
value++;
append_data(hdr->field, line->contents, strlen(line->contents), HEAD_BUF);
append_data(hdr->value, value, strlen(value), HEAD_BUF);
}
if (mess->h == NULL)
mess->h = hdr;
else
{
for (thdr = mess->h; thdr->next != NULL; thdr = thdr->next)
;
thdr->next = hdr;
}
code_header(hdr);
}
void
add_header(struct message *mess, char *field, char *value, int format)
{
struct header *hdr, *thdr;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "+ Add header: %s: %s\n", field, value);
#endif
if (mess->h != NULL)
for (thdr = mess->h; thdr != NULL; thdr = thdr->next)
{
if (thdr->field->end != 0 &&
cmatch(thdr->field->contents, field) == TRUE)
{
thdr->value->offset = 0;
thdr->value->end = 0;
thdr->value->bodyend = 0;
append_data(thdr->value, value, strlen(value), HEAD_BUF);
append_char(thdr->value, '\0', HEAD_BUF); /* NULL terminate */
thdr->format = format;
thdr->hvalue = NULL;
return;
}
hdr = thdr;
}
thdr = hdr;
hdr = (struct header *)Yalloc(sizeof(struct header));
hdr->type = EMHEADER;
hdr->format = format;
hdr->field = (struct data *)Yalloc(sizeof(struct data ));
hdr->value = (struct data *)Yalloc(sizeof(struct data ));
append_data(hdr->field, field, strlen(field), HEAD_BUF);
if (value != NULL)
append_data(hdr->value, value, strlen(value), HEAD_BUF);
if (mess->h == NULL)
mess->h = hdr;
else
thdr->next = hdr;
}
void
rm_header(struct message *mess, char *field)
{
struct header *hdr, *thdr;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "+ Remove header: %s: **\n", field);
#endif
if (mess->h != NULL)
for (thdr = mess->h; thdr != NULL; thdr = thdr->next)
{
if (thdr->field->end != 0 &&
cmatch(thdr->field->contents, field) == TRUE)
{
if (thdr != NULL && thdr == mess->h)
mess->h = thdr->next;
else
hdr->next = thdr->next;
break;
}
hdr = thdr;
}
}
int
isheader(char *string)
{
char *t, *p;
if ((t = index(string, ':')) == NULL || t == string)
return(0);
if ((p = index(string, ' ')) != NULL && p < t)
return(0);
return(1);
}
static void code_header(struct header *th)
{
struct data *outbuf;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "+ code_header.\n");
#endif
parse_rfc1522(th);
if (th->hvalue != NULL)
{
outbuf = (struct data *)Yalloc(sizeof(struct data));
(void)code_hvalue(th->hvalue, outbuf);
th->value = outbuf;
}
}
static void code_hvalue(struct hprs *h, struct data *outbuf)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "+ code_hvalue.\n");
#endif
switch (h->type)
{
case ATOM:
case DELIMITER:
case RFC1522:
append_data(outbuf, h->td->contents + h->td->bodystart,
h->td->bodyend - h->td->bodystart, HEAD_BUF);
break;
case DLITERAL:
append_char(outbuf, '[', HEAD_BUF);
break;
case COMMENT:
append_char(outbuf, '(', HEAD_BUF);
break;
case HQSTRING:
append_char(outbuf, '"', HEAD_BUF);
break;
case RADDR:
append_char(outbuf, '<', HEAD_BUF);
break;
default:
break;
}
if (h->child != NULL)
code_hvalue(h->child, outbuf);
switch(h->type)
{
case DLITERAL:
append_char(outbuf, ']', HEAD_BUF);
break;
case COMMENT:
append_char(outbuf, ')', HEAD_BUF);
break;
case HQSTRING:
append_char(outbuf, '"', HEAD_BUF);
break;
case RADDR:
append_char(outbuf, '>', HEAD_BUF);
break;
default:
break;
}
if (h->sibling != NULL)
code_hvalue(h->sibling, outbuf);
}
char *
clear_end_space(char *c)
{
char *d;
d = c + strlen(c) -1;
while (isspace(*d))
{
*d = '\0';
d--;
}
return(c);
}
syntax highlighted by Code2HTML, v. 0.9.1