Browse Source

[core] http_date_timegm() (portable timegm())

move from mod_openssl.c
master
Glenn Strauss 7 months ago
parent
commit
a0b615acd9
  1. 38
      src/http_date.c
  2. 10
      src/http_date.h
  3. 21
      src/mod_openssl.c

38
src/http_date.c

@ -276,26 +276,24 @@ http_date_time_to_str (char * const s, const size_t sz, const time_t t)
}
#ifdef HAVE_TIMEGM
#define http_date_timegm(tm) timegm(tm)
#else
#ifdef _WIN32
#define http_date_timegm(tm) _mkgmtime(tm)
#else
/* If OS missing timegm(), then for best portability it is recommended to set
* $ export LC_TIME=C TZ=UTC0
* or else time comparisons may be off by timezone offset (!!)
*
* tm->tm_isdst = 0 for mktime() to indicate daylight saving time not in effect
* which is fine since HTTP date strings should be GMT dates
*
* If not TZ=UTC0, and timegm() is not present, then can we expect gmtime() to
* be available so that we can mktime(gmtime_r(lmtime, &gtm)) ? That would be
* an expensive way to obtain TZ offset. XXX: maybe calculate TZ offset once
* at startup? Are there any (modern) systems missing timegm() or _mkgmtime()?
*/
#define http_date_timegm(tm) ((tm)->tm_isdst = 0, mktime(tm))
#endif
#if !defined(HAVE_TIMEGM) && !defined(_WIN32)
time_t
http_date_timegm (const struct tm * const tm)
{
int y = tm->tm_year + 1900;
int m = tm->tm_mon + 1;
int d = tm->tm_mday;
/* days_from_civil() http://howardhinnant.github.io/date_algorithms.html */
y -= m <= 2;
int era = y / 400;
int yoe = y - era * 400; // [0, 399]
int doy = (153 * (m + (m > 2 ? -3 : 9)) + 2) / 5 + d - 1; // [0, 365]
int doe = yoe * 365 + yoe / 4 - yoe / 100 + doy; // [0, 146096]
int days_since_1970 = era * 146097 + doe - 719468;
return 60*(60*(24L*days_since_1970+tm->tm_hour)+tm->tm_min)+tm->tm_sec;
}
#endif

10
src/http_date.h

@ -8,6 +8,8 @@
#define INCLUDED_HTTP_DATE_H
#include "first.h"
#include "sys-time.h"
#ifdef __cplusplus
extern "C" {
@ -20,6 +22,14 @@ uint32_t http_date_time_to_str (char *s, size_t sz, time_t t);
int http_date_if_modified_since (const char *ifmod, uint32_t ifmodlen, time_t lmtime);
#ifdef HAVE_TIMEGM
#define http_date_timegm(tm) timegm(tm)
#elif defined(_WIN32)
#define http_date_timegm(tm) _mkgmtime(tm)
#else
time_t http_date_timegm (const struct tm *tm);
#endif
#ifdef __cplusplus
}

21
src/mod_openssl.c

@ -84,6 +84,7 @@
#include "base.h"
#include "fdevent.h"
#include "http_date.h"
#include "http_header.h"
#include "http_kv.h"
#include "log.h"
@ -1448,28 +1449,10 @@ mod_openssl_asn1_time_to_posix (ASN1_TIME *asn1time)
&& x.tm_hour == 23 && x.tm_min == 59 && x.tm_sec == 59 && s[0] == 'Z')
return (time_t)-1; // 99991231235959Z RFC 5280
#if 0
#if defined(_WIN32) && !defined(__CYGWIN__)
#define timegm(x) _mkgmtime(x)
#endif
/* timegm() might not be available, and mktime() is sensitive to TZ */
x.tm_year-= 1900;
x.tm_mon -= 1;
time_t t = timegm(&d);
time_t t = http_date_timegm(&x);
return (t != (time_t)-1) ? t + offset : t;
#else
int y = x.tm_year;
int m = x.tm_mon;
int d = x.tm_mday;
/* days_from_civil() http://howardhinnant.github.io/date_algorithms.html */
y -= m <= 2;
int era = y / 400;
int yoe = y - era * 400; // [0, 399]
int doy = (153 * (m + (m > 2 ? -3 : 9)) + 2) / 5 + d - 1; // [0, 365]
int doe = yoe * 365 + yoe / 4 - yoe / 100 + doy; // [0, 146096]
int days_since_1970 = era * 146097 + doe - 719468;
return 60*(60*(24L*days_since_1970+x.tm_hour)+x.tm_min)+x.tm_sec+offset;
#endif
#else

Loading…
Cancel
Save