diff --git a/scripts/run_tests.sh b/scripts/run_tests.sh index 500281fdf..24d009057 100755 --- a/scripts/run_tests.sh +++ b/scripts/run_tests.sh @@ -2,7 +2,7 @@ # run_tests.sh cd ../tests/autotests -qmake DEFINES+=NO_SYSTEM_DATAPATH && make +(qmake DEFINES+=NO_SYSTEM_DATAPATH && make) || exit 1 cd ../../bin ./autotests diff --git a/src/lib/cookies/cookiejar.cpp b/src/lib/cookies/cookiejar.cpp index 42b6d2e70..40d4f9619 100644 --- a/src/lib/cookies/cookiejar.cpp +++ b/src/lib/cookies/cookiejar.cpp @@ -28,59 +28,6 @@ //#define COOKIE_DEBUG -#if QTWEBKIT_TO_2_3 -static bool blockThirdParty(QString string, QString domain) -{ - if (string.isEmpty()) { - // Some cookies have empty domain() ... bug? - return false; - } - - if (string.startsWith(QLatin1String("www."))) { - string = string.mid(3); - } - - if (domain.startsWith(QLatin1String("www."))) { - domain = domain.mid(4); - } - - return !domain.endsWith(string); -} -#endif - -static bool matchDomain(const QString &domain, const QString &filter) -{ - // According to RFC 6265 - - if (domain == filter) { - return true; - } - - if (!domain.endsWith(filter)) { - return false; - } - - int index = domain.indexOf(filter); - - return (index == 1 && domain[0] == QLatin1Char('.')) || - (index > 0 && filter[0] == QLatin1Char('.')); -} - -static int listContainsDomain(const QStringList &list, const QString &domain) -{ - if (domain.isEmpty()) { - return -1; - } - - foreach(const QString & d, list) { - if (matchDomain(domain, d)) { - return 1; - } - } - - return 0; -} - CookieJar::CookieJar(QupZilla* mainClass, QObject* parent) : QNetworkCookieJar(parent) , p_QupZilla(mainClass) @@ -120,8 +67,8 @@ bool CookieJar::rejectCookie(const QString &domain, const QNetworkCookie &cookie const QString &cookieDomain = cookie.domain(); if (!m_allowCookies) { - int result = listContainsDomain(m_whitelist, cookieDomain); - if (result != 1) { + bool result = listMatchesDomain(m_whitelist, cookieDomain); + if (!result) { #ifdef COOKIE_DEBUG qDebug() << "not in whitelist" << cookie; #endif @@ -130,8 +77,8 @@ bool CookieJar::rejectCookie(const QString &domain, const QNetworkCookie &cookie } if (m_allowCookies) { - int result = listContainsDomain(m_blacklist, cookieDomain); - if (result == 1) { + bool result = listMatchesDomain(m_blacklist, cookieDomain); + if (result) { #ifdef COOKIE_DEBUG qDebug() << "found in blacklist" << cookie; #endif @@ -142,8 +89,8 @@ bool CookieJar::rejectCookie(const QString &domain, const QNetworkCookie &cookie // This feature is now natively in QtWebKit 2.3 #if QTWEBKIT_TO_2_3 if (m_blockThirdParty) { - bool result = blockThirdParty(cookieDomain, domain); - if (result) { + bool result = matchDomain(cookieDomain, domain); + if (!result) { #ifdef COOKIE_DEBUG qDebug() << "purged for domain mismatch" << cookie << cookieDomain << domain; #endif @@ -164,12 +111,16 @@ bool CookieJar::rejectCookie(const QString &domain, const QNetworkCookie &cookie bool CookieJar::setCookiesFromUrl(const QList &cookieList, const QUrl &url) { - QList newList = cookieList; + QList newList; - foreach(const QNetworkCookie & cookie, newList) { - if (rejectCookie(url.host(), cookie)) { - newList.removeOne(cookie); - continue; + foreach(QNetworkCookie cookie, cookieList) { + // If cookie domain is empty, set it to url.host() + if (cookie.domain().isEmpty()) { + cookie.setDomain(url.host()); + } + + if (!rejectCookie(url.host(), cookie)) { + newList.append(cookie); } } @@ -195,7 +146,7 @@ void CookieJar::saveCookies() for (int i = 0; i < count; i++) { const QNetworkCookie &cookie = cookies.at(i); - int result = listContainsDomain(m_whitelist, cookie.domain()); + int result = listMatchesDomain(m_whitelist, cookie.domain()); if (result == 1) { allCookies.append(cookie); @@ -270,3 +221,40 @@ void CookieJar::setAllCookies(const QList &cookieList) { QNetworkCookieJar::setAllCookies(cookieList); } + +bool CookieJar::matchDomain(QString cookieDomain, QString siteDomain) +{ + // According to RFC 6265 + + // Remove leading dot + if (cookieDomain.startsWith(QLatin1Char('.'))) { + cookieDomain = cookieDomain.mid(1); + } + + if (siteDomain.startsWith(QLatin1Char('.'))) { + siteDomain = siteDomain.mid(1); + } + + if (cookieDomain == siteDomain) { + return true; + } + + if (!siteDomain.endsWith(cookieDomain)) { + return false; + } + + int index = siteDomain.indexOf(cookieDomain); + + return index > 0 && siteDomain[index - 1] == QLatin1Char('.'); +} + +bool CookieJar::listMatchesDomain(const QStringList &list, const QString &cookieDomain) +{ + foreach(const QString & d, list) { + if (matchDomain(d, cookieDomain)) { + return true; + } + } + + return false; +} diff --git a/src/lib/cookies/cookiejar.h b/src/lib/cookies/cookiejar.h index 0342a2f3c..3ceec5ea7 100644 --- a/src/lib/cookies/cookiejar.h +++ b/src/lib/cookies/cookiejar.h @@ -1,6 +1,6 @@ /* ============================================================ * QupZilla - WebKit based browser -* Copyright (C) 2010-2012 David Rosca +* Copyright (C) 2010-2013 David Rosca * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -42,6 +42,9 @@ public: void setAllowCookies(bool allow); + static bool matchDomain(QString cookieDomain, QString siteDomain); + static bool listMatchesDomain(const QStringList &list, const QString &cookieDomain); + private: bool rejectCookie(const QString &domain, const QNetworkCookie &cookie) const; diff --git a/tests/autotests/autotests.pro b/tests/autotests/autotests.pro index a7fdd0fd0..fc493fc61 100644 --- a/tests/autotests/autotests.pro +++ b/tests/autotests/autotests.pro @@ -47,9 +47,11 @@ INCLUDEPATH += $$PWD/../../src/lib/3rdparty\ HEADERS += \ qztoolstest.h \ - formcompletertest.h + formcompletertest.h \ + cookiestest.h SOURCES += \ qztoolstest.cpp \ main.cpp \ - formcompletertest.cpp + formcompletertest.cpp \ + cookiestest.cpp diff --git a/tests/autotests/cookiestest.cpp b/tests/autotests/cookiestest.cpp new file mode 100644 index 000000000..fc7c7a7fc --- /dev/null +++ b/tests/autotests/cookiestest.cpp @@ -0,0 +1,86 @@ +/* ============================================================ +* QupZilla - WebKit based browser +* Copyright (C) 2013 David Rosca +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +* ============================================================ */ +#include "cookiestest.h" +#include "cookiejar.h" + +#include + +void CookiesTest::domainMatchingTest_data() +{ + QTest::addColumn("cookieDomain"); + QTest::addColumn("siteDomain"); + QTest::addColumn("result"); + + /* http://stackoverflow.com/questions/1062963/how-do-browser-cookie-domains-work + 1) Cookie with Domain=.example.com will be available for www.example.com + 2) Cookie with Domain=.example.com will be available for example.com + 3) Cookie with Domain=example.com will be converted to .example.com and thus will also be available for www.example.com + 4) Cookie with Domain=example.com will not be available for anotherexample.com + */ + + QTest::newRow("test1") << ".example.com" << "www.example.com" << true; + QTest::newRow("test2") << ".example.com" << "example.com" << true; + QTest::newRow("test3") << "example.com" << "www.example.com" << true; + QTest::newRow("test4") << ".example.com" << "anotherexample.com" << false; + QTest::newRow("test5") << "test.example.com" << "example.com" << false; + QTest::newRow("test6") << ".www.example.com" << "www.example.com" << true; + QTest::newRow("test7") << ".www.example.com" << "example.com" << false; + QTest::newRow("test_empty") << ".www.example.com" << "" << false; + QTest::newRow("test_empty2") << "" << "example.com" << false; +} + +void CookiesTest::domainMatchingTest() +{ + QFETCH(QString, cookieDomain); + QFETCH(QString, siteDomain); + QFETCH(bool, result); + + QCOMPARE(CookieJar::matchDomain(cookieDomain, siteDomain), result); +} + +void CookiesTest::listMatchesDomainTest_data() +{ + QTest::addColumn("list"); + QTest::addColumn("cookieDomain"); + QTest::addColumn("result"); + + QStringList list; + list << "www.example.com" << "accounts.google.com"; + QStringList list2; + list2 << "anotherexample.com" << "a.b.x.google.com"; + + QTest::newRow("test1") << list << ".www.example.com" << true; + QTest::newRow("test2") << list << ".google.com" << false; + QTest::newRow("test3") << list << ".accounts.google.com" << true; + QTest::newRow("test4") << list << ".example.com" << false; + QTest::newRow("test5") << list2 << "example.com" << false; + QTest::newRow("test6") << list2 << "tst.anotherexample.com" << true; + QTest::newRow("test7") << list2 << "b.x.google.com" << false; + QTest::newRow("test8") << list2 << "c.a.b.x.google.com" << true; + QTest::newRow("test9") << list2 << ".a.b.x.google.com" << true; + QTest::newRow("test_empty") << list2 << "" << false; +} + +void CookiesTest::listMatchesDomainTest() +{ + QFETCH(QStringList, list); + QFETCH(QString, cookieDomain); + QFETCH(bool, result); + + QCOMPARE(CookieJar::listMatchesDomain(list, cookieDomain), result); +} diff --git a/tests/autotests/cookiestest.h b/tests/autotests/cookiestest.h new file mode 100644 index 000000000..d660be692 --- /dev/null +++ b/tests/autotests/cookiestest.h @@ -0,0 +1,36 @@ +/* ============================================================ +* QupZilla - WebKit based browser +* Copyright (C) 2013 David Rosca +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +* ============================================================ */ +#ifndef COOKIESTEST_H +#define COOKIESTEST_H + +#include + +class CookiesTest : public QObject +{ + Q_OBJECT + +private slots: + void domainMatchingTest_data(); + void domainMatchingTest(); + + void listMatchesDomainTest_data(); + void listMatchesDomainTest(); + +}; + +#endif // COOKIESTEST_H diff --git a/tests/autotests/main.cpp b/tests/autotests/main.cpp index 29477d0c0..489a9d8af 100644 --- a/tests/autotests/main.cpp +++ b/tests/autotests/main.cpp @@ -17,6 +17,7 @@ * ============================================================ */ #include "qztoolstest.h" #include "formcompletertest.h" +#include "cookiestest.h" #include @@ -31,5 +32,8 @@ int main(int argc, char *argv[]) FormCompleterTest formCompleterTest; QTest::qExec(&formCompleterTest, argc, argv); + CookiesTest cookiesTest; + QTest::qExec(&cookiesTest, argc, argv); + return 0; }