1 |
commit: 79bc863dc74675a14f4818e979cab9e62557c369 |
2 |
Author: Andreas Sturmlechner <asturm <AT> gentoo <DOT> org> |
3 |
AuthorDate: Mon Sep 28 22:41:56 2020 +0000 |
4 |
Commit: Andreas Sturmlechner <asturm <AT> gentoo <DOT> org> |
5 |
CommitDate: Tue Sep 29 12:46:43 2020 +0000 |
6 |
URL: https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=79bc863d |
7 |
|
8 |
kde-frameworks/kio: OpenUrlJob: handle all text scripts consistently |
9 |
|
10 |
Upstream commit fdd7c47c85d5d6dbf21e05e7a0d6afcf383f1d24 |
11 |
|
12 |
KDE-Bug: https://bugs.kde.org/show_bug.cgi?id=425829 |
13 |
Package-Manager: Portage-3.0.8, Repoman-3.0.1 |
14 |
Signed-off-by: Andreas Sturmlechner <asturm <AT> gentoo.org> |
15 |
|
16 |
...o-5.74.1-handle-shell-scripts-consistenty.patch | 310 +++++++++++++++++++++ |
17 |
kde-frameworks/kio/kio-5.74.1-r1.ebuild | 5 +- |
18 |
2 files changed, 314 insertions(+), 1 deletion(-) |
19 |
|
20 |
diff --git a/kde-frameworks/kio/files/kio-5.74.1-handle-shell-scripts-consistenty.patch b/kde-frameworks/kio/files/kio-5.74.1-handle-shell-scripts-consistenty.patch |
21 |
new file mode 100644 |
22 |
index 00000000000..f5e17f338fd |
23 |
--- /dev/null |
24 |
+++ b/kde-frameworks/kio/files/kio-5.74.1-handle-shell-scripts-consistenty.patch |
25 |
@@ -0,0 +1,310 @@ |
26 |
+From fdd7c47c85d5d6dbf21e05e7a0d6afcf383f1d24 Mon Sep 17 00:00:00 2001 |
27 |
+From: Ahmad Samir <a.samirh78@×××××.com> |
28 |
+Date: Tue, 15 Sep 2020 20:06:49 +0200 |
29 |
+Subject: [PATCH] OpenUrlJob: handle all text scripts consistently |
30 |
+ |
31 |
+Previously we only handled application/x-shellscript, but there are other |
32 |
+scripts; a script is technically a file that inherits both text/plain and |
33 |
+application/x-executable, e.g. .sh, .csh, .py, perl scripts ...etc. Treat |
34 |
+all those mime types the way we handled shell scripts: |
35 |
+ - if it's not a local url, or isn't executable we open it in the preferred |
36 |
+ text editor |
37 |
+ - if it's executable either show the OpenOrExecute dialog or execute |
38 |
+ directly depending on how the job is configured |
39 |
+ |
40 |
+The mimetype world is a confusing one: |
41 |
+ - Executables, this includes .exe files (MS Windows); and "application/x-executable" |
42 |
+ and "application/x-sharedlib", this depends on various parameters (e.g. |
43 |
+ stripped executables are x-sharedlib, the same executable if not stripped |
44 |
+ is x-executable...) |
45 |
+ - Scripts: shell, python, perl... etc scripts, which are text files that |
46 |
+ can be executed or opened as text. |
47 |
+ |
48 |
+Adjust the unit test. |
49 |
+ |
50 |
+BUG: 425829 |
51 |
+BUG: 425177 |
52 |
+FIXED-IN: 5.75 |
53 |
+--- |
54 |
+ autotests/openurljobtest.cpp | 56 +++++++++++++++++++++++-------- |
55 |
+ autotests/openurljobtest.h | 2 ++ |
56 |
+ src/gui/openurljob.cpp | 65 ++++++++++++++++++++++-------------- |
57 |
+ 3 files changed, 85 insertions(+), 38 deletions(-) |
58 |
+ |
59 |
+diff --git a/autotests/openurljobtest.cpp b/autotests/openurljobtest.cpp |
60 |
+index 2f2ef8ad..ed2211a8 100644 |
61 |
+--- a/autotests/openurljobtest.cpp |
62 |
++++ b/autotests/openurljobtest.cpp |
63 |
+@@ -103,14 +103,13 @@ void OpenUrlJobTest::initTestCase() |
64 |
+ KConfigGroup grp = mimeAppsCfg.group("Default Applications"); |
65 |
+ grp.writeEntry("text/plain", s_tempServiceName); |
66 |
+ grp.writeEntry("text/html", s_tempServiceName); |
67 |
+- grp.writeEntry("application/x-shellscript", s_tempServiceName); |
68 |
+ grp.sync(); |
69 |
+ |
70 |
+- for (const char *mimeType : {"text/plain", "application/x-shellscript"}) { |
71 |
+- KService::Ptr preferredTextEditor = KApplicationTrader::preferredService(QString::fromLatin1(mimeType)); |
72 |
+- QVERIFY(preferredTextEditor); |
73 |
+- QCOMPARE(preferredTextEditor->entryPath(), m_fakeService); |
74 |
+- } |
75 |
++ |
76 |
++ // "text/plain" encompasses all scripts (shell, python, perl) |
77 |
++ KService::Ptr preferredTextEditor = KApplicationTrader::preferredService(QStringLiteral("text/plain")); |
78 |
++ QVERIFY(preferredTextEditor); |
79 |
++ QCOMPARE(preferredTextEditor->entryPath(), m_fakeService); |
80 |
+ |
81 |
+ // As used for preferredService |
82 |
+ QVERIFY(KService::serviceByDesktopName("openurljobtest_service")); |
83 |
+@@ -230,17 +229,38 @@ void OpenUrlJobTest::invalidUrl() |
84 |
+ QCOMPARE(job2->errorString(), QStringLiteral("Malformed URL\n/pathonly")); |
85 |
+ } |
86 |
+ |
87 |
++void OpenUrlJobTest::refuseRunningNativeExecutables_data() |
88 |
++{ |
89 |
++ QTest::addColumn<QString>("mimeType"); |
90 |
++ |
91 |
++ // Executables under e.g. /usr/bin/ can be either of these two mimetypes |
92 |
++ // see https://gitlab.freedesktop.org/xdg/shared-mime-info/-/issues/11 |
93 |
++ QTest::newRow("x-sharedlib") << "application/x-sharedlib"; |
94 |
++ QTest::newRow("x-executable") << "application/x-executable"; |
95 |
++} |
96 |
++ |
97 |
+ void OpenUrlJobTest::refuseRunningNativeExecutables() |
98 |
+ { |
99 |
+- KIO::OpenUrlJob *job = new KIO::OpenUrlJob(QUrl::fromLocalFile(QCoreApplication::applicationFilePath()), QStringLiteral("application/x-executable"), this); |
100 |
++ QFETCH(QString, mimeType); |
101 |
++ |
102 |
++ KIO::OpenUrlJob *job = new KIO::OpenUrlJob(QUrl::fromLocalFile(QCoreApplication::applicationFilePath()), mimeType, this); |
103 |
+ QVERIFY(!job->exec()); |
104 |
+ QCOMPARE(job->error(), KJob::UserDefinedError); |
105 |
+ QVERIFY2(job->errorString().contains("For security reasons, launching executables is not allowed in this context."), qPrintable(job->errorString())); |
106 |
+ } |
107 |
+ |
108 |
++void OpenUrlJobTest::refuseRunningRemoteNativeExecutables_data() |
109 |
++{ |
110 |
++ QTest::addColumn<QString>("mimeType"); |
111 |
++ QTest::newRow("x-sharedlib") << "application/x-sharedlib"; |
112 |
++ QTest::newRow("x-executable") << "application/x-executable"; |
113 |
++} |
114 |
++ |
115 |
+ void OpenUrlJobTest::refuseRunningRemoteNativeExecutables() |
116 |
+ { |
117 |
+- KIO::OpenUrlJob *job = new KIO::OpenUrlJob(QUrl("protocol://host/path/exe"), QStringLiteral("application/x-executable"), this); |
118 |
++ QFETCH(QString, mimeType); |
119 |
++ |
120 |
++ KIO::OpenUrlJob *job = new KIO::OpenUrlJob(QUrl("protocol://host/path/exe"), mimeType, this); |
121 |
+ job->setRunExecutables(true); // even with this enabled, an error will occur |
122 |
+ QVERIFY(!job->exec()); |
123 |
+ QCOMPARE(job->error(), KJob::UserDefinedError); |
124 |
+@@ -273,8 +293,11 @@ void OpenUrlJobTest::runScript_data() |
125 |
+ { |
126 |
+ QTest::addColumn<QString>("mimeType"); |
127 |
+ |
128 |
++ // All text-based scripts inherit text/plain and application/x-executable, no need to test |
129 |
++ // all flavours (python, perl, lua, awk ...etc), this sample should be enough |
130 |
+ QTest::newRow("shellscript") << "application/x-shellscript"; |
131 |
+- QTest::newRow("native") << "application/x-executable"; |
132 |
++ QTest::newRow("pythonscript") << "text/x-python"; |
133 |
++ QTest::newRow("javascript") << "application/javascript"; |
134 |
+ } |
135 |
+ |
136 |
+ void OpenUrlJobTest::runScript() |
137 |
+@@ -305,16 +328,23 @@ void OpenUrlJobTest::runScript() |
138 |
+ |
139 |
+ void OpenUrlJobTest::runNativeExecutable_data() |
140 |
+ { |
141 |
++ QTest::addColumn<QString>("mimeType"); |
142 |
+ QTest::addColumn<bool>("withHandler"); |
143 |
+ QTest::addColumn<bool>("handlerRetVal"); |
144 |
+ |
145 |
+- QTest::newRow("no_handler") << false << false; |
146 |
+- QTest::newRow("handler_false") << true << false; |
147 |
+- QTest::newRow("handler_true") << true << true; |
148 |
++ QTest::newRow("no_handler_x-sharedlib") << "application/x-sharedlib" << false << false; |
149 |
++ QTest::newRow("handler_false_x-sharedlib") << "application/x-sharedlib" << true << false; |
150 |
++ QTest::newRow("handler_true_x-sharedlib") << "application/x-sharedlib" << true << true; |
151 |
++ |
152 |
++ QTest::newRow("no_handler_x-executable") << "application/x-executable" << false << false; |
153 |
++ QTest::newRow("handler_false_x-executable") << "application/x-executable" << true << false; |
154 |
++ QTest::newRow("handler_true_x-executable") << "application/x-executable" << true << true; |
155 |
++ |
156 |
+ } |
157 |
+ |
158 |
+ void OpenUrlJobTest::runNativeExecutable() |
159 |
+ { |
160 |
++ QFETCH(QString, mimeType); |
161 |
+ QFETCH(bool, withHandler); |
162 |
+ QFETCH(bool, handlerRetVal); |
163 |
+ |
164 |
+@@ -335,7 +365,7 @@ void OpenUrlJobTest::runNativeExecutable() |
165 |
+ KIO::setDefaultUntrustedProgramHandler(withHandler ? &s_handler : nullptr); |
166 |
+ |
167 |
+ // When using OpenUrlJob to run the executable |
168 |
+- KIO::OpenUrlJob *job = new KIO::OpenUrlJob(QUrl::fromLocalFile(scriptFile), QStringLiteral("application/x-executable"), this); |
169 |
++ KIO::OpenUrlJob *job = new KIO::OpenUrlJob(QUrl::fromLocalFile(scriptFile), mimeType, this); |
170 |
+ job->setRunExecutables(true); // startProcess tests the case where this isn't set |
171 |
+ const bool success = job->exec(); |
172 |
+ |
173 |
+diff --git a/autotests/openurljobtest.h b/autotests/openurljobtest.h |
174 |
+index e71987d9..f5b9a5be 100644 |
175 |
+--- a/autotests/openurljobtest.h |
176 |
++++ b/autotests/openurljobtest.h |
177 |
+@@ -26,7 +26,9 @@ private Q_SLOTS: |
178 |
+ |
179 |
+ void noServiceNoHandler(); |
180 |
+ void invalidUrl(); |
181 |
++ void refuseRunningNativeExecutables_data(); |
182 |
+ void refuseRunningNativeExecutables(); |
183 |
++ void refuseRunningRemoteNativeExecutables_data(); |
184 |
+ void refuseRunningRemoteNativeExecutables(); |
185 |
+ void notAuthorized(); |
186 |
+ void runScript_data(); |
187 |
+diff --git a/src/gui/openurljob.cpp b/src/gui/openurljob.cpp |
188 |
+index 8ac187b4..3e35c95c 100644 |
189 |
+--- a/src/gui/openurljob.cpp |
190 |
++++ b/src/gui/openurljob.cpp |
191 |
+@@ -73,9 +73,9 @@ public: |
192 |
+ |
193 |
+ private: |
194 |
+ void executeCommand(); |
195 |
+- void handleExecutables(const QMimeType &mimeType); |
196 |
++ void handleBinaries(const QMimeType &mimeType); |
197 |
+ void handleDesktopFiles(); |
198 |
+- void handleShellscripts(); |
199 |
++ void handleScripts(); |
200 |
+ void openInPreferredApp(); |
201 |
+ void runLink(const QString &filePath, const QString &urlStr, const QString &optionalServiceName); |
202 |
+ |
203 |
+@@ -439,14 +439,29 @@ void KIO::OpenUrlJobPrivate::emitAccessDenied() |
204 |
+ q->emitResult(); |
205 |
+ } |
206 |
+ |
207 |
+-// was: KRun::isExecutable (minus application/x-desktop and application/x-shellscript mimetypes). |
208 |
++// was: KRun::isExecutable (minus application/x-desktop mimetype). |
209 |
+ // Feel free to make public if needed. |
210 |
+-static bool isExecutableMime(const QMimeType &mimeType) |
211 |
++static bool isBinary(const QMimeType &mimeType) |
212 |
+ { |
213 |
+- return (mimeType.inherits(QStringLiteral("application/x-executable")) || |
214 |
+- /* e.g. /usr/bin/ls, see https://gitlab.freedesktop.org/xdg/shared-mime-info/-/issues/11 */ |
215 |
+- mimeType.inherits(QStringLiteral("application/x-sharedlib")) || |
216 |
+- mimeType.inherits(QStringLiteral("application/x-ms-dos-executable"))); |
217 |
++ // - Binaries could be e.g.: |
218 |
++ // - application/x-executable |
219 |
++ // - application/x-sharedlib e.g. /usr/bin/ls, see |
220 |
++ // https://gitlab.freedesktop.org/xdg/shared-mime-info/-/issues/11 |
221 |
++ // |
222 |
++ // - Mimetypes that inherit application/x-executable _and_ text/plain are scripts, these are |
223 |
++ // handled by handleScripts() |
224 |
++ |
225 |
++ return (mimeType.inherits(QStringLiteral("application/x-executable")) |
226 |
++ || mimeType.inherits(QStringLiteral("application/x-sharedlib")) |
227 |
++ || mimeType.inherits(QStringLiteral("application/x-ms-dos-executable"))); |
228 |
++} |
229 |
++ |
230 |
++// Helper function that returns whether a file is a text-based script |
231 |
++// e.g. ".sh", ".csh", ".py", ".js" |
232 |
++static bool isTextScript(const QMimeType &mimeType) |
233 |
++{ |
234 |
++ return (mimeType.inherits(QStringLiteral("application/x-executable")) |
235 |
++ && mimeType.inherits(QStringLiteral("text/plain"))); |
236 |
+ } |
237 |
+ |
238 |
+ // Helper function that returns whether a file has the execute bit set or not. |
239 |
+@@ -456,7 +471,7 @@ static bool hasExecuteBit(const QString &fileName) |
240 |
+ } |
241 |
+ |
242 |
+ // Handle native binaries (.e.g. /usr/bin/*); and .exe files |
243 |
+-void KIO::OpenUrlJobPrivate::handleExecutables(const QMimeType &mimeType) |
244 |
++void KIO::OpenUrlJobPrivate::handleBinaries(const QMimeType &mimeType) |
245 |
+ { |
246 |
+ if (!KAuthorized::authorize(QStringLiteral("shell_access"))) { |
247 |
+ emitAccessDenied(); |
248 |
+@@ -475,11 +490,9 @@ void KIO::OpenUrlJobPrivate::handleExecutables(const QMimeType &mimeType) |
249 |
+ |
250 |
+ const QString localPath = m_url.toLocalFile(); |
251 |
+ |
252 |
+- // Check whether file is an executable script |
253 |
+-#ifdef Q_OS_WIN |
254 |
+- const bool isNativeBinary = !mimeType.inherits(QStringLiteral("text/plain")); |
255 |
+-#else |
256 |
+- const bool isNativeBinary = !mimeType.inherits(QStringLiteral("text/plain")) && !mimeType.inherits(QStringLiteral("application/x-ms-dos-executable")); |
257 |
++ bool isNativeBinary = true; |
258 |
++#ifndef Q_OS_WIN |
259 |
++ isNativeBinary = !mimeType.inherits(QStringLiteral("application/x-ms-dos-executable")); |
260 |
+ #endif |
261 |
+ |
262 |
+ if (m_showOpenOrExecuteDialog) { |
263 |
+@@ -497,6 +510,8 @@ void KIO::OpenUrlJobPrivate::handleExecutables(const QMimeType &mimeType) |
264 |
+ } |
265 |
+ }; |
266 |
+ |
267 |
++ // Ask the user for confirmation before executing this binary (for binaries |
268 |
++ // the dialog will only show Execute/Cancel) |
269 |
+ showOpenOrExecuteFileDialog(dialogFinished); |
270 |
+ return; |
271 |
+ } |
272 |
+@@ -601,15 +616,15 @@ void KIO::OpenUrlJobPrivate::runUrlWithMimeType() |
273 |
+ return; |
274 |
+ } |
275 |
+ |
276 |
+- // Shell scripts |
277 |
+- if (mimeType.inherits(QStringLiteral("application/x-shellscript"))) { |
278 |
+- handleShellscripts(); |
279 |
++ // Scripts (e.g. .sh, .csh, .py, .js) |
280 |
++ if (isTextScript(mimeType)) { |
281 |
++ handleScripts(); |
282 |
+ return; |
283 |
+ } |
284 |
+ |
285 |
+- // Binaries (e.g. /usr/bin/konsole) and .exe files |
286 |
+- if (isExecutableMime(mimeType)) { |
287 |
+- handleExecutables(mimeType); |
288 |
++ // Binaries (e.g. /usr/bin/{konsole,ls}) and .exe files |
289 |
++ if (isBinary(mimeType)) { |
290 |
++ handleBinaries(mimeType); |
291 |
+ return; |
292 |
+ } |
293 |
+ |
294 |
+@@ -677,8 +692,9 @@ void KIO::OpenUrlJobPrivate::handleDesktopFiles() |
295 |
+ openInPreferredApp(); |
296 |
+ } |
297 |
+ |
298 |
+-void KIO::OpenUrlJobPrivate::handleShellscripts() |
299 |
++void KIO::OpenUrlJobPrivate::handleScripts() |
300 |
+ { |
301 |
++ // Executable scripts of any type can run arbitrary shell commands |
302 |
+ if (!KAuthorized::authorize(QStringLiteral("shell_access"))) { |
303 |
+ emitAccessDenied(); |
304 |
+ return; |
305 |
+@@ -687,8 +703,7 @@ void KIO::OpenUrlJobPrivate::handleShellscripts() |
306 |
+ const bool isLocal = m_url.isLocalFile(); |
307 |
+ const QString localPath = m_url.toLocalFile(); |
308 |
+ if (!isLocal || !hasExecuteBit(localPath)) { |
309 |
+- // Open remote shell scripts or ones without the execute bit, with the |
310 |
+- // default application |
311 |
++ // Open remote scripts or ones without the execute bit, with the default application |
312 |
+ openInPreferredApp(); |
313 |
+ return; |
314 |
+ } |
315 |
+@@ -706,7 +721,7 @@ void KIO::OpenUrlJobPrivate::handleShellscripts() |
316 |
+ return; |
317 |
+ } |
318 |
+ |
319 |
+- if (m_runExecutables) { // Local executable shell script, proceed |
320 |
++ if (m_runExecutables) { // Local executable script, proceed |
321 |
+ executeCommand(); |
322 |
+ } else { // Open in the default (text editor) app |
323 |
+ openInPreferredApp(); |
324 |
+@@ -767,7 +782,7 @@ void KIO::OpenUrlJobPrivate::showOpenOrExecuteFileDialog(std::function<void(bool |
325 |
+ |
326 |
+ if (!s_openOrExecuteFileHandler) { |
327 |
+ // No way to ask the user whether to execute or open |
328 |
+- if (mimeType.inherits(QStringLiteral("application/x-shellscript")) |
329 |
++ if (isTextScript(mimeType) |
330 |
+ || mimeType.inherits(QStringLiteral("application/x-desktop"))) { // Open text-based ones in the default app |
331 |
+ openInPreferredApp(); |
332 |
+ } else { |
333 |
+-- |
334 |
+GitLab |
335 |
+ |
336 |
|
337 |
diff --git a/kde-frameworks/kio/kio-5.74.1-r1.ebuild b/kde-frameworks/kio/kio-5.74.1-r1.ebuild |
338 |
index 8ba617db566..b77cae090c8 100644 |
339 |
--- a/kde-frameworks/kio/kio-5.74.1-r1.ebuild |
340 |
+++ b/kde-frameworks/kio/kio-5.74.1-r1.ebuild |
341 |
@@ -71,7 +71,10 @@ PDEPEND=" |
342 |
# tests hang |
343 |
RESTRICT+=" test" |
344 |
|
345 |
-PATCHES=( "${FILESDIR}"/${P}-kio_trash-too-strict-perms-check.patch ) |
346 |
+PATCHES=( |
347 |
+ "${FILESDIR}"/${P}-kio_trash-too-strict-perms-check.patch |
348 |
+ "${FILESDIR}"/${P}-handle-shell-scripts-consistenty.patch |
349 |
+) |
350 |
|
351 |
src_configure() { |
352 |
local mycmakeargs=( |