mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 16:22:00 +00:00
Fix for bug 112625. When decomosing a message to file, we need to parse children of a multipart/alternative part. R=cavin, SR=mscott
This commit is contained in:
parent
58dd9abb3a
commit
ab48b42be3
@ -1376,7 +1376,7 @@ mime_parse_stream_complete (nsMIMESession *stream)
|
||||
if( PL_strcasestr(mdd->messageBody->type, "text/html"))
|
||||
composeFormat = nsIMsgCompFormat::HTML;
|
||||
else if ( PL_strcasestr(mdd->messageBody->type, "text/plain") ||
|
||||
PL_strcasecmp(mdd->messageBody->type, "text") )
|
||||
!PL_strcasecmp(mdd->messageBody->type, "text") )
|
||||
composeFormat = nsIMsgCompFormat::PlainText;
|
||||
else
|
||||
{
|
||||
@ -1684,24 +1684,20 @@ mime_decompose_file_init_fn ( void *stream_closure, MimeHeaders *headers )
|
||||
if (!mdd || !headers)
|
||||
return -1;
|
||||
|
||||
if ( !mdd->options->is_multipart_msg )
|
||||
if (mdd->options->decompose_init_count)
|
||||
{
|
||||
if (mdd->options->decompose_init_count)
|
||||
{
|
||||
mdd->options->decompose_init_count++;
|
||||
NS_ASSERTION(mdd->curAttachment, "missing attachment in mime_decompose_file_init_fn");
|
||||
if (mdd->curAttachment) {
|
||||
char *ct = MimeHeaders_get(headers, HEADER_CONTENT_TYPE, PR_TRUE, PR_FALSE);
|
||||
if (ct)
|
||||
NS_MsgSACopy(&(mdd->curAttachment->type), ct);
|
||||
PR_FREEIF(ct);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
mdd->options->decompose_init_count++;
|
||||
mdd->options->decompose_init_count++;
|
||||
NS_ASSERTION(mdd->curAttachment, "missing attachment in mime_decompose_file_init_fn");
|
||||
if (mdd->curAttachment) {
|
||||
char *ct = MimeHeaders_get(headers, HEADER_CONTENT_TYPE, PR_TRUE, PR_FALSE);
|
||||
if (ct)
|
||||
NS_MsgSACopy(&(mdd->curAttachment->type), ct);
|
||||
PR_FREEIF(ct);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
mdd->options->decompose_init_count++;
|
||||
|
||||
nAttachments = mdd->attachments_count;
|
||||
|
||||
@ -1945,11 +1941,8 @@ mime_decompose_file_close_fn ( void *stream_closure )
|
||||
if ( !mdd || !mdd->tmpFileStream )
|
||||
return -1;
|
||||
|
||||
if ( !mdd->options->is_multipart_msg )
|
||||
{
|
||||
if ( --mdd->options->decompose_init_count > 0 )
|
||||
if ( --mdd->options->decompose_init_count > 0 )
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mdd->decoder_data) {
|
||||
MimeDecoderDestroy(mdd->decoder_data, PR_FALSE);
|
||||
@ -1958,7 +1951,10 @@ mime_decompose_file_close_fn ( void *stream_closure )
|
||||
|
||||
if (mdd->tmpFileStream->GetIStream())
|
||||
mdd->tmpFileStream->close();
|
||||
|
||||
delete mdd->tmpFileStream;
|
||||
mdd->tmpFileStream = nsnull;
|
||||
|
||||
delete mdd->tmpFileSpec;
|
||||
mdd->tmpFileSpec = nsnull;
|
||||
|
||||
@ -1973,8 +1969,8 @@ mime_bridge_create_draft_stream(
|
||||
nsMimeOutputType format_out)
|
||||
{
|
||||
int status = 0;
|
||||
nsMIMESession *stream = NULL;
|
||||
struct mime_draft_data *mdd = NULL;
|
||||
nsMIMESession *stream = nsnull;
|
||||
struct mime_draft_data *mdd = nsnull;
|
||||
MimeObject *obj;
|
||||
|
||||
if ( !uri )
|
||||
|
@ -44,18 +44,18 @@
|
||||
|
||||
#define MIME_SUPERCLASS mimeMultipartClass
|
||||
MimeDefClass(MimeMultipartAlternative, MimeMultipartAlternativeClass,
|
||||
mimeMultipartAlternativeClass, &MIME_SUPERCLASS);
|
||||
mimeMultipartAlternativeClass, &MIME_SUPERCLASS);
|
||||
|
||||
static int MimeMultipartAlternative_initialize (MimeObject *);
|
||||
static void MimeMultipartAlternative_finalize (MimeObject *);
|
||||
static int MimeMultipartAlternative_parse_eof (MimeObject *, PRBool);
|
||||
static int MimeMultipartAlternative_create_child(MimeObject *);
|
||||
static int MimeMultipartAlternative_parse_child_line (MimeObject *, char *,
|
||||
PRInt32, PRBool);
|
||||
PRInt32, PRBool);
|
||||
static int MimeMultipartAlternative_close_child(MimeObject *);
|
||||
|
||||
static PRBool MimeMultipartAlternative_display_part_p(MimeObject *self,
|
||||
MimeHeaders *sub_hdrs);
|
||||
MimeHeaders *sub_hdrs);
|
||||
static int MimeMultipartAlternative_discard_cached_part(MimeObject *);
|
||||
static int MimeMultipartAlternative_display_cached_part(MimeObject *);
|
||||
|
||||
@ -83,7 +83,7 @@ MimeMultipartAlternative_initialize (MimeObject *obj)
|
||||
PR_ASSERT(!malt->part_buffer);
|
||||
malt->part_buffer = MimePartBufferCreate();
|
||||
if (!malt->part_buffer)
|
||||
return MIME_OUT_OF_MEMORY;
|
||||
return MIME_OUT_OF_MEMORY;
|
||||
|
||||
return ((MimeObjectClass*)&MIME_SUPERCLASS)->initialize(obj);
|
||||
}
|
||||
@ -93,15 +93,15 @@ MimeMultipartAlternative_cleanup(MimeObject *obj)
|
||||
{
|
||||
MimeMultipartAlternative *malt = (MimeMultipartAlternative *) obj;
|
||||
if (malt->buffered_hdrs)
|
||||
{
|
||||
MimeHeaders_free(malt->buffered_hdrs);
|
||||
malt->buffered_hdrs = 0;
|
||||
}
|
||||
{
|
||||
MimeHeaders_free(malt->buffered_hdrs);
|
||||
malt->buffered_hdrs = 0;
|
||||
}
|
||||
if (malt->part_buffer)
|
||||
{
|
||||
MimePartBufferDestroy(malt->part_buffer);
|
||||
malt->part_buffer = 0;
|
||||
}
|
||||
{
|
||||
MimePartBufferDestroy(malt->part_buffer);
|
||||
malt->part_buffer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -127,10 +127,10 @@ MimeMultipartAlternative_parse_eof (MimeObject *obj, PRBool abort_p)
|
||||
/* If there's a cached part we haven't written out yet, do it now.
|
||||
*/
|
||||
if (malt->buffered_hdrs && !abort_p)
|
||||
{
|
||||
status = MimeMultipartAlternative_display_cached_part(obj);
|
||||
if (status < 0) return status;
|
||||
}
|
||||
{
|
||||
status = MimeMultipartAlternative_display_cached_part(obj);
|
||||
if (status < 0) return status;
|
||||
}
|
||||
|
||||
MimeMultipartAlternative_cleanup(obj);
|
||||
|
||||
@ -145,39 +145,39 @@ MimeMultipartAlternative_create_child(MimeObject *obj)
|
||||
MimeMultipartAlternative *malt = (MimeMultipartAlternative *) obj;
|
||||
|
||||
if (MimeMultipartAlternative_display_part_p (obj, mult->hdrs))
|
||||
{
|
||||
/* If this part is potentially displayable, begin populating the cache
|
||||
with it. If there's something in the cache already, discard it
|
||||
first. (Just because this part is displayable doesn't mean we will
|
||||
display it -- of two consecutive displayable parts, it is the second
|
||||
one that gets displayed.)
|
||||
*/
|
||||
int status;
|
||||
mult->state = MimeMultipartPartFirstLine;
|
||||
{
|
||||
/* If this part is potentially displayable, begin populating the cache
|
||||
with it. If there's something in the cache already, discard it
|
||||
first. (Just because this part is displayable doesn't mean we will
|
||||
display it -- of two consecutive displayable parts, it is the second
|
||||
one that gets displayed.)
|
||||
*/
|
||||
int status;
|
||||
mult->state = MimeMultipartPartFirstLine;
|
||||
|
||||
status = MimeMultipartAlternative_discard_cached_part(obj);
|
||||
if (status < 0) return status;
|
||||
status = MimeMultipartAlternative_discard_cached_part(obj);
|
||||
if (status < 0) return status;
|
||||
|
||||
PR_ASSERT(!malt->buffered_hdrs);
|
||||
malt->buffered_hdrs = MimeHeaders_copy(mult->hdrs);
|
||||
if (!malt->buffered_hdrs) return MIME_OUT_OF_MEMORY;
|
||||
return 0;
|
||||
}
|
||||
PR_ASSERT(!malt->buffered_hdrs);
|
||||
malt->buffered_hdrs = MimeHeaders_copy(mult->hdrs);
|
||||
if (!malt->buffered_hdrs) return MIME_OUT_OF_MEMORY;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If this part is not displayable, then we're done -- all that is left
|
||||
to do is to flush out the part that is currently in the cache.
|
||||
*/
|
||||
mult->state = MimeMultipartEpilogue;
|
||||
return MimeMultipartAlternative_display_cached_part(obj);
|
||||
}
|
||||
{
|
||||
/* If this part is not displayable, then we're done -- all that is left
|
||||
to do is to flush out the part that is currently in the cache.
|
||||
*/
|
||||
mult->state = MimeMultipartEpilogue;
|
||||
return MimeMultipartAlternative_display_cached_part(obj);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
MimeMultipartAlternative_parse_child_line (MimeObject *obj,
|
||||
char *line, PRInt32 length,
|
||||
PRBool first_line_p)
|
||||
char *line, PRInt32 length,
|
||||
PRBool first_line_p)
|
||||
{
|
||||
MimeMultipartAlternative *malt = (MimeMultipartAlternative *) obj;
|
||||
|
||||
@ -195,15 +195,15 @@ MimeMultipartAlternative_close_child(MimeObject *obj)
|
||||
MimeMultipart *mult = (MimeMultipart *) obj;
|
||||
MimeMultipartAlternative *malt = (MimeMultipartAlternative *) obj;
|
||||
|
||||
/* PR_ASSERT(malt->part_buffer); Some Mac brokenness trips this...
|
||||
/* PR_ASSERT(malt->part_buffer); Some Mac brokenness trips this...
|
||||
if (!malt->part_buffer) return -1; */
|
||||
|
||||
if (malt->part_buffer)
|
||||
MimePartBufferClose(malt->part_buffer);
|
||||
MimePartBufferClose(malt->part_buffer);
|
||||
|
||||
/* PR_ASSERT(mult->hdrs); I expect the Mac trips this too */
|
||||
/* PR_ASSERT(mult->hdrs); I expect the Mac trips this too */
|
||||
if (mult->hdrs)
|
||||
MimeHeaders_free(mult->hdrs);
|
||||
MimeHeaders_free(mult->hdrs);
|
||||
mult->hdrs = 0;
|
||||
|
||||
return 0;
|
||||
@ -212,26 +212,26 @@ MimeMultipartAlternative_close_child(MimeObject *obj)
|
||||
|
||||
static PRBool
|
||||
MimeMultipartAlternative_display_part_p(MimeObject *self,
|
||||
MimeHeaders *sub_hdrs)
|
||||
MimeHeaders *sub_hdrs)
|
||||
{
|
||||
char *ct = MimeHeaders_get (sub_hdrs, HEADER_CONTENT_TYPE, PR_TRUE, PR_FALSE);
|
||||
|
||||
/* RFC 1521 says:
|
||||
Receiving user agents should pick and display the last format
|
||||
they are capable of displaying. In the case where one of the
|
||||
alternatives is itself of type "multipart" and contains unrecognized
|
||||
sub-parts, the user agent may choose either to show that alternative,
|
||||
an earlier alternative, or both.
|
||||
Receiving user agents should pick and display the last format
|
||||
they are capable of displaying. In the case where one of the
|
||||
alternatives is itself of type "multipart" and contains unrecognized
|
||||
sub-parts, the user agent may choose either to show that alternative,
|
||||
an earlier alternative, or both.
|
||||
|
||||
Ugh. If there is a multipart subtype of alternative, we simply show
|
||||
that, without descending into it to determine if any of its sub-parts
|
||||
are themselves unknown.
|
||||
Ugh. If there is a multipart subtype of alternative, we simply show
|
||||
that, without descending into it to determine if any of its sub-parts
|
||||
are themselves unknown.
|
||||
*/
|
||||
|
||||
MimeObjectClass *clazz = mime_find_class (ct, sub_hdrs, self->options, PR_FALSE);
|
||||
PRBool result = (clazz
|
||||
? clazz->displayable_inline_p(clazz, sub_hdrs)
|
||||
: PR_FALSE);
|
||||
? clazz->displayable_inline_p(clazz, sub_hdrs)
|
||||
: PR_FALSE);
|
||||
PR_FREEIF(ct);
|
||||
return result;
|
||||
}
|
||||
@ -242,12 +242,12 @@ MimeMultipartAlternative_discard_cached_part(MimeObject *obj)
|
||||
MimeMultipartAlternative *malt = (MimeMultipartAlternative *) obj;
|
||||
|
||||
if (malt->buffered_hdrs)
|
||||
{
|
||||
MimeHeaders_free(malt->buffered_hdrs);
|
||||
malt->buffered_hdrs = 0;
|
||||
}
|
||||
{
|
||||
MimeHeaders_free(malt->buffered_hdrs);
|
||||
malt->buffered_hdrs = 0;
|
||||
}
|
||||
if (malt->part_buffer)
|
||||
MimePartBufferReset (malt->part_buffer);
|
||||
MimePartBufferReset (malt->part_buffer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -259,68 +259,70 @@ MimeMultipartAlternative_display_cached_part(MimeObject *obj)
|
||||
int status;
|
||||
|
||||
char *ct = (malt->buffered_hdrs
|
||||
? MimeHeaders_get (malt->buffered_hdrs, HEADER_CONTENT_TYPE,
|
||||
PR_TRUE, PR_FALSE)
|
||||
: 0);
|
||||
? MimeHeaders_get (malt->buffered_hdrs, HEADER_CONTENT_TYPE,
|
||||
PR_TRUE, PR_FALSE)
|
||||
: 0);
|
||||
const char *dct = (((MimeMultipartClass *) obj->clazz)->default_part_type);
|
||||
MimeObject *body;
|
||||
PRBool multipart_p;
|
||||
|
||||
/* Don't pass in NULL as the content-type (this means that the
|
||||
auto-uudecode-hack won't ever be done for subparts of a
|
||||
multipart, but only for untyped children of message/rfc822.
|
||||
auto-uudecode-hack won't ever be done for subparts of a
|
||||
multipart, but only for untyped children of message/rfc822.
|
||||
*/
|
||||
body = mime_create(((ct && *ct) ? ct : (dct ? dct: TEXT_PLAIN)),
|
||||
malt->buffered_hdrs, obj->options);
|
||||
malt->buffered_hdrs, obj->options);
|
||||
|
||||
PR_FREEIF(ct);
|
||||
if (!body) return MIME_OUT_OF_MEMORY;
|
||||
|
||||
multipart_p = mime_typep(body, (MimeObjectClass *) &mimeMultipartClass);
|
||||
|
||||
status = ((MimeContainerClass *) obj->clazz)->add_child(obj, body);
|
||||
if (status < 0)
|
||||
{
|
||||
mime_free(body);
|
||||
return status;
|
||||
}
|
||||
{
|
||||
mime_free(body);
|
||||
return status;
|
||||
}
|
||||
|
||||
#ifdef MIME_DRAFTS
|
||||
if ( obj->options &&
|
||||
obj->options->decompose_file_p &&
|
||||
!multipart_p &&
|
||||
obj->options->decompose_file_init_fn )
|
||||
{
|
||||
status = obj->options->decompose_file_init_fn (
|
||||
obj->options->stream_closure,
|
||||
malt->buffered_hdrs);
|
||||
if (status < 0) return status;
|
||||
}
|
||||
/* if this object is a child of a multipart/related object, the parent is
|
||||
taking care of decomposing the whole part, don't need to do it at this level.
|
||||
However, we still have to call decompose_file_init_fn and decompose_file_close_fn
|
||||
in order to set the correct content-type. But don't call MimePartBufferRead
|
||||
*/
|
||||
PRBool multipartChild = mime_typep(obj->parent, (MimeObjectClass *) &mimeMultipartClass);
|
||||
PRBool decomposeFile = obj->options &&
|
||||
obj->options->decompose_file_p &&
|
||||
obj->options->decompose_file_init_fn &&
|
||||
!mime_typep(body, (MimeObjectClass *) &mimeMultipartClass);
|
||||
|
||||
if (decomposeFile)
|
||||
{
|
||||
status = obj->options->decompose_file_init_fn (
|
||||
obj->options->stream_closure,
|
||||
malt->buffered_hdrs);
|
||||
if (status < 0) return status;
|
||||
}
|
||||
#endif /* MIME_DRAFTS */
|
||||
|
||||
|
||||
/* Now that we've added this new object to our list of children,
|
||||
start its parser going. */
|
||||
start its parser going. */
|
||||
status = body->clazz->parse_begin(body);
|
||||
if (status < 0) return status;
|
||||
|
||||
#ifdef MIME_DRAFTS
|
||||
if ( obj->options &&
|
||||
obj->options->decompose_file_p &&
|
||||
!multipart_p &&
|
||||
obj->options->decompose_file_output_fn )
|
||||
status = MimePartBufferRead (malt->part_buffer,
|
||||
obj->options->decompose_file_output_fn,
|
||||
obj->options->stream_closure);
|
||||
if (decomposeFile && !multipartChild)
|
||||
status = MimePartBufferRead (malt->part_buffer,
|
||||
obj->options->decompose_file_output_fn,
|
||||
obj->options->stream_closure);
|
||||
else
|
||||
#endif /* MIME_DRAFTS */
|
||||
|
||||
status = MimePartBufferRead (malt->part_buffer,
|
||||
/* The (nsresult (*) ...) cast is to turn the
|
||||
`void' argument into `MimeObject'. */
|
||||
((nsresult (*) (char *, PRInt32, void *))
|
||||
body->clazz->parse_buffer),
|
||||
body);
|
||||
status = MimePartBufferRead (malt->part_buffer,
|
||||
/* The (nsresult (*) ...) cast is to turn the
|
||||
`void' argument into `MimeObject'. */
|
||||
((nsresult (*) (char *, PRInt32, void *))
|
||||
body->clazz->parse_buffer),
|
||||
body);
|
||||
|
||||
if (status < 0) return status;
|
||||
|
||||
@ -333,12 +335,10 @@ MimeMultipartAlternative_display_cached_part(MimeObject *obj)
|
||||
if (status < 0) return status;
|
||||
|
||||
#ifdef MIME_DRAFTS
|
||||
if ( obj->options &&
|
||||
obj->options->decompose_file_p &&
|
||||
!multipart_p &&
|
||||
obj->options->decompose_file_close_fn ) {
|
||||
status = obj->options->decompose_file_close_fn ( obj->options->stream_closure );
|
||||
if (status < 0) return status;
|
||||
if (decomposeFile)
|
||||
{
|
||||
status = obj->options->decompose_file_close_fn ( obj->options->stream_closure );
|
||||
if (status < 0) return status;
|
||||
}
|
||||
#endif /* MIME_DRAFTS */
|
||||
|
||||
|
@ -189,10 +189,15 @@ MimeObject_parse_begin (MimeObject *obj)
|
||||
}
|
||||
|
||||
/* Decide whether this object should be output or not... */
|
||||
if (!obj->options || !obj->options->output_fn)
|
||||
obj->output_p = PR_FALSE;
|
||||
if (!obj->options || !obj->options->output_fn
|
||||
/* if we are decomposing the message in files and processing a multipart object,
|
||||
we must not output it without parsing it first */
|
||||
|| (obj->options->decompose_file_p && obj->options->decompose_file_output_fn &&
|
||||
mime_typep(obj, (MimeObjectClass*) &mimeMultipartClass))
|
||||
)
|
||||
obj->output_p = PR_FALSE;
|
||||
else if (!obj->options->part_to_load)
|
||||
obj->output_p = PR_TRUE;
|
||||
obj->output_p = PR_TRUE;
|
||||
else
|
||||
{
|
||||
char *id = mime_part_address(obj);
|
||||
|
Loading…
Reference in New Issue
Block a user