/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK *****
* This Original Code has been modified by IBM Corporation. Modifications made by IBM
* described herein are Copyright (c) International Business Machines Corporation, 2000.
* Modifications to Mozilla code or documentation identified per MPL Section 3.3
*
* Date Modified by Description of modification
* 04/20/2000 IBM Corp. OS/2 VisualAge build.
*/
#include "nsCOMPtr.h"
#include "modmimee.h"
#include "mimeobj.h"
#include "modlmime.h"
#include "mimei.h"
#include "mimebuf.h"
#include "mimemoz2.h"
#include "mimemsg.h"
#include "nsMimeTypes.h"
#include "prmem.h"
#include "plstr.h"
#include "prprf.h"
#include "prio.h"
#include "nsIPrefService.h"
#include "nsIPrefBranch.h"
#include "msgCore.h"
#include "nsCRT.h"
#include "nsEscape.h"
#include "nsIFileSpec.h"
#include "nsIMsgSend.h"
#include "nsFileStream.h"
#include "nsMimeStringResources.h"
#include "nsIIOService.h"
#include "comi18n.h"
#include "nsIMsgCompFields.h"
#include "nsMsgCompCID.h"
#include "nsIMsgComposeService.h"
#include "nsMsgI18N.h"
#include "nsSpecialSystemDirectory.h"
#include "nsIMsgMessageService.h"
#include "nsMsgUtils.h"
#include "nsXPIDLString.h"
#include "nsReadableUtils.h"
#include "nsCExternalHandlerService.h"
#include "nsIMIMEService.h"
#include "nsIMsgHeaderParser.h"
#include "nsIMsgAccountManager.h"
#include "nsMsgBaseCID.h"
//
// Header strings...
//
#define HEADER_NNTP_POSTING_HOST "NNTP-Posting-Host"
#define MIME_HEADER_TABLE "
");
NS_MsgSACat(&newBody, MSG_LINEBREAK "
");
if (html_tag)
NS_MsgSACat(&newBody, html_tag+6);
else if (*body)
NS_MsgSACat(&newBody, *body);
}
else
{
NS_MsgSACat(&newBody, MSG_LINEBREAK MSG_LINEBREAK);
if (*body)
NS_MsgSACat(&newBody, *body);
}
if (newBody)
{
PR_FREEIF(*body);
*body = newBody;
}
}
static void
mime_insert_normal_headers(char **body,
MimeHeaders *headers,
MSG_ComposeFormat composeFormat,
char *mailcharset)
{
char *newBody = nsnull;
char *subject = MimeHeaders_get(headers, HEADER_SUBJECT, PR_FALSE, PR_FALSE);
char *resent_comments = MimeHeaders_get(headers, HEADER_RESENT_COMMENTS, PR_FALSE, PR_FALSE);
char *resent_date = MimeHeaders_get(headers, HEADER_RESENT_DATE, PR_FALSE, PR_TRUE);
char *resent_from = MimeHeaders_get(headers, HEADER_RESENT_FROM, PR_FALSE, PR_TRUE);
char *resent_to = MimeHeaders_get(headers, HEADER_RESENT_TO, PR_FALSE, PR_TRUE);
char *resent_cc = MimeHeaders_get(headers, HEADER_RESENT_CC, PR_FALSE, PR_TRUE);
char *date = MimeHeaders_get(headers, HEADER_DATE, PR_FALSE, PR_TRUE);
char *from = MimeHeaders_get(headers, HEADER_FROM, PR_FALSE, PR_TRUE);
char *reply_to = MimeHeaders_get(headers, HEADER_REPLY_TO, PR_FALSE, PR_TRUE);
char *organization = MimeHeaders_get(headers, HEADER_ORGANIZATION, PR_FALSE, PR_FALSE);
char *to = MimeHeaders_get(headers, HEADER_TO, PR_FALSE, PR_TRUE);
char *cc = MimeHeaders_get(headers, HEADER_CC, PR_FALSE, PR_TRUE);
char *newsgroups = MimeHeaders_get(headers, HEADER_NEWSGROUPS, PR_FALSE, PR_TRUE);
char *followup_to = MimeHeaders_get(headers, HEADER_FOLLOWUP_TO, PR_FALSE, PR_TRUE);
char *references = MimeHeaders_get(headers, HEADER_REFERENCES, PR_FALSE, PR_TRUE);
const char *html_tag = nsnull;
if (*body)
html_tag = PL_strcasestr(*body, "");
PRBool htmlEdit = composeFormat == nsIMsgCompFormat::HTML;
if (!from)
from = MimeHeaders_get(headers, HEADER_SENDER, PR_FALSE, PR_TRUE);
if (!resent_from)
resent_from = MimeHeaders_get(headers, HEADER_RESENT_SENDER, PR_FALSE,
PR_TRUE);
nsCOMPtr parser = do_GetService(NS_MAILNEWS_MIME_HEADER_PARSER_CONTRACTID);
UnquoteMimeAddress(parser, &resent_from);
UnquoteMimeAddress(parser, &resent_to);
UnquoteMimeAddress(parser, &resent_cc);
UnquoteMimeAddress(parser, &reply_to);
UnquoteMimeAddress(parser, &from);
UnquoteMimeAddress(parser, &to);
UnquoteMimeAddress(parser, &cc);
if (htmlEdit)
{
NS_MsgSACopy(&(newBody), "
");
NS_MsgSACat(&newBody, MimeGetNamedString(MIME_FORWARDED_MESSAGE_HTML_USER_WROTE));
NS_MsgSACat(&newBody, MIME_HEADER_TABLE);
}
else
{
NS_MsgSACopy(&(newBody), MSG_LINEBREAK MSG_LINEBREAK);
NS_MsgSACat(&newBody, MimeGetNamedString(MIME_FORWARDED_MESSAGE_HTML_USER_WROTE));
}
if (subject)
mime_intl_insert_message_header_1(&newBody, &subject, HEADER_SUBJECT,
MimeGetNamedString(MIME_MHTML_SUBJECT),
mailcharset, htmlEdit);
if (resent_comments)
mime_intl_insert_message_header_1(&newBody, &resent_comments,
HEADER_RESENT_COMMENTS,
MimeGetNamedString(MIME_MHTML_RESENT_COMMENTS),
mailcharset, htmlEdit);
if (resent_date)
mime_intl_insert_message_header_1(&newBody, &resent_date,
HEADER_RESENT_DATE,
MimeGetNamedString(MIME_MHTML_RESENT_DATE),
mailcharset, htmlEdit);
if (resent_from)
{
if (htmlEdit) mime_fix_up_html_address(&resent_from);
mime_intl_insert_message_header_1(&newBody, &resent_from,
HEADER_RESENT_FROM,
MimeGetNamedString(MIME_MHTML_RESENT_FROM),
mailcharset, htmlEdit);
}
if (resent_to)
{
if (htmlEdit) mime_fix_up_html_address(&resent_to);
mime_intl_insert_message_header_1(&newBody, &resent_to,
HEADER_RESENT_TO,
MimeGetNamedString(MIME_MHTML_RESENT_TO),
mailcharset, htmlEdit);
}
if (resent_cc)
{
if (htmlEdit) mime_fix_up_html_address(&resent_cc);
mime_intl_insert_message_header_1(&newBody, &resent_cc,
HEADER_RESENT_CC,
MimeGetNamedString(MIME_MHTML_RESENT_CC),
mailcharset, htmlEdit);
}
if (date)
mime_intl_insert_message_header_1(&newBody, &date, HEADER_DATE,
MimeGetNamedString(MIME_MHTML_DATE),
mailcharset, htmlEdit);
if (from)
{
if (htmlEdit) mime_fix_up_html_address(&from);
mime_intl_insert_message_header_1(&newBody, &from, HEADER_FROM,
MimeGetNamedString(MIME_MHTML_FROM),
mailcharset, htmlEdit);
}
if (reply_to)
{
if (htmlEdit) mime_fix_up_html_address(&reply_to);
mime_intl_insert_message_header_1(&newBody, &reply_to, HEADER_REPLY_TO,
MimeGetNamedString(MIME_MHTML_REPLY_TO),
mailcharset, htmlEdit);
}
if (organization)
mime_intl_insert_message_header_1(&newBody, &organization,
HEADER_ORGANIZATION,
MimeGetNamedString(MIME_MHTML_ORGANIZATION),
mailcharset, htmlEdit);
if (to)
{
if (htmlEdit) mime_fix_up_html_address(&to);
mime_intl_insert_message_header_1(&newBody, &to, HEADER_TO,
MimeGetNamedString(MIME_MHTML_TO),
mailcharset, htmlEdit);
}
if (cc)
{
if (htmlEdit) mime_fix_up_html_address(&cc);
mime_intl_insert_message_header_1(&newBody, &cc, HEADER_CC,
MimeGetNamedString(MIME_MHTML_CC),
mailcharset, htmlEdit);
}
/*
Do not reveal bcc recipients when forwarding a message!
See http://bugzilla.mozilla.org/show_bug.cgi?id=41150
*/
if (newsgroups)
mime_intl_insert_message_header_1(&newBody, &newsgroups, HEADER_NEWSGROUPS,
MimeGetNamedString(MIME_MHTML_NEWSGROUPS),
mailcharset, htmlEdit);
if (followup_to)
{
if (htmlEdit) mime_fix_up_html_address(&followup_to);
mime_intl_insert_message_header_1(&newBody, &followup_to,
HEADER_FOLLOWUP_TO,
MimeGetNamedString(MIME_MHTML_FOLLOWUP_TO),
mailcharset, htmlEdit);
}
if (references)
{
if (htmlEdit) mime_fix_up_html_address(&references);
mime_intl_insert_message_header_1(&newBody, &references,
HEADER_REFERENCES,
MimeGetNamedString(MIME_MHTML_REFERENCES),
mailcharset, htmlEdit);
}
if (htmlEdit)
{
NS_MsgSACat(&newBody, "");
NS_MsgSACat(&newBody, MSG_LINEBREAK "
");
if (html_tag)
NS_MsgSACat(&newBody, html_tag+6);
else if (*body)
NS_MsgSACat(&newBody, *body);
}
else
{
NS_MsgSACat(&newBody, MSG_LINEBREAK MSG_LINEBREAK);
if (*body)
NS_MsgSACat(&newBody, *body);
}
if (newBody)
{
PR_FREEIF(*body);
*body = newBody;
}
PR_FREEIF(subject);
PR_FREEIF(resent_comments);
PR_FREEIF(resent_date);
PR_FREEIF(resent_from);
PR_FREEIF(resent_to);
PR_FREEIF(resent_cc);
PR_FREEIF(date);
PR_FREEIF(from);
PR_FREEIF(reply_to);
PR_FREEIF(organization);
PR_FREEIF(to);
PR_FREEIF(cc);
PR_FREEIF(newsgroups);
PR_FREEIF(followup_to);
PR_FREEIF(references);
}
static void
mime_insert_micro_headers(char **body,
MimeHeaders *headers,
MSG_ComposeFormat composeFormat,
char *mailcharset)
{
char *newBody = NULL;
char *subject = MimeHeaders_get(headers, HEADER_SUBJECT, PR_FALSE, PR_FALSE);
char *from = MimeHeaders_get(headers, HEADER_FROM, PR_FALSE, PR_TRUE);
char *resent_from = MimeHeaders_get(headers, HEADER_RESENT_FROM, PR_FALSE,
PR_TRUE);
char *date = MimeHeaders_get(headers, HEADER_DATE, PR_FALSE, PR_TRUE);
char *to = MimeHeaders_get(headers, HEADER_TO, PR_FALSE, PR_TRUE);
char *cc = MimeHeaders_get(headers, HEADER_CC, PR_FALSE, PR_TRUE);
char *newsgroups = MimeHeaders_get(headers, HEADER_NEWSGROUPS, PR_FALSE,
PR_TRUE);
const char *html_tag = nsnull;
if (*body)
html_tag = PL_strcasestr(*body, "");
PRBool htmlEdit = composeFormat == nsIMsgCompFormat::HTML;
if (!from)
from = MimeHeaders_get(headers, HEADER_SENDER, PR_FALSE, PR_TRUE);
if (!resent_from)
resent_from = MimeHeaders_get(headers, HEADER_RESENT_SENDER, PR_FALSE,
PR_TRUE);
if (!date)
date = MimeHeaders_get(headers, HEADER_RESENT_DATE, PR_FALSE, PR_TRUE);
nsCOMPtr parser = do_GetService(NS_MAILNEWS_MIME_HEADER_PARSER_CONTRACTID);
UnquoteMimeAddress(parser, &resent_from);
UnquoteMimeAddress(parser, &from);
UnquoteMimeAddress(parser, &to);
UnquoteMimeAddress(parser, &cc);
if (htmlEdit)
{
NS_MsgSACopy(&(newBody), "
");
NS_MsgSACat(&newBody, MimeGetNamedString(MIME_FORWARDED_MESSAGE_HTML_USER_WROTE));
NS_MsgSACat(&newBody, MIME_HEADER_TABLE);
}
else
{
NS_MsgSACopy(&(newBody), MSG_LINEBREAK MSG_LINEBREAK);
NS_MsgSACat(&newBody, MimeGetNamedString(MIME_FORWARDED_MESSAGE_HTML_USER_WROTE));
}
if (from)
{
if (htmlEdit)
mime_fix_up_html_address(&from);
mime_intl_insert_message_header_1(&newBody, &from, HEADER_FROM,
MimeGetNamedString(MIME_MHTML_FROM),
mailcharset, htmlEdit);
}
if (subject)
mime_intl_insert_message_header_1(&newBody, &subject, HEADER_SUBJECT,
MimeGetNamedString(MIME_MHTML_SUBJECT),
mailcharset, htmlEdit);
/*
if (date)
mime_intl_insert_message_header_1(&newBody, &date, HEADER_DATE,
MimeGetNamedString(MIME_MHTML_DATE),
mailcharset, htmlEdit);
*/
if (resent_from)
{
if (htmlEdit) mime_fix_up_html_address(&resent_from);
mime_intl_insert_message_header_1(&newBody, &resent_from,
HEADER_RESENT_FROM,
MimeGetNamedString(MIME_MHTML_RESENT_FROM),
mailcharset, htmlEdit);
}
if (to)
{
if (htmlEdit) mime_fix_up_html_address(&to);
mime_intl_insert_message_header_1(&newBody, &to, HEADER_TO,
MimeGetNamedString(MIME_MHTML_TO),
mailcharset, htmlEdit);
}
if (cc)
{
if (htmlEdit) mime_fix_up_html_address(&cc);
mime_intl_insert_message_header_1(&newBody, &cc, HEADER_CC,
MimeGetNamedString(MIME_MHTML_CC),
mailcharset, htmlEdit);
}
/*
Do not reveal bcc recipients when forwarding a message!
See http://bugzilla.mozilla.org/show_bug.cgi?id=41150
*/
if (newsgroups)
mime_intl_insert_message_header_1(&newBody, &newsgroups, HEADER_NEWSGROUPS,
MimeGetNamedString(MIME_MHTML_NEWSGROUPS),
mailcharset, htmlEdit);
if (htmlEdit)
{
NS_MsgSACat(&newBody, "");
NS_MsgSACat(&newBody, MSG_LINEBREAK "
");
if (html_tag)
NS_MsgSACat(&newBody, html_tag+6);
else if (*body)
NS_MsgSACat(&newBody, *body);
}
else
{
NS_MsgSACat(&newBody, MSG_LINEBREAK MSG_LINEBREAK);
if (*body)
NS_MsgSACat(&newBody, *body);
}
if (newBody)
{
PR_FREEIF(*body);
*body = newBody;
}
PR_FREEIF(subject);
PR_FREEIF(from);
PR_FREEIF(resent_from);
PR_FREEIF(date);
PR_FREEIF(to);
PR_FREEIF(cc);
PR_FREEIF(newsgroups);
}
// body has to be encoded in UTF-8
static void
mime_insert_forwarded_message_headers(char **body,
MimeHeaders *headers,
MSG_ComposeFormat composeFormat,
char *mailcharset)
{
if (!body || !headers)
return;
PRInt32 show_headers = 0;
nsresult res;
nsCOMPtr prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &res));
if (NS_SUCCEEDED(res))
prefBranch->GetIntPref("mail.show_headers", &show_headers);
switch (show_headers)
{
case 0:
mime_insert_micro_headers(body, headers, composeFormat, mailcharset);
break;
default:
case 1:
mime_insert_normal_headers(body, headers, composeFormat, mailcharset);
break;
case 2:
mime_insert_all_headers(body, headers, composeFormat, mailcharset);
break;
}
}
static void PR_CALLBACK
mime_parse_stream_complete (nsMIMESession *stream)
{
struct mime_draft_data *mdd = (struct mime_draft_data *) stream->data_object;
nsCOMPtr fields;
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;
char *identityKey = 0;
PRBool xlate_p = PR_FALSE; /* #### how do we determine this? */
PRBool sign_p = PR_FALSE; /* #### how do we determine this? */
PRBool forward_inline = PR_FALSE;
PRBool bodyAsAttachment = PR_FALSE;
PRBool charsetOverride = PR_FALSE;
NS_ASSERTION (mdd, "null mime draft data");
if (!mdd) return;
if (mdd->obj)
{
int status;
status = mdd->obj->clazz->parse_eof ( mdd->obj, PR_FALSE );
mdd->obj->clazz->parse_end( mdd->obj, status < 0 ? PR_TRUE : PR_FALSE );
xlate_p = mdd->options->decrypt_p;
sign_p = mdd->options->signed_p;
// RICHIE
// We need to figure out how to pass the forwarded flag along with this
// operation.
//forward_inline = (mdd->format_out != FO_CMDLINE_ATTACHMENTS);
forward_inline = mdd->forwardInline;
if (forward_inline)
{
#ifdef MOZ_SECURITY
HG88890
#endif
}
NS_ASSERTION ( mdd->options == mdd->obj->options, "mime draft options not same as obj->options" );
mime_free (mdd->obj);
mdd->obj = 0;
if (mdd->options)
{
// save the override flag before it's unavailable
charsetOverride = mdd->options->override_charset;
if ((!mdd->mailcharset || charsetOverride) && mdd->options->default_charset)
{
PR_Free(mdd->mailcharset);
mdd->mailcharset = nsCRT::strdup(mdd->options->default_charset);
}
// mscott: aren't we leaking a bunch of strings here like the charset strings and such?
delete mdd->options;
mdd->options = 0;
}
if (mdd->stream)
{
mdd->stream->complete ((nsMIMESession *)mdd->stream->data_object);
PR_Free( mdd->stream );
mdd->stream = 0;
}
}
//
// Now, process the attachments that we have gathered from the message
// on disk
//
nsMsgAttachmentData *newAttachData = mime_draft_process_attachments(mdd);
//
// time to bring up the compose windows with all the info gathered
//
if ( mdd->headers )
{
subj = MimeHeaders_get(mdd->headers, HEADER_SUBJECT, PR_FALSE, PR_FALSE);
if (forward_inline)
{
if (subj)
{
char *newSubj = PR_smprintf("[Fwd: %s]", subj);
if (newSubj)
{
PR_Free(subj);
subj = newSubj;
}
}
}
else
{
repl = MimeHeaders_get(mdd->headers, HEADER_REPLY_TO, PR_FALSE, PR_FALSE);
to = MimeHeaders_get(mdd->headers, HEADER_TO, PR_FALSE, PR_TRUE);
cc = MimeHeaders_get(mdd->headers, HEADER_CC, PR_FALSE, PR_TRUE);
bcc = MimeHeaders_get(mdd->headers, HEADER_BCC, PR_FALSE, PR_TRUE);
/* These headers should not be RFC-1522-decoded. */
grps = MimeHeaders_get(mdd->headers, HEADER_NEWSGROUPS, PR_FALSE, PR_TRUE);
foll = MimeHeaders_get(mdd->headers, HEADER_FOLLOWUP_TO, PR_FALSE, PR_TRUE);
host = MimeHeaders_get(mdd->headers, HEADER_X_MOZILLA_NEWSHOST, PR_FALSE, PR_FALSE);
if (!host)
host = MimeHeaders_get(mdd->headers, HEADER_NNTP_POSTING_HOST, PR_FALSE, PR_FALSE);
id = MimeHeaders_get(mdd->headers, HEADER_MESSAGE_ID, PR_FALSE, PR_FALSE);
refs = MimeHeaders_get(mdd->headers, HEADER_REFERENCES, PR_FALSE, PR_TRUE);
priority = MimeHeaders_get(mdd->headers, HEADER_X_PRIORITY, PR_FALSE, PR_FALSE);
if (host)
{
char *secure = NULL;
secure = PL_strcasestr(host, "secure");
if (secure)
{
*secure = 0;
news_host = PR_smprintf ("snews://%s", host);
}
else
{
news_host = PR_smprintf ("news://%s", host);
}
}
}
CreateCompositionFields( from, repl, to, cc, bcc, fcc, grps, foll,
org, subj, refs, 0, priority, news_host,
xlate_p, sign_p, mdd->mailcharset,
getter_AddRefs(fields));
draftInfo = MimeHeaders_get(mdd->headers, HEADER_X_MOZILLA_DRAFT_INFO, PR_FALSE, PR_FALSE);
if (draftInfo && fields && !forward_inline)
{
char *parm = 0;
parm = MimeHeaders_get_parameter(draftInfo, "vcard", NULL, NULL);
fields->SetAttachVCard(parm && !nsCRT::strcmp(parm, "1"));
fields->SetMessageId(id); // keep same message id for editing template.
PR_FREEIF(parm);
parm = MimeHeaders_get_parameter(draftInfo, "receipt", NULL, NULL);
if (parm && !nsCRT::strcmp(parm, "0"))
fields->SetReturnReceipt(PR_FALSE);
else
{
int receiptType = 0;
fields->SetReturnReceipt(PR_TRUE);
sscanf(parm, "%d", &receiptType);
// slight change compared to 4.x; we used to use receipt= to tell
// whether the draft/template has request for either MDN or DNS or both
// return receipt; since the DNS is out of the picture we now use the
// header type - 1 to tell whether user has requested the return receipt
fields->SetReceiptHeaderType(((PRInt32)receiptType) - 1);
}
PR_FREEIF(parm);
parm = MimeHeaders_get_parameter(draftInfo, "uuencode", NULL, NULL);
fields->SetUuEncodeAttachments(parm && !nsCRT::strcmp(parm, "1"));
PR_FREEIF(parm);
parm = MimeHeaders_get_parameter(draftInfo, "html", NULL, NULL);
if (parm)
sscanf(parm, "%d", &htmlAction);
PR_FREEIF(parm);
parm = MimeHeaders_get_parameter(draftInfo, "linewidth", NULL, NULL);
if (parm)
sscanf(parm, "%d", &lineWidth);
PR_FREEIF(parm);
}
// identity to prefer when opening the message in the compose window?
identityKey = MimeHeaders_get(mdd->headers, HEADER_X_MOZILLA_IDENTITY_KEY, PR_FALSE, PR_FALSE);
if ( identityKey && *identityKey )
{
nsresult rv = NS_OK;
nsCOMPtr< nsIMsgAccountManager > accountManager =
do_GetService( NS_MSGACCOUNTMANAGER_CONTRACTID, &rv );
if ( NS_SUCCEEDED(rv) && accountManager )
{
nsCOMPtr< nsIMsgIdentity > overrulingIdentity;
rv = accountManager->GetIdentity( identityKey, getter_AddRefs( overrulingIdentity ) );
if ( NS_SUCCEEDED(rv) && overrulingIdentity )
mdd->identity = overrulingIdentity;
}
}
if (mdd->messageBody)
{
MSG_ComposeFormat composeFormat = nsIMsgCompFormat::Default;
if (mdd->messageBody->type && *mdd->messageBody->type)
{
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") )
composeFormat = nsIMsgCompFormat::PlainText;
else
{
//We cannot use this kind of data for the message body! Therefore, move it as attachment
bodyAsAttachment = PR_TRUE;
}
}
else
composeFormat = nsIMsgCompFormat::PlainText;
char *body = nsnull;
PRUint32 bodyLen = 0;
if (!bodyAsAttachment)
{
bodyLen = mdd->messageBody->file_spec->GetFileSize();
body = (char *)PR_MALLOC (bodyLen + 1);
if (body)
{
memset (body, 0, bodyLen+1);
nsInputFileStream inputFile(*(mdd->messageBody->file_spec));
if (inputFile.is_open())
inputFile.read(body, bodyLen);
inputFile.close();
// Convert the body to UTF-8
char *mimeCharset = nsnull;
// Get a charset from the header if no override is set.
if (!charsetOverride)
mimeCharset = MimeHeaders_get_parameter (mdd->messageBody->type, "charset", nsnull, nsnull);
// If no charset is specified in the header then use the default.
char *bodyCharset = mimeCharset ? mimeCharset : mdd->mailcharset;
if (bodyCharset)
{
nsAutoString tempUnicodeString;
if (NS_SUCCEEDED(ConvertToUnicode(bodyCharset, body, tempUnicodeString)))
{
char *newBody = ToNewUTF8String(tempUnicodeString);
if (newBody)
{
PR_Free(body);
body = newBody;
bodyLen = strlen(newBody);
}
}
}
PR_FREEIF(mimeCharset);
}
}
// Since we have body text, then we should set the compose fields with
// this data.
// if (composeFormat == nsIMsgCompFormat::PlainText)
// fields->SetTheForcePlainText(PR_TRUE);
if (forward_inline)
{
if (mdd->identity)
{
PRBool bFormat;
mdd->identity->GetComposeHtml(&bFormat);
if (bFormat)
{
if (body && composeFormat == nsIMsgCompFormat::PlainText)
{
//We need to convert the plain/text to HTML in order to escape any HTML markup
char *escapedBody = nsEscapeHTML(body);
if (escapedBody)
{
PR_Free(body);
body = escapedBody;
bodyLen = strlen(body);
}
char* newbody = (char *)PR_MALLOC (bodyLen + 12); //+11 chars for &
tags
if (newbody)
{
*newbody = 0;
PL_strcat(newbody, "");
PL_strcat(newbody, body);
PL_strcat(newbody, "");
PR_Free(body);
body = newbody;
}
}
composeFormat = nsIMsgCompFormat::HTML;
}
}
mime_insert_forwarded_message_headers(&body, mdd->headers, composeFormat,
mdd->mailcharset);
}
// setting the charset while we are creating the composition fields
//fields->SetCharacterSet(NS_ConvertASCIItoUCS2(mdd->mailcharset));
// convert from UTF-8 to UTF-16
if (body)
{
fields->SetBody(NS_ConvertUTF8toUTF16(body));
PR_Free(body);
}
//
// At this point, we need to create a message compose window or editor
// window via XP-COM with the information that we have retrieved from
// the message store.
//
if (mdd->format_out == nsMimeOutput::nsMimeMessageEditorTemplate)
{
#ifdef NS_DEBUG
printf("RICHIE: Time to create the EDITOR with this template - HAS a body!!!!\n");
#endif
fields->SetDraftId(mdd->url_name);
CreateTheComposeWindow(fields, newAttachData, nsIMsgCompType::Template, composeFormat, mdd->identity, nsnull);
}
else
{
#ifdef NS_DEBUG
printf("Time to create the composition window WITH a body!!!!\n");
#endif
if (mdd->forwardInline)
CreateTheComposeWindow(fields, newAttachData, nsIMsgCompType::ForwardInline, composeFormat, mdd->identity, mdd->originalMsgURI);
else
{
fields->SetDraftId(mdd->url_name);
CreateTheComposeWindow(fields, newAttachData, nsIMsgCompType::Draft, composeFormat, mdd->identity, nsnull);
}
}
}
else
{
//
// At this point, we need to create a message compose window via
// XP-COM with the information that we have retrieved from the message store.
//
if (mdd->format_out == nsMimeOutput::nsMimeMessageEditorTemplate)
{
#ifdef NS_DEBUG
printf("RICHIE: Time to create the EDITOR with this template - NO body!!!!\n");
#endif
CreateTheComposeWindow(fields, newAttachData, nsIMsgCompType::Template, nsIMsgCompFormat::Default, mdd->identity, nsnull);
}
else
{
#ifdef NS_DEBUG
printf("Time to create the composition window WITHOUT a body!!!!\n");
#endif
if (mdd->forwardInline)
CreateTheComposeWindow(fields, newAttachData, nsIMsgCompType::ForwardInline, nsIMsgCompFormat::Default, mdd->identity, mdd->originalMsgURI);
else
{
fields->SetDraftId(mdd->url_name);
CreateTheComposeWindow(fields, newAttachData, nsIMsgCompType::Draft, nsIMsgCompFormat::Default, mdd->identity, nsnull);
}
}
}
}
else
{
CreateCompositionFields( from, repl, to, cc, bcc, fcc, grps, foll,
org, subj, refs, 0, priority, news_host,
GetMailXlateionPreference(),
GetMailSigningPreference(),
mdd->mailcharset,
getter_AddRefs(fields));
if (fields)
CreateTheComposeWindow(fields, newAttachData, nsIMsgCompType::New, nsIMsgCompFormat::Default, mdd->identity, nsnull);
}
if ( mdd->headers )
MimeHeaders_free ( mdd->headers );
//
// Free the original attachment structure...
// Make sure we only cleanup the local copy of the memory and not kill
// files we need on disk
//
if (bodyAsAttachment)
{
if ( mdd->messageBody->file_spec )
{
delete ( mdd->messageBody->file_spec );
mdd->messageBody->file_spec = nsnull;
}
}
mime_free_attachments (mdd->messageBody, 1);
if (mdd->attachments)
{
int i;
nsMsgAttachedFile *cur = mdd->attachments;
for ( i = 0; i < mdd->attachments_count; i++, cur++ )
{
if ( cur->file_spec )
{
delete ( cur->file_spec );
cur->file_spec = nsnull;
}
}
mime_free_attachments( mdd->attachments, mdd->attachments_count );
}
PR_FREEIF(mdd->mailcharset);
mdd->identity = nsnull;
PR_Free(mdd->url_name);
PR_Free(mdd->originalMsgURI);
PR_Free(mdd);
PR_FREEIF(host);
PR_FREEIF(to_and_cc);
PR_FREEIF(re_subject);
PR_FREEIF(new_refs);
PR_FREEIF(from);
PR_FREEIF(repl);
PR_FREEIF(subj);
PR_FREEIF(id);
PR_FREEIF(refs);
PR_FREEIF(to);
PR_FREEIF(cc);
PR_FREEIF(grps);
PR_FREEIF(foll);
PR_FREEIF(priority);
PR_FREEIF(draftInfo);
PR_Free(identityKey);
mime_free_attach_data(newAttachData);
}
static void PR_CALLBACK
mime_parse_stream_abort (nsMIMESession *stream, int status )
{
struct mime_draft_data *mdd = (struct mime_draft_data *) stream->data_object;
NS_ASSERTION (mdd, "null mime draft data");
if (!mdd)
return;
if (mdd->obj)
{
int status=0;
if ( !mdd->obj->closed_p )
status = mdd->obj->clazz->parse_eof ( mdd->obj, PR_TRUE );
if ( !mdd->obj->parsed_p )
mdd->obj->clazz->parse_end( mdd->obj, PR_TRUE );
NS_ASSERTION ( mdd->options == mdd->obj->options, "draft display options not same as mime obj" );
mime_free (mdd->obj);
mdd->obj = 0;
if (mdd->options)
{
delete mdd->options;
mdd->options = 0;
}
if (mdd->stream)
{
mdd->stream->abort ((nsMIMESession *)mdd->stream->data_object, status);
PR_Free( mdd->stream );
mdd->stream = 0;
}
}
if ( mdd->headers )
MimeHeaders_free (mdd->headers);
if (mdd->attachments)
mime_free_attachments( mdd->attachments, mdd->attachments_count );
PR_FREEIF(mdd->mailcharset);
PR_Free (mdd);
}
static int
make_mime_headers_copy ( void *closure, MimeHeaders *headers )
{
struct mime_draft_data *mdd = (struct mime_draft_data *) closure;
NS_ASSERTION ( mdd && headers, "null mime draft data and/or headers" );
if ( !mdd || ! headers )
return 0;
NS_ASSERTION ( mdd->headers == NULL , "non null mime draft data headers");
mdd->headers = MimeHeaders_copy ( headers );
mdd->options->done_parsing_outer_headers = PR_TRUE;
return 0;
}
nsresult
mime_decompose_file_init_fn ( void *stream_closure, MimeHeaders *headers )
{
struct mime_draft_data *mdd = (struct mime_draft_data *) stream_closure;
nsMsgAttachedFile *attachments = 0, *newAttachment = 0;
int nAttachments = 0;
//char *hdr_value = NULL;
char *parm_value = NULL;
PRBool needURL = PR_FALSE;
PRBool creatingMsgBody = PR_TRUE;
PRBool bodyPart = PR_FALSE;
NS_ASSERTION (mdd && headers, "null mime draft data and/or headers");
if (!mdd || !headers)
return -1;
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++;
nAttachments = mdd->attachments_count;
if (!nAttachments && !mdd->messageBody)
{
// if we've been told to use an override charset then do so....otherwise use the charset
// inside the message header...
if (mdd->options && mdd->options->override_charset)
mdd->mailcharset = nsCRT::strdup(mdd->options->default_charset);
else
{
char *contentType = NULL;
contentType = MimeHeaders_get(headers, HEADER_CONTENT_TYPE, PR_FALSE, PR_FALSE);
if (contentType)
{
mdd->mailcharset = MimeHeaders_get_parameter(contentType, "charset", NULL, NULL);
PR_FREEIF(contentType);
}
}
mdd->messageBody = PR_NEWZAP (nsMsgAttachedFile);
NS_ASSERTION (mdd->messageBody, "missing messageBody in mime_decompose_file_init_fn");
if (!mdd->messageBody)
return MIME_OUT_OF_MEMORY;
newAttachment = mdd->messageBody;
creatingMsgBody = PR_TRUE;
bodyPart = PR_TRUE;
}
else
{
/* always allocate one more extra; don't ask me why */
needURL = PR_TRUE;
if ( nAttachments )
{
NS_ASSERTION (mdd->attachments, "no attachments");
attachments = (nsMsgAttachedFile *)PR_REALLOC(mdd->attachments,
sizeof (nsMsgAttachedFile) *
(nAttachments + 2));
if (!attachments)
return MIME_OUT_OF_MEMORY;
mdd->attachments = attachments;
mdd->attachments_count++;
}
else {
NS_ASSERTION (!mdd->attachments, "have attachments but count is 0");
attachments = (nsMsgAttachedFile *) PR_MALLOC ( sizeof (nsMsgAttachedFile) * 2);
if (!attachments)
return MIME_OUT_OF_MEMORY;
mdd->attachments_count++;
mdd->attachments = attachments;
}
newAttachment = attachments + nAttachments;
memset ( newAttachment, 0, sizeof (nsMsgAttachedFile) * 2 );
}
char *workURLSpec = nsnull;
char *contLoc = nsnull;
newAttachment->real_name = MimeHeaders_get_name ( headers, mdd->options );
contLoc = MimeHeaders_get( headers, HEADER_CONTENT_LOCATION, PR_FALSE, PR_FALSE );
if (!contLoc)
contLoc = MimeHeaders_get( headers, HEADER_CONTENT_BASE, PR_FALSE, PR_FALSE );
if ( (!contLoc) && (newAttachment->real_name) )
workURLSpec = nsCRT::strdup(newAttachment->real_name);
if ( (contLoc) && (!workURLSpec) )
workURLSpec = nsCRT::strdup(contLoc);
PR_FREEIF(contLoc);
mdd->curAttachment = newAttachment;
newAttachment->type = MimeHeaders_get ( headers, HEADER_CONTENT_TYPE, PR_FALSE, PR_FALSE );
if (PL_strstr(newAttachment->type, MESSAGE_RFC822))
{
char *newName = PR_smprintf("%s.eml", newAttachment->real_name);
if (newName)
{
PR_Free(newAttachment->real_name);
newAttachment->real_name = newName;
}
}
//
// This is to handle the degenerated Apple Double attachment.
//
parm_value = MimeHeaders_get( headers, HEADER_CONTENT_TYPE, PR_FALSE, PR_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)
NS_MsgSACat(&(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);
PR_FREEIF(parm_value);
PR_FREEIF(boundary);
PR_FREEIF(tmp_value);
}
newAttachment->encoding = MimeHeaders_get ( headers, HEADER_CONTENT_TRANSFER_ENCODING,
PR_FALSE, PR_FALSE );
newAttachment->description = MimeHeaders_get( headers, HEADER_CONTENT_DESCRIPTION,
PR_FALSE, PR_FALSE );
//
// If we came up empty for description or the orig URL, we should do something about it.
//
if ( ( (!newAttachment->description) || (!*newAttachment->description) ) && (workURLSpec) )
newAttachment->description = nsCRT::strdup(workURLSpec);
nsFileSpec *tmpSpec = nsnull;
{
// Let's build a temp file with an extension based on the content-type: nsmail.
nsCAutoString newAttachName ("nsmail");
PRBool extensionAdded = PR_FALSE;
// the content type may contain a charset. i.e. text/html; ISO-2022-JP...we want to strip off the charset
// before we ask the mime service for a mime info for this content type.
nsCAutoString contentType (newAttachment->type);
PRInt32 pos = contentType.FindChar(';');
if (pos > 0)
contentType.Truncate(pos);
nsresult rv = NS_OK;
nsCOMPtr mimeFinder (do_GetService(NS_MIMESERVICE_CONTRACTID, &rv));
if (NS_SUCCEEDED(rv) && mimeFinder)
{
nsCAutoString fileExtension;
rv = mimeFinder->GetPrimaryExtension(contentType, EmptyCString(), fileExtension);
if (NS_SUCCEEDED(rv) && !fileExtension.IsEmpty())
{
newAttachName.Append(".");
newAttachName.Append(fileExtension);
extensionAdded = PR_TRUE;
}
}
if (!extensionAdded)
{
newAttachName.Append(".tmp");
}
tmpSpec = nsMsgCreateTempFileSpec(newAttachName.get());
}
// This needs to be done so the attachment structure has a handle
// on the temp file for this attachment...
// if ( (tmpSpec) && (!bodyPart) )
if (tmpSpec)
{
nsFileURL fileURL(*tmpSpec);
const char * tempSpecStr = fileURL.GetURLString();
nsMimeNewURI(getter_AddRefs(newAttachment->orig_url), tempSpecStr, nsnull);
}
PR_FREEIF(workURLSpec);
if (!tmpSpec)
return MIME_OUT_OF_MEMORY;
NS_NewFileSpecWithSpec(*tmpSpec, &mdd->tmpFileSpec);
if (!mdd->tmpFileSpec)
return MIME_OUT_OF_MEMORY;
newAttachment->file_spec = tmpSpec;
mdd->tmpFileStream = new nsOutputFileStream(*tmpSpec, PR_WRONLY | PR_CREATE_FILE, 00600);
if (!mdd->tmpFileStream)
return MIME_UNABLE_TO_OPEN_TMP_FILE;
// For now, we are always going to decode all of the attachments
// for the message. This way, we have native data
if (creatingMsgBody)
{
MimeDecoderData *(*fn) (nsresult (*) (const char*, PRInt32, void*), void*) = 0;
//
// Initialize a decoder if necessary.
//
if (!newAttachment->encoding)
;
else if (!nsCRT::strcasecmp(newAttachment->encoding, ENCODING_BASE64))
fn = &MimeB64DecoderInit;
else if (!nsCRT::strcasecmp(newAttachment->encoding, ENCODING_QUOTED_PRINTABLE))
{
mdd->decoder_data = MimeQPDecoderInit (/* The (nsresult (*) ...) cast is to turn the `void' argument into `MimeObject'. */
((nsresult (*) (const char *, PRInt32, void *))
dummy_file_write), mdd->tmpFileStream);
if (!mdd->decoder_data)
return MIME_OUT_OF_MEMORY;
}
else if (!nsCRT::strcasecmp(newAttachment->encoding, ENCODING_UUENCODE) ||
!nsCRT::strcasecmp(newAttachment->encoding, ENCODING_UUENCODE2) ||
!nsCRT::strcasecmp(newAttachment->encoding, ENCODING_UUENCODE3) ||
!nsCRT::strcasecmp(newAttachment->encoding, ENCODING_UUENCODE4))
fn = &MimeUUDecoderInit;
else if (!nsCRT::strcasecmp(newAttachment->encoding, ENCODING_YENCODE))
fn = &MimeYDecoderInit;
if (fn)
{
mdd->decoder_data = fn (/* The (nsresult (*) ...) cast is to turn the `void' argument into `MimeObject'. */
((nsresult (*) (const char *, PRInt32, void *))
dummy_file_write), mdd->tmpFileStream);
if (!mdd->decoder_data)
return MIME_OUT_OF_MEMORY;
}
}
return 0;
}
nsresult
mime_decompose_file_output_fn (const char *buf,
PRInt32 size,
void *stream_closure )
{
struct mime_draft_data *mdd = (struct mime_draft_data *) stream_closure;
int ret = 0;
NS_ASSERTION (mdd && buf, "missing mime draft data and/or buf");
if (!mdd || !buf) return -1;
if (!size) return NS_OK;
if ( !mdd->tmpFileStream )
return NS_OK;
if (mdd->decoder_data) {
ret = MimeDecoderWrite(mdd->decoder_data, buf, size);
if (ret == -1) return -1;
}
else
{
ret = mdd->tmpFileStream->write(buf, size);
if (ret < size)
return MIME_ERROR_WRITING_FILE;
}
return NS_OK;
}
nsresult
mime_decompose_file_close_fn ( void *stream_closure )
{
struct mime_draft_data *mdd = (struct mime_draft_data *) stream_closure;
if ( !mdd || !mdd->tmpFileStream )
return -1;
if ( --mdd->options->decompose_init_count > 0 )
return 0;
if (mdd->decoder_data) {
MimeDecoderDestroy(mdd->decoder_data, PR_FALSE);
mdd->decoder_data = 0;
}
if (mdd->tmpFileStream->GetIStream())
mdd->tmpFileStream->close();
delete mdd->tmpFileStream;
mdd->tmpFileStream = nsnull;
delete mdd->tmpFileSpec;
mdd->tmpFileSpec = nsnull;
return 0;
}
extern "C" void *
mime_bridge_create_draft_stream(
nsIMimeEmitter *newEmitter,
nsStreamConverter *newPluginObj2,
nsIURI *uri,
nsMimeOutputType format_out)
{
int status = 0;
nsMIMESession *stream = nsnull;
struct mime_draft_data *mdd = nsnull;
MimeObject *obj = nsnull;
if ( !uri )
return nsnull;
mdd = PR_NEWZAP(struct mime_draft_data);
if (!mdd)
return nsnull;
nsCAutoString turl;
nsCOMPtr msgService;
nsCOMPtr aURL;
nsCAutoString urlString;
nsresult rv;
// first, convert the rdf msg uri into a url that represents the message...
if (NS_FAILED(uri->GetSpec(turl)))
goto FAIL;
rv = GetMessageServiceFromURI(turl.get(), getter_AddRefs(msgService));
if (NS_FAILED(rv))
goto FAIL;
rv = msgService->GetUrlForUri(turl.get(), getter_AddRefs(aURL), nsnull);
if (NS_FAILED(rv))
goto FAIL;
if (NS_SUCCEEDED(aURL->GetSpec(urlString)))
{
mdd->url_name = ToNewCString(urlString);
if (!(mdd->url_name))
goto FAIL;
}
newPluginObj2->GetForwardInline(&mdd->forwardInline);
newPluginObj2->GetIdentity(getter_AddRefs(mdd->identity));
newPluginObj2->GetOriginalMsgURI(&mdd->originalMsgURI);
mdd->format_out = format_out;
mdd->options = new MimeDisplayOptions ;
if (!mdd->options)
goto FAIL;
mdd->options->url = nsCRT::strdup(mdd->url_name);
mdd->options->format_out = format_out; // output format
mdd->options->decompose_file_p = PR_TRUE; /* new field in MimeDisplayOptions */
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;
mdd->options->m_prefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
if (NS_FAILED(rv))
goto FAIL;
#ifdef ENABLE_SMIME
/* If we're attaching a message (for forwarding) then we must eradicate all
traces of xlateion from it, since forwarding someone else a message
that wasn't xlated for them doesn't work. We have to dexlate it
before sending it.
*/
mdd->options->decrypt_p = PR_TRUE;
#endif /* ENABLE_SMIME */
obj = mime_new ( (MimeObjectClass *) &mimeMessageClass, (MimeHeaders *) NULL, MESSAGE_RFC822 );
if ( !obj )
goto FAIL;
obj->options = mdd->options;
mdd->obj = obj;
stream = PR_NEWZAP ( nsMIMESession );
if ( !stream )
goto FAIL;
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->data_object = mdd;
status = obj->clazz->initialize ( obj );
if ( status >= 0 )
status = obj->clazz->parse_begin ( obj );
if ( status < 0 )
goto FAIL;
return stream;
FAIL:
if (mdd)
{
PR_Free(mdd->url_name);
PR_Free(mdd->originalMsgURI);
if (mdd->options)
delete mdd->options;
PR_Free ( mdd );
}
PR_Free ( stream );
PR_Free ( obj );
return nsnull;
}