Bug 468351 - "display of header values with unencoded special characters broken" - mailnews part [r=bienvenu sr=neil]

This commit is contained in:
Masatoshi Kimura 2009-07-27 19:42:45 +01:00
Родитель 8002a1caad
Коммит 93ed748f04
6 изменённых файлов: 152 добавлений и 21 удалений

Просмотреть файл

@ -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 <nsIMsgFolder> 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;
}
}

Просмотреть файл

@ -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);
}
}

Просмотреть файл

@ -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_ */

Просмотреть файл

@ -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);
}
}

Просмотреть файл

@ -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) {

Просмотреть файл

@ -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)
{