aboutsummaryrefslogtreecommitdiffstats
path: root/lang/cpp/src
diff options
context:
space:
mode:
Diffstat (limited to 'lang/cpp/src')
-rw-r--r--lang/cpp/src/importresult.cpp125
-rw-r--r--lang/cpp/src/importresult.h10
2 files changed, 135 insertions, 0 deletions
diff --git a/lang/cpp/src/importresult.cpp b/lang/cpp/src/importresult.cpp
index 803c34db..06258729 100644
--- a/lang/cpp/src/importresult.cpp
+++ b/lang/cpp/src/importresult.cpp
@@ -94,6 +94,131 @@ void GpgME::ImportResult::init(gpgme_ctx_t ctx)
make_standard_stuff(ImportResult)
+void GpgME::ImportResult::mergeWith(const ImportResult &other)
+{
+ if (other.isNull()) {
+ return;
+ }
+ if (isNull()) { // just assign
+ operator=(other);
+ return;
+ }
+
+ // Add the numbers of considered keys; the number will be corrected when
+ // merging the imports to account for duplicates
+ d->res.considered += other.d->res.considered;
+ // Add the numbers of keys without user ID; may count duplicates
+ d->res.no_user_id += other.d->res.no_user_id;
+ // Add the numbers of imported keys
+ d->res.imported += other.d->res.imported;
+ // Add the numbers of imported RSA keys
+ d->res.imported_rsa += other.d->res.imported_rsa;
+ // Add the numbers of unchanged keys; the number will be corrected when
+ // merging the imports to account for keys changed by this import
+ d->res.unchanged += other.d->res.unchanged;
+ // Add the numbers of new user IDs
+ d->res.new_user_ids += other.d->res.new_user_ids;
+ // Add the numbers of new subkeys
+ d->res.new_sub_keys += other.d->res.new_sub_keys;
+ // Add the numbers of new signatures
+ d->res.new_signatures += other.d->res.new_signatures;
+ // Add the numbers of new revocations
+ d->res.new_revocations += other.d->res.new_revocations;
+
+ // Add the numbers of considered secret keys; the number will be corrected when
+ // merging the imports to account for duplicates
+ d->res.secret_read += other.d->res.secret_read;
+ // Add the numbers of imported secret keys
+ d->res.secret_imported += other.d->res.secret_imported;
+ // Add the numbers of unchanged secret keys; the number will be corrected when
+ // merging the imports to account for keys changed by this import
+ d->res.secret_unchanged += other.d->res.secret_unchanged;
+
+ // Add the numbers of new keys that were skipped; may count duplicates
+ d->res.skipped_new_keys += other.d->res.skipped_new_keys;
+ // Add the numbers of keys that were not imported; may count duplicates
+ d->res.not_imported += other.d->res.not_imported;
+ // Add the numbers of v3 keys that were skipped; may count duplicates
+ d->res.skipped_v3_keys += other.d->res.skipped_v3_keys;
+
+ // Look at the list of keys for which an import was attempted during the
+ // other import to correct some of the consolidated numbers
+ for (auto it = std::begin(other.d->imports), end = std::end(other.d->imports); it != end; ++it) {
+ const char *fpr = (*it)->fpr;
+ if (!fpr || !*fpr) {
+ // we cannot derive any useful information about an import if the
+ // fingerprint is null or empty
+ continue;
+ }
+ // was this key also considered during the first import
+ const auto consideredInFirstImports =
+ std::any_of(std::begin(d->imports), std::end(d->imports), [fpr](const auto i) {
+ return i->fpr && !strcmp(i->fpr, fpr);
+ });
+ // did we see this key already in the list of keys of the other import
+ const auto consideredInPreviousOtherImports =
+ std::any_of(std::begin(other.d->imports), it, [fpr](const auto i) {
+ return i->fpr && !strcmp(i->fpr, fpr);
+ });
+ // was anything added to this key during the other import
+ const auto changedInOtherImports =
+ std::any_of(std::begin(other.d->imports), std::end(other.d->imports), [fpr](const auto i) {
+ return i->fpr && !strcmp(i->fpr, fpr) && (i->status != 0);
+ });
+ if (consideredInFirstImports && !consideredInPreviousOtherImports) {
+ // key was also considered during first import, but not before in the list of other imports
+ d->res.considered -= 1;
+ if (!changedInOtherImports) {
+ // key was (most likely) counted as unchanged in the second import;
+ // this needs to be corrected (regardless of whether it was changed in the first import)
+ d->res.unchanged -= 1;
+ }
+ }
+
+ // now do the same for the secret key counts
+ const auto secretKeyConsideredInFirstImports =
+ std::any_of(std::begin(d->imports), std::end(d->imports), [fpr](const auto i) {
+ return i->fpr && !strcmp(i->fpr, fpr) && (i->status & GPGME_IMPORT_SECRET);
+ });
+ const auto secretKeyConsideredInPreviousOtherImports =
+ std::any_of(std::begin(other.d->imports), it, [fpr](const auto i) {
+ return i->fpr && !strcmp(i->fpr, fpr) && (i->status & GPGME_IMPORT_SECRET);
+ });
+ const auto secretKeyChangedInOtherImports =
+ std::any_of(std::begin(other.d->imports), std::end(other.d->imports), [fpr](const auto i) {
+ return i->fpr && !strcmp(i->fpr, fpr) && (i->status & GPGME_IMPORT_SECRET) && (i->status != GPGME_IMPORT_SECRET);
+ });
+ if (secretKeyConsideredInFirstImports && !secretKeyConsideredInPreviousOtherImports) {
+ // key was also considered during first import, but not before in the list of other imports
+ d->res.secret_read -= 1;
+ if (!secretKeyChangedInOtherImports) {
+ // key was (most likely) counted as unchanged in the second import;
+ // this needs to be corrected (regardless of whether it was changed in the first import)
+ d->res.secret_unchanged -= 1;
+ }
+ }
+ }
+
+ // Now append the list of keys for which an import was attempted during the
+ // other import
+ d->imports.reserve(d->imports.size() + other.d->imports.size());
+ std::transform(std::begin(other.d->imports), std::end(other.d->imports),
+ std::back_inserter(d->imports),
+ [](const auto import) {
+ gpgme_import_status_t copy = new _gpgme_import_status{*import};
+ if (import->fpr) {
+ copy->fpr = strdup(import->fpr);
+ }
+ copy->next = nullptr; // should already be null, but better safe than sorry
+ return copy;
+ });
+
+ // Finally, merge the error if there was none yet
+ if (!bool(error())) {
+ Result::operator=(other);
+ }
+}
+
int GpgME::ImportResult::numConsidered() const
{
return d ? d->res.considered : 0 ;
diff --git a/lang/cpp/src/importresult.h b/lang/cpp/src/importresult.h
index bcd956c3..59366984 100644
--- a/lang/cpp/src/importresult.h
+++ b/lang/cpp/src/importresult.h
@@ -60,6 +60,16 @@ public:
swap(this->d, other.d);
}
+ /**
+ * Merges the result @p other into this result (and all of its copies).
+ *
+ * @note The merge algorithm assumes that @p other is the result of an
+ * import that was performed after the import of this result.
+ * @note Some numbers cannot be consolidated reliably, e.g. the number of
+ * keys without user ID.
+ */
+ void mergeWith(const ImportResult &other);
+
bool isNull() const;
int numConsidered() const;