aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsaturneric <[email protected]>2024-11-25 22:42:25 +0000
committersaturneric <[email protected]>2024-11-25 22:42:25 +0000
commit296de126739a0b0a1556f9f34533255c05634651 (patch)
tree8dd47144081f47d9e57eca3aa8b3da5278310827
parentfix: handling of split CRLF sequences during text insertion (diff)
downloadGpgFrontend-296de126739a0b0a1556f9f34533255c05634651.tar.gz
GpgFrontend-296de126739a0b0a1556f9f34533255c05634651.zip
feat: support verifying email through eml data
m---------modules0
-rw-r--r--src/core/GpgConstants.h3
-rw-r--r--src/ui/GpgFrontendUIInit.cpp2
-rw-r--r--src/ui/UserInterfaceUtils.cpp6
-rw-r--r--src/ui/dialog/keypair_details/KeyPairOperaTab.cpp6
-rw-r--r--src/ui/main_window/MainWindow.h32
-rw-r--r--src/ui/main_window/MainWindowFileSlotFunction.cpp32
-rw-r--r--src/ui/main_window/MainWindowGpgOperaFunction.cpp78
-rw-r--r--src/ui/main_window/MainWindowSlotFunction.cpp49
-rw-r--r--src/ui/main_window/MainWindowSlotUI.cpp8
-rw-r--r--src/ui/main_window/MainWindowUI.cpp24
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"));