cpp: Make signatures belonging to the same user ID sortable
lang/cpp/src/key.h, lang/cpp/src/key.cpp (UserID::Signature::operator<): New. lang/cpp/src/key.cpp (signature_index): New. -- operator< defines a canonical sort order for signatures belonging to the same user ID. It is based on the sort order defined by cmp_signodes() in g10/keylist.c of gnupg. In particular, the ordering of signatures made with the same key by creation time allows to see easily whether the most recent signature is a certification or a revocation. GnuPG-bug-id: 5094 recent
This commit is contained in:
parent
f042739d3a
commit
6a6d2a2764
1
NEWS
1
NEWS
@ -35,6 +35,7 @@ Noteworthy changes in version 1.14.1 (unreleased)
|
|||||||
cpp: Context::cancelPendingOperationImmediately NEW.
|
cpp: Context::cancelPendingOperationImmediately NEW.
|
||||||
cpp: Context::revokeSignature NEW.
|
cpp: Context::revokeSignature NEW.
|
||||||
cpp: Context::startRevokeSignature NEW.
|
cpp: Context::startRevokeSignature NEW.
|
||||||
|
cpp: UserID::Signature::operator< NEW.
|
||||||
qt: operator<<(QDebug debug, const GpgME::Error &err) NEW.
|
qt: operator<<(QDebug debug, const GpgME::Error &err) NEW.
|
||||||
qt: QuickJob::startRevokeSignature NEW.
|
qt: QuickJob::startRevokeSignature NEW.
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
|
#include <cassert>
|
||||||
#include <istream>
|
#include <istream>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
|
||||||
@ -839,18 +840,76 @@ gpgme_key_sig_t verify_signature(gpgme_user_id_t uid, gpgme_key_sig_t sig)
|
|||||||
return nullptr;
|
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() : key(), uid(nullptr), sig(nullptr) {}
|
||||||
|
|
||||||
UserID::Signature::Signature(const shared_gpgme_key_t &k, gpgme_user_id_t u, unsigned int idx)
|
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))
|
: 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)
|
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))
|
: 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
|
UserID UserID::Signature::parent() const
|
||||||
|
@ -467,6 +467,9 @@ public:
|
|||||||
swap(this->sig, other.sig);
|
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
|
bool isNull() const
|
||||||
{
|
{
|
||||||
return !sig || !uid || !key ;
|
return !sig || !uid || !key ;
|
||||||
|
Loading…
Reference in New Issue
Block a user