static char rcsid[] = "@(#)$Id: realfrom.c,v 1.3 2006/04/09 07:37:08 hurtta Exp $";
/******************************************************************************
* The Elm (ME+) Mail System - $Revision: 1.3 $ $State: Exp $
*
* Modified by: Kari Hurtta <hurtta+elm@posti.FMI.FI>
* (was hurtta+elm@ozone.FMI.FI)
******************************************************************************
* The Elm Mail System
*
* Copyright (c) 1993 USENET Community Trust
*****************************************************************************/
#include "def_mbox.h"
DEBUG_VAR(Debug,__FILE__,"addr");
int real_from(buffer, entry)
char *buffer;
struct header_rec *entry;
{
/*
* Breakup and validate the "From_" line in the "buffer". If "entry"
* is not NULL then the structure is filled in with sender and time
* information. Returns TRUE if the "From_" line is valid, otherwise
* FALSE.
*
* A valid from line will be in the following format:
*
* From <user> <weekday> <month> <day> <hr:min:sec>
* [TZ1 [TZ2]] <year> [remote from sitelist]
*
* We insist that all of the <angle bracket> fields are present.
* If two timezone fields are present, the first is used for date
* information. We do not look at anything beyond the <year> field.
* We just insist that everything up to the <year> field is present
* and valid.
*/
char field[STRING]; /* buffer for current field of line */
char field2[STRING]; /* buffer for current field of line */
char field3[STRING]; /* buffer for current field of line */
char save_tz[STRING]; /* extracted time zone field */
int len=0; /* length of current field */
int month, day, year, hours, mins, secs, tz, i;
int ef = give_dt_enumerate_as_int(&env_from_source);
int islocal = 0;
/*
* Zero out the portions of the record we fill in.
*/
if (entry != NULL) {
entry->time_zone[0] = '\0';
entry->env_from[0] = '\0';
entry->time_sent = 0;
entry->received_time = 0;
entry->tz_offset = 0;
}
/* env_from_source:
0 == forward-from,
1 == from,
2 == return-path
*/
DPRINT(Debug,9,(&Debug,
"env_from_source=%d\n",ef));
/* From */
if (strncmp(buffer, "From ", 5) != 0) {
DPRINT(Debug,4,(&Debug,
"real_from failed at beginning: \"*.5s\"",buffer));
return FALSE;
}
buffer += 5;
DPRINT(Debug,7,(&Debug,
"real_from parsing %s", buffer));
/* <user> or <weekday> */
if ((len = get_word(buffer, 0, field, sizeof(field))) < 0)
goto failed;
buffer += len;
/* <weekday> or <month> */
if ((len = get_word(buffer, 0, field2, sizeof(field2))) < 0)
goto failed;
buffer += len;
/* <month> or <day> */
if ((len = get_word(buffer, 0, field3, sizeof(field3))) < 0 )
goto failed;
buffer += len;
/* is <month> in field2 or field3? */
if (!cvt_monthname_to_monthnum(field3, &month))
if (!cvt_monthname_to_monthnum(field2, &month))
goto failed;
else {
/* field2 is month, field3 is day */
if (ef < 2) {
/* <user> */
if (entry != NULL)
*( entry->env_from ) = '\0';
DPRINT(Debug,7,(&Debug,
" user=\n"));
}
/* <day> */
if ((day = atonum(field3)) < 0 || day < 1 || day > 31)
goto failed;
}
else {
if (ef < 2) {
char *X = field;
int l;
if (0 != strcmp(field,"<>") &&
'<' == field[0] &&
(l = strlen(field)) &&
'>' == field[l-1]) {
X = field+1;
field[l-1] = '\0';
}
/* <user> */
if (entry != NULL)
strfcpy(entry->env_from, X, sizeof(entry->env_from));
DPRINT(Debug,7,(&Debug,
" user=%s\n", X));
}
/* <day> */
if ((len = get_word(buffer, 0, field, sizeof(field))) < 0 ||
(day = atonum(field)) < 0 || day < 1 || day > 31)
goto failed;
buffer += len;
}
/* <hr:min:sec> */
if ((len = get_word(buffer, 0, field, sizeof(field))) < 0 ||
!cvt_timestr_to_hhmmss(field, &hours, &mins, &secs))
goto failed;
buffer += len;
DPRINT(Debug,7,(&Debug,
" hours=%d mins=%d secs=%d\n", hours, mins, secs));
/*
* [ <tz> ... ] <year>
*
* This is messy. Not only is the timezone field optional, there
* might be multiple fields (e.g. "MET DST"), or it might be entirely
* bogus (e.g. some MTAs produce "0600" instead of "+0600".
*/
tz = 0;
save_tz[0] = save_tz[1] = '\0';
for (;;) {
if ((len = get_word(buffer, 0, field, sizeof(field))) < 0)
goto failed;
buffer += len;
/*
* First check if this is a TZ field. If so, pull in the info
* and continue onto the next field.
*/
if (cvt_timezone_to_offset(field, &i, sizeof field)) {
tz += i;
i = strlen(save_tz);
(void) strfcpy(save_tz+i, " ", sizeof(save_tz)-i);
++i;
(void) strfcpy(save_tz+i, field, sizeof(save_tz)-i);
continue;
}
/*
* If this isn't a valid TZ then it should be a year. If so
* then save off the year info and break out of this loop.
*/
if (cvt_yearstr_to_yearnum(field, &year))
break;
/*
* This isn't either a valid TZ or year. Assume it is a bogus
* timezone we don't understand, and continue processing the line.
*/
DPRINT(Debug,7,(&Debug,
" assuming \"%s\" is a bogus timezone, skipping it\n",
field));
}
if (!save_tz[0] && tz == 0) {
/* Assume local timezone */
long tzmin; /* number of minutes off gmt */
int tzsign; /* + or - gmt */
/* Try take account that timezone is different on summer time */
time_t XXX = make_gmttime(year, month, day, hours, mins, secs);
if ((tz = (tzmin = -get_tz_mins(XXX))) >= 0) {
tzsign = '+';
} else {
tzsign = '-';
tzmin = -tzmin;
}
elm_sfprintf(save_tz, sizeof save_tz,
FRM(" %c%02d%02d"),
tzsign,tzmin / 60, tzmin % 60);
DPRINT(Debug,7,(&Debug,
" assuming local timezone %s", save_tz));
islocal++;
}
if (entry != NULL) {
entry->tz_offset = tz * 60;
(void) strfcpy(entry->time_zone, save_tz+1, sizeof(entry->time_zone));
entry->received_time = entry->time_sent =
make_gmttime(year, month, day, hours, mins-tz, secs);
}
DPRINT(Debug,7,(&Debug,
" tz=%s tz_offset=%d", save_tz+1, tz));
DPRINT(Debug,7,(&Debug,
" month=%d day=%d year=%d\n", month, day, year));
if (islocal && entry) { /* Debug */
char * buf = ctime(& entry->received_time);
DPRINT(Debug,7,(&Debug," ctime=%s",buf));
}
/*
* The line is parsed and valid. There might be more but we don't care.
*/
DPRINT(Debug,7,(&Debug,
" return success\n"));
return TRUE;
failed:
DPRINT(Debug,4,(&Debug,
"real_from failed at \"%s\"\n",
(len <= 0 ? "<premature eol>" : field)));
return FALSE;
}
#ifdef _TEST
int debug = 9999;
main()
{
struct header_rec hdr;
char buf[1024];
extern char *ctime();
while (gets(buf) != NULL) {
if (!real_from(buf, &hdr))
printf("FAIL %s\n", buf);
else {
printf("OK %s\n", buf);
printf("from=%s time_zone=%s tz_offset=%d\n",
hdr.env_from, hdr.time_zone, hdr.tz_offset);
printf("time_sent=%ld received_time=%ld %s",
hdr.time_sent, hdr.received_time, ctime(&hdr.received_time));
}
putchar('\n');
}
exit(0);
}
#endif
/*
* Local Variables:
* mode:c
* c-basic-offset:4
* buffer-file-coding-system: iso-8859-1
* End:
*/
syntax highlighted by Code2HTML, v. 0.9.1