diff --git a/.gitmodules b/.gitmodules index 83943df..57e7597 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "src/m_email/vmime"] path = src/m_email/vmime - url = https://github.com/kisli/vmime.git + url = https://git.bktus.com/GpgFrontend/vmime.git diff --git a/src/m_email/EMAilHelper.cpp b/src/m_email/EMAilHelper.cpp index 7d19dad..ff9c0b7 100644 --- a/src/m_email/EMAilHelper.cpp +++ b/src/m_email/EMAilHelper.cpp @@ -64,7 +64,7 @@ auto ExtractFieldValue(const vmime::shared_ptr& header, auto field_value = field->getValue(); if (!field_value) { - FLOG_WARN("cannot get '%s' Field Value from header", field_name); + FLOG_WARN("cannot get '%1' Field Value from header", field_name); return {}; } @@ -81,7 +81,7 @@ auto ExtractFieldValueMailBox(const vmime::shared_ptr& header, auto field_value = field->getValue(); if (!field_value) { - FLOG_WARN("cannot get '%s' Field Value from header", field_name); + FLOG_WARN("cannot get '%1' Field Value from header", field_name); return {}; } @@ -99,7 +99,7 @@ auto ExtractFieldValueAddressList( auto field_value = field->getValue(); if (!field_value) { - FLOG_WARN("cannot get '%s' Field Value from header", field_name); + FLOG_WARN("cannot get '%1' Field Value from header", field_name); return {}; } @@ -114,6 +114,8 @@ auto ExtractFieldValueAddressList( auto ExtractFieldValueText(const vmime::shared_ptr& header, const QString& field_name) -> QString { + if (!header->hasField(field_name.toStdString())) return {}; + auto field = header->getField(field_name.toStdString()); if (!field) { FLOG_WARN("cannot get '%1' Field from header", field_name); @@ -122,7 +124,7 @@ auto ExtractFieldValueText(const vmime::shared_ptr& header, auto field_value = field->getValue(); if (!field_value) { - FLOG_WARN("cannot get '%s' Field Value from header", field_name); + FLOG_WARN("cannot get '%1' Field Value from header", field_name); return {}; } @@ -139,7 +141,7 @@ auto ExtractFieldValueDateTime(const vmime::shared_ptr& header, auto field_value = field->getValue(); if (!field_value) { - FLOG_WARN("cannot get '%s' Field Value from header", field_name); + FLOG_WARN("cannot get '%1' Field Value from header", field_name); return {}; } @@ -167,4 +169,162 @@ auto ParseEmailString(const QString& input, QString& name, } return false; +} + +auto EncodeBase64WithLineBreaks(const QByteArray& data, + int line_length) -> QString { + // Get the Base64 encoded data + QByteArray base64_data = data.toBase64(); + + // Split the base64 data into lines of the given line length + QStringList lines; + for (int i = 0; i < base64_data.size(); i += line_length) { + lines.append(base64_data.mid(i, line_length)); + } + + // Join lines with CRLF + return lines.join("\r\n"); +} + +auto CheckIfEMLMessage(const QByteArray& data, + vmime::shared_ptr& message) -> bool { + vmime::string vmime_data(data.constData(), data.size()); + + message = vmime::make_shared(); + try { + message->parse(vmime_data); + return message->getParsedLength() != 0 && !message->getHeader()->isEmpty(); + } catch (const vmime::exception& e) { + FLOG_DEBUG("error occurred when parsing vmime data: %1", e.what()); + return false; + } +} + +auto BuildPlainTextEML(const EMailMetaData& meta_data, + const QByteArray& body_data, QString& eml_data) -> int { + auto from = meta_data.from; + auto recipient_list = meta_data.to; + auto cc_list = meta_data.cc; + auto bcc_list = meta_data.bcc; + auto subject = meta_data.subject; + + 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.toStdString()); + plaintext_msg_body->setContents(mime_part_body_content); + + eml_data = + Q_SC(plaintext_msg->generate(vmime::lineLengthLimits::convenient)); + return 0; + + } catch (const vmime::exception& e) { + eml_data = QString("VMIME Error: %1").arg(e.what()); + return -1; + } +} + +auto GetMetaData(QByteArray& data, EMailMetaData& meta_data) {} + +auto GetEMLMetaData(vmime::shared_ptr& message, + EMailMetaData& meta_data) -> int { + auto header = message->getHeader(); + + auto from_field_value_text = + ExtractFieldValueMailBox(header, vmime::fields::FROM); + auto to_field_value_text = + ExtractFieldValueAddressList(header, vmime::fields::TO); + auto cc_field_value_text = + ExtractFieldValueAddressList(header, vmime::fields::CC); + auto bcc_field_value_text = + ExtractFieldValueAddressList(header, vmime::fields::BCC); + auto date_field_value = + ExtractFieldValueDateTime(header, vmime::fields::DATE); + auto subject_field_value_text = + ExtractFieldValueText(header, vmime::fields::SUBJECT); + auto reply_to_field_value_text = + ExtractFieldValueMailBox(header, vmime::fields::REPLY_TO); + auto organization_text = + ExtractFieldValueText(header, vmime::fields::ORGANIZATION); + + meta_data.from = from_field_value_text; + meta_data.to = to_field_value_text.split(','); + meta_data.cc = cc_field_value_text.split(','); + meta_data.bcc = bcc_field_value_text.split(','); + meta_data.subject = subject_field_value_text; + return 0; } \ No newline at end of file diff --git a/src/m_email/EMailBasicGpgOpera.cpp b/src/m_email/EMailBasicGpgOpera.cpp index bf60d1c..10988a6 100644 --- a/src/m_email/EMailBasicGpgOpera.cpp +++ b/src/m_email/EMailBasicGpgOpera.cpp @@ -49,90 +49,9 @@ auto EncryptEMLData(int channel, const QStringList& keys, 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); + QDUP(body_data), 1, &enc_result); if (ret != 0) { eml_data = "Encryption Failed"; @@ -260,7 +179,7 @@ auto EncryptEMLData(int channel, const QStringList& keys, encrypted_data.toStdString()); encrypted_data_body->setContents(encrypted_data_content); - eml_data = Q_SC(msg->generate(vmime::lineLengthLimits::infinite)); + eml_data = Q_SC(msg->generate(vmime::lineLengthLimits::convenient)); FLOG_DEBUG("EML Data: %1", eml_data); return 0; @@ -336,7 +255,9 @@ auto SignEMLData(int channel, const QString& key, } } - msg_builder.setSubject(vmime::text(subject.toStdString())); + if (!subject.isEmpty()) { + msg_builder.setSubject(vmime::text(subject.toStdString())); + } vmime::shared_ptr msg = msg_builder.construct(); @@ -461,13 +382,11 @@ auto SignEMLData(int channel, const QString& key, auto mime_part_part_body = mime_part->getBody(); auto mime_part_body_content = vmime::make_shared(); - mime_part_body_content->setData( - body_data.toBase64().toStdString(), - vmime::encoding(vmime::encodingTypes::BASE64)); + mime_part_body_content->setData(body_data.toBase64().toStdString()); mime_part_part_body->setContents(mime_part_body_content); auto container_raw_data = - Q_SC(container_part->generate(vmime::lineLengthLimits::infinite)); + Q_SC(container_part->generate(vmime::lineLengthLimits::convenient)); auto container_raw_data_hash = QCryptographicHash::hash( container_raw_data.toLatin1(), QCryptographicHash::Sha1); @@ -503,7 +422,218 @@ auto SignEMLData(int channel, const QString& key, signature.toStdString()); signature_part_body->setContents(signature_part_body_content); - eml_data = Q_SC(msg->generate(vmime::lineLengthLimits::infinite)); + eml_data = Q_SC(msg->generate(vmime::lineLengthLimits::convenient)); + + FLOG_DEBUG("EML Data: %1", eml_data); + + return 0; + + } catch (const vmime::exception& e) { + eml_data = QString("VMIME Error: %1").arg(e.what()); + return -1; + } + + eml_data = QString("Unknown Error: %1"); + return -1; +} + +auto AppendSignToEMLData(int channel, const QString& key, + const vmime::shared_ptr& message, + QString& eml_data) -> int { + try { + auto header = message->getHeader(); + + auto backup_body_component = message->getBody()->clone(); + + std::shared_ptr backup_body = + std::static_pointer_cast(backup_body_component); + + auto backup_content_type_header_field_component = + header->getField(vmime::fields::CONTENT_TYPE) + ->clone(); + + std::shared_ptr backup_content_type_header_field = + std::static_pointer_cast( + backup_content_type_header_field_component); + + auto backup_content_trans_encode_field_component = + header + ->getField( + vmime::fields::CONTENT_TRANSFER_ENCODING) + ->clone(); + + std::shared_ptr + backup_content_trans_encode_header_field = + std::static_pointer_cast( + backup_content_trans_encode_field_component); + + FLOG_DEBUG("Content-Transfer-Encoding Header Data: %1", + backup_content_trans_encode_header_field->generate()); + + // no Content-Transfer-Encoding + header->removeField( + header->getField(vmime::fields::CONTENT_TRANSFER_ENCODING)); + + FLOG_DEBUG("Backup Content-Type Header Data: %1", + backup_content_type_header_field->generate()); + FLOG_DEBUG("Backup Content-Transfer-Encoding Header Data: %1", + backup_content_trans_encode_header_field->generate()); + + auto content_type_header_field = + header->getField(vmime::fields::CONTENT_TYPE); + content_type_header_field->setValue("multipart/signed"); + auto body_boundary = vmime::body::generateRandomBoundaryString(); + content_type_header_field->appendParameter( + vmime::make_shared("protocol", + "application/pgp-signature")); + content_type_header_field->setBoundary(body_boundary); + + auto root_body_part = vmime::make_shared(); + auto container_part = vmime::make_shared(); + auto mime_part = vmime::make_shared(); + auto public_key_part = vmime::make_shared(); + auto signature_part = vmime::make_shared(); + + root_body_part->appendPart(container_part); + root_body_part->appendPart(signature_part); + message->setBody(root_body_part); + + root_body_part->setPrologText( + "This is an OpenPGP/MIME signed message (RFC 4880 and 3156)"); + + auto container_boundary = vmime::body::generateRandomBoundaryString(); + auto container_part_header = container_part->getHeader(); + auto container_part_content_ttype_header_field = + container_part_header->getField( + vmime::fields::CONTENT_TYPE); + container_part_content_ttype_header_field->setValue("multipart/mixed"); + container_part_content_ttype_header_field->setBoundary(container_boundary); + + auto container_part_body = container_part->getBody(); + + container_part_body->appendPart(mime_part); + container_part_body->appendPart(public_key_part); + + auto public_key_part_header = public_key_part->getHeader(); + + auto public_key_name = QString("OpenPGP_0x%1.asc").arg(key.toUpper()); + auto public_key_part_content_type_header_field = + public_key_part_header->getField( + vmime::fields::CONTENT_TYPE); + public_key_part_content_type_header_field->setValue("application/pgp-keys"); + public_key_part_content_type_header_field->appendParameter( + vmime::make_shared("name", + public_key_name.toStdString())); + + auto public_key_part_content_desc_header_field = + public_key_part_header->getField(vmime::fields::CONTENT_DESCRIPTION); + public_key_part_content_desc_header_field->setValue("OpenPGP public key"); + + auto public_key_part_content_trans_encode_field = + public_key_part_header->getField( + vmime::fields::CONTENT_TRANSFER_ENCODING); + public_key_part_content_trans_encode_field->setValue("quoted-printable"); + + auto public_key_part_content_disp_header_field = + public_key_part_header->getField( + vmime::fields::CONTENT_DISPOSITION); + public_key_part_content_disp_header_field->setValue("attachment"); + public_key_part_content_disp_header_field->setFilename( + vmime::word(public_key_name.toStdString())); + + auto signature_part_header = signature_part->getHeader(); + + auto signature_part_content_type_header_field = + signature_part_header->getField( + vmime::fields::CONTENT_TYPE); + signature_part_content_type_header_field->setValue( + "application/pgp-signature"); + signature_part_content_type_header_field->appendParameter( + vmime::make_shared("name", "OpenPGP_signature.asc")); + + auto signature_part_content_desc_header_field = + signature_part_header->getField(vmime::fields::CONTENT_DESCRIPTION); + signature_part_content_desc_header_field->setValue( + "OpenPGP digital signature"); + + auto signature_part_content_disp_header_field = + signature_part_header->getField( + vmime::fields::CONTENT_DISPOSITION); + signature_part_content_disp_header_field->setValue("attachment"); + signature_part_content_disp_header_field->setFilename( + vmime::word({"OpenPGP_signature.asc"})); + + auto public_key = UDUP(GFGpgPublicKey(channel, QDUP(key), 1)); + if (public_key.isEmpty()) { + eml_data = "Get Public Key of Sign Key Failed"; + return -1; + } + + auto public_key_part_part_body = public_key_part->getBody(); + auto public_key_part_body_content = + vmime::make_shared(); + public_key_part_body_content->setData( + public_key.toLatin1().replace('\n', "\r\n").toStdString(), + vmime::encoding(vmime::encodingTypes::QUOTED_PRINTABLE)); + public_key_part_part_body->setContents(public_key_part_body_content); + + auto mime_part_header = mime_part->getHeader(); + + auto mime_part_content_trans_encode_field = + mime_part_header->getField( + vmime::fields::CONTENT_TRANSFER_ENCODING); + mime_part_header->replaceField(mime_part_content_trans_encode_field, + backup_content_trans_encode_header_field); + + auto mime_part_content_type_header_field = + mime_part_header->getField( + vmime::fields::CONTENT_TYPE); + mime_part_header->replaceField(mime_part_content_type_header_field, + backup_content_type_header_field); + + mime_part->setBody(backup_body); + + auto container_raw_data = + Q_SC(container_part->generate(vmime::lineLengthLimits::convenient)); + + container_raw_data.replace("\r\n", "\n"); + container_raw_data.replace("\n", "\r\n"); + + 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, key); + + GFGpgSignResult* s; + auto ret = GFGpgSignData(channel, QListToCharArray({key}), 1, + QDUP(container_raw_data), 1, 1, &s); + + if (ret != 0) { + eml_data = "Sign Failed"; + return -1; + } + + auto signature = UDUP(s->signature); + auto hash_algo = UDUP(s->hash_algo); + + GFFreeMemory(s); + + FLOG_DEBUG("Hash Algo: %1 Signature Data: %2", hash_algo, signature); + content_type_header_field->appendParameter( + vmime::make_shared( + "micalg", + QString("pgp-%1").arg(hash_algo.toLower()).toStdString())); + + auto signature_part_body = signature_part->getBody(); + auto signature_part_body_content = + vmime::make_shared( + signature.toStdString()); + signature_part_body->setContents(signature_part_body_content); + + eml_data = Q_SC(message->generate(vmime::lineLengthLimits::convenient)); FLOG_DEBUG("EML Data: %1", eml_data); diff --git a/src/m_email/EMailBasicGpgOpera.h b/src/m_email/EMailBasicGpgOpera.h index 06753d3..4a6f5dc 100644 --- a/src/m_email/EMailBasicGpgOpera.h +++ b/src/m_email/EMailBasicGpgOpera.h @@ -56,4 +56,17 @@ auto EncryptEMLData(int channel, const QStringList& keys, */ auto SignEMLData(int channel, const QString& key, const EMailMetaData& meta_data, const QByteArray& body_data, - QString& eml_data) -> int; \ No newline at end of file + QString& eml_data) -> int; + +/** + * @brief + * + * @param channel + * @param key + * @param message + * @param eml_data + * @return int + */ +auto AppendSignToEMLData(int channel, const QString& key, + const vmime::shared_ptr& message, + QString& eml_data) -> int; \ No newline at end of file diff --git a/src/m_email/EMailHelper.h b/src/m_email/EMailHelper.h index a4a7b77..6f82b9c 100644 --- a/src/m_email/EMailHelper.h +++ b/src/m_email/EMailHelper.h @@ -31,12 +31,7 @@ #include #include -// vmime -#define VMIME_STATIC -#include -// vmime extra -#include -#include +#include "EMailModel.h" auto inline Q_SC(const std::string& s) -> QString { return QString::fromStdString(s); @@ -112,4 +107,44 @@ auto ExtractFieldValueDateTime(const vmime::shared_ptr& header, * @return false */ auto ParseEmailString(const QString& input, QString& name, - QString& email) -> bool; \ No newline at end of file + QString& email) -> bool; + +/** + * @brief + * + * @param data + * @param lineLength + * @return QString + */ +auto EncodeBase64WithLineBreaks(const QByteArray& data, + int lineLength = 76) -> QString; + +/** + * @brief + * + * @param data + * @return true + * @return false + */ +auto CheckIfEMLMessage(const QByteArray& data, + vmime::shared_ptr& message) -> bool; + +/** + * @brief + * + * @param meta_data + * @param eml_data + * @return int + */ +auto BuildPlainTextEML(const EMailMetaData& meta_data, + const QByteArray& body_data, QString& eml_data) -> int; + +/** + * @brief + * + * @param body_data + * @param meta_data + * @return int + */ +auto GetEMLMetaData(vmime::shared_ptr& message, + EMailMetaData& meta_data) -> int; \ No newline at end of file diff --git a/src/m_email/EMailMetaDataDialog.cpp b/src/m_email/EMailMetaDataDialog.cpp index bcabe48..3c8d137 100644 --- a/src/m_email/EMailMetaDataDialog.cpp +++ b/src/m_email/EMailMetaDataDialog.cpp @@ -118,9 +118,11 @@ void EMailMetaDataDialog::slot_parse_eml_meta_data() { auto subject = ui_->subjectEdit->text(); auto to = raw_to.split(';', Qt::SkipEmptyParts); - auto cc = raw_cc.split(';', Qt::SkipEmptyParts); - auto bcc = raw_bcc.split(';', Qt::SkipEmptyParts); - + auto cc = raw_cc.trimmed().isEmpty() ? QStringList() + : raw_cc.split(';', Qt::SkipEmptyParts); + auto bcc = raw_bcc.trimmed().isEmpty() + ? QStringList() + : raw_bcc.split(';', Qt::SkipEmptyParts); QString name; QString email; diff --git a/src/m_email/EMailModel.h b/src/m_email/EMailModel.h index 454645f..791bb17 100644 --- a/src/m_email/EMailModel.h +++ b/src/m_email/EMailModel.h @@ -31,6 +31,13 @@ #include #include +// vmime +#define VMIME_STATIC +#include +// vmime extra +#include +#include + struct EMailMetaData { QString from; QStringList to; diff --git a/src/m_email/EMailModule.cpp b/src/m_email/EMailModule.cpp index 9e76689..e00e276 100644 --- a/src/m_email/EMailModule.cpp +++ b/src/m_email/EMailModule.cpp @@ -430,6 +430,29 @@ REGISTER_EVENT_HANDLER(EMAIL_SIGN_EML_DATA, [](const MEvent& event) -> int { r_dialog->SetKeys({sign_key}); r_dialog->SetBodyData({body_data}); + vmime::shared_ptr message; + if (CheckIfEMLMessage(body_data, message)) { + EMailMetaData meta_data; + auto ret = GetEMLMetaData(message, meta_data); + + if (ret != 0) { + CB_ERR(event, -1, "Get MetaData From EML Data Failed"); + } + + QString eml_data; + ret = AppendSignToEMLData(channel, sign_key, message, eml_data); + if (ret != 0) { + CB_ERR(event, -2, eml_data); + } + + CB(event, GFGetModuleID(), + { + {"ret", QString::number(0)}, + {"eml_data", eml_data}, + }); + return 0; + } + GFUIShowDialog(dialog, nullptr); QObject::connect(r_dialog, &EMailMetaDataDialog::SignalEMLMetaData, r_dialog, [=](const EMailMetaData& meta_data) { @@ -469,6 +492,29 @@ REGISTER_EVENT_HANDLER(EMAIL_ENCRYPT_EML_DATA, [](const MEvent& event) -> int { auto body_data = QByteArray::fromBase64(QString(event["body_data"]).toLatin1()); + vmime::shared_ptr message; + if (CheckIfEMLMessage(body_data, message)) { + EMailMetaData meta_data; + auto ret = GetEMLMetaData(message, meta_data); + + if (ret != 0) { + CB_ERR(event, -1, "Get MetaData From EML Data Failed"); + } + + QString eml_data; + ret = EncryptEMLData(channel, encrypt_keys, meta_data, body_data, eml_data); + if (ret != 0) { + CB_ERR(event, -2, eml_data); + } + + CB(event, GFGetModuleID(), + { + {"ret", QString::number(0)}, + {"eml_data", eml_data}, + }); + return 0; + } + auto* dialog = GUI_OBJECT(CreateEMailMetaDataDialog, 1); auto* r_dialog = qobject_cast(static_cast(dialog)); @@ -481,22 +527,31 @@ REGISTER_EVENT_HANDLER(EMAIL_ENCRYPT_EML_DATA, [](const MEvent& event) -> int { GFUIShowDialog(dialog, nullptr); - QObject::connect(r_dialog, &EMailMetaDataDialog::SignalEMLMetaData, r_dialog, - [=](const EMailMetaData& meta_data) { - QString eml_data; - auto ret = EncryptEMLData(channel, encrypt_keys, meta_data, - body_data, eml_data); - if (ret != 0) { - CB_ERR(event, -2, eml_data); - } + QObject::connect( + r_dialog, &EMailMetaDataDialog::SignalEMLMetaData, r_dialog, + [=](const EMailMetaData& meta_data) { + QString eml_data; + QString plain_text_eml_data; - CB(event, GFGetModuleID(), - { - {"ret", QString::number(0)}, - {"eml_data", eml_data}, - }); - return 0; - }); + auto ret = BuildPlainTextEML(meta_data, body_data, plain_text_eml_data); + + if (ret != 0) { + CB_ERR(event, -1, "Build PlainText EML Data Failed"); + } + + ret = EncryptEMLData(channel, encrypt_keys, meta_data, + plain_text_eml_data.toLatin1(), eml_data); + if (ret != 0) { + CB_ERR(event, -2, eml_data); + } + + CB(event, GFGetModuleID(), + { + {"ret", QString::number(0)}, + {"eml_data", eml_data}, + }); + return 0; + }); QObject::connect( r_dialog, &EMailMetaDataDialog::SignalNoEMLMetaData, r_dialog, @@ -505,6 +560,67 @@ REGISTER_EVENT_HANDLER(EMAIL_ENCRYPT_EML_DATA, [](const MEvent& event) -> int { return 0; }); +REGISTER_EVENT_HANDLER( + EMAIL_ENCRYPT_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["encrypt_keys"].isEmpty()) + CB_ERR(event, -1, "encrypt_keys is empty"); + if (event["sign_key"].isEmpty()) CB_ERR(event, -1, "sign_key is empty"); + + auto channel = event.value("channel", "0").toInt(); + auto sign_key = event.value("sign_key", ""); + auto encrypt_keys = event.value("encrypt_keys", "").split(';'); + + FLOG_DEBUG("eml encrypt keys: %1", encrypt_keys.join(';')); + FLOG_DEBUG("eml sign key: %1", sign_key); + + auto body_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({body_data}); + + GFUIShowDialog(dialog, nullptr); + + QObject::connect(r_dialog, &EMailMetaDataDialog::SignalEMLMetaData, + r_dialog, [=](const EMailMetaData& meta_data) { + QString eml_data; + auto ret = SignEMLData(channel, sign_key, meta_data, + body_data, eml_data); + if (ret != 0) { + CB_ERR(event, -2, eml_data); + } + + ret = EncryptEMLData(channel, encrypt_keys, meta_data, + body_data, eml_data); + if (ret != 0) { + CB_ERR(event, -2, eml_data); + } + + CB(event, GFGetModuleID(), + { + {"ret", QString::number(0)}, + {"eml_data", eml_data}, + }); + return 0; + }); + + QObject::connect(r_dialog, &EMailMetaDataDialog::SignalNoEMLMetaData, + r_dialog, [=](const QString& error_string) { + CB_ERR(event, -1, error_string); + }); + + return 0; + }); + auto GFDeactivateModule() -> int { return 0; } auto GFUnregisterModule() -> int { diff --git a/src/m_email/vmime b/src/m_email/vmime index 43b262b..193a9ee 160000 --- a/src/m_email/vmime +++ b/src/m_email/vmime @@ -1 +1 @@ -Subproject commit 43b262bd8c79fbaadc9522eaa04a40427782e0c6 +Subproject commit 193a9ee85b1a491955a7181250ebf0296ccc5d0d