aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorsaturneric <[email protected]>2026-09-14 23:02:44 +0200
committersaturneric <[email protected]>2026-09-14 23:02:44 +0200
commit8cc5f09dbd09eff076901a3b497a206e23c2c690 (patch)
tree9184c9093c06ac6ad9be0ce005903c5384a88db6 /src
parentfix(email): free verification error string (diff)
downloadmodules-8cc5f09dbd09eff076901a3b497a206e23c2c690.tar.gz
modules-8cc5f09dbd09eff076901a3b497a206e23c2c690.zip
refactor(email): migrate to list-based GPG APIs
- replace raw recipient and address arrays with SDK list handles - use borrowed accessors with centralized list release - update key lookup rendering to consume key brief lists safely
Diffstat (limited to 'src')
-rw-r--r--src/m_email/EMailPageView.cpp72
-rw-r--r--src/m_email/EMailSecurityView.cpp39
2 files changed, 60 insertions, 51 deletions
diff --git a/src/m_email/EMailPageView.cpp b/src/m_email/EMailPageView.cpp
index b8bcb4a..f1511a7 100644
--- a/src/m_email/EMailPageView.cpp
+++ b/src/m_email/EMailPageView.cpp
@@ -29,7 +29,9 @@
#include "EMailPageView.h"
#include <GFSDKGpg.h>
+#include <GFSDKGpgList.h>
+#include <GFSDKBuffer.hpp>
#include <QAbstractItemView>
#include <QApplication>
#include <QButtonGroup>
@@ -1934,27 +1936,28 @@ void EMailPageView::refresh_locked_capability(const QStringList& named) {
// for mail encrypted to someone else who happened to share an address.
const auto* ciphertext = FindEncryptedCiphertextPart(tree_root_);
if (ciphertext != nullptr) {
- GFGpgEncRecipient* raw = nullptr;
- int count = 0;
- if (GFGpgSniffEncryptedRecipients(
- GFGpgCurrentGpgContextChannel(), ciphertext->data.constData(),
- static_cast<int>(ciphertext->data.size()), &raw, &count) == 0) {
+ auto in = GFBuf::Copy(ciphertext->data);
+ GFGpgRecipientListRef list = nullptr;
+ if (GFGpgSniffRecipients(GFGpgCurrentGpgContextChannel(), in.View(),
+ &list) == 0) {
+ const auto count = GFGpgRecipientListCount(list);
QList<EMailEncRecipient> recipients;
- recipients.reserve(count);
- for (int i = 0; i < count; ++i) {
- // Copied rather than taken: these strings belong to the array that
- // GFGpgFreeEncRecipients releases as a whole.
+ recipients.reserve(static_cast<qsizetype>(count));
+ for (size_t i = 0; i < count; ++i) {
+ // Copied rather than taken: every accessor here returns a BORROWED
+ // pointer that dies with the list. There is no per-element free to
+ // get wrong, and no count to hand back on release.
recipients.append(EMailEncRecipient{
- QString::fromUtf8(raw[i].key_id),
- QString::fromUtf8(raw[i].pub_algo),
- QString::fromUtf8(raw[i].fingerprint),
- QString::fromUtf8(raw[i].uid),
- raw[i].key_found != 0,
- raw[i].has_secret != 0,
- raw[i].hidden != 0,
+ QString::fromUtf8(GFGpgRecipientKeyId(list, i)),
+ QString::fromUtf8(GFGpgRecipientPubAlgo(list, i)),
+ QString::fromUtf8(GFGpgRecipientFingerprint(list, i)),
+ QString::fromUtf8(GFGpgRecipientUid(list, i)),
+ GFGpgRecipientKeyFound(list, i) != 0,
+ GFGpgRecipientHasSecret(list, i) != 0,
+ GFGpgRecipientHidden(list, i) != 0,
});
}
- GFGpgFreeEncRecipients(raw, count);
+ GFGpgRecipientListRelease(list);
if (!recipients.isEmpty()) {
show_decrypt_capability(DescribeDecryptCapability(recipients));
@@ -2014,20 +2017,20 @@ void EMailPageView::refresh_locked_capability_by_address(
// the key a message is encrypted to need not carry any of these addresses --
// so it is reached only when the message itself could not be read, and every
// wording below is hedged accordingly.
- char** addresses = nullptr;
- int count = 0;
- if (GFGpgListKeyAddresses(GFGpgCurrentGpgContextChannel(), 1, &addresses,
- &count) != 0) {
+ GFStringListRef addresses = nullptr;
+ if (GFGpgListAddresses(GFGpgCurrentGpgContextChannel(), 1, &addresses) != 0) {
locked_capability_->setVisible(false);
return;
}
QStringList mine;
- for (int i = 0; i < count; ++i) {
- const auto address = AddressOfUid(QString::fromUtf8(addresses[i]));
+ const auto count = GFStringListCount(addresses);
+ for (size_t i = 0; i < count; ++i) {
+ const auto address =
+ AddressOfUid(QString::fromUtf8(GFStringListAt(addresses, i)));
if (!address.isEmpty()) mine.append(address.toLower());
}
- GFGpgFreeStringArray(addresses, count);
+ GFStringListRelease(addresses);
// Nothing knowable either way: no recipient is named, or the keyring holds
// no private key at all. Saying something in that case would be inventing
@@ -2358,20 +2361,21 @@ void EMailPageView::refresh_send_state() {
*/
void EMailPageView::install_address_hints() {
const auto addresses = [](bool secret_only) {
- char** raw = nullptr;
- int count = 0;
- if (GFGpgListKeyAddresses(GFGpgCurrentGpgContextChannel(),
- secret_only ? 1 : 0, &raw, &count) != 0) {
+ GFStringListRef raw = nullptr;
+ if (GFGpgListAddresses(GFGpgCurrentGpgContextChannel(), secret_only ? 1 : 0,
+ &raw) != 0) {
return QStringList{};
}
+ const auto count = GFStringListCount(raw);
QStringList out;
- out.reserve(count);
- // Copied rather than taken: UnStrDup FREES what it is handed, and these
- // strings belong to the array that GFGpgFreeStringArray releases as a
- // whole.
- for (int i = 0; i < count; ++i) out.append(QString::fromUtf8(raw[i]));
- GFGpgFreeStringArray(raw, count);
+ out.reserve(static_cast<qsizetype>(count));
+ // Copied rather than taken: the accessor returns a BORROWED pointer that
+ // dies with the list, which goes back in a single release below.
+ for (size_t i = 0; i < count; ++i) {
+ out.append(QString::fromUtf8(GFStringListAt(raw, i)));
+ }
+ GFStringListRelease(raw);
return out;
};
diff --git a/src/m_email/EMailSecurityView.cpp b/src/m_email/EMailSecurityView.cpp
index 3b6e15c..2f32af5 100644
--- a/src/m_email/EMailSecurityView.cpp
+++ b/src/m_email/EMailSecurityView.cpp
@@ -29,6 +29,7 @@
#include "EMailSecurityView.h"
#include <GFSDKGpg.h>
+#include <GFSDKGpgList.h>
#include <QAbstractItemView>
#include <QApplication>
@@ -529,9 +530,11 @@ void EMailSecurityView::add_key_section(const QStringList& addresses,
if (email.isEmpty() || seen.contains(email)) continue;
seen.append(email);
- GFGpgKeyBrief* briefs = nullptr;
- int count = 0;
- GFGpgFindKeysByEmail(channel, email.toUtf8().constData(), &briefs, &count);
+ // The address stays ours: every SDK argument is borrowed, so the
+ // QByteArray below is safe to let die at the end of the statement.
+ GFGpgKeyBriefListRef briefs = nullptr;
+ GFGpgFindKeys(channel, email.toUtf8().constData(), &briefs);
+ const auto count = static_cast<int>(GFGpgKeyBriefListCount(briefs));
auto* item = new QTreeWidgetItem(group);
item->setText(kColItem, email);
@@ -542,31 +545,33 @@ void EMailSecurityView::add_key_section(const QStringList& addresses,
// Recorded on the row so the menu knows this is an address with nothing
// behind it, which is the one case where importing is worth offering.
item->setData(kColItem, kRoleMissingKey, true);
- GFGpgFreeKeyBriefs(briefs, count);
+ GFGpgKeyBriefListRelease(briefs);
continue;
}
item->setText(kColValue,
count == 1 ? tr("1 key") : tr("%1 keys").arg(count));
- for (int i = 0; i < count; ++i) {
- const auto& brief = briefs[i];
-
+ for (size_t i = 0; i < static_cast<size_t>(count); ++i) {
+ // Borrowed accessors throughout: nothing here is separately releasable,
+ // so the whole list goes back in one call at the end.
auto* key_item = new QTreeWidgetItem(item);
- key_item->setText(kColItem, QString::fromUtf8(brief.uid));
+ key_item->setText(kColItem,
+ QString::fromUtf8(GFGpgKeyBriefUid(briefs, i)));
// Usability. Says whether the key can be used at all -- and nothing
// whatsoever about whose key it is.
- key_item->setText(
- kColValue, tr("key is %1").arg(DescribeUsability(brief.usability)));
+ const auto usability = GFGpgKeyBriefUsability(briefs, i);
+ key_item->setText(kColValue,
+ tr("key is %1").arg(DescribeUsability(usability)));
EMailSetCellTone(
key_item, kColValue,
- brief.usability == kUSABLE ? EMailTone::kGOOD : EMailTone::kWARN,
- this);
+ usability == kUSABLE ? EMailTone::kGOOD : EMailTone::kWARN, this);
auto* fpr = new QTreeWidgetItem(key_item);
fpr->setText(kColItem, tr("Fingerprint"));
- fpr->setText(kColValue, QString::fromUtf8(brief.fingerprint));
+ fpr->setText(kColValue,
+ QString::fromUtf8(GFGpgKeyBriefFingerprint(briefs, i)));
EMailSetCellTone(fpr, kColItem, EMailTone::kMUTED, this);
// Identity binding, kept as its own row. A usable key carrying this
@@ -574,11 +579,11 @@ void EMailSecurityView::add_key_section(const QStringList& addresses,
// single combined verdict would bury.
auto* identity = new QTreeWidgetItem(key_item);
identity->setText(kColItem, tr("Identity"));
- if (brief.matched_uid_revoked != 0) {
+ if (GFGpgKeyBriefMatchedUidRevoked(briefs, i) != 0) {
identity->setText(
kColValue, tr("this address is on a REVOKED user ID of the key"));
EMailSetCellTone(identity, kColValue, EMailTone::kWARN, this);
- } else if (brief.matched_uid_is_primary != 0) {
+ } else if (GFGpgKeyBriefMatchedUidIsPrimary(briefs, i) != 0) {
identity->setText(kColValue, tr("this address is the key's primary "
"user ID"));
EMailSetCellTone(identity, kColValue, EMailTone::kGOOD, this);
@@ -588,7 +593,7 @@ void EMailSecurityView::add_key_section(const QStringList& addresses,
EMailSetCellTone(identity, kColValue, EMailTone::kMUTED, this);
}
- if (brief.can_encrypt == 0) {
+ if (GFGpgKeyBriefCanEncrypt(briefs, i) == 0) {
auto* note = new QTreeWidgetItem(key_item);
note->setText(kColItem, tr("Note"));
note->setText(kColValue, tr("this key cannot be used for encryption"));
@@ -596,7 +601,7 @@ void EMailSecurityView::add_key_section(const QStringList& addresses,
}
}
- GFGpgFreeKeyBriefs(briefs, count);
+ GFGpgKeyBriefListRelease(briefs);
}
}