Use RFC6265 rules for cookie path & path matching
Url encoding of paths is no longer used. This matches the current release behaviour of Firefox, Chrome and MSIE browsers. RFC6265 does not allow this type of encoding. This fixes remaining path test cases in the IETF test suite. Currently the path0027 test is passed by Firefox but failed by Chrome and MSIE, so there is a potential compatibility issue. However it is a corner case with a malformed cookie. Task-number: QTBUG-15794 Change-Id: I9b02bb5adc32d614f512d314d06f2c60894aa2b0 Reviewed-by: Richard J. Moore <rich@kde.org>
This commit is contained in:
parent
d76bd0d735
commit
058fddd1c0
@ -466,7 +466,7 @@ QByteArray QNetworkCookie::toRawForm(RawForm form) const
|
||||
}
|
||||
if (!d->path.isEmpty()) {
|
||||
result += "; path=";
|
||||
result += QUrl::toPercentEncoding(d->path, "/");
|
||||
result += d->path.toUtf8();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@ -954,8 +954,15 @@ QList<QNetworkCookie> QNetworkCookiePrivate::parseSetCookieHeaderLine(const QByt
|
||||
}
|
||||
//if unparsed, ignore the attribute but not the whole cookie (RFC6265 section 5.2.2)
|
||||
} else if (field.first == "path") {
|
||||
QString path = QUrl::fromPercentEncoding(field.second);
|
||||
cookie.setPath(path);
|
||||
if (field.second.startsWith('/')) {
|
||||
// ### we should treat cookie paths as an octet sequence internally
|
||||
// However RFC6265 says we should assume UTF-8 for presentation as a string
|
||||
cookie.setPath(QString::fromUtf8(field.second));
|
||||
} else {
|
||||
// if the path doesn't start with '/' then set the default path (RFC6265 section 5.2.4)
|
||||
// and also IETF test case path0030 which has valid and empty path in the same cookie
|
||||
cookie.setPath(QString());
|
||||
}
|
||||
} else if (field.first == "secure") {
|
||||
cookie.setSecure(true);
|
||||
} else if (field.first == "httponly") {
|
||||
|
@ -140,11 +140,21 @@ void QNetworkCookieJar::setAllCookies(const QList<QNetworkCookie> &cookieList)
|
||||
|
||||
static inline bool isParentPath(QString path, QString reference)
|
||||
{
|
||||
if (!path.endsWith(QLatin1Char('/')))
|
||||
path += QLatin1Char('/');
|
||||
if (!reference.endsWith(QLatin1Char('/')))
|
||||
reference += QLatin1Char('/');
|
||||
return path.startsWith(reference);
|
||||
if (path.startsWith(reference)) {
|
||||
//The cookie-path and the request-path are identical.
|
||||
if (path.length() == reference.length())
|
||||
return true;
|
||||
//The cookie-path is a prefix of the request-path, and the last
|
||||
//character of the cookie-path is %x2F ("/").
|
||||
if (reference.endsWith('/'))
|
||||
return true;
|
||||
//The cookie-path is a prefix of the request-path, and the first
|
||||
//character of the request-path that is not included in the cookie-
|
||||
//path is a %x2F ("/") character.
|
||||
if (path.at(reference.length()) == '/')
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool isParentDomain(QString domain, QString reference)
|
||||
|
@ -235,20 +235,24 @@ void tst_QNetworkCookie::parseSingleCookie_data()
|
||||
QTest::newRow("path9") << "a=b;path=/foo" << cookie;
|
||||
|
||||
// some weird paths:
|
||||
cookie.setPath("/with spaces");
|
||||
cookie.setPath("/with%20spaces");
|
||||
QTest::newRow("path-with-spaces") << "a=b;path=/with%20spaces" << cookie;
|
||||
QTest::newRow("path-with-spaces2") << "a=b; path=/with%20spaces " << cookie;
|
||||
cookie.setPath("\"/with spaces\"");
|
||||
QTest::newRow("path-with-spaces3") << "a=b; path=\"/with spaces\"" << cookie;
|
||||
QTest::newRow("path-with-spaces4") << "a=b; path = \"/with spaces\" " << cookie;
|
||||
cookie.setPath(QString());
|
||||
QTest::newRow("invalid-path-with-spaces3") << "a=b; path=\"/with spaces\"" << cookie;
|
||||
QTest::newRow("invalid-path-with-spaces4") << "a=b; path = \"/with spaces\" " << cookie;
|
||||
cookie.setPath("/with spaces");
|
||||
QTest::newRow("path-with-spaces5") << "a=b; path=/with spaces" << cookie;
|
||||
QTest::newRow("path-with-spaces6") << "a=b; path = /with spaces " << cookie;
|
||||
|
||||
cookie.setPath("/with\"Quotes");
|
||||
QTest::newRow("path-with-quotes") << "a=b; path = /with%22Quotes" << cookie;
|
||||
cookie.setPath("\"/with\\\"Quotes\"");
|
||||
QTest::newRow("path-with-quotes2") << "a=b; path = \"/with\\\"Quotes\"" << cookie;
|
||||
QTest::newRow("path-with-quotes") << "a=b; path = /with\"Quotes" << cookie;
|
||||
cookie.setPath(QString());
|
||||
QTest::newRow("invalid-path-with-quotes2") << "a=b; path = \"/with\\\"Quotes\"" << cookie;
|
||||
|
||||
cookie.setPath(QString::fromUtf8("/R\303\251sum\303\251"));
|
||||
QTest::newRow("path-with-utf8") << QString::fromUtf8("a=b;path=/R\303\251sum\303\251") << cookie;
|
||||
cookie.setPath("/R%C3%A9sum%C3%A9");
|
||||
QTest::newRow("path-with-utf8-2") << "a=b;path=/R%C3%A9sum%C3%A9" << cookie;
|
||||
|
||||
cookie.setPath(QString());
|
||||
@ -649,12 +653,21 @@ void tst_QNetworkCookie::parseMultipleCookies_data()
|
||||
QTest::newRow("invalid-06") << "=b" << list;
|
||||
QTest::newRow("invalid-07") << ";path=/" << list;
|
||||
|
||||
// these should be accepted by RFC6265 but ignoring the expires field
|
||||
// reason: malformed expiration date string
|
||||
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;
|
||||
QNetworkCookie datelessCookie;
|
||||
datelessCookie.setName("a");
|
||||
datelessCookie.setValue("b");
|
||||
list << datelessCookie;
|
||||
QTest::newRow("expiration-empty") << "a=b;expires=" << list;
|
||||
QTest::newRow("expiration-invalid-01") << "a=b;expires=foobar" << list;
|
||||
QTest::newRow("expiration-invalid-02") << "a=b;expires=foobar, abc" << list;
|
||||
QTest::newRow("expiration-invalid-03") << "a=b; expires=123" << list; // used to ASSERT
|
||||
datelessCookie.setPath("/");
|
||||
list.clear();
|
||||
list << datelessCookie;
|
||||
QTest::newRow("expiration-invalid-04") << "a=b;expires=foobar, dd-mmm-yyyy hh:mm:ss GMT; path=/" << list;
|
||||
QTest::newRow("expiration-invalid-05") << "a=b;expires=foobar, 32-Caz-1999 24:01:60 GMT; path=/" << list;
|
||||
|
||||
// cookies obtained from the network:
|
||||
QNetworkCookie cookie;
|
||||
@ -697,7 +710,6 @@ void tst_QNetworkCookie::parseMultipleCookies_data()
|
||||
cookie.setDomain("!@#$%^&*();:."); // the ';' is actually problematic, because it is a separator
|
||||
list = QList<QNetworkCookie>();
|
||||
QTest::newRow("domain-non-alpha-numeric") << "NonAlphNumDomName=NonAlphNumDomValue; domain=!@#$%^&*()" << list;
|
||||
QTest::newRow("expiration-3digit1") << "a=b; expires=123" << list; // used to ASSERT
|
||||
}
|
||||
|
||||
void tst_QNetworkCookie::parseMultipleCookies()
|
||||
|
Loading…
Reference in New Issue
Block a user