diff options
Diffstat (limited to 'src/ui/widgets')
-rw-r--r-- | src/ui/widgets/ExportKeyPackageDialog.cpp | 165 | ||||
-rw-r--r-- | src/ui/widgets/ExportKeyPackageDialog.h | 55 | ||||
-rw-r--r-- | src/ui/widgets/KeyList.cpp | 62 | ||||
-rw-r--r-- | src/ui/widgets/KeyList.h | 22 |
4 files changed, 298 insertions, 6 deletions
diff --git a/src/ui/widgets/ExportKeyPackageDialog.cpp b/src/ui/widgets/ExportKeyPackageDialog.cpp new file mode 100644 index 00000000..b5eea82d --- /dev/null +++ b/src/ui/widgets/ExportKeyPackageDialog.cpp @@ -0,0 +1,165 @@ +/** + * 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<[email protected]> starting on May 12, 2021. + * + */ + +#include "ExportKeyPackageDialog.h" + +#include <boost/format.hpp> + +#include "gpg/function/GpgKeyGetter.h" +#include "gpg/function/GpgKeyImportExporter.h" +#include "ui/aes/qaesencryption.h" +#include "ui_ExportKeyPackageDialog.h" + +GpgFrontend::UI::ExportKeyPackageDialog::ExportKeyPackageDialog( + KeyIdArgsListPtr key_ids, QWidget* parent) + : QDialog(parent), + ui(std::make_shared<Ui_exportKeyPackageDialog>()), + key_ids_(std::move(key_ids)), + mt(rd()) { + ui->setupUi(this); + + generate_key_package_name(); + + connect(ui->gnerateNameButton, &QPushButton::clicked, this, + [=]() { generate_key_package_name(); }); + + connect(ui->setOutputPathButton, &QPushButton::clicked, this, [=]() { + auto file_name = QFileDialog::getSaveFileName( + this, _("Export Key Package"), ui->nameValueLabel->text() + ".gfepack", + QString(_("Key Package")) + " (*.gfepack);;All Files (*)"); + ui->outputPathLabel->setText(file_name); + }); + + connect(ui->generatePassphraseButton, &QPushButton::clicked, this, [=]() { + passphrase_ = generate_passphrase(32); + auto file_name = QFileDialog::getSaveFileName( + this, _("Export Key Package Passphrase"), + ui->nameValueLabel->text() + ".key", + QString(_("Key File")) + " (*.key);;All Files (*)"); + ui->passphraseValueLabel->setText(file_name); + write_buffer_to_file(file_name.toStdString(), passphrase_); + }); + + connect(ui->buttonBox, &QDialogButtonBox::accepted, this, [=]() { + if (ui->outputPathLabel->text().isEmpty()) { + QMessageBox::critical( + nullptr, _("Forbidden"), + _("Please select an output path before exporting.")); + return; + } + + if (ui->passphraseValueLabel->text().isEmpty()) { + QMessageBox::critical( + nullptr, _("Forbidden"), + _("Please generate a password to protect your key before exporting, " + "it is very important. Don't forget to back up your password in a " + "safe place.")); + return; + } + auto key_id_exported = std::make_unique<KeyIdArgsList>(); + auto keys = GpgKeyGetter::GetInstance().GetKeys(key_ids_); + for (const auto& key : *keys) { + if (ui->noPublicKeyCheckBox->isChecked() && !key.is_private_key()) { + continue; + } + key_id_exported->push_back(key.id()); + } + + ByteArrayPtr key_export_data = nullptr; + if (!GpgKeyImportExporter::GetInstance().ExportKeys( + key_ids_, key_export_data, + ui->includeSecretKeyCheckBox->isChecked())) { + QMessageBox::critical(nullptr, _("Error"), _("Export Key(s) Failed.")); + this->close(); + return; + } + + auto key = passphrase_; + + QAESEncryption encryption(QAESEncryption::AES_256, QAESEncryption::ECB); + auto encoded = encryption.encode(key_export_data->data(), key.data()); + + write_buffer_to_file(ui->outputPathLabel->text().toStdString(), + encoded.toStdString()); + + QMessageBox::information( + this, _("Success"), + QString(_( + "The Key Package has been successfully generated and has been " + "protected by encryption algorithms. You can safely transfer your " + "Key Package.")) + + "<b>" + + _("But the key file cannot be leaked under any " + "circumstances. Please delete the Key Package and key file as " + "soon " + "as possible after completing the transfer operation") + + "</b>"); + }); + + connect(ui->buttonBox, &QDialogButtonBox::rejected, this, + [=]() { this->close(); }); + + ui->nameLabel->setText(_("Key Package Name")); + ui->selectOutputPathLabel->setText(_("Output Path")); + ui->passphraseLabel->setText(_("Passphrase")); + ui->tipsLabel->setText( + _("Tips: You can use Key Package to safely and conveniently transfer " + "your public and private keys between devices.")); + ui->generatePassphraseButton->setText(_("Generate and Save Passphrase")); + ui->gnerateNameButton->setText(_("Generate Key Package Name")); + ui->setOutputPathButton->setText(_("Select Output Path")); + + ui->includeSecretKeyCheckBox->setText( + _("Include secret key (Think twice before acting)")); + ui->noPublicKeyCheckBox->setText( + _("Exclude keys that do not have a private key")); + + setAttribute(Qt::WA_DeleteOnClose); + setWindowTitle(_("exportKeyPackageDialog")); +} + +std::string GpgFrontend::UI::ExportKeyPackageDialog::generate_passphrase( + const int len) { + std::uniform_int_distribution<int> dist(999, 99999); + static const char alphanum[] = + "0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz"; + std::string tmp_str; + tmp_str.reserve(len); + + for (int i = 0; i < len; ++i) { + tmp_str += alphanum[dist(mt) % (sizeof(alphanum) - 1)]; + } + + return tmp_str; +} + +void GpgFrontend::UI::ExportKeyPackageDialog::generate_key_package_name() { + std::uniform_int_distribution<int> dist(999, 99999); + auto file_string = boost::format("KeyPackage_%1%") % dist(mt); + ui->nameValueLabel->setText(file_string.str().c_str()); + ui->outputPathLabel->clear(); + ui->passphraseValueLabel->clear(); +} diff --git a/src/ui/widgets/ExportKeyPackageDialog.h b/src/ui/widgets/ExportKeyPackageDialog.h new file mode 100644 index 00000000..a254b453 --- /dev/null +++ b/src/ui/widgets/ExportKeyPackageDialog.h @@ -0,0 +1,55 @@ +/** + * 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<[email protected]> starting on May 12, 2021. + * + */ + +#ifndef GPGFRONTEND_EXPORTKEYPACKAGEDIALOG_H +#define GPGFRONTEND_EXPORTKEYPACKAGEDIALOG_H + +#include "GpgFrontendUI.h" + +class Ui_exportKeyPackageDialog; + +namespace GpgFrontend::UI { + +class ExportKeyPackageDialog : public QDialog { + Q_OBJECT + + public: + explicit ExportKeyPackageDialog(KeyIdArgsListPtr key_ids, QWidget* parent); + + std::string generate_passphrase(const int len); + + private: + std::shared_ptr<Ui_exportKeyPackageDialog> ui; + KeyIdArgsListPtr key_ids_; + + std::random_device rd; + std::mt19937 mt; + + std::string passphrase_; + + void generate_key_package_name(); +}; +} // namespace GpgFrontend::UI + +#endif // GPGFRONTEND_EXPORTKEYPACKAGEDIALOG_H diff --git a/src/ui/widgets/KeyList.cpp b/src/ui/widgets/KeyList.cpp index 6dec19e7..02a8dd92 100644 --- a/src/ui/widgets/KeyList.cpp +++ b/src/ui/widgets/KeyList.cpp @@ -38,11 +38,11 @@ namespace GpgFrontend::UI { int KeyList::key_list_id = 2048; -KeyList::KeyList(bool menu, QWidget* parent) +KeyList::KeyList(KeyMenuAbility::AbilityType menu_ability, QWidget* parent) : QWidget(parent), _m_key_list_id(key_list_id++), ui(std::make_shared<Ui_KeyList>()), - menu_status(menu) { + menu_ability_(menu_ability) { init(); } @@ -62,7 +62,11 @@ void KeyList::init() { ui->setupUi(this); - ui->menuWidget->setHidden(!menu_status); + ui->menuWidget->setHidden(!menu_ability_); + ui->refreshKeyListButton->setHidden(~menu_ability_ & KeyMenuAbility::REFRESH); + ui->syncButton->setHidden(~menu_ability_ & KeyMenuAbility::SYNC_PUBLIC_KEY); + ui->uncheckButton->setHidden(~menu_ability_ & KeyMenuAbility::UNCHECK_ALL); + ui->keyGroupTab->clear(); popupMenu = new QMenu(this); @@ -73,6 +77,10 @@ void KeyList::init() { SLOT(slotRefresh())); connect(ui->refreshKeyListButton, &QPushButton::clicked, this, &KeyList::slotRefresh); + connect(ui->uncheckButton, &QPushButton::clicked, this, + &KeyList::slotUncheckALL); + connect(ui->checkALLButton, &QPushButton::clicked, this, + &KeyList::slotCheckALL); connect(ui->syncButton, &QPushButton::clicked, this, &KeyList::slotSyncWithKeyServer); connect(this, &KeyList::signalRefreshStatusBar, SignalStation::GetInstance(), @@ -81,8 +89,16 @@ void KeyList::init() { setAcceptDrops(true); ui->refreshKeyListButton->setText(_("Refresh")); + ui->refreshKeyListButton->setToolTip( + _("Refresh the key list to synchronize changes.")); ui->syncButton->setText(_("Sync Public Key")); - ui->syncButton->setToolTip(_("Sync public key with your default keyserver")); + ui->syncButton->setToolTip(_("Sync public key with your default keyserver.")); + ui->uncheckButton->setText(_("Uncheck ALL")); + ui->uncheckButton->setToolTip( + _("Cancel all checked items in the current tab at once.")); + ui->checkALLButton->setText(_("Check ALL")); + ui->checkALLButton->setToolTip( + _("Check all items in the current tab at once")); } void KeyList::addListGroupTab( @@ -457,6 +473,32 @@ void KeyList::slotSyncWithKeyServer() { }); } +void KeyList::slotUncheckALL() { + auto key_list = qobject_cast<QTableWidget*>(ui->keyGroupTab->currentWidget()); + if (key_list == nullptr) return; + if (!mKeyTables.empty()) { + for (auto& key_table : mKeyTables) { + if (key_table.key_list == key_list) { + key_table.UncheckALL(); + break; + } + } + } +} + +void KeyList::slotCheckALL() { + auto key_list = qobject_cast<QTableWidget*>(ui->keyGroupTab->currentWidget()); + if (key_list == nullptr) return; + if (!mKeyTables.empty()) { + for (auto& key_table : mKeyTables) { + if (key_table.key_list == key_list) { + key_table.CheckALL(); + break; + } + } + } +} + KeyIdArgsListPtr& KeyTable::GetChecked() { LOG(INFO) << "called"; if (checked_key_ids_ == nullptr) @@ -597,4 +639,16 @@ void KeyTable::Refresh(KeyLinkListPtr m_keys) { LOG(INFO) << "End"; } + +void KeyTable::UncheckALL() const { + for (int i = 0; i < key_list->rowCount(); i++) { + key_list->item(i, 0)->setCheckState(Qt::Unchecked); + } +} + +void KeyTable::CheckALL() const { + for (int i = 0; i < key_list->rowCount(); i++) { + key_list->item(i, 0)->setCheckState(Qt::Checked); + } +} } // namespace GpgFrontend::UI diff --git a/src/ui/widgets/KeyList.h b/src/ui/widgets/KeyList.h index 8d6fb600..4b41decd 100644 --- a/src/ui/widgets/KeyList.h +++ b/src/ui/widgets/KeyList.h @@ -53,6 +53,17 @@ struct KeyListColumn { static constexpr InfoType FingerPrint = 1 << 5; }; +struct KeyMenuAbility { + using AbilityType = unsigned int; + + static constexpr AbilityType ALL = ~0; + static constexpr AbilityType NONE = 0; + static constexpr AbilityType REFRESH = 1 << 0; + static constexpr AbilityType SYNC_PUBLIC_KEY = 1 << 1; + static constexpr AbilityType UNCHECK_ALL = 1 << 3; + static constexpr AbilityType CHECK_ALL = 1 << 5; +}; + struct KeyTable { QTableWidget* key_list; KeyListRow::KeyType select_type; @@ -76,6 +87,10 @@ struct KeyTable { KeyIdArgsListPtr& GetChecked(); + void UncheckALL() const; + + void CheckALL() const; + void SetChecked(KeyIdArgsListPtr key_ids); }; @@ -83,7 +98,8 @@ class KeyList : public QWidget { Q_OBJECT public: - explicit KeyList(bool menu, QWidget* parent = nullptr); + explicit KeyList(KeyMenuAbility::AbilityType menu_ability, + QWidget* parent = nullptr); void addListGroupTab( const QString& name, @@ -124,6 +140,8 @@ class KeyList : public QWidget { private: void init(); void importKeys(const QByteArray& inBuffer); + void slotUncheckALL(); + void slotCheckALL(); static int key_list_id; int _m_key_list_id; @@ -135,7 +153,7 @@ class KeyList : public QWidget { QMenu* popupMenu{}; GpgFrontend::KeyLinkListPtr _buffered_keys_list; std::function<void(const GpgKey&, QWidget*)> mAction = nullptr; - bool menu_status = false; + KeyMenuAbility::AbilityType menu_ability_ = KeyMenuAbility::ALL; private slots: |