15#include "expirychecker.h" 
   18#include "expirycheckersettings.h" 
   20#include <libkleo/algorithm.h> 
   21#include <libkleo/formatting.h> 
   22#include <libkleo/keycache.h> 
   23#include <libkleo_debug.h> 
   25#include <KLocalizedString> 
   27#include <QGpgME/KeyListJob> 
   28#include <QGpgME/Protocol> 
   32#include <gpgme++/keylistresult.h> 
   41class Kleo::ExpiryCheckerPrivate
 
   43    Kleo::ExpiryChecker *q;
 
   46    ExpiryCheckerPrivate(ExpiryChecker *qq, 
const ExpiryCheckerSettings &settings_)
 
   52    ExpiryChecker::Expiration calculateExpiration(
const GpgME::Subkey &subkey) 
const;
 
   53    ExpiryChecker::Expiration checkForExpiration(
const GpgME::Key &key, Kleo::chrono::days threshold, ExpiryChecker::CheckFlags flags) 
const;
 
   55    ExpiryChecker::Result checkKeyNearExpiry(
const GpgME::Key &key, ExpiryChecker::CheckFlags flags);
 
   57    ExpiryCheckerSettings settings;
 
   58    std::set<QByteArray> alreadyWarnedFingerprints;
 
   59    std::shared_ptr<TimeProvider> timeProvider;
 
   62ExpiryChecker::ExpiryChecker(
const ExpiryCheckerSettings &settings, 
QObject *parent)
 
   64    , d{new ExpiryCheckerPrivate{this, settings}}
 
   68ExpiryChecker::~ExpiryChecker() = 
default;
 
   70ExpiryCheckerSettings ExpiryChecker::settings()
 const 
   75QString formatOpenPGPMessage(ExpiryChecker::Expiration expiration, ExpiryChecker::CheckFlags flags)
 
   77    const GpgME::Key key = expiration.certificate;
 
   78    const bool isOwnKey = flags & ExpiryChecker::OwnKey;
 
   79    const bool isSigningKey = flags & ExpiryChecker::SigningKey;
 
   80    const auto keyInfo = 
