Saving mail message fix for I18N - Beta1 Bug: 23418 - r: scottip

This commit is contained in:
rhp%netscape.com 2000-02-10 06:48:22 +00:00
parent 362103c7d3
commit 66fcba297a
24 changed files with 286 additions and 56 deletions

View File

@ -32,6 +32,7 @@
#include "nsIStringStream.h"
#include "nsEscape.h"
#include "nsXPIDLString.h"
#include "nsTextFormatter.h"
// necko
#include "nsMimeTypes.h"
@ -52,7 +53,7 @@
#include "nsIContentViewerFile.h"
#include "nsIContentViewer.h"
/* rhp - for access to webshell */
/* for access to webshell */
#include "nsIDOMWindow.h"
#include "nsIBrowserWindow.h"
#include "nsIWebShellWindow.h"
@ -92,6 +93,11 @@
#include "nsITransaction.h"
#include "nsMsgTxn.h"
// charset conversions
#include "nsMsgMimeCID.h"
#include "nsIMimeConverter.h"
static NS_DEFINE_CID(kCMimeConverterCID, NS_MIME_CONVERTER_CID);
static NS_DEFINE_CID(kIStreamConverterServiceCID, NS_STREAMCONVERTERSERVICE_CID);
static NS_DEFINE_CID(kCMsgMailSessionCID, NS_MSGMAILSESSION_CID);
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
@ -106,6 +112,71 @@ static NS_DEFINE_CID(kMsgCopyServiceCID, NS_MSGCOPYSERVICE_CID);
#define FOUR_K 4096
//
// Convert an nsString buffer to plain text...
//
#include "nsIParser.h"
#include "nsParserCIID.h"
#include "nsHTMLToTXTSinkStream.h"
#include "CNavDTD.h"
#include "nsICharsetConverterManager.h"
#include "nsIDocumentEncoder.h"
nsresult
ConvertBufToPlainText(nsString &aConBuf)
{
nsresult rv;
nsString convertedText;
nsIParser *parser;
if (aConBuf == "")
return NS_OK;
static NS_DEFINE_IID(kCParserIID, NS_IPARSER_IID);
static NS_DEFINE_IID(kCParserCID, NS_PARSER_IID);
rv = nsComponentManager::CreateInstance(kCParserCID, nsnull,
kCParserIID, (void **)&parser);
if (NS_SUCCEEDED(rv) && parser)
{
nsHTMLToTXTSinkStream *sink = nsnull;
PRUint32 converterFlags = 0;
PRUint32 wrapWidth = 72;
converterFlags |= nsIDocumentEncoder::OutputFormatted;
rv = NS_New_HTMLToTXT_SinkStream((nsIHTMLContentSink **)&sink, &convertedText, wrapWidth, converterFlags);
if (sink && NS_SUCCEEDED(rv))
{
sink->DoFragment(PR_TRUE);
parser->SetContentSink(sink);
nsIDTD* dtd = nsnull;
rv = NS_NewNavHTMLDTD(&dtd);
if (NS_SUCCEEDED(rv))
{
parser->RegisterDTD(dtd);
rv = parser->Parse(aConBuf, 0, "text/html", PR_FALSE, PR_TRUE);
}
NS_IF_RELEASE(dtd);
NS_IF_RELEASE(sink);
}
NS_RELEASE(parser);
//
// Now if we get here, we need to get from ASCII text to
// UTF-8 format or there is a problem downstream...
//
if (NS_SUCCEEDED(rv))
{
aConBuf = convertedText;
}
}
return rv;
}
// ***************************************************
// jefft - this is a rather obscured class serves for Save Message As File,
// Save Message As Template, and Save Attachment to a file
@ -130,6 +201,12 @@ public:
char *m_dataBuffer;
nsCOMPtr<nsIChannel> m_channel;
nsXPIDLCString m_templateUri;
// rhp: For character set handling
PRBool m_doCharsetConversion;
nsString m_charset;
nsString m_outputFormat;
nsString m_msgBuffer;
};
//
@ -517,7 +594,12 @@ nsMessenger::SaveAs(const char* url, PRBool asFile, nsIMsgIdentity* identity)
NS_ADDREF(aListener);
nsCOMPtr<nsIURI> aURL;
nsAutoString urlString = url;
urlString += "?header=none";
if (saveAsFileType == 2) // RICHIE - text hack, ugh!
urlString += "?header=quote";
else
urlString += "?header=saveas";
char *urlCString = urlString.ToNewCString();
rv = CreateStartupUrl(urlCString, getter_AddRefs(aURL));
nsCRT::free(urlCString);
@ -542,18 +624,26 @@ nsMessenger::SaveAs(const char* url, PRBool asFile, nsIMsgIdentity* identity)
NS_RELEASE(aListener);
goto done;
}
nsAutoString from, to;
nsAutoString from;
from = MESSAGE_RFC822;
to = saveAsFileType == 1 ? TEXT_HTML : TEXT_PLAIN;
aListener->m_outputFormat = saveAsFileType == 1 ? TEXT_HTML : TEXT_PLAIN;
// Mark the fact that we need to do charset handling/text conversion!
if (aListener->m_outputFormat == TEXT_PLAIN)
aListener->m_doCharsetConversion = PR_TRUE;
NS_WITH_SERVICE(nsIStreamConverterService,
streamConverterService,
kIStreamConverterServiceCID, &rv);
nsCOMPtr<nsISupports> channelSupport =
do_QueryInterface(aListener->m_channel);
nsCOMPtr<nsISupports> channelSupport = do_QueryInterface(aListener->m_channel);
nsCOMPtr<nsIStreamListener> convertedListener;
rv = streamConverterService->AsyncConvertData(
from.GetUnicode(), to.GetUnicode(), aListener,
channelSupport, getter_AddRefs(convertedListener));
from.GetUnicode(),
// RICHIE - we should be able to go RFC822 to TXT, but not until
// Bug #1775 is fixed. aListener->m_outputFormat.GetUnicode()
nsString(TEXT_HTML).GetUnicode(),
aListener,
channelSupport, getter_AddRefs(convertedListener));
if (NS_SUCCEEDED(rv))
messageService->DisplayMessage(url, convertedListener,mMsgWindow,
nsnull, nsnull);
@ -1229,6 +1319,12 @@ nsSaveAsListener::nsSaveAsListener(nsIFileSpec* aSpec)
if (aSpec)
m_fileSpec = do_QueryInterface(aSpec);
m_dataBuffer = nsnull;
// rhp: for charset handling
m_doCharsetConversion = PR_FALSE;
m_charset = "";
m_outputFormat = "";
m_msgBuffer = "";
}
nsSaveAsListener::~nsSaveAsListener()
@ -1339,13 +1435,46 @@ NS_IMETHODIMP
nsSaveAsListener::OnStopRequest(nsIChannel* aChannel, nsISupports* aSupport,
nsresult status, const PRUnichar* aMsg)
{
// close down the file stream and release ourself
nsresult rv = NS_OK;
// rhp: If we are doing the charset conversion magic, this is different
// processing, otherwise, its just business as usual.
//
if ( (m_doCharsetConversion) && (m_fileSpec) )
{
char *conBuf = nsnull;
PRUint32 conLength = 0;
// If we need text/plain, then we need to convert the HTML and then convert
// to the systems charset
//
if (m_outputFormat == TEXT_PLAIN)
{
ConvertBufToPlainText(m_msgBuffer);
rv = ConvertFromUnicode(msgCompFileSystemCharset(), m_msgBuffer, &conBuf);
if ( NS_SUCCEEDED(rv) && (conBuf) )
conLength = nsCRT::strlen(conBuf);
}
if ( (NS_SUCCEEDED(rv)) && (conBuf) )
{
PRUint32 writeCount;
rv = m_outputStream->Write(conBuf, conLength, &writeCount);
if (conLength != writeCount)
rv = NS_ERROR_FAILURE;
}
PR_FREEIF(conBuf);
}
// close down the file stream and release ourself
if (m_fileSpec)
{
m_fileSpec->Flush();
m_fileSpec->CloseStream();
m_outputStream = null_nsCOMPtr();
}
Release(); // all done kill ourself
return NS_OK;
}
@ -1367,9 +1496,39 @@ nsSaveAsListener::OnDataAvailable(nsIChannel* aChannel,
{
if (maxReadCount > available)
maxReadCount = available;
nsCRT::memset(m_dataBuffer, 0, FOUR_K+1);
rv = inStream->Read(m_dataBuffer, maxReadCount, &readCount);
if (NS_SUCCEEDED(rv))
rv = m_outputStream->Write(m_dataBuffer, readCount, &writeCount);
// rhp:
// Ok, here is where we need to see if any conversion needs to be
// done on this data as we write it out to disk. The logic of what
// type of conversion should be done by now and it should just be
// a matter of mashing the bits.
//
if ( (m_doCharsetConversion) && (m_outputFormat == TEXT_PLAIN) )
{
if (NS_SUCCEEDED(rv) && readCount > 0)
{
PRUnichar *u = nsnull;
nsAutoString fmt("%s");
u = nsTextFormatter::smprintf(fmt.GetUnicode(), m_dataBuffer); // this converts UTF-8 to UCS-2
if (u)
{
PRInt32 newLen = nsCRT::strlen(u);
m_msgBuffer.Append(u, newLen);
PR_FREEIF(u);
}
else
m_msgBuffer.Append(m_dataBuffer, readCount);
}
}
else
{
if (NS_SUCCEEDED(rv))
rv = m_outputStream->Write(m_dataBuffer, readCount, &writeCount);
}
available -= readCount;
}
}

