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