<refactor>(ui): take operations apart from key details.
This commit is contained in:
parent
5c9f64f4a4
commit
49ec72e3d5
@ -1,285 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* 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<eric@bktus.com> starting on May 12, 2021.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "ui/FileEncryptionDialog.h"
|
|
||||||
|
|
||||||
#include "gpg/function/BasicOperator.h"
|
|
||||||
#include "gpg/function/GpgKeyGetter.h"
|
|
||||||
|
|
||||||
namespace GpgFrontend::UI {
|
|
||||||
FileEncryptionDialog::FileEncryptionDialog(KeyIdArgsListPtr keyList,
|
|
||||||
DialogAction action, QWidget* parent)
|
|
||||||
: QDialog(parent), mAction(action) {
|
|
||||||
if (mAction == Decrypt) {
|
|
||||||
setWindowTitle(_("Decrypt File"));
|
|
||||||
} else if (mAction == Encrypt) {
|
|
||||||
setWindowTitle(_("Encrypt File"));
|
|
||||||
} else if (mAction == Sign) {
|
|
||||||
setWindowTitle(_("Sign File"));
|
|
||||||
} else if (mAction == Verify) {
|
|
||||||
setWindowTitle(_("Verify File"));
|
|
||||||
}
|
|
||||||
|
|
||||||
setModal(true);
|
|
||||||
|
|
||||||
auto* buttonBox =
|
|
||||||
new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
|
||||||
connect(buttonBox, SIGNAL(accepted()), this, SLOT(slotExecuteAction()));
|
|
||||||
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
|
||||||
|
|
||||||
auto* groupBox1 = new QGroupBox(_("Input Parameters"));
|
|
||||||
|
|
||||||
/* Setup input & Outputfileselection*/
|
|
||||||
inputFileEdit = new QLineEdit();
|
|
||||||
auto* fb1 = new QPushButton("Select");
|
|
||||||
connect(fb1, SIGNAL(clicked()), this, SLOT(slotSelectInputFile()));
|
|
||||||
auto* fl1 = new QLabel(_("Target File"));
|
|
||||||
fl1->setBuddy(inputFileEdit);
|
|
||||||
|
|
||||||
outputFileEdit = new QLineEdit();
|
|
||||||
auto* fb2 = new QPushButton("Select");
|
|
||||||
connect(fb2, SIGNAL(clicked()), this, SLOT(slotSelectOutputFile()));
|
|
||||||
auto* fl2 = new QLabel(_("Output File"));
|
|
||||||
fl2->setBuddy(outputFileEdit);
|
|
||||||
|
|
||||||
auto* gLayout = new QGridLayout();
|
|
||||||
gLayout->addWidget(fl1, 0, 0);
|
|
||||||
gLayout->addWidget(inputFileEdit, 0, 1);
|
|
||||||
gLayout->addWidget(fb1, 0, 2);
|
|
||||||
signFileEdit = new QLineEdit();
|
|
||||||
// verify does not need outfile, but signature file
|
|
||||||
if (mAction != Verify) {
|
|
||||||
gLayout->addWidget(fl2, 1, 0);
|
|
||||||
gLayout->addWidget(outputFileEdit, 1, 1);
|
|
||||||
gLayout->addWidget(fb2, 1, 2);
|
|
||||||
} else {
|
|
||||||
auto* sfb1 = new QPushButton("Select");
|
|
||||||
connect(sfb1, SIGNAL(clicked()), this, SLOT(slotSelectSignFile()));
|
|
||||||
auto* sfl1 = new QLabel(_("Signature File(.sig) Path"));
|
|
||||||
sfl1->setBuddy(signFileEdit);
|
|
||||||
|
|
||||||
gLayout->addWidget(sfl1, 1, 0);
|
|
||||||
gLayout->addWidget(signFileEdit, 1, 1);
|
|
||||||
gLayout->addWidget(sfb1, 1, 2);
|
|
||||||
}
|
|
||||||
groupBox1->setLayout(gLayout);
|
|
||||||
|
|
||||||
/*Setup KeyList*/
|
|
||||||
mKeyList = new KeyList(false, this);
|
|
||||||
if (mAction == Verify) {
|
|
||||||
mKeyList->addListGroupTab(
|
|
||||||
_("Default"), KeyListRow::ONLY_SECRET_KEY,
|
|
||||||
KeyListColumn::NAME | KeyListColumn::EmailAddress |
|
|
||||||
KeyListColumn::Usage,
|
|
||||||
[](const GpgKey& key) -> bool {
|
|
||||||
if (key.disabled() || key.expired() || key.revoked())
|
|
||||||
return false;
|
|
||||||
else
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mAction == Encrypt) {
|
|
||||||
mKeyList->addListGroupTab(_("Default"), KeyListRow::ONLY_SECRET_KEY,
|
|
||||||
KeyListColumn::NAME |
|
|
||||||
KeyListColumn::EmailAddress |
|
|
||||||
KeyListColumn::Usage,
|
|
||||||
[](const GpgKey& key) -> bool {
|
|
||||||
if (!key.CanEncrActual())
|
|
||||||
return false;
|
|
||||||
else
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mAction == Encrypt) {
|
|
||||||
mKeyList->addListGroupTab(_("Default"), KeyListRow::ONLY_SECRET_KEY,
|
|
||||||
KeyListColumn::NAME |
|
|
||||||
KeyListColumn::EmailAddress |
|
|
||||||
KeyListColumn::Usage,
|
|
||||||
[](const GpgKey& key) -> bool {
|
|
||||||
if (!key.CanSignActual())
|
|
||||||
return false;
|
|
||||||
else
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mAction == Decrypt) mKeyList->setDisabled(true);
|
|
||||||
|
|
||||||
mKeyList->slotRefresh();
|
|
||||||
mKeyList->setChecked(keyList);
|
|
||||||
|
|
||||||
statusLabel = new QLabel();
|
|
||||||
statusLabel->setStyleSheet("QLabel {color: red;}");
|
|
||||||
|
|
||||||
auto* vbox2 = new QVBoxLayout();
|
|
||||||
vbox2->addWidget(groupBox1);
|
|
||||||
vbox2->addWidget(mKeyList);
|
|
||||||
vbox2->addWidget(statusLabel);
|
|
||||||
vbox2->addWidget(buttonBox);
|
|
||||||
vbox2->addStretch(0);
|
|
||||||
setLayout(vbox2);
|
|
||||||
|
|
||||||
this->setMinimumWidth(480);
|
|
||||||
this->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileEncryptionDialog::slotSelectInputFile() {
|
|
||||||
QString path;
|
|
||||||
if (inputFileEdit->text().size() > 0) {
|
|
||||||
path = QFileInfo(inputFileEdit->text()).absolutePath();
|
|
||||||
}
|
|
||||||
|
|
||||||
// QString infileName = QFileDialog::getOpenFileName(this, _("Open File"),
|
|
||||||
// path, _("Files") + _("All Files (*)"));
|
|
||||||
QString infileName = QFileDialog::getOpenFileName(this, _("Open File"), path);
|
|
||||||
inputFileEdit->setText(infileName);
|
|
||||||
|
|
||||||
// try to find a matching output-filename, if not yet done
|
|
||||||
if (!infileName.isEmpty() && outputFileEdit->text().size() == 0 &&
|
|
||||||
signFileEdit->text().size() == 0) {
|
|
||||||
if (mAction == Encrypt) {
|
|
||||||
outputFileEdit->setText(infileName + ".asc");
|
|
||||||
} else if (mAction == Sign) {
|
|
||||||
outputFileEdit->setText(infileName + ".sig");
|
|
||||||
} else if (mAction == Verify) {
|
|
||||||
signFileEdit->setText(infileName + ".sig");
|
|
||||||
} else {
|
|
||||||
if (infileName.endsWith(".asc", Qt::CaseInsensitive)) {
|
|
||||||
QString ofn = infileName;
|
|
||||||
ofn.chop(4);
|
|
||||||
outputFileEdit->setText(ofn);
|
|
||||||
} else {
|
|
||||||
outputFileEdit->setText(infileName + ".out");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileEncryptionDialog::slotSelectOutputFile() {
|
|
||||||
QString path;
|
|
||||||
if (outputFileEdit->text().size() > 0) {
|
|
||||||
path = QFileInfo(outputFileEdit->text()).absolutePath();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString outfileName =
|
|
||||||
QFileDialog::getSaveFileName(this, _("Save File"), path, nullptr, nullptr,
|
|
||||||
QFileDialog::DontConfirmOverwrite);
|
|
||||||
outputFileEdit->setText(outfileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileEncryptionDialog::slotSelectSignFile() {
|
|
||||||
QString path;
|
|
||||||
if (signFileEdit->text().size() > 0) {
|
|
||||||
path = QFileInfo(signFileEdit->text()).absolutePath();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString signfileName =
|
|
||||||
QFileDialog::getSaveFileName(this, _("Open File"), path, nullptr, nullptr,
|
|
||||||
QFileDialog::DontConfirmOverwrite);
|
|
||||||
signFileEdit->setText(signfileName);
|
|
||||||
|
|
||||||
if (inputFileEdit->text().size() == 0 &&
|
|
||||||
signfileName.endsWith(".sig", Qt::CaseInsensitive)) {
|
|
||||||
QString sfn = signfileName;
|
|
||||||
sfn.chop(4);
|
|
||||||
inputFileEdit->setText(sfn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileEncryptionDialog::slotExecuteAction() {
|
|
||||||
QFile infile;
|
|
||||||
infile.setFileName(inputFileEdit->text());
|
|
||||||
if (!infile.open(QIODevice::ReadOnly)) {
|
|
||||||
statusLabel->setText(_("Couldn't open file"));
|
|
||||||
inputFileEdit->setStyleSheet("QLineEdit { background: yellow }");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto in_data = read_all_data_in_file(inputFileEdit->text().toStdString());
|
|
||||||
auto out_data = std::make_unique<ByteArray>();
|
|
||||||
|
|
||||||
auto key_ids = mKeyList->getChecked();
|
|
||||||
auto keys = GpgKeyGetter::GetInstance().GetKeys(key_ids);
|
|
||||||
|
|
||||||
if (mAction == Encrypt) {
|
|
||||||
qDebug() << "Action Encrypt";
|
|
||||||
GpgEncrResult result = nullptr;
|
|
||||||
gpgme_error_t err = BasicOperator::GetInstance().Encrypt(
|
|
||||||
std::move(keys), in_data, out_data, result);
|
|
||||||
if (gpgme_err_code(err) != GPG_ERR_NO_ERROR) {
|
|
||||||
qDebug() << "Error" << gpgme_strerror(err);
|
|
||||||
|
|
||||||
QMessageBox::warning(this, _("Error"),
|
|
||||||
_("Error Occurred During Encryption"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (mAction == Decrypt) {
|
|
||||||
qDebug() << "Action Decrypt";
|
|
||||||
GpgDecrResult result = nullptr;
|
|
||||||
gpgme_error_t err =
|
|
||||||
BasicOperator::GetInstance().Decrypt(in_data, out_data, result);
|
|
||||||
if (gpgme_err_code(err) != GPG_ERR_NO_ERROR) {
|
|
||||||
qDebug() << "Error" << gpgme_strerror(err);
|
|
||||||
QMessageBox::warning(this, _("Error"),
|
|
||||||
_("Error Occurred During Decryption"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (mAction == Sign) {
|
|
||||||
qDebug() << "Action Sign";
|
|
||||||
GpgSignResult result = nullptr;
|
|
||||||
gpgme_error_t err = BasicOperator::GetInstance().Sign(
|
|
||||||
std::move(keys), in_data, out_data, GPGME_SIG_MODE_DETACH, result);
|
|
||||||
if (gpgme_err_code(err) != GPG_ERR_NO_ERROR) {
|
|
||||||
qDebug() << "Error" << gpgme_strerror(err);
|
|
||||||
QMessageBox::warning(this, _("Error"),
|
|
||||||
_("Error Occurred During Signature"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mAction == Verify) {
|
|
||||||
auto sign_data = std::make_unique<ByteArray>(
|
|
||||||
read_all_data_in_file(signFileEdit->text().toStdString()));
|
|
||||||
GpgVerifyResult result = nullptr;
|
|
||||||
auto error =
|
|
||||||
BasicOperator::GetInstance().Verify(in_data, sign_data, result);
|
|
||||||
new VerifyDetailsDialog(this, error, std::move(result));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
write_buffer_to_file(outputFileEdit->text().toStdString(), *out_data);
|
|
||||||
|
|
||||||
accept();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileEncryptionDialog::slotShowKeyList() { mKeyList->show(); }
|
|
||||||
|
|
||||||
void FileEncryptionDialog::slotHideKeyList() { mKeyList->hide(); }
|
|
||||||
|
|
||||||
} // namespace GpgFrontend::UI
|
|
@ -1,114 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* 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<eric@bktus.com> starting on May 12, 2021.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __FILEENCRYPTIONDIALOG_H__
|
|
||||||
#define __FILEENCRYPTIONDIALOG_H__
|
|
||||||
|
|
||||||
#include "gpg/GpgContext.h"
|
|
||||||
#include "ui/GpgFrontendUI.h"
|
|
||||||
#include "ui/details/VerifyDetailsDialog.h"
|
|
||||||
#include "ui/widgets/KeyList.h"
|
|
||||||
|
|
||||||
namespace GpgFrontend::UI {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief
|
|
||||||
*
|
|
||||||
* @class FileEncryptionDialog fileencryptiondialog.h "fileencryptiondialog.h"
|
|
||||||
*/
|
|
||||||
class FileEncryptionDialog : public QDialog {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
enum DialogAction { Encrypt, Decrypt, Sign, Verify };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief
|
|
||||||
*
|
|
||||||
* @fn FileEncryptionDialog
|
|
||||||
* @param ctx
|
|
||||||
* @param keyList
|
|
||||||
* @param parent
|
|
||||||
*/
|
|
||||||
FileEncryptionDialog(KeyIdArgsListPtr keyList, DialogAction action,
|
|
||||||
QWidget* parent = nullptr);
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @details
|
|
||||||
*
|
|
||||||
* @fn selectInputFile
|
|
||||||
*/
|
|
||||||
void slotSelectInputFile();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief
|
|
||||||
*
|
|
||||||
* @fn selectOutputFile
|
|
||||||
*/
|
|
||||||
void slotSelectOutputFile();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief
|
|
||||||
*
|
|
||||||
* @fn selectSignFile
|
|
||||||
*/
|
|
||||||
void slotSelectSignFile();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief
|
|
||||||
*
|
|
||||||
* @fn executeAction
|
|
||||||
*/
|
|
||||||
void slotExecuteAction();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief
|
|
||||||
*
|
|
||||||
* @fn hideKeyList
|
|
||||||
*/
|
|
||||||
void slotHideKeyList();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief
|
|
||||||
*
|
|
||||||
* @fn showKeyList
|
|
||||||
*/
|
|
||||||
void slotShowKeyList();
|
|
||||||
|
|
||||||
private:
|
|
||||||
QLineEdit* outputFileEdit;
|
|
||||||
QLineEdit* inputFileEdit;
|
|
||||||
QLineEdit* signFileEdit;
|
|
||||||
DialogAction mAction;
|
|
||||||
QLabel* statusLabel;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
KeyList* mKeyList;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace GpgFrontend::UI
|
|
||||||
|
|
||||||
#endif // __FILEENCRYPTIONDIALOG_H__
|
|
@ -31,6 +31,7 @@
|
|||||||
#include "gpg/function/GpgKeyOpera.h"
|
#include "gpg/function/GpgKeyOpera.h"
|
||||||
#include "ui/SignalStation.h"
|
#include "ui/SignalStation.h"
|
||||||
#include "ui/UserInterfaceUtils.h"
|
#include "ui/UserInterfaceUtils.h"
|
||||||
|
#include "ui/keygen/SubkeyGenerateDialog.h"
|
||||||
#include "ui/settings/GlobalSettingStation.h"
|
#include "ui/settings/GlobalSettingStation.h"
|
||||||
|
|
||||||
namespace GpgFrontend::UI {
|
namespace GpgFrontend::UI {
|
||||||
|
@ -29,7 +29,6 @@
|
|||||||
#include "gpg/result_analyse/DecryptResultAnalyse.h"
|
#include "gpg/result_analyse/DecryptResultAnalyse.h"
|
||||||
#include "gpg/result_analyse/EncryptResultAnalyse.h"
|
#include "gpg/result_analyse/EncryptResultAnalyse.h"
|
||||||
#include "gpg/result_analyse/SignResultAnalyse.h"
|
#include "gpg/result_analyse/SignResultAnalyse.h"
|
||||||
#include "ui/FileEncryptionDialog.h"
|
|
||||||
#include "ui/FindWidget.h"
|
#include "ui/FindWidget.h"
|
||||||
#include "ui/GpgFrontendUI.h"
|
#include "ui/GpgFrontendUI.h"
|
||||||
#include "ui/KeyMgmt.h"
|
#include "ui/KeyMgmt.h"
|
||||||
@ -323,7 +322,7 @@ class MainWindow : public QMainWindow {
|
|||||||
QMenu* viewMenu{}; /** Submenu for view operations */
|
QMenu* viewMenu{}; /** Submenu for view operations */
|
||||||
QMenu* importKeyMenu{}; /** Sumenu for import operations */
|
QMenu* importKeyMenu{}; /** Sumenu for import operations */
|
||||||
#ifdef SMTP_SUPPORT
|
#ifdef SMTP_SUPPORT
|
||||||
QMenu* emailMenu{}; /** Sumenu for email operations */
|
QMenu* emailMenu{}; /** Sumenu for email operations */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QMenu* steganoMenu{}; /** Submenu for steganographic operations*/
|
QMenu* steganoMenu{}; /** Submenu for steganographic operations*/
|
||||||
|
@ -24,6 +24,11 @@
|
|||||||
|
|
||||||
#include "ui/keypair_details/KeyDetailsDialog.h"
|
#include "ui/keypair_details/KeyDetailsDialog.h"
|
||||||
|
|
||||||
|
#include "ui/keypair_details/KeyPairDetailTab.h"
|
||||||
|
#include "ui/keypair_details/KeyPairOperaTab.h"
|
||||||
|
#include "ui/keypair_details/KeyPairSubkeyTab.h"
|
||||||
|
#include "ui/keypair_details/KeyPairUIDTab.h"
|
||||||
|
|
||||||
namespace GpgFrontend::UI {
|
namespace GpgFrontend::UI {
|
||||||
KeyDetailsDialog::KeyDetailsDialog(const GpgKey& key, QWidget* parent)
|
KeyDetailsDialog::KeyDetailsDialog(const GpgKey& key, QWidget* parent)
|
||||||
: QDialog(parent) {
|
: QDialog(parent) {
|
||||||
@ -31,6 +36,7 @@ KeyDetailsDialog::KeyDetailsDialog(const GpgKey& key, QWidget* parent)
|
|||||||
tabWidget->addTab(new KeyPairDetailTab(key.id(), tabWidget), _("KeyPair"));
|
tabWidget->addTab(new KeyPairDetailTab(key.id(), tabWidget), _("KeyPair"));
|
||||||
tabWidget->addTab(new KeyPairUIDTab(key.id(), tabWidget), _("UIDs"));
|
tabWidget->addTab(new KeyPairUIDTab(key.id(), tabWidget), _("UIDs"));
|
||||||
tabWidget->addTab(new KeyPairSubkeyTab(key.id(), tabWidget), _("Subkeys"));
|
tabWidget->addTab(new KeyPairSubkeyTab(key.id(), tabWidget), _("Subkeys"));
|
||||||
|
tabWidget->addTab(new KeyPairOperaTab(key.id(), tabWidget), _("Operations"));
|
||||||
|
|
||||||
auto* mainLayout = new QVBoxLayout;
|
auto* mainLayout = new QVBoxLayout;
|
||||||
mainLayout->addWidget(tabWidget);
|
mainLayout->addWidget(tabWidget);
|
||||||
@ -42,7 +48,7 @@ KeyDetailsDialog::KeyDetailsDialog(const GpgKey& key, QWidget* parent)
|
|||||||
this->setLayout(mainLayout);
|
this->setLayout(mainLayout);
|
||||||
this->setWindowTitle(_("Key Details"));
|
this->setWindowTitle(_("Key Details"));
|
||||||
this->setModal(true);
|
this->setModal(true);
|
||||||
this->setMinimumSize({520, 800});
|
this->setMinimumSize({520, 600});
|
||||||
this->resize(this->minimumSize());
|
this->resize(this->minimumSize());
|
||||||
this->show();
|
this->show();
|
||||||
}
|
}
|
||||||
|
@ -25,9 +25,6 @@
|
|||||||
#ifndef __KEYDETAILSDIALOG_H__
|
#ifndef __KEYDETAILSDIALOG_H__
|
||||||
#define __KEYDETAILSDIALOG_H__
|
#define __KEYDETAILSDIALOG_H__
|
||||||
|
|
||||||
#include "KeyPairDetailTab.h"
|
|
||||||
#include "KeyPairSubkeyTab.h"
|
|
||||||
#include "KeyPairUIDTab.h"
|
|
||||||
#include "gpg/GpgContext.h"
|
#include "gpg/GpgContext.h"
|
||||||
#include "ui/GpgFrontendUI.h"
|
#include "ui/GpgFrontendUI.h"
|
||||||
|
|
||||||
|
@ -26,11 +26,8 @@
|
|||||||
|
|
||||||
#include "gpg/function/GpgKeyGetter.h"
|
#include "gpg/function/GpgKeyGetter.h"
|
||||||
#include "gpg/function/GpgKeyImportExporter.h"
|
#include "gpg/function/GpgKeyImportExporter.h"
|
||||||
#include "gpg/function/GpgKeyOpera.h"
|
|
||||||
#include "ui/SignalStation.h"
|
#include "ui/SignalStation.h"
|
||||||
#include "ui/UserInterfaceUtils.h"
|
|
||||||
#include "ui/WaitingDialog.h"
|
#include "ui/WaitingDialog.h"
|
||||||
#include "ui/settings/GlobalSettingStation.h"
|
|
||||||
|
|
||||||
namespace GpgFrontend::UI {
|
namespace GpgFrontend::UI {
|
||||||
KeyPairDetailTab::KeyPairDetailTab(const std::string& key_id, QWidget* parent)
|
KeyPairDetailTab::KeyPairDetailTab(const std::string& key_id, QWidget* parent)
|
||||||
@ -134,66 +131,6 @@ KeyPairDetailTab::KeyPairDetailTab(const std::string& key_id, QWidget* parent)
|
|||||||
mvbox->addWidget(fingerprintBox);
|
mvbox->addWidget(fingerprintBox);
|
||||||
mvbox->addStretch();
|
mvbox->addStretch();
|
||||||
|
|
||||||
// Set Menu
|
|
||||||
createOperaMenu();
|
|
||||||
|
|
||||||
auto* opera_key_box = new QGroupBox(_("Operations"));
|
|
||||||
auto* vbox_p_k = new QVBoxLayout();
|
|
||||||
|
|
||||||
auto export_h_box_layout = new QHBoxLayout();
|
|
||||||
vbox_p_k->addLayout(export_h_box_layout);
|
|
||||||
|
|
||||||
auto* export_public_button = new QPushButton(_("Export Public Key"));
|
|
||||||
export_h_box_layout->addWidget(export_public_button);
|
|
||||||
connect(export_public_button, SIGNAL(clicked()), this,
|
|
||||||
SLOT(slotExportPublicKey()));
|
|
||||||
|
|
||||||
if (mKey.is_private_key()) {
|
|
||||||
auto* export_private_button = new QPushButton(_("Export Private Key"));
|
|
||||||
export_private_button->setStyleSheet("text-align:center;");
|
|
||||||
export_private_button->setMenu(secretKeyExportOperaMenu);
|
|
||||||
export_h_box_layout->addWidget(export_private_button);
|
|
||||||
|
|
||||||
if (mKey.has_master_key()) {
|
|
||||||
auto* edit_expires_button =
|
|
||||||
new QPushButton(_("Modify Expiration Datetime (Primary Key)"));
|
|
||||||
connect(edit_expires_button, SIGNAL(clicked()), this,
|
|
||||||
SLOT(slotModifyEditDatetime()));
|
|
||||||
auto* edit_password_button = new QPushButton(_("Modify Password"));
|
|
||||||
connect(edit_password_button, SIGNAL(clicked()), this,
|
|
||||||
SLOT(slotModifyPassword()));
|
|
||||||
|
|
||||||
auto edit_h_box_layout = new QHBoxLayout();
|
|
||||||
edit_h_box_layout->addWidget(edit_expires_button);
|
|
||||||
edit_h_box_layout->addWidget(edit_password_button);
|
|
||||||
vbox_p_k->addLayout(edit_h_box_layout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto advance_h_box_layout = new QHBoxLayout();
|
|
||||||
auto* key_server_opera_button =
|
|
||||||
new QPushButton(_("Key Server Operation (Pubkey)"));
|
|
||||||
key_server_opera_button->setStyleSheet("text-align:center;");
|
|
||||||
key_server_opera_button->setMenu(keyServerOperaMenu);
|
|
||||||
advance_h_box_layout->addWidget(key_server_opera_button);
|
|
||||||
|
|
||||||
if (mKey.is_private_key() && mKey.has_master_key()) {
|
|
||||||
auto* revoke_cert_gen_button =
|
|
||||||
new QPushButton(_("Generate Revoke Certificate"));
|
|
||||||
connect(revoke_cert_gen_button, SIGNAL(clicked()), this,
|
|
||||||
SLOT(slotGenRevokeCert()));
|
|
||||||
advance_h_box_layout->addWidget(revoke_cert_gen_button);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* modify_tofu_button = new QPushButton(_("Modify TOFU Policy"));
|
|
||||||
connect(modify_tofu_button, SIGNAL(clicked()), this,
|
|
||||||
SLOT(slotModifyTOFUPolicy()));
|
|
||||||
|
|
||||||
vbox_p_k->addLayout(advance_h_box_layout);
|
|
||||||
opera_key_box->setLayout(vbox_p_k);
|
|
||||||
mvbox->addWidget(opera_key_box);
|
|
||||||
vbox_p_k->addWidget(modify_tofu_button);
|
|
||||||
|
|
||||||
auto* expBox = new QHBoxLayout();
|
auto* expBox = new QHBoxLayout();
|
||||||
QPixmap pixmap(":warning.png");
|
QPixmap pixmap(":warning.png");
|
||||||
|
|
||||||
@ -218,126 +155,12 @@ KeyPairDetailTab::KeyPairDetailTab(const std::string& key_id, QWidget* parent)
|
|||||||
setLayout(mvbox);
|
setLayout(mvbox);
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeyPairDetailTab::slotExportPublicKey() {
|
|
||||||
ByteArrayPtr keyArray = nullptr;
|
|
||||||
|
|
||||||
if (!GpgKeyImportExporter::GetInstance().ExportKey(mKey, keyArray)) {
|
|
||||||
QMessageBox::critical(this, _("Error"),
|
|
||||||
_("An error occurred during the export operation."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto file_string =
|
|
||||||
mKey.name() + " " + mKey.email() + "(" + mKey.id() + ")_pub.asc";
|
|
||||||
auto file_name =
|
|
||||||
QFileDialog::getSaveFileName(
|
|
||||||
this, _("Export Key To File"), QString::fromStdString(file_string),
|
|
||||||
QString(_("Key Files")) + " (*.asc *.txt);;All Files (*)")
|
|
||||||
.toStdString();
|
|
||||||
|
|
||||||
if (file_name.empty()) return;
|
|
||||||
|
|
||||||
if (!write_buffer_to_file(file_name, *keyArray)) {
|
|
||||||
QMessageBox::critical(
|
|
||||||
this, _("Export Error"),
|
|
||||||
QString(_("Couldn't open %1 for writing")).arg(file_name.c_str()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyPairDetailTab::slotExportShortPrivateKey() {
|
|
||||||
// Show a information box with explanation about private key
|
|
||||||
int ret = QMessageBox::information(
|
|
||||||
this, _("Exporting short private Key"),
|
|
||||||
"<h3>" + QString(_("You are about to export your")) +
|
|
||||||
"<font color=\"red\">" + _(" PRIVATE KEY ") + "</font>!</h3>\n" +
|
|
||||||
_("This is NOT your Public Key, so DON'T give it away.") + "<br />" +
|
|
||||||
_("Do you REALLY want to export your PRIVATE KEY in a Minimum "
|
|
||||||
"Size?") +
|
|
||||||
"<br />" +
|
|
||||||
_("For OpenPGP keys it removes all signatures except for the latest "
|
|
||||||
"self-signatures."),
|
|
||||||
QMessageBox::Cancel | QMessageBox::Ok);
|
|
||||||
|
|
||||||
// export key, if ok was clicked
|
|
||||||
if (ret == QMessageBox::Ok) {
|
|
||||||
ByteArrayPtr keyArray = nullptr;
|
|
||||||
|
|
||||||
if (!GpgKeyImportExporter::GetInstance().ExportSecretKeyShortest(
|
|
||||||
mKey, keyArray)) {
|
|
||||||
QMessageBox::critical(
|
|
||||||
this, _("Error"),
|
|
||||||
_("An error occurred during the export operation."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto file_string = mKey.name() + " " + mKey.email() + "(" + mKey.id() +
|
|
||||||
")_short_secret.asc";
|
|
||||||
auto file_name =
|
|
||||||
QFileDialog::getSaveFileName(
|
|
||||||
this, _("Export Key To File"), QString::fromStdString(file_string),
|
|
||||||
QString(_("Key Files")) + " (*.asc *.txt);;All Files (*)")
|
|
||||||
.toStdString();
|
|
||||||
|
|
||||||
if (file_name.empty()) return;
|
|
||||||
|
|
||||||
if (!write_buffer_to_file(file_name, *keyArray)) {
|
|
||||||
QMessageBox::critical(
|
|
||||||
this, _("Export Error"),
|
|
||||||
QString(_("Couldn't open %1 for writing")).arg(file_name.c_str()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyPairDetailTab::slotExportPrivateKey() {
|
|
||||||
// Show a information box with explanation about private key
|
|
||||||
int ret = QMessageBox::information(
|
|
||||||
this, _("Exporting private Key"),
|
|
||||||
"<h3>" + QString(_("You are about to export your")) +
|
|
||||||
"<font color=\"red\">" + _(" PRIVATE KEY ") + "</font>!</h3>\n" +
|
|
||||||
_("This is NOT your Public Key, so DON'T give it away.") + "<br />" +
|
|
||||||
_("Do you REALLY want to export your PRIVATE KEY?"),
|
|
||||||
QMessageBox::Cancel | QMessageBox::Ok);
|
|
||||||
|
|
||||||
// export key, if ok was clicked
|
|
||||||
if (ret == QMessageBox::Ok) {
|
|
||||||
ByteArrayPtr keyArray = nullptr;
|
|
||||||
|
|
||||||
if (!GpgKeyImportExporter::GetInstance().ExportSecretKey(mKey, keyArray)) {
|
|
||||||
QMessageBox::critical(
|
|
||||||
this, _("Error"),
|
|
||||||
_("An error occurred during the export operation."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto file_string = mKey.name() + " " + mKey.email() + "(" + mKey.id() +
|
|
||||||
")_full_secret.asc";
|
|
||||||
auto file_name =
|
|
||||||
QFileDialog::getSaveFileName(
|
|
||||||
this, _("Export Key To File"), QString::fromStdString(file_string),
|
|
||||||
QString(_("Key Files")) + " (*.asc *.txt);;All Files (*)")
|
|
||||||
.toStdString();
|
|
||||||
|
|
||||||
if (file_name.empty()) return;
|
|
||||||
|
|
||||||
if (!write_buffer_to_file(file_name, *keyArray)) {
|
|
||||||
QMessageBox::critical(
|
|
||||||
this, _("Export Error"),
|
|
||||||
QString(_("Couldn't open %1 for writing")).arg(file_name.c_str()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyPairDetailTab::slotCopyFingerprint() {
|
void KeyPairDetailTab::slotCopyFingerprint() {
|
||||||
QString fpr = fingerPrintVarLabel->text().trimmed().replace(" ", QString());
|
QString fpr = fingerPrintVarLabel->text().trimmed().replace(" ", QString());
|
||||||
QClipboard* cb = QApplication::clipboard();
|
QClipboard* cb = QApplication::clipboard();
|
||||||
cb->setText(fpr);
|
cb->setText(fpr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeyPairDetailTab::slotModifyEditDatetime() {
|
|
||||||
auto dialog = new KeySetExpireDateDialog(mKey.id(), this);
|
|
||||||
dialog->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyPairDetailTab::slotRefreshKeyInfo() {
|
void KeyPairDetailTab::slotRefreshKeyInfo() {
|
||||||
// Show the situation that primary key not exists.
|
// Show the situation that primary key not exists.
|
||||||
masterKeyExistVarLabel->setText(mKey.has_master_key() ? _("Exists")
|
masterKeyExistVarLabel->setText(mKey.has_master_key() ? _("Exists")
|
||||||
@ -430,142 +253,10 @@ void KeyPairDetailTab::slotRefreshKeyInfo() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeyPairDetailTab::createOperaMenu() {
|
|
||||||
keyServerOperaMenu = new QMenu(this);
|
|
||||||
|
|
||||||
auto* uploadKeyPair = new QAction(_("Upload Key Pair to Key Server"), this);
|
|
||||||
connect(uploadKeyPair, SIGNAL(triggered()), this,
|
|
||||||
SLOT(slotUploadKeyToServer()));
|
|
||||||
if (!(mKey.is_private_key() && mKey.has_master_key()))
|
|
||||||
uploadKeyPair->setDisabled(true);
|
|
||||||
|
|
||||||
auto* updateKeyPair = new QAction(_("Sync Key Pair From Key Server"), this);
|
|
||||||
connect(updateKeyPair, SIGNAL(triggered()), this,
|
|
||||||
SLOT(slotUpdateKeyFromServer()));
|
|
||||||
|
|
||||||
// when a key has primary key, it should always upload to keyserver.
|
|
||||||
if (mKey.has_master_key()) {
|
|
||||||
updateKeyPair->setDisabled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
keyServerOperaMenu->addAction(uploadKeyPair);
|
|
||||||
keyServerOperaMenu->addAction(updateKeyPair);
|
|
||||||
|
|
||||||
secretKeyExportOperaMenu = new QMenu(this);
|
|
||||||
|
|
||||||
auto* exportFullSecretKey = new QAction(_("Export Full Secret Key"), this);
|
|
||||||
connect(exportFullSecretKey, SIGNAL(triggered()), this,
|
|
||||||
SLOT(slotExportPrivateKey()));
|
|
||||||
if (!mKey.is_private_key()) exportFullSecretKey->setDisabled(true);
|
|
||||||
|
|
||||||
auto* exportShortestSecretKey =
|
|
||||||
new QAction(_("Export Shortest Secret Key"), this);
|
|
||||||
connect(exportShortestSecretKey, SIGNAL(triggered()), this,
|
|
||||||
SLOT(slotExportShortPrivateKey()));
|
|
||||||
|
|
||||||
secretKeyExportOperaMenu->addAction(exportFullSecretKey);
|
|
||||||
secretKeyExportOperaMenu->addAction(exportShortestSecretKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyPairDetailTab::slotUploadKeyToServer() {
|
|
||||||
auto keys = std::make_unique<KeyIdArgsList>();
|
|
||||||
keys->push_back(mKey.id());
|
|
||||||
auto* dialog = new KeyUploadDialog(keys, this);
|
|
||||||
dialog->show();
|
|
||||||
dialog->slotUpload();
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyPairDetailTab::slotUpdateKeyFromServer() {
|
|
||||||
auto keys = std::make_unique<KeyIdArgsList>();
|
|
||||||
keys->push_back(mKey.id());
|
|
||||||
auto* dialog = new KeyServerImportDialog(this);
|
|
||||||
dialog->show();
|
|
||||||
dialog->slotImport(keys);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyPairDetailTab::slotGenRevokeCert() {
|
|
||||||
auto literal = QString("%1 (*.rev)").arg(_("Revocation Certificates"));
|
|
||||||
QString m_output_file_name;
|
|
||||||
|
|
||||||
QFileDialog dialog(this, "Generate revocation certificate", QString(),
|
|
||||||
literal);
|
|
||||||
dialog.setDefaultSuffix(".rev");
|
|
||||||
dialog.setAcceptMode(QFileDialog::AcceptSave);
|
|
||||||
|
|
||||||
if (dialog.exec()) m_output_file_name = dialog.selectedFiles().front();
|
|
||||||
|
|
||||||
if (!m_output_file_name.isEmpty())
|
|
||||||
CommonUtils::GetInstance()->slotExecuteGpgCommand(
|
|
||||||
{"--command-fd", "0", "--status-fd", "1", "--no-tty", "-o",
|
|
||||||
m_output_file_name, "--gen-revoke", mKey.fpr().c_str()},
|
|
||||||
[](QProcess* proc) -> void {
|
|
||||||
// Code From Gpg4Win
|
|
||||||
while (proc->canReadLine()) {
|
|
||||||
const QString line = QString::fromUtf8(proc->readLine()).trimmed();
|
|
||||||
LOG(INFO) << "line" << line.toStdString();
|
|
||||||
if (line == QLatin1String("[GNUPG:] GET_BOOL gen_revoke.okay")) {
|
|
||||||
proc->write("y\n");
|
|
||||||
} else if (line == QLatin1String("[GNUPG:] GET_LINE "
|
|
||||||
"ask_revocation_reason.code")) {
|
|
||||||
proc->write("0\n");
|
|
||||||
} else if (line == QLatin1String("[GNUPG:] GET_LINE "
|
|
||||||
"ask_revocation_reason.text")) {
|
|
||||||
proc->write("\n");
|
|
||||||
} else if (line ==
|
|
||||||
QLatin1String(
|
|
||||||
"[GNUPG:] GET_BOOL openfile.overwrite.okay")) {
|
|
||||||
// We asked before
|
|
||||||
proc->write("y\n");
|
|
||||||
} else if (line == QLatin1String("[GNUPG:] GET_BOOL "
|
|
||||||
"ask_revocation_reason.okay")) {
|
|
||||||
proc->write("y\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
void KeyPairDetailTab::slotRefreshKey() {
|
void KeyPairDetailTab::slotRefreshKey() {
|
||||||
LOG(INFO) << _("Called");
|
LOG(INFO) << _("Called");
|
||||||
this->mKey = GpgKeyGetter::GetInstance().GetKey(mKey.id());
|
this->mKey = GpgKeyGetter::GetInstance().GetKey(mKey.id());
|
||||||
this->slotRefreshKeyInfo();
|
this->slotRefreshKeyInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeyPairDetailTab::slotModifyPassword() {
|
|
||||||
auto err = GpgKeyOpera::GetInstance().ModifyPassword(mKey);
|
|
||||||
if (check_gpg_error_2_err_code(err) != GPG_ERR_NO_ERROR) {
|
|
||||||
QMessageBox::critical(this, _("Not Successful"),
|
|
||||||
QString(_("Modify password not successfully.")));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyPairDetailTab::slotModifyTOFUPolicy() {
|
|
||||||
QStringList items;
|
|
||||||
items << _("Policy Auto") << _("Policy Good") << _("Policy Bad")
|
|
||||||
<< _("Policy Ask") << _("Policy Unknown");
|
|
||||||
|
|
||||||
bool ok;
|
|
||||||
QString item = QInputDialog::getItem(
|
|
||||||
this, _("Modify TOFU Policy(Default is Auto)"),
|
|
||||||
_("Policy for the Key Pair:"), items, 0, false, &ok);
|
|
||||||
if (ok && !item.isEmpty()) {
|
|
||||||
LOG(INFO) << "selected policy" << item.toStdString();
|
|
||||||
gpgme_tofu_policy_t tofu_policy = GPGME_TOFU_POLICY_AUTO;
|
|
||||||
if (item == _("Policy Auto")) {
|
|
||||||
tofu_policy = GPGME_TOFU_POLICY_AUTO;
|
|
||||||
} else if (item == _("Policy Good")) {
|
|
||||||
tofu_policy = GPGME_TOFU_POLICY_GOOD;
|
|
||||||
} else if (item == _("Policy Bad")) {
|
|
||||||
tofu_policy = GPGME_TOFU_POLICY_BAD;
|
|
||||||
} else if (item == _("Policy Ask")) {
|
|
||||||
tofu_policy = GPGME_TOFU_POLICY_ASK;
|
|
||||||
} else if (item == _("Policy Unknown")) {
|
|
||||||
tofu_policy = GPGME_TOFU_POLICY_UNKNOWN;
|
|
||||||
}
|
|
||||||
auto err = GpgKeyOpera::GetInstance().ModifyTOFUPolicy(mKey, tofu_policy);
|
|
||||||
if (check_gpg_error_2_err_code(err) != GPG_ERR_NO_ERROR) {
|
|
||||||
QMessageBox::critical(this, _("Not Successful"),
|
|
||||||
QString(_("Modify TOFU policy not successfully.")));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace GpgFrontend::UI
|
} // namespace GpgFrontend::UI
|
||||||
|
@ -36,40 +36,17 @@ namespace GpgFrontend::UI {
|
|||||||
class KeyPairDetailTab : public QWidget {
|
class KeyPairDetailTab : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
void createOperaMenu();
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
/**
|
|
||||||
* @details Export the key to a file, which is chosen in a file dialog
|
|
||||||
*/
|
|
||||||
void slotExportPrivateKey();
|
|
||||||
|
|
||||||
void slotExportShortPrivateKey();
|
|
||||||
|
|
||||||
void slotExportPublicKey();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @details Copy the fingerprint to clipboard
|
* @details Copy the fingerprint to clipboard
|
||||||
*/
|
*/
|
||||||
void slotCopyFingerprint();
|
void slotCopyFingerprint();
|
||||||
|
|
||||||
void slotModifyEditDatetime();
|
|
||||||
|
|
||||||
void slotModifyPassword();
|
|
||||||
|
|
||||||
void slotRefreshKeyInfo();
|
void slotRefreshKeyInfo();
|
||||||
|
|
||||||
void slotUploadKeyToServer();
|
|
||||||
|
|
||||||
void slotUpdateKeyFromServer();
|
|
||||||
|
|
||||||
void slotGenRevokeCert();
|
|
||||||
|
|
||||||
void slotRefreshKey();
|
void slotRefreshKey();
|
||||||
|
|
||||||
void slotModifyTOFUPolicy();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GpgKey mKey;
|
GpgKey mKey;
|
||||||
|
|
||||||
|
349
src/ui/keypair_details/KeyPairOperaTab.cpp
Normal file
349
src/ui/keypair_details/KeyPairOperaTab.cpp
Normal file
@ -0,0 +1,349 @@
|
|||||||
|
/**
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* 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<eric@bktus.com><eric@bktus.com> starting on May 12, 2021.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "KeyPairOperaTab.h"
|
||||||
|
|
||||||
|
#include "gpg/function/GpgKeyImportExporter.h"
|
||||||
|
#include "gpg/function/GpgKeyOpera.h"
|
||||||
|
#include "ui/KeyUploadDialog.h"
|
||||||
|
#include "ui/SignalStation.h"
|
||||||
|
#include "ui/UserInterfaceUtils.h"
|
||||||
|
#include "ui/keypair_details/KeySetExpireDateDialog.h"
|
||||||
|
|
||||||
|
namespace GpgFrontend::UI {
|
||||||
|
|
||||||
|
KeyPairOperaTab::KeyPairOperaTab(const std::string& key_id, QWidget* parent)
|
||||||
|
: QWidget(parent), m_key_(GpgKeyGetter::GetInstance().GetKey(key_id)) {
|
||||||
|
// Set Menu
|
||||||
|
createOperaMenu();
|
||||||
|
auto m_vbox = new QVBoxLayout(this);
|
||||||
|
|
||||||
|
auto* opera_key_box = new QGroupBox(_("General Operations"));
|
||||||
|
auto* vbox_p_k = new QVBoxLayout();
|
||||||
|
|
||||||
|
auto export_h_box_layout = new QHBoxLayout();
|
||||||
|
vbox_p_k->addLayout(export_h_box_layout);
|
||||||
|
|
||||||
|
auto* export_public_button = new QPushButton(_("Export Public Key"));
|
||||||
|
export_h_box_layout->addWidget(export_public_button);
|
||||||
|
connect(export_public_button, SIGNAL(clicked()), this,
|
||||||
|
SLOT(slotExportPublicKey()));
|
||||||
|
|
||||||
|
if (m_key_.is_private_key()) {
|
||||||
|
auto* export_private_button = new QPushButton(_("Export Private Key"));
|
||||||
|
export_private_button->setStyleSheet("text-align:center;");
|
||||||
|
export_private_button->setMenu(secretKeyExportOperaMenu);
|
||||||
|
export_h_box_layout->addWidget(export_private_button);
|
||||||
|
|
||||||
|
if (m_key_.has_master_key()) {
|
||||||
|
auto* edit_expires_button =
|
||||||
|
new QPushButton(_("Modify Expiration Datetime (Primary Key)"));
|
||||||
|
connect(edit_expires_button, SIGNAL(clicked()), this,
|
||||||
|
SLOT(slotModifyEditDatetime()));
|
||||||
|
auto* edit_password_button = new QPushButton(_("Modify Password"));
|
||||||
|
connect(edit_password_button, SIGNAL(clicked()), this,
|
||||||
|
SLOT(slotModifyPassword()));
|
||||||
|
|
||||||
|
vbox_p_k->addWidget(edit_expires_button);
|
||||||
|
vbox_p_k->addWidget(edit_password_button);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto advance_h_box_layout = new QHBoxLayout();
|
||||||
|
auto* key_server_opera_button =
|
||||||
|
new QPushButton(_("Key Server Operation (Pubkey)"));
|
||||||
|
key_server_opera_button->setStyleSheet("text-align:center;");
|
||||||
|
key_server_opera_button->setMenu(keyServerOperaMenu);
|
||||||
|
advance_h_box_layout->addWidget(key_server_opera_button);
|
||||||
|
|
||||||
|
if (m_key_.is_private_key() && m_key_.has_master_key()) {
|
||||||
|
auto* revoke_cert_gen_button =
|
||||||
|
new QPushButton(_("Generate Revoke Certificate"));
|
||||||
|
connect(revoke_cert_gen_button, SIGNAL(clicked()), this,
|
||||||
|
SLOT(slotGenRevokeCert()));
|
||||||
|
advance_h_box_layout->addWidget(revoke_cert_gen_button);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* modify_tofu_button = new QPushButton(_("Modify TOFU Policy"));
|
||||||
|
connect(modify_tofu_button, SIGNAL(clicked()), this,
|
||||||
|
SLOT(slotModifyTOFUPolicy()));
|
||||||
|
|
||||||
|
vbox_p_k->addLayout(advance_h_box_layout);
|
||||||
|
opera_key_box->setLayout(vbox_p_k);
|
||||||
|
m_vbox->addWidget(opera_key_box);
|
||||||
|
vbox_p_k->addWidget(modify_tofu_button);
|
||||||
|
m_vbox->addStretch(0);
|
||||||
|
|
||||||
|
setLayout(m_vbox);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyPairOperaTab::createOperaMenu() {
|
||||||
|
keyServerOperaMenu = new QMenu(this);
|
||||||
|
|
||||||
|
auto* uploadKeyPair = new QAction(_("Upload Key Pair to Key Server"), this);
|
||||||
|
connect(uploadKeyPair, SIGNAL(triggered()), this,
|
||||||
|
SLOT(slotUploadKeyToServer()));
|
||||||
|
if (!(m_key_.is_private_key() && m_key_.has_master_key()))
|
||||||
|
uploadKeyPair->setDisabled(true);
|
||||||
|
|
||||||
|
auto* updateKeyPair = new QAction(_("Sync Key Pair From Key Server"), this);
|
||||||
|
connect(updateKeyPair, SIGNAL(triggered()), this,
|
||||||
|
SLOT(slotUpdateKeyFromServer()));
|
||||||
|
|
||||||
|
// when a key has primary key, it should always upload to keyserver.
|
||||||
|
if (m_key_.has_master_key()) {
|
||||||
|
updateKeyPair->setDisabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
keyServerOperaMenu->addAction(uploadKeyPair);
|
||||||
|
keyServerOperaMenu->addAction(updateKeyPair);
|
||||||
|
|
||||||
|
secretKeyExportOperaMenu = new QMenu(this);
|
||||||
|
|
||||||
|
auto* exportFullSecretKey = new QAction(_("Export Full Secret Key"), this);
|
||||||
|
connect(exportFullSecretKey, SIGNAL(triggered()), this,
|
||||||
|
SLOT(slotExportPrivateKey()));
|
||||||
|
if (!m_key_.is_private_key()) exportFullSecretKey->setDisabled(true);
|
||||||
|
|
||||||
|
auto* exportShortestSecretKey =
|
||||||
|
new QAction(_("Export Shortest Secret Key"), this);
|
||||||
|
connect(exportShortestSecretKey, SIGNAL(triggered()), this,
|
||||||
|
SLOT(slotExportShortPrivateKey()));
|
||||||
|
|
||||||
|
secretKeyExportOperaMenu->addAction(exportFullSecretKey);
|
||||||
|
secretKeyExportOperaMenu->addAction(exportShortestSecretKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyPairOperaTab::slotExportPublicKey() {
|
||||||
|
ByteArrayPtr keyArray = nullptr;
|
||||||
|
|
||||||
|
if (!GpgKeyImportExporter::GetInstance().ExportKey(m_key_, keyArray)) {
|
||||||
|
QMessageBox::critical(this, _("Error"),
|
||||||
|
_("An error occurred during the export operation."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto file_string =
|
||||||
|
m_key_.name() + " " + m_key_.email() + "(" + m_key_.id() + ")_pub.asc";
|
||||||
|
auto file_name =
|
||||||
|
QFileDialog::getSaveFileName(
|
||||||
|
this, _("Export Key To File"), QString::fromStdString(file_string),
|
||||||
|
QString(_("Key Files")) + " (*.asc *.txt);;All Files (*)")
|
||||||
|
.toStdString();
|
||||||
|
|
||||||
|
if (file_name.empty()) return;
|
||||||
|
|
||||||
|
if (!write_buffer_to_file(file_name, *keyArray)) {
|
||||||
|
QMessageBox::critical(
|
||||||
|
this, _("Export Error"),
|
||||||
|
QString(_("Couldn't open %1 for writing")).arg(file_name.c_str()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyPairOperaTab::slotExportShortPrivateKey() {
|
||||||
|
// Show a information box with explanation about private key
|
||||||
|
int ret = QMessageBox::information(
|
||||||
|
this, _("Exporting short private Key"),
|
||||||
|
"<h3>" + QString(_("You are about to export your")) +
|
||||||
|
"<font color=\"red\">" + _(" PRIVATE KEY ") + "</font>!</h3>\n" +
|
||||||
|
_("This is NOT your Public Key, so DON'T give it away.") + "<br />" +
|
||||||
|
_("Do you REALLY want to export your PRIVATE KEY in a Minimum "
|
||||||
|
"Size?") +
|
||||||
|
"<br />" +
|
||||||
|
_("For OpenPGP keys it removes all signatures except for the latest "
|
||||||
|
"self-signatures."),
|
||||||
|
QMessageBox::Cancel | QMessageBox::Ok);
|
||||||
|
|
||||||
|
// export key, if ok was clicked
|
||||||
|
if (ret == QMessageBox::Ok) {
|
||||||
|
ByteArrayPtr keyArray = nullptr;
|
||||||
|
|
||||||
|
if (!GpgKeyImportExporter::GetInstance().ExportSecretKeyShortest(
|
||||||
|
m_key_, keyArray)) {
|
||||||
|
QMessageBox::critical(
|
||||||
|
this, _("Error"),
|
||||||
|
_("An error occurred during the export operation."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto file_string = m_key_.name() + " " + m_key_.email() + "(" +
|
||||||
|
m_key_.id() + ")_short_secret.asc";
|
||||||
|
auto file_name =
|
||||||
|
QFileDialog::getSaveFileName(
|
||||||
|
this, _("Export Key To File"), QString::fromStdString(file_string),
|
||||||
|
QString(_("Key Files")) + " (*.asc *.txt);;All Files (*)")
|
||||||
|
.toStdString();
|
||||||
|
|
||||||
|
if (file_name.empty()) return;
|
||||||
|
|
||||||
|
if (!write_buffer_to_file(file_name, *keyArray)) {
|
||||||
|
QMessageBox::critical(
|
||||||
|
this, _("Export Error"),
|
||||||
|
QString(_("Couldn't open %1 for writing")).arg(file_name.c_str()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyPairOperaTab::slotExportPrivateKey() {
|
||||||
|
// Show a information box with explanation about private key
|
||||||
|
int ret = QMessageBox::information(
|
||||||
|
this, _("Exporting private Key"),
|
||||||
|
"<h3>" + QString(_("You are about to export your")) +
|
||||||
|
"<font color=\"red\">" + _(" PRIVATE KEY ") + "</font>!</h3>\n" +
|
||||||
|
_("This is NOT your Public Key, so DON'T give it away.") + "<br />" +
|
||||||
|
_("Do you REALLY want to export your PRIVATE KEY?"),
|
||||||
|
QMessageBox::Cancel | QMessageBox::Ok);
|
||||||
|
|
||||||
|
// export key, if ok was clicked
|
||||||
|
if (ret == QMessageBox::Ok) {
|
||||||
|
ByteArrayPtr keyArray = nullptr;
|
||||||
|
|
||||||
|
if (!GpgKeyImportExporter::GetInstance().ExportSecretKey(m_key_,
|
||||||
|
keyArray)) {
|
||||||
|
QMessageBox::critical(
|
||||||
|
this, _("Error"),
|
||||||
|
_("An error occurred during the export operation."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto file_string = m_key_.name() + " " + m_key_.email() + "(" +
|
||||||
|
m_key_.id() + ")_full_secret.asc";
|
||||||
|
auto file_name =
|
||||||
|
QFileDialog::getSaveFileName(
|
||||||
|
this, _("Export Key To File"), QString::fromStdString(file_string),
|
||||||
|
QString(_("Key Files")) + " (*.asc *.txt);;All Files (*)")
|
||||||
|
.toStdString();
|
||||||
|
|
||||||
|
if (file_name.empty()) return;
|
||||||
|
|
||||||
|
if (!write_buffer_to_file(file_name, *keyArray)) {
|
||||||
|
QMessageBox::critical(
|
||||||
|
this, _("Export Error"),
|
||||||
|
QString(_("Couldn't open %1 for writing")).arg(file_name.c_str()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyPairOperaTab::slotModifyEditDatetime() {
|
||||||
|
auto dialog = new KeySetExpireDateDialog(m_key_.id(), this);
|
||||||
|
dialog->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyPairOperaTab::slotUploadKeyToServer() {
|
||||||
|
auto keys = std::make_unique<KeyIdArgsList>();
|
||||||
|
keys->push_back(m_key_.id());
|
||||||
|
auto* dialog = new KeyUploadDialog(keys, this);
|
||||||
|
dialog->show();
|
||||||
|
dialog->slotUpload();
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyPairOperaTab::slotUpdateKeyFromServer() {
|
||||||
|
auto keys = std::make_unique<KeyIdArgsList>();
|
||||||
|
keys->push_back(m_key_.id());
|
||||||
|
auto* dialog = new KeyServerImportDialog(this);
|
||||||
|
dialog->show();
|
||||||
|
dialog->slotImport(keys);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyPairOperaTab::slotGenRevokeCert() {
|
||||||
|
auto literal = QString("%1 (*.rev)").arg(_("Revocation Certificates"));
|
||||||
|
QString m_output_file_name;
|
||||||
|
|
||||||
|
QFileDialog dialog(this, "Generate revocation certificate", QString(),
|
||||||
|
literal);
|
||||||
|
dialog.setDefaultSuffix(".rev");
|
||||||
|
dialog.setAcceptMode(QFileDialog::AcceptSave);
|
||||||
|
|
||||||
|
if (dialog.exec()) m_output_file_name = dialog.selectedFiles().front();
|
||||||
|
|
||||||
|
if (!m_output_file_name.isEmpty())
|
||||||
|
CommonUtils::GetInstance()->slotExecuteGpgCommand(
|
||||||
|
{"--command-fd", "0", "--status-fd", "1", "--no-tty", "-o",
|
||||||
|
m_output_file_name, "--gen-revoke", m_key_.fpr().c_str()},
|
||||||
|
[](QProcess* proc) -> void {
|
||||||
|
// Code From Gpg4Win
|
||||||
|
while (proc->canReadLine()) {
|
||||||
|
const QString line = QString::fromUtf8(proc->readLine()).trimmed();
|
||||||
|
LOG(INFO) << "line" << line.toStdString();
|
||||||
|
if (line == QLatin1String("[GNUPG:] GET_BOOL gen_revoke.okay")) {
|
||||||
|
proc->write("y\n");
|
||||||
|
} else if (line == QLatin1String("[GNUPG:] GET_LINE "
|
||||||
|
"ask_revocation_reason.code")) {
|
||||||
|
proc->write("0\n");
|
||||||
|
} else if (line == QLatin1String("[GNUPG:] GET_LINE "
|
||||||
|
"ask_revocation_reason.text")) {
|
||||||
|
proc->write("\n");
|
||||||
|
} else if (line ==
|
||||||
|
QLatin1String(
|
||||||
|
"[GNUPG:] GET_BOOL openfile.overwrite.okay")) {
|
||||||
|
// We asked before
|
||||||
|
proc->write("y\n");
|
||||||
|
} else if (line == QLatin1String("[GNUPG:] GET_BOOL "
|
||||||
|
"ask_revocation_reason.okay")) {
|
||||||
|
proc->write("y\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyPairOperaTab::slotModifyPassword() {
|
||||||
|
auto err = GpgKeyOpera::GetInstance().ModifyPassword(m_key_);
|
||||||
|
if (check_gpg_error_2_err_code(err) != GPG_ERR_NO_ERROR) {
|
||||||
|
QMessageBox::critical(this, _("Not Successful"),
|
||||||
|
QString(_("Modify password not successfully.")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyPairOperaTab::slotModifyTOFUPolicy() {
|
||||||
|
QStringList items;
|
||||||
|
items << _("Policy Auto") << _("Policy Good") << _("Policy Bad")
|
||||||
|
<< _("Policy Ask") << _("Policy Unknown");
|
||||||
|
|
||||||
|
bool ok;
|
||||||
|
QString item = QInputDialog::getItem(
|
||||||
|
this, _("Modify TOFU Policy(Default is Auto)"),
|
||||||
|
_("Policy for the Key Pair:"), items, 0, false, &ok);
|
||||||
|
if (ok && !item.isEmpty()) {
|
||||||
|
LOG(INFO) << "selected policy" << item.toStdString();
|
||||||
|
gpgme_tofu_policy_t tofu_policy = GPGME_TOFU_POLICY_AUTO;
|
||||||
|
if (item == _("Policy Auto")) {
|
||||||
|
tofu_policy = GPGME_TOFU_POLICY_AUTO;
|
||||||
|
} else if (item == _("Policy Good")) {
|
||||||
|
tofu_policy = GPGME_TOFU_POLICY_GOOD;
|
||||||
|
} else if (item == _("Policy Bad")) {
|
||||||
|
tofu_policy = GPGME_TOFU_POLICY_BAD;
|
||||||
|
} else if (item == _("Policy Ask")) {
|
||||||
|
tofu_policy = GPGME_TOFU_POLICY_ASK;
|
||||||
|
} else if (item == _("Policy Unknown")) {
|
||||||
|
tofu_policy = GPGME_TOFU_POLICY_UNKNOWN;
|
||||||
|
}
|
||||||
|
auto err = GpgKeyOpera::GetInstance().ModifyTOFUPolicy(m_key_, tofu_policy);
|
||||||
|
if (check_gpg_error_2_err_code(err) != GPG_ERR_NO_ERROR) {
|
||||||
|
QMessageBox::critical(this, _("Not Successful"),
|
||||||
|
QString(_("Modify TOFU policy not successfully.")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace GpgFrontend::UI
|
69
src/ui/keypair_details/KeyPairOperaTab.h
Normal file
69
src/ui/keypair_details/KeyPairOperaTab.h
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/**
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* 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<eric@bktus.com><eric@bktus.com> starting on May 12, 2021.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GPGFRONTEND_KEYPAIROPERATAB_H
|
||||||
|
#define GPGFRONTEND_KEYPAIROPERATAB_H
|
||||||
|
|
||||||
|
#include "gpg/function/GpgKeyGetter.h"
|
||||||
|
#include "ui/GpgFrontendUI.h"
|
||||||
|
|
||||||
|
namespace GpgFrontend::UI {
|
||||||
|
class KeyPairOperaTab : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
KeyPairOperaTab(const std::string& key_id, QWidget* parent);
|
||||||
|
|
||||||
|
void createOperaMenu();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @details Export the key to a file, which is chosen in a file dialog
|
||||||
|
*/
|
||||||
|
void slotExportPrivateKey();
|
||||||
|
|
||||||
|
void slotExportShortPrivateKey();
|
||||||
|
|
||||||
|
void slotExportPublicKey();
|
||||||
|
|
||||||
|
void slotModifyEditDatetime();
|
||||||
|
|
||||||
|
void slotModifyPassword();
|
||||||
|
|
||||||
|
void slotUploadKeyToServer();
|
||||||
|
|
||||||
|
void slotUpdateKeyFromServer();
|
||||||
|
|
||||||
|
void slotGenRevokeCert();
|
||||||
|
|
||||||
|
void slotModifyTOFUPolicy();
|
||||||
|
|
||||||
|
private:
|
||||||
|
GpgKey m_key_;
|
||||||
|
QMenu* keyServerOperaMenu{};
|
||||||
|
QMenu* secretKeyExportOperaMenu{};
|
||||||
|
};
|
||||||
|
} // namespace GpgFrontend::UI
|
||||||
|
|
||||||
|
#endif // GPGFRONTEND_KEYPAIROPERATAB_H
|
Loading…
x
Reference in New Issue
Block a user