diff options
Diffstat (limited to 'src/module/integrated/gnupg_info_gathering_module/GnuPGInfoGatheringModule.cpp')
-rw-r--r-- | src/module/integrated/gnupg_info_gathering_module/GnuPGInfoGatheringModule.cpp | 607 |
1 files changed, 333 insertions, 274 deletions
diff --git a/src/module/integrated/gnupg_info_gathering_module/GnuPGInfoGatheringModule.cpp b/src/module/integrated/gnupg_info_gathering_module/GnuPGInfoGatheringModule.cpp index a1e5cd5a..67dd5227 100644 --- a/src/module/integrated/gnupg_info_gathering_module/GnuPGInfoGatheringModule.cpp +++ b/src/module/integrated/gnupg_info_gathering_module/GnuPGInfoGatheringModule.cpp @@ -28,29 +28,162 @@ #include "GnuPGInfoGatheringModule.h" -#include <vector> - +#include "Basic.h" #include "GpgInfo.h" #include "Log.h" -#include "core/function/gpg/GpgCommandExecutor.h" -#include "core/module/ModuleManager.h" -namespace GpgFrontend::Module::Integrated::GnuPGInfoGatheringModule { +ModuleMetaData *g_module_metadata = nullptr; + +extern auto CheckBinaryChacksum(QString path) -> std::optional<QString>; + +extern void GetGpgComponentInfos(void *, int, const char *, const char *); + +extern void GetGpgDirectoryInfos(void *, int, const char *, const char *); + +extern void GetGpgOptionInfos(void *, int, const char *, const char *); + +using Context = struct { + QString gpgme_version; + QString gpgconf_path; + GpgComponentInfo component_info; +}; + +auto RegisterModule() -> int { + ModuleLogDebug("gnupg info gathering module registering"); + + g_module_metadata = + static_cast<ModuleMetaData *>(AllocateMemory(sizeof(ModuleMetaData))); + + auto *p_meta = g_module_metadata; + p_meta->key = "description"; + p_meta->value = "try to gathering gnupg informations"; + p_meta->next = + static_cast<ModuleMetaData *>(AllocateMemory(sizeof(ModuleMetaData))); + p_meta = p_meta->next; + p_meta->key = "author"; + p_meta->value = "saturneric"; + p_meta->next = nullptr; + return 0; +} + +auto GetModuleID() -> const char * { + return "com.bktus.gpgfrontend.module.integrated.gnupg-info-gathering"; +} + +auto GetModuleVersion() -> const char * { return "1.0.0"; } + +auto GetModuleMetaData() -> ModuleMetaData * { return g_module_metadata; } + +auto ActiveModule() -> int { + ModuleLogDebug("gnupg info gathering module activating"); + ListenEvent(GetModuleID(), "GPGFRONTEND_CORE_INITLIZED"); + return 0; +} + +auto ExecuteModule(ModuleEvent *event) -> int { + ModuleLogDebug( + fmt::format("gnupg info gathering module executing, event id: {}", + event->id) + .c_str()); + + ModuleLogDebug("start to load extra info at module gnupginfogathering..."); + + const auto *const gpgme_version = + RetrieveRTValueOrDefault("core", "gpgme.version", "0.0.0"); + ModuleLogDebug( + fmt::format("got gpgme version from rt: {}", gpgme_version).c_str()); + + const auto *const gpgconf_path = + RetrieveRTValueOrDefault("core", "gpgme.ctx.gpgconf_path", ""); + ModuleLogDebug( + fmt::format("got gpgconf path from rt: {}", gpgconf_path).c_str()); + + auto context = Context{gpgme_version, gpgconf_path}; + + // get all components + const char *argv[] = {"--list-components"}; + ExecuteCommandSync(gpgconf_path, 1, argv, GetGpgComponentInfos, &context); + + QList<CommandExecuteContext> exec_contexts; + + const char *argv_0[] = {"--list-dirs"}; + exec_contexts.push_back( + {gpgconf_path, 1, argv_0, GetGpgDirectoryInfos, nullptr}); + + char **components_c_array; + int ret = + ListRTChildKeys(GetModuleID(), "gnupg.components", &components_c_array); + if (components_c_array == nullptr || ret == 0) return -1; + + QStringList components; + auto *p_a = components_c_array; + for (int i = 0; i < ret; i++) components.append(QString::fromUtf8(p_a[i])); + + for (const auto &component : components) { + const auto *component_info_json = RetrieveRTValueOrDefault( + GetModuleID(), QString("gnupg.components.%1").arg(component).toUtf8(), + nullptr); + + auto jsonlized_component_info = + QJsonDocument::fromJson(component_info_json); + assert(jsonlized_component_info.isObject()); + + auto component_info = GpgComponentInfo(jsonlized_component_info.object()); + ModuleLogDebug(fmt::format("gpgconf check options ready, component: {}", + component_info.name) + .c_str()); + + if (component_info.name == "gpgme" || component_info.name == "gpgconf") { + continue; + } + + auto context = Context{gpgme_version, gpgconf_path, component_info}; + + const char *argv_0[] = {"--list-options", component_info.name.toUtf8()}; + exec_contexts.push_back( + {gpgconf_path, 1, argv_0, GetGpgDirectoryInfos, &context}); + } + + ExecuteCommandBatchSync(static_cast<int32_t>(exec_contexts.size()), + exec_contexts.constData()); + + UpsertRTValue(GetModuleID(), "gnupg.gathering_done", "true"); + + char **event_argv = static_cast<char **>(AllocateMemory(sizeof(char *) * 1)); + event_argv[0] = static_cast<char *>(AllocateMemory(5)); + memcpy(event_argv[0], "true", 4); + event_argv[0][4] = '\0'; + + TriggerModuleEventCallback(event, GetModuleID(), 1, event_argv); + + ModuleLogDebug("gnupg external info gathering done"); + return 0; +} + +auto DeactiveModule() -> int { return 0; } + +auto UnregisterModule() -> int { + ModuleLogDebug("gnupg info gathering module unregistering"); + FreeMemory(g_module_metadata); + return 0; +} auto CheckBinaryChacksum(QString path) -> std::optional<QString> { // check file info and access rights QFileInfo info(path); if (!info.exists() || !info.isFile() || !info.isReadable()) { - MODULE_LOG_ERROR("get info for file {} error, exists: {}", info.filePath(), - info.exists()); + ModuleLogError(fmt::format("get info for file {} error, exists: {}", + info.filePath(), info.exists()) + .c_str()); return {}; } // open and read file QFile f(info.filePath()); if (!f.open(QIODevice::ReadOnly)) { - MODULE_LOG_ERROR("open {} to calculate check sum error: {}", path, - f.errorString()); + ModuleLogError(fmt::format("open {} to calculate check sum error: {}", path, + f.errorString()) + .c_str()); return {}; } @@ -64,289 +197,215 @@ auto CheckBinaryChacksum(QString path) -> std::optional<QString> { return QString(hash_sha.result().toHex()).left(6); } -GnuPGInfoGatheringModule::GnuPGInfoGatheringModule() - : Module( - "com.bktus.gpgfrontend.module.integrated.gnupg-info-gathering", - "1.0.0", - ModuleMetaData{{"description", "try to gathering gnupg informations"}, - {"author", "saturneric"}}) {} - -GnuPGInfoGatheringModule::~GnuPGInfoGatheringModule() = default; - -auto GnuPGInfoGatheringModule::Register() -> bool { - MODULE_LOG_DEBUG("gnupg info gathering module registering"); - listenEvent("GPGFRONTEND_CORE_INITLIZED"); - return true; -} - -auto GnuPGInfoGatheringModule::Active() -> bool { - MODULE_LOG_DEBUG("gnupg info gathering module activating"); - return true; -} - -auto GnuPGInfoGatheringModule::Exec(EventRefrernce event) -> int { - MODULE_LOG_DEBUG("gnupg info gathering module executing, event id: {}", - event->GetIdentifier()); - - const auto gpgme_version = RetrieveRTValueTypedOrDefault<>( - "core", "gpgme.version", QString{"0.0.0"}); - MODULE_LOG_DEBUG("got gpgme version from rt: {}", gpgme_version); - - const auto gpgconf_path = RetrieveRTValueTypedOrDefault<>( - "core", "gpgme.ctx.gpgconf_path", QString{}); - MODULE_LOG_DEBUG("got gpgconf path from rt: {}", gpgconf_path); +void GetGpgComponentInfos(void *data, int exit_code, const char *out, + const char *err) { + auto *context = reinterpret_cast<Context *>(data); + auto p_out = QString::fromUtf8(out); + auto p_err = QString::fromUtf8(err); + + ModuleLogDebug( + fmt::format("gpgconf components exit_code: {} process stdout size: {}", + exit_code, p_out.size()) + .c_str()); + + if (exit_code != 0) { + ModuleLogError(fmt::format("gpgconf execute error, process stderr: {}, " + "process stdout: {}", + p_err, p_out) + .c_str()); + return; + } - MODULE_LOG_DEBUG("start to load extra info at module gnupginfogathering..."); - - // get all components - GpgCommandExecutor::ExecuteSync( - {gpgconf_path, QStringList{"--list-components"}, - [this, gpgme_version, gpgconf_path](int exit_code, const QString &p_out, - const QString &p_err) { - MODULE_LOG_DEBUG( - "gpgconf components exit_code: {} process stdout size: {}", - exit_code, p_out.size()); - - if (exit_code != 0) { - MODULE_LOG_ERROR( - "gpgconf execute error, process stderr: {}, " - "process stdout: {}", - p_err, p_out); - return; - } - - std::vector<GpgComponentInfo> component_infos; - GpgComponentInfo c_i_gpgme; - c_i_gpgme.name = "gpgme"; - c_i_gpgme.desc = "GPG Made Easy"; - c_i_gpgme.version = gpgme_version; - c_i_gpgme.path = tr("Embedded In"); - c_i_gpgme.binary_checksum = "/"; - - GpgComponentInfo c_i_gpgconf; - c_i_gpgconf.name = "gpgconf"; - c_i_gpgconf.desc = "GPG Configure"; - c_i_gpgconf.version = "/"; - c_i_gpgconf.path = gpgconf_path; - auto gpgconf_binary_checksum = CheckBinaryChacksum(gpgconf_path); - c_i_gpgconf.binary_checksum = (gpgconf_binary_checksum.has_value() - ? gpgconf_binary_checksum.value() - : QString("/")); - - component_infos.push_back(c_i_gpgme); - component_infos.push_back(c_i_gpgconf); - - auto const jsonlized_gpgme_component_info = c_i_gpgme.Json(); - auto const jsonlized_gpgconf_component_info = c_i_gpgconf.Json(); - UpsertRTValue(GetModuleIdentifier(), "gnupg.components.gpgme", - QJsonDocument(jsonlized_gpgme_component_info).toJson()); - UpsertRTValue( - GetModuleIdentifier(), "gnupg.components.gpgconf", - QJsonDocument(jsonlized_gpgconf_component_info).toJson()); - - auto line_split_list = p_out.split("\n"); - - for (const auto &line : line_split_list) { - auto info_split_list = line.split(":"); - - if (info_split_list.size() != 3) continue; - - auto component_name = info_split_list[0].trimmed(); - auto component_desc = info_split_list[1].trimmed(); - auto component_path = info_split_list[2].trimmed(); + std::vector<GpgComponentInfo> component_infos; + GpgComponentInfo c_i_gpgme; + c_i_gpgme.name = "gpgme"; + c_i_gpgme.desc = "GPG Made Easy"; + c_i_gpgme.version = context->gpgme_version; + c_i_gpgme.path = "Embedded In"; + c_i_gpgme.binary_checksum = "/"; + + GpgComponentInfo c_i_gpgconf; + c_i_gpgconf.name = "gpgconf"; + c_i_gpgconf.desc = "GPG Configure"; + c_i_gpgconf.version = "/"; + c_i_gpgconf.path = context->gpgconf_path; + auto gpgconf_binary_checksum = CheckBinaryChacksum(context->gpgconf_path); + c_i_gpgconf.binary_checksum = + (gpgconf_binary_checksum.has_value() ? gpgconf_binary_checksum.value() + : QString("/")); + + component_infos.push_back(c_i_gpgme); + component_infos.push_back(c_i_gpgconf); + + auto const jsonlized_gpgme_component_info = c_i_gpgme.Json(); + auto const jsonlized_gpgconf_component_info = c_i_gpgconf.Json(); + UpsertRTValue(GetModuleID(), "gnupg.components.gpgme", + QJsonDocument(jsonlized_gpgme_component_info).toJson()); + UpsertRTValue(GetModuleID(), "gnupg.components.gpgconf", + QJsonDocument(jsonlized_gpgconf_component_info).toJson()); + + auto line_split_list = p_out.split("\n"); + + for (const auto &line : line_split_list) { + auto info_split_list = line.split(":"); + + if (info_split_list.size() != 3) continue; + + auto component_name = info_split_list[0].trimmed(); + auto component_desc = info_split_list[1].trimmed(); + auto component_path = info_split_list[2].trimmed(); #ifdef WINDOWS - // replace some special substrings on windows platform - component_path.replace("%3a", ":"); -#endif - - auto binary_checksum = CheckBinaryChacksum(component_path); - - MODULE_LOG_DEBUG( - "gnupg component name: {} desc: {} checksum: {} path: {} ", - component_name, component_desc, - binary_checksum.has_value() ? binary_checksum.value() : "/", - component_path); - - QString version = "/"; - - if (component_name == "gpg") { - version = RetrieveRTValueTypedOrDefault<>( - "core", "gpgme.ctx.gnupg_version", QString{"2.0.0"}); - } - if (component_name == "gpg-agent") { - UpsertRTValue(GetModuleIdentifier(), "gnupg.gpg_agent_path", - QString(component_path)); - } - if (component_name == "dirmngr") { - UpsertRTValue(GetModuleIdentifier(), "gnupg.dirmngr_path", - QString(component_path)); - } - if (component_name == "keyboxd") { - UpsertRTValue(GetModuleIdentifier(), "gnupg.keyboxd_path", - QString(component_path)); - } - - { - GpgComponentInfo c_i; - c_i.name = component_name; - c_i.desc = component_desc; - c_i.version = version; - c_i.path = component_path; - c_i.binary_checksum = - (binary_checksum.has_value() ? binary_checksum.value() - : QString("/")); - - auto const jsonlized_component_info = c_i.Json(); - UpsertRTValue(GetModuleIdentifier(), - QString("gnupg.components.%1").arg(component_name), - QJsonDocument(jsonlized_component_info).toJson()); - - component_infos.push_back(c_i); - } - } - }, - getTaskRunner()}); - - GpgCommandExecutor::ExecuteContexts exec_contexts; -#ifdef QT5_BUILD - exec_contexts.push_back(GpgCommandExecutor::ExecuteContext{ -#else - exec_contexts.emplace_back(GpgCommandExecutor::ExecuteContext{ + // replace some special substrings on windows platform + component_path.replace("%3a", ":"); #endif - gpgconf_path, QStringList{"--list-dirs"}, - [this](int exit_code, const QString &p_out, const QString &p_err) { - if (exit_code != 0) return; - auto line_split_list = p_out.split("\n"); + auto binary_checksum = CheckBinaryChacksum(component_path); - for (const auto &line : line_split_list) { - auto info_split_list = line.split(":"); - MODULE_LOG_DEBUG("gpgconf direcrotries info line: {} info size: {}", - line, info_split_list.size()); + ModuleLogDebug( + fmt::format("gnupg component name: {} desc: {} checksum: {} path: {} ", + component_name, component_desc, + binary_checksum.has_value() ? binary_checksum.value() : "/", + component_path) + .c_str()); - if (info_split_list.size() != 2) continue; + QString version = "/"; - auto configuration_name = info_split_list[0].trimmed(); - auto configuration_value = info_split_list[1].trimmed(); + if (component_name == "gpg") { + version = + RetrieveRTValueOrDefault("core", "gpgme.ctx.gnupg_version", "2.0.0"); + } + if (component_name == "gpg-agent") { + UpsertRTValue(GetModuleID(), "gnupg.gpg_agent_path", + QString(component_path).toUtf8()); + } + if (component_name == "dirmngr") { + UpsertRTValue(GetModuleID(), "gnupg.dirmngr_path", + QString(component_path).toUtf8()); + } + if (component_name == "keyboxd") { + UpsertRTValue(GetModuleID(), "gnupg.keyboxd_path", + QString(component_path).toUtf8()); + } -#ifdef WINDOWS - // replace some special substrings on windows platform - configuration_value.replace("%3a", ":"); -#endif + { + GpgComponentInfo c_i; + c_i.name = component_name; + c_i.desc = component_desc; + c_i.version = version; + c_i.path = component_path; + c_i.binary_checksum = + (binary_checksum.has_value() ? binary_checksum.value() + : QString("/")); + + auto const jsonlized_component_info = c_i.Json(); + UpsertRTValue(GetModuleID(), + QString("gnupg.components.%1").arg(component_name).toUtf8(), + QJsonDocument(jsonlized_component_info).toJson()); + + component_infos.push_back(c_i); + } + } +} - // record gnupg home path - if (configuration_name == "homedir") { - UpsertRTValue(GetModuleIdentifier(), "gnupg.home_path", - configuration_value); - } +void GetGpgDirectoryInfos(void *, int exit_code, const char *out, + const char *err) { + if (exit_code != 0) return; - UpsertRTValue(GetModuleIdentifier(), - QString("gnupg.dirs.%1").arg(configuration_name), - configuration_value); - } - }, - getTaskRunner()}); + auto p_out = QString::fromUtf8(out); + auto p_err = QString::fromUtf8(err); + auto line_split_list = p_out.split("\n"); - auto components = ListRTChildKeys(GetModuleIdentifier(), "gnupg.components"); + for (const auto &line : line_split_list) { + auto info_split_list = line.split(":"); + ModuleLogDebug( + fmt::format("gpgconf direcrotries info line: {} info size: {}", line, + info_split_list.size()) + .c_str()); - for (const auto &component : components) { - auto component_info_json = RetrieveRTValueTypedOrDefault( - GetModuleIdentifier(), QString("gnupg.components.%1").arg(component), - QByteArray{}); + if (info_split_list.size() != 2) continue; - auto jsonlized_component_info = - QJsonDocument::fromJson(component_info_json); - assert(jsonlized_component_info.isObject()); + auto configuration_name = info_split_list[0].trimmed(); + auto configuration_value = info_split_list[1].trimmed(); - auto component_info = GpgComponentInfo(jsonlized_component_info.object()); - MODULE_LOG_DEBUG("gpgconf check options ready, component: {}", - component_info.name); +#ifdef WINDOWS + // replace some special substrings on windows platform + configuration_value.replace("%3a", ":"); +#endif - if (component_info.name == "gpgme" || component_info.name == "gpgconf") { - continue; + // record gnupg home path + if (configuration_name == "homedir") { + UpsertRTValue(GetModuleID(), "gnupg.home_path", + configuration_value.toUtf8()); } -#ifdef QT5_BUILD - exec_contexts.push_back(GpgCommandExecutor::ExecuteContext{ -#else - exec_contexts.emplace_back(GpgCommandExecutor::ExecuteContext{ -#endif - gpgconf_path, QStringList{"--list-options", component_info.name}, - [this, component_info](int exit_code, const QString &p_out, - const QString &p_err) { - MODULE_LOG_DEBUG( - "gpgconf {} avaliable options exit_code: {} process stdout " - "size: {} ", - component_info.name, exit_code, p_out.size()); - - if (exit_code != 0) { - MODULE_LOG_ERROR( - "gpgconf {} avaliable options execute error, process stderr: " - "{} , process stdout:", - component_info.name, p_err, p_out); - return; - } - - std::vector<GpgOptionsInfo> options_infos; - - auto line_split_list = p_out.split("\n"); - - for (const auto &line : line_split_list) { - auto info_split_list = line.split(":"); - - MODULE_LOG_DEBUG( - "component {} avaliable options line: {} info size: {}", - component_info.name, line, info_split_list.size()); - - if (info_split_list.size() < 10) continue; - - // The format of each line is: - // name:flags:level:description:type:alt-type:argname:default:argdef:value - - auto option_name = info_split_list[0].trimmed(); - auto option_flags = info_split_list[1].trimmed(); - auto option_level = info_split_list[2].trimmed(); - auto option_desc = info_split_list[3].trimmed(); - auto option_type = info_split_list[4].trimmed(); - auto option_alt_type = info_split_list[5].trimmed(); - auto option_argname = info_split_list[6].trimmed(); - auto option_default = info_split_list[7].trimmed(); - auto option_argdef = info_split_list[8].trimmed(); - auto option_value = info_split_list[9].trimmed(); - - GpgOptionsInfo info; - info.name = option_name; - info.flags = option_flags; - info.level = option_level; - info.description = option_desc; - info.type = option_type; - info.alt_type = option_alt_type; - info.argname = option_argname; - info.default_value = option_default; - info.argdef = option_argdef; - info.value = option_value; - - auto const jsonlized_option_info = info.Json(); - UpsertRTValue(GetModuleIdentifier(), - QString("gnupg.components.%1.options.%2") - .arg(component_info.name) - .arg(option_name), - QJsonDocument(jsonlized_option_info).toJson()); - options_infos.push_back(info); - } - }, - getTaskRunner()}); + UpsertRTValue(GetModuleID(), + QString("gnupg.dirs.%1").arg(configuration_name).toUtf8(), + configuration_value.toUtf8()); } - - GpgCommandExecutor::ExecuteConcurrentlySync(exec_contexts); - UpsertRTValue(GetModuleIdentifier(), "gnupg.gathering_done", true); - event->ExecuteCallback(GetModuleIdentifier(), TransferParams(true)); - - MODULE_LOG_DEBUG("gnupg external info gathering done"); - return 0; } -auto GnuPGInfoGatheringModule::Deactive() -> bool { return true; } - -} // namespace GpgFrontend::Module::Integrated::GnuPGInfoGatheringModule +void GetGpgOptionInfos(void *data, int exit_code, const char *out, + const char *err) { + if (exit_code != 0) return; + + auto p_out = QString::fromUtf8(out); + auto p_err = QString::fromUtf8(err); + auto *context = reinterpret_cast<Context *>(data); + + ModuleLogDebug( + fmt::format("gpgconf {} avaliable options exit_code: {} process stdout " + "size: {} ", + context->component_info.name, exit_code, p_out.size()) + .c_str()); + + std::vector<GpgOptionsInfo> options_infos; + + auto line_split_list = p_out.split("\n"); + + for (const auto &line : line_split_list) { + auto info_split_list = line.split(":"); + + ModuleLogDebug( + fmt::format("component {} avaliable options line: {} info size: {}", + context->component_info.name, line, info_split_list.size()) + .c_str()); + + if (info_split_list.size() < 10) continue; + + // The format of each line is: + // name:flags:level:description:type:alt-type:argname:default:argdef:value + + auto option_name = info_split_list[0].trimmed(); + auto option_flags = info_split_list[1].trimmed(); + auto option_level = info_split_list[2].trimmed(); + auto option_desc = info_split_list[3].trimmed(); + auto option_type = info_split_list[4].trimmed(); + auto option_alt_type = info_split_list[5].trimmed(); + auto option_argname = info_split_list[6].trimmed(); + auto option_default = info_split_list[7].trimmed(); + auto option_argdef = info_split_list[8].trimmed(); + auto option_value = info_split_list[9].trimmed(); + + GpgOptionsInfo info; + info.name = option_name; + info.flags = option_flags; + info.level = option_level; + info.description = option_desc; + info.type = option_type; + info.alt_type = option_alt_type; + info.argname = option_argname; + info.default_value = option_default; + info.argdef = option_argdef; + info.value = option_value; + + auto const jsonlized_option_info = info.Json(); + UpsertRTValue(GetModuleID(), + QString("gnupg.components.%1.options.%2") + .arg(context->component_info.name) + .arg(option_name) + .toUtf8(), + QJsonDocument(jsonlized_option_info).toJson()); + options_infos.push_back(info); + } +} |