• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdeio/tdeio
 

tdeio/tdeio

  • tdeio
  • tdeio
krun.cpp
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 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Library General Public
7  License as published by the Free Software Foundation; either
8  version 2 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Library General Public License for more details.
14 
15  You should have received a copy of the GNU Library General Public License
16  along with this library; see the file COPYING.LIB. If not, write to
17  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  Boston, MA 02110-1301, USA.
19 */
20 
21 #include "krun.h"
22 
23 #include <assert.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <typeinfo>
28 
29 #include <tqwidget.h>
30 #include <tqguardedptr.h>
31 
32 #include "kuserprofile.h"
33 #include "kmimetype.h"
34 #include "kmimemagic.h"
35 #include "tdeio/job.h"
36 #include "tdeio/global.h"
37 #include "tdeio/scheduler.h"
38 #include "tdeio/netaccess.h"
39 #include "tdefile/kopenwith.h"
40 #include "tdefile/tderecentdocument.h"
41 
42 #include <kdatastream.h>
43 #include <kmessageboxwrapper.h>
44 #include <kurl.h>
45 #include <tdeapplication.h>
46 #include <kdebug.h>
47 #include <tdelocale.h>
48 #include <kprotocolinfo.h>
49 #include <kstandarddirs.h>
50 #include <kprocess.h>
51 #include <dcopclient.h>
52 #include <tqfile.h>
53 #include <tqfileinfo.h>
54 #include <tqtextstream.h>
55 #include <tqdatetime.h>
56 #include <tqregexp.h>
57 #include <kdesktopfile.h>
58 #include <tdestartupinfo.h>
59 #include <kmacroexpander.h>
60 #include <kshell.h>
61 #include <kde_file.h>
62 #include <kstringhandler.h>
63 
64 #ifdef Q_WS_X11
65 #include <twin.h>
66 #endif
67 
68 class KRun::KRunPrivate
69 {
70 public:
71  KRunPrivate() { m_showingError = false; }
72 
73  bool m_showingError;
74  bool m_runExecutables;
75 
76  TQString m_preferredService;
77  TQString m_externalBrowser;
78  TQString m_localPath;
79  TQString m_suggestedFileName;
80  TQGuardedPtr <TQWidget> m_window;
81  TQCString m_asn;
82 };
83 
84 pid_t KRun::runURL( const KURL& u, const TQString& _mimetype )
85 {
86  return runURL( u, _mimetype, false, true, TQString::null );
87 }
88 
89 pid_t KRun::runURL( const KURL& u, const TQString& _mimetype, bool tempFile )
90 {
91  return runURL( u, _mimetype, tempFile, true, TQString::null );
92 }
93 
94 pid_t KRun::runURL( const KURL& u, const TQString& _mimetype, bool tempFile, bool runExecutables )
95 {
96  return runURL( u, _mimetype, tempFile, runExecutables, TQString::null );
97 }
98 
99 bool KRun::isExecutableFile( const KURL& url, const TQString &mimetype )
100 {
101  if ( !url.isLocalFile() )
102  return false;
103  TQFileInfo file( url.path() );
104  if ( file.isExecutable() ) // Got a prospective file to run
105  {
106  KMimeType::Ptr mimeType = KMimeType::mimeType( mimetype );
107 
108  if ( mimeType->is("application/x-executable") || mimeType->is("application/x-executable-script") )
109  return true;
110  }
111  return false;
112 }
113 
114 pid_t KRun::runURL( const KURL& u, const TQString& _mimetype, bool tempFile, bool runExecutables, const TQString& suggestedFileName )
115 {
116  return runURL( u, _mimetype, NULL, "", tempFile, runExecutables, suggestedFileName );
117 }
118 
119 // This is called by foundMimeType, since it knows the mimetype of the URL
120 pid_t KRun::runURL( const KURL& u, const TQString& _mimetype, TQWidget* window, const TQCString& asn,
121  bool tempFile, bool runExecutables, const TQString& suggestedFileName )
122 {
123  bool noRun = false;
124  bool noAuth = false;
125  if ( _mimetype == "inode/directory-locked" )
126  {
127  KMessageBoxWrapper::error( window,
128  i18n("<qt>Unable to enter <b>%1</b>.\nYou do not have access rights to this location.</qt>").arg(u.htmlURL()) );
129  return 0;
130  }
131  else if ( (_mimetype == "application/x-desktop") ||
132  (_mimetype == "media/builtin-mydocuments") ||
133  (_mimetype == "media/builtin-mycomputer") ||
134  (_mimetype == "media/builtin-mynetworkplaces") ||
135  (_mimetype == "media/builtin-printers") ||
136  (_mimetype == "media/builtin-trash") ||
137  (_mimetype == "media/builtin-webbrowser") )
138  {
139  if ( u.isLocalFile() && runExecutables )
140  return KDEDesktopMimeType::run( u, true );
141  }
142  else if ( isExecutableFile(u, _mimetype) )
143  {
144  if ( u.isLocalFile() && runExecutables)
145  {
146  if (kapp->authorize("shell_access"))
147  {
148  TQString path = u.path();
149  shellQuote( path );
150  return (KRun::runCommand(path, TQString::null, TQString::null, window, asn)); // just execute the url as a command
151  // ## TODO implement deleting the file if tempFile==true
152  }
153  else
154  {
155  noAuth = true;
156  }
157  }
158  else if (_mimetype == "application/x-executable")
159  noRun = true;
160  }
161  else if ( isExecutable(_mimetype) )
162  {
163  if (!runExecutables)
164  noRun = true;
165 
166  if (!kapp->authorize("shell_access"))
167  noAuth = true;
168  }
169 
170  if ( noRun )
171  {
172  KMessageBox::sorry( window,
173  i18n("<qt>The file <b>%1</b> is an executable program. "
174  "For safety it will not be started.</qt>").arg(u.htmlURL()));
175  return 0;
176  }
177  if ( noAuth )
178  {
179  KMessageBoxWrapper::error( window,
180  i18n("<qt>You do not have permission to run <b>%1</b>.</qt>").arg(u.htmlURL()) );
181  return 0;
182  }
183 
184  KURL::List lst;
185  lst.append( u );
186 
187  static const TQString& app_str = TDEGlobal::staticQString("Application");
188 
189  KService::Ptr offer = KServiceTypeProfile::preferredService( _mimetype, app_str );
190 
191  if ( !offer )
192  {
193  // Open-with dialog
194  // TODO : pass the mimetype as a parameter, to show it (comment field) in the dialog !
195  // Hmm, in fact KOpenWithDlg::setServiceType already guesses the mimetype from the first URL of the list...
196  return displayOpenWithDialog( lst, tempFile, suggestedFileName );
197  }
198 
199  return KRun::run( *offer, lst, window, asn, tempFile, suggestedFileName );
200 }
201 
202 bool KRun::displayOpenWithDialog( const KURL::List& lst )
203 {
204  return displayOpenWithDialog( lst, false, TQString::null );
205 }
206 
207 bool KRun::displayOpenWithDialog( const KURL::List& lst, bool tempFiles )
208 {
209  return displayOpenWithDialog( lst, tempFiles, TQString::null );
210 }
211 
212 bool KRun::displayOpenWithDialog( const KURL::List& lst, bool tempFiles, const TQString& suggestedFileName )
213 {
214  if (kapp && !kapp->authorizeTDEAction("openwith"))
215  {
216  // TODO: Better message, i18n freeze :-(
217  KMessageBox::sorry(0L, i18n("You are not authorized to open this file."));
218  return false;
219  }
220 
221  KOpenWithDlg l( lst, i18n("Open with:"), TQString::null, 0L );
222  if ( l.exec() )
223  {
224  KService::Ptr service = l.service();
225  if ( !!service )
226  return KRun::run( *service, lst, 0 /*window*/, tempFiles, suggestedFileName );
227 
228  kdDebug(7010) << "No service set, running " << l.text() << endl;
229  return KRun::run( l.text(), lst, suggestedFileName ); // TODO handle tempFiles
230  }
231  return false;
232 }
233 
234 void KRun::shellQuote( TQString &_str )
235 {
236  // Credits to Walter, says Bernd G. :)
237  if (_str.isEmpty()) // Don't create an explicit empty parameter
238  return;
239  TQChar q('\'');
240  _str.replace(q, "'\\''").prepend(q).append(q);
241 }
242 
243 
244 class KRunMX1 : public KMacroExpanderBase {
245 public:
246  KRunMX1( const KService &_service ) :
247  KMacroExpanderBase( '%' ), hasUrls( false ), hasSpec( false ), service( _service ) {}
248  bool hasUrls:1, hasSpec:1;
249 
250 protected:
251  virtual int expandEscapedMacro( const TQString &str, uint pos, TQStringList &ret );
252 
253 private:
254  const KService &service;
255 };
256 
257 int
258 KRunMX1::expandEscapedMacro( const TQString &str, uint pos, TQStringList &ret )
259 {
260  uint option = str[pos + 1];
261  switch( option ) {
262  case 'c':
263  ret << service.name().replace( '%', "%%" );
264  break;
265  case 'k':
266  ret << service.desktopEntryPath().replace( '%', "%%" );
267  break;
268  case 'i':
269  ret << "-icon" << service.icon().replace( '%', "%%" );
270  break;
271  case 'm':
272  ret << "-miniicon" << service.icon().replace( '%', "%%" );
273  break;
274  case 'u':
275  case 'U':
276  hasUrls = true;
277  /* fallthrough */
278  case 'f':
279  case 'F':
280  case 'n':
281  case 'N':
282  case 'd':
283  case 'D':
284  case 'v':
285  hasSpec = true;
286  /* fallthrough */
287  default:
288  return -2; // subst with same and skip
289  }
290  return 2;
291 }
292 
293 class KRunMX2 : public KMacroExpanderBase {
294 public:
295  KRunMX2( const KURL::List &_urls ) :
296  KMacroExpanderBase( '%' ), ignFile( false ), urls( _urls ) {}
297  bool ignFile:1;
298 
299 protected:
300  virtual int expandEscapedMacro( const TQString &str, uint pos, TQStringList &ret );
301 
302 private:
303  void subst( int option, const KURL &url, TQStringList &ret );
304 
305  const KURL::List &urls;
306 };
307 
308 void
309 KRunMX2::subst( int option, const KURL &url, TQStringList &ret )
310 {
311  switch( option ) {
312  case 'u':
313  ret << url.pathOrURL();
314  break;
315  case 'd':
316  ret << url.directory();
317  break;
318  case 'f':
319  ret << url.path();
320  break;
321  case 'n':
322  ret << url.fileName();
323  break;
324  case 'v':
325  if (url.isLocalFile() && TQFile::exists( url.path() ) )
326  ret << KDesktopFile( url.path(), true ).readEntry( "Dev" );
327  break;
328  }
329  return;
330 }
331 
332 int
333 KRunMX2::expandEscapedMacro( const TQString &str, uint pos, TQStringList &ret )
334 {
335  uint option = str[pos + 1];
336  switch( option ) {
337  case 'f':
338  case 'u':
339  case 'n':
340  case 'd':
341  case 'v':
342  if( urls.isEmpty() ) {
343  if (!ignFile)
344  kdDebug() << "KRun::processDesktopExec: No URLs supplied to single-URL service " << str << endl;
345  } else if( urls.count() > 1 )
346  kdWarning() << "KRun::processDesktopExec: " << urls.count() << " URLs supplied to single-URL service " << str << endl;
347  else
348  subst( option, urls.first(), ret );
349  break;
350  case 'F':
351  case 'U':
352  case 'N':
353  case 'D':
354  option += 'a' - 'A';
355  for( KURL::List::ConstIterator it = urls.begin(); it != urls.end(); ++it )
356  subst( option, *it, ret );
357  break;
358  case '%':
359  ret = "%";
360  break;
361  default:
362  return -2; // subst with same and skip
363  }
364  return 2;
365 }
366 
367 // BIC: merge methods below
368 TQStringList KRun::processDesktopExec(const KService &_service, const KURL::List& _urls, bool has_shell) {
369  return processDesktopExec( _service, _urls, has_shell, false, TQString::null );
370 }
371 
372 TQStringList KRun::processDesktopExec(const KService &_service, const KURL::List& _urls, bool has_shell /* KDE4: remove */, bool tempFiles)
373 {
374  return processDesktopExec( _service, _urls, has_shell, tempFiles, TQString::null );
375 }
376 
377 TQStringList KRun::processDesktopExec(const KService &_service, const KURL::List& _urls, bool has_shell /* KDE4: remove */, bool tempFiles, const TQString& suggestedFileName)
378 {
379  TQString exec = _service.exec();
380  TQStringList result;
381  bool appHasTempFileOption;
382 
383  KRunMX1 mx1( _service );
384  KRunMX2 mx2( _urls );
385 
387  TQRegExp re("^\\s*(?:/bin/)?sh\\s+-c\\s+(.*)$");
388  if (!re.search( exec )) {
389  exec = TQString(re.cap( 1 )).stripWhiteSpace();
390  for (uint pos = 0; pos < exec.length(); ) {
391  TQChar c = exec.unicode()[pos];
392  if (c != '\'' && c != '"')
393  goto synerr; // what else can we do? after normal parsing the substs would be insecure
394  int pos2 = exec.find( c, pos + 1 ) - 1;
395  if (pos2 < 0)
396  goto synerr; // quoting error
397  memcpy( (void *)(exec.unicode() + pos), exec.unicode() + pos + 1, (pos2 - pos) * sizeof(TQChar));
398  pos = pos2;
399  exec.remove( pos, 2 );
400  }
401  }
402 
403  if( !mx1.expandMacrosShellQuote( exec ) )
404  goto synerr; // error in shell syntax
405 
406  // FIXME: the current way of invoking tdeioexec disables term and su use
407 
408  // Check if we need "tempexec" (tdeioexec in fact)
409  appHasTempFileOption = tempFiles && _service.property("X-TDE-HasTempFileOption").toBool();
410  if( tempFiles && !appHasTempFileOption && _urls.size() ) {
411  result << "tdeioexec" << "--tempfiles" << exec;
412  result += _urls.toStringList();
413  if (has_shell)
414  result = KShell::joinArgs( result );
415  return result;
416  }
417 
418  // Check if we need tdeioexec
419  if( !mx1.hasUrls ) {
420  for( KURL::List::ConstIterator it = _urls.begin(); it != _urls.end(); ++it )
421  if ( !(*it).isLocalFile() && !KProtocolInfo::isHelperProtocol(*it) ) {
422  // We need to run the app through tdeioexec
423  result << "tdeioexec";
424  if ( tempFiles )
425  result << "--tempfiles";
426  if ( !suggestedFileName.isEmpty() ) {
427  result << "--suggestedfilename";
428  result << suggestedFileName;
429  }
430  result << exec;
431  result += _urls.toStringList();
432  if (has_shell)
433  result = KShell::joinArgs( result );
434  return result;
435  }
436  }
437 
438  if ( appHasTempFileOption )
439  exec += " --tempfile";
440 
441  // Did the user forget to append something like '%f'?
442  // If so, then assume that '%f' is the right choice => the application
443  // accepts only local files.
444  if( !mx1.hasSpec ) {
445  exec += " %f";
446  mx2.ignFile = true;
447  }
448 
449  mx2.expandMacrosShellQuote( exec ); // syntax was already checked, so don't check return value
450 
451 /*
452  1 = need_shell, 2 = terminal, 4 = su, 8 = has_shell
453 
454  0 << split(cmd)
455  1 << "sh" << "-c" << cmd
456  2 << split(term) << "-e" << split(cmd)
457  3 << split(term) << "-e" << "sh" << "-c" << cmd
458 
459  4 << "tdesu" << "-u" << user << "-c" << cmd
460  5 << "tdesu" << "-u" << user << "-c" << ("sh -c " + quote(cmd))
461  6 << split(term) << "-e" << "su" << user << "-c" << cmd
462  7 << split(term) << "-e" << "su" << user << "-c" << ("sh -c " + quote(cmd))
463 
464  8 << cmd
465  9 << cmd
466  a << term << "-e" << cmd
467  b << term << "-e" << ("sh -c " + quote(cmd))
468 
469  c << "tdesu" << "-u" << user << "-c" << quote(cmd)
470  d << "tdesu" << "-u" << user << "-c" << quote("sh -c " + quote(cmd))
471  e << term << "-e" << "su" << user << "-c" << quote(cmd)
472  f << term << "-e" << "su" << user << "-c" << quote("sh -c " + quote(cmd))
473 
474  "sh -c" is needed in the "su" case, too, as su uses the user's login shell, not sh.
475  this could be optimized with the -s switch of some su versions (e.g., debian linux).
476 */
477 
478  if (_service.terminal()) {
479  TDEConfigGroupSaver gs(TDEGlobal::config(), "General");
480  TQString terminal = TDEGlobal::config()->readPathEntry("TerminalApplication", "konsole");
481  if (terminal == "konsole")
482  terminal += " -caption=%c %i %m";
483  terminal += " ";
484  terminal += _service.terminalOptions();
485  if( !mx1.expandMacrosShellQuote( terminal ) ) {
486  kdWarning() << "KRun: syntax error in command `" << terminal << "', service `" << _service.name() << "'" << endl;
487  return TQStringList();
488  }
489  mx2.expandMacrosShellQuote( terminal );
490  if (has_shell)
491  result << terminal;
492  else
493  result = KShell::splitArgs( terminal ); // assuming that the term spec never needs a shell!
494  result << "-e";
495  }
496 
497  int err;
498  if (_service.substituteUid()) {
499  if (_service.terminal())
500  result << "su";
501  else
502  result << "tdesu" << "-u";
503  result << _service.username() << "-c";
504  KShell::splitArgs(exec, KShell::AbortOnMeta | KShell::TildeExpand, &err);
505  if (err == KShell::FoundMeta) {
506  shellQuote( exec );
507  exec.prepend( "/bin/sh -c " );
508  } else if (err != KShell::NoError)
509  goto synerr;
510  if (has_shell)
511  shellQuote( exec );
512  result << exec;
513  } else {
514  if (has_shell) {
515  if (_service.terminal()) {
516  KShell::splitArgs(exec, KShell::AbortOnMeta | KShell::TildeExpand, &err);
517  if (err == KShell::FoundMeta) {
518  shellQuote( exec );
519  exec.prepend( "/bin/sh -c " );
520  } else if (err != KShell::NoError)
521  goto synerr;
522  }
523  result << exec;
524  } else {
525  result += KShell::splitArgs(exec, KShell::AbortOnMeta | KShell::TildeExpand, &err);
526  if (err == KShell::FoundMeta)
527  result << "/bin/sh" << "-c" << exec;
528  else if (err != KShell::NoError)
529  goto synerr;
530  }
531  }
532 
533  return result;
534 
535  synerr:
536  kdWarning() << "KRun: syntax error in command `" << _service.exec() << "', service `" << _service.name() << "'" << endl;
537  return TQStringList();
538 }
539 
540 //static
541 TQString KRun::binaryName( const TQString & execLine, bool removePath )
542 {
543  // Remove parameters and/or trailing spaces.
544  TQStringList args = KShell::splitArgs( execLine );
545  for (TQStringList::ConstIterator it = args.begin(); it != args.end(); ++it)
546  if (!(*it).contains('='))
547  // Remove path if wanted
548  return removePath ? (*it).mid(TQString(*it).findRev('/') + 1) : *it;
549  return TQString();
550 }
551 
552 static pid_t runCommandInternal( TDEProcess* proc, const KService* service, const TQString& binName,
553  const TQString &execName, const TQString & iconName, TQWidget* window, TQCString asn )
554 {
555  if (service && !service->desktopEntryPath().isEmpty()
556  && !KDesktopFile::isAuthorizedDesktopFile( service->desktopEntryPath() ))
557  {
558  kdWarning() << "No authorization to execute " << service->desktopEntryPath() << endl;
559  KMessageBox::sorry(window, i18n("You are not authorized to execute this file."));
560  return 0;
561  }
562  TQString bin = KRun::binaryName( binName, true );
563 #ifdef Q_WS_X11 // Startup notification doesn't work with QT/E, service isn't needed without Startup notification
564  bool silent;
565  TQCString wmclass;
566  TDEStartupInfoId id;
567  bool startup_notify = ( asn != "0" && KRun::checkStartupNotify( binName, service, &silent, &wmclass ));
568  if( startup_notify )
569  {
570  id.initId( asn );
571  id.setupStartupEnv();
572  TDEStartupInfoData data;
573  data.setHostname();
574  data.setBin( bin );
575  if( !execName.isEmpty())
576  data.setName( execName );
577  else if( service && !service->name().isEmpty())
578  data.setName( service->name());
579  data.setDescription( i18n( "Launching %1" ).arg( data.name()));
580  if( !iconName.isEmpty())
581  data.setIcon( iconName );
582  else if( service && !service->icon().isEmpty())
583  data.setIcon( service->icon());
584  if( !wmclass.isEmpty())
585  data.setWMClass( wmclass );
586  if( silent )
587  data.setSilent( TDEStartupInfoData::Yes );
588  data.setDesktop( KWin::currentDesktop());
589  if( window )
590  data.setLaunchedBy( window->winId());
591  TDEStartupInfo::sendStartup( id, data );
592  }
593  pid_t pid = TDEProcessRunner::run( proc, binName, id );
594  if( startup_notify && pid )
595  {
596  TDEStartupInfoData data;
597  data.addPid( pid );
598  TDEStartupInfo::sendChange( id, data );
599  TDEStartupInfo::resetStartupEnv();
600  }
601  return pid;
602 #else
603  Q_UNUSED( execName );
604  Q_UNUSED( iconName );
605  return TDEProcessRunner::run( proc, bin );
606 #endif
607 }
608 
609 // This code is also used in tdelauncher.
610 bool KRun::checkStartupNotify( const TQString& /*binName*/, const KService* service, bool* silent_arg, TQCString* wmclass_arg )
611 {
612  bool silent = false;
613  TQCString wmclass;
614  if( service && service->property( "StartupNotify" ).isValid())
615  {
616  silent = !service->property( "StartupNotify" ).toBool();
617  wmclass = service->property( "StartupWMClass" ).toString().latin1();
618  }
619  else if( service && service->property( "X-TDE-StartupNotify" ).isValid())
620  {
621  silent = !service->property( "X-TDE-StartupNotify" ).toBool();
622  wmclass = service->property( "X-TDE-WMClass" ).toString().latin1();
623  }
624  else // non-compliant app
625  {
626  if( service )
627  {
628  if( service->type() == "Application" )
629  wmclass = "0"; // doesn't have .desktop entries needed, start as non-compliant
630  else
631  return false; // no startup notification at all
632  }
633  else
634  {
635 #if 0
636  // Create startup notification even for apps for which there shouldn't be any,
637  // just without any visual feedback. This will ensure they'll be positioned on the proper
638  // virtual desktop, and will get user timestamp from the ASN ID.
639  wmclass = "0";
640  silent = true;
641 #else // That unfortunately doesn't work, when the launched non-compliant application
642  // launches another one that is compliant and there is any delay inbetween (bnc:#343359)
643  return false;
644 #endif
645  }
646  }
647  if( silent_arg != NULL )
648  *silent_arg = silent;
649  if( wmclass_arg != NULL )
650  *wmclass_arg = wmclass;
651  return true;
652 }
653 
654 static pid_t runTempService( const KService& _service, const KURL::List& _urls, TQWidget* window,
655  const TQCString& asn, bool tempFiles, const TQString& suggestedFileName )
656 {
657  if (!_urls.isEmpty()) {
658  kdDebug(7010) << "runTempService: first url " << _urls.first().url() << endl;
659  }
660 
661  TQStringList args;
662  if ((_urls.count() > 1) && !_service.allowMultipleFiles())
663  {
664  // We need to launch the application N times. That sucks.
665  // We ignore the result for application 2 to N.
666  // For the first file we launch the application in the
667  // usual way. The reported result is based on this
668  // application.
669  KURL::List::ConstIterator it = _urls.begin();
670  while(++it != _urls.end())
671  {
672  KURL::List singleUrl;
673  singleUrl.append(*it);
674  runTempService( _service, singleUrl, window, "", tempFiles, suggestedFileName );
675  }
676  KURL::List singleUrl;
677  singleUrl.append(_urls.first());
678  args = KRun::processDesktopExec(_service, singleUrl, false, tempFiles, suggestedFileName);
679  }
680  else
681  {
682  args = KRun::processDesktopExec(_service, _urls, false, tempFiles, suggestedFileName);
683  }
684  kdDebug(7010) << "runTempService: TDEProcess args=" << args << endl;
685 
686  TDEProcess * proc = new TDEProcess;
687  *proc << args;
688 
689  if (!_service.path().isEmpty())
690  proc->setWorkingDirectory(_service.path());
691 
692  return runCommandInternal( proc, &_service, KRun::binaryName( _service.exec(), false ),
693  _service.name(), _service.icon(), window, asn );
694 }
695 
696 // WARNING: don't call this from processDesktopExec, since tdelauncher uses that too...
697 static KURL::List resolveURLs( const KURL::List& _urls, const KService& _service )
698 {
699  // Check which protocols the application supports.
700  // This can be a list of actual protocol names, or just TDEIO for KDE apps.
701  TQStringList supportedProtocols = _service.property("X-TDE-Protocols").toStringList();
702  KRunMX1 mx1( _service );
703  TQString exec = _service.exec();
704  if ( mx1.expandMacrosShellQuote( exec ) && !mx1.hasUrls ) {
705  Q_ASSERT( supportedProtocols.isEmpty() ); // huh? If you support protocols you need %u or %U...
706  } else {
707  if ( supportedProtocols.isEmpty() )
708  {
709  // compat mode: assume TDEIO if not set and it's a KDE app
710  TQStringList categories = _service.property("Categories").toStringList();
711  if (( categories.find("TDE") != categories.end() ) && ( categories.find("KDE") != categories.end() ))
712  supportedProtocols.append( "TDEIO" );
713  else { // if no KDE app, be a bit over-generic
714  supportedProtocols.append( "http");
715  supportedProtocols.append( "ftp");
716  }
717  }
718  }
719  kdDebug(7010) << "supportedProtocols:" << supportedProtocols << endl;
720 
721  KURL::List urls( _urls );
722  if ( supportedProtocols.find( "TDEIO" ) == supportedProtocols.end() ) {
723  for( KURL::List::Iterator it = urls.begin(); it != urls.end(); ++it ) {
724  const KURL url = *it;
725  bool supported = url.isLocalFile() || supportedProtocols.find( url.protocol().lower() ) != supportedProtocols.end();
726  kdDebug(7010) << "Looking at url=" << url << " supported=" << supported << endl;
727  if ( !supported && KProtocolInfo::protocolClass(url.protocol()) == ":local" )
728  {
729  // Maybe we can resolve to a local URL?
730  KURL localURL = TDEIO::NetAccess::mostLocalURL( url, 0 );
731  if ( localURL != url ) {
732  *it = localURL;
733  kdDebug(7010) << "Changed to " << localURL << endl;
734  }
735  }
736  }
737  }
738  return urls;
739 }
740 
741 // BIC merge methods below
742 pid_t KRun::run( const KService& _service, const KURL::List& _urls )
743 {
744  return run( _service, _urls, 0, false, TQString::null );
745 }
746 
747 pid_t KRun::run( const KService& _service, const KURL::List& _urls, bool tempFiles )
748 {
749  return run( _service, _urls, 0, tempFiles, TQString::null );
750 }
751 
752 pid_t KRun::run( const KService& _service, const KURL::List& _urls, TQWidget* window, bool tempFiles )
753 {
754  return run( _service, _urls, window, "", tempFiles, TQString::null );
755 }
756 
757 pid_t KRun::run( const KService& _service, const KURL::List& _urls, TQWidget* window, const TQCString& asn, bool tempFiles )
758 {
759  return run( _service, _urls, window, asn, tempFiles, TQString::null );
760 }
761 
762 pid_t KRun::run( const KService& _service, const KURL::List& _urls, TQWidget* window, bool tempFiles, const TQString& suggestedFileName )
763 {
764  return run( _service, _urls, window, "", tempFiles, suggestedFileName );
765 }
766 
767 pid_t KRun::run( const KService& _service, const KURL::List& _urls, TQWidget* window, const TQCString& asn,
768  bool tempFiles, const TQString& suggestedFileName )
769 {
770  if (!_service.desktopEntryPath().isEmpty() &&
771  !KDesktopFile::isAuthorizedDesktopFile( _service.desktopEntryPath()))
772  {
773  kdWarning() << "No authorization to execute " << _service.desktopEntryPath() << endl;
774  KMessageBox::sorry(window, i18n("You are not authorized to execute this service."));
775  return 0;
776  }
777 
778  if ( !tempFiles )
779  {
780  // Remember we opened those urls, for the "recent documents" menu in kicker
781  KURL::List::ConstIterator it = _urls.begin();
782  for(; it != _urls.end(); ++it) {
783  //kdDebug(7010) << "TDERecentDocument::adding " << (*it).url() << endl;
784  TDERecentDocument::add( *it, _service.desktopEntryName() );
785  }
786  }
787 
788  if ( tempFiles || _service.desktopEntryPath().isEmpty() || !suggestedFileName.isEmpty() )
789  {
790  return runTempService(_service, _urls, window, asn, tempFiles, suggestedFileName);
791  }
792 
793  kdDebug(7010) << "KRun::run " << _service.desktopEntryPath() << endl;
794 
795  if (!_urls.isEmpty()) {
796  kdDebug(7010) << "First url " << _urls.first().url() << endl;
797  }
798 
799  // Resolve urls if needed, depending on what the app supports
800  const KURL::List urls = resolveURLs( _urls, _service );
801 
802  TQString error;
803  int pid = 0;
804 
805  TQCString myasn = asn;
806  // startServiceByDesktopPath() doesn't take TQWidget*, add it to the startup info now
807  if( window != NULL )
808  {
809  if( myasn.isEmpty())
810  myasn = TDEStartupInfo::createNewStartupId();
811  if( myasn != "0" )
812  {
813  TDEStartupInfoId id;
814  id.initId( myasn );
815  TDEStartupInfoData data;
816  data.setLaunchedBy( window->winId());
817  TDEStartupInfo::sendChange( id, data );
818  }
819  }
820 
821  int i = TDEApplication::startServiceByDesktopPath(
822  _service.desktopEntryPath(), urls.toStringList(), &error, 0L, &pid, myasn
823  );
824 
825  if (i != 0)
826  {
827  kdDebug(7010) << error << endl;
828  KMessageBox::sorry( window, error );
829  return 0;
830  }
831 
832  kdDebug(7010) << "startServiceByDesktopPath worked fine" << endl;
833  return (pid_t) pid;
834 }
835 
836 
837 pid_t KRun::run( const TQString& _exec, const KURL::List& _urls, const TQString& _name,
838  const TQString& _icon, const TQString&, const TQString&)
839 {
840  KService::Ptr service = new KService(_name, _exec, _icon);
841 
842  return run(*service, _urls);
843 }
844 
845 pid_t KRun::runCommand( TQString cmd )
846 {
847  return KRun::runCommand( cmd, TQString::null, TQString::null, NULL, "" );
848 }
849 
850 pid_t KRun::runCommand( const TQString& cmd, const TQString &execName, const TQString & iconName )
851 {
852  return KRun::runCommand( cmd, execName, iconName, NULL, "" );
853 }
854 
855 pid_t KRun::runCommand( const TQString& cmd, const TQString &execName, const TQString & iconName,
856  TQWidget* window, const TQCString& asn )
857 {
858  kdDebug(7010) << "runCommand " << cmd << "," << execName << endl;
859  TDEProcess * proc = new TDEProcess;
860  proc->setUseShell(true);
861  *proc << cmd;
862  KService::Ptr service = KService::serviceByDesktopName( binaryName( execName, true ) );
863  TQString bin = binaryName( cmd, false );
864  int pos = bin.findRev( '/' );
865  if (pos != -1) {
866  proc->setWorkingDirectory( bin.mid(0, pos) );
867  }
868  return runCommandInternal( proc, service.data(), binaryName( execName, false ), execName, iconName, window, asn );
869 }
870 
871 KRun::KRun( const KURL& url, mode_t mode, bool isLocalFile, bool showProgressInfo )
872  :m_timer(0,"KRun::timer")
873 {
874  init (url, 0, "", mode, isLocalFile, showProgressInfo);
875 }
876 
877 KRun::KRun( const KURL& url, TQWidget* window, mode_t mode, bool isLocalFile,
878  bool showProgressInfo )
879  :m_timer(0,"KRun::timer")
880 {
881  init (url, window, "", mode, isLocalFile, showProgressInfo);
882 }
883 
884 KRun::KRun( const KURL& url, TQWidget* window, const TQCString& asn, mode_t mode, bool isLocalFile,
885  bool showProgressInfo )
886  :m_timer(0,"KRun::timer")
887 {
888  init (url, window, asn, mode, isLocalFile, showProgressInfo);
889 }
890 
891 void KRun::init ( const KURL& url, TQWidget* window, const TQCString& asn, mode_t mode, bool isLocalFile,
892  bool showProgressInfo )
893 {
894  m_bFault = false;
895  m_bAutoDelete = true;
896  m_bProgressInfo = showProgressInfo;
897  m_bFinished = false;
898  m_job = 0L;
899  m_strURL = url;
900  m_bScanFile = false;
901  m_bIsDirectory = false;
902  m_bIsLocalFile = isLocalFile;
903  m_mode = mode;
904  d = new KRunPrivate;
905  d->m_runExecutables = true;
906  d->m_window = window;
907  d->m_asn = asn;
908  setEnableExternalBrowser(true);
909 
910  // Start the timer. This means we will return to the event
911  // loop and do initialization afterwards.
912  // Reason: We must complete the constructor before we do anything else.
913  m_bInit = true;
914  connect( &m_timer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( slotTimeout() ) );
915  m_timer.start( 0, true );
916  kdDebug(7010) << " new KRun " << this << " " << url.prettyURL() << " timer=" << &m_timer << endl;
917 
918  kapp->ref();
919 }
920 
921 void KRun::init()
922 {
923  kdDebug(7010) << "INIT called" << endl;
924 
925  bool bypassErrorMessage = false;
926 
927  if (m_strURL.url().startsWith("$(")) {
928  // check for environment variables and make necessary translations
929  TQString aValue = m_strURL.url();
930  int nDollarPos = aValue.find( '$' );
931 
932  while( nDollarPos != -1 && nDollarPos+1 < static_cast<int>(aValue.length())) {
933  // there is at least one $
934  if( (aValue)[nDollarPos+1] == '(' ) {
935  uint nEndPos = nDollarPos+1;
936  // the next character is no $
937  while ( (nEndPos <= aValue.length()) && (aValue[nEndPos]!=')') )
938  nEndPos++;
939  nEndPos++;
940  TQString cmd = aValue.mid( nDollarPos+2, nEndPos-nDollarPos-3 );
941 
942  TQString result;
943  FILE *fs = popen(TQFile::encodeName(cmd).data(), "r");
944  if (fs)
945  {
946  {
947  TQTextStream ts(fs, IO_ReadOnly);
948  result = ts.read().stripWhiteSpace();
949  }
950  pclose(fs);
951  }
952  aValue.replace( nDollarPos, nEndPos-nDollarPos, result );
953  } else if( (aValue)[nDollarPos+1] != '$' ) {
954  uint nEndPos = nDollarPos+1;
955  // the next character is no $
956  TQString aVarName;
957  if (aValue[nEndPos]=='{')
958  {
959  while ( (nEndPos <= aValue.length()) && (aValue[nEndPos]!='}') )
960  nEndPos++;
961  nEndPos++;
962  aVarName = aValue.mid( nDollarPos+2, nEndPos-nDollarPos-3 );
963  }
964  else
965  {
966  while ( nEndPos <= aValue.length() && (aValue[nEndPos].isNumber()
967  || aValue[nEndPos].isLetter() || aValue[nEndPos]=='_' ) )
968  nEndPos++;
969  aVarName = aValue.mid( nDollarPos+1, nEndPos-nDollarPos-1 );
970  }
971  const char* pEnv = 0;
972  if (!aVarName.isEmpty())
973  pEnv = getenv( aVarName.ascii() );
974  if( pEnv ) {
975  // !!! Sergey A. Sukiyazov <corwin@micom.don.ru> !!!
976  // A environment variables may contain values in 8bit
977  // locale cpecified encoding or in UTF8 encoding.
978  aValue.replace( nDollarPos, nEndPos-nDollarPos, KStringHandler::from8Bit( pEnv ) );
979  } else
980  aValue.remove( nDollarPos, nEndPos-nDollarPos );
981  } else {
982  // remove one of the dollar signs
983  aValue.remove( nDollarPos, 1 );
984  nDollarPos++;
985  }
986  nDollarPos = aValue.find( '$', nDollarPos );
987  }
988  m_strURL = KURL(aValue);
989  bypassErrorMessage = true;
990  }
991 
992  if ( !m_strURL.isValid() )
993  {
994  if (bypassErrorMessage == false) {
995  d->m_showingError = true;
996  KMessageBoxWrapper::error( d->m_window, i18n( "Malformed URL\n%1" ).arg( m_strURL.url() ) );
997  d->m_showingError = false;
998  }
999  m_bFault = true;
1000  m_bFinished = true;
1001  m_timer.start( 0, true );
1002  return;
1003  }
1004  if ( !kapp->authorizeURLAction( "open", KURL(), m_strURL))
1005  {
1006  TQString msg = TDEIO::buildErrorString(TDEIO::ERR_ACCESS_DENIED, m_strURL.prettyURL());
1007  d->m_showingError = true;
1008  KMessageBoxWrapper::error( d->m_window, msg );
1009  d->m_showingError = false;
1010  m_bFault = true;
1011  m_bFinished = true;
1012  m_timer.start( 0, true );
1013  return;
1014  }
1015 
1016  if ( !m_bIsLocalFile && m_strURL.isLocalFile() )
1017  m_bIsLocalFile = true;
1018 
1019  TQString exec;
1020  if (m_strURL.protocol().startsWith("http"))
1021  {
1022  exec = d->m_externalBrowser;
1023  }
1024 
1025  if ( m_bIsLocalFile )
1026  {
1027  if ( m_mode == 0 )
1028  {
1029  KDE_struct_stat buff;
1030  if ( KDE_stat( TQFile::encodeName(m_strURL.path()), &buff ) == -1 )
1031  {
1032  d->m_showingError = true;
1033  KMessageBoxWrapper::error( d->m_window, i18n( "<qt>Unable to run the command specified. The file or folder <b>%1</b> does not exist.</qt>" ).arg( m_strURL.htmlURL() ) );
1034  d->m_showingError = false;
1035  m_bFault = true;
1036  m_bFinished = true;
1037  m_timer.start( 0, true );
1038  return;
1039  }
1040  m_mode = buff.st_mode;
1041  }
1042 
1043  KMimeType::Ptr mime = KMimeType::findByURL( m_strURL, m_mode, m_bIsLocalFile );
1044  assert( mime != 0L );
1045  kdDebug(7010) << "MIME TYPE is " << mime->name() << endl;
1046  foundMimeType( mime->name() );
1047  return;
1048  }
1049  else if ( !exec.isEmpty() || KProtocolInfo::isHelperProtocol( m_strURL ) ) {
1050  kdDebug(7010) << "Helper protocol" << endl;
1051 
1052  bool ok = false;
1053  KURL::List urls;
1054  if (!((m_strURL.protocol().startsWith("http")) && (m_strURL.url() == "http://default.browser")))
1055  urls.append( m_strURL );
1056  if (exec.isEmpty())
1057  {
1058  exec = KProtocolInfo::exec( m_strURL.protocol() );
1059  if (exec.isEmpty())
1060  {
1061  foundMimeType(KProtocolInfo::defaultMimetype(m_strURL));
1062  return;
1063  }
1064  run( exec, urls );
1065  ok = true;
1066  }
1067  else if (exec.startsWith("!"))
1068  {
1069  exec = exec.mid(1); // Literal command
1070  exec += " %u";
1071  run( exec, urls );
1072  ok = true;
1073  }
1074  else
1075  {
1076  KService::Ptr service = KService::serviceByStorageId( exec );
1077  if (service)
1078  {
1079  run( *service, urls, d->m_window, d->m_asn );
1080  ok = true;
1081  }
1082  }
1083 
1084  if (ok)
1085  {
1086  m_bFinished = true;
1087  // will emit the error and autodelete this
1088  m_timer.start( 0, true );
1089  return;
1090  }
1091  }
1092 
1093  if ((m_strURL.protocol().startsWith("http")) && (m_strURL.url() == "http://default.browser")) {
1094  KURL::List urls;
1095  run( "kfmclient openProfile webbrowsing", urls );
1096  m_bFinished = true;
1097  // will emit the error and autodelete this
1098  m_timer.start( 0, true );
1099  return;
1100  }
1101 
1102  // Did we already get the information that it is a directory ?
1103  if ( S_ISDIR( m_mode ) )
1104  {
1105  foundMimeType( "inode/directory" );
1106  return;
1107  }
1108 
1109  // Let's see whether it is a directory
1110 
1111  if ( !KProtocolInfo::supportsListing( m_strURL ) )
1112  {
1113  //kdDebug(7010) << "Protocol has no support for listing" << endl;
1114  // No support for listing => it can't be a directory (example: http)
1115  scanFile();
1116  return;
1117  }
1118 
1119  kdDebug(7010) << "Testing directory (stating)" << endl;
1120 
1121  // It may be a directory or a file, let's stat
1122  TDEIO::StatJob *job = TDEIO::stat( m_strURL, true, 0 /* no details */, m_bProgressInfo );
1123  job->setWindow (d->m_window);
1124  connect( job, TQT_SIGNAL( result( TDEIO::Job * ) ),
1125  this, TQT_SLOT( slotStatResult( TDEIO::Job * ) ) );
1126  m_job = job;
1127  kdDebug(7010) << " Job " << job << " is about stating " << m_strURL.url() << endl;
1128 }
1129 
1130 KRun::~KRun()
1131 {
1132  kdDebug(7010) << "KRun::~KRun() " << this << endl;
1133  m_timer.stop();
1134  killJob();
1135  kapp->deref();
1136  kdDebug(7010) << "KRun::~KRun() done " << this << endl;
1137  delete d;
1138 }
1139 
1140 void KRun::scanFile()
1141 {
1142  kdDebug(7010) << "###### KRun::scanFile " << m_strURL.url() << endl;
1143  // First, let's check for well-known extensions
1144  // Not when there is a query in the URL, in any case.
1145  if ( m_strURL.query().isEmpty() )
1146  {
1147  KMimeType::Ptr mime = KMimeType::findByURL( m_strURL );
1148  assert( mime != 0L );
1149  if ( mime->name() != "application/octet-stream" || m_bIsLocalFile )
1150  {
1151  kdDebug(7010) << "Scanfile: MIME TYPE is " << mime->name() << endl;
1152  foundMimeType( mime->name() );
1153  return;
1154  }
1155  }
1156 
1157  // No mimetype found, and the URL is not local (or fast mode not allowed).
1158  // We need to apply the 'TDEIO' method, i.e. either asking the server or
1159  // getting some data out of the file, to know what mimetype it is.
1160 
1161  if ( !KProtocolInfo::supportsReading( m_strURL ) )
1162  {
1163  kdError(7010) << "#### NO SUPPORT FOR READING!" << endl;
1164  m_bFault = true;
1165  m_bFinished = true;
1166  m_timer.start( 0, true );
1167  return;
1168  }
1169  kdDebug(7010) << this << " Scanning file " << m_strURL.url() << endl;
1170 
1171  TDEIO::TransferJob *job = TDEIO::get( m_strURL, false /*reload*/, m_bProgressInfo );
1172  job->setWindow (d->m_window);
1173  connect(job, TQT_SIGNAL( result(TDEIO::Job *)),
1174  this, TQT_SLOT( slotScanFinished(TDEIO::Job *)));
1175  connect(job, TQT_SIGNAL( mimetype(TDEIO::Job *, const TQString &)),
1176  this, TQT_SLOT( slotScanMimeType(TDEIO::Job *, const TQString &)));
1177  m_job = job;
1178  kdDebug(7010) << " Job " << job << " is about getting from " << m_strURL.url() << endl;
1179 }
1180 
1181 void KRun::slotTimeout()
1182 {
1183  kdDebug(7010) << this << " slotTimeout called" << endl;
1184  if ( m_bInit )
1185  {
1186  m_bInit = false;
1187  init();
1188  return;
1189  }
1190 
1191  if ( m_bFault ) {
1192  emit error();
1193  }
1194  if ( m_bFinished ) {
1195  emit finished();
1196  }
1197  else
1198  {
1199  if ( m_bScanFile )
1200  {
1201  m_bScanFile = false;
1202  scanFile();
1203  return;
1204  }
1205  else if ( m_bIsDirectory )
1206  {
1207  m_bIsDirectory = false;
1208  foundMimeType( "inode/directory" );
1209  return;
1210  }
1211  }
1212 
1213  if ( m_bAutoDelete )
1214  {
1215  delete this;
1216  return;
1217  }
1218 }
1219 
1220 void KRun::slotStatResult( TDEIO::Job * job )
1221 {
1222  m_job = 0L;
1223  if (job->error())
1224  {
1225  d->m_showingError = true;
1226  kdError(7010) << this << " ERROR " << job->error() << " " << job->errorString() << endl;
1227  job->showErrorDialog();
1228  //kdDebug(7010) << this << " KRun returning from showErrorDialog, starting timer to delete us" << endl;
1229  d->m_showingError = false;
1230 
1231  m_bFault = true;
1232  m_bFinished = true;
1233 
1234  // will emit the error and autodelete this
1235  m_timer.start( 0, true );
1236 
1237  } else {
1238 
1239  kdDebug(7010) << "Finished" << endl;
1240  if(!dynamic_cast<TDEIO::StatJob*>(job))
1241  kdFatal() << "job is a " << typeid(*job).name() << " should be a StatJob" << endl;
1242 
1243  TQString knownMimeType;
1244  TDEIO::UDSEntry entry = ((TDEIO::StatJob*)job)->statResult();
1245  TDEIO::UDSEntry::ConstIterator it = entry.begin();
1246  for( ; it != entry.end(); it++ ) {
1247  switch( (*it).m_uds ) {
1248  case TDEIO::UDS_FILE_TYPE:
1249  if ( S_ISDIR( (mode_t)((*it).m_long) ) )
1250  m_bIsDirectory = true; // it's a dir
1251  else
1252  m_bScanFile = true; // it's a file
1253  break;
1254  case TDEIO::UDS_MIME_TYPE: // mimetype already known? (e.g. print:/manager)
1255  knownMimeType = (*it).m_str;
1256  break;
1257  case TDEIO::UDS_LOCAL_PATH:
1258  d->m_localPath = (*it).m_str;
1259  break;
1260  default:
1261  break;
1262  }
1263  }
1264  if ( !knownMimeType.isEmpty() )
1265  {
1266  foundMimeType( knownMimeType );
1267  m_bFinished = true;
1268  }
1269 
1270  // We should have found something
1271  assert ( m_bScanFile || m_bIsDirectory );
1272 
1273  // Start the timer. Once we get the timer event this
1274  // protocol server is back in the pool and we can reuse it.
1275  // This gives better performance than starting a new slave
1276  m_timer.start( 0, true );
1277  }
1278 }
1279 
1280 void KRun::slotScanMimeType( TDEIO::Job *, const TQString &mimetype )
1281 {
1282  if ( mimetype.isEmpty() )
1283  kdWarning(7010) << "KRun::slotScanFinished : MimetypeJob didn't find a mimetype! Probably a tdeioslave bug." << endl;
1284  foundMimeType( mimetype );
1285  m_job = 0;
1286 }
1287 
1288 void KRun::slotScanFinished( TDEIO::Job *job )
1289 {
1290  m_job = 0;
1291  if (job->error())
1292  {
1293  d->m_showingError = true;
1294  kdError(7010) << this << " ERROR (stat) : " << job->error() << " " << job->errorString() << endl;
1295  job->showErrorDialog();
1296  //kdDebug(7010) << this << " KRun returning from showErrorDialog, starting timer to delete us" << endl;
1297  d->m_showingError = false;
1298 
1299  m_bFault = true;
1300  m_bFinished = true;
1301 
1302  // will emit the error and autodelete this
1303  m_timer.start( 0, true );
1304  }
1305 }
1306 
1307 void KRun::foundMimeType( const TQString& type )
1308 {
1309  kdDebug(7010) << "Resulting mime type is " << type << endl;
1310 
1311 /*
1312  // Automatically unzip stuff
1313 
1314  // Disabled since the new TDEIO doesn't have filters yet.
1315 
1316  if ( type == "application/x-gzip" ||
1317  type == "application/x-bzip" ||
1318  type == "application/x-bzip2" )
1319  {
1320  KURL::List lst = KURL::split( m_strURL );
1321  if ( lst.isEmpty() )
1322  {
1323  TQString tmp = i18n( "Malformed URL" );
1324  tmp += "\n";
1325  tmp += m_strURL.url();
1326  KMessageBoxWrapper::error( 0L, tmp );
1327  return;
1328  }
1329 
1330  if ( type == "application/x-gzip" )
1331  lst.prepend( KURL( "gzip:/decompress" ) );
1332  else if ( type == "application/x-bzip" )
1333  lst.prepend( KURL( "bzip:/decompress" ) );
1334  else if ( type == "application/x-bzip2" )
1335  lst.prepend( KURL( "bzip2:/decompress" ) );
1336  else if ( type == "application/x-tar" )
1337  lst.prepend( KURL( "tar:/" ) );
1338 
1339  // Move the HTML style reference to the leftmost URL
1340  KURL::List::Iterator it = lst.begin();
1341  ++it;
1342  (*lst.begin()).setRef( (*it).ref() );
1343  (*it).setRef( TQString::null );
1344 
1345  // Create the new URL
1346  m_strURL = KURL::join( lst );
1347 
1348  kdDebug(7010) << "Now trying with " << debugString(m_strURL.url()) << endl;
1349 
1350  killJob();
1351 
1352  // We don't know if this is a file or a directory. Let's test this first.
1353  // (For instance a tar.gz is a directory contained inside a file)
1354  // It may be a directory or a file, let's stat
1355  TDEIO::StatJob *job = TDEIO::stat( m_strURL, m_bProgressInfo );
1356  connect( job, TQT_SIGNAL( result( TDEIO::Job * ) ),
1357  this, TQT_SLOT( slotStatResult( TDEIO::Job * ) ) );
1358  m_job = job;
1359 
1360  return;
1361  }
1362 */
1363  TDEIO::TransferJob *job = ::tqqt_cast<TDEIO::TransferJob *>( m_job );
1364  if ( job )
1365  {
1366  job->putOnHold();
1367  TDEIO::Scheduler::publishSlaveOnHold();
1368  m_job = 0;
1369  }
1370 
1371  Q_ASSERT( !m_bFinished );
1372 
1373  // Suport for preferred service setting, see setPreferredService
1374  if ( !d->m_preferredService.isEmpty() ) {
1375  kdDebug(7010) << "Attempting to open with preferred service: " << d->m_preferredService << endl;
1376  KService::Ptr serv = KService::serviceByDesktopName( d->m_preferredService );
1377  if ( serv && serv->hasServiceType( type ) )
1378  {
1379  KURL::List lst;
1380  lst.append( m_strURL );
1381  m_bFinished = KRun::run( *serv, lst, d->m_window, d->m_asn );
1386  }
1387  }
1388 
1389  // Resolve .desktop files from media:/, remote:/, applications:/ etc.
1390  if ( ((type == "application/x-desktop") ||
1391  (type == "media/builtin-mydocuments") ||
1392  (type == "media/builtin-mycomputer") ||
1393  (type == "media/builtin-mynetworkplaces") ||
1394  (type == "media/builtin-printers") ||
1395  (type == "media/builtin-trash") ||
1396  (type == "media/builtin-webbrowser")) /* or inheriting? */ && (!d->m_localPath.isEmpty()) )
1397  {
1398  m_strURL = KURL();
1399  m_strURL.setPath( d->m_localPath );
1400  }
1401 
1402  if (!m_bFinished && KRun::runURL( m_strURL, type, d->m_window, d->m_asn, false, d->m_runExecutables, d->m_suggestedFileName )){
1403  m_bFinished = true;
1404  }
1405  else{
1406  m_bFinished = true;
1407  m_bFault = true;
1408  }
1409 
1410  m_timer.start( 0, true );
1411 }
1412 
1413 void KRun::killJob()
1414 {
1415  if ( m_job )
1416  {
1417  kdDebug(7010) << "KRun::killJob run=" << this << " m_job=" << m_job << endl;
1418  m_job->kill();
1419  m_job = 0L;
1420  }
1421 }
1422 
1423 void KRun::abort()
1424 {
1425  kdDebug(7010) << "KRun::abort " << this << " m_showingError=" << d->m_showingError << endl;
1426  killJob();
1427  // If we're showing an error message box, the rest will be done
1428  // after closing the msgbox -> don't autodelete nor emit signals now.
1429  if ( d->m_showingError )
1430  return;
1431  m_bFault = true;
1432  m_bFinished = true;
1433  m_bInit = false;
1434  m_bScanFile = false;
1435 
1436  // will emit the error and autodelete this
1437  m_timer.start( 0, true );
1438 }
1439 
1440 void KRun::setEnableExternalBrowser(bool b)
1441 {
1442  if (b)
1443  d->m_externalBrowser = TDEConfigGroup(TDEGlobal::config(), "General").readEntry("BrowserApplication");
1444  else
1445  d->m_externalBrowser = TQString::null;
1446 }
1447 
1448 void KRun::setPreferredService( const TQString& desktopEntryName )
1449 {
1450  d->m_preferredService = desktopEntryName;
1451 }
1452 
1453 void KRun::setRunExecutables(bool b)
1454 {
1455  d->m_runExecutables = b;
1456 }
1457 
1458 void KRun::setSuggestedFileName( const TQString& fileName )
1459 {
1460  d->m_suggestedFileName = fileName;
1461 }
1462 
1463 bool KRun::isExecutable( const TQString& serviceType )
1464 {
1465  return ( serviceType == "application/x-desktop" ||
1466  serviceType == "media/builtin-mydocuments" ||
1467  serviceType == "media/builtin-mycomputer" ||
1468  serviceType == "media/builtin-mynetworkplaces" ||
1469  serviceType == "media/builtin-printers" ||
1470  serviceType == "media/builtin-trash" ||
1471  serviceType == "media/builtin-webbrowser" ||
1472  serviceType == "application/x-executable" ||
1473  serviceType == "application/x-msdos-program" ||
1474  serviceType == "application/x-shellscript" );
1475 }
1476 
1477 /****************/
1478 
1479 pid_t
1480 TDEProcessRunner::run(TDEProcess * p, const TQString & binName)
1481 {
1482  return (new TDEProcessRunner(p, binName))->pid();
1483 }
1484 
1485 #ifdef Q_WS_X11
1486 pid_t
1487 TDEProcessRunner::run(TDEProcess * p, const TQString & binName, const TDEStartupInfoId& id )
1488 {
1489  return (new TDEProcessRunner(p, binName, id))->pid();
1490 }
1491 #endif
1492 
1493 TDEProcessRunner::TDEProcessRunner(TDEProcess * p, const TQString & _binName )
1494  : TQObject(),
1495  process_(p),
1496  binName( _binName )
1497 {
1498  TQObject::connect(
1499  process_, TQT_SIGNAL(processExited(TDEProcess *)),
1500  this, TQT_SLOT(slotProcessExited(TDEProcess *)));
1501 
1502  process_->start();
1503  if ( !process_->pid() )
1504  slotProcessExited( process_ );
1505 }
1506 
1507 #ifdef Q_WS_X11
1508 TDEProcessRunner::TDEProcessRunner(TDEProcess * p, const TQString & _binName, const TDEStartupInfoId& id )
1509  : TQObject(),
1510  process_(p),
1511  binName( _binName ),
1512  id_( id )
1513 {
1514  TQObject::connect(
1515  process_, TQT_SIGNAL(processExited(TDEProcess *)),
1516  this, TQT_SLOT(slotProcessExited(TDEProcess *)));
1517 
1518  process_->start();
1519  if ( !process_->pid() )
1520  slotProcessExited( process_ );
1521 }
1522 #endif
1523 
1524 TDEProcessRunner::~TDEProcessRunner()
1525 {
1526  delete process_;
1527 }
1528 
1529  pid_t
1530 TDEProcessRunner::pid() const
1531 {
1532  return process_->pid();
1533 }
1534 
1535  void
1536 TDEProcessRunner::slotProcessExited(TDEProcess * p)
1537 {
1538  if (p != process_)
1539  return; // Eh ?
1540 
1541  kdDebug(7010) << "slotProcessExited " << binName << endl;
1542  kdDebug(7010) << "normalExit " << process_->normalExit() << endl;
1543  kdDebug(7010) << "exitStatus " << process_->exitStatus() << endl;
1544  bool showErr = process_->normalExit()
1545  && ( process_->exitStatus() == 127 || process_->exitStatus() == 1 );
1546  if ( !binName.isEmpty() && ( showErr || process_->pid() == 0 ) )
1547  {
1548  // Often we get 1 (zsh, csh) or 127 (ksh, bash) because the binary doesn't exist.
1549  // We can't just rely on that, but it's a good hint.
1550  // Before assuming its really so, we'll try to find the binName
1551  // relatively to current directory, and then in the PATH.
1552  if ( !TQFile( binName ).exists() && TDEStandardDirs::findExe( binName ).isEmpty() )
1553  {
1554  kapp->ref();
1555  KMessageBox::sorry( 0L, i18n("Could not find the program '%1'").arg( binName ) );
1556  kapp->deref();
1557  }
1558  }
1559 #ifdef Q_WS_X11
1560  if( !id_.none())
1561  {
1562  TDEStartupInfoData data;
1563  data.addPid( pid()); // announce this pid for the startup notification has finished
1564  data.setHostname();
1565  TDEStartupInfo::sendFinish( id_, data );
1566  }
1567 #endif
1568  deleteLater();
1569 }
1570 
1571 void KRun::virtual_hook( int, void* )
1572 { /*BASE::virtual_hook( id, data );*/ }
1573 
1574 #include "krun.moc"
TDEIO::UDS_LOCAL_PATH
A local file path if the ioslave display files sitting on the local filesystem (but in another hierar...
Definition: global.h:338
KRun::setEnableExternalBrowser
void setEnableExternalBrowser(bool b)
Sets whether the external webbrowser setting should be honoured.
Definition: krun.cpp:1440
TDEIO::UDSEntry
TQValueList< UDSAtom > UDSEntry
An entry is the list of atoms containing all the information for a file or URL.
Definition: global.h:507
TDEIO::NetAccess::mostLocalURL
static KURL mostLocalURL(const KURL &url, TQWidget *window)
Tries to map a local URL for the given URL.
Definition: netaccess.cpp:213
KRun::abort
void abort()
Abort this KRun.
Definition: krun.cpp:1423
KRun::runURL
static pid_t runURL(const KURL &_url, const TQString &_mimetype, bool tempFile, bool runExecutables)
Open the given URL.
Definition: krun.cpp:94
KService::terminalOptions
TQString terminalOptions() const
Returns any options associated with the terminal the service runs in, if it requires a terminal...
Definition: kservice.h:147
KService::desktopEntryName
TQString desktopEntryName() const
Returns the filename of the service desktop entry without any extension.
Definition: kservice.h:182
KService::serviceByStorageId
static Ptr serviceByStorageId(const TQString &_storageId)
Find a service by its storage-id or desktop-file path.
Definition: kservice.cpp:694
KRun::setSuggestedFileName
void setSuggestedFileName(const TQString &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:1458
KService::property
virtual TQVariant property(const TQString &_name) const
Returns the requested property.
Definition: kservice.cpp:528
KRun::setRunExecutables
void setRunExecutables(bool b)
Sets whether executables, .desktop files or shell scripts should be run by KRun.
Definition: krun.cpp:1453
KService
Represent a service, i.e.
Definition: kservice.h:48
TDEIO::Job::errorString
TQString errorString() const
Converts an error code and a non-i18n error message into an error message in the current language...
Definition: global.cpp:225
KRun::setPreferredService
void setPreferredService(const TQString &desktopEntryName)
Set the preferred service for opening this URL, after its mimetype will have been found by KRun...
Definition: krun.cpp:1448
KService::substituteUid
bool substituteUid() const
Checks whether the service runs with a different user id.
Definition: kservice.cpp:726
KMimeType::mimeType
static Ptr mimeType(const TQString &_name)
Retrieve a pointer to the mime type _name or a pointer to the default mime type "application/octet-st...
Definition: kmimetype.cpp:141
KProtocolInfo::supportsReading
static bool supportsReading(const KURL &url)
Returns whether the protocol can retrieve data from URLs.
Definition: kprotocolinfo.cpp:139
KService::username
TQString username() const
Returns the user name, if the service runs with a different user id.
Definition: kservice.cpp:740
KRun::run
static pid_t run(const KService &_service, const KURL::List &_urls, TQWidget *window, bool tempFiles=false)
Open a list of URLs with a certain service (application).
Definition: krun.cpp:752
TDEIO::Job
The base class for all jobs.
Definition: jobclasses.h:68
TDEIO::StatJob
A TDEIO job that retrieves information about a file or directory.
Definition: jobclasses.h:688
KRun::binaryName
static TQString binaryName(const TQString &execLine, bool removePath)
Given a full command line (e.g.
Definition: krun.cpp:541
KProtocolInfo::exec
static TQString exec(const TQString &protocol)
Returns the library / executable to open for the protocol protocol Example : "tdeio_ftp", meaning either the executable "tdeio_ftp" or the library "tdeio_ftp.la" (recommended), whichever is available.
KService::type
virtual TQString type() const
Returns the type of the service.
Definition: kservice.h:92
TDEIO::Job::setWindow
void setWindow(TQWidget *window)
Associate this job with a window given by window.
Definition: job.cpp:352
KRun::finished
void finished()
Emitted when the operation finished.
KRun::processDesktopExec
static TQStringList processDesktopExec(const KService &_service, const KURL::List &_urls, bool has_shell, bool tempFiles)
Processes a Exec= line as found in .desktop files.
Definition: krun.cpp:372
TDEIO::Job::kill
virtual void kill(bool quietly=true)
Abort this job.
Definition: job.cpp:239
TDEIO::Job::error
int error() const
Returns the error code, if there has been an error.
Definition: jobclasses.h:95
KProtocolInfo::supportsListing
static bool supportsListing(const KURL &url)
Returns whether the protocol can list files/objects.
Definition: kprotocolinfo.cpp:121
KService::path
TQString path() const
Returns the working directory to run the program in.
Definition: kservice.h:226
TDEIO::stat
TDEIO_EXPORT StatJob * stat(const KURL &url, bool showProgressInfo=true)
Find all details for one file or directory.
Definition: job.cpp:921
TDEIO::UDS_MIME_TYPE
A mime type; prevents guessing.
Definition: global.h:373
KRun::KRun
KRun(const KURL &url, mode_t mode=0, bool isLocalFile=false, bool showProgressInfo=true)
Create a KRun object to run the preferred application for a file/URL.
Definition: krun.cpp:871
TDEIO::get
TDEIO_EXPORT TransferJob * get(const KURL &url, bool reload=false, bool showProgressInfo=true)
Get (a.k.a.
Definition: job.cpp:1255
KMimeType::findByURL
static Ptr findByURL(const KURL &_url, mode_t _mode=0, bool _is_local_file=false, bool _fast_mode=false)
Finds a KMimeType with the given _url.
Definition: kmimetype.cpp:165
KProtocolInfo::protocolClass
static TQString protocolClass(const TQString &protocol)
Returns the protocol class for the specified protocol.
KService::exec
TQString exec() const
Returns the executable.
Definition: kservice.h:104
TDEIO::Scheduler::publishSlaveOnHold
static void publishSlaveOnHold()
Send the slave that was put on hold back to TDELauncher.
Definition: scheduler.h:182
KService::desktopEntryPath
TQString desktopEntryPath() const
Returns the path to the location where the service desktop entry is stored.
Definition: kservice.h:174
KService::allowMultipleFiles
bool allowMultipleFiles() const
Checks whether this service can handle several files as startup arguments.
Definition: kservice.cpp:824
KService::terminal
bool terminal() const
Checks whethe the service should be run in a terminal.
Definition: kservice.h:138
KRun::isExecutable
static bool isExecutable(const TQString &serviceType)
Returns whether serviceType refers to an executable program instead of a data file.
Definition: krun.cpp:1463
KRun::isExecutableFile
static bool isExecutableFile(const KURL &url, const TQString &mimetype)
Returns wether the url of mimetype is executable.
Definition: krun.cpp:99
TDEIO::Job::showErrorDialog
void showErrorDialog(TQWidget *parent=0L)
Display a dialog box to inform the user of the error given by this job.
Definition: job.cpp:294
TDEIO::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: global.h:366
KDEDesktopMimeType::run
static pid_t run(const KURL &_url, bool _is_local)
Invokes the default action for the desktop entry.
Definition: kmimetype.cpp:786
KService::name
virtual TQString name() const
Returns the name of the service.
Definition: kservice.h:98
KService::serviceByDesktopName
static Ptr serviceByDesktopName(const TQString &_name)
Find a service by the name of its desktop file, not depending on its actual location (as long as it&#39;s...
Definition: kservice.cpp:680
KRun::error
void error()
Emitted when the operation had an error.
KRun::m_bScanFile
bool m_bScanFile
Used to indicate that the next action is to scan the file.
Definition: krun.h:434
KRun::runCommand
static pid_t runCommand(TQString cmd)
Run the given shell command and notifies kicker of the starting of the application.
Definition: krun.cpp:845
KProtocolInfo::isHelperProtocol
static bool isHelperProtocol(const KURL &url)
Returns whether the protocol can act as a helper protocol.
Definition: kprotocolinfo.cpp:94
KServiceTypeProfile::preferredService
static KService::Ptr preferredService(const TQString &serviceType, const TQString &genericServiceType)
Returns the preferred service for _serviceType and _genericServiceType ("Application", type of component, or null).
Definition: kuserprofile.cpp:303
TDEIO::buildErrorString
TDEIO_EXPORT TQString buildErrorString(int errorCode, const TQString &errorText)
Returns a translated error message for errorCode using the additional error information provided by e...
Definition: global.cpp:230
KRun::~KRun
virtual ~KRun()
Destructor.
Definition: krun.cpp:1130
TDEIO::TransferJob
The transfer job pumps data into and/or out of a Slave.
Definition: jobclasses.h:875
KRun::displayOpenWithDialog
static bool displayOpenWithDialog(const KURL::List &lst, bool tempFiles)
Display the Open-With dialog for those URLs, and run the chosen application.
Definition: krun.cpp:207
KRun::foundMimeType
virtual void foundMimeType(const TQString &_type)
Called if the mimetype has been detected.
Definition: krun.cpp:1307
KRun::shellQuote
static void shellQuote(TQString &_str)
Quotes a string for the shell.
Definition: krun.cpp:234
KProtocolInfo::defaultMimetype
static TQString defaultMimetype(const KURL &url)
Returns default mimetype for this URL based on the protocol.
Definition: kprotocolinfo.cpp:249
KRun::m_bInit
bool m_bInit
USed to indicate that the next action is to initialize.
Definition: krun.h:441
TDEIO::SimpleJob::putOnHold
virtual void putOnHold()
Abort job.
Definition: job.cpp:464
KService::icon
TQString icon() const
Returns the name of the icon.
Definition: kservice.h:125

tdeio/tdeio

Skip menu "tdeio/tdeio"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

tdeio/tdeio

Skip menu "tdeio/tdeio"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdeio/tdeio by doxygen 1.8.11
This website is maintained by Timothy Pearson.