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

KIO

  • sources
  • kde-4.14
  • kdelibs
  • 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 
87 KRun::KRunPrivate::KRunPrivate(KRun *parent)
88  : q(parent),
89  m_showingDialog(false)
90 {
91 }
92 
93 void KRun::KRunPrivate::startTimer()
94 {
95  m_timer.start(0);
96 }
97 
98 // ---------------------------------------------------------------------------
99 
100 bool 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
122 bool 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 
193 bool 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
223 void 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 
235 class KRunMX1 : public KMacroExpanderBase
236 {
237 public:
238  KRunMX1(const KService &_service) :
239  KMacroExpanderBase('%'), hasUrls(false), hasSpec(false), service(_service) {}
240 
241  bool hasUrls: 1, hasSpec: 1;
242 
243 protected:
244  virtual int expandEscapedMacro(const QString &str, int pos, QStringList &ret);
245 
246 private:
247  const KService &service;
248 };
249 
250 int
251 KRunMX1::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 
288 class KRunMX2 : public KMacroExpanderBase
289 {
290 public:
291  KRunMX2(const KUrl::List &_urls) :
292  KMacroExpanderBase('%'), ignFile(false), urls(_urls) {}
293 
294  bool ignFile: 1;
295 
296 protected:
297  virtual int expandEscapedMacro(const QString &str, int pos, QStringList &ret);
298 
299 private:
300  void subst(int option, const KUrl &url, QStringList &ret);
301 
302  const KUrl::List &urls;
303 };
304 
305 void
306 KRunMX2::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 
331 int
332 KRunMX2::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 
370 static 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 
400 static 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 
407 QStringList 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
568 QString 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 
580 static 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.
651 bool 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 
694 static 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...
745 static 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.
771 class 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.
825 static 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.
898 static 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 
984 bool 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 
1049 bool 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 
1057 bool KRun::runCommand(const QString &cmd, QWidget* window)
1058 {
1059  return runCommand(cmd, window, QString());
1060 }
1061 
1062 bool 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 
1079 bool 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 
1084 bool 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 
1101 KRun::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 
1110 void 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 
1139 void 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 
1255 KRun::~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 
1265 bool 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 
1289 void 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.
1330 void 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 
1364 void 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 
1425 void 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 
1434 void 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 
1457 void 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 
1472 void 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 
1522 void 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 
1531 void 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 
1552 QWidget* KRun::window() const
1553 {
1554  return d->m_window;
1555 }
1556 
1557 bool KRun::hasError() const
1558 {
1559  return d->m_bFault;
1560 }
1561 
1562 bool KRun::hasFinished() const
1563 {
1564  return d->m_bFinished;
1565 }
1566 
1567 bool KRun::autoDelete() const
1568 {
1569  return d->m_bAutoDelete;
1570 }
1571 
1572 void KRun::setAutoDelete(bool b)
1573 {
1574  d->m_bAutoDelete = b;
1575 }
1576 
1577 void 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 
1587 void KRun::setPreferredService(const QString& desktopEntryName)
1588 {
1589  d->m_preferredService = desktopEntryName;
1590 }
1591 
1592 void KRun::setRunExecutables(bool b)
1593 {
1594  d->m_runExecutables = b;
1595 }
1596 
1597 void KRun::setSuggestedFileName(const QString& fileName)
1598 {
1599  d->m_suggestedFileName = fileName;
1600 }
1601 
1602 QString KRun::suggestedFileName() const
1603 {
1604  return d->m_suggestedFileName;
1605 }
1606 
1607 bool 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 
1615 void KRun::setUrl(const KUrl &url)
1616 {
1617  d->m_strURL = url;
1618 }
1619 
1620 KUrl KRun::url() const
1621 {
1622  return d->m_strURL;
1623 }
1624 
1625 void KRun::setError(bool error)
1626 {
1627  d->m_bFault = error;
1628 }
1629 
1630 void KRun::setProgressInfo(bool progressInfo)
1631 {
1632  d->m_bProgressInfo = progressInfo;
1633 }
1634 
1635 bool KRun::progressInfo() const
1636 {
1637  return d->m_bProgressInfo;
1638 }
1639 
1640 void KRun::setFinished(bool finished)
1641 {
1642  d->m_bFinished = finished;
1643  if (finished)
1644  d->startTimer();
1645 }
1646 
1647 void KRun::setJob(KIO::Job *job)
1648 {
1649  d->m_job = job;
1650 }
1651 
1652 KIO::Job* KRun::job()
1653 {
1654  return d->m_job;
1655 }
1656 
1657 #ifndef KDE_NO_DEPRECATED
1658 QTimer& KRun::timer()
1659 {
1660  return d->m_timer;
1661 }
1662 #endif
1663 
1664 #ifndef KDE_NO_DEPRECATED
1665 void KRun::setDoScanFile(bool scanFile)
1666 {
1667  d->m_bScanFile = scanFile;
1668 }
1669 #endif
1670 
1671 #ifndef KDE_NO_DEPRECATED
1672 bool KRun::doScanFile() const
1673 {
1674  return d->m_bScanFile;
1675 }
1676 #endif
1677 
1678 #ifndef KDE_NO_DEPRECATED
1679 void KRun::setIsDirecory(bool isDirectory)
1680 {
1681  d->m_bIsDirectory = isDirectory;
1682 }
1683 #endif
1684 
1685 bool KRun::isDirectory() const
1686 {
1687  return d->m_bIsDirectory;
1688 }
1689 
1690 #ifndef KDE_NO_DEPRECATED
1691 void KRun::setInitializeNextAction(bool initialize)
1692 {
1693  d->m_bInit = initialize;
1694 }
1695 #endif
1696 
1697 #ifndef KDE_NO_DEPRECATED
1698 bool KRun::initializeNextAction() const
1699 {
1700  return d->m_bInit;
1701 }
1702 #endif
1703 
1704 void KRun::setIsLocalFile(bool isLocalFile)
1705 {
1706  d->m_bIsLocalFile = isLocalFile;
1707 }
1708 
1709 bool KRun::isLocalFile() const
1710 {
1711  return d->m_bIsLocalFile;
1712 }
1713 
1714 void KRun::setMode(mode_t mode)
1715 {
1716  d->m_mode = mode;
1717 }
1718 
1719 mode_t KRun::mode() const
1720 {
1721  return d->m_mode;
1722 }
1723 
1724 /****************/
1725 
1726 #ifndef Q_WS_X11
1727 int KProcessRunner::run(KProcess * p, const QString & executable)
1728 {
1729  return (new KProcessRunner(p, executable))->pid();
1730 }
1731 #else
1732 int 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
1739 KProcessRunner::KProcessRunner(KProcess * p, const QString & executable)
1740 #else
1741 KProcessRunner::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 
1765 KProcessRunner::~KProcessRunner()
1766 {
1767  delete process;
1768 }
1769 
1770 int KProcessRunner::pid() const
1771 {
1772  return m_pid;
1773 }
1774 
1775 void 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 
1788 void
1789 KProcessRunner::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"
KIO::JobUiDelegate::setWindow
virtual void setWindow(QWidget *window)
Associate this job with a window given by window.
Definition: jobuidelegate.cpp:58
KStartupInfo::resetStartupEnv
static void resetStartupEnv()
KProcess::setShellCommand
void setShellCommand(const QString &cmd)
message
void message(KMessage::MessageType messageType, const QString &text, const QString &caption=QString())
kdialog.h
i18n
QString i18n(const char *text)
KCompositeJob::kill
bool kill(KillVerbosity verbosity=Quietly)
KRun::KRunPrivate::m_bInit
bool m_bInit
Used to indicate that the next action is to initialize.
Definition: krun_p.h:126
KConfigGroup::readPathEntry
QString readPathEntry(const QString &pKey, const QString &aDefault) const
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
KSharedPtr< KService >
KRun::setEnableExternalBrowser
void setEnableExternalBrowser(bool b)
Sets whether the external webbrowser setting should be honoured.
Definition: krun.cpp:1577
QWidget
KMacroExpanderBase
QDir::toNativeSeparators
QString toNativeSeparators(const QString &pathName)
kopenwithdialog.h
KRun::KRunPrivate::startTimer
void startTimer()
Definition: krun.cpp:93
QString::append
QString & append(QChar ch)
KProcess
header
const char header[]
KUrl::directory
QString directory(const DirectoryOptions &options=IgnoreTrailingSlash) const
netaccess.h
QSize::width
int width() const
KRun::slotTimeout
void slotTimeout()
All following protected slots are used by subclasses of KRun!
Definition: krun.cpp:1330
KRun::foundMimeType
virtual void foundMimeType(const QString &type)
Called if the mimetype has been detected.
Definition: krun.cpp:1472
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
KRun::abort
void abort()
Abort this KRun.
Definition: krun.cpp:1531
KRun::setDoScanFile
void setDoScanFile(bool scanFile)
Indicate that the next action is to scan the file.
Definition: krun.cpp:1665
KRun::progressInfo
bool progressInfo() const
Returns whether progress information are shown.
Definition: krun.cpp:1635
kdebug.h
KRun::KRunPrivate::m_runExecutables
bool m_runExecutables
Definition: krun_p.h:99
KSharedPtr::data
T * data()
kmimetype.h
KStandardDirs::realFilePath
static QString realFilePath(const QString &filename)
kurl.h
KRun::setIsDirecory
void setIsDirecory(bool isDirectory)
Sets whether it is a directory.
Definition: krun.cpp:1679
QByteArray
KIconLoader::global
static KIconLoader * global()
KIO::UDSEntry
Universal Directory Service.
Definition: udsentry.h:58
KService::serviceByDesktopName
static Ptr serviceByDesktopName(const QString &_name)
QWidget::setWindowModality
void setWindowModality(Qt::WindowModality windowModality)
QIODevice::errorString
QString errorString() const
kauthorized.h
QChar
timeout
int timeout
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
QString::prepend
QString & prepend(QChar ch)
KIO::mimetype
MimetypeJob * mimetype(const KUrl &url, JobFlags flags=DefaultFlags)
Find mimetype for one file or directory.
Definition: job.cpp:1856
KRun::setRunExecutables
void setRunExecutables(bool b)
Sets whether executables, .desktop files or shell scripts should be run by KRun.
Definition: krun.cpp:1592
KService
KIO::HideProgressInfo
Hide progress information dialog, i.e.
Definition: jobclasses.h:51
QLabel::setPixmap
void setPixmap(const QPixmap &)
ksavefile.h
KRun::KRunPrivate::m_bProgressInfo
bool m_bProgressInfo
Definition: krun_p.h:110
QByteArray::isNull
bool isNull() const
kshell.h
KProcessRunner::slotProcessExited
void slotProcessExited(int, QProcess::ExitStatus)
Definition: krun.cpp:1789
KSaveFile
KService::property
QVariant property(const QString &_name, QVariant::Type t) const
KSaveFile::open
virtual bool open(OpenMode flags=QIODevice::ReadWrite)
kstandardguiitem.h
KIO::UDSEntry::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
QStringList::contains
bool contains(const QString &str, Qt::CaseSensitivity cs) const
QByteArray::isEmpty
bool isEmpty() const
KRun::KRunPrivate::m_window
QPointer< QWidget > m_window
Definition: krun_p.h:105
KIO::get
TransferJob * get(const KUrl &url, LoadType reload=NoReload, JobFlags flags=DefaultFlags)
Get (a.k.a.
Definition: job.cpp:1369
KDE::stat
int stat(const QString &path, KDE_struct_stat *buf)
KRun::isDirectory
bool isDirectory() const
Returns whether it is a directory.
Definition: krun.cpp:1685
KIO::SimpleJob::url
const KUrl & url() const
Returns the SimpleJob's URL.
Definition: job.cpp:341
QHBoxLayout
kError
static QDebug kError(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
KIO::stat
StatJob * stat(const KUrl &url, JobFlags flags=DefaultFlags)
Find all details for one file or directory.
Definition: job.cpp:924
QDialog::exec
int exec()
KRun::url
KUrl url() const
Returns the url.
Definition: krun.cpp:1620
QPlainTextEdit
KStartupInfoId
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
KService::genericName
QString genericName() const
KIO::StatJob
A KIO job that retrieves information about a file or directory.
Definition: jobclasses.h:440
KUrl::toLocalFile
QString toLocalFile(AdjustPathOption trailing=LeaveTrailingSlash) const
KIO::UDSEntry::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
QFile::setPermissions
bool setPermissions(QFlags< QFile::Permission > permissions)
KRun::hasError
bool hasError() const
Returns true if the KRun instance has an error.
Definition: krun.cpp:1557
KDialog
QFontMetrics
KService::terminalOptions
QString terminalOptions() const
QFile::exists
bool exists() const
KService::substituteUid
bool substituteUid() const
KRecentDocument::add
static void add(const KUrl &url)
Add a new item to the Recent Document menu.
Definition: krecentdocument.cpp:88
KRun::KRunPrivate::m_bIsDirectory
bool m_bIsDirectory
Definition: krun_p.h:120
KSaveFile::abort
void abort()
KIconLoader::NoGroup
KRun::initializeNextAction
bool initializeNextAction() const
Definition: krun.cpp:1698
KStartupInfoData::setBin
void setBin(const QString &bin)
kdesktopfile.h
KRun::scanFile
virtual void scanFile()
Start scanning a file.
Definition: krun.cpp:1289
ktoolinvocation.h
kDebug
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
klocale.h
global.h
KRun::checkStartupNotify
static bool checkStartupNotify(const QString &binName, const KService *service, bool *silent_arg, QByteArray *wmclass_arg)
Definition: krun.cpp:651
KStartupInfoData::setName
void setName(const QString &name)
KGlobal::ref
void ref()
QFile
KDesktopFileActions::run
bool run(const KUrl &_url, bool _is_local)
Invokes the default action for the desktop entry.
Definition: kdesktopfileactions.cpp:54
KRun::KRunPrivate::m_strURL
KUrl m_strURL
Definition: krun_p.h:107
KUrl
KService::isApplication
bool isApplication() const
KRun::setUrl
void setUrl(const KUrl &url)
Sets the url.
Definition: krun.cpp:1615
i18nc
QString i18nc(const char *ctxt, const char *text)
QList::size
int size() const
KRun
To open files with their associated applications in KDE, use KRun.
Definition: krun.h:59
KGlobal::config
KSharedConfigPtr config()
kprotocolmanager.h
QString::isNull
bool isNull() const
KService::exec
QString exec() const
KUrl::setPath
void setPath(const QString &path)
KIO::Job::ui
JobUiDelegate * ui() const
Retrieves the UI delegate of this job.
Definition: job.cpp:90
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
KShell::splitArgs
QStringList splitArgs(const QString &cmd, Options flags=NoOptions, Errors *err=0)
KDesktopFile::isAuthorizedDesktopFile
static bool isAuthorizedDesktopFile(const QString &path)
KService::path
QString path() const
QString::clear
void clear()
scheduler.h
QIODevice::peek
qint64 peek(char *data, qint64 maxSize)
KIO::DefaultFlags
Show the progress info GUI, no Resume and no Overwrite.
Definition: jobclasses.h:46
QWidget::size
size
KProcessRunner::pid
int pid() const
Definition: krun.cpp:1770
kdesktopfileactions.h
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
KStartupInfo::sendChange
static bool sendChange(const KStartupInfoId &id, const KStartupInfoData &data)
QRect
KRun::setError
void setError(bool error)
Sets whether an error has occurred.
Definition: krun.cpp:1625
KRun::isExecutableFile
static bool isExecutableFile(const KUrl &url, const QString &mimetype)
Returns whether the url of mimetype is executable.
Definition: krun.cpp:100
KWindowSystem::currentDesktop
static int currentDesktop()
kglobal.h
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)
kprocess.h
KRun::KRunPrivate::q
KRun * q
Definition: krun_p.h:97
QBoxLayout::addWidget
void addWidget(QWidget *widget, int stretch, QFlags< Qt::AlignmentFlag > alignment)
QList::count
int count(const T &value) const
KSaveFile::errorString
QString errorString() const
QList::append
void append(const T &value)
KRun::KRunPrivate::m_localPath
QString m_localPath
Definition: krun_p.h:103
KStartupInfoData::setDescription
void setDescription(const QString &descr)
KStartupInfo::sendStartup
static bool sendStartup(const KStartupInfoId &id, const KStartupInfoData &data)
KRun::finished
void finished()
Emitted when the operation finished.
KGlobal::deref
void deref()
KRun::setIsLocalFile
void setIsLocalFile(bool isLocalFile)
Sets whether it is a local file.
Definition: krun.cpp:1704
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
QWidget::topLevelWidget
QWidget * topLevelWidget() const
QTimer
kmacroexpander.h
KShell::FoundMeta
KStartupInfoData
KStartupInfoData::setIcon
void setIcon(const QString &icon)
QShowEvent
KGuiItem
KAuthorized::authorizeUrlAction
bool authorizeUrlAction(const QString &action, const KUrl &baseUrl, const KUrl &destUrl)
KService::Ptr
KSharedPtr< KService > Ptr
KUrl::protocol
QString protocol() const
KRun::window
QWidget * window() const
Associated window, as passed to the constructor.
Definition: krun.cpp:1552
QList::isEmpty
bool isEmpty() const
KRun::killJob
virtual void killJob()
Kills the file scanning job.
Definition: krun.cpp:1522
KMessageBox::sorry
static void sorry(QWidget *parent, const QString &text, const QString &caption=QString(), Options options=Notify)
QObject::setObjectName
void setObjectName(const QString &name)
KStartupInfoData::name
const QString & name() const
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
QString::isEmpty
bool isEmpty() const
KStartupInfoData::setSilent
void setSilent(TriState state)
KRun::KRunPrivate::m_preferredService
QString m_preferredService
Definition: krun_p.h:101
QUrl::fragment
QString fragment() const
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::slotStatResult
virtual void slotStatResult(KJob *)
This slot is called when the 'stat' job has finished.
Definition: krun.cpp:1364
QString::startsWith
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
QIODevice::readAll
QByteArray readAll()
kmimetypetrader.h
KShell::Errors
Errors
KRun::autoDelete
bool autoDelete() const
Checks whether auto delete is activated.
Definition: krun.cpp:1567
KRun::job
KIO::Job * job()
Returns the job.
Definition: krun.cpp:1652
KOpenWithDialog
"Open With" dialog box.
Definition: kopenwithdialog.h:39
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
KMimeTypeTrader::self
static KMimeTypeTrader * self()
QVBoxLayout
KRun::KRunPrivate::KRunPrivate
KRunPrivate(KRun *parent)
Definition: krun.cpp:87
KRun::doScanFile
bool doScanFile() const
Returns whether the file shall be scanned.
Definition: krun.cpp:1672
QList< KUrl >::Iterator
typedef Iterator
KProtocolManager::defaultMimetype
static QString defaultMimetype(const KUrl &url)
Returns default mimetype for this URL based on the protocol.
Definition: kprotocolmanager.cpp:1169
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
KProcessRunner::~KProcessRunner
virtual ~KProcessRunner()
Definition: krun.cpp:1765
QWidget::winId
WId winId() const
KRun::mode
mode_t mode() const
Returns the file mode.
Definition: krun.cpp:1719
kmessageboxwrapper.h
QObject::deleteLater
void deleteLater()
KStartupInfoData::setHostname
void setHostname(const QByteArray &hostname=QByteArray())
QList::first
T & first()
KRun::slotScanFinished
void slotScanFinished(KJob *)
This slot is called when the scan job is finished.
Definition: krun.cpp:1434
KProcessRunner::run
static int run(KProcess *, const QString &executable, const KStartupInfoId &id)
Definition: krun.cpp:1732
QString
KRun::KRunPrivate::m_timer
QTimer m_timer
Definition: krun_p.h:113
KProcessRunner
Definition: krun_p.h:37
KProtocolInfo::protocolClass
static QString protocolClass(const QString &protocol)
KStartupInfoData::Yes
QFile::open
virtual bool open(QFlags< QIODevice::OpenModeFlag > mode)
QStringList
KProcess::start
void start()
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
KStartupInfoData::setApplicationId
void setApplicationId(const QString &desktop)
KService::allowMultipleFiles
bool allowMultipleFiles() const
QPixmap
KService::username
QString username() const
jobuidelegate.h
QFileInfo
QList::end
iterator end()
QString::toLower
QString toLower() const
KRun::mimeTypeDetermined
void mimeTypeDetermined(const QString &mimeType)
Call this from subclasses when you have determined the mimetype.
Definition: krun.cpp:1457
QDesktopWidget::screen
QWidget * screen(int screen)
KShell::quoteArg
QString quoteArg(const QString &arg)
KRun::KRunPrivate::m_bIsLocalFile
bool m_bIsLocalFile
Definition: krun_p.h:128
KService::icon
QString icon() const
KProtocolManager::supportsReading
static bool supportsReading(const KUrl &url)
Returns whether the protocol can retrieve data from URLs.
Definition: kprotocolmanager.cpp:1050
KRun::setMode
void setMode(mode_t mode)
Sets the file mode.
Definition: krun.cpp:1714
QSize
KService::terminal
bool terminal() const
QProcess::waitForStarted
bool waitForStarted(int msecs)
KSaveFile::finalize
bool finalize()
QProcess::setWorkingDirectory
void setWorkingDirectory(const QString &dir)
KRun::KRunPrivate::m_bFinished
bool m_bFinished
Definition: krun_p.h:111
KStartupInfo::sendFinish
static bool sendFinish(const KStartupInfoId &id)
QTimer::stop
void stop()
KProtocolInfo::exec
static QString exec(const QString &protocol)
QFile::close
virtual void close()
KDesktopFile
KIconLoader::SizeHuge
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
subst
KProtocolInfo::isHelperProtocol
static bool isHelperProtocol(const KUrl &url)
KIO::ERR_ACCESS_DENIED
Definition: global.h:209
job.h
KOpenWithDialog::text
QString text() const
Definition: kopenwithdialog.cpp:962
KConfigGroup
QString::replace
QString & replace(int position, int n, QChar after)
QString::unicode
const QChar * unicode() const
KUrl::List
krun.h
KRun::KRunPrivate::m_externalBrowser
QString m_externalBrowser
Definition: krun_p.h:102
QObject::startTimer
int startTimer(int interval)
KRun::setInitializeNextAction
void setInitializeNextAction(bool initialize)
Definition: krun.cpp:1691
QUrl::isValid
bool isValid() const
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
supportedProtocols
static QStringList supportedProtocols(const KService &_service)
Definition: krun.cpp:370
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
KStartupInfoData::setWMClass
void setWMClass(const QByteArray &wmclass)
KRun::KRunPrivate::m_bScanFile
bool m_bScanFile
Used to indicate that the next action is to scan the file.
Definition: krun_p.h:119
QString::toLatin1
QByteArray toLatin1() const
makeServiceExecutable
static bool makeServiceExecutable(const KService &service, QWidget *window)
Definition: krun.cpp:898
QString::mid
QString mid(int position, int n) const
KRun::isLocalFile
bool isLocalFile() const
Returns whether it is a local file.
Definition: krun.cpp:1709
QVariant::toStringList
QStringList toStringList() const
KRun::suggestedFileName
QString suggestedFileName() const
Suggested file name given by the server (e.g.
Definition: krun.cpp:1602
KRun::setAutoDelete
void setAutoDelete(bool b)
Enables or disabled auto deletion.
Definition: krun.cpp:1572
KStartupInfo::createNewStartupId
static QByteArray createNewStartupId()
QLatin1String
QApplication::desktop
QDesktopWidget * desktop()
KService::desktopEntryName
QString desktopEntryName() const
KUrl::fileName
QString fileName(const DirectoryOptions &options=IgnoreTrailingSlash) const
QBoxLayout::addStretch
void addStretch(int stretch)
KRun::error
void error()
Emitted when the operation had an error.
jobclasses.h
Qt::escape
QString escape(const QString &plain)
KRun::setJob
void setJob(KIO::Job *job)
Sets the job.
Definition: krun.cpp:1647
kstandarddirs.h
KRun::timer
QTimer & timer()
Returns the timer object.
Definition: krun.cpp:1658
KRun::KRunPrivate::m_showingDialog
bool m_showingDialog
Definition: krun_p.h:98
krun_p.h
makeFileExecutable
static bool makeFileExecutable(const QString &fileName)
Definition: krun.cpp:825
QUrl::encodedQuery
QByteArray encodedQuery() const
KStandardDirs::findExe
static QString findExe(const QString &appname, const QString &pathstr=QString(), SearchOptions options=NoSearchOptions)
QList< KUrl >::ConstIterator
typedef ConstIterator
KRun::setFinished
void setFinished(bool finished)
Marks this 'KRun' instance as finished.
Definition: krun.cpp:1640
QSize::height
int height() const
KIO::Job
The base class for all jobs.
Definition: jobclasses.h:94
KSaveFile::setFileName
void setFileName(const QString &filename)
KIO::NoReload
Definition: job.h:29
KUrl::List::toStringList
QStringList toStringList() const
KShell::NoError
krecentdocument.h
KIO::ERR_NO_CONTENT
Definition: global.h:255
KRun::init
virtual void init()
All following protected methods are used by subclasses of KRun!
Definition: krun.cpp:1139
KUrl::query
QString query() const
QVariant::toBool
bool toBool() const
kwindowsystem.h
QDialog::showEvent
virtual void showEvent(QShowEvent *event)
kWarning
static QDebug kWarning(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
QIODevice::write
qint64 write(const char *data, qint64 maxSize)
KAuthorized::authorize
bool authorize(const QString &genericAction)
KShell::joinArgs
QString joinArgs(const QStringList &args)
KIO::SimpleJob::putOnHold
virtual void putOnHold()
Abort job.
Definition: job.cpp:346
QVariant::isValid
bool isValid() const
isProtocolInSupportedList
static bool isProtocolInSupportedList(const KUrl &url, const QStringList &supportedProtocols)
Definition: krun.cpp:400
KStandardGuiItem::cont
KGuiItem cont()
KProcess::pid
int pid() const
KUrl::url
QString url(AdjustPathOption trailing=LeaveTrailingSlash) const
KRun::~KRun
virtual ~KRun()
Destructor.
Definition: krun.cpp:1255
KIO::UDSEntry::UDS_MIME_TYPE
A mime type; the slave should set it if it's known.
Definition: udsentry.h:192
KRun::KRunPrivate::m_mode
mode_t m_mode
Definition: krun_p.h:129
KIO::StatJob::SourceSide
Definition: jobclasses.h:446
KProtocolManager::supportsListing
static bool supportsListing(const KUrl &url)
Returns whether the protocol can list files/objects.
Definition: kprotocolmanager.cpp:1032
KRun::KRunPrivate::m_bAutoDelete
bool m_bAutoDelete
Definition: krun_p.h:109
KIO::TransferJob
The transfer job pumps data into and/or out of a Slave.
Definition: jobclasses.h:555
KRun::setProgressInfo
void setProgressInfo(bool progressInfo)
Sets whether progress information shall be shown.
Definition: krun.cpp:1630
QFile::permissions
Permissions permissions() const
QDesktopServices::openUrl
bool openUrl(const QUrl &url)
KRun::KRunPrivate::runExecutable
bool runExecutable(const QString &_exec)
Definition: krun.cpp:1265
KIO::Scheduler::publishSlaveOnHold
static void publishSlaveOnHold()
Send the slave that was put on hold back to KLauncher.
Definition: scheduler.cpp:830
KIO::StatJob::statResult
const UDSEntry & statResult() const
Result of the stat operation.
Definition: job.cpp:839
KUrl::isLocalFile
bool isLocalFile() const
KRun::KRunPrivate::m_bFault
bool m_bFault
Definition: krun_p.h:108
QByteArray::size
int size() const
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
KStartupInfoData::setDesktop
void setDesktop(int desktop)
QLabel
QObject::parent
QObject * parent() const
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_asn
QByteArray m_asn
Definition: krun_p.h:106
kguiitem.h
KStartupInfoId::initId
void initId(const QByteArray &id="")
QVariant::toString
QString toString() const
KService::hasMimeType
bool hasMimeType(const KServiceType *mimeTypePtr) const
KConfigGroup::readEntry
T readEntry(const QString &key, const T &aDefault) const
KRun::KRunPrivate::m_suggestedFileName
QString m_suggestedFileName
Definition: krun_p.h:104
KStartupInfoData::addPid
void addPid(pid_t pid)
KJob
kFatal
static QDebug kFatal(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
KRun::KRunPrivate::m_job
KIO::Job * m_job
Definition: krun_p.h:112
KRun::binaryName
static QString binaryName(const QString &execLine, bool removePath)
Given a full command line (e.g.
Definition: krun.cpp:568
KMessageBoxWrapper::error
static void error(QWidget *parent, const QString &text, const QString &caption=QString())
Definition: kmessageboxwrapper.h:33
QProcess::exitStatus
QProcess::ExitStatus exitStatus() const
QList::begin
iterator begin()
KRun::shellQuote
static void shellQuote(QString &str)
Quotes a string for the shell.
Definition: krun.cpp:223
KUrl::prettyUrl
QString prettyUrl(AdjustPathOption trailing=LeaveTrailingSlash) const
KAuthorized::authorizeKAction
bool authorizeKAction(const QString &action)
KMimeTypeTrader::preferredService
KService::Ptr preferredService(const QString &mimeType, const QString &genericServiceType=QString::fromLatin1("Application"))
resolveURLs
static KUrl::List resolveURLs(const KUrl::List &_urls, const KService &_service)
Definition: krun.cpp:745
KShell::AbortOnMeta
QProcess::readAllStandardError
QByteArray readAllStandardError()
kconfiggroup.h
KRun::KRunPrivate
Definition: krun_p.h:77
KOpenWithDialog::service
KService::Ptr service() const
Definition: kopenwithdialog.cpp:983
QBoxLayout::addLayout
void addLayout(QLayout *layout, int stretch)
KShell::TildeExpand
KStartupInfoData::setLaunchedBy
void setLaunchedBy(WId window)
KService::serviceByStorageId
static Ptr serviceByStorageId(const QString &_storageId)
KRun::hasFinished
bool hasFinished() const
Returns true if the KRun instance has finished.
Definition: krun.cpp:1562
QTimer::setSingleShot
void setSingleShot(bool singleShot)
QList::replace
void replace(int i, const T &value)
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:24:53 by doxygen 1.8.7 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 API Reference

Skip menu "kdelibs 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

Search



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