diff options
23 files changed, 310 insertions, 130 deletions
diff --git a/gpg4usb.qrc b/gpg4usb.qrc index 792d6324..912d47c1 100644 --- a/gpg4usb.qrc +++ b/gpg4usb.qrc @@ -17,6 +17,7 @@ <file alias="decrypted.png">release/icons/decrypted.png</file> <file alias="edit.png">release/icons/edit.png</file> <file alias="encrypted.png">release/icons/encrypted.png</file> + <file alias="encrypted_signed.png">release/icons/encrypted_signed.png</file> <file alias="exit.png">release/icons/exit.png</file> <file alias="export_key_to_file.png">release/icons/export_key_to_file.png</file> <file alias="fileencryption.png">release/icons/fileencrytion.png</file> diff --git a/include/MainWindow.h b/include/MainWindow.h index 19eddf13..c8efd63c 100644 --- a/include/MainWindow.h +++ b/include/MainWindow.h @@ -71,6 +71,12 @@ private slots: void slotEncrypt(); /** + * @details encrypt and sign the text of currently active textedit-page + * with the currently checked keys + */ + void slotEncryptSign(); + + /** * @details Show a passphrase dialog and decrypt the text of currently active tab. */ void slotDecrypt(); @@ -306,6 +312,7 @@ private: QAction *closeTabAct; /** Action to print */ QAction *quitAct; /** Action to quit application */ QAction *encryptAct; /** Action to encrypt text */ + QAction *encryptSignAct; /** Action to encrypt text */ QAction *decryptAct; /** Action to decrypt text */ QAction *signAct; /** Action to sign text */ QAction *verifyAct; /** Action to verify text */ diff --git a/include/gpg/GpgContext.h b/include/gpg/GpgContext.h index 3d3f2ffa..41fdca55 100644 --- a/include/gpg/GpgContext.h +++ b/include/gpg/GpgContext.h @@ -86,6 +86,9 @@ namespace GpgME { bool encrypt(QStringList *uidList, const QByteArray &inBuffer, QByteArray *outBuffer); + bool encryptSign(QVector<GpgKey> &keys, const QByteArray &inBuffer, + QByteArray *outBuffer); + bool decrypt(const QByteArray &inBuffer, QByteArray *outBuffer); void clearPasswordCache(); @@ -102,7 +105,7 @@ namespace GpgME { gpgme_signature_t verify(QByteArray *inBuffer, QByteArray *sigBuffer = nullptr); - bool sign(QStringList *uidList, const QByteArray &inBuffer, QByteArray *outBuffer, bool detached = false); + bool sign(QVector<GpgKey> keys, const QByteArray &inBuffer, QByteArray *outBuffer, bool detached = false); bool addUID(const GpgKey &key, const UID &uid); @@ -112,6 +115,11 @@ namespace GpgME { bool setExpire(const GpgKey &key, const GpgSubKey *subkey, QDateTime *expires); + static bool checkIfKeyCanSign(const GpgKey &key); + static bool checkIfKeyCanCert(const GpgKey &key); + static bool checkIfKeyCanAuth(const GpgKey &key); + static bool checkIfKeyCanEncr(const GpgKey &key); + /** * @details If text contains PGP-message, put a linebreak before the message, * so that gpgme can decrypt correctly diff --git a/include/ui/VerifyDetailsDialog.h b/include/ui/VerifyDetailsDialog.h index 396e9ad8..74e059a7 100644 --- a/include/ui/VerifyDetailsDialog.h +++ b/include/ui/VerifyDetailsDialog.h @@ -26,7 +26,7 @@ #define __VERIFYDETAILSDIALOG_H__ #include "ui/EditorPage.h" -#include "VerifyKeyDetailBox.h" +#include "ui/widgets/VerifyKeyDetailBox.h" class VerifyDetailsDialog : public QDialog { Q_OBJECT diff --git a/include/ui/VerifyNotification.h b/include/ui/VerifyNotification.h index bf700c1a..a42a6b22 100644 --- a/include/ui/VerifyNotification.h +++ b/include/ui/VerifyNotification.h @@ -69,7 +69,7 @@ public: * @param text The text to be set. * @param verifyLabelStatus The status of label to set the specified color. */ - void setVerifyLabel(const QString& text, verify_label_status verifyLabelStatus); + void setInfoBoard(const QString& text, verify_label_status verifyLabelStatus); /** * @details Show the import from keyserver-action in detailsmenu. @@ -104,6 +104,7 @@ private: QAction *showVerifyDetailsAct; /** Action for showing verify detail dialog */ QPushButton *detailsButton; /** Button shown in verifynotification */ QLabel *verifyLabel; /** Label holding the text shown in verifyNotification */ + QTextEdit *infoBoard; GpgME::GpgContext *mCtx; /** GpgME Context */ KeyList *mKeyList; /** Table holding the keys */ QTextEdit *mTextpage; /** Textedit associated to the notification */ diff --git a/include/ui/keypair_details/KeyPairDetailTab.h b/include/ui/keypair_details/KeyPairDetailTab.h index d081ac46..ad0b13f6 100644 --- a/include/ui/keypair_details/KeyPairDetailTab.h +++ b/include/ui/keypair_details/KeyPairDetailTab.h @@ -77,6 +77,7 @@ private: QLabel *keyidVarLabel; /** Label containng the keys keyid */ QLabel *fingerPrintVarLabel; /** Label containng the keys fingerprint */ QLabel *usageVarLabel; + QLabel *actualUsageVarLabel; QLabel *masterKeyExistVarLabel; public: diff --git a/include/ui/widgets/KeyList.h b/include/ui/widgets/KeyList.h index 06e80910..295ba224 100644 --- a/include/ui/widgets/KeyList.h +++ b/include/ui/widgets/KeyList.h @@ -79,6 +79,8 @@ public: QStringList *getPrivateChecked(); + void getPrivateCheckedKeys(QVector<GpgKey> &keys); + QStringList *getAllPrivateKeys(); void setChecked(QStringList *keyIds); diff --git a/include/ui/VerifyKeyDetailBox.h b/include/ui/widgets/VerifyKeyDetailBox.h index 66f01a8e..66f01a8e 100644 --- a/include/ui/VerifyKeyDetailBox.h +++ b/include/ui/widgets/VerifyKeyDetailBox.h diff --git a/release/icons/decrypted.png b/release/icons/decrypted.png Binary files differindex 2b49969a..9fe6970a 100644 --- a/release/icons/decrypted.png +++ b/release/icons/decrypted.png diff --git a/release/icons/encrypted.png b/release/icons/encrypted.png Binary files differindex 4ae41eee..45bbf696 100644 --- a/release/icons/encrypted.png +++ b/release/icons/encrypted.png diff --git a/release/icons/encrypted_signed.png b/release/icons/encrypted_signed.png Binary files differnew file mode 100644 index 00000000..ffb57196 --- /dev/null +++ b/release/icons/encrypted_signed.png diff --git a/release/icons/fileencrytion.png b/release/icons/fileencrytion.png Binary files differindex 36adbc8e..b4546e2a 100644 --- a/release/icons/fileencrytion.png +++ b/release/icons/fileencrytion.png diff --git a/release/icons/signature.png b/release/icons/signature.png Binary files differindex 015e5cc3..3aea526b 100755..100644 --- a/release/icons/signature.png +++ b/release/icons/signature.png diff --git a/release/icons/verify.png b/release/icons/verify.png Binary files differindex c6075d82..bfaa5536 100644 --- a/release/icons/verify.png +++ b/release/icons/verify.png diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 7cb08835..cd65c18f 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -284,6 +284,12 @@ void MainWindow::createActions() { encryptAct->setToolTip(tr("Encrypt Message")); connect(encryptAct, SIGNAL(triggered()), this, SLOT(slotEncrypt())); + encryptSignAct = new QAction(tr("&Encrypt Sign"), this); + encryptSignAct->setIcon(QIcon(":encrypted_signed.png")); + encryptSignAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_E + Qt::Key_S)); + encryptSignAct->setToolTip(tr("Encrypt And Sign Message")); + connect(encryptSignAct, SIGNAL(triggered()), this, SLOT(slotEncryptSign())); + decryptAct = new QAction(tr("&Decrypt"), this); decryptAct->setIcon(QIcon(":decrypted.png")); decryptAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_D)); @@ -474,6 +480,7 @@ void MainWindow::createMenus() { cryptMenu = menuBar()->addMenu(tr("&Crypt")); cryptMenu->addAction(encryptAct); + cryptMenu->addAction(encryptSignAct); cryptMenu->addAction(decryptAct); cryptMenu->addSeparator(); cryptMenu->addAction(signAct); @@ -525,6 +532,7 @@ void MainWindow::createToolBars() { cryptToolBar = addToolBar(tr("Crypt")); cryptToolBar->setObjectName("cryptToolBar"); cryptToolBar->addAction(encryptAct); + cryptToolBar->addAction(encryptSignAct); cryptToolBar->addAction(decryptAct); cryptToolBar->addAction(signAct); cryptToolBar->addAction(verifyAct); @@ -771,9 +779,23 @@ void MainWindow::slotSign() { QStringList *uidList = mKeyList->getPrivateChecked(); + QVector<GpgKey> keys; + + mKeyList->getPrivateCheckedKeys(keys); + + for(const auto &key : keys) { + if(!GpgME::GpgContext::checkIfKeyCanSign(key)) { + QMessageBox::information(nullptr, + tr("Invalid Operation"), + tr("The selected key contains a key that does not actually have a signature function.<br/>") + + tr("<br/>For example the Following Key: <br/>") + key.uids.first().uid); + return; + } + } + auto *tmp = new QByteArray(); - if (mCtx->sign(uidList, edit->curTextPage()->toPlainText().toUtf8(), tmp)) { + if (mCtx->sign(keys, edit->curTextPage()->toPlainText().toUtf8(), tmp)) { edit->slotFillTextEditWithText(QString::fromUtf8(*tmp)); } } @@ -844,6 +866,7 @@ void MainWindow::slotVerify() { if (vn->slotRefresh()) { edit->slotCurPage()->showNotificationWidget(vn, "verifyNotification"); } else { + QMessageBox::warning(nullptr, "Signature NOT Found", "The signature was not found in the target text"); vn->close(); } } @@ -1020,3 +1043,29 @@ void MainWindow::slotSetRestartNeeded(bool needed) { bool MainWindow::getRestartNeeded() const { return this->restartNeeded; } + +void MainWindow::slotEncryptSign() { + + if (edit->tabCount() == 0 || edit->slotCurPage() == nullptr) { + return; + } + + QVector<GpgKey> keys; + mKeyList->getCheckedKeys(keys); + + for(const auto &key : keys) { + if(!GpgME::GpgContext::checkIfKeyCanSign(key) || !GpgME::GpgContext::checkIfKeyCanEncr(key)) { + QMessageBox::information(nullptr, + tr("Invalid Operation"), + tr("The selected key cannot be used for signing and encryption at the same time.<br/>") + + tr("<br/>For example the Following Key: <br/>") + key.uids.first().uid); + return; + } + } + + auto *tmp = new QByteArray(); + if (mCtx->encryptSign(keys, edit->curTextPage()->toPlainText().toUtf8(), tmp)) { + auto *tmp2 = new QString(*tmp); + edit->slotFillTextEditWithText(*tmp2); + } +} diff --git a/src/gpg/GpgContext.cpp b/src/gpg/GpgContext.cpp index 9d1bc083..492aef83 100644 --- a/src/gpg/GpgContext.cpp +++ b/src/gpg/GpgContext.cpp @@ -710,35 +710,21 @@ namespace GpgME { verify_result = gpgme_op_verify_result (mCtx); */ //} - bool GpgContext::sign(QStringList *uidList, const QByteArray &inBuffer, QByteArray *outBuffer, bool detached) { + bool GpgContext::sign(QVector<GpgKey> keys, const QByteArray &inBuffer, QByteArray *outBuffer, bool detached) { gpgme_error_t gpgmeError; gpgme_data_t dataIn, dataOut; gpgme_sign_result_t result; gpgme_sig_mode_t mode; - if (uidList->isEmpty()) { + if (keys.isEmpty()) { QMessageBox::critical(nullptr, tr("Key Selection"), tr("No Private Key Selected")); return false; } // at start or end? - gpgme_signers_clear(mCtx); - - //gpgme_encrypt_result_t e_result; - gpgme_key_t signers[uidList->count() + 1]; - - // TODO: do we really need array? adding one key dataIn loop should be ok - for (int i = 0; i < uidList->count(); i++) { - // the last 0 is for public keys, 1 would return private keys - gpgme_op_keylist_start(mCtx, uidList->at(i).toUtf8().constData(), 0); - gpgme_op_keylist_next(mCtx, &signers[i]); - gpgme_op_keylist_end(mCtx); - - gpgmeError = gpgme_signers_add(mCtx, signers[i]); - checkErr(gpgmeError); - } + setSigners(keys); gpgmeError = gpgme_data_new_from_mem(&dataIn, inBuffer.data(), inBuffer.size(), 1); checkErr(gpgmeError); @@ -1079,6 +1065,79 @@ namespace GpgME { } } + bool GpgContext::checkIfKeyCanSign(const GpgKey &key) { + if(std::any_of(key.subKeys.begin(), key.subKeys.end(), [] (const GpgSubKey &subkey) -> bool { + return subkey.secret && subkey.can_sign && !subkey.disabled && !subkey.revoked && !subkey.expired; + })) return true; + return false; + } + + bool GpgContext::checkIfKeyCanCert(const GpgKey &key) { + return key.has_master_key && !key.expired && !key.revoked && !key.disabled; + } + + bool GpgContext::checkIfKeyCanAuth(const GpgKey &key) { + if(std::any_of(key.subKeys.begin(), key.subKeys.end(), [] (const GpgSubKey &subkey) -> bool { + return subkey.secret && subkey.can_authenticate && !subkey.disabled && !subkey.revoked && !subkey.expired; + })) return true; + return false; + } + + bool GpgContext::checkIfKeyCanEncr(const GpgKey &key) { + if(std::any_of(key.subKeys.begin(), key.subKeys.end(), [] (const GpgSubKey &subkey) -> bool { + return subkey.can_encrypt && !subkey.disabled && !subkey.revoked && !subkey.expired; + })) return true; + return false; + } + + bool GpgContext::encryptSign(QVector<GpgKey> &keys, const QByteArray &inBuffer, QByteArray *outBuffer) { + gpgme_data_t dataIn = nullptr, dataOut = nullptr; + outBuffer->resize(0); + + if (keys.count() == 0) { + QMessageBox::critical(nullptr, tr("No Key Selected"), tr("No Key Selected")); + return false; + } + + setSigners(keys); + + //gpgme_encrypt_result_t e_result; + gpgme_key_t recipients[keys.count() + 1]; + + /* set key for user */ + int index = 0; + for(const auto &key : keys) { + recipients[index++] = key.key_refer; + } + //Last entry dataIn array has to be nullptr + recipients[keys.count()] = nullptr; + + //If the last parameter isnt 0, a private copy of data is made + if (mCtx) { + err = gpgme_data_new_from_mem(&dataIn, inBuffer.data(), inBuffer.size(), 1); + checkErr(err); + if (!err) { + err = gpgme_data_new(&dataOut); + checkErr(err); + if (!err) { + err = gpgme_op_encrypt_sign(mCtx, recipients, GPGME_ENCRYPT_ALWAYS_TRUST, dataIn, dataOut); + checkErr(err); + if (!err) { + err = readToBuffer(dataOut, outBuffer); + checkErr(err); + } + } + } + } + if (dataIn) { + gpgme_data_release(dataIn); + } + if (dataOut) { + gpgme_data_release(dataOut); + } + return (err == GPG_ERR_NO_ERROR); + } + } diff --git a/src/ui/FileEncryptionDialog.cpp b/src/ui/FileEncryptionDialog.cpp index 97e0d357..d4c0d6d1 100755 --- a/src/ui/FileEncryptionDialog.cpp +++ b/src/ui/FileEncryptionDialog.cpp @@ -26,21 +26,16 @@ FileEncryptionDialog::FileEncryptionDialog(GpgME::GpgContext *ctx, QStringList keyList, DialogAction action, QWidget *parent) - : QDialog(parent) { - mAction = action; - mCtx = ctx; + : QDialog(parent), mAction(action), mCtx(ctx){ + if (mAction == Decrypt) { setWindowTitle(tr("Decrypt File")); - resize(500, 200); } else if (mAction == Encrypt) { setWindowTitle(tr("Encrypt File")); - resize(500, 400); } else if (mAction == Sign) { setWindowTitle(tr("Sign File")); - resize(500, 400); } else if (mAction == Verify) { setWindowTitle(tr("Verify File")); - resize(500, 200); } setModal(true); @@ -49,19 +44,19 @@ FileEncryptionDialog::FileEncryptionDialog(GpgME::GpgContext *ctx, QStringList k connect(buttonBox, SIGNAL(accepted()), this, SLOT(slotExecuteAction())); connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); - auto *groupBox1 = new QGroupBox(tr("File")); + auto *groupBox1 = new QGroupBox(tr("Input Parameters")); /* Setup input & Outputfileselection*/ inputFileEdit = new QLineEdit(); - auto *fb1 = new QPushButton("..."); + auto *fb1 = new QPushButton("Select"); connect(fb1, SIGNAL(clicked()), this, SLOT(slotSelectInputFile())); - auto *fl1 = new QLabel(tr("Input")); + auto *fl1 = new QLabel(tr("Target File")); fl1->setBuddy(inputFileEdit); outputFileEdit = new QLineEdit(); - auto *fb2 = new QPushButton("..."); + auto *fb2 = new QPushButton("Select"); connect(fb2, SIGNAL(clicked()), this, SLOT(slotSelectOutputFile())); - auto *fl2 = new QLabel(tr("Output")); + auto *fl2 = new QLabel(tr("Output File")); fl2->setBuddy(outputFileEdit); auto *gLayout = new QGridLayout(); @@ -75,9 +70,9 @@ FileEncryptionDialog::FileEncryptionDialog(GpgME::GpgContext *ctx, QStringList k gLayout->addWidget(outputFileEdit, 1, 1); gLayout->addWidget(fb2, 1, 2); } else { - auto *sfb1 = new QPushButton("..."); + auto *sfb1 = new QPushButton("Select"); connect(sfb1, SIGNAL(clicked()), this, SLOT(slotSelectSignFile())); - auto *sfl1 = new QLabel(tr("Signature")); + auto *sfl1 = new QLabel(tr("Signature File(.sig) Path")); sfl1->setBuddy(signFileEdit); gLayout->addWidget(sfl1, 1, 0); @@ -87,7 +82,30 @@ FileEncryptionDialog::FileEncryptionDialog(GpgME::GpgContext *ctx, QStringList k groupBox1->setLayout(gLayout); /*Setup KeyList*/ - mKeyList = new KeyList(mCtx, KeyListRow::ONLY_SECRET_KEY, KeyListColumn::NAME | KeyListColumn::EmailAddress); + mKeyList = new KeyList(mCtx, KeyListRow::ONLY_SECRET_KEY, + KeyListColumn::NAME | KeyListColumn::EmailAddress | KeyListColumn::Usage); + if(mAction == Verify) + mKeyList->setFilter([](const GpgKey &key) -> bool { + if(key.disabled || key.expired || key.revoked) return false; + else return true; + }); + + if(mAction == Encrypt) + mKeyList->setFilter([](const GpgKey &key) -> bool { + if(!GpgME::GpgContext::checkIfKeyCanEncr(key)) return false; + else return true; + }); + + if(mAction == Sign) + mKeyList->setFilter([](const GpgKey &key) -> bool { + if(!GpgME::GpgContext::checkIfKeyCanSign(key)) return false; + else return true; + }); + + if(mAction == Decrypt) + mKeyList->setDisabled(true); + + mKeyList->slotRefresh(); mKeyList->setChecked(&keyList); statusLabel = new QLabel(); @@ -101,11 +119,9 @@ FileEncryptionDialog::FileEncryptionDialog(GpgME::GpgContext *ctx, QStringList k vbox2->addStretch(0); setLayout(vbox2); - if (action == Encrypt || action == Sign) { - slotShowKeyList(); - } + this->setMinimumWidth(480); + this->show(); - exec(); } void FileEncryptionDialog::slotSelectInputFile() { @@ -192,7 +208,10 @@ void FileEncryptionDialog::slotExecuteAction() { } if (mAction == Sign) { - if (!mCtx->sign(mKeyList->getChecked(), inBuffer, outBuffer, true)) return; + QVector<GpgKey> keys; + mKeyList->getCheckedKeys(keys); + if (!mCtx->sign(keys, inBuffer, outBuffer, true)) return; + } if (mAction == Verify) { diff --git a/src/ui/KeyMgmt.cpp b/src/ui/KeyMgmt.cpp index 3b04a22f..e32a1092 100755 --- a/src/ui/KeyMgmt.cpp +++ b/src/ui/KeyMgmt.cpp @@ -62,7 +62,7 @@ KeyMgmt::KeyMgmt(GpgME::GpgContext *ctx, QWidget *parent ) : QMainWindow(parent this->resize(size); this->move(pos); } else { - this->resize(QSize(800, 400)); + this->resize(QSize(1000, 600)); } setWindowTitle(tr("KeyPairs Management")); diff --git a/src/ui/VerifyDetailsDialog.cpp b/src/ui/VerifyDetailsDialog.cpp index 65183c5f..27306280 100644 --- a/src/ui/VerifyDetailsDialog.cpp +++ b/src/ui/VerifyDetailsDialog.cpp @@ -33,7 +33,7 @@ VerifyDetailsDialog::VerifyDetailsDialog(QWidget *parent, GpgME::GpgContext *ctx mInputData = inputData; mInputSignature = inputSignature; - this->setWindowTitle(tr("Signaturedetails")); + this->setWindowTitle(tr("Signature Details")); connect(mCtx, SIGNAL(keyDBChanged()), this, SLOT(slotRefresh())); mainLayout = new QHBoxLayout(); @@ -81,20 +81,10 @@ void VerifyDetailsDialog::slotRefresh() { mVboxLayout->addWidget(new QLabel(tr("Error Validating signature"))); } else if (mInputSignature != nullptr) { mVboxLayout->addWidget(new QLabel( - tr("File was signed on <br/> %1 by:<br/>").arg(timestamp.toString(Qt::SystemLocaleLongDate)))); + tr("File was signed on %1 <br/> It Contains:<br/>").arg(timestamp.toString(Qt::SystemLocaleLongDate)))); } else { - switch (GpgME::GpgContext::textIsSigned(*mInputData)) { - case 2: { - mVboxLayout->addWidget(new QLabel(tr("Text was completely signed on <br/> %1 by:<br/>").arg( - timestamp.toString(Qt::SystemLocaleLongDate)))); - break; - } - case 1: { - mVboxLayout->addWidget(new QLabel(tr("Text was partially signed on <br/> %1 by:<br/>").arg( - timestamp.toString(Qt::SystemLocaleLongDate)))); - break; - } - } + mVboxLayout->addWidget(new QLabel(tr("Signed on %1 <br/> It Contains:<br/>").arg( + timestamp.toString(Qt::SystemLocaleLongDate)))); } // Add informationbox for every single key while (sign) { diff --git a/src/ui/VerifyNotification.cpp b/src/ui/VerifyNotification.cpp index cd8c705f..8b79f16b 100644 --- a/src/ui/VerifyNotification.cpp +++ b/src/ui/VerifyNotification.cpp @@ -25,13 +25,16 @@ #include "ui/VerifyNotification.h" VerifyNotification::VerifyNotification(QWidget *parent, GpgME::GpgContext *ctx, KeyList *keyList, QTextEdit *edit) : - QWidget(parent) { - mCtx = ctx; - mKeyList = keyList; - mTextpage = edit; + QWidget(parent), mCtx(ctx), mKeyList(keyList), mTextpage(edit) { + verifyLabel = new QLabel(this); + infoBoard = new QTextEdit(this); + infoBoard->setReadOnly(true); + infoBoard->setFixedHeight(160); + + this->setFixedHeight(170); - connect(mCtx, SIGNAL(keyDBChanged()), this, SLOT(slotRefresh())); + connect(mCtx, SIGNAL(signalKeyInfoChanged()), this, SLOT(slotRefresh())); connect(edit, SIGNAL(textChanged()), this, SLOT(close())); importFromKeyserverAct = new QAction(tr("Import missing key from Keyserver"), this); @@ -49,8 +52,7 @@ VerifyNotification::VerifyNotification(QWidget *parent, GpgME::GpgContext *ctx, 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(infoBoard); notificationWidgetLayout->addWidget(detailsButton); this->setLayout(notificationWidgetLayout); } @@ -60,9 +62,9 @@ void VerifyNotification::slotImportFromKeyserver() { importDialog->slotImport(*keysNotInList); } -void VerifyNotification::setVerifyLabel(const QString &text, verify_label_status verifyLabelStatus) { +void VerifyNotification::setInfoBoard(const QString &text, verify_label_status verifyLabelStatus) { QString color; - verifyLabel->setText(text); + infoBoard->setText(text); switch (verifyLabelStatus) { case VERIFY_ERROR_OK: color = "#ccffcc"; @@ -77,10 +79,11 @@ void VerifyNotification::setVerifyLabel(const QString &text, verify_label_status break; } - verifyLabel->setAutoFillBackground(true); - QPalette status = verifyLabel->palette(); - status.setColor(QPalette::Background, color); - verifyLabel->setPalette(status); + infoBoard->setAutoFillBackground(true); + QPalette status = infoBoard->palette(); + status.setColor(QPalette::Text, color); + infoBoard->setPalette(status); + infoBoard->setFont(QFont("Times", 10, QFont::Bold)); } void VerifyNotification::showImportAction(bool visible) { @@ -203,7 +206,7 @@ bool VerifyNotification::slotRefresh() { // Remove the last linebreak verifyLabelText.remove(verifyLabelText.length() - 1, 1); - this->setVerifyLabel(verifyLabelText, verifyStatus); + setInfoBoard(verifyLabelText, verifyStatus); return true; } diff --git a/src/ui/keypair_details/KeyPairDetailTab.cpp b/src/ui/keypair_details/KeyPairDetailTab.cpp index 5ba8d1e9..97b9cf87 100644 --- a/src/ui/keypair_details/KeyPairDetailTab.cpp +++ b/src/ui/keypair_details/KeyPairDetailTab.cpp @@ -29,53 +29,28 @@ KeyPairDetailTab::KeyPairDetailTab(GpgME::GpgContext *ctx, const GpgKey &mKey, Q mCtx = ctx; keyid = new QString(mKey.id); - ownerBox = new QGroupBox(tr("Owner details")); - keyBox = new QGroupBox(tr("Key details")); + ownerBox = new QGroupBox(tr("Owner")); + keyBox = new QGroupBox(tr("Master Key")); fingerprintBox = new QGroupBox(tr("Fingerprint")); - additionalUidBox = new QGroupBox(tr("Additional Uids")); + additionalUidBox = new QGroupBox(tr("Additional UIDs")); - nameVarLabel = new QLabel(mKey.name); + nameVarLabel = new QLabel(); nameVarLabel->setTextInteractionFlags(Qt::TextSelectableByMouse); - emailVarLabel = new QLabel(mKey.email); + emailVarLabel = new QLabel(); emailVarLabel->setTextInteractionFlags(Qt::TextSelectableByMouse); - commentVarLabel = new QLabel(mKey.comment); + commentVarLabel = new QLabel(); commentVarLabel->setTextInteractionFlags(Qt::TextSelectableByMouse); - keyidVarLabel = new QLabel(mKey.id); + keyidVarLabel = new QLabel(); keyidVarLabel->setTextInteractionFlags(Qt::TextSelectableByMouse); - QString usage; - QTextStream usage_steam(&usage); + usageVarLabel = new QLabel(); + actualUsageVarLabel = new QLabel(); - 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 = new QLabel(usage); - - QString keySizeVal, keyExpireVal, keyCreateTimeVal, keyAlgoVal; - - keySizeVal = QString::number(mKey.length); - - if (mKey.expires.toTime_t() == 0) { - keyExpireVal = tr("Never Expires"); - } else { - keyExpireVal = mKey.expires.toString(); - } - - - keyAlgoVal = mKey.pubkey_algo; - keyCreateTimeVal = mKey.create_time.toString(); - - keySizeVarLabel = new QLabel(keySizeVal); - expireVarLabel = new QLabel(keyExpireVal); - createdVarLabel = new QLabel(keyCreateTimeVal); - algorithmVarLabel = new QLabel(keyAlgoVal); + 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"); @@ -112,20 +87,22 @@ KeyPairDetailTab::KeyPairDetailTab(GpgME::GpgContext *ctx, const GpgKey &mKey, Q 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("Usage: ")), 3, 0); - vboxKD->addWidget(new QLabel(tr("Expires on: ")), 4, 0); - vboxKD->addWidget(new QLabel(tr("Last Update: ")), 5, 0); - vboxKD->addWidget(new QLabel(tr("Existence: ")), 6, 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, 4, 1); + vboxKD->addWidget(expireVarLabel, 5, 1); vboxKD->addWidget(algorithmVarLabel, 1, 1); - vboxKD->addWidget(createdVarLabel, 5, 1); + vboxKD->addWidget(createdVarLabel, 6, 1); vboxKD->addWidget(keyidVarLabel, 0, 1); vboxKD->addWidget(usageVarLabel, 3, 1); - vboxKD->addWidget(masterKeyExistVarLabel, 6, 1); + vboxKD->addWidget(actualUsageVarLabel, 4, 1); + vboxKD->addWidget(masterKeyExistVarLabel, 7, 1); ownerBox->setLayout(vboxOD); mvbox->addWidget(ownerBox); @@ -194,6 +171,8 @@ KeyPairDetailTab::KeyPairDetailTab(GpgME::GpgContext *ctx, const GpgKey &mKey, Q connect(mCtx, SIGNAL(signalKeyInfoChanged()), this, SLOT(slotRefreshKeyInfo())); + slotRefreshKeyInfo(); + setAttribute(Qt::WA_DeleteOnClose, true); setLayout(mvbox); } @@ -269,12 +248,26 @@ void KeyPairDetailTab::slotRefreshKeyInfo() { 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 Expired"); + keyExpireVal = tr("Never Expire"); } else { keyExpireVal = mKey.expires.toString(); } diff --git a/src/ui/widgets/KeyList.cpp b/src/ui/widgets/KeyList.cpp index b6596402..dccf1a56 100644 --- a/src/ui/widgets/KeyList.cpp +++ b/src/ui/widgets/KeyList.cpp @@ -176,13 +176,13 @@ void KeyList::slotRefresh() QString usage; QTextStream usage_steam(&usage); - if(it->can_certify) + if(GpgME::GpgContext::checkIfKeyCanCert(*it)) usage_steam << "C"; - if(it->can_encrypt) + if(GpgME::GpgContext::checkIfKeyCanEncr(*it)) usage_steam << "E"; - if(it->can_sign) + if(GpgME::GpgContext::checkIfKeyCanSign(*it)) usage_steam << "S"; - if(it->can_authenticate) + if(GpgME::GpgContext::checkIfKeyCanAuth(*it)) usage_steam << "A"; auto *temp_usage = new QTableWidgetItem(usage); @@ -463,3 +463,12 @@ void KeyList::slotDoubleClicked(const QModelIndex &index) { void KeyList::setDoubleClickedAction(std::function<void(const GpgKey &, QWidget *)> action) { this->mAction = std::move(action); } + +void KeyList::getPrivateCheckedKeys(QVector<GpgKey> &keys) { + keys.clear(); + for (int i = 0; i < mKeyList->rowCount(); i++) { + if (mKeyList->item(i, 0)->checkState() == Qt::Checked && buffered_keys[i].is_private_key) { + keys.push_back(buffered_keys[i]); + } + } +} diff --git a/src/ui/VerifyKeyDetailBox.cpp b/src/ui/widgets/VerifyKeyDetailBox.cpp index c393f468..3091d672 100644 --- a/src/ui/VerifyKeyDetailBox.cpp +++ b/src/ui/widgets/VerifyKeyDetailBox.cpp @@ -22,7 +22,7 @@ * */ -#include "ui/VerifyKeyDetailBox.h" +#include "ui/widgets/VerifyKeyDetailBox.h" VerifyKeyDetailBox::VerifyKeyDetailBox(QWidget *parent, GpgME::GpgContext *ctx, KeyList *keyList, gpgme_signature_t signature) : @@ -35,6 +35,7 @@ VerifyKeyDetailBox::VerifyKeyDetailBox(QWidget *parent, GpgME::GpgContext *ctx, switch (gpg_err_code(signature->status)) { case GPG_ERR_NO_PUBKEY: { + this->setTitle("A Error Signature"); auto *importButton = new QPushButton(tr("Import from keyserver")); connect(importButton, SIGNAL(clicked()), this, SLOT(slotImportFormKeyserver())); @@ -52,49 +53,86 @@ VerifyKeyDetailBox::VerifyKeyDetailBox(QWidget *parent, GpgME::GpgContext *ctx, break; } case GPG_ERR_NO_ERROR: { + this->setTitle("A Signature:"); auto gird = createKeyInfoGrid(signature); if(gird != nullptr) { vbox->addLayout(gird); + } else { + vbox->addWidget(new QLabel(tr("Key Information is NOT Available"))); + if(signature->fpr != nullptr) { + vbox->addWidget(new QLabel(tr("Fingerprint: ") + QString(signature->fpr))); + } } break; } case GPG_ERR_CERT_REVOKED: { - vbox->addWidget(new QLabel(tr("Cert Revoked"))); + this->setTitle("An Error Signature"); + vbox->addWidget(new QLabel(tr("Status: Cert Revoked"))); auto gird = createKeyInfoGrid(signature); if (gird != nullptr) { vbox->addLayout(gird); + } else { + vbox->addWidget(new QLabel(tr("Key Information is NOT Available"))); + if(signature->fpr != nullptr) { + vbox->addWidget(new QLabel(tr("Fingerprint: ") + QString(signature->fpr))); + } } break; } case GPG_ERR_SIG_EXPIRED: { - vbox->addWidget(new QLabel(tr("Signature Expired"))); + this->setTitle("An Error Signature"); + vbox->addWidget(new QLabel(tr("Status: Signature Expired"))); auto gird = createKeyInfoGrid(signature); if (gird != nullptr) { vbox->addLayout(gird); + } else { + vbox->addWidget(new QLabel(tr("Key Information is NOT Available"))); + if(signature->fpr != nullptr) { + vbox->addWidget(new QLabel(tr("Fingerprint: ") + QString(signature->fpr))); + } } break; } case GPG_ERR_KEY_EXPIRED: { - vbox->addWidget(new QLabel(tr("Key Expired"))); + this->setTitle("An Error Signature"); + vbox->addWidget(new QLabel(tr("Status: Signature Expired"))); + vbox->addWidget(new QLabel(tr("Status: Key Expired"))); auto gird = createKeyInfoGrid(signature); if (gird != nullptr) { vbox->addLayout(gird); + } else { + vbox->addWidget(new QLabel(tr("Key Information is NOT Available"))); + if(signature->fpr != nullptr) { + vbox->addWidget(new QLabel(tr("Fingerprint: ") + QString(signature->fpr))); + } } break; } case GPG_ERR_GENERAL: { - vbox->addWidget(new QLabel(tr("General Error"))); + this->setTitle("An Error Signature"); + vbox->addWidget(new QLabel(tr("Status: General Error"))); auto gird = createKeyInfoGrid(signature); if (gird != nullptr) { vbox->addLayout(gird); + } else { + vbox->addWidget(new QLabel(tr("Key Information is NOT Available"))); + if(signature->fpr != nullptr) { + vbox->addWidget(new QLabel(tr("Fingerprint: ") + QString(signature->fpr))); + } } break; } default: { - this->setTitle(tr("Error for key with id 0x") + fpr); + this->setTitle("An Error Signature"); + this->setTitle(tr("Status: Unknown Error")); auto gird = createKeyInfoGrid(signature); if (gird != nullptr) { vbox->addLayout(gird); + } else { + vbox->addWidget(new QLabel(tr("Key Information is NOT Available"))); + if(signature->fpr != nullptr) { + vbox->addWidget(new QLabel(tr("Fingerprint: ") + QString(signature->fpr))); + } } break; } @@ -121,9 +159,9 @@ QGridLayout *VerifyKeyDetailBox::createKeyInfoGrid(gpgme_signature_t &signature) GpgKey key = mCtx->getKeyByFpr(signature->fpr); if(!key.good) return nullptr; - grid->addWidget(new QLabel(tr("Name:")), 0, 0); - grid->addWidget(new QLabel(tr("Email:")), 1, 0); - grid->addWidget(new QLabel(tr("Fingerprint:")), 2, 0); + grid->addWidget(new QLabel(tr("Signer Name:")), 0, 0); + grid->addWidget(new QLabel(tr("Signer Email:")), 1, 0); + grid->addWidget(new QLabel(tr("Key's Fingerprint:")), 2, 0); grid->addWidget(new QLabel(tr("Valid:")), 3, 0); grid->addWidget(new QLabel(tr("Flags:")), 4, 0); |