in mailnews/mime/src/mimemsg.cpp [224:482]
static int MimeMessage_close_headers(MimeObject* obj) {
MimeMessage* msg = (MimeMessage*)obj;
int status = 0;
char* ct = 0; /* Content-Type header */
MimeObject* body;
// Do a proper decoding of the munged subject.
if (obj->headers && msg->hdrs && msg->grabSubject &&
obj->headers->munged_subject) {
// nsMsgI18NConvertToUnicode wants nsAStrings...
nsDependentCString orig(obj->headers->munged_subject);
nsAutoString dest;
// First, get the Content-Type, then extract the charset="whatever" part of
// it.
nsCString charset;
nsCString contentType;
contentType.Adopt(
MimeHeaders_get(msg->hdrs, HEADER_CONTENT_TYPE, false, false));
if (!contentType.IsEmpty())
charset.Adopt(MimeHeaders_get_parameter(contentType.get(), "charset",
nullptr, nullptr));
// If we've got a charset, use nsMsgI18NConvertToUnicode to magically decode
// the munged subject.
if (!charset.IsEmpty()) {
nsresult rv = nsMsgI18NConvertToUnicode(charset, orig, dest);
// If we managed to convert the string, replace munged_subject with the
// UTF8 version of it, otherwise, just forget about it (maybe there was an
// improperly encoded string in there).
PR_Free(obj->headers->munged_subject);
if (NS_SUCCEEDED(rv))
obj->headers->munged_subject = ToNewUTF8String(dest);
else
obj->headers->munged_subject = nullptr;
} else {
PR_Free(obj->headers->munged_subject);
obj->headers->munged_subject = nullptr;
}
}
if (msg->hdrs) {
bool outer_p = !obj->headers; /* is this the outermost message? */
#ifdef MIME_DRAFTS
if (outer_p && obj->options &&
(obj->options->decompose_file_p ||
obj->options->caller_need_root_headers) &&
obj->options->decompose_headers_info_fn) {
# ifdef ENABLE_SMIME
if (obj->options->decrypt_p &&
!mime_crypto_object_p(msg->hdrs, false, obj->options))
obj->options->decrypt_p = false;
# endif /* ENABLE_SMIME */
if (!obj->options->caller_need_root_headers ||
(obj == obj->options->state->root))
status = obj->options->decompose_headers_info_fn(
obj->options->stream_closure, msg->hdrs);
}
#endif /* MIME_DRAFTS */
/* If this is the outermost message, we need to run the
`generate_header' callback. This happens here instead of
in `parse_begin', because it's only now that we've parsed
our headers. However, since this is the outermost message,
we have yet to write any HTML, so that's fine.
*/
if (outer_p && obj->output_p && obj->options &&
obj->options->write_html_p && obj->options->generate_header_html_fn) {
int lstatus = 0;
char* html = 0;
/* The generate_header_html_fn might return HTML, so it's important
that the output stream be set up with the proper type before we
make the MimeObject_write() call below. */
if (!obj->options->state->first_data_written_p) {
lstatus = MimeObject_output_init(obj, TEXT_HTML);
if (lstatus < 0) return lstatus;
PR_ASSERT(obj->options->state->first_data_written_p);
}
html = obj->options->generate_header_html_fn(
NULL, obj->options->html_closure, msg->hdrs);
if (html) {
lstatus = MimeObject_write(obj, html, strlen(html), false);
PR_Free(html);
if (lstatus < 0) return lstatus;
}
}
/* Find the content-type of the body of this message.
*/
{
bool ok = true;
char* mv = MimeHeaders_get(msg->hdrs, HEADER_MIME_VERSION, true, false);
#ifdef REQUIRE_MIME_VERSION_HEADER
/* If this is the outermost message, it must have a MIME-Version
header with the value 1.0 for us to believe what might be in
the Content-Type header. If the MIME-Version header is not
present, we must treat this message as untyped.
*/
ok = (mv && !strcmp(mv, "1.0"));
#else
/* #### actually, we didn't check this in Mozilla 2.0, and checking
it now could cause some compatibility nonsense, so for now, let's
just believe any Content-Type header we see.
*/
ok = true;
#endif
if (ok) {
ct = MimeHeaders_get(msg->hdrs, HEADER_CONTENT_TYPE, true, false);
/* If there is no Content-Type header, but there is a MIME-Version
header, then assume that this *is* in fact a MIME message.
(I've seen messages with
MIME-Version: 1.0
Content-Transfer-Encoding: quoted-printable
and no Content-Type, and we should treat those as being of type
MimeInlineTextPlain rather than MimeUntypedText.)
*/
if (mv && !ct) ct = strdup(TEXT_PLAIN);
}
PR_FREEIF(mv); /* done with this now. */
}
/* If this message has a body which is encrypted and we're going to
decrypt it (without converting it to HTML, since decrypt_p and
write_html_p are never true at the same time)
*/
if (obj->output_p && obj->options && obj->options->decrypt_p
#ifdef ENABLE_SMIME
&& !mime_crypto_object_p(msg->hdrs, false, obj->options)
#endif /* ENABLE_SMIME */
) {
/* The body of this message is not an encrypted object, so we need
to turn off the decrypt_p flag (to prevent us from s#$%ing the
body of the internal object up into one.) In this case,
our output will end up being identical to our input.
*/
obj->options->decrypt_p = false;
}
/* Emit the HTML for this message's headers. Do this before
creating the object representing the body.
*/
if (obj->output_p && obj->options && obj->options->write_html_p) {
/* If citation headers are on, and this is not the outermost message,
turn them off. */
if (obj->options->headers == MimeHeadersCitation && !outer_p)
obj->options->headers = MimeHeadersSome;
/* Emit a normal header block. */
status = MimeMessage_write_headers_html(obj);
if (status < 0) {
PR_FREEIF(ct);
return status;
}
} else if (obj->output_p) {
/* Dump the headers, raw. */
status = MimeObject_write(obj, "", 0, false); /* initialize */
if (status < 0) {
PR_FREEIF(ct);
return status;
}
status = MimeHeaders_write_raw_headers(msg->hdrs, obj->options,
obj->options->decrypt_p);
if (status < 0) {
PR_FREEIF(ct);
return status;
}
}
#ifdef XP_UNIX
if (outer_p && obj->output_p) /* Kludge from mimehdrs.c */
MimeHeaders_do_unix_display_hook_hack(msg->hdrs);
#endif /* XP_UNIX */
}
/* Never put out a separator after a message header block. */
if (obj->options && obj->options->state)
obj->options->state->separator_suppressed_p = true;
#ifdef MIME_DRAFTS
if (!obj->headers && /* outer most message header */
obj->options && obj->options->decompose_file_p && ct)
obj->options->is_multipart_msg = PL_strcasestr(ct, "multipart/") != NULL;
#endif /* MIME_DRAFTS */
body = mime_create(ct, msg->hdrs, obj->options);
PR_FREEIF(ct);
if (!body) return MIME_OUT_OF_MEMORY;
status = ((MimeContainerClass*)obj->clazz)->add_child(obj, body);
if (status < 0) {
mime_free(body);
return status;
}
// Only do this if this is a Text Object!
if (mime_typep(body, (MimeObjectClass*)&mimeInlineTextClass)) {
((MimeInlineText*)body)->needUpdateMsgWinCharset = true;
}
/* Now that we've added this new object to our list of children,
start its parser going. */
status = body->clazz->parse_begin(body);
if (status < 0) return status;
// Now notify the emitter if this is the outer most message, unless
// it is a part that is not the head of the message. If it's a part,
// we need to figure out the content type/charset of the part
//
bool outer_p = !obj->headers; /* is this the outermost message? */
if ((outer_p || obj->options->notify_nested_bodies) &&
(!obj->options->part_to_load ||
obj->options->format_out == nsMimeOutput::nsMimeMessageBodyDisplay)) {
// call SetMailCharacterSetToMsgWindow() to set a menu charset
if (mime_typep(body, (MimeObjectClass*)&mimeInlineTextClass)) {
MimeInlineText* text = (MimeInlineText*)body;
if (text && text->charset && *text->charset)
SetMailCharacterSetToMsgWindow(body, text->charset);
}
char* msgID = MimeHeaders_get(msg->hdrs, HEADER_MESSAGE_ID, false, false);
const char* outCharset = NULL;
if (!obj->options
->force_user_charset) /* Only convert if the user prefs is false */
outCharset = "UTF-8";
mimeEmitterStartBody(obj->options,
(obj->options->headers == MimeHeadersNone), msgID,
outCharset);
PR_FREEIF(msgID);
// setting up truncated message html fotter function
char* xmoz =
MimeHeaders_get(msg->hdrs, HEADER_X_MOZILLA_STATUS, false, false);
if (xmoz) {
uint32_t flags = 0;
char dummy = 0;
if (sscanf(xmoz, " %x %c", &flags, &dummy) == 1 &&
flags & nsMsgMessageFlags::Partial) {
obj->options->html_closure =
MimeClosure(MimeClosure::isMimeMessage, obj);
obj->options->generate_footer_html_fn =
MimeMessage_partial_message_html;
}
PR_FREEIF(xmoz);
}
}
return 0;
}