mirror of
https://github.com/libevent/libevent.git
synced 2025-01-31 09:12:55 +08:00
Merge branch 'date-rfc1123'
Follow RFC2616 (Date header should be in RFC1123 format). But to reproduce this bug, program that uses libevent http-server should call `setlocale(LC_ALL, "")` to properly initliaze locale, so that strftime() retruns locale-specific dates. * date-rfc1123: add tests for evutil_date_rfc1123(). http: do not use local settings for Date header Closes: #417
This commit is contained in:
commit
68def4352c
@ -145,6 +145,34 @@ evutil_usleep_(const struct timeval *tv)
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
evutil_date_rfc1123(char *date, const size_t datelen, struct tm *cur_p) {
|
||||
static const char *DAYS[] =
|
||||
{ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
|
||||
static const char *MONTHS[] =
|
||||
{ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
|
||||
|
||||
time_t t = time(NULL);
|
||||
|
||||
/* If `cur_p` is null, set system's current time. */
|
||||
if (cur_p == NULL) {
|
||||
#ifdef _WIN32
|
||||
cur_p = gmtime(&t);
|
||||
#else
|
||||
{
|
||||
struct tm cur;
|
||||
gmtime_r(&t, &cur);
|
||||
cur_p = &cur;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return evutil_snprintf(
|
||||
date, datelen, "%s, %02d %s %4d %02d:%02d:%02d GMT",
|
||||
DAYS[cur_p->tm_wday], cur_p->tm_mday, MONTHS[cur_p->tm_mon],
|
||||
1900+cur_p->tm_year, cur_p->tm_hour, cur_p->tm_min, cur_p->tm_sec);
|
||||
}
|
||||
|
||||
/*
|
||||
This function assumes it's called repeatedly with a
|
||||
not-actually-so-monotonic time source whose outputs are in 'tv'. It
|
||||
|
15
http.c
15
http.c
@ -80,7 +80,6 @@
|
||||
#include <syslog.h>
|
||||
#endif
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#ifdef EVENT__HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
@ -491,19 +490,7 @@ evhttp_maybe_add_date_header(struct evkeyvalq *headers)
|
||||
{
|
||||
if (evhttp_find_header(headers, "Date") == NULL) {
|
||||
char date[50];
|
||||
#ifndef _WIN32
|
||||
struct tm cur;
|
||||
#endif
|
||||
struct tm *cur_p;
|
||||
time_t t = time(NULL);
|
||||
#ifdef _WIN32
|
||||
cur_p = gmtime(&t);
|
||||
#else
|
||||
gmtime_r(&t, &cur);
|
||||
cur_p = &cur;
|
||||
#endif
|
||||
if (strftime(date, sizeof(date),
|
||||
"%a, %d %b %Y %H:%M:%S GMT", cur_p) != 0) {
|
||||
if (sizeof(date) - evutil_date_rfc1123(date, sizeof(date), NULL) > 0) {
|
||||
evhttp_add_header(headers, "Date", date);
|
||||
}
|
||||
}
|
||||
|
@ -77,6 +77,8 @@ extern "C" {
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#include <time.h>
|
||||
|
||||
/* Some openbsd autoconf versions get the name of this macro wrong. */
|
||||
#if defined(EVENT__SIZEOF_VOID__) && !defined(EVENT__SIZEOF_VOID_P)
|
||||
#define EVENT__SIZEOF_VOID_P EVENT__SIZEOF_VOID__
|
||||
@ -331,6 +333,15 @@ struct evutil_monotonic_timer
|
||||
#define EV_MONOT_PRECISE 1
|
||||
#define EV_MONOT_FALLBACK 2
|
||||
|
||||
/** Format a date string using RFC 1123 format (used in HTTP).
|
||||
* If `cur_p` is NULL, current system's time will be used.
|
||||
* The number of characters written will be returned.
|
||||
* One should check if the return value is smaller than `datelen` to check if
|
||||
* the result is truncated or not.
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evutil_date_rfc1123(char *date, const size_t datelen, struct tm *cur_p);
|
||||
|
||||
/** Allocate a new struct evutil_monotonic_timer for use with the
|
||||
* evutil_configure_monotonic_time() and evutil_gettime_monotonic()
|
||||
* functions. You must configure the timer with
|
||||
|
@ -1378,6 +1378,70 @@ end:
|
||||
;
|
||||
}
|
||||
|
||||
static void
|
||||
create_tm_from_unix_epoch(struct tm *cur_p, const time_t t) {
|
||||
#ifdef _WIN32
|
||||
cur_p = gmtime(&t);
|
||||
#else
|
||||
gmtime_r(&t, cur_p);
|
||||
#endif
|
||||
}
|
||||
|
||||
static struct date_rfc1123_case {
|
||||
time_t t;
|
||||
char date[30];
|
||||
} date_rfc1123_cases[] = {
|
||||
{ 0, "Thu, 01 Jan 1970 00:00:00 GMT"} /* UNIX time of zero */,
|
||||
{ 946684799, "Fri, 31 Dec 1999 23:59:59 GMT"} /* the last moment of the 20th century */,
|
||||
{ 946684800, "Sat, 01 Jan 2000 00:00:00 GMT"} /* the first moment of the 21st century */,
|
||||
{ 981072000, "Fri, 02 Feb 2001 00:00:00 GMT"},
|
||||
{ 1015113600, "Sun, 03 Mar 2002 00:00:00 GMT"},
|
||||
{ 1049414400, "Fri, 04 Apr 2003 00:00:00 GMT"},
|
||||
{ 1083715200, "Wed, 05 May 2004 00:00:00 GMT"},
|
||||
{ 1118016000, "Mon, 06 Jun 2005 00:00:00 GMT"},
|
||||
{ 1152230400, "Fri, 07 Jul 2006 00:00:00 GMT"},
|
||||
{ 1186531200, "Wed, 08 Aug 2007 00:00:00 GMT"},
|
||||
{ 1220918400, "Tue, 09 Sep 2008 00:00:00 GMT"},
|
||||
{ 1255132800, "Sat, 10 Oct 2009 00:00:00 GMT"},
|
||||
{ 1289433600, "Thu, 11 Nov 2010 00:00:00 GMT"},
|
||||
{ 1323648000, "Mon, 12 Dec 2011 00:00:00 GMT"},
|
||||
{ 4294967296, "Sun, 07 Feb 2106 06:28:16 GMT"} /* 2^32 */,
|
||||
{253402300799, "Fri, 31 Dec 9999 23:59:59 GMT"} /* long long future no one can imagine */,
|
||||
{ 1456704000, "Mon, 29 Feb 2016 00:00:00 GMT"} /* leap year */,
|
||||
{ 1435708800, "Wed, 01 Jul 2015 00:00:00 GMT"} /* leap second */,
|
||||
{ 1481866376, "Fri, 16 Dec 2016 05:32:56 GMT"} /* the time this test case is generated */,
|
||||
{0, ""} /* end of test cases. */
|
||||
};
|
||||
|
||||
static void
|
||||
test_evutil_date_rfc1123(void *arg)
|
||||
{
|
||||
struct tm query;
|
||||
char result[30];
|
||||
|
||||
/* Checks if too small buffers are safely accepted. */
|
||||
{
|
||||
create_tm_from_unix_epoch(&query, 0);
|
||||
evutil_date_rfc1123(result, 8, &query);
|
||||
tt_str_op(result, ==, "Thu, 01");
|
||||
}
|
||||
|
||||
/* Checks for testcases. */
|
||||
for (size_t i=0; ; i++) {
|
||||
struct date_rfc1123_case c = date_rfc1123_cases[i];
|
||||
|
||||
if (strlen(c.date) == 0)
|
||||
break;
|
||||
|
||||
create_tm_from_unix_epoch(&query, c.t);
|
||||
evutil_date_rfc1123(result, sizeof(result), &query);
|
||||
tt_str_op(result, ==, c.date);
|
||||
}
|
||||
|
||||
end:
|
||||
;
|
||||
}
|
||||
|
||||
struct testcase_t util_testcases[] = {
|
||||
{ "ipv4_parse", regress_ipv4_parse, 0, NULL, NULL },
|
||||
{ "ipv6_parse", regress_ipv6_parse, 0, NULL, NULL },
|
||||
@ -1408,6 +1472,7 @@ struct testcase_t util_testcases[] = {
|
||||
{ "monotonic_prc", test_evutil_monotonic_prc, 0, &basic_setup, (void*)"" },
|
||||
{ "monotonic_prc_precise", test_evutil_monotonic_prc, 0, &basic_setup, (void*)"precise" },
|
||||
{ "monotonic_prc_fallback", test_evutil_monotonic_prc, 0, &basic_setup, (void*)"fallback" },
|
||||
{ "date_rfc1123", test_evutil_date_rfc1123, 0, NULL, NULL },
|
||||
END_OF_TESTCASES,
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user