/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "str.h"
#include "utc-mktime.h"
#include "http-date.h"
#include <ctype.h>
The defined syntax is as follows:
HTTP-date = IMF-fixdate / obs-date
Preferred format:
IMF-fixdate = day-name "," SP date1 SP time-of-day SP GMT
; fixed length/zone/capitalization subset of the format
; see Section 3.3 of [RFC5322]
day-name = %x4D.6F.6E ; "Mon", case-sensitive
/ %x54.75.65 ; "Tue", case-sensitive
/ %x57.65.64 ; "Wed", case-sensitive
/ %x54.68.75 ; "Thu", case-sensitive
/ %x46.72.69 ; "Fri", case-sensitive
/ %x53.61.74 ; "Sat", case-sensitive
/ %x53.75.6E ; "Sun", case-sensitive
date1 = day SP month SP year
; e.g., 02 Jun 1982
day = 2DIGIT
month = %x4A.61.6E ; "Jan", case-sensitive
/ %x46.65.62 ; "Feb", case-sensitive
/ %x4D.61.72 ; "Mar", case-sensitive
/ %x41.70.72 ; "Apr", case-sensitive
/ %x4D.61.79 ; "May", case-sensitive
/ %x4A.75.6E ; "Jun", case-sensitive
/ %x4A.75.6C ; "Jul", case-sensitive
/ %x41.75.67 ; "Aug", case-sensitive
/ %x53.65.70 ; "Sep", case-sensitive
/ %x4F.63.74 ; "Oct", case-sensitive
/ %x4E.6F.76 ; "Nov", case-sensitive
/ %x44.65.63 ; "Dec", case-sensitive
year = 4DIGIT
GMT = %x47.4D.54 ; "GMT", case-sensitive
time-of-day = hour ":" minute ":" second
; 00:00:00 - 23:59:60 (leap second)
hour = 2DIGIT
minute = 2DIGIT
second = 2DIGIT
Obsolete formats:
obs-date = rfc850-date / asctime-date
rfc850-date = day-name-l "," SP date2 SP time-of-day SP GMT
date2 = day "-" month "-" 2DIGIT
; e.g., 02-Jun-82
day-name-l = %x4D.6F.6E.64.61.79 ; "Monday", case-sensitive
/ %x54.75.65.73.64.61.79 ; "Tuesday", case-sensitive
/ %x57.65.64.6E.65.73.64.61.79 ; "Wednesday", case-sensitive
/ %x54.68.75.72.73.64.61.79 ; "Thursday", case-sensitive
/ %x46.72.69.64.61.79 ; "Friday", case-sensitive
/ %x53.61.74.75.72.64.61.79 ; "Saturday", case-sensitive
/ %x53.75.6E.64.61.79 ; "Sunday", case-sensitive
asctime-date = day-name SP date3 SP time-of-day SP year
date3 = month SP ( 2DIGIT / ( SP 1DIGIT ))
; e.g., Jun 2
*/
static const char *month_names[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
static const char *weekday_names[] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
static const char *weekday_names_long[] = {
"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
};
struct http_date_parser {
int timezone_offset;
};
static inline int
{
return -1;
return 0;
return 1;
}
static inline int
{
int i;
return 0;
for (i=0; i < digits-1; i++) {
return -1;
}
return 1;
}
static inline int
{
int i;
return 0;
for (i=0; i < maxchars-1; i++) {
break;
}
return -1;
return 1;
}
static inline int
{
/* year = 4DIGIT */
return -1;
return -1;
return 1;
}
static inline int
{
int i;
return -1;
for (i = 0; i < 12; i++) {
break;
}
}
if (i >= 12)
return -1;
return 1;
}
static inline int
{
/* day = 2DIGIT */
return -1;
return 1;
}
static int
{
/* time-of-day = hour ":" minute ":" second
; 00:00:00 - 23:59:59
hour = 2DIGIT
minute = 2DIGIT
second = 2DIGIT
*/
/* hour = 2DIGIT */
return -1;
/* ":" */
return -1;
/* minute = 2DIGIT */
return -1;
/* ":" */
return -1;
/* second = 2DIGIT */
return -1;
return 1;
}
static inline int
{
/* Remaining: {...} SP time-of-day SP GMT
*/
/* SP time-of-day */
if (http_date_parse_sp(parser) <= 0)
return -1;
if (http_date_parse_time_of_day(parser) <= 0)
return -1;
/* SP GMT */
if (http_date_parse_sp(parser) <= 0)
return -1;
return -1;
return 1;
}
static int
{
/*
IMF-fixdate = day-name "," SP date1 SP time-of-day SP GMT
; fixed length/zone/capitalization subset of the format
; see Section 3.3 of [RFC5322]
date1 = day SP month SP year
; e.g., 02 Jun 1982
Remaining: {...} SP day SP month SP year SP time-of-day SP GMT
*/
/* SP day */
if (http_date_parse_sp(parser) <= 0)
return -1;
if (http_date_parse_day(parser) <= 0)
return -1;
/* SP month */
if (http_date_parse_sp(parser) <= 0)
return -1;
if (http_date_parse_month(parser) <= 0)
return -1;
/* SP year */
if (http_date_parse_sp(parser) <= 0)
return -1;
if (http_date_parse_year(parser) <= 0)
return -1;
/* SP time-of-day SP GMT */
return http_date_parse_time_gmt(parser);
}
static int
{
/*
rfc850-date = day-name-l "," SP date2 SP time-of-day SP GMT
date2 = day "-" month "-" 2DIGIT
; day-month-year (e.g., 02-Jun-82)
Remaining: "," SP day "-" month "-" 2DIGIT SP time-of-day SP GMT
*/
/* "," SP */
return -1;
if (http_date_parse_sp(parser) <= 0)
return -1;
/* day */
if (http_date_parse_day(parser) <= 0)
return -1;
/* "-" */
return -1;
/* month */
if (http_date_parse_month(parser) <= 0)
return -1;
/* "-" */
return -1;
/* 2DIGIT */
return -1;
/* SP time-of-day SP GMT */
return http_date_parse_time_gmt(parser);
}
static int
{
int ret;
/*
asctime-date = day-name SP date3 SP time-of-day SP year
date3 = month SP ( 2DIGIT / ( SP 1DIGIT ))
; month day (e.g., Jun 2)
Remaining: {...} month SP ( 2DIGIT / ( SP 1DIGIT )) SP time-of-day SP year
*/
/* month */
if (http_date_parse_month(parser) <= 0)
return -1;
/* SP */
if (http_date_parse_sp(parser) <= 0)
return -1;
/* SP 1DIGIT / 2DIGIT */
return -1;
if (ret == 0) {
return -1;
} else {
return -1;
}
/* SP time-of-day */
if (http_date_parse_sp(parser) <= 0)
return -1;
if (http_date_parse_time_of_day(parser) <= 0)
return -1;
/* SP year */
if (http_date_parse_sp(parser) <= 0)
return -1;
return http_date_parse_year(parser);
}
static int
{
int i;
/*
HTTP-date = IMF-fixdate / obs-date
IMF-fixdate = day-name "," SP date1 SP time-of-day SP GMT
; fixed length/zone/capitalization subset of the format
; see Section 3.3 of [RFC5322]
obs-date = rfc850-date / asctime-date
rfc850-date = day-name-l "," SP date2 SP time-of-day SP GMT
asctime-date = day-name SP date3 SP time-of-day SP year
*/
return -1;
/* rfc850-date */
for (i = 0; i < 7; i++) {
break;
}
}
if (i >= 7)
return -1;
return http_date_parse_format_rfc850(parser);
}
/* IMF-fixdate / asctime-date */
for (i = 0; i < 7; i++) {
break;
}
}
return -1;
/* asctime-date */
return http_date_parse_format_asctime(parser);
}
return -1;
/* IMF-fixdate */
return http_date_parse_format_imf_fixdate(parser);
}
{
if (http_date_parse_format_any(&parser) <= 0)
return FALSE;
return FALSE;
return FALSE;
*timestamp_r = timestamp;
return TRUE;
}
{
return FALSE;
return TRUE;
}
{
return t_strdup_printf("%s, %02d %s %04d %02d:%02d:%02d GMT",
}
{
return http_date_create_tm(tm);
}