/* time.c - UTCTime and GeneralizedTime helper
* Copyright (C) 2001, 2003, 2005, 2012 g10 Code GmbH
*
* This file is part of KSBA.
*
* KSBA is free software; you can redistribute it and/or modify
* it under the terms of either
*
* - the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at
* your option) any later version.
*
* or
*
* - the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* or both in parallel, as here.
*
* KSBA is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
* License for more details.
*
* You should have received a copies of the GNU General Public License
* and the GNU Lesser General Public License along with this program;
* if not, see .
*/
#include
#include
#include
#include
#include
#include
#include "util.h"
#include "convert.h"
/* Converts an UTCTime or GeneralizedTime to ISO format. Sets the
returns string to empty on error and returns the error code. The
function figures automagically the right format. fixme: Currently
we only zupport Zulu time and no timezone which is sufficient for
DER encoding. It IS_UTCTIME is true, the function assumes that the
time is in UTCTime and thus allows to parse UTCTimes without
seconds (which is legal ASN.1; however Gutmann claims that the
rules changed in 1996 to always require seconds; OTOH, Dubuisson's
reference book from 2001 doesn't say so). */
gpg_error_t
_ksba_asntime_to_iso (const char *buffer, size_t length, int is_utctime,
ksba_isotime_t timebuf)
{
const char *s;
size_t n;
int year;
*timebuf = 0;
for (s=buffer, n=0; n < length && digitp (s); n++, s++)
;
if (is_utctime)
{
if ((n != 10 && n != 12) || *s != 'Z')
return gpg_error (GPG_ERR_INV_TIME);
}
else if ((n != 12 && n != 14) || *s != 'Z')
return gpg_error (GPG_ERR_INV_TIME);
s = buffer;
if (n==12 || n == 10 ) /* UTCTime with or without seconds. */
{
year = atoi_2 (s);
timebuf[0] = year < 50? '2': '1';
timebuf[1] = year < 50? '0': '9';
memcpy (timebuf+2, s, 6);
s += 6;
}
else
{
memcpy (timebuf, s, 8);
s += 8;
}
timebuf[8] = 'T';
if (n == 10) /* UTCTime w/0 seconds. */
{
memcpy (timebuf+9, s, 4);
timebuf[13] = timebuf[14] = '0';
}
else
{
memcpy (timebuf+9, s, 6);
}
timebuf[15] = 0;
return 0;
}
/* Return 0 if ATIME has the proper format (e.g. "19660205T131415"). */
gpg_error_t
_ksba_assert_time_format (const ksba_isotime_t atime)
{
int i;
const char *s;
if (!*atime)
return gpg_error (GPG_ERR_NO_VALUE);
for (s=atime, i=0; i < 8; i++, s++)
if (!digitp (s))
return gpg_error (GPG_ERR_BUG);
if (*s != 'T')
return gpg_error (GPG_ERR_BUG);
for (s++, i=9; i < 15; i++, s++)
if (!digitp (s))
return gpg_error (GPG_ERR_BUG);
if (*s)
return gpg_error (GPG_ERR_BUG);
return 0;
}
/* Copy ISO time S to D. This is a function so that we can detect
faulty time formats. */
void
_ksba_copy_time (ksba_isotime_t d, const ksba_isotime_t s)
{
if (!*s)
memset (d, 0, 16);
else if ( _ksba_assert_time_format (s) )
{
fprintf (stderr, "BUG: invalid isotime buffer\n");
abort ();
}
else
strcpy (d, s);
}
/* Compare the time strings A and B. Return 0 if they show the very
same time, return 1 if A is newer than B and -1 if A is older than
B. */
int
_ksba_cmp_time (const ksba_isotime_t a, const ksba_isotime_t b)
{
return strcmp (a, b);
}
/* Fill the TIMEBUF with the current time (UTC of course). */
void
_ksba_current_time (ksba_isotime_t timebuf)
{
time_t epoch = time (NULL);
struct tm *tp;
#ifdef HAVE_GMTIME_R
struct tm tmbuf;
tp = gmtime_r ( &epoch, &tmbuf);
#else
tp = gmtime ( &epoch );
#endif
sprintf (timebuf,"%04d%02d%02dT%02d%02d%02d",
1900 + tp->tm_year, tp->tm_mon+1, tp->tm_mday,
tp->tm_hour, tp->tm_min, tp->tm_sec);
}