From f1172ac0177f48b86f01805387a2dbbb3a6a85e5 Mon Sep 17 00:00:00 2001 From: Jakub Kucharski Date: Wed, 17 Feb 2016 14:26:26 +0100 Subject: [PATCH] glib & cpp: return dates in UTC format --- cpp/poppler-document.cpp | 5 ++++- cpp/poppler-embedded-file.cpp | 7 ++++-- cpp/poppler-global.cpp | 10 +-------- cpp/poppler-global.h | 3 +-- cpp/poppler-private.cpp | 24 +------------------- cpp/poppler-private.h | 3 +-- glib/poppler-document.cc | 24 +++++++++----------- poppler/DateInfo.cc | 52 +++++++++++++++++++++++++++++++++++++++++++ poppler/DateInfo.h | 4 ++++ 9 files changed, 79 insertions(+), 53 deletions(-) diff --git a/cpp/poppler-document.cpp b/cpp/poppler-document.cpp index 1c24b47..fafd0a9 100644 --- a/cpp/poppler-document.cpp +++ b/cpp/poppler-document.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2009-2011, Pino Toscano + * Copyright (C) 2016 Jakub Kucharski * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -356,6 +357,8 @@ ustring document::info_key(const std::string &key) const return result; } +#include "DateInfo.h" + /** Gets the time_t value value of the specified \p key of the document information. @@ -379,7 +382,7 @@ time_type document::info_date(const std::string &key) const Object obj; time_type result = time_type(-1); if (info_dict->lookup(PSTR(key.c_str()), &obj)->isString()) { - result = detail::convert_date(obj.getString()->getCString()); + result = dateStringToTime(obj.getString()); } obj.free(); info.free(); diff --git a/cpp/poppler-embedded-file.cpp b/cpp/poppler-embedded-file.cpp index 2c5d077..03517d9 100644 --- a/cpp/poppler-embedded-file.cpp +++ b/cpp/poppler-embedded-file.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2009-2011, Pino Toscano + * Copyright (C) 2016 Jakub Kucharski * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -100,6 +101,8 @@ int embedded_file::size() const return d->file_spec->getEmbeddedFile()->size(); } +#include "DateInfo.h" + /** \returns the time_t representing the modification date of the embedded file, if available @@ -107,7 +110,7 @@ int embedded_file::size() const time_type embedded_file::modification_date() const { GooString *goo = d->file_spec->getEmbeddedFile()->modDate(); - return goo ? detail::convert_date(goo->getCString()) : time_type(-1); + return goo ? dateStringToTime(goo) : time_type(-1); } /** @@ -117,7 +120,7 @@ time_type embedded_file::modification_date() const time_type embedded_file::creation_date() const { GooString *goo = d->file_spec->getEmbeddedFile()->createDate(); - return goo ? detail::convert_date(goo->getCString()) : time_type(-1); + return goo ? dateStringToTime(goo) : time_type(-1); } /** diff --git a/cpp/poppler-global.cpp b/cpp/poppler-global.cpp index b99259f..cc32a8a 100644 --- a/cpp/poppler-global.cpp +++ b/cpp/poppler-global.cpp @@ -3,6 +3,7 @@ * Copyright (C) 2010, Hib Eris * Copyright (C) 2014, 2015 Hans-Peter Deifel * Copyright (C) 2015, Tamas Szekeres + * Copyright (C) 2016 Jakub Kucharski * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -309,15 +310,6 @@ ustring ustring::from_latin1(const std::string &str) return ret; } - -/** - Converts a string representing a PDF date to a value compatible with time_t. - */ -time_type poppler::convert_date(const std::string &date) -{ - return detail::convert_date(date.c_str()); -} - std::ostream& poppler::operator<<(std::ostream& stream, const byte_array &array) { stream << "["; diff --git a/cpp/poppler-global.h b/cpp/poppler-global.h index eb7ec24..00175da 100644 --- a/cpp/poppler-global.h +++ b/cpp/poppler-global.h @@ -2,6 +2,7 @@ * Copyright (C) 2009-2010, Pino Toscano * Copyright (C) 2010, Patrick Spendrin * Copyright (C) 2014, Hans-Peter Deifel + * Copyright (C) 2016 Jakub Kucharski * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -103,8 +104,6 @@ private: #pragma warning(pop) #endif -POPPLER_CPP_EXPORT time_type convert_date(const std::string &date); - POPPLER_CPP_EXPORT std::ostream& operator<<(std::ostream& stream, const byte_array &array); typedef void(*debug_func)(const std::string &, void *); diff --git a/cpp/poppler-private.cpp b/cpp/poppler-private.cpp index 3c3fe95..f7d8980 100644 --- a/cpp/poppler-private.cpp +++ b/cpp/poppler-private.cpp @@ -2,6 +2,7 @@ * Copyright (C) 2009-2010, Pino Toscano * Copyright (C) 2013 Adrian Johnson * Copyright (C) 2014, Hans-Peter Deifel + * Copyright (C) 2016 Jakub Kucharski * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -115,26 +116,3 @@ GooString* detail::ustring_to_unicode_GooString(const ustring &str) GooString *goo = new GooString(&ba[0]); return goo; } - -time_type detail::convert_date(const char *date) -{ - int year, mon, day, hour, min, sec, tzHours, tzMins; - char tz; - - if (!parseDateString(date, &year, &mon, &day, &hour, &min, &sec, - &tz, &tzHours, &tzMins)) { - return time_type(-1); - } - - struct tm time; - time.tm_sec = sec; - time.tm_min = min; - time.tm_hour = hour; - time.tm_mday = day; - time.tm_mon = mon - 1; - time.tm_year = year - 1900; - time.tm_wday = -1; - time.tm_yday = -1; - time.tm_isdst = -1; - return mktime(&time); -} diff --git a/cpp/poppler-private.h b/cpp/poppler-private.h index 8d315c8..7d554d0 100644 --- a/cpp/poppler-private.h +++ b/cpp/poppler-private.h @@ -2,6 +2,7 @@ * Copyright (C) 2009, Pino Toscano * Copyright (C) 2013 Adrian Johnson * Copyright (C) 2014, Hans-Peter Deifel + * Copyright (C) 2016 Jakub Kucharski * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -50,8 +51,6 @@ ustring unicode_GooString_to_ustring(GooString *str); ustring unicode_to_ustring(const Unicode *u, int length); GooString* ustring_to_unicode_GooString(const ustring &str); -time_type convert_date(const char *date); - } template diff --git a/glib/poppler-document.cc b/glib/poppler-document.cc index 61d92e8..eb88124 100644 --- a/glib/poppler-document.cc +++ b/glib/poppler-document.cc @@ -1,6 +1,8 @@ /* poppler-document.cc: glib wrapper for poppler * Copyright (C) 2005, Red Hat, Inc. * + * Copyright (C) 2016 Jakub Kucharski + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) @@ -2698,23 +2700,17 @@ poppler_document_get_form_field (PopplerDocument *document, return NULL; } +#include "DateInfo.h" + gboolean -_poppler_convert_pdf_date_to_gtime (GooString *date, - time_t *gdate) +_poppler_convert_pdf_date_to_gtime (GooString *date, time_t *gdate) { - gchar *date_string; - gboolean retval; + time_t t = dateStringToTime(date); - if (date->hasUnicodeMarker()) { - date_string = g_convert (date->getCString () + 2, - date->getLength () - 2, - "UTF-8", "UTF-16BE", NULL, NULL, NULL); + if (t != -1) { + *gdate = t; + return TRUE; } else { - date_string = g_strndup (date->getCString (), date->getLength ()); + return FALSE; } - - retval = poppler_date_parse (date_string, gdate); - g_free (date_string); - - return retval; } diff --git a/poppler/DateInfo.cc b/poppler/DateInfo.cc index 563204a..6c02c10 100644 --- a/poppler/DateInfo.cc +++ b/poppler/DateInfo.cc @@ -4,6 +4,7 @@ // // Copyright (C) 2008 Albert Astals Cid // Copyright (C) 2009 Carlos Garcia Campos +// Copyright (C) 2016 Jakub Kucharski // // To see a description of the changes please see the Changelog file that // came with your tarball or type make ChangeLog if you are building from git @@ -116,3 +117,54 @@ GooString *timeToDateString(time_t *timet) { return dateString; } +static int leapYearsBefore(int year) +{ + year--; + return (year / 4) - (year / 100) + (year / 400); +} + +static int leapYearsBetween(int start, int end) +{ + return leapYearsBefore(end) - leapYearsBefore(start); +} + +static GBool leapYear(int year) +{ + return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0; +} + +static int daysInYearBeforeMon(int mon, int year) +{ + static const int days[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; + return days[mon-1] + ((leapYear(year) && mon > 2) ? 1 : 0); +} + +static time_t utcmktime(int year, int mon, int day, int hour, int min, int sec) +{ + int leapYears = leapYearsBetween(1970, year); + time_t fullDays = (year-1970) * 365 + leapYears + daysInYearBeforeMon(mon, year) + day - 1; + + return fullDays*24*60*60 + hour*60*60 + min*60 + sec; +} + +time_t dateStringToTime(GooString *str) +{ + char *data = str->getCString(); + if (str->hasUnicodeMarker()) { + data += 2; + } + + int year, mon, day, hour, min, sec, tzHours, tzMins; + char tz; + + if (!parseDateString(data, &year, &mon, &day, &hour, &min, &sec, &tz, &tzHours, &tzMins)) { + return -1; + } + + long offset = tzHours*60*60 + tzMins*60; + if (tz == '-') { + offset *= -1; + } + + return utcmktime(year, mon, day, hour, min, sec) - offset; +} diff --git a/poppler/DateInfo.h b/poppler/DateInfo.h index 116350f..963be14 100644 --- a/poppler/DateInfo.h +++ b/poppler/DateInfo.h @@ -4,6 +4,7 @@ // // Copyright (C) 2008 Albert Astals Cid // Copyright (C) 2009 Carlos Garcia Campos +// Copyright (C) 2016 Jakub Kucharski // // To see a description of the changes please see the Changelog file that // came with your tarball or type make ChangeLog if you are building from git @@ -32,4 +33,7 @@ GBool parseDateString(const char *string, int *year, int *month, int *day, int * */ GooString *timeToDateString(time_t *timet); +// converts PDF Date format string to time_t +time_t dateStringToTime(GooString *str); + #endif -- 2.7.1