• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.14.38 API Reference
  • KDE Home
  • Contact Us
 

KIO

  • kio
  • kio
krun.cpp
Go to the documentation of this file.
1/* This file is part of the KDE libraries
2 Copyright (C) 2000 Torben Weis <weis@kde.org>
3 Copyright (C) 2006 David Faure <faure@kde.org>
4 Copyright (C) 2009 Michael Pyne <michael.pyne@kdemail.net>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20*/
21
22#include "krun.h"
23#include "krun_p.h"
24
25#include <config.h>
26
27#include <assert.h>
28#include <stdlib.h>
29#include <string.h>
30#include <unistd.h>
31#include <typeinfo>
32#include <sys/stat.h>
33
34#include <QtGui/QWidget>
35#include <QtGui/QLabel>
36#include <QtGui/QVBoxLayout>
37#include <QtGui/QHBoxLayout>
38#include <QtGui/QPlainTextEdit>
39#include <QtGui/QApplication>
40#include <QtGui/QDesktopWidget>
41
42#include <kmimetypetrader.h>
43#include <kmimetype.h>
44#include "kio/jobclasses.h" // for KIO::JobFlags
45#include "kio/job.h"
46#include "kio/jobuidelegate.h"
47#include "kio/global.h"
48#include "kio/scheduler.h"
49#include "kio/netaccess.h"
50#include "kfile/kopenwithdialog.h"
51#include "kfile/krecentdocument.h"
52#include "kdesktopfileactions.h"
53
54#include <kauthorized.h>
55#include <kmessageboxwrapper.h>
56#include <kurl.h>
57#include <kglobal.h>
58#include <ktoolinvocation.h>
59#include <kdebug.h>
60#include <klocale.h>
61#include <kprotocolmanager.h>
62#include <kstandarddirs.h>
63#include <kprocess.h>
64#include <QtCore/QFile>
65#include <QtCore/QFileInfo>
66#include <QtCore/QTextIStream>
67#include <QtCore/QDate>
68#include <QtCore/QRegExp>
69#include <QDir>
70#include <kdesktopfile.h>
71#include <kmacroexpander.h>
72#include <kshell.h>
73#include <QTextDocument>
74#include <kde_file.h>
75#include <kconfiggroup.h>
76#include <kdialog.h>
77#include <kstandardguiitem.h>
78#include <kguiitem.h>
79#include <ksavefile.h>
80
81#ifdef Q_WS_X11
82#include <kwindowsystem.h>
83#elif defined(Q_WS_WIN)
84#include <QDesktopServices>
85#endif
86
87KRun::KRunPrivate::KRunPrivate(KRun *parent)
88 : q(parent),
89 m_showingDialog(false)
90{
91}
92
93void KRun::KRunPrivate::startTimer()
94{
95 m_timer.start(0);
96}
97
98// ---------------------------------------------------------------------------
99
100bool KRun::isExecutableFile(const KUrl& url, const QString &mimetype)
101{
102 if (!url.isLocalFile()) {
103 return false;
104 }
105 QFileInfo file(url.toLocalFile());
106 if (file.isExecutable()) { // Got a prospective file to run
107 KMimeType::Ptr mimeType = KMimeType::mimeType(mimetype, KMimeType::ResolveAliases);
108 if (mimeType && (mimeType->is(QLatin1String("application/x-executable")) ||
109#ifdef Q_WS_WIN
110 mimeType->is(QLatin1String("application/x-ms-dos-executable")) ||
111#endif
112 mimeType->is(QLatin1String("application/x-executable-script")))
113 )
114 {
115 return true;
116 }
117 }
118 return false;
119}
120
121// This is called by foundMimeType, since it knows the mimetype of the URL
122bool KRun::runUrl(const KUrl& u, const QString& _mimetype, QWidget* window, bool tempFile, bool runExecutables, const QString& suggestedFileName, const QByteArray& asn)
123{
124 bool noRun = false;
125 bool noAuth = false;
126 if (_mimetype == QLatin1String("inode/directory-locked")) {
127 KMessageBoxWrapper::error(window,
128 i18n("<qt>Unable to enter <b>%1</b>.\nYou do not have access rights to this location.</qt>", Qt::escape(u.prettyUrl())));
129 return false;
130 }
131 else if (_mimetype == QLatin1String("application/x-desktop")) {
132 if (u.isLocalFile() && runExecutables) {
133 return KDesktopFileActions::run(u, true);
134 }
135 }
136 else if (isExecutableFile(u, _mimetype)) {
137 if (u.isLocalFile() && runExecutables) {
138 if (KAuthorized::authorize("shell_access")) {
139 return (KRun::runCommand(KShell::quoteArg(u.toLocalFile()), QString(), QString(), window, asn, u.directory())); // just execute the url as a command
140 // ## TODO implement deleting the file if tempFile==true
141 }
142 else {
143 noAuth = true;
144 }
145 }
146 else if (_mimetype == QLatin1String("application/x-executable")) {
147 noRun = true;
148 }
149 }
150 else if (isExecutable(_mimetype)) {
151 if (!runExecutables) {
152 noRun = true;
153 }
154
155 if (!KAuthorized::authorize("shell_access")) {
156 noAuth = true;
157 }
158 }
159
160 if (noRun) {
161 KMessageBox::sorry(window,
162 i18n("<qt>The file <b>%1</b> is an executable program. "
163 "For safety it will not be started.</qt>", Qt::escape(u.prettyUrl())));
164 return false;
165 }
166 if (noAuth) {
167 KMessageBoxWrapper::error(window,
168 i18n("<qt>You do not have permission to run <b>%1</b>.</qt>", Qt::escape(u.prettyUrl())));
169 return false;
170 }
171
172 KUrl::List lst;
173 lst.append(u);
174
175 KService::Ptr offer = KMimeTypeTrader::self()->preferredService(_mimetype);
176
177 if (!offer) {
178#ifdef Q_WS_WIN
179 // As KDE on windows doesnt know about the windows default applications offers will be empty in nearly all cases.
180 // So we use QDesktopServices::openUrl to let windows decide how to open the file
181 return QDesktopServices::openUrl(u);
182#else
183 // Open-with dialog
184 // TODO : pass the mimetype as a parameter, to show it (comment field) in the dialog !
185 // Hmm, in fact KOpenWithDialog::setServiceType already guesses the mimetype from the first URL of the list...
186 return displayOpenWithDialog(lst, window, tempFile, suggestedFileName, asn);
187#endif
188 }
189
190 return KRun::run(*offer, lst, window, tempFile, suggestedFileName, asn);
191}
192
193bool KRun::displayOpenWithDialog(const KUrl::List& lst, QWidget* window, bool tempFiles,
194 const QString& suggestedFileName, const QByteArray& asn)
195{
196 if (!KAuthorized::authorizeKAction("openwith")) {
197 KMessageBox::sorry(window,
198 i18n("You are not authorized to select an application to open this file."));
199 return false;
200 }
201
202#ifdef Q_WS_WIN
203 KConfigGroup cfgGroup(KGlobal::config(), "KOpenWithDialog Settings");
204 if (cfgGroup.readEntry("Native", true)) {
205 return KRun::KRunPrivate::displayNativeOpenWithDialog(lst, window, tempFiles,
206 suggestedFileName, asn);
207 }
208#endif
209 KOpenWithDialog l(lst, i18n("Open with:"), QString(), window);
210 l.setWindowModality(Qt::WindowModal);
211 if (l.exec()) {
212 KService::Ptr service = l.service();
213 if (!service) {
214 kDebug(7010) << "No service set, running " << l.text();
215 service = KService::Ptr(new KService(QString() /*name*/, l.text(), QString() /*icon*/));
216 }
217 return KRun::run(*service, lst, window, tempFiles, suggestedFileName, asn);
218 }
219 return false;
220}
221
222#ifndef KDE_NO_DEPRECATED
223void KRun::shellQuote(QString &_str)
224{
225 // Credits to Walter, says Bernd G. :)
226 if (_str.isEmpty()) { // Don't create an explicit empty parameter
227 return;
228 }
229 QChar q('\'');
230 _str.replace(q, "'\\''").prepend(q).append(q);
231}
232#endif
233
234
235class KRunMX1 : public KMacroExpanderBase
236{
237public:
238 KRunMX1(const KService &_service) :
239 KMacroExpanderBase('%'), hasUrls(false), hasSpec(false), service(_service) {}
240
241 bool hasUrls: 1, hasSpec: 1;
242
243protected:
244 virtual int expandEscapedMacro(const QString &str, int pos, QStringList &ret);
245
246private:
247 const KService &service;
248};
249
250int
251KRunMX1::expandEscapedMacro(const QString &str, int pos, QStringList &ret)
252{
253 uint option = str[pos + 1].unicode();
254 switch (option) {
255 case 'c':
256 ret << service.name().replace('%', "%%");
257 break;
258 case 'k':
259 ret << service.entryPath().replace('%', "%%");
260 break;
261 case 'i':
262 ret << "--icon" << service.icon().replace('%', "%%");
263 break;
264 case 'm':
265// ret << "-miniicon" << service.icon().replace( '%', "%%" );
266 kWarning() << "-miniicon isn't supported anymore (service"
267 << service.name() << ')';
268 break;
269 case 'u':
270 case 'U':
271 hasUrls = true;
272 /* fallthrough */
273 case 'f':
274 case 'F':
275 case 'n':
276 case 'N':
277 case 'd':
278 case 'D':
279 case 'v':
280 hasSpec = true;
281 /* fallthrough */
282 default:
283 return -2; // subst with same and skip
284 }
285 return 2;
286}
287
288class KRunMX2 : public KMacroExpanderBase
289{
290public:
291 KRunMX2(const KUrl::List &_urls) :
292 KMacroExpanderBase('%'), ignFile(false), urls(_urls) {}
293
294 bool ignFile: 1;
295
296protected:
297 virtual int expandEscapedMacro(const QString &str, int pos, QStringList &ret);
298
299private:
300 void subst(int option, const KUrl &url, QStringList &ret);
301
302 const KUrl::List &urls;
303};
304
305void
306KRunMX2::subst(int option, const KUrl &url, QStringList &ret)
307{
308 switch (option) {
309 case 'u':
310 ret << ((url.isLocalFile() && url.fragment().isNull() && url.encodedQuery().isNull()) ?
311 QDir::toNativeSeparators(url.toLocalFile()) : url.url());
312 break;
313 case 'd':
314 ret << url.directory();
315 break;
316 case 'f':
317 ret << QDir::toNativeSeparators(url.toLocalFile());
318 break;
319 case 'n':
320 ret << url.fileName();
321 break;
322 case 'v':
323 if (url.isLocalFile() && QFile::exists(url.toLocalFile())) {
324 ret << KDesktopFile(url.toLocalFile()).desktopGroup().readEntry("Dev");
325 }
326 break;
327 }
328 return;
329}
330
331int
332KRunMX2::expandEscapedMacro(const QString &str, int pos, QStringList &ret)
333{
334 uint option = str[pos + 1].unicode();
335 switch (option) {
336 case 'f':
337 case 'u':
338 case 'n':
339 case 'd':
340 case 'v':
341 if (urls.isEmpty()) {
342 if (!ignFile) {
343 kDebug() << "No URLs supplied to single-URL service" << str;
344 }
345 }
346 else if (urls.count() > 1) {
347 kWarning() << urls.count() << "URLs supplied to single-URL service" << str;
348 }
349 else {
350 subst(option, urls.first(), ret);
351 }
352 break;
353 case 'F':
354 case 'U':
355 case 'N':
356 case 'D':
357 option += 'a' - 'A';
358 for (KUrl::List::ConstIterator it = urls.begin(); it != urls.end(); ++it)
359 subst(option, *it, ret);
360 break;
361 case '%':
362 ret = QStringList(QLatin1String("%"));
363 break;
364 default:
365 return -2; // subst with same and skip
366 }
367 return 2;
368}
369
370static QStringList supportedProtocols(const KService& _service)
371{
372 // Check which protocols the application supports.
373 // This can be a list of actual protocol names, or just KIO for KDE apps.
374 QStringList supportedProtocols = _service.property("X-KDE-Protocols").toStringList();
375 KRunMX1 mx1(_service);
376 QString exec = _service.exec();
377 if (mx1.expandMacrosShellQuote(exec) && !mx1.hasUrls) {
378 Q_ASSERT(supportedProtocols.isEmpty()); // huh? If you support protocols you need %u or %U...
379 }
380 else {
381 if (supportedProtocols.isEmpty()) {
382 // compat mode: assume KIO if not set and it's a KDE app (or a KDE service)
383 const QStringList categories = _service.property("Categories").toStringList();
384 if (categories.contains("KDE")
385 || !_service.isApplication()
386 || _service.entryPath().isEmpty() /*temp service*/) {
387 supportedProtocols.append("KIO");
388 }
389 else { // if no KDE app, be a bit over-generic
390 supportedProtocols.append("http");
391 supportedProtocols.append("https"); // #253294
392 supportedProtocols.append("ftp");
393 }
394 }
395 }
396 kDebug(7010) << "supportedProtocols:" << supportedProtocols;
397 return supportedProtocols;
398}
399
400static bool isProtocolInSupportedList(const KUrl& url, const QStringList& supportedProtocols)
401{
402 if (supportedProtocols.contains("KIO"))
403 return true;
404 return url.isLocalFile() || supportedProtocols.contains(url.protocol().toLower());
405}
406
407QStringList KRun::processDesktopExec(const KService &_service, const KUrl::List& _urls, bool tempFiles, const QString& suggestedFileName)
408{
409 QString exec = _service.exec();
410 if (exec.isEmpty()) {
411 kWarning() << "KRun: no Exec field in `" << _service.entryPath() << "' !";
412 return QStringList();
413 }
414
415 QStringList result;
416 bool appHasTempFileOption;
417
418 KRunMX1 mx1(_service);
419 KRunMX2 mx2(_urls);
420
421 if (!mx1.expandMacrosShellQuote(exec)) { // Error in shell syntax
422 kWarning() << "KRun: syntax error in command" << _service.exec() << ", service" << _service.name();
423 return QStringList();
424 }
425
426 // FIXME: the current way of invoking kioexec disables term and su use
427
428 // Check if we need "tempexec" (kioexec in fact)
429 appHasTempFileOption = tempFiles && _service.property("X-KDE-HasTempFileOption").toBool();
430 if (tempFiles && !appHasTempFileOption && _urls.size()) {
431 const QString kioexec = KStandardDirs::findExe("kioexec");
432 Q_ASSERT(!kioexec.isEmpty());
433 result << kioexec << "--tempfiles" << exec;
434 if (!suggestedFileName.isEmpty()) {
435 result << "--suggestedfilename";
436 result << suggestedFileName;
437 }
438 result += _urls.toStringList();
439 return result;
440 }
441
442 // Check if we need kioexec
443 bool useKioexec = false;
444 if (!mx1.hasUrls) {
445 for (KUrl::List::ConstIterator it = _urls.begin(); it != _urls.end(); ++it)
446 if (!(*it).isLocalFile() && !KProtocolInfo::isHelperProtocol(*it)) {
447 useKioexec = true;
448 kDebug(7010) << "non-local files, application does not support urls, using kioexec";
449 break;
450 }
451 } else { // app claims to support %u/%U, check which protocols
452 QStringList appSupportedProtocols = supportedProtocols(_service);
453 for (KUrl::List::ConstIterator it = _urls.begin(); it != _urls.end(); ++it)
454 if (!isProtocolInSupportedList(*it, appSupportedProtocols) && !KProtocolInfo::isHelperProtocol(*it)) {
455 useKioexec = true;
456 kDebug(7010) << "application does not support url, using kioexec:" << *it;
457 break;
458 }
459 }
460 if (useKioexec) {
461 // We need to run the app through kioexec
462 const QString kioexec = KStandardDirs::findExe("kioexec");
463 Q_ASSERT(!kioexec.isEmpty());
464 result << kioexec;
465 if (tempFiles) {
466 result << "--tempfiles";
467 }
468 if (!suggestedFileName.isEmpty()) {
469 result << "--suggestedfilename";
470 result << suggestedFileName;
471 }
472 result << exec;
473 result += _urls.toStringList();
474 return result;
475 }
476
477 if (appHasTempFileOption) {
478 exec += " --tempfile";
479 }
480
481 // Did the user forget to append something like '%f'?
482 // If so, then assume that '%f' is the right choice => the application
483 // accepts only local files.
484 if (!mx1.hasSpec) {
485 exec += " %f";
486 mx2.ignFile = true;
487 }
488
489 mx2.expandMacrosShellQuote(exec); // syntax was already checked, so don't check return value
490
491 /*
492 1 = need_shell, 2 = terminal, 4 = su
493
494 0 << split(cmd)
495 1 << "sh" << "-c" << cmd
496 2 << split(term) << "-e" << split(cmd)
497 3 << split(term) << "-e" << "sh" << "-c" << cmd
498
499 4 << "kdesu" << "-u" << user << "-c" << cmd
500 5 << "kdesu" << "-u" << user << "-c" << ("sh -c " + quote(cmd))
501 6 << split(term) << "-e" << "su" << user << "-c" << cmd
502 7 << split(term) << "-e" << "su" << user << "-c" << ("sh -c " + quote(cmd))
503
504 "sh -c" is needed in the "su" case, too, as su uses the user's login shell, not sh.
505 this could be optimized with the -s switch of some su versions (e.g., debian linux).
506 */
507
508 if (_service.terminal()) {
509 KConfigGroup cg(KGlobal::config(), "General");
510 QString terminal = cg.readPathEntry("TerminalApplication", "konsole");
511 if (terminal == "konsole") {
512 if (!_service.path().isEmpty()) {
513 terminal += " --workdir " + KShell::quoteArg(_service.path());
514 }
515 terminal += " -caption=%c %i %m";
516 }
517 terminal += ' ';
518 terminal += _service.terminalOptions();
519 if (!mx1.expandMacrosShellQuote(terminal)) {
520 kWarning() << "KRun: syntax error in command" << terminal << ", service" << _service.name();
521 return QStringList();
522 }
523 mx2.expandMacrosShellQuote(terminal);
524 result = KShell::splitArgs(terminal); // assuming that the term spec never needs a shell!
525 result << "-e";
526 }
527
528 KShell::Errors err;
529 QStringList execlist = KShell::splitArgs(exec, KShell::AbortOnMeta | KShell::TildeExpand, &err);
530 if (err == KShell::NoError && !execlist.isEmpty()) { // mx1 checked for syntax errors already
531 // Resolve the executable to ensure that helpers in lib/kde4/libexec/ are found.
532 // Too bad for commands that need a shell - they must reside in $PATH.
533 const QString exePath = KStandardDirs::findExe(execlist[0]);
534 if (!exePath.isEmpty()) {
535 execlist[0] = exePath;
536 }
537 }
538 if (_service.substituteUid()) {
539 if (_service.terminal()) {
540 result << "su";
541 }
542 else {
543 result << KStandardDirs::findExe("kdesu") << "-u";
544 }
545
546 result << _service.username() << "-c";
547 if (err == KShell::FoundMeta) {
548 exec = "/bin/sh -c " + KShell::quoteArg(exec);
549 }
550 else {
551 exec = KShell::joinArgs(execlist);
552 }
553 result << exec;
554 }
555 else {
556 if (err == KShell::FoundMeta) {
557 result << "/bin/sh" << "-c" << exec;
558 }
559 else {
560 result += execlist;
561 }
562 }
563
564 return result;
565}
566
567//static
568QString KRun::binaryName(const QString & execLine, bool removePath)
569{
570 // Remove parameters and/or trailing spaces.
571 const QStringList args = KShell::splitArgs(execLine);
572 for (QStringList::ConstIterator it = args.begin(); it != args.end(); ++it)
573 if (!(*it).contains('=')) {
574 // Remove path if wanted
575 return removePath ? (*it).mid((*it).lastIndexOf('/') + 1) : *it;
576 }
577 return QString();
578}
579
580static bool runCommandInternal(KProcess* proc, const KService* service, const QString& executable,
581 const QString &userVisibleName, const QString & iconName, QWidget* window,
582 const QByteArray& asn)
583{
584 if (window != NULL) {
585 window = window->topLevelWidget();
586 }
587 if (service && !service->entryPath().isEmpty()
588 && !KDesktopFile::isAuthorizedDesktopFile(service->entryPath()))
589 {
590 kWarning() << "No authorization to execute " << service->entryPath();
591 KMessageBox::sorry(window, i18n("You are not authorized to execute this file."));
592 delete proc;
593 return false;
594 }
595
596 QString bin = KRun::binaryName(executable, true);
597#ifdef Q_WS_X11 // Startup notification doesn't work with QT/E, service isn't needed without Startup notification
598 bool silent;
599 QByteArray wmclass;
600 KStartupInfoId id;
601 bool startup_notify = (asn != "0" && KRun::checkStartupNotify(QString() /*unused*/, service, &silent, &wmclass));
602 if (startup_notify) {
603 id.initId(asn);
604 id.setupStartupEnv();
605 KStartupInfoData data;
606 data.setHostname();
607 data.setBin(bin);
608 if (!userVisibleName.isEmpty()) {
609 data.setName(userVisibleName);
610 }
611 else if (service && !service->name().isEmpty()) {
612 data.setName(service->name());
613 }
614 data.setDescription(i18n("Launching %1" , data.name()));
615 if (!iconName.isEmpty()) {
616 data.setIcon(iconName);
617 }
618 else if (service && !service->icon().isEmpty()) {
619 data.setIcon(service->icon());
620 }
621 if (!wmclass.isEmpty()) {
622 data.setWMClass(wmclass);
623 }
624 if (silent) {
625 data.setSilent(KStartupInfoData::Yes);
626 }
627 data.setDesktop(KWindowSystem::currentDesktop());
628 if (window) {
629 data.setLaunchedBy(window->winId());
630 }
631 if(service && !service->entryPath().isEmpty())
632 data.setApplicationId(service->entryPath());
633 KStartupInfo::sendStartup(id, data);
634 }
635 int pid = KProcessRunner::run(proc, executable, id);
636 if (startup_notify && pid) {
637 KStartupInfoData data;
638 data.addPid(pid);
639 KStartupInfo::sendChange(id, data);
640 KStartupInfo::resetStartupEnv();
641 }
642 return pid != 0;
643#else
644 Q_UNUSED(userVisibleName);
645 Q_UNUSED(iconName);
646 return KProcessRunner::run(proc, bin) != 0;
647#endif
648}
649
650// This code is also used in klauncher.
651bool KRun::checkStartupNotify(const QString& /*binName*/, const KService* service, bool* silent_arg, QByteArray* wmclass_arg)
652{
653 bool silent = false;
654 QByteArray wmclass;
655 if (service && service->property("StartupNotify").isValid()) {
656 silent = !service->property("StartupNotify").toBool();
657 wmclass = service->property("StartupWMClass").toString().toLatin1();
658 }
659 else if (service && service->property("X-KDE-StartupNotify").isValid()) {
660 silent = !service->property("X-KDE-StartupNotify").toBool();
661 wmclass = service->property("X-KDE-WMClass").toString().toLatin1();
662 }
663 else { // non-compliant app
664 if (service) {
665 if (service->isApplication()) { // doesn't have .desktop entries needed, start as non-compliant
666 wmclass = "0"; // krazy:exclude=doublequote_chars
667 }
668 else {
669 return false; // no startup notification at all
670 }
671 }
672 else {
673#if 0
674 // Create startup notification even for apps for which there shouldn't be any,
675 // just without any visual feedback. This will ensure they'll be positioned on the proper
676 // virtual desktop, and will get user timestamp from the ASN ID.
677 wmclass = '0';
678 silent = true;
679#else // That unfortunately doesn't work, when the launched non-compliant application
680 // launches another one that is compliant and there is any delay inbetween (bnc:#343359)
681 return false;
682#endif
683 }
684 }
685 if (silent_arg != NULL) {
686 *silent_arg = silent;
687 }
688 if (wmclass_arg != NULL) {
689 *wmclass_arg = wmclass;
690 }
691 return true;
692}
693
694static bool runTempService(const KService& _service, const KUrl::List& _urls, QWidget* window,
695 bool tempFiles, const QString& suggestedFileName, const QByteArray& asn)
696{
697 if (!_urls.isEmpty()) {
698 kDebug(7010) << "runTempService: first url " << _urls.first().url();
699 }
700
701 QStringList args;
702 if ((_urls.count() > 1) && !_service.allowMultipleFiles()) {
703 // We need to launch the application N times. That sucks.
704 // We ignore the result for application 2 to N.
705 // For the first file we launch the application in the
706 // usual way. The reported result is based on this
707 // application.
708 KUrl::List::ConstIterator it = _urls.begin();
709 while (++it != _urls.end()) {
710 KUrl::List singleUrl;
711 singleUrl.append(*it);
712 runTempService(_service, singleUrl, window, tempFiles, suggestedFileName, QByteArray());
713 }
714 KUrl::List singleUrl;
715 singleUrl.append(_urls.first());
716 args = KRun::processDesktopExec(_service, singleUrl, tempFiles, suggestedFileName);
717 }
718 else {
719 args = KRun::processDesktopExec(_service, _urls, tempFiles, suggestedFileName);
720 }
721 if (args.isEmpty()) {
722 KMessageBox::sorry(window, i18n("Error processing Exec field in %1", _service.entryPath()));
723 return false;
724 }
725 kDebug(7010) << "runTempService: KProcess args=" << args;
726
727 KProcess * proc = new KProcess;
728 *proc << args;
729
730 const QString& path = _service.path();
731 if (!path.isEmpty()) {
732 proc->setWorkingDirectory(path);
733 } else if (!_urls.isEmpty()) {
734 const KUrl& url = _urls.first();
735 if (url.isLocalFile()) {
736 proc->setWorkingDirectory(url.directory());
737 }
738 }
739
740 return runCommandInternal(proc, &_service, KRun::binaryName(_service.exec(), false),
741 _service.name(), _service.icon(), window, asn);
742}
743
744// WARNING: don't call this from processDesktopExec, since klauncher uses that too...
745static KUrl::List resolveURLs(const KUrl::List& _urls, const KService& _service)
746{
747 // Check which protocols the application supports.
748 // This can be a list of actual protocol names, or just KIO for KDE apps.
749 QStringList appSupportedProtocols = supportedProtocols(_service);
750 KUrl::List urls(_urls);
751 if (!appSupportedProtocols.contains("KIO")) {
752 for (KUrl::List::Iterator it = urls.begin(); it != urls.end(); ++it) {
753 const KUrl url = *it;
754 bool supported = isProtocolInSupportedList(url, appSupportedProtocols);
755 kDebug(7010) << "Looking at url=" << url << " supported=" << supported;
756 if (!supported && KProtocolInfo::protocolClass(url.protocol()) == ":local") {
757 // Maybe we can resolve to a local URL?
758 KUrl localURL = KIO::NetAccess::mostLocalUrl(url, 0);
759 if (localURL != url) {
760 *it = localURL;
761 kDebug(7010) << "Changed to " << localURL;
762 }
763 }
764 }
765 }
766 return urls;
767}
768
769// Simple KDialog that resizes the given text edit after being shown to more
770// or less fit the enclosed text.
771class SecureMessageDialog : public KDialog
772{
773 public:
774 SecureMessageDialog(QWidget *parent) : KDialog(parent), m_textEdit(0)
775 {
776 }
777
778 void setTextEdit(QPlainTextEdit *textEdit)
779 {
780 m_textEdit = textEdit;
781 }
782
783 protected:
784 virtual void showEvent(QShowEvent* e)
785 {
786 // Now that we're shown, use our width to calculate a good
787 // bounding box for the text, and resize m_textEdit appropriately.
788 KDialog::showEvent(e);
789
790 if(!m_textEdit)
791 return;
792
793 QSize fudge(20, 24); // About what it sounds like :-/
794
795 // Form rect with a lot of height for bounding. Use no more than
796 // 5 lines.
797 QRect curRect(m_textEdit->rect());
798 QFontMetrics metrics(fontMetrics());
799 curRect.setHeight(5 * metrics.lineSpacing());
800 curRect.setWidth(qMax(curRect.width(), 300)); // At least 300 pixels ok?
801
802 QString text(m_textEdit->toPlainText());
803 curRect = metrics.boundingRect(curRect, Qt::TextWordWrap | Qt::TextSingleLine, text);
804
805 // Scroll bars interfere. If we don't think there's enough room, enable
806 // the vertical scrollbar however.
807 m_textEdit->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
808 if(curRect.height() < m_textEdit->height()) { // then we've got room
809 m_textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
810 m_textEdit->setMaximumHeight(curRect.height() + fudge.height());
811 }
812
813 m_textEdit->setMinimumSize(curRect.size() + fudge);
814 m_textEdit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
815 updateGeometry();
816 }
817
818 private:
819 QPlainTextEdit *m_textEdit;
820};
821
822// Helper function to make the given .desktop file executable by ensuring
823// that a #!/usr/bin/env xdg-open line is added if necessary and the file has
824// the +x bit set for the user. Returns false if either fails.
825static bool makeFileExecutable(const QString &fileName)
826{
827 // Open the file and read the first two characters, check if it's
828 // #!. If not, create a new file, prepend appropriate lines, and copy
829 // over.
830 QFile desktopFile(fileName);
831 if (!desktopFile.open(QFile::ReadOnly)) {
832 kError(7010) << "Error opening service" << fileName << desktopFile.errorString();
833 return false;
834 }
835
836 QByteArray header = desktopFile.peek(2); // First two chars of file
837 if (header.size() == 0) {
838 kError(7010) << "Error inspecting service" << fileName << desktopFile.errorString();
839 return false; // Some kind of error
840 }
841
842 if (header != "#!") {
843 // Add header
844 KSaveFile saveFile;
845 saveFile.setFileName(fileName);
846 if (!saveFile.open()) {
847 kError(7010) << "Unable to open replacement file for" << fileName << saveFile.errorString();
848 return false;
849 }
850
851 QByteArray shebang("#!/usr/bin/env xdg-open\n");
852 if (saveFile.write(shebang) != shebang.size()) {
853 kError(7010) << "Error occurred adding header for" << fileName << saveFile.errorString();
854 saveFile.abort();
855 return false;
856 }
857
858 // Now copy the one into the other and then close and reopen desktopFile
859 QByteArray desktopData(desktopFile.readAll());
860 if (desktopData.isEmpty()) {
861 kError(7010) << "Unable to read service" << fileName << desktopFile.errorString();
862 saveFile.abort();
863 return false;
864 }
865
866 if (saveFile.write(desktopData) != desktopData.size()) {
867 kError(7010) << "Error copying service" << fileName << saveFile.errorString();
868 saveFile.abort();
869 return false;
870 }
871
872 desktopFile.close();
873 if (!saveFile.finalize()) { // Figures....
874 kError(7010) << "Error committing changes to service" << fileName << saveFile.errorString();
875 return false;
876 }
877
878 if (!desktopFile.open(QFile::ReadOnly)) {
879 kError(7010) << "Error re-opening service" << fileName << desktopFile.errorString();
880 return false;
881 }
882 } // Add header
883
884 // corresponds to owner on unix, which will have to do since if the user
885 // isn't the owner we can't change perms anyways.
886 if (!desktopFile.setPermissions(QFile::ExeUser | desktopFile.permissions())) {
887 kError(7010) << "Unable to change permissions for" << fileName << desktopFile.errorString();
888 return false;
889 }
890
891 // whew
892 return true;
893}
894
895// Helper function to make a .desktop file executable if prompted by the user.
896// returns true if KRun::run() should continue with execution, false if user declined
897// to make the file executable or we failed to make it executable.
898static bool makeServiceExecutable(const KService& service, QWidget* window)
899{
900 if (!KAuthorized::authorize("run_desktop_files")) {
901 kWarning() << "No authorization to execute " << service.entryPath();
902 KMessageBox::sorry(window, i18n("You are not authorized to execute this service."));
903 return false; // Don't circumvent the Kiosk
904 }
905
906 KGuiItem continueItem = KStandardGuiItem::cont();
907
908 SecureMessageDialog *baseDialog = new SecureMessageDialog(window);
909
910 baseDialog->setButtons(KDialog::Ok | KDialog::Cancel);
911 baseDialog->setButtonGuiItem(KDialog::Ok, continueItem);
912 baseDialog->setDefaultButton(KDialog::Cancel);
913 baseDialog->setButtonFocus(KDialog::Cancel);
914 baseDialog->setCaption(i18nc("Warning about executing unknown .desktop file", "Warning"));
915
916 // Dialog will have explanatory text with a disabled lineedit with the
917 // Exec= to make it visually distinct.
918 QWidget *baseWidget = new QWidget(baseDialog);
919 QHBoxLayout *mainLayout = new QHBoxLayout(baseWidget);
920
921 QLabel *iconLabel = new QLabel(baseWidget);
922 QPixmap warningIcon(KIconLoader::global()->loadIcon("dialog-warning", KIconLoader::NoGroup, KIconLoader::SizeHuge));
923 mainLayout->addWidget(iconLabel);
924 iconLabel->setPixmap(warningIcon);
925
926 QVBoxLayout *contentLayout = new QVBoxLayout;
927 QString warningMessage = i18nc("program name follows in a line edit below",
928 "This will start the program:");
929
930 QLabel *message = new QLabel(warningMessage, baseWidget);
931 contentLayout->addWidget(message);
932
933 // We can use KStandardDirs::findExe to resolve relative pathnames
934 // but that gets rid of the command line arguments.
935 QString program = KStandardDirs::realFilePath(service.exec());
936
937 QPlainTextEdit *textEdit = new QPlainTextEdit(baseWidget);
938 textEdit->setPlainText(program);
939 textEdit->setReadOnly(true);
940 contentLayout->addWidget(textEdit);
941
942 QLabel *footerLabel = new QLabel(i18n("If you do not trust this program, click Cancel"));
943 contentLayout->addWidget(footerLabel);
944 contentLayout->addStretch(0); // Don't allow the text edit to expand
945
946 mainLayout->addLayout(contentLayout);
947
948 baseDialog->setMainWidget(baseWidget);
949 baseDialog->setTextEdit(textEdit);
950
951 // Constrain maximum size. Minimum size set in
952 // the dialog's show event.
953 QSize screenSize = QApplication::desktop()->screen()->size();
954 baseDialog->resize(screenSize.width() / 4, 50);
955 baseDialog->setMaximumHeight(screenSize.height() / 3);
956 baseDialog->setMaximumWidth(screenSize.width() / 10 * 8);
957
958 int result = baseDialog->exec();
959 if (result != KDialog::Accepted) {
960 return false;
961 }
962
963 // Assume that service is an absolute path since we're being called (relative paths
964 // would have been allowed unless Kiosk said no, therefore we already know where the
965 // .desktop file is. Now add a header to it if it doesn't already have one
966 // and add the +x bit.
967
968 if (!::makeFileExecutable(service.entryPath())) {
969 QString serviceName = service.name();
970 if(serviceName.isEmpty())
971 serviceName = service.genericName();
972
973 KMessageBox::sorry(
974 window,
975 i18n("Unable to make the service %1 executable, aborting execution", serviceName)
976 );
977
978 return false;
979 }
980
981 return true;
982}
983
984bool KRun::run(const KService& _service, const KUrl::List& _urls, QWidget* window,
985 bool tempFiles, const QString& suggestedFileName, const QByteArray& asn)
986{
987 if (!_service.entryPath().isEmpty() &&
988 !KDesktopFile::isAuthorizedDesktopFile(_service.entryPath()) &&
989 !::makeServiceExecutable(_service, window))
990 {
991 return false;
992 }
993
994 if (!tempFiles) {
995 // Remember we opened those urls, for the "recent documents" menu in kicker
996 KUrl::List::ConstIterator it = _urls.begin();
997 for (; it != _urls.end(); ++it) {
998 //kDebug(7010) << "KRecentDocument::adding " << (*it).url();
999 KRecentDocument::add(*it, _service.desktopEntryName());
1000 }
1001 }
1002
1003 if (tempFiles || _service.entryPath().isEmpty() || !suggestedFileName.isEmpty()) {
1004 return runTempService(_service, _urls, window, tempFiles, suggestedFileName, asn);
1005 }
1006
1007 kDebug(7010) << "KRun::run " << _service.entryPath();
1008
1009 if (!_urls.isEmpty()) {
1010 kDebug(7010) << "First url " << _urls.first().url();
1011 }
1012
1013 // Resolve urls if needed, depending on what the app supports
1014 const KUrl::List urls = resolveURLs(_urls, _service);
1015
1016 QString error;
1017 int pid = 0;
1018
1019 QByteArray myasn = asn;
1020 // startServiceByDesktopPath() doesn't take QWidget*, add it to the startup info now
1021 if (window != NULL) {
1022 if (myasn.isEmpty()) {
1023 myasn = KStartupInfo::createNewStartupId();
1024 }
1025 if (myasn != "0") {
1026 KStartupInfoId id;
1027 id.initId(myasn);
1028 KStartupInfoData data;
1029 data.setLaunchedBy(window->winId());
1030 KStartupInfo::sendChange(id, data);
1031 }
1032 }
1033
1034 int i = KToolInvocation::startServiceByDesktopPath(
1035 _service.entryPath(), urls.toStringList(), &error, 0L, &pid, myasn
1036 );
1037
1038 if (i != 0) {
1039 kDebug(7010) << error;
1040 KMessageBox::sorry(window, error);
1041 return false;
1042 }
1043
1044 kDebug(7010) << "startServiceByDesktopPath worked fine";
1045 return true;
1046}
1047
1048
1049bool KRun::run(const QString& _exec, const KUrl::List& _urls, QWidget* window, const QString& _name,
1050 const QString& _icon, const QByteArray& asn)
1051{
1052 KService::Ptr service(new KService(_name, _exec, _icon));
1053
1054 return run(*service, _urls, window, false, QString(), asn);
1055}
1056
1057bool KRun::runCommand(const QString &cmd, QWidget* window)
1058{
1059 return runCommand(cmd, window, QString());
1060}
1061
1062bool KRun::runCommand(const QString& cmd, QWidget* window, const QString& workingDirectory)
1063{
1064 if (cmd.isEmpty()) {
1065 kWarning() << "Command was empty, nothing to run";
1066 return false;
1067 }
1068
1069 const QStringList args = KShell::splitArgs(cmd);
1070 if (args.isEmpty()) {
1071 kWarning() << "Command could not be parsed.";
1072 return false;
1073 }
1074
1075 const QString bin = args.first();
1076 return KRun::runCommand(cmd, bin, bin /*iconName*/, window, QByteArray(), workingDirectory);
1077}
1078
1079bool KRun::runCommand(const QString& cmd, const QString &execName, const QString & iconName, QWidget* window, const QByteArray& asn)
1080{
1081 return runCommand(cmd, execName, iconName, window, asn, QString());
1082}
1083
1084bool KRun::runCommand(const QString& cmd, const QString &execName, const QString & iconName,
1085 QWidget* window, const QByteArray& asn, const QString& workingDirectory)
1086{
1087 kDebug(7010) << "runCommand " << cmd << "," << execName;
1088 KProcess * proc = new KProcess;
1089 proc->setShellCommand(cmd);
1090 if (!workingDirectory.isEmpty()) {
1091 proc->setWorkingDirectory(workingDirectory);
1092 }
1093 QString bin = binaryName(execName, true);
1094 KService::Ptr service = KService::serviceByDesktopName(bin);
1095 return runCommandInternal(proc, service.data(),
1096 execName /*executable to check for in slotProcessExited*/,
1097 execName /*user-visible name*/,
1098 iconName, window, asn);
1099}
1100
1101KRun::KRun(const KUrl& url, QWidget* window, mode_t mode, bool isLocalFile,
1102 bool showProgressInfo, const QByteArray& asn)
1103 : d(new KRunPrivate(this))
1104{
1105 d->m_timer.setObjectName("KRun::timer");
1106 d->m_timer.setSingleShot(true);
1107 d->init(url, window, mode, isLocalFile, showProgressInfo, asn);
1108}
1109
1110void KRun::KRunPrivate::init(const KUrl& url, QWidget* window, mode_t mode, bool isLocalFile,
1111 bool showProgressInfo, const QByteArray& asn)
1112{
1113 m_bFault = false;
1114 m_bAutoDelete = true;
1115 m_bProgressInfo = showProgressInfo;
1116 m_bFinished = false;
1117 m_job = 0L;
1118 m_strURL = url;
1119 m_bScanFile = false;
1120 m_bIsDirectory = false;
1121 m_bIsLocalFile = isLocalFile;
1122 m_mode = mode;
1123 m_runExecutables = true;
1124 m_window = window;
1125 m_asn = asn;
1126 q->setEnableExternalBrowser(true);
1127
1128 // Start the timer. This means we will return to the event
1129 // loop and do initialization afterwards.
1130 // Reason: We must complete the constructor before we do anything else.
1131 m_bInit = true;
1132 q->connect(&m_timer, SIGNAL(timeout()), q, SLOT(slotTimeout()));
1133 startTimer();
1134 //kDebug(7010) << "new KRun" << q << url << "timer=" << &m_timer;
1135
1136 KGlobal::ref();
1137}
1138
1139void KRun::init()
1140{
1141 kDebug(7010) << "INIT called";
1142 if (!d->m_strURL.isValid()) {
1143 // TODO KDE5: call virtual method on error (see BrowserRun::init)
1144 d->m_showingDialog = true;
1145 KMessageBoxWrapper::error(d->m_window, i18n("Malformed URL\n%1", d->m_strURL.url()));
1146 d->m_showingDialog = false;
1147 d->m_bFault = true;
1148 d->m_bFinished = true;
1149 d->startTimer();
1150 return;
1151 }
1152 if (!KAuthorized::authorizeUrlAction("open", KUrl(), d->m_strURL)) {
1153 QString msg = KIO::buildErrorString(KIO::ERR_ACCESS_DENIED, d->m_strURL.prettyUrl());
1154 d->m_showingDialog = true;
1155 KMessageBoxWrapper::error(d->m_window, msg);
1156 d->m_showingDialog = false;
1157 d->m_bFault = true;
1158 d->m_bFinished = true;
1159 d->startTimer();
1160 return;
1161 }
1162
1163 if (!d->m_bIsLocalFile && d->m_strURL.isLocalFile()) {
1164 d->m_bIsLocalFile = true;
1165 }
1166
1167 if (!d->m_externalBrowser.isEmpty() && d->m_strURL.protocol().startsWith(QLatin1String("http"))) {
1168 if (d->runExecutable(d->m_externalBrowser)) {
1169 return;
1170 }
1171 } else if (d->m_bIsLocalFile) {
1172 if (d->m_mode == 0) {
1173 KDE_struct_stat buff;
1174 if (KDE::stat(d->m_strURL.toLocalFile(), &buff) == -1) {
1175 d->m_showingDialog = true;
1176 KMessageBoxWrapper::error(d->m_window,
1177 i18n("<qt>Unable to run the command specified. "
1178 "The file or folder <b>%1</b> does not exist.</qt>" ,
1179 Qt::escape(d->m_strURL.prettyUrl())));
1180 d->m_showingDialog = false;
1181 d->m_bFault = true;
1182 d->m_bFinished = true;
1183 d->startTimer();
1184 return;
1185 }
1186 d->m_mode = buff.st_mode;
1187 }
1188
1189 KMimeType::Ptr mime = KMimeType::findByUrl(d->m_strURL, d->m_mode, true /*local*/);
1190 assert(mime);
1191 kDebug(7010) << "MIME TYPE is " << mime->name();
1192 if (!d->m_externalBrowser.isEmpty() &&
1193 (mime->is(QLatin1String("text/html")) ||
1194 mime->is(QLatin1String("application/xhtml+xml")))) {
1195 if (d->runExecutable(d->m_externalBrowser)) {
1196 return;
1197 }
1198 } else if (mime->isDefault() && !QFileInfo(d->m_strURL.toLocalFile()).isReadable()) {
1199 // Unknown mimetype because the file is unreadable, no point in showing an open-with dialog (#261002)
1200 const QString msg = KIO::buildErrorString(KIO::ERR_ACCESS_DENIED, d->m_strURL.prettyUrl());
1201 d->m_showingDialog = true;
1202 KMessageBoxWrapper::error(d->m_window, msg);
1203 d->m_showingDialog = false;
1204 d->m_bFault = true;
1205 d->m_bFinished = true;
1206 d->startTimer();
1207 return;
1208 } else {
1209 mimeTypeDetermined(mime->name());
1210 return;
1211 }
1212 }
1213 else if (KProtocolInfo::isHelperProtocol(d->m_strURL)) {
1214 kDebug(7010) << "Helper protocol";
1215 const QString exec = KProtocolInfo::exec(d->m_strURL.protocol());
1216 if (exec.isEmpty()) {
1217 mimeTypeDetermined(KProtocolManager::defaultMimetype(d->m_strURL));
1218 return;
1219 } else {
1220 if (run(exec, KUrl::List() << d->m_strURL, d->m_window, QString(), QString(), d->m_asn)) {
1221 d->m_bFinished = true;
1222 d->startTimer();
1223 return;
1224 }
1225 }
1226 }
1227
1228 // Did we already get the information that it is a directory ?
1229 if (S_ISDIR(d->m_mode)) {
1230 mimeTypeDetermined("inode/directory");
1231 return;
1232 }
1233
1234 // Let's see whether it is a directory
1235
1236 if (!KProtocolManager::supportsListing(d->m_strURL)) {
1237 //kDebug(7010) << "Protocol has no support for listing";
1238 // No support for listing => it can't be a directory (example: http)
1239 scanFile();
1240 return;
1241 }
1242
1243 kDebug(7010) << "Testing directory (stating)";
1244
1245 // It may be a directory or a file, let's stat
1246 KIO::JobFlags flags = d->m_bProgressInfo ? KIO::DefaultFlags : KIO::HideProgressInfo;
1247 KIO::StatJob *job = KIO::stat(d->m_strURL, KIO::StatJob::SourceSide, 0 /* no details */, flags);
1248 job->ui()->setWindow(d->m_window);
1249 connect(job, SIGNAL(result(KJob*)),
1250 this, SLOT(slotStatResult(KJob*)));
1251 d->m_job = job;
1252 kDebug(7010) << " Job " << job << " is about stating " << d->m_strURL.url();
1253}
1254
1255KRun::~KRun()
1256{
1257 //kDebug(7010) << this;
1258 d->m_timer.stop();
1259 killJob();
1260 KGlobal::deref();
1261 //kDebug(7010) << this << "done";
1262 delete d;
1263}
1264
1265bool KRun::KRunPrivate::runExecutable(const QString& _exec)
1266{
1267 KUrl::List urls;
1268 urls.append(m_strURL);
1269 if (_exec.startsWith('!')) {
1270 QString exec = _exec.mid(1); // Literal command
1271 exec += " %u";
1272 if (q->run(exec, urls, m_window, QString(), QString(), m_asn)) {
1273 m_bFinished = true;
1274 startTimer();
1275 return true;
1276 }
1277 }
1278 else {
1279 KService::Ptr service = KService::serviceByStorageId(_exec);
1280 if (service && q->run(*service, urls, m_window, false, QString(), m_asn)) {
1281 m_bFinished = true;
1282 startTimer();
1283 return true;
1284 }
1285 }
1286 return false;
1287}
1288
1289void KRun::scanFile()
1290{
1291 kDebug(7010) << d->m_strURL;
1292 // First, let's check for well-known extensions
1293 // Not when there is a query in the URL, in any case.
1294 if (d->m_strURL.query().isEmpty()) {
1295 KMimeType::Ptr mime = KMimeType::findByUrl(d->m_strURL);
1296 assert(mime);
1297 if (!mime->isDefault() || d->m_bIsLocalFile) {
1298 kDebug(7010) << "Scanfile: MIME TYPE is " << mime->name();
1299 mimeTypeDetermined(mime->name());
1300 return;
1301 }
1302 }
1303
1304 // No mimetype found, and the URL is not local (or fast mode not allowed).
1305 // We need to apply the 'KIO' method, i.e. either asking the server or
1306 // getting some data out of the file, to know what mimetype it is.
1307
1308 if (!KProtocolManager::supportsReading(d->m_strURL)) {
1309 kError(7010) << "#### NO SUPPORT FOR READING!";
1310 d->m_bFault = true;
1311 d->m_bFinished = true;
1312 d->startTimer();
1313 return;
1314 }
1315 kDebug(7010) << this << " Scanning file " << d->m_strURL.url();
1316
1317 KIO::JobFlags flags = d->m_bProgressInfo ? KIO::DefaultFlags : KIO::HideProgressInfo;
1318 KIO::TransferJob *job = KIO::get(d->m_strURL, KIO::NoReload /*reload*/, flags);
1319 job->ui()->setWindow(d->m_window);
1320 connect(job, SIGNAL(result(KJob*)),
1321 this, SLOT(slotScanFinished(KJob*)));
1322 connect(job, SIGNAL(mimetype(KIO::Job*,QString)),
1323 this, SLOT(slotScanMimeType(KIO::Job*,QString)));
1324 d->m_job = job;
1325 kDebug(7010) << " Job " << job << " is about getting from " << d->m_strURL.url();
1326}
1327
1328// When arriving in that method there are 5 possible states:
1329// must_init, must_scan_file, found_dir, done+error or done+success.
1330void KRun::slotTimeout()
1331{
1332 kDebug(7010) << this << " slotTimeout called";
1333 if (d->m_bInit) {
1334 d->m_bInit = false;
1335 init();
1336 return;
1337 }
1338
1339 if (d->m_bFault) {
1340 emit error();
1341 }
1342 if (d->m_bFinished) {
1343 emit finished();
1344 }
1345 else {
1346 if (d->m_bScanFile) {
1347 d->m_bScanFile = false;
1348 scanFile();
1349 return;
1350 }
1351 else if (d->m_bIsDirectory) {
1352 d->m_bIsDirectory = false;
1353 mimeTypeDetermined("inode/directory");
1354 return;
1355 }
1356 }
1357
1358 if (d->m_bAutoDelete) {
1359 deleteLater();
1360 return;
1361 }
1362}
1363
1364void KRun::slotStatResult(KJob * job)
1365{
1366 d->m_job = 0L;
1367 const int errCode = job->error();
1368 if (errCode) {
1369 // ERR_NO_CONTENT is not an error, but an indication no further
1370 // actions needs to be taken.
1371 if (errCode != KIO::ERR_NO_CONTENT) {
1372 d->m_showingDialog = true;
1373 kError(7010) << this << "ERROR" << job->error() << job->errorString();
1374 job->uiDelegate()->showErrorMessage();
1375 //kDebug(7010) << this << " KRun returning from showErrorDialog, starting timer to delete us";
1376 d->m_showingDialog = false;
1377 d->m_bFault = true;
1378 }
1379
1380 d->m_bFinished = true;
1381
1382 // will emit the error and autodelete this
1383 d->startTimer();
1384 }
1385 else {
1386 kDebug(7010) << "Finished";
1387
1388 KIO::StatJob* statJob = qobject_cast<KIO::StatJob*>(job);
1389 if (!statJob) {
1390 kFatal() << "job is a " << typeid(*job).name() << " should be a StatJob";
1391 }
1392
1393 // Update our URL in case of a redirection
1394 setUrl(statJob->url());
1395
1396 const KIO::UDSEntry entry = statJob->statResult();
1397 const mode_t mode = entry.numberValue(KIO::UDSEntry::UDS_FILE_TYPE);
1398 if (S_ISDIR(mode)) {
1399 d->m_bIsDirectory = true; // it's a dir
1400 }
1401 else {
1402 d->m_bScanFile = true; // it's a file
1403 }
1404
1405 d->m_localPath = entry.stringValue(KIO::UDSEntry::UDS_LOCAL_PATH);
1406
1407 // mimetype already known? (e.g. print:/manager)
1408 const QString knownMimeType = entry.stringValue(KIO::UDSEntry::UDS_MIME_TYPE) ;
1409
1410 if (!knownMimeType.isEmpty()) {
1411 mimeTypeDetermined(knownMimeType);
1412 d->m_bFinished = true;
1413 }
1414
1415 // We should have found something
1416 assert(d->m_bScanFile || d->m_bIsDirectory);
1417
1418 // Start the timer. Once we get the timer event this
1419 // protocol server is back in the pool and we can reuse it.
1420 // This gives better performance than starting a new slave
1421 d->startTimer();
1422 }
1423}
1424
1425void KRun::slotScanMimeType(KIO::Job *, const QString &mimetype)
1426{
1427 if (mimetype.isEmpty()) {
1428 kWarning(7010) << "get() didn't emit a mimetype! Probably a kioslave bug, please check the implementation of" << url().protocol();
1429 }
1430 mimeTypeDetermined(mimetype);
1431 d->m_job = 0;
1432}
1433
1434void KRun::slotScanFinished(KJob *job)
1435{
1436 d->m_job = 0;
1437 const int errCode = job->error();
1438 if (errCode) {
1439 // ERR_NO_CONTENT is not an error, but an indication no further
1440 // actions needs to be taken.
1441 if (errCode != KIO::ERR_NO_CONTENT) {
1442 d->m_showingDialog = true;
1443 kError(7010) << this << "ERROR (stat):" << job->error() << ' ' << job->errorString();
1444 job->uiDelegate()->showErrorMessage();
1445 //kDebug(7010) << this << " KRun returning from showErrorDialog, starting timer to delete us";
1446 d->m_showingDialog = false;
1447
1448 d->m_bFault = true;
1449 }
1450
1451 d->m_bFinished = true;
1452 // will emit the error and autodelete this
1453 d->startTimer();
1454 }
1455}
1456
1457void KRun::mimeTypeDetermined(const QString& mimeType)
1458{
1459 // foundMimeType reimplementations might show a dialog box;
1460 // make sure some timer doesn't kill us meanwhile (#137678, #156447)
1461 Q_ASSERT(!d->m_showingDialog);
1462 d->m_showingDialog = true;
1463
1464 foundMimeType(mimeType);
1465
1466 d->m_showingDialog = false;
1467
1468 // We cannot assume that we're finished here. Some reimplementations
1469 // start a KIO job and call setFinished only later.
1470}
1471
1472void KRun::foundMimeType(const QString& type)
1473{
1474 kDebug(7010) << "Resulting mime type is " << type;
1475
1476 KIO::TransferJob *job = qobject_cast<KIO::TransferJob *>(d->m_job);
1477 if (job) {
1478 // Update our URL in case of a redirection
1479 setUrl( job->url() );
1480
1481 job->putOnHold();
1482 KIO::Scheduler::publishSlaveOnHold();
1483 d->m_job = 0;
1484 }
1485
1486 Q_ASSERT(!d->m_bFinished);
1487
1488 // Support for preferred service setting, see setPreferredService
1489 if (!d->m_preferredService.isEmpty()) {
1490 kDebug(7010) << "Attempting to open with preferred service: " << d->m_preferredService;
1491 KService::Ptr serv = KService::serviceByDesktopName(d->m_preferredService);
1492 if (serv && serv->hasMimeType(type)) {
1493 KUrl::List lst;
1494 lst.append(d->m_strURL);
1495 if (KRun::run(*serv, lst, d->m_window, false, QString(), d->m_asn)) {
1496 setFinished(true);
1497 return;
1498 }
1503 }
1504 }
1505
1506 // Resolve .desktop files from media:/, remote:/, applications:/ etc.
1507 KMimeType::Ptr mime = KMimeType::mimeType(type, KMimeType::ResolveAliases);
1508 if (!mime) {
1509 kWarning(7010) << "Unknown mimetype " << type;
1510 }
1511 if (mime && mime->is("application/x-desktop") && !d->m_localPath.isEmpty()) {
1512 d->m_strURL = KUrl();
1513 d->m_strURL.setPath(d->m_localPath);
1514 }
1515
1516 if (!KRun::runUrl(d->m_strURL, type, d->m_window, false /*tempfile*/, d->m_runExecutables, d->m_suggestedFileName, d->m_asn)) {
1517 d->m_bFault = true;
1518 }
1519 setFinished(true);
1520}
1521
1522void KRun::killJob()
1523{
1524 if (d->m_job) {
1525 kDebug(7010) << this << "m_job=" << d->m_job;
1526 d->m_job->kill();
1527 d->m_job = 0L;
1528 }
1529}
1530
1531void KRun::abort()
1532{
1533 if (d->m_bFinished) {
1534 return;
1535 }
1536 kDebug(7010) << this << "m_showingDialog=" << d->m_showingDialog;
1537 killJob();
1538 // If we're showing an error message box, the rest will be done
1539 // after closing the msgbox -> don't autodelete nor emit signals now.
1540 if (d->m_showingDialog) {
1541 return;
1542 }
1543 d->m_bFault = true;
1544 d->m_bFinished = true;
1545 d->m_bInit = false;
1546 d->m_bScanFile = false;
1547
1548 // will emit the error and autodelete this
1549 d->startTimer();
1550}
1551
1552QWidget* KRun::window() const
1553{
1554 return d->m_window;
1555}
1556
1557bool KRun::hasError() const
1558{
1559 return d->m_bFault;
1560}
1561
1562bool KRun::hasFinished() const
1563{
1564 return d->m_bFinished;
1565}
1566
1567bool KRun::autoDelete() const
1568{
1569 return d->m_bAutoDelete;
1570}
1571
1572void KRun::setAutoDelete(bool b)
1573{
1574 d->m_bAutoDelete = b;
1575}
1576
1577void KRun::setEnableExternalBrowser(bool b)
1578{
1579 if (b) {
1580 d->m_externalBrowser = KConfigGroup(KGlobal::config(), "General").readEntry("BrowserApplication");
1581 }
1582 else {
1583 d->m_externalBrowser.clear();
1584 }
1585}
1586
1587void KRun::setPreferredService(const QString& desktopEntryName)
1588{
1589 d->m_preferredService = desktopEntryName;
1590}
1591
1592void KRun::setRunExecutables(bool b)
1593{
1594 d->m_runExecutables = b;
1595}
1596
1597void KRun::setSuggestedFileName(const QString& fileName)
1598{
1599 d->m_suggestedFileName = fileName;
1600}
1601
1602QString KRun::suggestedFileName() const
1603{
1604 return d->m_suggestedFileName;
1605}
1606
1607bool KRun::isExecutable(const QString& serviceType)
1608{
1609 return (serviceType == "application/x-desktop" ||
1610 serviceType == "application/x-executable" ||
1611 serviceType == "application/x-ms-dos-executable" ||
1612 serviceType == "application/x-shellscript");
1613}
1614
1615void KRun::setUrl(const KUrl &url)
1616{
1617 d->m_strURL = url;
1618}
1619
1620KUrl KRun::url() const
1621{
1622 return d->m_strURL;
1623}
1624
1625void KRun::setError(bool error)
1626{
1627 d->m_bFault = error;
1628}
1629
1630void KRun::setProgressInfo(bool progressInfo)
1631{
1632 d->m_bProgressInfo = progressInfo;
1633}
1634
1635bool KRun::progressInfo() const
1636{
1637 return d->m_bProgressInfo;
1638}
1639
1640void KRun::setFinished(bool finished)
1641{
1642 d->m_bFinished = finished;
1643 if (finished)
1644 d->startTimer();
1645}
1646
1647void KRun::setJob(KIO::Job *job)
1648{
1649 d->m_job = job;
1650}
1651
1652KIO::Job* KRun::job()
1653{
1654 return d->m_job;
1655}
1656
1657#ifndef KDE_NO_DEPRECATED
1658QTimer& KRun::timer()
1659{
1660 return d->m_timer;
1661}
1662#endif
1663
1664#ifndef KDE_NO_DEPRECATED
1665void KRun::setDoScanFile(bool scanFile)
1666{
1667 d->m_bScanFile = scanFile;
1668}
1669#endif
1670
1671#ifndef KDE_NO_DEPRECATED
1672bool KRun::doScanFile() const
1673{
1674 return d->m_bScanFile;
1675}
1676#endif
1677
1678#ifndef KDE_NO_DEPRECATED
1679void KRun::setIsDirecory(bool isDirectory)
1680{
1681 d->m_bIsDirectory = isDirectory;
1682}
1683#endif
1684
1685bool KRun::isDirectory() const
1686{
1687 return d->m_bIsDirectory;
1688}
1689
1690#ifndef KDE_NO_DEPRECATED
1691void KRun::setInitializeNextAction(bool initialize)
1692{
1693 d->m_bInit = initialize;
1694}
1695#endif
1696
1697#ifndef KDE_NO_DEPRECATED
1698bool KRun::initializeNextAction() const
1699{
1700 return d->m_bInit;
1701}
1702#endif
1703
1704void KRun::setIsLocalFile(bool isLocalFile)
1705{
1706 d->m_bIsLocalFile = isLocalFile;
1707}
1708
1709bool KRun::isLocalFile() const
1710{
1711 return d->m_bIsLocalFile;
1712}
1713
1714void KRun::setMode(mode_t mode)
1715{
1716 d->m_mode = mode;
1717}
1718
1719mode_t KRun::mode() const
1720{
1721 return d->m_mode;
1722}
1723
1724/****************/
1725
1726#ifndef Q_WS_X11
1727int KProcessRunner::run(KProcess * p, const QString & executable)
1728{
1729 return (new KProcessRunner(p, executable))->pid();
1730}
1731#else
1732int KProcessRunner::run(KProcess * p, const QString & executable, const KStartupInfoId& id)
1733{
1734 return (new KProcessRunner(p, executable, id))->pid();
1735}
1736#endif
1737
1738#ifndef Q_WS_X11
1739KProcessRunner::KProcessRunner(KProcess * p, const QString & executable)
1740#else
1741KProcessRunner::KProcessRunner(KProcess * p, const QString & executable, const KStartupInfoId& _id) :
1742 id(_id)
1743#endif
1744{
1745 m_pid = 0;
1746 process = p;
1747 m_executable = executable;
1748 connect(process, SIGNAL(finished(int,QProcess::ExitStatus)),
1749 this, SLOT(slotProcessExited(int,QProcess::ExitStatus)));
1750
1751 process->start();
1752 if (!process->waitForStarted()) {
1753 //kDebug() << "wait for started failed, exitCode=" << process->exitCode()
1754 // << "exitStatus=" << process->exitStatus();
1755 // Note that exitCode is 255 here (the first time), and 0 later on (bug?).
1756 slotProcessExited(255, process->exitStatus());
1757 }
1758 else {
1759#ifdef Q_WS_X11
1760 m_pid = process->pid();
1761#endif
1762 }
1763}
1764
1765KProcessRunner::~KProcessRunner()
1766{
1767 delete process;
1768}
1769
1770int KProcessRunner::pid() const
1771{
1772 return m_pid;
1773}
1774
1775void KProcessRunner::terminateStartupNotification()
1776{
1777#ifdef Q_WS_X11
1778 if (!id.none()) {
1779 KStartupInfoData data;
1780 data.addPid(m_pid); // announce this pid for the startup notification has finished
1781 data.setHostname();
1782 KStartupInfo::sendFinish(id, data);
1783 }
1784#endif
1785
1786}
1787
1788void
1789KProcessRunner::slotProcessExited(int exitCode, QProcess::ExitStatus exitStatus)
1790{
1791 kDebug(7010) << m_executable << "exitCode=" << exitCode << "exitStatus=" << exitStatus;
1792 Q_UNUSED(exitStatus);
1793
1794 terminateStartupNotification(); // do this before the messagebox
1795 if (exitCode != 0 && !m_executable.isEmpty()) {
1796 // Let's see if the error is because the exe doesn't exist.
1797 // When this happens, waitForStarted returns false, but not if kioexec
1798 // was involved, then we come here, that's why the code is here.
1799 //
1800 // We'll try to find the executable relatively to current directory,
1801 // (or with a full path, if m_executable is absolute), and then in the PATH.
1802 if (!QFile(m_executable).exists() && KStandardDirs::findExe(m_executable).isEmpty()) {
1803 KGlobal::ref();
1804 KMessageBox::sorry(0L, i18n("Could not find the program '%1'", m_executable));
1805 KGlobal::deref();
1806 }
1807 else {
1808 kDebug() << process->readAllStandardError();
1809 }
1810 }
1811 deleteLater();
1812}
1813
1814#include "krun.moc"
1815#include "krun_p.moc"
KConfigGroup
KConfigGroup::readPathEntry
QString readPathEntry(const char *key, const QString &aDefault) const
KConfigGroup::readEntry
QString readEntry(const char *key, const char *aDefault=0) const
KDesktopFile
KDesktopFile::desktopGroup
KConfigGroup desktopGroup() const
KDesktopFile::isAuthorizedDesktopFile
static bool isAuthorizedDesktopFile(const QString &path)
KDialog
KDialog::Ok
Ok
KDialog::Cancel
Cancel
KGuiItem
KIO::JobUiDelegate::setWindow
virtual void setWindow(QWidget *window)
Associate this job with a window given by window.
Definition: jobuidelegate.cpp:58
KIO::Job
The base class for all jobs.
Definition: jobclasses.h:94
KIO::Job::ui
JobUiDelegate * ui() const
Retrieves the UI delegate of this job.
Definition: job.cpp:90
KIO::NetAccess::mostLocalUrl
static KUrl mostLocalUrl(const KUrl &url, QWidget *window)
Tries to map a local URL for the given URL.
Definition: netaccess.cpp:234
KIO::Scheduler::publishSlaveOnHold
static void publishSlaveOnHold()
Send the slave that was put on hold back to KLauncher.
Definition: scheduler.cpp:830
KIO::SimpleJob::putOnHold
virtual void putOnHold()
Abort job.
Definition: job.cpp:346
KIO::SimpleJob::url
const KUrl & url() const
Returns the SimpleJob's URL.
Definition: job.cpp:341
KIO::StatJob
A KIO job that retrieves information about a file or directory.
Definition: jobclasses.h:440
KIO::StatJob::SourceSide
@ SourceSide
Definition: jobclasses.h:446
KIO::StatJob::statResult
const UDSEntry & statResult() const
Result of the stat operation.
Definition: job.cpp:839
KIO::TransferJob
The transfer job pumps data into and/or out of a Slave.
Definition: jobclasses.h:555
KIO::UDSEntry
Universal Directory Service.
Definition: udsentry.h:59
KIO::UDSEntry::stringValue
QString stringValue(uint field) const
Definition: udsentry.cpp:73
KIO::UDSEntry::numberValue
long long numberValue(uint field, long long defaultValue=0) const
Definition: udsentry.cpp:78
KIO::UDSEntry::UDS_MIME_TYPE
@ UDS_MIME_TYPE
A mime type; the slave should set it if it's known.
Definition: udsentry.h:192
KIO::UDSEntry::UDS_LOCAL_PATH
@ UDS_LOCAL_PATH
A local file path if the ioslave display files sitting on the local filesystem (but in another hierar...
Definition: udsentry.h:166
KIO::UDSEntry::UDS_FILE_TYPE
@ UDS_FILE_TYPE
File type, part of the mode returned by stat (for a link, this returns the file type of the pointed i...
Definition: udsentry.h:181
KIconLoader::NoGroup
NoGroup
KIconLoader::global
static KIconLoader * global()
KIconLoader::SizeHuge
SizeHuge
KJobUiDelegate::showErrorMessage
virtual void showErrorMessage()
KJob
KJob::errorString
virtual QString errorString() const
KJob::error
int error() const
KJob::kill
bool kill(KillVerbosity verbosity=Quietly)
KJob::uiDelegate
KJobUiDelegate * uiDelegate() const
KMacroExpanderBase
KMessageBoxWrapper::error
static void error(QWidget *parent, const QString &text, const QString &caption=QString())
Definition: kmessageboxwrapper.h:33
KMessageBox::sorry
static void sorry(QWidget *parent, const QString &text, const QString &caption=QString(), Options options=Notify)
KMimeTypeTrader::preferredService
KService::Ptr preferredService(const QString &mimeType, const QString &genericServiceType=QString::fromLatin1("Application"))
KMimeTypeTrader::self
static KMimeTypeTrader * self()
KMimeType::ResolveAliases
ResolveAliases
KMimeType::mimeType
static Ptr mimeType(const QString &name, FindByNameOption options=ResolveAliases)
KMimeType::findByUrl
static Ptr findByUrl(const KUrl &url, mode_t mode=0, bool is_local_file=false, bool fast_mode=false, int *accuracy=0)
KOpenWithDialog
"Open With" dialog box.
Definition: kopenwithdialog.h:40
KOpenWithDialog::service
KService::Ptr service() const
Definition: kopenwithdialog.cpp:983
KOpenWithDialog::text
QString text() const
Definition: kopenwithdialog.cpp:962
KProcessRunner
Definition: krun_p.h:38
KProcessRunner::~KProcessRunner
virtual ~KProcessRunner()
Definition: krun.cpp:1765
KProcessRunner::pid
int pid() const
Definition: krun.cpp:1770
KProcessRunner::slotProcessExited
void slotProcessExited(int, QProcess::ExitStatus)
Definition: krun.cpp:1789
KProcessRunner::run
static int run(KProcess *, const QString &executable, const KStartupInfoId &id)
Definition: krun.cpp:1732
KProcess
KProcess::pid
int pid() const
KProcess::start
void start()
KProcess::setShellCommand
void setShellCommand(const QString &cmd)
KProtocolManager::supportsReading
static bool supportsReading(const KUrl &url)
Returns whether the protocol can retrieve data from URLs.
Definition: kprotocolmanager.cpp:1051
KProtocolManager::supportsListing
static bool supportsListing(const KUrl &url)
Returns whether the protocol can list files/objects.
Definition: kprotocolmanager.cpp:1033
KProtocolManager::defaultMimetype
static QString defaultMimetype(const KUrl &url)
Returns default mimetype for this URL based on the protocol.
Definition: kprotocolmanager.cpp:1170
KRecentDocument::add
static void add(const KUrl &url)
Add a new item to the Recent Document menu.
Definition: krecentdocument.cpp:88
KRun::KRunPrivate
Definition: krun_p.h:78
KRun::KRunPrivate::m_runExecutables
bool m_runExecutables
Definition: krun_p.h:99
KRun::KRunPrivate::runExecutable
bool runExecutable(const QString &_exec)
Definition: krun.cpp:1265
KRun::KRunPrivate::m_bScanFile
bool m_bScanFile
Used to indicate that the next action is to scan the file.
Definition: krun_p.h:119
KRun::KRunPrivate::displayNativeOpenWithDialog
static bool displayNativeOpenWithDialog(const KUrl::List &lst, QWidget *window, bool tempFiles, const QString &suggestedFileName, const QByteArray &asn)
Definition: krun_win.cpp:82
KRun::KRunPrivate::m_strURL
KUrl m_strURL
Definition: krun_p.h:107
KRun::KRunPrivate::m_mode
mode_t m_mode
Definition: krun_p.h:129
KRun::KRunPrivate::m_suggestedFileName
QString m_suggestedFileName
Definition: krun_p.h:104
KRun::KRunPrivate::m_bProgressInfo
bool m_bProgressInfo
Definition: krun_p.h:110
KRun::KRunPrivate::m_timer
QTimer m_timer
Definition: krun_p.h:113
KRun::KRunPrivate::init
void init(const KUrl &url, QWidget *window, mode_t mode, bool isLocalFile, bool showProgressInfo, const QByteArray &asn)
Definition: krun.cpp:1110
KRun::KRunPrivate::m_bInit
bool m_bInit
Used to indicate that the next action is to initialize.
Definition: krun_p.h:126
KRun::KRunPrivate::m_bIsLocalFile
bool m_bIsLocalFile
Definition: krun_p.h:128
KRun::KRunPrivate::m_bIsDirectory
bool m_bIsDirectory
Definition: krun_p.h:120
KRun::KRunPrivate::m_bAutoDelete
bool m_bAutoDelete
Definition: krun_p.h:109
KRun::KRunPrivate::m_asn
QByteArray m_asn
Definition: krun_p.h:106
KRun::KRunPrivate::q
KRun * q
Definition: krun_p.h:97
KRun::KRunPrivate::m_externalBrowser
QString m_externalBrowser
Definition: krun_p.h:102
KRun::KRunPrivate::KRunPrivate
KRunPrivate(KRun *parent)
Definition: krun.cpp:87
KRun::KRunPrivate::m_preferredService
QString m_preferredService
Definition: krun_p.h:101
KRun::KRunPrivate::m_window
QPointer< QWidget > m_window
Definition: krun_p.h:105
KRun::KRunPrivate::m_job
KIO::Job * m_job
Definition: krun_p.h:112
KRun::KRunPrivate::m_showingDialog
bool m_showingDialog
Definition: krun_p.h:98
KRun::KRunPrivate::m_bFinished
bool m_bFinished
Definition: krun_p.h:111
KRun::KRunPrivate::m_bFault
bool m_bFault
Definition: krun_p.h:108
KRun::KRunPrivate::m_localPath
QString m_localPath
Definition: krun_p.h:103
KRun::KRunPrivate::startTimer
void startTimer()
Definition: krun.cpp:93
KRun
To open files with their associated applications in KDE, use KRun.
Definition: krun.h:60
KRun::isDirectory
bool isDirectory() const
Returns whether it is a directory.
Definition: krun.cpp:1685
KRun::finished
void finished()
Emitted when the operation finished.
KRun::checkStartupNotify
static bool checkStartupNotify(const QString &binName, const KService *service, bool *silent_arg, QByteArray *wmclass_arg)
Definition: krun.cpp:651
KRun::slotStatResult
virtual void slotStatResult(KJob *)
This slot is called when the 'stat' job has finished.
Definition: krun.cpp:1364
KRun::setJob
void setJob(KIO::Job *job)
Sets the job.
Definition: krun.cpp:1647
KRun::init
virtual void init()
All following protected methods are used by subclasses of KRun!
Definition: krun.cpp:1139
KRun::autoDelete
bool autoDelete() const
Checks whether auto delete is activated.
Definition: krun.cpp:1567
KRun::timer
QTimer & timer()
Returns the timer object.
Definition: krun.cpp:1658
KRun::progressInfo
bool progressInfo() const
Returns whether progress information are shown.
Definition: krun.cpp:1635
KRun::hasError
bool hasError() const
Returns true if the KRun instance has an error.
Definition: krun.cpp:1557
KRun::suggestedFileName
QString suggestedFileName() const
Suggested file name given by the server (e.g.
Definition: krun.cpp:1602
KRun::slotTimeout
void slotTimeout()
All following protected slots are used by subclasses of KRun!
Definition: krun.cpp:1330
KRun::setIsDirecory
void setIsDirecory(bool isDirectory)
Sets whether it is a directory.
Definition: krun.cpp:1679
KRun::slotScanFinished
void slotScanFinished(KJob *)
This slot is called when the scan job is finished.
Definition: krun.cpp:1434
KRun::processDesktopExec
static QStringList processDesktopExec(const KService &_service, const KUrl::List &_urls, bool tempFiles=false, const QString &suggestedFileName=QString())
Processes a Exec= line as found in .desktop files.
Definition: krun.cpp:407
KRun::isExecutableFile
static bool isExecutableFile(const KUrl &url, const QString &mimetype)
Returns whether the url of mimetype is executable.
Definition: krun.cpp:100
KRun::initializeNextAction
bool initializeNextAction() const
Definition: krun.cpp:1698
KRun::setInitializeNextAction
void setInitializeNextAction(bool initialize)
Definition: krun.cpp:1691
KRun::runCommand
static bool runCommand(const QString &cmd, QWidget *window)
Run the given shell command and notifies KDE of the starting of the application.
Definition: krun.cpp:1057
KRun::url
KUrl url() const
Returns the url.
Definition: krun.cpp:1620
KRun::slotScanMimeType
void slotScanMimeType(KIO::Job *, const QString &type)
This slot is called when the scan job has found out the mime type.
Definition: krun.cpp:1425
KRun::scanFile
virtual void scanFile()
Start scanning a file.
Definition: krun.cpp:1289
KRun::setRunExecutables
void setRunExecutables(bool b)
Sets whether executables, .desktop files or shell scripts should be run by KRun.
Definition: krun.cpp:1592
KRun::displayOpenWithDialog
static bool displayOpenWithDialog(const KUrl::List &lst, QWidget *window, bool tempFiles=false, const QString &suggestedFileName=QString(), const QByteArray &asn=QByteArray())
Display the Open-With dialog for those URLs, and run the chosen application.
Definition: krun.cpp:193
KRun::setEnableExternalBrowser
void setEnableExternalBrowser(bool b)
Sets whether the external webbrowser setting should be honoured.
Definition: krun.cpp:1577
KRun::setMode
void setMode(mode_t mode)
Sets the file mode.
Definition: krun.cpp:1714
KRun::setSuggestedFileName
void setSuggestedFileName(const QString &fileName)
Sets the file name to use in the case of downloading the file to a tempfile in order to give to a non...
Definition: krun.cpp:1597
KRun::KRun
KRun(const KUrl &url, QWidget *window, mode_t mode=0, bool isLocalFile=false, bool showProgressInfo=true, const QByteArray &asn=QByteArray())
Definition: krun.cpp:1101
KRun::mode
mode_t mode() const
Returns the file mode.
Definition: krun.cpp:1719
KRun::shellQuote
static void shellQuote(QString &str)
Quotes a string for the shell.
Definition: krun.cpp:223
KRun::setPreferredService
void setPreferredService(const QString &desktopEntryName)
Set the preferred service for opening this URL, after its mimetype will have been found by KRun.
Definition: krun.cpp:1587
KRun::error
void error()
Emitted when the operation had an error.
KRun::isLocalFile
bool isLocalFile() const
Returns whether it is a local file.
Definition: krun.cpp:1709
KRun::job
KIO::Job * job()
Returns the job.
Definition: krun.cpp:1652
KRun::hasFinished
bool hasFinished() const
Returns true if the KRun instance has finished.
Definition: krun.cpp:1562
KRun::foundMimeType
virtual void foundMimeType(const QString &type)
Called if the mimetype has been detected.
Definition: krun.cpp:1472
KRun::doScanFile
bool doScanFile() const
Returns whether the file shall be scanned.
Definition: krun.cpp:1672
KRun::abort
void abort()
Abort this KRun.
Definition: krun.cpp:1531
KRun::runUrl
static bool runUrl(const KUrl &url, const QString &mimetype, QWidget *window, bool tempFile=false, bool runExecutables=true, const QString &suggestedFileName=QString(), const QByteArray &asn=QByteArray())
Open the given URL.
Definition: krun.cpp:122
KRun::setAutoDelete
void setAutoDelete(bool b)
Enables or disabled auto deletion.
Definition: krun.cpp:1572
KRun::setDoScanFile
void setDoScanFile(bool scanFile)
Indicate that the next action is to scan the file.
Definition: krun.cpp:1665
KRun::killJob
virtual void killJob()
Kills the file scanning job.
Definition: krun.cpp:1522
KRun::window
QWidget * window() const
Associated window, as passed to the constructor.
Definition: krun.cpp:1552
KRun::isExecutable
static bool isExecutable(const QString &serviceType)
Returns whether serviceType refers to an executable program instead of a data file.
Definition: krun.cpp:1607
KRun::setUrl
void setUrl(const KUrl &url)
Sets the url.
Definition: krun.cpp:1615
KRun::~KRun
virtual ~KRun()
Destructor.
Definition: krun.cpp:1255
KRun::setIsLocalFile
void setIsLocalFile(bool isLocalFile)
Sets whether it is a local file.
Definition: krun.cpp:1704
KRun::setError
void setError(bool error)
Sets whether an error has occurred.
Definition: krun.cpp:1625
KRun::binaryName
static QString binaryName(const QString &execLine, bool removePath)
Given a full command line (e.g.
Definition: krun.cpp:568
KRun::setProgressInfo
void setProgressInfo(bool progressInfo)
Sets whether progress information shall be shown.
Definition: krun.cpp:1630
KRun::run
static bool run(const KService &service, const KUrl::List &urls, QWidget *window, bool tempFiles=false, const QString &suggestedFileName=QString(), const QByteArray &asn=QByteArray())
Open a list of URLs with a certain service (application).
Definition: krun.cpp:984
KRun::setFinished
void setFinished(bool finished)
Marks this 'KRun' instance as finished.
Definition: krun.cpp:1640
KRun::mimeTypeDetermined
void mimeTypeDetermined(const QString &mimeType)
Call this from subclasses when you have determined the mimetype.
Definition: krun.cpp:1457
KSaveFile
KSaveFile::finalize
bool finalize()
KSaveFile::open
virtual bool open(OpenMode flags=QIODevice::ReadWrite)
KSaveFile::errorString
QString errorString() const
KSaveFile::setFileName
void setFileName(const QString &filename)
KSaveFile::abort
void abort()
KService
KService::serviceByStorageId
static Ptr serviceByStorageId(const QString &_storageId)
KService::Ptr
KSharedPtr< KService > Ptr
KService::desktopEntryName
QString desktopEntryName() const
KService::allowMultipleFiles
bool allowMultipleFiles() const
KService::genericName
QString genericName() const
KService::substituteUid
bool substituteUid() const
KService::terminal
bool terminal() const
KService::terminalOptions
QString terminalOptions() const
KService::username
QString username() const
KService::serviceByDesktopName
static Ptr serviceByDesktopName(const QString &_name)
KService::property
QVariant property(const QString &_name, QVariant::Type t) const
KService::exec
QString exec() const
KService::icon
QString icon() const
KService::path
QString path() const
KService::isApplication
bool isApplication() const
KSharedPtr< KMimeType >
KSharedPtr::data
T * data()
KStandardDirs::findExe
static QString findExe(const QString &appname, const QString &pathstr=QString(), SearchOptions options=NoSearchOptions)
KStandardDirs::realFilePath
static QString realFilePath(const QString &filename)
KStartupInfoData
KStartupInfoData::Yes
Yes
KStartupInfoData::setHostname
void setHostname(const QByteArray &hostname=QByteArray())
KStartupInfoData::setDesktop
void setDesktop(int desktop)
KStartupInfoData::name
const QString & name() const
KStartupInfoData::addPid
void addPid(pid_t pid)
KStartupInfoData::setName
void setName(const QString &name)
KStartupInfoData::setLaunchedBy
void setLaunchedBy(WId window)
KStartupInfoData::setWMClass
void setWMClass(const QByteArray &wmclass)
KStartupInfoData::setIcon
void setIcon(const QString &icon)
KStartupInfoData::setBin
void setBin(const QString &bin)
KStartupInfoData::setDescription
void setDescription(const QString &descr)
KStartupInfoData::setSilent
void setSilent(TriState state)
KStartupInfoData::setApplicationId
void setApplicationId(const QString &desktop)
KStartupInfoId
KStartupInfoId::initId
void initId(const QByteArray &id="")
KStartupInfo::sendStartup
static bool sendStartup(const KStartupInfoId &id, const KStartupInfoData &data)
KStartupInfo::sendChange
static bool sendChange(const KStartupInfoId &id, const KStartupInfoData &data)
KStartupInfo::resetStartupEnv
static void resetStartupEnv()
KStartupInfo::sendFinish
static bool sendFinish(const KStartupInfoId &id)
KStartupInfo::createNewStartupId
static QByteArray createNewStartupId()
KSycocaEntry::name
QString name() const
KSycocaEntry::entryPath
QString entryPath() const
KToolInvocation::startServiceByDesktopPath
static int startServiceByDesktopPath(const QString &_name, const QString &URL, QString *error=0, QString *serviceName=0, int *pid=0, const QByteArray &startup_id=QByteArray(), bool noWait=false)
KUrl::List
KUrl::List::toStringList
QStringList toStringList() const
KUrl
KUrl::prettyUrl
QString prettyUrl(AdjustPathOption trailing=LeaveTrailingSlash) const
KUrl::url
QString url(AdjustPathOption trailing=LeaveTrailingSlash) const
KUrl::query
QString query() const
KUrl::directory
QString directory(const DirectoryOptions &options=IgnoreTrailingSlash) const
KUrl::isLocalFile
bool isLocalFile() const
KUrl::setPath
void setPath(const QString &path)
KUrl::fileName
QString fileName(const DirectoryOptions &options=IgnoreTrailingSlash) const
KUrl::protocol
QString protocol() const
KUrl::toLocalFile
QString toLocalFile(AdjustPathOption trailing=LeaveTrailingSlash) const
KWindowSystem::currentDesktop
static int currentDesktop()
QLabel
QWidget
header
const char header[]
global.h
kDebug
#define kDebug
kWarning
#define kWarning
job.h
jobclasses.h
jobuidelegate.h
kauthorized.h
kconfiggroup.h
kdebug.h
kdesktopfile.h
kdesktopfileactions.h
kdialog.h
kglobal.h
kguiitem.h
timeout
int timeout
klocale.h
i18n
QString i18n(const char *text)
i18nc
QString i18nc(const char *ctxt, const char *text)
kmacroexpander.h
kmessageboxwrapper.h
kmimetype.h
kmimetypetrader.h
kopenwithdialog.h
kprocess.h
kprotocolmanager.h
krecentdocument.h
supportedProtocols
static QStringList supportedProtocols(const KService &_service)
Definition: krun.cpp:370
runCommandInternal
static bool runCommandInternal(KProcess *proc, const KService *service, const QString &executable, const QString &userVisibleName, const QString &iconName, QWidget *window, const QByteArray &asn)
Definition: krun.cpp:580
runTempService
static bool runTempService(const KService &_service, const KUrl::List &_urls, QWidget *window, bool tempFiles, const QString &suggestedFileName, const QByteArray &asn)
Definition: krun.cpp:694
makeServiceExecutable
static bool makeServiceExecutable(const KService &service, QWidget *window)
Definition: krun.cpp:898
makeFileExecutable
static bool makeFileExecutable(const QString &fileName)
Definition: krun.cpp:825
isProtocolInSupportedList
static bool isProtocolInSupportedList(const KUrl &url, const QStringList &supportedProtocols)
Definition: krun.cpp:400
resolveURLs
static KUrl::List resolveURLs(const KUrl::List &_urls, const KService &_service)
Definition: krun.cpp:745
krun.h
krun_p.h
ksavefile.h
kshell.h
kstandarddirs.h
kstandardguiitem.h
ktoolinvocation.h
kurl.h
kwindowsystem.h
KAuthorized::authorizeUrlAction
bool authorizeUrlAction(const QString &action, const KUrl &baseUrl, const KUrl &destUrl)
KAuthorized::authorize
bool authorize(const QString &genericAction)
KAuthorized::authorizeKAction
bool authorizeKAction(const QString &action)
KDE::stat
int stat(const QString &path, KDE_struct_stat *buf)
KDesktopFileActions::run
bool run(const KUrl &_url, bool _is_local)
Invokes the default action for the desktop entry.
Definition: kdesktopfileactions.cpp:54
KGlobal::deref
void deref()
KGlobal::ref
void ref()
KGlobal::config
KSharedConfigPtr config()
KIO::buildErrorString
QString buildErrorString(int errorCode, const QString &errorText)
Returns a translated error message for errorCode using the additional error information provided by e...
Definition: global.cpp:164
KIO::stat
StatJob * stat(const KUrl &url, JobFlags flags=DefaultFlags)
Find all details for one file or directory.
Definition: job.cpp:924
KIO::get
TransferJob * get(const KUrl &url, LoadType reload=NoReload, JobFlags flags=DefaultFlags)
Get (a.k.a.
Definition: job.cpp:1369
KIO::NoReload
@ NoReload
Definition: job.h:29
KIO::DefaultFlags
@ DefaultFlags
Show the progress info GUI, no Resume and no Overwrite.
Definition: jobclasses.h:46
KIO::HideProgressInfo
@ HideProgressInfo
Hide progress information dialog, i.e.
Definition: jobclasses.h:51
KIO::ERR_NO_CONTENT
@ ERR_NO_CONTENT
Definition: global.h:255
KIO::ERR_ACCESS_DENIED
@ ERR_ACCESS_DENIED
Definition: global.h:209
subst
subst
message
void message(KMessage::MessageType messageType, const QString &text, const QString &caption=QString())
KShell::quoteArg
QString quoteArg(const QString &arg)
KShell::splitArgs
QStringList splitArgs(const QString &cmd, Options flags=NoOptions, Errors *err=0)
KShell::TildeExpand
TildeExpand
KShell::AbortOnMeta
AbortOnMeta
KShell::joinArgs
QString joinArgs(const QStringList &args)
KShell::Errors
Errors
KShell::FoundMeta
FoundMeta
KShell::NoError
NoError
KStandardGuiItem::cont
KGuiItem cont()
netaccess.h
scheduler.h
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KIO

Skip menu "KIO"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal