gecko-dev/lib/libmime/mimedrft.c

934 строки
25 KiB
C

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/* mimedrft.c --- save and restore drafts of unfinished messages
*/
#include "xp.h"
#include "xpgetstr.h"
#include "libi18n.h"
#include "xp_time.h"
#include "msgcom.h"
#include "mimeobj.h"
#include "mimemsg.h"
#include "mimeenc.h" /* jrm - needed to make it build 97/02/21 */
#define HEADER_NNTP_POSTING_HOST "NNTP-Posting-Host"
extern int MK_UNABLE_TO_OPEN_TMP_FILE;
extern int MK_MIME_ERROR_WRITING_FILE;
extern int MK_MIMEHTML_DISP_SUBJECT;
extern int MK_MIMEHTML_DISP_DATE;
extern int MK_MIMEHTML_DISP_FROM;
extern int MK_MIMEHTML_DISP_ORGANIZATION;
extern int MK_MIMEHTML_DISP_TO;
extern int MK_MIMEHTML_DISP_CC;
extern int MK_MIMEHTML_DISP_NEWSGROUPS;
extern int MK_MIMEHTML_DISP_BCC;
int
mime_decompose_file_init_fn ( void *stream_closure,
MimeHeaders *headers );
int
mime_decompose_file_output_fn ( char *buf,
int32 size,
void *stream_closure );
int
mime_decompose_file_close_fn ( void *stream_closure );
extern char *
strip_continuations(char *original);
/* This struct is the state we used in MIME_ToDraftConverter() */
struct mime_draft_data {
URL_Struct *url; /* original url */
int format_out; /* intended output format;
should be FO_OPEN_DRAFT */
MWContext *context;
NET_StreamClass *stream; /* not used for now */
MimeObject *obj; /* The root */
MimeDisplayOptions *options; /* data for communicating with libmime.a */
MimeHeaders *headers; /* copy of outer most mime header */
int attachments_count; /* how many attachments we have */
MSG_AttachedFile *attachments; /* attachments */
MSG_AttachedFile *messageBody; /* message body */
MSG_AttachedFile *curAttachment; /* temp */
char *tmp_file_name; /* current opened file for output */
XP_File tmp_file; /* output file handle */
MimeDecoderData *decoder_data;
int16 mailcsid; /* get it from CHARSET of Content-Type and convert to csid */
};
static int
dummy_file_write( char *buf, int32 size, void *fileHandle )
{
return XP_FileWrite(buf, size, (XP_File) fileHandle);
}
static int
mime_parse_stream_write ( NET_StreamClass *stream,
const char *buf,
int32 size )
{
struct mime_draft_data *mdd = (struct mime_draft_data *) stream->data_object;
XP_ASSERT ( mdd );
if ( !mdd || !mdd->obj ) return -1;
return mdd->obj->class->parse_buffer ((char *) buf, size, mdd->obj);
}
static unsigned int
mime_parse_stream_write_ready ( NET_StreamClass *stream )
{
struct mime_draft_data *mdd = (struct mime_draft_data *) stream->data_object;
XP_ASSERT (mdd);
if (!mdd) return MAX_WRITE_READY;
if (mdd->stream)
return mdd->stream->is_write_ready ( mdd->stream );
else
return MAX_WRITE_READY;
}
static void
mime_free_attachments ( MSG_AttachedFile *attachments,
int count )
{
int i;
MSG_AttachedFile *cur = attachments;
XP_ASSERT ( attachments && count > 0 );
if ( !attachments || count <= 0 ) return;
for ( i = 0; i < count; i++, cur++ ) {
FREEIF ( cur->orig_url );
FREEIF ( cur->type );
FREEIF ( cur->encoding );
FREEIF ( cur->description );
FREEIF ( cur->x_mac_type );
FREEIF ( cur->x_mac_creator );
if ( cur->file_name ) {
XP_FileRemove( cur->file_name, xpFileToPost );
FREEIF ( cur->file_name );
}
}
XP_FREE ( attachments );
}
static int
mime_draft_process_attachments ( struct mime_draft_data *mdd,
MSG_Pane *cpane )
{
struct MSG_AttachmentData *attachData = NULL, *tmp = NULL;
struct MSG_AttachedFile *tmpFile = NULL;
int i;
XP_ASSERT ( mdd->attachments_count && mdd->attachments );
if ( !mdd->attachments || !mdd->attachments_count )
return -1;
attachData = XP_ALLOC( ( (mdd->attachments_count+1) * sizeof (MSG_AttachmentData) ) );
if ( !attachData ) return MK_OUT_OF_MEMORY;
XP_MEMSET ( attachData, 0, (mdd->attachments_count+1) * sizeof (MSG_AttachmentData) );
tmpFile = mdd->attachments;
tmp = attachData;
for ( i=0; i < mdd->attachments_count; i++, tmp++, tmpFile++ ) {
if (tmpFile->type) {
if (strcasecomp ( tmpFile->type, "text/x-vcard") == 0)
StrAllocCopy (tmp->real_name, tmpFile->description);
}
if ( tmpFile->orig_url ) {
StrAllocCopy ( tmp->url, tmpFile->orig_url );
if (!tmp->real_name)
StrAllocCopy ( tmp->real_name, tmpFile->orig_url );
}
if ( tmpFile->type ) {
StrAllocCopy ( tmp->desired_type, tmpFile->type );
StrAllocCopy ( tmp->real_type, tmpFile->type );
}
if ( tmpFile->encoding ) {
StrAllocCopy ( tmp->real_encoding, tmpFile->encoding );
}
if ( tmpFile->description ) {
StrAllocCopy ( tmp->description, tmpFile->description );
}
if ( tmpFile->x_mac_type ) {
StrAllocCopy ( tmp->x_mac_type, tmpFile->x_mac_type );
}
if ( tmpFile->x_mac_creator ) {
StrAllocCopy ( tmp->x_mac_creator, tmpFile->x_mac_creator );
}
}
MSG_SetPreloadedAttachments ( cpane, MSG_GetContext (cpane), attachData,
mdd->attachments, mdd->attachments_count );
XP_FREE (attachData);
return 0;
}
static void mime_fix_up_html_address( char **addr)
{
/* We need to replace paired <> they are treated as HTML tag */
if (addr && *addr &&
XP_STRCHR(*addr, '<') && XP_STRCHR(*addr, '>'))
{
char *lt = NULL;
int32 newLen = 0;
do
{
newLen = XP_STRLEN(*addr) + 3 + 1;
*addr = (char *) XP_REALLOC(*addr, newLen);
XP_ASSERT (*addr);
lt = XP_STRCHR(*addr, '<');
XP_ASSERT(lt);
XP_MEMCPY(lt+4, lt+1, newLen - 4 - (lt - *addr));
*lt++ = '&';
*lt++ = 'l';
*lt++ = 't';
*lt = ';';
} while (XP_STRCHR(*addr, '<'));
}
}
static void mime_intl_mimepart_2_str(char **str, int16 mcsid)
{
if (str && *str)
{
char *newStr = (char *) IntlDecodeMimePartIIStr
(*str, INTL_DocToWinCharSetID(mcsid), FALSE);
if (newStr && newStr != *str)
{
FREEIF(*str);
*str = newStr;
}
else
{
strip_continuations(*str);
}
}
}
static void mime_intl_insert_message_header(char **body, char**hdr_value,
char *hdr_str,
int html_hdr_id,
int16 mailcsid,
XP_Bool htmlEdit)
{
const char *newName = NULL;
if (!body || !hdr_value || !hdr_str)
return;
mime_intl_mimepart_2_str(hdr_value, mailcsid);
if (htmlEdit)
StrAllocCat(*body, LINEBREAK "<BR><B>");
else
StrAllocCat(*body, LINEBREAK);
newName = XP_GetStringForHTML(html_hdr_id, mailcsid, hdr_str);
if (!newName)
newName = hdr_str;
StrAllocCat(*body, newName);
if (htmlEdit)
StrAllocCat(*body, ":</B> ");
else
StrAllocCat(*body, ": ");
StrAllocCat(*body, *hdr_value);
}
static void
mime_parse_stream_complete (NET_StreamClass *stream)
{
struct mime_draft_data *mdd = (struct mime_draft_data *) stream->data_object;
MSG_Pane * cpane = NULL;
MSG_CompositionFields *fields = NULL;
int htmlAction = 0;
int lineWidth = 0;
char *host = 0;
char *news_host = 0;
char *to_and_cc = 0;
char *re_subject = 0;
char *new_refs = 0;
char *from = 0;
char *repl = 0;
char *subj = 0;
char *id = 0;
char *refs = 0;
char *to = 0;
char *cc = 0;
char *bcc = 0;
char *fcc = 0;
char *org = 0;
char *grps = 0;
char *foll = 0;
char *priority = 0;
char *draftInfo = 0;
XP_Bool encrypt_p = FALSE; /* #### how do we determine this? */
XP_Bool sign_p = FALSE; /* #### how do we determine this? */
XP_ASSERT (mdd);
if (!mdd) return;
if (mdd->obj) {
int status;
status = mdd->obj->class->parse_eof ( mdd->obj, FALSE );
mdd->obj->class->parse_end( mdd->obj, status < 0 ? TRUE : FALSE );
encrypt_p = mdd->options->decrypt_p;
sign_p = mdd->options->signed_p;
XP_ASSERT ( mdd->options == mdd->obj->options );
mime_free (mdd->obj);
mdd->obj = 0;
if (mdd->options) {
FREEIF (mdd->options->part_to_load);
XP_FREE(mdd->options);
mdd->options = 0;
}
if (mdd->stream) {
mdd->stream->complete (mdd->stream);
XP_FREE( mdd->stream );
mdd->stream = 0;
}
}
/* time to bring up the compose windows with all the info gathered */
if ( mdd->headers )
{
subj = MimeHeaders_get(mdd->headers, HEADER_SUBJECT, FALSE, FALSE);
repl = MimeHeaders_get(mdd->headers, HEADER_REPLY_TO, FALSE, FALSE);
to = MimeHeaders_get(mdd->headers, HEADER_TO, FALSE, TRUE);
cc = MimeHeaders_get(mdd->headers, HEADER_CC, FALSE, TRUE);
bcc = MimeHeaders_get(mdd->headers, HEADER_BCC, FALSE, TRUE);
/* These headers should not be RFC-1522-decoded. */
grps = MimeHeaders_get(mdd->headers, HEADER_NEWSGROUPS, FALSE, TRUE);
foll = MimeHeaders_get(mdd->headers, HEADER_FOLLOWUP_TO, FALSE, TRUE);
host = MimeHeaders_get(mdd->headers, HEADER_X_MOZILLA_NEWSHOST, FALSE, FALSE);
if (!host)
host = MimeHeaders_get(mdd->headers, HEADER_NNTP_POSTING_HOST, FALSE, FALSE);
id = MimeHeaders_get(mdd->headers, HEADER_MESSAGE_ID, FALSE, FALSE);
refs = MimeHeaders_get(mdd->headers, HEADER_REFERENCES, FALSE, TRUE);
priority = MimeHeaders_get(mdd->headers, HEADER_X_PRIORITY, FALSE, FALSE);
mime_intl_mimepart_2_str(&repl, mdd->mailcsid);
mime_intl_mimepart_2_str(&to, mdd->mailcsid);
mime_intl_mimepart_2_str(&cc, mdd->mailcsid);
mime_intl_mimepart_2_str(&bcc, mdd->mailcsid);
mime_intl_mimepart_2_str(&grps, mdd->mailcsid);
mime_intl_mimepart_2_str(&foll, mdd->mailcsid);
mime_intl_mimepart_2_str(&host, mdd->mailcsid);
if (host) {
char *secure = NULL;
secure = strcasestr(host, "secure");
if (secure) {
*secure = 0;
news_host = PR_smprintf ("snews://%s", host);
}
else {
news_host = PR_smprintf ("news://%s", host);
}
}
mime_intl_mimepart_2_str(&subj, mdd->mailcsid);
fields = MSG_CreateCompositionFields( from, repl, to, cc, bcc, fcc, grps, foll,
org, subj, refs, 0, priority, 0, news_host,
encrypt_p, sign_p);
draftInfo = MimeHeaders_get(mdd->headers, HEADER_X_MOZILLA_DRAFT_INFO, FALSE, FALSE);
if (draftInfo && fields) {
char *parm = 0;
parm = MimeHeaders_get_parameter(draftInfo, "vcard", NULL, NULL);
if (parm && !XP_STRCMP(parm, "1"))
MSG_SetCompFieldsBoolHeader(fields,
MSG_ATTACH_VCARD_BOOL_HEADER_MASK,
TRUE);
else
MSG_SetCompFieldsBoolHeader(fields,
MSG_ATTACH_VCARD_BOOL_HEADER_MASK,
FALSE);
FREEIF(parm);
parm = MimeHeaders_get_parameter(draftInfo, "receipt", NULL, NULL);
if (parm && !XP_STRCMP(parm, "0"))
MSG_SetCompFieldsBoolHeader(fields,
MSG_RETURN_RECEIPT_BOOL_HEADER_MASK,
FALSE);
else
{
int receiptType = 0;
MSG_SetCompFieldsBoolHeader(fields,
MSG_RETURN_RECEIPT_BOOL_HEADER_MASK,
TRUE);
sscanf(parm, "%d", &receiptType);
MSG_SetCompFieldsReceiptType(fields, (int32) receiptType);
}
FREEIF(parm);
parm = MimeHeaders_get_parameter(draftInfo, "uuencode", NULL, NULL);
if (parm && !XP_STRCMP(parm, "1"))
MSG_SetCompFieldsBoolHeader(fields,
MSG_UUENCODE_BINARY_BOOL_HEADER_MASK,
TRUE);
else
MSG_SetCompFieldsBoolHeader(fields,
MSG_UUENCODE_BINARY_BOOL_HEADER_MASK,
FALSE);
FREEIF(parm);
parm = MimeHeaders_get_parameter(draftInfo, "html", NULL, NULL);
if (parm)
sscanf(parm, "%d", &htmlAction);
FREEIF(parm);
parm = MimeHeaders_get_parameter(draftInfo, "linewidth", NULL, NULL);
if (parm)
sscanf(parm, "%d", &lineWidth);
FREEIF(parm);
}
if (mdd->messageBody) {
char *body;
XP_StatStruct st;
uint32 bodyLen = 0;
XP_File file;
MSG_EditorType editorType = MSG_DEFAULT;
st.st_size = 0;
XP_Stat (mdd->messageBody->file_name, &st, xpFileToPost);
bodyLen = st.st_size;
body = XP_ALLOC (bodyLen + 1);
if (body)
{
XP_MEMSET (body, 0, bodyLen+1);
file = XP_FileOpen (mdd->messageBody->file_name, xpFileToPost,
XP_FILE_READ_BIN);
XP_FileRead (body, bodyLen, file);
XP_FileClose(file);
if (mdd->messageBody->type && *mdd->messageBody->type)
{
if( XP_STRSTR(mdd->messageBody->type, "text/html") != NULL )
editorType = MSG_HTML_EDITOR;
else if ( XP_STRSTR(mdd->messageBody->type, "text/plain") != NULL )
editorType = MSG_PLAINTEXT_EDITOR;
}
else
{
editorType = MSG_PLAINTEXT_EDITOR;
}
{
CCCDataObject conv = INTL_CreateCharCodeConverter();
if(conv) {
if (INTL_GetCharCodeConverter(mdd->mailcsid,
INTL_DocToWinCharSetID(mdd->mailcsid), conv))
{
char *newBody = NULL;
newBody = (char *)INTL_CallCharCodeConverter(
conv, (unsigned char *) body, (int32) bodyLen);
if (newBody) {
/* CharCodeConverter return the char* to the orginal string
we don't want to free body in that case */
if( newBody != body)
FREEIF(body);
body = newBody;
}
}
INTL_DestroyCharCodeConverter(conv);
}
}
}
cpane = FE_CreateCompositionPane (mdd->context, fields, body, editorType);
XP_FREE (body);
mime_free_attachments (mdd->messageBody, 1);
}
else
{
cpane = FE_CreateCompositionPane(mdd->context, fields, NULL, MSG_DEFAULT);
}
if (cpane)
{
/* clear the message body in case someone store the signature string in it */
MSG_SetCompBody(cpane, "");
MSG_SetHTMLAction(cpane, (MSG_HTMLComposeAction) htmlAction);
if (lineWidth > 0)
MSG_SetLineWidth(cpane, lineWidth);
if ( mdd->attachments_count)
mime_draft_process_attachments (mdd, cpane);
}
}
else
{
fields = MSG_CreateCompositionFields( from, repl, to, cc, bcc, fcc, grps, foll,
org, subj, refs, 0, priority, 0, news_host,
MSG_GetMailEncryptionPreference(),
MSG_GetMailSigningPreference());
if (fields)
cpane = FE_CreateCompositionPane(mdd->context, fields, NULL, MSG_DEFAULT);
}
if (cpane && mdd->url->fe_data)
{
if ( mdd->format_out != FO_CMDLINE_ATTACHMENTS )
{
MSG_SetPostDeliveryActionInfo (cpane, mdd->url->fe_data);
}
else
{
MSG_SetAttachmentList ( cpane, (MSG_AttachmentData*)(mdd->url->fe_data));
}
}
if ( mdd->headers )
MimeHeaders_free ( mdd->headers );
if (mdd->attachments)
/* do not call mime_free_attachments just use FREEIF() */
FREEIF ( mdd->attachments );
if (fields)
MSG_DestroyCompositionFields(fields);
XP_FREE (mdd);
FREEIF(host);
FREEIF(to_and_cc);
FREEIF(re_subject);
FREEIF(new_refs);
FREEIF(from);
FREEIF(repl);
FREEIF(subj);
FREEIF(id);
FREEIF(refs);
FREEIF(to);
FREEIF(cc);
FREEIF(grps);
FREEIF(foll);
FREEIF(priority);
FREEIF(draftInfo);
}
static void
mime_parse_stream_abort (NET_StreamClass *stream, int status )
{
struct mime_draft_data *mdd = (struct mime_draft_data *) stream->data_object;
XP_ASSERT (mdd);
if (!mdd) return;
if (mdd->obj) {
int status;
if ( !mdd->obj->closed_p )
status = mdd->obj->class->parse_eof ( mdd->obj, TRUE );
if ( !mdd->obj->parsed_p )
mdd->obj->class->parse_end( mdd->obj, TRUE );
XP_ASSERT ( mdd->options == mdd->obj->options );
mime_free (mdd->obj);
mdd->obj = 0;
if (mdd->options) {
FREEIF (mdd->options->part_to_load);
XP_FREE(mdd->options);
mdd->options = 0;
}
if (mdd->stream) {
mdd->stream->abort (mdd->stream, status);
XP_FREE( mdd->stream );
mdd->stream = 0;
}
}
if ( mdd->headers )
MimeHeaders_free (mdd->headers);
if (mdd->attachments)
mime_free_attachments( mdd->attachments, mdd->attachments_count );
XP_FREE (mdd);
}
static int
make_mime_headers_copy ( void *closure,
MimeHeaders *headers )
{
struct mime_draft_data *mdd = (struct mime_draft_data *) closure;
XP_ASSERT ( mdd && headers );
if ( !mdd || ! headers ) return 0;
XP_ASSERT ( mdd->headers == NULL );
mdd->headers = MimeHeaders_copy ( headers );
mdd->options->done_parsing_outer_headers = TRUE;
return 0;
}
int
mime_decompose_file_init_fn ( void *stream_closure,
MimeHeaders *headers )
{
struct mime_draft_data *mdd = (struct mime_draft_data *) stream_closure;
MSG_AttachedFile *attachments = 0, *newAttachment = 0;
int nAttachments = 0;
char *hdr_value = NULL, *parm_value = NULL;
XP_Bool needURL = FALSE;
XP_Bool creatingMsgBody = FALSE;
XP_ASSERT (mdd && headers);
if (!mdd || !headers) return -1;
if ( !mdd->options->is_multipart_msg ) {
if (mdd->options->decompose_init_count) {
mdd->options->decompose_init_count++;
XP_ASSERT(mdd->curAttachment);
if (mdd->curAttachment) {
char *ct = MimeHeaders_get(headers, HEADER_CONTENT_TYPE, TRUE, FALSE);
if (ct)
StrAllocCopy(mdd->curAttachment->type, ct);
FREEIF(ct);
}
return 0;
}
else {
mdd->options->decompose_init_count++;
}
}
nAttachments = mdd->attachments_count;
if (!nAttachments && !mdd->messageBody) {
char *charset = NULL, *contentType = NULL;
contentType = MimeHeaders_get(headers, HEADER_CONTENT_TYPE, FALSE, FALSE);
if (contentType) {
charset = MimeHeaders_get_parameter(contentType, "charset", NULL, NULL);
mdd->mailcsid = INTL_CharSetNameToID(charset);
FREEIF(charset);
FREEIF(contentType);
}
mdd->messageBody = XP_NEW_ZAP (MSG_AttachedFile);
XP_ASSERT (mdd->messageBody);
if (!mdd->messageBody)
return MK_OUT_OF_MEMORY;
newAttachment = mdd->messageBody;
creatingMsgBody = TRUE;
}
else {
/* always allocate one more extra; don't ask me why */
needURL = TRUE;
if ( nAttachments ) {
XP_ASSERT (mdd->attachments);
attachments = XP_REALLOC (mdd->attachments,
sizeof (MSG_AttachedFile) *
(nAttachments + 2));
if (!attachments)
return MK_OUT_OF_MEMORY;
mdd->attachments = attachments;
mdd->attachments_count++;
}
else {
XP_ASSERT (!mdd->attachments);
attachments = XP_ALLOC ( sizeof (MSG_AttachedFile) * 2);
if (!attachments)
return MK_OUT_OF_MEMORY;
mdd->attachments_count++;
mdd->attachments = attachments;
}
newAttachment = attachments + nAttachments;
XP_MEMSET ( newAttachment, 0, sizeof (MSG_AttachedFile) * 2 );
}
newAttachment->orig_url = MimeHeaders_get_name ( headers );
if (!newAttachment->orig_url) {
parm_value = MimeHeaders_get( headers, HEADER_CONTENT_BASE, FALSE, FALSE );
if (parm_value) {
char *cp = NULL, *cp1=NULL ;
NET_UnEscape(parm_value);
/* strip '"' */
cp = parm_value;
while (*cp == '"') cp++;
if ((cp1 = XP_STRCHR(cp, '"')))
*cp1 = 0;
StrAllocCopy(newAttachment->orig_url, cp);
FREEIF(parm_value);
}
}
mdd->curAttachment = newAttachment;
newAttachment->type = MimeHeaders_get ( headers, HEADER_CONTENT_TYPE,
TRUE, FALSE );
/* This is to handle the degenerated Apple Double attachment.
*/
parm_value = MimeHeaders_get( headers, HEADER_CONTENT_TYPE,
FALSE, FALSE );
if (parm_value) {
char *boundary = NULL;
char *tmp_value = NULL;
boundary = MimeHeaders_get_parameter(parm_value, "boundary", NULL, NULL);
if (boundary)
tmp_value = PR_smprintf("; boundary=\"%s\"", boundary);
if (tmp_value)
StrAllocCat(newAttachment->type, tmp_value);
newAttachment->x_mac_type =
MimeHeaders_get_parameter(parm_value, "x-mac-type", NULL, NULL);
newAttachment->x_mac_creator =
MimeHeaders_get_parameter(parm_value, "x-mac-creator", NULL, NULL);
FREEIF(parm_value);
FREEIF(boundary);
FREEIF(tmp_value);
}
newAttachment->encoding = MimeHeaders_get ( headers,
HEADER_CONTENT_TRANSFER_ENCODING,
FALSE, FALSE );
newAttachment->description = MimeHeaders_get( headers,
HEADER_CONTENT_DESCRIPTION,
FALSE, FALSE );
mdd->tmp_file_name = WH_TempName (xpFileToPost, "nsmail");
if (!mdd->tmp_file_name)
return MK_OUT_OF_MEMORY;
StrAllocCopy (newAttachment->file_name, mdd->tmp_file_name);
mdd->tmp_file = XP_FileOpen ( mdd->tmp_file_name,
xpFileToPost, XP_FILE_WRITE_BIN );
if (!mdd->tmp_file)
return MK_UNABLE_TO_OPEN_TMP_FILE;
/* if need an URL and we don't have one, let's fake one */
if (needURL && !newAttachment->orig_url) {
newAttachment->orig_url = PR_smprintf ("file://%s", mdd->tmp_file_name);
}
if (creatingMsgBody) {
MimeDecoderData *(*fn) (int (*) (const char*, int32, void*), void*) = 0;
/* Initialize a decoder if necessary.
*/
if (!newAttachment->encoding || mdd->options->decrypt_p)
;
else if (!strcasecomp(newAttachment->encoding, ENCODING_BASE64))
fn = &MimeB64DecoderInit;
else if (!strcasecomp(newAttachment->encoding, ENCODING_QUOTED_PRINTABLE))
fn = &MimeQPDecoderInit;
else if (!strcasecomp(newAttachment->encoding, ENCODING_UUENCODE) ||
!strcasecomp(newAttachment->encoding, ENCODING_UUENCODE2) ||
!strcasecomp(newAttachment->encoding, ENCODING_UUENCODE3) ||
!strcasecomp(newAttachment->encoding, ENCODING_UUENCODE4))
fn = &MimeUUDecoderInit;
if (fn) {
mdd->decoder_data =
fn (/* The (int (*) ...) cast is to turn the `void' argument
into `MimeObject'. */
((int (*) (const char *, int32, void *))
dummy_file_write),
mdd->tmp_file);
if (!mdd->decoder_data)
return MK_OUT_OF_MEMORY;
}
}
return 0;
}
int
mime_decompose_file_output_fn ( char *buf,
int32 size,
void *stream_closure )
{
struct mime_draft_data *mdd = (struct mime_draft_data *) stream_closure;
int ret = 0;
XP_ASSERT (mdd && buf);
if (!mdd || !buf) return -1;
if (!size) return 0;
/****** doesn't seem to be needed *****
XP_ASSERT (mdd->tmp_file && mdd->tmp_file_name);
*/
if ( !mdd->tmp_file )
return 0;
if (mdd->decoder_data) {
ret = MimeDecoderWrite(mdd->decoder_data, buf, size);
if (ret == -1) return -1;
}
else {
ret = XP_FileWrite(buf, size, mdd->tmp_file);
if (ret < size)
return MK_MIME_ERROR_WRITING_FILE;
}
return 0;
}
int
mime_decompose_file_close_fn ( void *stream_closure )
{
struct mime_draft_data *mdd = (struct mime_draft_data *) stream_closure;
/* relax the rule in case we encountered invalid encrypted situation
XP_ASSERT (mdd && mdd->tmp_file);
*/
if ( !mdd || !mdd->tmp_file )
return -1;
if ( !mdd->options->is_multipart_msg ) {
if ( --mdd->options->decompose_init_count > 0 )
return 0;
}
if (mdd->decoder_data) {
MimeDecoderDestroy(mdd->decoder_data, FALSE);
mdd->decoder_data = 0;
}
XP_FileClose ( mdd->tmp_file );
mdd->tmp_file = 0;
FREEIF ( mdd->tmp_file_name );
mdd->tmp_file_name = 0;
return 0;
}
extern NET_StreamClass *
MIME_ToDraftConverter ( int format_out,
void *closure,
URL_Struct *url,
MWContext *context )
{
int status = 0;
NET_StreamClass * stream = NULL;
struct mime_draft_data *mdd = NULL;
MimeObject *obj;
XP_ASSERT (url && context);
if ( !url || !context ) return NULL;
mdd = XP_NEW_ZAP (struct mime_draft_data);
if (!mdd) return 0;
mdd->url = url;
mdd->context = context;
mdd->format_out = format_out;
mdd->options = XP_NEW_ZAP ( MimeDisplayOptions );
if ( !mdd->options ) {
XP_FREE (mdd);
return 0;
}
mdd->options->passwd_prompt_fn_arg = context;
mdd->options->decompose_file_p = TRUE; /* new field in MimeDisplayOptions */
mdd->options->url = url->address;
mdd->options->stream_closure = mdd;
mdd->options->html_closure = mdd;
mdd->options->decompose_headers_info_fn = make_mime_headers_copy;
mdd->options->decompose_file_init_fn = mime_decompose_file_init_fn;
mdd->options->decompose_file_output_fn = mime_decompose_file_output_fn;
mdd->options->decompose_file_close_fn = mime_decompose_file_close_fn;
#ifdef FO_MAIL_MESSAGE_TO
/* If we're attaching a message (for forwarding) then we must eradicate all
traces of encryption from it, since forwarding someone else a message
that wasn't encrypted for them doesn't work. We have to decrypt it
before sending it.
*/
mdd->options->decrypt_p = TRUE;
#endif /* FO_MAIL_MESSAGE_TO */
obj = mime_new ( (MimeObjectClass *) &mimeMessageClass,
(MimeHeaders *) NULL,
MESSAGE_RFC822 );
if ( !obj ) {
FREEIF( mdd->options->part_to_load );
XP_FREE ( mdd->options );
XP_FREE ( mdd );
return 0;
}
obj->options = mdd->options;
mdd->obj = obj;
stream = XP_NEW_ZAP ( NET_StreamClass );
if ( !stream ) {
FREEIF( mdd->options->part_to_load );
XP_FREE ( mdd->options );
XP_FREE ( mdd );
XP_FREE ( obj );
return 0;
}
stream->name = "MIME To Draft Converter Stream";
stream->complete = mime_parse_stream_complete;
stream->abort = mime_parse_stream_abort;
stream->put_block = mime_parse_stream_write;
stream->is_write_ready = mime_parse_stream_write_ready;
stream->data_object = mdd;
stream->window_id = context;
status = obj->class->initialize ( obj );
if ( status >= 0 )
status = obj->class->parse_begin ( obj );
if ( status < 0 ) {
XP_FREE ( stream );
FREEIF( mdd->options->part_to_load );
XP_FREE ( mdd->options );
XP_FREE ( mdd );
XP_FREE ( obj );
return 0;
}
return stream;
}