Messagelib

dkimwidgetinfo.cpp
1 /*
2  SPDX-FileCopyrightText: 2019-2023 Laurent Montel <[email protected]>
3 
4  SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6 
7 #include "dkimwidgetinfo.h"
8 #include "dkimmanager.h"
9 #include "dkimutil.h"
10 #include "messageviewer_dkimcheckerdebug.h"
11 #include <KColorScheme>
12 #include <KLocalizedString>
13 
14 #include <QHBoxLayout>
15 #include <QLabel>
16 
17 using namespace MessageViewer;
18 DKIMWidgetInfo::DKIMWidgetInfo(QWidget *parent)
19  : QWidget(parent)
20  , mLabel(new QLabel(this))
21 {
22  auto mainLayout = new QHBoxLayout(this);
23  mainLayout->setObjectName(QStringLiteral("mainLayout"));
24  mainLayout->setContentsMargins({});
25 
26  mLabel->setAutoFillBackground(true);
27  mLabel->setObjectName(QStringLiteral("label"));
28  mainLayout->addWidget(mLabel);
29  connect(DKIMManager::self(), &DKIMManager::result, this, &DKIMWidgetInfo::setResult);
30  connect(DKIMManager::self(), &DKIMManager::clearInfo, this, &DKIMWidgetInfo::clear);
31  initColors();
32 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
33  connect(qApp, &QApplication::paletteChanged, this, &DKIMWidgetInfo::updatePalette);
34 #endif
35 }
36 
37 DKIMWidgetInfo::~DKIMWidgetInfo() = default;
38 
39 void DKIMWidgetInfo::updatePalette()
40 {
41  initColors();
42  updateInfo();
43 }
44 
45 void DKIMWidgetInfo::initColors()
46 {
47  const KColorScheme colorScheme{QPalette::Active};
48  mWarningColor = colorScheme.background(KColorScheme::NeutralBackground).color();
49  mErrorColor = colorScheme.background(KColorScheme::NegativeBackground).color();
50  mOkColor = colorScheme.background(KColorScheme::PositiveBackground).color();
51  mDefaultColor = colorScheme.background(KColorScheme::ActiveBackground).color();
52 }
53 
54 MessageViewer::DKIMCheckSignatureJob::CheckSignatureResult DKIMWidgetInfo::result() const
55 {
56  return mResult;
57 }
58 
59 Akonadi::Item::Id DKIMWidgetInfo::currentItemId() const
60 {
61  return mCurrentItemId;
62 }
63 
64 void DKIMWidgetInfo::setCurrentItemId(Akonadi::Item::Id currentItemId)
65 {
66  mCurrentItemId = currentItemId;
67 }
68 
69 void DKIMWidgetInfo::setResult(const DKIMCheckSignatureJob::CheckSignatureResult &checkResult, Akonadi::Item::Id id)
70 {
71  if (mCurrentItemId == id) {
72  if (mResult != checkResult) {
73  mResult = checkResult;
74  updateInfo();
75  }
76  }
77 }
78 
79 void DKIMWidgetInfo::clear()
80 {
81  mLabel->clear();
82  mLabel->setToolTip(QString());
83  QPalette pal = mLabel->palette();
84  pal.setColor(backgroundRole(), mDefaultColor);
85  mLabel->setPalette(pal);
86  mCurrentItemId = -1;
87  mResult = {};
88 }
89 
90 void DKIMWidgetInfo::updateInfo()
91 {
92  QPalette pal = mLabel->palette();
93  switch (mResult.status) {
94  case DKIMCheckSignatureJob::DKIMStatus::Unknown:
95  pal.setColor(backgroundRole(), mDefaultColor);
96  mLabel->setPalette(pal);
97  mLabel->setText(i18n("Unknown"));
98  break;
99  case DKIMCheckSignatureJob::DKIMStatus::Valid:
100  if (mResult.sdid.isEmpty()) {
101  qCWarning(MESSAGEVIEWER_DKIMCHECKER_LOG) << "mResult.sdid is empty. It's a bug";
102  }
103  mLabel->setText(i18n("DKIM: valid (signed by %1)", mResult.sdid));
104  pal.setColor(backgroundRole(), (mResult.warning != DKIMCheckSignatureJob::DKIMWarning::Any) ? mWarningColor : mOkColor);
105  mLabel->setPalette(pal);
106  break;
107  case DKIMCheckSignatureJob::DKIMStatus::Invalid:
108  pal.setColor(backgroundRole(), mErrorColor);
109  mLabel->setPalette(pal);
110  mLabel->setText(i18n("DKIM: invalid"));
111  break;
112  case DKIMCheckSignatureJob::DKIMStatus::EmailNotSigned:
113  mLabel->setText(i18n("DKIM: Not signed"));
114  pal.setColor(backgroundRole(), mDefaultColor);
115  mLabel->setPalette(pal);
116  break;
117  case DKIMCheckSignatureJob::DKIMStatus::NeedToBeSigned:
118  mLabel->setText(i18n("DKIM: Should Be Signed by %1", mResult.sdid));
119  pal.setColor(backgroundRole(), mErrorColor);
120  mLabel->setPalette(pal);
121  break;
122  }
123  updateToolTip();
124 }
125 
126 void DKIMWidgetInfo::updateToolTip()
127 {
128  QString tooltip;
129  if (mResult.status == DKIMCheckSignatureJob::DKIMStatus::Invalid) {
130  switch (mResult.error) {
131  case DKIMCheckSignatureJob::DKIMError::Any:
132  break;
133  case DKIMCheckSignatureJob::DKIMError::CorruptedBodyHash:
134  tooltip = i18n("Body Hash was corrupted.");
135  break;
136  case DKIMCheckSignatureJob::DKIMError::DomainNotExist:
137  tooltip = i18n("The domain doesn't exist.");
138  break;
139  case DKIMCheckSignatureJob::DKIMError::MissingFrom:
140  tooltip = i18n("Missing header From.");
141  break;
142  case DKIMCheckSignatureJob::DKIMError::MissingSignature:
143  tooltip = i18n("Missing signature.");
144  break;
145  case DKIMCheckSignatureJob::DKIMError::InvalidQueryMethod:
146  tooltip = i18n("Invalid query method.");
147  break;
148  case DKIMCheckSignatureJob::DKIMError::InvalidHeaderCanonicalization:
149  tooltip = i18n("Invalid header canonicalization.");
150  break;
151  case DKIMCheckSignatureJob::DKIMError::InvalidBodyCanonicalization:
152  tooltip = i18n("Invalid body canonicalization.");
153  break;
154  case DKIMCheckSignatureJob::DKIMError::InvalidBodyHashAlgorithm:
155  tooltip = i18n("Unknown Body Hash Algorithm.");
156  break;
157  case DKIMCheckSignatureJob::DKIMError::InvalidSignAlgorithm:
158  tooltip = i18n("Signature algorithm is invalid.");
159  break;
160  case DKIMCheckSignatureJob::DKIMError::PublicKeyWasRevoked:
161  tooltip = i18n("The public key was revoked.");
162  break;
163  case DKIMCheckSignatureJob::DKIMError::SignatureTooLarge:
164  tooltip = i18n("Signature is too large.");
165  break;
166  case DKIMCheckSignatureJob::DKIMError::InsupportedHashAlgorithm:
167  tooltip = i18n("Hash Algorithm is unsupported.");
168  break;
169  case DKIMCheckSignatureJob::DKIMError::PublicKeyTooSmall:
170  tooltip = i18n("Public key is too small.");
171  break;
172  case DKIMCheckSignatureJob::DKIMError::ImpossibleToVerifySignature:
173  tooltip = i18n("Impossible to verify signature.");
174  break;
175  case DKIMCheckSignatureJob::DKIMError::DomainI:
176  tooltip = i18n("AUID must be in the same domain as SDID (s-flag set in key record).");
177  break;
178  case DKIMCheckSignatureJob::DKIMError::TestKeyMode:
179  tooltip = i18n("The signing domain is only testing DKIM.");
180  break;
181  case DKIMCheckSignatureJob::DKIMError::ImpossibleToDownloadKey:
182  tooltip = i18n("Impossible to download key.");
183  break;
184  case DKIMCheckSignatureJob::DKIMError::HashAlgorithmUnsafeSha1:
185  tooltip = i18n("Hash Algorithm unsafe (sha1)");
186  break;
187  case DKIMCheckSignatureJob::DKIMError::IDomainError:
188  tooltip = i18n("AUID is not in a subdomain of SDID");
189  break;
190  case DKIMCheckSignatureJob::DKIMError::PublicKeyConversionError:
191  tooltip = i18n("Problem during converting public key");
192  break;
193  }
194  }
195 
196  switch (mResult.warning) {
197  case DKIMCheckSignatureJob::DKIMWarning::Any:
198  break;
199  case DKIMCheckSignatureJob::DKIMWarning::SignatureExpired:
200  tooltip += (tooltip.isEmpty() ? QChar() : QLatin1Char('\n')) + i18n("Signature expired");
201  break;
202  case DKIMCheckSignatureJob::DKIMWarning::SignatureCreatedInFuture:
203  tooltip += (tooltip.isEmpty() ? QChar() : QLatin1Char('\n')) + i18n("Signature created in the future");
204  break;
205  case DKIMCheckSignatureJob::DKIMWarning::SignatureTooSmall:
206  tooltip += (tooltip.isEmpty() ? QChar() : QLatin1Char('\n')) + i18n("Signature too small");
207  break;
208  case DKIMCheckSignatureJob::DKIMWarning::HashAlgorithmUnsafe:
209  tooltip += (tooltip.isEmpty() ? QChar() : QLatin1Char('\n')) + i18n("Hash Algorithm unsafe (sha1)");
210  break;
211  case DKIMCheckSignatureJob::DKIMWarning::PublicRsaKeyTooSmall:
212  tooltip += (tooltip.isEmpty() ? QChar() : QLatin1Char('\n')) + i18n("Public Key too small");
213  break;
214  }
215 
216  if (mResult.status != DKIMCheckSignatureJob::DKIMStatus::Invalid) {
217  QStringList tooltipList;
218  for (const DKIMCheckSignatureJob::DKIMCheckSignatureAuthenticationResult &result : std::as_const(mResult.listSignatureAuthenticationResult)) {
219  switch (result.status) {
220  case DKIMCheckSignatureJob::DKIMStatus::Unknown:
221  break;
222  case DKIMCheckSignatureJob::DKIMStatus::Invalid:
223  switch (result.method) {
224  case DKIMCheckSignatureJob::AuthenticationMethod::Unknown: {
225  break;
226  }
227  case DKIMCheckSignatureJob::AuthenticationMethod::Spf:
228  case DKIMCheckSignatureJob::AuthenticationMethod::Dkim:
229  case DKIMCheckSignatureJob::AuthenticationMethod::Dmarc:
230  case DKIMCheckSignatureJob::AuthenticationMethod::Auth:
231  case DKIMCheckSignatureJob::AuthenticationMethod::Dkimatps: {
232  const QString str = i18nc("method name: info about it from parsing",
233  "%1: %2",
234  MessageViewer::DKIMUtil::convertAuthenticationMethodEnumToString(result.method),
235  result.infoResult);
236  if (!tooltipList.contains(str)) {
237  tooltipList.append(str);
238  }
239  break;
240  }
241  }
242  break;
243 
244  case DKIMCheckSignatureJob::DKIMStatus::NeedToBeSigned:
245  break;
246  case DKIMCheckSignatureJob::DKIMStatus::EmailNotSigned:
247  switch (result.method) {
248  case DKIMCheckSignatureJob::AuthenticationMethod::Unknown: {
249  break;
250  }
251  case DKIMCheckSignatureJob::AuthenticationMethod::Spf:
252  case DKIMCheckSignatureJob::AuthenticationMethod::Dkim:
253  case DKIMCheckSignatureJob::AuthenticationMethod::Dmarc:
254  case DKIMCheckSignatureJob::AuthenticationMethod::Auth:
255  case DKIMCheckSignatureJob::AuthenticationMethod::Dkimatps: {
256  const QString str = i18n("%1: None", MessageViewer::DKIMUtil::convertAuthenticationMethodEnumToString(result.method));
257  if (!tooltipList.contains(str)) {
258  tooltipList.append(str);
259  }
260  break;
261  }
262  }
263  break;
264  case DKIMCheckSignatureJob::DKIMStatus::Valid:
265  switch (result.method) {
266  case DKIMCheckSignatureJob::AuthenticationMethod::Unknown: {
267  break;
268  }
269  case DKIMCheckSignatureJob::AuthenticationMethod::Dkim: {
270  const QString str =
271  i18n("%1: Valid (Signed by %2)", MessageViewer::DKIMUtil::convertAuthenticationMethodEnumToString(result.method), result.sdid);
272  if (!tooltipList.contains(str)) {
273  tooltipList.append(str);
274  }
275  break;
276  }
277  case DKIMCheckSignatureJob::AuthenticationMethod::Spf: {
278  const QString str = i18nc("method name: info about it from parsing",
279  "%1: %2",
280  MessageViewer::DKIMUtil::convertAuthenticationMethodEnumToString(result.method),
281  result.infoResult);
282  if (!tooltipList.contains(str)) {
283  tooltipList.append(str);
284  }
285 
286  break;
287  }
288  case DKIMCheckSignatureJob::AuthenticationMethod::Auth:
289  case DKIMCheckSignatureJob::AuthenticationMethod::Dkimatps:
290  case DKIMCheckSignatureJob::AuthenticationMethod::Dmarc: {
291  const QString str = i18n("%1: Valid", MessageViewer::DKIMUtil::convertAuthenticationMethodEnumToString(result.method));
292  if (!tooltipList.contains(str)) {
293  tooltipList.append(str);
294  }
295 
296  break;
297  }
298  }
299  break;
300  }
301  }
302  if (!tooltipList.isEmpty()) {
303  tooltip += (tooltip.isEmpty() ? QChar() : QLatin1Char('\n')) + tooltipList.join(QLatin1Char('\n'));
304  }
305  if (mResult.listSignatureAuthenticationResult.isEmpty()) {
306  tooltip += (tooltip.isEmpty() ? QChar() : QLatin1Char('\n')) + i18n("Not Signed");
307  }
308  }
309  qCDebug(MESSAGEVIEWER_DKIMCHECKER_LOG) << "mResult.authentication " << mResult.listSignatureAuthenticationResult;
310 
311  mLabel->setToolTip(tooltip);
312 }
313 
314 bool DKIMWidgetInfo::event(QEvent *e)
315 {
316 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
318  updatePalette();
319  }
320 #endif
321  return QWidget::event(e);
322 }
void append(const T &value)
void paletteChanged(const QPalette &palette)
ApplicationPaletteChange
void setText(const QString &)
bool contains(const QString &str, Qt::CaseSensitivity cs) const const
virtual bool event(QEvent *event) override
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QString i18n(const char *text, const TYPE &arg...)
bool isEmpty() const const
bool isEmpty() const const
void setColor(QPalette::ColorGroup group, QPalette::ColorRole role, const QColor &color)
void setToolTip(const QString &)
QEvent::Type type() const const
void clear()
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QPalette::ColorRole backgroundRole() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Wed Mar 22 2023 04:07:14 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.