ki18nc(
"<b>User ID of key</b> (Key ID key ID of key in hex notation)", 
"<b>%1</b> (Key ID 0x%2)")
 
   83    if (expiration.status == ExpiryChecker::Expired) {
 
   84        qCDebug(LIBKLEO_LOG) << 
"Key" << key << 
"expired" << expiration.duration.count() << 
"days ago";
 
   85        if (expiration.duration.count() == 0) {
 
   88                msg = 
ki18n(
"<p>Your OpenPGP signing key</p><p align=center>%1</p><p>expired less than a day ago.</p>");
 
   89            } 
else if (isOwnKey) {
 
   90                msg = 
ki18n(
"<p>Your OpenPGP encryption key</p><p align=center>%1</p><p>expired less than a day ago.</p>");
 
   92                msg = 
ki18n(
"<p>The OpenPGP key for</p><p align=center>%1</p><p>expired less than a day ago.</p>");
 
   98            msg = 
ki18np(
"<p>Your OpenPGP signing key</p><p align=center>%2</p><p>expired yesterday.</p>",
 
   99                         "<p>Your OpenPGP signing key</p><p align=center>%2</p><p>expired %1 days ago.</p>");
 
  100        } 
else if (isOwnKey) {
 
  101            msg = 
ki18np(
"<p>Your OpenPGP encryption key</p><p align=center>%2</p><p>expired yesterday.</p>",
 
  102                         "<p>Your OpenPGP encryption key</p><p align=center>%2</p><p>expired %1 days ago.</p>");
 
  104            msg = 
ki18np(
"<p>The OpenPGP key for</p><p align=center>%2</p><p>expired yesterday.</p>",
 
  105                         "<p>The OpenPGP key for</p><p align=center>%2</p><p>expired %1 days ago.</p>");
 
  109    qCDebug(LIBKLEO_LOG) << 
"Key" << key << 
"expires in" << expiration.duration.count() << 
"days";
 
  110    if (expiration.duration.count() == 0) {
 
  111        KLocalizedString msg;
 
  113            msg = 
ki18n(
"<p>Your OpenPGP signing key</p><p align=center>%1</p><p>expires today.</p>");
 
  114        } 
else if (isOwnKey) {
 
  115            msg = 
ki18n(
"<p>Your OpenPGP encryption key</p><p align=center>%1</p><p>expires today.</p>");
 
  117            msg = 
ki18n(
"<p>The OpenPGP key for</p><p align=center>%1</p><p>expires today.</p>");
 
  121    KLocalizedString msg;
 
  123        msg = 
ki18np(
"<p>Your OpenPGP signing key</p><p align=center>%2</p><p>expires tomorrow.</p>",
 
  124                     "<p>Your OpenPGP signing key</p><p align=center>%2</p><p>expires in %1 days.</p>");
 
  125    } 
else if (isOwnKey) {
 
  126        msg = 
ki18np(
"<p>Your OpenPGP encryption key</p><p align=center>%2</p><p>expires tomorrow.</p>",
 
  127                     "<p>Your OpenPGP encryption key</p><p align=center>%2</p><p>expires in %1 days.</p>");
 
  129        msg = 
ki18np(
"<p>The OpenPGP key for</p><p align=center>%2</p><p>expires tomorrow.</p>",
 
  130                     "<p>The OpenPGP key for</p><p align=center>%2</p><p>expires in %1 days.</p>");
 
  135QString formatSMIMEMessage(
const GpgME::Key &orig_key, ExpiryChecker::Expiration expiration, ExpiryChecker::CheckFlags flags, 
bool ca)
 
  137    const GpgME::Key key = expiration.certificate;
 
  138    const bool isOwnKey = flags & ExpiryChecker::OwnKey;
 
  139    const bool isSigningKey = flags & ExpiryChecker::SigningKey;
 
  140    const auto userCert = orig_key.isNull() ? key : orig_key;
 
  141    const auto userCertInfo = 
ki18nc(
"<b>User ID of certificate</b> (serial number serial no. of certificate)", 
"<b>%1</b> (serial number %2)")
 
  142                                  .
subs(Formatting::prettyDN(userCert.userID(0).id()))
 
  144    if (expiration.status == ExpiryChecker::Expired) {
 
  145        qCDebug(LIBKLEO_LOG) << 
"Certificate" << key << 
"expired" << expiration.duration.count() << 
"days ago";
 
  148                if (expiration.duration.count() == 0) {
 
  149                    KLocalizedString msg;
 
  152                            "<p>The root certificate</p><p align=center><b>%2</b></p>" 
  153                            "<p>for your S/MIME signing certificate</p><p align=center>%1</p>" 
  154                            "<p>expired less than a day ago.</p>");
 
  155                    } 
else if (isOwnKey) {
 
  157                            "<p>The root certificate</p><p align=center><b>%2</b></p>" 
  158                            "<p>for your S/MIME encryption certificate</p><p align=center>%1</p>" 
  159                            "<p>expired less than a day ago.</p>");
 
  162                            "<p>The root certificate</p><p align=center><b>%2</b></p>" 
  163                            "<p>for S/MIME certificate</p><p align=center>%1</p>" 
  164                            "<p>expired less than a day ago.</p>");
 
  166                    return msg.
subs(userCertInfo).
subs(Formatting::prettyDN(key.userID(0).id())).
toString();
 
  168                KLocalizedString msg;
 
  171                        "<p>The root certificate</p><p align=center><b>%3</b></p>" 
  172                        "<p>for your S/MIME signing certificate</p><p align=center>%2</p>" 
  173                        "<p>expired yesterday.</p>",
 
  174                        "<p>The root certificate</p><p align=center><b>%3</b></p>" 
  175                        "<p>for your S/MIME signing certificate</p><p align=center>%2</p>" 
  176                        "<p>expired %1 days ago.</p>");
 
  177                } 
