File indexing completed on 2024-04-28 03:54:59

0001 /*
0002     SPDX-FileCopyrightText: 2002, 2003 David Faure <faure@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-only
0005 */
0006 
0007 #include "kurifiltertest.h"
0008 
0009 #include <KConfigGroup>
0010 #include <KSharedConfig>
0011 #include <KUriFilter>
0012 #include <QLoggingCategory>
0013 
0014 #include <KPluginMetaData>
0015 #include <QDir>
0016 #include <QHostInfo>
0017 #include <QRegularExpression>
0018 #include <QtTestWidgets>
0019 
0020 #include <iostream>
0021 
0022 QTEST_MAIN(KUriFilterTest)
0023 
0024 static const char *const s_uritypes[] = {"NetProtocol", "LOCAL_FILE", "LOCAL_DIR", "EXECUTABLE", "HELP", "SHELL", "BLOCKED", "ERROR", "UNKNOWN"};
0025 static constexpr int s_noFiltering = -2;
0026 
0027 static void setupColumns()
0028 {
0029     QTest::addColumn<QString>("input");
0030     QTest::addColumn<QString>("expectedResult");
0031     QTest::addColumn<int>("expectedUriType");
0032     QTest::addColumn<QStringList>("list");
0033     QTest::addColumn<QString>("absPath");
0034     QTest::addColumn<bool>("checkForExecutables");
0035 }
0036 
0037 static void addRow(const char *input,
0038                    const QString &expectedResult = QString(),
0039                    int expectedUriType = -1,
0040                    const QStringList &list = QStringList(),
0041                    const QString &absPath = QString(),
0042                    bool checkForExecutables = true)
0043 {
0044     QTest::newRow(input) << input << expectedResult << expectedUriType << list << absPath << checkForExecutables;
0045 }
0046 
0047 static void runFilterTest(const QString &a,
0048                           const QString &expectedResult = nullptr,
0049                           int expectedUriType = -1,
0050                           const QStringList &list = QStringList(),
0051                           const QString &absPath = nullptr,
0052                           bool checkForExecutables = true)
0053 {
0054     KUriFilterData *filterData = new KUriFilterData;
0055     filterData->setData(a);
0056     filterData->setCheckForExecutables(checkForExecutables);
0057 
0058     if (!absPath.isEmpty()) {
0059         filterData->setAbsolutePath(absPath);
0060         qDebug() << "Filtering: " << a << " with absPath=" << absPath;
0061     } else {
0062         qDebug() << "Filtering: " << a;
0063     }
0064 
0065     if (KUriFilter::self()->filterUri(*filterData, list)) {
0066         if (expectedUriType == s_noFiltering) {
0067             qCritical() << a << "Did not expect filtering. Got" << filterData->uri();
0068             QVERIFY(expectedUriType != s_noFiltering); // fail the test
0069         }
0070 
0071         // Copied from minicli...
0072         QString cmd;
0073         QUrl uri = filterData->uri();
0074 
0075         if (uri.isLocalFile() && !uri.hasFragment() && !uri.hasQuery() && (filterData->uriType() != KUriFilterData::NetProtocol)) {
0076             cmd = uri.toLocalFile();
0077         } else {
0078             cmd = uri.url(QUrl::FullyEncoded);
0079         }
0080 
0081         switch (filterData->uriType()) {
0082         case KUriFilterData::LocalFile:
0083         case KUriFilterData::LocalDir:
0084             qDebug() << "*** Result: Local Resource =>  '" << filterData->uri().toLocalFile() << "'";
0085             break;
0086         case KUriFilterData::Help:
0087             qDebug() << "*** Result: Local Resource =>  '" << filterData->uri().url() << "'";
0088             break;
0089         case KUriFilterData::NetProtocol:
0090             qDebug() << "*** Result: Network Resource => '" << filterData->uri().url() << "'";
0091             break;
0092         case KUriFilterData::Shell:
0093         case KUriFilterData::Executable:
0094             if (filterData->hasArgsAndOptions()) {
0095                 cmd += filterData->argsAndOptions();
0096             }
0097             qDebug() << "*** Result: Executable/Shell => '" << cmd << "'";
0098             break;
0099         case KUriFilterData::Error:
0100             qDebug() << "*** Result: Encountered error => '" << cmd << "'";
0101             qDebug() << "Reason:" << filterData->errorMsg();
0102             break;
0103         default:
0104             qDebug() << "*** Result: Unknown or invalid resource.";
0105         }
0106 
0107         if (!expectedResult.isEmpty()) {
0108             // Hack for other locales than english, normalize google hosts to google.com
0109             cmd.replace(QRegularExpression(QStringLiteral("www\\.google\\.[^/]*/")), QStringLiteral("www.google.com/"));
0110             if (cmd != expectedResult) {
0111                 qWarning() << a;
0112                 QCOMPARE(cmd, expectedResult);
0113             }
0114         }
0115 
0116         if (expectedUriType != -1 && expectedUriType != filterData->uriType()) {
0117             qWarning() << a << "Got URI type" << s_uritypes[filterData->uriType()] << "expected" << s_uritypes[expectedUriType];
0118             QCOMPARE(s_uritypes[filterData->uriType()], s_uritypes[expectedUriType]);
0119         }
0120     } else {
0121         if (expectedUriType == s_noFiltering) {
0122             qDebug() << "*** No filtering required.";
0123         } else {
0124             qDebug() << "*** Could not be filtered.";
0125             if (expectedUriType != filterData->uriType()) {
0126                 QCOMPARE(s_uritypes[filterData->uriType()], s_uritypes[expectedUriType]);
0127             }
0128         }
0129     }
0130 
0131     delete filterData;
0132     qDebug() << "-----";
0133 }
0134 
0135 static void runFilterTest()
0136 {
0137     QFETCH(QString, input);
0138     QFETCH(QString, expectedResult);
0139     QFETCH(int, expectedUriType);
0140     QFETCH(QStringList, list);
0141     QFETCH(QString, absPath);
0142     QFETCH(bool, checkForExecutables);
0143     runFilterTest(input, expectedResult, expectedUriType, list, absPath, checkForExecutables);
0144 }
0145 
0146 static void testLocalFile(const QString &filename)
0147 {
0148     QFile tmpFile(filename); // Yeah, I know, security risk blah blah. This is a test prog!
0149 
0150     if (tmpFile.open(QIODevice::ReadWrite)) {
0151         QByteArray fname = QFile::encodeName(tmpFile.fileName());
0152         runFilterTest(fname, fname, KUriFilterData::LocalFile);
0153         tmpFile.close();
0154         tmpFile.remove();
0155     } else {
0156         qDebug() << "Couldn't create " << tmpFile.fileName() << ", skipping test";
0157     }
0158 }
0159 
0160 static const char s_delimiter = WEBSHORTCUT_SEPARATOR;
0161 
0162 void KUriFilterTest::initTestCase()
0163 {
0164     QStandardPaths::setTestModeEnabled(true);
0165     minicliFilters << QStringLiteral("kshorturifilter") << QStringLiteral("kurisearchfilter") << QStringLiteral("localdomainurifilter");
0166     qtdir = qgetenv("QTDIR");
0167     home = qgetenv("HOME");
0168     qputenv("DATAHOME", QFile::encodeName(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)));
0169     datahome = qgetenv("DATAHOME");
0170     qDebug() << "libpaths" << QCoreApplication::libraryPaths();
0171 
0172     QLoggingCategory::setFilterRules(QStringLiteral("kf.kio.urifilters.*=true"));
0173 
0174     QString searchProvidersDir = QFINDTESTDATA("../src/urifilters/ikws/searchproviders/google.desktop").section('/', 0, -2);
0175     QVERIFY(!searchProvidersDir.isEmpty());
0176     qputenv("KIO_SEARCHPROVIDERS_DIR", QFile::encodeName(searchProvidersDir));
0177 
0178     // Many tests check the "default search engine" feature.
0179     // There is no default search engine by default (since it was annoying when making typos),
0180     // so the user has to set it up, which we do here.
0181     {
0182         KConfigGroup cfg(KSharedConfig::openConfig(QStringLiteral("kuriikwsfilterrc"), KConfig::SimpleConfig), QStringLiteral("General"));
0183         cfg.writeEntry("DefaultWebShortcut", "google");
0184         cfg.writeEntry("KeywordDelimiter", QString(s_delimiter));
0185         cfg.sync();
0186     }
0187 
0188     QDir().mkpath(datahome + QStringLiteral("/urifilter"));
0189 }
0190 
0191 void KUriFilterTest::pluginNames()
0192 {
0193     const QStringList plugins = KUriFilter::self()->pluginNames();
0194     const QByteArray debugData = plugins.join(',').toLatin1();
0195     const char *debugString = debugData.constData();
0196     // To make it possible to have external plugins (if there's any...)
0197     // we don't just have an expected result list, we just probe it for specific entries.
0198     QVERIFY2(plugins.contains("kshorturifilter"), debugString);
0199     QVERIFY2(plugins.contains("kurisearchfilter"), debugString);
0200     QVERIFY2(plugins.contains("localdomainurifilter"), debugString);
0201     QVERIFY2(plugins.contains("fixhosturifilter"), debugString);
0202     QVERIFY2(plugins.contains("kuriikwsfilter"), debugString);
0203     // No duplicates
0204     QCOMPARE(plugins.count("kshorturifilter"), 1);
0205 }
0206 
0207 void KUriFilterTest::noFiltering_data()
0208 {
0209     setupColumns();
0210     // URI that should require no filtering
0211     addRow("http://www.kde.org", QStringLiteral("http://www.kde.org"), KUriFilterData::NetProtocol);
0212     // qtbase commit eaf4438b3511c preserves the double slashes
0213     addRow("http://www.kde.org/developer//index.html", QStringLiteral("http://www.kde.org/developer//index.html"), KUriFilterData::NetProtocol);
0214     addRow("file:///", QStringLiteral("/"), KUriFilterData::LocalDir);
0215     addRow("file:///etc", QStringLiteral("/etc"), KUriFilterData::LocalDir);
0216     addRow("file:///etc/passwd", QStringLiteral("/etc/passwd"), KUriFilterData::LocalFile);
0217 }
0218 
0219 void KUriFilterTest::noFiltering()
0220 {
0221     runFilterTest();
0222 }
0223 
0224 void KUriFilterTest::localFiles_data()
0225 {
0226     setupColumns();
0227     addRow("/", QStringLiteral("/"), KUriFilterData::LocalDir);
0228     addRow("/", QStringLiteral("/"), KUriFilterData::LocalDir, QStringList(QStringLiteral("kshorturifilter")));
0229     addRow("//", QStringLiteral("/"), KUriFilterData::LocalDir);
0230     addRow("///", QStringLiteral("/"), KUriFilterData::LocalDir);
0231     addRow("////", QStringLiteral("/"), KUriFilterData::LocalDir);
0232     addRow("///tmp", QStringLiteral("/tmp"), KUriFilterData::LocalDir);
0233     addRow("///tmp/", QStringLiteral("/tmp/"), KUriFilterData::LocalDir);
0234     addRow("///tmp//", QStringLiteral("/tmp/"), KUriFilterData::LocalDir);
0235     addRow("///tmp///", QStringLiteral("/tmp/"), KUriFilterData::LocalDir);
0236 
0237     if (QFile::exists(QDir::homePath() + QLatin1String("/.bashrc"))) {
0238         addRow("~/.bashrc", QDir::homePath() + QStringLiteral("/.bashrc"), KUriFilterData::LocalFile, QStringList(QStringLiteral("kshorturifilter")));
0239     }
0240     addRow("~", QDir::homePath(), KUriFilterData::LocalDir, QStringList(QStringLiteral("kshorturifilter")), QStringLiteral("/tmp"));
0241     addRow("~bin", nullptr, KUriFilterData::LocalDir, QStringList(QStringLiteral("kshorturifilter")));
0242     addRow("~does_not_exist", nullptr, KUriFilterData::Error, QStringList(QStringLiteral("kshorturifilter")));
0243     addRow("~/does_not_exist", QDir::homePath() + "/does_not_exist", KUriFilterData::LocalFile, QStringList(QStringLiteral("kshorturifilter")));
0244 
0245     // Absolute Path tests for kshorturifilter
0246     const QStringList kshorturifilter(QStringLiteral("kshorturifilter"));
0247     addRow("./", datahome, KUriFilterData::LocalDir, kshorturifilter, datahome + QStringLiteral("/")); // cleanPath removes the trailing slash
0248     const QString parentDir = QDir().cleanPath(datahome + QStringLiteral("/.."));
0249     addRow("../", QFile::encodeName(parentDir), KUriFilterData::LocalDir, kshorturifilter, datahome);
0250     addRow("share", datahome, KUriFilterData::LocalDir, kshorturifilter, QFile::encodeName(parentDir));
0251     // Invalid URLs
0252     addRow("http://a[b]", QStringLiteral("http://a[b]"), KUriFilterData::Unknown, kshorturifilter, QStringLiteral("/"));
0253 }
0254 
0255 void KUriFilterTest::localFiles()
0256 {
0257     runFilterTest();
0258 }
0259 
0260 void KUriFilterTest::refOrQuery_data()
0261 {
0262     setupColumns();
0263     // URL with reference
0264     addRow("http://www.kde.org/index.html#q8", QStringLiteral("http://www.kde.org/index.html#q8"), KUriFilterData::NetProtocol);
0265     // local file with reference
0266     addRow("file:/etc/passwd#q8", QStringLiteral("file:///etc/passwd#q8"), KUriFilterData::LocalFile);
0267     addRow("file:///etc/passwd#q8", QStringLiteral("file:///etc/passwd#q8"), KUriFilterData::LocalFile);
0268     addRow("/etc/passwd#q8", QStringLiteral("file:///etc/passwd#q8"), KUriFilterData::LocalFile);
0269     // local file with query (can be used by javascript)
0270     addRow("file:/etc/passwd?foo=bar", QStringLiteral("file:///etc/passwd?foo=bar"), KUriFilterData::LocalFile);
0271     testLocalFile(QStringLiteral("/tmp/kurifiltertest?foo")); // local file with ? in the name (#58990)
0272     testLocalFile(QStringLiteral("/tmp/kurlfiltertest#foo")); // local file with '#' in the name
0273     testLocalFile(QStringLiteral("/tmp/kurlfiltertest#foo?bar")); // local file with both
0274     testLocalFile(QStringLiteral("/tmp/kurlfiltertest?foo#bar")); // local file with both, the other way round
0275 }
0276 
0277 void KUriFilterTest::refOrQuery()
0278 {
0279     runFilterTest();
0280 }
0281 
0282 void KUriFilterTest::shortUris_data()
0283 {
0284     setupColumns();
0285     // hostnames are lowercased by QUrl
0286     // qtbase commit eaf4438b3511c preserves the double slashes
0287     addRow("http://www.myDomain.commyPort/ViewObjectRes//Default:name=hello",
0288            QStringLiteral("http://www.mydomain.commyport/ViewObjectRes//Default:name=hello"),
0289            KUriFilterData::NetProtocol);
0290     addRow("http://www.myDomain.commyPort/ViewObjectRes/Default:name=hello?a=a///////",
0291            QStringLiteral("http://www.mydomain.commyport/ViewObjectRes/Default:name=hello?a=a///////"),
0292            KUriFilterData::NetProtocol);
0293     addRow("ftp://ftp.kde.org", QStringLiteral("ftp://ftp.kde.org"), KUriFilterData::NetProtocol);
0294     addRow("ftp://username@ftp.kde.org:500", QStringLiteral("ftp://username@ftp.kde.org:500"), KUriFilterData::NetProtocol);
0295 
0296     // ShortURI/LocalDomain filter tests.
0297     addRow("linuxtoday.com", QStringLiteral("https://linuxtoday.com"), KUriFilterData::NetProtocol);
0298     addRow("LINUXTODAY.COM", QStringLiteral("https://linuxtoday.com"), KUriFilterData::NetProtocol);
0299     addRow("kde.org", QStringLiteral("https://kde.org"), KUriFilterData::NetProtocol);
0300     addRow("ftp.kde.org", QStringLiteral("ftp://ftp.kde.org"), KUriFilterData::NetProtocol);
0301     addRow("ftp.kde.org:21", QStringLiteral("ftp://ftp.kde.org:21"), KUriFilterData::NetProtocol);
0302     addRow("cr.yp.to", QStringLiteral("https://cr.yp.to"), KUriFilterData::NetProtocol);
0303     addRow("www.kde.org:21", QStringLiteral("https://www.kde.org:21"), KUriFilterData::NetProtocol);
0304     // This one passes but the DNS lookup takes 5 seconds to fail
0305     // addRow("foobar.local:8000", QStringLiteral("https://foobar.local:8000"), KUriFilterData::NetProtocol);
0306     addRow("foo@bar.com", QStringLiteral("mailto:foo@bar.com"), KUriFilterData::NetProtocol);
0307     addRow("firstname.lastname@x.foo.bar", QStringLiteral("mailto:firstname.lastname@x.foo.bar"), KUriFilterData::NetProtocol);
0308     addRow("mailto:foo@bar.com", QStringLiteral("mailto:foo@bar.com"), KUriFilterData::NetProtocol);
0309     addRow("www.123.foo", QStringLiteral("https://www.123.foo"), KUriFilterData::NetProtocol);
0310     addRow("user@www.123.foo:3128", QStringLiteral("https://user@www.123.foo:3128"), KUriFilterData::NetProtocol);
0311     addRow("ftp://user@user@www.123.foo:3128", QStringLiteral("ftp://user%40user@www.123.foo:3128"), KUriFilterData::NetProtocol);
0312     addRow("user@user@www.123.foo:3128", QStringLiteral("https://user%40user@www.123.foo:3128"), KUriFilterData::NetProtocol);
0313 
0314     // IPv4 address formats...
0315     addRow("user@192.168.1.0:3128", QStringLiteral("https://user@192.168.1.0:3128"), KUriFilterData::NetProtocol);
0316     addRow("127.0.0.1", QStringLiteral("https://127.0.0.1"), KUriFilterData::NetProtocol);
0317     addRow("127.0.0.1:3128", QStringLiteral("https://127.0.0.1:3128"), KUriFilterData::NetProtocol);
0318     addRow("127.1", QStringLiteral("https://127.0.0.1"), KUriFilterData::NetProtocol); // Qt5: QUrl resolves to 127.0.0.1
0319     addRow("127.0.1", QStringLiteral("https://127.0.0.1"), KUriFilterData::NetProtocol); // Qt5: QUrl resolves to 127.0.0.1
0320 
0321     // IPv6 address formats (taken from RFC 2732)...
0322     addRow("[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html",
0323            QStringLiteral("https://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:80/index.html"),
0324            KUriFilterData::NetProtocol);
0325     addRow("[1080:0:0:0:8:800:200C:417A]/index.html",
0326            QStringLiteral("https://[1080::8:800:200c:417a]/index.html"),
0327            KUriFilterData::NetProtocol); // Qt5 QUrl change
0328     addRow("[3ffe:2a00:100:7031::1]", QStringLiteral("https://[3ffe:2a00:100:7031::1]"), KUriFilterData::NetProtocol);
0329     addRow("[1080::8:800:200C:417A]/foo", QStringLiteral("https://[1080::8:800:200c:417a]/foo"), KUriFilterData::NetProtocol);
0330     addRow("[::192.9.5.5]/ipng", QStringLiteral("https://[::192.9.5.5]/ipng"), KUriFilterData::NetProtocol);
0331     addRow("[::FFFF:129.144.52.38]:80/index.html", QStringLiteral("https://[::ffff:129.144.52.38]:80/index.html"), KUriFilterData::NetProtocol);
0332     addRow("[2010:836B:4179::836B:4179]", QStringLiteral("https://[2010:836b:4179::836b:4179]"), KUriFilterData::NetProtocol);
0333 
0334     // Local domain filter - If you uncomment these test, make sure you
0335     // you adjust it based on the localhost entry in your /etc/hosts file.
0336     // addRow( "localhost:3128", "http://localhost.localdomain:3128", KUriFilterData::NetProtocol );
0337     // addRow( "localhost", "http://localhost.localdomain", KUriFilterData::NetProtocol );
0338     // addRow( "localhost/~blah", "http://localhost.localdomain/~blah", KUriFilterData::NetProtocol );
0339 
0340     addRow("user@host.domain", QStringLiteral("mailto:user@host.domain"), KUriFilterData::NetProtocol); // new in KDE-3.2
0341 
0342     // Windows style SMB (UNC) URL. Should be converted into the valid smb format...
0343     addRow("\\\\mainserver\\share\\file", QStringLiteral("smb://mainserver/share/file"), KUriFilterData::NetProtocol);
0344 
0345     // KDE3: was not be filtered at all. All valid protocols of this form were be ignored.
0346     // KDE4: parsed as "network protocol", seems fine to me (DF)
0347     addRow("ftp:", QStringLiteral("ftp:"), KUriFilterData::NetProtocol);
0348     addRow("http:", QStringLiteral("http:"), KUriFilterData::NetProtocol);
0349 
0350     // The default search engine is set to 'Google'
0351     addRow("gg:", QLatin1String(""), KUriFilterData::NetProtocol); // see bug 56218
0352     // disable localdomain in case the local DNS or /etc/hosts knows domains KDE or HTTP (e.g. due to search domain)
0353     addRow("KDE",
0354            QStringLiteral("https://www.google.com/search?q=KDE&ie=UTF-8"),
0355            KUriFilterData::NetProtocol,
0356            {QStringLiteral("kshorturifilter"), QStringLiteral("kuriikwsfilter")});
0357     addRow("HTTP",
0358            QStringLiteral("https://www.google.com/search?q=HTTP&ie=UTF-8"),
0359            KUriFilterData::NetProtocol,
0360            {QStringLiteral("kshorturifilter"), QStringLiteral("kuriikwsfilter")});
0361 }
0362 
0363 void KUriFilterTest::shortUris()
0364 {
0365     runFilterTest();
0366 }
0367 
0368 void KUriFilterTest::executables_data()
0369 {
0370     setupColumns();
0371     // Executable tests - No IKWS in minicli
0372     addRow("cp", QStringLiteral("cp"), KUriFilterData::Executable, minicliFilters);
0373     addRow("kbuildsycoca6", QStringLiteral("kbuildsycoca6"), KUriFilterData::Executable, minicliFilters);
0374     addRow("KDE", QStringLiteral("KDE"), s_noFiltering, minicliFilters);
0375     addRow("does/not/exist", QStringLiteral("does/not/exist"), s_noFiltering, minicliFilters);
0376     addRow("/does/not/exist", QStringLiteral("/does/not/exist"), KUriFilterData::LocalFile, minicliFilters);
0377     addRow("/does/not/exist#a", QStringLiteral("/does/not/exist#a"), KUriFilterData::LocalFile, minicliFilters);
0378     addRow("kbuildsycoca6 --help", QStringLiteral("kbuildsycoca6 --help"), KUriFilterData::Executable, minicliFilters); // the args are in argsAndOptions()
0379     addRow("/bin/sh", QStringLiteral("/bin/sh"), KUriFilterData::Executable, minicliFilters);
0380     addRow("/bin/sh -q -option arg1",
0381            QStringLiteral("/bin/sh -q -option arg1"),
0382            KUriFilterData::Executable,
0383            minicliFilters); // the args are in argsAndOptions()
0384 
0385     // Typing 'cp' or any other valid unix command in konq's location bar should result in
0386     // a search using the default search engine
0387     // 'ls' is a bit of a special case though, due to the toplevel domain called 'ls'
0388     addRow("cp",
0389            QStringLiteral("https://www.google.com/search?q=cp&ie=UTF-8"),
0390            KUriFilterData::NetProtocol,
0391            QStringList(),
0392            nullptr,
0393            false /* don't check for executables, see konq_misc.cc */);
0394 }
0395 
0396 void KUriFilterTest::executables()
0397 {
0398     runFilterTest();
0399 }
0400 
0401 void KUriFilterTest::environmentVariables_data()
0402 {
0403     setupColumns();
0404     // ENVIRONMENT variable
0405     qputenv("SOMEVAR", "/somevar");
0406     qputenv("ETC", "/etc");
0407 
0408     addRow("$SOMEVAR/kdelibs/kio", "/somevar/kdelibs/kio", KUriFilterData::LocalFile); // note: this dir doesn't exist...
0409     addRow("$ETC/passwd", QStringLiteral("/etc/passwd"), KUriFilterData::LocalFile);
0410     QString qtdocPath = qtdir + QStringLiteral("/doc/html/functions.html");
0411     if (QFile::exists(qtdocPath)) {
0412         QString expectedUrl = QUrl::fromLocalFile(qtdocPath).toString() + "#s";
0413         addRow("$QTDIR/doc/html/functions.html#s", expectedUrl.toUtf8(), KUriFilterData::LocalFile);
0414     }
0415     addRow("http://www.kde.org/$USER", QStringLiteral("http://www.kde.org/$USER"), KUriFilterData::NetProtocol); // no expansion
0416 
0417     addRow("$DATAHOME", datahome, KUriFilterData::LocalDir);
0418     QDir().mkpath(datahome + QStringLiteral("/urifilter/a+plus"));
0419     addRow("$DATAHOME/urifilter/a+plus", datahome + QStringLiteral("/urifilter/a+plus"), KUriFilterData::LocalDir);
0420 
0421     // BR 27788
0422     QDir().mkpath(datahome + QStringLiteral("/Dir With Space"));
0423     addRow("$DATAHOME/Dir With Space", datahome + QStringLiteral("/Dir With Space"), KUriFilterData::LocalDir);
0424 
0425     // support for name filters (BR 93825)
0426     addRow("$DATAHOME/*.txt", datahome + QStringLiteral("/*.txt"), KUriFilterData::LocalDir);
0427     addRow("$DATAHOME/[a-b]*.txt", datahome + QStringLiteral("/[a-b]*.txt"), KUriFilterData::LocalDir);
0428     addRow("$DATAHOME/a?c.txt", datahome + QStringLiteral("/a?c.txt"), KUriFilterData::LocalDir);
0429     addRow("$DATAHOME/?c.txt", datahome + QStringLiteral("/?c.txt"), KUriFilterData::LocalDir);
0430     // but let's check that a directory with * in the name still works
0431     QDir().mkpath(datahome + QStringLiteral("/share/Dir*With*Stars"));
0432     addRow("$DATAHOME/Dir*With*Stars", datahome + QStringLiteral("/Dir*With*Stars"), KUriFilterData::LocalDir);
0433     QDir().mkpath(datahome + QStringLiteral("/Dir?QuestionMark"));
0434     addRow("$DATAHOME/Dir?QuestionMark", datahome + QStringLiteral("/Dir?QuestionMark"), KUriFilterData::LocalDir);
0435     QDir().mkpath(datahome + QStringLiteral("/Dir[Bracket"));
0436     addRow("$DATAHOME/Dir[Bracket", datahome + QStringLiteral("/Dir[Bracket"), KUriFilterData::LocalDir);
0437 
0438     addRow("$HOME/$KDEDIR/kdebase/kcontrol/ebrowsing", "", KUriFilterData::LocalFile);
0439     addRow("$1/$2/$3",
0440            QStringLiteral("https://www.google.com/search?q=%241%2F%242%2F%243&ie=UTF-8"),
0441            KUriFilterData::NetProtocol); // can be used as bogus or valid test. Currently triggers default search, i.e. google
0442     addRow("$$$$", QStringLiteral("https://www.google.com/search?q=%24%24%24%24&ie=UTF-8"), KUriFilterData::NetProtocol); // worst case scenarios.
0443 
0444     if (!qtdir.isEmpty()) {
0445         addRow("$QTDIR", qtdir, KUriFilterData::LocalDir, QStringList(QStringLiteral("kshorturifilter"))); // use specific filter.
0446     }
0447     addRow("$HOME", home, KUriFilterData::LocalDir, QStringList(QStringLiteral("kshorturifilter"))); // use specific filter.
0448 }
0449 
0450 void KUriFilterTest::environmentVariables()
0451 {
0452     runFilterTest();
0453 }
0454 
0455 void KUriFilterTest::internetKeywords_data()
0456 {
0457     setupColumns();
0458     addRow(QString::asprintf("gg%cfoo bar", s_delimiter).toUtf8(),
0459            QStringLiteral("https://www.google.com/search?q=foo%20bar&ie=UTF-8"),
0460            KUriFilterData::NetProtocol);
0461     addRow("!gg foo bar", QStringLiteral("https://www.google.com/search?q=foo%20bar&ie=UTF-8"), KUriFilterData::NetProtocol);
0462     addRow("foo !gg bar", QStringLiteral("https://www.google.com/search?q=foo%20bar&ie=UTF-8"), KUriFilterData::NetProtocol);
0463     addRow("foo bar!gg", QStringLiteral("https://www.google.com/search?q=foo%20bar&ie=UTF-8"), KUriFilterData::NetProtocol);
0464     addRow("wp bar!gg", QStringLiteral("https://www.google.com/search?q=wp%20bar&ie=UTF-8"), KUriFilterData::NetProtocol);
0465     addRow(QString::asprintf("bug%c55798", s_delimiter).toUtf8(),
0466            QStringLiteral("https://bugs.kde.org/buglist.cgi?quicksearch=55798"),
0467            KUriFilterData::NetProtocol);
0468 
0469     // See https://bugs.kde.org/show_bug.cgi?id=437660
0470     addRow(QString::asprintf("bug%c55798!does_not_exist", s_delimiter).toUtf8(),
0471            QStringLiteral("https://bugs.kde.org/buglist.cgi?quicksearch=55798%21does_not_exist"),
0472            KUriFilterData::NetProtocol);
0473 
0474     addRow(QString::asprintf("gg%cC++", s_delimiter).toUtf8(), QStringLiteral("https://www.google.com/search?q=C%2B%2B&ie=UTF-8"), KUriFilterData::NetProtocol);
0475     addRow(QString::asprintf("gg%cC#", s_delimiter).toUtf8(), QStringLiteral("https://www.google.com/search?q=C%23&ie=UTF-8"), KUriFilterData::NetProtocol);
0476     addRow(QString::asprintf("ya%cfoo bar was here", s_delimiter).toUtf8(), nullptr, -1); // this triggers default search, i.e. google
0477     addRow(QString::asprintf("gg%cwww.kde.org", s_delimiter).toUtf8(),
0478            QStringLiteral("https://www.google.com/search?q=www.kde.org&ie=UTF-8"),
0479            KUriFilterData::NetProtocol);
0480     addRow(QStringLiteral("gg%1é").arg(s_delimiter).toUtf8() /*eaccent in utf8*/,
0481            QStringLiteral("https://www.google.com/search?q=%C3%A9&ie=UTF-8"),
0482            KUriFilterData::NetProtocol);
0483     addRow(QStringLiteral("gg%1прйвет").arg(s_delimiter).toUtf8() /* greetings in russian utf-8*/,
0484            QStringLiteral("https://www.google.com/search?q=%D0%BF%D1%80%D0%B9%D0%B2%D0%B5%D1%82&ie=UTF-8"),
0485            KUriFilterData::NetProtocol);
0486 }
0487 
0488 void KUriFilterTest::internetKeywords()
0489 {
0490     runFilterTest();
0491 }
0492 
0493 void KUriFilterTest::localdomain()
0494 {
0495     const QString host = QHostInfo::localHostName();
0496     if (host.isEmpty()) {
0497         const QString expected = QLatin1String("http://") + host;
0498         runFilterTest(host, expected, KUriFilterData::NetProtocol, QStringList{QStringLiteral("localdomainurifilter")}, nullptr, false);
0499     }
0500 }
0501 
0502 void KUriFilterTest::relativeGoUp()
0503 {
0504     // When the text is "../"
0505     KUriFilterData filteredData(QStringLiteral("../"));
0506     filteredData.setCheckForExecutables(false);
0507     // Using kshorturifilter
0508     const auto filtersList = QStringList{QStringLiteral("kshorturifilter")};
0509     // Then the text isn't filtered and returned as-is
0510     QVERIFY(!KUriFilter::self()->filterUri(filteredData, filtersList));
0511 }
0512 
0513 #include "moc_kurifiltertest.cpp"