Import _gpgme_parse_timestamp from gpgme as parse_timestamp.
authorNeal H. Walfield <neal@g10code.de>
Mon, 23 Mar 2015 12:22:48 +0000 (13:22 +0100)
committerNeal H. Walfield <neal@g10code.de>
Mon, 23 Mar 2015 18:58:28 +0000 (19:58 +0100)
* common/gettime.h (parse_timestamp): New declaration.
* common/gettime.c (_win32_timegm): New function imported from
gpgme/src/conversion.c:_gpgme_timegm.
(parse_timestamp): New function imported from
gpgme/src/conversion.c:_gpgme_parse_timestamp.

--
Signed-off-by: Neal H. Walfield <neal@g10code.de>
common/gettime.c
common/gettime.h

index 788743f..80a56bb 100644 (file)
@@ -393,6 +393,108 @@ epoch2isotime (gnupg_isotime_t timebuf, time_t atime)
 }
 
 
+/* This function is a copy of gpgme/src/conversion.c:_gpgme_timegm.
+   If you change it, then update the other one too.  */
+#ifdef HAVE_W32_SYSTEM
+static time_t
+_win32_timegm (struct tm *tm)
+{
+  /* This one is thread safe.  */
+  SYSTEMTIME st;
+  FILETIME ft;
+  unsigned long long cnsecs;
+
+  st.wYear   = tm->tm_year + 1900;
+  st.wMonth  = tm->tm_mon  + 1;
+  st.wDay    = tm->tm_mday;
+  st.wHour   = tm->tm_hour;
+  st.wMinute = tm->tm_min;
+  st.wSecond = tm->tm_sec;
+  st.wMilliseconds = 0; /* Not available.  */
+  st.wDayOfWeek = 0;    /* Ignored.  */
+
+  /* System time is UTC thus the conversion is pretty easy.  */
+  if (!SystemTimeToFileTime (&st, &ft))
+    {
+      gpg_err_set_errno (EINVAL);
+      return (time_t)(-1);
+    }
+
+  cnsecs = (((unsigned long long)ft.dwHighDateTime << 32)
+           | ft.dwLowDateTime);
+  cnsecs -= 116444736000000000ULL; /* The filetime epoch is 1601-01-01.  */
+  return (time_t)(cnsecs / 10000000ULL);
+}
+#endif
+
+
+/* Parse the string TIMESTAMP into a time_t.  The string may either be
+   seconds since Epoch or in the ISO 8601 format like
+   "20390815T143012".  Returns 0 for an empty string or seconds since
+   Epoch. Leading spaces are skipped. If ENDP is not NULL, it will
+   point to the next non-parsed character in TIMESTRING.
+
+   This function is a copy of
+   gpgme/src/conversion.c:_gpgme_parse_timestamp.  If you change it,
+   then update the other one too.  */
+time_t
+parse_timestamp (const char *timestamp, char **endp)
+{
+  /* Need to skip leading spaces, because that is what strtoul does
+     but not our ISO 8601 checking code. */
+  while (*timestamp && *timestamp== ' ')
+    timestamp++;
+  if (!*timestamp)
+    return 0;
+
+  if (strlen (timestamp) >= 15 && timestamp[8] == 'T')
+    {
+      struct tm buf;
+      int year;
+
+      year = atoi_4 (timestamp);
+      if (year < 1900)
+        return (time_t)(-1);
+
+      if (endp)
+        *endp = (char*)(timestamp + 15);
+
+      /* Fixme: We would better use a configure test to see whether
+         mktime can handle dates beyond 2038. */
+      if (sizeof (time_t) <= 4 && year >= 2038)
+        return (time_t)2145914603; /* 2037-12-31 23:23:23 */
+
+      memset (&buf, 0, sizeof buf);
+      buf.tm_year = year - 1900;
+      buf.tm_mon = atoi_2 (timestamp+4) - 1;
+      buf.tm_mday = atoi_2 (timestamp+6);
+      buf.tm_hour = atoi_2 (timestamp+9);
+      buf.tm_min = atoi_2 (timestamp+11);
+      buf.tm_sec = atoi_2 (timestamp+13);
+
+#ifdef HAVE_W32_SYSTEM
+      return _win32_timegm (&buf);
+#else
+#ifdef HAVE_TIMEGM
+      return timegm (&buf);
+#else
+      {
+        time_t tim;
+
+        putenv ("TZ=UTC");
+        tim = mktime (&buf);
+#ifdef __GNUC__
+#warning fixme: we must somehow reset TZ here.  It is not threadsafe anyway.
+#endif
+        return tim;
+      }
+#endif /* !HAVE_TIMEGM */
+#endif /* !HAVE_W32_SYSTEM */
+    }
+  else
+    return (time_t)strtoul (timestamp, endp, 10);
+}
+
 
 
 u32
index 736eb41..10cae17 100644 (file)
@@ -41,6 +41,7 @@ int    isotime_human_p (const char *string);
 size_t string2isotime (gnupg_isotime_t atime, const char *string);
 time_t isotime2epoch (const char *string);
 void   epoch2isotime (gnupg_isotime_t timebuf, time_t atime);
+time_t parse_timestamp (const char *timestamp, char **endp);
 u32    add_days_to_timestamp (u32 stamp, u16 days);
 const char *strtimevalue (u32 stamp);
 const char *strtimestamp (u32 stamp); /* GMT */