diff options
author | saturneric <[email protected]> | 2024-11-25 22:42:25 +0000 |
---|---|---|
committer | saturneric <[email protected]> | 2024-11-25 22:42:25 +0000 |
commit | 296de126739a0b0a1556f9f34533255c05634651 (patch) | |
tree | 8dd47144081f47d9e57eca3aa8b3da5278310827 | |
parent | fix: handling of split CRLF sequences during text insertion (diff) | |
download | GpgFrontend-296de126739a0b0a1556f9f34533255c05634651.tar.gz GpgFrontend-296de126739a0b0a1556f9f34533255c05634651.zip |
feat: support verifying email through eml data
m--------- | modules | 0 | ||||
-rw-r--r-- | src/core/GpgConstants.h | 3 | ||||
-rw-r--r-- | src/ui/GpgFrontendUIInit.cpp | 2 | ||||
-rw-r--r-- | src/ui/UserInterfaceUtils.cpp | 6 | ||||
-rw-r--r-- | src/ui/dialog/keypair_details/KeyPairOperaTab.cpp | 6 | ||||
-rw-r--r-- | src/ui/main_window/MainWindow.h | 32 | ||||
-rw-r--r-- | src/ui/main_window/MainWindowFileSlotFunction.cpp | 32 | ||||
-rw-r--r-- | src/ui/main_window/MainWindowGpgOperaFunction.cpp | 78 | ||||
-rw-r--r-- | src/ui/main_window/MainWindowSlotFunction.cpp | 49 | ||||
-rw-r--r-- | src/ui/main_window/MainWindowSlotUI.cpp | 8 | ||||
-rw-r--r-- | src/ui/main_window/MainWindowUI.cpp | 24 |
11 files changed, 213 insertions, 27 deletions
diff --git a/modules b/modules -Subproject 9146f7ad486e34f52ad794db4c3085f913369a2 +Subproject 7238486de0c4f13f61626f0bccfc7502c45f979 diff --git a/src/core/GpgConstants.h b/src/core/GpgConstants.h index 7cf926cb..6945b27a 100644 --- a/src/core/GpgConstants.h +++ b/src/core/GpgConstants.h @@ -61,5 +61,8 @@ constexpr const char* kPinentryModuleID = "com.bktus.gpgfrontend.module.pinentry"; constexpr const char* kPaperKeyModuleID = "com.bktus.gpgfrontend.module.paper_key"; +constexpr const char* kKeyServerSyncModuleID = + "com.bktus.gpgfrontend.module.key_server_sync"; +constexpr const char* kEmailModuleID = "com.bktus.gpgfrontend.module.email"; } // namespace GpgFrontend diff --git a/src/ui/GpgFrontendUIInit.cpp b/src/ui/GpgFrontendUIInit.cpp index e93a8e3c..0baa1fbb 100644 --- a/src/ui/GpgFrontendUIInit.cpp +++ b/src/ui/GpgFrontendUIInit.cpp @@ -119,6 +119,8 @@ void PreInitGpgFrontendUI() { // declare module ui entry mount points UIModuleManager::GetInstance().DeclareMountPoint("AboutDialogTabs", "QWidget", {}); + UIModuleManager::GetInstance().DeclareMountPoint("GnuPGControllerDialogTabs", + "QWidget", {}); } void InitGpgFrontendUI(QApplication* /*app*/) { diff --git a/src/ui/UserInterfaceUtils.cpp b/src/ui/UserInterfaceUtils.cpp index 5c07e009..fc90fa7c 100644 --- a/src/ui/UserInterfaceUtils.cpp +++ b/src/ui/UserInterfaceUtils.cpp @@ -413,8 +413,7 @@ void CommonUtils::SlotImportKeyFromKeyServer( return; } - if (Module::IsModuleActivate( - "com.bktus.gpgfrontend.module.key_server_sync")) { + if (Module::IsModuleActivate(kKeyServerSyncModuleID)) { // LOOP decltype(key_ids.size()) current_index = 1; decltype(key_ids.size()) all_index = key_ids.size(); @@ -659,8 +658,7 @@ void CommonUtils::ImportKeyFromKeyServer(int channel, void CommonUtils::ImportKeyByKeyServerSyncModule(QWidget *parent, int channel, const QList<QString> &fprs) { - if (!Module::IsModuleActivate( - "com.bktus.gpgfrontend.module.key_server_sync")) { + if (!Module::IsModuleActivate(kKeyServerSyncModuleID)) { return; } diff --git a/src/ui/dialog/keypair_details/KeyPairOperaTab.cpp b/src/ui/dialog/keypair_details/KeyPairOperaTab.cpp index 35e93faf..ba3f299a 100644 --- a/src/ui/dialog/keypair_details/KeyPairOperaTab.cpp +++ b/src/ui/dialog/keypair_details/KeyPairOperaTab.cpp @@ -357,8 +357,7 @@ void KeyPairOperaTab::slot_modify_edit_datetime() { } void KeyPairOperaTab::slot_publish_key_to_server() { - if (Module::IsModuleActivate( - "com.bktus.gpgfrontend.module.key_server_sync")) { + if (Module::IsModuleActivate(kKeyServerSyncModuleID)) { auto [err, gf_buffer] = GpgKeyImportExporter::GetInstance(current_gpg_context_channel_) .ExportKey(m_key_, false, true, false); @@ -454,8 +453,7 @@ void KeyPairOperaTab::slot_publish_key_to_server() { } void KeyPairOperaTab::slot_update_key_from_server() { - if (Module::IsModuleActivate( - "com.bktus.gpgfrontend.module.key_server_sync")) { + if (Module::IsModuleActivate(kKeyServerSyncModuleID)) { CommonUtils::GetInstance()->ImportKeyByKeyServerSyncModule( this, current_gpg_context_channel_, {m_key_.GetFingerprint()}); return; diff --git a/src/ui/main_window/MainWindow.h b/src/ui/main_window/MainWindow.h index 6a5b081e..35620843 100644 --- a/src/ui/main_window/MainWindow.h +++ b/src/ui/main_window/MainWindow.h @@ -155,6 +155,20 @@ class MainWindow : public GeneralMainWindow { void SlotVerify(); /** + * @brief + * + * @param raw_data + * @param signature + */ + void SlotVerify(const QByteArray& raw_data, const QByteArray& signature); + + /** + * @brief + * + */ + void SlotVerifyEML(); + + /** * @details decrypt and verify the text of currently active textedit-page * with the currently checked keys */ @@ -204,6 +218,13 @@ class MainWindow : public GeneralMainWindow { * * @param path */ + void SlotFileVerifyEML(const QString& path); + + /** + * @brief + * + * @param path + */ void SlotFileEncryptSign(const QString& path); /** @@ -369,6 +390,12 @@ class MainWindow : public GeneralMainWindow { */ void slot_set_owner_trust_level_of_key(); + /** + * @brief + * + */ + void slot_verify_email_by_eml_data(const QByteArray& buffer); + private: /** * @details Create actions for the main-menu and the context-menu of the @@ -425,9 +452,7 @@ class MainWindow : public GeneralMainWindow { QMenu* key_menu_{}; ///< Submenu for key-operations QMenu* view_menu_{}; ///< Submenu for view operations QMenu* import_key_menu_{}; ///< Submenu for import operations -#ifdef SMTP_SUPPORT - QMenu* email_menu_{}; ///< Submenu for email operations -#endif + QMenu* email_menu_{}; ///< Submenu for email operations QToolBar* crypt_tool_bar_{}; ///< Toolbar holding crypt actions QToolBar* file_tool_bar_{}; ///< Toolbar holding file actions @@ -505,6 +530,7 @@ class MainWindow : public GeneralMainWindow { QAction* import_key_from_file_act_{}; ///< QAction* import_key_from_clipboard_act_{}; ///< QAction* import_key_from_key_server_act_{}; ///< + QAction* verify_email_by_eml_data_{}; ///< QLabel* status_bar_icon_{}; ///< diff --git a/src/ui/main_window/MainWindowFileSlotFunction.cpp b/src/ui/main_window/MainWindowFileSlotFunction.cpp index c85b616a..599fe4d6 100644 --- a/src/ui/main_window/MainWindowFileSlotFunction.cpp +++ b/src/ui/main_window/MainWindowFileSlotFunction.cpp @@ -556,8 +556,7 @@ void MainWindow::SlotFileVerify(const QString& path) { process_result_analyse(edit_, info_board_, result_analyse); if (!result_analyse.GetUnknownSignatures().isEmpty() && - Module::IsModuleActivate( - "com.bktus.gpgfrontend.module.key_server_sync")) { + Module::IsModuleActivate(kKeyServerSyncModuleID)) { LOG_D() << "try to sync missing key info from server" << result_analyse.GetUnknownSignatures(); @@ -901,8 +900,7 @@ void MainWindow::SlotFileDecryptVerify(const QString& path) { this->slot_refresh_current_file_view(); if (!verify_result_analyse.GetUnknownSignatures().isEmpty() && - Module::IsModuleActivate( - "com.bktus.gpgfrontend.module.key_server_sync")) { + Module::IsModuleActivate(kKeyServerSyncModuleID)) { LOG_D() << "try to sync missing key info from server" << verify_result_analyse.GetUnknownSignatures(); @@ -1018,4 +1016,30 @@ void MainWindow::SlotArchiveDecryptVerify(const QString& path) { }); } +void MainWindow::SlotFileVerifyEML(const QString& path) { + auto check_result = TargetFilePreCheck(path, true); + if (!std::get<0>(check_result)) { + QMessageBox::critical(this, tr("Error"), + tr("Cannot read from file: %1").arg(path)); + return; + } + + QFileInfo file_info(path); + if (file_info.size() > static_cast<qint64>(1024 * 1024 * 32)) { + QMessageBox::warning( + this, tr("EML File Too Large"), + tr("The EML file \"%1\" is larger than 32MB and will not be opened.") + .arg(file_info.fileName())); + return; + } + + QFile eml_file(path); + if (!eml_file.open(QIODevice::ReadOnly)) return; + auto buffer = eml_file.readAll(); + + // LOG_D() << "EML BUFFER (FILE): " << buffer; + + slot_verify_email_by_eml_data(buffer); +} + } // namespace GpgFrontend::UI diff --git a/src/ui/main_window/MainWindowGpgOperaFunction.cpp b/src/ui/main_window/MainWindowGpgOperaFunction.cpp index b8935efb..7a7c206c 100644 --- a/src/ui/main_window/MainWindowGpgOperaFunction.cpp +++ b/src/ui/main_window/MainWindowGpgOperaFunction.cpp @@ -291,8 +291,79 @@ void MainWindow::SlotVerify() { process_result_analyse(edit_, info_board_, result_analyse); if (!result_analyse.GetUnknownSignatures().isEmpty() && - Module::IsModuleActivate( - "com.bktus.gpgfrontend.module.key_server_sync")) { + Module::IsModuleActivate(kKeyServerSyncModuleID)) { + 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.")); + } + } + }); + }); +} + +void MainWindow::SlotVerify(const QByteArray& raw_data, + const QByteArray& signature) { + // set input buffer + auto raw_data_buffer = GFBuffer(raw_data); + auto signature_buffer = GFBuffer(signature); + + CommonUtils::WaitForOpera( + this, tr("Verifying"), + [this, raw_data_buffer, signature_buffer](const OperaWaitingHd& hd) { + GpgFrontend::GpgBasicOperator::GetInstance( + m_key_list_->GetCurrentGpgContextChannel()) + .Verify( + raw_data_buffer, signature_buffer, + [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(kKeyServerSyncModuleID)) { LOG_D() << "try to sync missing key info from server" << result_analyse.GetUnknownSignatures(); @@ -479,8 +550,7 @@ void MainWindow::SlotDecryptVerify() { } if (!verify_result_analyse.GetUnknownSignatures().isEmpty() && - Module::IsModuleActivate( - "com.bktus.gpgfrontend.module.key_server_sync")) { + Module::IsModuleActivate(kKeyServerSyncModuleID)) { LOG_D() << "try to sync missing key info from server" << verify_result_analyse.GetUnknownSignatures(); diff --git a/src/ui/main_window/MainWindowSlotFunction.cpp b/src/ui/main_window/MainWindowSlotFunction.cpp index 9a8e57d0..b4a59a14 100644 --- a/src/ui/main_window/MainWindowSlotFunction.cpp +++ b/src/ui/main_window/MainWindowSlotFunction.cpp @@ -338,4 +338,53 @@ void MainWindow::slot_refresh_current_file_view() { } } +void MainWindow::slot_import_key_from_edit() { + if (edit_->TabCount() == 0 || edit_->SlotCurPageTextEdit() == nullptr) return; + + CommonUtils::GetInstance()->SlotImportKeys( + this, m_key_list_->GetCurrentGpgContextChannel(), + edit_->CurTextPage()->GetTextPage()->toPlainText().toLatin1()); +} + +void MainWindow::slot_verify_email_by_eml_data(const QByteArray& buffer) { + Module::TriggerEvent( + "EMAIL_VERIFY_EML_DATA", + { + {"eml_data", QString::fromLatin1(buffer.toBase64())}, + }, + [=](Module::EventIdentifier i, Module::Event::ListenerIdentifier ei, + Module::Event::Params p) { + LOG_D() << "EMAIL_VERIFY_EML_DATA callback: " << i << ei; + if (p["ret"] != "0" || !p["error_msg"].isEmpty()) { + LOG_E() << "An error occurred trying to verify email, " + << "error message: " << p["error_msg"] + << "reply data: " << p["reply_data"]; + } else if (p.contains("signature") && p.contains("mime")) { + const auto mime = QByteArray::fromBase64(p["mime"].toLatin1()); + const auto signature = + QByteArray::fromBase64(p["signature"].toLatin1()); + + auto part_mime_content_hash = + QCryptographicHash::hash(mime, QCryptographicHash::Sha1); + LOG_D() << "get raw data of mime part, size:" << mime.size() + << "sha1 hash:" << part_mime_content_hash.toHex(); + + SlotVerify(mime, signature); + } else { + LOG_E() << "mime or signature data is missing"; + } + }); +} + +void MainWindow::SlotVerifyEML() { + if (edit_->TabCount() == 0 || edit_->SlotCurPageTextEdit() == nullptr) return; + + auto buffer = edit_->CurTextPage()->GetTextPage()->toPlainText().toLatin1(); + buffer = buffer.replace("\n", "\r\n"); + + // LOG_D() << "EML BUFFER: " << buffer; + + slot_verify_email_by_eml_data(buffer); +} + } // namespace GpgFrontend::UI diff --git a/src/ui/main_window/MainWindowSlotUI.cpp b/src/ui/main_window/MainWindowSlotUI.cpp index fc9ab850..3cf79eea 100644 --- a/src/ui/main_window/MainWindowSlotUI.cpp +++ b/src/ui/main_window/MainWindowSlotUI.cpp @@ -50,14 +50,6 @@ void MainWindow::slot_start_wizard() { wizard->setModal(true); } -void MainWindow::slot_import_key_from_edit() { - if (edit_->TabCount() == 0 || edit_->SlotCurPageTextEdit() == nullptr) return; - - CommonUtils::GetInstance()->SlotImportKeys( - this, m_key_list_->GetCurrentGpgContextChannel(), - edit_->CurTextPage()->GetTextPage()->toPlainText().toLatin1()); -} - void MainWindow::slot_open_key_management() { auto* dialog = new KeyMgmt(this); dialog->setWindowModality(Qt::ApplicationModal); diff --git a/src/ui/main_window/MainWindowUI.cpp b/src/ui/main_window/MainWindowUI.cpp index 151e5cfa..70bf300b 100644 --- a/src/ui/main_window/MainWindowUI.cpp +++ b/src/ui/main_window/MainWindowUI.cpp @@ -422,6 +422,25 @@ void MainWindow::create_actions() { connect(module_controller_open_act_, &QAction::triggered, this, [this]() { (new ModuleControllerDialog(this))->exec(); }); + /** + * E-Mmail Menu + */ + if (Module::IsModuleActivate(kEmailModuleID)) { + verify_email_by_eml_data_ = new QAction(tr("Verify E-Mail"), this); + verify_email_by_eml_data_->setIcon(QIcon(":/icons/verify.png")); + verify_email_by_eml_data_->setToolTip(tr("Verify RAW E-Mail Data (EML)")); + connect(verify_email_by_eml_data_, &QAction::triggered, this, [this]() { + if (edit_->SlotCurPageFileTreeView() != nullptr) { + const auto* file_tree_view = edit_->SlotCurPageFileTreeView(); + const auto path = file_tree_view->GetSelected(); + + const auto file_info = QFileInfo(path); + if (file_info.isFile()) this->SlotFileVerifyEML(path); + } + if (edit_->SlotCurPageTextEdit() != nullptr) this->SlotVerifyEML(); + }); + } + /* * About Menu */ @@ -619,6 +638,11 @@ void MainWindow::create_menus() { advance_menu_->addAction(gnupg_controller_open_act_); advance_menu_->addAction(module_controller_open_act_); + if (Module::IsModuleActivate(kEmailModuleID)) { + email_menu_ = menuBar()->addMenu(tr("E-Mail")); + email_menu_->addAction(verify_email_by_eml_data_); + } + view_menu_ = menuBar()->addMenu(tr("View")); help_menu_ = menuBar()->addMenu(tr("Help")); |