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

tdeio/tdeio

Skip menu "tdeio/tdeio"
  • Main Page
  • 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.9.8
This website is maintained by Timothy Pearson.