diff options
author | saturneric <[email protected]> | 2023-12-03 20:25:21 +0000 |
---|---|---|
committer | saturneric <[email protected]> | 2023-12-03 20:25:21 +0000 |
commit | 054e6e28cca2517dda2319ef683314b3318c39a6 (patch) | |
tree | ae9ff4a9fe280f3640ca249bad45ab250cfd1610 | |
parent | fix: slove issues in key/subkey generation (diff) | |
download | GpgFrontend-054e6e28cca2517dda2319ef683314b3318c39a6.tar.gz GpgFrontend-054e6e28cca2517dda2319ef683314b3318c39a6.zip |
feat: standarized and speed up app env loading process
Diffstat (limited to '')
35 files changed, 805 insertions, 538 deletions
diff --git a/src/app.cpp b/src/app.cpp index 1213aebd..8df46024 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -79,7 +79,7 @@ auto StartApplication(InitArgs args) -> int { args.argc, args.argv, true); // init the logging system for main - InitModules(args); + InitLoggingSystem(args); // change path to search for related InitGlobalPathEnv(); @@ -98,10 +98,18 @@ auto StartApplication(InitArgs args) -> int { int r = setjmp(recover_env); #endif if (!r) { - // init ui library + // should load module system first + GpgFrontend::Module::ModuleInitArgs module_init_args; + module_init_args.log_level = args.log_level; + GpgFrontend::Module::LoadGpgFrontendModules(module_init_args); + + // then load core + GpgFrontend::InitGpgFrontendCore(); + + // after that load ui library GpgFrontend::UI::InitGpgFrontendUI(app); - // create main window + // finally create main window return_from_event_loop_code = GpgFrontend::UI::RunGpgFrontendUI(app); } else { SPDLOG_ERROR("recover from a crash"); @@ -117,6 +125,16 @@ auto StartApplication(InitArgs args) -> int { return_from_event_loop_code = kCrashCode; } + SPDLOG_DEBUG("try to destroy modules system and core"); + + // first should shutdown the module system + GpgFrontend::Module::ShutdownGpgFrontendModules(); + + // then shutdown the core + GpgFrontend::DestroyGpgFrontendCore(); + + SPDLOG_DEBUG("core and modules system destroyed"); + restart_count++; SPDLOG_DEBUG("restart loop refresh, event loop code: {}, restart count: {}", @@ -125,7 +143,7 @@ auto StartApplication(InitArgs args) -> int { restart_count < 3); // close logging system - ShutdownModules(); + ShutdownLoggingSystem(); // log for debug SPDLOG_INFO("GpgFrontend is about to exit."); diff --git a/src/cmd.cpp b/src/cmd.cpp index 66e2604f..24080a08 100644 --- a/src/cmd.cpp +++ b/src/cmd.cpp @@ -36,6 +36,7 @@ // GpgFrontend #include "GpgFrontendBuildInfo.h" +#include "spdlog/common.h" namespace po = boost::program_options; @@ -61,13 +62,19 @@ auto ParseLogLevel(const po::variables_map& vm) -> spdlog::level::level_enum { if (log_level == "trace") { return spdlog::level::trace; - } else if (log_level == "debug") { + } + if (log_level == "debug") { return spdlog::level::debug; - } else if (log_level == "info") { + } + if (log_level == "info") { return spdlog::level::info; - } else if (log_level == "warn") { + } + if (log_level == "warn") { return spdlog::level::warn; - } else if (log_level == "error") { + } + if (log_level == "error") { return spdlog::level::err; } + + return spdlog::level::info; }
\ No newline at end of file diff --git a/src/core/GpgCoreInit.cpp b/src/core/GpgCoreInit.cpp index 09b3a0ec..dcd0dcfb 100644 --- a/src/core/GpgCoreInit.cpp +++ b/src/core/GpgCoreInit.cpp @@ -27,6 +27,7 @@ */ #include "GpgCoreInit.h" +#include <gpgme.h> #include <spdlog/async.h> #include <spdlog/common.h> #include <spdlog/sinks/rotating_file_sink.h> @@ -35,15 +36,19 @@ #include <boost/date_time.hpp> #include "core/function/GlobalSettingStation.h" +#include "core/function/basic/ChannelObject.h" +#include "core/function/basic/SingletonStorage.h" #include "core/function/gpg/GpgAdvancedOperator.h" #include "core/function/gpg/GpgContext.h" #include "core/module/ModuleManager.h" #include "core/thread/Task.h" #include "core/thread/TaskRunner.h" #include "core/thread/TaskRunnerGetter.h" +#include "core/utils/CommonUtils.h" +#include "core/utils/GpgUtils.h" #include "core/utils/MemoryUtils.h" -#include "function/basic/ChannelObject.h" -#include "function/basic/SingletonStorage.h" +#include "function/CoreSignalStation.h" +#include "function/gpg/GpgKeyGetter.h" namespace GpgFrontend { @@ -99,123 +104,206 @@ void ShutdownCoreLoggingSystem() { #endif } -void ResetGpgFrontendCore() { reset_gpgfrontend_core(); } +void DestroyGpgFrontendCore() { + SingletonStorageCollection::Destroy(); + ShutdownCoreLoggingSystem(); +} + +auto InitGpgME() -> bool { + // init gpgme subsystem and get gpgme library version + Module::UpsertRTValue("core", "gpgme.version", + std::string(gpgme_check_version(nullptr))); -void InitGpgFrontendCore() { - /* Initialize the locale environment. */ - SPDLOG_DEBUG("locale: {}", setlocale(LC_CTYPE, nullptr)); - // init gpgme subsystem - gpgme_check_version(nullptr); gpgme_set_locale(nullptr, LC_CTYPE, setlocale(LC_CTYPE, nullptr)); #ifdef LC_MESSAGES gpgme_set_locale(nullptr, LC_MESSAGES, setlocale(LC_MESSAGES, nullptr)); #endif - // read settings - bool forbid_all_gnupg_connection = - GlobalSettingStation::GetInstance().LookupSettings( - "network.forbid_all_gnupg_connection", false); - - bool auto_import_missing_key = - GlobalSettingStation::GetInstance().LookupSettings( - "network.auto_import_missing_key", false); - - bool use_custom_key_database_path = - GlobalSettingStation::GetInstance().LookupSettings( - "general.use_custom_key_database_path", false); + gpgme_ctx_t p_ctx; + + CheckGpgError(gpgme_new(&p_ctx)); + + // get engine info + auto* engine_info = gpgme_ctx_get_engine_info(p_ctx); + // Check ENV before running + bool find_openpgp = false; + bool find_gpgconf = false; + bool find_cms = false; + + while (engine_info != nullptr) { + if (strcmp(engine_info->version, "1.0.0") == 0) { + engine_info = engine_info->next; + continue; + } + + SPDLOG_DEBUG( + "gpg context engine info: {} {} {} {}", + gpgme_get_protocol_name(engine_info->protocol), + std::string(engine_info->file_name == nullptr ? "null" + : engine_info->file_name), + std::string(engine_info->home_dir == nullptr ? "null" + : engine_info->home_dir), + std::string(engine_info->version ? "null" : engine_info->version)); + + switch (engine_info->protocol) { + case GPGME_PROTOCOL_OpenPGP: + find_openpgp = true; + + Module::UpsertRTValue("core", "gpgme.engine.openpgp", "1"); + Module::UpsertRTValue("core", "gpgme.ctx.app_path", + std::string(engine_info->file_name)); + Module::UpsertRTValue("core", "gpgme.ctx.gnupg_version", + std::string(engine_info->version)); + Module::UpsertRTValue("core", "gpgme.ctx.database_path", + std::string(engine_info->home_dir == nullptr + ? "default" + : engine_info->home_dir)); + break; + case GPGME_PROTOCOL_CMS: + find_cms = true; + Module::UpsertRTValue("core", "gpgme.engine.cms", "1"); + Module::UpsertRTValue("core", "gpgme.ctx.cms_path", + std::string(engine_info->file_name)); + + break; + case GPGME_PROTOCOL_GPGCONF: + find_gpgconf = true; + + Module::UpsertRTValue("core", "gpgme.engine.gpgconf", "1"); + Module::UpsertRTValue("core", "gpgme.ctx.gpgconf_path", + std::string(engine_info->file_name)); + break; + case GPGME_PROTOCOL_ASSUAN: + + Module::UpsertRTValue("core", "gpgme.engine.assuan", "1"); + Module::UpsertRTValue("core", "gpgme.ctx.assuan_path", + std::string(engine_info->file_name)); + break; + case GPGME_PROTOCOL_G13: + break; + case GPGME_PROTOCOL_UISERVER: + break; + case GPGME_PROTOCOL_SPAWN: + break; + case GPGME_PROTOCOL_DEFAULT: + break; + case GPGME_PROTOCOL_UNKNOWN: + break; + } + engine_info = engine_info->next; + } - std::string custom_key_database_path = - GlobalSettingStation::GetInstance().LookupSettings( - "general.custom_key_database_path", std::string{}); + const auto gnupg_version = Module::RetrieveRTValueTypedOrDefault<>( + "core", "gpgme.ctx.gnupg_version", std::string{"0.0.0"}); + SPDLOG_DEBUG("got gnupg version from rt: {}", gnupg_version); - bool use_custom_gnupg_install_path = - GlobalSettingStation::GetInstance().LookupSettings( - "general.use_custom_gnupg_install_path", false); + // conditional check: only support gpg 2.1.x now + if (!(CompareSoftwareVersion(gnupg_version, "2.1.0") >= 0 && find_gpgconf && + find_openpgp && find_cms)) { + SPDLOG_ERROR("gpgme env check failed, abort"); + return false; + } - std::string custom_gnupg_install_path = - GlobalSettingStation::GetInstance().LookupSettings( - "general.custom_gnupg_install_path", std::string{}); + Module::UpsertRTValue("core", "env.state.gpgme", std::string{"1"}); + return true; +} - bool use_pinentry_as_password_input_dialog = - GpgFrontend::GlobalSettingStation::GetInstance().LookupSettings( - "general.use_pinentry_as_password_input_dialog", false); +void InitGpgFrontendCore() { + // initialize global register table + Module::UpsertRTValue("core", "env.state.gpgme", std::string{"0"}); + Module::UpsertRTValue("core", "env.state.ctx", std::string{"0"}); + Module::UpsertRTValue("core", "env.state.gnupg", std::string{"0"}); + Module::UpsertRTValue("core", "env.state.basic", std::string{"0"}); + Module::UpsertRTValue("core", "env.state.all", std::string{"0"}); + + // initialize locale environment + SPDLOG_DEBUG("locale: {}", setlocale(LC_CTYPE, nullptr)); - SPDLOG_DEBUG("core loaded if use custom key databse path: {}", - use_custom_key_database_path); - SPDLOG_DEBUG("core loaded custom key databse path: {}", - custom_key_database_path); + // initialize library gpgme + if (!InitGpgME()) { + CoreSignalStation::GetInstance()->SignalBadGnupgEnv(); + return; + } - // check gpgconf path - std::filesystem::path custom_gnupg_install_fs_path = - custom_gnupg_install_path; + // start the thread to check ctx and gnupg state + // it may take a few seconds or minutes + GpgFrontend::Thread::TaskRunnerGetter::GetInstance() + .GetTaskRunner() + ->PostTask(new Thread::Task( + [](const DataObjectPtr&) -> int { + // read settings from config file + auto forbid_all_gnupg_connection = + GlobalSettingStation::GetInstance().LookupSettings( + "network.forbid_all_gnupg_connection", false); + + auto auto_import_missing_key = + GlobalSettingStation::GetInstance().LookupSettings( + "network.auto_import_missing_key", false); + + auto use_custom_key_database_path = + GlobalSettingStation::GetInstance().LookupSettings( + "general.use_custom_key_database_path", false); + + auto custom_key_database_path = + GlobalSettingStation::GetInstance().LookupSettings( + "general.custom_key_database_path", std::string{}); + + auto use_custom_gnupg_install_path = + GlobalSettingStation::GetInstance().LookupSettings( + "general.use_custom_gnupg_install_path", false); + + auto custom_gnupg_install_path = + GlobalSettingStation::GetInstance().LookupSettings( + "general.custom_gnupg_install_path", std::string{}); + + auto use_pinentry_as_password_input_dialog = + GpgFrontend::GlobalSettingStation::GetInstance().LookupSettings( + "general.use_pinentry_as_password_input_dialog", false); + + SPDLOG_DEBUG("core loaded if use custom key databse path: {}", + use_custom_key_database_path); + SPDLOG_DEBUG("core loaded custom key databse path: {}", + custom_key_database_path); + + // check gpgconf path + std::filesystem::path custom_gnupg_install_fs_path = + custom_gnupg_install_path; #ifdef WINDOWS - custom_gnupg_install_fs_path /= "gpgconf.exe"; + custom_gnupg_install_fs_path /= "gpgconf.exe"; #else - custom_gnupg_install_fs_path /= "gpgconf"; + custom_gnupg_install_fs_path /= "gpgconf"; #endif - if (!custom_gnupg_install_fs_path.is_absolute() || - !std::filesystem::exists(custom_gnupg_install_fs_path) || - !std::filesystem::is_regular_file(custom_gnupg_install_fs_path)) { - use_custom_gnupg_install_path = false; - SPDLOG_ERROR("core loaded custom gpgconf path is illegal: {}", - custom_gnupg_install_fs_path.u8string()); - } else { - SPDLOG_DEBUG("core loaded custom gpgconf path: {}", - custom_gnupg_install_fs_path.u8string()); - } - - // check key database path - std::filesystem::path custom_key_database_fs_path = custom_key_database_path; - if (!custom_key_database_fs_path.is_absolute() || - !std::filesystem::exists(custom_key_database_fs_path) || - !std::filesystem::is_directory(custom_key_database_fs_path)) { - use_custom_key_database_path = false; - SPDLOG_ERROR("core loaded custom gpg key database is illegal: {}", - custom_key_database_fs_path.u8string()); - } else { - SPDLOG_DEBUG("core loaded custom gpg key database path: {}", - custom_key_database_fs_path.u8string()); - } - - // init default channel - auto& default_ctx = GpgFrontend::GpgContext::CreateInstance( - kGpgfrontendDefaultChannel, [=]() -> ChannelObjectPtr { - GpgFrontend::GpgContextInitArgs args; - - // set key database path - if (use_custom_key_database_path && !custom_key_database_path.empty()) { - args.db_path = custom_key_database_path; - } - - if (use_custom_gnupg_install_path) { - args.custom_gpgconf = true; - args.custom_gpgconf_path = custom_gnupg_install_fs_path.u8string(); - } - - args.offline_mode = forbid_all_gnupg_connection; - args.auto_import_missing_key = auto_import_missing_key; - args.use_pinentry = use_pinentry_as_password_input_dialog; - - return ConvertToChannelObjectPtr<>(SecureCreateUniqueObject<GpgContext>( - args, kGpgFrontendDefaultChannel)); - }); - - // exit if failed - if (!default_ctx.Good()) { - SPDLOG_ERROR("default gnupg context init error"); - }; - - // async init no-ascii(binary output) channel - Thread::TaskRunnerGetter::GetInstance() - .GetTaskRunner(Thread::TaskRunnerGetter::kTaskRunnerType_GPG) - ->PostTask(new Thread::Task( - [=](const DataObjectPtr& /*data_obj*/) -> int { - // init non-ascii channel + if (!custom_gnupg_install_fs_path.is_absolute() || + !std::filesystem::exists(custom_gnupg_install_fs_path) || + !std::filesystem::is_regular_file( + custom_gnupg_install_fs_path)) { + use_custom_gnupg_install_path = false; + SPDLOG_ERROR("core loaded custom gpgconf path is illegal: {}", + custom_gnupg_install_fs_path.u8string()); + } else { + SPDLOG_DEBUG("core loaded custom gpgconf path: {}", + custom_gnupg_install_fs_path.u8string()); + } + + // check key database path + std::filesystem::path custom_key_database_fs_path = + custom_key_database_path; + if (!custom_key_database_fs_path.is_absolute() || + !std::filesystem::exists(custom_key_database_fs_path) || + !std::filesystem::is_directory(custom_key_database_fs_path)) { + use_custom_key_database_path = false; + SPDLOG_ERROR("core loaded custom gpg key database is illegal: {}", + custom_key_database_fs_path.u8string()); + } else { + SPDLOG_DEBUG("core loaded custom gpg key database path: {}", + custom_key_database_fs_path.u8string()); + } + + // init ctx, also checking the basical env auto& ctx = GpgFrontend::GpgContext::CreateInstance( - kGpgfrontendNonAsciiChannel, [=]() -> ChannelObjectPtr { + kGpgfrontendDefaultChannel, [=]() -> ChannelObjectPtr { GpgFrontend::GpgContextInitArgs args; - args.ascii = false; // set key database path if (use_custom_key_database_path && @@ -223,6 +311,7 @@ void InitGpgFrontendCore() { args.db_path = custom_key_database_path; } + // set custom gnupg path if (use_custom_gnupg_install_path) { args.custom_gpgconf = true; args.custom_gpgconf_path = @@ -235,31 +324,68 @@ void InitGpgFrontendCore() { return ConvertToChannelObjectPtr<>( SecureCreateUniqueObject<GpgContext>( - args, kGpgfrontendNonAsciiChannel)); + args, kGpgFrontendDefaultChannel)); }); - if (!ctx.Good()) SPDLOG_ERROR("no-ascii channel init error"); - return ctx.Good() ? 0 : -1; + // exit if failed + if (!ctx.Good()) { + SPDLOG_ERROR("default gnupg context init error, abort"); + CoreSignalStation::GetInstance()->SignalBadGnupgEnv(); + return -1; + } + Module::UpsertRTValue("core", "env.state.ctx", std::string{"1"}); + + // if gnupg-info-gathering module activated + if (Module::IsModuleAcivate("com.bktus.gpgfrontend.module." + "integrated.gnupg-info-gathering")) { + SPDLOG_DEBUG("gnupg-info-gathering is activated"); + + // gather external gnupg info + Module::TriggerEvent( + "GPGFRONTEND_CORE_INITLIZED", + [](const Module::EventIdentifier& /*e*/, + const Module::Event::ListenerIdentifier& l_id, + DataObjectPtr o) { + SPDLOG_DEBUG( + "received event GPGFRONTEND_CORE_INITLIZED callback " + "from module: {}", + l_id); + + if (l_id == + "com.bktus.gpgfrontend.module.integrated.gnupg-info-" + "gathering") { + SPDLOG_DEBUG( + "received callback from gnupg-info-gathering "); + + // try to restart all components + GpgFrontend::GpgAdvancedOperator::RestartGpgComponents(); + Module::UpsertRTValue("core", "env.state.gnupg", + std::string{"1"}); + + // announce that all checkings were finished + SPDLOG_INFO( + "all env checking finished, including gpgme, " + "ctx and " + "gnupg"); + Module::UpsertRTValue("core", "env.state.all", + std::string{"1"}); + } + }); + } else { + SPDLOG_DEBUG("gnupg-info-gathering is not activated"); + Module::UpsertRTValue("core", "env.state.all", std::string{"1"}); + } + + GpgKeyGetter::GetInstance().FlushKeyCache(); + SPDLOG_INFO( + "basic env checking finished, including gpgme, ctx, and key " + "infos"); + Module::UpsertRTValue("core", "env.state.basic", std::string{"1"}); + CoreSignalStation::GetInstance()->SignalGoodGnupgEnv(); + + return 0; }, - "default_channel_ctx_init")); - - Module::TriggerEvent( - "GPGFRONTEND_CORE_INITLIZED", - [](const Module::EventIdentifier& /*e*/, - const Module::Event::ListenerIdentifier& l_id, DataObjectPtr o) { - if (l_id == - "com.bktus.gpgfrontend.module.integrated." - "gnupginfogathering") { - SPDLOG_DEBUG( - "gnupg-info-gathering gnupg.gathering_done changed, restarting " - "gpg " - "components"); - // try to restart all components - GpgFrontend::GpgAdvancedOperator::RestartGpgComponents(); - } - }); + "core_init_task")); } -void reset_gpgfrontend_core() { SingletonStorageCollection::GetInstance(true); } - } // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/GpgCoreInit.h b/src/core/GpgCoreInit.h index 0a10a639..7666761a 100644 --- a/src/core/GpgCoreInit.h +++ b/src/core/GpgCoreInit.h @@ -49,7 +49,7 @@ void GPGFRONTEND_CORE_EXPORT ShutdownCoreLoggingSystem(); * @brief * */ -void GPGFRONTEND_CORE_EXPORT ResetGpgFrontendCore(); +void GPGFRONTEND_CORE_EXPORT DestroyGpgFrontendCore(); /** * @brief @@ -57,10 +57,4 @@ void GPGFRONTEND_CORE_EXPORT ResetGpgFrontendCore(); */ void GPGFRONTEND_CORE_EXPORT InitGpgFrontendCore(); -/** - * @brief - * - */ -void reset_gpgfrontend_core(); - } // namespace GpgFrontend diff --git a/src/core/function/CoreSignalStation.h b/src/core/function/CoreSignalStation.h index a53f2eb4..57bd4e44 100644 --- a/src/core/function/CoreSignalStation.h +++ b/src/core/function/CoreSignalStation.h @@ -66,7 +66,13 @@ class GPGFRONTEND_CORE_EXPORT CoreSignalStation : public QObject { * @brief * */ - void SignalGnupgNotInstall(); + void SignalBadGnupgEnv(); + + /** + * @brief + * + */ + void SignalGoodGnupgEnv(); }; } // namespace GpgFrontend diff --git a/src/core/function/basic/GpgFunctionObject.h b/src/core/function/basic/GpgFunctionObject.h index ec0cebac..619cad04 100644 --- a/src/core/function/basic/GpgFunctionObject.h +++ b/src/core/function/basic/GpgFunctionObject.h @@ -79,7 +79,7 @@ class SingletonFunctionObject : public ChannelObject { } } - static_assert(std::is_base_of<SingletonFunctionObject<T>, T>::value, + static_assert(std::is_base_of_v<SingletonFunctionObject<T>, T>, "T not derived from SingletonFunctionObject<T>"); auto* p_storage = @@ -123,7 +123,7 @@ class SingletonFunctionObject : public ChannelObject { */ static auto CreateInstance( int channel, const std::function<ChannelObjectPtr(void)>& factory) -> T& { - static_assert(std::is_base_of<SingletonFunctionObject<T>, T>::value, + static_assert(std::is_base_of_v<SingletonFunctionObject<T>, T>, "T not derived from SingletonFunctionObject<T>"); auto* p_storage = diff --git a/src/core/function/basic/SingletonStorageCollection.cpp b/src/core/function/basic/SingletonStorageCollection.cpp index 144b69e2..e69c1279 100644 --- a/src/core/function/basic/SingletonStorageCollection.cpp +++ b/src/core/function/basic/SingletonStorageCollection.cpp @@ -28,6 +28,7 @@ #include "SingletonStorageCollection.h" +#include <memory> #include <shared_mutex> #include "core/function/basic/SingletonStorage.h" @@ -35,6 +36,10 @@ namespace GpgFrontend { +std::unique_ptr<SingletonStorageCollection, + SecureObjectDeleter<SingletonStorageCollection>> + instance = nullptr; + class SingletonStorageCollection::Impl { public: /** @@ -43,18 +48,22 @@ class SingletonStorageCollection::Impl { * @return SingletonStorageCollection* */ static auto GetInstance(bool force_refresh) -> SingletonStorageCollection* { - static SingletonStorageCollection* instance = nullptr; - if (force_refresh || instance == nullptr) { - instance = new SingletonStorageCollection(); - SPDLOG_TRACE("new single storage collection created: {}", - static_cast<void*>(instance)); + instance = SecureCreateUniqueObject<SingletonStorageCollection>(); + SPDLOG_TRACE("a new single storage collection created, address: {}", + static_cast<void*>(instance.get())); } - - return instance; + return instance.get(); } /** + * @brief Get the Instance object + * + * @return SingletonStorageCollection* + */ + static void Destroy() { instance = nullptr; } + + /** * @brief Get the Singleton Storage object * * @param singleton_function_object @@ -95,14 +104,18 @@ SingletonStorageCollection::SingletonStorageCollection() noexcept SingletonStorageCollection::~SingletonStorageCollection() = default; +auto GpgFrontend::SingletonStorageCollection::GetInstance(bool force_refresh) + -> GpgFrontend::SingletonStorageCollection* { + return Impl::GetInstance(force_refresh); +} + +void SingletonStorageCollection::Destroy() { + return SingletonStorageCollection::Impl::Destroy(); +} + auto SingletonStorageCollection::GetSingletonStorage( const std::type_info& type_id) -> GpgFrontend::SingletonStorage* { return p_->GetSingletonStorage(type_id); } -auto GpgFrontend::SingletonStorageCollection::GetInstance( - bool force_refresh = false) -> GpgFrontend::SingletonStorageCollection* { - return Impl::GetInstance(force_refresh); -} - } // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/function/basic/SingletonStorageCollection.h b/src/core/function/basic/SingletonStorageCollection.h index b96bff3d..70b91cb9 100644 --- a/src/core/function/basic/SingletonStorageCollection.h +++ b/src/core/function/basic/SingletonStorageCollection.h @@ -28,8 +28,6 @@ #pragma once -#include <core/function/SecureMemoryAllocator.h> - #include "core/function/SecureMemoryAllocator.h" namespace GpgFrontend { @@ -41,6 +39,18 @@ using SingletonStoragePtr = class GPGFRONTEND_CORE_EXPORT SingletonStorageCollection { public: /** + * @brief + * + */ + SingletonStorageCollection() noexcept; + + /** + * @brief + * + */ + ~SingletonStorageCollection(); + + /** * @brief Get the Instance object * * @return SingletonStorageCollection* @@ -48,6 +58,12 @@ class GPGFRONTEND_CORE_EXPORT SingletonStorageCollection { static auto GetInstance(bool force_refresh) -> SingletonStorageCollection*; /** + * @brief + * + */ + static void Destroy(); + + /** * @brief Get the Singleton Storage object * * @param singleton_function_object @@ -58,18 +74,6 @@ class GPGFRONTEND_CORE_EXPORT SingletonStorageCollection { private: class Impl; std::unique_ptr<Impl> p_; - - /** - * @brief - * - */ - SingletonStorageCollection() noexcept; - - /** - * @brief - * - */ - ~SingletonStorageCollection(); }; } // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/function/gpg/GpgBasicOperator.cpp b/src/core/function/gpg/GpgBasicOperator.cpp index 4f524d3d..d8a45489 100644 --- a/src/core/function/gpg/GpgBasicOperator.cpp +++ b/src/core/function/gpg/GpgBasicOperator.cpp @@ -52,13 +52,14 @@ auto GpgFrontend::GpgBasicOperator::Encrypt( GpgData data_in(in_buffer.data(), in_buffer.size()); GpgData data_out; - gpgme_error_t err = CheckGpgError(gpgme_op_encrypt( - ctx_, recipients, GPGME_ENCRYPT_ALWAYS_TRUST, data_in, data_out)); + gpgme_error_t err = CheckGpgError( + gpgme_op_encrypt(ctx_.DefaultContext(), recipients, + GPGME_ENCRYPT_ALWAYS_TRUST, data_in, data_out)); auto temp_data_out = data_out.Read2Buffer(); std::swap(temp_data_out, out_buffer); - auto temp_result = NewResult(gpgme_op_encrypt_result(ctx_)); + auto temp_result = NewResult(gpgme_op_encrypt_result(ctx_.DefaultContext())); std::swap(result, temp_result); return err; @@ -71,12 +72,13 @@ auto GpgFrontend::GpgBasicOperator::Decrypt( GpgData data_in(in_buffer.data(), in_buffer.size()); GpgData data_out; - err = CheckGpgError(gpgme_op_decrypt(ctx_, data_in, data_out)); + err = + CheckGpgError(gpgme_op_decrypt(ctx_.DefaultContext(), data_in, data_out)); auto temp_data_out = data_out.Read2Buffer(); std::swap(temp_data_out, out_buffer); - auto temp_result = NewResult(gpgme_op_decrypt_result(ctx_)); + auto temp_result = NewResult(gpgme_op_decrypt_result(ctx_.DefaultContext())); std::swap(result, temp_result); return err; @@ -93,12 +95,14 @@ auto GpgFrontend::GpgBasicOperator::Verify(BypeArrayRef& in_buffer, if (sig_buffer != nullptr && !sig_buffer->empty()) { GpgData sig_data(sig_buffer->data(), sig_buffer->size()); - err = CheckGpgError(gpgme_op_verify(ctx_, sig_data, data_in, nullptr)); + err = CheckGpgError( + gpgme_op_verify(ctx_.DefaultContext(), sig_data, data_in, nullptr)); } else { - err = CheckGpgError(gpgme_op_verify(ctx_, data_in, nullptr, data_out)); + err = CheckGpgError( + gpgme_op_verify(ctx_.DefaultContext(), data_in, nullptr, data_out)); } - auto temp_result = NewResult(gpgme_op_verify_result(ctx_)); + auto temp_result = NewResult(gpgme_op_verify_result(ctx_.DefaultContext())); std::swap(result, temp_result); return err; @@ -115,12 +119,13 @@ auto GpgFrontend::GpgBasicOperator::Sign( GpgData data_in(in_buffer.data(), in_buffer.size()); GpgData data_out; - err = CheckGpgError(gpgme_op_sign(ctx_, data_in, data_out, mode)); + err = CheckGpgError( + gpgme_op_sign(ctx_.DefaultContext(), data_in, data_out, mode)); auto temp_data_out = data_out.Read2Buffer(); std::swap(temp_data_out, out_buffer); - auto temp_result = NewResult(gpgme_op_sign_result(ctx_)); + auto temp_result = NewResult(gpgme_op_sign_result(ctx_.DefaultContext())); std::swap(result, temp_result); @@ -136,15 +141,18 @@ auto GpgFrontend::GpgBasicOperator::DecryptVerify( GpgData data_in(in_buffer.data(), in_buffer.size()); GpgData data_out; - err = CheckGpgError(gpgme_op_decrypt_verify(ctx_, data_in, data_out)); + err = CheckGpgError( + gpgme_op_decrypt_verify(ctx_.DefaultContext(), data_in, data_out)); auto temp_data_out = data_out.Read2Buffer(); std::swap(temp_data_out, out_buffer); - auto temp_decr_result = NewResult(gpgme_op_decrypt_result(ctx_)); + auto temp_decr_result = + NewResult(gpgme_op_decrypt_result(ctx_.DefaultContext())); std::swap(decrypt_result, temp_decr_result); - auto temp_verify_result = NewResult(gpgme_op_verify_result(ctx_)); + auto temp_verify_result = + NewResult(gpgme_op_verify_result(ctx_.DefaultContext())); std::swap(verify_result, temp_verify_result); return err; @@ -173,40 +181,43 @@ auto GpgFrontend::GpgBasicOperator::EncryptSign( GpgData data_out; // If the last parameter isnt 0, a private copy of data is made - err = CheckGpgError(gpgme_op_encrypt_sign( - ctx_, recipients, GPGME_ENCRYPT_ALWAYS_TRUST, data_in, data_out)); + err = CheckGpgError(gpgme_op_encrypt_sign(ctx_.DefaultContext(), recipients, + GPGME_ENCRYPT_ALWAYS_TRUST, data_in, + data_out)); auto temp_data_out = data_out.Read2Buffer(); std::swap(temp_data_out, out_buffer); - auto temp_encr_result = NewResult(gpgme_op_encrypt_result(ctx_)); + auto temp_encr_result = + NewResult(gpgme_op_encrypt_result(ctx_.DefaultContext())); swap(encr_result, temp_encr_result); - auto temp_sign_result = NewResult(gpgme_op_sign_result(ctx_)); + auto temp_sign_result = + NewResult(gpgme_op_sign_result(ctx_.DefaultContext())); swap(sign_result, temp_sign_result); return err; } void GpgFrontend::GpgBasicOperator::SetSigners(KeyArgsList& signers) { - gpgme_signers_clear(ctx_); + gpgme_signers_clear(ctx_.DefaultContext()); for (const GpgKey& key : signers) { SPDLOG_DEBUG("key fpr: {}", key.GetFingerprint()); if (key.IsHasActualSigningCapability()) { SPDLOG_DEBUG("signer"); - auto error = gpgme_signers_add(ctx_, gpgme_key_t(key)); + auto error = gpgme_signers_add(ctx_.DefaultContext(), gpgme_key_t(key)); CheckGpgError(error); } } - if (signers.size() != gpgme_signers_count(ctx_)) + if (signers.size() != gpgme_signers_count(ctx_.DefaultContext())) SPDLOG_DEBUG("not all signers added"); } auto GpgFrontend::GpgBasicOperator::GetSigners() -> std::unique_ptr<GpgFrontend::KeyArgsList> { - auto count = gpgme_signers_count(ctx_); + auto count = gpgme_signers_count(ctx_.DefaultContext()); auto signers = std::make_unique<std::vector<GpgKey>>(); for (auto i = 0U; i < count; i++) { - auto key = GpgKey(gpgme_signers_enum(ctx_, i)); + auto key = GpgKey(gpgme_signers_enum(ctx_.DefaultContext(), i)); signers->push_back(GpgKey(std::move(key))); } return signers; @@ -219,15 +230,17 @@ auto GpgFrontend::GpgBasicOperator::EncryptSymmetric( GpgData data_in(in_buffer.data(), in_buffer.size()); GpgData data_out; - gpgme_error_t err = CheckGpgError(gpgme_op_encrypt( - ctx_, nullptr, GPGME_ENCRYPT_SYMMETRIC, data_in, data_out)); + gpgme_error_t err = CheckGpgError( + gpgme_op_encrypt(ctx_.DefaultContext(), nullptr, GPGME_ENCRYPT_SYMMETRIC, + data_in, data_out)); auto temp_data_out = data_out.Read2Buffer(); std::swap(temp_data_out, out_buffer); // TODO(Saturneric): maybe a bug of gpgme if (gpgme_err_code(err) == GPG_ERR_NO_ERROR) { - auto temp_result = NewResult(gpgme_op_encrypt_result(ctx_)); + auto temp_result = + NewResult(gpgme_op_encrypt_result(ctx_.DefaultContext())); std::swap(result, temp_result); } diff --git a/src/core/function/gpg/GpgCommandExecutor.cpp b/src/core/function/gpg/GpgCommandExecutor.cpp index d05cc626..1717c6e0 100644 --- a/src/core/function/gpg/GpgCommandExecutor.cpp +++ b/src/core/function/gpg/GpgCommandExecutor.cpp @@ -35,6 +35,7 @@ #include "core/module/Module.h" #include "core/thread/Task.h" #include "core/thread/TaskRunnerGetter.h" +#include "spdlog/spdlog.h" namespace GpgFrontend { @@ -231,6 +232,9 @@ void GpgCommandExecutor::ExecuteConcurrentlyAsync(ExecuteContexts contexts) { void GpgCommandExecutor::ExecuteConcurrentlySync(ExecuteContexts contexts) { QEventLoop looper; auto remaining_tasks = contexts.size(); + Thread::TaskRunnerPtr target_task_runner = nullptr; + + bool need_looper = true; for (auto &context : contexts) { const auto &cmd = context.cmd; @@ -240,22 +244,37 @@ void GpgCommandExecutor::ExecuteConcurrentlySync(ExecuteContexts contexts) { QObject::connect(task, &Thread::Task::SignalTaskEnd, [&]() { --remaining_tasks; + SPDLOG_DEBUG("remaining tasks: {}", remaining_tasks); if (remaining_tasks <= 0) { + SPDLOG_DEBUG("no remaining task, quit"); looper.quit(); } }); if (context.task_runner != nullptr) { - context.task_runner->PostTask(task); + target_task_runner = context.task_runner; } else { - GpgFrontend::Thread::TaskRunnerGetter::GetInstance() - .GetTaskRunner( - Thread::TaskRunnerGetter::kTaskRunnerType_External_Process) - ->PostTask(task); + target_task_runner = + GpgFrontend::Thread::TaskRunnerGetter::GetInstance().GetTaskRunner( + Thread::TaskRunnerGetter::kTaskRunnerType_External_Process); + } + + target_task_runner->PostTask(task); + + // to arvoid dead lock issue we need to check if current thread is the same + // as + // target thread. if it is, we can't call exec() because it will block the + // current thread. + if (QThread::currentThread() == target_task_runner->GetThread()) { + need_looper = false; } } - looper.exec(); + if (need_looper) { + // block until task finished + // this is to keep reference vaild until task finished + looper.exec(); + } } } // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/function/gpg/GpgContext.cpp b/src/core/function/gpg/GpgContext.cpp index 40a70cee..9b24af3c 100644 --- a/src/core/function/gpg/GpgContext.cpp +++ b/src/core/function/gpg/GpgContext.cpp @@ -31,17 +31,13 @@ #include <gpg-error.h> #include <gpgme.h> +#include <cassert> + #include "core/function/CoreSignalStation.h" #include "core/function/basic/GpgFunctionObject.h" -#include "core/function/gpg/GpgCommandExecutor.h" -#include "core/function/gpg/GpgKeyGetter.h" #include "core/module/ModuleManager.h" -#include "core/thread/Task.h" -#include "core/thread/TaskRunnerGetter.h" -#include "core/utils/CacheUtils.h" -#include "core/utils/CommonUtils.h" #include "core/utils/GpgUtils.h" -#include "function/CacheManager.h" +#include "spdlog/spdlog.h" #ifdef _WIN32 #include <windows.h> @@ -49,6 +45,15 @@ namespace GpgFrontend { +struct CtxRefDeleter { + void operator()(gpgme_ctx_t _ctx) { + if (_ctx != nullptr) gpgme_release(_ctx); + } +}; + +using CtxRefHandler = + std::unique_ptr<struct gpgme_context, CtxRefDeleter>; ///< + class GpgContext::Impl : public SingletonFunctionObject<GpgContext::Impl> { public: /** @@ -58,169 +63,29 @@ class GpgContext::Impl : public SingletonFunctionObject<GpgContext::Impl> { Impl(GpgContext *parent, const GpgContextInitArgs &args, int channel) : SingletonFunctionObject<GpgContext::Impl>(channel), parent_(parent), - args_(args) { - gpgme_ctx_t p_ctx; - - // get gpgme library version - Module::UpsertRTValue("core", "gpgme.version", - std::string(gpgme_check_version(nullptr))); - - // create a new context - CheckGpgError(gpgme_new(&p_ctx)); - ctx_ref_ = CtxRefHandler(p_ctx); - - if (args.custom_gpgconf && !args.custom_gpgconf_path.empty()) { - SPDLOG_DEBUG("set custom gpgconf path: {}", args.custom_gpgconf_path); - auto err = - gpgme_ctx_set_engine_info(ctx_ref_.get(), GPGME_PROTOCOL_GPGCONF, - args.custom_gpgconf_path.c_str(), nullptr); - assert(CheckGpgError(err) == GPG_ERR_NO_ERROR); - } - - // set context offline mode - SPDLOG_DEBUG("gpg context offline mode: {}", args_.offline_mode); - gpgme_set_offline(ctx_ref_.get(), args_.offline_mode ? 1 : 0); - - // set option auto import missing key - // invalid at offline mode - SPDLOG_DEBUG("gpg context auto import missing key: {}", args_.offline_mode); - if (!args.offline_mode && args.auto_import_missing_key) { - CheckGpgError(gpgme_set_ctx_flag(ctx_ref_.get(), "auto-key-import", "1")); - } - - // get engine info - auto *engine_info = gpgme_ctx_get_engine_info(*this); - // Check ENV before running - bool check_passed = false; - bool find_openpgp = false; - bool find_gpgconf = false; - bool find_cms = false; - - while (engine_info != nullptr) { - if (strcmp(engine_info->version, "1.0.0") == 0) { - engine_info = engine_info->next; - continue; - } - - SPDLOG_DEBUG( - "gpg context engine info: {} {} {} {}", - gpgme_get_protocol_name(engine_info->protocol), - std::string(engine_info->file_name == nullptr - ? "null" - : engine_info->file_name), - std::string(engine_info->home_dir == nullptr ? "null" - : engine_info->home_dir), - std::string(engine_info->version ? "null" : engine_info->version)); - - switch (engine_info->protocol) { - case GPGME_PROTOCOL_OpenPGP: - find_openpgp = true; - - Module::UpsertRTValue("core", "gpgme.ctx.app_path", - std::string(engine_info->file_name)); - Module::UpsertRTValue("core", "gpgme.ctx.gnupg_version", - std::string(engine_info->version)); - Module::UpsertRTValue("core", "gpgme.ctx.database_path", - std::string(engine_info->home_dir == nullptr - ? "default" - : engine_info->home_dir)); - break; - case GPGME_PROTOCOL_CMS: - find_cms = true; - Module::UpsertRTValue("core", "gpgme.ctx.cms_path", - std::string(engine_info->file_name)); - - break; - case GPGME_PROTOCOL_GPGCONF: - find_gpgconf = true; - Module::UpsertRTValue("core", "gpgme.ctx.gpgconf_path", - std::string(engine_info->file_name)); - break; - case GPGME_PROTOCOL_ASSUAN: - Module::UpsertRTValue("core", "gpgme.ctx.assuan_path", - std::string(engine_info->file_name)); - break; - case GPGME_PROTOCOL_G13: - break; - case GPGME_PROTOCOL_UISERVER: - break; - case GPGME_PROTOCOL_SPAWN: - break; - case GPGME_PROTOCOL_DEFAULT: - break; - case GPGME_PROTOCOL_UNKNOWN: - break; - } - engine_info = engine_info->next; - } - - const auto gnupg_version = Module::RetrieveRTValueTypedOrDefault<>( - "core", "gpgme.ctx.gnupg_version", std::string{"0.0.0"}); - SPDLOG_DEBUG("got gnupg version from rt: {}", gnupg_version); - - // conditional check: only support gpg 2.x now - if ((CompareSoftwareVersion(gnupg_version, "2.0.0") >= 0 && find_gpgconf && - find_openpgp && find_cms)) { - check_passed = true; - } - - if (!check_passed) { - this->good_ = false; - SPDLOG_ERROR("env check failed"); - return; - } + args_(args), + good_(default_ctx_initialize(args) && binary_ctx_initialize(args)) {} - // speed up loading process - gpgme_set_offline(*this, 1); - - // set keylist mode - if (gnupg_version >= "2.0.0") { - CheckGpgError(gpgme_set_keylist_mode( - *this, GPGME_KEYLIST_MODE_LOCAL | GPGME_KEYLIST_MODE_WITH_SECRET | - GPGME_KEYLIST_MODE_SIGS | - GPGME_KEYLIST_MODE_SIG_NOTATIONS | - GPGME_KEYLIST_MODE_WITH_TOFU)); - } else { - CheckGpgError(gpgme_set_keylist_mode( - *this, GPGME_KEYLIST_MODE_LOCAL | GPGME_KEYLIST_MODE_SIGS | - GPGME_KEYLIST_MODE_SIG_NOTATIONS | - GPGME_KEYLIST_MODE_WITH_TOFU)); - } - - // async, init context - Thread::TaskRunnerGetter::GetInstance() - .GetTaskRunner(Thread::TaskRunnerGetter::kTaskRunnerType_GPG) - ->PostTask(new Thread::Task( - [=](const DataObjectPtr &) -> int { - ctx_post_initialize(); - return 0; - }, - "ctx_post_initialize")); - - good_ = true; + [[nodiscard]] auto BinaryContext() const -> gpgme_ctx_t { + return binary_ctx_ref_.get(); } - /** - * @brief - * - * @return gpgme_ctx_t - */ - operator gpgme_ctx_t() const { return ctx_ref_.get(); } + [[nodiscard]] auto DefaultContext() const -> gpgme_ctx_t { + return ctx_ref_.get(); + } [[nodiscard]] auto Good() const -> bool { return good_; } - void SetPassphraseCb(gpgme_passphrase_cb_t cb) { - const auto gnupg_version = Module::RetrieveRTValueTypedOrDefault<>( - "core", "gpgme.ctx.gnupg_version", std::string{"2.0.0"}); - - if (CompareSoftwareVersion(gnupg_version, "2.1.0") >= 0) { - if (gpgme_get_pinentry_mode(*this) != GPGME_PINENTRY_MODE_LOOPBACK) { - gpgme_set_pinentry_mode(*this, GPGME_PINENTRY_MODE_LOOPBACK); + auto SetPassphraseCb(const CtxRefHandler &ctx, gpgme_passphrase_cb_t cb) + -> bool { + if (gpgme_get_pinentry_mode(ctx.get()) != GPGME_PINENTRY_MODE_LOOPBACK) { + if (CheckGpgError(gpgme_set_pinentry_mode( + ctx.get(), GPGME_PINENTRY_MODE_LOOPBACK)) != GPG_ERR_NO_ERROR) { + return false; } - gpgme_set_passphrase_cb(*this, cb, reinterpret_cast<void *>(parent_)); - } else { - SPDLOG_ERROR("not supported for gnupg version: {}", gnupg_version); } + gpgme_set_passphrase_cb(ctx.get(), cb, reinterpret_cast<void *>(parent_)); + return true; } static auto TestPassphraseCb(void *opaque, const char *uid_hint, @@ -288,47 +153,82 @@ class GpgContext::Impl : public SingletonFunctionObject<GpgContext::Impl> { } private: - struct CtxRefDeleter { - void operator()(gpgme_ctx_t _ctx) { - if (_ctx != nullptr) gpgme_release(_ctx); + GpgContext *parent_; + GpgContextInitArgs args_{}; ///< + CtxRefHandler ctx_ref_ = nullptr; ///< + CtxRefHandler binary_ctx_ref_ = nullptr; ///< + bool good_ = true; + + static auto set_ctx_key_list_mode(const CtxRefHandler &ctx) -> bool { + assert(ctx.get() != nullptr); + + const auto gpgme_version = Module::RetrieveRTValueTypedOrDefault<>( + "core", "gpgme.version", std::string{"0.0.0"}); + SPDLOG_DEBUG("got gpgme version version from rt: {}", gpgme_version); + + if (gpgme_get_keylist_mode(ctx.get()) == 0) { + SPDLOG_ERROR( + "ctx is not a valid pointer, reported by gpgme_get_keylist_mode"); + return false; } - }; - using CtxRefHandler = - std::unique_ptr<struct gpgme_context, CtxRefDeleter>; ///< + // set keylist mode + return CheckGpgError(gpgme_set_keylist_mode( + ctx.get(), + GPGME_KEYLIST_MODE_LOCAL | GPGME_KEYLIST_MODE_WITH_SECRET | + GPGME_KEYLIST_MODE_SIGS | GPGME_KEYLIST_MODE_SIG_NOTATIONS | + GPGME_KEYLIST_MODE_WITH_TOFU)) == GPG_ERR_NO_ERROR; + } - GpgContext *parent_; - GpgContextInitArgs args_{}; ///< - CtxRefHandler ctx_ref_ = nullptr; ///< - bool good_ = true; + auto common_ctx_initialize(const CtxRefHandler &ctx, + const GpgContextInitArgs &args) -> bool { + assert(ctx.get() != nullptr); - void ctx_post_initialize() { - const auto gnupg_version = Module::RetrieveRTValueTypedOrDefault<>( - "core", "gpgme.ctx.gnupg_version", std::string{"2.0.0"}); - - if (args_.ascii) { - /** Setting the output type must be done at the beginning */ - /** think this means ascii-armor --> ? */ - gpgme_set_armor(*this, 1); - } else { - /** Setting the output type must be done at the beginning */ - /** think this means ascii-armor --> ? */ - gpgme_set_armor(*this, 0); + if (args.custom_gpgconf && !args.custom_gpgconf_path.empty()) { + SPDLOG_DEBUG("set custom gpgconf path: {}", args.custom_gpgconf_path); + auto err = + gpgme_ctx_set_engine_info(ctx.get(), GPGME_PROTOCOL_GPGCONF, + args.custom_gpgconf_path.c_str(), nullptr); + + assert(CheckGpgError(err) == GPG_ERR_NO_ERROR); + if (CheckGpgError(err) != GPG_ERR_NO_ERROR) { + return false; + } } - // for unit test - if (args_.test_mode) { - if (CompareSoftwareVersion(gnupg_version, "2.1.0") >= 0) { - SetPassphraseCb(TestPassphraseCb); + // set context offline mode + SPDLOG_DEBUG("gpg context offline mode: {}", args_.offline_mode); + gpgme_set_offline(ctx.get(), args_.offline_mode ? 1 : 0); + + // set option auto import missing key + // invalid at offline mode + SPDLOG_DEBUG("gpg context auto import missing key: {}", args_.offline_mode); + if (!args.offline_mode && args.auto_import_missing_key) { + if (CheckGpgError(gpgme_set_ctx_flag(ctx.get(), "auto-key-import", + "1")) != GPG_ERR_NO_ERROR) { + return false; } - gpgme_set_status_cb(*this, TestStatusCb, nullptr); } - if (!args_.use_pinentry) { - SetPassphraseCb(CustomPassphraseCb); + if (!set_ctx_key_list_mode(ctx)) { + SPDLOG_DEBUG("set ctx key list mode failed"); + return false; + } + + // for unit test + if (args_.test_mode) { + if (!SetPassphraseCb(ctx, TestPassphraseCb)) { + SPDLOG_ERROR("set passphrase cb failed, test"); + return false; + }; + } else if (!args_.use_pinentry) { + if (!SetPassphraseCb(ctx, CustomPassphraseCb)) { + SPDLOG_DEBUG("set passphrase cb failed, custom"); + return false; + } } - // set custom key db path + // set custom gpg key db path if (!args_.db_path.empty()) { Module::UpsertRTValue("core", "gpgme.ctx.database_path", std::string(args_.db_path)); @@ -342,8 +242,50 @@ class GpgContext::Impl : public SingletonFunctionObject<GpgContext::Impl> { gpgme_ctx_set_engine_info(ctx_ref_.get(), GPGME_PROTOCOL_OpenPGP, app_path.c_str(), database_path.c_str()); SPDLOG_DEBUG("ctx set custom key db path: {}", database_path); + assert(CheckGpgError(err) == GPG_ERR_NO_ERROR); + if (CheckGpgError(err) != GPG_ERR_NO_ERROR) { + return false; + } } + + return true; + } + + auto binary_ctx_initialize(const GpgContextInitArgs &args) -> bool { + gpgme_ctx_t p_ctx; + if (CheckGpgError(gpgme_new(&p_ctx)) != GPG_ERR_NO_ERROR) { + return false; + } + assert(p_ctx != nullptr); + binary_ctx_ref_ = CtxRefHandler(p_ctx); + + if (!common_ctx_initialize(binary_ctx_ref_, args)) { + SPDLOG_ERROR("get new ctx failed, binary"); + return false; + } + + /** Setting the output type must be done at the beginning */ + /** think this means ascii-armor --> ? */ + gpgme_set_armor(binary_ctx_ref_.get(), 0); + return true; + } + + auto default_ctx_initialize(const GpgContextInitArgs &args) -> bool { + gpgme_ctx_t p_ctx; + if (CheckGpgError(gpgme_new(&p_ctx)) != GPG_ERR_NO_ERROR) { + SPDLOG_ERROR("get new ctx failed, default"); + return false; + } + assert(p_ctx != nullptr); + ctx_ref_ = CtxRefHandler(p_ctx); + + if (!common_ctx_initialize(ctx_ref_, args)) { + return false; + } + + gpgme_set_armor(ctx_ref_.get(), 1); + return true; } }; @@ -357,12 +299,10 @@ GpgContext::GpgContext(const GpgContextInitArgs &args, int channel) auto GpgContext::Good() const -> bool { return p_->Good(); } -void GpgContext::SetPassphraseCb(gpgme_passphrase_cb_t passphrase_cb) const { - p_->SetPassphraseCb(passphrase_cb); -} +auto GpgContext::BinaryContext() -> gpgme_ctx_t { return p_->BinaryContext(); } -GpgContext::operator gpgme_ctx_t() const { - return static_cast<gpgme_ctx_t>(*p_); +auto GpgContext::DefaultContext() -> gpgme_ctx_t { + return p_->DefaultContext(); } GpgContext::~GpgContext() = default; diff --git a/src/core/function/gpg/GpgContext.h b/src/core/function/gpg/GpgContext.h index 527099fc..ea8c0e6a 100644 --- a/src/core/function/gpg/GpgContext.h +++ b/src/core/function/gpg/GpgContext.h @@ -37,17 +37,16 @@ namespace GpgFrontend { * */ struct GpgContextInitArgs { - std::string db_path = {}; + std::string db_path = {}; ///< - bool test_mode = false; - bool ascii = true; - bool offline_mode = false; - bool auto_import_missing_key = false; + bool test_mode = false; ///< + bool offline_mode = false; ///< + bool auto_import_missing_key = false; ///< - bool custom_gpgconf = false; - std::string custom_gpgconf_path; + bool custom_gpgconf = false; ///< + std::string custom_gpgconf_path; ///< - bool use_pinentry = false; + bool use_pinentry = false; ///< }; /** @@ -67,9 +66,9 @@ class GPGFRONTEND_CORE_EXPORT GpgContext [[nodiscard]] auto Good() const -> bool; - operator gpgme_ctx_t() const; + auto BinaryContext() -> gpgme_ctx_t; - void SetPassphraseCb(gpgme_passphrase_cb_t passphrase_cb) const; + auto DefaultContext() -> gpgme_ctx_t; private: class Impl; diff --git a/src/core/function/gpg/GpgKeyGetter.cpp b/src/core/function/gpg/GpgKeyGetter.cpp index cad2d884..a60b66c9 100644 --- a/src/core/function/gpg/GpgKeyGetter.cpp +++ b/src/core/function/gpg/GpgKeyGetter.cpp @@ -54,7 +54,7 @@ class GpgKeyGetter::Impl : public SingletonFunctionObject<GpgKeyGetter::Impl> { } gpgme_key_t p_key = nullptr; - gpgme_get_key(ctx_, fpr.c_str(), &p_key, 1); + gpgme_get_key(ctx_.DefaultContext(), fpr.c_str(), &p_key, 1); if (p_key == nullptr) { SPDLOG_WARN("GpgKeyGetter GetKey Private _p_key Null fpr", fpr); return GetPubkey(fpr, true); @@ -70,7 +70,7 @@ class GpgKeyGetter::Impl : public SingletonFunctionObject<GpgKeyGetter::Impl> { } gpgme_key_t p_key = nullptr; - gpgme_get_key(ctx_, fpr.c_str(), &p_key, 0); + gpgme_get_key(ctx_.DefaultContext(), fpr.c_str(), &p_key, 0); if (p_key == nullptr) SPDLOG_WARN("GpgKeyGetter GetKey _p_key Null", fpr); return GpgKey(std::move(p_key)); } @@ -88,13 +88,13 @@ class GpgKeyGetter::Impl : public SingletonFunctionObject<GpgKeyGetter::Impl> { } void FlushKeyCache() { - SPDLOG_DEBUG("called channel id: {}", GetChannel()); + SPDLOG_DEBUG("flush key channel called, channel: {}", GetChannel()); // clear the keys cache keys_cache_.clear(); // init - GpgError err = gpgme_op_keylist_start(ctx_, nullptr, 0); + GpgError err = gpgme_op_keylist_start(ctx_.DefaultContext(), nullptr, 0); // for debug assert(CheckGpgError(err) == GPG_ERR_NO_ERROR); @@ -106,7 +106,8 @@ class GpgKeyGetter::Impl : public SingletonFunctionObject<GpgKeyGetter::Impl> { // get the lock std::lock_guard<std::mutex> lock(keys_cache_mutex_); gpgme_key_t key; - while ((err = gpgme_op_keylist_next(ctx_, &key)) == GPG_ERR_NO_ERROR) { + while ((err = gpgme_op_keylist_next(ctx_.DefaultContext(), &key)) == + GPG_ERR_NO_ERROR) { auto gpg_key = GpgKey(std::move(key)); // detect if the key is in a smartcard @@ -120,14 +121,16 @@ class GpgKeyGetter::Impl : public SingletonFunctionObject<GpgKeyGetter::Impl> { } } - SPDLOG_DEBUG("cache address: {} object address: {}", + SPDLOG_DEBUG("flush key channel cache address: {} object address: {}", static_cast<void*>(&keys_cache_), static_cast<void*>(this)); // for debug assert(CheckGpgError2ErrCode(err, GPG_ERR_EOF) == GPG_ERR_EOF); - err = gpgme_op_keylist_end(ctx_); + err = gpgme_op_keylist_end(ctx_.DefaultContext()); assert(CheckGpgError2ErrCode(err, GPG_ERR_EOF) == GPG_ERR_NO_ERROR); + + SPDLOG_DEBUG("flush key channel done, channel: {}", GetChannel()); } auto GetKeys(const KeyIdArgsListPtr& ids) -> KeyListPtr { diff --git a/src/core/function/gpg/GpgKeyImportExporter.cpp b/src/core/function/gpg/GpgKeyImportExporter.cpp index c0d578c8..a2db25e1 100644 --- a/src/core/function/gpg/GpgKeyImportExporter.cpp +++ b/src/core/function/gpg/GpgKeyImportExporter.cpp @@ -48,11 +48,11 @@ auto GpgKeyImportExporter::ImportKey(StdBypeArrayPtr in_buffer) if (in_buffer->empty()) return {}; GpgData data_in(in_buffer->data(), in_buffer->size()); - auto err = CheckGpgError(gpgme_op_import(ctx_, data_in)); + auto err = CheckGpgError(gpgme_op_import(ctx_.DefaultContext(), data_in)); if (gpgme_err_code(err) != GPG_ERR_NO_ERROR) return {}; gpgme_import_result_t result; - result = gpgme_op_import_result(ctx_); + result = gpgme_op_import_result(ctx_.DefaultContext()); gpgme_import_status_t status = result->imports; auto import_info = std::make_unique<GpgImportInformation>(result); while (status != nullptr) { @@ -90,7 +90,8 @@ auto GpgKeyImportExporter::ExportKeys(KeyIdArgsListPtr& uid_list, keys_array[index] = nullptr; GpgData data_out; - auto err = gpgme_op_export_keys(ctx_, keys_array, mode, data_out); + auto err = + gpgme_op_export_keys(ctx_.DefaultContext(), keys_array, mode, data_out); if (gpgme_err_code(err) != GPG_ERR_NO_ERROR) return false; delete[] keys_array; @@ -156,7 +157,7 @@ auto GpgKeyImportExporter::ExportSecretKey(const GpgKey& key, GpgData data_out; // export private key to outBuffer - gpgme_error_t err = gpgme_op_export_keys(ctx_, target_key, + gpgme_error_t err = gpgme_op_export_keys(ctx_.DefaultContext(), target_key, GPGME_EXPORT_MODE_SECRET, data_out); auto temp_out_buffer = data_out.Read2Buffer(); @@ -168,7 +169,8 @@ auto GpgKeyImportExporter::ExportSecretKey(const GpgKey& key, auto GpgKeyImportExporter::ExportKey(const GpgKey& key, ByteArrayPtr& out_buffer) const -> bool { GpgData data_out; - auto err = gpgme_op_export(ctx_, key.GetId().c_str(), 0, data_out); + auto err = + gpgme_op_export(ctx_.DefaultContext(), key.GetId().c_str(), 0, data_out); SPDLOG_DEBUG("export keys read_bytes: {}", gpgme_data_seek(data_out, 0, SEEK_END)); @@ -182,8 +184,8 @@ auto GpgKeyImportExporter::ExportKeyOpenSSH(const GpgKey& key, ByteArrayPtr& out_buffer) const -> bool { GpgData data_out; - auto err = gpgme_op_export(ctx_, key.GetId().c_str(), GPGME_EXPORT_MODE_SSH, - data_out); + auto err = gpgme_op_export(ctx_.DefaultContext(), key.GetId().c_str(), + GPGME_EXPORT_MODE_SSH, data_out); SPDLOG_DEBUG("read_bytes: {}", gpgme_data_seek(data_out, 0, SEEK_END)); @@ -195,7 +197,7 @@ auto GpgKeyImportExporter::ExportKeyOpenSSH(const GpgKey& key, auto GpgKeyImportExporter::ExportSecretKeyShortest( const GpgKey& key, ByteArrayPtr& out_buffer) const -> bool { GpgData data_out; - auto err = gpgme_op_export(ctx_, key.GetId().c_str(), + auto err = gpgme_op_export(ctx_.DefaultContext(), key.GetId().c_str(), GPGME_EXPORT_MODE_MINIMAL, data_out); SPDLOG_DEBUG("read_bytes: {}", gpgme_data_seek(data_out, 0, SEEK_END)); diff --git a/src/core/function/gpg/GpgKeyManager.cpp b/src/core/function/gpg/GpgKeyManager.cpp index 726b2b66..4a67a3f4 100644 --- a/src/core/function/gpg/GpgKeyManager.cpp +++ b/src/core/function/gpg/GpgKeyManager.cpp @@ -54,9 +54,9 @@ auto GpgFrontend::GpgKeyManager::SignKey( expires_time_t = to_time_t(*expires); } - auto err = - CheckGpgError(gpgme_op_keysign(ctx_, static_cast<gpgme_key_t>(target), - uid.c_str(), expires_time_t, flags)); + auto err = CheckGpgError( + gpgme_op_keysign(ctx_.DefaultContext(), static_cast<gpgme_key_t>(target), + uid.c_str(), expires_time_t, flags)); return CheckGpgError(err) == GPG_ERR_NO_ERROR; } @@ -69,9 +69,9 @@ auto GpgFrontend::GpgKeyManager::RevSign( for (const auto& sign_id : *signature_id) { auto signing_key = key_getter.GetKey(sign_id.first); assert(signing_key.IsGood()); - auto err = CheckGpgError(gpgme_op_revsig(ctx_, gpgme_key_t(key), - gpgme_key_t(signing_key), - sign_id.second.c_str(), 0)); + auto err = CheckGpgError( + gpgme_op_revsig(ctx_.DefaultContext(), gpgme_key_t(key), + gpgme_key_t(signing_key), sign_id.second.c_str(), 0)); if (CheckGpgError(err) != GPG_ERR_NO_ERROR) return false; } return true; @@ -90,8 +90,9 @@ auto GpgFrontend::GpgKeyManager::SetExpire( if (subkey != nullptr) sub_fprs = subkey->GetFingerprint().c_str(); - auto err = CheckGpgError(gpgme_op_setexpire( - ctx_, static_cast<gpgme_key_t>(key), expires_time, sub_fprs, 0)); + auto err = CheckGpgError(gpgme_op_setexpire(ctx_.DefaultContext(), + static_cast<gpgme_key_t>(key), + expires_time, sub_fprs, 0)); return CheckGpgError(err) == GPG_ERR_NO_ERROR; } @@ -180,9 +181,9 @@ auto GpgFrontend::GpgKeyManager::SetOwnerTrustLevel(const GpgKey& key, GpgData data_out; - auto err = gpgme_op_interact(ctx_, static_cast<gpgme_key_t>(key), 0, - GpgKeyManager::interactor_cb_fnc, - (void*)&handel_struct, data_out); + auto err = gpgme_op_interact( + ctx_.DefaultContext(), static_cast<gpgme_key_t>(key), 0, + GpgKeyManager::interactor_cb_fnc, (void*)&handel_struct, data_out); if (err != GPG_ERR_NO_ERROR) { SPDLOG_ERROR("fail to set owner trust level {} to key {}, err: {}", trust_level, key.GetId(), gpgme_strerror(err)); diff --git a/src/core/function/gpg/GpgKeyOpera.cpp b/src/core/function/gpg/GpgKeyOpera.cpp index b4aa85eb..a89badc6 100644 --- a/src/core/function/gpg/GpgKeyOpera.cpp +++ b/src/core/function/gpg/GpgKeyOpera.cpp @@ -63,9 +63,9 @@ void GpgKeyOpera::DeleteKeys(GpgFrontend::KeyIdArgsListPtr key_ids) { for (const auto& tmp : *key_ids) { auto key = GpgKeyGetter::GetInstance().GetKey(tmp); if (key.IsGood()) { - err = CheckGpgError( - gpgme_op_delete_ext(ctx_, static_cast<gpgme_key_t>(key), - GPGME_DELETE_ALLOW_SECRET | GPGME_DELETE_FORCE)); + err = CheckGpgError(gpgme_op_delete_ext( + ctx_.DefaultContext(), static_cast<gpgme_key_t>(key), + GPGME_DELETE_ALLOW_SECRET | GPGME_DELETE_FORCE)); assert(gpg_err_code(err) == GPG_ERR_NO_ERROR); } else { SPDLOG_WARN("GpgKeyOpera DeleteKeys get key failed", tmp); @@ -95,11 +95,13 @@ auto GpgKeyOpera::SetExpire(const GpgKey& key, const SubkeyId& subkey_fpr, GpgError err; if (key.GetFingerprint() == subkey_fpr || subkey_fpr.empty()) { - err = gpgme_op_setexpire(ctx_, static_cast<gpgme_key_t>(key), expires_time, - nullptr, 0); + err = + gpgme_op_setexpire(ctx_.DefaultContext(), static_cast<gpgme_key_t>(key), + expires_time, nullptr, 0); } else { - err = gpgme_op_setexpire(ctx_, static_cast<gpgme_key_t>(key), expires_time, - subkey_fpr.c_str(), 0); + err = + gpgme_op_setexpire(ctx_.DefaultContext(), static_cast<gpgme_key_t>(key), + expires_time, subkey_fpr.c_str(), 0); } return err; @@ -192,11 +194,13 @@ void GpgKeyOpera::GenerateKey(const std::shared_ptr<GenKeyInfo>& params, if (params->IsNoPassPhrase()) flags |= GPGME_CREATE_NOPASSWD; SPDLOG_DEBUG("key generation args: {}", userid, algo, expires, flags); - err = gpgme_op_createkey(ctx, userid, algo, 0, expires, nullptr, flags); + err = gpgme_op_createkey(ctx.DefaultContext(), userid, algo, 0, expires, + nullptr, flags); GpgGenKeyResult result; if (CheckGpgError(err) == GPG_ERR_NO_ERROR) { - auto temp_result = NewResult(gpgme_op_genkey_result(ctx)); + auto temp_result = + NewResult(gpgme_op_genkey_result(ctx.DefaultContext())); std::swap(temp_result, result); } data_object->Swap({result}); @@ -241,8 +245,9 @@ void GpgKeyOpera::GenerateSubkey(const GpgKey& key, SPDLOG_DEBUG("args: {} {} {} {}", key.GetId(), algo, expires, flags); - auto err = gpgme_op_createsubkey(ctx, static_cast<gpgme_key_t>(key), - algo, 0, expires, flags); + auto err = gpgme_op_createsubkey(ctx.DefaultContext(), + static_cast<gpgme_key_t>(key), algo, 0, + expires, flags); return CheckGpgError(err); }, callback, "gpgme_op_createsubkey", "2.1.13"); @@ -252,7 +257,8 @@ void GpgKeyOpera::ModifyPassword(const GpgKey& key, const GpgOperationCallback& callback) { RunGpgOperaAsync( [&key, &ctx = ctx_](const DataObjectPtr&) -> GpgError { - return gpgme_op_passwd(ctx, static_cast<gpgme_key_t>(key), 0); + return gpgme_op_passwd(ctx.DefaultContext(), + static_cast<gpgme_key_t>(key), 0); }, callback, "gpgme_op_passwd", "2.0.15"); } @@ -269,8 +275,8 @@ auto GpgKeyOpera::ModifyTOFUPolicy(const GpgKey& key, return GPG_ERR_NOT_SUPPORTED; } - auto err = - gpgme_op_tofu_policy(ctx_, static_cast<gpgme_key_t>(key), tofu_policy); + auto err = gpgme_op_tofu_policy(ctx_.DefaultContext(), + static_cast<gpgme_key_t>(key), tofu_policy); return CheckGpgError(err); } diff --git a/src/core/function/gpg/GpgUIDOperator.cpp b/src/core/function/gpg/GpgUIDOperator.cpp index a614d2ee..4610c504 100644 --- a/src/core/function/gpg/GpgUIDOperator.cpp +++ b/src/core/function/gpg/GpgUIDOperator.cpp @@ -39,21 +39,22 @@ GpgUIDOperator::GpgUIDOperator(int channel) : SingletonFunctionObject<GpgUIDOperator>(channel) {} auto GpgUIDOperator::AddUID(const GpgKey& key, const std::string& uid) -> bool { - auto err = - gpgme_op_adduid(ctx_, static_cast<gpgme_key_t>(key), uid.c_str(), 0); + auto err = gpgme_op_adduid(ctx_.DefaultContext(), + static_cast<gpgme_key_t>(key), uid.c_str(), 0); return CheckGpgError(err) == GPG_ERR_NO_ERROR; } auto GpgUIDOperator::RevUID(const GpgKey& key, const std::string& uid) -> bool { - auto err = CheckGpgError( - gpgme_op_revuid(ctx_, static_cast<gpgme_key_t>(key), uid.c_str(), 0)); + auto err = CheckGpgError(gpgme_op_revuid( + ctx_.DefaultContext(), static_cast<gpgme_key_t>(key), uid.c_str(), 0)); return CheckGpgError(err) == GPG_ERR_NO_ERROR; } auto GpgUIDOperator::SetPrimaryUID(const GpgKey& key, const std::string& uid) -> bool { auto err = CheckGpgError(gpgme_op_set_uid_flag( - ctx_, static_cast<gpgme_key_t>(key), uid.c_str(), "primary", nullptr)); + ctx_.DefaultContext(), static_cast<gpgme_key_t>(key), uid.c_str(), + "primary", nullptr)); return CheckGpgError(err) == GPG_ERR_NO_ERROR; } auto GpgUIDOperator::AddUID(const GpgKey& key, const std::string& name, diff --git a/src/core/module/Event.cpp b/src/core/module/Event.cpp index 020f5c69..3c1314fe 100644 --- a/src/core/module/Event.cpp +++ b/src/core/module/Event.cpp @@ -80,8 +80,10 @@ class Event::Impl { void ExecuteCallback(ListenerIdentifier listener_id, const DataObjectPtr& data_object) { + SPDLOG_DEBUG("try to execute callback for event {} with listener {}", + event_identifier_, listener_id); if (callback_) { - SPDLOG_DEBUG("execute callback for event {} with listener {}", + SPDLOG_DEBUG("executing callback for event {} with listener {}", event_identifier_, listener_id); if (!QMetaObject::invokeMethod( callback_thread_, diff --git a/src/core/module/GlobalModuleContext.cpp b/src/core/module/GlobalModuleContext.cpp index 4195d719..88250a1e 100644 --- a/src/core/module/GlobalModuleContext.cpp +++ b/src/core/module/GlobalModuleContext.cpp @@ -273,8 +273,9 @@ class GlobalModuleContext::Impl { return true; } - auto IsModuleExists(const ModuleIdentifier& m_id) const -> bool { - return search_module_register_table(m_id).has_value(); + auto IsModuleActivated(const ModuleIdentifier& m_id) const -> bool { + auto m = search_module_register_table(m_id); + return m.has_value() && m->get()->activate; } private: @@ -374,8 +375,8 @@ auto GlobalModuleContext::GetDefaultChannel(ModuleRawPtr channel) -> int { return GlobalModuleContext::Impl::GetDefaultChannel(channel); } -auto GlobalModuleContext::IsModuleExists(ModuleIdentifier m_id) -> bool { - return p_->IsModuleExists(std::move(m_id)); +auto GlobalModuleContext::IsModuleActivated(ModuleIdentifier m_id) -> bool { + return p_->IsModuleActivated(std::move(m_id)); } } // namespace GpgFrontend::Module diff --git a/src/core/module/GlobalModuleContext.h b/src/core/module/GlobalModuleContext.h index ea9465e1..1535f2ca 100644 --- a/src/core/module/GlobalModuleContext.h +++ b/src/core/module/GlobalModuleContext.h @@ -77,7 +77,7 @@ class GPGFRONTEND_CORE_EXPORT GlobalModuleContext : public QObject { auto TriggerEvent(EventRefrernce) -> bool; - auto IsModuleExists(ModuleIdentifier) -> bool; + auto IsModuleActivated(ModuleIdentifier) -> bool; private: class Impl; diff --git a/src/core/module/ModuleManager.cpp b/src/core/module/ModuleManager.cpp index 5e2aa994..03ac21a8 100644 --- a/src/core/module/ModuleManager.cpp +++ b/src/core/module/ModuleManager.cpp @@ -102,6 +102,10 @@ class ModuleManager::Impl { return grt_->ListChildKeys(n, k); } + auto IsModuleActivated(ModuleIdentifier id) -> bool { + return gmc_->IsModuleActivated(id); + } + private: static ModuleMangerPtr global_module_manager; TaskRunnerPtr task_runner_; @@ -109,6 +113,10 @@ class ModuleManager::Impl { GRTPtr grt_; }; +auto IsModuleAcivate(ModuleIdentifier id) -> bool { + return ModuleManager::GetInstance()->IsModuleActivated(id); +} + auto UpsertRTValue(const std::string& namespace_, const std::string& key, const std::any& value) -> bool { return ModuleManager::GetInstance()->UpsertRTValue(namespace_, key, @@ -170,4 +178,8 @@ auto ModuleManager::ListRTChildKeys(const std::string& n, const std::string& k) return p_->ListRTChildKeys(n, k); } +auto ModuleManager::IsModuleActivated(ModuleIdentifier id) -> bool { + return p_->IsModuleActivated(id); +} + } // namespace GpgFrontend::Module
\ No newline at end of file diff --git a/src/core/module/ModuleManager.h b/src/core/module/ModuleManager.h index 76d6c042..bc05860b 100644 --- a/src/core/module/ModuleManager.h +++ b/src/core/module/ModuleManager.h @@ -63,6 +63,8 @@ class GPGFRONTEND_CORE_EXPORT ModuleManager : public QObject { void RegisterModule(ModulePtr); + auto IsModuleActivated(ModuleIdentifier) -> bool; + void TriggerEvent(EventRefrernce); void ActiveModule(ModuleIdentifier); @@ -110,13 +112,43 @@ void TriggerEvent(const EventIdentifier& event_id, Args&&... args, std::move(MakeEvent(event_id, std::forward<Args>(args)..., e_cb))); } +/** + * @brief + * + * @return true + * @return false + */ +auto GPGFRONTEND_CORE_EXPORT IsModuleAcivate(ModuleIdentifier) -> bool; + +/** + * @brief + * + * @param namespace_ + * @param key + * @param value + * @return true + * @return false + */ auto GPGFRONTEND_CORE_EXPORT UpsertRTValue(const std::string& namespace_, const std::string& key, const std::any& value) -> bool; +/** + * @brief + * + * @return true + * @return false + */ auto GPGFRONTEND_CORE_EXPORT ListenRTPublishEvent(QObject*, Namespace, Key, LPCallback) -> bool; +/** + * @brief + * + * @param namespace_ + * @param key + * @return std::vector<Key> + */ auto GPGFRONTEND_CORE_EXPORT ListRTChildKeys(const std::string& namespace_, const std::string& key) -> std::vector<Key>; diff --git a/src/core/thread/CtxCheckTask.cpp b/src/core/thread/CtxCheckTask.cpp index 3c24ca79..88e60f79 100644 --- a/src/core/thread/CtxCheckTask.cpp +++ b/src/core/thread/CtxCheckTask.cpp @@ -37,9 +37,9 @@ namespace GpgFrontend { Thread::CoreInitTask::CoreInitTask() : Task("ctx_check_task") { - connect(this, &CoreInitTask::SignalGnupgNotInstall, + connect(this, &CoreInitTask::SignalBadGnupgEnv, CoreSignalStation::GetInstance(), - &CoreSignalStation::SignalGnupgNotInstall); + &CoreSignalStation::SignalBadGnupgEnv); } void Thread::CoreInitTask::Run() { @@ -48,7 +48,7 @@ void Thread::CoreInitTask::Run() { // Create & Check Gnupg Context Status if (!GpgContext::GetInstance().Good()) { - emit SignalGnupgNotInstall(); + emit SignalBadGnupgEnv(); } // Try flushing key cache else { diff --git a/src/core/thread/CtxCheckTask.h b/src/core/thread/CtxCheckTask.h index 08eb3fc3..4e5f0d84 100644 --- a/src/core/thread/CtxCheckTask.h +++ b/src/core/thread/CtxCheckTask.h @@ -50,7 +50,7 @@ class GPGFRONTEND_CORE_EXPORT CoreInitTask : public Task { * @brief * */ - void SignalGnupgNotInstall(); + void SignalBadGnupgEnv(); protected: /** diff --git a/src/core/utils/GpgUtils.cpp b/src/core/utils/GpgUtils.cpp index 3e8c5f44..8588f117 100644 --- a/src/core/utils/GpgUtils.cpp +++ b/src/core/utils/GpgUtils.cpp @@ -55,8 +55,9 @@ static inline auto Trim(std::string& s) -> std::string { auto CheckGpgError(GpgError err) -> GpgError { if (gpg_err_code(err) != GPG_ERR_NO_ERROR) { - SPDLOG_ERROR("[error: {}] source: {} description: {}", gpg_err_code(err), - gpgme_strsource(err), gpgme_strerror(err)); + SPDLOG_ERROR( + "gpg operation failed [error code: {}], source: {} description: {}", + gpg_err_code(err), gpgme_strsource(err), gpgme_strerror(err)); } return err; } diff --git a/src/init.cpp b/src/init.cpp index 91d02ac8..f9f1801f 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -41,7 +41,7 @@ #include "core/function/GlobalSettingStation.h" #include "core/utils/MemoryUtils.h" #include "module/GpgFrontendModuleInit.h" -#include "spdlog/logger.h" +#include "module/sdk/Log.h" #include "ui/GpgFrontendUIInit.h" // main @@ -88,7 +88,7 @@ void InitMainLoggingSystem(spdlog::level::level_enum level) { spdlog::set_default_logger(main_logger); } -void InitModules(InitArgs args) { +void InitLoggingSystem(InitArgs args) { // init the logging system for main InitMainLoggingSystem(args.log_level); @@ -97,21 +97,15 @@ void InitModules(InitArgs args) { // init the logging system for ui GpgFrontend::UI::InitUILoggingSystem(args.log_level); - - // init the logging system for modules - GpgFrontend::Module::ModuleInitArgs module_init_args; - module_init_args.log_level = args.log_level; - // - GpgFrontend::Module::LoadGpgFrontendModules(module_init_args); } -void ShutdownModules() { - // shutdown the logging system for core - GpgFrontend::Module::ShutdownGpgFrontendModules(); - +void ShutdownLoggingSystem() { // shutdown the logging system for ui GpgFrontend::UI::ShutdownUILoggingSystem(); + // shutdown the logging system for modules + GpgFrontend::Module::ShutdownGpgFrontendModulesLoggingSystem(); + // shutdown the logging system for core GpgFrontend::ShutdownCoreLoggingSystem(); @@ -44,16 +44,17 @@ void HandleSignal(int sig); void BeforeExit(); /** - * @brief initialize the logging system. + * @brief * + * @param args */ -void InitModules(InitArgs); +void InitLoggingSystem(InitArgs args); /** * @brief initialize the logging system. * */ -void ShutdownModules(); +void ShutdownLoggingSystem(); /** * @brief init global PATH env diff --git a/src/module/GpgFrontendModuleInit.cpp b/src/module/GpgFrontendModuleInit.cpp index 367d1be1..1e83af0e 100644 --- a/src/module/GpgFrontendModuleInit.cpp +++ b/src/module/GpgFrontendModuleInit.cpp @@ -29,7 +29,9 @@ #include "GpgFrontendModuleInit.h" #include <core/module/ModuleManager.h> -#include <module/sdk/Log.h> + +#include "core/thread/Task.h" +#include "core/thread/TaskRunnerGetter.h" // integrated modules #include "integrated/gnupg_info_gathering_module/GnuPGInfoGatheringModule.h" @@ -37,8 +39,17 @@ namespace GpgFrontend::Module { +void LoadGpgFrontendModulesLoggingSystem(ModuleInitArgs args) { + GpgFrontend::Module::SDK::InitModuleLoggingSystem(args.log_level); +} + +void ShutdownGpgFrontendModulesLoggingSystem() { + GpgFrontend::Module::SDK::ShutdownModuleLoggingSystem(); +} + void LoadGpgFrontendModules(ModuleInitArgs args) { - SDK::InitModuleLoggingSystem(args.log_level); + // init the logging system for module system + LoadGpgFrontendModulesLoggingSystem(args); MODULE_LOG_INFO("loading integrated module..."); @@ -51,8 +62,13 @@ void LoadGpgFrontendModules(ModuleInitArgs args) { Integrated::GnuPGInfoGatheringModule::GnuPGInfoGatheringModule>(); MODULE_LOG_INFO("load integrated module done."); + + // must init at default thread before core + Thread::TaskRunnerGetter::GetInstance().GetTaskRunner()->PostTask( + new Thread::Task([](const DataObjectPtr&) -> int { return 0; }, + "modules_system_init_task")); } -void ShutdownGpgFrontendModules() { SDK::ShutdownModuleLoggingSystem(); } +void ShutdownGpgFrontendModules() {} } // namespace GpgFrontend::Module
\ No newline at end of file diff --git a/src/module/GpgFrontendModuleInit.h b/src/module/GpgFrontendModuleInit.h index 252338bf..a706bbb4 100644 --- a/src/module/GpgFrontendModuleInit.h +++ b/src/module/GpgFrontendModuleInit.h @@ -37,10 +37,24 @@ struct ModuleInitArgs { }; /** + * @brief + * + * @param args + */ +void GPGFRONTEND_MODULE_EXPORT +LoadGpgFrontendModulesLoggingSystem(ModuleInitArgs args); + +/** + * @brief + * + */ +void GPGFRONTEND_MODULE_EXPORT ShutdownGpgFrontendModulesLoggingSystem(); + +/** * @brief init the module library * */ -void GPGFRONTEND_MODULE_EXPORT LoadGpgFrontendModules(ModuleInitArgs); +void GPGFRONTEND_MODULE_EXPORT LoadGpgFrontendModules(ModuleInitArgs args); /** * @brief shutdown the module library diff --git a/src/module/integrated/gnupg_info_gathering_module/GnuPGInfoGatheringModule.cpp b/src/module/integrated/gnupg_info_gathering_module/GnuPGInfoGatheringModule.cpp index 492c87f1..9477848b 100644 --- a/src/module/integrated/gnupg_info_gathering_module/GnuPGInfoGatheringModule.cpp +++ b/src/module/integrated/gnupg_info_gathering_module/GnuPGInfoGatheringModule.cpp @@ -97,7 +97,7 @@ int GnuPGInfoGatheringModule::Exec(EventRefrernce event) { event->GetIdentifier()); const auto gpgme_version = RetrieveRTValueTypedOrDefault<>( - "core", "gpgme.version", std::string{"2.0.0"}); + "core", "gpgme.version", std::string{"0.0.0"}); MODULE_LOG_DEBUG("got gpgme version from rt: {}", gpgme_version); const auto gpgconf_path = RetrieveRTValueTypedOrDefault<>( @@ -289,8 +289,7 @@ int GnuPGInfoGatheringModule::Exec(EventRefrernce event) { std::string{}); auto jsonlized_component_info = nlohmann::json::parse(component_info_json); - GpgComponentInfo component_info = - jsonlized_component_info.get<GpgComponentInfo>(); + auto component_info = jsonlized_component_info.get<GpgComponentInfo>(); MODULE_LOG_DEBUG("gpgconf check options ready, component: {}", component_info.name); @@ -393,6 +392,8 @@ int GnuPGInfoGatheringModule::Exec(EventRefrernce event) { UpsertRTValue(GetModuleIdentifier(), "gnupg.gathering_done", true); event->ExecuteCallback(GetModuleIdentifier(), TransferParams(true)); + SPDLOG_INFO("gnupg external info gathering done"); + return 0; } diff --git a/src/module/sdk/Log.cpp b/src/module/sdk/Log.cpp index 4d6620ff..b70f5bbb 100644 --- a/src/module/sdk/Log.cpp +++ b/src/module/sdk/Log.cpp @@ -33,6 +33,8 @@ #include <spdlog/sinks/rotating_file_sink.h> #include <spdlog/sinks/stdout_color_sinks.h> +#include <stdexcept> + #include "core/function/GlobalSettingStation.h" namespace GpgFrontend::Module::SDK { @@ -81,7 +83,13 @@ void ShutdownModuleLoggingSystem() { #endif } -std::shared_ptr<spdlog::logger> GetModuleLogger() { +auto GetModuleLogger() -> std::shared_ptr<spdlog::logger> { + // check if logging system is initalized + auto ptr = spdlog::get("module"); + if (ptr == nullptr) { + throw std::runtime_error("logging system of modules is not initialized"); + } + return spdlog::get("module"); } diff --git a/src/ui/GpgFrontendUIInit.cpp b/src/ui/GpgFrontendUIInit.cpp index 454e0e2a..0d2a3331 100644 --- a/src/ui/GpgFrontendUIInit.cpp +++ b/src/ui/GpgFrontendUIInit.cpp @@ -28,6 +28,7 @@ #include "GpgFrontendUIInit.h" +#include <qapplication.h> #include <spdlog/async.h> #include <spdlog/common.h> #include <spdlog/sinks/rotating_file_sink.h> @@ -37,9 +38,12 @@ #include <string> #include "core/GpgConstants.h" +#include "core/function/CoreSignalStation.h" #include "core/function/GlobalSettingStation.h" +#include "core/module/ModuleManager.h" #include "core/thread/CtxCheckTask.h" #include "core/thread/TaskRunnerGetter.h" +#include "spdlog/spdlog.h" #include "ui/UISignalStation.h" #include "ui/UserInterfaceUtils.h" #include "ui/main_window/MainWindow.h" @@ -52,6 +56,65 @@ namespace GpgFrontend::UI { extern void InitLocale(); +void WaitEnvCheckingProcess() { + SPDLOG_DEBUG("need to waiting for env checking process"); + + // create and show loading window before starting the main window + auto* waiting_dialog = new QProgressDialog(); + waiting_dialog->setMaximum(0); + waiting_dialog->setMinimum(0); + auto* waiting_dialog_label = + new QLabel(QString(_("Loading Gnupg Info...")) + "<br /><br />" + + _("If this process is too slow, please set the key " + "server address appropriately in the gnupg configuration " + "file (depending " + "on the network situation in your country or region).")); + waiting_dialog_label->setWordWrap(true); + waiting_dialog->setLabel(waiting_dialog_label); + waiting_dialog->resize(420, 120); + QApplication::connect(CoreSignalStation::GetInstance(), + &CoreSignalStation::SignalGoodGnupgEnv, waiting_dialog, + [=]() { + SPDLOG_DEBUG("gpg env loaded successfuly"); + waiting_dialog->finished(0); + waiting_dialog->deleteLater(); + }); + + // new local event looper + QEventLoop looper; + QApplication::connect(CoreSignalStation::GetInstance(), + &CoreSignalStation::SignalGoodGnupgEnv, &looper, + &QEventLoop::quit); + + QApplication::connect(waiting_dialog, &QProgressDialog::canceled, [=]() { + SPDLOG_DEBUG("cancel clicked on wairing dialog"); + QApplication::quit(); + exit(0); + }); + + auto env_state = Module::RetrieveRTValueTypedOrDefault<>( + "core", "env.state.basic", std::string{"0"}); + + SPDLOG_DEBUG("ui is ready to wating for env initialized, env_state: {}", + env_state); + + // check twice to avoid some unlucky sitations + if (env_state == "1") { + SPDLOG_DEBUG("env state turned initialized before the looper start"); + waiting_dialog->finished(0); + waiting_dialog->deleteLater(); + return; + } + + // show the loading window + waiting_dialog->setModal(true); + waiting_dialog->setFocus(); + waiting_dialog->show(); + + // block the main thread until the gpg context is loaded + looper.exec(); +} + void InitGpgFrontendUI(QApplication* app) { // init locale InitLocale(); @@ -132,51 +195,10 @@ void InitGpgFrontendUI(QApplication* app) { QNetworkProxy::setApplicationProxy(QNetworkProxy::NoProxy); } - // create the thread to load the gpg context - auto* init_ctx_task = new Thread::CoreInitTask(); - - // create and show loading window before starting the main window - auto* waiting_dialog = new QProgressDialog(); - waiting_dialog->setMaximum(0); - waiting_dialog->setMinimum(0); - auto waiting_dialog_label = - new QLabel(QString(_("Loading Gnupg Info...")) + "<br /><br />" + - _("If this process is too slow, please set the key " - "server address appropriately in the gnupg configuration " - "file (depending " - "on the network situation in your country or region).")); - waiting_dialog_label->setWordWrap(true); - waiting_dialog->setLabel(waiting_dialog_label); - waiting_dialog->resize(420, 120); - app->connect(init_ctx_task, &Thread::CoreInitTask::SignalTaskEnd, - waiting_dialog, [=]() { - SPDLOG_DEBUG("gpg context loaded"); - waiting_dialog->finished(0); - waiting_dialog->deleteLater(); - }); - - app->connect(waiting_dialog, &QProgressDialog::canceled, [=]() { - SPDLOG_DEBUG("cancel clicked"); - app->quit(); - exit(0); - }); - - // show the loading window - waiting_dialog->setModal(true); - waiting_dialog->setFocus(); - waiting_dialog->show(); - - // new local event looper - QEventLoop looper; - app->connect(init_ctx_task, &Thread::CoreInitTask::SignalTaskEnd, &looper, - &QEventLoop::quit); - - // start the thread to load the gpg context - Thread::TaskRunnerGetter::GetInstance().GetTaskRunner()->PostTask( - init_ctx_task); - - // block the main thread until the gpg context is loaded - looper.exec(); + if (Module::RetrieveRTValueTypedOrDefault<>("core", "env.state.basic", + std::string{"0"}) == "0") { + WaitEnvCheckingProcess(); + } } int RunGpgFrontendUI(QApplication* app) { @@ -187,12 +209,15 @@ int RunGpgFrontendUI(QApplication* app) { if (CommonUtils::GetInstance()->isApplicationNeedRestart()) { SPDLOG_DEBUG("application need to restart, before mian window init"); return kDeepRestartCode; - } else { - main_window->Init(); - SPDLOG_DEBUG("main window inited"); - main_window->show(); } + // init main window + main_window->Init(); + + // show main windows + SPDLOG_DEBUG("main window is ready to show"); + main_window->show(); + // start the main event loop return app->exec(); } @@ -242,6 +267,8 @@ void ShutdownUILoggingSystem() { #endif } +void GPGFRONTEND_UI_EXPORT DestroyGpgFrontendUI() { ShutdownUILoggingSystem(); } + /** * @brief setup the locale and load the translations * diff --git a/src/ui/GpgFrontendUIInit.h b/src/ui/GpgFrontendUIInit.h index b14b43b9..0ed630bb 100644 --- a/src/ui/GpgFrontendUIInit.h +++ b/src/ui/GpgFrontendUIInit.h @@ -45,6 +45,12 @@ void GPGFRONTEND_UI_EXPORT InitGpgFrontendUI(QApplication *); void GPGFRONTEND_UI_EXPORT InitUILoggingSystem(spdlog::level::level_enum level); /** + * @brief init the UI library + * + */ +void GPGFRONTEND_UI_EXPORT DestroyGpgFrontendUI(); + +/** * @brief * */ diff --git a/src/ui/UserInterfaceUtils.cpp b/src/ui/UserInterfaceUtils.cpp index a73f56d2..6f4ca7d0 100644 --- a/src/ui/UserInterfaceUtils.cpp +++ b/src/ui/UserInterfaceUtils.cpp @@ -160,8 +160,8 @@ CommonUtils *CommonUtils::GetInstance() { CommonUtils::CommonUtils() : QWidget(nullptr) { connect(CoreSignalStation::GetInstance(), - &CoreSignalStation::SignalGnupgNotInstall, this, - &CommonUtils::SignalGnupgNotInstall); + &CoreSignalStation::SignalBadGnupgEnv, this, + &CommonUtils::SignalBadGnupgEnv); connect(this, &CommonUtils::SignalKeyStatusUpdated, UISignalStation::GetInstance(), &UISignalStation::SignalKeyDatabaseRefresh); @@ -184,7 +184,7 @@ CommonUtils::CommonUtils() : QWidget(nullptr) { &UISignalStation::SignalRestartApplication, this, &CommonUtils::SlotRestartApplication); - connect(this, &CommonUtils::SignalGnupgNotInstall, this, [=]() { + connect(this, &CommonUtils::SignalBadGnupgEnv, this, [=]() { QMessageBox msgBox; msgBox.setText(_("GnuPG Context Loading Failed")); msgBox.setInformativeText( diff --git a/src/ui/UserInterfaceUtils.h b/src/ui/UserInterfaceUtils.h index a1719016..f9210125 100644 --- a/src/ui/UserInterfaceUtils.h +++ b/src/ui/UserInterfaceUtils.h @@ -207,7 +207,7 @@ class CommonUtils : public QWidget { * @brief * */ - void SignalGnupgNotInstall(); + void SignalBadGnupgEnv(); /** * @brief emit when the key database is refreshed |