KIO

openurljob.cpp
1/*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 2020 David Faure <faure@kde.org>
4 SPDX-FileCopyrightText: 2022 Harald Sitter <sitter@kde.org>
5
6 SPDX-License-Identifier: LGPL-2.0-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
7*/
8
9#include "openurljob.h"
10#include "commandlauncherjob.h"
11#include "desktopexecparser.h"
12#include "global.h"
13#include "job.h" // for buildErrorString
14#include "jobuidelegatefactory.h"
15#include "kiogui_debug.h"
16#include "openorexecutefileinterface.h"
17#include "openwithhandlerinterface.h"
18#include "untrustedprogramhandlerinterface.h"
19
20#include <KApplicationTrader>
21#include <KAuthorized>
22#include <KConfigGroup>
23#include <KDesktopFile>
24#include <KLocalizedString>
25#include <KSandbox>
26#include <KUrlAuthorized>
27#include <QFileInfo>
28
29#include <KProtocolManager>
30#include <KSharedConfig>
31#include <QDesktopServices>
32#include <QHostInfo>
33#include <QMimeDatabase>
34#include <QOperatingSystemVersion>
35#include <mimetypefinderjob.h>
36
37// For unit test purposes, to test both code paths in externalBrowser()
38KIOGUI_EXPORT bool openurljob_force_use_browserapp_kdeglobals = false;
39
40class KIO::OpenUrlJobPrivate
41{
42public:
43 explicit OpenUrlJobPrivate(const QUrl &url, OpenUrlJob *qq)
44 : m_url(url)
45 , q(qq)
46 {
48 }
49
50 void emitAccessDenied();
51 void runUrlWithMimeType();
52 QString externalBrowser() const;
53 bool runExternalBrowser(const QString &exe);
54 void useSchemeHandler();
55
56 QUrl m_url;
57 KIO::OpenUrlJob *const q;
58 QString m_suggestedFileName;
59 QByteArray m_startupId;
60 QString m_mimeTypeName;
61 KService::Ptr m_preferredService;
62 bool m_deleteTemporaryFile = false;
63 bool m_runExecutables = false;
64 bool m_showOpenOrExecuteDialog = false;
65 bool m_externalBrowserEnabled = true;
66 bool m_followRedirections = true;
67
68private:
69 void executeCommand();
70 void handleBinaries(const QMimeType &mimeType);
71 void handleBinariesHelper(const QString &localPath, bool isNativeBinary);
72 void handleDesktopFiles();
73 void handleScripts();
74 void openInPreferredApp();
75 void runLink(const QString &filePath, const QString &urlStr, const QString &optionalServiceName);
76
77 void showOpenWithDialog();
78 void showOpenOrExecuteFileDialog(std::function<void(bool)> dialogFinished);
79 void showUntrustedProgramWarningDialog(const QString &filePath);
80
81 void startService(const KService::Ptr &service, const QList<QUrl> &urls);
82 void startService(const KService::Ptr &service)
83 {
84 startService(service, {m_url});
85 }
86};
87
89 : KCompositeJob(parent)
90 , d(new OpenUrlJobPrivate(url, this))
91{
92}
93
94KIO::OpenUrlJob::OpenUrlJob(const QUrl &url, const QString &mimeType, QObject *parent)
95 : KCompositeJob(parent)
96 , d(new OpenUrlJobPrivate(url, this))
97{
98 d->m_mimeTypeName = mimeType;
99}
100
104
106{
107 d->m_deleteTemporaryFile = b;
108}
109
110void KIO::OpenUrlJob::setSuggestedFileName(const QString &suggestedFileName)
111{
112 d->m_suggestedFileName = suggestedFileName;
113}
114
116{
117 d->m_startupId = startupId;
118}
119
121{
122 d->m_runExecutables = allow;
123}
124
126{
127 d->m_showOpenOrExecuteDialog = b;
128}
129
131{
132 d->m_externalBrowserEnabled = b;
133}
134
136{
137 d->m_followRedirections = b;
138}
139
141{
142 if (!d->m_url.isValid() || d->m_url.scheme().isEmpty()) {
143 const QString error = !d->m_url.isValid() ? d->m_url.errorString() : d->m_url.toDisplayString();
144 setError(KIO::ERR_MALFORMED_URL);
145 setErrorText(i18n("Malformed URL\n%1", error));
146 emitResult();
147 return;
148 }
149 if (!KUrlAuthorized::authorizeUrlAction(QStringLiteral("open"), QUrl(), d->m_url)) {
150 d->emitAccessDenied();
151 return;
152 }
153
154 auto qtOpenUrl = [this]() {
155 if (!QDesktopServices::openUrl(d->m_url)) {
156 // Is this an actual error, or USER_CANCELED?
157 setError(KJob::UserDefinedError);
158 setErrorText(i18n("Failed to open %1", d->m_url.toDisplayString()));
159 }
160 emitResult();
161 };
162
163#if defined(Q_OS_WIN) || defined(Q_OS_MACOS)
164 if (d->m_externalBrowserEnabled) {
165 // For Windows and MacOS, the mimetypes handling is different, so use QDesktopServices
166 qtOpenUrl();
167 return;
168 }
169#endif
170
171 if (d->m_externalBrowserEnabled && KSandbox::isInside()) {
172 // Use the function from QDesktopServices as it handles portals correctly
173 // Note that it falls back to "normal way" if the portal service isn't running.
174 qtOpenUrl();
175 return;
176 }
177
178 // If we know the MIME type, proceed
179 if (!d->m_mimeTypeName.isEmpty()) {
180 d->runUrlWithMimeType();
181 return;
182 }
183
184 if (d->m_url.scheme().startsWith(QLatin1String("http"))) {
185 if (d->m_externalBrowserEnabled) {
186 const QString externalBrowser = d->externalBrowser();
187 if (!externalBrowser.isEmpty() && d->runExternalBrowser(externalBrowser)) {
188 return;
189 }
190 }
191 } else {
193 d->useSchemeHandler();
194 return;
195 }
196 }
197
198 auto *job = new KIO::MimeTypeFinderJob(d->m_url, this);
199 job->setFollowRedirections(d->m_followRedirections);
200 job->setSuggestedFileName(d->m_suggestedFileName);
201 connect(job, &KJob::result, this, [job, this]() {
202 const int errCode = job->error();
203 if (errCode) {
204 setError(errCode);
205 setErrorText(job->errorText());
206 emitResult();
207 } else {
208 d->m_suggestedFileName = job->suggestedFileName();
209 d->m_mimeTypeName = job->mimeType();
210 d->runUrlWithMimeType();
211 }
212 });
213 job->start();
214}
215
216bool KIO::OpenUrlJob::doKill()
217{
218 return true;
219}
220
221QString KIO::OpenUrlJobPrivate::externalBrowser() const
222{
223 if (!m_externalBrowserEnabled) {
224 return QString();
225 }
226
227 if (!openurljob_force_use_browserapp_kdeglobals) {
228 KService::Ptr externalBrowser = KApplicationTrader::preferredService(QStringLiteral("x-scheme-handler/https"));
229 if (!externalBrowser) {
230 externalBrowser = KApplicationTrader::preferredService(QStringLiteral("x-scheme-handler/http"));
231 }
232 if (externalBrowser) {
233 return externalBrowser->storageId();
234 }
235 }
236
237 const QString browserApp = KConfigGroup(KSharedConfig::openConfig(), QStringLiteral("General")).readEntry("BrowserApplication");
238 return browserApp;
239}
240
241bool KIO::OpenUrlJobPrivate::runExternalBrowser(const QString &exec)
242{
243 if (exec.startsWith(QLatin1Char('!'))) {
244 // Literal command
245 const QString command = QStringView(exec).mid(1) + QLatin1String(" %u");
246 KService::Ptr service(new KService(QString(), command, QString()));
247 startService(service);
248 return true;
249 } else {
250 // Name of desktop file
252 if (service) {
253 startService(service);
254 return true;
255 }
256 }
257 return false;
258}
259
260void KIO::OpenUrlJobPrivate::useSchemeHandler()
261{
262 // look for an application associated with x-scheme-handler/<protocol>
263 const KService::Ptr service = KApplicationTrader::preferredService(QLatin1String("x-scheme-handler/") + m_url.scheme());
264 if (service) {
265 startService(service);
266 return;
267 }
268 // fallback, look for associated helper protocol
269 Q_ASSERT(KProtocolInfo::isHelperProtocol(m_url.scheme()));
270 const auto exec = KProtocolInfo::exec(m_url.scheme());
271 if (exec.isEmpty()) {
272 // use default MIME type opener for file
273 m_mimeTypeName = KProtocolManager::defaultMimetype(m_url);
274 runUrlWithMimeType();
275 } else {
276 KService::Ptr servicePtr(new KService(QString(), exec, QString()));
277 startService(servicePtr);
278 }
279}
280
281void KIO::OpenUrlJobPrivate::startService(const KService::Ptr &service, const QList<QUrl> &urls)
282{
284 job->setUrls(urls);
285 job->setRunFlags(m_deleteTemporaryFile ? KIO::ApplicationLauncherJob::DeleteTemporaryFiles : KIO::ApplicationLauncherJob::RunFlags{});
286 job->setSuggestedFileName(m_suggestedFileName);
287 job->setStartupId(m_startupId);
288 q->addSubjob(job);
289 job->start();
290}
291
292void KIO::OpenUrlJobPrivate::runLink(const QString &filePath, const QString &urlStr, const QString &optionalServiceName)
293{
294 if (urlStr.isEmpty()) {
295 q->setError(KJob::UserDefinedError);
296 q->setErrorText(i18n("The desktop entry file\n%1\nis of type Link but has no URL=... entry.", filePath));
297 q->emitResult();
298 return;
299 }
300
301 m_url = QUrl::fromUserInput(urlStr);
302 m_mimeTypeName.clear();
303
304 // X-KDE-LastOpenedWith holds the service desktop entry name that
305 // should be preferred for opening this URL if possible.
306 // This is used by the Recent Documents menu for instance.
307 if (!optionalServiceName.isEmpty()) {
308 m_preferredService = KService::serviceByDesktopName(optionalServiceName);
309 }
310
311 // Restart from scratch with the target of the link
312 q->start();
313}
314
315void KIO::OpenUrlJobPrivate::emitAccessDenied()
316{
317 q->setError(KIO::ERR_ACCESS_DENIED);
318 q->setErrorText(KIO::buildErrorString(KIO::ERR_ACCESS_DENIED, m_url.toDisplayString()));
319 q->emitResult();
320}
321
322// was: KRun::isExecutable (minus application/x-desktop MIME type).
323// Feel free to make public if needed.
324static bool isBinary(const QMimeType &mimeType)
325{
326 // - Binaries could be e.g.:
327 // - application/x-executable
328 // - application/x-sharedlib e.g. /usr/bin/ls, see
329 // https://gitlab.freedesktop.org/xdg/shared-mime-info/-/issues/11
330 //
331 // - MIME types that inherit application/x-executable _and_ text/plain are scripts, these are
332 // handled by handleScripts()
333
334 return (mimeType.inherits(QStringLiteral("application/x-executable")) || mimeType.inherits(QStringLiteral("application/x-ms-dos-executable")));
335}
336
337// Helper function that returns whether a file is a text-based script
338// e.g. ".sh", ".csh", ".py", ".js"
339static bool isTextScript(const QMimeType &mimeType)
340{
341 return (mimeType.inherits(QStringLiteral("application/x-executable")) && mimeType.inherits(QStringLiteral("text/plain")));
342}
343
344// Helper function that returns whether a file has the execute bit set or not.
345static bool hasExecuteBit(const QString &fileName)
346{
347 return QFileInfo(fileName).isExecutable();
348}
349
350bool KIO::OpenUrlJob::isExecutableFile(const QUrl &url, const QString &mimetypeString)
351{
352 if (!url.isLocalFile()) {
353 return false;
354 }
355
356 QMimeDatabase db;
357 QMimeType mimeType = db.mimeTypeForName(mimetypeString);
358 return (isBinary(mimeType) || isTextScript(mimeType)) && hasExecuteBit(url.toLocalFile());
359}
360
361// Handle native binaries (.e.g. /usr/bin/*); and .exe files
362void KIO::OpenUrlJobPrivate::handleBinaries(const QMimeType &mimeType)
363{
364 if (!KAuthorized::authorize(KAuthorized::SHELL_ACCESS)) {
365 emitAccessDenied();
366 return;
367 }
368
369 const bool isLocal = m_url.isLocalFile();
370 // Don't run remote executables
371 if (!isLocal) {
372 q->setError(KJob::UserDefinedError);
373 q->setErrorText(
374 i18n("The executable file \"%1\" is located on a remote filesystem. "
375 "For safety reasons it will not be started.",
376 m_url.toDisplayString()));
377 q->emitResult();
378 return;
379 }
380
381 const QString localPath = m_url.toLocalFile();
382
383 bool isNativeBinary = true;
384#ifndef Q_OS_WIN
385 isNativeBinary = !mimeType.inherits(QStringLiteral("application/x-ms-dos-executable"));
386#endif
387
388 if (m_showOpenOrExecuteDialog) {
389 auto dialogFinished = [this, localPath, isNativeBinary](bool shouldExecute) {
390 // shouldExecute is always true if we get here, because for binaries the
391 // dialog only offers Execute/Cancel
392 Q_UNUSED(shouldExecute)
393
394 handleBinariesHelper(localPath, isNativeBinary);
395 };
396
397 // Ask the user for confirmation before executing this binary (for binaries
398 // the dialog will only show Execute/Cancel)
399 showOpenOrExecuteFileDialog(dialogFinished);
400 return;
401 }
402
403 handleBinariesHelper(localPath, isNativeBinary);
404}
405
406void KIO::OpenUrlJobPrivate::handleBinariesHelper(const QString &localPath, bool isNativeBinary)
407{
408 if (!m_runExecutables) {
409 q->setError(KJob::UserDefinedError);
410 q->setErrorText(i18n("For security reasons, launching executables is not allowed in this context."));
411 q->emitResult();
412 return;
413 }
414
415 // For local .exe files, open in the default app (e.g. WINE)
416 if (!isNativeBinary) {
417 openInPreferredApp();
418 return;
419 }
420
421 // Native binaries
422 if (!hasExecuteBit(localPath)) {
423 // Show untrustedProgram dialog for local, native executables without the execute bit
424 showUntrustedProgramWarningDialog(localPath);
425 return;
426 }
427
428 // Local executable with execute bit, proceed
429 executeCommand();
430}
431
432// For local, native executables (i.e. not shell scripts) without execute bit,
433// show a prompt asking the user if he wants to run the program.
434void KIO::OpenUrlJobPrivate::showUntrustedProgramWarningDialog(const QString &filePath)
435{
437 if (!untrustedProgramHandler) {
438 // No way to ask the user to make it executable
439 q->setError(KJob::UserDefinedError);
440 q->setErrorText(i18n("The program \"%1\" needs to have executable permission before it can be launched.", filePath));
441 q->emitResult();
442 return;
443 }
444 QObject::connect(untrustedProgramHandler, &KIO::UntrustedProgramHandlerInterface::result, q, [=, this](bool result) {
445 if (result) {
446 QString errorString;
447 if (untrustedProgramHandler->setExecuteBit(filePath, errorString)) {
448 executeCommand();
449 } else {
450 q->setError(KJob::UserDefinedError);
451 q->setErrorText(i18n("Unable to make file \"%1\" executable.\n%2.", filePath, errorString));
452 q->emitResult();
453 }
454 } else {
455 q->setError(KIO::ERR_USER_CANCELED);
456 q->emitResult();
457 }
458 });
459 untrustedProgramHandler->showUntrustedProgramWarning(q, m_url.fileName());
460}
461
462void KIO::OpenUrlJobPrivate::executeCommand()
463{
464 // Execute the URL as a command. This is how we start scripts and executables
466 job->setStartupId(m_startupId);
468 q->addSubjob(job);
469 job->start();
470
471 // TODO implement deleting the file if tempFile==true
472 // CommandLauncherJob doesn't support that, unlike ApplicationLauncherJob
473 // We'd have to do it in KProcessRunner.
474}
475
476void KIO::OpenUrlJobPrivate::runUrlWithMimeType()
477{
478 // Tell the app, in case it wants us to stop here
479 Q_EMIT q->mimeTypeFound(m_mimeTypeName);
480 if (q->error() == KJob::KilledJobError) {
481 q->emitResult();
482 return;
483 }
484
485 // Support for preferred service setting, see setPreferredService
486 if (m_preferredService && m_preferredService->hasMimeType(m_mimeTypeName)) {
487 startService(m_preferredService);
488 return;
489 }
490
491 // Scripts and executables
492 QMimeDatabase db;
493 const QMimeType mimeType = db.mimeTypeForName(m_mimeTypeName);
494
495 // .desktop files
496 if (mimeType.inherits(QStringLiteral("application/x-desktop"))) {
497 handleDesktopFiles();
498 return;
499 }
500
501 // Scripts (e.g. .sh, .csh, .py, .js)
502 if (isTextScript(mimeType)) {
503 handleScripts();
504 return;
505 }
506
507 // Binaries (e.g. /usr/bin/{konsole,ls}) and .exe files
508 if (isBinary(mimeType)) {
509 handleBinaries(mimeType);
510 return;
511 }
512
513 // General case: look up associated application
514 openInPreferredApp();
515}
516
517void KIO::OpenUrlJobPrivate::handleDesktopFiles()
518{
519 // Open remote .desktop files in the default (text editor) app
520 if (!m_url.isLocalFile()) {
521 openInPreferredApp();
522 return;
523 }
524
525 if (m_url.fileName() == QLatin1String(".directory") || m_mimeTypeName == QLatin1String("application/x-theme")) {
526 // We cannot execute these files, open in the default app
527 m_mimeTypeName = QStringLiteral("text/plain");
528 openInPreferredApp();
529 return;
530 }
531
532 const QString filePath = m_url.toLocalFile();
533 KDesktopFile cfg(filePath);
534 KConfigGroup cfgGroup = cfg.desktopGroup();
535 if (!cfgGroup.hasKey("Type")) {
536 q->setError(KJob::UserDefinedError);
537 q->setErrorText(i18n("The desktop entry file %1 has no Type=... entry.", filePath));
538 q->emitResult();
539 openInPreferredApp();
540 return;
541 }
542
543 if (cfg.hasLinkType()) {
544 runLink(filePath, cfg.readUrl(), cfg.desktopGroup().readEntry("X-KDE-LastOpenedWith"));
545 return;
546 }
547
548 if ((cfg.hasApplicationType() || cfg.readType() == QLatin1String("Service"))) { // kio_settings lets users run Type=Service desktop files
549 KService::Ptr service(new KService(filePath));
550 if (!service->exec().isEmpty()) {
551 if (m_showOpenOrExecuteDialog) { // Show the openOrExecute dialog
552 auto dialogFinished = [this, filePath, service](bool shouldExecute) {
553 if (shouldExecute) { // Run the file
554 startService(service, {});
555 return;
556 }
557 // The user selected "open"
558 openInPreferredApp();
559 };
560
561 showOpenOrExecuteFileDialog(dialogFinished);
562 return;
563 }
564
565 if (m_runExecutables) {
566 startService(service, {});
567 return;
568 }
569 } // exec is not empty
570 } // type Application or Service
571
572 // Fallback to opening in the default app
573 openInPreferredApp();
574}
575
576void KIO::OpenUrlJobPrivate::handleScripts()
577{
578 // Executable scripts of any type can run arbitrary shell commands
579 if (!KAuthorized::authorize(KAuthorized::SHELL_ACCESS)) {
580 emitAccessDenied();
581 return;
582 }
583
584 const bool isLocal = m_url.isLocalFile();
585 const QString localPath = m_url.toLocalFile();
586 if (!isLocal || !hasExecuteBit(localPath)) {
587 // Open remote scripts or ones without the execute bit, with the default application
588 openInPreferredApp();
589 return;
590 }
591
592 if (m_showOpenOrExecuteDialog) {
593 auto dialogFinished = [this](bool shouldExecute) {
594 if (shouldExecute) {
595 executeCommand();
596 } else {
597 openInPreferredApp();
598 }
599 };
600
601 showOpenOrExecuteFileDialog(dialogFinished);
602 return;
603 }
604
605 if (m_runExecutables) { // Local executable script, proceed
606 executeCommand();
607 } else { // Open in the default (text editor) app
608 openInPreferredApp();
609 }
610}
611
612void KIO::OpenUrlJobPrivate::openInPreferredApp()
613{
614 KService::Ptr service = KApplicationTrader::preferredService(m_mimeTypeName);
615 if (service) {
616 startService(service);
617 } else {
618 // Avoid directly opening partial downloads and incomplete files
619 // This is done here in the off chance the user actually has a default handler for it
620 if (m_mimeTypeName == QLatin1String("application/x-partial-download")) {
621 q->setError(KJob::UserDefinedError);
622 q->setErrorText(
623 i18n("This file is incomplete and should not be opened.\n"
624 "Check your open applications and the notification area for any pending tasks or downloads."));
625 q->emitResult();
626 return;
627 }
628
629 showOpenWithDialog();
630 }
631}
632
633void KIO::OpenUrlJobPrivate::showOpenWithDialog()
634{
635 if (!KAuthorized::authorizeAction(QStringLiteral("openwith"))) {
636 q->setError(KJob::UserDefinedError);
637 q->setErrorText(i18n("You are not authorized to select an application to open this file."));
638 q->emitResult();
639 return;
640 }
641
644 // As KDE on windows doesn't know about the windows default applications, offers will be empty in nearly all cases.
645 // So we use QDesktopServices::openUrl to let windows decide how to open the file.
646 // It's also our fallback if there's no handler to show an open-with dialog.
647 if (!QDesktopServices::openUrl(m_url)) {
648 q->setError(KJob::UserDefinedError);
649 q->setErrorText(i18n("Failed to open the file."));
650 }
651 q->emitResult();
652 return;
653 }
654
655 QObject::connect(openWithHandler, &KIO::OpenWithHandlerInterface::canceled, q, [this]() {
656 q->setError(KIO::ERR_USER_CANCELED);
657 q->emitResult();
658 });
659
660 QObject::connect(openWithHandler, &KIO::OpenWithHandlerInterface::serviceSelected, q, [this](const KService::Ptr &service) {
661 startService(service);
662 });
663
664 QObject::connect(openWithHandler, &KIO::OpenWithHandlerInterface::handled, q, [this]() {
665 q->emitResult();
666 });
667
668 openWithHandler->promptUserForApplication(q, {m_url}, m_mimeTypeName);
669}
670
671void KIO::OpenUrlJobPrivate::showOpenOrExecuteFileDialog(std::function<void(bool)> dialogFinished)
672{
673 QMimeDatabase db;
674 QMimeType mimeType = db.mimeTypeForName(m_mimeTypeName);
675
676 auto *openOrExecuteFileHandler = KIO::delegateExtension<KIO::OpenOrExecuteFileInterface *>(q);
677 if (!openOrExecuteFileHandler) {
678 // No way to ask the user whether to execute or open
679 if (isTextScript(mimeType) || mimeType.inherits(QStringLiteral("application/x-desktop"))) { // Open text-based ones in the default app
680 openInPreferredApp();
681 } else {
682 q->setError(KJob::UserDefinedError);
683 q->setErrorText(i18n("The program \"%1\" could not be launched.", m_url.toDisplayString(QUrl::PreferLocalFile)));
684 q->emitResult();
685 }
686 return;
687 }
688
689 QObject::connect(openOrExecuteFileHandler, &KIO::OpenOrExecuteFileInterface::canceled, q, [this]() {
690 q->setError(KIO::ERR_USER_CANCELED);
691 q->emitResult();
692 });
693
694 QObject::connect(openOrExecuteFileHandler, &KIO::OpenOrExecuteFileInterface::executeFile, q, [this, dialogFinished](bool shouldExecute) {
695 m_runExecutables = shouldExecute;
696 dialogFinished(shouldExecute);
697 });
698
699 openOrExecuteFileHandler->promptUserOpenOrExecute(q, m_mimeTypeName);
700}
701
702void KIO::OpenUrlJob::slotResult(KJob *job)
703{
704 // This is only used for the final application/launcher job, so we're done when it's done
705 const int errCode = job->error();
706 if (errCode) {
707 setError(errCode);
708 // We're a KJob, not a KIO::Job, so build the error string here
709 setErrorText(KIO::buildErrorString(errCode, job->errorText()));
710 }
711 emitResult();
712}
713
714#include "moc_openurljob.cpp"
static Q_INVOKABLE bool authorize(const QString &action)
static Q_INVOKABLE bool authorizeAction(const QString &action)
virtual bool addSubjob(KJob *job)
bool hasKey(const char *key) const
QString readEntry(const char *key, const char *aDefault=nullptr) const
ApplicationLauncherJob runs an application and watches it while running.
void setSuggestedFileName(const QString &suggestedFileName)
Sets the file name to use in the case of downloading the file to a tempfile in order to give to a non...
@ DeleteTemporaryFiles
the URLs passed to the service will be deleted when it exits (if the URLs are local files)
void setRunFlags(RunFlags runFlags)
Specifies various flags.
void setStartupId(const QByteArray &startupId)
Sets the platform-specific startup id of the application launch.
void start() override
Starts the job.
void setUrls(const QList< QUrl > &urls)
Specifies the URLs to be passed to the application.
CommandLauncherJob runs a command and watches it while running.
void setWorkingDirectory(const QString &workingDirectory)
Sets the working directory from which to run the command.
void start() override
Starts the job.
void setStartupId(const QByteArray &startupId)
Sets the platform-specific startup id of the command launch.
static bool hasSchemeHandler(const QUrl &url)
Returns true if protocol should be opened by a "handler" application, i.e. an application associated ...
MimeTypeFinderJob finds out the MIME type of a URL.
void executeFile(bool enable)
Emitted by promptUserOpenOrExecute() once the user chooses an action.
void canceled()
Emitted by promptUserOpenOrExecute() if user selects cancel.
OpenUrlJob finds out the right way to "open" a URL.
Definition openurljob.h:42
void setSuggestedFileName(const QString &suggestedFileName)
Sets the file name to use in the case of downloading the file to a tempfile, in order to give it to a...
void setDeleteTemporaryFile(bool b)
Specifies that the URL passed to the application will be deleted when it exits (if the URL is a local...
void start() override
Starts the job.
void setEnableExternalBrowser(bool b)
Sets whether the external webbrowser setting should be honoured.
void setFollowRedirections(bool b)
Sets whether the job should follow URL redirections.
void setRunExecutables(bool allow)
Set this to true if this class should allow the user to run executables.
void mimeTypeFound(const QString &mimeType)
Emitted when the MIME type is determined.
OpenUrlJob(const QUrl &url, QObject *parent=nullptr)
Creates an OpenUrlJob in order to open a URL.
static bool isExecutableFile(const QUrl &url, const QString &mimetypeName)
Returns whether the url of mimetype is executable.
~OpenUrlJob() override
Destructor.
void setShowOpenOrExecuteDialog(bool b)
Set this to true if this class should show a dialog to ask the user about how to handle various types...
void setStartupId(const QByteArray &startupId)
Sets the platform-specific startup id of the application launch.
void serviceSelected(const KService::Ptr &service)
Emitted by promptUserForApplication() once the user chooses an application.
void handled()
Emitted by promptUserForApplication() if it fully handled it including launching the app.
void canceled()
Emitted by promptUserForApplication() if the user canceled the application selection dialog.
void result(bool confirmed)
Implementations of this interface must emit result in showUntrustedProgramWarning.
void setErrorText(const QString &errorText)
void emitResult()
int error() const
void result(KJob *job)
void setError(int errorCode)
void setCapabilities(Capabilities capabilities)
QString errorText() const
static QString exec(const QString &protocol)
Returns the library / executable to open for the protocol protocol Example : "kio_ftp",...
static bool isHelperProtocol(const QUrl &url)
Returns whether the protocol can act as a helper protocol.
static QString defaultMimetype(const QUrl &url)
Returns default MIME type for this URL based on the protocol.
static Ptr serviceByStorageId(const QString &_storageId)
QString storageId() const
static Ptr serviceByDesktopName(const QString &_name)
QString exec() const
bool hasMimeType(const QString &mimeType) const
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
QString i18n(const char *text, const TYPE &arg...)
KSERVICE_EXPORT KService::Ptr preferredService(const QString &mimeType)
KCALUTILS_EXPORT QString mimeType()
A namespace for KIO globals.
KIOCORE_EXPORT QString buildErrorString(int errorCode, const QString &errorText)
Returns a translated error message for errorCode using the additional error information provided by e...
Definition job_error.cpp:31
T delegateExtension(KJob *job)
Returns the child of the job's uiDelegate() that implements the given extension, or nullptr if none w...
KCOREADDONS_EXPORT bool isInside()
bool authorizeUrlAction(const QString &action, const QUrl &baseURL, const QUrl &destURL)
Returns whether a certain URL related action is authorized.
bool openUrl(const QUrl &url)
bool isExecutable() const const
QMimeType mimeTypeForName(const QString &nameOrAlias) const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
void clear()
bool isEmpty() const const
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
QStringView mid(qsizetype start, qsizetype length) const const
RemoveFilename
QUrl adjusted(FormattingOptions options) const const
QString fileName(ComponentFormattingOptions options) const const
QUrl fromUserInput(const QString &userInput, const QString &workingDirectory, UserInputResolutionOptions options)
bool isLocalFile() const const
QString scheme() const const
QString toDisplayString(FormattingOptions options) const const
QString toLocalFile() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Jul 19 2024 11:57:19 by doxygen 1.11.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.