зеркало из https://github.com/mozilla/pjs.git
Backed out changeset cd5ac132e763
This commit is contained in:
Родитель
6e8cb9e4a8
Коммит
a8eaf5a43f
|
@ -169,136 +169,6 @@ void RemoveQuotedStringEscapes(char *src)
|
|||
*dst = 0;
|
||||
}
|
||||
|
||||
// Support for continuations (RFC 2231, Section 3)
|
||||
|
||||
// only a sane number supported
|
||||
#define MAX_CONTINUATIONS 999
|
||||
|
||||
// part of a continuation
|
||||
|
||||
class Continuation {
|
||||
public:
|
||||
Continuation(const char *aValue, PRUint32 aLength,
|
||||
bool aNeedsPercentDecoding) {
|
||||
value = aValue;
|
||||
length = aLength;
|
||||
needsPercentDecoding = aNeedsPercentDecoding;
|
||||
}
|
||||
Continuation() {
|
||||
// empty constructor needed for nsTArray
|
||||
value = 0L;
|
||||
length = 0;
|
||||
needsPercentDecoding = false;
|
||||
}
|
||||
~Continuation() {}
|
||||
|
||||
const char *value;
|
||||
PRUint32 length;
|
||||
bool needsPercentDecoding;
|
||||
};
|
||||
|
||||
// combine segments into a single string, returning the allocated string
|
||||
// (or NULL) while emptying the list
|
||||
char *combineContinuations(nsTArray<Continuation>& aArray)
|
||||
{
|
||||
// Sanity check
|
||||
if (aArray.Length() == 0)
|
||||
return NULL;
|
||||
|
||||
// Get an upper bound for the length
|
||||
PRUint32 length = 0;
|
||||
for (PRUint32 i = 0; i < aArray.Length(); i++) {
|
||||
length += aArray[i].length;
|
||||
}
|
||||
|
||||
// Allocate
|
||||
char *result = (char *) nsMemory::Alloc(length + 1);
|
||||
|
||||
// Concatenate
|
||||
if (result) {
|
||||
*result = '\0';
|
||||
|
||||
for (PRUint32 i = 0; i < aArray.Length(); i++) {
|
||||
Continuation cont = aArray[i];
|
||||
if (! cont.value) break;
|
||||
|
||||
char *c = result + strlen(result);
|
||||
strncat(result, cont.value, cont.length);
|
||||
if (cont.needsPercentDecoding) {
|
||||
nsUnescape(c);
|
||||
}
|
||||
}
|
||||
|
||||
// return null if empty value
|
||||
if (*result == '\0') {
|
||||
nsMemory::Free(result);
|
||||
result = NULL;
|
||||
}
|
||||
} else {
|
||||
// Handle OOM
|
||||
NS_WARNING("Out of memory\n");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// add a continuation, return false on error if segment already has been seen
|
||||
bool addContinuation(nsTArray<Continuation>& aArray, PRUint32 aIndex,
|
||||
const char *aValue, PRUint32 aLength,
|
||||
bool aNeedsPercentDecoding)
|
||||
{
|
||||
if (aIndex < aArray.Length() && aArray[aIndex].value) {
|
||||
NS_WARNING("duplicate RC2231 continuation segment #\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aIndex > MAX_CONTINUATIONS) {
|
||||
NS_WARNING("RC2231 continuation segment # exceeds limit\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
Continuation cont (aValue, aLength, aNeedsPercentDecoding);
|
||||
|
||||
if (aArray.Length() <= aIndex) {
|
||||
aArray.SetLength(aIndex + 1);
|
||||
}
|
||||
aArray[aIndex] = cont;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// parse a segment number; return -1 on error
|
||||
PRInt32 parseSegmentNumber(const char *aValue, PRInt32 aLen)
|
||||
{
|
||||
if (aLen < 1) {
|
||||
NS_WARNING("segment number missing\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (aLen > 1 && aValue[0] == '0') {
|
||||
NS_WARNING("leading '0' not allowed in segment number\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
PRInt32 segmentNumber = 0;
|
||||
|
||||
for (PRInt32 i = 0; i < aLen; i++) {
|
||||
if (! (aValue[i] >= '0' && aValue[i] <= '9')) {
|
||||
NS_WARNING("invalid characters in segment number\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
segmentNumber *= 10;
|
||||
segmentNumber += aValue[i] - '0';
|
||||
if (segmentNumber > MAX_CONTINUATIONS) {
|
||||
NS_WARNING("Segment number exceeds sane size\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return segmentNumber;
|
||||
}
|
||||
|
||||
// moved almost verbatim from mimehdrs.cpp
|
||||
// char *
|
||||
// MimeHeaders_get_parameter (const char *header_value, const char *parm_name,
|
||||
|
@ -335,10 +205,6 @@ nsMIMEHeaderParamImpl::DoParameterInternal(const char *aHeaderValue,
|
|||
if (aCharset) *aCharset = nsnull;
|
||||
if (aLang) *aLang = nsnull;
|
||||
|
||||
nsCAutoString charset;
|
||||
|
||||
bool acceptContinuations = (aDecoding != RFC_5987_DECODING);
|
||||
|
||||
const char *str = aHeaderValue;
|
||||
|
||||
// skip leading white space.
|
||||
|
@ -389,52 +255,37 @@ nsMIMEHeaderParamImpl::DoParameterInternal(const char *aHeaderValue,
|
|||
// title*1="There is no charset and lang info."
|
||||
// RFC5987: only A and B
|
||||
|
||||
// collect results for the different algorithms (plain filename,
|
||||
// RFC5987/2231-encoded filename, + continuations) separately and decide
|
||||
// which to use at the end
|
||||
char *caseAResult = NULL;
|
||||
char *caseBResult = NULL;
|
||||
char *caseCDResult = NULL;
|
||||
|
||||
// collect continuation segments
|
||||
nsTArray<Continuation> segments;
|
||||
|
||||
|
||||
// our copies of the charset parameter, kept separately as they might
|
||||
// differ for the two formats
|
||||
nsDependentCSubstring charsetB, charsetCD;
|
||||
|
||||
nsDependentCSubstring lang;
|
||||
|
||||
PRInt32 paramLen = strlen(aParamName);
|
||||
|
||||
while (*str) {
|
||||
// find name/value
|
||||
bool haveCaseAValue = false;
|
||||
PRInt32 nextContinuation = 0; // next value in series, or -1 if error
|
||||
|
||||
const char *nameStart = str;
|
||||
const char *nameEnd = NULL;
|
||||
while (*str) {
|
||||
const char *tokenStart = str;
|
||||
const char *tokenEnd = 0;
|
||||
const char *valueStart = str;
|
||||
const char *valueEnd = NULL;
|
||||
bool isQuotedString = false;
|
||||
const char *valueEnd = 0;
|
||||
bool seenEquals = false;
|
||||
|
||||
NS_ASSERTION(!nsCRT::IsAsciiSpace(*str), "should be after whitespace.");
|
||||
|
||||
// Skip forward to the end of this token.
|
||||
for (; *str && !nsCRT::IsAsciiSpace(*str) && *str != '=' && *str != ';'; str++)
|
||||
;
|
||||
nameEnd = str;
|
||||
|
||||
PRInt32 nameLen = nameEnd - nameStart;
|
||||
tokenEnd = str;
|
||||
|
||||
// Skip over whitespace, '=', and whitespace
|
||||
while (nsCRT::IsAsciiSpace(*str)) ++str;
|
||||
if (*str++ != '=') {
|
||||
// don't accept parameters without "="
|
||||
goto increment_str;
|
||||
if (*str == '=') {
|
||||
++str;
|
||||
seenEquals = true;
|
||||
}
|
||||
while (nsCRT::IsAsciiSpace(*str)) ++str;
|
||||
|
||||
if (*str != '"') {
|
||||
bool needUnquote = false;
|
||||
|
||||
if (*str != '"')
|
||||
{
|
||||
// The value is a token, not a quoted string.
|
||||
valueStart = str;
|
||||
for (valueEnd = str;
|
||||
|
@ -442,12 +293,16 @@ nsMIMEHeaderParamImpl::DoParameterInternal(const char *aHeaderValue,
|
|||
valueEnd++)
|
||||
;
|
||||
str = valueEnd;
|
||||
} else {
|
||||
isQuotedString = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The value is a quoted string.
|
||||
needUnquote = true;
|
||||
|
||||
++str;
|
||||
valueStart = str;
|
||||
for (valueEnd = str; *valueEnd; ++valueEnd) {
|
||||
for (valueEnd = str; *valueEnd; ++valueEnd)
|
||||
{
|
||||
if (*valueEnd == '\\')
|
||||
++valueEnd;
|
||||
else if (*valueEnd == '"')
|
||||
|
@ -462,14 +317,16 @@ nsMIMEHeaderParamImpl::DoParameterInternal(const char *aHeaderValue,
|
|||
// See if this is the simplest case (case A above),
|
||||
// a 'single' line value with no charset and lang.
|
||||
// If so, copy it and return.
|
||||
if (nameLen == paramLen &&
|
||||
!nsCRT::strncasecmp(nameStart, aParamName, paramLen)) {
|
||||
|
||||
if (caseAResult) {
|
||||
// we already have one caseA result, ignore subsequent ones
|
||||
if (tokenEnd - tokenStart == paramLen &&
|
||||
seenEquals &&
|
||||
!nsCRT::strncasecmp(tokenStart, aParamName, paramLen))
|
||||
{
|
||||
if (*aResult)
|
||||
{
|
||||
// either seen earlier caseA value already--we prefer first--or caseA
|
||||
// came after a continuation: either way, prefer other value
|
||||
goto increment_str;
|
||||
}
|
||||
|
||||
// if the parameter spans across multiple lines we have to strip out the
|
||||
// line continuation -- jht 4/29/98
|
||||
nsCAutoString tempStr(valueStart, valueEnd - valueStart);
|
||||
|
@ -477,131 +334,144 @@ nsMIMEHeaderParamImpl::DoParameterInternal(const char *aHeaderValue,
|
|||
char *res = ToNewCString(tempStr);
|
||||
NS_ENSURE_TRUE(res, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
if (isQuotedString)
|
||||
if (needUnquote)
|
||||
RemoveQuotedStringEscapes(res);
|
||||
|
||||
caseAResult = res;
|
||||
|
||||
*aResult = res;
|
||||
|
||||
haveCaseAValue = true;
|
||||
// keep going, we may find a RFC 2231/5987 encoded alternative
|
||||
}
|
||||
// case B, C, and D
|
||||
else if (nameLen > paramLen &&
|
||||
!nsCRT::strncasecmp(nameStart, aParamName, paramLen) &&
|
||||
*(nameStart + paramLen) == '*') {
|
||||
|
||||
// 1st char past '*'
|
||||
const char *cp = nameStart + paramLen + 1;
|
||||
|
||||
// if param name ends in "*" we need do to RFC5987 "ext-value" decoding
|
||||
bool needExtDecoding = *(nameEnd - 1) == '*';
|
||||
|
||||
bool caseB = nameLen == paramLen + 1;
|
||||
bool caseCStart = (*cp == '0') && needExtDecoding;
|
||||
|
||||
// parse the segment number
|
||||
PRInt32 segmentNumber = -1;
|
||||
if (!caseB) {
|
||||
PRInt32 segLen = (nameEnd - cp) - (needExtDecoding ? 1 : 0);
|
||||
segmentNumber = parseSegmentNumber(cp, segLen);
|
||||
|
||||
if (segmentNumber == -1) {
|
||||
acceptContinuations = false;
|
||||
goto increment_str;
|
||||
}
|
||||
}
|
||||
else if (tokenEnd - tokenStart > paramLen &&
|
||||
!nsCRT::strncasecmp(tokenStart, aParamName, paramLen) &&
|
||||
seenEquals &&
|
||||
*(tokenStart + paramLen) == '*')
|
||||
{
|
||||
const char *cp = tokenStart + paramLen + 1; // 1st char past '*'
|
||||
bool needUnescape = *(tokenEnd - 1) == '*';
|
||||
|
||||
bool caseB = (tokenEnd - tokenStart) == paramLen + 1;
|
||||
bool caseCorDStart = (*cp == '0') && needUnescape;
|
||||
bool acceptContinuations = (aDecoding != RFC_5987_DECODING);
|
||||
|
||||
// CaseB and start of CaseC: requires charset and optional language
|
||||
// in quotes (quotes required even if lang is blank)
|
||||
if (caseB || (caseCStart && acceptContinuations)) {
|
||||
if (caseB || (caseCorDStart && acceptContinuations))
|
||||
{
|
||||
if (caseCorDStart) {
|
||||
if (nextContinuation++ != 0)
|
||||
{
|
||||
// error: already started a continuation. Skip future
|
||||
// continuations and return whatever initial parts were in order.
|
||||
nextContinuation = -1;
|
||||
goto increment_str;
|
||||
}
|
||||
}
|
||||
// look for single quotation mark(')
|
||||
const char *sQuote1 = PL_strchr(valueStart, 0x27);
|
||||
const char *sQuote2 = sQuote1 ? PL_strchr(sQuote1 + 1, 0x27) : nsnull;
|
||||
const char *sQuote2 = (char *) (sQuote1 ? PL_strchr(sQuote1 + 1, 0x27) : nsnull);
|
||||
|
||||
// Two single quotation marks must be present even in
|
||||
// absence of charset and lang.
|
||||
if (!sQuote1 || !sQuote2) {
|
||||
if (!sQuote1 || !sQuote2)
|
||||
NS_WARNING("Mandatory two single quotes are missing in header parameter\n");
|
||||
if (aCharset && sQuote1 > valueStart && sQuote1 < valueEnd)
|
||||
{
|
||||
*aCharset = (char *) nsMemory::Clone(valueStart, sQuote1 - valueStart + 1);
|
||||
if (*aCharset)
|
||||
*(*aCharset + (sQuote1 - valueStart)) = 0;
|
||||
}
|
||||
if (aLang && sQuote1 && sQuote2 && sQuote2 > sQuote1 + 1 &&
|
||||
sQuote2 < valueEnd)
|
||||
{
|
||||
*aLang = (char *) nsMemory::Clone(sQuote1 + 1, sQuote2 - (sQuote1 + 1) + 1);
|
||||
if (*aLang)
|
||||
*(*aLang + (sQuote2 - (sQuote1 + 1))) = 0;
|
||||
}
|
||||
|
||||
const char *charsetStart = NULL;
|
||||
PRInt32 charsetLength = 0;
|
||||
const char *langStart = NULL;
|
||||
PRInt32 langLength = 0;
|
||||
const char *rawValStart = NULL;
|
||||
PRInt32 rawValLength = 0;
|
||||
|
||||
if (sQuote2 && sQuote1) {
|
||||
// both delimiters present: charSet'lang'rawVal
|
||||
rawValStart = sQuote2 + 1;
|
||||
rawValLength = valueEnd - rawValStart;
|
||||
|
||||
langStart = sQuote1 + 1;
|
||||
langLength = sQuote2 - langStart;
|
||||
|
||||
charsetStart = valueStart;
|
||||
charsetLength = sQuote1 - charsetStart;
|
||||
// Be generous and handle gracefully when required
|
||||
// single quotes are absent.
|
||||
if (sQuote1)
|
||||
{
|
||||
if(!sQuote2)
|
||||
sQuote2 = sQuote1;
|
||||
}
|
||||
else if (sQuote1) {
|
||||
// one delimiter; assume charset'rawVal
|
||||
rawValStart = sQuote1 + 1;
|
||||
rawValLength = valueEnd - rawValStart;
|
||||
else
|
||||
sQuote2 = valueStart - 1;
|
||||
|
||||
charsetStart = valueStart;
|
||||
charsetLength = sQuote1 - valueStart;
|
||||
}
|
||||
else {
|
||||
// no delimiter: just rawVal
|
||||
rawValStart = valueStart;
|
||||
rawValLength = valueEnd - valueStart;
|
||||
}
|
||||
|
||||
if (langLength != 0) {
|
||||
lang.Assign(langStart, langLength);
|
||||
}
|
||||
|
||||
// keep the charset for later
|
||||
if (caseB) {
|
||||
charsetB.Assign(charsetStart, charsetLength);
|
||||
} else {
|
||||
// if caseCorD
|
||||
charsetCD.Assign(charsetStart, charsetLength);
|
||||
}
|
||||
|
||||
// non-empty value part
|
||||
if (rawValLength > 0) {
|
||||
if (!caseBResult && caseB) {
|
||||
// allocate buffer for the raw value
|
||||
char *tmpResult = (char *) nsMemory::Clone(rawValStart, rawValLength + 1);
|
||||
if (!tmpResult) {
|
||||
goto increment_str;
|
||||
}
|
||||
*(tmpResult + rawValLength) = 0;
|
||||
|
||||
nsUnescape(tmpResult);
|
||||
caseBResult = tmpResult;
|
||||
} else {
|
||||
// caseC
|
||||
bool added = addContinuation(segments, 0, rawValStart,
|
||||
rawValLength, needExtDecoding);
|
||||
|
||||
if (!added) {
|
||||
// continuation not added, stop processing them
|
||||
acceptContinuations = false;
|
||||
if (sQuote2 && sQuote2 + 1 < valueEnd)
|
||||
{
|
||||
if (*aResult)
|
||||
{
|
||||
// caseA value already read, or caseC/D value already read
|
||||
// but we're now reading caseB: either way, drop old value
|
||||
nsMemory::Free(*aResult);
|
||||
haveCaseAValue = false;
|
||||
}
|
||||
*aResult = (char *) nsMemory::Alloc(valueEnd - (sQuote2 + 1) + 1);
|
||||
if (*aResult)
|
||||
{
|
||||
memcpy(*aResult, sQuote2 + 1, valueEnd - (sQuote2 + 1));
|
||||
*(*aResult + (valueEnd - (sQuote2 + 1))) = 0;
|
||||
if (needUnescape)
|
||||
{
|
||||
nsUnescape(*aResult);
|
||||
if (caseB)
|
||||
return NS_OK; // caseB wins over everything else
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end of if-block : title*0*= or title*=
|
||||
// caseD: a line of multiline param with no need for unescaping : title*[0-9]=
|
||||
// or 2nd or later lines of a caseC param : title*[1-9]*=
|
||||
else if (acceptContinuations && segmentNumber != -1) {
|
||||
PRUint32 valueLength = valueEnd - valueStart;
|
||||
|
||||
bool added = addContinuation(segments, segmentNumber, valueStart,
|
||||
valueLength, needExtDecoding);
|
||||
|
||||
if (!added) {
|
||||
// continuation not added, stop processing them
|
||||
acceptContinuations = false;
|
||||
else if (acceptContinuations && nsCRT::IsAsciiDigit(PRUnichar(*cp)))
|
||||
{
|
||||
PRInt32 nextSegment = atoi(cp);
|
||||
// no leading zeros allowed except for ... position 0
|
||||
bool broken = nextSegment > 0 && *cp == '0';
|
||||
|
||||
if (broken || nextSegment != nextContinuation++)
|
||||
{
|
||||
// error: gap in continuation or unneccessary leading 0.
|
||||
// Skip future continuations and return whatever initial parts were
|
||||
// in order.
|
||||
nextContinuation = -1;
|
||||
goto increment_str;
|
||||
}
|
||||
if (haveCaseAValue && *aResult)
|
||||
{
|
||||
// drop caseA value
|
||||
nsMemory::Free(*aResult);
|
||||
*aResult = 0;
|
||||
haveCaseAValue = false;
|
||||
}
|
||||
PRInt32 len = 0;
|
||||
if (*aResult) // 2nd or later lines of multiline parameter
|
||||
{
|
||||
len = strlen(*aResult);
|
||||
char *ns = (char *) nsMemory::Realloc(*aResult, len + (valueEnd - valueStart) + 1);
|
||||
if (!ns)
|
||||
{
|
||||
nsMemory::Free(*aResult);
|
||||
}
|
||||
*aResult = ns;
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_ASSERTION(*cp == '0', "Not first value in continuation"); // must be; 1st line : title*0=
|
||||
*aResult = (char *) nsMemory::Alloc(valueEnd - valueStart + 1);
|
||||
}
|
||||
if (*aResult)
|
||||
{
|
||||
// append a partial value
|
||||
memcpy(*aResult + len, valueStart, valueEnd - valueStart);
|
||||
*(*aResult + len + (valueEnd - valueStart)) = 0;
|
||||
if (needUnescape)
|
||||
nsUnescape(*aResult + len);
|
||||
}
|
||||
else
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
} // end of if-block : title*[0-9]= or title*[1-9]*=
|
||||
}
|
||||
|
||||
|
@ -613,50 +483,10 @@ increment_str:
|
|||
while (nsCRT::IsAsciiSpace(*str)) ++str;
|
||||
}
|
||||
|
||||
caseCDResult = combineContinuations(segments);
|
||||
|
||||
if (caseBResult) {
|
||||
// prefer simple 5987 format over 2231 with continuations
|
||||
*aResult = caseBResult;
|
||||
caseBResult = NULL;
|
||||
charset.Assign(charsetB);
|
||||
}
|
||||
else if (caseCDResult) {
|
||||
// prefer 2231/5987 with or without continuations over plain format
|
||||
*aResult = caseCDResult;
|
||||
caseCDResult = NULL;
|
||||
charset.Assign(charsetCD);
|
||||
}
|
||||
else if (caseAResult) {
|
||||
*aResult = caseAResult;
|
||||
caseAResult = NULL;
|
||||
}
|
||||
|
||||
// free unused stuff
|
||||
nsMemory::Free(caseAResult);
|
||||
nsMemory::Free(caseBResult);
|
||||
nsMemory::Free(caseCDResult);
|
||||
|
||||
// if we have a result
|
||||
if (*aResult) {
|
||||
// then return charset and lang as well
|
||||
if (aLang && !lang.IsEmpty()) {
|
||||
PRUint32 len = lang.Length();
|
||||
*aLang = (char *) nsMemory::Clone(lang.BeginReading(), len + 1);
|
||||
if (*aLang) {
|
||||
*(*aLang + len) = 0;
|
||||
}
|
||||
}
|
||||
if (aCharset && !charset.IsEmpty()) {
|
||||
PRUint32 len = charset.Length();
|
||||
*aCharset = (char *) nsMemory::Clone(charset.BeginReading(), len + 1);
|
||||
if (*aCharset) {
|
||||
*(*aCharset + len) = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return *aResult ? NS_OK : NS_ERROR_INVALID_ARG;
|
||||
if (*aResult)
|
||||
return NS_OK;
|
||||
else
|
||||
return NS_ERROR_INVALID_ARG; // aParameter not found !!
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -96,16 +96,16 @@ var tests = [
|
|||
"attachment", Cr.NS_ERROR_INVALID_ARG],
|
||||
|
||||
// continuations should prevail over non-extended (unless RFC 5987)
|
||||
["attachment; filename=basic; filename*0*=UTF-8''multi;\r\n"
|
||||
+ " filename*1=line;\r\n"
|
||||
["attachment; filename=basic; filename*0*=UTF-8''multi\r\n"
|
||||
+ " filename*1=line\r\n"
|
||||
+ " filename*2*=%20extended",
|
||||
"attachment", "multiline extended",
|
||||
"attachment", "basic"],
|
||||
|
||||
// Gaps should result in returning only value until gap hit
|
||||
// (invalid; error recovery)
|
||||
["attachment; filename=basic; filename*0*=UTF-8''multi;\r\n"
|
||||
+ " filename*1=line;\r\n"
|
||||
["attachment; filename=basic; filename*0*=UTF-8''multi\r\n"
|
||||
+ " filename*1=line\r\n"
|
||||
+ " filename*3*=%20extended",
|
||||
"attachment", "multiline",
|
||||
"attachment", "basic"],
|
||||
|
@ -113,60 +113,68 @@ var tests = [
|
|||
// First series, only please, and don't slurp up higher elements (*2 in this
|
||||
// case) from later series into earlier one (invalid; error recovery)
|
||||
["attachment; filename=basic; filename*0*=UTF-8''multi\r\n"
|
||||
+ " filename*1=line;\r\n"
|
||||
+ " filename*0*=UTF-8''wrong;\r\n"
|
||||
+ " filename*1=bad;\r\n"
|
||||
+ " filename*1=line\r\n"
|
||||
+ " filename*0*=UTF-8''wrong\r\n"
|
||||
+ " filename*1=bad\r\n"
|
||||
+ " filename*2=evil",
|
||||
"attachment", "multiline",
|
||||
"attachment", "basic"],
|
||||
|
||||
// RFC 2231 not clear on correct outcome: we prefer non-continued extended
|
||||
// (invalid; error recovery)
|
||||
["attachment; filename=basic; filename*0=UTF-8''multi\r\n;"
|
||||
+ " filename*=UTF-8''extended;\r\n"
|
||||
+ " filename*1=line;\r\n"
|
||||
["attachment; filename=basic; filename*0=UTF-8''multi\r\n"
|
||||
+ " filename*=UTF-8''extended\r\n"
|
||||
+ " filename*1=line\r\n"
|
||||
+ " filename*2*=%20extended",
|
||||
"attachment", "extended"],
|
||||
|
||||
// sneaky: if unescaped, make sure we leave UTF-8'' in value
|
||||
["attachment; filename*0=UTF-8''unescaped;\r\n"
|
||||
["attachment; filename*0=UTF-8''unescaped\r\n"
|
||||
+ " filename*1*=%20so%20includes%20UTF-8''%20in%20value",
|
||||
"attachment", "UTF-8''unescaped so includes UTF-8'' in value",
|
||||
"attachment", Cr.NS_ERROR_INVALID_ARG],
|
||||
|
||||
// sneaky: if unescaped, make sure we leave UTF-8'' in value
|
||||
["attachment; filename=basic; filename*0=UTF-8''unescaped;\r\n"
|
||||
["attachment; filename=basic; filename*0=UTF-8''unescaped\r\n"
|
||||
+ " filename*1*=%20so%20includes%20UTF-8''%20in%20value",
|
||||
"attachment", "UTF-8''unescaped so includes UTF-8'' in value",
|
||||
"attachment", "basic"],
|
||||
|
||||
// Prefer basic over invalid continuation
|
||||
// (invalid; error recovery)
|
||||
["attachment; filename=basic; filename*1=multi;\r\n"
|
||||
+ " filename*2=line;\r\n"
|
||||
["attachment; filename=basic; filename*1=multi\r\n"
|
||||
+ " filename*2=line\r\n"
|
||||
+ " filename*3*=%20extended",
|
||||
"attachment", "basic"],
|
||||
|
||||
// support digits over 10
|
||||
["attachment; filename=basic; filename*0*=UTF-8''0;\r\n"
|
||||
+ " filename*1=1; filename*2=2;filename*3=3;filename*4=4;filename*5=5;\r\n"
|
||||
+ " filename*6=6; filename*7=7;filename*8=8;filename*9=9;filename*10=a;\r\n"
|
||||
["attachment; filename=basic; filename*0*=UTF-8''0\r\n"
|
||||
+ " filename*1=1; filename*2=2;filename*3=3;filename*4=4;filename*5=5\r\n"
|
||||
+ " filename*6=6; filename*7=7;filename*8=8;filename*9=9;filename*10=a\r\n"
|
||||
+ " filename*11=b; filename*12=c;filename*13=d;filename*14=e;filename*15=f\r\n",
|
||||
"attachment", "0123456789abcdef",
|
||||
"attachment", "basic"],
|
||||
|
||||
// support digits over 10 (check ordering)
|
||||
["attachment; filename=basic; filename*0*=UTF-8''0\r\n"
|
||||
+ " filename*1=1; filename*2=2;filename*3=3;filename*4=4;filename*5=5\r\n"
|
||||
+ " filename*6=6; filename*7=7;filename*8=8;filename*9=9;filename*10=a\r\n"
|
||||
+ " filename*11=b; filename*12=c;filename*13=d;filename*15=f;filename*14=e\r\n",
|
||||
"attachment", "0123456789abcd" /* should see the 'f', see bug 588414 */,
|
||||
"attachment", "basic"],
|
||||
|
||||
// support digits over 10 (detect gaps)
|
||||
["attachment; filename=basic; filename*0*=UTF-8''0;\r\n"
|
||||
+ " filename*1=1; filename*2=2;filename*3=3;filename*4=4;filename*5=5;\r\n"
|
||||
+ " filename*6=6; filename*7=7;filename*8=8;filename*9=9;filename*10=a;\r\n"
|
||||
["attachment; filename=basic; filename*0*=UTF-8''0\r\n"
|
||||
+ " filename*1=1; filename*2=2;filename*3=3;filename*4=4;filename*5=5\r\n"
|
||||
+ " filename*6=6; filename*7=7;filename*8=8;filename*9=9;filename*10=a\r\n"
|
||||
+ " filename*11=b; filename*12=c;filename*14=e\r\n",
|
||||
"attachment", "0123456789abc",
|
||||
"attachment", "basic"],
|
||||
|
||||
// return nothing: invalid
|
||||
// (invalid; error recovery)
|
||||
["attachment; filename*1=multi;\r\n"
|
||||
+ " filename*2=line;\r\n"
|
||||
["attachment; filename*1=multi\r\n"
|
||||
+ " filename*2=line\r\n"
|
||||
+ " filename*3*=%20extended",
|
||||
"attachment", Cr.NS_ERROR_INVALID_ARG],
|
||||
|
||||
|
@ -187,53 +195,6 @@ var tests = [
|
|||
"filename=foo.html", "foo.html",
|
||||
"filename=foo.html", "foo.html"],
|
||||
|
||||
// Bug 384571: RFC 2231 parameters not decoded when appearing in reversed order
|
||||
|
||||
// check ordering
|
||||
["attachment; filename=basic; filename*0*=UTF-8''0;\r\n"
|
||||
+ " filename*1=1; filename*2=2;filename*3=3;filename*4=4;filename*5=5;\r\n"
|
||||
+ " filename*6=6; filename*7=7;filename*8=8;filename*9=9;filename*10=a;\r\n"
|
||||
+ " filename*11=b; filename*12=c;filename*13=d;filename*15=f;filename*14=e;\r\n",
|
||||
"attachment", "0123456789abcdef",
|
||||
"attachment", "basic"],
|
||||
|
||||
// check non-digits in sequence numbers
|
||||
["attachment; filename=basic; filename*0*=UTF-8''0;\r\n"
|
||||
+ " filename*1a=1\r\n",
|
||||
"attachment", "0",
|
||||
"attachment", "basic"],
|
||||
|
||||
// check duplicate sequence numbers
|
||||
["attachment; filename=basic; filename*0*=UTF-8''0;\r\n"
|
||||
+ " filename*0=bad; filename*1=1\;r\n",
|
||||
"attachment", "0",
|
||||
"attachment", "basic"],
|
||||
|
||||
// check overflow
|
||||
["attachment; filename=basic; filename*0*=UTF-8''0;\r\n"
|
||||
+ " filename*11111111111111111111111111111111111111111111111111111111111=1",
|
||||
"attachment", "0",
|
||||
"attachment", "basic"],
|
||||
|
||||
// check underflow
|
||||
["attachment; filename=basic; filename*0*=UTF-8''0;\r\n"
|
||||
+ " filename*-1=1",
|
||||
"attachment", "0",
|
||||
"attachment", "basic"],
|
||||
|
||||
// check mixed token/quoted-string
|
||||
["attachment; filename=basic; filename*0=\"0\";\r\n"
|
||||
+ " filename*1=1;\r\n"
|
||||
+ " filename*2*=%32",
|
||||
"attachment", "012",
|
||||
"attachment", "basic"],
|
||||
|
||||
// check empty sequence number
|
||||
["attachment; filename=basic; filename**=UTF-8''0\r\n",
|
||||
"attachment", "basic",
|
||||
"attachment", "basic"],
|
||||
|
||||
|
||||
// Bug 419157: ensure that a MIME parameter with no charset information
|
||||
// fallbacks to Latin-1
|
||||
|
||||
|
@ -340,12 +301,6 @@ var tests = [
|
|||
|
||||
["attachment; filename=\"",
|
||||
"attachment", ""],
|
||||
|
||||
// Bug 732369: Content-Disposition parser does not require presence of ";" between params
|
||||
|
||||
["attachment; extension=bla filename=foo",
|
||||
"attachment", "foo"],
|
||||
|
||||
];
|
||||
|
||||
function do_tests(whichRFC)
|
||||
|
|
Загрузка…
Ссылка в новой задаче