aboutsummaryrefslogtreecommitdiffstats
path: root/src/core/function/gpg
diff options
context:
space:
mode:
authorsaturneric <[email protected]>2025-04-15 23:19:53 +0000
committersaturneric <[email protected]>2025-04-15 23:19:53 +0000
commit73a0f7ddf8a8db0057201374f1518d2063ad9a06 (patch)
tree4dfdf140fa639f0ab8799433c4d9cf5079a92bf0 /src/core/function/gpg
parentrefactor: code cleanup (diff)
downloadGpgFrontend-73a0f7ddf8a8db0057201374f1518d2063ad9a06.tar.gz
GpgFrontend-73a0f7ddf8a8db0057201374f1518d2063ad9a06.zip
feat: support key groups
Diffstat (limited to 'src/core/function/gpg')
-rw-r--r--src/core/function/gpg/GpgAbstractKeyGetter.cpp85
-rw-r--r--src/core/function/gpg/GpgAbstractKeyGetter.h102
-rw-r--r--src/core/function/gpg/GpgAdvancedOperator.h2
-rw-r--r--src/core/function/gpg/GpgAssuanHelper.h8
-rw-r--r--src/core/function/gpg/GpgAutomatonHandler.cpp6
-rw-r--r--src/core/function/gpg/GpgAutomatonHandler.h2
-rw-r--r--src/core/function/gpg/GpgBasicOperator.cpp48
-rw-r--r--src/core/function/gpg/GpgBasicOperator.h16
-rw-r--r--src/core/function/gpg/GpgContext.cpp5
-rw-r--r--src/core/function/gpg/GpgContext.h2
-rw-r--r--src/core/function/gpg/GpgFileOpera.cpp62
-rw-r--r--src/core/function/gpg/GpgFileOpera.h41
-rw-r--r--src/core/function/gpg/GpgKeyGetter.cpp49
-rw-r--r--src/core/function/gpg/GpgKeyGetter.h39
-rw-r--r--src/core/function/gpg/GpgKeyGroupGetter.cpp311
-rw-r--r--src/core/function/gpg/GpgKeyGroupGetter.h215
-rw-r--r--src/core/function/gpg/GpgKeyImportExporter.cpp28
-rw-r--r--src/core/function/gpg/GpgKeyImportExporter.h10
-rw-r--r--src/core/function/gpg/GpgKeyManager.cpp28
-rw-r--r--src/core/function/gpg/GpgKeyManager.h17
-rw-r--r--src/core/function/gpg/GpgKeyOpera.cpp86
-rw-r--r--src/core/function/gpg/GpgKeyOpera.h22
-rw-r--r--src/core/function/gpg/GpgUIDOperator.cpp22
-rw-r--r--src/core/function/gpg/GpgUIDOperator.h10
24 files changed, 999 insertions, 217 deletions
diff --git a/src/core/function/gpg/GpgAbstractKeyGetter.cpp b/src/core/function/gpg/GpgAbstractKeyGetter.cpp
new file mode 100644
index 00000000..0b544469
--- /dev/null
+++ b/src/core/function/gpg/GpgAbstractKeyGetter.cpp
@@ -0,0 +1,85 @@
+/**
+ * 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 "GpgAbstractKeyGetter.h"
+
+#include "core/model/GpgKeyTableModel.h"
+#include "core/utils/GpgUtils.h"
+
+namespace GpgFrontend {
+
+GpgAbstractKeyGetter::GpgAbstractKeyGetter(int channel)
+ : SingletonFunctionObject<GpgAbstractKeyGetter>(channel){};
+
+auto GpgAbstractKeyGetter::Fetch() -> GpgAbstractKeyPtrList {
+ auto ret = GpgAbstractKeyPtrList{};
+
+ auto keys = key_.Fetch();
+ for (const auto& key : keys) {
+ ret.push_back(qSharedPointerCast<GpgAbstractKey>(key));
+ }
+
+ auto kgs = kg_.Fetch();
+ for (const auto& kg : kgs) {
+ ret.push_back(qSharedPointerCast<GpgAbstractKey>(kg));
+ }
+
+ return ret;
+}
+
+auto GpgAbstractKeyGetter::GetGpgKeyTableModel()
+ -> QSharedPointer<GpgKeyTableModel> {
+ return SecureCreateQSharedObject<GpgKeyTableModel>(
+ SingletonFunctionObject::GetChannel(), Fetch(), nullptr);
+}
+
+auto GpgAbstractKeyGetter::FlushCache() -> bool {
+ return key_.FlushKeyCache() && kg_.FlushCache();
+}
+
+auto GpgAbstractKeyGetter::GetKey(const QString& key_id) -> GpgAbstractKeyPtr {
+ if (IsKeyGroupID(key_id)) {
+ return kg_.KeyGroup(key_id);
+ }
+ return key_.GetKeyPtr(key_id);
+}
+
+auto GpgAbstractKeyGetter::GetKeys(const QStringList& key_ids)
+ -> GpgAbstractKeyPtrList {
+ auto ret = GpgAbstractKeyPtrList{};
+ for (const auto& key_id : key_ids) {
+ auto key = GetKey(key_id);
+ if (key == nullptr) continue;
+
+ ret.push_back(key);
+ }
+ return ret;
+}
+
+GpgAbstractKeyGetter::~GpgAbstractKeyGetter() = default;
+} // namespace GpgFrontend \ No newline at end of file
diff --git a/src/core/function/gpg/GpgAbstractKeyGetter.h b/src/core/function/gpg/GpgAbstractKeyGetter.h
new file mode 100644
index 00000000..571121a9
--- /dev/null
+++ b/src/core/function/gpg/GpgAbstractKeyGetter.h
@@ -0,0 +1,102 @@
+/**
+ * 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/basic/GpgFunctionObject.h"
+#include "core/function/gpg/GpgKeyGetter.h"
+#include "core/function/gpg/GpgKeyGroupGetter.h"
+#include "core/typedef/GpgTypedef.h"
+
+namespace GpgFrontend {
+
+class GpgKeyTableModel;
+
+/**
+ * @brief
+ *
+ */
+class GPGFRONTEND_CORE_EXPORT GpgAbstractKeyGetter
+ : public SingletonFunctionObject<GpgAbstractKeyGetter> {
+ public:
+ /**
+ * @brief Construct a new Gpg Key Getter object
+ *
+ * @param channel
+ */
+ explicit GpgAbstractKeyGetter(int channel = kGpgFrontendDefaultChannel);
+
+ /**
+ * @brief Destroy the Gpg Key Getter object
+ *
+ */
+ ~GpgAbstractKeyGetter();
+
+ /**
+ * @brief Get the Key object
+ *
+ * @param fpr
+ * @return GpgKey
+ */
+ auto GetKey(const QString& key_id) -> GpgAbstractKeyPtr;
+
+ /**
+ * @brief Get the Keys object
+ *
+ * @param key_ids
+ * @return auto
+ */
+ auto GetKeys(const QStringList& key_ids) -> GpgAbstractKeyPtrList;
+
+ /**
+ * @brief Get all the keys by receiving a linked list
+ *
+ * @return KeyLinkListPtr
+ */
+ auto Fetch() -> GpgAbstractKeyPtrList;
+
+ /**
+ * @brief flush the keys in the cache
+ *
+ */
+ auto FlushCache() -> bool;
+
+ /**
+ * @brief
+ *
+ * @return GpgKeyTableModel
+ */
+ auto GetGpgKeyTableModel() -> QSharedPointer<GpgKeyTableModel>;
+
+ private:
+ GpgKeyGetter& key_ =
+ GpgKeyGetter::GetInstance(SingletonFunctionObject::GetChannel());
+ GpgKeyGroupGetter& kg_ =
+ GpgKeyGroupGetter::GetInstance(SingletonFunctionObject::GetChannel());
+};
+} // namespace GpgFrontend
diff --git a/src/core/function/gpg/GpgAdvancedOperator.h b/src/core/function/gpg/GpgAdvancedOperator.h
index cfd5fbcf..57279adb 100644
--- a/src/core/function/gpg/GpgAdvancedOperator.h
+++ b/src/core/function/gpg/GpgAdvancedOperator.h
@@ -32,7 +32,7 @@
#pragma once
-#include "core/typedef/CoreTypedef.h"
+#include "core/model/DataObject.h"
namespace GpgFrontend {
diff --git a/src/core/function/gpg/GpgAssuanHelper.h b/src/core/function/gpg/GpgAssuanHelper.h
index 6e58e27c..a0c45d7a 100644
--- a/src/core/function/gpg/GpgAssuanHelper.h
+++ b/src/core/function/gpg/GpgAssuanHelper.h
@@ -113,6 +113,10 @@ class GPGFRONTEND_CORE_EXPORT GpgAssuanHelper
GpgContext::GetInstance(SingletonFunctionObject::GetChannel());
QMap<GpgComponentType, assuan_context_t> assuan_ctx_;
+ QByteArray temp_data_;
+ QString temp_status_;
+ QString gpgconf_path_;
+
/**
* @brief
*
@@ -169,10 +173,6 @@ class GPGFRONTEND_CORE_EXPORT GpgAssuanHelper
*/
static auto default_inquery_callback(void* opaque,
const char* inquery) -> gpgme_error_t;
-
- QByteArray temp_data_;
- QString temp_status_;
- QString gpgconf_path_;
};
}; // namespace GpgFrontend \ No newline at end of file
diff --git a/src/core/function/gpg/GpgAutomatonHandler.cpp b/src/core/function/gpg/GpgAutomatonHandler.cpp
index af2f0cba..b2d9d562 100644
--- a/src/core/function/gpg/GpgAutomatonHandler.cpp
+++ b/src/core/function/gpg/GpgAutomatonHandler.cpp
@@ -97,13 +97,13 @@ auto GpgAutomatonHandler::interator_cb_func(void* handle, const char* status,
}
auto GpgAutomatonHandler::DoInteract(
- const GpgKey& key, AutomatonNextStateHandler next_state_handler,
+ const GpgKeyPtr& key, AutomatonNextStateHandler next_state_handler,
AutomatonActionHandler action_handler, int flags) -> bool {
gpgme_key_t p_key =
- flags == GPGME_INTERACT_CARD ? nullptr : static_cast<gpgme_key_t>(key);
+ flags == GPGME_INTERACT_CARD ? nullptr : static_cast<gpgme_key_t>(*key);
AutomatonHandelStruct handel_struct(
- flags == GPGME_INTERACT_CARD ? "" : key.Fingerprint());
+ flags == GPGME_INTERACT_CARD ? "" : key->Fingerprint());
handel_struct.SetHandler(std::move(next_state_handler),
std::move(action_handler));
diff --git a/src/core/function/gpg/GpgAutomatonHandler.h b/src/core/function/gpg/GpgAutomatonHandler.h
index f86299e8..cdf96060 100644
--- a/src/core/function/gpg/GpgAutomatonHandler.h
+++ b/src/core/function/gpg/GpgAutomatonHandler.h
@@ -97,7 +97,7 @@ class GpgAutomatonHandler
* @return true
* @return false
*/
- auto DoInteract(const GpgKey& key,
+ auto DoInteract(const GpgKeyPtr& key,
AutomatonNextStateHandler next_state_handler,
AutomatonActionHandler action_handler, int flags = 0) -> bool;
diff --git a/src/core/function/gpg/GpgBasicOperator.cpp b/src/core/function/gpg/GpgBasicOperator.cpp
index 2548409e..43917db3 100644
--- a/src/core/function/gpg/GpgBasicOperator.cpp
+++ b/src/core/function/gpg/GpgBasicOperator.cpp
@@ -43,15 +43,17 @@ namespace GpgFrontend {
GpgBasicOperator::GpgBasicOperator(int channel)
: SingletonFunctionObject<GpgBasicOperator>(channel) {}
-void SetSignersImpl(GpgContext& ctx_, const KeyArgsList& signers, bool ascii) {
+void SetSignersImpl(GpgContext& ctx_, const GpgAbstractKeyPtrList& signers,
+ bool ascii) {
auto* ctx = ascii ? ctx_.DefaultContext() : ctx_.BinaryContext();
gpgme_signers_clear(ctx);
- for (const GpgKey& key : signers) {
- LOG_D() << "signer's key fpr: " << key.Fingerprint();
- if (key.IsHasActualSignCap()) {
- auto error = gpgme_signers_add(ctx, gpgme_key_t(key));
+ auto keys = ConvertKey2GpgKeyList(ctx_.GetChannel(), signers);
+ for (const auto& key : keys) {
+ LOG_D() << "signer's key fpr: " << key->Fingerprint();
+ if (key->IsHasSignCap()) {
+ auto error = gpgme_signers_add(ctx, static_cast<gpgme_key_t>(*key));
CheckGpgError(error);
}
}
@@ -62,10 +64,10 @@ void SetSignersImpl(GpgContext& ctx_, const KeyArgsList& signers, bool ascii) {
}
}
-auto EncryptImpl(GpgContext& ctx_, const KeyArgsList& keys,
+auto EncryptImpl(GpgContext& ctx_, const GpgAbstractKeyPtrList& keys,
const GFBuffer& in_buffer, bool ascii,
const DataObjectPtr& data_object) -> GpgError {
- auto recipients = Convert2RawGpgMEKeyList(keys);
+ auto recipients = Convert2RawGpgMEKeyList(ctx_.GetChannel(), keys);
GpgData data_in(in_buffer);
GpgData data_out;
@@ -82,7 +84,7 @@ auto EncryptImpl(GpgContext& ctx_, const KeyArgsList& keys,
return err;
}
-void GpgBasicOperator::Encrypt(const KeyArgsList& keys,
+void GpgBasicOperator::Encrypt(const GpgAbstractKeyPtrList& keys,
const GFBuffer& in_buffer, bool ascii,
const GpgOperationCallback& cb) {
RunGpgOperaAsync(
@@ -92,7 +94,7 @@ void GpgBasicOperator::Encrypt(const KeyArgsList& keys,
cb, "gpgme_op_encrypt", "2.1.0");
}
-auto GpgBasicOperator::EncryptSync(const KeyArgsList& keys,
+auto GpgBasicOperator::EncryptSync(const GpgAbstractKeyPtrList& keys,
const GFBuffer& in_buffer, bool ascii)
-> std::tuple<GpgError, DataObjectPtr> {
return RunGpgOperaSync(
@@ -199,7 +201,7 @@ auto GpgBasicOperator::VerifySync(const GFBuffer& in_buffer,
"gpgme_op_verify", "2.1.0");
}
-auto SignImpl(GpgContext& ctx_, const KeyArgsList& signers,
+auto SignImpl(GpgContext& ctx_, const GpgAbstractKeyPtrList& signers,
const GFBuffer& in_buffer, GpgSignMode mode, bool ascii,
const DataObjectPtr& data_object) -> GpgError {
if (signers.empty()) return GPG_ERR_CANCELED;
@@ -222,7 +224,7 @@ auto SignImpl(GpgContext& ctx_, const KeyArgsList& signers,
return err;
}
-void GpgBasicOperator::Sign(const KeyArgsList& signers,
+void GpgBasicOperator::Sign(const GpgAbstractKeyPtrList& signers,
const GFBuffer& in_buffer, GpgSignMode mode,
bool ascii, const GpgOperationCallback& cb) {
RunGpgOperaAsync(
@@ -233,8 +235,8 @@ void GpgBasicOperator::Sign(const KeyArgsList& signers,
}
auto GpgBasicOperator::SignSync(
- const KeyArgsList& signers, const GFBuffer& in_buffer, GpgSignMode mode,
- bool ascii) -> std::tuple<GpgError, DataObjectPtr> {
+ const GpgAbstractKeyPtrList& signers, const GFBuffer& in_buffer,
+ GpgSignMode mode, bool ascii) -> std::tuple<GpgError, DataObjectPtr> {
return RunGpgOperaSync(
[=](const DataObjectPtr& data_object) {
return SignImpl(ctx_, signers, in_buffer, mode, ascii, data_object);
@@ -279,13 +281,14 @@ auto GpgBasicOperator::DecryptVerifySync(const GFBuffer& in_buffer)
"gpgme_op_decrypt_verify", "2.1.0");
}
-auto EncryptSignImpl(GpgContext& ctx_, const KeyArgsList& keys,
- const KeyArgsList& signers, const GFBuffer& in_buffer,
- bool ascii, const DataObjectPtr& data_object) -> GpgError {
+auto EncryptSignImpl(GpgContext& ctx_, const GpgAbstractKeyPtrList& keys,
+ const GpgAbstractKeyPtrList& signers,
+ const GFBuffer& in_buffer, bool ascii,
+ const DataObjectPtr& data_object) -> GpgError {
if (keys.empty() || signers.empty()) return GPG_ERR_CANCELED;
GpgError err;
- QContainer<gpgme_key_t> recipients(keys.begin(), keys.end());
+ auto recipients = Convert2RawGpgMEKeyList(ctx_.GetChannel(), keys);
// Last entry data_in array has to be nullptr
recipients.push_back(nullptr);
@@ -307,8 +310,8 @@ auto EncryptSignImpl(GpgContext& ctx_, const KeyArgsList& keys,
return err;
}
-void GpgBasicOperator::EncryptSign(const KeyArgsList& keys,
- const KeyArgsList& signers,
+void GpgBasicOperator::EncryptSign(const GpgAbstractKeyPtrList& keys,
+ const GpgAbstractKeyPtrList& signers,
const GFBuffer& in_buffer, bool ascii,
const GpgOperationCallback& cb) {
RunGpgOperaAsync(
@@ -319,8 +322,8 @@ void GpgBasicOperator::EncryptSign(const KeyArgsList& keys,
cb, "gpgme_op_encrypt_sign", "2.1.0");
}
-auto GpgBasicOperator::EncryptSignSync(const KeyArgsList& keys,
- const KeyArgsList& signers,
+auto GpgBasicOperator::EncryptSignSync(const GpgAbstractKeyPtrList& keys,
+ const GpgAbstractKeyPtrList& signers,
const GFBuffer& in_buffer, bool ascii)
-> std::tuple<GpgError, DataObjectPtr> {
return RunGpgOperaSync(
@@ -331,7 +334,8 @@ auto GpgBasicOperator::EncryptSignSync(const KeyArgsList& keys,
"gpgme_op_encrypt_sign", "2.1.0");
}
-void GpgBasicOperator::SetSigners(const KeyArgsList& signers, bool ascii) {
+void GpgBasicOperator::SetSigners(const GpgAbstractKeyPtrList& signers,
+ bool ascii) {
SetSignersImpl(ctx_, signers, ascii);
}
diff --git a/src/core/function/gpg/GpgBasicOperator.h b/src/core/function/gpg/GpgBasicOperator.h
index 990d7af5..ac6908f4 100644
--- a/src/core/function/gpg/GpgBasicOperator.h
+++ b/src/core/function/gpg/GpgBasicOperator.h
@@ -56,14 +56,14 @@ class GPGFRONTEND_CORE_EXPORT GpgBasicOperator
* @brief
*
*/
- void Encrypt(const KeyArgsList&, const GFBuffer&, bool,
+ void Encrypt(const GpgAbstractKeyPtrList&, const GFBuffer&, bool,
const GpgOperationCallback&);
/**
* @brief
*
*/
- auto EncryptSync(const KeyArgsList&, const GFBuffer&,
+ auto EncryptSync(const GpgAbstractKeyPtrList&, const GFBuffer&,
bool) -> std::tuple<GpgError, DataObjectPtr>;
/**
@@ -99,7 +99,8 @@ class GPGFRONTEND_CORE_EXPORT GpgBasicOperator
* @param ascii ascii mode
* @return
*/
- void EncryptSign(const KeyArgsList& keys, const KeyArgsList& signers,
+ void EncryptSign(const GpgAbstractKeyPtrList& keys,
+ const GpgAbstractKeyPtrList& signers,
const GFBuffer& in_buffer, bool ascii,
const GpgOperationCallback& cb);
@@ -112,7 +113,8 @@ class GPGFRONTEND_CORE_EXPORT GpgBasicOperator
* @param ascii
* @param cb
*/
- auto EncryptSignSync(const KeyArgsList& keys, const KeyArgsList& signers,
+ auto EncryptSignSync(const GpgAbstractKeyPtrList& keys,
+ const GpgAbstractKeyPtrList& signers,
const GFBuffer& in_buffer,
bool ascii) -> std::tuple<GpgError, DataObjectPtr>;
@@ -196,7 +198,7 @@ class GPGFRONTEND_CORE_EXPORT GpgBasicOperator
* @param result the result of the operation
* @return error code
*/
- void Sign(const KeyArgsList& signers, const GFBuffer& in_buffer,
+ void Sign(const GpgAbstractKeyPtrList& signers, const GFBuffer& in_buffer,
GpgSignMode mode, bool ascii, const GpgOperationCallback& cb);
/**
@@ -209,7 +211,7 @@ class GPGFRONTEND_CORE_EXPORT GpgBasicOperator
* @param cb
* @return std::tuple<GpgError, DataObjectPtr>
*/
- auto SignSync(const KeyArgsList& signers, const GFBuffer& in_buffer,
+ auto SignSync(const GpgAbstractKeyPtrList& signers, const GFBuffer& in_buffer,
GpgSignMode mode,
bool ascii) -> std::tuple<GpgError, DataObjectPtr>;
@@ -219,7 +221,7 @@ class GPGFRONTEND_CORE_EXPORT GpgBasicOperator
*
* @param keys
*/
- void SetSigners(const KeyArgsList& signers, bool ascii);
+ void SetSigners(const GpgAbstractKeyPtrList& signers, bool ascii);
/**
* @brief Get a global signature private keys that has been set.
diff --git a/src/core/function/gpg/GpgContext.cpp b/src/core/function/gpg/GpgContext.cpp
index 88eb3c1b..de450356 100644
--- a/src/core/function/gpg/GpgContext.cpp
+++ b/src/core/function/gpg/GpgContext.cpp
@@ -189,6 +189,8 @@ class GpgContext::Impl {
return component_dirs_.value(component_type_to_q_string(type), "");
}
+ [[nodiscard]] auto KeyDBName() const -> QString { return db_name_; }
+
private:
GpgContext *parent_;
GpgContextInitArgs args_{}; ///<
@@ -199,6 +201,7 @@ class GpgContext::Impl {
std::mutex ctx_ref_lock_;
std::mutex binary_ctx_ref_lock_;
+ QString db_name_;
QString gpgconf_path_;
QString database_path_;
QMap<QString, QString> component_dirs_;
@@ -250,6 +253,7 @@ class GpgContext::Impl {
// set custom gpg key db path
if (!args_.db_path.isEmpty()) {
database_path_ = args_.db_path;
+ db_name_ = args_.db_name;
}
LOG_D() << "ctx set engine info, channel: " << parent_->GetChannel()
@@ -445,4 +449,5 @@ auto GpgContext::ComponentDirectory(GpgComponentType type) const -> QString {
return p_->ComponentDirectories(type);
}
+auto GpgContext::KeyDBName() const -> QString { return p_->KeyDBName(); }
} // namespace GpgFrontend \ No newline at end of file
diff --git a/src/core/function/gpg/GpgContext.h b/src/core/function/gpg/GpgContext.h
index 4c683c0b..350c153e 100644
--- a/src/core/function/gpg/GpgContext.h
+++ b/src/core/function/gpg/GpgContext.h
@@ -71,6 +71,8 @@ class GPGFRONTEND_CORE_EXPORT GpgContext
auto DefaultContext() -> gpgme_ctx_t;
+ [[nodiscard]] auto KeyDBName() const -> QString;
+
[[nodiscard]] auto HomeDirectory() const -> QString;
[[nodiscard]] auto ComponentDirectory(GpgComponentType) const -> QString;
diff --git a/src/core/function/gpg/GpgFileOpera.cpp b/src/core/function/gpg/GpgFileOpera.cpp
index a3ad1ac5..334aae6f 100644
--- a/src/core/function/gpg/GpgFileOpera.cpp
+++ b/src/core/function/gpg/GpgFileOpera.cpp
@@ -66,10 +66,10 @@ void CreateArchiveHelper(const QString& in_path,
GpgFileOpera::GpgFileOpera(int channel)
: SingletonFunctionObject<GpgFileOpera>(channel) {}
-auto EncryptFileGpgDataImpl(GpgContext& ctx_, const KeyArgsList& keys,
+auto EncryptFileGpgDataImpl(GpgContext& ctx_, const GpgAbstractKeyPtrList& keys,
GpgData& data_in, bool ascii, GpgData& data_out,
const DataObjectPtr& data_object) -> GpgError {
- auto recipients = Convert2RawGpgMEKeyList(keys);
+ auto recipients = Convert2RawGpgMEKeyList(ctx_.GetChannel(), keys);
auto* ctx = ascii ? ctx_.DefaultContext() : ctx_.BinaryContext();
auto err = CheckGpgError(
@@ -79,7 +79,7 @@ auto EncryptFileGpgDataImpl(GpgContext& ctx_, const KeyArgsList& keys,
return err;
}
-auto EncryptFileImpl(GpgContext& ctx_, const KeyArgsList& keys,
+auto EncryptFileImpl(GpgContext& ctx_, const GpgAbstractKeyPtrList& keys,
const QString& in_path, bool ascii,
const QString& out_path,
const DataObjectPtr& data_object) -> GpgError {
@@ -90,8 +90,9 @@ auto EncryptFileImpl(GpgContext& ctx_, const KeyArgsList& keys,
data_object);
}
-void GpgFileOpera::EncryptFile(const KeyArgsList& keys, const QString& in_path,
- bool ascii, const QString& out_path,
+void GpgFileOpera::EncryptFile(const GpgAbstractKeyPtrList& keys,
+ const QString& in_path, bool ascii,
+ const QString& out_path,
const GpgOperationCallback& cb) {
RunGpgOperaAsync(
[=](const DataObjectPtr& data_object) {
@@ -102,7 +103,7 @@ void GpgFileOpera::EncryptFile(const KeyArgsList& keys, const QString& in_path,
}
auto GpgFileOpera::EncryptFileSync(
- const KeyArgsList& keys, const QString& in_path, bool ascii,
+ const GpgAbstractKeyPtrList& keys, const QString& in_path, bool ascii,
const QString& out_path) -> std::tuple<GpgError, DataObjectPtr> {
return RunGpgOperaSync(
[=](const DataObjectPtr& data_object) {
@@ -112,7 +113,7 @@ auto GpgFileOpera::EncryptFileSync(
"gpgme_op_encrypt", "2.1.0");
}
-void GpgFileOpera::EncryptDirectory(const KeyArgsList& keys,
+void GpgFileOpera::EncryptDirectory(const GpgAbstractKeyPtrList& keys,
const QString& in_path, bool ascii,
const QString& out_path,
const GpgOperationCallback& cb) {
@@ -186,8 +187,8 @@ void GpgFileOpera::DecryptArchive(const QString& in_path,
}
auto SignFileGpgDataImpl(GpgContext& ctx_, GpgBasicOperator& basic_opera_,
- const KeyArgsList& keys, GpgData& data_in, bool ascii,
- GpgData& data_out,
+ const GpgAbstractKeyPtrList& keys, GpgData& data_in,
+ bool ascii, GpgData& data_out,
const DataObjectPtr& data_object) -> GpgError {
GpgError err;
@@ -205,8 +206,8 @@ auto SignFileGpgDataImpl(GpgContext& ctx_, GpgBasicOperator& basic_opera_,
}
auto SignFileImpl(GpgContext& ctx_, GpgBasicOperator& basic_opera_,
- const KeyArgsList& keys, const QString& in_path, bool ascii,
- const QString& out_path,
+ const GpgAbstractKeyPtrList& keys, const QString& in_path,
+ bool ascii, const QString& out_path,
const DataObjectPtr& data_object) -> GpgError {
GpgData data_in(in_path, true);
GpgData data_out(out_path, false);
@@ -215,8 +216,9 @@ auto SignFileImpl(GpgContext& ctx_, GpgBasicOperator& basic_opera_,
data_object);
}
-void GpgFileOpera::SignFile(const KeyArgsList& keys, const QString& in_path,
- bool ascii, const QString& out_path,
+void GpgFileOpera::SignFile(const GpgAbstractKeyPtrList& keys,
+ const QString& in_path, bool ascii,
+ const QString& out_path,
const GpgOperationCallback& cb) {
RunGpgOperaAsync(
[=](const DataObjectPtr& data_object) {
@@ -226,9 +228,9 @@ void GpgFileOpera::SignFile(const KeyArgsList& keys, const QString& in_path,
cb, "gpgme_op_sign", "2.1.0");
}
-auto GpgFileOpera::SignFileSync(const KeyArgsList& keys, const QString& in_path,
- bool ascii, const QString& out_path)
- -> std::tuple<GpgError, DataObjectPtr> {
+auto GpgFileOpera::SignFileSync(
+ const GpgAbstractKeyPtrList& keys, const QString& in_path, bool ascii,
+ const QString& out_path) -> std::tuple<GpgError, DataObjectPtr> {
return RunGpgOperaSync(
[=](const DataObjectPtr& data_object) {
return SignFileImpl(ctx_, basic_opera_, keys, in_path, ascii, out_path,
@@ -282,12 +284,12 @@ auto GpgFileOpera::VerifyFileSync(const QString& data_path,
auto EncryptSignFileGpgDataImpl(GpgContext& ctx_,
GpgBasicOperator& basic_opera_,
- const KeyArgsList& keys,
- const KeyArgsList& signer_keys,
+ const GpgAbstractKeyPtrList& keys,
+ const GpgAbstractKeyPtrList& signer_keys,
GpgData& data_in, bool ascii, GpgData& data_out,
const DataObjectPtr& data_object) -> GpgError {
GpgError err;
- auto recipients = Convert2RawGpgMEKeyList(keys);
+ auto recipients = Convert2RawGpgMEKeyList(ctx_.GetChannel(), keys);
basic_opera_.SetSigners(signer_keys, ascii);
@@ -304,9 +306,10 @@ auto EncryptSignFileGpgDataImpl(GpgContext& ctx_,
}
auto EncryptSignFileImpl(GpgContext& ctx_, GpgBasicOperator& basic_opera_,
- const KeyArgsList& keys,
- const KeyArgsList& signer_keys, const QString& in_path,
- bool ascii, const QString& out_path,
+ const GpgAbstractKeyPtrList& keys,
+ const GpgAbstractKeyPtrList& signer_keys,
+ const QString& in_path, bool ascii,
+ const QString& out_path,
const DataObjectPtr& data_object) -> GpgError {
GpgData data_in(in_path, true);
GpgData data_out(out_path, false);
@@ -315,8 +318,8 @@ auto EncryptSignFileImpl(GpgContext& ctx_, GpgBasicOperator& basic_opera_,
data_in, ascii, data_out, data_object);
}
-void GpgFileOpera::EncryptSignFile(const KeyArgsList& keys,
- const KeyArgsList& signer_keys,
+void GpgFileOpera::EncryptSignFile(const GpgAbstractKeyPtrList& keys,
+ const GpgAbstractKeyPtrList& signer_keys,
const QString& in_path, bool ascii,
const QString& out_path,
const GpgOperationCallback& cb) {
@@ -329,7 +332,7 @@ void GpgFileOpera::EncryptSignFile(const KeyArgsList& keys,
}
auto GpgFileOpera::EncryptSignFileSync(
- const KeyArgsList& keys, const KeyArgsList& signer_keys,
+ const GpgAbstractKeyPtrList& keys, const GpgAbstractKeyPtrList& signer_keys,
const QString& in_path, bool ascii,
const QString& out_path) -> std::tuple<GpgError, DataObjectPtr> {
return RunGpgOperaSync(
@@ -340,11 +343,10 @@ auto GpgFileOpera::EncryptSignFileSync(
"gpgme_op_encrypt_sign", "2.1.0");
}
-void GpgFileOpera::EncryptSignDirectory(const KeyArgsList& keys,
- const KeyArgsList& signer_keys,
- const QString& in_path, bool ascii,
- const QString& out_path,
- const GpgOperationCallback& cb) {
+void GpgFileOpera::EncryptSignDirectory(
+ const GpgAbstractKeyPtrList& keys, const GpgAbstractKeyPtrList& signer_keys,
+ const QString& in_path, bool ascii, const QString& out_path,
+ const GpgOperationCallback& cb) {
auto ex = CreateStandardGFDataExchanger();
RunGpgOperaAsync(
diff --git a/src/core/function/gpg/GpgFileOpera.h b/src/core/function/gpg/GpgFileOpera.h
index 5119bb36..4cbe70d2 100644
--- a/src/core/function/gpg/GpgFileOpera.h
+++ b/src/core/function/gpg/GpgFileOpera.h
@@ -61,8 +61,9 @@ class GPGFRONTEND_CORE_EXPORT GpgFileOpera
* @param channel Channel in context
* @return unsigned int error code
*/
- void EncryptFile(const KeyArgsList& keys, const QString& in_path, bool ascii,
- const QString& out_path, const GpgOperationCallback& cb);
+ void EncryptFile(const GpgAbstractKeyPtrList& keys, const QString& in_path,
+ bool ascii, const QString& out_path,
+ const GpgOperationCallback& cb);
/**
* @brief
@@ -73,9 +74,9 @@ class GPGFRONTEND_CORE_EXPORT GpgFileOpera
* @param out_path
* @return std::tuple<GpgError, DataObjectPtr>
*/
- auto EncryptFileSync(const KeyArgsList& keys, const QString& in_path,
- bool ascii, const QString& out_path)
- -> std::tuple<GpgError, DataObjectPtr>;
+ auto EncryptFileSync(
+ const GpgAbstractKeyPtrList& keys, const QString& in_path, bool ascii,
+ const QString& out_path) -> std::tuple<GpgError, DataObjectPtr>;
/**
* @brief
@@ -86,8 +87,9 @@ class GPGFRONTEND_CORE_EXPORT GpgFileOpera
* @param out_path
* @param cb
*/
- void EncryptDirectory(const KeyArgsList& keys, const QString& in_path,
- bool ascii, const QString& out_path,
+ void EncryptDirectory(const GpgAbstractKeyPtrList& keys,
+ const QString& in_path, bool ascii,
+ const QString& out_path,
const GpgOperationCallback& cb);
/**
@@ -180,8 +182,9 @@ class GPGFRONTEND_CORE_EXPORT GpgFileOpera
* @param channel
* @return GpgError
*/
- void SignFile(const KeyArgsList& keys, const QString& in_path, bool ascii,
- const QString& out_path, const GpgOperationCallback& cb);
+ void SignFile(const GpgAbstractKeyPtrList& keys, const QString& in_path,
+ bool ascii, const QString& out_path,
+ const GpgOperationCallback& cb);
/**
* @brief
@@ -192,8 +195,8 @@ class GPGFRONTEND_CORE_EXPORT GpgFileOpera
* @param out_path
* @return std::tuple<GpgError, DataObjectPtr>
*/
- auto SignFileSync(const KeyArgsList& keys, const QString& in_path, bool ascii,
- const QString& out_path)
+ auto SignFileSync(const GpgAbstractKeyPtrList& keys, const QString& in_path,
+ bool ascii, const QString& out_path)
-> std::tuple<GpgError, DataObjectPtr>;
/**
@@ -228,7 +231,8 @@ class GPGFRONTEND_CORE_EXPORT GpgFileOpera
* @param out_path
* @param cb
*/
- void EncryptSignFile(const KeyArgsList& keys, const KeyArgsList& signer_keys,
+ void EncryptSignFile(const GpgAbstractKeyPtrList& keys,
+ const GpgAbstractKeyPtrList& signer_keys,
const QString& in_path, bool ascii,
const QString& out_path, const GpgOperationCallback& cb);
@@ -241,10 +245,11 @@ class GPGFRONTEND_CORE_EXPORT GpgFileOpera
* @param ascii
* @param out_path
*/
- auto EncryptSignFileSync(
- const KeyArgsList& keys, const KeyArgsList& signer_keys,
- const QString& in_path, bool ascii,
- const QString& out_path) -> std::tuple<GpgError, DataObjectPtr>;
+ auto EncryptSignFileSync(const GpgAbstractKeyPtrList& keys,
+ const GpgAbstractKeyPtrList& signer_keys,
+ const QString& in_path, bool ascii,
+ const QString& out_path)
+ -> std::tuple<GpgError, DataObjectPtr>;
/**
* @brief
@@ -256,8 +261,8 @@ class GPGFRONTEND_CORE_EXPORT GpgFileOpera
* @param out_path
* @param cb
*/
- void EncryptSignDirectory(const KeyArgsList& keys,
- const KeyArgsList& signer_keys,
+ void EncryptSignDirectory(const GpgAbstractKeyPtrList& keys,
+ const GpgAbstractKeyPtrList& signer_keys,
const QString& in_path, bool ascii,
const QString& out_path,
const GpgOperationCallback& cb);
diff --git a/src/core/function/gpg/GpgKeyGetter.cpp b/src/core/function/gpg/GpgKeyGetter.cpp
index 14145f7f..86218a94 100644
--- a/src/core/function/gpg/GpgKeyGetter.cpp
+++ b/src/core/function/gpg/GpgKeyGetter.cpp
@@ -34,6 +34,7 @@
#include "core/GpgModel.h"
#include "core/function/gpg/GpgContext.h"
+#include "core/function/gpg/GpgKeyGroupGetter.h"
#include "core/utils/GpgUtils.h"
namespace GpgFrontend {
@@ -70,7 +71,13 @@ class GpgKeyGetter::Impl : public SingletonFunctionObject<GpgKeyGetter::Impl> {
gpgme_get_key(ctx_.DefaultContext(), fpr.toUtf8(), &p_key, 0);
if (p_key == nullptr)
LOG_W() << "GpgKeyGetter GetKey _p_key Null, fpr: " << fpr;
- return GpgKey(std::move(p_key));
+ return GpgKey(p_key);
+ }
+
+ auto GetPubkeyPtr(const QString& fpr, bool use_cache) -> GpgKeyPtr {
+ auto key = GetPubkey(fpr, use_cache);
+ if (!key.IsGood()) return nullptr;
+ return QSharedPointer<GpgKey>::create(key);
}
auto FetchKey() -> GpgKeyList {
@@ -89,19 +96,20 @@ class GpgKeyGetter::Impl : public SingletonFunctionObject<GpgKeyGetter::Impl> {
return keys_list;
}
- auto FetchGpgKeyList() -> GpgKeyList {
+ auto FetchGpgKeyList() -> GpgAbstractKeyPtrList {
if (keys_search_cache_.empty()) {
FlushKeyCache();
}
- auto keys_list = GpgKeyList{};
+ auto keys_list = GpgAbstractKeyPtrList{};
{
// get the lock
std::lock_guard<std::mutex> lock(keys_cache_mutex_);
for (const auto& key : keys_cache_) {
- keys_list.push_back(key);
+ keys_list.push_back(QSharedPointer<GpgKey>::create(key));
}
}
+
return keys_list;
}
@@ -163,9 +171,21 @@ class GpgKeyGetter::Impl : public SingletonFunctionObject<GpgKeyGetter::Impl> {
return keys_copy;
}
- auto GetGpgKeyTableModel() -> QSharedPointer<GpgKeyTableModel> {
- return SecureCreateQSharedObject<GpgKeyTableModel>(
- SingletonFunctionObject::GetChannel(), FetchGpgKeyList(), nullptr);
+ auto Fetch() -> QContainer<QSharedPointer<GpgKey>> {
+ auto keys = FetchKey();
+
+ auto ret = QContainer<QSharedPointer<GpgKey>>();
+ for (const auto& key : keys) {
+ ret.append(QSharedPointer<GpgKey>::create(key));
+ }
+ return ret;
+ }
+
+ auto GetKeyPtr(const QString& key_id,
+ bool use_cache) -> QSharedPointer<GpgKey> {
+ auto key = GetKey(key_id, use_cache);
+ if (!key.IsGood()) return nullptr;
+ return QSharedPointer<GpgKey>::create(key);
}
private:
@@ -229,10 +249,20 @@ auto GpgKeyGetter::GetKey(const QString& key_id, bool use_cache) -> GpgKey {
return p_->GetKey(key_id, use_cache);
}
+auto GpgKeyGetter::GetKeyPtr(const QString& key_id,
+ bool use_cache) -> QSharedPointer<GpgKey> {
+ return p_->GetKeyPtr(key_id, use_cache);
+}
+
auto GpgKeyGetter::GetPubkey(const QString& key_id, bool use_cache) -> GpgKey {
return p_->GetPubkey(key_id, use_cache);
}
+auto GpgKeyGetter::GetPubkeyPtr(const QString& key_id,
+ bool use_cache) -> GpgKeyPtr {
+ return p_->GetPubkeyPtr(key_id, use_cache);
+}
+
auto GpgKeyGetter::FlushKeyCache() -> bool { return p_->FlushKeyCache(); }
auto GpgKeyGetter::GetKeys(const KeyIdArgsList& ids) -> GpgKeyList {
@@ -245,8 +275,7 @@ auto GpgKeyGetter::GetKeysCopy(const GpgKeyList& keys) -> GpgKeyList {
auto GpgKeyGetter::FetchKey() -> GpgKeyList { return p_->FetchKey(); }
-auto GpgKeyGetter::GetGpgKeyTableModel() -> QSharedPointer<GpgKeyTableModel> {
- return p_->GetGpgKeyTableModel();
+auto GpgKeyGetter::Fetch() -> QContainer<QSharedPointer<GpgKey>> {
+ return p_->Fetch();
}
-
} // namespace GpgFrontend
diff --git a/src/core/function/gpg/GpgKeyGetter.h b/src/core/function/gpg/GpgKeyGetter.h
index 2ed34531..b266bf17 100644
--- a/src/core/function/gpg/GpgKeyGetter.h
+++ b/src/core/function/gpg/GpgKeyGetter.h
@@ -63,12 +63,14 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyGetter
auto GetKey(const QString& key_id, bool use_cache = true) -> GpgKey;
/**
- * @brief Get the Keys object
+ * @brief Get the Key Ptr object
*
- * @param ids
- * @return KeyListPtr
+ * @param key_id
+ * @param use_cache
+ * @return QSharedPointer<GpgKey>
*/
- auto GetKeys(const KeyIdArgsList& key_ids) -> GpgKeyList;
+ auto GetKeyPtr(const QString& key_id,
+ bool use_cache = true) -> QSharedPointer<GpgKey>;
/**
* @brief Get the Pubkey object
@@ -79,6 +81,15 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyGetter
auto GetPubkey(const QString& key_id, bool use_cache = true) -> GpgKey;
/**
+ * @brief Get the Pubkey Ptr object
+ *
+ * @param key_id
+ * @param use_cache
+ * @return GpgKeyPtr
+ */
+ auto GetPubkeyPtr(const QString& key_id, bool use_cache = true) -> GpgKeyPtr;
+
+ /**
* @brief Get all the keys by receiving a linked list
*
* @return KeyLinkListPtr
@@ -86,25 +97,33 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyGetter
auto FetchKey() -> GpgKeyList;
/**
+ * @brief
+ *
+ * @return QContainer<QSharedPointer<GpgKey>>
+ */
+ auto Fetch() -> QContainer<QSharedPointer<GpgKey>>;
+
+ /**
* @brief flush the keys in the cache
*
*/
auto FlushKeyCache() -> bool;
/**
- * @brief Get the Keys Copy object
+ * @brief Get the Keys object
*
- * @param keys
+ * @param ids
* @return KeyListPtr
*/
- auto GetKeysCopy(const GpgKeyList& keys) -> GpgKeyList;
+ auto GetKeys(const KeyIdArgsList& key_ids) -> GpgKeyList;
/**
- * @brief
+ * @brief Get the Keys Copy object
*
- * @return GpgKeyTableModel
+ * @param keys
+ * @return KeyListPtr
*/
- auto GetGpgKeyTableModel() -> QSharedPointer<GpgKeyTableModel>;
+ auto GetKeysCopy(const GpgKeyList& keys) -> GpgKeyList;
private:
class Impl;
diff --git a/src/core/function/gpg/GpgKeyGroupGetter.cpp b/src/core/function/gpg/GpgKeyGroupGetter.cpp
new file mode 100644
index 00000000..47878414
--- /dev/null
+++ b/src/core/function/gpg/GpgKeyGroupGetter.cpp
@@ -0,0 +1,311 @@
+/**
+ * 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 "GpgKeyGroupGetter.h"
+
+#include "core/function/CacheManager.h"
+#include "core/function/gpg/GpgAbstractKeyGetter.h"
+#include "core/struct/cache_object/KeyGroupsCO.h"
+#include "utils/GpgUtils.h"
+
+namespace GpgFrontend {
+
+GpgKeyGroupGetter::GpgKeyGroupGetter(int channel)
+ : SingletonFunctionObject<GpgKeyGroupGetter>(channel) {
+ fetch_key_groups();
+}
+
+auto GpgKeyGroupGetter::Fetch() -> QContainer<QSharedPointer<GpgKeyGroup>> {
+ QContainer<QSharedPointer<GpgKeyGroup>> ret;
+ for (const auto& node : key_groups_forest_) {
+ ret.push_back(node->key_group);
+ }
+ return ret;
+}
+
+void GpgKeyGroupGetter::Remove(const QString& id) {
+ if (id.isEmpty() || !key_groups_forest_.contains(id)) return;
+
+ auto target_node = key_groups_forest_.value(id);
+
+ for (const auto& node : key_groups_forest_) {
+ if (target_node == node) continue;
+ node->RemoveChildren(target_node.get());
+ }
+
+ key_groups_forest_.remove(id);
+ FlushCache();
+}
+
+void GpgKeyGroupGetter::fetch_key_groups() {
+ key_groups_forest_.clear();
+ auto key = QString("kgs:%1").arg(ctx_.KeyDBName());
+ auto json = cm_.LoadDurableCache(key);
+
+ auto key_groups = KeyGroupsCO(json.object());
+ if (key_groups.key_db_name != ctx_.KeyDBName()) return;
+
+ for (const auto& key_group : key_groups.key_groups) {
+ if (key_group.id.isEmpty()) continue;
+
+ LOG_D() << "load raw key group:" << key_group.id
+ << "key ids: " << key_group.key_ids;
+
+ key_groups_forest_.insert(
+ key_group.id,
+ QSharedPointer<GpgKeyGroupTreeNode>::create(GpgKeyGroup{key_group}));
+ }
+
+ build_gpg_key_group_tree();
+ check_all_key_groups();
+}
+
+void GpgKeyGroupGetter::persist_key_groups() {
+ auto key = QString("kgs:%1").arg(ctx_.KeyDBName());
+
+ KeyGroupsCO key_groups;
+ key_groups.key_db_name = ctx_.KeyDBName();
+
+ for (const auto& node : key_groups_forest_) {
+ if (node->key_group == nullptr) continue;
+ LOG_D() << "persist key group: " << node->key_group->ID()
+ << "key ids:" << node->key_group->KeyIds();
+ key_groups.key_groups.push_back(node->key_group->ToCacheObject());
+ }
+
+ cm_.SaveDurableCache(key, QJsonDocument{key_groups.ToJson()}, true);
+}
+
+auto GpgKeyGroupGetter::KeyGroup(const QString& id)
+ -> QSharedPointer<GpgKeyGroup> {
+ if (!key_groups_forest_.contains(id)) return nullptr;
+ return key_groups_forest_.value(id)->key_group;
+}
+
+void GpgKeyGroupGetter::check_key_group(
+ const QSharedPointer<GpgKeyGroup>& key_group) {
+ if (key_group == nullptr || key_group->IsDisabled()) return;
+
+ for (const auto& key_id : key_group->KeyIds()) {
+ LOG_D() << "check" << key_id << "of" << key_group->UID();
+
+ if (IsKeyGroupID(key_id) || key_id == key_group->ID()) {
+ if (!key_groups_forest_.contains(key_id)) {
+ key_group->SetDisabled(true);
+ return;
+ }
+
+ auto s_node = key_groups_forest_.value(key_id, nullptr);
+ check_key_group(s_node->key_group);
+
+ if (s_node->key_group->IsDisabled()) {
+ key_group->SetDisabled(true);
+ return;
+ }
+
+ } else {
+ auto key = GpgKeyGetter::GetInstance(GetChannel()).GetKeyPtr(key_id);
+ if (key == nullptr || !key->IsHasEncrCap()) {
+ key_group->SetDisabled(true);
+ return;
+ }
+ }
+ }
+}
+
+void GpgKeyGroupGetter::check_all_key_groups() {
+ for (const auto& node : key_groups_forest_) {
+ node->key_group->SetDisabled(false);
+ }
+
+ for (const auto& node : key_groups_forest_) {
+ auto key_group = node->key_group;
+ check_key_group(key_group);
+
+ LOG_D() << "key group" << key_group->ID() << "ids: " << key_group->KeyIds()
+ << "status: " << key_group->IsDisabled();
+ }
+}
+
+auto GpgKeyGroupGetter::FlushCache() -> bool {
+ check_all_key_groups();
+ persist_key_groups();
+ return true;
+}
+
+void GpgKeyGroupGetter::build_gpg_key_group_tree() {
+ for (const auto& node : key_groups_forest_) {
+ LOG_D() << "load key group: " << node->key_group->ID()
+ << "ids: " << node->key_group->KeyIds();
+ for (const auto& key_id : node->key_group->KeyIds()) {
+ if (!IsKeyGroupID(key_id) || !key_groups_forest_.contains(key_id)) {
+ continue;
+ }
+
+ auto target = key_groups_forest_.value(key_id);
+ if (!node->AddChildren(target.get())) {
+ LOG_E() << "found ring in key groups relations, key group:"
+ << node->key_group->ID() << "child: " << key_id;
+ continue;
+ }
+ }
+ node->Apply();
+ }
+}
+
+void GpgKeyGroupGetter::AddKeyGroup(const GpgKeyGroup& key_group) {
+ auto node = QSharedPointer<GpgKeyGroupTreeNode>::create(key_group);
+
+ key_groups_forest_.insert(node->key_group->ID(), node);
+ LOG_D() << "add new key group" << key_group.ID()
+ << "key ids:" << key_group.KeyIds();
+
+ for (const auto& key_id : node->key_group->KeyIds()) {
+ if (!IsKeyGroupID(key_id) || !key_groups_forest_.contains(key_id)) continue;
+
+ auto target = key_groups_forest_.value(key_id);
+ node->AddChildren(target.get());
+ }
+ node->Apply();
+ FlushCache();
+}
+
+auto GpgKeyGroupGetter::AddKey2KeyGroup(const QString& id,
+ const GpgAbstractKeyPtr& key) -> bool {
+ if (!key_groups_forest_.contains(id)) return false;
+ auto key_group = key_groups_forest_.value(id);
+
+ if (key->KeyType() != GpgAbstractKeyType::kGPG_KEYGROUP) {
+ auto ret = key_group->AddNonKeyGroupKey(key);
+ FlushCache();
+ return ret;
+ }
+
+ if (!key_groups_forest_.contains(key->ID())) {
+ LOG_E() << "try adding invalid key group id:" << key->ID();
+ return false;
+ }
+
+ auto s_key_group = key_groups_forest_.value(key->ID());
+ auto ret = key_group->AddChildren(s_key_group.get());
+ FlushCache();
+ return ret;
+}
+
+auto GpgKeyGroupGetter::RemoveKeyFromKeyGroup(const QString& id,
+ const QString& key_id) -> bool {
+ if (!key_groups_forest_.contains(id)) return false;
+ auto key_group = key_groups_forest_.value(id);
+
+ if (!IsKeyGroupID(key_id)) {
+ LOG_D() << "removing non key group id" << key_id << "form key group" << id;
+ key_group->RemoveNonKeyGroupKey(key_id);
+ FlushCache();
+ return true;
+ }
+
+ if (!key_groups_forest_.contains(key_id)) {
+ LOG_E() << "try remove invalid key group id:" << key_id;
+ return false;
+ }
+
+ auto s_key_group = key_groups_forest_.value(key_id);
+ auto ret = key_group->RemoveChildren(s_key_group.get());
+ FlushCache();
+ return ret;
+}
+
+GpgKeyGroupTreeNode::GpgKeyGroupTreeNode(GpgKeyGroup kg)
+ : key_group(QSharedPointer<GpgKeyGroup>::create(kg)) {
+ for (const auto& key_id : key_group->KeyIds()) {
+ if (!IsKeyGroupID(key_id)) {
+ non_key_group_ids.push_back(key_id);
+ }
+ }
+}
+
+void GpgKeyGroupTreeNode::Apply() {
+ QStringList key_ids;
+ for (const auto& child : children) {
+ key_ids.push_back(child->key_group->ID());
+ }
+
+ for (const auto& key_id : non_key_group_ids) {
+ key_ids.push_back(key_id);
+ }
+
+ key_group->SetKeyIds(key_ids);
+}
+
+auto GpgKeyGroupTreeNode::AddNonKeyGroupKey(const GpgAbstractKeyPtr& key)
+ -> bool {
+ if (key->KeyType() == GpgAbstractKeyType::kGPG_KEYGROUP ||
+ non_key_group_ids.contains(key->ID())) {
+ return false;
+ }
+ non_key_group_ids.push_back(key->ID());
+ non_key_group_ids.removeDuplicates();
+ Apply();
+ return true;
+}
+
+auto GpgKeyGroupTreeNode::HasAncestor(GpgKeyGroupTreeNode* target) -> bool {
+ for (const auto& parent : parents) {
+ if (parent == target || parent->HasAncestor(target)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+auto GpgKeyGroupTreeNode::AddChildren(GpgKeyGroupTreeNode* target) -> bool {
+ if (target == this || children.contains(target) || HasAncestor(target)) {
+ return false;
+ }
+
+ children.push_back(target);
+ target->parents.push_back(this);
+ Apply();
+ return true;
+}
+
+auto GpgKeyGroupTreeNode::RemoveChildren(GpgKeyGroupTreeNode* target) -> bool {
+ if (!children.contains(target)) return false;
+ children.removeAll(target);
+ target->parents.removeAll(this);
+ Apply();
+ return true;
+}
+
+auto GpgKeyGroupTreeNode::RemoveNonKeyGroupKey(const QString& key) -> bool {
+ if (!non_key_group_ids.contains(key)) return false;
+ non_key_group_ids.removeAll(key);
+ Apply();
+ return true;
+}
+} // namespace GpgFrontend \ No newline at end of file
diff --git a/src/core/function/gpg/GpgKeyGroupGetter.h b/src/core/function/gpg/GpgKeyGroupGetter.h
new file mode 100644
index 00000000..9eabccde
--- /dev/null
+++ b/src/core/function/gpg/GpgKeyGroupGetter.h
@@ -0,0 +1,215 @@
+/**
+ * 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/CacheManager.h"
+#include "core/function/basic/GpgFunctionObject.h"
+#include "core/function/gpg/GpgContext.h"
+#include "core/model/GpgKeyGroup.h"
+
+namespace GpgFrontend {
+
+struct GpgKeyGroupTreeNode {
+ QContainer<GpgKeyGroupTreeNode*> parents;
+ QContainer<GpgKeyGroupTreeNode*> children;
+ QSharedPointer<GpgKeyGroup> key_group;
+
+ // over take
+ QStringList non_key_group_ids;
+
+ /**
+ * @brief Construct a new Gpg Key Group Tree Node object
+ *
+ */
+ GpgKeyGroupTreeNode() = default;
+
+ /**
+ * @brief Construct a new Gpg Key Group Tree Node object
+ *
+ * @param kg
+ */
+ explicit GpgKeyGroupTreeNode(GpgKeyGroup kg);
+
+ /**
+ * @brief
+ *
+ */
+ void Apply();
+
+ /**
+ * @brief
+ *
+ * @param key
+ * @return true
+ * @return false
+ */
+ auto AddNonKeyGroupKey(const GpgAbstractKeyPtr& key) -> bool;
+
+ /**
+ * @brief
+ *
+ * @param target
+ * @return true
+ * @return false
+ */
+ auto HasAncestor(GpgKeyGroupTreeNode* target) -> bool;
+
+ /**
+ * @brief
+ *
+ * @param target
+ * @return true
+ * @return false
+ */
+ auto AddChildren(GpgKeyGroupTreeNode* target) -> bool;
+
+ /**
+ * @brief
+ *
+ * @param target
+ * @return true
+ * @return false
+ */
+ auto RemoveChildren(GpgKeyGroupTreeNode* target) -> bool;
+
+ /**
+ * @brief
+ *
+ * @param key
+ * @return true
+ * @return false
+ */
+ auto RemoveNonKeyGroupKey(const QString& key) -> bool;
+};
+
+class GPGFRONTEND_CORE_EXPORT GpgKeyGroupGetter
+ : public SingletonFunctionObject<GpgKeyGroupGetter> {
+ public:
+ /**
+ * @brief GpgKeyGroupGetter constructor
+ *
+ * @param channel channel
+ */
+ explicit GpgKeyGroupGetter(
+ int channel = SingletonFunctionObject::GetDefaultChannel());
+
+ /**
+ * @brief
+ *
+ * @return QContainer<GpgKeyGroup>
+ */
+ auto Fetch() -> QContainer<QSharedPointer<GpgKeyGroup>>;
+
+ /**
+ * @brief
+ *
+ * @return QContainer<GpgKeyGroup>
+ */
+ auto FlushCache() -> bool;
+
+ /**
+ * @brief
+ *
+ */
+ void AddKeyGroup(const GpgKeyGroup&);
+
+ /**
+ * @brief
+ *
+ * @param id
+ * @param key
+ * @return true
+ * @return false
+ */
+ auto AddKey2KeyGroup(const QString& id, const GpgAbstractKeyPtr& key) -> bool;
+
+ /**
+ * @brief
+ *
+ * @param id
+ * @param key
+ * @return true
+ * @return false
+ */
+ auto RemoveKeyFromKeyGroup(const QString& id, const QString& key_id) -> bool;
+
+ /**
+ * @brief
+ *
+ * @param id
+ */
+ void Remove(const QString& id);
+
+ /**
+ * @brief
+ *
+ * @param id
+ */
+ auto KeyGroup(const QString& id) -> QSharedPointer<GpgKeyGroup>;
+
+ private:
+ GpgContext& ctx_ =
+ GpgContext::GetInstance(SingletonFunctionObject::GetChannel());
+ CacheManager& cm_ =
+ CacheManager::GetInstance(SingletonFunctionObject::GetChannel());
+
+ QMap<QString, QSharedPointer<GpgKeyGroupTreeNode>> key_groups_forest_;
+
+ /**
+ * @brief
+ *
+ */
+ void fetch_key_groups();
+
+ /**
+ * @brief
+ *
+ */
+ void persist_key_groups();
+
+ /**
+ * @brief
+ *
+ */
+ void check_all_key_groups();
+
+ /**
+ * @brief
+ *
+ */
+ void check_key_group(const QSharedPointer<GpgKeyGroup>&);
+
+ /**
+ * @brief
+ *
+ */
+ void build_gpg_key_group_tree();
+};
+
+} // namespace GpgFrontend
diff --git a/src/core/function/gpg/GpgKeyImportExporter.cpp b/src/core/function/gpg/GpgKeyImportExporter.cpp
index 60c06995..08e67748 100644
--- a/src/core/function/gpg/GpgKeyImportExporter.cpp
+++ b/src/core/function/gpg/GpgKeyImportExporter.cpp
@@ -72,21 +72,18 @@ auto GpgKeyImportExporter::ImportKey(const GFBuffer& in_buffer)
* @param outBuffer output byte array
* @return if success
*/
-auto GpgKeyImportExporter::ExportKey(const GpgKey& key, bool secret, bool ascii,
- bool shortest, bool ssh_mode) const
- -> std::tuple<GpgError, GFBuffer> {
- if (!key.IsGood()) return {GPG_ERR_CANCELED, {}};
+auto GpgKeyImportExporter::ExportKey(
+ const GpgAbstractKeyPtr& key, bool secret, bool ascii, bool shortest,
+ bool ssh_mode) const -> std::tuple<GpgError, GFBuffer> {
+ if (key == nullptr) return {GPG_ERR_CANCELED, {}};
int mode = 0;
if (secret) mode |= GPGME_EXPORT_MODE_SECRET;
if (shortest) mode |= GPGME_EXPORT_MODE_MINIMAL;
if (ssh_mode) mode |= GPGME_EXPORT_MODE_SSH;
- QContainer<gpgme_key_t> keys_array;
-
- // Last entry data_in array has to be nullptr
- keys_array.push_back(static_cast<gpgme_key_t>(key));
- keys_array.push_back(nullptr);
+ QContainer<gpgme_key_t> keys_array =
+ Convert2RawGpgMEKeyList(GetChannel(), {key});
GpgData data_out;
auto* ctx = ascii ? ctx_.DefaultContext() : ctx_.BinaryContext();
@@ -102,8 +99,9 @@ auto GpgKeyImportExporter::ExportKey(const GpgKey& key, bool secret, bool ascii,
* @param outBuffer output byte array
* @return if success
*/
-void GpgKeyImportExporter::ExportKeys(const KeyArgsList& keys, bool secret,
- bool ascii, bool shortest, bool ssh_mode,
+void GpgKeyImportExporter::ExportKeys(const GpgAbstractKeyPtrList& keys,
+ bool secret, bool ascii, bool shortest,
+ bool ssh_mode,
const GpgOperationCallback& cb) const {
RunGpgOperaAsync(
[=](const DataObjectPtr& data_object) -> GpgError {
@@ -114,7 +112,7 @@ void GpgKeyImportExporter::ExportKeys(const KeyArgsList& keys, bool secret,
if (shortest) mode |= GPGME_EXPORT_MODE_MINIMAL;
if (ssh_mode) mode |= GPGME_EXPORT_MODE_SSH;
- QContainer<gpgme_key_t> keys_array(keys.begin(), keys.end());
+ auto keys_array = Convert2RawGpgMEKeyList(GetChannel(), keys);
// Last entry data_in array has to be nullptr
keys_array.push_back(nullptr);
@@ -136,15 +134,15 @@ void GpgKeyImportExporter::ExportKeys(const KeyArgsList& keys, bool secret,
* @param outBuffer output byte array
* @return if success
*/
-void GpgKeyImportExporter::ExportAllKeys(const KeyArgsList& keys, bool secret,
- bool ascii,
+void GpgKeyImportExporter::ExportAllKeys(const GpgAbstractKeyPtrList& keys,
+ bool secret, bool ascii,
const GpgOperationCallback& cb) const {
RunGpgOperaAsync(
[=](const DataObjectPtr& data_object) -> GpgError {
if (keys.empty()) return GPG_ERR_CANCELED;
int mode = 0;
- QContainer<gpgme_key_t> keys_array(keys.begin(), keys.end());
+ auto keys_array = Convert2RawGpgMEKeyList(GetChannel(), keys);
// Last entry data_in array has to be nullptr
keys_array.push_back(nullptr);
diff --git a/src/core/function/gpg/GpgKeyImportExporter.h b/src/core/function/gpg/GpgKeyImportExporter.h
index cc7b3f6f..4f938cb7 100644
--- a/src/core/function/gpg/GpgKeyImportExporter.h
+++ b/src/core/function/gpg/GpgKeyImportExporter.h
@@ -68,9 +68,9 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyImportExporter
* @param ascii
* @return std::tuple<GpgError, GFBuffer>
*/
- [[nodiscard]] auto ExportKey(const GpgKey& key, bool secret, bool ascii,
- bool shortest, bool ssh_mode = false) const
- -> std::tuple<GpgError, GFBuffer>;
+ [[nodiscard]] auto ExportKey(
+ const GpgAbstractKeyPtr& key, bool secret, bool ascii, bool shortest,
+ bool ssh_mode = false) const -> std::tuple<GpgError, GFBuffer>;
/**
* @brief
@@ -91,7 +91,7 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyImportExporter
* @return true
* @return false
*/
- void ExportKeys(const KeyArgsList& keys, bool secret, bool ascii,
+ void ExportKeys(const GpgAbstractKeyPtrList& keys, bool secret, bool ascii,
bool shortest, bool ssh_mode,
const GpgOperationCallback& cb) const;
@@ -103,7 +103,7 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyImportExporter
* @param ascii
* @param cb
*/
- void ExportAllKeys(const KeyArgsList& keys, bool secret, bool ascii,
+ void ExportAllKeys(const GpgAbstractKeyPtrList& keys, bool secret, bool ascii,
const GpgOperationCallback& cb) const;
private:
diff --git a/src/core/function/gpg/GpgKeyManager.cpp b/src/core/function/gpg/GpgKeyManager.cpp
index bd514cf3..a2c53975 100644
--- a/src/core/function/gpg/GpgKeyManager.cpp
+++ b/src/core/function/gpg/GpgKeyManager.cpp
@@ -39,7 +39,8 @@ namespace GpgFrontend {
GpgKeyManager::GpgKeyManager(int channel)
: SingletonFunctionObject<GpgKeyManager>(channel) {}
-auto GpgKeyManager::SignKey(const GpgKey& target, KeyArgsList& keys,
+auto GpgKeyManager::SignKey(const GpgKeyPtr& key,
+ const GpgAbstractKeyPtrList& keys,
const QString& uid,
const std::unique_ptr<QDateTime>& expires) -> bool {
GpgBasicOperator::GetInstance(GetChannel()).SetSigners(keys, true);
@@ -54,13 +55,13 @@ auto GpgKeyManager::SignKey(const GpgKey& target, KeyArgsList& keys,
}
auto err = CheckGpgError(
- gpgme_op_keysign(ctx_.DefaultContext(), static_cast<gpgme_key_t>(target),
+ gpgme_op_keysign(ctx_.DefaultContext(), static_cast<gpgme_key_t>(*key),
uid.toUtf8(), expires_time_t, flags));
return CheckGpgError(err) == GPG_ERR_NO_ERROR;
}
-auto GpgKeyManager::RevSign(const GpgKey& key,
+auto GpgKeyManager::RevSign(const GpgKeyPtr& key,
const SignIdArgsList& signature_id) -> bool {
auto& key_getter = GpgKeyGetter::GetInstance(GetChannel());
@@ -69,14 +70,14 @@ auto GpgKeyManager::RevSign(const GpgKey& key,
assert(signing_key.IsGood());
auto err = CheckGpgError(
- gpgme_op_revsig(ctx_.DefaultContext(), gpgme_key_t(key),
+ gpgme_op_revsig(ctx_.DefaultContext(), gpgme_key_t(*key),
gpgme_key_t(signing_key), sign_id.second.toUtf8(), 0));
if (CheckGpgError(err) != GPG_ERR_NO_ERROR) return false;
}
return true;
}
-auto GpgKeyManager::SetExpire(const GpgKey& key,
+auto GpgKeyManager::SetExpire(const GpgKeyPtr& key,
std::unique_ptr<GpgSubKey>& subkey,
std::unique_ptr<QDateTime>& expires) -> bool {
unsigned long expires_time = 0;
@@ -88,13 +89,13 @@ auto GpgKeyManager::SetExpire(const GpgKey& key,
if (subkey != nullptr) sub_fprs = subkey->Fingerprint().toUtf8();
auto err = CheckGpgError(gpgme_op_setexpire(ctx_.DefaultContext(),
- static_cast<gpgme_key_t>(key),
+ static_cast<gpgme_key_t>(*key),
expires_time, sub_fprs, 0));
return CheckGpgError(err) == GPG_ERR_NO_ERROR;
}
-auto GpgKeyManager::SetOwnerTrustLevel(const GpgKey& key,
+auto GpgKeyManager::SetOwnerTrustLevel(const GpgKeyPtr& key,
int trust_level) -> bool {
if (trust_level < 1 || trust_level > 5) {
FLOG_W("illegal owner trust level: %d", trust_level);
@@ -172,9 +173,10 @@ auto GpgKeyManager::SetOwnerTrustLevel(const GpgKey& key,
.DoInteract(key, next_state_handler, action_handler);
}
-auto GpgKeyManager::DeleteSubkey(const GpgKey& key, int subkey_index) -> bool {
+auto GpgKeyManager::DeleteSubkey(const GpgKeyPtr& key,
+ int subkey_index) -> bool {
if (subkey_index < 0 ||
- subkey_index >= static_cast<int>(key.SubKeys().size())) {
+ subkey_index >= static_cast<int>(key->SubKeys().size())) {
LOG_W() << "illegal subkey index: " << subkey_index;
return false;
}
@@ -246,7 +248,7 @@ auto GpgKeyManager::DeleteSubkey(const GpgKey& key, int subkey_index) -> bool {
return QString("");
};
- auto key_fpr = key.Fingerprint();
+ auto key_fpr = key->Fingerprint();
AutomatonHandelStruct handel_struct(key_fpr);
handel_struct.SetHandler(next_state_handler, action_handler);
@@ -256,11 +258,11 @@ auto GpgKeyManager::DeleteSubkey(const GpgKey& key, int subkey_index) -> bool {
.DoInteract(key, next_state_handler, action_handler);
}
-auto GpgKeyManager::RevokeSubkey(const GpgKey& key, int subkey_index,
+auto GpgKeyManager::RevokeSubkey(const GpgKeyPtr& key, int subkey_index,
int reason_code,
const QString& reason_text) -> bool {
if (subkey_index < 0 ||
- subkey_index >= static_cast<int>(key.SubKeys().size())) {
+ subkey_index >= static_cast<int>(key->SubKeys().size())) {
LOG_W() << "illegal subkey index: " << subkey_index;
return false;
}
@@ -369,7 +371,7 @@ auto GpgKeyManager::RevokeSubkey(const GpgKey& key, int subkey_index,
return QString("");
};
- auto key_fpr = key.Fingerprint();
+ auto key_fpr = key->Fingerprint();
AutomatonHandelStruct handel_struct(key_fpr);
handel_struct.SetHandler(next_state_handler, action_handler);
diff --git a/src/core/function/gpg/GpgKeyManager.h b/src/core/function/gpg/GpgKeyManager.h
index 817179e1..ccf69b53 100644
--- a/src/core/function/gpg/GpgKeyManager.h
+++ b/src/core/function/gpg/GpgKeyManager.h
@@ -51,12 +51,13 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyManager
/**
* @brief Sign a key pair(actually a certain uid)
- * @param target target key pair
+ * @param key target key pair
* @param uid target
* @param expires expire date and time of the signature
* @return if successful
*/
- auto SignKey(const GpgKey& target, KeyArgsList& keys, const QString& uid,
+ auto SignKey(const GpgKeyPtr& key, const GpgAbstractKeyPtrList& keys,
+ const QString& uid,
const std::unique_ptr<QDateTime>& expires) -> bool;
/**
@@ -67,8 +68,8 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyManager
* @return true
* @return false
*/
- auto RevSign(const GpgFrontend::GpgKey& key,
- const GpgFrontend::SignIdArgsList& signature_id) -> bool;
+ auto RevSign(const GpgKeyPtr& key,
+ const SignIdArgsList& signature_id) -> bool;
/**
* @brief Set the Expire object
@@ -79,7 +80,7 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyManager
* @return true
* @return false
*/
- auto SetExpire(const GpgKey& key, std::unique_ptr<GpgSubKey>& subkey,
+ auto SetExpire(const GpgKeyPtr& key, std::unique_ptr<GpgSubKey>& subkey,
std::unique_ptr<QDateTime>& expires) -> bool;
/**
@@ -87,7 +88,7 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyManager
*
* @return
*/
- auto SetOwnerTrustLevel(const GpgKey& key, int trust_level) -> bool;
+ auto SetOwnerTrustLevel(const GpgKeyPtr& key, int trust_level) -> bool;
/**
* @brief
@@ -97,7 +98,7 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyManager
* @return true
* @return false
*/
- auto DeleteSubkey(const GpgKey& key, int subkey_index) -> bool;
+ auto DeleteSubkey(const GpgKeyPtr& key, int subkey_index) -> bool;
/**
* @brief
@@ -107,7 +108,7 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyManager
* @return true
* @return false
*/
- auto RevokeSubkey(const GpgKey& key, int subkey_index, int reason_code,
+ auto RevokeSubkey(const GpgKeyPtr& key, int subkey_index, int reason_code,
const QString& reason_text) -> bool;
private:
diff --git a/src/core/function/gpg/GpgKeyOpera.cpp b/src/core/function/gpg/GpgKeyOpera.cpp
index 3d9b8eda..3e4fe6d4 100644
--- a/src/core/function/gpg/GpgKeyOpera.cpp
+++ b/src/core/function/gpg/GpgKeyOpera.cpp
@@ -28,9 +28,8 @@
#include "GpgKeyOpera.h"
-#include "core/GpgModel.h"
#include "core/function/gpg/GpgCommandExecutor.h"
-#include "core/function/gpg/GpgKeyGetter.h"
+#include "core/function/gpg/GpgKeyGroupGetter.h"
#include "core/model/DataObject.h"
#include "core/model/GpgGenerateKeyResult.h"
#include "core/model/GpgKeyGenerateInfo.h"
@@ -49,17 +48,21 @@ GpgKeyOpera::GpgKeyOpera(int channel)
* Delete keys
* @param uidList key ids
*/
-void GpgKeyOpera::DeleteKeys(KeyIdArgsList key_ids) {
+void GpgKeyOpera::DeleteKeys(const GpgAbstractKeyPtrList& keys) {
GpgError err;
- for (const auto& tmp : key_ids) {
- auto key = GpgKeyGetter::GetInstance(GetChannel()).GetKey(tmp);
- if (key.IsGood()) {
+ for (const auto& key : keys) {
+ if (key->KeyType() == GpgAbstractKeyType::kGPG_KEY && key->IsGood()) {
+ auto k = qSharedPointerDynamicCast<GpgKey>(key);
err = CheckGpgError(gpgme_op_delete_ext(
- ctx_.DefaultContext(), static_cast<gpgme_key_t>(key),
+ ctx_.DefaultContext(), static_cast<gpgme_key_t>(*k),
GPGME_DELETE_ALLOW_SECRET | GPGME_DELETE_FORCE));
assert(gpg_err_code(err) == GPG_ERR_NO_ERROR);
} else {
- LOG_W() << "GpgKeyOpera DeleteKeys get key failed: " << tmp;
+ LOG_W() << "GpgKeyOpera DeleteKeys get key failed: " << key->ID();
+ }
+
+ if (key->KeyType() == GpgAbstractKeyType::kGPG_KEYGROUP) {
+ GpgKeyGroupGetter::GetInstance(GetChannel()).Remove(key->ID());
}
}
}
@@ -72,7 +75,7 @@ void GpgKeyOpera::DeleteKeys(KeyIdArgsList key_ids) {
* @param expires date and time
* @return if successful
*/
-auto GpgKeyOpera::SetExpire(const GpgKey& key, const SubkeyId& subkey_fpr,
+auto GpgKeyOpera::SetExpire(const GpgKeyPtr& key, const SubkeyId& subkey_fpr,
std::unique_ptr<QDateTime>& expires) -> GpgError {
unsigned long expires_time = 0;
@@ -81,15 +84,15 @@ auto GpgKeyOpera::SetExpire(const GpgKey& key, const SubkeyId& subkey_fpr,
}
GpgError err;
- if (key.Fingerprint() == subkey_fpr || subkey_fpr.isEmpty()) {
- err =
- gpgme_op_setexpire(ctx_.DefaultContext(), static_cast<gpgme_key_t>(key),
- expires_time, nullptr, 0);
+ if (key->Fingerprint() == subkey_fpr || subkey_fpr.isEmpty()) {
+ err = gpgme_op_setexpire(ctx_.DefaultContext(),
+ static_cast<gpgme_key_t>(*key), expires_time,
+ nullptr, 0);
assert(gpg_err_code(err) == GPG_ERR_NO_ERROR);
} else {
- err =
- gpgme_op_setexpire(ctx_.DefaultContext(), static_cast<gpgme_key_t>(key),
- expires_time, subkey_fpr.toUtf8(), 0);
+ err = gpgme_op_setexpire(ctx_.DefaultContext(),
+ static_cast<gpgme_key_t>(*key), expires_time,
+ subkey_fpr.toUtf8(), 0);
assert(gpg_err_code(err) == GPG_ERR_NO_ERROR);
}
@@ -102,7 +105,7 @@ auto GpgKeyOpera::SetExpire(const GpgKey& key, const SubkeyId& subkey_fpr,
* @param outputFileName out file name(path)
* @return the process doing this job
*/
-void GpgKeyOpera::GenerateRevokeCert(const GpgKey& key,
+void GpgKeyOpera::GenerateRevokeCert(const GpgKeyPtr& key,
const QString& output_path,
int revocation_reason_code,
const QString& revocation_reason_text) {
@@ -119,7 +122,7 @@ void GpgKeyOpera::GenerateRevokeCert(const GpgKey& key,
GpgCommandExecutor::ExecuteSync(
{app_path,
QStringList{"--command-fd", "0", "--status-fd", "1", "--no-tty", "-o",
- output_path, "--gen-revoke", key.Fingerprint()},
+ output_path, "--gen-revoke", key->Fingerprint()},
[=](int exit_code, const QString& p_out, const QString& p_err) {
if (exit_code != 0) {
LOG_W() << "gnupg gen revoke execute error, process stderr: "
@@ -226,7 +229,7 @@ auto GpgKeyOpera::GenerateKeySync(const QSharedPointer<KeyGenerateInfo>& params)
"gpgme_op_createkey", "2.1.0");
}
-auto GenerateSubKeyImpl(GpgContext& ctx, const GpgKey& key,
+auto GenerateSubKeyImpl(GpgContext& ctx, const GpgKeyPtr& key,
const QSharedPointer<KeyGenerateInfo>& params,
const DataObjectPtr& data_object) -> GpgError {
if (params == nullptr || params->GetAlgo() == KeyGenerateInfo::kNoneAlgo ||
@@ -246,11 +249,12 @@ auto GenerateSubKeyImpl(GpgContext& ctx, const GpgKey& key,
if (params->IsNonExpired()) flags |= GPGME_CREATE_NOEXPIRE;
if (params->IsNoPassPhrase()) flags |= GPGME_CREATE_NOPASSWD;
- LOG_D() << "subkey generation args: " << key.ID() << algo << expires << flags;
+ LOG_D() << "subkey generation args: " << key->ID() << algo << expires
+ << flags;
- auto err =
- gpgme_op_createsubkey(ctx.DefaultContext(), static_cast<gpgme_key_t>(key),
- algo.toLatin1(), 0, expires, flags);
+ auto err = gpgme_op_createsubkey(ctx.DefaultContext(),
+ static_cast<gpgme_key_t>(*key),
+ algo.toLatin1(), 0, expires, flags);
if (CheckGpgError(err) != GPG_ERR_NO_ERROR) {
data_object->Swap({GpgGenerateKeyResult{}});
return err;
@@ -261,7 +265,7 @@ auto GenerateSubKeyImpl(GpgContext& ctx, const GpgKey& key,
return CheckGpgError(err);
}
-void GpgKeyOpera::GenerateSubkey(const GpgKey& key,
+void GpgKeyOpera::GenerateSubkey(const GpgKeyPtr& key,
const QSharedPointer<KeyGenerateInfo>& params,
const GpgOperationCallback& callback) {
RunGpgOperaAsync(
@@ -272,7 +276,7 @@ void GpgKeyOpera::GenerateSubkey(const GpgKey& key,
}
auto GpgKeyOpera::GenerateSubkeySync(
- const GpgKey& key, const QSharedPointer<KeyGenerateInfo>& params)
+ const GpgKeyPtr& key, const QSharedPointer<KeyGenerateInfo>& params)
-> std::tuple<GpgError, DataObjectPtr> {
return RunGpgOperaSync(
[=](const DataObjectPtr& data_object) -> GpgError {
@@ -291,8 +295,8 @@ auto GenerateKeyWithSubkeyImpl(GpgContext& ctx, GpgKeyGetter& key_getter,
if (!data_object->Check<GpgGenerateKeyResult>()) return GPG_ERR_CANCELED;
auto result = ExtractParams<GpgGenerateKeyResult>(data_object, 0);
- auto key = key_getter.GetKey(result.GetFingerprint());
- if (!key.IsGood()) {
+ auto key = key_getter.GetKeyPtr(result.GetFingerprint());
+ if (key == nullptr) {
LOG_W() << "cannot get key which has been generated, fpr: "
<< result.GetFingerprint();
return GPG_ERR_CANCELED;
@@ -332,18 +336,18 @@ auto GpgKeyOpera::GenerateKeyWithSubkeySync(
"gpgme_op_createkey&gpgme_op_createsubkey", "2.1.0");
}
-void GpgKeyOpera::ModifyPassword(const GpgKey& key,
+void GpgKeyOpera::ModifyPassword(const GpgKeyPtr& key,
const GpgOperationCallback& callback) {
RunGpgOperaAsync(
[&key, &ctx = ctx_](const DataObjectPtr&) -> GpgError {
return gpgme_op_passwd(ctx.DefaultContext(),
- static_cast<gpgme_key_t>(key), 0);
+ static_cast<gpgme_key_t>(*key), 0);
},
callback, "gpgme_op_passwd", "2.0.15");
}
auto GpgKeyOpera::ModifyTOFUPolicy(
- const GpgKey& key, gpgme_tofu_policy_t tofu_policy) -> GpgError {
+ 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;
@@ -354,26 +358,22 @@ auto GpgKeyOpera::ModifyTOFUPolicy(
}
auto err = gpgme_op_tofu_policy(ctx_.DefaultContext(),
- static_cast<gpgme_key_t>(key), tofu_policy);
+ static_cast<gpgme_key_t>(*key), tofu_policy);
return CheckGpgError(err);
}
-void GpgKeyOpera::DeleteKey(const KeyId& key_id) {
- auto keys = KeyIdArgsList{};
- keys.push_back(key_id);
- DeleteKeys(keys);
-}
+void GpgKeyOpera::DeleteKey(const GpgAbstractKeyPtr& key) { DeleteKeys({key}); }
-auto AddADSKImpl(GpgContext& ctx, const GpgKey& key, const GpgSubKey& adsk,
+auto AddADSKImpl(GpgContext& ctx, const GpgKeyPtr& key, const GpgSubKey& adsk,
const DataObjectPtr& data_object) -> GpgError {
auto algo = adsk.Fingerprint();
unsigned int flags = GPGME_CREATE_ADSK;
- LOG_D() << "add adsk args: " << key.ID() << algo;
+ LOG_D() << "add adsk args: " << key->ID() << algo;
- auto err =
- gpgme_op_createsubkey(ctx.DefaultContext(), static_cast<gpgme_key_t>(key),
- algo.toLatin1(), 0, 0, flags);
+ auto err = gpgme_op_createsubkey(ctx.DefaultContext(),
+ static_cast<gpgme_key_t>(*key),
+ algo.toLatin1(), 0, 0, flags);
if (CheckGpgError(err) != GPG_ERR_NO_ERROR) {
data_object->Swap({GpgGenerateKeyResult{}});
return err;
@@ -384,7 +384,7 @@ auto AddADSKImpl(GpgContext& ctx, const GpgKey& key, const GpgSubKey& adsk,
return CheckGpgError(err);
}
-void GpgKeyOpera::AddADSK(const GpgKey& key, const GpgSubKey& adsk,
+void GpgKeyOpera::AddADSK(const GpgKeyPtr& key, const GpgSubKey& adsk,
const GpgOperationCallback& callback) {
RunGpgOperaAsync(
[=](const DataObjectPtr& data_object) -> GpgError {
@@ -393,7 +393,7 @@ void GpgKeyOpera::AddADSK(const GpgKey& key, const GpgSubKey& adsk,
callback, "gpgme_op_createsubkey", "2.4.1");
}
-auto GpgKeyOpera::AddADSKSync(const GpgKey& key, const GpgSubKey& adsk)
+auto GpgKeyOpera::AddADSKSync(const GpgKeyPtr& key, const GpgSubKey& adsk)
-> std::tuple<GpgError, DataObjectPtr> {
return RunGpgOperaSync(
[=](const DataObjectPtr& data_object) -> GpgError {
diff --git a/src/core/function/gpg/GpgKeyOpera.h b/src/core/function/gpg/GpgKeyOpera.h
index 4728992d..0b91f88a 100644
--- a/src/core/function/gpg/GpgKeyOpera.h
+++ b/src/core/function/gpg/GpgKeyOpera.h
@@ -61,14 +61,14 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyOpera
*
* @param key_ids
*/
- void DeleteKeys(KeyIdArgsList key_ids);
+ void DeleteKeys(const GpgAbstractKeyPtrList& keys);
/**
* @brief
*
* @param key_id
*/
- void DeleteKey(const KeyId& key_id);
+ void DeleteKey(const GpgAbstractKeyPtr& key_id);
/**
* @brief Set the Expire object
@@ -78,7 +78,7 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyOpera
* @param expires
* @return GpgError
*/
- auto SetExpire(const GpgKey& key, const SubkeyId& subkey_fpr,
+ auto SetExpire(const GpgKeyPtr& key, const SubkeyId& subkey_fpr,
std::unique_ptr<QDateTime>& expires) -> GpgError;
/**
@@ -87,7 +87,7 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyOpera
* @param key
* @param output_file_name
*/
- void GenerateRevokeCert(const GpgKey& key, const QString& output_path,
+ void GenerateRevokeCert(const GpgKeyPtr& key, const QString& output_path,
int revocation_reason_code,
const QString& revocation_reason_text);
@@ -97,7 +97,7 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyOpera
* @param key
* @return GpgFrontend::GpgError
*/
- void ModifyPassword(const GpgKey& key, const GpgOperationCallback&);
+ void ModifyPassword(const GpgKeyPtr& key, const GpgOperationCallback&);
/**
* @brief
@@ -106,8 +106,8 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyOpera
* @param tofu_policy
* @return GpgFrontend::GpgError
*/
- auto ModifyTOFUPolicy(const GpgKey& key, gpgme_tofu_policy_t tofu_policy)
- -> GpgFrontend::GpgError;
+ auto ModifyTOFUPolicy(const GpgKeyPtr& key,
+ gpgme_tofu_policy_t tofu_policy) -> GpgError;
/**
* @brief
*
@@ -133,7 +133,7 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyOpera
* @param params
* @return GpgFrontend::GpgError
*/
- void GenerateSubkey(const GpgKey& key,
+ void GenerateSubkey(const GpgKeyPtr& key,
const QSharedPointer<KeyGenerateInfo>& params,
const GpgOperationCallback&);
@@ -143,7 +143,7 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyOpera
* @param key
* @param params
*/
- auto GenerateSubkeySync(const GpgKey& key,
+ auto GenerateSubkeySync(const GpgKeyPtr& key,
const QSharedPointer<KeyGenerateInfo>& params)
-> std::tuple<GpgError, DataObjectPtr>;
@@ -176,7 +176,7 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyOpera
* @param key
* @param adsk
*/
- void AddADSK(const GpgKey& key, const GpgSubKey& adsk,
+ void AddADSK(const GpgKeyPtr& key, const GpgSubKey& adsk,
const GpgOperationCallback&);
/**
@@ -186,7 +186,7 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyOpera
* @param adsk
* @return GpgError
*/
- auto AddADSKSync(const GpgKey& key, const GpgSubKey& adsk)
+ auto AddADSKSync(const GpgKeyPtr& key, const GpgSubKey& adsk)
-> std::tuple<GpgError, DataObjectPtr>;
private:
diff --git a/src/core/function/gpg/GpgUIDOperator.cpp b/src/core/function/gpg/GpgUIDOperator.cpp
index f3e4fcc2..a951fa6f 100644
--- a/src/core/function/gpg/GpgUIDOperator.cpp
+++ b/src/core/function/gpg/GpgUIDOperator.cpp
@@ -37,29 +37,29 @@ namespace GpgFrontend {
GpgUIDOperator::GpgUIDOperator(int channel)
: SingletonFunctionObject<GpgUIDOperator>(channel) {}
-auto GpgUIDOperator::AddUID(const GpgKey& key, const QString& uid) -> bool {
+auto GpgUIDOperator::AddUID(const GpgKeyPtr& key, const QString& uid) -> bool {
auto err = gpgme_op_adduid(ctx_.DefaultContext(),
- static_cast<gpgme_key_t>(key), uid.toUtf8(), 0);
+ static_cast<gpgme_key_t>(*key), uid.toUtf8(), 0);
return CheckGpgError(err) == GPG_ERR_NO_ERROR;
}
-auto GpgUIDOperator::SetPrimaryUID(const GpgKey& key,
+auto GpgUIDOperator::SetPrimaryUID(const GpgKeyPtr& key,
const QString& uid) -> bool {
auto err = CheckGpgError(gpgme_op_set_uid_flag(
- ctx_.DefaultContext(), static_cast<gpgme_key_t>(key), uid.toUtf8(),
+ ctx_.DefaultContext(), static_cast<gpgme_key_t>(*key), uid.toUtf8(),
"primary", nullptr));
return CheckGpgError(err) == GPG_ERR_NO_ERROR;
}
-auto GpgUIDOperator::AddUID(const GpgKey& key, const QString& name,
+auto GpgUIDOperator::AddUID(const GpgKeyPtr& key, const QString& name,
const QString& comment,
const QString& email) -> bool {
LOG_D() << "new uuid:" << name << comment << email;
return AddUID(key, QString("%1(%2)<%3>").arg(name).arg(comment).arg(email));
}
-auto GpgUIDOperator::DeleteUID(const GpgKey& key, int uid_index) -> bool {
- if (uid_index < 2 || uid_index > static_cast<int>(key.UIDs().size())) {
+auto GpgUIDOperator::DeleteUID(const GpgKeyPtr& key, int uid_index) -> bool {
+ if (uid_index < 2 || uid_index > static_cast<int>(key->UIDs().size())) {
LOG_W() << "illegal uid_index index: " << uid_index;
return false;
}
@@ -131,7 +131,7 @@ auto GpgUIDOperator::DeleteUID(const GpgKey& key, int uid_index) -> bool {
return QString("");
};
- auto key_fpr = key.Fingerprint();
+ auto key_fpr = key->Fingerprint();
AutomatonHandelStruct handel_struct(key_fpr);
handel_struct.SetHandler(next_state_handler, action_handler);
@@ -141,10 +141,10 @@ auto GpgUIDOperator::DeleteUID(const GpgKey& key, int uid_index) -> bool {
.DoInteract(key, next_state_handler, action_handler);
}
-auto GpgUIDOperator::RevokeUID(const GpgKey& key, int uid_index,
+auto GpgUIDOperator::RevokeUID(const GpgKeyPtr& key, int uid_index,
int reason_code,
const QString& reason_text) -> bool {
- if (uid_index < 2 || uid_index > static_cast<int>(key.UIDs().size())) {
+ if (uid_index < 2 || uid_index > static_cast<int>(key->UIDs().size())) {
LOG_W() << "illegal uid index: " << uid_index;
return false;
}
@@ -253,7 +253,7 @@ auto GpgUIDOperator::RevokeUID(const GpgKey& key, int uid_index,
return QString("");
};
- auto key_fpr = key.Fingerprint();
+ auto key_fpr = key->Fingerprint();
AutomatonHandelStruct handel_struct(key_fpr);
handel_struct.SetHandler(next_state_handler, action_handler);
diff --git a/src/core/function/gpg/GpgUIDOperator.h b/src/core/function/gpg/GpgUIDOperator.h
index f0e925ed..e5e2f190 100644
--- a/src/core/function/gpg/GpgUIDOperator.h
+++ b/src/core/function/gpg/GpgUIDOperator.h
@@ -53,7 +53,7 @@ class GPGFRONTEND_CORE_EXPORT GpgUIDOperator
* @param uid uid args(combine name&comment&email)
* @return if successful
*/
- auto AddUID(const GpgKey& key, const QString& uid) -> bool;
+ auto AddUID(const GpgKeyPtr& key, const QString& uid) -> bool;
/**
* create a new uid in certain key pair
@@ -63,7 +63,7 @@ class GPGFRONTEND_CORE_EXPORT GpgUIDOperator
* @param email
* @return
*/
- auto AddUID(const GpgKey& key, const QString& name, const QString& comment,
+ auto AddUID(const GpgKeyPtr& key, const QString& name, const QString& comment,
const QString& email) -> bool;
/**
@@ -74,7 +74,7 @@ class GPGFRONTEND_CORE_EXPORT GpgUIDOperator
* @return true
* @return false
*/
- auto DeleteUID(const GpgKey& key, int uid_index) -> bool;
+ auto DeleteUID(const GpgKeyPtr& key, int uid_index) -> bool;
/**
* @brief
@@ -86,7 +86,7 @@ class GPGFRONTEND_CORE_EXPORT GpgUIDOperator
* @return true
* @return false
*/
- auto RevokeUID(const GpgKey& key, int uid_index, int reason_code,
+ auto RevokeUID(const GpgKeyPtr& key, int uid_index, int reason_code,
const QString& reason_text) -> bool;
/**
@@ -95,7 +95,7 @@ class GPGFRONTEND_CORE_EXPORT GpgUIDOperator
* @param uid target uid
* @return if successful
*/
- auto SetPrimaryUID(const GpgKey& key, const QString& uid) -> bool;
+ auto SetPrimaryUID(const GpgKeyPtr& key, const QString& uid) -> bool;
private:
GpgContext& ctx_ =