From da105c4ae189f63b74e4f2df96031caffba68afc Mon Sep 17 00:00:00 2001 From: saturneric Date: Wed, 27 Nov 2024 23:41:40 +0100 Subject: [PATCH] feat: support email encryption --- src/m_email/EMailMetaDataDialog.cpp | 435 ++++++++++++++++++++++++++-- src/m_email/EMailMetaDataDialog.h | 40 ++- src/m_email/EMailMetaDataDialog.ui | 434 ++++++++++----------------- src/m_email/EMailModule.cpp | 56 +++- 4 files changed, 654 insertions(+), 311 deletions(-) diff --git a/src/m_email/EMailMetaDataDialog.cpp b/src/m_email/EMailMetaDataDialog.cpp index 11583b9..d3ef010 100644 --- a/src/m_email/EMailMetaDataDialog.cpp +++ b/src/m_email/EMailMetaDataDialog.cpp @@ -41,6 +41,9 @@ static const QRegularExpression kNameEmailStringRegex{ R"(^\s*(.*)\s*<\s*([^<>@\s]+@[^<>@\s]+)\s*>\s*$)"}; +static const QRegularExpression kNameEmailStringValidateRegex( + R"(^\s*(.*\s*)?<\s*([a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+)\s*>\s*$|(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$))"); + auto ParseEmailString(const QString& input, QString& name, QString& email) -> bool { QRegularExpressionMatch match = kNameEmailStringRegex.match(input); @@ -69,14 +72,42 @@ class ContentTypeField : public vmime::contentTypeField { ContentTypeField() = default; }; -EMailMetaDataDialog::EMailMetaDataDialog(QByteArray body_data, QWidget* parent) +EMailMetaDataDialog::EMailMetaDataDialog(int mode, QWidget* parent) : QDialog(parent), ui_(QSharedPointer::create()), - body_data_(std::move(body_data)) { + mode_(mode) { ui_->setupUi(this); - connect(ui_->exportMailButton, &QPushButton::clicked, this, - &EMailMetaDataDialog::slot_export_eml_data); + ui_->ccEdit->setHidden(true); + ui_->ccLabel->setHidden(true); + ui_->bccEdit->setHidden(true); + ui_->bccLabel->setHidden(true); + + if (mode == 0) { + connect(ui_->okButton, &QPushButton::clicked, this, + &EMailMetaDataDialog::slot_sign_eml_data); + } else { + connect(ui_->okButton, &QPushButton::clicked, this, + &EMailMetaDataDialog::slot_encrypt_eml_data); + } + + connect(ui_->cancelButton, &QPushButton::clicked, this, &QDialog::close); + + connect(ui_->ccButton, &QPushButton::clicked, this, [this]() { + ui_->ccEdit->setHidden(!ui_->ccEdit->isHidden()); + ui_->ccLabel->setHidden(!ui_->ccLabel->isHidden()); + }); + + connect(ui_->bccButton, &QPushButton::clicked, this, [this]() { + ui_->bccEdit->setHidden(!ui_->bccEdit->isHidden()); + ui_->bccLabel->setHidden(!ui_->bccLabel->isHidden()); + }); + + connect(this, &EMailMetaDataDialog::SignalEMLDataGenerateSuccess, this, + &QDialog::close); + + connect(this, &EMailMetaDataDialog::SignalEMLDataGenerateFailed, this, + &QDialog::close); setModal(true); setAttribute(Qt::WA_DeleteOnClose); @@ -85,13 +116,20 @@ EMailMetaDataDialog::EMailMetaDataDialog(QByteArray body_data, QWidget* parent) Q_VARIANT_Q_OBJECT_FACTORY_DEFINE(CreateEMailMetaDataDialog, [](QVariant data) -> void* { - return new EMailMetaDataDialog( - data.toByteArray(), nullptr); + return new EMailMetaDataDialog(data.toInt(), + nullptr); }); -void EMailMetaDataDialog::slot_export_eml_data() { +void EMailMetaDataDialog::slot_sign_eml_data() { // sign key is a must - if (sign_key_.isEmpty()) emit SignalEMLDataGenerateFailed("No Sign Key"); + if (keys_.isEmpty()) emit SignalEMLDataGenerateFailed("No Sign Key"); + + // only allow one sign key + const auto sign_key = keys_.front(); + + // validate + slot_validate_inputs_and_show_errors(); + if (!ui_->errorLabel->text().trimmed().isEmpty()) return; auto from = ui_->fromEdit->text(); auto to = ui_->toEdit->text(); @@ -203,7 +241,7 @@ void EMailMetaDataDialog::slot_export_eml_data() { auto public_key_part_header = public_key_part->getHeader(); - auto public_key_name = QString("OpenPGP_0x%1.asc").arg(sign_key_.toUpper()); + auto public_key_name = QString("OpenPGP_0x%1.asc").arg(sign_key.toUpper()); auto public_key_part_content_type_header_field = public_key_part_header->getField( vmime::fields::CONTENT_TYPE); @@ -250,7 +288,7 @@ void EMailMetaDataDialog::slot_export_eml_data() { signature_part_content_disp_header_field->setFilename( vmime::word({"OpenPGP_signature.asc"})); - auto public_key = UDUP(GFGpgPublicKey(channel_, QDUP(sign_key_), 1)); + auto public_key = UDUP(GFGpgPublicKey(channel_, QDUP(sign_key), 1)); if (public_key.isEmpty()) { emit SignalEMLDataGenerateFailed("Get Public Key of Sign Key Failed"); return; @@ -287,24 +325,19 @@ void EMailMetaDataDialog::slot_export_eml_data() { mime_part_part_body->setContents(mime_part_body_content); auto container_raw_data = - container_part->generate(vmime::lineLengthLimits::infinite); - qDebug().noquote() << "\n" << container_raw_data; + Q_SC(container_part->generate(vmime::lineLengthLimits::infinite)); - container_raw_data = - container_part->generate(vmime::lineLengthLimits::infinite); - qDebug().noquote() << "\n" << container_raw_data; - - auto container_raw_data_hash = - QCryptographicHash::hash(container_raw_data, QCryptographicHash::Sha1); + auto container_raw_data_hash = QCryptographicHash::hash( + container_raw_data.toLatin1(), QCryptographicHash::Sha1); FLOG_DEBUG("raw content of signature hash: %1", container_raw_data_hash.toHex()); FLOG_DEBUG("MIME Raw Data For Signature: %1", container_raw_data); - FLOG_DEBUG("Signature Channel: %1, Sign Key: %2", channel_, sign_key_); + FLOG_DEBUG("Signature Channel: %1, Sign Key: %2", channel_, sign_key); GFGpgSignResult* s; - auto ret = GFGpgSignData(channel_, QListToCharArray({sign_key_}), 1, - QDUP(Q_SC(container_raw_data)), 1, 1, &s); + auto ret = GFGpgSignData(channel_, QListToCharArray({sign_key}), 1, + QDUP(container_raw_data), 1, 1, &s); if (ret != 0) { emit SignalEMLDataGenerateFailed("Sign Failed"); @@ -350,18 +383,26 @@ void EMailMetaDataDialog::slot_export_eml_data() { void EMailMetaDataDialog::slot_export_encrypted_data() {} -void EMailMetaDataDialog::SetSignKey(QString k) { - sign_key_ = std::move(k); - slot_set_from_field_by_sign_key(); +void EMailMetaDataDialog::SetKeys(QStringList k) { + keys_ = std::move(k); + + if (mode_ == 0) { + slot_set_from_field_by_sign_key(); + } else { + slot_set_to_field_by_encrypt_keys(); + } } void EMailMetaDataDialog::SetChannel(int c) { channel_ = c; } void EMailMetaDataDialog::slot_set_from_field_by_sign_key() { + // only allow one sign key + const auto sign_key = keys_.front(); + GFGpgKeyUID* s; - auto ret = GFGpgKeyPrimaryUID(channel_, QDUP(sign_key_), &s); + auto ret = GFGpgKeyPrimaryUID(channel_, QDUP(sign_key), &s); if (ret != 0) { - FLOG_WARN("cannot get primary uid from sign key %1, ret: %2", sign_key_, + FLOG_WARN("cannot get primary uid from sign key %1, ret: %2", sign_key, ret); return; } @@ -374,3 +415,345 @@ void EMailMetaDataDialog::slot_set_from_field_by_sign_key() { ui_->fromEdit->setText(QString("%1 <%2>").arg(from_name_).arg(from_email_)); } + +void EMailMetaDataDialog::slot_validate_inputs_and_show_errors() { + QString error_message; + + if (ui_->fromEdit->text().trimmed().isEmpty()) { + error_message = tr("The 'From' field cannot be empty."); + } else if (!is_valid_email(ui_->fromEdit->text().trimmed())) { + error_message = tr("The 'From' field must contain a valid email address."); + } + + if (error_message.isEmpty() && ui_->toEdit->text().trimmed().isEmpty()) { + error_message = tr("The 'To' field cannot be empty."); + } else if (error_message.isEmpty() && + !are_valid_emails(ui_->toEdit->text())) { + error_message = + tr("One or more 'To' addresses are invalid. Please separate multiple " + "addresses with \";\"."); + } + + if (error_message.isEmpty() && !ui_->ccEdit->text().trimmed().isEmpty()) { + if (!are_valid_emails(ui_->ccEdit->text())) { + error_message = + tr("One or more 'CC' addresses are invalid. Please separate " + "multiple addresses with \";\"."); + } + } + + if (error_message.isEmpty() && !ui_->bccEdit->text().trimmed().isEmpty()) { + if (!are_valid_emails(ui_->bccEdit->text())) { + error_message = + tr("One or more 'BCC' addresses are invalid. Please separate " + "multiple addresses with \";\"."); + } + } + + if (error_message.isEmpty() && ui_->subjectEdit->text().trimmed().isEmpty()) { + error_message = tr("The 'Subject' field cannot be empty."); + } + + if (!error_message.isEmpty()) { + ui_->errorLabel->setText(error_message); + ui_->errorLabel->setStyleSheet("QLabel { color : red; }"); + } else { + ui_->errorLabel->clear(); + } +} + +auto EMailMetaDataDialog::are_valid_emails(const QString& emails) -> bool { + QStringList email_list = emails.split(';', Qt::SkipEmptyParts); + for (const QString& email : email_list) { + if (!is_valid_email(email.trimmed())) { + return false; + } + } + return true; +} + +auto EMailMetaDataDialog::is_valid_email(const QString& email) -> bool { + return kNameEmailStringValidateRegex.match(email).hasMatch(); +} + +void EMailMetaDataDialog::SetBodyData(QByteArray b) { + body_data_ = std::move(b); +} + +void EMailMetaDataDialog::slot_encrypt_eml_data() { + if (keys_.isEmpty()) { + emit SignalEMLDataGenerateFailed("No Encryption Key Selected"); + return; + } + + const auto encrypt_key = keys_.front(); + + slot_validate_inputs_and_show_errors(); + if (!ui_->errorLabel->text().trimmed().isEmpty()) { + return; + } + + auto from = ui_->fromEdit->text(); + auto to = ui_->toEdit->text(); + auto cc = ui_->ccEdit->text(); + auto bcc = ui_->bccEdit->text(); + auto subject = ui_->subjectEdit->text(); + + auto recipient_list = to.split(';', Qt::SkipEmptyParts); + auto cc_list = cc.split(';', Qt::SkipEmptyParts); + auto bcc_list = bcc.split(';', Qt::SkipEmptyParts); + + QString name; + QString email; + + try { + vmime::messageBuilder plaintext_msg_builder; + + if (ParseEmailString(from, name, email)) { + plaintext_msg_builder.setExpeditor( + vmime::mailbox(vmime::text(name.toStdString()), email.toStdString())); + } else { + plaintext_msg_builder.setExpeditor(vmime::mailbox(from.toStdString())); + } + + for (const QString& recipient : recipient_list) { + auto trimmed_recipient = recipient.trimmed(); + if (ParseEmailString(trimmed_recipient, name, email)) { + plaintext_msg_builder.getRecipients().appendAddress( + vmime::make_shared(vmime::text(name.toStdString()), + email.toStdString())); + } else { + plaintext_msg_builder.getRecipients().appendAddress( + vmime::make_shared( + trimmed_recipient.toStdString())); + } + } + + for (const QString& recipient : cc_list) { + auto trimmed_recipient = recipient.trimmed(); + if (ParseEmailString(trimmed_recipient, name, email)) { + plaintext_msg_builder.getCopyRecipients().appendAddress( + vmime::make_shared(vmime::text(name.toStdString()), + email.toStdString())); + } else { + plaintext_msg_builder.getCopyRecipients().appendAddress( + vmime::make_shared( + trimmed_recipient.toStdString())); + } + } + + for (const QString& recipient : bcc_list) { + auto trimmed_recipient = recipient.trimmed(); + if (ParseEmailString(trimmed_recipient, name, email)) { + plaintext_msg_builder.getBlindCopyRecipients().appendAddress( + vmime::make_shared(vmime::text(name.toStdString()), + email.toStdString())); + } else { + plaintext_msg_builder.getBlindCopyRecipients().appendAddress( + vmime::make_shared( + trimmed_recipient.toStdString())); + } + } + + plaintext_msg_builder.setSubject(vmime::text(subject.toStdString())); + + vmime::shared_ptr plaintext_msg = + plaintext_msg_builder.construct(); + + auto plaintext_msg_header = plaintext_msg->getHeader(); + + auto plaintext_msg_content_type_header_field = + plaintext_msg_header->getField( + vmime::fields::CONTENT_TYPE); + plaintext_msg_content_type_header_field->setValue("text/plain"); + plaintext_msg_content_type_header_field->appendParameter( + vmime::make_shared("charset", "UTF-8")); + plaintext_msg_content_type_header_field->appendParameter( + vmime::make_shared("format", "flowed")); + + auto plaintext_msg_content_trans_encode_field = + plaintext_msg_header->getField( + vmime::fields::CONTENT_TRANSFER_ENCODING); + plaintext_msg_content_trans_encode_field->setValue("base64"); + + auto plaintext_msg_body = plaintext_msg->getBody(); + + auto mime_part_body_content = + vmime::make_shared(); + mime_part_body_content->setData( + body_data_.toBase64().toStdString(), + vmime::encoding(vmime::encodingTypes::BASE64)); + plaintext_msg_body->setContents(mime_part_body_content); + + auto plaintext_eml_data = + Q_SC(plaintext_msg->generate(vmime::lineLengthLimits::infinite)); + + GFGpgEncryptionResult* enc_result = nullptr; + auto ret = GFGpgEncryptData(channel_, QListToCharArray(keys_), keys_.size(), + QDUP(plaintext_eml_data), 1, &enc_result); + + if (ret != 0) { + emit SignalEMLDataGenerateFailed("Encryption Failed"); + return; + } + + auto encrypted_data = UDUP(enc_result->encrypted_data); + GFFreeMemory(enc_result); + + vmime::messageBuilder msg_builder; + + if (ParseEmailString(from, name, email)) { + msg_builder.setExpeditor(vmime::mailbox(email.toStdString())); + } else { + msg_builder.setExpeditor(vmime::mailbox(from.toStdString())); + } + + for (const QString& recipient : recipient_list) { + auto trimmed_recipient = recipient.trimmed(); + if (ParseEmailString(trimmed_recipient, name, email)) { + msg_builder.getRecipients().appendAddress( + vmime::make_shared(email.toStdString())); + } else { + msg_builder.getRecipients().appendAddress( + vmime::make_shared( + trimmed_recipient.toStdString())); + } + } + + for (const QString& recipient : cc_list) { + auto trimmed_recipient = recipient.trimmed(); + if (ParseEmailString(trimmed_recipient, name, email)) { + msg_builder.getCopyRecipients().appendAddress( + vmime::make_shared(email.toStdString())); + } else { + msg_builder.getCopyRecipients().appendAddress( + vmime::make_shared( + trimmed_recipient.toStdString())); + } + } + + for (const QString& recipient : bcc_list) { + auto trimmed_recipient = recipient.trimmed(); + if (ParseEmailString(trimmed_recipient, name, email)) { + msg_builder.getBlindCopyRecipients().appendAddress( + vmime::make_shared(email.toStdString())); + } else { + msg_builder.getBlindCopyRecipients().appendAddress( + vmime::make_shared( + trimmed_recipient.toStdString())); + } + } + + msg_builder.setSubject(vmime::text("...")); + + vmime::shared_ptr msg = msg_builder.construct(); + + auto header = msg->getHeader(); + + // no Content-Transfer-Encoding + header->removeField( + header->getField(vmime::fields::CONTENT_TRANSFER_ENCODING)); + + auto content_type_header_field = + header->getField(vmime::fields::CONTENT_TYPE); + content_type_header_field->setValue("multipart/encrypted"); + content_type_header_field->appendParameter( + vmime::make_shared("protocol", + "application/pgp-encrypted")); + + auto root_part_boundary = vmime::body::generateRandomBoundaryString(); + content_type_header_field->setBoundary(root_part_boundary); + + auto root_body_part = vmime::make_shared(); + auto control_info_part = vmime::make_shared(); + auto encrypted_data_part = vmime::make_shared(); + + root_body_part->appendPart(control_info_part); + root_body_part->appendPart(encrypted_data_part); + msg->setBody(root_body_part); + + root_body_part->setPrologText( + "This is an OpenPGP/MIME encrypted message (RFC 4880 and 3156)"); + + auto control_info_part_header = control_info_part->getHeader(); + auto control_info_content_type_field = + control_info_part_header->getField( + vmime::fields::CONTENT_TYPE); + control_info_content_type_field->setValue("application/pgp-encrypted"); + + auto control_info_part_content_desc_header_field = + control_info_part_header->getField(vmime::fields::CONTENT_DESCRIPTION); + control_info_part_content_desc_header_field->setValue( + "PGP/MIME version identification"); + + auto control_info_body = control_info_part->getBody(); + auto control_info_content = + vmime::make_shared("Version: 1"); + control_info_body->setContents(control_info_content); + + auto encrypted_data_part_header = encrypted_data_part->getHeader(); + auto encrypted_data_content_type_field = + encrypted_data_part_header->getField( + vmime::fields::CONTENT_TYPE); + encrypted_data_content_type_field->setValue("application/octet-stream"); + encrypted_data_content_type_field->appendParameter( + vmime::make_shared("name", "encrypted.asc")); + + auto encrypted_data_content_desc_header_field = + encrypted_data_part_header->getField( + vmime::fields::CONTENT_DESCRIPTION); + encrypted_data_content_desc_header_field->setValue( + "OpenPGP encrypted message"); + + auto encrypted_data_content_disp_header_field = + encrypted_data_part_header->getField( + vmime::fields::CONTENT_DISPOSITION); + encrypted_data_content_disp_header_field->setValue("inline"); + encrypted_data_content_disp_header_field->setFilename( + vmime::word({"encrypted.asc"})); + + auto encrypted_data_body = encrypted_data_part->getBody(); + auto encrypted_data_content = + vmime::make_shared( + encrypted_data.toStdString()); + encrypted_data_body->setContents(encrypted_data_content); + + auto eml_data = Q_SC(msg->generate(vmime::lineLengthLimits::infinite)); + FLOG_DEBUG("EML Data: %1", eml_data); + + emit SignalEMLDataGenerateSuccess(eml_data); + + return; + + } catch (const vmime::exception& e) { + QMessageBox::critical(this, tr("Error"), + tr("Failed to export EML Data: %1").arg(e.what())); + emit SignalEMLDataGenerateFailed(e.what()); + return; + } + + emit SignalEMLDataGenerateFailed("Unknown Error"); +} + +void EMailMetaDataDialog::slot_set_to_field_by_encrypt_keys() { + QStringList to_list; + + for (const auto& key : keys_) { + GFGpgKeyUID* s; + auto ret = GFGpgKeyPrimaryUID(channel_, QDUP(key), &s); + if (ret != 0) { + FLOG_WARN("cannot get primary uid from sign key %1, ret: %2", key, ret); + continue; + } + + from_name_ = UDUP(s->name); + from_email_ = UDUP(s->email); + auto comment = UDUP(s->comment); + + GFFreeMemory(s); + + to_list.append(QString("%1 <%2>").arg(from_name_).arg(from_email_)); + } + + ui_->toEdit->setText(to_list.join("; ")); +} \ No newline at end of file diff --git a/src/m_email/EMailMetaDataDialog.h b/src/m_email/EMailMetaDataDialog.h index 983dc0a..c4ce5e4 100644 --- a/src/m_email/EMailMetaDataDialog.h +++ b/src/m_email/EMailMetaDataDialog.h @@ -39,7 +39,7 @@ class Ui_EMailMetaDataDialog; class EMailMetaDataDialog : public QDialog { Q_OBJECT public: - explicit EMailMetaDataDialog(QByteArray body_data, QWidget *parent); + explicit EMailMetaDataDialog(int mode, QWidget* parent); /** * @brief Set the Channel object @@ -51,7 +51,14 @@ class EMailMetaDataDialog : public QDialog { * @brief Set the Sign Keys object * */ - void SetSignKey(QString k); + void SetKeys(QStringList ks); + + /** + * @brief Set the Body Data object + * + * @param b + */ + void SetBodyData(QByteArray b); signals: @@ -61,17 +68,42 @@ class EMailMetaDataDialog : public QDialog { private slots: - void slot_export_eml_data(); + void slot_sign_eml_data(); + + void slot_encrypt_eml_data(); void slot_export_encrypted_data(); void slot_set_from_field_by_sign_key(); + void slot_set_to_field_by_encrypt_keys(); + + void slot_validate_inputs_and_show_errors(); + private: + /** + * @brief + * + * @param email + * @return true + * @return false + */ + static auto is_valid_email(const QString& email) -> bool; + + /** + * @brief + * + * @param emails + * @return true + * @return false + */ + static auto are_valid_emails(const QString& emails) -> bool; + QSharedPointer ui_; + int mode_; QByteArray body_data_; int channel_; - QString sign_key_; + QStringList keys_; QString from_name_; QString from_email_; }; diff --git a/src/m_email/EMailMetaDataDialog.ui b/src/m_email/EMailMetaDataDialog.ui index 977a535..ea503f8 100644 --- a/src/m_email/EMailMetaDataDialog.ui +++ b/src/m_email/EMailMetaDataDialog.ui @@ -6,8 +6,8 @@ 0 0 - 599 - 522 + 525 + 346 @@ -26,255 +26,111 @@ false - + + 5 + + + 5 + + + 5 + + + 5 + + - - - - 6 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - From - - - 5 - - - - - - - - - - 0 - - - false - - - 2 - - - Qt::Orientation::Vertical - - - - - - - CC - - - true - - - - - - - BCC - - - true - - - - - + + + + + + 50 + 0 + + + + From + + + 5 + + + + + + + - - - - 6 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - To - - - 5 - - - - - - - - - - Edit Recipients(s) - - - - - + + + + + + 50 + 0 + + + + To + + + 5 + + + + + + + - - - Qt::Orientation::Horizontal - - + + + + + + 50 + 0 + + + + CC + + + 5 + + + + + + + - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Subject - - - 5 - - - - - - - - - - - - - Qt::Orientation::Horizontal - - - - - - - - 6 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - CC - - - 5 - - - - - - - - - - Edit CC(s) - - - - - - - - - - - 6 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - BCC - - - 5 - - - - - - - - - - Edit BCC(s) - - - - - - - - - - Tips: You can fill in multiple email addresses, please separate them with ";". - - + + + + + + 50 + 0 + + + + BCC + + + 5 + + + + + + + @@ -284,37 +140,57 @@ - - - - - - + + + + + + 50 + 0 + + - GPG Keys: + Subject + + + 5 - - - - 0 - 0 - - - - - - - true + + + + 0 + 0 + - + + + Tips: You can fill in multiple email addresses, please separate them with ";", except for the 'From' field. + + + true + + + + + + + Qt::Orientation::Vertical + + + + 20 + 40 + + + @@ -323,22 +199,19 @@ - - - - Qt::Orientation::Horizontal - - - - + - Encrypt + CC - - true + + + + + + BCC @@ -355,10 +228,17 @@ - - + + - Export + Cancel + + + + + + + OK diff --git a/src/m_email/EMailModule.cpp b/src/m_email/EMailModule.cpp index 1262c75..ee46bb9 100644 --- a/src/m_email/EMailModule.cpp +++ b/src/m_email/EMailModule.cpp @@ -65,7 +65,8 @@ auto GFRegisterModule() -> int { LISTEN("EMAIL_VERIFY_EML_DATA"); LISTEN("EMAIL_DECRYPT_EML_DATA"); - LISTEN("EMAIL_EXPORT_EML_DATA"); + LISTEN("EMAIL_SIGN_EML_DATA"); + LISTEN("EMAIL_ENCRYPT_EML_DATA"); return 0; } @@ -405,7 +406,7 @@ REGISTER_EVENT_HANDLER(EMAIL_DECRYPT_EML_DATA, [](const MEvent& event) -> int { return 0; }); -REGISTER_EVENT_HANDLER(EMAIL_EXPORT_EML_DATA, [](const MEvent& event) -> int { +REGISTER_EVENT_HANDLER(EMAIL_SIGN_EML_DATA, [](const MEvent& event) -> int { if (event["body_data"].isEmpty()) CB_ERR(event, -1, "body_data is empty"); if (event["channel"].isEmpty()) CB_ERR(event, -1, "channel is empty"); if (event["sign_key"].isEmpty()) CB_ERR(event, -1, "sign_key is empty"); @@ -417,13 +418,15 @@ REGISTER_EVENT_HANDLER(EMAIL_EXPORT_EML_DATA, [](const MEvent& event) -> int { auto data = QByteArray::fromBase64(QString(event["body_data"]).toLatin1()); - auto* dialog = GUI_OBJECT(CreateEMailMetaDataDialog, {data}); + auto* dialog = GUI_OBJECT(CreateEMailMetaDataDialog, 0); auto* r_dialog = qobject_cast(static_cast(dialog)); if (r_dialog == nullptr) CB_ERR(event, -1, "convert dialog to r_dialog failed"); + r_dialog->SetChannel(channel); - r_dialog->SetSignKey(sign_key); + r_dialog->SetKeys({sign_key}); + r_dialog->SetBodyData({data}); GFUIShowDialog(dialog, nullptr); @@ -445,6 +448,51 @@ REGISTER_EVENT_HANDLER(EMAIL_EXPORT_EML_DATA, [](const MEvent& event) -> int { return 0; }); + +REGISTER_EVENT_HANDLER(EMAIL_ENCRYPT_EML_DATA, [](const MEvent& event) -> int { + if (event["body_data"].isEmpty()) CB_ERR(event, -1, "body_data is empty"); + if (event["channel"].isEmpty()) CB_ERR(event, -1, "channel is empty"); + if (event["encrypt_keys"].isEmpty()) + CB_ERR(event, -1, "encrypt_keys is empty"); + + auto channel = event.value("channel", "0").toInt(); + auto encrypt_keys = event.value("encrypt_keys", "").split(';'); + + FLOG_DEBUG("eml encrypt keys: %1", encrypt_keys.join(';')); + + auto data = QByteArray::fromBase64(QString(event["body_data"]).toLatin1()); + + auto* dialog = GUI_OBJECT(CreateEMailMetaDataDialog, 1); + auto* r_dialog = + qobject_cast(static_cast(dialog)); + if (r_dialog == nullptr) + CB_ERR(event, -1, "convert dialog to r_dialog failed"); + + r_dialog->SetChannel(channel); + r_dialog->SetKeys(encrypt_keys); + r_dialog->SetBodyData({data}); + + GFUIShowDialog(dialog, nullptr); + + QObject::connect(r_dialog, &EMailMetaDataDialog::SignalEMLDataGenerateSuccess, + r_dialog, [=](QString eml_data) { + // callback + CB(event, GFGetModuleID(), + { + {"ret", QString::number(0)}, + {"eml_data", eml_data}, + }); + }); + + QObject::connect(r_dialog, &EMailMetaDataDialog::SignalEMLDataGenerateFailed, + r_dialog, [=](QString error) { + // callback + CB_ERR(event, -1, "Generate EML Data Failed: " + error); + }); + + return 0; +}); + auto GFDeactivateModule() -> int { return 0; } auto GFUnregisterModule() -> int {