aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorsaturneric <[email protected]>2025-01-27 15:39:09 +0000
committersaturneric <[email protected]>2025-01-27 15:39:09 +0000
commitaf1870fd422fc615a7039b998f505f100e98474a (patch)
tree5453ac586ce694863ecf438136614d3675b83aca /src
parentfeat: allow changing sort options by ui at file page (diff)
downloadGpgFrontend-af1870fd422fc615a7039b998f505f100e98474a.tar.gz
GpgFrontend-af1870fd422fc615a7039b998f505f100e98474a.zip
fix: kill all gnupg daemons in a proper way
Diffstat (limited to 'src')
-rw-r--r--src/GpgFrontendContext.h2
-rw-r--r--src/app.cpp23
-rw-r--r--src/core/GpgConstants.h1
-rw-r--r--src/core/GpgCoreInit.cpp68
-rw-r--r--src/core/function/GlobalSettingStation.cpp3
-rw-r--r--src/core/function/GlobalSettingStation.h3
-rw-r--r--src/core/function/gpg/GpgAdvancedOperator.cpp311
-rw-r--r--src/core/function/gpg/GpgAdvancedOperator.h22
-rw-r--r--src/init.cpp28
-rw-r--r--src/ui/main_window/MainWindow.cpp7
-rw-r--r--src/ui/main_window/MainWindowSlotUI.cpp9
-rw-r--r--src/ui/struct/GpgOperaResult.cpp36
-rw-r--r--src/ui/struct/GpgOperaResult.h5
-rw-r--r--src/ui/struct/GpgOperaResultContext.cpp83
-rw-r--r--src/ui/struct/GpgOperaResultContext.h49
15 files changed, 384 insertions, 266 deletions
diff --git a/src/GpgFrontendContext.h b/src/GpgFrontendContext.h
index ae3177aa..2815caad 100644
--- a/src/GpgFrontendContext.h
+++ b/src/GpgFrontendContext.h
@@ -46,6 +46,8 @@ struct GpgFrontendContext {
bool gather_external_gnupg_info;
bool unit_test_mode;
+ int rtn = GpgFrontend::kCrashCode;
+
/**
* @brief Construct a new Gpg Frontend Context object
*
diff --git a/src/app.cpp b/src/app.cpp
index 0804d64e..6d28ac6b 100644
--- a/src/app.cpp
+++ b/src/app.cpp
@@ -28,8 +28,7 @@
#include "GpgFrontendContext.h"
#include "core/GpgConstants.h"
-#include "core/GpgCoreInit.h"
-#include "core/module/ModuleInit.h"
+#include "core/function/CacheManager.h"
#include "ui/GpgFrontendUIInit.h"
// main
@@ -37,8 +36,6 @@
namespace GpgFrontend {
-constexpr int kCrashCode = ~0; ///<
-
/**
* @brief
*
@@ -79,26 +76,18 @@ auto StartApplication(const GFCxtWPtr& p_ctx) -> int {
// load module's translations
GpgFrontend::UI::InitModulesTranslations();
-
-
-
// finally create main window
return_from_event_loop_code = GpgFrontend::UI::RunGpgFrontendUI(app);
} while (return_from_event_loop_code == GpgFrontend::kRestartCode &&
restart_count++ < 99);
- // first should shutdown the module system
- GpgFrontend::Module::ShutdownGpgFrontendModules();
-
- // then shutdown the core
- GpgFrontend::DestroyGpgFrontendCore();
+ // clear cache of unsaved pages
+ GpgFrontend::CacheManager::GetInstance().SaveDurableCache(
+ "editor_unsaved_pages", QJsonDocument(QJsonArray()), true);
- // deep restart mode
- if (return_from_event_loop_code == GpgFrontend::kDeepRestartCode ||
- return_from_event_loop_code == kCrashCode) {
- QProcess::startDetached(qApp->arguments()[0], qApp->arguments());
- };
+ // set return code
+ ctx->rtn = return_from_event_loop_code;
// exit the program
return return_from_event_loop_code;
diff --git a/src/core/GpgConstants.h b/src/core/GpgConstants.h
index 6945b27a..d6632b2a 100644
--- a/src/core/GpgConstants.h
+++ b/src/core/GpgConstants.h
@@ -33,6 +33,7 @@ namespace GpgFrontend {
constexpr int kNonRestartCode = 0;
constexpr int kRestartCode = 1000; ///< only refresh ui
constexpr int kDeepRestartCode = 1001; // refresh core and ui
+constexpr int kCrashCode = ~0; ///< application crash
// Channels
constexpr int kGpgFrontendDefaultChannel = 0; ///<
diff --git a/src/core/GpgCoreInit.cpp b/src/core/GpgCoreInit.cpp
index 86d68af4..d6de2240 100644
--- a/src/core/GpgCoreInit.cpp
+++ b/src/core/GpgCoreInit.cpp
@@ -36,9 +36,7 @@
#include "core/function/gpg/GpgAdvancedOperator.h"
#include "core/function/gpg/GpgContext.h"
#include "core/function/gpg/GpgKeyGetter.h"
-#include "core/model/SettingsObject.h"
#include "core/module/ModuleManager.h"
-#include "core/struct/settings_object/KeyDatabaseListSO.h"
#include "core/thread/Task.h"
#include "core/thread/TaskRunnerGetter.h"
#include "core/utils/CommonUtils.h"
@@ -47,7 +45,13 @@
namespace GpgFrontend {
-void DestroyGpgFrontendCore() { SingletonStorageCollection::Destroy(); }
+void DestroyGpgFrontendCore() {
+ // stop all task runner
+ Thread::TaskRunnerGetter::GetInstance().StopAllTeakRunner();
+
+ // destroy all singleton objects
+ SingletonStorageCollection::Destroy();
+}
auto VerifyGpgconfPath(const QFileInfo& gnupg_install_fs_path) -> bool {
return gnupg_install_fs_path.isAbsolute() && gnupg_install_fs_path.exists() &&
@@ -260,7 +264,8 @@ auto RefreshGpgMEBackendEngine(const QString& gpgconf_path,
return true;
}
-auto GetGnuPGPathByGpgConf(const QString& gpgconf_install_fs_path) -> QString {
+auto GetComponentPathsByGpgConf(const QString& gpgconf_install_fs_path)
+ -> bool {
auto* process = new QProcess(QCoreApplication::instance());
process->setProgram(gpgconf_install_fs_path);
process->start();
@@ -268,7 +273,7 @@ auto GetGnuPGPathByGpgConf(const QString& gpgconf_install_fs_path) -> QString {
auto output_buffer = process->readAllStandardOutput();
process->deleteLater();
- if (output_buffer.isEmpty()) return {};
+ if (output_buffer.isEmpty()) return false;
auto line_split_list = QString(output_buffer).split("\n");
for (const auto& line : line_split_list) {
@@ -276,23 +281,26 @@ auto GetGnuPGPathByGpgConf(const QString& gpgconf_install_fs_path) -> QString {
if (info_split_list.size() != 3) continue;
- auto component_name = info_split_list[0].trimmed();
+ auto component_name = info_split_list[0].trimmed().toLower();
auto component_desc = info_split_list[1].trimmed();
auto component_path = info_split_list[2].trimmed();
- if (component_name.toLower() == "gpg") {
#if defined(_WIN32) || defined(WIN32)
- // replace some special substrings on windows platform
- component_path.replace("%3a", ":");
+ // replace some special substrings on windows platform
+ component_path.replace("%3a", ":");
#endif
- QFileInfo file_info(component_path);
- if (file_info.exists() && file_info.isFile()) {
- return file_info.absoluteFilePath();
- }
- return {};
- }
+
+ QFileInfo file_info(component_path);
+ if (!file_info.exists() || !file_info.isFile()) continue;
+
+ Module::UpsertRTValue("core", "gnupg.component.paths." + component_name,
+ file_info.absoluteFilePath());
+
+ LOG_D() << "gpg components: " << component_name
+ << "path: " << file_info.absoluteFilePath();
}
- return "";
+
+ return true;
}
auto DecideGpgConfPath(const QString& default_gpgconf_path) -> QString {
@@ -349,8 +357,15 @@ auto DecideGpgConfPath(const QString& default_gpgconf_path) -> QString {
return "";
}
-auto DecideGnuPGPath(const QString& gpgconf_path) -> QString {
- return GetGnuPGPathByGpgConf(gpgconf_path);
+auto DecideGnuPGPath(const QString& default_gnupg_path) -> QString {
+ QFileInfo info(default_gnupg_path);
+
+ if (default_gnupg_path.isEmpty() || !info.exists() || !info.isFile()) {
+ return Module::RetrieveRTValueTypedOrDefault<>(
+ "core", "gnupg.component.paths.gpg", QString{});
+ }
+
+ return default_gnupg_path;
}
auto InitBasicPath() -> bool {
@@ -364,12 +379,23 @@ auto InitBasicPath() -> bool {
LOG_I() << "default gnupg path found by gpgme: " << default_gnupg_path;
auto target_gpgconf_path = DecideGpgConfPath(default_gpgconf_path);
+
+ if (!GetComponentPathsByGpgConf(default_gpgconf_path)) {
+ LOG_E() << "Cannot get components paths by gpgconf!"
+ << "GpgFrontend cannot start under this situation!";
+ CoreSignalStation::GetInstance()->SignalBadGnupgEnv(
+ QCoreApplication::tr("Cannot get Infos from GpgConf"));
+ return false;
+ }
+
auto target_gnupg_path = default_gnupg_path;
+
if (target_gpgconf_path != default_gpgconf_path) {
- target_gnupg_path = DecideGnuPGPath(target_gpgconf_path);
+ target_gnupg_path = DecideGnuPGPath(target_gnupg_path);
}
+
LOG_I() << "gpgconf path used: " << target_gpgconf_path;
- LOG_I() << "gnupg path provided by gpgconf: " << target_gnupg_path;
+ LOG_I() << "gnupg path used: " << target_gnupg_path;
if (target_gpgconf_path.isEmpty()) {
LOG_E() << "Cannot find gpgconf!"
@@ -577,7 +603,7 @@ auto InitGpgFrontendCore(CoreInitArgs args) -> int {
->PostTask(task);
if (!args.unit_test_mode && restart_all_gnupg_components_on_start) {
- GpgAdvancedOperator::RestartGpgComponents();
+ GpgAdvancedOperator::RestartGpgComponents(nullptr);
}
return 0;
}
diff --git a/src/core/function/GlobalSettingStation.cpp b/src/core/function/GlobalSettingStation.cpp
index 5c6149df..62b24331 100644
--- a/src/core/function/GlobalSettingStation.cpp
+++ b/src/core/function/GlobalSettingStation.cpp
@@ -256,4 +256,7 @@ auto GlobalSettingStation::GetIntegratedModulePath() const -> QString {
auto GlobalSettingStation::IsProtableMode() const -> bool {
return p_->IsProtableMode();
}
+auto GetSettings() -> QSettings {
+ return GlobalSettingStation::GetInstance().GetSettings();
+}
} // namespace GpgFrontend \ No newline at end of file
diff --git a/src/core/function/GlobalSettingStation.h b/src/core/function/GlobalSettingStation.h
index b7670b95..9ef29792 100644
--- a/src/core/function/GlobalSettingStation.h
+++ b/src/core/function/GlobalSettingStation.h
@@ -143,4 +143,7 @@ class GPGFRONTEND_CORE_EXPORT GlobalSettingStation
class Impl;
SecureUniquePtr<Impl> p_;
};
+
+auto GPGFRONTEND_CORE_EXPORT GetSettings() -> QSettings;
+
} // namespace GpgFrontend
diff --git a/src/core/function/gpg/GpgAdvancedOperator.cpp b/src/core/function/gpg/GpgAdvancedOperator.cpp
index 6b56d867..b310df85 100644
--- a/src/core/function/gpg/GpgAdvancedOperator.cpp
+++ b/src/core/function/gpg/GpgAdvancedOperator.cpp
@@ -34,6 +34,7 @@
#include "core/function/gpg/GpgCommandExecutor.h"
#include "core/module/ModuleManager.h"
+#include "core/utils/GpgUtils.h"
void GpgFrontend::GpgAdvancedOperator::ClearGpgPasswordCache(
OperationCallback cb) {
@@ -42,21 +43,40 @@ void GpgFrontend::GpgAdvancedOperator::ClearGpgPasswordCache(
if (gpgconf_path.isEmpty()) {
FLOG_W("cannot get valid gpgconf path from rt, abort.");
- cb(-1, TransferParams());
+ if (cb) cb(-1, TransferParams());
return;
}
-#if defined(__APPLE__) && defined(__MACH__)
- FLOG_I("kill all gpg components in order to clear gpg password cache");
- KillAllGpgComponents();
-#else
- GpgFrontend::GpgCommandExecutor::ExecuteSync(
- {gpgconf_path, QStringList{"--reload", "gpg-agent"},
- [=](int exit_code, const QString & /*p_out*/,
- const QString & /*p_err*/) {
- cb(exit_code == 0 ? 0 : -1, TransferParams());
- }});
-#endif
+ auto key_dbs = GetGpgKeyDatabaseInfos();
+ auto total_tasks = static_cast<int>(key_dbs.size());
+ std::atomic<int> completed_tasks{0};
+ std::vector<int> results(total_tasks, 0);
+
+ int task_index = 0;
+ for (const auto &key_db : key_dbs) {
+ const int current_index = task_index++;
+ const auto target_home_dir =
+ QDir::toNativeSeparators(QFileInfo(key_db.path).canonicalFilePath());
+
+ GpgFrontend::GpgCommandExecutor::ExecuteSync(
+ {gpgconf_path,
+ QStringList{"--homedir", target_home_dir, "--reload", "gpg-agent"},
+ [=, &completed_tasks, &results](int exit_code, const QString &,
+ const QString &) {
+ FLOG_D("gpgconf reload exit code: %d", exit_code);
+
+ results[current_index] = exit_code;
+
+ if (++completed_tasks == total_tasks && cb) {
+ int final_result =
+ std::all_of(results.begin(), results.end(),
+ [](int result) { return result >= 0; })
+ ? 0
+ : -1;
+ cb(final_result, TransferParams());
+ }
+ }});
+ }
}
void GpgFrontend::GpgAdvancedOperator::ReloadGpgComponents(
@@ -66,83 +86,99 @@ void GpgFrontend::GpgAdvancedOperator::ReloadGpgComponents(
if (gpgconf_path.isEmpty()) {
FLOG_W("cannot get valid gpgconf path from rt, abort.");
- cb(-1, TransferParams());
+ if (cb) cb(-1, TransferParams());
return;
}
- GpgFrontend::GpgCommandExecutor::ExecuteSync(
- {gpgconf_path, QStringList{"--reload"},
- [=](int exit_code, const QString &, const QString &) {
- FLOG_D("gpgconf reload exit code: %d", exit_code);
- cb(exit_code == 0 ? 0 : -1, TransferParams());
- }});
+ auto key_dbs = GetGpgKeyDatabaseInfos();
+ auto total_tasks = static_cast<int>(key_dbs.size());
+ std::atomic<int> completed_tasks{0};
+ std::vector<int> results(total_tasks, 0);
+
+ int task_index = 0;
+ for (const auto &key_db : key_dbs) {
+ const int current_index = task_index++;
+ const auto target_home_dir =
+ QDir::toNativeSeparators(QFileInfo(key_db.path).canonicalFilePath());
+
+ GpgFrontend::GpgCommandExecutor::ExecuteSync(
+ {gpgconf_path,
+ QStringList{"--homedir", target_home_dir, "--reload", "all"},
+ [=, &completed_tasks, &results](int exit_code, const QString &,
+ const QString &) {
+ FLOG_D("gpgconf reload exit code: %d", exit_code);
+ results[current_index] = exit_code;
+
+ if (++completed_tasks == total_tasks && cb) {
+ int final_result =
+ std::all_of(results.begin(), results.end(),
+ [](int result) { return result >= 0; })
+ ? 0
+ : -1;
+ cb(final_result, TransferParams());
+ }
+ }});
+ }
}
-void GpgFrontend::GpgAdvancedOperator::KillAllGpgComponents() {
+void GpgFrontend::GpgAdvancedOperator::KillAllGpgComponents(
+ OperationCallback cb) {
const auto gpgconf_path = Module::RetrieveRTValueTypedOrDefault<>(
"core", "gpgme.ctx.gpgconf_path", QString{});
if (gpgconf_path.isEmpty()) {
FLOG_W("cannot get valid gpgconf path from rt, abort.");
+ if (cb) cb(-1, TransferParams());
return;
}
- GpgFrontend::GpgCommandExecutor::ExecuteSync(
- {gpgconf_path, QStringList{"--verbose", "--kill", "all"},
- [=](int exit_code, const QString &p_out, const QString &p_err) {
- bool success = true;
- if (exit_code != 0) {
- success = false;
- LOG_W() << "gpgconf execute error, process stderr: " << p_err
- << ", process stdout: " << p_out;
- return;
- }
-
- FLOG_D("gpgconf --kill --all execute result: %d", success);
- }});
+ auto key_dbs = GetGpgKeyDatabaseInfos();
+ auto total_tasks = static_cast<int>(key_dbs.size());
+ std::atomic<int> completed_tasks{0};
+ std::vector<int> results(total_tasks, 0);
+
+ int task_index = 0;
+ for (const auto &key_db : key_dbs) {
+ const int current_index = task_index++;
+ const auto target_home_dir =
+ QDir::toNativeSeparators(QFileInfo(key_db.path).canonicalFilePath());
+
+ LOG_D() << "closing all gpg component at home path: " << target_home_dir;
+ GpgFrontend::GpgCommandExecutor::ExecuteSync(
+ {gpgconf_path,
+ QStringList{"--homedir", target_home_dir, "--kill", "all"},
+ [=, &completed_tasks, &results](int exit_code, const QString &p_out,
+ const QString &p_err) {
+ FLOG_D("gpgconf --kill --all exit code: %d", exit_code);
+
+ results[current_index] = exit_code;
+
+ if (++completed_tasks == total_tasks && cb) {
+ int final_result =
+ std::all_of(results.begin(), results.end(),
+ [](int result) { return result >= 0; })
+ ? 0
+ : -1;
+ cb(final_result, TransferParams());
+ }
+ }});
+ }
}
-void GpgFrontend::GpgAdvancedOperator::RestartGpgComponents() {
+void GpgFrontend::GpgAdvancedOperator::RestartGpgComponents(
+ OperationCallback cb) {
const auto gpgconf_path = Module::RetrieveRTValueTypedOrDefault<>(
"core", "gpgme.ctx.gpgconf_path", QString{});
if (gpgconf_path.isEmpty()) {
FLOG_W("cannot get valid gpgconf path from rt, abort.");
+ if (cb) cb(-1, TransferParams());
return;
}
- GpgFrontend::GpgCommandExecutor::ExecuteSync(
- {gpgconf_path, QStringList{"--verbose", "--kill", "all"},
- [=](int exit_code, const QString &p_out, const QString &p_err) {
- FLOG_D("gpgconf --kill all command got exit code: %d", exit_code);
- bool success = true;
- if (exit_code != 0) {
- success = false;
- LOG_W() << "gpgconf execute error, process stderr: " << p_err
- << ", process stdout: " << p_out;
- return;
- }
-
- FLOG_D("gpgconf --kill --all execute result: %d", success);
- if (!success) {
- FLOG_W("restart all component after core initalized failed");
- Module::UpsertRTValue(
- "core", "gpg_advanced_operator.restart_gpg_components", false);
- return;
- }
-
-#if defined(__APPLE__) && defined(__MACH__)
- FLOG_I("getting gpg-agent to start automatically on macOS");
-#else
- StartGpgAgent([](int err, DataObjectPtr) {
- if (err >= 0) {
- Module::UpsertRTValue(
- "core", "gpg_advanced_operator.restart_gpg_components", true);
- return;
- }
- });
-#endif
- }});
+ KillAllGpgComponents(nullptr);
+
+ LaunchGpgComponents(cb);
}
void GpgFrontend::GpgAdvancedOperator::ResetConfigures(OperationCallback cb) {
@@ -151,92 +187,81 @@ void GpgFrontend::GpgAdvancedOperator::ResetConfigures(OperationCallback cb) {
if (gpgconf_path.isEmpty()) {
FLOG_W("cannot get valid gpgconf path from rt, abort.");
- cb(-1, TransferParams());
+ if (cb) cb(-1, TransferParams());
return;
}
- GpgFrontend::GpgCommandExecutor::ExecuteSync(
- {gpgconf_path, QStringList{"--apply-defaults"},
- [=](int exit_code, const QString &, const QString &) {
- FLOG_D("gpgconf apply-defaults exit code: %d", exit_code);
- cb(exit_code == 0 ? 0 : -1, TransferParams());
- }});
-}
-
-void GpgFrontend::GpgAdvancedOperator::StartGpgAgent(OperationCallback cb) {
- if (!Module::IsModuleActivate(kGnuPGInfoGatheringModuleID)) {
- cb(-1, TransferParams());
- return;
- }
-
- const auto gpg_agent_path = Module::RetrieveRTValueTypedOrDefault<>(
- kGnuPGInfoGatheringModuleID, "gnupg.gpg_agent_path", QString{});
-
- const auto home_path = Module::RetrieveRTValueTypedOrDefault<>(
- kGnuPGInfoGatheringModuleID, "gnupg.home_path", QString{});
-
- if (gpg_agent_path.isEmpty()) {
- FLOG_W("cannot get valid gpg agent path from rt, abort.");
- cb(-1, TransferParams());
- return;
+ auto key_dbs = GetGpgKeyDatabaseInfos();
+ auto total_tasks = static_cast<int>(key_dbs.size());
+ std::atomic<int> completed_tasks{0};
+ std::vector<int> results(total_tasks, 0);
+
+ int task_index = 0;
+ for (const auto &key_db : key_dbs) {
+ const int current_index = task_index++;
+ const auto target_home_dir =
+ QDir::toNativeSeparators(QFileInfo(key_db.path).canonicalFilePath());
+
+ GpgFrontend::GpgCommandExecutor::ExecuteSync(
+ {gpgconf_path,
+ QStringList{"--homedir", target_home_dir, "--apply-defaults"},
+ [=, &completed_tasks, &results](int exit_code, const QString &,
+ const QString &) {
+ FLOG_D("gpgconf --apply-defaults exit code: %d", exit_code);
+
+ results[current_index] = exit_code;
+
+ if (++completed_tasks == total_tasks && cb) {
+ int final_result =
+ std::all_of(results.begin(), results.end(),
+ [](int result) { return result >= 0; })
+ ? 0
+ : -1;
+ cb(final_result, TransferParams());
+ }
+ }});
}
-
- GpgFrontend::GpgCommandExecutor::ExecuteSync(
- {gpg_agent_path, QStringList{"--homedir", home_path, "--daemon"},
- [=](int exit_code, const QString &, const QString &) {
- FLOG_D("gpg-agent daemon exit code: %d", exit_code);
- cb(exit_code >= 0 ? 0 : -1, TransferParams());
- }});
}
-void GpgFrontend::GpgAdvancedOperator::StartDirmngr(OperationCallback cb) {
- if (!Module::IsModuleActivate(kGnuPGInfoGatheringModuleID)) {
- cb(-1, TransferParams());
- return;
- }
-
- const auto dirmngr_path = Module::RetrieveRTValueTypedOrDefault<>(
- kGnuPGInfoGatheringModuleID, "gnupg.dirmngr_path", QString{});
-
- const auto home_path = Module::RetrieveRTValueTypedOrDefault<>(
- kGnuPGInfoGatheringModuleID, "gnupg.home_path", QString{});
-
- if (dirmngr_path.isEmpty()) {
- FLOG_W("cannot get valid dirmngr path from rt, abort.");
- cb(-1, TransferParams());
- return;
- }
-
- GpgFrontend::GpgCommandExecutor::ExecuteSync(
- {dirmngr_path, QStringList{"--homedir", home_path, "--daemon"},
- [=](int exit_code, const QString &, const QString &) {
- FLOG_D("gpgconf daemon exit code: %d", exit_code);
- cb(exit_code >= 0 ? 0 : -1, TransferParams());
- }});
-}
+void GpgFrontend::GpgAdvancedOperator::LaunchGpgComponents(
+ OperationCallback cb) {
+ const auto gpgconf_path = Module::RetrieveRTValueTypedOrDefault<>(
+ "core", "gpgme.ctx.gpgconf_path", QString{});
-void GpgFrontend::GpgAdvancedOperator::StartKeyBoxd(OperationCallback cb) {
- if (!Module::IsModuleActivate(kGnuPGInfoGatheringModuleID)) {
- cb(-1, TransferParams());
+ if (gpgconf_path.isEmpty()) {
+ FLOG_W("cannot get valid gpgconf path from rt, abort.");
+ if (cb) cb(-1, TransferParams());
return;
}
- const auto keyboxd_path = Module::RetrieveRTValueTypedOrDefault<>(
- kGnuPGInfoGatheringModuleID, "gnupg.keyboxd_path", QString{});
-
- const auto home_path = Module::RetrieveRTValueTypedOrDefault<>(
- kGnuPGInfoGatheringModuleID, "gnupg.home_path", QString{});
-
- if (keyboxd_path.isEmpty()) {
- FLOG_W("cannot get valid keyboxd path from rt, abort.");
- cb(-1, TransferParams());
- return;
+ auto key_dbs = GetGpgKeyDatabaseInfos();
+ auto total_tasks = static_cast<int>(key_dbs.size());
+ std::atomic<int> completed_tasks{0};
+ std::vector<int> results(total_tasks, 0);
+
+ int task_index = 0;
+ for (const auto &key_db : key_dbs) {
+ const int current_index = task_index++;
+ const auto target_home_dir =
+ QDir::toNativeSeparators(QFileInfo(key_db.path).canonicalFilePath());
+
+ GpgFrontend::GpgCommandExecutor::ExecuteSync(
+ {gpgconf_path,
+ QStringList{"--homedir", target_home_dir, "--launch", "all"},
+ [=, &completed_tasks, &results](int exit_code, const QString &,
+ const QString &) {
+ FLOG_D("gpgconf --launch all exit code: %d", exit_code);
+
+ results[current_index] = exit_code;
+
+ if (++completed_tasks == total_tasks && cb) {
+ int final_result =
+ std::all_of(results.begin(), results.end(),
+ [](int result) { return result >= 0; })
+ ? 0
+ : -1;
+ cb(final_result, TransferParams());
+ }
+ }});
}
-
- GpgFrontend::GpgCommandExecutor::ExecuteSync(
- {keyboxd_path, QStringList{"--homedir", home_path, "--daemon"},
- [=](int exit_code, const QString &, const QString &) {
- FLOG_D("gpgconf daemon exit code: %d", exit_code);
- cb(exit_code >= 0 ? 0 : -1, TransferParams());
- }});
}
diff --git a/src/core/function/gpg/GpgAdvancedOperator.h b/src/core/function/gpg/GpgAdvancedOperator.h
index 1be2c2e4..cfd5fbcf 100644
--- a/src/core/function/gpg/GpgAdvancedOperator.h
+++ b/src/core/function/gpg/GpgAdvancedOperator.h
@@ -60,7 +60,7 @@ class GPGFRONTEND_CORE_EXPORT GpgAdvancedOperator {
* @return true
* @return false
*/
- static void RestartGpgComponents();
+ static void RestartGpgComponents(OperationCallback);
/**
* @brief
@@ -76,29 +76,13 @@ class GPGFRONTEND_CORE_EXPORT GpgAdvancedOperator {
* @return true
* @return false
*/
- static void StartGpgAgent(OperationCallback);
-
- /**
- * @brief
- *
- * @return true
- * @return false
- */
- static void StartDirmngr(OperationCallback);
-
- /**
- * @brief
- *
- * @return true
- * @return false
- */
- static void StartKeyBoxd(OperationCallback);
+ static void LaunchGpgComponents(OperationCallback);
/**
* @brief
*
*/
- static void KillAllGpgComponents();
+ static void KillAllGpgComponents(OperationCallback);
};
} // namespace GpgFrontend
diff --git a/src/init.cpp b/src/init.cpp
index e1668ec5..54745d65 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -184,18 +184,30 @@ void ShutdownGlobalBasicEnv(const GFCxtWPtr &p_ctx) {
}
auto clear_gpg_password_cache =
- GlobalSettingStation::GetInstance()
- .GetSettings()
- .value("basic/clear_gpg_password_cache", false)
+ GetSettings().value("basic/clear_gpg_password_cache", false).toBool();
+
+ auto kill_all_gnupg_daemon_at_close =
+ GetSettings()
+ .value("gnupg/kill_all_gnupg_daemon_at_close", false)
.toBool();
- // clear password cache
- if (!ctx->unit_test_mode && clear_gpg_password_cache) {
- GpgAdvancedOperator::ClearGpgPasswordCache([](int, DataObjectPtr) {});
+
+ if (!ctx->unit_test_mode && kill_all_gnupg_daemon_at_close) {
+ GpgAdvancedOperator::KillAllGpgComponents(nullptr);
+ } else if (!ctx->unit_test_mode && clear_gpg_password_cache) {
+ GpgAdvancedOperator::ClearGpgPasswordCache(nullptr);
}
- Thread::TaskRunnerGetter::GetInstance().StopAllTeakRunner();
+ // first should shutdown the module system
+ GpgFrontend::Module::ShutdownGpgFrontendModules();
+
+ // then shutdown the core
+ GpgFrontend::DestroyGpgFrontendCore();
- DestroyGpgFrontendCore();
+ // deep restart mode
+ if (ctx->rtn == GpgFrontend::kDeepRestartCode ||
+ ctx->rtn == GpgFrontend::kCrashCode) {
+ QProcess::startDetached(qApp->arguments()[0], qApp->arguments());
+ };
}
} // namespace GpgFrontend
diff --git a/src/ui/main_window/MainWindow.cpp b/src/ui/main_window/MainWindow.cpp
index 4817cbcd..b32d9c94 100644
--- a/src/ui/main_window/MainWindow.cpp
+++ b/src/ui/main_window/MainWindow.cpp
@@ -30,11 +30,12 @@
#include "core/function/CacheManager.h"
#include "core/function/GlobalSettingStation.h"
+#include "core/function/gpg/GpgAdvancedOperator.h"
#include "core/model/SettingsObject.h"
#include "core/module/ModuleManager.h"
-#include "struct/settings_object/AppearanceSO.h"
#include "ui/UISignalStation.h"
#include "ui/main_window/GeneralMainWindow.h"
+#include "ui/struct/settings_object/AppearanceSO.h"
#include "ui/struct/settings_object/KeyServerSO.h"
#include "ui/widgets/KeyList.h"
#include "ui/widgets/TextEdit.h"
@@ -274,10 +275,6 @@ void MainWindow::closeEvent(QCloseEvent* event) {
}
if (event->isAccepted()) {
- // clear cache of unsaved page
- CacheManager::GetInstance().SaveDurableCache(
- "editor_unsaved_pages", QJsonDocument(QJsonArray()), true);
-
// call parent
GeneralMainWindow::closeEvent(event);
}
diff --git a/src/ui/main_window/MainWindowSlotUI.cpp b/src/ui/main_window/MainWindowSlotUI.cpp
index dc282c64..7ce0024e 100644
--- a/src/ui/main_window/MainWindowSlotUI.cpp
+++ b/src/ui/main_window/MainWindowSlotUI.cpp
@@ -330,12 +330,9 @@ void MainWindow::slot_reload_gpg_components(bool) {
}
void MainWindow::slot_restart_gpg_components(bool) {
- GpgFrontend::GpgAdvancedOperator::RestartGpgComponents();
- Module::ListenRTPublishEvent(
- this, "core", "gpg_advanced_operator.restart_gpg_components",
- [=](Module::Namespace, Module::Key, int, std::any value) {
- bool success_state = std::any_cast<bool>(value);
- if (success_state) {
+ GpgFrontend::GpgAdvancedOperator::RestartGpgComponents(
+ [=](int err, DataObjectPtr) {
+ if (err >= 0) {
QMessageBox::information(
this, tr("Successful Operation"),
tr("Restart all the GnuPG's components successfully"));
diff --git a/src/ui/struct/GpgOperaResult.cpp b/src/ui/struct/GpgOperaResult.cpp
new file mode 100644
index 00000000..9d612cc3
--- /dev/null
+++ b/src/ui/struct/GpgOperaResult.cpp
@@ -0,0 +1,36 @@
+/**
+ * Copyright (C) 2021-2024 Saturneric <[email protected]>
+ *
+ * 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 "GpgOperaResult.h"
+
+namespace GpgFrontend::UI {
+
+GpgOperaResult::GpgOperaResult(int status, QString report, QString tag)
+ : status(status), report(std::move(report)), tag(std::move(tag)) {}
+
+} // namespace GpgFrontend::UI \ No newline at end of file
diff --git a/src/ui/struct/GpgOperaResult.h b/src/ui/struct/GpgOperaResult.h
index e3bfd61a..7ee6ad37 100644
--- a/src/ui/struct/GpgOperaResult.h
+++ b/src/ui/struct/GpgOperaResult.h
@@ -1,5 +1,3 @@
-#include <utility>
-
/**
* Copyright (C) 2021-2024 Saturneric <[email protected]>
*
@@ -37,8 +35,7 @@ struct GpgOperaResult {
QString report;
QString tag;
- GpgOperaResult(int status, QString report, QString tag)
- : status(status), report(std::move(report)), tag(std::move(tag)) {}
+ GpgOperaResult(int status, QString report, QString tag);
};
} // namespace GpgFrontend::UI \ No newline at end of file
diff --git a/src/ui/struct/GpgOperaResultContext.cpp b/src/ui/struct/GpgOperaResultContext.cpp
new file mode 100644
index 00000000..c36d0ec6
--- /dev/null
+++ b/src/ui/struct/GpgOperaResultContext.cpp
@@ -0,0 +1,83 @@
+/**
+ * Copyright (C) 2021-2024 Saturneric <[email protected]>
+ *
+ * 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 "GpgOperaResultContext.h"
+
+namespace GpgFrontend::UI {
+
+GpgOperaContext::GpgOperaContext(QContainer<OperaWaitingCb>& operas,
+ QContainer<GpgOperaResult>& opera_results,
+ GpgKeyList& keys, GpgKeyList& singer_keys,
+ QStringList& unknown_fprs)
+ : operas(operas),
+ opera_results(opera_results),
+ keys(keys),
+ singer_keys(singer_keys),
+ unknown_fprs(unknown_fprs) {}
+
+auto GpgOperaContexts::GetContextPath(int category) -> QStringList& {
+ if (!categories.contains(category)) categories[category] = {};
+ return categories[category].paths;
+}
+
+auto GpgOperaContexts::GetContextOutPath(int category) -> QStringList& {
+ if (!categories.contains(category)) categories[category] = {};
+ return categories[category].o_paths;
+}
+
+auto GpgOperaContexts::GetAllPath() -> QStringList {
+ QStringList res;
+
+ for (auto& category : categories) {
+ res.append(category.paths);
+ }
+ return res;
+}
+
+auto GpgOperaContexts::GetAllOutPath() -> QStringList {
+ QStringList res;
+
+ for (auto& category : categories) {
+ res.append(category.o_paths);
+ }
+ return res;
+}
+
+auto GpgOperaContexts::GetContext(int category)
+ -> QSharedPointer<GpgOperaContext> {
+ if (GetContextPath(category).empty()) return nullptr;
+
+ auto context = QSharedPointer<GpgOperaContext>::create(
+ operas, opera_results, keys, singer_keys, unknown_fprs);
+ context->ascii = ascii;
+
+ context->paths = GetContextPath(category);
+ context->o_paths = GetContextOutPath(category);
+ return context;
+}
+} // namespace GpgFrontend::UI \ No newline at end of file
diff --git a/src/ui/struct/GpgOperaResultContext.h b/src/ui/struct/GpgOperaResultContext.h
index ca68dde1..be245bad 100644
--- a/src/ui/struct/GpgOperaResultContext.h
+++ b/src/ui/struct/GpgOperaResultContext.h
@@ -1,5 +1,3 @@
-#include <utility>
-
/**
* Copyright (C) 2021-2024 Saturneric <[email protected]>
*
@@ -53,12 +51,7 @@ struct GpgOperaContext {
GpgOperaContext(QContainer<OperaWaitingCb>& operas,
QContainer<GpgOperaResult>& opera_results, GpgKeyList& keys,
- GpgKeyList& singer_keys, QStringList& unknown_fprs)
- : operas(operas),
- opera_results(opera_results),
- keys(keys),
- singer_keys(singer_keys),
- unknown_fprs(unknown_fprs) {}
+ GpgKeyList& singer_keys, QStringList& unknown_fprs);
};
struct GpgOperaContexts {
@@ -71,45 +64,15 @@ struct GpgOperaContexts {
QMap<int, GpgOperaCategory> categories;
- auto GetContextPath(int category) -> QStringList& {
- if (!categories.contains(category)) categories[category] = {};
- return categories[category].paths;
- }
-
- auto GetContextOutPath(int category) -> QStringList& {
- if (!categories.contains(category)) categories[category] = {};
- return categories[category].o_paths;
- }
-
- auto GetAllPath() -> QStringList {
- QStringList res;
-
- for (auto& category : categories) {
- res.append(category.paths);
- }
- return res;
- }
-
- auto GetAllOutPath() -> QStringList {
- QStringList res;
+ auto GetContextPath(int category) -> QStringList&;
- for (auto& category : categories) {
- res.append(category.o_paths);
- }
- return res;
- }
+ auto GetContextOutPath(int category) -> QStringList&;
- auto GetContext(int category) -> QSharedPointer<GpgOperaContext> {
- if (GetContextPath(category).empty()) return nullptr;
+ auto GetAllPath() -> QStringList;
- auto context = QSharedPointer<GpgOperaContext>::create(
- operas, opera_results, keys, singer_keys, unknown_fprs);
- context->ascii = ascii;
+ auto GetAllOutPath() -> QStringList;
- context->paths = GetContextPath(category);
- context->o_paths = GetContextOutPath(category);
- return context;
- }
+ auto GetContext(int category) -> QSharedPointer<GpgOperaContext>;
};
} // namespace GpgFrontend::UI \ No newline at end of file