diff options
author | saturneric <[email protected]> | 2025-04-18 15:54:54 +0000 |
---|---|---|
committer | saturneric <[email protected]> | 2025-04-18 15:54:54 +0000 |
commit | 8f14fdc7325cb9635e3d92873baaa58f430fca01 (patch) | |
tree | 323f462c283ac2151a23cfffd08d52a678c06541 /src | |
parent | fix: add missing libGLESv2.dll on windows platform (diff) | |
download | GpgFrontend-8f14fdc7325cb9635e3d92873baaa58f430fca01.tar.gz GpgFrontend-8f14fdc7325cb9635e3d92873baaa58f430fca01.zip |
feat: add more info check
Diffstat (limited to 'src')
35 files changed, 826 insertions, 465 deletions
diff --git a/src/core/GpgCoreInit.cpp b/src/core/GpgCoreInit.cpp index b544d071..ff9bb231 100644 --- a/src/core/GpgCoreInit.cpp +++ b/src/core/GpgCoreInit.cpp @@ -225,17 +225,17 @@ auto InitGpgME() -> bool { "core", "gpgme.ctx.gnupg_version", QString{}); if (!has_gpgconf) { - FLOG_E() << "cannot get gpgconf backend engine, abort..."; + LOG_E() << "cannot get gpgconf backend engine, abort..."; return false; } if (!has_openpgp) { - FLOG_E() << "cannot get openpgp backend engine, abort..."; + LOG_E() << "cannot get openpgp backend engine, abort..."; return false; } if (!has_cms) { - FLOG_E() << "cannot get cms backend engine, abort..."; + LOG_E() << "cannot get cms backend engine, abort..."; return false; } @@ -520,8 +520,8 @@ auto InitGpgFrontendCore(CoreInitArgs args) -> int { assert(!key_dbs.isEmpty()); if (key_dbs.isEmpty()) { - FLOG_E() << "Cannot find any valid key database!" - << "GpgFrontend cannot start under this situation!"; + LOG_E() << "Cannot find any valid key database!" + << "GpgFrontend cannot start under this situation!"; Module::UpsertRTValue("core", "env.state.ctx", -1); CoreSignalStation::GetInstance()->SignalBadGnupgEnv( QCoreApplication::tr("No valid Key Database")); @@ -549,8 +549,8 @@ auto InitGpgFrontendCore(CoreInitArgs args) -> int { args, kGpgFrontendDefaultChannel)); }); if (!default_ctx.Good()) { - FLOG_E() << "Init GpgME Default Context failed!" - << "GpgFrontend cannot start under this situation!"; + LOG_E() << "Init GpgME Default Context failed!" + << "GpgFrontend cannot start under this situation!"; Module::UpsertRTValue("core", "env.state.ctx", -1); CoreSignalStation::GetInstance()->SignalBadGnupgEnv( QCoreApplication::tr("GpgME Default Context Initiation Failed")); @@ -560,8 +560,8 @@ auto InitGpgFrontendCore(CoreInitArgs args) -> int { Module::UpsertRTValue("core", "env.state.ctx", 1); if (!GpgKeyGetter::GetInstance(kGpgFrontendDefaultChannel).FlushKeyCache()) { - FLOG_E() << "Init GpgME Default Key Database failed!" - << "GpgFrontend cannot start under this situation!"; + LOG_E() << "Init GpgME Default Key Database failed!" + << "GpgFrontend cannot start under this situation!"; Module::UpsertRTValue("core", "env.state.ctx", -1); CoreSignalStation::GetInstance()->SignalBadGnupgEnv( QCoreApplication::tr("Gpg Default Key Database Initiation Failed")); @@ -602,13 +602,13 @@ auto InitGpgFrontendCore(CoreInitArgs args) -> int { }); if (!ctx.Good()) { - FLOG_E() << "gpgme context init failed, index:" << channel_index; + LOG_E() << "gpgme context init failed, index:" << channel_index; continue; } if (!GpgKeyGetter::GetInstance(ctx.GetChannel()).FlushKeyCache()) { - FLOG_E() << "gpgme context init key cache failed, index:" - << channel_index; + LOG_E() << "gpgme context init key cache failed, index:" + << channel_index; continue; } @@ -631,9 +631,16 @@ auto InitGpgFrontendCore(CoreInitArgs args) -> int { .GetTaskRunner(Thread::TaskRunnerGetter::kTaskRunnerType_Default) ->PostTask(task); - if (!args.unit_test_mode && restart_all_gnupg_components_on_start) { - GpgAdvancedOperator::RestartGpgComponents(nullptr); + const auto size = GpgContext::GetAllChannelId().size(); + for (auto i = 0; i < size; i++) { + if (!args.unit_test_mode && restart_all_gnupg_components_on_start) { + assert(GpgAdvancedOperator::GetInstance().RestartGpgComponents()); + } else { + // ensure gpg-agent is running + assert(GpgAdvancedOperator::GetInstance().LaunchAllGpgComponents()); + } } + return 0; } diff --git a/src/core/function/gpg/GpgAdvancedOperator.cpp b/src/core/function/gpg/GpgAdvancedOperator.cpp index 492297c6..c9af8b59 100644 --- a/src/core/function/gpg/GpgAdvancedOperator.cpp +++ b/src/core/function/gpg/GpgAdvancedOperator.cpp @@ -33,91 +33,38 @@ #include "GpgAdvancedOperator.h" #include "core/function/gpg/GpgCommandExecutor.h" -#include "core/module/ModuleManager.h" -#include "core/utils/GpgUtils.h" - namespace GpgFrontend { -void ExecuteGpgCommand(const QString &operation, const QStringList &extra_args, - OperationCallback cb) { - const auto gpgconf_path = Module::RetrieveRTValueTypedOrDefault<>( - "core", "gpgme.ctx.gpgconf_path", QString{}); - - if (gpgconf_path.isEmpty()) { - FLOG_W("cannot get valid gpgconf path from rt, abort."); - if (cb) cb(-1, TransferParams()); - return; - } - - auto key_dbs = GetGpgKeyDatabaseInfos(); - auto total_tasks = static_cast<int>(key_dbs.size()); - std::atomic<int> completed_tasks{0}; - std::vector<int> results(total_tasks, 0); - - // kill default gpg-agent - key_dbs.push_back({}); - - int task_index = 0; - for (const auto &key_db : key_dbs) { - const int current_index = task_index++; - const auto target_home_dir = - QDir::toNativeSeparators(QFileInfo(key_db.path).canonicalFilePath()); - - QStringList arguments = !target_home_dir.isEmpty() - ? QStringList{"--homedir", target_home_dir} - : QStringList{}; - arguments.append(extra_args); - - GpgCommandExecutor::ExecuteSync( - {gpgconf_path, arguments, - [=, &completed_tasks, &results](int exit_code, const QString &, - const QString &) { - FLOG_D("%s exit code: %d", qPrintable(operation), exit_code); - - results[current_index] = exit_code; - - if (++completed_tasks == total_tasks && cb) { - int final_result = - std::all_of(results.begin(), results.end(), - [](int result) { return result >= 0; }) - ? 0 - : -1; - cb(final_result, TransferParams()); - } - }}); - } -} - -void GpgAdvancedOperator::ClearGpgPasswordCache(OperationCallback cb) { - ExecuteGpgCommand("Clear GPG Password Cache", {"--reload", "gpg-agent"}, - std::move(cb)); +auto GpgAdvancedOperator::ClearGpgPasswordCache() -> bool { + auto [ret, out] = exec_.GpgConfExecuteSync({{"--reload", "gpg-agent"}}); + return ret == 0; } -void GpgAdvancedOperator::ReloadGpgComponents(OperationCallback cb) { - const auto gpgconf_path = Module::RetrieveRTValueTypedOrDefault<>( - "core", "gpgme.ctx.gpgconf_path", QString{}); - ExecuteGpgCommand("Reload GPG Components", {"--reload", "all"}, - std::move(cb)); +auto GpgAdvancedOperator::ReloadAllGpgComponents() -> bool { + auto [ret, out] = exec_.GpgConfExecuteSync({{"--reload", "all"}}); + return ret == 0; } -void GpgAdvancedOperator::KillAllGpgComponents(OperationCallback cb) { - ExecuteGpgCommand("Kill All GPG Components", {"--kill", "all"}, - std::move(cb)); +auto GpgAdvancedOperator::KillAllGpgComponents() -> bool { + auto [ret, out] = exec_.GpgConfExecuteSync({{"--kill", "all"}}); + return ret == 0; } -void GpgAdvancedOperator::ResetConfigures(OperationCallback cb) { - ExecuteGpgCommand("Reset Gnupg Configures", {"--apply-defaults"}, - std::move(cb)); +auto GpgAdvancedOperator::ResetConfigures() -> bool { + auto [ret, out] = exec_.GpgConfExecuteSync({{"--apply-defaults"}}); + return ret == 0; } -void GpgAdvancedOperator::LaunchGpgComponents(OperationCallback cb) { - ExecuteGpgCommand("Launch All GPG Components", {"--launch", "all"}, - std::move(cb)); +auto GpgAdvancedOperator::LaunchAllGpgComponents() -> bool { + auto [ret, out] = exec_.GpgConfExecuteSync({{"--launch", "all"}}); + return ret == 0; } -void GpgAdvancedOperator::RestartGpgComponents(OperationCallback cb) { - KillAllGpgComponents(nullptr); - LaunchGpgComponents(std::move(cb)); +auto GpgAdvancedOperator::RestartGpgComponents() -> bool { + if (!KillAllGpgComponents()) return false; + return LaunchAllGpgComponents(); } +GpgAdvancedOperator::GpgAdvancedOperator(int channel) + : SingletonFunctionObject<GpgAdvancedOperator>(channel) {} } // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/function/gpg/GpgAdvancedOperator.h b/src/core/function/gpg/GpgAdvancedOperator.h index 57279adb..1099c3b3 100644 --- a/src/core/function/gpg/GpgAdvancedOperator.h +++ b/src/core/function/gpg/GpgAdvancedOperator.h @@ -32,19 +32,29 @@ #pragma once +#include "core/function/basic/GpgFunctionObject.h" +#include "core/function/gpg/GpgCommandExecutor.h" #include "core/model/DataObject.h" namespace GpgFrontend { -class GPGFRONTEND_CORE_EXPORT GpgAdvancedOperator { +class GPGFRONTEND_CORE_EXPORT GpgAdvancedOperator + : public SingletonFunctionObject<GpgAdvancedOperator> { public: /** + * @brief Construct a new Gpg Advanced Operator object + * + * @param channel + */ + explicit GpgAdvancedOperator(int channel); + + /** * @brief * * @return true * @return false */ - static void ClearGpgPasswordCache(OperationCallback); + auto ClearGpgPasswordCache() -> bool; /** * @brief @@ -52,7 +62,7 @@ class GPGFRONTEND_CORE_EXPORT GpgAdvancedOperator { * @return true * @return false */ - static void ReloadGpgComponents(OperationCallback); + auto ReloadAllGpgComponents() -> bool; /** * @brief @@ -60,7 +70,7 @@ class GPGFRONTEND_CORE_EXPORT GpgAdvancedOperator { * @return true * @return false */ - static void RestartGpgComponents(OperationCallback); + auto RestartGpgComponents() -> bool; /** * @brief @@ -68,7 +78,7 @@ class GPGFRONTEND_CORE_EXPORT GpgAdvancedOperator { * @return true * @return false */ - static void ResetConfigures(OperationCallback); + auto ResetConfigures() -> bool; /** * @brief @@ -76,13 +86,17 @@ class GPGFRONTEND_CORE_EXPORT GpgAdvancedOperator { * @return true * @return false */ - static void LaunchGpgComponents(OperationCallback); + auto LaunchAllGpgComponents() -> bool; /** * @brief * */ - static void KillAllGpgComponents(OperationCallback); + auto KillAllGpgComponents() -> bool; + + private: + GpgCommandExecutor& exec_ = + GpgCommandExecutor::GetInstance(SingletonFunctionObject::GetChannel()); }; } // namespace GpgFrontend diff --git a/src/core/function/gpg/GpgAssuanHelper.cpp b/src/core/function/gpg/GpgAssuanHelper.cpp index 0d1b9cdc..128ecaa9 100644 --- a/src/core/function/gpg/GpgAssuanHelper.cpp +++ b/src/core/function/gpg/GpgAssuanHelper.cpp @@ -44,14 +44,14 @@ GpgAssuanHelper::~GpgAssuanHelper() { } } -auto GpgAssuanHelper::ConnectToSocket(GpgComponentType type) -> bool { - if (assuan_ctx_.contains(type)) return true; +auto GpgAssuanHelper::ConnectToSocket(GpgComponentType type) -> GpgError { + if (assuan_ctx_.contains(type)) return GPG_ERR_NO_ERROR; auto socket_path = ctx_.ComponentDirectory(type); if (socket_path.isEmpty()) { LOG_W() << "socket path of component: " << component_type_to_q_string(type) << " is empty"; - return false; + return GPG_ERR_ENOPKG; } QFileInfo info(socket_path); @@ -65,7 +65,7 @@ auto GpgAssuanHelper::ConnectToSocket(GpgComponentType type) -> bool { if (!info.exists()) { LOG_W() << "socket path is still not exists: " << socket_path << "abort..."; - return false; + return GPG_ERR_ENOTSOCK; } } @@ -76,7 +76,7 @@ auto GpgAssuanHelper::ConnectToSocket(GpgComponentType type) -> bool { ASSUAN_INVALID_PID, 0); if (err != GPG_ERR_NO_ERROR) { LOG_W() << "failed to connect to socket:" << CheckGpgError(err); - return false; + return err; } LOG_D() << "connected to socket by assuan protocol: " @@ -86,21 +86,23 @@ auto GpgAssuanHelper::ConnectToSocket(GpgComponentType type) -> bool { nullptr, nullptr, nullptr, nullptr); if (err != GPG_ERR_NO_ERROR) { LOG_W() << "failed to test assuan connection:" << CheckGpgError(err); - return false; + return err; } assuan_ctx_[type] = a_ctx; - return true; + return err; } auto GpgAssuanHelper::SendCommand(GpgComponentType type, const QString& command, DataCallback data_cb, InqueryCallback inquery_cb, - StatusCallback status_cb) -> bool { + StatusCallback status_cb) -> GpgError { if (!assuan_ctx_.contains(type)) { LOG_W() << "haven't connect to: " << component_type_to_q_string(type) << ", trying to make a connection"; - if (!ConnectToSocket(type)) return false; + + auto err = CheckGpgError(ConnectToSocket(type)); + if (err != GPG_ERR_NO_ERROR) return err; } auto context = QSharedPointer<AssuanCallbackContext>::create(); @@ -122,15 +124,15 @@ auto GpgAssuanHelper::SendCommand(GpgComponentType type, const QString& command, if (CheckGpgError(err) == 32877) { assuan_ctx_.remove(type); } - return false; + return err; } - return true; + return err; } auto GpgAssuanHelper::SendStatusCommand(GpgComponentType type, const QString& command) - -> std::tuple<bool, QStringList> { + -> std::tuple<GpgError, QStringList> { GpgAssuanHelper::DataCallback d_cb = [&](const QSharedPointer<GpgAssuanHelper::AssuanCallbackContext>& ctx) -> gpg_error_t { @@ -147,29 +149,29 @@ auto GpgAssuanHelper::SendStatusCommand(GpgComponentType type, return 0; }; - QStringList status_lines; + QStringList lines; GpgAssuanHelper::StatusCallback s_cb = [&](const QSharedPointer<GpgAssuanHelper::AssuanCallbackContext>& ctx) -> gpg_error_t { LOG_D() << "status callback of command: " << command << ": " << ctx->status; - status_lines.append(ctx->status); + lines.append(ctx->status); return 0; }; auto ret = SendCommand(type, command, d_cb, i_cb, s_cb); - return {ret, status_lines}; + return {ret, lines}; } auto GpgAssuanHelper::SendDataCommand(GpgComponentType type, const QString& command) -> std::tuple<bool, QStringList> { - QStringList data_lines; + QStringList lines; GpgAssuanHelper::DataCallback d_cb = [&](const QSharedPointer<GpgAssuanHelper::AssuanCallbackContext>& ctx) -> gpg_error_t { LOG_D() << "data callback of command " << command << ": " << ctx->buffer; - data_lines.push_back(QString::fromUtf8(ctx->buffer)); + lines.push_back(QString::fromUtf8(ctx->buffer)); return 0; }; @@ -192,7 +194,7 @@ auto GpgAssuanHelper::SendDataCommand(GpgComponentType type, }; auto ret = SendCommand(type, command, d_cb, i_cb, s_cb); - return {ret, data_lines}; + return {ret, lines}; } auto GpgAssuanHelper::default_data_callback(void* opaque, const void* buffer, diff --git a/src/core/function/gpg/GpgAssuanHelper.h b/src/core/function/gpg/GpgAssuanHelper.h index 294d33e0..7f3854b6 100644 --- a/src/core/function/gpg/GpgAssuanHelper.h +++ b/src/core/function/gpg/GpgAssuanHelper.h @@ -81,7 +81,7 @@ class GPGFRONTEND_CORE_EXPORT GpgAssuanHelper * @return true * @return false */ - auto ConnectToSocket(GpgComponentType) -> bool; + auto ConnectToSocket(GpgComponentType) -> GpgError; /** * @brief @@ -96,7 +96,7 @@ class GPGFRONTEND_CORE_EXPORT GpgAssuanHelper */ auto SendCommand(GpgComponentType type, const QString& command, DataCallback data_cb, InqueryCallback inquery_cb, - StatusCallback status_cb) -> bool; + StatusCallback status_cb) -> GpgError; /** * @brief @@ -106,7 +106,7 @@ class GPGFRONTEND_CORE_EXPORT GpgAssuanHelper * @return std::tuple<bool, QStringList> */ auto SendStatusCommand(GpgComponentType type, const QString& command) - -> std::tuple<bool, QStringList>; + -> std::tuple<GpgError, QStringList>; /** * @brief diff --git a/src/core/function/gpg/GpgAutomatonHandler.cpp b/src/core/function/gpg/GpgAutomatonHandler.cpp index 656bb018..afa55299 100644 --- a/src/core/function/gpg/GpgAutomatonHandler.cpp +++ b/src/core/function/gpg/GpgAutomatonHandler.cpp @@ -39,65 +39,61 @@ GpgAutomatonHandler::GpgAutomatonHandler(int channel) auto InteratorCbFunc(void* handle, const char* status, const char* args, int fd) -> gpgme_error_t { - auto* handle_struct = static_cast<AutomatonHandelStruct*>(handle); - QString status_s = status; - QString args_s = args; + auto* handel = static_cast<AutomatonHandelStruct*>(handle); + const auto status_s = QString::fromUtf8(status); + const auto args_s = QString::fromUtf8(args); if (status_s == "KEY_CONSIDERED") { auto tokens = QString(args).split(' '); - if (handle_struct->KeyFpr().isEmpty()) return 0; + if (handel->KeyFpr().isEmpty()) return GPG_ERR_NO_ERROR; - if (tokens.empty() || tokens[0] != handle_struct->KeyFpr()) { - LOG_W() << "handle struct key fpr: " << handle_struct->KeyFpr() + if (tokens.empty() || tokens[0] != handel->KeyFpr()) { + LOG_W() << "handle struct key fpr: " << handel->KeyFpr() << "mismatch token: " << tokens[0] << ", exit..."; - + handel->SetSuccess(false); return -1; } - return 0; + return GPG_ERR_NO_ERROR; } if (status_s == "CARDCTRL") { auto tokens = QString(args).split(' '); - if (handle_struct->SerialNumber().isEmpty()) return 0; + if (handel->SerialNumber().isEmpty()) return GPG_ERR_NO_ERROR; - if (tokens.empty() || tokens[0] != handle_struct->SerialNumber()) { - LOG_W() << "handle struct serial number: " - << handle_struct->SerialNumber() + if (tokens.empty() || tokens[0] != handel->SerialNumber()) { + LOG_W() << "handle struct serial number: " << handel->SerialNumber() << "mismatch token: " << tokens[0] << ", exit..."; - + handel->SetSuccess(false); return -1; } - return 0; + return GPG_ERR_NO_ERROR; } if (status_s == "GOT_IT" || status_s.isEmpty()) { FLOG_D("gpg reply is GOT_IT, continue..."); - return 0; + return GPG_ERR_NO_ERROR; } - LOG_D() << "current state" << handle_struct->CurrentStatus() + LOG_D() << "current state" << handel->CurrentStatus() << "gpg status: " << status_s << ", args: " << args_s; - handle_struct->SetPromptStatus(status_s, args_s); + handel->SetPromptStatus(status_s, args_s); - AutomatonState next_state = handle_struct->NextState(status_s, args_s); + AutomatonState next_state = handel->NextState(status_s, args_s); if (next_state == GpgAutomatonHandler::kAS_ERROR) { - FLOG_D("handle struct next state caught error, abort..."); + FLOG_D("handel next state caught error, abort..."); + handel->SetSuccess(false); return -1; } - LOG_D() << "next state" << next_state; - - if (next_state == GpgAutomatonHandler::kAS_SAVE) { - handle_struct->SetSuccess(true); - } + LOG_D() << "next state:" << next_state; // set state and preform action - handle_struct->SetStatus(next_state); - GpgAutomatonHandler::Command cmd = handle_struct->Action(); + handel->SetStatus(next_state); + GpgAutomatonHandler::Command cmd = handel->Action(); LOG_D() << "next action, cmd:" << cmd; @@ -110,32 +106,33 @@ auto InteratorCbFunc(void* handle, const char* status, const char* args, return GPG_ERR_FALSE; } - return 0; + return GPG_ERR_NO_ERROR; } auto DoInteractImpl(GpgContext& ctx_, const GpgKeyPtr& key, bool card_edit, const QString& id, AutomatonNextStateHandler next_state_handler, - AutomatonActionHandler action_handler, int flags) -> bool { + AutomatonActionHandler action_handler, + int flags) -> std::tuple<GpgError, bool> { gpgme_key_t p_key = key == nullptr ? nullptr : static_cast<gpgme_key_t>(*key); - AutomatonHandelStruct handel_struct(card_edit, id); - handel_struct.SetHandler(std::move(next_state_handler), - std::move(action_handler)); + AutomatonHandelStruct handel(card_edit, id); + handel.SetHandler(std::move(next_state_handler), std::move(action_handler)); GpgData data_out; auto err = gpgme_op_interact(ctx_.DefaultContext(), p_key, flags, InteratorCbFunc, - static_cast<void*>(&handel_struct), data_out); - return CheckGpgError(err) == GPG_ERR_NO_ERROR && handel_struct.Success(); + static_cast<void*>(&handel), data_out); + return {err, handel.Success()}; } auto GpgAutomatonHandler::DoInteract( const GpgKeyPtr& key, AutomatonNextStateHandler next_state_handler, - AutomatonActionHandler action_handler, int flags) -> bool { + AutomatonActionHandler action_handler, + int flags) -> std::tuple<GpgError, bool> { assert(key != nullptr); - if (key == nullptr) return false; + if (key == nullptr) return {GPG_ERR_USER_1, false}; return DoInteractImpl(ctx_, key, false, key->ID(), std::move(next_state_handler), std::move(action_handler), flags); @@ -143,7 +140,7 @@ auto GpgAutomatonHandler::DoInteract( auto GpgAutomatonHandler::DoCardInteract( const QString& serial_number, AutomatonNextStateHandler next_state_handler, - AutomatonActionHandler action_handler) -> bool { + AutomatonActionHandler action_handler) -> std::tuple<GpgError, bool> { return DoInteractImpl(ctx_, nullptr, true, serial_number, std::move(next_state_handler), std::move(action_handler), GPGME_INTERACT_CARD); diff --git a/src/core/function/gpg/GpgAutomatonHandler.h b/src/core/function/gpg/GpgAutomatonHandler.h index 4363cf30..7ab2bf44 100644 --- a/src/core/function/gpg/GpgAutomatonHandler.h +++ b/src/core/function/gpg/GpgAutomatonHandler.h @@ -83,7 +83,7 @@ class GpgAutomatonHandler AutomatonState current_state_ = kAS_START; AutomatonNextStateHandler next_state_handler_; AutomatonActionHandler action_handler_; - bool success_ = false; + bool success_ = true; bool card_edit_; QString id_; QString prompt_status_; @@ -110,7 +110,8 @@ class GpgAutomatonHandler */ auto DoInteract(const GpgKeyPtr& key, AutomatonNextStateHandler next_state_handler, - AutomatonActionHandler action_handler, int flags = 0) -> bool; + AutomatonActionHandler action_handler, + int flags = 0) -> std::tuple<GpgError, bool>; /** * @brief @@ -122,7 +123,8 @@ class GpgAutomatonHandler */ auto DoCardInteract(const QString& serial_number, AutomatonNextStateHandler next_state_handler, - AutomatonActionHandler action_handler) -> bool; + AutomatonActionHandler action_handler) + -> std::tuple<GpgError, bool>; private: GpgContext& ctx_ = diff --git a/src/core/function/gpg/GpgBasicOperator.cpp b/src/core/function/gpg/GpgBasicOperator.cpp index 2f624b60..bdb687bc 100644 --- a/src/core/function/gpg/GpgBasicOperator.cpp +++ b/src/core/function/gpg/GpgBasicOperator.cpp @@ -88,39 +88,43 @@ void GpgBasicOperator::Encrypt(const GpgAbstractKeyPtrList& keys, const GFBuffer& in_buffer, bool ascii, const GpgOperationCallback& cb) { RunGpgOperaAsync( + GetChannel(), [=](const DataObjectPtr& data_object) { return EncryptImpl(ctx_, keys, in_buffer, ascii, data_object); }, - cb, "gpgme_op_encrypt", "2.1.0"); + cb, "gpgme_op_encrypt", "2.2.0"); } auto GpgBasicOperator::EncryptSync(const GpgAbstractKeyPtrList& keys, const GFBuffer& in_buffer, bool ascii) -> std::tuple<GpgError, DataObjectPtr> { return RunGpgOperaSync( + GetChannel(), [=](const DataObjectPtr& data_object) { return EncryptImpl(ctx_, keys, in_buffer, ascii, data_object); }, - "gpgme_op_encrypt", "2.1.0"); + "gpgme_op_encrypt", "2.2.0"); } void GpgBasicOperator::EncryptSymmetric(const GFBuffer& in_buffer, bool ascii, const GpgOperationCallback& cb) { RunGpgOperaAsync( + GetChannel(), [=](const DataObjectPtr& data_object) { return EncryptImpl(ctx_, {}, in_buffer, ascii, data_object); }, - cb, "gpgme_op_encrypt_symmetric", "2.1.0"); + cb, "gpgme_op_encrypt_symmetric", "2.2.0"); } auto GpgBasicOperator::EncryptSymmetricSync(const GFBuffer& in_buffer, bool ascii) -> std::tuple<GpgError, DataObjectPtr> { return RunGpgOperaSync( + GetChannel(), [=](const DataObjectPtr& data_object) { return EncryptImpl(ctx_, {}, in_buffer, ascii, data_object); }, - "gpgme_op_encrypt_symmetric", "2.1.0"); + "gpgme_op_encrypt_symmetric", "2.2.0"); } auto DecryptImpl(GpgContext& ctx_, const GFBuffer& in_buffer, @@ -141,19 +145,21 @@ auto DecryptImpl(GpgContext& ctx_, const GFBuffer& in_buffer, void GpgBasicOperator::Decrypt(const GFBuffer& in_buffer, const GpgOperationCallback& cb) { RunGpgOperaAsync( + GetChannel(), [=](const DataObjectPtr& data_object) { return DecryptImpl(ctx_, in_buffer, data_object); }, - cb, "gpgme_op_decrypt", "2.1.0"); + cb, "gpgme_op_decrypt", "2.2.0"); } auto GpgBasicOperator::DecryptSync(const GFBuffer& in_buffer) -> std::tuple<GpgError, DataObjectPtr> { return RunGpgOperaSync( + GetChannel(), [=](const DataObjectPtr& data_object) { return DecryptImpl(ctx_, in_buffer, data_object); }, - "gpgme_op_decrypt", "2.1.0"); + "gpgme_op_decrypt", "2.2.0"); } auto VerifyImpl(GpgContext& ctx_, const GFBuffer& in_buffer, @@ -185,20 +191,22 @@ void GpgBasicOperator::Verify(const GFBuffer& in_buffer, const GFBuffer& sig_buffer, const GpgOperationCallback& cb) { RunGpgOperaAsync( + GetChannel(), [=](const DataObjectPtr& data_object) -> GpgError { return VerifyImpl(ctx_, in_buffer, sig_buffer, data_object); }, - cb, "gpgme_op_verify", "2.1.0"); + cb, "gpgme_op_verify", "2.2.0"); } auto GpgBasicOperator::VerifySync(const GFBuffer& in_buffer, const GFBuffer& sig_buffer) -> std::tuple<GpgError, DataObjectPtr> { return RunGpgOperaSync( + GetChannel(), [=](const DataObjectPtr& data_object) { return VerifyImpl(ctx_, in_buffer, sig_buffer, data_object); }, - "gpgme_op_verify", "2.1.0"); + "gpgme_op_verify", "2.2.0"); } auto SignImpl(GpgContext& ctx_, const GpgAbstractKeyPtrList& signers, @@ -228,20 +236,22 @@ void GpgBasicOperator::Sign(const GpgAbstractKeyPtrList& signers, const GFBuffer& in_buffer, GpgSignMode mode, bool ascii, const GpgOperationCallback& cb) { RunGpgOperaAsync( + GetChannel(), [=](const DataObjectPtr& data_object) { return SignImpl(ctx_, signers, in_buffer, mode, ascii, data_object); }, - cb, "gpgme_op_sign", "2.1.0"); + cb, "gpgme_op_sign", "2.2.0"); } auto GpgBasicOperator::SignSync( const GpgAbstractKeyPtrList& signers, const GFBuffer& in_buffer, GpgSignMode mode, bool ascii) -> std::tuple<GpgError, DataObjectPtr> { return RunGpgOperaSync( + GetChannel(), [=](const DataObjectPtr& data_object) { return SignImpl(ctx_, signers, in_buffer, mode, ascii, data_object); }, - "gpgme_op_sign", "2.1.0"); + "gpgme_op_sign", "2.2.0"); } auto DecryptVerifyImpl(GpgContext& ctx_, const GFBuffer& in_buffer, @@ -266,19 +276,21 @@ auto DecryptVerifyImpl(GpgContext& ctx_, const GFBuffer& in_buffer, void GpgBasicOperator::DecryptVerify(const GFBuffer& in_buffer, const GpgOperationCallback& cb) { RunGpgOperaAsync( + GetChannel(), [=](const DataObjectPtr& data_object) { return DecryptVerifyImpl(ctx_, in_buffer, data_object); }, - cb, "gpgme_op_decrypt_verify", "2.1.0"); + cb, "gpgme_op_decrypt_verify", "2.2.0"); } auto GpgBasicOperator::DecryptVerifySync(const GFBuffer& in_buffer) -> std::tuple<GpgError, DataObjectPtr> { return RunGpgOperaSync( + GetChannel(), [=](const DataObjectPtr& data_object) -> GpgError { return DecryptVerifyImpl(ctx_, in_buffer, data_object); }, - "gpgme_op_decrypt_verify", "2.1.0"); + "gpgme_op_decrypt_verify", "2.2.0"); } auto EncryptSignImpl(GpgContext& ctx_, const GpgAbstractKeyPtrList& keys, @@ -315,11 +327,12 @@ void GpgBasicOperator::EncryptSign(const GpgAbstractKeyPtrList& keys, const GFBuffer& in_buffer, bool ascii, const GpgOperationCallback& cb) { RunGpgOperaAsync( + GetChannel(), [=](const DataObjectPtr& data_object) -> GpgError { return EncryptSignImpl(ctx_, keys, signers, in_buffer, ascii, data_object); }, - cb, "gpgme_op_encrypt_sign", "2.1.0"); + cb, "gpgme_op_encrypt_sign", "2.2.0"); } auto GpgBasicOperator::EncryptSignSync(const GpgAbstractKeyPtrList& keys, @@ -327,11 +340,12 @@ auto GpgBasicOperator::EncryptSignSync(const GpgAbstractKeyPtrList& keys, const GFBuffer& in_buffer, bool ascii) -> std::tuple<GpgError, DataObjectPtr> { return RunGpgOperaSync( + GetChannel(), [=](const DataObjectPtr& data_object) -> GpgError { return EncryptSignImpl(ctx_, keys, signers, in_buffer, ascii, data_object); }, - "gpgme_op_encrypt_sign", "2.1.0"); + "gpgme_op_encrypt_sign", "2.2.0"); } void GpgBasicOperator::SetSigners(const GpgAbstractKeyPtrList& signers, @@ -346,7 +360,7 @@ auto GpgBasicOperator::GetSigners(bool ascii) -> KeyArgsList { auto signers = KeyArgsList{}; for (auto i = 0U; i < count; i++) { auto key = GpgKey(gpgme_signers_enum(ctx, i)); - signers.push_back(GpgKey(std::move(key))); + signers.push_back(GpgKey(key)); } return signers; } diff --git a/src/core/function/gpg/GpgCommandExecutor.cpp b/src/core/function/gpg/GpgCommandExecutor.cpp index dd8a500e..72988a55 100644 --- a/src/core/function/gpg/GpgCommandExecutor.cpp +++ b/src/core/function/gpg/GpgCommandExecutor.cpp @@ -41,26 +41,25 @@ auto BuildTaskFromExecCtx(const GpgCommandExecutor::ExecuteContext &context) -> Thread::Task * { const auto &cmd = context.cmd; const auto &arguments = context.arguments; - const auto &interact_function = context.int_func; - const auto &cmd_executor_callback = context.cb_func; + const auto &int_func = context.int_func; + const auto &cb = context.cb_func; - Thread::Task::TaskCallback result_callback = - [cmd](int /*rtn*/, const DataObjectPtr &data_object) { - LOG_D() << "data object args count of cmd executor result callback:" - << data_object->GetObjectSize(); + Thread::Task::TaskCallback result_callback = [cmd](int /*rtn*/, + const DataObjectPtr &obj) { + LOG_D() << "data object args count of cmd executor result callback:" + << obj->GetObjectSize(); - if (!data_object->Check<int, QString, GpgCommandExecutorCallback>()) { - FLOG_W("data object checking failed"); - return; - } + if (!obj->Check<int, QByteArray, GpgCommandExecutorCallback>()) { + FLOG_W("data object checking failed"); + return; + } - auto exit_code = ExtractParams<int>(data_object, 0); - auto process_stdout = ExtractParams<QString>(data_object, 1); - auto callback = - ExtractParams<GpgCommandExecutorCallback>(data_object, 2); + auto code = ExtractParams<int>(obj, 0); + auto out = ExtractParams<QByteArray>(obj, 1); + auto cb = ExtractParams<GpgCommandExecutorCallback>(obj, 2); - callback(exit_code, process_stdout, {}); - }; + cb(code, out, {}); + }; Thread::Task::TaskRunnable runner = [](const DataObjectPtr &data_object) -> int { @@ -82,71 +81,67 @@ auto BuildTaskFromExecCtx(const GpgCommandExecutor::ExecuteContext &context) const QString joined_argument = arguments.join(" "); // create process - auto *cmd_process = new QProcess(); + auto *pcs = new QProcess(); // move to current thread // - cmd_process->moveToThread(QThread::currentThread()); + pcs->moveToThread(QThread::currentThread()); // set process channel mode // this is to make sure we can get all output from stdout and stderr - cmd_process->setProcessChannelMode(QProcess::MergedChannels); - cmd_process->setProgram(cmd); + pcs->setProcessChannelMode(QProcess::MergedChannels); + pcs->setProgram(cmd); // set arguments QStringList q_arguments; for (const auto &argument : arguments) { q_arguments.append(argument); } - cmd_process->setArguments(q_arguments); + pcs->setArguments(q_arguments); + QObject::connect(pcs, &QProcess::started, [cmd, joined_argument]() -> void { + LOG_D() << "\n== Process Execute Started ==\nCommand: " << cmd + << "\nArguments: " << joined_argument + << " \n========================"; + }); + QObject::connect(pcs, &QProcess::readyReadStandardOutput, + [interact_func, pcs]() { interact_func(pcs); }); QObject::connect( - cmd_process, &QProcess::started, [cmd, joined_argument]() -> void { - LOG_D() << "\n== Process Execute Started ==\nCommand: " << cmd - << "\nArguments: " << joined_argument - << " \n========================"; + pcs, &QProcess::errorOccurred, [=](QProcess::ProcessError error) { + LOG_W() << "caught error while executing command: " << cmd + << joined_argument << ", error:" << error; }); - QObject::connect( - cmd_process, &QProcess::readyReadStandardOutput, - [interact_func, cmd_process]() { interact_func(cmd_process); }); - QObject::connect(cmd_process, &QProcess::errorOccurred, - [=](QProcess::ProcessError error) { - LOG_W() - << "caught error while executing command: " << cmd - << joined_argument << ", error:" << error; - }); LOG_D() << "\n== Process Execute Ready ==\nCommand: " << cmd << "\nArguments: " << joined_argument << "\n========================"; - cmd_process->start(); - cmd_process->waitForFinished(); + pcs->start(); + pcs->waitForFinished(); - QString process_stdout = cmd_process->readAllStandardOutput(); - int exit_code = cmd_process->exitCode(); + auto out = pcs->readAllStandardOutput(); + auto code = pcs->exitCode(); LOG_D() << "\n==== Process Execution Summary ====\n" << "Command: " << cmd << "\n" << "Arguments: " << joined_argument << "\n" - << "Exit Code: " << exit_code << "\n" + << "Exit Code: " << code << "\n" << "---- Standard Output ----\n" - << process_stdout << "\n" + << out << "\n" << "==============================="; - cmd_process->close(); - cmd_process->deleteLater(); + pcs->close(); + pcs->deleteLater(); - data_object->Swap({exit_code, process_stdout, callback}); + data_object->Swap({code, out, callback}); return 0; }; return new Thread::Task( std::move(runner), QString("GpgCommamdExecutor(%1){%2}").arg(cmd).arg(arguments.join(' ')), - TransferParams(cmd, arguments, interact_function, cmd_executor_callback), - std::move(result_callback)); + TransferParams(cmd, arguments, int_func, cb), std::move(result_callback)); } -void GpgCommandExecutor::ExecuteSync(ExecuteContext context) { +void GpgCommandExecutor::ExecuteSync(const ExecuteContext &context) { Thread::Task *task = BuildTaskFromExecCtx(context); QPointer<Thread::Task> p_t = task; @@ -174,8 +169,9 @@ void GpgCommandExecutor::ExecuteSync(ExecuteContext context) { looper->deleteLater(); } -void GpgCommandExecutor::ExecuteConcurrentlyAsync(ExecuteContexts contexts) { - for (auto &context : contexts) { +void GpgCommandExecutor::ExecuteConcurrentlyAsync( + const ExecuteContexts &contexts) { + for (const auto &context : contexts) { Thread::Task *task = BuildTaskFromExecCtx(context); if (context.task_runner != nullptr) { @@ -189,12 +185,13 @@ void GpgCommandExecutor::ExecuteConcurrentlyAsync(ExecuteContexts contexts) { } } -void GpgCommandExecutor::ExecuteConcurrentlySync(ExecuteContexts contexts) { +void GpgCommandExecutor::ExecuteConcurrentlySync( + const ExecuteContexts &contexts) { QEventLoop looper; auto remaining_tasks = contexts.size(); Thread::TaskRunnerPtr target_task_runner = nullptr; - for (auto &context : contexts) { + for (const auto &context : contexts) { const auto &cmd = context.cmd; LOG_D() << "gpg concurrently called cmd: " << cmd; @@ -235,24 +232,30 @@ GpgCommandExecutor::ExecuteContext::ExecuteContext( int_func(std::move(int_func)), task_runner(std::move(task_runner)) {} +GpgCommandExecutor::ExecuteContext::ExecuteContext( + QStringList arguments, GpgCommandExecutorCallback callback, + Module::TaskRunnerPtr task_runner, GpgCommandExecutorInterator int_func) + : arguments(std::move(arguments)), + cb_func(std::move(callback)), + int_func(std::move(int_func)), + task_runner(std::move(task_runner)) {} + GpgCommandExecutor::GpgCommandExecutor(int channel) : GpgFrontend::SingletonFunctionObject<GpgCommandExecutor>(channel) {} -void GpgCommandExecutor::GpgExecuteSync(const ExecuteContext &context) { - const auto gpg_path = Module::RetrieveRTValueTypedOrDefault<>( - "core", "gpgme.ctx.app_path", QString{}); - - if (context.cmd.isEmpty() && gpg_path.isEmpty()) { +auto PrepareContext(const GpgContext &ctx_, const QString &path, + const GpgCommandExecutor::ExecuteContext &context) + -> std::tuple<bool, GpgCommandExecutor::ExecuteContext> { + if (context.cmd.isEmpty() && path.isEmpty()) { LOG_E() << "failed to execute gpg command, gpg binary path is empty."; - return; + return {false, {}}; } - LOG_D() << "got gpg binary path:" << gpg_path; - LOG_D() << "context channel:" << GetChannel() + LOG_D() << "got path:" << path << "context channel:" << ctx_.GetChannel() << "home path: " << ctx_.HomeDirectory(); - ExecuteContext ctx = { - context.cmd.isEmpty() ? gpg_path : context.cmd, + GpgCommandExecutor::ExecuteContext ctx = { + context.cmd.isEmpty() ? path : context.cmd, context.arguments, context.cb_func, context.task_runner, @@ -260,10 +263,71 @@ void GpgCommandExecutor::GpgExecuteSync(const ExecuteContext &context) { }; if (!ctx.arguments.contains("--homedir") && !ctx_.HomeDirectory().isEmpty()) { - ctx.arguments.append("--homedir"); - ctx.arguments.append(ctx_.HomeDirectory()); + ctx.arguments.prepend(QDir::toNativeSeparators((ctx_.HomeDirectory()))); + ctx.arguments.prepend("--homedir"); + } + + return {true, ctx}; +} + +auto PrepareExecuteSyncContext(const GpgContext &ctx_, const QString &path, + const GpgCommandExecutor::ExecuteContext + &context) -> std::tuple<int, QString> { + auto ctx = context; + + int pcs_exit_code; + QString pcs_stdout; + + // proxy + ctx.cb_func = [&](int exit_code, const QString &out, const QString &) { + pcs_exit_code = exit_code; + pcs_stdout = out; + }; + + auto [ret, ctx2] = PrepareContext(ctx_, path, ctx); + if (ret) { + GpgFrontend::GpgCommandExecutor::ExecuteSync(ctx2); + return {pcs_exit_code, pcs_stdout}; } + return {-1, "invalid context"}; +} + +void PrepareExecuteAsyncContext( + const GpgContext &ctx_, const QString &path, + const GpgCommandExecutor::ExecuteContext &context) { + auto [ret, ctx] = PrepareContext(ctx_, path, context); + GpgFrontend::GpgCommandExecutor::ExecuteConcurrentlyAsync({ctx}); +} + +auto GpgCommandExecutor::GpgExecuteSync(const ExecuteContext &context) + -> std::tuple<int, QString> { + return PrepareExecuteSyncContext(ctx_, + Module::RetrieveRTValueTypedOrDefault<>( + "core", "gpgme.ctx.app_path", QString{}), + context); +} + +auto GpgCommandExecutor::GpgConfExecuteSync(const ExecuteContext &context) + + -> std::tuple<int, QString> { + return PrepareExecuteSyncContext( + ctx_, + Module::RetrieveRTValueTypedOrDefault<>("core", "gpgme.ctx.gpgconf_path", + QString{}), + context); +} + +void GpgCommandExecutor::GpgExecuteAsync(const ExecuteContext &context) { + PrepareExecuteAsyncContext(ctx_, + Module::RetrieveRTValueTypedOrDefault<>( + "core", "gpgme.ctx.app_path", QString{}), + context); +} - return ExecuteSync(ctx); +void GpgCommandExecutor::GpgConfExecuteAsync(const ExecuteContext &context) { + PrepareExecuteAsyncContext(ctx_, + Module::RetrieveRTValueTypedOrDefault<>( + "core", "gpgme.ctx.gpgconf_path", QString{}), + context); } } // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/function/gpg/GpgCommandExecutor.h b/src/core/function/gpg/GpgCommandExecutor.h index fd2181d3..046b61e4 100644 --- a/src/core/function/gpg/GpgCommandExecutor.h +++ b/src/core/function/gpg/GpgCommandExecutor.h @@ -51,12 +51,42 @@ class GPGFRONTEND_CORE_EXPORT GpgCommandExecutor GpgCommandExecutorInterator int_func; Module::TaskRunnerPtr task_runner = nullptr; + /** + * @brief Construct a new Execute Context object + * + */ + ExecuteContext() = default; + + /** + * @brief Construct a new Execute Context object + * + * @param cmd + * @param arguments + * @param callback + * @param task_runner + * @param int_func + */ ExecuteContext( QString cmd, QStringList arguments, GpgCommandExecutorCallback callback = [](int, const QString &, const QString &) {}, Module::TaskRunnerPtr task_runner = nullptr, GpgCommandExecutorInterator int_func = [](QProcess *) {}); + + /** + * @brief Construct a new Execute Context object + * + * @param arguments + * @param callback + * @param task_runner + * @param int_func + */ + ExecuteContext( + QStringList arguments, + GpgCommandExecutorCallback callback = [](int, const QString &, + const QString &) {}, + Module::TaskRunnerPtr task_runner = nullptr, + GpgCommandExecutorInterator int_func = [](QProcess *) {}); }; using ExecuteContexts = QContainer<ExecuteContext>; @@ -69,13 +99,45 @@ class GPGFRONTEND_CORE_EXPORT GpgCommandExecutor * @param arguments Command parameters * @param interact_func Command answering function */ - static void ExecuteSync(ExecuteContext); + static void ExecuteSync(const ExecuteContext &); + + /** + * @brief + * + */ + static void ExecuteConcurrentlyAsync(const ExecuteContexts &); + + /** + * @brief + * + */ + static void ExecuteConcurrentlySync(const ExecuteContexts &); - static void ExecuteConcurrentlyAsync(ExecuteContexts); + /** + * @brief + * + */ + auto GpgExecuteSync(const ExecuteContext &) -> std::tuple<int, QString>; + + /** + * @brief + * + */ + auto GpgConfExecuteSync(const ExecuteContext &) -> std::tuple<int, QString>; - static void ExecuteConcurrentlySync(ExecuteContexts); + /** + * @brief + * + * @param context + */ + void GpgExecuteAsync(const ExecuteContext &); - void GpgExecuteSync(const ExecuteContext &); + /** + * @brief + * + * @param context + */ + void GpgConfExecuteAsync(const ExecuteContext &); private: GpgContext &ctx_ = diff --git a/src/core/function/gpg/GpgComponentInfoGetter.cpp b/src/core/function/gpg/GpgComponentInfoGetter.cpp new file mode 100644 index 00000000..317f334f --- /dev/null +++ b/src/core/function/gpg/GpgComponentInfoGetter.cpp @@ -0,0 +1,64 @@ +/** + * Copyright (C) 2021-2024 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#include "GpgComponentInfoGetter.h" + +namespace GpgFrontend { + +GpgComponentInfoGetter::GpgComponentInfoGetter(int channel) + : GpgFrontend::SingletonFunctionObject<GpgComponentInfoGetter>(channel) {} + +auto GpgComponentInfoGetter::GetGpgAgentVersion() -> QString { + if (!gpg_agent_version_.isEmpty()) return gpg_agent_version_; + + auto [r, s] = + assuan_.SendDataCommand(GpgComponentType::kGPG_AGENT, "GETINFO version"); + if (s.isEmpty()) { + LOG_D() << "invalid response of GETINFO version: " << s; + return {}; + } + + gpg_agent_version_ = s.front(); + return gpg_agent_version_; +} + +auto GpgComponentInfoGetter::GetScdaemonVersion() -> QString { + if (!scdaemon_version_.isEmpty()) return scdaemon_version_; + + auto [r, s] = assuan_.SendDataCommand(GpgComponentType::kGPG_AGENT, + "SCD GETINFO version"); + if (s.isEmpty()) { + LOG_D() << "invalid response of SCD GETINFO version: " << s; + return {}; + } + + scdaemon_version_ = s.front(); + return scdaemon_version_; +} + +} // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/function/gpg/GpgComponentInfoGetter.h b/src/core/function/gpg/GpgComponentInfoGetter.h new file mode 100644 index 00000000..3f8b560b --- /dev/null +++ b/src/core/function/gpg/GpgComponentInfoGetter.h @@ -0,0 +1,72 @@ +/** + * Copyright (C) 2021-2024 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#pragma once + +#include "core/function/gpg/GpgAssuanHelper.h" +#include "core/function/gpg/GpgContext.h" + +namespace GpgFrontend { + +class GPGFRONTEND_CORE_EXPORT GpgComponentInfoGetter + : public SingletonFunctionObject<GpgComponentInfoGetter> { + public: + /** + * @brief Construct a new Gpg Assuan Helper object + * + * @param channel + */ + explicit GpgComponentInfoGetter(int channel); + + /** + * @brief + * + * @return true + * @return false + */ + auto GetGpgAgentVersion() -> QString; + + /** + * @brief + * + * @return true + * @return false + */ + auto GetScdaemonVersion() -> QString; + + private: + GpgContext& ctx_ = + GpgContext::GetInstance(SingletonFunctionObject::GetChannel()); + GpgAssuanHelper& assuan_ = + GpgAssuanHelper::GetInstance(SingletonFunctionObject::GetChannel()); + + QString gpg_agent_version_; + QString scdaemon_version_; +}; + +}; // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/function/gpg/GpgFileOpera.cpp b/src/core/function/gpg/GpgFileOpera.cpp index 334aae6f..b498461f 100644 --- a/src/core/function/gpg/GpgFileOpera.cpp +++ b/src/core/function/gpg/GpgFileOpera.cpp @@ -32,7 +32,6 @@ #include "core/model/GpgData.h" #include "core/model/GpgDecryptResult.h" #include "core/model/GpgEncryptResult.h" -#include "core/model/GpgKey.h" #include "core/model/GpgSignResult.h" #include "core/model/GpgVerifyResult.h" #include "core/utils/AsyncUtils.h" @@ -95,22 +94,24 @@ void GpgFileOpera::EncryptFile(const GpgAbstractKeyPtrList& keys, const QString& out_path, const GpgOperationCallback& cb) { RunGpgOperaAsync( + GetChannel(), [=](const DataObjectPtr& data_object) { return EncryptFileImpl(ctx_, keys, in_path, ascii, out_path, data_object); }, - cb, "gpgme_op_encrypt", "2.1.0"); + cb, "gpgme_op_encrypt", "2.2.0"); } auto GpgFileOpera::EncryptFileSync( const GpgAbstractKeyPtrList& keys, const QString& in_path, bool ascii, const QString& out_path) -> std::tuple<GpgError, DataObjectPtr> { return RunGpgOperaSync( + GetChannel(), [=](const DataObjectPtr& data_object) { return EncryptFileImpl(ctx_, keys, in_path, ascii, out_path, data_object); }, - "gpgme_op_encrypt", "2.1.0"); + "gpgme_op_encrypt", "2.2.0"); } void GpgFileOpera::EncryptDirectory(const GpgAbstractKeyPtrList& keys, @@ -120,6 +121,7 @@ void GpgFileOpera::EncryptDirectory(const GpgAbstractKeyPtrList& keys, auto ex = CreateStandardGFDataExchanger(); RunGpgOperaAsync( + GetChannel(), [=](const DataObjectPtr& data_object) -> GpgError { GpgData data_in(ex); GpgData data_out(out_path, false); @@ -127,7 +129,7 @@ void GpgFileOpera::EncryptDirectory(const GpgAbstractKeyPtrList& keys, return EncryptFileGpgDataImpl(ctx_, keys, data_in, ascii, data_out, data_object); }, - cb, "gpgme_op_encrypt", "2.1.0"); + cb, "gpgme_op_encrypt", "2.2.0"); CreateArchiveHelper(in_path, ex); } @@ -155,20 +157,22 @@ auto DecryptFileImpl(GpgContext& ctx_, const QString& in_path, void GpgFileOpera::DecryptFile(const QString& in_path, const QString& out_path, const GpgOperationCallback& cb) { RunGpgOperaAsync( + GetChannel(), [=](const DataObjectPtr& data_object) { return DecryptFileImpl(ctx_, in_path, out_path, data_object); }, - cb, "gpgme_op_decrypt", "2.1.0"); + cb, "gpgme_op_decrypt", "2.2.0"); } auto GpgFileOpera::DecryptFileSync(const QString& in_path, const QString& out_path) -> std::tuple<GpgError, DataObjectPtr> { return RunGpgOperaSync( + GetChannel(), [=](const DataObjectPtr& data_object) { return DecryptFileImpl(ctx_, in_path, out_path, data_object); }, - "gpgme_op_decrypt", "2.1.0"); + "gpgme_op_decrypt", "2.2.0"); } void GpgFileOpera::DecryptArchive(const QString& in_path, @@ -177,13 +181,14 @@ void GpgFileOpera::DecryptArchive(const QString& in_path, auto ex = ExtractArchiveHelper(out_path); RunGpgOperaAsync( + GetChannel(), [=](const DataObjectPtr& data_object) -> GpgError { GpgData data_in(in_path, true); GpgData data_out(ex); return DecryptFileGpgDataImpl(ctx_, data_in, data_out, data_object); }, - cb, "gpgme_op_decrypt", "2.1.0"); + cb, "gpgme_op_decrypt", "2.2.0"); } auto SignFileGpgDataImpl(GpgContext& ctx_, GpgBasicOperator& basic_opera_, @@ -221,22 +226,24 @@ void GpgFileOpera::SignFile(const GpgAbstractKeyPtrList& keys, const QString& out_path, const GpgOperationCallback& cb) { RunGpgOperaAsync( + GetChannel(), [=](const DataObjectPtr& data_object) { return SignFileImpl(ctx_, basic_opera_, keys, in_path, ascii, out_path, data_object); }, - cb, "gpgme_op_sign", "2.1.0"); + cb, "gpgme_op_sign", "2.2.0"); } auto GpgFileOpera::SignFileSync( const GpgAbstractKeyPtrList& keys, const QString& in_path, bool ascii, const QString& out_path) -> std::tuple<GpgError, DataObjectPtr> { return RunGpgOperaSync( + GetChannel(), [=](const DataObjectPtr& data_object) { return SignFileImpl(ctx_, basic_opera_, keys, in_path, ascii, out_path, data_object); }, - "gpgme_op_sign", "2.1.0"); + "gpgme_op_sign", "2.2.0"); } auto VerifyFileImpl(GpgContext& ctx_, const QString& data_path, @@ -266,20 +273,22 @@ void GpgFileOpera::VerifyFile(const QString& data_path, const QString& sign_path, const GpgOperationCallback& cb) { RunGpgOperaAsync( + GetChannel(), [=](const DataObjectPtr& data_object) -> GpgError { return VerifyFileImpl(ctx_, data_path, sign_path, data_object); }, - cb, "gpgme_op_verify", "2.1.0"); + cb, "gpgme_op_verify", "2.2.0"); } auto GpgFileOpera::VerifyFileSync(const QString& data_path, const QString& sign_path) -> std::tuple<GpgError, DataObjectPtr> { return RunGpgOperaSync( + GetChannel(), [=](const DataObjectPtr& data_object) -> GpgError { return VerifyFileImpl(ctx_, data_path, sign_path, data_object); }, - "gpgme_op_verify", "2.1.0"); + "gpgme_op_verify", "2.2.0"); } auto EncryptSignFileGpgDataImpl(GpgContext& ctx_, @@ -324,11 +333,12 @@ void GpgFileOpera::EncryptSignFile(const GpgAbstractKeyPtrList& keys, const QString& out_path, const GpgOperationCallback& cb) { RunGpgOperaAsync( + GetChannel(), [=](const DataObjectPtr& data_object) { return EncryptSignFileImpl(ctx_, basic_opera_, keys, signer_keys, in_path, ascii, out_path, data_object); }, - cb, "gpgme_op_encrypt_sign", "2.1.0"); + cb, "gpgme_op_encrypt_sign", "2.2.0"); } auto GpgFileOpera::EncryptSignFileSync( @@ -336,11 +346,12 @@ auto GpgFileOpera::EncryptSignFileSync( const QString& in_path, bool ascii, const QString& out_path) -> std::tuple<GpgError, DataObjectPtr> { return RunGpgOperaSync( + GetChannel(), [=](const DataObjectPtr& data_object) { return EncryptSignFileImpl(ctx_, basic_opera_, keys, signer_keys, in_path, ascii, out_path, data_object); }, - "gpgme_op_encrypt_sign", "2.1.0"); + "gpgme_op_encrypt_sign", "2.2.0"); } void GpgFileOpera::EncryptSignDirectory( @@ -350,6 +361,7 @@ void GpgFileOpera::EncryptSignDirectory( auto ex = CreateStandardGFDataExchanger(); RunGpgOperaAsync( + GetChannel(), [=](const DataObjectPtr& data_object) -> GpgError { GpgData data_in(ex); GpgData data_out(out_path, false); @@ -358,7 +370,7 @@ void GpgFileOpera::EncryptSignDirectory( data_in, ascii, data_out, data_object); }, - cb, "gpgme_op_encrypt_sign", "2.1.0"); + cb, "gpgme_op_encrypt_sign", "2.2.0"); CreateArchiveHelper(in_path, ex); } @@ -389,20 +401,22 @@ void GpgFileOpera::DecryptVerifyFile(const QString& in_path, const QString& out_path, const GpgOperationCallback& cb) { RunGpgOperaAsync( + GetChannel(), [=](const DataObjectPtr& data_object) -> GpgError { return DecryptVerifyFileImpl(ctx_, in_path, out_path, data_object); }, - cb, "gpgme_op_decrypt_verify", "2.1.0"); + cb, "gpgme_op_decrypt_verify", "2.2.0"); } auto GpgFileOpera::DecryptVerifyFileSync(const QString& in_path, const QString& out_path) -> std::tuple<GpgError, DataObjectPtr> { return RunGpgOperaSync( + GetChannel(), [=](const DataObjectPtr& data_object) -> GpgError { return DecryptVerifyFileImpl(ctx_, in_path, out_path, data_object); }, - "gpgme_op_decrypt_verify", "2.1.0"); + "gpgme_op_decrypt_verify", "2.2.0"); } void GpgFileOpera::DecryptVerifyArchive(const QString& in_path, @@ -411,33 +425,36 @@ void GpgFileOpera::DecryptVerifyArchive(const QString& in_path, auto ex = ExtractArchiveHelper(out_path); RunGpgOperaAsync( + GetChannel(), [=](const DataObjectPtr& data_object) -> GpgError { GpgData data_in(in_path, true); GpgData data_out(ex); return DecryptVerifyFileGpgDataImpl(ctx_, data_in, data_out, data_object); }, - cb, "gpgme_op_decrypt_verify", "2.1.0"); + cb, "gpgme_op_decrypt_verify", "2.2.0"); } void GpgFileOpera::EncryptFileSymmetric(const QString& in_path, bool ascii, const QString& out_path, const GpgOperationCallback& cb) { RunGpgOperaAsync( + GetChannel(), [=](const DataObjectPtr& data_object) -> GpgError { return EncryptFileImpl(ctx_, {}, in_path, ascii, out_path, data_object); }, - cb, "gpgme_op_encrypt_symmetric", "2.1.0"); + cb, "gpgme_op_encrypt_symmetric", "2.2.0"); } auto GpgFileOpera::EncryptFileSymmetricSync(const QString& in_path, bool ascii, const QString& out_path) -> std::tuple<GpgError, DataObjectPtr> { return RunGpgOperaSync( + GetChannel(), [=](const DataObjectPtr& data_object) -> GpgError { return EncryptFileImpl(ctx_, {}, in_path, ascii, out_path, data_object); }, - "gpgme_op_encrypt_symmetric", "2.1.0"); + "gpgme_op_encrypt_symmetric", "2.2.0"); } void GpgFileOpera::EncryptDirectorySymmetric(const QString& in_path, bool ascii, @@ -446,6 +463,7 @@ void GpgFileOpera::EncryptDirectorySymmetric(const QString& in_path, bool ascii, auto ex = CreateStandardGFDataExchanger(); RunGpgOperaAsync( + GetChannel(), [=](const DataObjectPtr& data_object) { GpgData data_in(ex); GpgData data_out(out_path, false); @@ -453,7 +471,7 @@ void GpgFileOpera::EncryptDirectorySymmetric(const QString& in_path, bool ascii, return EncryptFileGpgDataImpl(ctx_, {}, data_in, ascii, data_out, data_object); }, - cb, "gpgme_op_encrypt_symmetric", "2.1.0"); + cb, "gpgme_op_encrypt_symmetric", "2.2.0"); CreateArchiveHelper(in_path, ex); } @@ -466,6 +484,7 @@ auto GpgFileOpera::EncryptDirectorySymmetricSync( CreateArchiveHelper(in_path, ex); return RunGpgOperaSync( + GetChannel(), [=](const DataObjectPtr& data_object) -> GpgError { GpgData data_in(ex); GpgData data_out(out_path, false); @@ -473,7 +492,7 @@ auto GpgFileOpera::EncryptDirectorySymmetricSync( return EncryptFileGpgDataImpl(ctx_, {}, data_in, ascii, data_out, data_object); }, - "gpgme_op_encrypt_symmetric", "2.1.0"); + "gpgme_op_encrypt_symmetric", "2.2.0"); } } // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/function/gpg/GpgKeyImportExporter.cpp b/src/core/function/gpg/GpgKeyImportExporter.cpp index eda36273..4e306233 100644 --- a/src/core/function/gpg/GpgKeyImportExporter.cpp +++ b/src/core/function/gpg/GpgKeyImportExporter.cpp @@ -105,6 +105,7 @@ void GpgKeyImportExporter::ExportKeys(const GpgAbstractKeyPtrList& keys, bool ssh_mode, const GpgOperationCallback& cb) const { RunGpgOperaAsync( + GetChannel(), [=](const DataObjectPtr& data_object) -> GpgError { if (keys.empty()) return GPG_ERR_CANCELED; @@ -139,6 +140,7 @@ void GpgKeyImportExporter::ExportAllKeys(const GpgAbstractKeyPtrList& keys, bool secret, bool ascii, const GpgOperationCallback& cb) const { RunGpgOperaAsync( + GetChannel(), [=](const DataObjectPtr& data_object) -> GpgError { if (keys.empty()) return GPG_ERR_CANCELED; diff --git a/src/core/function/gpg/GpgKeyManager.cpp b/src/core/function/gpg/GpgKeyManager.cpp index 1fa050bb..5fca4ed4 100644 --- a/src/core/function/gpg/GpgKeyManager.cpp +++ b/src/core/function/gpg/GpgKeyManager.cpp @@ -31,7 +31,6 @@ #include "core/function/gpg/GpgAutomatonHandler.h" #include "core/function/gpg/GpgBasicOperator.h" #include "core/function/gpg/GpgKeyGetter.h" -#include "core/model/GpgData.h" #include "core/utils/GpgUtils.h" namespace GpgFrontend { @@ -69,9 +68,9 @@ auto GpgKeyManager::RevSign(const GpgKeyPtr& key, auto signing_key = key_getter.GetKey(sign_id.first); assert(signing_key.IsGood()); - auto err = CheckGpgError( - gpgme_op_revsig(ctx_.DefaultContext(), gpgme_key_t(*key), - gpgme_key_t(signing_key), sign_id.second.toUtf8(), 0)); + auto err = CheckGpgError(gpgme_op_revsig( + ctx_.DefaultContext(), static_cast<gpgme_key_t>(*key), + static_cast<gpgme_key_t>(signing_key), sign_id.second.toUtf8(), 0)); if (CheckGpgError(err) != GPG_ERR_NO_ERROR) return false; } return true; @@ -102,7 +101,7 @@ auto GpgKeyManager::SetOwnerTrustLevel(const GpgKeyPtr& key, } GpgAutomatonHandler::AutomatonNextStateHandler next_state_handler = - [](AutomatonState state, QString status, QString args) { + [](AutomatonState state, const QString& status, const QString& args) { auto tokens = args.split(' '); switch (state) { @@ -162,15 +161,14 @@ auto GpgKeyManager::SetOwnerTrustLevel(const GpgKeyPtr& key, return QString("Y"); case GpgAutomatonHandler::kAS_START: case GpgAutomatonHandler::kAS_ERROR: - return QString(""); default: return QString(""); } return QString(""); }; - return GpgAutomatonHandler::GetInstance(GetChannel()) - .DoInteract(key, next_state_handler, action_handler); + auto [err, succ] = auto_.DoInteract(key, next_state_handler, action_handler); + return err == GPG_ERR_NO_ERROR && !succ; } auto GpgKeyManager::DeleteSubkey(const GpgKeyPtr& key, @@ -182,7 +180,7 @@ auto GpgKeyManager::DeleteSubkey(const GpgKeyPtr& key, } AutomatonNextStateHandler next_state_handler = - [](AutomatonState state, QString status, QString args) { + [](AutomatonState state, const QString& status, const QString& args) { auto tokens = args.split(' '); switch (state) { @@ -247,8 +245,8 @@ auto GpgKeyManager::DeleteSubkey(const GpgKeyPtr& key, return QString(""); }; - return GpgAutomatonHandler::GetInstance(GetChannel()) - .DoInteract(key, next_state_handler, action_handler); + auto [err, succ] = auto_.DoInteract(key, next_state_handler, action_handler); + return err == GPG_ERR_NO_ERROR && !succ; } auto GpgKeyManager::RevokeSubkey(const GpgKeyPtr& key, int subkey_index, @@ -270,7 +268,7 @@ auto GpgKeyManager::RevokeSubkey(const GpgKeyPtr& key, int subkey_index, reason_text.split('\n', Qt::SkipEmptyParts)); AutomatonNextStateHandler next_state_handler = - [](AutomatonState state, QString status, QString args) { + [](AutomatonState state, const QString& status, const QString& args) { auto tokens = args.split(' '); switch (state) { @@ -363,8 +361,8 @@ auto GpgKeyManager::RevokeSubkey(const GpgKeyPtr& key, int subkey_index, return QString(""); }; - return GpgAutomatonHandler::GetInstance(GetChannel()) - .DoInteract(key, next_state_handler, action_handler); + auto [err, succ] = auto_.DoInteract(key, next_state_handler, action_handler); + return err == GPG_ERR_NO_ERROR && !succ; } } // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/function/gpg/GpgKeyManager.h b/src/core/function/gpg/GpgKeyManager.h index ccf69b53..384319f8 100644 --- a/src/core/function/gpg/GpgKeyManager.h +++ b/src/core/function/gpg/GpgKeyManager.h @@ -29,6 +29,7 @@ #pragma once #include "core/function/basic/GpgFunctionObject.h" +#include "core/function/gpg/GpgAutomatonHandler.h" #include "core/function/gpg/GpgContext.h" #include "core/typedef/GpgTypedef.h" @@ -114,6 +115,8 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyManager private: GpgContext& ctx_ = GpgContext::GetInstance(SingletonFunctionObject::GetChannel()); ///< + GpgAutomatonHandler& auto_ = GpgAutomatonHandler::GetInstance( + SingletonFunctionObject::GetChannel()); ///< }; } // namespace GpgFrontend diff --git a/src/core/function/gpg/GpgKeyOpera.cpp b/src/core/function/gpg/GpgKeyOpera.cpp index e97eebd8..bcc3cc44 100644 --- a/src/core/function/gpg/GpgKeyOpera.cpp +++ b/src/core/function/gpg/GpgKeyOpera.cpp @@ -215,19 +215,21 @@ auto GenerateKeyImpl(GpgContext& ctx, void GpgKeyOpera::GenerateKey(const QSharedPointer<KeyGenerateInfo>& params, const GpgOperationCallback& callback) { RunGpgOperaAsync( + GetChannel(), [=](const DataObjectPtr& data_object) -> GpgError { return GenerateKeyImpl(ctx_, params, data_object); }, - callback, "gpgme_op_createkey", "2.1.0"); + callback, "gpgme_op_createkey", "2.2.0"); } auto GpgKeyOpera::GenerateKeySync(const QSharedPointer<KeyGenerateInfo>& params) -> std::tuple<GpgError, DataObjectPtr> { return RunGpgOperaSync( + GetChannel(), [=](const DataObjectPtr& data_object) -> GpgError { return GenerateKeyImpl(ctx_, params, data_object); }, - "gpgme_op_createkey", "2.1.0"); + "gpgme_op_createkey", "2.2.0"); } auto GenerateSubKeyImpl(GpgContext& ctx, const GpgKeyPtr& key, @@ -270,6 +272,7 @@ void GpgKeyOpera::GenerateSubkey(const GpgKeyPtr& key, const QSharedPointer<KeyGenerateInfo>& params, const GpgOperationCallback& callback) { RunGpgOperaAsync( + GetChannel(), [=](const DataObjectPtr& data_object) -> GpgError { return GenerateSubKeyImpl(ctx_, key, params, data_object); }, @@ -280,6 +283,7 @@ auto GpgKeyOpera::GenerateSubkeySync( const GpgKeyPtr& key, const QSharedPointer<KeyGenerateInfo>& params) -> std::tuple<GpgError, DataObjectPtr> { return RunGpgOperaSync( + GetChannel(), [=](const DataObjectPtr& data_object) -> GpgError { return GenerateSubKeyImpl(ctx_, key, params, data_object); }, @@ -318,11 +322,12 @@ void GpgKeyOpera::GenerateKeyWithSubkey( const QSharedPointer<KeyGenerateInfo>& s_params, const GpgOperationCallback& callback) { RunGpgOperaAsync( + GetChannel(), [=](const DataObjectPtr& data_object) -> GpgError { return GenerateKeyWithSubkeyImpl(ctx_, key_getter_, p_params, s_params, data_object); }, - callback, "gpgme_op_createkey&gpgme_op_createsubkey", "2.1.0"); + callback, "gpgme_op_createkey&gpgme_op_createsubkey", "2.2.0"); } auto GpgKeyOpera::GenerateKeyWithSubkeySync( @@ -330,36 +335,35 @@ auto GpgKeyOpera::GenerateKeyWithSubkeySync( const QSharedPointer<KeyGenerateInfo>& s_params) -> std::tuple<GpgError, DataObjectPtr> { return RunGpgOperaSync( + GetChannel(), [=](const DataObjectPtr& data_object) -> GpgError { return GenerateKeyWithSubkeyImpl(ctx_, key_getter_, p_params, s_params, data_object); }, - "gpgme_op_createkey&gpgme_op_createsubkey", "2.1.0"); + "gpgme_op_createkey&gpgme_op_createsubkey", "2.2.0"); } void GpgKeyOpera::ModifyPassword(const GpgKeyPtr& key, const GpgOperationCallback& callback) { RunGpgOperaAsync( + GetChannel(), [&key, &ctx = ctx_](const DataObjectPtr&) -> GpgError { return gpgme_op_passwd(ctx.DefaultContext(), static_cast<gpgme_key_t>(*key), 0); }, - callback, "gpgme_op_passwd", "2.0.15"); + callback, "gpgme_op_passwd", "2.2.0"); } auto GpgKeyOpera::ModifyTOFUPolicy( const GpgKeyPtr& key, gpgme_tofu_policy_t tofu_policy) -> GpgError { - const auto gnupg_version = Module::RetrieveRTValueTypedOrDefault<>( - "core", "gpgme.ctx.gnupg_version", QString{"2.0.0"}); - LOG_D() << "got gnupg version from rt: " << gnupg_version; - - if (GFCompareSoftwareVersion(gnupg_version, "2.1.10") < 0) { - FLOG_W("operator not support"); - return GPG_ERR_NOT_SUPPORTED; - } + auto [err, obj] = RunGpgOperaSync( + GetChannel(), + [=](const DataObjectPtr&) -> GpgError { + return gpgme_op_tofu_policy( + ctx_.DefaultContext(), static_cast<gpgme_key_t>(*key), tofu_policy); + }, + "gpgme_op_tofu_policy", "2.2.0"); - auto err = gpgme_op_tofu_policy(ctx_.DefaultContext(), - static_cast<gpgme_key_t>(*key), tofu_policy); return CheckGpgError(err); } @@ -388,6 +392,7 @@ auto AddADSKImpl(GpgContext& ctx, const GpgKeyPtr& key, const GpgSubKey& adsk, void GpgKeyOpera::AddADSK(const GpgKeyPtr& key, const GpgSubKey& adsk, const GpgOperationCallback& callback) { RunGpgOperaAsync( + GetChannel(), [=](const DataObjectPtr& data_object) -> GpgError { return AddADSKImpl(ctx_, key, adsk, data_object); }, @@ -397,6 +402,7 @@ void GpgKeyOpera::AddADSK(const GpgKeyPtr& key, const GpgSubKey& adsk, auto GpgKeyOpera::AddADSKSync(const GpgKeyPtr& key, const GpgSubKey& adsk) -> std::tuple<GpgError, DataObjectPtr> { return RunGpgOperaSync( + GetChannel(), [=](const DataObjectPtr& data_object) -> GpgError { return AddADSKImpl(ctx_, key, adsk, data_object); }, diff --git a/src/core/function/gpg/GpgSmartCardManager.cpp b/src/core/function/gpg/GpgSmartCardManager.cpp index 5442ea88..203c36ec 100644 --- a/src/core/function/gpg/GpgSmartCardManager.cpp +++ b/src/core/function/gpg/GpgSmartCardManager.cpp @@ -30,17 +30,16 @@ #include "core/function/gpg/GpgAutomatonHandler.h" #include "core/utils/CommonUtils.h" +#include "core/utils/GpgUtils.h" namespace GpgFrontend { GpgSmartCardManager::GpgSmartCardManager(int channel) : SingletonFunctionObject<GpgSmartCardManager>(channel) {} -auto GpgSmartCardManager::Fetch(const QString& serial_number) -> bool { +auto GpgSmartCardManager::Fetch(const QString& serial_number) -> GpgError { GpgAutomatonHandler::AutomatonNextStateHandler next_state_handler = - [=](AutomatonState state, QString status, QString args) { - auto tokens = args.split(' '); - + [=](AutomatonState state, const QString& status, const QString& args) { switch (state) { case GpgAutomatonHandler::kAS_START: if (status == "GET_LINE" && args == "cardedit.prompt") { @@ -63,7 +62,7 @@ auto GpgSmartCardManager::Fetch(const QString& serial_number) -> bool { }; }; - AutomatonActionHandler action_handler = [](AutomatonHandelStruct& handler, + AutomatonActionHandler action_handler = [](AutomatonHandelStruct&, AutomatonState state) { switch (state) { case GpgAutomatonHandler::kAS_COMMAND: @@ -78,25 +77,22 @@ auto GpgSmartCardManager::Fetch(const QString& serial_number) -> bool { return QString(""); }; - return GpgAutomatonHandler::GetInstance(GetChannel()) - .DoCardInteract(serial_number, next_state_handler, action_handler); + auto [err, succ] = + GpgAutomatonHandler::GetInstance(GetChannel()) + .DoCardInteract(serial_number, next_state_handler, action_handler); + + if (err == GPG_ERR_NO_ERROR && !succ) return GPG_ERR_USER_1; + return err; } auto GpgSmartCardManager::IsSCDVersionSupported() -> bool { - auto [r, s] = assuan_.SendDataCommand(GpgComponentType::kGPG_AGENT, - "SCD GETINFO version"); - if (s.isEmpty()) { - LOG_D() << "invalid response of SCD GETINFO version: " << s; - return false; - } - - return GFCompareSoftwareVersion(s.front(), "2.3.0") > 0; + return GFSoftwareVersionGreaterThan(info_.GetScdaemonVersion(), "2.3.0"); } auto GpgSmartCardManager::GetSerialNumbers() -> QStringList { auto [r, s] = assuan_.SendStatusCommand(GpgComponentType::kGPG_AGENT, "SCD SERIALNO --all"); - if (!r) { + if (r != GPG_ERR_NO_ERROR) { cached_scd_serialno_status_hash_.clear(); cache_scd_card_serial_numbers_.clear(); return {}; @@ -112,9 +108,9 @@ auto GpgSmartCardManager::GetSerialNumbers() -> QStringList { cached_scd_serialno_status_hash_.clear(); cache_scd_card_serial_numbers_.clear(); - auto [ret, status] = assuan_.SendStatusCommand(GpgComponentType::kGPG_AGENT, + auto [err, status] = assuan_.SendStatusCommand(GpgComponentType::kGPG_AGENT, "SCD GETINFO all_active_apps"); - if (!ret || status.empty()) { + if (err != GPG_ERR_NO_ERROR || status.empty()) { LOG_D() << "command SCD GETINFO all_active_apps failed, resetting..."; return {}; } @@ -142,14 +138,14 @@ auto GpgSmartCardManager::GetSerialNumbers() -> QStringList { } auto GpgSmartCardManager::SelectCardBySerialNumber(const QString& serial_number) - -> std::tuple<bool, QString> { + -> std::tuple<GpgError, QString> { if (serial_number.isEmpty()) return {false, "Serial Number is empty."}; - auto [ret, status] = assuan_.SendStatusCommand( + auto [err, status] = assuan_.SendStatusCommand( GpgComponentType::kGPG_AGENT, QString("SCD SERIALNO --demand=%1 openpgp").arg(serial_number)); - if (!ret || status.isEmpty()) { - return {false, status.join(' ')}; + if (err != GPG_ERR_NO_ERROR || status.isEmpty()) { + return {err, status.join(' ')}; } auto line = status.front(); @@ -157,22 +153,21 @@ auto GpgSmartCardManager::SelectCardBySerialNumber(const QString& serial_number) if (token.size() != 2) { LOG_E() << "invalid response of command SERIALNO: " << line; - return {false, line}; + return {GPG_ERR_USER_1, line}; } LOG_D() << "selected smart card by serial number: " << serial_number; - - return {true, {}}; + return {err, {}}; } auto GpgSmartCardManager::FetchCardInfoBySerialNumber( const QString& serial_number) -> QSharedPointer<GpgOpenPGPCard> { if (serial_number.trimmed().isEmpty()) return nullptr; - auto [ret, status] = assuan_.SendStatusCommand( + auto [err, status] = assuan_.SendStatusCommand( GpgComponentType::kGPG_AGENT, "SCD LEARN --force " + serial_number); - if (!ret || status.isEmpty()) { - LOG_E() << "scd learn failed: " << status; + if (err != GPG_ERR_NO_ERROR || status.isEmpty()) { + LOG_E() << "scd learn failed, err: " << CheckGpgError(err) << "" << status; return nullptr; } @@ -201,7 +196,7 @@ auto PercentDataEscape(const QByteArray& data, bool plus_escape = false, } } - for (unsigned char ch : data) { + for (char ch : data) { if (ch == '\0') { result += "%00"; } else if (ch == '%') { @@ -219,29 +214,25 @@ auto PercentDataEscape(const QByteArray& data, bool plus_escape = false, } auto GpgSmartCardManager::ModifyAttr(const QString& attr, const QString& value) - -> std::tuple<bool, QString> { + -> std::tuple<GpgError, QString> { if (attr.trimmed().isEmpty() || value.trimmed().isEmpty()) { - return {false, "ATTR or Value is empty"}; + return {GPG_ERR_INV_ARG, "ATTR or Value is empty"}; } const auto command = QString("SCD SETATTR %1 ").arg(attr); const auto escaped_command = PercentDataEscape(value.trimmed().toUtf8(), true, command); - auto [r, s] = + auto [err, status] = assuan_.SendStatusCommand(GpgComponentType::kGPG_AGENT, escaped_command); - - if (!r) { - LOG_E() << "SCD SETATTR command failed for attr" << attr; - return {false, s.join(' ')}; - } - - return {true, {}}; + return {err, status.join(' ')}; } auto GpgSmartCardManager::ModifyPin(const QString& pin_ref) - -> std::tuple<bool, QString> { - if (pin_ref.trimmed().isEmpty()) return {false, "PIN Reference is empty"}; + -> std::tuple<GpgError, QString> { + if (pin_ref.trimmed().isEmpty()) { + return {GPG_ERR_INV_ARG, "PIN Reference is empty"}; + } QString command; if (pin_ref == "OPENPGP.1") { @@ -254,23 +245,17 @@ auto GpgSmartCardManager::ModifyPin(const QString& pin_ref) command = QString("SCD PASSWD %1").arg(pin_ref); } - auto [success, status] = + auto [err, status] = assuan_.SendStatusCommand(GpgComponentType::kGPG_AGENT, command); - - if (!success) { - LOG_E() << "modify pin of smart failed: " << status; - return {false, status.join(' ')}; - } - - return {true, {}}; + return {err, status.join(' ')}; } auto GpgSmartCardManager::GenerateKey( const QString& serial_number, const QString& name, const QString& email, const QString& comment, const QDateTime& expire, - bool non_expire) -> std::tuple<bool, QString> { + bool non_expire) -> std::tuple<GpgError, QString> { if (name.isEmpty() || email.isEmpty()) { - return {false, "name or email is empty"}; + return {GPG_ERR_INV_ARG, "name or email is empty"}; } qint64 days_before_expire = 0; @@ -280,8 +265,6 @@ auto GpgSmartCardManager::GenerateKey( GpgAutomatonHandler::AutomatonNextStateHandler next_state_handler = [=](AutomatonState state, const QString& status, const QString& args) { - auto tokens = args.split(' '); - switch (state) { case GpgAutomatonHandler::kAS_START: if (status == "GET_LINE" && args == "cardedit.prompt") { @@ -382,9 +365,10 @@ auto GpgSmartCardManager::GenerateKey( return QString{}; }; - return { + auto [err, succ] = GpgAutomatonHandler::GetInstance(GetChannel()) - .DoCardInteract(serial_number, next_state_handler, action_handler), - "unknown error"}; + .DoCardInteract(serial_number, next_state_handler, action_handler); + if (err == GPG_ERR_NO_ERROR && !succ) return {GPG_ERR_USER_1, {}}; + return {err, {}}; } } // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/function/gpg/GpgSmartCardManager.h b/src/core/function/gpg/GpgSmartCardManager.h index 2fe194f3..02b07fa2 100644 --- a/src/core/function/gpg/GpgSmartCardManager.h +++ b/src/core/function/gpg/GpgSmartCardManager.h @@ -30,9 +30,9 @@ #include "core/function/basic/GpgFunctionObject.h" #include "core/function/gpg/GpgAssuanHelper.h" +#include "core/function/gpg/GpgComponentInfoGetter.h" #include "core/function/gpg/GpgContext.h" #include "core/model/GpgOpenPGPCard.h" -#include "core/typedef/GpgTypedef.h" namespace GpgFrontend { @@ -63,7 +63,8 @@ class GPGFRONTEND_CORE_EXPORT GpgSmartCardManager * * @return std::tuple<bool, QString> */ - auto SelectCardBySerialNumber(const QString&) -> std::tuple<bool, QString>; + auto SelectCardBySerialNumber(const QString&) + -> std::tuple<GpgError, QString>; /** * @brief @@ -81,7 +82,7 @@ class GPGFRONTEND_CORE_EXPORT GpgSmartCardManager * @return true * @return false */ - auto Fetch(const QString& serial_number) -> bool; + auto Fetch(const QString& serial_number) -> GpgError; /** * @brief @@ -89,7 +90,7 @@ class GPGFRONTEND_CORE_EXPORT GpgSmartCardManager * @return std::tuple<bool, QString> */ auto ModifyAttr(const QString& attr, - const QString& value) -> std::tuple<bool, QString>; + const QString& value) -> std::tuple<GpgError, QString>; /** * @brief @@ -97,7 +98,7 @@ class GPGFRONTEND_CORE_EXPORT GpgSmartCardManager * @param pin_ref * @return std::tuple<bool, QString> */ - auto ModifyPin(const QString& pin_ref) -> std::tuple<bool, QString>; + auto ModifyPin(const QString& pin_ref) -> std::tuple<GpgError, QString>; /** * @brief @@ -107,7 +108,7 @@ class GPGFRONTEND_CORE_EXPORT GpgSmartCardManager auto GenerateKey(const QString& serial_number, const QString& name, const QString& email, const QString& comment, const QDateTime& expire, - bool non_expire) -> std::tuple<bool, QString>; + bool non_expire) -> std::tuple<GpgError, QString>; /** * @brief @@ -122,6 +123,9 @@ class GPGFRONTEND_CORE_EXPORT GpgSmartCardManager GpgContext::GetInstance(SingletonFunctionObject::GetChannel()); ///< GpgAssuanHelper& assuan_ = GpgAssuanHelper::GetInstance(SingletonFunctionObject::GetChannel()); ///< + GpgComponentInfoGetter& info_ = GpgComponentInfoGetter::GetInstance( + SingletonFunctionObject::GetChannel()); ///< + QString cached_scd_serialno_status_hash_; QContainer<QString> cache_scd_card_serial_numbers_; }; diff --git a/src/core/function/gpg/GpgUIDOperator.cpp b/src/core/function/gpg/GpgUIDOperator.cpp index e07b4192..ca056be0 100644 --- a/src/core/function/gpg/GpgUIDOperator.cpp +++ b/src/core/function/gpg/GpgUIDOperator.cpp @@ -29,7 +29,6 @@ #include "GpgUIDOperator.h" #include "core/function/gpg/GpgAutomatonHandler.h" -#include "core/model/GpgData.h" #include "core/utils/GpgUtils.h" namespace GpgFrontend { @@ -65,8 +64,8 @@ auto GpgUIDOperator::DeleteUID(const GpgKeyPtr& key, int uid_index) -> bool { } AutomatonNextStateHandler next_state_handler = [](AutomatonState state, - QString status, - QString args) { + const QString& status, + const QString& args) { auto tokens = args.split(' '); switch (state) { @@ -124,15 +123,14 @@ auto GpgUIDOperator::DeleteUID(const GpgKeyPtr& key, int uid_index) -> bool { return QString("Y"); case GpgAutomatonHandler::kAS_START: case GpgAutomatonHandler::kAS_ERROR: - return QString(""); default: return QString(""); } return QString(""); }; - return GpgAutomatonHandler::GetInstance(GetChannel()) - .DoInteract(key, next_state_handler, action_handler); + auto [err, succ] = auto_.DoInteract(key, next_state_handler, action_handler); + return err == GPG_ERR_NO_ERROR && !succ; } auto GpgUIDOperator::RevokeUID(const GpgKeyPtr& key, int uid_index, @@ -153,8 +151,8 @@ auto GpgUIDOperator::RevokeUID(const GpgKeyPtr& key, int uid_index, reason_text.split('\n', Qt::SkipEmptyParts)); AutomatonNextStateHandler next_state_handler = [](AutomatonState state, - QString status, - QString args) { + const QString& status, + const QString& args) { auto tokens = args.split(' '); switch (state) { @@ -240,15 +238,14 @@ auto GpgUIDOperator::RevokeUID(const GpgKeyPtr& key, int uid_index, return QString("Y"); case GpgAutomatonHandler::kAS_START: case GpgAutomatonHandler::kAS_ERROR: - return QString(""); default: return QString(""); } return QString(""); }; - return GpgAutomatonHandler::GetInstance(GetChannel()) - .DoInteract(key, next_state_handler, action_handler); + auto [err, succ] = auto_.DoInteract(key, next_state_handler, action_handler); + return err == GPG_ERR_NO_ERROR && !succ; } } // namespace GpgFrontend diff --git a/src/core/function/gpg/GpgUIDOperator.h b/src/core/function/gpg/GpgUIDOperator.h index e5e2f190..0e222388 100644 --- a/src/core/function/gpg/GpgUIDOperator.h +++ b/src/core/function/gpg/GpgUIDOperator.h @@ -28,6 +28,7 @@ #pragma once +#include "core/function/gpg/GpgAutomatonHandler.h" #include "core/function/gpg/GpgContext.h" #include "core/typedef/GpgTypedef.h" @@ -100,6 +101,8 @@ class GPGFRONTEND_CORE_EXPORT GpgUIDOperator private: GpgContext& ctx_ = GpgContext::GetInstance(SingletonFunctionObject::GetChannel()); ///< + GpgAutomatonHandler& auto_ = GpgAutomatonHandler::GetInstance( + SingletonFunctionObject::GetChannel()); ///< }; } // namespace GpgFrontend diff --git a/src/core/utils/AsyncUtils.cpp b/src/core/utils/AsyncUtils.cpp index a4bc66fa..a3ab9eb8 100644 --- a/src/core/utils/AsyncUtils.cpp +++ b/src/core/utils/AsyncUtils.cpp @@ -28,24 +28,20 @@ #include "AsyncUtils.h" +#include "core/model/DataObject.h" #include "core/module/ModuleManager.h" #include "core/thread/Task.h" #include "core/thread/TaskRunnerGetter.h" -#include "core/utils/CommonUtils.h" -#include "model/DataObject.h" +#include "core/utils/GpgUtils.h" namespace GpgFrontend { -auto RunGpgOperaAsync(const GpgOperaRunnable& runnable, +auto RunGpgOperaAsync(int channel, const GpgOperaRunnable& runnable, const GpgOperationCallback& callback, - const QString& operation, const QString& minial_version) + const QString& operation, const QString& minimal_version) -> Thread::Task::TaskHandler { - const auto gnupg_version = Module::RetrieveRTValueTypedOrDefault<>( - "core", "gpgme.ctx.gnupg_version", minial_version); - - if (GFCompareSoftwareVersion(gnupg_version, minial_version) < 0) { - LOG_W() << "operation" << operation - << " not support for gnupg version: " << gnupg_version; + if (!CheckGpgVersion(channel, minimal_version)) { + LOG_W() << "operation: " << operation << "is not supported."; callback(GPG_ERR_NOT_SUPPORTED, TransferParams()); return Thread::Task::TaskHandler(nullptr); } @@ -75,15 +71,11 @@ auto RunGpgOperaAsync(const GpgOperaRunnable& runnable, return handler; } -auto RunGpgOperaSync(const GpgOperaRunnable& runnable, const QString& operation, - const QString& minial_version) +auto RunGpgOperaSync(int channel, const GpgOperaRunnable& runnable, + const QString& operation, const QString& minimal_version) -> std::tuple<GpgError, DataObjectPtr> { - const auto gnupg_version = Module::RetrieveRTValueTypedOrDefault<>( - "core", "gpgme.ctx.gnupg_version", minial_version); - - if (GFCompareSoftwareVersion(gnupg_version, minial_version) < 0) { - LOG_W() << "operation" << operation - << " not support for gnupg version: " << gnupg_version; + if (!CheckGpgVersion(channel, minimal_version)) { + LOG_W() << "operation: " << operation << "is not supported."; return {GPG_ERR_NOT_SUPPORTED, TransferParams()}; } diff --git a/src/core/utils/AsyncUtils.h b/src/core/utils/AsyncUtils.h index eb55cf89..5be3b230 100644 --- a/src/core/utils/AsyncUtils.h +++ b/src/core/utils/AsyncUtils.h @@ -41,24 +41,24 @@ namespace GpgFrontend { * @param runnable * @param callback * @param operation - * @param minial_version + * @param minimal_version */ auto GPGFRONTEND_CORE_EXPORT -RunGpgOperaAsync(const GpgOperaRunnable& runnable, +RunGpgOperaAsync(int channel, const GpgOperaRunnable& runnable, const GpgOperationCallback& callback, const QString& operation, - const QString& minial_version) -> Thread::Task::TaskHandler; + const QString& minimal_version) -> Thread::Task::TaskHandler; /** * @brief * * @param runnable * @param operation - * @param minial_version + * @param minimal_version * @return std::tuple<GpgError, DataObjectPtr> */ auto GPGFRONTEND_CORE_EXPORT RunGpgOperaSync( - const GpgOperaRunnable& runnable, const QString& operation, - const QString& minial_version) -> std::tuple<GpgError, DataObjectPtr>; + int channel, const GpgOperaRunnable& runnable, const QString& operation, + const QString& minimal_version) -> std::tuple<GpgError, DataObjectPtr>; /** * @brief diff --git a/src/core/utils/CommonUtils.cpp b/src/core/utils/CommonUtils.cpp index ce36c71e..eec5deef 100644 --- a/src/core/utils/CommonUtils.cpp +++ b/src/core/utils/CommonUtils.cpp @@ -74,6 +74,11 @@ auto GFCompareSoftwareVersion(const QString& a, const QString& b) -> int { return 0; } +auto GFSoftwareVersionGreaterThan(const QString& a, const QString& b) -> bool { + if (a.isEmpty()) return false; + return GFCompareSoftwareVersion(a, b) > 0; +} + auto GFStrDup(const QString& s) -> char* { if (s.isEmpty()) return nullptr; diff --git a/src/core/utils/CommonUtils.h b/src/core/utils/CommonUtils.h index d62f4867..b7d18891 100644 --- a/src/core/utils/CommonUtils.h +++ b/src/core/utils/CommonUtils.h @@ -90,4 +90,14 @@ auto GPGFRONTEND_CORE_EXPORT ParseHexEncodedVersionTuple(const QString &s) */ auto GPGFRONTEND_CORE_EXPORT IsEmailAddress(const QString &) -> bool; +/** + * @brief if a > b + * + * @param a + * @param b + * @return auto + */ +auto GPGFRONTEND_CORE_EXPORT +GFSoftwareVersionGreaterThan(const QString &a, const QString &b) -> bool; + } // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/utils/GpgUtils.cpp b/src/core/utils/GpgUtils.cpp index b8824673..13f6ef05 100644 --- a/src/core/utils/GpgUtils.cpp +++ b/src/core/utils/GpgUtils.cpp @@ -30,12 +30,15 @@ #include "core/function/GlobalSettingStation.h" #include "core/function/gpg/GpgAbstractKeyGetter.h" +#include "core/function/gpg/GpgComponentInfoGetter.h" #include "core/model/GpgKey.h" #include "core/model/GpgKeyGroup.h" #include "core/model/KeyDatabaseInfo.h" #include "core/model/SettingsObject.h" #include "core/module/ModuleManager.h" #include "core/struct/settings_object/KeyDatabaseListSO.h" +#include "core/utils/CommonUtils.h" + namespace GpgFrontend { inline auto Trim(QString& s) -> QString { return s.trimmed(); } @@ -424,4 +427,33 @@ auto GPGFRONTEND_CORE_EXPORT IsKeyGroupID(const KeyId& id) -> bool { return id.startsWith("#&"); } +auto GPGFRONTEND_CORE_EXPORT +GpgAgentVersionGreaterThan(int channel, const QString& v) -> bool { + return GFSoftwareVersionGreaterThan( + GpgComponentInfoGetter::GetInstance(channel).GetGpgAgentVersion(), v); +} + +auto GPGFRONTEND_CORE_EXPORT CheckGpgVersion(int channel, + const QString& v) -> bool { + const auto ver = + GpgComponentInfoGetter::GetInstance(channel).GetGpgAgentVersion(); + + if (ver.isEmpty() || !GFSoftwareVersionGreaterThan(ver, v)) { + LOG_W() << "operation not support for gpg-agent version: " << ver + << "minimal version: " << v; + return false; + } + + const auto gnupg_version = Module::RetrieveRTValueTypedOrDefault<>( + "core", "gpgme.ctx.gnupg_version", QString{}); + + if (gnupg_version.isEmpty() || + GFCompareSoftwareVersion(gnupg_version, v) < 0) { + LOG_W() << "operation not support for gnupg version: " << gnupg_version + << "minimal version: " << v; + return false; + } + + return true; +} } // namespace GpgFrontend diff --git a/src/core/utils/GpgUtils.h b/src/core/utils/GpgUtils.h index 13612b4f..d0fe1701 100644 --- a/src/core/utils/GpgUtils.h +++ b/src/core/utils/GpgUtils.h @@ -202,4 +202,23 @@ auto GPGFRONTEND_CORE_EXPORT GetGpgKeyByGpgAbstractKey(GpgAbstractKey*) * @return false */ auto GPGFRONTEND_CORE_EXPORT IsKeyGroupID(const KeyId& id) -> bool; + +/** + * @brief + * + * @return bool + */ +auto GPGFRONTEND_CORE_EXPORT GpgAgentVersionGreaterThan(int channel, + const QString&) -> bool; + +/** + * @brief + * + * @param channel + * @return true + * @return false + */ +auto GPGFRONTEND_CORE_EXPORT CheckGpgVersion(int channel, + const QString&) -> bool; + } // namespace GpgFrontend
\ No newline at end of file diff --git a/src/init.cpp b/src/init.cpp index 71f24668..3d1f344b 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -184,9 +184,15 @@ void ShutdownGlobalBasicEnv(const GFCxtWPtr &p_ctx) { .toBool(); if (ctx->unit_test_mode || kill_all_gnupg_daemon_at_close) { - GpgAdvancedOperator::KillAllGpgComponents(nullptr); + const auto size = GpgContext::GetAllChannelId().size(); + for (auto i = 0; i < size; i++) { + assert(GpgAdvancedOperator::GetInstance().KillAllGpgComponents()); + } } else if (!ctx->unit_test_mode && clear_gpg_password_cache) { - GpgAdvancedOperator::ClearGpgPasswordCache(nullptr); + const auto size = GpgContext::GetAllChannelId().size(); + for (auto i = 0; i < size; i++) { + assert(GpgAdvancedOperator::GetInstance().ClearGpgPasswordCache()); + } } // first should shutdown the module system diff --git a/src/ui/UserInterfaceUtils.cpp b/src/ui/UserInterfaceUtils.cpp index 8d277ab4..ed76824a 100644 --- a/src/ui/UserInterfaceUtils.cpp +++ b/src/ui/UserInterfaceUtils.cpp @@ -167,16 +167,17 @@ void CommonUtils::RaiseMessageBox(QWidget *parent, GpgError err) { } } -void CommonUtils::RaiseFailureMessageBox(QWidget *parent, GpgError err) { +void CommonUtils::RaiseFailureMessageBox(QWidget *parent, GpgError err, + const QString &msg) { GpgErrorDesc desc = DescribeGpgErrCode(err); GpgErrorCode err_code = CheckGpgError2ErrCode(err); QMessageBox::critical(parent, tr("Failure"), - tr("Gpg Operation failed.\n\nError code: %1\nSource: " - " %2\nDescription: %3") - .arg(err_code) - .arg(desc.first) - .arg(desc.second)); + tr("Gpg Operation failed.") + "\n\n" + + tr("Error code: %1").arg(err_code) + "\n\n\n" + + tr("Source: %1").arg(desc.first) + "\n" + + tr("Description: %1").arg(desc.second) + "\n" + + tr("Error Message: %1").arg(msg)); } void CommonUtils::SlotImportKeys(QWidget *parent, int channel, diff --git a/src/ui/UserInterfaceUtils.h b/src/ui/UserInterfaceUtils.h index fe912fcf..b544ffc3 100644 --- a/src/ui/UserInterfaceUtils.h +++ b/src/ui/UserInterfaceUtils.h @@ -113,7 +113,8 @@ class CommonUtils : public QWidget { * * @param err */ - static void RaiseFailureMessageBox(QWidget* parent, GpgError err); + static void RaiseFailureMessageBox(QWidget* parent, GpgError err, + const QString& msg = {}); /** * @brief diff --git a/src/ui/dialog/ADSKsPicker.cpp b/src/ui/dialog/ADSKsPicker.cpp index 878c5e96..56039a15 100644 --- a/src/ui/dialog/ADSKsPicker.cpp +++ b/src/ui/dialog/ADSKsPicker.cpp @@ -115,8 +115,7 @@ void ADSKsPicker::slot_add_adsk(const QContainer<GpgSubKey>& s_keys) { for (const auto& info : err_sub_key_infos) { failed_info.append(info); } - QString details = failed_info.join("\n\n"); - + auto details = failed_info.join("\n\n"); auto* msg_box = new QMessageBox(nullptr); msg_box->setIcon(QMessageBox::Warning); msg_box->setWindowTitle(err_sub_key_infos.size() == s_keys.size() diff --git a/src/ui/dialog/controller/SmartCardControllerDialog.cpp b/src/ui/dialog/controller/SmartCardControllerDialog.cpp index 73dd48b9..797fe052 100644 --- a/src/ui/dialog/controller/SmartCardControllerDialog.cpp +++ b/src/ui/dialog/controller/SmartCardControllerDialog.cpp @@ -33,6 +33,7 @@ #include "core/function/gpg/GpgSmartCardManager.h" #include "core/utils/GpgUtils.h" #include "ui/UISignalStation.h" +#include "ui/UserInterfaceUtils.h" #include "ui/dialog/key_generate/GenerateCardKeyDialog.h" // @@ -110,18 +111,22 @@ SmartCardControllerDialog::SmartCardControllerDialog(QWidget* parent) [=](bool) { modify_key_pin("OPENPGP.2"); }); connect(ui_->restartGpgAgentButton, &QPushButton::clicked, this, [=](bool) { - GpgFrontend::GpgAdvancedOperator::RestartGpgComponents( - [=](int err, DataObjectPtr) { - if (err >= 0) { - QMessageBox::information( - this, tr("Successful Operation"), - tr("Restart all the GnuPG's components successfully")); - } else { - QMessageBox::critical( - this, tr("Failed Operation"), - tr("Failed to restart all or one of the GnuPG's component(s)")); - } - }); + bool ret = true; + const auto size = GpgContext::GetAllChannelId().size(); + for (auto i = 0; i < size; i++) { + ret = GpgAdvancedOperator::GetInstance().RestartGpgComponents(); + if (!ret) break; + } + + if (ret) { + QMessageBox::information( + this, tr("Successful Operation"), + tr("Restart all the GnuPG's components successfully")); + } else { + QMessageBox::critical( + this, tr("Failed Operation"), + tr("Failed to restart all or one of the GnuPG's component(s)")); + } }); connect(ui_->generateKeysButton, &QPushButton::clicked, this, [=](bool) { @@ -163,11 +168,13 @@ void SmartCardControllerDialog::select_smart_card_by_serial_number( return; } - auto [ret, err] = + auto [err, status] = GpgSmartCardManager::GetInstance(channel_).SelectCardBySerialNumber( serial_number); - if (!ret) { - LOG_E() << "select card by serial number failed: " << err; + if (err != GPG_ERR_NO_ERROR) { + LOG_E() << "select card by serial number failed, err:" << CheckGpgError(err) + << "status:" << status; + CommonUtils::RaiseFailureMessageBox(this, err, status); reset_status(); return; } @@ -188,6 +195,7 @@ void SmartCardControllerDialog::fetch_smart_card_info( GpgSmartCardManager::GetInstance(channel_).FetchCardInfoBySerialNumber( serial_number); if (card_info == nullptr) { + LOG_E() << "card info is nullptr, serial number:" << serial_number; reset_status(); return; } @@ -446,9 +454,14 @@ void SmartCardControllerDialog::slot_disable_controllers(bool disable) { void SmartCardControllerDialog::slot_fetch_smart_card_keys() { ui_->fetchButton->setDisabled(true); - GpgSmartCardManager::GetInstance().Fetch( + auto err = GpgSmartCardManager::GetInstance().Fetch( ui_->currentCardComboBox->currentText()); + if (err != GPG_ERR_NO_ERROR) { + CommonUtils::RaiseFailureMessageBox(this, err); + return; + } + QTimer::singleShot(1000, [=]() { GpgCommandExecutor::GetInstance(channel_).GpgExecuteSync( {{}, @@ -524,14 +537,13 @@ void SmartCardControllerDialog::modify_key_attribute(const QString& attr) { } } - auto [r, err] = + auto [err, status] = GpgSmartCardManager::GetInstance(channel_).ModifyAttr(attr, value); - if (!r) { - LOG_D() << "SCD SETATTR command failed for attr" << attr; - QMessageBox::critical( - this, tr("Failed"), - tr("Failed to set attribute '%1'. Reason: %2. ").arg(attr).arg(err)); + if (err != GPG_ERR_NO_ERROR) { + LOG_D() << "SCD SETATTR command failed for attr:" << attr + << ", err:" << CheckGpgError(err); + CommonUtils::RaiseFailureMessageBox(this, err, status); return; } QMessageBox::information(this, tr("Success"), @@ -540,22 +552,11 @@ void SmartCardControllerDialog::modify_key_attribute(const QString& attr) { } void SmartCardControllerDialog::modify_key_pin(const QString& pinref) { - auto [success, err] = + auto [err, status] = GpgSmartCardManager::GetInstance(channel_).ModifyPin(pinref); - if (!success) { - QString message; - if (pinref == "OPENPGP.3") { - message = tr("Failed to change Admin PIN."); - } else if (pinref == "OPENPGP.2") { - message = tr("Failed to set the Reset Code."); - } else { - message = tr("Failed to change PIN."); - } - - message += tr("Reason: ") + err; - - QMessageBox::critical(this, tr("Error"), message); + if (err != GPG_ERR_NO_ERROR) { + CommonUtils::RaiseFailureMessageBox(this, err, status); return; } diff --git a/src/ui/function/GpgOperaHelper.cpp b/src/ui/function/GpgOperaHelper.cpp index 91bc6c38..82742b93 100644 --- a/src/ui/function/GpgOperaHelper.cpp +++ b/src/ui/function/GpgOperaHelper.cpp @@ -90,6 +90,12 @@ auto GpgOperaHelper::BuildSimpleGpgFileOperasHelper( // stop waiting op_hd(); + if (CheckGpgError(err) == GPG_ERR_NOT_SUPPORTED) { + opera_results.append({-1, "# " + tr("Operation Not Supported"), + QFileInfo(path).fileName()}); + return; + } + if (CheckGpgError(err) == GPG_ERR_USER_1 || data_obj == nullptr || !data_obj->Check<ResultType>()) { opera_results.append( @@ -126,6 +132,12 @@ auto GpgOperaHelper::BuildComplexGpgFileOperasHelper( // stop waiting op_hd(); + if (CheckGpgError(err) == GPG_ERR_NOT_SUPPORTED) { + opera_results.append({-1, "# " + tr("Operation Not Supported"), + QFileInfo(path).fileName()}); + return; + } + if (CheckGpgError(err) == GPG_ERR_USER_1 || data_obj == nullptr || !data_obj->Check<ResultTypeA, ResultTypeB>()) { opera_results.append( @@ -169,6 +181,11 @@ auto GpgOperaHelper::BuildSimpleGpgOperasHelper( // stop waiting op_hd(); + if (CheckGpgError(err) == GPG_ERR_NOT_SUPPORTED) { + opera_results.append({-1, "# " + tr("Operation Not Supported"), {}}); + return; + } + if (CheckGpgError(err) == GPG_ERR_USER_1 || data_obj == nullptr || !data_obj->Check<ResultType, GFBuffer>()) { opera_results.append({-1, "# " + tr("Critical Error"), {}}); @@ -207,6 +224,11 @@ auto GpgOperaHelper::BuildComplexGpgOperasHelper( // stop waiting op_hd(); + if (CheckGpgError(err) == GPG_ERR_NOT_SUPPORTED) { + opera_results.append({-1, "# " + tr("Operation Not Supported"), {}}); + return; + } + if (CheckGpgError(err) == GPG_ERR_USER_1 || data_obj == nullptr || !data_obj->Check<ResultTypeA, ResultTypeB, GFBuffer>()) { opera_results.append({-1, "# " + tr("Critical Error"), {}}); diff --git a/src/ui/main_window/MainWindow.h b/src/ui/main_window/MainWindow.h index 15fb9fb1..16092609 100644 --- a/src/ui/main_window/MainWindow.h +++ b/src/ui/main_window/MainWindow.h @@ -528,7 +528,7 @@ class MainWindow : public GeneralMainWindow { * * @param results */ - void slot_update_operations_menu_by_checked_keys(unsigned int type); + void slot_update_operations_menu_by_checked_keys(unsigned int mask); /** * @brief diff --git a/src/ui/main_window/MainWindowSlotUI.cpp b/src/ui/main_window/MainWindowSlotUI.cpp index e0a72ed1..6b945beb 100644 --- a/src/ui/main_window/MainWindowSlotUI.cpp +++ b/src/ui/main_window/MainWindowSlotUI.cpp @@ -311,46 +311,58 @@ void MainWindow::SlotGeneralDecryptVerify(bool) { } void MainWindow::slot_clean_gpg_password_cache(bool) { - GpgFrontend::GpgAdvancedOperator::ClearGpgPasswordCache( - [=](int err, DataObjectPtr) { - if (err >= 0) { - QMessageBox::information(this, tr("Successful Operation"), - tr("Clear password cache successfully")); - } else { - QMessageBox::critical(this, tr("Failed Operation"), - tr("Failed to clear password cache of GnuPG")); - } - }); + bool ret = true; + const auto size = GpgContext::GetAllChannelId().size(); + for (auto i = 0; i < size; i++) { + ret = GpgAdvancedOperator::GetInstance().ClearGpgPasswordCache(); + if (!ret) break; + } + + if (ret) { + QMessageBox::information(this, tr("Successful Operation"), + tr("Clear password cache successfully")); + } else { + QMessageBox::critical(this, tr("Failed Operation"), + tr("Failed to clear password cache of GnuPG")); + } } void MainWindow::slot_reload_gpg_components(bool) { - GpgFrontend::GpgAdvancedOperator::ReloadGpgComponents( - [=](int err, DataObjectPtr) { - if (err >= 0) { - QMessageBox::information( - this, tr("Successful Operation"), - tr("Reload all the GnuPG's components successfully")); - } else { - QMessageBox::critical( - this, tr("Failed Operation"), - tr("Failed to reload all or one of the GnuPG's component(s)")); - } - }); + bool ret = true; + const auto size = GpgContext::GetAllChannelId().size(); + for (auto i = 0; i < size; i++) { + ret = GpgAdvancedOperator::GetInstance().ReloadAllGpgComponents(); + if (!ret) break; + } + + if (ret) { + QMessageBox::information( + this, tr("Successful Operation"), + tr("Reload all the GnuPG's components successfully")); + } else { + QMessageBox::critical( + this, tr("Failed Operation"), + tr("Failed to reload all or one of the GnuPG's component(s)")); + } } void MainWindow::slot_restart_gpg_components(bool) { - GpgFrontend::GpgAdvancedOperator::RestartGpgComponents( - [=](int err, DataObjectPtr) { - if (err >= 0) { - QMessageBox::information( - this, tr("Successful Operation"), - tr("Restart all the GnuPG's components successfully")); - } else { - QMessageBox::critical( - this, tr("Failed Operation"), - tr("Failed to restart all or one of the GnuPG's component(s)")); - } - }); + bool ret = true; + const auto size = GpgContext::GetAllChannelId().size(); + for (auto i = 0; i < size; i++) { + ret = GpgAdvancedOperator::GetInstance().RestartGpgComponents(); + if (!ret) break; + } + + if (ret) { + QMessageBox::information( + this, tr("Successful Operation"), + tr("Restart all the GnuPG's components successfully")); + } else { + QMessageBox::critical( + this, tr("Failed Operation"), + tr("Failed to restart all or one of the GnuPG's component(s)")); + } } void MainWindow::slot_update_operations_menu_by_checked_keys( |