Bug 493544 - Don't decode the encoded text until it ends. r=smontagu

This commit is contained in:
Zane U. Ji 2012-12-22 17:54:00 +09:00
parent 20a6d96dc4
commit f3d486af9c

View File

@ -1091,6 +1091,43 @@ void CopyRawHeader(const char *aInput, uint32_t aLen,
}
}
nsresult DecodeQOrBase64Str(const char *aEncoded, size_t aLen, char aQOrBase64,
const char *aCharset, nsACString &aResult)
{
char *decodedText;
NS_ASSERTION(aQOrBase64 == 'Q' || aQOrBase64 == 'B', "Should be 'Q' or 'B'");
if(aQOrBase64 == 'Q')
decodedText = DecodeQ(aEncoded, aLen);
else if (aQOrBase64 == 'B') {
decodedText = PL_Base64Decode(aEncoded, aLen, nullptr);
} else {
return NS_ERROR_INVALID_ARG;
}
if (!decodedText) {
return NS_ERROR_INVALID_ARG;
}
nsresult rv;
nsCOMPtr<nsIUTF8ConverterService>
cvtUTF8(do_GetService(NS_UTF8CONVERTERSERVICE_CONTRACTID, &rv));
nsAutoCString utf8Text;
if (NS_SUCCEEDED(rv)) {
// skip ASCIIness/UTF8ness test if aCharset is 7bit non-ascii charset.
rv = cvtUTF8->ConvertStringToUTF8(nsDependentCString(decodedText),
aCharset,
IS_7BIT_NON_ASCII_CHARSET(aCharset),
true, 1, utf8Text);
}
PR_Free(decodedText);
if (NS_FAILED(rv)) {
return rv;
}
aResult.Append(utf8Text);
return NS_OK;
}
static const char especials[] = "()<>@,;:\\\"/[]?.=";
// |decode_mime_part2_str| taken from comi18n.c
@ -1103,14 +1140,13 @@ nsresult DecodeRFC2047Str(const char *aHeader, const char *aDefaultCharset,
bool aOverrideCharset, nsACString &aResult)
{
const char *p, *q = nullptr, *r;
char *decodedText;
const char *begin; // tracking pointer for where we are in the input buffer
int32_t isLastEncodedWord = 0;
const char *charsetStart, *charsetEnd;
char charset[80];
// initialize charset name to an empty string
charset[0] = '\0';
nsAutoCString prevCharset, curCharset;
nsAutoCString encodedText;
char prevEncoding = '\0', curEncoding;
nsresult rv;
begin = aHeader;
@ -1155,15 +1191,9 @@ nsresult DecodeRFC2047Str(const char *aHeader, const char *aDefaultCharset,
charsetEnd = q;
}
// Check for too-long charset name
if (uint32_t(charsetEnd - charsetStart) >= sizeof(charset))
goto badsyntax;
memcpy(charset, charsetStart, charsetEnd - charsetStart);
charset[charsetEnd - charsetStart] = 0;
q++;
if (*q != 'Q' && *q != 'q' && *q != 'B' && *q != 'b')
curEncoding = nsCRT::ToUpper(*q);
if (curEncoding != 'Q' && curEncoding != 'B')
goto badsyntax;
if (q[1] != '?')
@ -1182,55 +1212,88 @@ nsresult DecodeRFC2047Str(const char *aHeader, const char *aDefaultCharset,
continue;
}
if(*q == 'Q' || *q == 'q')
decodedText = DecodeQ(q + 2, r - (q + 2));
else {
curCharset.Assign(charsetStart, charsetEnd - charsetStart);
// Override charset if requested. Never override labeled UTF-8.
// Use default charset instead of UNKNOWN-8BIT
if ((aOverrideCharset && 0 != nsCRT::strcasecmp(curCharset.get(), "UTF-8"))
|| (aDefaultCharset && 0 == nsCRT::strcasecmp(curCharset.get(), "UNKNOWN-8BIT"))
) {
curCharset = aDefaultCharset;
}
const char *R;
R = r;
if (curEncoding == 'B') {
// bug 227290. ignore an extraneous '=' at the end.
// (# of characters in B-encoded part has to be a multiple of 4)
int32_t n = r - (q + 2);
n -= (n % 4 == 1 && !PL_strncmp(r - 3, "===", 3)) ? 1 : 0;
decodedText = PL_Base64Decode(q + 2, n, nullptr);
R -= (n % 4 == 1 && !PL_strncmp(r - 3, "===", 3)) ? 1 : 0;
}
// Bug 493544. Don't decode the encoded text until it ends
if (R[-1] != '='
&& (prevCharset.IsEmpty()
|| (curCharset == prevCharset && curEncoding == prevEncoding))
) {
encodedText.Append(q + 2, R - (q + 2));
prevCharset = curCharset;
prevEncoding = curEncoding;
begin = r + 2;
isLastEncodedWord = 1;
continue;
}
if (decodedText == nullptr)
goto badsyntax;
// Override charset if requested. Never override labeled UTF-8.
// Use default charset instead of UNKNOWN-8BIT
if ((aOverrideCharset && 0 != nsCRT::strcasecmp(charset, "UTF-8")) ||
(aDefaultCharset && 0 == nsCRT::strcasecmp(charset, "UNKNOWN-8BIT"))) {
PL_strncpy(charset, aDefaultCharset, sizeof(charset) - 1);
charset[sizeof(charset) - 1] = '\0';
bool bDecoded; // If the current line has been decoded.
bDecoded = false;
if (!encodedText.IsEmpty()) {
if (curCharset == prevCharset && curEncoding == prevEncoding) {
encodedText.Append(q + 2, R - (q + 2));
bDecoded = true;
}
rv = DecodeQOrBase64Str(encodedText.get(), encodedText.Length(),
prevEncoding, prevCharset.get(), aResult);
if (NS_FAILED(rv)) {
aResult.Append(encodedText);
}
encodedText.Truncate();
prevCharset.Truncate();
}
{
nsCOMPtr<nsIUTF8ConverterService>
cvtUTF8(do_GetService(NS_UTF8CONVERTERSERVICE_CONTRACTID));
nsAutoCString utf8Text;
// skip ASCIIness/UTF8ness test if aCharset is 7bit non-ascii charset.
if (cvtUTF8 &&
NS_SUCCEEDED(
cvtUTF8->ConvertStringToUTF8(nsDependentCString(decodedText),
charset,
IS_7BIT_NON_ASCII_CHARSET(charset),
true, 1, utf8Text))) {
aResult.Append(utf8Text);
} else {
aResult.Append(REPLACEMENT_CHAR);
if (!bDecoded) {
rv = DecodeQOrBase64Str(q + 2, R - (q + 2), curEncoding,
curCharset.get(), aResult);
if (NS_FAILED(rv)) {
aResult.Append(encodedText);
}
}
PR_Free(decodedText);
begin = r + 2;
isLastEncodedWord = 1;
continue;
badsyntax:
if (!encodedText.IsEmpty()) {
rv = DecodeQOrBase64Str(encodedText.get(), encodedText.Length(),
prevEncoding, prevCharset.get(), aResult);
if (NS_FAILED(rv)) {
aResult.Append(encodedText);
}
encodedText.Truncate();
prevCharset.Truncate();
}
// copy the part before the encoded-word
aResult.Append(begin, p - begin);
begin = p;
isLastEncodedWord = 0;
}
if (!encodedText.IsEmpty()) {
rv = DecodeQOrBase64Str(encodedText.get(), encodedText.Length(),
prevEncoding, prevCharset.get(), aResult);
if (NS_FAILED(rv)) {
aResult.Append(encodedText);
}
}
// put the tail back
CopyRawHeader(begin, strlen(begin), aDefaultCharset, aResult);