else if (isOwnKey) {
 
  179                        "<p>The root certificate</p><p align=center><b>%3</b></p>" 
  180                        "<p>for your S/MIME encryption certificate</p><p align=center>%2</p>" 
  181                        "<p>expired yesterday.</p>",
 
  182                        "<p>The root certificate</p><p align=center><b>%3</b></p>" 
  183                        "<p>for your S/MIME encryption certificate</p><p align=center>%2</p>" 
  184                        "<p>expired %1 days ago.</p>");
 
  187                        "<p>The root certificate</p><p align=center><b>%3</b></p>" 
  188                        "<p>for S/MIME certificate</p><p align=center>%2</p>" 
  189                        "<p>expired yesterday.</p>",
 
  190                        "<p>The root certificate</p><p align=center><b>%3</b></p>" 
  191                        "<p>for S/MIME certificate</p><p align=center>%2</p>" 
  192                        "<p>expired %1 days ago.</p>");
 
  194                return msg.
subs(expiration.duration.count()).
subs(userCertInfo).
subs(Formatting::prettyDN(key.userID(0).id())).
toString();
 
  196                if (expiration.duration.count() == 0) {
 
  197                    KLocalizedString msg;
 
  200                            "<p>The intermediate CA certificate</p><p align=center><b>%2</b></p>" 
  201                            "<p>for your S/MIME signing certificate</p><p align=center>%1</p>" 
  202                            "<p>expired less than a day ago.</p>");
 
  203                    } 
else if (isOwnKey) {
 
  205                            "<p>The intermediate CA certificate</p><p align=center><b>%2</b></p>" 
  206                            "<p>for your S/MIME encryption certificate</p><p align=center>%1</p>" 
  207                            "<p>expired less than a day ago.</p>");
 
  210                            "<p>The intermediate CA certificate</p><p align=center><b>%2</b></p>" 
  211                            "<p>for S/MIME certificate</p><p align=center>%1</p>" 
  212                            "<p>expired less than a day ago.</p>");
 
  214                    return msg.
subs(userCertInfo).
subs(Formatting::prettyDN(key.userID(0).id())).
toString();
 
  216                KLocalizedString msg;
 
  219                        "<p>The intermediate CA certificate</p><p align=center><b>%3</b></p>" 
  220                        "<p>for your S/MIME signing certificate</p><p align=center>%2</p>" 
  221                        "<p>expired yesterday.</p>",
 
  222                        "<p>The intermediate CA certificate</p><p align=center><b>%3</b></p>" 
  223                        "<p>for your S/MIME signing certificate</p><p align=center>%2</p>" 
  224                        "<p>expired %1 days ago.</p>");
 
  225                } 
else if (isOwnKey) {
 
  227                        "<p>The intermediate CA certificate</p><p align=center><b>%3</b></p>" 
  228                        "<p>for your S/MIME encryption certificate</p><p align=center>%2</p>" 
  229                        "<p>expired yesterday.</p>",
 
  230                        "<p>The intermediate CA certificate</p><p align=center><b>%3</b></p>" 
  231                        "<p>for your S/MIME encryption certificate</p><p align=center>%2</p>" 
  232                        "<p>expired %1 days ago.</p>");
 
  235                        "<p>The intermediate CA certificate</p><p align=center><b>%3</b></p>" 
  236                        "<p>for S/MIME certificate</p><p align=center>%2</p>" 
  237                        "<p>expired yesterday.</p>",
 
  238                        "<p>The intermediate CA certificate</p><p align=center><b>%3</b></p>" 
  239                        "<p>for S/MIME certificate</p><p align=center>%2</p>" 
  240                        "<p>expired %1 days ago.</p>");
 
  242                return msg.
subs(expiration.duration.count()).
subs(userCertInfo).
subs(Formatting::prettyDN(key.userID(0).id())).
toString();
 
  245            if (expiration.duration.count() == 0) {
 
  246                KLocalizedString msg;
 
  248                    msg = 
ki18n(
"<p>Your S/MIME signing certificate</p><p align=center>%1</p><p>expired less than a day ago.</p>");
 
  249                } 
