File indexing completed on 2024-11-24 04:49:36
0001 /* 0002 kconfigbasedkeyfilter.cpp 0003 0004 This file is part of libkleopatra, the KDE keymanagement library 0005 SPDX-FileCopyrightText: 2004 Klarälvdalens Datakonsult AB 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 0010 #include <config-libkleo.h> 0011 0012 #include "kconfigbasedkeyfilter.h" 0013 0014 #include <KConfigBase> 0015 #include <KConfigGroup> 0016 0017 #include <QDebug> 0018 #include <QRegularExpression> 0019 0020 #include <algorithm> 0021 0022 using namespace Kleo; 0023 using namespace GpgME; 0024 0025 // 0026 // 0027 // FontDescription - intuitive font property resolving 0028 // (QFont::resolve doesn't work for us) 0029 // 0030 // 0031 struct KeyFilter::FontDescription::Private { 0032 bool bold, italic, strikeOut, fullFont; 0033 QFont font; 0034 }; 0035 0036 KeyFilter::FontDescription::FontDescription() 0037 : d(new Private) 0038 { 0039 d->bold = d->italic = d->strikeOut = d->fullFont = false; 0040 } 0041 0042 KeyFilter::FontDescription::FontDescription(const FontDescription &other) 0043 : d(new Private(*other.d)) 0044 { 0045 } 0046 0047 KeyFilter::FontDescription::~FontDescription() = default; 0048 0049 KeyFilter::FontDescription KeyFilter::FontDescription::create(bool b, bool i, bool s) 0050 { 0051 FontDescription fd; 0052 fd.d->bold = b; 0053 fd.d->italic = i; 0054 fd.d->strikeOut = s; 0055 return fd; 0056 } 0057 0058 KeyFilter::FontDescription KeyFilter::FontDescription::create(const QFont &f, bool b, bool i, bool s) 0059 { 0060 FontDescription fd; 0061 fd.d->fullFont = true; 0062 fd.d->font = f; 0063 fd.d->bold = b; 0064 fd.d->italic = i; 0065 fd.d->strikeOut = s; 0066 return fd; 0067 } 0068 0069 QFont KeyFilter::FontDescription::font(const QFont &base) const 0070 { 0071 QFont font; 0072 if (d->fullFont) { 0073 font = d->font; 0074 font.setPointSize(base.pointSize()); 0075 } else { 0076 font = base; 0077 } 0078 if (d->bold) { 0079 font.setBold(true); 0080 } 0081 if (d->italic) { 0082 font.setItalic(true); 0083 } 0084 if (d->strikeOut) { 0085 font.setStrikeOut(true); 0086 } 0087 return font; 0088 } 0089 0090 KeyFilter::FontDescription KeyFilter::FontDescription::resolve(const FontDescription &other) const 0091 { 0092 FontDescription fd; 0093 fd.d->fullFont = this->d->fullFont || other.d->fullFont; 0094 if (fd.d->fullFont) { 0095 fd.d->font = this->d->fullFont ? this->d->font : other.d->font; 0096 } 0097 fd.d->bold = this->d->bold || other.d->bold; 0098 fd.d->italic = this->d->italic || other.d->italic; 0099 fd.d->strikeOut = this->d->strikeOut || other.d->strikeOut; 0100 return fd; 0101 } 0102 0103 static const struct { 0104 const char *name; 0105 Key::OwnerTrust trust; 0106 UserID::Validity validity; 0107 } ownerTrustAndValidityMap[] = { 0108 // clang-format off 0109 {"unknown", Key::Unknown, UserID::Unknown }, 0110 {"undefined", Key::Undefined, UserID::Undefined}, 0111 {"never", Key::Never, UserID::Never }, 0112 {"marginal", Key::Marginal, UserID::Marginal }, 0113 {"full", Key::Full, UserID::Full }, 0114 {"ultimate", Key::Ultimate, UserID::Ultimate }, 0115 // clang-format on 0116 }; 0117 0118 static Key::OwnerTrust map2OwnerTrust(const QString &s) 0119 { 0120 for (unsigned int i = 0; i < sizeof ownerTrustAndValidityMap / sizeof *ownerTrustAndValidityMap; ++i) { 0121 if (s.toLower() == QLatin1StringView(ownerTrustAndValidityMap[i].name)) { 0122 return ownerTrustAndValidityMap[i].trust; 0123 } 0124 } 0125 return ownerTrustAndValidityMap[0].trust; 0126 } 0127 0128 static UserID::Validity map2Validity(const QString &s) 0129 { 0130 for (unsigned int i = 0; i < sizeof ownerTrustAndValidityMap / sizeof *ownerTrustAndValidityMap; ++i) { 0131 if (s.toLower() == QLatin1StringView(ownerTrustAndValidityMap[i].name)) { 0132 return ownerTrustAndValidityMap[i].validity; 0133 } 0134 } 0135 return ownerTrustAndValidityMap[0].validity; 0136 } 0137 0138 KConfigBasedKeyFilter::KConfigBasedKeyFilter(const KConfigGroup &config) 0139 : DefaultKeyFilter() 0140 { 0141 setFgColor(config.readEntry<QColor>("foreground-color", QColor())); 0142 setBgColor(config.readEntry<QColor>("background-color", QColor())); 0143 setName(config.readEntry("Name", config.name())); 0144 setIcon(config.readEntry("icon")); 0145 setId(config.readEntry("id", config.name())); 0146 if (config.hasKey("font")) { 0147 setUseFullFont(true); 0148 setFont(config.readEntry("font")); 0149 } else { 0150 setUseFullFont(false); 0151 setItalic(config.readEntry("font-italic", false)); 0152 setBold(config.readEntry("font-bold", false)); 0153 } 0154 setStrikeOut(config.readEntry("font-strikeout", false)); 0155 #ifdef SET 0156 #undef SET 0157 #endif 0158 #define SET(member, key) \ 0159 if (config.hasKey(key)) { \ 0160 set##member(config.readEntry(key, false) ? Set : NotSet); \ 0161 setSpecificity(specificity() + 1); \ 0162 } 0163 SET(Revoked, "is-revoked"); 0164 SET(Expired, "is-expired"); 0165 SET(Disabled, "is-disabled"); 0166 SET(Root, "is-root-certificate"); 0167 SET(CanEncrypt, "can-encrypt"); 0168 SET(CanSign, "can-sign"); 0169 SET(CanCertify, "can-certify"); 0170 SET(CanAuthenticate, "can-authenticate"); 0171 SET(HasEncrypt, "has-encrypt"); 0172 SET(HasSign, "has-sign"); 0173 SET(HasCertify, "has-certify"); 0174 SET(HasAuthenticate, "has-authenticate"); 0175 SET(Qualified, "is-qualified"); 0176 SET(CardKey, "is-cardkey"); 0177 SET(HasSecret, "has-secret-key"); 0178 SET(IsOpenPGP, "is-openpgp-key"); 0179 SET(WasValidated, "was-validated"); 0180 SET(IsDeVs, "is-de-vs"); 0181 #undef SET 0182 static const struct { 0183 const char *prefix; 0184 LevelState state; 0185 } prefixMap[] = { 0186 {"is-", Is}, 0187 {"is-not-", IsNot}, 0188 {"is-at-least-", IsAtLeast}, 0189 {"is-at-most-", IsAtMost}, 0190 }; 0191 for (unsigned int i = 0; i < sizeof prefixMap / sizeof *prefixMap; ++i) { 0192 const QString key = QLatin1StringView(prefixMap[i].prefix) + QLatin1String("ownertrust"); 0193 if (config.hasKey(key)) { 0194 setOwnerTrust(prefixMap[i].state); 0195 setOwnerTrustReferenceLevel(map2OwnerTrust(config.readEntry(key, QString()))); 0196 setSpecificity(specificity() + 1); 0197 break; 0198 } 0199 } 0200 for (unsigned int i = 0; i < sizeof prefixMap / sizeof *prefixMap; ++i) { 0201 const QString key = QLatin1StringView(prefixMap[i].prefix) + QLatin1String("validity"); 0202 if (config.hasKey(key)) { 0203 setValidity(prefixMap[i].state); 0204 setValidityReferenceLevel(map2Validity(config.readEntry(key, QString()))); 0205 setSpecificity(specificity() + 1); 0206 break; 0207 } 0208 } 0209 static const struct { 0210 const char *key; 0211 MatchContext context; 0212 } matchMap[] = { 0213 {"any", AnyMatchContext}, 0214 {"appearance", Appearance}, 0215 {"filtering", Filtering}, 0216 }; 0217 static const QRegularExpression reg(QRegularExpression(QLatin1StringView("[^a-z!]+"))); 0218 const QStringList contexts = config.readEntry("match-contexts", "any").toLower().split(reg, Qt::SkipEmptyParts); 0219 setMatchContexts(NoMatchContext); 0220 for (const QString &ctx : contexts) { 0221 bool found = false; 0222 for (unsigned int i = 0; i < sizeof matchMap / sizeof *matchMap; ++i) { 0223 if (ctx == QLatin1StringView(matchMap[i].key)) { 0224 setMatchContexts(availableMatchContexts() |= matchMap[i].context); 0225 found = true; 0226 break; 0227 } else if (ctx.startsWith(QLatin1Char('!')) && ctx.mid(1) == QLatin1StringView(matchMap[i].key)) { 0228 setMatchContexts(availableMatchContexts() &= matchMap[i].context); 0229 found = true; 0230 break; 0231 } 0232 } 0233 if (!found) { 0234 qWarning() << QStringLiteral("KConfigBasedKeyFilter: found unknown match context '%1' in group '%2'").arg(ctx, config.name()); 0235 } 0236 } 0237 if (availableMatchContexts() == NoMatchContext) { 0238 qWarning() << QStringLiteral( 0239 "KConfigBasedKeyFilter: match context in group '%1' evaluates to NoMatchContext, " 0240 "replaced by AnyMatchContext") 0241 .arg(config.name()); 0242 setMatchContexts(AnyMatchContext); 0243 } 0244 }