message: detect top-level smime parts + test

Fixes #2745
This commit is contained in:
Dirk-Jan C. Binnema
2024-08-22 22:34:34 +03:00
parent 79dd15424b
commit c28bfe04e1
3 changed files with 119 additions and 47 deletions

View File

@ -484,6 +484,28 @@ handle_encrypted(const MimeMultipartEncrypted& part, Message::Private& info)
handle_object(part, res->first, info);
}
static void
maybe_handle_pkcs7(const MimeObject& obj, Message::Private& info)
{
if (obj.is_mime_application_pkcs7_mime()) {
MimeApplicationPkcs7Mime smime(obj);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wswitch-enum"
// CompressedData, CertsOnly, Unknown
switch (smime.smime_type()) {
case Mu::MimeApplicationPkcs7Mime::SecureMimeType::SignedData:
info.flags |= Flags::Signed;
break;
case Mu::MimeApplicationPkcs7Mime::SecureMimeType::EnvelopedData:
info.flags |= Flags::Encrypted;
break;
default:
break;
}
#pragma GCC diagnostic pop
}
}
static void
handle_object(const MimeObject& parent,
@ -508,23 +530,8 @@ handle_object(const MimeObject& parent,
/* FIXME: An encrypted part might be signed at the same time.
* In that case the signed flag is lost. */
info.flags |= Flags::Encrypted;
} else if (obj.is_mime_application_pkcs7_mime()) {
MimeApplicationPkcs7Mime smime(obj);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wswitch-enum"
// CompressedData, CertsOnly, Unknown
switch (smime.smime_type()) {
case Mu::MimeApplicationPkcs7Mime::SecureMimeType::SignedData:
info.flags |= Flags::Signed;
break;
case Mu::MimeApplicationPkcs7Mime::SecureMimeType::EnvelopedData:
info.flags |= Flags::Encrypted;
break;
default:
break;
}
#pragma GCC diagnostic pop
}
} else
maybe_handle_pkcs7(obj, info);
}
/**
@ -548,6 +555,10 @@ process_message(const MimeMessage& mime_msg, const std::string& path,
info.flags |= Flags::Unread;
}
// handle top-level
if (const auto mpart = mime_msg.mime_part(); mpart)
maybe_handle_pkcs7(*mpart, info);
// parts
mime_msg.for_each([&](auto&& parent, auto&& child_obj) {
handle_object(parent, child_obj, info);

View File

@ -171,9 +171,6 @@ private:
};
/**
* Thin wrapper around a GMimeContentType
@ -200,6 +197,15 @@ struct MimeContentType: public Object {
return g_mime_content_type_is_type(self(), type.c_str(),
subtype.c_str());
}
Option<std::string> parameter(const std::string& name) const noexcept {
const char *param{g_mime_content_type_get_parameter(self(), name.c_str())};
if (!param || !param[0])
return Nothing;
else
return Some(std::string{param});
}
private:
GMimeContentType* self() const {
return reinterpret_cast<GMimeContentType*>(object());
@ -929,6 +935,19 @@ public:
throw std::runtime_error("not a mime-message");
}
/**
* Get the top-level MIME-part or Nothing if there is none
*
* @return MIME-part of nothing
*/
Option<MimeObject> mime_part() const noexcept {
auto obj = g_mime_message_get_mime_part(self());
if (!obj)
return Nothing;
else
return MimeObject{obj};
}
/**
* Make a MimeMessage from a file
*