mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 20:05:49 +00:00
Bug 493544 - Don't decode the encoded text until it ends. r=smontagu
This commit is contained in:
parent
53a5112fb0
commit
ecdc94030a
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user