From 329e84b859525482a5a293ff8372bef95dc2f644 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A9ven=20Car?= Date: Mon, 10 Aug 2026 10:13:14 +0000 Subject: [PATCH 1/3] openurljob: open a shell script rather than refuse it as a program shared-mime-info 2.5.1 renamed application/x-shellscript to text/x-shellscript and left application/x-executable as its only parent, where a script used to be a kind of text/plain as well. Being both is how a script was told apart from a binary, so a shell script now reads as a binary and opening one where running is not allowed ends in an error rather than in the editor. The same loss took the text editors away from scripts, so one that nothing else claims is opened with whatever opens text. BUG: 522948 FIXED-IN: 6.30 --- src/gui/openurljob.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/gui/openurljob.cpp b/src/gui/openurljob.cpp index 5fc0b93261..f3701661e4 100644 --- a/src/gui/openurljob.cpp +++ b/src/gui/openurljob.cpp @@ -367,7 +367,13 @@ static bool isBinary(const QMimeType &mimeType) // e.g. ".sh", ".csh", ".py", ".js" static bool isTextScript(const QMimeType &mimeType) { - return (mimeType.inherits(QStringLiteral("application/x-executable")) && mimeType.inherits(QStringLiteral("text/plain"))); + if (!mimeType.inherits(QStringLiteral("application/x-executable"))) { + return false; + } + + // A type under text/ holds text whether or not the database spells out that it is a + // kind of text/plain, and shared-mime-info stopped saying so for shell scripts. + return mimeType.inherits(QStringLiteral("text/plain")) || mimeType.name().startsWith(QLatin1String("text/")); } // Helper function that returns whether a file has the execute bit set or not. @@ -645,6 +651,16 @@ void KIO::OpenUrlJobPrivate::handleScripts() void KIO::OpenUrlJobPrivate::openInPreferredApp() { KService::Ptr service = KApplicationTrader::preferredService(m_mimeTypeName); + if (!service) { + // A script is text, and the program someone picked for text is the one to show it + // to them in. The MIME database used to say a script is a kind of text/plain and + // no longer does for every script, so the text program is asked for by name. + const QMimeType mimeType = QMimeDatabase().mimeTypeForName(m_mimeTypeName); + if (isTextScript(mimeType)) { + service = KApplicationTrader::preferredService(QStringLiteral("text/plain")); + } + } + if (service) { // If file mimetype is set to xdg-open or kde-open, the file will be opened in endless loop // In these cases, showOpenWithDialog instead -- GitLab From 71fcfa96e292a15d395b2c756bb03afff1063d90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A9ven=20Car?= Date: Mon, 10 Aug 2026 10:13:14 +0000 Subject: [PATCH 2/3] autotests: ask the mime database which type a test means shared-mime-info 2.5.1 made application/x-shellscript another name of text/x-shellscript and made text/x-csrc a kind of text/x-c++src. Tests that spell those names out fail on the renames alone, although the files they look at are the same as ever. --- autotests/kdirlistertest.cpp | 4 +++- autotests/mimetypefinderjobtest.cpp | 9 +++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/autotests/kdirlistertest.cpp b/autotests/kdirlistertest.cpp index d45472757a..4fa88be50b 100644 --- a/autotests/kdirlistertest.cpp +++ b/autotests/kdirlistertest.cpp @@ -1536,7 +1536,9 @@ void KDirListerTest::testMimeFilter_data() const QStringList files = {"bla.txt", "main.cpp", "main.c", "image.jpeg", "picture.png"}; - QTest::newRow("single_file_exact_mimetype") << files << QStringList{"text/x-c++src"} << QStringList{"main.cpp"}; + // Not a C or C++ source: shared-mime-info made C source a kind of C++ source, so a + // filter on one of them takes both and says nothing about matching a type exactly. + QTest::newRow("single_file_exact_mimetype") << files << QStringList{"image/png"} << QStringList{"picture.png"}; QTest::newRow("inherited_mimetype") << files << QStringList{"text/plain"} << QStringList{"bla.txt", "main.cpp", "main.c"}; QTest::newRow("no_match") << files << QStringList{"audio/flac"} << QStringList{}; QTest::newRow("glob") << files << QStringList{"image/*"} << QStringList{"image.jpeg", "picture.png"}; diff --git a/autotests/mimetypefinderjobtest.cpp b/autotests/mimetypefinderjobtest.cpp index 9a41ac7fc3..0be00dd119 100644 --- a/autotests/mimetypefinderjobtest.cpp +++ b/autotests/mimetypefinderjobtest.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -74,7 +75,11 @@ void MimeTypeFinderJobTest::determineMimeType() // When running a MimeTypeFinderJob KIO::MimeTypeFinderJob *job = new KIO::MimeTypeFinderJob(url, this); QVERIFY2(job->exec(), qPrintable(job->errorString())); - QCOMPARE(job->mimeType(), mimeType); + // The database gives a type one name of its own and knows it under others as well, so + // both sides are asked which type they mean rather than compared as they are spelled. + QMimeDatabase db; + const QString expected = db.mimeTypeForName(mimeType).name(); + QCOMPARE(db.mimeTypeForName(job->mimeType()).name(), expected); // Check that the result is the same when accessing the source, skip on Windows #ifndef Q_OS_WIN @@ -86,7 +91,7 @@ void MimeTypeFinderJobTest::determineMimeType() job = new KIO::MimeTypeFinderJob(linkUrl, this); QVERIFY2(job->exec(), qPrintable(job->errorString())); - QCOMPARE(job->mimeType(), mimeType); + QCOMPARE(db.mimeTypeForName(job->mimeType()).name(), expected); #endif } From 92594ac39daeba6ffe117812055fcde2ae50d6b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A9ven=20Car?= Date: Tue, 4 Aug 2026 16:00:51 +0000 Subject: [PATCH 3/3] openurljobtest: wait for the launched processes before ending a test A KProcessRunner watches its process until it exits, then deletes itself. A test that ends before that leaves the runner behind, and the CI leak checker reports it, failing the test even though every case passed. Each case now waits for the runners to be gone, as applicationlauncherjobtest and commandlauncherjobtest already do. --- autotests/openurljobtest.cpp | 7 +++++++ autotests/openurljobtest.h | 1 + 2 files changed, 8 insertions(+) diff --git a/autotests/openurljobtest.cpp b/autotests/openurljobtest.cpp index 456c086c1a..0cee9a6e79 100644 --- a/autotests/openurljobtest.cpp +++ b/autotests/openurljobtest.cpp @@ -91,6 +91,13 @@ void OpenUrlJobTest::init() QFile::remove(m_tempDir.path() + "/dest"); } +void OpenUrlJobTest::cleanup() +{ + // A launched process is watched by a runner that deletes itself once the process is gone. A test that + // ends before that leaves the runner behind, which the leak checker of the CI reports. + QTRY_COMPARE(KProcessRunner::instanceCount(), 0); +} + static void createSrcFile(const QString &path) { QFile srcFile(path); diff --git a/autotests/openurljobtest.h b/autotests/openurljobtest.h index b874d52e34..4c046b94e1 100644 --- a/autotests/openurljobtest.h +++ b/autotests/openurljobtest.h @@ -20,6 +20,7 @@ private Q_SLOTS: void initTestCase(); void cleanupTestCase(); void init(); + void cleanup(); void startProcess_data(); void startProcess(); -- GitLab