From db60ade81d43e9aaf03273d162878a9cc976f57b Mon Sep 17 00:00:00 2001
From: Vis Virial <visvrial@gmail.com>
Date: Thu, 10 Nov 2016 21:58:15 +0900
Subject: [PATCH] http: do not use local settings for Date header

---
 evutil_time.c         | 28 ++++++++++++++++++++++++++++
 http.c                | 15 +--------------
 include/event2/util.h | 11 +++++++++++
 3 files changed, 40 insertions(+), 14 deletions(-)

diff --git a/evutil_time.c b/evutil_time.c
index 32da2d6e..3a8424ea 100644
--- a/evutil_time.c
+++ b/evutil_time.c
@@ -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
diff --git a/http.c b/http.c
index 3c4116de..f5a2ef93 100644
--- a/http.c
+++ b/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);
 		}
 	}
diff --git a/include/event2/util.h b/include/event2/util.h
index 2c43e30e..defe00a3 100644
--- a/include/event2/util.h
+++ b/include/event2/util.h
@@ -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
-- 
2.40.0