else if (isOwnKey) {
 
  250                    msg = 
ki18n(
"<p>Your S/MIME encryption certificate</p><p align=center>%1</p><p>expired less than a day ago.</p>");
 
  252                    msg = 
ki18n(
"<p>The S/MIME certificate for</p><p align=center>%1</p><p>expired less than a day ago.</p>");
 
  256            KLocalizedString msg;
 
  258                msg = 
ki18np(
"<p>Your S/MIME signing certificate</p><p align=center>%2</p><p>expired yesterday.</p>",
 
  259                             "<p>Your S/MIME signing certificate</p><p align=center>%2</p><p>expired %1 days ago.</p>");
 
  260            } 
else if (isOwnKey) {
 
  261                msg = 
ki18np(
"<p>Your S/MIME encryption certificate</p><p align=center>%2</p><p>expired yesterday.</p>",
 
  262                             "<p>Your S/MIME encryption certificate</p><p align=center>%2</p><p>expired %1 days ago.</p>");
 
  264                msg = 
ki18np(
"<p>The S/MIME certificate for</p><p align=center>%2</p><p>expired yesterday.</p>",
 
  265                             "<p>The S/MIME certificate for</p><p align=center>%2</p><p>expired %1 days ago.</p>");
 
  270    qCDebug(LIBKLEO_LOG) << 
"Certificate" << key << 
"expires in" << expiration.duration.count() << 
"days";
 
  273            if (expiration.duration.count() == 0) {
 
  274                KLocalizedString msg;
 
  277                        "<p>The root certificate</p><p align=center><b>%3</b></p>" 
  278                        "<p>for your S/MIME signing certificate</p><p align=center>%2</p>" 
  279                        "<p>expires today.</p>");
 
  280                } 
else if (isOwnKey) {
 
  282                        "<p>The root certificate</p><p align=center><b>%3</b></p>" 
  283                        "<p>for your S/MIME encryption certificate</p><p align=center>%2</p>" 
  284                        "<p>expires today.</p>");
 
  287                        "<p>The root certificate</p><p align=center><b>%3</b></p>" 
  288                        "<p>for S/MIME certificate</p><p align=center>%2</p>" 
  289                        "<p>expires today.</p>");
 
  291                return msg.
subs(userCertInfo).
subs(Formatting::prettyDN(key.userID(0).id())).
toString();
 
  293            KLocalizedString msg;
 
  296                    "<p>The root certificate</p><p align=center><b>%3</b></p>" 
  297                    "<p>for your S/MIME signing certificate</p><p align=center>%2</p>" 
  298                    "<p>expires tomorrow.</p>",
 
  299                    "<p>The root certificate</p><p align=center><b>%3</b></p>" 
  300                    "<p>for your S/MIME signing certificate</p><p align=center>%2</p>" 
  301                    "<p>expires in %1 days.</p>");
 
  302            } 
else if (isOwnKey) {
 
  304                    "<p>The root certificate</p><p align=center><b>%3</b></p>" 
  305                    "<p>for your S/MIME encryption certificate</p><p align=center>%2</p>" 
  306                    "<p>expires tomorrow.</p>",
 
  307                    "<p>The root certificate</p><p align=center><b>%3</b></p>" 
  308                    "<p>for your S/MIME encryption certificate</p><p align=center>%2</p>" 
  309                    "<p>expires in %1 days.</p>");
 
  312                    "<p>The root certificate</p><p align=center><b>%3</b></p>" 
  313                    "<p>for S/MIME certificate</p><p align=center>%2</p>" 
  314                    "<p>expires tomorrow.</p>",
 
  315                    "<p>The root certificate</p><p align=center><b>%3</b></p>" 
  316                    "<p>for S/MIME certificate</p><p align=center>%2</p>" 
  317                    "<p>expires in %1 days.</p>");
 
  319            return msg.
