diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/core/function/result_analyse/GpgVerifyResultAnalyse.cpp | 7 | ||||
-rw-r--r-- | src/core/function/result_analyse/GpgVerifyResultAnalyse.h | 10 | ||||
-rw-r--r-- | src/ui/UserInterfaceUtils.cpp | 117 | ||||
-rw-r--r-- | src/ui/UserInterfaceUtils.h | 10 | ||||
-rw-r--r-- | src/ui/main_window/MainWindowFileSlotFunction.cpp | 91 | ||||
-rw-r--r-- | src/ui/main_window/MainWindowGpgOperaFunction.cpp | 118 |
6 files changed, 309 insertions, 44 deletions
diff --git a/src/core/function/result_analyse/GpgVerifyResultAnalyse.cpp b/src/core/function/result_analyse/GpgVerifyResultAnalyse.cpp index b53ae9b8..9512189d 100644 --- a/src/core/function/result_analyse/GpgVerifyResultAnalyse.cpp +++ b/src/core/function/result_analyse/GpgVerifyResultAnalyse.cpp @@ -126,6 +126,8 @@ void GpgFrontend::GpgVerifyResultAnalyse::doAnalyse() { << Qt::endl; setStatus(-2); print_signer_without_key(stream_, GpgSignature(sign)); + unknown_signer_fpr_list_.push_back( + GpgSignature(sign).GetFingerprint()); break; case GPG_ERR_CERT_REVOKED: stream_ << tr("A signature is valid but the key used to verify the " @@ -252,3 +254,8 @@ auto GpgFrontend::GpgVerifyResultAnalyse::TakeChargeOfResult() -> GpgFrontend::GpgVerifyResult { return result_; } + +auto GpgFrontend::GpgVerifyResultAnalyse::GetUnknownSignatures() const + -> QList<QString> { + return unknown_signer_fpr_list_; +} diff --git a/src/core/function/result_analyse/GpgVerifyResultAnalyse.h b/src/core/function/result_analyse/GpgVerifyResultAnalyse.h index 422cec43..b3e318b8 100644 --- a/src/core/function/result_analyse/GpgVerifyResultAnalyse.h +++ b/src/core/function/result_analyse/GpgVerifyResultAnalyse.h @@ -53,7 +53,7 @@ class GPGFRONTEND_CORE_EXPORT GpgVerifyResultAnalyse : public GpgResultAnalyse { * * @return gpgme_signature_t */ - auto GetSignatures() const -> gpgme_signature_t; + [[nodiscard]] auto GetSignatures() const -> gpgme_signature_t; /** * @brief @@ -62,6 +62,13 @@ class GPGFRONTEND_CORE_EXPORT GpgVerifyResultAnalyse : public GpgResultAnalyse { */ auto TakeChargeOfResult() -> GpgVerifyResult; + /** + * @brief Get the Unknown Signatures object + * + * @return QList<QString> + */ + [[nodiscard]] auto GetUnknownSignatures() const -> QList<QString>; + protected: /** * @brief @@ -92,6 +99,7 @@ class GPGFRONTEND_CORE_EXPORT GpgVerifyResultAnalyse : public GpgResultAnalyse { GpgError error_; ///< GpgVerifyResult result_; ///< + QList<QString> unknown_signer_fpr_list_; }; } // namespace GpgFrontend diff --git a/src/ui/UserInterfaceUtils.cpp b/src/ui/UserInterfaceUtils.cpp index db54dd15..ba3c323b 100644 --- a/src/ui/UserInterfaceUtils.cpp +++ b/src/ui/UserInterfaceUtils.cpp @@ -411,6 +411,67 @@ void CommonUtils::SlotImportKeyFromKeyServer( return; } + if (Module::IsModuleActivate( + "com.bktus.gpgfrontend.module.key_server_sync")) { + // LOOP + decltype(key_ids.size()) current_index = 1; + decltype(key_ids.size()) all_index = key_ids.size(); + + for (const auto &key_id : key_ids) { + Thread::TaskRunnerGetter::GetInstance() + .GetTaskRunner(Thread::TaskRunnerGetter::kTaskRunnerType_Network) + ->PostTask(new Thread::Task( + [=](const DataObjectPtr &data_obj) -> int { + Module::TriggerEvent( + "REQUEST_GET_PUBLIC_KEY_BY_KEY_ID", + { + {"key_id", QString(key_id)}, + }, + [key_id, channel, callback, current_index, all_index]( + Module::EventIdentifier i, + Module::Event::ListenerIdentifier ei, + Module::Event::Params p) { + LOG_D() + << "REQUEST_GET_PUBLIC_KEY_BY_FINGERPRINT callback: " + << i << ei; + + QString status; + + if (p["ret"] != "0" || !p["error_msg"].isEmpty()) { + LOG_E() + << "An error occurred trying to get data from key:" + << key_id << "error message: " << p["error_msg"] + << "reply data: " << p["reply_data"]; + status = p["error_msg"] + p["reply_data"]; + } else if (p.contains("key_data")) { + const auto key_data = p["key_data"]; + LOG_D() << "got key data of key " << key_id + << " from key server: " << key_data; + + auto result = GpgKeyImportExporter::GetInstance(channel) + .ImportKey(GFBuffer(key_data)); + if (result->imported == 1) { + status = tr("The key has been updated"); + } else { + status = tr("No need to update the key"); + } + } + + callback(key_id, status, current_index, all_index); + }); + + return 0; + }, + QString("key_%1_import_task").arg(key_id))); + + // not too fast to hit rate limit + QThread::msleep(200); + current_index++; + } + + return; + } + auto *thread = QThread::create([target_keyserver, key_ids, callback, channel]() { QUrl target_keyserver_url(target_keyserver); @@ -594,4 +655,60 @@ void CommonUtils::ImportKeyFromKeyServer(int channel, ->PostTask(task); } +void CommonUtils::ImportKeyByKeyServerSyncModule(QWidget *parent, int channel, + const QList<QString> &fprs) { + if (!Module::IsModuleActivate( + "com.bktus.gpgfrontend.module.key_server_sync")) { + return; + } + + auto all_key_data = QSharedPointer<QString>::create(); + auto remaining_tasks = QSharedPointer<int>::create(fprs.size()); + + for (const auto &fpr : fprs) { + Thread::TaskRunnerGetter::GetInstance() + .GetTaskRunner(Thread::TaskRunnerGetter::kTaskRunnerType_Network) + ->PostTask(new Thread::Task( + [=](const DataObjectPtr &data_obj) -> int { + Module::TriggerEvent( + "REQUEST_GET_PUBLIC_KEY_BY_FINGERPRINT", + { + {"fingerprint", QString(fpr)}, + }, + [fpr, all_key_data, remaining_tasks, this, parent, channel]( + Module::EventIdentifier i, + Module::Event::ListenerIdentifier ei, + Module::Event::Params p) { + LOG_D() + << "REQUEST_GET_PUBLIC_KEY_BY_FINGERPRINT callback: " + << i << ei; + + if (p["ret"] != "0" || !p["error_msg"].isEmpty()) { + LOG_E() + << "An error occurred trying to get data from key:" + << fpr << "error message: " << p["error_msg"] + << "reply data: " << p["reply_data"]; + } else if (p.contains("key_data")) { + const auto key_data = p["key_data"]; + LOG_D() << "got key data of key " << fpr + << " from key server: " << key_data; + + *all_key_data += key_data; + } + + // it only uses one thread for these operations + // so that is no need for locking now + (*remaining_tasks)--; + + if (*remaining_tasks == 0) { + this->SlotImportKeys(parent, channel, + all_key_data->toUtf8()); + } + }); + + return 0; + }, + QString("key_%1_import_task").arg(fpr))); + } +} } // namespace GpgFrontend::UI
\ No newline at end of file diff --git a/src/ui/UserInterfaceUtils.h b/src/ui/UserInterfaceUtils.h index fd5de9de..650d049e 100644 --- a/src/ui/UserInterfaceUtils.h +++ b/src/ui/UserInterfaceUtils.h @@ -237,7 +237,7 @@ class CommonUtils : public QWidget { * * @param parent */ - void SlotImportKeyFromFile(QWidget* parentint, int channel); + void SlotImportKeyFromFile(QWidget* parent, int channel); /** * @brief @@ -256,6 +256,14 @@ class CommonUtils : public QWidget { /** * @brief * + * @param channel + */ + void ImportKeyByKeyServerSyncModule(QWidget* parent, int channel, + const QList<QString>& fprs); + + /** + * @brief + * * @param ctx_channel * @param key_ids * @param callback diff --git a/src/ui/main_window/MainWindowFileSlotFunction.cpp b/src/ui/main_window/MainWindowFileSlotFunction.cpp index 4b1eec9f..c85b616a 100644 --- a/src/ui/main_window/MainWindowFileSlotFunction.cpp +++ b/src/ui/main_window/MainWindowFileSlotFunction.cpp @@ -34,6 +34,7 @@ #include "core/function/result_analyse/GpgEncryptResultAnalyse.h" #include "core/function/result_analyse/GpgSignResultAnalyse.h" #include "core/function/result_analyse/GpgVerifyResultAnalyse.h" +#include "core/module/ModuleManager.h" #include "core/utils/GpgUtils.h" #include "core/utils/IOUtils.h" #include "ui/UserInterfaceUtils.h" @@ -554,14 +555,41 @@ void MainWindow::SlotFileVerify(const QString& path) { process_result_analyse(edit_, info_board_, result_analyse); - // pause this feature - // if (result_analyse.GetStatus() == -2) { - // import_unknown_key_from_keyserver(this, result_analyse); - // } - // pause this feature - // if (result_analyse.GetStatus() >= 0) { - // show_verify_details(this, info_board_, err, result); - // } + if (!result_analyse.GetUnknownSignatures().isEmpty() && + Module::IsModuleActivate( + "com.bktus.gpgfrontend.module.key_server_sync")) { + LOG_D() << "try to sync missing key info from server" + << result_analyse.GetUnknownSignatures(); + + QString fingerprint_list; + for (const auto& fingerprint : + result_analyse.GetUnknownSignatures()) { + fingerprint_list += fingerprint + "\n"; + } + + // Interaction with user + auto user_response = QMessageBox::question( + this, tr("Missing Keys"), + tr("Some signatures cannot be verified because the " + "corresponding keys are missing.\n\n" + "The following fingerprints are missing:\n%1\n\n" + "Would you like to fetch these keys from the key " + "server?") + .arg(fingerprint_list), + QMessageBox::Yes | QMessageBox::No); + + if (user_response == QMessageBox::Yes) { + CommonUtils::GetInstance() + ->ImportKeyByKeyServerSyncModule( + this, m_key_list_->GetCurrentGpgContextChannel(), + result_analyse.GetUnknownSignatures()); + } else { + QMessageBox::information( + this, tr("Verification Incomplete"), + tr("Verification was incomplete due to missing " + "keys. You can manually import the keys later.")); + } + } this->slot_refresh_current_file_view(); }); @@ -870,18 +898,43 @@ void MainWindow::SlotFileDecryptVerify(const QString& path) { decrypt_result_analyse, verify_result_analyse); - // pause this feature - // if (verify_result_analyse.GetStatus() == -2) { - // import_unknown_key_from_keyserver(this, - // verify_result_analyse); - // } - // pause this feature - // if (verify_result_analyse.GetStatus() >= 0) { - // show_verify_details(this, info_board_, err, - // verify_result); - // } - this->slot_refresh_current_file_view(); + + if (!verify_result_analyse.GetUnknownSignatures().isEmpty() && + Module::IsModuleActivate( + "com.bktus.gpgfrontend.module.key_server_sync")) { + LOG_D() << "try to sync missing key info from server" + << verify_result_analyse.GetUnknownSignatures(); + + QString fingerprint_list; + for (const auto& fingerprint : + verify_result_analyse.GetUnknownSignatures()) { + fingerprint_list += fingerprint + "\n"; + } + + // Interaction with user + auto user_response = QMessageBox::question( + this, tr("Missing Keys"), + tr("Some signatures cannot be verified because the " + "corresponding keys are missing.\n\n" + "The following fingerprints are missing:\n%1\n\n" + "Would you like to fetch these keys from the key " + "server?") + .arg(fingerprint_list), + QMessageBox::Yes | QMessageBox::No); + + if (user_response == QMessageBox::Yes) { + CommonUtils::GetInstance() + ->ImportKeyByKeyServerSyncModule( + this, m_key_list_->GetCurrentGpgContextChannel(), + verify_result_analyse.GetUnknownSignatures()); + } else { + QMessageBox::information( + this, tr("Verification Incomplete"), + tr("Verification was incomplete due to missing " + "keys. You can manually import the keys later.")); + } + } }); }); } diff --git a/src/ui/main_window/MainWindowGpgOperaFunction.cpp b/src/ui/main_window/MainWindowGpgOperaFunction.cpp index 5069f600..b8935efb 100644 --- a/src/ui/main_window/MainWindowGpgOperaFunction.cpp +++ b/src/ui/main_window/MainWindowGpgOperaFunction.cpp @@ -35,6 +35,7 @@ #include "core/function/result_analyse/GpgVerifyResultAnalyse.h" #include "core/model/DataObject.h" #include "core/model/GpgEncryptResult.h" +#include "core/module/ModuleManager.h" #include "core/utils/GpgUtils.h" #include "ui/UserInterfaceUtils.h" #include "ui/dialog/SignersPicker.h" @@ -266,29 +267,65 @@ void MainWindow::SlotVerify() { this, tr("Verifying"), [this, buffer](const OperaWaitingHd& hd) { GpgFrontend::GpgBasicOperator::GetInstance( m_key_list_->GetCurrentGpgContextChannel()) - .Verify(buffer, GFBuffer(), - [this, hd](GpgError err, const DataObjectPtr& data_obj) { - // stop waiting - hd(); - - if (CheckGpgError(err) == GPG_ERR_USER_1 || - data_obj == nullptr || - !data_obj->Check<GpgVerifyResult>()) { - QMessageBox::critical(this, tr("Error"), - tr("Unknown error occurred")); - return; - } - auto verify_result = - ExtractParams<GpgVerifyResult>(data_obj, 0); - - // analyse result - auto result_analyse = GpgVerifyResultAnalyse( - m_key_list_->GetCurrentGpgContextChannel(), err, - verify_result); - result_analyse.Analyse(); - process_result_analyse(edit_, info_board_, - result_analyse); - }); + .Verify( + buffer, GFBuffer(), + [this, hd](GpgError err, const DataObjectPtr& data_obj) { + // stop waiting + hd(); + + if (CheckGpgError(err) == GPG_ERR_USER_1 || + data_obj == nullptr || + !data_obj->Check<GpgVerifyResult>()) { + QMessageBox::critical(this, tr("Error"), + tr("Unknown error occurred")); + return; + } + auto verify_result = + ExtractParams<GpgVerifyResult>(data_obj, 0); + + // analyse result + auto result_analyse = GpgVerifyResultAnalyse( + m_key_list_->GetCurrentGpgContextChannel(), err, + verify_result); + result_analyse.Analyse(); + process_result_analyse(edit_, info_board_, result_analyse); + + if (!result_analyse.GetUnknownSignatures().isEmpty() && + Module::IsModuleActivate( + "com.bktus.gpgfrontend.module.key_server_sync")) { + LOG_D() << "try to sync missing key info from server" + << result_analyse.GetUnknownSignatures(); + + QString fingerprint_list; + for (const auto& fingerprint : + result_analyse.GetUnknownSignatures()) { + fingerprint_list += fingerprint + "\n"; + } + + // Interaction with user + auto user_response = QMessageBox::question( + this, tr("Missing Keys"), + tr("Some signatures cannot be verified because the " + "corresponding keys are missing.\n\n" + "The following fingerprints are missing:\n%1\n\n" + "Would you like to fetch these keys from the key " + "server?") + .arg(fingerprint_list), + QMessageBox::Yes | QMessageBox::No); + + if (user_response == QMessageBox::Yes) { + CommonUtils::GetInstance() + ->ImportKeyByKeyServerSyncModule( + this, m_key_list_->GetCurrentGpgContextChannel(), + result_analyse.GetUnknownSignatures()); + } else { + QMessageBox::information( + this, tr("Verification Incomplete"), + tr("Verification was incomplete due to missing " + "keys. You can manually import the keys later.")); + } + } + }); }); } @@ -440,6 +477,41 @@ void MainWindow::SlotDecryptVerify() { edit_->SlotFillTextEditWithText( out_buffer.ConvertToQByteArray()); } + + if (!verify_result_analyse.GetUnknownSignatures().isEmpty() && + Module::IsModuleActivate( + "com.bktus.gpgfrontend.module.key_server_sync")) { + LOG_D() << "try to sync missing key info from server" + << verify_result_analyse.GetUnknownSignatures(); + + QString fingerprint_list; + for (const auto& fingerprint : + verify_result_analyse.GetUnknownSignatures()) { + fingerprint_list += fingerprint + "\n"; + } + + // Interaction with user + auto user_response = QMessageBox::question( + this, tr("Missing Keys"), + tr("Some signatures cannot be verified because the " + "corresponding keys are missing.\n\n" + "The following fingerprints are missing:\n%1\n\n" + "Would you like to fetch these keys from the key " + "server?") + .arg(fingerprint_list), + QMessageBox::Yes | QMessageBox::No); + + if (user_response == QMessageBox::Yes) { + CommonUtils::GetInstance()->ImportKeyByKeyServerSyncModule( + this, m_key_list_->GetCurrentGpgContextChannel(), + verify_result_analyse.GetUnknownSignatures()); + } else { + QMessageBox::information( + this, tr("Verification Incomplete"), + tr("Verification was incomplete due to missing " + "keys. You can manually import the keys later.")); + } + } }); }); } |