View File

@ -347,9 +347,6 @@ ACTUALLY, EVERY TIME YOU TYPE ANY OF THE KEY DEFINED HERE AFTER WITHOUT ANY OF T
</template>
</menu>
<menuitem value="&uuEncodeCmd.label;" accesskey="&uuEncodeCmd.accesskey;" oncommand="UUEncodeMenuSelect();"/>
<menuseparator/>
<menuitem value="&addSignatureCmd.label;" disabled="true" oncommand=""/>
<menuitem value="&attachVCardCmd.label;" disabled="true" accesskey="&attachVCardCmd.accesskey;" oncommand="AttachVCard()"/>
</menupopup>

View File

@ -114,8 +114,6 @@
<!ENTITY highestPriorityCmd.label "Highest">
<!ENTITY returnReceiptCmd.label "Return receipt">
<!ENTITY uuEncodeCmd.label "Uuencode instead of MIME for Attachments">
<!ENTITY uuEncodeCmd.accesskey "U">
<!ENTITY outputFormatMenu.label "Format">
<!ENTITY askmeFormatCmd.label ".Ask me">

View File

@ -899,7 +899,7 @@ nsMsgAttachmentHandler::UrlExit(nsresult status, const PRUnichar* aMsg)
if (NS_SUCCEEDED(LoadDataFromFile(*mFileSpec, conData)))
{
if (NS_SUCCEEDED(ConvertBufToPlainText(conData, m_charset)))
if (NS_SUCCEEDED(ConvertBufToPlainText(conData)))
{
mFileSpec->Delete(PR_FALSE);

View File

@ -766,7 +766,7 @@ nsresult nsMsgCompFields::ConvertBodyToPlainText()
{
nsString body(ubody);
PR_Free(ubody);
rv = ConvertBufToPlainText(body, msgCompHeaderInternalCharset());
rv = ConvertBufToPlainText(body);
if (NS_SUCCEEDED(rv))
rv = SetBody(body.GetUnicode());
}

View File

@ -1935,7 +1935,7 @@ ERROR_OUT:
#include "nsICharsetConverterManager.h"
nsresult
ConvertBufToPlainText(nsString &aConBuf, const char *charSet)
ConvertBufToPlainText(nsString &aConBuf)
{
nsresult rv;
nsString convertedText;
@ -1967,7 +1967,6 @@ ConvertBufToPlainText(nsString &aConBuf, const char *charSet)
converterFlags |= nsIDocumentEncoder::OutputFormatFlowed;
}
nsAutoString charSetStr(charSet);
rv = NS_New_HTMLToTXT_SinkStream((nsIHTMLContentSink **)&sink, &convertedText, wrapWidth, converterFlags);
if (sink && NS_SUCCEEDED(rv))
{

View File

@ -128,7 +128,7 @@ char *GetFolderURIFromUserPrefs(nsMsgDeliverMode aMode,
nsIMsgIdentity *identity);
// File calls...
nsresult ConvertBufToPlainText(nsString &aConBuf, const char *charSet);
nsresult ConvertBufToPlainText(nsString &aConBuf);
// Conversion...
void DoLineEndingConJob(char *aBuf, PRUint32 aLen);

View File

@ -1103,9 +1103,9 @@ QuotingOutputStreamListener::ConvertToPlainText()
{
nsresult rv = NS_OK;
rv += ConvertBufToPlainText(mCitePrefix, "UTF-8");
rv += ConvertBufToPlainText(mMsgBody, "UTF-8");
rv += ConvertBufToPlainText(mSignature, "UTF-8");
rv += ConvertBufToPlainText(mCitePrefix);
rv += ConvertBufToPlainText(mMsgBody);
rv += ConvertBufToPlainText(mSignature);
return rv;
}
@ -1702,7 +1702,7 @@ nsMsgCompose::ConvertHTMLToText(nsFileSpec& aSigFile, nsString &aSigData)
if (NS_FAILED(rv))
return rv;
ConvertBufToPlainText(origBuf, nsnull);
ConvertBufToPlainText(origBuf);
aSigData = origBuf;
return NS_OK;
}

View File

@ -1998,9 +1998,9 @@ nsMsgComposeAndSend::HackAttachments(const nsMsgAttachmentData *attachments,
// sniff the file and see if we can figure it out.
if ( (m_attachments[i].m_type) && (*m_attachments[i].m_type) )
{
if (PL_strcasecmp(m_attachments[i].m_type, TEXT_HTML) == 0)
if ( (PL_strcasecmp(m_attachments[i].m_type, TEXT_HTML) == 0) && (preloaded_attachments[i].file_spec) )
{
char *tmpCharset = (char *)nsMsgI18NParseMetaCharset(m_attachments[i].mFileSpec);
char *tmpCharset = (char *)nsMsgI18NParseMetaCharset(preloaded_attachments[i].file_spec);
if (tmpCharset[0] != '\0')
{
PR_FREEIF(m_attachments[i].m_charset);

View File

@ -57,12 +57,14 @@ nsMimeBaseEmitter::nsMimeBaseEmitter()
NS_INIT_REFCNT();
// Initialize data output vars...
mFirstHeaders = PR_TRUE;
mBufferMgr = NULL;
mTotalWritten = 0;
mTotalRead = 0;
mInputStream = nsnull;
mOutStream = nsnull;
mOutListener = nsnull;
mChannel = nsnull;
// Display output control vars...
mDocHeader = PR_FALSE;
@ -83,14 +85,12 @@ nsMimeBaseEmitter::nsMimeBaseEmitter()
// HTML Header Data...
mHTMLHeaders = "";
mCharset = "";
// Init the body...
mBodyStarted = PR_FALSE;
mBody = "";
// Setup format for output...
mFormat = nsMimeOutput::nsMimeMessageXULDisplay;
// This is needed for conversion of I18N Strings...
nsComponentManager::CreateInstance(kCMimeConverterCID, nsnull,
NS_GET_IID(nsIMimeConverter),
@ -283,7 +283,7 @@ nsMimeBaseEmitter::SetPipe(nsIInputStream * aInputStream, nsIOutputStream *outSt
// anything to the stream since these may be image data
// output streams, etc...
NS_IMETHODIMP
nsMimeBaseEmitter::Initialize(nsIURI *url, nsIChannel * aChannel)
nsMimeBaseEmitter::Initialize(nsIURI *url, nsIChannel * aChannel, PRInt32 aFormat)
{
// set the url
mURL = url;
@ -295,6 +295,7 @@ nsMimeBaseEmitter::Initialize(nsIURI *url, nsIChannel * aChannel)
// Counters for output stream
mTotalWritten = 0;
mTotalRead = 0;
mFormat = aFormat;
return NS_OK;
}
@ -475,6 +476,7 @@ nsMimeBaseEmitter::StartHeader(PRBool rootMailHeader, PRBool headerOnly, const c
if (mDocHeader)
UpdateCharacterSet(outCharset);
mCharset = outCharset;
return NS_OK;
}
@ -549,7 +551,7 @@ nsMimeBaseEmitter::AddHeaderField(const char *field, const char *value)
{
ptr->name = nsCRT::strdup(field);
if (mDocHeader)
if ( (mDocHeader) || (mFormat != nsMimeOutput::nsMimeMessageSaveAs) )
ptr->value = nsCRT::strdup(value);
else
ptr->value = nsAutoString(value).ToNewUTF8String();
@ -580,19 +582,23 @@ nsMimeBaseEmitter::WriteHeaderFieldHTML(const char *field, const char *value)
if (!EmitThisHeaderForPrefSetting(mHeaderDisplayType, field))
return NS_OK;
if (mUnicodeConverter)
if ( (mUnicodeConverter) && (mFormat != nsMimeOutput::nsMimeMessageSaveAs) )
{
nsAutoString unicodeHeaderValue;
nsAutoString charset ("UTF-8");
nsAutoString unicodeHeaderValue;
nsAutoString charset ("UTF-8");
char *tValue = nsnull;
// we're going to need a converter to convert
nsresult rv = mUnicodeConverter->DecodeMimePartIIStr(value, charset, unicodeHeaderValue);
char *tValue = unicodeHeaderValue.ToNewCString();
if (!tValue)
return NS_OK;
if (NS_SUCCEEDED(rv))
{
tValue = unicodeHeaderValue.ToNewCString();
if (!tValue)
return NS_OK;
newValue = nsEscapeHTML(tValue);
PR_FREEIF(tValue);
newValue = nsEscapeHTML(tValue);
PR_FREEIF(tValue);
}
}
else
{
@ -605,7 +611,10 @@ nsMimeBaseEmitter::WriteHeaderFieldHTML(const char *field, const char *value)
mHTMLHeaders.Append("<TR>");
mHTMLHeaders.Append("<TD>");
mHTMLHeaders.Append("<DIV CLASS=\"headerdisplayname\" style=\"display:inline;\">");
if (mFormat == nsMimeOutput::nsMimeMessageSaveAs)
mHTMLHeaders.Append("<B>");
else
mHTMLHeaders.Append("<DIV CLASS=\"headerdisplayname\" style=\"display:inline;\">");
// Here is where we are going to try to L10N the tagName so we will always
// get a field name next to an emitted header value. Note: Default will always
@ -625,7 +634,10 @@ nsMimeBaseEmitter::WriteHeaderFieldHTML(const char *field, const char *value)
}
mHTMLHeaders.Append(": ");
mHTMLHeaders.Append("</DIV>");
if (mFormat == nsMimeOutput::nsMimeMessageSaveAs)
mHTMLHeaders.Append("</B>");
else
mHTMLHeaders.Append("</DIV>");
// Now write out the actual value itself and move on!
//
@ -641,7 +653,14 @@ nsMimeBaseEmitter::WriteHeaderFieldHTML(const char *field, const char *value)
nsresult
nsMimeBaseEmitter::WriteHeaderFieldHTMLPrefix()
{
mHTMLHeaders.Append("<BR><HR WIDTH=\"90%\" SIZE=4><BR>");
// This mess is for Save As operations...
if ( ( (mFormat == nsMimeOutput::nsMimeMessageSaveAs) && (!mFirstHeaders) ) || // RICHIE: Goes away when we have the
( (mFormat == nsMimeOutput::nsMimeMessageQuoting) && (!mFirstHeaders) ) || // HTML-TEXT stream converter interface
( (mFormat != nsMimeOutput::nsMimeMessageSaveAs) && (mFormat != nsMimeOutput::nsMimeMessageQuoting) )
)
mHTMLHeaders.Append("<BR><HR WIDTH=\"90%\" SIZE=4><BR>");
mFirstHeaders = PR_FALSE;
mHTMLHeaders.Append("<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 WIDTH=\"100%\">");
return NS_OK;
}

View File

@ -142,12 +142,14 @@ protected:
// For body caching...
PRBool mBodyStarted;
nsCString mBody;
PRBool mFirstHeaders;
// For the format being used...
PRInt32 mFormat;
// For I18N Conversion...
nsCOMPtr<nsIMimeConverter> mUnicodeConverter;
nsString mCharset;
};
#endif /* _nsMimeBaseEmitter_h_ */

View File

@ -54,7 +54,6 @@ nsresult NS_NewMimeHtmlDisplayEmitter(const nsIID& iid, void **result)
*/
nsMimeHtmlDisplayEmitter::nsMimeHtmlDisplayEmitter()
{
mFormat = nsMimeOutput::nsMimeMessageBodyQuoting;
mFirst = PR_TRUE;
mSkipAttachment = PR_FALSE;
}
@ -111,7 +110,7 @@ nsresult
nsMimeHtmlDisplayEmitter::GetHeaderSink(nsIMsgHeaderSink ** aHeaderSink)
{
nsresult rv = NS_OK;
if (!mHeaderSink)
if ( (mChannel) && (!mHeaderSink) )
{
nsCOMPtr<nsIURI> uri;
mChannel->GetURI(getter_AddRefs(uri));
@ -266,7 +265,7 @@ nsMimeHtmlDisplayEmitter::StartAttachmentInBody(const char *name, const char *co
else
mSkipAttachment = PR_FALSE;
if (mFirst)
if (!mFirst)
UtilityWrite("<HR WIDTH=\"90%\" SIZE=4>");
mFirst = PR_FALSE;

View File

@ -71,8 +71,6 @@ nsMimeXULEmitter::nsMimeXULEmitter()
mBody = "";
mBodyStarted = PR_FALSE;
mFormat = nsMimeOutput::nsMimeMessageXULDisplay;
if (mPrefs)
mPrefs->GetIntPref("mailnews.max_header_display_length", &mCutoffValue);

View File

@ -77,6 +77,11 @@ public:
const PRInt32 encodedWordSize,
char **encodedString) = 0;
// Apply charset conversion to a given buffer. The conversion is done by an unicode round trip.
NS_IMETHOD ConvertCharset(const PRBool autoDetection, const char* from_charset, const char* to_charset,
const char* inBuffer, const PRInt32 inLength, char** outBuffer, PRInt32* outLength,
PRInt32* numUnConverted) = 0;
NS_IMETHOD B64EncoderInit(int (*output_fn) (const char *buf, PRInt32 size, void *closure),
void *closure, MimeEncoderData **returnEncoderData) = 0;

View File

@ -45,7 +45,7 @@ interface nsMimeHeaderDisplayTypes
interface nsIMimeEmitter : nsISupports{
// These will be called to start and stop the total operation
void Initialize(in nsIURI url, in nsIChannel aChannel);
void Initialize(in nsIURI url, in nsIChannel aChannel, in long aFormat);
void Complete();
// Set the output stream/listener for processed data.

View File

@ -48,7 +48,8 @@ interface nsMimeOutput
const long nsMimeMessageEditorTemplate = 7;
const long nsMimeMessageXULDisplay = 8;
const long nsMimeMessagePrintOutput = 9;
const long nsMimeUnknown = 10;
const long nsMimeMessageSaveAs = 10;
const long nsMimeUnknown = 11;
};
[scriptable, uuid(FA81CAA0-6261-11d3-8311-00805F2A0107)]

View File

@ -1367,6 +1367,7 @@ MimeObject_output_init(MimeObject *obj, const char *content_type)
if ( (obj->options) &&
( (obj->options->format_out == nsMimeOutput::nsMimeMessageQuoting) ||
(obj->options->format_out == nsMimeOutput::nsMimeMessageBodyQuoting) ||
(obj->options->format_out == nsMimeOutput::nsMimeMessageSaveAs) ||
(obj->options->format_out == nsMimeOutput::nsMimeMessagePrintOutput) ) )
ResetChannelCharset(obj);

View File

@ -468,6 +468,7 @@ NotifyEmittersOfAttachmentList(MimeDisplayOptions *opt,
if ( (opt->format_out == nsMimeOutput::nsMimeMessageQuoting) ||
(opt->format_out == nsMimeOutput::nsMimeMessageBodyQuoting) ||
(opt->format_out == nsMimeOutput::nsMimeMessageSaveAs) ||
(opt->format_out == nsMimeOutput::nsMimeMessagePrintOutput) )
{
mimeEmitterAddAttachmentField(opt, HEADER_CONTENT_DESCRIPTION, tmp->description);
@ -1200,6 +1201,7 @@ mime_bridge_create_display_stream(
msd->options->fancy_links_p = PR_TRUE;
break;
case nsMimeOutput::nsMimeMessageSaveAs: // Save As operations
case nsMimeOutput::nsMimeMessageQuoting: // all HTML quoted/printed output
case nsMimeOutput::nsMimeMessagePrintOutput:
msd->options->fancy_headers_p = PR_TRUE;
@ -1266,7 +1268,7 @@ mime_bridge_create_display_stream(
msd->options->set_html_state_fn = mime_set_html_state_fn;
if ( format_out == nsMimeOutput::nsMimeMessageQuoting || format_out == nsMimeOutput::nsMimeMessageBodyQuoting ||
format_out == nsMimeOutput::nsMimeMessagePrintOutput )
format_out == nsMimeOutput::nsMimeMessagePrintOutput || format_out == nsMimeOutput::nsMimeMessageSaveAs )
{
msd->options->charset_conversion_fn = mime_insert_html_convert_charset;
}
@ -1649,8 +1651,31 @@ ResetChannelCharset(MimeObject *obj)
if ( (ct) && (msd) && (msd->channel) )
{
char *ptr = PL_strstr(ct, "charset=");
if (ptr)
if (ptr)
{
// First, setup the channel!
msd->channel->SetContentType(ct);
// Second, if this is a Save As operation, then we need to convert
// to override the output charset!
mime_stream_data *msd = GetMSD(obj->options);
if ( (msd) && (msd->format_out == nsMimeOutput::nsMimeMessageSaveAs) )
{
// Extract the charset alone
char *cSet = nsCRT::strdup(ptr+8);
if (cSet)
{
char *ptr2 = cSet;
while ( (*cSet) && (*cSet != ' ') && (*cSet != ';') && (*cSet != CR) && (*cSet != LF) )
ptr2++;
if (*cSet)
obj->options->override_charset = nsCRT::strdup(cSet);
PR_FREEIF(cSet);
}
}
}
PR_FREEIF(ct);
}
}

View File

@ -273,7 +273,8 @@ MimeInlineText_rotate_convert_and_parse_line(char *line, PRInt32 length,
//
PRBool doConvert = PR_TRUE;
// Don't convert vCard data
if ( (obj->content_type) && (!PL_strcasecmp(obj->content_type, TEXT_VCARD)) )
if ( ( (obj->content_type) && (!PL_strcasecmp(obj->content_type, TEXT_VCARD)) ) ||
(obj->options->format_out == nsMimeOutput::nsMimeMessageSaveAs) )
doConvert = PR_FALSE;
// Only convert if the user prefs is false

View File

@ -282,7 +282,8 @@ MimeInlineTextPlainFlowed_parse_line (char *line, PRInt32 length, MimeObject *ob
PRBool skipScanning = (!conv) ||
(obj->options && obj->options->force_user_charset) ||
(obj->options && (obj->options->format_out == nsMimeOutput::nsMimeMessageQuoting)) ||
(obj->options && (obj->options->format_out == nsMimeOutput::nsMimeMessageBodyQuoting));
(obj->options && (obj->options->format_out == nsMimeOutput::nsMimeMessageBodyQuoting) ||
(obj->options && (obj->options->format_out == nsMimeOutput::nsMimeMessageSaveAs)));
if (!skipScanning)
{

View File

@ -160,7 +160,8 @@ MimeInlineTextPlain_parse_line (char *line, PRInt32 length, MimeObject *obj)
PRBool skipScanning = (!conv) ||
(obj->options && obj->options->force_user_charset) ||
(obj->options && (obj->options->format_out == nsMimeOutput::nsMimeMessageQuoting)) ||
(obj->options && (obj->options->format_out == nsMimeOutput::nsMimeMessageBodyQuoting));
(obj->options && (obj->options->format_out == nsMimeOutput::nsMimeMessageBodyQuoting)) ||
(obj->options && (obj->options->format_out == nsMimeOutput::nsMimeMessageSaveAs));
if (!skipScanning)
{

View File

@ -129,6 +129,17 @@ nsMimeConverter::EncodeMimePartIIStr_UTF8(const char *header,
}
}
// Apply charset conversion to a given buffer. The conversion is done by an unicode round trip.
nsresult
nsMimeConverter::ConvertCharset(const PRBool autoDetection, const char* from_charset, const char* to_charset,
const char* inBuffer, const PRInt32 inLength, char** outBuffer, PRInt32* outLength,
PRInt32* numUnConverted)
{
return MIME_ConvertCharset(autoDetection, from_charset, to_charset, inBuffer, inLength,
outBuffer, outLength, numUnConverted);
}
nsresult
nsMimeConverter::B64EncoderInit(int (*output_fn) (const char *buf, PRInt32 size, void *closure), void *closure,
MimeEncoderData **returnEncoderData)

View File

@ -67,6 +67,11 @@ public:
const PRInt32 encodedWordSize,
char **encodedString);
// Apply charset conversion to a given buffer. The conversion is done by an unicode round trip.
NS_IMETHOD ConvertCharset(const PRBool autoDetection, const char* from_charset, const char* to_charset,
const char* inBuffer, const PRInt32 inLength, char** outBuffer, PRInt32* outLength,
PRInt32* numUnConverted);
NS_IMETHOD B64EncoderInit(int (*output_fn) (const char *buf, PRInt32 size, void *closure),
void *closure, MimeEncoderData **returnEncoderData);

View File

@ -255,6 +255,7 @@ nsStreamConverter::DetermineOutputFormat(const char *url, nsMimeOutputType *aNe
char *ptr4 = PL_strcasestr ("quotebody", (header+lenOfHeader));
char *ptr5 = PL_strcasestr ("none", (header+lenOfHeader));
char *ptr6 = PL_strcasestr ("print", (header+lenOfHeader));
char *ptr7 = PL_strcasestr ("saveas", (header+lenOfHeader));
if (ptr5)
{
PR_FREEIF(mOutputFormat);
@ -285,6 +286,12 @@ nsStreamConverter::DetermineOutputFormat(const char *url, nsMimeOutputType *aNe
mOutputFormat = nsCRT::strdup("text/html");
*aNewType = nsMimeOutput::nsMimeMessagePrintOutput;
}
else if (ptr7)
{
PR_FREEIF(mOutputFormat);
mOutputFormat = nsCRT::strdup("text/html");
*aNewType = nsMimeOutput::nsMimeMessageSaveAs;
}
}
else
{
@ -406,6 +413,7 @@ NS_IMETHODIMP nsStreamConverter::Init(nsIURI *aURI, nsIStreamListener * aOutList
break;
case nsMimeOutput::nsMimeMessageQuoting: // all HTML quoted output
case nsMimeOutput::nsMimeMessageSaveAs: // Save as operation
case nsMimeOutput::nsMimeMessageBodyQuoting: // only HTML body quoted output
case nsMimeOutput::nsMimeMessagePrintOutput: // all Printing output
PR_FREEIF(mOutputFormat);
@ -500,7 +508,7 @@ NS_IMETHODIMP nsStreamConverter::Init(nsIURI *aURI, nsIStreamListener * aOutList
// initialize our emitter
if (NS_SUCCEEDED(rv) && mEmitter)
{
mEmitter->Initialize(aURI, mOutgoingChannel);
mEmitter->Initialize(aURI, mOutgoingChannel, newType);
mEmitter->SetPipe(mInputStream, mOutputStream);
mEmitter->SetOutputListener(aOutListener);
}