File indexing completed on 2025-03-09 04:54:31
0001 /* 0002 SPDX-FileCopyrightText: 2019-2024 Laurent Montel <montel@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "dkimwidgetinfo.h" 0008 #include "dkimmanager.h" 0009 #include "dkimutil.h" 0010 #include "messageviewer_dkimcheckerdebug.h" 0011 #include <KColorScheme> 0012 #include <KLocalizedString> 0013 0014 #include <QHBoxLayout> 0015 #include <QLabel> 0016 0017 using namespace MessageViewer; 0018 DKIMWidgetInfo::DKIMWidgetInfo(QWidget *parent) 0019 : QWidget(parent) 0020 , mLabel(new QLabel(this)) 0021 { 0022 auto mainLayout = new QHBoxLayout(this); 0023 mainLayout->setObjectName(QLatin1StringView("mainLayout")); 0024 mainLayout->setContentsMargins({}); 0025 0026 mLabel->setAutoFillBackground(true); 0027 mLabel->setObjectName(QLatin1StringView("label")); 0028 mainLayout->addWidget(mLabel); 0029 connect(DKIMManager::self(), &DKIMManager::result, this, &DKIMWidgetInfo::setResult); 0030 connect(DKIMManager::self(), &DKIMManager::clearInfo, this, &DKIMWidgetInfo::clear); 0031 initColors(); 0032 } 0033 0034 DKIMWidgetInfo::~DKIMWidgetInfo() = default; 0035 0036 void DKIMWidgetInfo::updatePalette() 0037 { 0038 initColors(); 0039 updateInfo(); 0040 } 0041 0042 void DKIMWidgetInfo::initColors() 0043 { 0044 const KColorScheme colorScheme{QPalette::Active}; 0045 mWarningColor = colorScheme.background(KColorScheme::NeutralBackground).color(); 0046 mErrorColor = colorScheme.background(KColorScheme::NegativeBackground).color(); 0047 mOkColor = colorScheme.background(KColorScheme::PositiveBackground).color(); 0048 mDefaultColor = Qt::transparent; // colorScheme.background(KColorScheme::ActiveBackground).color(); 0049 } 0050 0051 MessageViewer::DKIMCheckSignatureJob::CheckSignatureResult DKIMWidgetInfo::result() const 0052 { 0053 return mResult; 0054 } 0055 0056 Akonadi::Item::Id DKIMWidgetInfo::currentItemId() const 0057 { 0058 return mCurrentItemId; 0059 } 0060 0061 void DKIMWidgetInfo::setCurrentItemId(Akonadi::Item::Id currentItemId) 0062 { 0063 mCurrentItemId = currentItemId; 0064 } 0065 0066 void DKIMWidgetInfo::setResult(const DKIMCheckSignatureJob::CheckSignatureResult &checkResult, Akonadi::Item::Id id) 0067 { 0068 if (mCurrentItemId == id) { 0069 if (mResult != checkResult) { 0070 mResult = checkResult; 0071 updateInfo(); 0072 } 0073 } 0074 } 0075 0076 void DKIMWidgetInfo::clear() 0077 { 0078 mLabel->clear(); 0079 mLabel->setToolTip(QString()); 0080 QPalette pal = mLabel->palette(); 0081 pal.setColor(backgroundRole(), mDefaultColor); 0082 mLabel->setPalette(pal); 0083 mCurrentItemId = -1; 0084 mResult = {}; 0085 } 0086 0087 void DKIMWidgetInfo::updateInfo() 0088 { 0089 QPalette pal = mLabel->palette(); 0090 switch (mResult.status) { 0091 case DKIMCheckSignatureJob::DKIMStatus::Unknown: 0092 pal.setColor(backgroundRole(), mDefaultColor); 0093 mLabel->setPalette(pal); 0094 mLabel->setText(i18n("Unknown")); 0095 break; 0096 case DKIMCheckSignatureJob::DKIMStatus::Valid: 0097 if (mResult.sdid.isEmpty()) { 0098 qCWarning(MESSAGEVIEWER_DKIMCHECKER_LOG) << "mResult.sdid is empty. It's a bug"; 0099 } 0100 mLabel->setText(i18n("DKIM: valid (signed by %1)", mResult.sdid)); 0101 pal.setColor(backgroundRole(), (mResult.warning != DKIMCheckSignatureJob::DKIMWarning::Any) ? mWarningColor : mOkColor); 0102 mLabel->setPalette(pal); 0103 break; 0104 case DKIMCheckSignatureJob::DKIMStatus::Invalid: 0105 pal.setColor(backgroundRole(), mErrorColor); 0106 mLabel->setPalette(pal); 0107 mLabel->setText(i18n("DKIM: invalid")); 0108 break; 0109 case DKIMCheckSignatureJob::DKIMStatus::EmailNotSigned: 0110 mLabel->setText(i18n("DKIM: Not signed")); 0111 pal.setColor(backgroundRole(), mDefaultColor); 0112 mLabel->setPalette(pal); 0113 break; 0114 case DKIMCheckSignatureJob::DKIMStatus::NeedToBeSigned: 0115 mLabel->setText(i18n("DKIM: Should Be Signed by %1", mResult.sdid)); 0116 pal.setColor(backgroundRole(), mErrorColor); 0117 mLabel->setPalette(pal); 0118 break; 0119 } 0120 updateToolTip(); 0121 } 0122 0123 void DKIMWidgetInfo::updateToolTip() 0124 { 0125 QString tooltip; 0126 if (mResult.status == DKIMCheckSignatureJob::DKIMStatus::Invalid) { 0127 switch (mResult.error) { 0128 case DKIMCheckSignatureJob::DKIMError::Any: 0129 break; 0130 case DKIMCheckSignatureJob::DKIMError::CorruptedBodyHash: 0131 tooltip = i18n("Body Hash was corrupted."); 0132 break; 0133 case DKIMCheckSignatureJob::DKIMError::DomainNotExist: 0134 tooltip = i18n("The domain doesn't exist."); 0135 break; 0136 case DKIMCheckSignatureJob::DKIMError::MissingFrom: 0137 tooltip = i18n("Missing header From."); 0138 break; 0139 case DKIMCheckSignatureJob::DKIMError::MissingSignature: 0140 tooltip = i18n("Missing signature."); 0141 break; 0142 case DKIMCheckSignatureJob::DKIMError::InvalidQueryMethod: 0143 tooltip = i18n("Invalid query method."); 0144 break; 0145 case DKIMCheckSignatureJob::DKIMError::InvalidHeaderCanonicalization: 0146 tooltip = i18n("Invalid header canonicalization."); 0147 break; 0148 case DKIMCheckSignatureJob::DKIMError::InvalidBodyCanonicalization: 0149 tooltip = i18n("Invalid body canonicalization."); 0150 break; 0151 case DKIMCheckSignatureJob::DKIMError::InvalidBodyHashAlgorithm: 0152 tooltip = i18n("Unknown Body Hash Algorithm."); 0153 break; 0154 case DKIMCheckSignatureJob::DKIMError::InvalidSignAlgorithm: 0155 tooltip = i18n("Signature algorithm is invalid."); 0156 break; 0157 case DKIMCheckSignatureJob::DKIMError::PublicKeyWasRevoked: 0158 tooltip = i18n("The public key was revoked."); 0159 break; 0160 case DKIMCheckSignatureJob::DKIMError::SignatureTooLarge: 0161 tooltip = i18n("Signature is too large."); 0162 break; 0163 case DKIMCheckSignatureJob::DKIMError::InsupportedHashAlgorithm: 0164 tooltip = i18n("Hash Algorithm is unsupported."); 0165 break; 0166 case DKIMCheckSignatureJob::DKIMError::PublicKeyTooSmall: 0167 tooltip = i18n("Public key is too small."); 0168 break; 0169 case DKIMCheckSignatureJob::DKIMError::ImpossibleToVerifySignature: 0170 tooltip = i18n("Impossible to verify signature."); 0171 break; 0172 case DKIMCheckSignatureJob::DKIMError::DomainI: 0173 tooltip = i18n("AUID must be in the same domain as SDID (s-flag set in key record)."); 0174 break; 0175 case DKIMCheckSignatureJob::DKIMError::TestKeyMode: 0176 tooltip = i18n("The signing domain is only testing DKIM."); 0177 break; 0178 case DKIMCheckSignatureJob::DKIMError::ImpossibleToDownloadKey: 0179 tooltip = i18n("Impossible to download key."); 0180 break; 0181 case DKIMCheckSignatureJob::DKIMError::HashAlgorithmUnsafeSha1: 0182 tooltip = i18n("Hash Algorithm unsafe (sha1)"); 0183 break; 0184 case DKIMCheckSignatureJob::DKIMError::IDomainError: 0185 tooltip = i18n("AUID is not in a subdomain of SDID"); 0186 break; 0187 case DKIMCheckSignatureJob::DKIMError::PublicKeyConversionError: 0188 tooltip = i18n("Problem during converting public key"); 0189 break; 0190 } 0191 } 0192 0193 switch (mResult.warning) { 0194 case DKIMCheckSignatureJob::DKIMWarning::Any: 0195 break; 0196 case DKIMCheckSignatureJob::DKIMWarning::SignatureExpired: 0197 tooltip += (tooltip.isEmpty() ? QChar() : QLatin1Char('\n')) + i18n("Signature expired"); 0198 break; 0199 case DKIMCheckSignatureJob::DKIMWarning::SignatureCreatedInFuture: 0200 tooltip += (tooltip.isEmpty() ? QChar() : QLatin1Char('\n')) + i18n("Signature created in the future"); 0201 break; 0202 case DKIMCheckSignatureJob::DKIMWarning::SignatureTooSmall: 0203 tooltip += (tooltip.isEmpty() ? QChar() : QLatin1Char('\n')) + i18n("Signature too small"); 0204 break; 0205 case DKIMCheckSignatureJob::DKIMWarning::HashAlgorithmUnsafe: 0206 tooltip += (tooltip.isEmpty() ? QChar() : QLatin1Char('\n')) + i18n("Hash Algorithm unsafe (sha1)"); 0207 break; 0208 case DKIMCheckSignatureJob::DKIMWarning::PublicRsaKeyTooSmall: 0209 tooltip += (tooltip.isEmpty() ? QChar() : QLatin1Char('\n')) + i18n("Public Key too small"); 0210 break; 0211 } 0212 0213 if (mResult.status != DKIMCheckSignatureJob::DKIMStatus::Invalid) { 0214 QStringList tooltipList; 0215 for (const DKIMCheckSignatureJob::DKIMCheckSignatureAuthenticationResult &result : std::as_const(mResult.listSignatureAuthenticationResult)) { 0216 switch (result.status) { 0217 case DKIMCheckSignatureJob::DKIMStatus::Unknown: 0218 break; 0219 case DKIMCheckSignatureJob::DKIMStatus::Invalid: 0220 switch (result.method) { 0221 case DKIMCheckSignatureJob::AuthenticationMethod::Unknown: { 0222 break; 0223 } 0224 case DKIMCheckSignatureJob::AuthenticationMethod::Spf: 0225 case DKIMCheckSignatureJob::AuthenticationMethod::Dkim: 0226 case DKIMCheckSignatureJob::AuthenticationMethod::Dmarc: 0227 case DKIMCheckSignatureJob::AuthenticationMethod::Auth: 0228 case DKIMCheckSignatureJob::AuthenticationMethod::Dkimatps: { 0229 const QString str = i18nc("method name: info about it from parsing", 0230 "%1: %2", 0231 MessageViewer::DKIMUtil::convertAuthenticationMethodEnumToString(result.method), 0232 result.infoResult); 0233 if (!tooltipList.contains(str)) { 0234 tooltipList.append(str); 0235 } 0236 break; 0237 } 0238 } 0239 break; 0240 0241 case DKIMCheckSignatureJob::DKIMStatus::NeedToBeSigned: 0242 break; 0243 case DKIMCheckSignatureJob::DKIMStatus::EmailNotSigned: 0244 switch (result.method) { 0245 case DKIMCheckSignatureJob::AuthenticationMethod::Unknown: { 0246 break; 0247 } 0248 case DKIMCheckSignatureJob::AuthenticationMethod::Spf: 0249 case DKIMCheckSignatureJob::AuthenticationMethod::Dkim: 0250 case DKIMCheckSignatureJob::AuthenticationMethod::Dmarc: 0251 case DKIMCheckSignatureJob::AuthenticationMethod::Auth: 0252 case DKIMCheckSignatureJob::AuthenticationMethod::Dkimatps: { 0253 const QString str = i18n("%1: None", MessageViewer::DKIMUtil::convertAuthenticationMethodEnumToString(result.method)); 0254 if (!tooltipList.contains(str)) { 0255 tooltipList.append(str); 0256 } 0257 break; 0258 } 0259 } 0260 break; 0261 case DKIMCheckSignatureJob::DKIMStatus::Valid: 0262 switch (result.method) { 0263 case DKIMCheckSignatureJob::AuthenticationMethod::Unknown: { 0264 break; 0265 } 0266 case DKIMCheckSignatureJob::AuthenticationMethod::Dkim: { 0267 const QString str = 0268 i18n("%1: Valid (Signed by %2)", MessageViewer::DKIMUtil::convertAuthenticationMethodEnumToString(result.method), result.sdid); 0269 if (!tooltipList.contains(str)) { 0270 tooltipList.append(str); 0271 } 0272 break; 0273 } 0274 case DKIMCheckSignatureJob::AuthenticationMethod::Spf: { 0275 const QString str = i18nc("method name: info about it from parsing", 0276 "%1: %2", 0277 MessageViewer::DKIMUtil::convertAuthenticationMethodEnumToString(result.method), 0278 result.infoResult); 0279 if (!tooltipList.contains(str)) { 0280 tooltipList.append(str); 0281 } 0282 0283 break; 0284 } 0285 case DKIMCheckSignatureJob::AuthenticationMethod::Auth: 0286 case DKIMCheckSignatureJob::AuthenticationMethod::Dkimatps: 0287 case DKIMCheckSignatureJob::AuthenticationMethod::Dmarc: { 0288 const QString str = i18n("%1: Valid", MessageViewer::DKIMUtil::convertAuthenticationMethodEnumToString(result.method)); 0289 if (!tooltipList.contains(str)) { 0290 tooltipList.append(str); 0291 } 0292 0293 break; 0294 } 0295 } 0296 break; 0297 } 0298 } 0299 if (!tooltipList.isEmpty()) { 0300 tooltip += (tooltip.isEmpty() ? QChar() : QLatin1Char('\n')) + tooltipList.join(QLatin1Char('\n')); 0301 } 0302 if (mResult.listSignatureAuthenticationResult.isEmpty()) { 0303 tooltip += (tooltip.isEmpty() ? QChar() : QLatin1Char('\n')) + i18n("Not Signed"); 0304 } 0305 } 0306 qCDebug(MESSAGEVIEWER_DKIMCHECKER_LOG) << "mResult.authentication " << mResult.listSignatureAuthenticationResult; 0307 0308 mLabel->setToolTip(tooltip); 0309 } 0310 0311 bool DKIMWidgetInfo::event(QEvent *e) 0312 { 0313 if (e->type() == QEvent::ApplicationPaletteChange) { 0314 updatePalette(); 0315 } 0316 return QWidget::event(e); 0317 } 0318 0319 #include "moc_dkimwidgetinfo.cpp"