diff --git a/mailnews/base/src/nsMsgDBView.cpp b/mailnews/base/src/nsMsgDBView.cpp index 56ec59dc43..d25c07364d 100644 --- a/mailnews/base/src/nsMsgDBView.cpp +++ b/mailnews/base/src/nsMsgDBView.cpp @@ -393,12 +393,22 @@ nsresult nsMsgDBView::FetchAuthor(nsIMsgDBHdr * aHdr, nsAString &aSenderString) if (NS_SUCCEEDED(rv) && !name.IsEmpty()) { nsCString charset; - rv = aHdr->GetCharset(getter_Copies(charset)); + nsCOMPtr folder; + aHdr->GetFolder(getter_AddRefs(folder)); + PRBool charsetOverride; + folder->GetCharsetOverride(&charsetOverride); + if (charsetOverride || + NS_FAILED(aHdr->GetCharset(getter_Copies(charset))) || + charset.IsEmpty() || + charset.Equals("us-ascii")) + folder->GetCharset(charset); rv = mimeConverter->DecodeMimeHeader(name.get(), charset.get(), - PR_FALSE, + charsetOverride, PR_TRUE, aSenderString); + if (NS_FAILED(rv) || aSenderString.IsEmpty()) + CopyUTF8toUTF16(name, aSenderString); return NS_OK; } } diff --git a/mailnews/base/util/nsMsgI18N.cpp b/mailnews/base/util/nsMsgI18N.cpp index b1afb9451f..b41faac422 100644 --- a/mailnews/base/util/nsMsgI18N.cpp +++ b/mailnews/base/util/nsMsgI18N.cpp @@ -557,3 +557,61 @@ nsresult nsMsgI18NShrinkUTF8Str(const nsCString &inString, outString.Assign(Substring(inString, 0, len)); return NS_OK; } + +void nsMsgI18NConvertRawBytesToUTF16(const nsCString& inString, + const char* charset, + nsAString& outString) +{ + if (IsUTF8(inString)) + { + CopyUTF8toUTF16(inString, outString); + return; + } + + nsresult rv = ConvertToUnicode(charset, inString, outString); + if (NS_SUCCEEDED(rv)) + return; + + const char* cur = inString.BeginReading(); + const char* end = inString.EndReading(); + outString.Truncate(); + while (cur < end) { + char c = *cur++; + if (c & char(0x80)) + outString.Append(UCS2_REPLACEMENT_CHAR); + else + outString.Append(c); + } +} + +void nsMsgI18NConvertRawBytesToUTF8(const nsCString& inString, + const char* charset, + nsACString& outString) +{ + if (IsUTF8(inString)) + { + outString.Assign(inString); + return; + } + + nsAutoString utf16Text; + nsresult rv = ConvertToUnicode(charset, inString, utf16Text); + if (NS_SUCCEEDED(rv)) + { + CopyUTF16toUTF8(utf16Text, outString); + return; + } + + // EF BF BD (UTF-8 encoding of U+FFFD) + NS_NAMED_LITERAL_CSTRING(utf8ReplacementChar, "\357\277\275"); + const char* cur = inString.BeginReading(); + const char* end = inString.EndReading(); + outString.Truncate(); + while (cur < end) { + char c = *cur++; + if (c & char(0x80)) + outString.Append(utf8ReplacementChar); + else + outString.Append(c); + } +} diff --git a/mailnews/base/util/nsMsgI18N.h b/mailnews/base/util/nsMsgI18N.h index 5a3f9bad6e..b48392ea9e 100644 --- a/mailnews/base/util/nsMsgI18N.h +++ b/mailnews/base/util/nsMsgI18N.h @@ -167,6 +167,26 @@ NS_MSG_BASE nsresult nsMsgI18NShrinkUTF8Str(const nsCString &inString, PRUint32 aMaxLength, nsACString &outString); +/* + * Convert raw bytes in header to UTF-16 + * + * @param inString [IN] Input raw octets + * @param outString [OUT] Output UTF-16 string + */ +NS_MSG_BASE void nsMsgI18NConvertRawBytesToUTF16(const nsCString& inString, + const char* charset, + nsAString& outString); + +/* + * Convert raw bytes in header to UTF-8 + * + * @param inString [IN] Input raw octets + * @param outString [OUT] Output UTF-8 string + */ +NS_MSG_BASE void nsMsgI18NConvertRawBytesToUTF8(const nsCString& inString, + const char* charset, + nsACString& outString); + // inline forwarders to avoid littering with 'x-imap4-.....' inline nsresult CopyUTF16toMUTF7(const nsString &aSrc, nsACString& aDest) { @@ -198,4 +218,24 @@ inline nsresult ConvertFromUnicode(const char* charset, return nsMsgI18NConvertFromUnicode(charset, aSrc, aDest); } +inline void ConvertRawBytesToUTF16(const nsCString& inString, + const char* charset, nsAString& outString) +{ + return nsMsgI18NConvertRawBytesToUTF16(inString, charset, outString); +} + +inline void ConvertRawBytesToUTF16(const char* inString, + const char* charset, nsAString& outString) +{ + return nsMsgI18NConvertRawBytesToUTF16(nsDependentCString(inString), + charset, + outString); +} + +inline void ConvertRawBytesToUTF8(const nsCString& inString, + const char* charset, nsACString& outString) +{ + return nsMsgI18NConvertRawBytesToUTF8(inString, charset, outString); +} + #endif /* _nsMsgI18N_H_ */ diff --git a/mailnews/compose/src/nsMsgCompose.cpp b/mailnews/compose/src/nsMsgCompose.cpp index 3a0d59056c..11d934896d 100644 --- a/mailnews/compose/src/nsMsgCompose.cpp +++ b/mailnews/compose/src/nsMsgCompose.cpp @@ -2007,7 +2007,8 @@ nsresult nsMsgCompose::CreateMessage(const char * originalMsgURI, else toField.Assign(author); - m_compFields->SetTo(toField.get()); + ConvertRawBytesToUTF8(toField, originCharset.get(), decodedCString); + m_compFields->SetTo(decodedCString.get()); // Setup quoting callbacks for later... mWhatHolder = 1; @@ -2463,17 +2464,21 @@ NS_IMETHODIMP QuotingOutputStreamListener::OnStopRequest(nsIRequest *request, ns if (type == nsIMsgCompType::ReplyAll) { mHeaders->ExtractHeader(HEADER_TO, PR_TRUE, getter_Copies(outCString)); - CopyUTF8toUTF16(outCString, recipient); + ConvertRawBytesToUTF16(outCString, charset.get(), recipient); mHeaders->ExtractHeader(HEADER_CC, PR_TRUE, getter_Copies(outCString)); - CopyUTF8toUTF16(outCString, cc); + ConvertRawBytesToUTF16(outCString, charset.get(), cc); // preserve BCC for the reply-to-self case mHeaders->ExtractHeader(HEADER_BCC, PR_TRUE, getter_Copies(outCString)); if (!outCString.IsEmpty()) - compFields->SetBcc(NS_ConvertUTF8toUTF16(outCString)); + { + nsAutoString bcc; + ConvertRawBytesToUTF16(outCString, charset.get(), bcc); + compFields->SetBcc(bcc); + } mHeaders->ExtractHeader(HEADER_MAIL_FOLLOWUP_TO, PR_TRUE, getter_Copies(outCString)); - CopyUTF8toUTF16(outCString, mailFollowupTo); + ConvertRawBytesToUTF16(outCString, charset.get(), mailFollowupTo); if (! mailFollowupTo.IsEmpty()) { // handle Mail-Followup-To (http://cr.yp.to/proto/replyto.html) @@ -2507,9 +2512,9 @@ NS_IMETHODIMP QuotingOutputStreamListener::OnStopRequest(nsIRequest *request, ns } mHeaders->ExtractHeader(HEADER_REPLY_TO, PR_FALSE, getter_Copies(outCString)); - CopyUTF8toUTF16(outCString, replyTo); + ConvertRawBytesToUTF16(outCString, charset.get(), replyTo); mHeaders->ExtractHeader(HEADER_MAIL_REPLY_TO, PR_TRUE, getter_Copies(outCString)); - CopyUTF8toUTF16(outCString, mailReplyTo); + ConvertRawBytesToUTF16(outCString, charset.get(), mailReplyTo); mHeaders->ExtractHeader(HEADER_NEWSGROUPS, PR_FALSE, getter_Copies(outCString)); if (!outCString.IsEmpty()) @@ -2575,7 +2580,9 @@ NS_IMETHODIMP QuotingOutputStreamListener::OnStopRequest(nsIRequest *request, ns mHeaders->ExtractHeader(HEADER_FROM, PR_FALSE, getter_Copies(outCString)); if (!outCString.IsEmpty()) { - compFields->SetTo(NS_ConvertUTF8toUTF16(outCString)); + nsAutoString from; + ConvertRawBytesToUTF16(outCString, charset.get(), from); + compFields->SetTo(from); } } diff --git a/mailnews/mime/src/mimedrft.cpp b/mailnews/mime/src/mimedrft.cpp index 373caed9c8..9375194c7e 100644 --- a/mailnews/mime/src/mimedrft.cpp +++ b/mailnews/mime/src/mimedrft.cpp @@ -293,9 +293,11 @@ CreateCompositionFields(const char *from, cFields->SetCharacterSet(!PL_strcasecmp("us-ascii", charset) ? "ISO-8859-1" : charset); char *val; + nsAutoString outString; if (from) { - cFields->SetFrom(NS_ConvertUTF8toUTF16(from)); + ConvertRawBytesToUTF16(from, charset, outString); + cFields->SetFrom(outString); } if (subject) { @@ -305,19 +307,23 @@ CreateCompositionFields(const char *from, } if (reply_to) { - cFields->SetReplyTo(NS_ConvertUTF8toUTF16(reply_to)); + ConvertRawBytesToUTF16(reply_to, charset, outString); + cFields->SetReplyTo(outString); } if (to) { - cFields->SetTo(NS_ConvertUTF8toUTF16(to)); + ConvertRawBytesToUTF16(to, charset, outString); + cFields->SetTo(outString); } if (cc) { - cFields->SetCc(NS_ConvertUTF8toUTF16(cc)); + ConvertRawBytesToUTF16(cc, charset, outString); + cFields->SetCc(outString); } if (bcc) { - cFields->SetBcc(NS_ConvertUTF8toUTF16(bcc)); + ConvertRawBytesToUTF16(bcc, charset, outString); + cFields->SetBcc(outString); } if (fcc) { diff --git a/mailnews/mime/src/mimehdrs.cpp b/mailnews/mime/src/mimehdrs.cpp index 45dd2b25a7..94c805ea29 100644 --- a/mailnews/mime/src/mimehdrs.cpp +++ b/mailnews/mime/src/mimehdrs.cpp @@ -61,13 +61,22 @@ PRInt32 MimeHeaders_build_heads_list(MimeHeaders *hdrs); static void -MimeHeaders_convert_header_value(MimeDisplayOptions *opt, nsCString &value) +MimeHeaders_convert_header_value(MimeDisplayOptions *opt, nsCString &value, + PRBool convert_charset_only) { char *converted; if (value.IsEmpty()) return; + if (convert_charset_only) + { + nsCAutoString output; + ConvertRawBytesToUTF8(value, opt->default_charset, output); + value.Assign(output); + return; + } + if (opt && opt->rfc1522_conversion_p) { converted = MIME_DecodeMimeHeader(value.get(), opt->default_charset, @@ -590,19 +599,20 @@ MimeHeaders_write_all_headers (MimeHeaders *hdrs, MimeDisplayOptions *opt, PRBoo } // MW Fixme: more? + PRBool convert_charset_only = #ifdef MOZILLA_INTERNAL_API - if (!(name.LowerCaseEqualsLiteral("to") || name.LowerCaseEqualsLiteral("from") || + name.LowerCaseEqualsLiteral("to") || name.LowerCaseEqualsLiteral("from") || name.LowerCaseEqualsLiteral("cc") || name.LowerCaseEqualsLiteral("bcc") || - name.LowerCaseEqualsLiteral("reply-to") || name.LowerCaseEqualsLiteral("sender"))) + name.LowerCaseEqualsLiteral("reply-to") || name.LowerCaseEqualsLiteral("sender"); #else - if (!(name.Equals("to", CaseInsensitiveCompare) || + name.Equals("to", CaseInsensitiveCompare) || name.Equals("from", CaseInsensitiveCompare) || name.Equals("cc", CaseInsensitiveCompare) || name.Equals("bcc", CaseInsensitiveCompare) || name.Equals("reply-to", CaseInsensitiveCompare) || - name.Equals("sender", CaseInsensitiveCompare))) + name.Equals("sender", CaseInsensitiveCompare); #endif - MimeHeaders_convert_header_value(opt, hdr_value); + MimeHeaders_convert_header_value(opt, hdr_value, convert_charset_only); // if we're saving as html, we need to convert headers from utf8 to message charset, if any if (opt->format_out == nsMimeOutput::nsMimeMessageSaveAs && charset) {