subs(expiration.duration.count()).
subs(userCertInfo).
subs(Formatting::prettyDN(key.userID(0).id())).
toString();
 
  321        if (expiration.duration.count() == 0) {
 
  322            KLocalizedString msg;
 
  325                    "<p>The intermediate CA certificate</p><p align=center><b>%3</b></p>" 
  326                    "<p>for your S/MIME signing certificate</p><p align=center>%2</p>" 
  327                    "<p>expires today.</p>");
 
  328            } 
else if (isOwnKey) {
 
  330                    "<p>The intermediate CA certificate</p><p align=center><b>%3</b></p>" 
  331                    "<p>for your S/MIME encryption certificate</p><p align=center>%2</p>" 
  332                    "<p>expires today.</p>");
 
  335                    "<p>The intermediate CA certificate</p><p align=center><b>%3</b></p>" 
  336                    "<p>for S/MIME certificate</p><p align=center>%2</p>" 
  337                    "<p>expires today.</p>");
 
  340        KLocalizedString msg;
 
  343                "<p>The intermediate CA certificate</p><p align=center><b>%3</b></p>" 
  344                "<p>for your S/MIME signing certificate</p><p align=center>%2</p>" 
  345                "<p>expires tomorrow.</p>",
 
  346                "<p>The intermediate CA certificate</p><p align=center><b>%3</b></p>" 
  347                "<p>for your S/MIME signing certificate</p><p align=center>%2</p>" 
  348                "<p>expires in %1 days.</p>");
 
  349        } 
else if (isOwnKey) {
 
  351                "<p>The intermediate CA certificate</p><p align=center><b>%3</b></p>" 
  352                "<p>for your S/MIME encryption certificate</p><p align=center>%2</p>" 
  353                "<p>expires tomorrow.</p>",
 
  354                "<p>The intermediate CA certificate</p><p align=center><b>%3</b></p>" 
  355                "<p>for your S/MIME encryption certificate</p><p align=center>%2</p>" 
  356                "<p>expires in %1 days.</p>");
 
  359                "<p>The intermediate CA certificate</p><p align=center><b>%3</b></p>" 
  360                "<p>for S/MIME certificate</p><p align=center>%2</p>" 
  361                "<p>expires tomorrow.</p>",
 
  362                "<p>The intermediate CA certificate</p><p align=center><b>%3</b></p>" 
  363                "<p>for S/MIME certificate</p><p align=center>%2</p>" 
  364                "<p>expires in %1 days.</p>");
 
  366        return msg.
subs(expiration.duration.count()).
subs(userCertInfo).
subs(Formatting::prettyDN(key.userID(0).id())).
toString();
 
  368    if (expiration.duration.count() == 0) {
 
  369        KLocalizedString msg;
 
  371            msg = 
ki18n(
"<p>Your S/MIME signing certificate</p><p align=center>%2</p><p>expires today.</p>");
 
  372        } 
else if (isOwnKey) {
 
  373            msg = 
ki18n(
"<p>Your S/MIME encryption certificate</p><p align=center>%2</p><p>expires today.</p>");
 
  375            msg = 
ki18n(
"<p>The S/MIME certificate for</p><p align=center>%2</p><p>expires today.</p>");
 
  379    KLocalizedString msg;
 
  382            "<p>Your S/MIME signing certificate</p><p align=center>%2</p>" 
  383            "<p>expires tomorrow.</p>",
 
  384            "<p>Your S/MIME signing certificate</p><p align=center>%2</p>" 
  385            "<p>expires in %1 days.</p>");
 
  386    } 
