Changeset View
Changeset View
Standalone View
Standalone View
src/widgets/krun.cpp
Show First 20 Lines • Show All 52 Lines • ▼ Show 20 Line(s) | |||||
53 | #include <kjobuidelegate.h> | 53 | #include <kjobuidelegate.h> | ||
54 | #include <kmimetypetrader.h> | 54 | #include <kmimetypetrader.h> | ||
55 | #include "kio/job.h" | 55 | #include "kio/job.h" | ||
56 | #include "kio/global.h" | 56 | #include "kio/global.h" | ||
57 | #include "kio/scheduler.h" | 57 | #include "kio/scheduler.h" | ||
58 | #include "kopenwithdialog.h" | 58 | #include "kopenwithdialog.h" | ||
59 | #include "krecentdocument.h" | 59 | #include "krecentdocument.h" | ||
60 | #include "kdesktopfileactions.h" | 60 | #include "kdesktopfileactions.h" | ||
61 | #include "executablefileopendialog_p.h" | | |||
62 | #include <kio/desktopexecparser.h> | 61 | #include <kio/desktopexecparser.h> | ||
63 | 62 | | |||
64 | #include <kurlauthorized.h> | 63 | #include <kurlauthorized.h> | ||
65 | #include <kmessagebox.h> | 64 | #include <kmessagebox.h> | ||
66 | #include <ktoolinvocation.h> | 65 | #include <ktoolinvocation.h> | ||
67 | #include <klocalizedstring.h> | 66 | #include <klocalizedstring.h> | ||
68 | #include <kprotocolmanager.h> | 67 | #include <kprotocolmanager.h> | ||
69 | #include <kprocess.h> | 68 | #include <kprocess.h> | ||
▲ Show 20 Lines • Show All 80 Lines • ▼ Show 20 Line(s) | 148 | if (!url.isLocalFile()) { | |||
150 | return false; | 149 | return false; | ||
151 | } | 150 | } | ||
152 | 151 | | |||
153 | // While isExecutable performs similar check to this one, some users depend on | 152 | // While isExecutable performs similar check to this one, some users depend on | ||
154 | // this method not returning true for application/x-desktop | 153 | // this method not returning true for application/x-desktop | ||
155 | QMimeDatabase db; | 154 | QMimeDatabase db; | ||
156 | QMimeType mimeType = db.mimeTypeForName(mimetype); | 155 | QMimeType mimeType = db.mimeTypeForName(mimetype); | ||
157 | if (!mimeType.inherits(QStringLiteral("application/x-executable")) | 156 | if (!mimeType.inherits(QStringLiteral("application/x-executable")) | ||
158 | #ifdef Q_OS_WIN | | |||
159 | && !mimeType.inherits(QStringLiteral("application/x-ms-dos-executable")) | 157 | && !mimeType.inherits(QStringLiteral("application/x-ms-dos-executable")) | ||
160 | #endif | | |||
161 | && !mimeType.inherits(QStringLiteral("application/x-executable-script")) | 158 | && !mimeType.inherits(QStringLiteral("application/x-executable-script")) | ||
162 | && !mimeType.inherits(QStringLiteral("application/x-sharedlib"))) { | 159 | && !mimeType.inherits(QStringLiteral("application/x-sharedlib"))) { | ||
163 | return false; | 160 | return false; | ||
164 | } | 161 | } | ||
165 | 162 | | |||
166 | if (!hasExecuteBit(url.toLocalFile())) { | 163 | if (!hasExecuteBit(url.toLocalFile()) && !mimeType.inherits(QStringLiteral("application/x-ms-dos-executable"))) { | ||
167 | return false; | 164 | return false; | ||
168 | } | 165 | } | ||
169 | 166 | | |||
170 | return true; | 167 | return true; | ||
171 | } | 168 | } | ||
172 | 169 | | |||
173 | void KRun::handleInitError(int kioErrorCode, const QString &errorMsg) | 170 | void KRun::handleInitError(int kioErrorCode, const QString &errorMsg) | ||
174 | { | 171 | { | ||
▲ Show 20 Lines • Show All 177 Lines • ▼ Show 20 Line(s) | 346 | if (_mimetype == QLatin1String("inode/directory-locked")) { | |||
352 | return false; | 349 | return false; | ||
353 | } else if (_mimetype == QLatin1String("application/x-desktop")) { | 350 | } else if (_mimetype == QLatin1String("application/x-desktop")) { | ||
354 | if (u.isLocalFile() && runExecutables) { | 351 | if (u.isLocalFile() && runExecutables) { | ||
355 | return KDesktopFileActions::runWithStartup(u, true, asn); | 352 | return KDesktopFileActions::runWithStartup(u, true, asn); | ||
356 | } | 353 | } | ||
357 | } else if (isExecutable(_mimetype)) { | 354 | } else if (isExecutable(_mimetype)) { | ||
358 | // Check whether file is executable script | 355 | // Check whether file is executable script | ||
359 | const QMimeType mime = db.mimeTypeForName(_mimetype); | 356 | const QMimeType mime = db.mimeTypeForName(_mimetype); | ||
360 | bool isTextFile = mime.inherits(QStringLiteral("text/plain")); | 357 | #ifdef Q_OS_WIN | ||
358 | bool isNativeBinary = !mime.inherits(QStringLiteral("text/plain")); | ||||
359 | #else | ||||
360 | bool isNativeBinary = !mime.inherits(QStringLiteral("text/plain")) && !mime.inherits(QStringLiteral("application/x-ms-dos-executable")); | ||||
361 | #endif | ||||
361 | // Only run local files | 362 | // Only run local files | ||
362 | if (u.isLocalFile() && runExecutables) { | 363 | if (u.isLocalFile() && runExecutables) { | ||
363 | if (KAuthorized::authorize(QStringLiteral("shell_access"))) { | 364 | if (KAuthorized::authorize(QStringLiteral("shell_access"))) { | ||
364 | 365 | | |||
365 | bool canRun = true; | 366 | bool canRun = true; | ||
366 | bool isFileExecutable = hasExecuteBit(u.toLocalFile()); | 367 | bool isFileExecutable = hasExecuteBit(u.toLocalFile()); | ||
367 | 368 | | |||
368 | #ifdef Q_OS_WIN | | |||
369 | // On Windows, run all executables normally | | |||
370 | const bool supportsRunningExecutable = true; | | |||
371 | #else | | |||
372 | // On non-Windows systems, this will prevent Windows executables | | |||
373 | // from being run, so that programs like Wine can handle them instead. | | |||
374 | const bool supportsRunningExecutable = !mime.inherits(QStringLiteral("application/x-ms-dos-executable")); | | |||
375 | #endif | | |||
376 | | ||||
377 | if (!supportsRunningExecutable) { | | |||
378 | // Don't run Windows executables on non-Windows platform | | |||
379 | canRun = false; | | |||
380 | } else if (!isFileExecutable && !isTextFile) { | | |||
381 | // For executables that aren't scripts and without execute bit, | 369 | // For executables that aren't scripts and without execute bit, | ||
382 | // show prompt asking user if he wants to run the program. | 370 | // show prompt asking user if he wants to run the program. | ||
371 | if (!isFileExecutable && isNativeBinary) { | ||||
383 | canRun = false; | 372 | canRun = false; | ||
384 | int result = showUntrustedProgramWarning(u.fileName(), window); | 373 | int result = showUntrustedProgramWarning(u.fileName(), window); | ||
385 | if (result == QDialog::Accepted) { | 374 | if (result == QDialog::Accepted) { | ||
386 | QString errorString; | 375 | QString errorString; | ||
387 | if (!setExecuteBit(u.toLocalFile(), errorString)) { | 376 | if (!setExecuteBit(u.toLocalFile(), errorString)) { | ||
388 | KMessageBox::sorry( | 377 | KMessageBox::sorry( | ||
389 | window, | 378 | window, | ||
390 | i18n("<qt>Unable to make file <b>%1</b> executable.\n%2.</qt>", | 379 | i18n("<qt>Unable to make file <b>%1</b> executable.\n%2.</qt>", | ||
391 | u.toLocalFile(), errorString) | 380 | u.toLocalFile(), errorString) | ||
392 | ); | 381 | ); | ||
393 | } else { | 382 | } else { | ||
394 | canRun = true; | 383 | canRun = true; | ||
395 | } | 384 | } | ||
396 | } | 385 | } | ||
397 | } else if (!isFileExecutable && isTextFile) { | 386 | } else if (!isFileExecutable && !isNativeBinary) { | ||
398 | // Don't try to run scripts without execute bit, instead | 387 | // Don't try to run scripts/exes without execute bit, instead | ||
399 | // open them with default application | 388 | // open them with default application | ||
400 | canRun = false; | 389 | canRun = false; | ||
401 | } | 390 | } | ||
402 | 391 | | |||
403 | if (canRun) { | 392 | if (canRun) { | ||
404 | return (KRun::runCommand(KShell::quoteArg(u.toLocalFile()), QString(), QString(), | 393 | return (KRun::runCommand(KShell::quoteArg(u.toLocalFile()), QString(), QString(), | ||
405 | window, asn, u.adjusted(QUrl::RemoveFilename).toLocalFile())); // just execute the url as a command | 394 | window, asn, u.adjusted(QUrl::RemoveFilename).toLocalFile())); // just execute the url as a command | ||
406 | // ## TODO implement deleting the file if tempFile==true | 395 | // ## TODO implement deleting the file if tempFile==true | ||
407 | } | 396 | } | ||
408 | 397 | | |||
409 | } else { | 398 | } else { | ||
410 | // Show no permission warning | 399 | // Show no permission warning | ||
411 | noAuth = true; | 400 | noAuth = true; | ||
412 | } | 401 | } | ||
413 | } else if (!isTextFile) { | 402 | } else if (isNativeBinary) { | ||
414 | // Show warning for executables that aren't scripts | 403 | // Show warning for executables that aren't scripts | ||
415 | noRun = true; | 404 | noRun = true; | ||
416 | } | 405 | } | ||
417 | } | 406 | } | ||
418 | 407 | | |||
419 | if (noRun) { | 408 | if (noRun) { | ||
420 | KMessageBox::sorry(window, | 409 | KMessageBox::sorry(window, | ||
421 | i18n("<qt>The file <b>%1</b> is an executable program. " | 410 | i18n("<qt>The file <b>%1</b> is an executable program. " | ||
▲ Show 20 Lines • Show All 643 Lines • ▼ Show 20 Line(s) | 1051 | if (service && q->runApplication(*service, urls, m_window, RunFlags{}, QString(), m_asn)) { | |||
1065 | return true; | 1054 | return true; | ||
1066 | } | 1055 | } | ||
1067 | } | 1056 | } | ||
1068 | return false; | 1057 | return false; | ||
1069 | } | 1058 | } | ||
1070 | 1059 | | |||
1071 | void KRun::KRunPrivate::showPrompt() | 1060 | void KRun::KRunPrivate::showPrompt() | ||
1072 | { | 1061 | { | ||
1073 | ExecutableFileOpenDialog *dialog = new ExecutableFileOpenDialog(q->window()); | 1062 | ExecutableFileOpenDialog *dialog = new ExecutableFileOpenDialog(promptMode(), q->window()); | ||
1074 | dialog->setAttribute(Qt::WA_DeleteOnClose); | 1063 | dialog->setAttribute(Qt::WA_DeleteOnClose); | ||
1075 | connect(dialog, &ExecutableFileOpenDialog::finished, q, [this, dialog](int result){ | 1064 | connect(dialog, &ExecutableFileOpenDialog::finished, q, [this, dialog](int result){ | ||
1076 | onDialogFinished(result, dialog->isDontAskAgainChecked()); | 1065 | onDialogFinished(result, dialog->isDontAskAgainChecked()); | ||
1077 | }); | 1066 | }); | ||
1078 | dialog->show(); | 1067 | dialog->show(); | ||
1079 | } | 1068 | } | ||
1080 | 1069 | | |||
1081 | bool KRun::KRunPrivate::isPromptNeeded() | 1070 | bool KRun::KRunPrivate::isPromptNeeded() | ||
1082 | { | 1071 | { | ||
1083 | if (m_strURL == QUrl(QStringLiteral("remote:/x-wizard_service.desktop"))) { | 1072 | if (m_strURL == QUrl(QStringLiteral("remote:/x-wizard_service.desktop"))) { | ||
1084 | return false; | 1073 | return false; | ||
1085 | } | 1074 | } | ||
1086 | const QMimeDatabase db; | 1075 | const QMimeDatabase db; | ||
1087 | const QMimeType mime = db.mimeTypeForUrl(m_strURL); | 1076 | const QMimeType mime = db.mimeTypeForUrl(m_strURL); | ||
1088 | 1077 | | |||
1089 | const bool isFileExecutable = (isExecutableFile(m_strURL, mime.name()) || | 1078 | const bool isFileExecutable = (isExecutableFile(m_strURL, mime.name()) || | ||
1090 | mime.inherits(QStringLiteral("application/x-desktop"))); | 1079 | mime.inherits(QStringLiteral("application/x-desktop"))); | ||
1091 | const bool isTextFile = mime.inherits(QStringLiteral("text/plain")); | | |||
1092 | 1080 | | |||
1093 | if (isFileExecutable && isTextFile) { | 1081 | if (isFileExecutable) { | ||
1094 | KConfigGroup cfgGroup(KSharedConfig::openConfig(QStringLiteral("kiorc")), "Executable scripts"); | 1082 | KConfigGroup cfgGroup(KSharedConfig::openConfig(QStringLiteral("kiorc")), "Executable scripts"); | ||
1095 | const QString value = cfgGroup.readEntry("behaviourOnLaunch", "alwaysAsk"); | 1083 | const QString value = cfgGroup.readEntry("behaviourOnLaunch", "alwaysAsk"); | ||
1096 | 1084 | | |||
1097 | if (value == QLatin1String("alwaysAsk")) { | 1085 | if (value == QLatin1String("alwaysAsk")) { | ||
1098 | return true; | 1086 | return true; | ||
1099 | } else { | 1087 | } else { | ||
1100 | q->setRunExecutables(value == QLatin1String("execute")); | 1088 | q->setRunExecutables(value == QLatin1String("execute")); | ||
1101 | } | 1089 | } | ||
1102 | } | 1090 | } | ||
1103 | 1091 | | |||
1104 | return false; | 1092 | return false; | ||
1105 | } | 1093 | } | ||
1106 | 1094 | | |||
1095 | ExecutableFileOpenDialog::Mode KRun::KRunPrivate::promptMode() | ||||
1096 | { | ||||
1097 | const QMimeDatabase db; | ||||
1098 | const QMimeType mime = db.mimeTypeForUrl(m_strURL); | ||||
1099 | | ||||
1100 | if (mime.inherits(QStringLiteral("text/plain"))) { | ||||
1101 | return ExecutableFileOpenDialog::OpenOrExecute; | ||||
dfaure: should this be in ifdef Q_OS_WIN?
On windows, *.exe is executed, not opened (with e.g. wine) | |||||
guoyunhe: Yes, I updated this part. | |||||
1102 | } | ||||
1103 | #ifndef Q_OS_WIN | ||||
1104 | if (mime.inherits(QStringLiteral("application/x-ms-dos-executable"))) { | ||||
1105 | return ExecutableFileOpenDialog::OpenAsExecute; | ||||
1106 | } | ||||
1107 | #endif | ||||
1108 | return ExecutableFileOpenDialog::OnlyExecute; | ||||
1109 | } | ||||
1110 | | ||||
1107 | void KRun::KRunPrivate::onDialogFinished(int result, bool isDontAskAgainSet) | 1111 | void KRun::KRunPrivate::onDialogFinished(int result, bool isDontAskAgainSet) | ||
1108 | { | 1112 | { | ||
1109 | if (result == ExecutableFileOpenDialog::Rejected) { | 1113 | if (result == ExecutableFileOpenDialog::Rejected) { | ||
1110 | m_bFinished = true; | 1114 | m_bFinished = true; | ||
1111 | m_bInit = false; | 1115 | m_bInit = false; | ||
1112 | startTimer(); | 1116 | startTimer(); | ||
1113 | return; | 1117 | return; | ||
1114 | } | 1118 | } | ||
▲ Show 20 Lines • Show All 682 Lines • Show Last 20 Lines |
should this be in ifdef Q_OS_WIN?
On windows, *.exe is executed, not opened (with e.g. wine)