/* vi: set sw=4 ts=4: * * Copyright (C) 2001 - 2012 Christian Hohnstaedt. * * All rights reserved. */ #include #include "base.h" #include "func.h" #include "exception.h" #include "asn1time.h" #include #include #include #include #include #include /* 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()); }