/**
* This file is part of GPGFrontend.
*
* GPGFrontend is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Foobar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Foobar. If not, see .
*
* The initial version of the source code is inherited from gpg4usb-team.
* Their source code version also complies with GNU General Public License.
*
* The source code version of this software was modified and released
* by Saturneric starting on May 12, 2021.
*
*/
#include "ui/VerifyNotification.h"
VerifyNotification::VerifyNotification(QWidget *parent, GpgME::GpgContext *ctx, KeyList *keyList, QTextEdit *edit) :
QWidget(parent) {
mCtx = ctx;
mKeyList = keyList;
mTextpage = edit;
verifyLabel = new QLabel(this);
connect(mCtx, SIGNAL(keyDBChanged()), this, SLOT(slotRefresh()));
connect(edit, SIGNAL(textChanged()), this, SLOT(close()));
importFromKeyserverAct = new QAction(tr("Import missing key from Keyserver"), this);
connect(importFromKeyserverAct, SIGNAL(triggered()), this, SLOT(slotImportFromKeyserver()));
showVerifyDetailsAct = new QAction(tr("Show detailed verify information"), this);
connect(showVerifyDetailsAct, SIGNAL(triggered()), this, SLOT(slotShowVerifyDetails()));
detailMenu = new QMenu(this);
detailMenu->addAction(showVerifyDetailsAct);
detailMenu->addAction(importFromKeyserverAct);
importFromKeyserverAct->setVisible(false);
keysNotInList = new QStringList();
detailsButton = new QPushButton(tr("Details"), this);
detailsButton->setMenu(detailMenu);
auto *notificationWidgetLayout = new QHBoxLayout(this);
notificationWidgetLayout->setContentsMargins(10, 0, 0, 0);
notificationWidgetLayout->addWidget(verifyLabel, 2);
notificationWidgetLayout->addWidget(detailsButton);
this->setLayout(notificationWidgetLayout);
}
void VerifyNotification::slotImportFromKeyserver() {
auto *importDialog = new KeyServerImportDialog(mCtx, mKeyList, this);
importDialog->slotImport(*keysNotInList);
}
void VerifyNotification::setVerifyLabel(const QString &text, verify_label_status verifyLabelStatus) {
QString color;
verifyLabel->setText(text);
switch (verifyLabelStatus) {
case VERIFY_ERROR_OK:
color = "#ccffcc";
break;
case VERIFY_ERROR_WARN:
color = "#ececba";
break;
case VERIFY_ERROR_CRITICAL:
color = "#ff8080";
break;
default:
break;
}
verifyLabel->setAutoFillBackground(true);
QPalette status = verifyLabel->palette();
status.setColor(QPalette::Background, color);
verifyLabel->setPalette(status);
}
void VerifyNotification::showImportAction(bool visible) {
importFromKeyserverAct->setVisible(visible);
}
void VerifyNotification::slotShowVerifyDetails() {
QByteArray text = mTextpage->toPlainText().toUtf8();
GpgME::GpgContext::preventNoDataErr(&text);
new VerifyDetailsDialog(this, mCtx, mKeyList, &text);
}
bool VerifyNotification::slotRefresh() {
verify_label_status verifyStatus = VERIFY_ERROR_OK;
QByteArray text = mTextpage->toPlainText().toUtf8();
GpgME::GpgContext::preventNoDataErr(&text);
int textIsSigned = GpgME::GpgContext::textIsSigned(text);
gpgme_signature_t sign = mCtx->verify(&text);
if (sign == nullptr) {
return false;
}
QString verifyLabelText;
bool unknownKeyFound = false;
while (sign) {
switch (gpg_err_code(sign->status)) {
case GPG_ERR_NO_PUBKEY: {
verifyStatus = VERIFY_ERROR_WARN;
verifyLabelText.append(tr("Key not present with id 0x") + QString(sign->fpr));
this->keysNotInList->append(sign->fpr);
unknownKeyFound = true;
break;
}
case GPG_ERR_NO_ERROR: {
GpgKey key = mCtx->getKeyByFpr(sign->fpr);
verifyLabelText.append(key.name);
if (!key.email.isEmpty()) {
verifyLabelText.append("<" + key.email + ">");
}
break;
}
case GPG_ERR_BAD_SIGNATURE: {
textIsSigned = 3;
verifyStatus = VERIFY_ERROR_CRITICAL;
GpgKey key = mCtx->getKeyById(sign->fpr);
if(!key.good) break;
verifyLabelText.append(key.name);
if (!key.email.isEmpty()) {
verifyLabelText.append("<" + key.email + ">");
}
break;
}
default: {
//textIsSigned = 3;
verifyStatus = VERIFY_ERROR_WARN;
//GpgKey key = mKeyList->getKeyByFpr(sign->fpr);
verifyLabelText.append(tr("Error for key with fingerprint ") +
GpgME::GpgContext::beautifyFingerprint(QString(sign->fpr)));
break;
}
}
verifyLabelText.append("\n");
sign = sign->next;
}
switch (textIsSigned) {
case 3:
verifyLabelText.prepend(tr("Error validating signature by: "));
break;
case 2:
verifyLabelText.prepend(tr("Text was completely signed by: "));
break;
case 1:
verifyLabelText.prepend(tr("Text was partially signed by: "));
break;
}
// If an unknown key is found, enable the importfromkeyserveraction
this->showImportAction(unknownKeyFound);
// Remove the last linebreak
verifyLabelText.remove(verifyLabelText.length() - 1, 1);
this->setVerifyLabel(verifyLabelText, verifyStatus);
return true;
}