aboutsummaryrefslogtreecommitdiffstats
path: root/src/ui/dialog/import_export
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/dialog/import_export')
-rw-r--r--src/ui/dialog/import_export/ExportKeyPackageDialog.cpp145
-rw-r--r--src/ui/dialog/import_export/ExportKeyPackageDialog.h62
-rw-r--r--src/ui/dialog/import_export/KeyImportDetailDialog.cpp204
-rw-r--r--src/ui/dialog/import_export/KeyImportDetailDialog.h92
-rw-r--r--src/ui/dialog/import_export/KeyServerImportDialog.cpp550
-rw-r--r--src/ui/dialog/import_export/KeyServerImportDialog.h182
-rw-r--r--src/ui/dialog/import_export/KeyUploadDialog.cpp159
-rw-r--r--src/ui/dialog/import_export/KeyUploadDialog.h83
8 files changed, 1477 insertions, 0 deletions
diff --git a/src/ui/dialog/import_export/ExportKeyPackageDialog.cpp b/src/ui/dialog/import_export/ExportKeyPackageDialog.cpp
new file mode 100644
index 00000000..312cd946
--- /dev/null
+++ b/src/ui/dialog/import_export/ExportKeyPackageDialog.cpp
@@ -0,0 +1,145 @@
+/**
+ * Copyright (C) 2021 Saturneric
+ *
+ * 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.
+ *
+ * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * The initial version of the source code is inherited from
+ * the gpg4usb project, which is under GPL-3.0-or-later.
+ *
+ * All the source code of GpgFrontend was modified and released by
+ * Saturneric<[email protected]> starting on May 12, 2021.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#include "ExportKeyPackageDialog.h"
+
+#include <boost/format.hpp>
+
+#include "core/function/KeyPackageOperator.h"
+#include "core/function/gpg/GpgKeyGetter.h"
+#include "ui_ExportKeyPackageDialog.h"
+
+GpgFrontend::UI::ExportKeyPackageDialog::ExportKeyPackageDialog(
+ KeyIdArgsListPtr key_ids, QWidget* parent)
+ : GeneralDialog(typeid(ExportKeyPackageDialog).name(), parent),
+ ui_(std::make_shared<Ui_exportKeyPackageDialog>()),
+ key_ids_(std::move(key_ids)) {
+ ui_->setupUi(this);
+
+ ui_->nameValueLabel->setText(
+ KeyPackageOperator::GenerateKeyPackageName().c_str());
+
+ connect(ui_->gnerateNameButton, &QPushButton::clicked, this, [=]() {
+ ui_->nameValueLabel->setText(
+ KeyPackageOperator::GenerateKeyPackageName().c_str());
+ });
+
+ 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, [=]() {
+ auto file_name = QFileDialog::getSaveFileName(
+ this, _("Export Key Package Passphrase"),
+ ui_->nameValueLabel->text() + ".key",
+ QString(_("Key File")) + " (*.key);;All Files (*)");
+
+ if (!KeyPackageOperator::GeneratePassphrase(file_name.toStdString(),
+ passphrase_)) {
+ QMessageBox::critical(
+ this, _("Error"),
+ _("An error occurred while generating the passphrase file."));
+ return;
+ }
+ ui_->passphraseValueLabel->setText(file_name);
+ });
+
+ connect(ui_->button_box_, &QDialogButtonBox::accepted, this, [=]() {
+ if (ui_->outputPathLabel->text().isEmpty()) {
+ QMessageBox::critical(
+ this, _("Forbidden"),
+ _("Please select an output path before exporting."));
+ return;
+ }
+
+ if (ui_->passphraseValueLabel->text().isEmpty()) {
+ QMessageBox::critical(
+ this, _("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;
+ }
+
+ // get suitable key ids
+ 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.IsPrivateKey())
+ continue;
+ key_id_exported->push_back(key.GetId());
+ }
+
+ if (KeyPackageOperator::GenerateKeyPackage(
+ ui_->outputPathLabel->text().toStdString(),
+ ui_->nameValueLabel->text().toStdString(), key_id_exported,
+ passphrase_, ui_->includeSecretKeyCheckBox->isChecked())) {
+ QMessageBox::information(
+ this, _("Success"),
+ QString(
+ _("The Key Package has been successfully generated and has been "
+ "protected by encryption algorithms(AES-256-ECB). You can "
+ "safely transfer your Key Package.")) +
+ "<br /><br />" + "<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>");
+ accept();
+ } else {
+ QMessageBox::critical(
+ this, _("Error"),
+ _("An error occurred while exporting the key package."));
+ }
+ });
+
+ connect(ui_->button_box_, &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(_("Export As Key Package"));
+}
diff --git a/src/ui/dialog/import_export/ExportKeyPackageDialog.h b/src/ui/dialog/import_export/ExportKeyPackageDialog.h
new file mode 100644
index 00000000..c5f9a2b1
--- /dev/null
+++ b/src/ui/dialog/import_export/ExportKeyPackageDialog.h
@@ -0,0 +1,62 @@
+/**
+ * Copyright (C) 2021 Saturneric
+ *
+ * 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.
+ *
+ * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * The initial version of the source code is inherited from
+ * the gpg4usb project, which is under GPL-3.0-or-later.
+ *
+ * All the source code of GpgFrontend was modified and released by
+ * Saturneric<[email protected]> starting on May 12, 2021.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#ifndef GPGFRONTEND_EXPORTKEYPACKAGEDIALOG_H
+#define GPGFRONTEND_EXPORTKEYPACKAGEDIALOG_H
+
+#include "GpgFrontendUI.h"
+#include "ui/dialog/GeneralDialog.h"
+
+class Ui_exportKeyPackageDialog;
+
+namespace GpgFrontend::UI {
+
+/**
+ * @brief
+ *
+ */
+class ExportKeyPackageDialog : public GeneralDialog {
+ Q_OBJECT
+
+ public:
+ /**
+ * @brief Construct a new Export Key Package Dialog object
+ *
+ * @param key_ids
+ * @param parent
+ */
+ explicit ExportKeyPackageDialog(KeyIdArgsListPtr key_ids, QWidget* parent);
+
+ private:
+ std::shared_ptr<Ui_exportKeyPackageDialog> ui_; ///<
+ KeyIdArgsListPtr key_ids_; ///<
+ std::string passphrase_; ///<
+};
+} // namespace GpgFrontend::UI
+
+#endif // GPGFRONTEND_EXPORTKEYPACKAGEDIALOG_H
diff --git a/src/ui/dialog/import_export/KeyImportDetailDialog.cpp b/src/ui/dialog/import_export/KeyImportDetailDialog.cpp
new file mode 100644
index 00000000..31183a34
--- /dev/null
+++ b/src/ui/dialog/import_export/KeyImportDetailDialog.cpp
@@ -0,0 +1,204 @@
+/**
+ * Copyright (C) 2021 Saturneric
+ *
+ * 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.
+ *
+ * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * The initial version of the source code is inherited from
+ * the gpg4usb project, which is under GPL-3.0-or-later.
+ *
+ * All the source code of GpgFrontend was modified and released by
+ * Saturneric<[email protected]> starting on May 12, 2021.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#include "KeyImportDetailDialog.h"
+
+#include "core/function/gpg/GpgKeyGetter.h"
+
+namespace GpgFrontend::UI {
+KeyImportDetailDialog::KeyImportDetailDialog(GpgImportInformation result,
+ bool automatic, QWidget* parent)
+ : GeneralDialog(typeid(KeyImportDetailDialog).name(), parent),
+ m_result_(std::move(result)) {
+ // If no key for import found, just show a message
+ if (m_result_.considered == 0) {
+ if (automatic)
+ QMessageBox::information(parent, _("Key Update Details"),
+ _("No keys found"));
+ else
+ QMessageBox::information(parent, _("Key Import Details"),
+ _("No keys found to import"));
+ emit finished(0);
+ this->close();
+ this->deleteLater();
+ } else {
+ auto* mv_box = new QVBoxLayout();
+
+ this->create_general_info_box();
+ mv_box->addWidget(general_info_box_);
+ this->create_keys_table();
+ mv_box->addWidget(keys_table_);
+ this->create_button_box();
+ mv_box->addWidget(button_box_);
+
+ this->setLayout(mv_box);
+ if (automatic)
+ this->setWindowTitle(_("Key Update Details"));
+ else
+ this->setWindowTitle(_("Key Import Details"));
+
+ auto pos = QPoint(100, 100);
+ if (parent) pos += parent->pos();
+ this->move(pos);
+
+ this->setMinimumSize(QSize(600, 300));
+ this->adjustSize();
+
+ this->setModal(true);
+ this->show();
+ }
+}
+
+void KeyImportDetailDialog::create_general_info_box() {
+ // GridBox for general import information
+ general_info_box_ = new QGroupBox(_("General key info"));
+ auto* generalInfoBoxLayout = new QGridLayout(general_info_box_);
+
+ generalInfoBoxLayout->addWidget(new QLabel(QString(_("Considered")) + ": "),
+ 1, 0);
+ generalInfoBoxLayout->addWidget(
+ new QLabel(QString::number(m_result_.considered)), 1, 1);
+ int row = 2;
+ if (m_result_.unchanged != 0) {
+ generalInfoBoxLayout->addWidget(
+ new QLabel(QString(_("Public unchanged")) + ": "), row, 0);
+ generalInfoBoxLayout->addWidget(
+ new QLabel(QString::number(m_result_.unchanged)), row, 1);
+ row++;
+ }
+ if (m_result_.imported != 0) {
+ generalInfoBoxLayout->addWidget(new QLabel(QString(_("Imported")) + ": "),
+ row, 0);
+ generalInfoBoxLayout->addWidget(
+ new QLabel(QString::number(m_result_.imported)), row, 1);
+ row++;
+ }
+ if (m_result_.not_imported != 0) {
+ generalInfoBoxLayout->addWidget(
+ new QLabel(QString(_("Not Imported")) + ": "), row, 0);
+ generalInfoBoxLayout->addWidget(
+ new QLabel(QString::number(m_result_.not_imported)), row, 1);
+ row++;
+ }
+ if (m_result_.secret_read != 0) {
+ generalInfoBoxLayout->addWidget(
+ new QLabel(QString(_("Private Read")) + ": "), row, 0);
+ generalInfoBoxLayout->addWidget(
+ new QLabel(QString::number(m_result_.secret_read)), row, 1);
+ row++;
+ }
+ if (m_result_.secret_imported != 0) {
+ generalInfoBoxLayout->addWidget(
+ new QLabel(QString(_("Private Imported")) + ": "), row, 0);
+ generalInfoBoxLayout->addWidget(
+ new QLabel(QString::number(m_result_.secret_imported)), row, 1);
+ row++;
+ }
+ if (m_result_.secret_unchanged != 0) {
+ generalInfoBoxLayout->addWidget(
+ new QLabel(QString(_("Private Unchanged")) + ": "), row, 0);
+ generalInfoBoxLayout->addWidget(
+ new QLabel(QString::number(m_result_.secret_unchanged)), row, 1);
+ row++;
+ }
+}
+
+void KeyImportDetailDialog::create_keys_table() {
+ LOG(INFO) << "KeyImportDetailDialog::create_keys_table() Called";
+
+ keys_table_ = new QTableWidget(this);
+ keys_table_->setRowCount(0);
+ keys_table_->setColumnCount(4);
+ keys_table_->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ // Nothing is selectable
+ keys_table_->setSelectionMode(QAbstractItemView::NoSelection);
+
+ QStringList headerLabels;
+ headerLabels << _("Name") << _("Email") << _("Status") << _("Fingerprint");
+ keys_table_->verticalHeader()->hide();
+
+ keys_table_->setHorizontalHeaderLabels(headerLabels);
+ int row = 0;
+ for (const auto& imp_key : m_result_.importedKeys) {
+ keys_table_->setRowCount(row + 1);
+ GpgKey key = GpgKeyGetter::GetInstance().GetKey(imp_key.fpr);
+ if (!key.IsGood()) continue;
+ keys_table_->setItem(
+ row, 0, new QTableWidgetItem(QString::fromStdString(key.GetName())));
+ keys_table_->setItem(
+ row, 1, new QTableWidgetItem(QString::fromStdString(key.GetEmail())));
+ keys_table_->setItem(
+ row, 2, new QTableWidgetItem(get_status_string(imp_key.import_status)));
+ keys_table_->setItem(
+ row, 3, new QTableWidgetItem(QString::fromStdString(imp_key.fpr)));
+ row++;
+ }
+ keys_table_->horizontalHeader()->setSectionResizeMode(
+ 0, QHeaderView::ResizeToContents);
+ keys_table_->horizontalHeader()->setStretchLastSection(true);
+ keys_table_->resizeColumnsToContents();
+}
+
+QString KeyImportDetailDialog::get_status_string(int keyStatus) {
+ QString statusString;
+ // keystatus is greater than 15, if key is private
+ if (keyStatus > 15) {
+ statusString.append(_("Private"));
+ keyStatus = keyStatus - 16;
+ } else {
+ statusString.append(_("Public"));
+ }
+ if (keyStatus == 0) {
+ statusString.append(", " + QString(_("Unchanged")));
+ } else {
+ if (keyStatus == 1) {
+ statusString.append(", " + QString(_("New Key")));
+ } else {
+ if (keyStatus > 7) {
+ statusString.append(", " + QString(_("New Subkey")));
+ keyStatus = keyStatus - 8;
+ }
+ if (keyStatus > 3) {
+ statusString.append(", " + QString(_("New Signature")));
+ keyStatus = keyStatus - 4;
+ }
+ if (keyStatus > 1) {
+ statusString.append(", " + QString(_("New UID")));
+ keyStatus = keyStatus - 2;
+ }
+ }
+ }
+ return statusString;
+}
+
+void KeyImportDetailDialog::create_button_box() {
+ button_box_ = new QDialogButtonBox(QDialogButtonBox::Ok);
+ connect(button_box_, &QDialogButtonBox::accepted, this,
+ &KeyImportDetailDialog::close);
+}
+} // namespace GpgFrontend::UI
diff --git a/src/ui/dialog/import_export/KeyImportDetailDialog.h b/src/ui/dialog/import_export/KeyImportDetailDialog.h
new file mode 100644
index 00000000..06f44e94
--- /dev/null
+++ b/src/ui/dialog/import_export/KeyImportDetailDialog.h
@@ -0,0 +1,92 @@
+/**
+ * Copyright (C) 2021 Saturneric
+ *
+ * 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.
+ *
+ * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * The initial version of the source code is inherited from
+ * the gpg4usb project, which is under GPL-3.0-or-later.
+ *
+ * All the source code of GpgFrontend was modified and released by
+ * Saturneric<[email protected]> starting on May 12, 2021.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#ifndef __KEYIMPORTDETAILSDIALOG_H__
+#define __KEYIMPORTDETAILSDIALOG_H__
+
+#include "core/GpgContext.h"
+#include "core/function/gpg/GpgKeyImportExporter.h"
+#include "ui/GpgFrontendUI.h"
+#include "ui/dialog/GeneralDialog.h"
+
+namespace GpgFrontend::UI {
+
+/**
+ * @brief
+ *
+ */
+class KeyImportDetailDialog : public GeneralDialog {
+ Q_OBJECT
+
+ public:
+ /**
+ * @brief Construct a new Key Import Detail Dialog object
+ *
+ * @param result
+ * @param automatic
+ * @param parent
+ */
+ KeyImportDetailDialog(GpgImportInformation result, bool automatic,
+ QWidget* parent = nullptr);
+
+ private:
+ /**
+ * @brief Create a general info box object
+ *
+ */
+ void create_general_info_box();
+
+ /**
+ * @brief Create a keys table object
+ *
+ */
+ void create_keys_table();
+
+ /**
+ * @brief Create a button box object
+ *
+ */
+ void create_button_box();
+
+ /**
+ * @brief Get the status string object
+ *
+ * @param keyStatus
+ * @return QString
+ */
+ static QString get_status_string(int keyStatus);
+
+ QTableWidget* keys_table_{}; ///<
+ QGroupBox* general_info_box_{}; ///<
+ QGroupBox* key_info_box_{}; ///<
+ QDialogButtonBox* button_box_{}; ///<
+ GpgImportInformation m_result_; ///<
+};
+} // namespace GpgFrontend::UI
+
+#endif // __KEYIMPORTDETAILSDIALOG_H__
diff --git a/src/ui/dialog/import_export/KeyServerImportDialog.cpp b/src/ui/dialog/import_export/KeyServerImportDialog.cpp
new file mode 100644
index 00000000..6430a22e
--- /dev/null
+++ b/src/ui/dialog/import_export/KeyServerImportDialog.cpp
@@ -0,0 +1,550 @@
+/**
+ * Copyright (C) 2021 Saturneric
+ *
+ * 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.
+ *
+ * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * The initial version of the source code is inherited from
+ * the gpg4usb project, which is under GPL-3.0-or-later.
+ *
+ * All the source code of GpgFrontend was modified and released by
+ * Saturneric<[email protected]> starting on May 12, 2021.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#include "KeyServerImportDialog.h"
+
+#include <string>
+#include <utility>
+
+#include "core/function/GlobalSettingStation.h"
+#include "core/function/gpg/GpgKeyImportExporter.h"
+#include "thread/KeyServerImportTask.h"
+#include "ui/SignalStation.h"
+#include "ui/struct/SettingsObject.h"
+#include "ui/thread/KeyServerSearchTask.h"
+
+namespace GpgFrontend::UI {
+
+KeyServerImportDialog::KeyServerImportDialog(bool automatic, QWidget* parent)
+ : GeneralDialog("key_server_import_dialog", parent),
+ m_automatic_(automatic) {
+ // Layout for messagebox
+ auto* message_layout = new QHBoxLayout();
+
+ if (automatic) {
+ setWindowFlags(Qt::Window | Qt::WindowTitleHint | Qt::CustomizeWindowHint);
+ } else {
+ // Buttons
+
+ close_button_ = new QPushButton(_("Close"));
+ connect(close_button_, &QPushButton::clicked, this,
+ &KeyServerImportDialog::close);
+ import_button_ = new QPushButton(_("Import ALL"));
+ connect(import_button_, &QPushButton::clicked, this,
+ &KeyServerImportDialog::slot_import);
+ import_button_->setDisabled(true);
+ search_button_ = new QPushButton(_("Search"));
+ connect(search_button_, &QPushButton::clicked, this,
+ &KeyServerImportDialog::slot_search);
+
+ // Line edits for search string
+ search_label_ = new QLabel(QString(_("Search String")) + _(": "));
+ search_line_edit_ = new QLineEdit();
+
+ // combobox for keyserver list
+ key_server_label_ = new QLabel(QString(_("Key Server")) + _(": "));
+ key_server_combo_box_ = create_comboBox();
+
+ // table containing the keys found
+ create_keys_table();
+ message_ = new QLabel();
+ message_->setFixedHeight(24);
+ icon_ = new QLabel();
+ icon_->setFixedHeight(24);
+
+ message_layout->addWidget(icon_);
+ message_layout->addWidget(message_);
+ message_layout->addStretch();
+ }
+
+ // Network Waiting
+ waiting_bar_ = new QProgressBar();
+ waiting_bar_->setVisible(false);
+ waiting_bar_->setRange(0, 0);
+ waiting_bar_->setFixedWidth(200);
+ message_layout->addWidget(waiting_bar_);
+
+ auto* mainLayout = new QGridLayout;
+
+ // 自动化调用界面布局
+ if (automatic) {
+ mainLayout->addLayout(message_layout, 0, 0, 1, 3);
+ } else {
+ mainLayout->addWidget(search_label_, 1, 0);
+ mainLayout->addWidget(search_line_edit_, 1, 1);
+ mainLayout->addWidget(search_button_, 1, 2);
+ mainLayout->addWidget(key_server_label_, 2, 0);
+ mainLayout->addWidget(key_server_combo_box_, 2, 1);
+ mainLayout->addWidget(keys_table_, 3, 0, 1, 3);
+ mainLayout->addLayout(message_layout, 4, 0, 1, 3);
+
+ // Layout for import and close button
+ auto* buttonsLayout = new QHBoxLayout;
+ buttonsLayout->addStretch();
+ buttonsLayout->addWidget(import_button_);
+ buttonsLayout->addWidget(close_button_);
+ mainLayout->addLayout(buttonsLayout, 6, 0, 1, 3);
+ }
+
+ this->setLayout(mainLayout);
+ if (automatic)
+ this->setWindowTitle(_("Update Keys from Keyserver"));
+ else
+ this->setWindowTitle(_("Import Keys from Keyserver"));
+
+ if (automatic) {
+ this->setFixedSize(240, 42);
+ }
+
+ this->setModal(true);
+
+ connect(this, &KeyServerImportDialog::SignalKeyImported,
+ SignalStation::GetInstance(),
+ &SignalStation::SignalKeyDatabaseRefresh);
+}
+
+KeyServerImportDialog::KeyServerImportDialog(QWidget* parent)
+ : GeneralDialog("key_server_import_dialog", parent), m_automatic_(true) {
+ setWindowFlags(Qt::Window | Qt::WindowTitleHint | Qt::CustomizeWindowHint);
+
+ // Network Waiting
+ waiting_bar_ = new QProgressBar();
+ waiting_bar_->setVisible(false);
+ waiting_bar_->setRange(0, 0);
+ waiting_bar_->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ waiting_bar_->setTextVisible(false);
+
+ // Layout for messagebox
+ auto* layout = new QHBoxLayout();
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+ layout->addWidget(waiting_bar_);
+
+ key_server_combo_box_ = create_comboBox();
+
+ this->setLayout(layout);
+ this->setWindowTitle(_("Update Keys from Keyserver"));
+ this->setFixedSize(240, 42);
+ this->setModal(true);
+}
+
+QComboBox* KeyServerImportDialog::create_comboBox() {
+ auto* comboBox = new QComboBox;
+ comboBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
+
+ try {
+ SettingsObject key_server_json("key_server");
+
+ const auto key_server_list =
+ key_server_json.Check("server_list", nlohmann::json::array());
+
+ for (const auto& key_server : key_server_list) {
+ const auto key_server_str = key_server.get<std::string>();
+ comboBox->addItem(key_server_str.c_str());
+ }
+
+ int default_key_server_index = key_server_json.Check("default_server", 0);
+ if (default_key_server_index >= key_server_list.size()) {
+ throw std::runtime_error("default_server index out of range");
+ }
+ std::string default_key_server =
+ key_server_list[default_key_server_index].get<std::string>();
+
+ comboBox->setCurrentText(default_key_server.c_str());
+ } catch (...) {
+ LOG(ERROR) << _("Setting Operation Error") << "server_list"
+ << "default_server";
+ }
+
+ return comboBox;
+}
+
+void KeyServerImportDialog::create_keys_table() {
+ keys_table_ = new QTableWidget();
+ keys_table_->setColumnCount(4);
+
+ // always a whole row is marked
+ keys_table_->setSelectionBehavior(QAbstractItemView::SelectRows);
+ keys_table_->setEditTriggers(QAbstractItemView::NoEditTriggers);
+
+ // Make just one row selectable
+ keys_table_->setSelectionMode(QAbstractItemView::SingleSelection);
+
+ QStringList labels;
+ labels << _("UID") << _("Creation date") << _("KeyID") << _("Tag");
+ keys_table_->horizontalHeader()->setSectionResizeMode(
+ 0, QHeaderView::ResizeToContents);
+ keys_table_->setHorizontalHeaderLabels(labels);
+ keys_table_->verticalHeader()->hide();
+
+ connect(keys_table_, &QTableWidget::cellActivated, this,
+ &KeyServerImportDialog::slot_import);
+}
+
+void KeyServerImportDialog::set_message(const QString& text, bool error) {
+ if (m_automatic_) return;
+
+ message_->setText(text);
+ if (error) {
+ icon_->setPixmap(
+ QPixmap(":error.png").scaled(QSize(24, 24), Qt::KeepAspectRatio));
+ } else {
+ icon_->setPixmap(
+ QPixmap(":info.png").scaled(QSize(24, 24), Qt::KeepAspectRatio));
+ }
+}
+
+void KeyServerImportDialog::slot_search() {
+ if (search_line_edit_->text().isEmpty()) {
+ set_message("<h4>" + QString(_("Text is empty.")) + "</h4>", false);
+ return;
+ }
+
+ auto* task = new KeyServerSearchTask(
+ key_server_combo_box_->currentText().toStdString(),
+ search_line_edit_->text().toStdString());
+
+ connect(task, &KeyServerSearchTask::SignalKeyServerSearchResult, this,
+ &KeyServerImportDialog::slot_search_finished);
+
+ connect(task, &KeyServerSearchTask::SignalKeyServerSearchResult, this, [=]() {
+ this->search_button_->setDisabled(false);
+ this->key_server_combo_box_->setDisabled(false);
+ this->search_line_edit_->setReadOnly(false);
+ this->import_button_->setDisabled(false);
+ set_loading(false);
+ });
+
+ set_loading(true);
+ this->search_button_->setDisabled(true);
+ this->key_server_combo_box_->setDisabled(true);
+ this->search_line_edit_->setReadOnly(true);
+ this->import_button_->setDisabled(true);
+
+ Thread::TaskRunnerGetter::GetInstance()
+ .GetTaskRunner(Thread::TaskRunnerGetter::kTaskRunnerType_Network)
+ ->PostTask(task);
+}
+
+void KeyServerImportDialog::slot_search_finished(
+ QNetworkReply::NetworkError error, QByteArray buffer) {
+ LOG(INFO) << "Called" << error << buffer.size();
+ LOG(INFO) << buffer.toStdString();
+
+ keys_table_->clearContents();
+ keys_table_->setRowCount(0);
+
+ auto stream = QTextStream(buffer);
+
+ if (error != QNetworkReply::NoError) {
+ LOG(INFO) << "Error From Reply" << error;
+
+ switch (error) {
+ case QNetworkReply::ContentNotFoundError:
+ set_message(_("Not Key Found"), true);
+ break;
+ case QNetworkReply::TimeoutError:
+ set_message(_("Timeout"), true);
+ break;
+ case QNetworkReply::HostNotFoundError:
+ set_message(_("Key Server Not Found"), true);
+ break;
+ default:
+ set_message(_("Connection Error"), true);
+ }
+ return;
+ }
+
+ if (stream.readLine().contains("Error")) {
+ auto text = stream.readLine(1024);
+
+ if (text.contains("Too many responses")) {
+ set_message(
+ "<h4>" + QString(_("Too many responses from keyserver!")) + "</h4>",
+ true);
+ return;
+ } else if (text.contains("No keys found")) {
+ // if string looks like hex string, search again with 0x prepended
+ QRegExp rx("[0-9A-Fa-f]*");
+ QString query = search_line_edit_->text();
+ if (rx.exactMatch(query)) {
+ set_message(
+ "<h4>" +
+ QString(_("No keys found, input may be kexId, retrying search "
+ "with 0x.")) +
+ "</h4>",
+ true);
+ search_line_edit_->setText(query.prepend("0x"));
+ this->slot_search();
+ return;
+ } else {
+ set_message(
+ "<h4>" + QString(_("No keys found containing the search string!")) +
+ "</h4>",
+ true);
+ return;
+ }
+ } else if (text.contains("Insufficiently specific words")) {
+ set_message("<h4>" +
+ QString(_("Insufficiently specific search string!")) +
+ "</h4>",
+ true);
+ return;
+ } else {
+ set_message(text, true);
+ return;
+ }
+ } else {
+ int row = 0;
+ bool strikeout = false;
+
+ // read lines until end of steam
+ while (!stream.atEnd()) {
+ QStringList line =
+ QString::fromUtf8(QByteArray::fromPercentEncoding(
+ stream.readLine().trimmed().toUtf8()))
+ .split(":");
+
+ // TODO: have a look at two following pub lines
+ if (line[0] == "pub") {
+ strikeout = false;
+
+ QString flags = line[line.size() - 1];
+ keys_table_->setRowCount(row + 1);
+
+ // flags can be "d" for disabled, "r" for revoked
+ // or "e" for expired
+ if (flags.contains("r") or flags.contains("d") or flags.contains("e")) {
+ strikeout = true;
+ if (flags.contains("e")) {
+ keys_table_->setItem(row, 3,
+ new QTableWidgetItem(QString("expired")));
+ }
+ if (flags.contains("r")) {
+ keys_table_->setItem(row, 3,
+ new QTableWidgetItem(QString(_("revoked"))));
+ }
+ if (flags.contains("d")) {
+ keys_table_->setItem(row, 3,
+ new QTableWidgetItem(QString(_("disabled"))));
+ }
+ }
+
+ QStringList line2 = QString(QByteArray::fromPercentEncoding(
+ stream.readLine().trimmed().toUtf8()))
+ .split(":");
+
+ auto* uid = new QTableWidgetItem();
+ if (line2.size() > 1) {
+ uid->setText(line2[1]);
+ keys_table_->setItem(row, 0, uid);
+ }
+ auto* creation_date = new QTableWidgetItem(
+ QDateTime::fromTime_t(line[4].toInt()).toString("dd. MMM. yyyy"));
+ keys_table_->setItem(row, 1, creation_date);
+ auto* keyid = new QTableWidgetItem(line[1]);
+ keys_table_->setItem(row, 2, keyid);
+ if (strikeout) {
+ QFont strike = uid->font();
+ strike.setStrikeOut(true);
+ uid->setFont(strike);
+ creation_date->setFont(strike);
+ keyid->setFont(strike);
+ }
+ row++;
+ } else {
+ if (line[0] == "uid") {
+ QStringList l;
+ int height = keys_table_->rowHeight(row - 1);
+ keys_table_->setRowHeight(row - 1, height + 16);
+ QString tmp = keys_table_->item(row - 1, 0)->text();
+ tmp.append(QString("\n") + line[1]);
+ auto* tmp1 = new QTableWidgetItem(tmp);
+ keys_table_->setItem(row - 1, 0, tmp1);
+ if (strikeout) {
+ QFont strike = tmp1->font();
+ strike.setStrikeOut(true);
+ tmp1->setFont(strike);
+ }
+ }
+ }
+ set_message(
+ QString("<h4>") +
+ QString(_("%1 keys found. Double click a key to import it."))
+ .arg(row) +
+ "</h4>",
+ false);
+ }
+ keys_table_->resizeColumnsToContents();
+ import_button_->setDisabled(keys_table_->size().isEmpty());
+ }
+}
+
+void KeyServerImportDialog::slot_import() {
+ std::vector<std::string> key_ids;
+ const int row_count = keys_table_->rowCount();
+ for (int i = 0; i < row_count; ++i) {
+ if (keys_table_->item(i, 2)->isSelected()) {
+ QString keyid = keys_table_->item(i, 2)->text();
+ key_ids.push_back(keyid.toStdString());
+ }
+ }
+ if (!key_ids.empty())
+ SlotImport(key_ids, key_server_combo_box_->currentText().toStdString());
+}
+
+void KeyServerImportDialog::SlotImport(const KeyIdArgsListPtr& keys) {
+ // keyserver host url
+ std::string target_keyserver;
+
+ if (key_server_combo_box_ != nullptr) {
+ target_keyserver = key_server_combo_box_->currentText().toStdString();
+ }
+ if (target_keyserver.empty()) {
+ try {
+ SettingsObject key_server_json("key_server");
+ const auto key_server_list =
+ key_server_json.Check("server_list", nlohmann::json::array());
+
+ int default_key_server_index = key_server_json.Check("default_server", 0);
+ if (default_key_server_index >= key_server_list.size()) {
+ throw std::runtime_error("default_server index out of range");
+ }
+ std::string default_key_server =
+ key_server_list[default_key_server_index].get<std::string>();
+
+ target_keyserver = default_key_server;
+ } catch (...) {
+ LOG(ERROR) << _("Setting Operation Error") << "server_list"
+ << "default_server";
+ QMessageBox::critical(
+ nullptr, _("Default Keyserver Not Found"),
+ _("Cannot read default keyserver from your settings, "
+ "please set a default keyserver first"));
+ return;
+ }
+ }
+ std::vector<std::string> key_ids;
+ for (const auto& key_id : *keys) {
+ key_ids.push_back(key_id);
+ }
+ SlotImport(key_ids, target_keyserver);
+}
+
+void KeyServerImportDialog::SlotImport(std::vector<std::string> key_ids,
+ std::string keyserver_url) {
+ auto* task = new KeyServerImportTask(keyserver_url, key_ids);
+
+ connect(task, &KeyServerImportTask::SignalKeyServerImportResult, this,
+ &KeyServerImportDialog::slot_import_finished);
+
+ Thread::TaskRunnerGetter::GetInstance()
+ .GetTaskRunner(Thread::TaskRunnerGetter::kTaskRunnerType_Network)
+ ->PostTask(task);
+}
+
+void KeyServerImportDialog::slot_import_finished(
+ QNetworkReply::NetworkError error, QByteArray buffer) {
+ LOG(INFO) << _("Called");
+
+ if (error != QNetworkReply::NoError) {
+ LOG(ERROR) << "Error From Reply" << buffer.toStdString();
+ if (!m_automatic_) {
+ switch (error) {
+ case QNetworkReply::ContentNotFoundError:
+ set_message(_("Key Not Found"), true);
+ break;
+ case QNetworkReply::TimeoutError:
+ set_message(_("Timeout"), true);
+ break;
+ case QNetworkReply::HostNotFoundError:
+ set_message(_("Key Server Not Found"), true);
+ break;
+ default:
+ set_message(_("Connection Error"), true);
+ }
+ } else {
+ switch (error) {
+ case QNetworkReply::ContentNotFoundError:
+ QMessageBox::critical(nullptr, _("Key Not Found"),
+ QString(_("key not found in the Keyserver")));
+ break;
+ case QNetworkReply::TimeoutError:
+ QMessageBox::critical(nullptr, _("Timeout"), "Connection timeout");
+ break;
+ case QNetworkReply::HostNotFoundError:
+ QMessageBox::critical(nullptr, _("Host Not Found"),
+ "cannot resolve the default Keyserver");
+ break;
+ default:
+ QMessageBox::critical(nullptr, _("Connection Error"),
+ _("General Connection Error"));
+ }
+ }
+ if (m_automatic_) {
+ setWindowFlags(Qt::Window | Qt::WindowTitleHint |
+ Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint);
+ }
+ return;
+ }
+
+ this->import_keys(
+ std::make_unique<ByteArray>(buffer.constData(), buffer.length()));
+
+ if (!m_automatic_) {
+ set_message(QString("<h4>") + _("Key Imported") + "</h4>", false);
+ }
+}
+
+void KeyServerImportDialog::import_keys(ByteArrayPtr in_data) {
+ GpgImportInformation result =
+ GpgKeyImportExporter::GetInstance().ImportKey(std::move(in_data));
+
+ // refresh the key database
+ emit SignalKeyImported();
+
+ QWidget* _parent = qobject_cast<QWidget*>(parent());
+ if (m_automatic_) {
+ auto dialog = new KeyImportDetailDialog(result, true, _parent);
+ dialog->show();
+ this->accept();
+ } else {
+ auto dialog = new KeyImportDetailDialog(result, false, this);
+ dialog->exec();
+ }
+}
+
+void KeyServerImportDialog::set_loading(bool status) {
+ waiting_bar_->setVisible(status);
+ if (!m_automatic_) {
+ icon_->setVisible(!status);
+ message_->setVisible(!status);
+ }
+}
+
+} // namespace GpgFrontend::UI
diff --git a/src/ui/dialog/import_export/KeyServerImportDialog.h b/src/ui/dialog/import_export/KeyServerImportDialog.h
new file mode 100644
index 00000000..fd912bdd
--- /dev/null
+++ b/src/ui/dialog/import_export/KeyServerImportDialog.h
@@ -0,0 +1,182 @@
+/**
+ * Copyright (C) 2021 Saturneric
+ *
+ * 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.
+ *
+ * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * The initial version of the source code is inherited from
+ * the gpg4usb project, which is under GPL-3.0-or-later.
+ *
+ * All the source code of GpgFrontend was modified and released by
+ * Saturneric<[email protected]> starting on May 12, 2021.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#ifndef __KEY_SERVER_IMPORT_DIALOG_H__
+#define __KEY_SERVER_IMPORT_DIALOG_H__
+
+#include <string>
+
+#include "KeyImportDetailDialog.h"
+#include "core/GpgContext.h"
+#include "ui/GpgFrontendUI.h"
+#include "ui/dialog/GeneralDialog.h"
+#include "ui/widgets/KeyList.h"
+
+namespace GpgFrontend::UI {
+
+/**
+ * @brief
+ *
+ */
+class KeyServerImportDialog : public GeneralDialog {
+ Q_OBJECT
+
+ public:
+ /**
+ * @brief Construct a new Key Server Import Dialog object
+ *
+ * @param automatic
+ * @param parent
+ */
+ KeyServerImportDialog(bool automatic, QWidget* parent);
+
+ /**
+ * @brief Construct a new Key Server Import Dialog object
+ *
+ * @param parent
+ */
+ explicit KeyServerImportDialog(QWidget* parent);
+
+ public slots:
+
+ /**
+ * @brief
+ *
+ * @param keys
+ */
+ void SlotImport(const KeyIdArgsListPtr& keys);
+
+ /**
+ * @brief
+ *
+ * @param keyIds
+ * @param keyserverUrl
+ */
+ void SlotImport(std::vector<std::string> key_ids_list,
+ std::string keyserver_url);
+
+ signals:
+
+ /**
+ * @brief
+ *
+ */
+ void SignalKeyImported();
+
+ private slots:
+
+ /**
+ * @brief import key(s) for the key table selection
+ *
+ */
+ void slot_import();
+
+ /**
+ * @brief
+ *
+ */
+ void slot_search_finished(QNetworkReply::NetworkError reply,
+ QByteArray buffer);
+
+ /**
+ * @brief
+ *
+ * @param keyid
+ */
+ void slot_import_finished(QNetworkReply::NetworkError error,
+ QByteArray buffer);
+
+ /**
+ * @brief
+ *
+ */
+ void slot_search();
+
+ private:
+ /**
+ * @brief Create a keys table object
+ *
+ */
+ void create_keys_table();
+
+ /**
+ * @brief Set the message object
+ *
+ * @param text
+ * @param error
+ */
+ void set_message(const QString& text, bool error);
+
+ /**
+ * @brief
+ *
+ * @param in_data
+ */
+ void import_keys(ByteArrayPtr in_data);
+
+ /**
+ * @brief Set the loading object
+ *
+ * @param status
+ */
+ void set_loading(bool status);
+
+ /**
+ * @brief Create a button object
+ *
+ * @param text
+ * @param member
+ * @return QPushButton*
+ */
+ QPushButton* create_button(const QString& text, const char* member);
+
+ /**
+ * @brief Create a comboBox object
+ *
+ * @return QComboBox*
+ */
+ QComboBox* create_comboBox();
+
+ bool m_automatic_ = false; ///<
+
+ QLineEdit* search_line_edit_{}; ///<
+ QComboBox* key_server_combo_box_{}; ///<
+ QProgressBar* waiting_bar_; ///<
+ QLabel* search_label_{}; ///<
+ QLabel* key_server_label_{}; ///<
+ QLabel* message_{}; ///<
+ QLabel* icon_{}; ///<
+ QPushButton* close_button_{}; ///<
+ QPushButton* import_button_{}; ///<
+ QPushButton* search_button_{}; ///<
+ QTableWidget* keys_table_{}; ///<
+};
+
+} // namespace GpgFrontend::UI
+
+#endif // __KEY_SERVER_IMPORT_DIALOG_H__
diff --git a/src/ui/dialog/import_export/KeyUploadDialog.cpp b/src/ui/dialog/import_export/KeyUploadDialog.cpp
new file mode 100644
index 00000000..055f2e1f
--- /dev/null
+++ b/src/ui/dialog/import_export/KeyUploadDialog.cpp
@@ -0,0 +1,159 @@
+/**
+ * Copyright (C) 2021 Saturneric
+ *
+ * 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.
+ *
+ * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * The initial version of the source code is inherited from
+ * the gpg4usb project, which is under GPL-3.0-or-later.
+ *
+ * All the source code of GpgFrontend was modified and released by
+ * Saturneric<[email protected]> starting on May 12, 2021.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#include "KeyUploadDialog.h"
+
+#include <algorithm>
+
+#include "core/function/GlobalSettingStation.h"
+#include "core/function/gpg/GpgKeyGetter.h"
+#include "core/function/gpg/GpgKeyImportExporter.h"
+
+namespace GpgFrontend::UI {
+
+KeyUploadDialog::KeyUploadDialog(const KeyIdArgsListPtr& keys_ids,
+ QWidget* parent)
+ : GeneralDialog(typeid(KeyUploadDialog).name(), parent),
+ m_keys_(GpgKeyGetter::GetInstance().GetKeys(keys_ids)) {
+ auto* pb = new QProgressBar();
+ pb->setRange(0, 0);
+ pb->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ pb->setTextVisible(false);
+
+ auto* layout = new QVBoxLayout();
+ layout->addWidget(pb);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+ this->setLayout(layout);
+
+ this->setModal(true);
+ this->setWindowTitle(_("Uploading Public Key"));
+ this->setFixedSize(240, 42);
+}
+
+void KeyUploadDialog::SlotUpload() {
+ auto out_data = std::make_unique<ByteArray>();
+ GpgKeyImportExporter::GetInstance().ExportKeys(*m_keys_, out_data);
+ slot_upload_key_to_server(*out_data);
+}
+
+void KeyUploadDialog::slot_upload_key_to_server(
+ const GpgFrontend::ByteArray& keys_data) {
+ std::string target_keyserver;
+ if (target_keyserver.empty()) {
+ try {
+ auto& settings = GlobalSettingStation::GetInstance().GetUISettings();
+
+ target_keyserver = settings.lookup("keyserver.default_server").c_str();
+
+ LOG(INFO) << _("Set target Key Server to default Key Server")
+ << target_keyserver;
+ } catch (...) {
+ LOG(ERROR) << _("Cannot read default_keyserver From Settings");
+ QMessageBox::critical(
+ nullptr, _("Default Keyserver Not Found"),
+ _("Cannot read default keyserver from your settings, "
+ "please set a default keyserver first"));
+ return;
+ }
+ }
+
+ QUrl req_url(QString::fromStdString(target_keyserver + "/pks/add"));
+ auto qnam = new QNetworkAccessManager(this);
+
+ // Building Post Data
+ QByteArray postData;
+
+ auto data = std::string(keys_data);
+
+ boost::algorithm::replace_all(data, "\n", "%0A");
+ boost::algorithm::replace_all(data, "\r", "%0D");
+ boost::algorithm::replace_all(data, "(", "%28");
+ boost::algorithm::replace_all(data, ")", "%29");
+ boost::algorithm::replace_all(data, "/", "%2F");
+ boost::algorithm::replace_all(data, ":", "%3A");
+ boost::algorithm::replace_all(data, "+", "%2B");
+ boost::algorithm::replace_all(data, "=", "%3D");
+ boost::algorithm::replace_all(data, " ", "+");
+
+ QNetworkRequest request(req_url);
+ request.setHeader(QNetworkRequest::ContentTypeHeader,
+ "application/x-www-form-urlencoded");
+
+ postData.append("keytext").append("=").append(
+ QString::fromStdString(data).toUtf8());
+
+ // Send Post Data
+ QNetworkReply* reply = qnam->post(request, postData);
+ connect(reply, &QNetworkReply::finished, this,
+ &KeyUploadDialog::slot_upload_finished);
+
+ // Keep Waiting
+ while (reply->isRunning()) {
+ QApplication::processEvents();
+ }
+
+ // Done
+ this->hide();
+ this->close();
+}
+
+void KeyUploadDialog::slot_upload_finished() {
+ auto* reply = qobject_cast<QNetworkReply*>(sender());
+
+ QByteArray response = reply->readAll();
+ LOG(INFO) << "Response: " << response.toStdString();
+
+ auto error = reply->error();
+ if (error != QNetworkReply::NoError) {
+ LOG(INFO) << "Error From Reply" << reply->errorString().toStdString();
+ QString message;
+ switch (error) {
+ case QNetworkReply::ContentNotFoundError:
+ message = _("Key Not Found");
+ break;
+ case QNetworkReply::TimeoutError:
+ message = _("Timeout");
+ break;
+ case QNetworkReply::HostNotFoundError:
+ message = _("Key Server Not Found");
+ break;
+ default:
+ message = _("Connection Error");
+ }
+ QMessageBox::critical(this, "Upload Failed", message);
+ return;
+ } else {
+ QMessageBox::information(this, _("Upload Success"),
+ _("Upload Public Key Successfully"));
+ LOG(INFO) << "Success while contacting keyserver!";
+ }
+ reply->deleteLater();
+}
+
+} // namespace GpgFrontend::UI
diff --git a/src/ui/dialog/import_export/KeyUploadDialog.h b/src/ui/dialog/import_export/KeyUploadDialog.h
new file mode 100644
index 00000000..d621f33a
--- /dev/null
+++ b/src/ui/dialog/import_export/KeyUploadDialog.h
@@ -0,0 +1,83 @@
+/**
+ * Copyright (C) 2021 Saturneric
+ *
+ * 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.
+ *
+ * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * The initial version of the source code is inherited from
+ * the gpg4usb project, which is under GPL-3.0-or-later.
+ *
+ * All the source code of GpgFrontend was modified and released by
+ * Saturneric<[email protected]> starting on May 12, 2021.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#ifndef GPGFRONTEND_KEYUPLOADWIDGET_H
+#define GPGFRONTEND_KEYUPLOADWIDGET_H
+
+#include "core/GpgContext.h"
+#include "ui/GpgFrontendUI.h"
+#include "ui/dialog/GeneralDialog.h"
+
+namespace GpgFrontend::UI {
+
+/**
+ * @brief
+ *
+ */
+class KeyUploadDialog : public GeneralDialog {
+ Q_OBJECT
+ public:
+ /**
+ * @brief Construct a new Key Upload Dialog object
+ *
+ * @param keys_ids
+ * @param parent
+ */
+ explicit KeyUploadDialog(const KeyIdArgsListPtr& keys_ids, QWidget* parent);
+
+ public slots:
+
+ /**
+ * @brief
+ *
+ */
+ void SlotUpload();
+
+ private slots:
+
+ /**
+ * @brief
+ *
+ * @param keys_data
+ */
+ void slot_upload_key_to_server(const GpgFrontend::ByteArray& keys_data);
+
+ /**
+ * @brief
+ *
+ */
+ void slot_upload_finished();
+
+ private:
+ KeyListPtr m_keys_; ///<
+ QByteArray m_key_data_; ///<
+};
+
+} // namespace GpgFrontend::UI
+
+#endif // GPGFRONTEND_KEYUPLOADWIDGET_H