Remove support for multiple cookies in one Set-Cookie header to follow RFC6265.

This also allows cookie values to contain commas to increase compatibility like
most popular browsers do even though the RFC still reserves them for future uses.

Reviewed-by: Peter Hartmann <peter.hartmann@nokia.com>
Task-number: QTBUG-21456
(cherry-picked from 8ba781b01e900148fec2e9d26485369b3295487f)

Change-Id: Ib09ab2411dddf7f99de1c0c31680428b7412fc7e
Reviewed-by: Shane Kearns <shane.kearns@accenture.com>
This commit is contained in:
Jocelyn Turcotte 2011-09-14 16:12:10 +02:00 committed by Qt by Nokia
parent e1402c0d27
commit 297a25cc4b
2 changed files with 20 additions and 52 deletions

View File

@ -386,7 +386,7 @@ static QPair<QByteArray, QByteArray> nextField(const QByteArray &text, int &posi
// parse the first part, before the equal sign
for (i = position; i < length; ++i) {
register char c = text.at(i);
if (c == ';' || c == ',' || c == '=')
if (c == ';' || c == '=')
break;
}
@ -437,7 +437,7 @@ static QPair<QByteArray, QByteArray> nextField(const QByteArray &text, int &posi
for ( ; i < length; ++i) {
register char c = text.at(i);
if (c == ',' || c == ';')
if (c == ';')
break;
}
position = i;
@ -448,7 +448,7 @@ static QPair<QByteArray, QByteArray> nextField(const QByteArray &text, int &posi
register char c = text.at(i);
// for name value pairs, we want to parse until reaching the next ';'
// and not break when reaching a space char
if (c == ',' || c == ';' || ((isNameValue && (c == '\n' || c == '\r')) || (!isNameValue && isLWS(c))))
if (c == ';' || ((isNameValue && (c == '\n' || c == '\r')) || (!isNameValue && isLWS(c))))
break;
}
@ -475,8 +475,7 @@ static QPair<QByteArray, QByteArray> nextField(const QByteArray &text, int &posi
\value Full makes toRawForm() return the full
cookie contents, as suitable for sending to a client in a
server's "Set-Cookie:" header. Multiple cookies are separated
by commas in a "Set-Cookie:" header.
server's "Set-Cookie:" header.
Note that only the Full form of the cookie can be parsed back into
its original contents.
@ -502,7 +501,6 @@ QByteArray QNetworkCookie::toRawForm(RawForm form) const
result = d->name;
result += '=';
if ((d->value.contains(';') ||
d->value.contains(',') ||
d->value.contains('"')) &&
(!d->value.startsWith('"') &&
!d->value.endsWith('"'))) {
@ -981,14 +979,8 @@ QList<QNetworkCookie> QNetworkCookiePrivate::parseSetCookieHeaderLine(const QByt
cookie.setValue(field.second);
position = nextNonWhitespace(cookieString, position);
bool endOfCookie = false;
while (!endOfCookie && position < length) {
while (position < length) {
switch (cookieString.at(position++)) {
case ',':
// end of the cookie
endOfCookie = true;
break;
case ';':
// new field in the cookie
field = nextField(cookieString, position, false);

View File

@ -181,6 +181,14 @@ void tst_QNetworkCookie::parseSingleCookie_data()
QTest::newRow("with-value-with-special4") << "a = \"\\\"\" " << cookie;
cookie.setValue("\"\\\"a, b; c\\\"\"");
QTest::newRow("with-value-with-special5") << "a = \"\\\"a, b; c\\\"\"" << cookie;
// RFC6265 states that cookie values shouldn't contain commas, but we still allow them
// since they are only reserved for future compatibility and other browsers do the same.
cookie.setValue(",");
QTest::newRow("with-value-with-special6") << "a = ," << cookie;
cookie.setValue(",b");
QTest::newRow("with-value-with-special7") << "a = ,b" << cookie;
cookie.setValue("b,");
QTest::newRow("with-value-with-special8") << "a = b," << cookie;
cookie.setValue("b c");
QTest::newRow("with-value-with-whitespace") << "a = b c" << cookie;
@ -599,7 +607,6 @@ void tst_QNetworkCookie::parseSingleCookie()
//QEXPECT_FAIL("network2", "QDateTime parsing problem: the date is beyond year 8000", Abort);
QCOMPARE(result.count(), 1);
QEXPECT_FAIL("network3", "Cookie value contains commas, violating the HTTP spec", Abort);
QCOMPARE(result.at(0), expectedCookie);
result = QNetworkCookie::parseCookies(result.at(0).toRawForm());
@ -634,48 +641,17 @@ void tst_QNetworkCookie::parseMultipleCookies_data()
// reason: malformed NAME=VALUE pair
QTest::newRow("invalid-05") << "foo" << list;
QTest::newRow("invalid-06") << "=b" << list;
QTest::newRow("invalid-09") << "foo,a=b" << list;
QTest::newRow("invalid-11") << ";path=/" << list;
QTest::newRow("invalid-07") << ";path=/" << list;
// reason: malformed expiration date string
QTest::newRow("invalid-12") << "a=b;expires=" << list;
QTest::newRow("invalid-13") << "a=b;expires=foobar" << list;
QTest::newRow("invalid-14") << "a=b;expires=foobar, abc" << list;
QTest::newRow("invalid-15") << "a=b;expires=foobar, dd-mmm-yyyy hh:mm:ss GMT; path=/" << list;
QTest::newRow("invalid-16") << "a=b;expires=foobar, 32-Caz-1999 24:01:60 GMT; path=/" << list;
QNetworkCookie cookie;
cookie.setName("a");
list += cookie;
cookie.setName("c");
cookie.setValue("d");
list += cookie;
QTest::newRow("two-1") << "a=,c=d" << list;
QTest::newRow("two-2") << "a=, c=d" << list;
QTest::newRow("two-3") << "a= ,c=d" << list;
QTest::newRow("two-4") << "a= , c=d" << list;
list.clear();
list += cookie;
cookie.setName("a");
cookie.setValue(QByteArray());
list += cookie;
QTest::newRow("two-5") << "c=d,a=" << list;
QTest::newRow("two-6") << "c=d, a=" << list;
QTest::newRow("two-7") << "c=d , a=" << list;
cookie.setName("foo");
cookie.setValue("bar");
cookie.setPath("/");
list += cookie;
QTest::newRow("complex-1") << "c=d, a=, foo=bar; path=/" << list;
cookie.setName("baz");
cookie.setDomain(".qt.nokia.com");
list.prepend(cookie);
QTest::newRow("complex-2") << "baz=bar; path=/; domain=.qt.nokia.com, c=d,a=,foo=bar; path=/" << list;
QTest::newRow("invalid-08") << "a=b;expires=" << list;
QTest::newRow("invalid-09") << "a=b;expires=foobar" << list;
QTest::newRow("invalid-10") << "a=b;expires=foobar, abc" << list;
QTest::newRow("invalid-11") << "a=b;expires=foobar, dd-mmm-yyyy hh:mm:ss GMT; path=/" << list;
QTest::newRow("invalid-12") << "a=b;expires=foobar, 32-Caz-1999 24:01:60 GMT; path=/" << list;
// cookies obtained from the network:
QNetworkCookie cookie;
cookie = QNetworkCookie("id", "51706646077999719");
cookie.setDomain(".bluestreak.com");
cookie.setPath("/");