File indexing completed on 2024-05-12 05:46:42
0001 /* 0002 This file is part of KDE 0003 0004 Copyright (C) 2004 Waldo Bastian (bastian@kde.org) 0005 Copyright 2008 David Faure <faure@kde.org> 0006 0007 This library is free software; you can redistribute it and/or 0008 modify it under the terms of the GNU Library General Public License 0009 as published by the Free Software Foundation; either 0010 version 2, or (at your option) version 3. 0011 0012 This software is distributed in the hope that it will be useful, 0013 but WITHOUT ANY WARRANTY; without even the implied warranty of 0014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0015 General Public License for more details. 0016 0017 You should have received a copy of the GNU General Public License 0018 along with this library; see the file COPYING. If not, write to 0019 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0020 Boston, MA 02110-1301, USA. 0021 */ 0022 0023 #include <QDate> 0024 #include <QString> 0025 0026 #include <QtTest> 0027 #include <qplatformdefs.h> 0028 #include <qstandardpaths.h> 0029 0030 #include "../../src/ioslaves/http/kcookiejar/kcookiejar.cpp" 0031 0032 static KCookieJar *jar; 0033 static QString *lastYear; 0034 static QString *nextYear; 0035 static KConfig *config = nullptr; 0036 static int windowId = 1234; // random number to be used as windowId for test cookies 0037 0038 static void FAIL(const QString &msg) 0039 { 0040 qWarning("%s", msg.toLocal8Bit().data()); 0041 exit(1); 0042 } 0043 0044 static void popArg(QString &command, QString &line) 0045 { 0046 int i = line.indexOf(' '); 0047 if (i != -1) { 0048 command = line.left(i); 0049 line = line.mid(i + 1); 0050 } else { 0051 command = line; 0052 line.clear(); 0053 } 0054 } 0055 0056 static void clearConfig() 0057 { 0058 delete config; 0059 QString file = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QLatin1Char('/') + "kcookiejar-testconfig"; 0060 QFile::remove(file); 0061 config = new KConfig(file); 0062 KConfigGroup cg(config, "Cookie Policy"); 0063 cg.writeEntry("RejectCrossDomainCookies", false); 0064 cg.writeEntry("AcceptSessionCookies", false); 0065 cg.writeEntry("CookieGlobalAdvice", "Ask"); 0066 jar->loadConfig(config, false); 0067 } 0068 0069 static void clearCookies(bool sessionOnly = false) 0070 { 0071 if (sessionOnly) { 0072 jar->eatSessionCookies(windowId); 0073 } else { 0074 jar->eatAllCookies(); 0075 } 0076 } 0077 0078 static void saveCookies() 0079 { 0080 QString file = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QLatin1Char('/') + "kcookiejar-testcookies"; 0081 QFile::remove(file); 0082 jar->saveCookies(file); 0083 0084 // Add an empty domain to the cookies file, just for testing robustness 0085 QFile f(file); 0086 f.open(QIODevice::Append); 0087 f.write("[]\n \"\" \"/\" 1584320400 0 h 4 x\n"); 0088 f.close(); 0089 0090 delete jar; 0091 jar = new KCookieJar(); 0092 clearConfig(); 0093 jar->loadCookies(file); 0094 } 0095 0096 static void endSession() 0097 { 0098 jar->eatSessionCookies(windowId); 0099 } 0100 0101 static void processCookie(QString &line) 0102 { 0103 QString policy; 0104 popArg(policy, line); 0105 KCookieAdvice expectedAdvice = KCookieJar::strToAdvice(policy); 0106 if (expectedAdvice == KCookieDunno) { 0107 FAIL(QStringLiteral("Unknown accept policy '%1'").arg(policy)); 0108 } 0109 0110 QString urlStr; 0111 popArg(urlStr, line); 0112 QUrl url(urlStr); 0113 if (!url.isValid()) { 0114 FAIL(QStringLiteral("Invalid URL '%1'").arg(urlStr)); 0115 } 0116 if (url.isEmpty()) { 0117 FAIL(QStringLiteral("Missing URL")); 0118 } 0119 0120 line.replace(QLatin1String("%LASTYEAR%"), *lastYear); 0121 line.replace(QLatin1String("%NEXTYEAR%"), *nextYear); 0122 0123 KHttpCookieList list = jar->makeCookies(urlStr, line.toUtf8(), windowId); 0124 0125 if (list.isEmpty()) { 0126 FAIL(QStringLiteral("Failed to make cookies from: '%1'").arg(line)); 0127 } 0128 0129 for (KHttpCookieList::iterator cookieIterator = list.begin(); 0130 cookieIterator != list.end(); ++cookieIterator) { 0131 KHttpCookie &cookie = *cookieIterator; 0132 const KCookieAdvice cookieAdvice = jar->cookieAdvice(cookie); 0133 if (cookieAdvice != expectedAdvice) 0134 FAIL(urlStr + QStringLiteral("\n'%2'\nGot advice '%3' expected '%4'") 0135 .arg(line, KCookieJar::adviceToStr(cookieAdvice), KCookieJar::adviceToStr(expectedAdvice)) 0136 ); 0137 jar->addCookie(cookie); 0138 } 0139 } 0140 0141 static void processCheck(QString &line) 0142 { 0143 QString urlStr; 0144 popArg(urlStr, line); 0145 QUrl url(urlStr); 0146 if (!url.isValid()) { 0147 FAIL(QStringLiteral("Invalid URL '%1'").arg(urlStr)); 0148 } 0149 if (url.isEmpty()) { 0150 FAIL(QStringLiteral("Missing URL")); 0151 } 0152 0153 QString expectedCookies = line; 0154 0155 QString cookies = jar->findCookies(urlStr, false, windowId, nullptr).trimmed(); 0156 if (cookies != expectedCookies) 0157 FAIL(urlStr + QStringLiteral("\nGot '%1' expected '%2'") 0158 .arg(cookies, expectedCookies)); 0159 } 0160 0161 static void processClear(QString &line) 0162 { 0163 if (line == QLatin1String("CONFIG")) { 0164 clearConfig(); 0165 } else if (line == QLatin1String("COOKIES")) { 0166 clearCookies(); 0167 } else if (line == QLatin1String("SESSIONCOOKIES")) { 0168 clearCookies(true); 0169 } else { 0170 FAIL(QStringLiteral("Unknown command 'CLEAR %1'").arg(line)); 0171 } 0172 } 0173 0174 static void processConfig(QString &line) 0175 { 0176 QString key; 0177 popArg(key, line); 0178 0179 if (key.isEmpty()) { 0180 FAIL(QStringLiteral("Missing Key")); 0181 } 0182 0183 KConfigGroup cg(config, "Cookie Policy"); 0184 cg.writeEntry(key, line); 0185 jar->loadConfig(config, false); 0186 } 0187 0188 static void processLine(QString line) 0189 { 0190 if (line.isEmpty()) { 0191 return; 0192 } 0193 0194 if (line[0] == '#') { 0195 if (line[1] == '#') { 0196 qDebug("%s", line.toLatin1().constData()); 0197 } 0198 return; 0199 } 0200 0201 QString command; 0202 popArg(command, line); 0203 if (command.isEmpty()) { 0204 return; 0205 } 0206 0207 if (command == QLatin1String("COOKIE")) { 0208 processCookie(line); 0209 } else if (command == QLatin1String("CHECK")) { 0210 processCheck(line); 0211 } else if (command == QLatin1String("CLEAR")) { 0212 processClear(line); 0213 } else if (command == QLatin1String("CONFIG")) { 0214 processConfig(line); 0215 } else if (command == QLatin1String("SAVE")) { 0216 saveCookies(); 0217 } else if (command == QLatin1String("ENDSESSION")) { 0218 endSession(); 0219 } else { 0220 FAIL(QStringLiteral("Unknown command '%1'").arg(command)); 0221 } 0222 } 0223 0224 static void runRegression(const QString &filename) 0225 { 0226 FILE *file = QT_FOPEN(QFile::encodeName(filename).constData(), "r"); 0227 if (!file) { 0228 FAIL(QStringLiteral("Can't open '%1'").arg(filename)); 0229 } 0230 0231 char buf[4096]; 0232 while (fgets(buf, sizeof(buf), file)) { 0233 int l = strlen(buf); 0234 if (l) { 0235 l--; 0236 buf[l] = 0; 0237 } 0238 processLine(QString::fromUtf8(buf)); 0239 } 0240 fclose(file); 0241 qDebug("%s OK", filename.toLocal8Bit().data()); 0242 } 0243 0244 class KCookieJarTest : public QObject 0245 { 0246 Q_OBJECT 0247 private Q_SLOTS: 0248 void initTestCase() 0249 { 0250 QStandardPaths::setTestModeEnabled(true); 0251 jar = new KCookieJar; 0252 QDateTime dt = QDateTime::currentDateTime(); 0253 lastYear = new QString(dt.addYears(-1).toString(Qt::RFC2822Date)); 0254 nextYear = new QString(dt.addYears(1).toString(Qt::RFC2822Date)); 0255 } 0256 void testCookieFile_data() 0257 { 0258 QTest::addColumn<QString>("fileName"); 0259 QTest::newRow("cookie.test") << QFINDTESTDATA("cookie.test"); 0260 QTest::newRow("cookie_rfc.test") << QFINDTESTDATA("cookie_rfc.test"); 0261 QTest::newRow("cookie_saving.test") << QFINDTESTDATA("cookie_saving.test"); 0262 QTest::newRow("cookie_settings.test") << QFINDTESTDATA("cookie_settings.test"); 0263 QTest::newRow("cookie_session.test") << QFINDTESTDATA("cookie_session.test"); 0264 } 0265 void testCookieFile() 0266 { 0267 QFETCH(QString, fileName); 0268 clearConfig(); 0269 runRegression(fileName); 0270 } 0271 0272 void testParseUrl_data() 0273 { 0274 QTest::addColumn<QString>("url"); 0275 QTest::addColumn<bool>("expectedResult"); 0276 QTest::addColumn<QString>("expectedFqdn"); 0277 QTest::addColumn<QString>("expectedPath"); 0278 QTest::newRow("empty") << "" << false << "" << ""; 0279 QTest::newRow("url with no path") << "http://bugs.kde.org" << true << "bugs.kde.org" << "/"; 0280 QTest::newRow("url with path") << "http://bugs.kde.org/foo" << true << "bugs.kde.org" << "/foo"; 0281 QTest::newRow("just a host") << "bugs.kde.org" << false << "" << ""; 0282 } 0283 void testParseUrl() 0284 { 0285 QFETCH(QString, url); 0286 QFETCH(bool, expectedResult); 0287 QFETCH(QString, expectedFqdn); 0288 QFETCH(QString, expectedPath); 0289 QString fqdn; 0290 QString path; 0291 bool result = KCookieJar::parseUrl(url, fqdn, path); 0292 QCOMPARE(result, expectedResult); 0293 QCOMPARE(fqdn, expectedFqdn); 0294 QCOMPARE(path, expectedPath); 0295 } 0296 0297 void testExtractDomains_data() 0298 { 0299 QTest::addColumn<QString>("fqdn"); 0300 QTest::addColumn<QStringList>("expectedDomains"); 0301 QTest::newRow("empty") << "" << (QStringList() << QStringLiteral("localhost")); 0302 QTest::newRow("ipv4") << "1.2.3.4" << (QStringList() << QStringLiteral("1.2.3.4")); 0303 QTest::newRow("ipv6") << "[fe80::213:d3ff:fef4:8c92]" << (QStringList() << QStringLiteral("[fe80::213:d3ff:fef4:8c92]")); 0304 QTest::newRow("bugs.kde.org") << "bugs.kde.org" << (QStringList() << QStringLiteral("bugs.kde.org") << QStringLiteral(".bugs.kde.org") << QStringLiteral("kde.org") << QStringLiteral(".kde.org")); 0305 0306 } 0307 void testExtractDomains() 0308 { 0309 QFETCH(QString, fqdn); 0310 QFETCH(QStringList, expectedDomains); 0311 KCookieJar jar; 0312 QStringList lst; 0313 jar.extractDomains(fqdn, lst); 0314 QCOMPARE(lst, expectedDomains); 0315 } 0316 }; 0317 0318 QTEST_MAIN(KCookieJarTest) 0319 0320 #include "kcookiejartest.moc"