static char rcsid[] = "@(#)$Id: parsarpdat.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__,"header");
/*
Quoting from RFC 822:
5. DATE AND TIME SPECIFICATION
5.1. SYNTAX
date-time = [ day "," ] date time ; dd mm yy
; hh:mm:ss zzz
day = "Mon" / "Tue" / "Wed" / "Thu"
/ "Fri" / "Sat" / "Sun"
date = 1*2DIGIT month 2DIGIT ; day month year
; e.g. 20 Jun 82
month = "Jan" / "Feb" / "Mar" / "Apr"
/ "May" / "Jun" / "Jul" / "Aug"
/ "Sep" / "Oct" / "Nov" / "Dec"
time = hour zone ; ANSI and Military
hour = 2DIGIT ":" 2DIGIT [":" 2DIGIT]
; 00:00:00 - 23:59:59
zone = "UT" / "GMT" ; Universal Time
; North American : UT
/ "EST" / "EDT" ; Eastern: - 5/ - 4
/ "CST" / "CDT" ; Central: - 6/ - 5
/ "MST" / "MDT" ; Mountain: - 7/ - 6
/ "PST" / "PDT" ; Pacific: - 8/ - 7
/ 1ALPHA ; Military: Z = UT;
; A:-1; (J not used)
; M:-12; N:+1; Y:+12
/ ( ("+" / "-") 4DIGIT ) ; Local differential
; hours+min. (HHMM)
*/
int parse_date_time(str,time_zone,size_time_zone,tz_offset, time_result)
CONST char *str;
char *time_zone;
int size_time_zone;
time_t *tz_offset;
time_t *time_result;
{
/*
* Parse a date field in either RFC-822 or Unix date(1) format.
*/
char field[STRING], save_tz[STRING];
int month, day, year, hours, mins, secs, tz, len, i;
/*
* Since this is an RFC-822 field, there might be parenthetical
* comments. Yank them out. Note that strip_parens() returns
* a pointer to static data.
*/
str = strip_parens(str);
/*
* The first field is an optional day of the week. If it exists
* it is supposed to have a trailing comma by RFC-822, but we won't
* complain if it doesn't. If the date string was generated by
* the Unix date(1) command then it won't have the comma. We don't
* do anything with this information, just skip over it if it exists.
*/
if ((len = get_word(str, 0, field, sizeof(field))) < 0)
goto failed;
if (cvt_dayname_to_daynum(field, &i))
str += len;
/*
* Peek at the next character to determine what format to
* parse the rest of the line as.
*/
while (isspace(*str))
++str;
if (!isdigit(*str)) {
/*
* Parse the line in Unix date(1) format. The syntax is:
*
* month day hh:mm:ss [tz] year
*
* e.g. "Jun 21 06:45:44 CDT 1989". The timezone is optional.
*/
DPRINT(Debug,7,(&Debug,
"parse_date_time parsing \"%s\" in time(1) format\n",
str));
/* <month> */
if ((len = get_word(str, 0, field, sizeof(field))) < 0 ||
!cvt_monthname_to_monthnum(field, &month))
goto failed;
str += len;
/* <day> */
if ((len = get_word(str, 0, field, sizeof(field))) < 0 ||
(day = atonum(field)) < 0)
goto failed;
str += len;
/* <hh:mm:ss> */
if ((len = get_word(str, 0, field, sizeof(field))) < 0 ||
!cvt_timestr_to_hhmmss(field, &hours, &mins, &secs))
goto failed;
str += len;
/* optional <tz> */
save_tz[0] = save_tz[1] = '\0';
tz = 0;
while ((len = get_word(str, 0, field, sizeof(field))) > 0 &&
cvt_timezone_to_offset(field, &i, sizeof field)) {
(void) strfcat(save_tz, " ", sizeof save_tz);
(void) strfcat(save_tz, field, sizeof save_tz);
tz += i;
str += len;
}
/* <year> */
if ((len = get_word(str, 0, field, sizeof(field))) < 0 ||
(year = atonum(field)) < 0)
goto failed;
str += len;
/* there might be more...but we ignore it */
} else {
/*
* Parse the line in RFC-822 format. The syntax is:
*
* day month year hh:mm:ss zone
*
* e.g. "17 Nov 92 23:34:25 CST".
*/
DPRINT(Debug,7,(&Debug,
"parse_date_time parsing \"%s\" in RFC-822 format\n",
str));
/* <day> */
if ((len = get_word(str, 0, field, sizeof(field))) < 0 ||
(day = atonum(field)) < 0)
goto failed;
str += len;
/* <month> */
if ((len = get_word(str, 0, field, sizeof(field))) < 0 ||
!cvt_monthname_to_monthnum(field, &month))
goto failed;
str += len;
/* <year> */
if ((len = get_word(str, 0, field, sizeof(field))) < 0 ||
!cvt_yearstr_to_yearnum(field, &year))
goto failed;
str += len;
/* <hh:mm:ss> */
if ((len = get_word(str, 0, field, sizeof(field))) < 0) {
/* on expires header there is no necessary time -part */
save_tz[0] = save_tz[1] = '\0';
tz = 0;
hours = 0;
mins = 0;
secs = 0;
DPRINT(Debug,7,(&Debug,
" only date given (no time and timezone)\n"));
goto notime;
}
if (!cvt_timestr_to_hhmmss(field, &hours, &mins, &secs))
goto failed;
str += len;
/* <tz> - silently ignore bogus or missing timezones */
save_tz[0] = save_tz[1] = '\0';
tz = 0;
while ((len = get_word(str, 0, field, sizeof(field))) > 0 &&
cvt_timezone_to_offset(field, &i, sizeof field)) {
(void) strfcat(save_tz, " ", sizeof save_tz);
(void) strfcat(save_tz, field, sizeof save_tz);
tz += i;
str += len;
}
/* there might be more...but we ignore it */
}
notime:
if (time_zone)
strfcpy(time_zone, save_tz+1, size_time_zone);
if (tz_offset)
*tz_offset = tz*60;
*time_result = make_gmttime(year, month, day, hours, mins-tz, secs);
DPRINT(Debug,7,(&Debug, " year=%d month=%d day=%d\n", year, month, day));
DPRINT(Debug,7,(&Debug, " hours=%d mins=%d secs=%d tz=%d\n",
hours, mins, secs, tz));
DPRINT(Debug,7,(&Debug, " time_result=%ld\n",(long)*time_result));
DPRINT(Debug,7,(&Debug, " return success\n"));
return TRUE;
failed:
DPRINT(Debug,4,(&Debug, "parse_date_time failed at \"%s\"\n",
(len <= 0 ? "<premature eol>" : field)));
return FALSE;
}
int parse_arpa_date(src, entry)
char *src;
struct header_rec *entry;
{
/*
* Parse a date field in either RFC-822 or Unix date(1) format.
* We will fill in the "time_zone", "tz_offset", and "time_sent"
* parts of the "entry" structure. Return TRUE on success, FALSE
* on failure.
*/
if (parse_date_time(src,
entry->time_zone,sizeof(entry->time_zone),
&(entry->tz_offset), &(entry->time_sent))) {
DPRINT(Debug,7,(&Debug,
"parse_arpa_date SUCCESS for %s\n",src));
return TRUE;
}
DPRINT(Debug,7,(&Debug,
"parse_arpa_date failed for %s\n",src));
return FALSE;
}
#ifdef _TEST
int debug = 9999;
main()
{
struct header_rec hdr;
char buf[1024];
while (gets(buf) != NULL) {
if (!parse_arpa_date(buf, &hdr))
fprintf(stderr, "FAIL %s\n", buf);
else {
fprintf(stderr, "OK %s\n", buf);
fprintf(stderr, "time_zone=%s tz_offset=%d time_sent=%ld\n",
hdr.time_zone, hdr.tz_offset, hdr.time_sent);
}
putc('\n', stderr);
}
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