/**
* 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/keypair_details/KeyPairDetailTab.h"
KeyPairDetailTab::KeyPairDetailTab(GpgME::GpgContext *ctx, const GpgKey &mKey, QWidget *parent) : mKey(mKey), QWidget(parent) {
mCtx = ctx;
keyid = new QString(mKey.id);
ownerBox = new QGroupBox(tr("Owner"));
keyBox = new QGroupBox(tr("Master Key"));
fingerprintBox = new QGroupBox(tr("Fingerprint"));
additionalUidBox = new QGroupBox(tr("Additional UIDs"));
nameVarLabel = new QLabel();
nameVarLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
emailVarLabel = new QLabel();
emailVarLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
commentVarLabel = new QLabel();
commentVarLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
keyidVarLabel = new QLabel();
keyidVarLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
usageVarLabel = new QLabel();
actualUsageVarLabel = new QLabel();
keySizeVarLabel = new QLabel();
expireVarLabel = new QLabel();
createdVarLabel = new QLabel();
algorithmVarLabel = new QLabel();
// Show the situation that master key not exists.
masterKeyExistVarLabel = new QLabel(mKey.has_master_key ? "Exists" : "Not Exists");
if(!mKey.has_master_key){
auto paletteExpired = masterKeyExistVarLabel->palette();
paletteExpired.setColor(masterKeyExistVarLabel->foregroundRole(), Qt::red);
masterKeyExistVarLabel->setPalette(paletteExpired);
} else {
auto paletteValid = masterKeyExistVarLabel->palette();
paletteValid.setColor(masterKeyExistVarLabel->foregroundRole(), Qt::darkGreen);
masterKeyExistVarLabel->setPalette(paletteValid);
}
if(mKey.expired){
auto paletteExpired = expireVarLabel->palette();
paletteExpired.setColor(expireVarLabel->foregroundRole(), Qt::red);
expireVarLabel->setPalette(paletteExpired);
} else {
auto paletteValid = expireVarLabel->palette();
paletteValid.setColor(expireVarLabel->foregroundRole(), Qt::darkGreen);
expireVarLabel->setPalette(paletteValid);
}
auto *mvbox = new QVBoxLayout();
auto *vboxKD = new QGridLayout();
auto *vboxOD = new QGridLayout();
vboxOD->addWidget(new QLabel(tr("Name:")), 0, 0);
vboxOD->addWidget(new QLabel(tr("Email Address:")), 1, 0);
vboxOD->addWidget(new QLabel(tr("Comment:")), 2, 0);
vboxOD->addWidget(nameVarLabel, 0, 1);
vboxOD->addWidget(emailVarLabel, 1, 1);
vboxOD->addWidget(commentVarLabel, 2, 1);
vboxKD->addWidget(new QLabel(tr("Key ID: ")), 0, 0);
vboxKD->addWidget(new QLabel(tr("Algorithm: ")), 1, 0);
vboxKD->addWidget(new QLabel(tr("Key Size:")), 2, 0);
vboxKD->addWidget(new QLabel(tr("Nominal Usage: ")), 3, 0);
vboxKD->addWidget(new QLabel(tr("Actual Usage: ")), 4, 0);
vboxKD->addWidget(new QLabel(tr("Expires on: ")), 5, 0);
vboxKD->addWidget(new QLabel(tr("Last Update: ")), 6, 0);
vboxKD->addWidget(new QLabel(tr("Secret Key Existence: ")), 7, 0);
vboxKD->addWidget(keySizeVarLabel, 2, 1);
vboxKD->addWidget(expireVarLabel, 5, 1);
vboxKD->addWidget(algorithmVarLabel, 1, 1);
vboxKD->addWidget(createdVarLabel, 6, 1);
vboxKD->addWidget(keyidVarLabel, 0, 1);
vboxKD->addWidget(usageVarLabel, 3, 1);
vboxKD->addWidget(actualUsageVarLabel, 4, 1);
vboxKD->addWidget(masterKeyExistVarLabel, 7, 1);
ownerBox->setLayout(vboxOD);
mvbox->addWidget(ownerBox);
keyBox->setLayout(vboxKD);
mvbox->addWidget(keyBox);
fingerPrintVarLabel = new QLabel(beautifyFingerprint(mKey.fpr));
fingerPrintVarLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
fingerPrintVarLabel->setStyleSheet("margin-left: 0; margin-right: 5;");
auto *hboxFP = new QHBoxLayout();
hboxFP->addWidget(fingerPrintVarLabel);
auto *copyFingerprintButton = new QPushButton(tr("Copy"));
copyFingerprintButton->setFlat(true);
copyFingerprintButton->setToolTip(tr("copy fingerprint to clipboard"));
connect(copyFingerprintButton, SIGNAL(clicked()), this, SLOT(slotCopyFingerprint()));
hboxFP->addWidget(copyFingerprintButton);
fingerprintBox->setLayout(hboxFP);
mvbox->addWidget(fingerprintBox);
mvbox->addStretch();
if (mKey.is_private_key) {
auto *privKeyBox = new QGroupBox(tr("Operations"));
auto *vboxPK = new QVBoxLayout();
auto *exportButton = new QPushButton(tr("Export Private Key (Include Subkeys)"));
vboxPK->addWidget(exportButton);
connect(exportButton, SIGNAL(clicked()), this, SLOT(slotExportPrivateKey()));
if(mKey.has_master_key) {
auto *editExpiresButton = new QPushButton(tr("Modify Expiration Datetime (Master Key)"));
vboxPK->addWidget(editExpiresButton);
connect(editExpiresButton, SIGNAL(clicked()), this, SLOT(slotModifyEditDatetime()));
auto *keyServerOperaButton = new QPushButton(tr("Key Server Operation (Pubkey)"));
keyServerOperaButton->setStyleSheet("text-align:center;");
vboxPK->addWidget(keyServerOperaButton);
connect(keyServerOperaButton, SIGNAL(clicked()), this, SLOT(slotModifyEditDatetime()));
// Set Menu
createKeyServerOperaMenu();
keyServerOperaButton->setMenu(keyServerOperaMenu);
}
privKeyBox->setLayout(vboxPK);
mvbox->addWidget(privKeyBox);
}
if ((mKey.expired) || (mKey.revoked)) {
auto *expBox = new QHBoxLayout();
QPixmap pixmap(":warning.png");
auto *expLabel = new QLabel();
auto *iconLabel = new QLabel();
if (mKey.expired) {
expLabel->setText(tr("Warning: The Master Key has expired."));
}
if (mKey.revoked) {
expLabel->setText(tr("Warning: The Master Key has been revoked"));
}
iconLabel->setPixmap(pixmap.scaled(24,24,Qt::KeepAspectRatio));
QFont font = expLabel->font();
font.setBold(true);
expLabel->setFont(font);
expLabel->setAlignment(Qt::AlignCenter);
expBox->addWidget(iconLabel);
expBox->addWidget(expLabel);
mvbox->addLayout(expBox);
}
connect(mCtx, SIGNAL(signalKeyInfoChanged()), this, SLOT(slotRefreshKeyInfo()));
slotRefreshKeyInfo();
setAttribute(Qt::WA_DeleteOnClose, true);
setLayout(mvbox);
}
void KeyPairDetailTab::slotExportPrivateKey() {
// Show a information box with explanation about private key
int ret = QMessageBox::information(this, tr("Exporting private Key"),
tr("You are about to export your PRIVATE KEY!
\n"
"This is NOT your Public Key, so DON'T give it away.
"
"Do you REALLY want to export your PRIVATE KEY?"),
QMessageBox::Cancel | QMessageBox::Ok);
// export key, if ok was clicked
if (ret == QMessageBox::Ok) {
auto *keyArray = new QByteArray();
if(!mCtx->exportSecretKey(mKey, keyArray)) {
QMessageBox::critical(this, "Error", "An error occurred during the export operation.");
return;
}
auto &key = mCtx->getKeyById(*keyid);
QString fileString = key.name + " " +key.email + "(" +
key.id + ")_secret.asc";
QString fileName = QFileDialog::getSaveFileName(this, tr("Export Key To File"), fileString,
tr("Key Files") + " (*.asc *.txt);;All Files (*)");
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QMessageBox::critical(nullptr, tr("Export Error"), tr("Couldn't open %1 for writing").arg(fileName));
return;
}
QTextStream stream(&file);
stream << *keyArray;
file.close();
delete keyArray;
}
}
QString KeyPairDetailTab::beautifyFingerprint(QString fingerprint) {
uint len = fingerprint.length();
if ((len > 0) && (len % 4 == 0))
for (uint n = 0; 4 * (n + 1) < len; ++n)
fingerprint.insert(static_cast(5u * n + 4u), ' ');
return fingerprint;
}
void KeyPairDetailTab::slotCopyFingerprint() {
QString fpr = fingerPrintVarLabel->text().trimmed().replace(" ", "");
QClipboard *cb = QApplication::clipboard();
cb->setText(fpr);
}
void KeyPairDetailTab::slotModifyEditDatetime() {
auto dialog = new KeySetExpireDateDialog(mCtx, mKey, nullptr, this);
dialog->show();
}
void KeyPairDetailTab::slotRefreshKeyInfo() {
nameVarLabel->setText(mKey.name);
emailVarLabel->setText(mKey.email);
commentVarLabel->setText(mKey.comment);
keyidVarLabel->setText(mKey.id);
QString usage;
QTextStream usage_steam(&usage);
if(mKey.can_certify)
usage_steam << "Cert ";
if(mKey.can_encrypt)
usage_steam << "Encr ";
if(mKey.can_sign)
usage_steam << "Sign ";
if(mKey.can_authenticate)
usage_steam << "Auth ";
usageVarLabel->setText(usage);
QString actualUsage;
QTextStream actual_usage_steam(&actualUsage);
if(GpgME::GpgContext::checkIfKeyCanCert(mKey))
actual_usage_steam << "Cert ";
if(GpgME::GpgContext::checkIfKeyCanEncr(mKey))
actual_usage_steam << "Encr ";
if(GpgME::GpgContext::checkIfKeyCanSign(mKey))
actual_usage_steam << "Sign ";
if(GpgME::GpgContext::checkIfKeyCanAuth(mKey))
actual_usage_steam << "Auth ";
actualUsageVarLabel->setText(actualUsage);
QString keySizeVal, keyExpireVal, keyCreateTimeVal, keyAlgoVal;
keySizeVal = QString::number(mKey.length);
if (mKey.expires.toTime_t() == 0) {
keyExpireVal = tr("Never Expire");
} else {
keyExpireVal = mKey.expires.toString();
}
keyAlgoVal = mKey.pubkey_algo;
keyCreateTimeVal = mKey.create_time.toString();
keySizeVarLabel->setText(keySizeVal);
expireVarLabel->setText(keyExpireVal);
createdVarLabel->setText(keyCreateTimeVal);
algorithmVarLabel->setText(keyAlgoVal);
fingerPrintVarLabel->setText(beautifyFingerprint(mKey.fpr));
}
void KeyPairDetailTab::createKeyServerOperaMenu() {
keyServerOperaMenu = new QMenu(this);
auto *uploadKeyPair = new QAction(tr("Upload Key Pair"), this);
connect(uploadKeyPair, SIGNAL(triggered()), this, SLOT(slotUploadKeyToServer()));
auto *updateKeyPair = new QAction(tr("Update Key Pair"), this);
connect(updateKeyPair, SIGNAL(triggered()), this, SLOT(slotUpdateKeyToServer()));
keyServerOperaMenu->addAction(uploadKeyPair);
// TODO Solve Refresh Problem
// keyServerOperaMenu->addAction(updateKeyPair);
}
void KeyPairDetailTab::slotUploadKeyToServer() {
QVector keys;
keys.append(mKey);
auto *dialog = new KeyUploadDialog(mCtx, keys);
}
void KeyPairDetailTab::slotUpdateKeyToServer() {
QVector keys;
keys.append(mKey);
auto *dialog = new KeyServerImportDialog(mCtx, this);
dialog->show();
dialog->slotImportKey(keys);
}