aboutsummaryrefslogtreecommitdiffstats
path: root/lang/cpp/src
diff options
context:
space:
mode:
Diffstat (limited to 'lang/cpp/src')
-rw-r--r--lang/cpp/src/key.cpp61
-rw-r--r--lang/cpp/src/key.h3
2 files changed, 63 insertions, 1 deletions
diff --git a/lang/cpp/src/key.cpp b/lang/cpp/src/key.cpp
index 4ebd3fe0..017f6624 100644
--- a/lang/cpp/src/key.cpp
+++ b/lang/cpp/src/key.cpp
@@ -35,6 +35,7 @@
#include <string.h>
#include <strings.h>
+#include <cassert>
#include <istream>
#include <iterator>
@@ -839,18 +840,76 @@ gpgme_key_sig_t verify_signature(gpgme_user_id_t uid, gpgme_key_sig_t sig)
return nullptr;
}
+static int signature_index(gpgme_user_id_t uid, gpgme_key_sig_t sig)
+{
+ if (uid) {
+ int i = 0;
+ for (gpgme_key_sig_t s = uid->signatures ; s ; s = s->next, ++i) {
+ if (s == sig) {
+ return i;
+ }
+ }
+ }
+ return -1;
+}
+
UserID::Signature::Signature() : key(), uid(nullptr), sig(nullptr) {}
UserID::Signature::Signature(const shared_gpgme_key_t &k, gpgme_user_id_t u, unsigned int idx)
: key(k), uid(verify_uid(k, u)), sig(find_signature(uid, idx))
{
-
}
UserID::Signature::Signature(const shared_gpgme_key_t &k, gpgme_user_id_t u, gpgme_key_sig_t s)
: key(k), uid(verify_uid(k, u)), sig(verify_signature(uid, s))
{
+}
+
+bool UserID::Signature::operator<(const Signature &other)
+{
+ // based on cmp_signodes() in g10/keylist.c
+
+ // both signatures must belong to the same user ID
+ assert(uid == other.uid);
+
+ // self-signatures are ordered first
+ const char *primaryKeyId = parent().parent().keyID();
+ const bool thisIsSelfSignature = strcmp(signerKeyID(), primaryKeyId) == 0;
+ const bool otherIsSelfSignature = strcmp(other.signerKeyID(), primaryKeyId) == 0;
+ if (thisIsSelfSignature && !otherIsSelfSignature) {
+ return true;
+ }
+ if (otherIsSelfSignature && !thisIsSelfSignature) {
+ return false;
+ }
+
+ // then sort by signer key ID (which are or course the same for self-sigs)
+ const int keyIdComparison = strcmp(signerKeyID(), other.signerKeyID());
+ if (keyIdComparison < 0) {
+ return true;
+ }
+ if (keyIdComparison > 0) {
+ return false;
+ }
+
+ // followed by creation time
+ if (creationTime() < other.creationTime()) {
+ return true;
+ }
+ if (creationTime() > other.creationTime()) {
+ return false;
+ }
+
+ // followed by the class in a way that a rev comes first
+ if (certClass() < other.certClass()) {
+ return true;
+ }
+ if (certClass() > other.certClass()) {
+ return false;
+ }
+ // to make the sort stable we compare the indexes of the signatures as last resort
+ return signature_index(uid, sig) < signature_index(uid, other.sig);
}
UserID UserID::Signature::parent() const
diff --git a/lang/cpp/src/key.h b/lang/cpp/src/key.h
index d3c6125a..a7931672 100644
--- a/lang/cpp/src/key.h
+++ b/lang/cpp/src/key.h
@@ -467,6 +467,9 @@ public:
swap(this->sig, other.sig);
}
+ /*! Defines a canonical sort order for signatures of the same user ID. */
+ bool operator<(const Signature &other);
+
bool isNull() const
{
return !sig || !uid || !key ;