Bug 1240290

Tag #1273
This commit is contained in:
Matt A. Tobin 2019-11-11 01:56:34 -05:00 committed by Roy Tam
commit 800fce0b81
14 changed files with 282 additions and 215 deletions

View file

@ -116,7 +116,6 @@ nsMsgAttachmentHandler::nsMsgAttachmentHandler() :
m_bogus_attachment(false),
m_done(false),
m_already_encoded_p(false),
m_decrypted_p(false),
mDeleteFile(false),
mMHTMLPart(false),
mPartUserOmissionOverride(false),

View file

@ -140,16 +140,6 @@ public:
bool m_already_encoded_p; // If we attach a document that is already
// encoded, we just pass it through.
bool m_decrypted_p; /* S/MIME -- when attaching a message that was
encrypted, it's necessary to decrypt it first
(since nobody but the original recipient can
read it -- if you forward it to someone in the
raw, it will be useless to them.) This flag
indicates whether decryption occurred, so that
libmsg can issue appropriate warnings about
doing a cleartext forward of a message that was
originally encrypted. */
bool mDeleteFile; // If this is true, Delete the file...its
// NOT the original file!

View file

@ -8,6 +8,7 @@
#include "nsICMSMessageErrors.h"
#include "nsICMSDecoder.h"
#include "mimecms.h"
#include "mimemcms.h"
#include "mimemsig.h"
#include "nspr.h"
#include "mimemsg.h"
@ -28,6 +29,9 @@
using namespace mozilla::mailnews;
// The name "mime encrypted" is misleading, because this code is used
// both for CMS messages that are encrypted, and also for messages that
// aren't encrypted, but only contain a signature.
#define MIME_SUPERCLASS mimeEncryptedClass
MimeDefClass(MimeEncryptedCMS, MimeEncryptedCMSClass,
@ -68,10 +72,11 @@ typedef struct MimeCMSdata
bool ci_is_encrypted;
char *sender_addr;
bool decoding_failed;
bool skip_content;
uint32_t decoded_bytes;
MimeObject *self;
bool parent_is_encrypted_p;
bool parent_holds_stamp_p;
bool any_parent_is_encrypted_p;
bool any_parent_is_signed_p;
nsCOMPtr<nsIMsgSMIMEHeaderSink> smimeHeaderSink;
nsCString url;
@ -81,12 +86,11 @@ typedef struct MimeCMSdata
ci_is_encrypted(false),
sender_addr(nullptr),
decoding_failed(false),
skip_content(false),
decoded_bytes(0),
self(nullptr),
parent_is_encrypted_p(false),
parent_holds_stamp_p(false)
{
}
any_parent_is_encrypted_p(false),
any_parent_is_signed_p(false) {}
~MimeCMSdata()
{
@ -140,6 +144,46 @@ bool MimeEncryptedCMS_encrypted_p (MimeObject *obj)
return false;
}
bool MimeEncOrMP_CMS_signed_p(MimeObject *obj) {
bool is_signed;
if (!obj) return false;
if (mime_typep(obj, (MimeObjectClass *)&mimeMultipartSignedCMSClass)) {
return true;
}
if (mime_typep(obj, (MimeObjectClass *)&mimeEncryptedCMSClass)) {
MimeEncrypted *enc = (MimeEncrypted *)obj;
MimeCMSdata *data = (MimeCMSdata *)enc->crypto_closure;
if (!data || !data->content_info) return false;
data->content_info->ContentIsSigned(&is_signed);
return is_signed;
}
return false;
}
bool MimeAnyParentCMSEncrypted(MimeObject *obj)
{
MimeObject *o2 = obj;
while (o2 && o2->parent) {
if (MimeEncryptedCMS_encrypted_p(o2->parent)) {
return true;
}
o2 = o2->parent;
}
return false;
}
bool MimeAnyParentCMSSigned(MimeObject *obj)
{
MimeObject *o2 = obj;
while (o2 && o2->parent) {
if (MimeEncOrMP_CMS_signed_p(o2->parent)) {
return true;
}
o2 = o2->parent;
}
return false;
}
bool MimeCMSHeadersAndCertsMatch(nsICMSMessage *content_info,
nsIX509Cert *signerCert,
@ -439,38 +483,37 @@ static void *MimeCMS_init(MimeObject *obj,
data->output_fn = output_fn;
data->output_closure = output_closure;
PR_SetError(0, 0);
data->decoder_context = do_CreateInstance(NS_CMSDECODER_CONTRACTID, &rv);
if (NS_FAILED(rv))
{
delete data;
return 0;
data->any_parent_is_signed_p = MimeAnyParentCMSSigned(obj);
if (data->any_parent_is_signed_p) {
// Parent is signed.
// We don't know yet if this child is signed or encrypted.
// (We'll know after decoding has completed and EOF is called.)
// We don't support "inner encrypt" with outer sign, because the
// inner encrypted part could have been produced by an attacker who
// stripped away a part containing the signature (S/MIME doesn't
// have integrity protection).
// A sign-then-sign encoding is confusing, too, because it could be
// an attempt to influence which signature is shown.
data->skip_content = true;
}
rv = data->decoder_context->Start(MimeCMS_content_callback, data);
if (NS_FAILED(rv))
{
delete data;
return 0;
if (!data->skip_content) {
data->decoder_context = do_CreateInstance(NS_CMSDECODER_CONTRACTID, &rv);
if (NS_FAILED(rv)) {
delete data;
return 0;
}
rv = data->decoder_context->Start(MimeCMS_content_callback, data);
if (NS_FAILED(rv)) {
delete data;
return 0;
}
}
// XXX Fix later XXX //
data->parent_holds_stamp_p =
(obj->parent &&
(mime_crypto_stamped_p(obj->parent) ||
mime_typep(obj->parent, (MimeObjectClass *) &mimeEncryptedClass)));
data->parent_is_encrypted_p =
(obj->parent && MimeEncryptedCMS_encrypted_p (obj->parent));
/* If the parent of this object is a crypto-blob, then it's the grandparent
who would have written out the headers and prepared for a stamp...
(This shit sucks.)
*/
if (data->parent_is_encrypted_p &&
!data->parent_holds_stamp_p &&
obj->parent && obj->parent->parent)
data->parent_holds_stamp_p =
mime_crypto_stamped_p (obj->parent->parent);
data->any_parent_is_encrypted_p = MimeAnyParentCMSEncrypted(obj);
mime_stream_data *msd = (mime_stream_data *) (data->self->options->stream_closure);
if (msd)
@ -530,9 +573,11 @@ MimeCMS_write (const char *buf, int32_t buf_size, void *closure)
if (!data || !data->output_fn || !data->decoder_context) return -1;
PR_SetError(0, 0);
rv = data->decoder_context->Update(buf, buf_size);
data->decoding_failed = NS_FAILED(rv);
if (!data->decoding_failed && !data->skip_content) {
PR_SetError(0, 0);
rv = data->decoder_context->Update(buf, buf_size);
data->decoding_failed = NS_FAILED(rv);
}
return 0;
}
@ -606,7 +651,12 @@ MimeCMS_eof (void *crypto_closure, bool abort_p)
nsresult rv;
int32_t status = nsICMSMessageErrors::SUCCESS;
if (!data || !data->output_fn || !data->decoder_context) {
if (!data || !data->output_fn) {
return -1;
}
if (!data->skip_content && !data->decoder_context) {
// If we don't skip, we should have a context.
return -1;
}
@ -621,11 +671,12 @@ MimeCMS_eof (void *crypto_closure, bool abort_p)
*/
PR_SetError(0, 0);
rv = data->decoder_context->Finish(getter_AddRefs(data->content_info));
if (NS_FAILED(rv))
status = nsICMSMessageErrors::GENERAL_ERROR;
if (!data->skip_content) {
rv = data->decoder_context->Finish(getter_AddRefs(data->content_info));
if (NS_FAILED(rv)) status = nsICMSMessageErrors::GENERAL_ERROR;
data->decoder_context = nullptr;
data->decoder_context = nullptr;
}
nsCOMPtr<nsIX509Cert> certOfInterest;
@ -644,6 +695,21 @@ MimeCMS_eof (void *crypto_closure, bool abort_p)
if (data->decoding_failed)
status = nsICMSMessageErrors::GENERAL_ERROR;
if (data->skip_content) {
// Skipping content means, we detected a forbidden combination
// of CMS objects, so let's make sure we replace the parent status
// with a bad status.
if (data->any_parent_is_signed_p) {
data->smimeHeaderSink->SignedStatus(aRelativeNestLevel,
nsICMSMessageErrors::GENERAL_ERROR, nullptr, data->url);
}
if (data->any_parent_is_encrypted_p) {
data->smimeHeaderSink->EncryptionStatus(aRelativeNestLevel,
nsICMSMessageErrors::GENERAL_ERROR, nullptr, data->url);
}
return 0;
}
if (!data->content_info)
{
if (!data->decoded_bytes)

View file

@ -418,18 +418,8 @@ MimeEncrypted_emit_buffered_child(MimeObject *obj)
obj->options->headers != MimeHeadersCitation &&
obj->options->write_html_p &&
obj->options->output_fn)
// && !mime_crypto_object_p(enc->hdrs, true, obj->options)) // XXX fix later XXX //
{
char *html;
#if 0 // XXX Fix this later XXX //
char *html = (((MimeEncryptedClass *) obj->clazz)->crypto_generate_html
(enc->crypto_closure));
if (!html) return -1; /* MK_OUT_OF_MEMORY? */
status = MimeObject_write(obj, html, strlen(html), false);
PR_FREEIF(html);
if (status < 0) return status;
#endif
/* Now that we have written out the crypto stamp, the outermost header
block is well and truly closed. If this is in fact the outermost
@ -445,7 +435,8 @@ MimeEncrypted_emit_buffered_child(MimeObject *obj)
for (p = obj; p->parent; p = p->parent)
outer_headers = p->headers;
NS_ASSERTION(obj->options->state->first_data_written_p, "1.2 <mscott@netscape.com> 01 Nov 2001 17:59");
html = obj->options->generate_post_header_html_fn(NULL,
char *html = obj->options->generate_post_header_html_fn(
NULL,
obj->options->html_closure,
outer_headers);
obj->options->state->post_header_html_run_p = true;

View file

@ -234,3 +234,13 @@ MimeExternalObject_displayable_inline_p (MimeObjectClass *clazz,
{
return false;
}
#undef MIME_SUPERCLASS
#define MIME_SUPERCLASS mimeExternalObjectClass
MimeDefClass(MimeSuppressedCrypto, MimeSuppressedCryptoClass,
mimeSuppressedCryptoClass, &MIME_SUPERCLASS);
static int MimeSuppressedCryptoClassInitialize(MimeSuppressedCryptoClass *clazz) {
MimeExternalObjectClass *lclass = (MimeExternalObjectClass *)clazz;
return MimeExternalObjectClassInitialize(lclass);
}

View file

@ -31,4 +31,20 @@ struct MimeExternalObject {
#define MimeExternalObjectClassInitializer(ITYPE,CSUPER) \
{ MimeLeafClassInitializer(ITYPE,CSUPER) }
typedef struct MimeSuppressedCryptoClass MimeSuppressedCryptoClass;
typedef struct MimeSuppressedCrypto MimeSuppressedCrypto;
struct MimeSuppressedCryptoClass {
MimeExternalObjectClass eobj;
};
extern "C" MimeSuppressedCryptoClass mimeSuppressedCryptoClass;
struct MimeSuppressedCrypto {
MimeExternalObject eobj;
};
#define MimeSuppressedCryptoClassInitializer(ITYPE, CSUPER) \
{ MimeExternalObjectClassInitializer(ITYPE, CSUPER) }
#endif /* _MIMEEOBJ_H_ */

View file

@ -731,7 +731,7 @@ mime_find_class (const char *content_type, MimeHeaders *hdrs,
// Allowing them would leak the plain text in case the part is
// cleverly hidden and the decrypted content gets included in
// replies and forwards.
clazz = (MimeObjectClass *)&mimeExternalObjectClass;
clazz = (MimeObjectClass *)&mimeSuppressedCryptoClass;
return clazz;
}
@ -951,9 +951,14 @@ mime_create (const char *content_type, MimeHeaders *hdrs,
(clazz != (MimeObjectClass *)&mimeInlineTextRichtextClass) &&
(clazz != (MimeObjectClass *)&mimeInlineTextEnrichedClass) &&
(clazz != (MimeObjectClass *)&mimeMessageClass) &&
(clazz != (MimeObjectClass *)&mimeInlineImageClass) )
(clazz != (MimeObjectClass *)&mimeInlineImageClass) ) {
// not a special inline type, so show as attachment
clazz = (MimeObjectClass *)&mimeExternalObjectClass;
// However, mimeSuppressedCryptoClass is treated identically as
// mimeExternalObjectClass, let's not lose that type information.
if (clazz != (MimeObjectClass *)&mimeSuppressedCryptoClass) {
clazz = (MimeObjectClass *)&mimeExternalObjectClass;
}
}
}
/* If the option `Show Attachments Inline' is off, now would be the time to change our mind... */
@ -1221,21 +1226,6 @@ mime_crypto_object_p(MimeHeaders *hdrs, bool clearsigned_counts, MimeDisplayOpti
return false;
}
/* Whether the given object has written out the HTML version of its headers
in such a way that it will have a "crypto stamp" next to the headers. If
this is true, then the child must write out its HTML slightly differently
to take this into account...
*/
bool
mime_crypto_stamped_p(MimeObject *obj)
{
if (!obj) return false;
if (mime_typep (obj, (MimeObjectClass *) &mimeMessageClass))
return ((MimeMessage *) obj)->crypto_stamped_p;
else
return false;
}
#endif // ENABLE_SMIME
/* Puts a part-number into a URL. If append_p is true, then the part number

View file

@ -332,14 +332,6 @@ extern void mime_get_crypto_state (MimeObject *obj,
bool *signed_p, bool *encrypted_p,
bool *signed_ok, bool *encrypted_ok);
/* Whether the given object has written out the HTML version of its headers
in such a way that it will have a "crypto stamp" next to the headers. If
this is true, then the child must write out its HTML slightly differently
to take this into account...
*/
extern bool mime_crypto_stamped_p(MimeObject *obj);
/* How the crypto code tells the MimeMessage object what the crypto stamp
on it says. */
extern void mime_set_crypto_stamp(MimeObject *obj,
@ -352,7 +344,7 @@ public:
MimeParseStateObject()
{root = 0; separator_queued_p = false; separator_suppressed_p = false;
first_part_written_p = false; post_header_html_run_p = false; first_data_written_p = false;
decrypted_p = false; strippingPart = false;
strippingPart = false;
}
MimeObject *root; /* The outermost parser object. */
@ -376,10 +368,6 @@ public:
bool first_data_written_p; /* State used for Mozilla lazy-stream-
creation evilness. */
bool decrypted_p; /* If options->dexlate_p is true, then this
will be set to indicate whether any
dexlateion did in fact occur.
*/
nsTArray<nsCString> partsToStrip; /* if we're stripping parts, what parts to strip */
nsTArray<nsCString> detachToFiles; /* if we're detaching parts, where each part was detached to */
bool strippingPart;

View file

@ -38,6 +38,7 @@ static int MimeMultCMS_sig_eof (void *, bool);
static int MimeMultCMS_sig_init (void *, MimeObject *, MimeHeaders *);
static char * MimeMultCMS_generate (void *);
static void MimeMultCMS_free (void *);
static void MimeMultCMS_suppressed_child(void *crypto_closure);
extern int SEC_ERROR_CERT_ADDR_MISMATCH;
@ -56,6 +57,7 @@ MimeMultipartSignedCMSClassInitialize(MimeMultipartSignedCMSClass *clazz)
sclass->crypto_signature_hash = MimeMultCMS_sig_hash;
sclass->crypto_signature_eof = MimeMultCMS_sig_eof;
sclass->crypto_generate_html = MimeMultCMS_generate;
sclass->crypto_notify_suppressed_child = MimeMultCMS_suppressed_child;
sclass->crypto_free = MimeMultCMS_free;
PR_ASSERT(!oclass->class_initialized);
@ -80,8 +82,6 @@ typedef struct MimeMultCMSdata
unsigned char* item_data;
uint32_t item_len;
MimeObject *self;
bool parent_is_encrypted_p;
bool parent_holds_stamp_p;
nsCOMPtr<nsIMsgSMIMEHeaderSink> smimeHeaderSink;
nsCString url;
@ -90,11 +90,7 @@ typedef struct MimeMultCMSdata
sender_addr(nullptr),
decoding_failed(false),
item_data(nullptr),
self(nullptr),
parent_is_encrypted_p(false),
parent_holds_stamp_p(false)
{
}
self(nullptr) {}
~MimeMultCMSdata()
{
@ -113,7 +109,7 @@ typedef struct MimeMultCMSdata
/* #### MimeEncryptedCMS and MimeMultipartSignedCMS have a sleazy,
incestuous, dysfunctional relationship. */
extern bool MimeEncryptedCMS_encrypted_p (MimeObject *obj);
extern bool MimeAnyParentCMSSigned(MimeObject *obj);
extern void MimeCMSGetFromSender(MimeObject *obj,
nsCString &from_addr,
nsCString &from_name,
@ -142,82 +138,11 @@ MimeMultCMS_init (MimeObject *obj)
int16_t hash_type;
nsresult rv;
ct = MimeHeaders_get (hdrs, HEADER_CONTENT_TYPE, false, false);
if (!ct) return 0; /* #### bogus message? out of memory? */
micalg = MimeHeaders_get_parameter (ct, PARAM_MICALG, NULL, NULL);
PR_Free(ct);
ct = 0;
if (!micalg) return 0; /* #### bogus message? out of memory? */
if (!PL_strcasecmp(micalg, PARAM_MICALG_MD5) ||
!PL_strcasecmp(micalg, PARAM_MICALG_MD5_2))
hash_type = nsICryptoHash::MD5;
else if (!PL_strcasecmp(micalg, PARAM_MICALG_SHA1) ||
!PL_strcasecmp(micalg, PARAM_MICALG_SHA1_2) ||
!PL_strcasecmp(micalg, PARAM_MICALG_SHA1_3) ||
!PL_strcasecmp(micalg, PARAM_MICALG_SHA1_4) ||
!PL_strcasecmp(micalg, PARAM_MICALG_SHA1_5))
hash_type = nsICryptoHash::SHA1;
else if (!PL_strcasecmp(micalg, PARAM_MICALG_SHA256) ||
!PL_strcasecmp(micalg, PARAM_MICALG_SHA256_2) ||
!PL_strcasecmp(micalg, PARAM_MICALG_SHA256_3))
hash_type = nsICryptoHash::SHA256;
else if (!PL_strcasecmp(micalg, PARAM_MICALG_SHA384) ||
!PL_strcasecmp(micalg, PARAM_MICALG_SHA384_2) ||
!PL_strcasecmp(micalg, PARAM_MICALG_SHA384_3))
hash_type = nsICryptoHash::SHA384;
else if (!PL_strcasecmp(micalg, PARAM_MICALG_SHA512) ||
!PL_strcasecmp(micalg, PARAM_MICALG_SHA512_2) ||
!PL_strcasecmp(micalg, PARAM_MICALG_SHA512_3))
hash_type = nsICryptoHash::SHA512;
else if (!PL_strcasecmp(micalg, PARAM_MICALG_MD2))
hash_type = nsICryptoHash::MD2;
else
hash_type = -1;
PR_Free(micalg);
micalg = 0;
if (hash_type == -1) return 0; /* #### bogus message? */
data = new MimeMultCMSdata;
if (!data)
return 0;
data->self = obj;
data->hash_type = hash_type;
data->data_hash_context = do_CreateInstance("@mozilla.org/security/hash;1", &rv);
if (NS_FAILED(rv))
{
delete data;
return 0;
}
rv = data->data_hash_context->Init(data->hash_type);
if (NS_FAILED(rv))
{
delete data;
return 0;
}
PR_SetError(0,0);
data->parent_holds_stamp_p =
(obj->parent && mime_crypto_stamped_p(obj->parent));
data->parent_is_encrypted_p =
(obj->parent && MimeEncryptedCMS_encrypted_p (obj->parent));
/* If the parent of this object is a crypto-blob, then it's the grandparent
who would have written out the headers and prepared for a stamp...
(This s##t s$%#s.)
*/
if (data->parent_is_encrypted_p &&
!data->parent_holds_stamp_p &&
obj->parent && obj->parent->parent)
data->parent_holds_stamp_p =
mime_crypto_stamped_p (obj->parent->parent);
mime_stream_data *msd = (mime_stream_data *) (data->self->options->stream_closure);
if (msd)
@ -266,6 +191,89 @@ MimeMultCMS_init (MimeObject *obj)
} // if channel
} // if msd
if (obj->parent && MimeAnyParentCMSSigned(obj)) {
// Parent is signed. We know this part is a signature, too, because
// multipart doesn't allow encryption.
// We don't support "inner sign" with outer sign, because the
// inner encrypted part could have been produced by an attacker who
// stripped away a part containing the signature (S/MIME doesn't
// have integrity protection).
// Also we don't want to support sign-then-sign, that's misleading,
// which part would be shown as having a signature?
// TODO: should we show all contents, without any signature info?
if (data->smimeHeaderSink) {
data->smimeHeaderSink->SignedStatus(
MIMEGetRelativeCryptoNestLevel(data->self),
nsICMSMessageErrors::GENERAL_ERROR, nullptr, data->url);
}
delete data;
PR_SetError(-1, 0);
return 0;
}
ct = MimeHeaders_get(hdrs, HEADER_CONTENT_TYPE, false, false);
if (!ct) {
delete data;
return 0; /* #### bogus message? out of memory? */
}
micalg = MimeHeaders_get_parameter(ct, PARAM_MICALG, NULL, NULL);
PR_Free(ct);
ct = 0;
if (!micalg) {
delete data;
return 0; /* #### bogus message? out of memory? */
}
if (!PL_strcasecmp(micalg, PARAM_MICALG_MD5) ||
!PL_strcasecmp(micalg, PARAM_MICALG_MD5_2))
hash_type = nsICryptoHash::MD5;
else if (!PL_strcasecmp(micalg, PARAM_MICALG_SHA1) ||
!PL_strcasecmp(micalg, PARAM_MICALG_SHA1_2) ||
!PL_strcasecmp(micalg, PARAM_MICALG_SHA1_3) ||
!PL_strcasecmp(micalg, PARAM_MICALG_SHA1_4) ||
!PL_strcasecmp(micalg, PARAM_MICALG_SHA1_5))
hash_type = nsICryptoHash::SHA1;
else if (!PL_strcasecmp(micalg, PARAM_MICALG_SHA256) ||
!PL_strcasecmp(micalg, PARAM_MICALG_SHA256_2) ||
!PL_strcasecmp(micalg, PARAM_MICALG_SHA256_3))
hash_type = nsICryptoHash::SHA256;
else if (!PL_strcasecmp(micalg, PARAM_MICALG_SHA384) ||
!PL_strcasecmp(micalg, PARAM_MICALG_SHA384_2) ||
!PL_strcasecmp(micalg, PARAM_MICALG_SHA384_3))
hash_type = nsICryptoHash::SHA384;
else if (!PL_strcasecmp(micalg, PARAM_MICALG_SHA512) ||
!PL_strcasecmp(micalg, PARAM_MICALG_SHA512_2) ||
!PL_strcasecmp(micalg, PARAM_MICALG_SHA512_3))
hash_type = nsICryptoHash::SHA512;
else
hash_type = -1;
PR_Free(micalg);
micalg = 0;
if (hash_type == -1) {
delete data;
return 0; /* #### bogus message? */
}
data->hash_type = hash_type;
data->data_hash_context =
do_CreateInstance("@mozilla.org/security/hash;1", &rv);
if (NS_FAILED(rv)) {
delete data;
return 0;
}
rv = data->data_hash_context->Init(data->hash_type);
if (NS_FAILED(rv)) {
delete data;
return 0;
}
PR_SetError(0, 0);
return data;
}
@ -400,6 +408,17 @@ MimeMultCMS_free (void *crypto_closure)
delete data;
}
static void MimeMultCMS_suppressed_child(void *crypto_closure) {
// I'm a multipart/signed. If one of my cryptographic child elements
// was suppressed, then I want my signature to be shown as invalid.
MimeMultCMSdata *data = (MimeMultCMSdata *)crypto_closure;
if (data && data->smimeHeaderSink) {
data->smimeHeaderSink->SignedStatus(
MIMEGetRelativeCryptoNestLevel(data->self),
nsICMSMessageErrors::GENERAL_ERROR, nullptr, data->url);
}
}
static char *
MimeMultCMS_generate (void *crypto_closure)
{

View file

@ -786,34 +786,22 @@ MimeMessage_write_headers_html (MimeObject *obj)
return status;
}
if (!msg->crypto_stamped_p)
{
/* If we're not writing a xlation stamp, and this is the outermost
message, then now is the time to run the post_header_html_fn.
(Otherwise, it will be run when the xlation-stamp is finally
closed off, in MimeXlateed_emit_buffered_child() or
MimeMultipartSigned_emit_child().)
*/
if (obj->options &&
obj->options->state &&
// If this is the outermost message, then now is the time to run the
// post_header_html_fn.
if (obj->options && obj->options->state &&
obj->options->generate_post_header_html_fn &&
!obj->options->state->post_header_html_run_p)
{
char *html = 0;
PR_ASSERT(obj->options->state->first_data_written_p);
html = obj->options->generate_post_header_html_fn(NULL,
obj->options->html_closure,
msg->hdrs);
obj->options->state->post_header_html_run_p = true;
if (html)
{
status = MimeObject_write(obj, html, strlen(html), false);
PR_Free(html);
if (status < 0)
{
mimeEmitterEndHeader(obj->options, obj);
return status;
}
!obj->options->state->post_header_html_run_p) {
char *html = 0;
PR_ASSERT(obj->options->state->first_data_written_p);
html = obj->options->generate_post_header_html_fn(
NULL, obj->options->html_closure, msg->hdrs);
obj->options->state->post_header_html_run_p = true;
if (html) {
status = MimeObject_write(obj, html, strlen(html), false);
PR_Free(html);
if (status < 0) {
mimeEmitterEndHeader(obj->options, obj);
return status;
}
}
}

View file

@ -25,12 +25,6 @@ struct MimeMessage {
MimeContainer container; /* superclass variables */
MimeHeaders *hdrs; /* headers of this message */
bool newline_p; /* whether the last line ended in a newline */
bool crypto_stamped_p; /* whether the header of this message has been
emitted expecting its child to emit HTML
which says that it is xlated. */
bool crypto_msg_signed_p; /* What the emitted xlation-stamp *says*. */
bool crypto_msg_encrypted_p;
bool grabSubject; /* Should we try to grab the subject of this message */
int32_t bodyLength; /* Used for determining if the body has been truncated */
int32_t sizeSoFar; /* The total size of the MIME message, once parsing is

View file

@ -14,6 +14,7 @@
#include "msgCore.h"
#include "nsMimeStringResources.h"
#include "mimemoz2.h"
#include "mimeeobj.h"
#include "nsIMimeConverter.h" // for MimeConverterOutputCallback
#include "mozilla/Attributes.h"
@ -32,6 +33,8 @@ static void MimeMultipartSigned_finalize (MimeObject *);
static int MimeMultipartSigned_emit_child (MimeObject *obj);
extern "C" MimeSuppressedCryptoClass mimeSuppressedCryptoClass;
static int
MimeMultipartSignedClassInitialize(MimeMultipartSignedClass *clazz)
{
@ -582,6 +585,11 @@ MimeMultipartSigned_emit_child (MimeObject *obj)
int status = 0;
MimeObject *body;
if (!sig->crypto_closure) {
// We might have decided to skip processing this part.
return 0;
}
NS_ASSERTION(sig->crypto_closure, "no crypto closure");
/* Emit some HTML saying whether the signature was cool.
@ -594,15 +602,11 @@ MimeMultipartSigned_emit_child (MimeObject *obj)
obj->options->headers != MimeHeadersCitation &&
sig->crypto_closure)
{
// Calling crypto_generate_html may trigger wanted side effects,
// but we're no longer using its results.
char *html = (((MimeMultipartSignedClass *) obj->clazz)
->crypto_generate_html (sig->crypto_closure));
#if 0 // XXX For the moment, no HTML output. Fix this XXX //
if (!html) return -1; /* MIME_OUT_OF_MEMORY? */
status = MimeObject_write(obj, html, strlen(html), false);
PR_Free(html);
if (status < 0) return status;
#endif
PR_FREEIF(html);
/* Now that we have written out the crypto stamp, the outermost header
block is well and truly closed. If this is in fact the outermost
@ -719,6 +723,11 @@ MimeMultipartSigned_emit_child (MimeObject *obj)
if (!body)
return -1;
if (mime_typep(body, (MimeObjectClass *)&mimeSuppressedCryptoClass)) {
((MimeMultipartSignedClass *)obj->clazz)
->crypto_notify_suppressed_child(sig->crypto_closure);
}
#ifdef MIME_DRAFTS
if (body->options->decompose_file_p) {
body->options->signed_p = true;

View file

@ -105,6 +105,8 @@ struct MimeMultipartSignedClass {
char * (*crypto_generate_html) (void *crypto_closure);
void (*crypto_notify_suppressed_child)(void *crypto_closure);
void (*crypto_free) (void *crypto_closure);
};

View file

@ -43,6 +43,7 @@ extern "C" MimeObjectClass mimeMultipartRelatedClass;
extern "C" MimeObjectClass mimeMultipartSignedClass;
extern "C" MimeObjectClass mimeInlineTextVCardClass;
extern "C" MimeExternalObjectClass mimeExternalObjectClass;
extern "C" MimeSuppressedCryptoClass mimeSuppressedCryptoClass;
#if defined(DEBUG) && defined(XP_UNIX)
static int MimeMultipart_debug_print (MimeObject *, PRFileDesc *, int32_t);
@ -471,7 +472,9 @@ MimeMultipart_create_child(MimeObject *obj)
part functions set correctly */
!mime_typep(body, (MimeObjectClass*) &mimeMultipartClass)
#endif
&& ! (mime_typep(body, (MimeObjectClass*)&mimeExternalObjectClass) && !strcmp(body->content_type, "text/x-vcard"))
&& !((mime_typep(body, (MimeObjectClass *)&mimeExternalObjectClass) ||
mime_typep(body, (MimeObjectClass *)&mimeSuppressedCryptoClass)) &&
!strcmp(body->content_type, "text/x-vcard"))
)
{
status = obj->options->decompose_file_init_fn ( obj->options->stream_closure, mult->hdrs );
@ -575,7 +578,9 @@ MimeMultipart_close_child(MimeObject *object)
part functions set correctly */
!mime_typep(kid,(MimeObjectClass*) &mimeMultipartClass)
#endif
&& !(mime_typep(kid, (MimeObjectClass*)&mimeExternalObjectClass) && !strcmp(kid->content_type, "text/x-vcard"))
&& !((mime_typep(kid, (MimeObjectClass *)&mimeExternalObjectClass) ||
mime_typep(kid, (MimeObjectClass *)&mimeSuppressedCryptoClass)) &&
!strcmp(kid->content_type, "text/x-vcard"))
)
{
status = object->options->decompose_file_close_fn ( object->options->stream_closure );