File indexing completed on 2024-04-28 15:19:33
0001 /* 0002 SPDX-FileCopyrightText: 2006 David Faure <faure@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-only 0005 */ 0006 #include "kdesktopfiletest.h" 0007 #include "helper.h" 0008 #include <kconfiggroup.h> 0009 #include <ksharedconfig.h> 0010 #include <qtemporaryfile.h> 0011 0012 #include "kdesktopfile.h" 0013 0014 #include <QTest> 0015 0016 #if defined(Q_OS_UNIX) 0017 #include <unistd.h> 0018 #endif 0019 0020 QTEST_MAIN(KDesktopFileTest) 0021 0022 void KDesktopFileTest::initTestCase() 0023 { 0024 QStandardPaths::setTestModeEnabled(true); 0025 0026 KConfigGroup actionRestrictions(KSharedConfig::openConfig(), "KDE Action Restrictions"); 0027 actionRestrictions.writeEntry("someBlockedAction", false); 0028 } 0029 0030 void KDesktopFileTest::testRead() 0031 { 0032 QTemporaryFile file(QStringLiteral("testReadXXXXXX.desktop")); 0033 QVERIFY(file.open()); 0034 const QString fileName = file.fileName(); 0035 QTextStream ts(&file); 0036 ts << "[Desktop Entry]\n" 0037 "Type= Application\n" 0038 "Name=My Application\n" 0039 "Icon = foo\n" 0040 "MimeType =text/plain;image/png;\n" 0041 "\n"; 0042 file.close(); 0043 QVERIFY(QFile::exists(fileName)); 0044 QVERIFY(KDesktopFile::isDesktopFile(fileName)); 0045 KDesktopFile df(fileName); 0046 QCOMPARE(df.readType(), QString::fromLatin1("Application")); 0047 QVERIFY(df.hasApplicationType()); 0048 QCOMPARE(df.readName(), QString::fromLatin1("My Application")); 0049 QCOMPARE(df.readIcon(), QString::fromLatin1("foo")); 0050 QCOMPARE(df.readMimeTypes(), QStringList() << QString::fromLatin1("text/plain") << QString::fromLatin1("image/png")); 0051 QVERIFY(!df.hasLinkType()); 0052 QCOMPARE(df.fileName(), QFileInfo(fileName).canonicalFilePath()); 0053 } 0054 0055 #if KCONFIGCORE_ENABLE_DEPRECATED_SINCE(5, 0) 0056 void KDesktopFileTest::testReadDirectory() 0057 { 0058 QTemporaryFile file(QStringLiteral("testReadDirectoryXXXXXX.directory")); 0059 QVERIFY(file.open()); 0060 const QString fileName = file.fileName(); 0061 QTextStream ts(&file); 0062 ts << "[Desktop Entry]\n" 0063 "Type=Directory\n" 0064 "SortOrder=2.desktop;1.desktop;\n" 0065 "\n"; 0066 file.close(); 0067 QVERIFY(QFile::exists(fileName)); 0068 KDesktopFile df(fileName); 0069 QCOMPARE(df.readType(), QString::fromLatin1("Directory")); 0070 QCOMPARE(df.sortOrder(), QStringList() << QString::fromLatin1("2.desktop") << QString::fromLatin1("1.desktop")); 0071 } 0072 #endif 0073 0074 void KDesktopFileTest::testReadLocalized_data() 0075 { 0076 QTest::addColumn<QLocale>("locale"); 0077 QTest::addColumn<QString>("translation"); 0078 0079 const QString german = QStringLiteral("Meine Anwendung"); 0080 const QString swiss = QStringLiteral("Mein Anwendungsli"); 0081 0082 QTest::newRow("de") << QLocale(QLocale::German) << german; 0083 QTest::newRow("de_DE") << QLocale(QStringLiteral("de_DE")) << german; 0084 QTest::newRow("de_DE@bayern") << QLocale(QStringLiteral("de_DE@bayern")) << german; 0085 QTest::newRow("de@bayern") << QLocale(QStringLiteral("de@bayern")) << german; 0086 QTest::newRow("de@freiburg") << QLocale(QStringLiteral("de@freiburg")) << QStringLiteral("Mein Anwendungsle"); 0087 // For CH we have a special translation 0088 QTest::newRow("de_CH") << QLocale(QLocale::German, QLocale::Switzerland) << swiss; 0089 QTest::newRow("de_CH@bern") << QLocale(QStringLiteral("de_CH@bern")) << swiss; 0090 // Austria should fall back to "de" 0091 QTest::newRow("de_AT") << QLocale(QLocale::German, QLocale::Austria) << german; 0092 QTest::newRow("de_AT@tirol") << QLocale(QStringLiteral("de_AT@tirol")) << german; 0093 // no translation for French 0094 QTest::newRow("fr") << QLocale(QLocale::French) << QStringLiteral("My Application"); 0095 } 0096 0097 void KDesktopFileTest::testReadLocalized() 0098 { 0099 QTemporaryFile file(QStringLiteral("testReadLocalizedXXXXXX.desktop")); 0100 QVERIFY(file.open()); 0101 const QString fileName = file.fileName(); 0102 QTextStream ts(&file); 0103 ts << "[Desktop Entry]\n" 0104 "Type=Application\n" 0105 "Name=My Application\n" 0106 "Name[de]=Meine Anwendung\n" 0107 "Name[de@freiburg]=Mein Anwendungsle\n" 0108 "Name[de_CH]=Mein Anwendungsli\n" 0109 "Icon=foo\n" 0110 "\n"; 0111 file.close(); 0112 QVERIFY(QFile::exists(fileName)); 0113 QVERIFY(KDesktopFile::isDesktopFile(fileName)); 0114 0115 DefaultLocale defaultLocale; 0116 0117 QFETCH(QLocale, locale); 0118 QLocale::setDefault(locale); 0119 KDesktopFile df(fileName); 0120 0121 QEXPECT_FAIL("de@freiburg", "QLocale doesn't support modifiers", Continue); 0122 QTEST(df.readName(), "translation"); 0123 } 0124 0125 void KDesktopFileTest::testSuccessfulTryExec() 0126 { 0127 QTemporaryFile file; 0128 QVERIFY(file.open()); 0129 const QString fileName = file.fileName(); 0130 QTextStream ts(&file); 0131 ts << "[Desktop Entry]\n" 0132 "TryExec=whoami\n" 0133 "\n"; 0134 file.close(); 0135 QVERIFY(QFile::exists(fileName)); 0136 KDesktopFile df(fileName); 0137 QCOMPARE(df.tryExec(), true); 0138 } 0139 0140 void KDesktopFileTest::testUnsuccessfulTryExec() 0141 { 0142 QTemporaryFile file; 0143 QVERIFY(file.open()); 0144 const QString fileName = file.fileName(); 0145 QTextStream ts(&file); 0146 ts << "[Desktop Entry]\n" 0147 "TryExec=/does/not/exist\n" 0148 "\n"; 0149 file.close(); 0150 QVERIFY(QFile::exists(fileName)); 0151 KDesktopFile df(fileName); 0152 QCOMPARE(df.tryExec(), false); 0153 } 0154 0155 void KDesktopFileTest::testActionGroup() 0156 { 0157 QTemporaryFile file; 0158 QVERIFY(file.open()); 0159 const QString fileName = file.fileName(); 0160 QTextStream ts(&file); 0161 ts << "[Desktop Entry]\n" 0162 // make sure escaping of ';' using "\;" works 0163 "Actions=encrypt;semi\\;colon;decrypt;\n" 0164 "[Desktop Action encrypt]\n" 0165 "Name=Encrypt file\n" 0166 "[Desktop Action decrypt]\n" 0167 "Name=Decrypt file\n" 0168 // no escaping needed in group header 0169 "[Desktop Action semi;colon]\n" 0170 "Name=With semicolon\n" 0171 "\n"; 0172 file.close(); 0173 QVERIFY(QFile::exists(fileName)); 0174 KDesktopFile df(fileName); 0175 QCOMPARE(df.readType(), QString()); 0176 QCOMPARE(df.fileName(), QFileInfo(fileName).canonicalFilePath()); 0177 QCOMPARE(df.readActions(), (QStringList{QStringLiteral("encrypt"), QStringLiteral("semi;colon"), QStringLiteral("decrypt")})); 0178 QCOMPARE(df.hasActionGroup(QStringLiteral("encrypt")), true); 0179 QCOMPARE(df.hasActionGroup(QStringLiteral("semi;colon")), true); 0180 QCOMPARE(df.hasActionGroup(QStringLiteral("decrypt")), true); 0181 QCOMPARE(df.hasActionGroup(QStringLiteral("doesnotexist")), false); 0182 KConfigGroup cg = df.actionGroup(QStringLiteral("encrypt")); 0183 QVERIFY(cg.hasKey("Name")); 0184 QCOMPARE(cg.readEntry("Name"), QStringLiteral("Encrypt file")); 0185 cg = df.actionGroup(QStringLiteral("decrypt")); 0186 QVERIFY(cg.hasKey("Name")); 0187 QCOMPARE(cg.readEntry("Name"), QStringLiteral("Decrypt file")); 0188 cg = df.actionGroup(QStringLiteral("semi;colon")); 0189 QVERIFY(cg.hasKey("Name")); 0190 QCOMPARE(cg.readEntry("Name"), QStringLiteral("With semicolon")); 0191 } 0192 0193 void KDesktopFileTest::testIsAuthorizedDesktopFile() 0194 { 0195 QTemporaryFile file(QStringLiteral("testAuthXXXXXX.desktop")); 0196 QVERIFY(file.open()); 0197 const QString fileName = file.fileName(); 0198 QTextStream ts(&file); 0199 ts << "[Desktop Entry]\n" 0200 "Type=Application\n" 0201 "Name=My Application\n" 0202 "Exec=kfoo\n" 0203 "\n"; 0204 file.close(); 0205 QVERIFY(QFile::exists(fileName)); 0206 0207 #if defined(Q_OS_UNIX) 0208 // Try to fix test failing in docker running as root 0209 const QFileInfo entryInfo(fileName); 0210 if (entryInfo.ownerId() == 0) { 0211 // try to find a valid user/group combination 0212 for (int i = 1; i < 100; ++i) { 0213 if (chown(fileName.toLocal8Bit().constData(), i, i) == 0) { 0214 break; 0215 } 0216 } 0217 const QFileInfo entryInfo1(fileName); 0218 if (entryInfo1.ownerId() == 0) { 0219 QEXPECT_FAIL("", "Running test as root and could not find a non root user to change the ownership of the file too", Continue); 0220 } 0221 } 0222 #endif 0223 0224 QVERIFY(!KDesktopFile::isAuthorizedDesktopFile(fileName)); 0225 0226 const QString installedFile = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("/kservices5/http_cache_cleaner.desktop")); 0227 if (!installedFile.isEmpty()) { 0228 QVERIFY(KDesktopFile::isAuthorizedDesktopFile(installedFile)); 0229 } else { 0230 qWarning("Skipping test for http_cache_cleaner.desktop, not found. kio not installed?"); 0231 } 0232 0233 const QString autostartFile = QStandardPaths::locate(QStandardPaths::GenericConfigLocation, QStringLiteral("autostart/plasma-desktop.desktop")); 0234 if (!autostartFile.isEmpty()) { 0235 QVERIFY(KDesktopFile::isAuthorizedDesktopFile(autostartFile)); 0236 } else { 0237 qWarning("Skipping test for plasma-desktop.desktop, not found. kde-workspace not installed?"); 0238 } 0239 } 0240 0241 void KDesktopFileTest::testTryExecWithAuthorizeAction() 0242 { 0243 { 0244 QTemporaryFile file(QStringLiteral("testAuthActionXXXXXX.desktop")); 0245 QVERIFY(file.open()); 0246 const QString fileName = file.fileName(); 0247 QTextStream ts(&file); 0248 ts << "[Desktop Entry]\n" 0249 "Type=Application\n" 0250 "Name=My Application\n" 0251 "Exec=kfoo\n" 0252 "TryExec="; 0253 #ifdef Q_OS_WIN 0254 ts << "cmd\n"; 0255 #else 0256 ts << "bash\n"; 0257 #endif 0258 ts << "X-KDE-AuthorizeAction=someAction" 0259 "\n"; 0260 file.close(); 0261 0262 KDesktopFile desktopFile(fileName); 0263 QVERIFY(desktopFile.tryExec()); 0264 } 0265 { 0266 QTemporaryFile file(QStringLiteral("testAuthActionXXXXXX.desktop")); 0267 QVERIFY(file.open()); 0268 const QString fileName = file.fileName(); 0269 QTextStream ts(&file); 0270 ts << "[Desktop Entry]\n" 0271 "Type=Application\n" 0272 "Name=My Application\n" 0273 "Exec=kfoo\n" 0274 "TryExec=bash\n" 0275 "X-KDE-AuthorizeAction=someBlockedAction" 0276 "\n"; 0277 file.close(); 0278 0279 KDesktopFile desktopFile(fileName); 0280 QVERIFY(!desktopFile.tryExec()); 0281 } 0282 } 0283 0284 void KDesktopFileTest::testLocateLocal_data() 0285 { 0286 const QString systemConfigLocation = QStandardPaths::standardLocations(QStandardPaths::GenericConfigLocation).constLast(); 0287 const QString writableConfigLocation = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); 0288 const QString systemDataLocation = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation).constLast(); 0289 const QString writableDataLocation = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation); 0290 0291 QTest::addColumn<QString>("path"); 0292 QTest::addColumn<QString>("result"); 0293 0294 QTest::newRow("configLocation, system-wide") << systemConfigLocation + QLatin1String{"/test.desktop"} 0295 << writableConfigLocation + QLatin1String{"/test.desktop"}; 0296 QTest::newRow("autostart, system-wide") << systemConfigLocation + QLatin1String{"/autostart/test.desktop"} 0297 << writableConfigLocation + QLatin1String{"/autostart/test.desktop"}; 0298 QTest::newRow("dataLocation, system-wide") << systemDataLocation + QLatin1String{"/test.desktop"} << writableDataLocation + QLatin1String{"/test.desktop"}; 0299 QTest::newRow("applications, system-wide") << systemDataLocation + QLatin1String{"/applications/test.desktop"} 0300 << writableDataLocation + QLatin1String{"/applications/test.desktop"}; 0301 QTest::newRow("desktop-directories, system-wide") << systemDataLocation + QLatin1String{"/desktop-directories/test.directory"} 0302 << writableDataLocation + QLatin1String{"/desktop-directories/test.directory"}; 0303 QTest::newRow("configLocation, writable") << writableConfigLocation + QLatin1String{"/test.desktop"} 0304 << writableConfigLocation + QLatin1String{"/test.desktop"}; 0305 QTest::newRow("autostart, writable") << writableConfigLocation + QLatin1String{"/autostart/test.desktop"} 0306 << writableConfigLocation + QLatin1String{"/autostart/test.desktop"}; 0307 QTest::newRow("dataLocation, writable") << writableDataLocation + QLatin1String{"/test.desktop"} << writableDataLocation + QLatin1String{"/test.desktop"}; 0308 QTest::newRow("applications, writable") << writableDataLocation + QLatin1String{"/applications/test.desktop"} 0309 << writableDataLocation + QLatin1String{"/applications/test.desktop"}; 0310 QTest::newRow("desktop-directories, writable") << writableDataLocation + QLatin1String{"/desktop-directories/test.directory"} 0311 << writableDataLocation + QLatin1String{"/desktop-directories/test.directory"}; 0312 QTest::newRow("unknown location") << QStringLiteral("/test.desktop") << writableDataLocation + QLatin1String{"/test.desktop"}; 0313 } 0314 0315 void KDesktopFileTest::testLocateLocal() 0316 { 0317 QFETCH(QString, path); 0318 QFETCH(QString, result); 0319 0320 QCOMPARE(KDesktopFile::locateLocal(path), result); 0321 } 0322 0323 #include "moc_kdesktopfiletest.cpp"