From 34c57901974906b06d107a8b50af7ff6b1f9ad41 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Tue, 23 Feb 2016 21:01:49 +1030 Subject: [PATCH 2/4] glib: return date in UTC instead of local time Bug 94173 --- ConfigureChecks.cmake | 1 + config.h.cmake | 3 +++ configure.ac | 1 + glib/poppler-date.cc | 33 +++++++------------------------- goo/glibc.cc | 24 ++++++++++++++++++++++++ goo/glibc.h | 4 ++++ poppler/DateInfo.cc | 52 +++++++++++++++++++++++++++++---------------------- poppler/DateInfo.h | 6 +++++- poppler/Form.cc | 2 +- 9 files changed, 76 insertions(+), 50 deletions(-) diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake index d3f5732..345f29c 100644 --- a/ConfigureChecks.cmake +++ b/ConfigureChecks.cmake @@ -30,6 +30,7 @@ check_function_exists(ftell64 HAVE_FTELL64) check_function_exists(pread64 HAVE_PREAD64) check_function_exists(lseek64 HAVE_LSEEK64) check_function_exists(gmtime_r HAVE_GMTIME_R) +check_function_exists(timegm HAVE_TIMEGM) check_function_exists(gettimeofday HAVE_GETTIMEOFDAY) check_function_exists(localtime_r HAVE_LOCALTIME_R) check_function_exists(popen HAVE_POPEN) diff --git a/config.h.cmake b/config.h.cmake index 85c6d32..7988b74 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -64,6 +64,9 @@ /* Defines if gmtime_r is available on your system */ #cmakedefine HAVE_GMTIME_R 1 +/* Defines if timegm is available on your system */ +#cmakedefine HAVE_TIMEGM 1 + /* Define if you have the iconv() function and it works. */ #cmakedefine HAVE_ICONV 1 diff --git a/configure.ac b/configure.ac index 72ea87d..3f819e8 100644 --- a/configure.ac +++ b/configure.ac @@ -178,6 +178,7 @@ AC_LANG_CPLUSPLUS AC_CHECK_DECL(gettimeofday, [AC_CHECK_FUNC(gettimeofday, AC_DEFINE(HAVE_GETTIMEOFDAY, 1, [Defines if gettimeofday is available on your system]))],[],[#include ]) AC_CHECK_FUNC(localtime_r, AC_DEFINE(HAVE_LOCALTIME_R, 1, [Defines if localtime_r is available on your system])) AC_CHECK_FUNC(gmtime_r, AC_DEFINE(HAVE_GMTIME_R, 1, [Defines if gmtime_r is available on your system])) +AC_CHECK_FUNC(timegm, AC_DEFINE(HAVE_TIMEGM, 1, [Defines if timegm is available on your system])) AC_CHECK_FUNC(rand_r, AC_DEFINE(HAVE_RAND_R, 1, [Defines if rand_r is available on your system])) dnl ##### Check for extra libraries needed by X. (LynxOS needs this.) diff --git a/glib/poppler-date.cc b/glib/poppler-date.cc index e3141c1..ad86b30 100644 --- a/glib/poppler-date.cc +++ b/glib/poppler-date.cc @@ -17,6 +17,7 @@ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ +#include #include #include "poppler-date.h" @@ -37,32 +38,12 @@ gboolean poppler_date_parse (const gchar *date, time_t *timet) { - gint year, mon, day, hour, min, sec, tz_hour, tz_minute; - gchar tz; - struct tm time; - time_t retval; - - /* See PDF Reference 1.3, Section 3.8.2 for PDF Date representation */ - // TODO do something with the timezone information - if (!parseDateString (date, &year, &mon, &day, &hour, &min, &sec, &tz, &tz_hour, &tz_minute)) + time_t t; + GooString dateString(date); + t = dateStringToTime(&dateString); + if (t == (time_t)-1) return FALSE; - - time.tm_year = year - 1900; - time.tm_mon = mon - 1; - time.tm_mday = day; - time.tm_hour = hour; - time.tm_min = min; - time.tm_sec = sec; - time.tm_wday = -1; - time.tm_yday = -1; - time.tm_isdst = -1; /* 0 = DST off, 1 = DST on, -1 = don't know */ - - /* compute tm_wday and tm_yday and check date */ - retval = mktime (&time); - if (retval == (time_t) - 1) - return FALSE; - - *timet = retval; - return TRUE; + *timet = t; + return TRUE; } diff --git a/goo/glibc.cc b/goo/glibc.cc index fa1c858..4968047 100644 --- a/goo/glibc.cc +++ b/goo/glibc.cc @@ -32,3 +32,27 @@ struct tm *localtime_r(const time_t *timep, struct tm *result) return lt; } #endif + +#ifndef HAVE_TIMEGM +// Get offset of local time from UTC in seconds. DST is ignored. +static time_t getLocalTimeZoneOffset() +{ + time_t utc, local; + struct tm tm_utc; + time (&utc); + gmtime_r(&utc, &tm_utc); + local = mktime(&tm_utc); + return difftime(utc, local); +} + +time_t timegm(struct tm *tm) +{ + tm->tm_isdst = 0; + time_t t = mktime(tm); + if (t == -1) + return t; + + t += getLocalTimeZoneOffset(); + return t; +} +#endif diff --git a/goo/glibc.h b/goo/glibc.h index cc156e7..49479e9 100644 --- a/goo/glibc.h +++ b/goo/glibc.h @@ -27,6 +27,10 @@ struct tm *gmtime_r(const time_t *timep, struct tm *result); struct tm *localtime_r(const time_t *timep, struct tm *result); #endif +#ifndef HAVE_TIMEGM +time_t timegm(struct tm *tm); +#endif + }; #endif // GLIBC_H diff --git a/poppler/DateInfo.cc b/poppler/DateInfo.cc index 99da404..791f19e 100644 --- a/poppler/DateInfo.cc +++ b/poppler/DateInfo.cc @@ -75,7 +75,7 @@ GBool parseDateString(const char *dateString, int *year, int *month, int *day, i return gFalse; } - +// Convert time to PDF date string GooString *timeToDateString(time_t *timet) { GooString *dateString; char s[5]; @@ -115,27 +115,35 @@ GooString *timeToDateString(time_t *timet) { return dateString; } -time_t pdfTimeToInteger(GooString *time_str) -{ +// Convert PDF date string to time. Returns -1 if conversion fails. +time_t dateStringToTime(GooString *dateString) { int year, mon, day, hour, min, sec, tz_hour, tz_minute; char tz; - struct tm time_struct; - - if (!parseDateString (time_str->getCString(), &year, - &mon, &day, &hour, &min, &sec, &tz, &tz_hour, &tz_minute)) - return 0; - - time_struct.tm_year = year - 1900; - time_struct.tm_mon = mon - 1; - time_struct.tm_mday = day; - time_struct.tm_hour = hour; - time_struct.tm_min = min; - time_struct.tm_sec = sec; - time_struct.tm_wday = -1; - time_struct.tm_yday = -1; - time_struct.tm_isdst = -1; - - time_t unix_time = mktime(&time_struct); - - return unix_time; + struct tm tm; + time_t time; + + if (!parseDateString (dateString->getCString(), &year, &mon, &day, &hour, &min, &sec, &tz, &tz_hour, &tz_minute)) + return -1; + + tm.tm_year = year - 1900; + tm.tm_mon = mon - 1; + tm.tm_mday = day; + tm.tm_hour = hour; + tm.tm_min = min; + tm.tm_sec = sec; + tm.tm_wday = -1; + tm.tm_yday = -1; + tm.tm_isdst = -1; /* 0 = DST off, 1 = DST on, -1 = don't know */ + + /* compute tm_wday and tm_yday and check date */ + time = timegm (&tm); + if (time == (time_t)-1) + return time; + + time_t offset = (tz_hour*60 + tz_minute)*60; + if (tz == '-') + offset *= -1; + time -= offset; + + return time; } diff --git a/poppler/DateInfo.h b/poppler/DateInfo.h index 840ee5a..e411268 100644 --- a/poppler/DateInfo.h +++ b/poppler/DateInfo.h @@ -33,6 +33,10 @@ GBool parseDateString(const char *string, int *year, int *month, int *day, int * * If timet is NULL, current time is used. */ GooString *timeToDateString(time_t *timet); -time_t pdfTimeToInteger(GooString *time_str); + +/* Convert PDF date string to time. + * Returns -1 if conversion fails. + */ +time_t dateStringToTime(GooString *dateString); #endif diff --git a/poppler/Form.cc b/poppler/Form.cc index 4dd56b7..b63ea36 100644 --- a/poppler/Form.cc +++ b/poppler/Form.cc @@ -1421,7 +1421,7 @@ void FormFieldSignature::parseInfo() sig_dict.dictLookup("M", &time_of_signing); if (time_of_signing.isString()) { GooString *time_str = time_of_signing.getString(); - signature_info->setSigningTime(pdfTimeToInteger(time_str)); // Put this information directly in SignatureInfo object + signature_info->setSigningTime(dateStringToTime(time_str)); // Put this information directly in SignatureInfo object time_of_signing.free(); } -- 2.1.4