xca/lib/asn1time.cpp
Christian Hohnstaedt 2dd2477d62 Add tests for entropy and asn1time
Make a1time::get*() const, because functions return a pointer
still owned by a1time.
Switch from deprecated setTimeSpec() to setTimeZone(()
2023-10-15 21:15:28 +02:00

235 lines
4.5 KiB
C++

/* vi: set sw=4 ts=4:
*
* Copyright (C) 2001 - 2012 Christian Hohnstaedt.
*
* All rights reserved.
*/
#include <time.h>
#include "base.h"
#include "func.h"
#include "exception.h"
#include "asn1time.h"
#include <openssl/x509.h>
#include <openssl/err.h>
#include <openssl/opensslv.h>
#include <QObject>
#include <QLocale>
#include <QTimeZone>
/* As defined in rfc-5280 4.1.2.5 */
#define UNDEFINED_DATE "99991231235959Z"
#define UTC_FORMAT "yyMMddHHmmss'Z'"
#define GEN_FORMAT "yy" UTC_FORMAT
bool a1time::isUndefined() const
{
return toSecsSinceEpoch() == 0;
}
a1time &a1time::setUndefined()
{
/* This way we handle "Jan 01, 1970 00:00:00"
* like RFC-5280 undefined date. I dare it */
setTimeZone(QTimeZone::utc());
setSecsSinceEpoch(0);
return *this;
}
int a1time::from_asn1(const ASN1_TIME *a)
{
ASN1_GENERALIZEDTIME *gt;
QString t;
*this = QDateTime();
if (!a)
return -1;
gt = ASN1_TIME_to_generalizedtime((ASN1_TIME*)a, NULL);
if (!gt)
return -1;
t = QString::fromLatin1((char*)gt->data, gt->length);
ASN1_GENERALIZEDTIME_free(gt);
return fromPlain(t);
}
int a1time::fromPlain(const QString &plain)
{
setTimeZone(QTimeZone::systemTimeZone());
if (plain == UNDEFINED_DATE)
setUndefined();
else
*this = fromString(plain, GEN_FORMAT);
setTimeZone(QTimeZone::utc());
return isValid() ? 0 : -1;
}
int a1time::set_asn1(const QString &str, int type) const
{
if (!atime)
atime = ASN1_TIME_new();
if (!atime)
return -1;
atime->type = type;
if (ASN1_STRING_set(atime, str.toLatin1(), str.length()))
return -1;
return 0;
}
a1time &a1time::operator = (const a1time &a)
{
if (atime)
ASN1_TIME_free(atime);
QDateTime::operator=(a);
return *this;
}
a1time::a1time()
{
*this = now();
}
a1time::a1time(const ASN1_TIME *a)
{
from_asn1(a);
}
a1time::a1time(const QString &plain)
{
fromPlain(plain);
}
a1time::~a1time()
{
if (atime)
ASN1_TIME_free(atime);
}
const ASN1_TIME *a1time::get_utc() const
{
int year = date().year();
if (!isValid() || isUndefined() || year > 2049 || year < 1950)
return get();
set_asn1(toUTC().toString(UTC_FORMAT), V_ASN1_UTCTIME);
return atime;
}
const ASN1_TIME *a1time::get() const
{
if (isUndefined())
set_asn1(UNDEFINED_DATE, V_ASN1_GENERALIZEDTIME);
else if (!isValid())
throw errorEx("Invalid Time");
else
set_asn1(toUTC().toString(GEN_FORMAT),
V_ASN1_GENERALIZEDTIME);
return atime;
}
a1time &a1time::set(const ASN1_TIME *a)
{
from_asn1(a);
return *this;
}
QString a1time::toString(QString fmt, Qt::TimeSpec spec) const
{
if (isUndefined())
return QObject::tr("Undefined");
if (!isValid())
return QObject::tr("Broken / Invalid");
return QLocale().toString(
spec == Qt::UTC ? toUTC() : toLocalTime(), fmt);
}
QString a1time::toPretty() const
{
QString fmt = QLocale().dateTimeFormat();
return toString(fmt, Qt::LocalTime);
}
QString a1time::toPrettyGMT() const
{
return toString("yyyy-MM-dd'T'HH:mm:ss' GMT'");
}
QString a1time::toSortable() const
{
return toString("yyyy-MM-dd");
}
QString a1time::toPlain(const QString &fmt) const
{
if (isUndefined())
return QString(UNDEFINED_DATE);
if (!isValid())
return QString("Broken-InvalidZ");
return toString(fmt.isEmpty() ? GEN_FORMAT : fmt);
}
qint64 a1time::age() const
{
return secsTo(now());
}
QString a1time::toFancy() const
{
QString fmt("Dunno");
qint64 diff = age();
int dtn = toLocalTime().daysTo(now().toLocalTime());
bool future = false;
if (diff < 0) {
future = true;
diff *= -1;
}
if (diff < 2 * SECS_PER_MINUTE) {
fmt = future ? QObject::tr("in %1 seconds") :
QObject::tr("%1 seconds ago");
} else if (diff < 2 *SECS_PER_HOUR) {
diff /= SECS_PER_MINUTE;
fmt = future ? QObject::tr("in %1 minutes") :
QObject::tr("%1 minutes ago");
} else if (dtn == 1) {
return QObject::tr("Yesterday");
} else if (dtn == -1) {
return QObject::tr("Tomorrow");
} else if (diff < SECS_PER_DAY) {
diff /= SECS_PER_HOUR;
fmt = future ? QObject::tr("in %1 hours") :
QObject::tr("%1 hours ago");
} else {
return QLocale().toString(date(),
QLocale::ShortFormat);
}
return fmt.arg(diff);
}
QString a1time::toPlainUTC() const
{
return toPlain(UTC_FORMAT);
}
QDateTime a1time::now(int delta)
{
return QDateTime::currentDateTime().toUTC().addSecs(delta);
}
void a1time::d2i(QByteArray &ba)
{
ASN1_TIME *n = (ASN1_TIME*)d2i_bytearray( D2I_VOID(d2i_ASN1_TIME), ba);
openssl_error();
if (n) {
from_asn1(n);
ASN1_TIME_free(n);
}
}
QByteArray a1time::i2d() const
{
return i2d_bytearray(I2D_VOID(i2d_ASN1_TIME), get());
}