else if (isOwnKey) {
 
  388            "<p>Your S/MIME encryption certificate</p><p align=center>%2</p>" 
  389            "<p>expires tomorrow.</p>",
 
  390            "<p>Your S/MIME encryption certificate</p><p align=center>%2</p>" 
  391            "<p>expires in %1 days.</p>");
 
  394            "<p>The S/MIME certificate for</p><p align=center>%2</p>" 
  395            "<p>expires tomorrow.</p>",
 
  396            "<p>The S/MIME certificate for</p><p align=center>%2</p>" 
  397            "<p>expires in %1 days.</p>");
 
  402static GpgME::Subkey findBestSubkey(
const GpgME::Key &key, ExpiryChecker::CheckFlags usageFlags)
 
  405    if (!(usageFlags & ExpiryChecker::UsageMask)) {
 
  407        return key.subkey(0);
 
  409    GpgME::Subkey result;
 
  410    for (
unsigned int i = 0; i < key.numSubkeys(); ++i) {
 
  411        const auto subkey = key.subkey(i);
 
  412        if (subkey.isRevoked() || subkey.isInvalid() || subkey.isDisabled()) {
 
  416        if (((usageFlags & ExpiryChecker::EncryptionKey) && !subkey.canEncrypt()) 
 
  417            || ((usageFlags & ExpiryChecker::SigningKey) && !subkey.canSign()) 
 
  418            || ((usageFlags & ExpiryChecker::CertificationKey) && !subkey.canCertify())) {
 
  422        if (subkey.neverExpires()) {
 
  425            return key.subkey(0);
 
  427        if (quint32(subkey.expirationTime()) > quint32(result.expirationTime())) {
 
  434ExpiryChecker::Expiration ExpiryCheckerPrivate::calculateExpiration(
const GpgME::Subkey &subkey)
 const 
  436    if (subkey.neverExpires()) {
 
  437        return {subkey.parent(), ExpiryChecker::NotNearExpiry, Kleo::chrono::days::zero()};
 
  440    const auto currentDate = timeProvider ? timeProvider->currentDate() : 
QDate::currentDate();
 
  441    const auto timeZone = timeProvider ? timeProvider->timeZone() : QTimeZone{
QTimeZone::LocalTime};
 
  443    const qint64 expirationTime = qint64(subkey.expirationTime() < 0 ? quint32(subkey.expirationTime()) : subkey.expirationTime());
 
  445    if (expirationTime <= currentTime) {
 
  446        return {subkey.parent(), ExpiryChecker::Expired, Kleo::chrono::days{expirationDate.
daysTo(currentDate)}};
 
  448        return {subkey.parent(), ExpiryChecker::ExpiresSoon, Kleo::chrono::days{currentDate.daysTo(expirationDate)}};
 
  452ExpiryChecker::Expiration ExpiryCheckerPrivate::checkForExpiration(
const GpgME::Key &key, 
 
  453                                                                   Kleo::chrono::days threshold,
 
  454                                                                   ExpiryChecker::CheckFlags usageFlags)
 const 
  456    const auto subkey = findBestSubkey(key, usageFlags);
 
  457    if (subkey.isNull()) {
 
  458        return {key, ExpiryChecker::NoSuitableSubkey, {}};
 
  460    ExpiryChecker::Expiration expiration = calculateExpiration(subkey);
 
  461    if ((expiration.status == ExpiryChecker::ExpiresSoon) && (expiration.duration > threshold)) {
 
  463        expiration.status = ExpiryChecker::NotNearExpiry;
 
  468ExpiryChecker::Result ExpiryCheckerPrivate::checkKeyNearExpiry(
const GpgME::Key &orig_key, ExpiryChecker::CheckFlags flags)
 
  470    static const int maximumCertificateChainLength = 100;
 
  471    const bool isOwnKey = flags & ExpiryChecker::OwnKey;
 
  473    ExpiryChecker::Result result;
 
  474    result.checkFlags = flags;
 
  475    result.expiration.certificate = orig_key;
 
  478    std::vector<std::string> checkedCertificates;
 
  480    for (
int chainCount = 0; chainCount < maximumCertificateChainLength; ++chainCount) {
 
  481        checkedCertificates.push_back(key.primaryFingerprint());
 
  483        const GpgME::Subkey subkey = key.subkey(0);
 
  485        const bool newMessage = !alreadyWarnedFingerprints.count(subkey.fingerprint());
 
  487        const auto threshold = chainCount > 0 
 
  488            ? (key.isRoot() ? settings.rootCertThreshold() : settings.chainCertThreshold()) 
 
  489            : (isOwnKey ? settings.ownKeyThreshold() : settings.otherKeyThreshold());
 
  490        const auto usageFlags = (chainCount == 0) ? (flags & ExpiryChecker::UsageMask) : ExpiryChecker::CheckFlags{};
 
  491        const auto expiration = checkForExpiration(key, threshold, usageFlags);
 
  492        if (chainCount == 0) {
 
  493            result.expiration = expiration;
 
  494        } 
else if (expiration.status != ExpiryChecker::NotNearExpiry) {
 
  495            result.chainExpiration.push_back(expiration);
 
  497        if (expiration.status == ExpiryChecker::Expired) {
 
  498            const QString msg = key.protocol() == GpgME::OpenPGP 
 
  499                ? formatOpenPGPMessage(expiration, flags)
 
  500                : formatSMIMEMessage(orig_key, expiration, flags, chainCount > 0);
 
  501            alreadyWarnedFingerprints.
insert(subkey.fingerprint());
 
  502            Q_EMIT q->expiryMessage(key, msg, isOwnKey ? ExpiryChecker::OwnKeyExpired : ExpiryChecker::OtherKeyExpired, newMessage);
 
  503        } 
else if (expiration.status == ExpiryChecker::ExpiresSoon) {
 
  504            const QString msg = key.protocol() == GpgME::OpenPGP 
 
  505                ? formatOpenPGPMessage(expiration, flags)
 
  506                : formatSMIMEMessage(orig_key, expiration, flags, chainCount > 0);
 
  507            alreadyWarnedFingerprints.
insert(subkey.fingerprint());
 
  508            Q_EMIT q->expiryMessage(key, msg, isOwnKey ? ExpiryChecker::OwnKeyNearExpiry : ExpiryChecker::OtherKeyNearExpiry, newMessage);
 
  509        } 
else if (expiration.status == ExpiryChecker::NoSuitableSubkey) {
 
  512        if (!(flags & ExpiryChecker::CheckChain) || key.isRoot() || (key.protocol() != GpgME::CMS)) {
 
  515        const auto keys = KeyCache::instance()->findIssuers(key, KeyCache::NoOption);
 
  520        if (Kleo::contains(checkedCertificates, key.primaryFingerprint())) {
 
  527ExpiryChecker::Result ExpiryChecker::checkKey(
const GpgME::Key &key, CheckFlags flags)
 const 
  530        qWarning(LIBKLEO_LOG) << __func__ << 
"called with null key";
 
  531        return {flags, {key, InvalidKey, {}}, {}};
 
  533    if (!(flags & UsageMask)) {
 
  534        qWarning(LIBKLEO_LOG) << __func__ << 
"called with invalid flags:" << flags;
 
  535        return {flags, {key, InvalidCheckFlags, {}}, {}};
 
  537    return d->checkKeyNearExpiry(key, flags);
 
  540void ExpiryChecker::setTimeProviderForTest(
const std::shared_ptr<TimeProvider> &timeProvider)
 
  542    d->timeProvider = timeProvider;
 
  545#include "moc_expirychecker.cpp" 
KLocalizedString subs(const KLocalizedString &a, int fieldWidth=0, QChar fillChar=QLatin1Char(' ')) const
 
KLocalizedString KI18N_EXPORT ki18np(const char *singular, const char *plural)
 
KLocalizedString KI18N_EXPORT ki18n(const char *text)
 
KLocalizedString KI18N_EXPORT ki18nc(const char *context, const char *text)
 
qint64 daysTo(QDate d) const const
 
qint64 currentSecsSinceEpoch()
 
QDateTime fromSecsSinceEpoch(qint64 secs)
 
QString fromLatin1(QByteArrayView str)
 
QString fromUtf8(QByteArrayView str)
 
QString & insert(qsizetype position, QChar ch)