/** * 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 . * * 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 starting on May 12, 2021. * * SPDX-License-Identifier: GPL-3.0-or-later * */ #include "SettingsKeyServer.h" #include "core/function/GlobalSettingStation.h" #include "core/thread/Task.h" #include "core/thread/TaskRunnerGetter.h" #include "ui/struct/SettingsObject.h" #include "ui/thread/ListedKeyServerTestTask.h" #include "ui_KeyServerSettings.h" namespace GpgFrontend::UI { KeyserverTab::KeyserverTab(QWidget* parent) : QWidget(parent), ui_(std::make_shared()) { ui_->setupUi(this); ui_->keyServerListTable->setSizeAdjustPolicy( QAbstractScrollArea::AdjustToContents); connect(ui_->addKeyServerPushButton, &QPushButton::clicked, this, &KeyserverTab::slot_add_key_server); connect(ui_->testKeyServerButton, &QPushButton::clicked, this, &KeyserverTab::slot_test_listed_key_server); ui_->keyServerListGroupBox->setTitle(_("Keyserver List")); ui_->operationsGroupBox->setTitle(_("Operations")); ui_->keyServerListTable->horizontalHeaderItem(0)->setText(_("Default")); ui_->keyServerListTable->horizontalHeaderItem(1)->setText( _("Keyserver Address")); ui_->keyServerListTable->horizontalHeaderItem(2)->setText(_("Security")); ui_->keyServerListTable->horizontalHeaderItem(3)->setText(_("Available")); ui_->addKeyServerPushButton->setText(_("Add")); ui_->testKeyServerButton->setText(_("Test Listed Keyserver")); ui_->tipsLabel->setText( _("Tips: Please Double-click table item to edit it.")); ui_->actionDelete_Selected_Key_Server->setText(_("Delete Selected")); ui_->actionDelete_Selected_Key_Server->setToolTip( _("Delete Selected Key Server")); ui_->actionSet_As_Default->setText(_("Set As Default")); ui_->actionSet_As_Default->setToolTip(_("Set As Default")); popup_menu_ = new QMenu(this); popup_menu_->addAction(ui_->actionSet_As_Default); popup_menu_->addAction(ui_->actionDelete_Selected_Key_Server); connect(ui_->keyServerListTable, &QTableWidget::itemChanged, [=](QTableWidgetItem* item) { LOG(INFO) << "item edited" << item->column(); if (item->column() != 1) return; const auto row_size = ui_->keyServerListTable->rowCount(); // Update Actions if (row_size > 0) { key_server_str_list_.clear(); for (int i = 0; i < row_size; i++) { const auto key_server = ui_->keyServerListTable->item(i, 1)->text(); key_server_str_list_.append(key_server); } } }); connect(ui_->actionSet_As_Default, &QAction::triggered, [=]() { const auto row_size = ui_->keyServerListTable->rowCount(); for (int i = 0; i < row_size; i++) { const auto item = ui_->keyServerListTable->item(i, 1); if (!item->isSelected()) continue; this->default_key_server_ = item->text(); } this->slot_refresh_table(); }); connect(ui_->actionDelete_Selected_Key_Server, &QAction::triggered, [=]() { const auto row_size = ui_->keyServerListTable->rowCount(); for (int i = 0; i < row_size; i++) { const auto item = ui_->keyServerListTable->item(i, 1); if (!item->isSelected()) continue; this->key_server_str_list_.removeAt(i); break; } this->slot_refresh_table(); }); // Read key-list from ini-file and fill it into combobox SetSettings(); slot_refresh_table(); } /********************************** * Read the settings from config * and set the buttons and checkboxes * appropriately **********************************/ void KeyserverTab::SetSettings() { 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(); this->key_server_str_list_.append(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(); if (!key_server_str_list_.contains(default_key_server.c_str())) key_server_str_list_.append(default_key_server.c_str()); default_key_server_ = QString::fromStdString(default_key_server); } catch (const std::exception& e) { LOG(ERROR) << "Error reading key-server settings: " << e.what(); } } void KeyserverTab::slot_add_key_server() { auto target_url = ui_->addKeyServerEdit->text(); if (url_reg_.match(target_url).hasMatch()) { if (target_url.startsWith("https://")) { ; } else if (target_url.startsWith("http://")) { QMessageBox::warning( this, _("Insecure keyserver address"), _("For security reasons, using HTTP as the communication protocol " "with " "the key server is not recommended. It is recommended to use " "HTTPS.")); } key_server_str_list_.append(ui_->addKeyServerEdit->text()); } else { auto ret = QMessageBox::warning( this, _("Warning"), _("You may not use HTTPS or HTTP as the protocol for communicating " "with the key server, which may not be wrong. But please check the " "address you entered again to make sure it is correct. Are you " "sure " "that want to add it into the keyserver list?"), QMessageBox::Ok | QMessageBox::Cancel); if (ret == QMessageBox::Cancel) return; else key_server_str_list_.append(ui_->addKeyServerEdit->text()); } slot_refresh_table(); } void KeyserverTab::ApplySettings() { SettingsObject key_server_json("key_server"); key_server_json["server_list"] = nlohmann::json::array(); auto& key_server_list = key_server_json["server_list"]; const auto list_size = key_server_str_list_.size(); for (int i = 0; i < list_size; i++) { const auto key_server = key_server_str_list_[i]; if (default_key_server_ == key_server) key_server_json["default_server"] = i; key_server_list.insert(key_server_list.end(), key_server.toStdString()); } } void KeyserverTab::slot_refresh_table() { LOG(INFO) << "Start Refreshing Key Server Table"; ui_->keyServerListTable->blockSignals(true); ui_->keyServerListTable->setRowCount(key_server_str_list_.size()); int index = 0; for (const auto& server : key_server_str_list_) { auto* tmp1 = new QTableWidgetItem(server == default_key_server_ ? "*" : QString{}); tmp1->setTextAlignment(Qt::AlignCenter); ui_->keyServerListTable->setItem(index, 0, tmp1); tmp1->setFlags(tmp1->flags() ^ Qt::ItemIsEditable); auto* tmp2 = new QTableWidgetItem(server); tmp2->setTextAlignment(Qt::AlignCenter); ui_->keyServerListTable->setItem(index, 1, tmp2); auto* tmp3 = new QTableWidgetItem(server.startsWith("https") ? _("true") : _("false")); tmp3->setTextAlignment(Qt::AlignCenter); ui_->keyServerListTable->setItem(index, 2, tmp3); tmp3->setFlags(tmp3->flags() ^ Qt::ItemIsEditable); auto* tmp4 = new QTableWidgetItem(_("unknown")); tmp4->setTextAlignment(Qt::AlignCenter); ui_->keyServerListTable->setItem(index, 3, tmp4); tmp4->setFlags(tmp3->flags() ^ Qt::ItemIsEditable); index++; } const auto column_count = ui_->keyServerListTable->columnCount(); for (int i = 0; i < column_count; i++) { ui_->keyServerListTable->resizeColumnToContents(i); } ui_->keyServerListTable->blockSignals(false); } void KeyserverTab::slot_test_listed_key_server() { auto timeout = QInputDialog::getInt(this, _("Set TCP Timeout"), tr("timeout(ms): "), 2500, 200, 16000); QStringList urls; const auto row_size = ui_->keyServerListTable->rowCount(); for (int i = 0; i < row_size; i++) { const auto keyserver_url = ui_->keyServerListTable->item(i, 1)->text(); urls.push_back(keyserver_url); } auto* task = new ListedKeyServerTestTask(urls, timeout, this); connect( task, &GpgFrontend::UI::ListedKeyServerTestTask::SignalKeyServerListTestResult, this, [=](std::vector result) { const auto row_size = ui_->keyServerListTable->rowCount(); if (result.size() != row_size) return; ui_->keyServerListTable->blockSignals(true); for (int i = 0; i < row_size; i++) { const auto status = result[i]; auto status_iem = ui_->keyServerListTable->item(i, 3); if (status == ListedKeyServerTestTask::kTestResultType_Success) { status_iem->setText(_("Reachable")); status_iem->setForeground(QBrush(QColor::fromRgb(0, 255, 0))); } else { status_iem->setText(_("Not Reachable")); status_iem->setForeground(QBrush(QColor::fromRgb(255, 0, 0))); } } ui_->keyServerListTable->blockSignals(false); }); // Waiting Dialog auto* waiting_dialog = new QProgressDialog(this); waiting_dialog->setMaximum(0); waiting_dialog->setMinimum(0); auto waiting_dialog_label = new QLabel(QString(_("Test Key Server Connection...")) + "

" + _("This test only tests the network connectivity of the key " "server. Passing the test does not mean that the key server " "is functionally available.")); waiting_dialog_label->setWordWrap(true); waiting_dialog->setLabel(waiting_dialog_label); waiting_dialog->resize(420, 120); waiting_dialog->setModal(true); connect(task, &Thread::Task::SignalTaskFinished, [=]() { waiting_dialog->close(); waiting_dialog->deleteLater(); }); // Show Waiting Dialog waiting_dialog->show(); waiting_dialog->setFocus(); Thread::TaskRunnerGetter::GetInstance() .GetTaskRunner(Thread::TaskRunnerGetter::kTaskRunnerType_Network) ->PostTask(task); } void KeyserverTab::contextMenuEvent(QContextMenuEvent* event) { QWidget::contextMenuEvent(event); if (ui_->keyServerListTable->selectedItems().length() > 0) { popup_menu_->exec(event->globalPos()); } } } // namespace GpgFrontend::UI