00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
#include <assert.h>
00021
#include <stdlib.h>
00022
#include <string.h>
00023
#include <unistd.h>
00024
00025
#include "krun.h"
00026
#include "kuserprofile.h"
00027
#include "kmimetype.h"
00028
#include "kmimemagic.h"
00029
#include "kio/job.h"
00030
#include "kio/global.h"
00031
#include "kio/scheduler.h"
00032
#include "kfile/kopenwith.h"
00033
#include "kfile/krecentdocument.h"
00034
00035
#include <kdatastream.h>
00036
#include <kmessageboxwrapper.h>
00037
#include <kurl.h>
00038
#include <kapplication.h>
00039
#include <kdebug.h>
00040
#include <klocale.h>
00041
#include <kprotocolinfo.h>
00042
#include <kstandarddirs.h>
00043
#include <kprocess.h>
00044
#include <dcopclient.h>
00045
#include <qfile.h>
00046
#include <qtextstream.h>
00047
#include <qdatetime.h>
00048
#include <qregexp.h>
00049
#include <kwin.h>
00050
#include <kdesktopfile.h>
00051
#include <kstartupinfo.h>
00052
#include <kmacroexpander.h>
00053
#include <kshell.h>
00054
#include <typeinfo>
00055
#include <qwidget.h>
00056
#include <qguardedptr.h>
00057
00058
#ifdef Q_WS_X11
00059
#include <X11/Xlib.h>
00060
#include <fixx11h.h>
00061
extern Time qt_x_user_time;
00062
#endif
00063
00064
class KRun::KRunPrivate
00065 {
00066
public:
00067 KRunPrivate() { m_showingError =
false; }
00068
00069
bool m_showingError;
00070
bool m_runExecutables;
00071
00072
QString m_preferredService;
00073 QGuardedPtr <QWidget> m_window;
00074 };
00075
00076 pid_t
KRun::runURL(
const KURL& u,
const QString& _mimetype )
00077 {
00078
return runURL( u, _mimetype,
false,
true );
00079 }
00080
00081 pid_t
KRun::runURL(
const KURL& u,
const QString& _mimetype,
bool tempFile )
00082 {
00083
return runURL( u, _mimetype, tempFile,
true );
00084 }
00085
00086
00087 pid_t
KRun::runURL(
const KURL& u,
const QString& _mimetype,
bool tempFile,
bool runExecutables )
00088 {
00089
bool noRun =
false;
00090
bool noAuth =
false;
00091
if ( _mimetype ==
"inode/directory-locked" )
00092 {
00093 KMessageBoxWrapper::error( 0L,
00094 i18n(
"<qt>Unable to enter <b>%1</b>.\nYou do not have access rights to this location.</qt>").arg(u.
htmlURL()) );
00095
return 0;
00096 }
00097
else if ( _mimetype ==
"application/x-desktop" )
00098 {
00099
if ( u.
isLocalFile() && runExecutables)
00100
return KDEDesktopMimeType::run( u,
true );
00101 }
00102
else if ( _mimetype ==
"application/x-executable" ||
00103 _mimetype ==
"application/x-shellscript")
00104 {
00105
if ( u.
isLocalFile() && runExecutables)
00106 {
00107
if (kapp->authorize(
"shell_access"))
00108 {
00109
QString path = u.
path();
00110
shellQuote( path );
00111
return (
KRun::runCommand(path));
00112
00113 }
00114
else
00115 {
00116 noAuth =
true;
00117 }
00118 }
00119
else if (_mimetype ==
"application/x-executable")
00120 noRun =
true;
00121 }
00122
else if (
isExecutable(_mimetype) )
00123 {
00124
if (!runExecutables)
00125 noRun =
true;
00126
00127
if (!kapp->authorize(
"shell_access"))
00128 noAuth =
true;
00129 }
00130
00131
if ( noRun )
00132 {
00133 KMessageBox::sorry( 0L,
00134 i18n(
"<qt>The file <b>%1</b> is an executable program. "
00135
"For safety it will not be started.</qt>").arg(u.
htmlURL()));
00136
return 0;
00137 }
00138
if ( noAuth )
00139 {
00140 KMessageBoxWrapper::error( 0L,
00141 i18n(
"<qt>You do not have permission to run <b>%1</b>.</qt>").arg(u.
htmlURL()) );
00142
return 0;
00143 }
00144
00145
KURL::List lst;
00146 lst.append( u );
00147
00148
static const QString& app_str = KGlobal::staticQString(
"Application");
00149
00150
KService::Ptr offer = KServiceTypeProfile::preferredService( _mimetype, app_str );
00151
00152
if ( !offer )
00153 {
00154
00155
00156
00157
return displayOpenWithDialog( lst, tempFile );
00158 }
00159
00160
return KRun::run( *offer, lst, tempFile );
00161 }
00162
00163
bool KRun::displayOpenWithDialog(
const KURL::List& lst )
00164 {
00165
return displayOpenWithDialog( lst,
false );
00166 }
00167
00168 bool KRun::displayOpenWithDialog(
const KURL::List& lst,
bool tempFiles )
00169 {
00170
if (kapp && !kapp->authorizeKAction(
"openwith"))
00171 {
00172
00173 KMessageBox::sorry(0L, i18n(
"You are not authorized to execute this file."));
00174
return false;
00175 }
00176
00177
KOpenWithDlg l( lst, i18n(
"Open with:"), QString::null, 0L );
00178
if ( l.exec() )
00179 {
00180
KService::Ptr service = l.
service();
00181
if ( !!service )
00182
return KRun::run( *service, lst, tempFiles );
00183
00184
kdDebug(250) <<
"No service set, running " << l.
text() <<
endl;
00185
return KRun::run( l.
text(), lst );
00186 }
00187
return false;
00188 }
00189
00190 void KRun::shellQuote(
QString &_str )
00191 {
00192
00193
if (_str.isEmpty())
00194
return;
00195
QChar q(
'\'');
00196 _str.replace(q,
"'\\''").prepend(q).append(q);
00197 }
00198
00199
00200
class KRunMX1 :
public KMacroExpanderBase {
00201
public:
00202 KRunMX1(
const KService &_service ) :
00203
KMacroExpanderBase( '%' ), hasUrls( false ), hasSpec( false ), service( _service ) {}
00204
bool hasUrls:1, hasSpec:1;
00205
00206
protected:
00207
virtual int expandEscapedMacro(
const QString &str, uint pos,
QStringList &ret );
00208
00209
private:
00210
const KService &service;
00211 };
00212
00213
int
00214 KRunMX1::expandEscapedMacro(
const QString &str, uint pos,
QStringList &ret )
00215 {
00216 uint option = str[pos + 1];
00217
switch( option ) {
00218
case 'c':
00219 ret << service.name().replace(
'%',
"%%" );
00220
break;
00221
case 'k':
00222 ret << service.desktopEntryPath().replace(
'%',
"%%" );
00223
break;
00224
case 'i':
00225 ret <<
"-icon" << service.icon().replace(
'%',
"%%" );
00226
break;
00227
case 'm':
00228 ret <<
"-miniicon" << service.icon().replace(
'%',
"%%" );
00229
break;
00230
case 'u':
00231
case 'U':
00232 hasUrls =
true;
00233
00234
case 'f':
00235
case 'F':
00236
case 'n':
00237
case 'N':
00238
case 'd':
00239
case 'D':
00240
case 'v':
00241 hasSpec =
true;
00242
00243
default:
00244
return -2;
00245 }
00246
return 2;
00247 }
00248
00249
class KRunMX2 :
public KMacroExpanderBase {
00250
public:
00251 KRunMX2(
const KURL::List &_urls ) :
00252
KMacroExpanderBase( '%' ), ignFile( false ), urls( _urls ) {}
00253
bool ignFile:1;
00254
00255
protected:
00256
virtual int expandEscapedMacro(
const QString &str, uint pos,
QStringList &ret );
00257
00258
private:
00259
void subst(
int option,
const KURL &url,
QStringList &ret );
00260
00261
const KURL::List &urls;
00262 };
00263
00264
void
00265 KRunMX2::subst(
int option,
const KURL &url,
QStringList &ret )
00266 {
00267
switch( option ) {
00268
case 'u':
00269 ret << (url.
isLocalFile() ? url.
path() : url.url());
00270
break;
00271
case 'd':
00272 ret << url.
directory();
00273
break;
00274
case 'f':
00275 ret << url.
path();
00276
break;
00277
case 'n':
00278 ret << url.
fileName();
00279
break;
00280
case 'v':
00281
if (url.
isLocalFile() && QFile::exists( url.
path() ) )
00282 ret <<
KDesktopFile( url.
path(),
true ).readEntry(
"Dev" );
00283
break;
00284 }
00285
return;
00286 }
00287
00288
int
00289 KRunMX2::expandEscapedMacro(
const QString &str, uint pos,
QStringList &ret )
00290 {
00291 uint option = str[pos + 1];
00292
switch( option ) {
00293
case 'f':
00294
case 'u':
00295
case 'n':
00296
case 'd':
00297
case 'v':
00298
if( urls.isEmpty() ) {
00299
if (!ignFile)
00300
kdWarning() <<
"KRun::processDesktopExec: No URLs supplied to single-URL service " << str <<
endl;
00301 }
else if( urls.count() > 1 )
00302
kdWarning() <<
"KRun::processDesktopExec: " << urls.count() <<
" URLs supplied to single-URL service " << str <<
endl;
00303
else
00304 subst( option, urls.first(), ret );
00305
break;
00306
case 'F':
00307
case 'U':
00308
case 'N':
00309
case 'D':
00310 option +=
'a' -
'A';
00311
for( KURL::List::ConstIterator it = urls.begin(); it != urls.end(); ++it )
00312 subst( option, *it, ret );
00313
break;
00314
case '%':
00315 ret =
"%";
00316
break;
00317
default:
00318
return -2;
00319 }
00320
return 2;
00321 }
00322
00323
00324
QStringList KRun::processDesktopExec(
const KService &_service,
const KURL::List& _urls,
bool has_shell) {
00325
return processDesktopExec( _service, _urls, has_shell,
false );
00326 }
00327
00328 QStringList KRun::processDesktopExec(
const KService &_service,
const KURL::List& _urls,
bool has_shell ,
bool tempFiles)
00329 {
00330
QString exec = _service.
exec();
00331
QStringList result;
00332
00333 KRunMX1 mx1( _service );
00334 KRunMX2 mx2( _urls );
00335
00337
QRegExp re(
"^\\s*(?:/bin/)?sh\\s+-c\\s+(.*)$");
00338
if (!re.search( exec )) {
00339 exec = re.cap( 1 ).stripWhiteSpace();
00340
for (uint pos = 0; pos < exec.length(); ) {
00341
QChar c = exec.unicode()[pos];
00342
if (c !=
'\'' && c !=
'"')
00343
goto synerr;
00344
int pos2 = exec.find( c, pos + 1 ) - 1;
00345
if (pos2 < 0)
00346
goto synerr;
00347 memcpy( (
void *)(exec.unicode() + pos), exec.unicode() + pos + 1, (pos2 - pos) *
sizeof(
QChar));
00348 pos = pos2;
00349 exec.remove( pos, 2 );
00350 }
00351 }
00352
00353
if( !mx1.expandMacrosShellQuote( exec ) )
00354
goto synerr;
00355
00356
00357
00358
00359
if( tempFiles ) {
00360 result <<
"kioexec" <<
"--tempfiles" << exec;
00361 result += _urls.
toStringList();
00362
if (has_shell)
00363 result =
KShell::joinArgs( result );
00364
return result;
00365 }
00366
00367
00368
if( !mx1.hasUrls ) {
00369
for( KURL::List::ConstIterator it = _urls.begin(); it != _urls.end(); ++it )
00370
if ( !(*it).isLocalFile() ) {
00371
00372 result <<
"kioexec" << exec;
00373 result += _urls.
toStringList();
00374
if (has_shell)
00375 result =
KShell::joinArgs( result );
00376
return result;
00377 }
00378 }
00379
00380
00381
00382
00383
if( !mx1.hasSpec ) {
00384 exec +=
" %f";
00385 mx2.ignFile =
true;
00386 }
00387
00388 mx2.expandMacrosShellQuote( exec );
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
if (_service.
terminal()) {
00418
KConfigGroupSaver gs(KGlobal::config(),
"General");
00419
QString terminal =
KGlobal::config()->
readPathEntry(
"TerminalApplication");
00420
if( terminal.isEmpty() )
00421 {
00422
if( !KStandardDirs::findExe(
"konsole" ).isEmpty() )
00423 terminal =
"konsole";
00424
else
00425 terminal =
"xvt";
00426 }
00427
if (terminal ==
"konsole")
00428 terminal +=
" -caption=%c %i %m";
00429 terminal +=
" ";
00430 terminal += _service.
terminalOptions();
00431
if( !mx1.expandMacrosShellQuote( terminal ) ) {
00432
kdWarning() <<
"KRun: syntax error in command `" << terminal <<
"', service `" << _service.
name() <<
"'" <<
endl;
00433
return QStringList();
00434 }
00435 mx2.expandMacrosShellQuote( terminal );
00436
if (has_shell)
00437 result << terminal;
00438
else
00439 result =
KShell::splitArgs( terminal );
00440 result <<
"-e";
00441 }
00442
00443
int err;
00444
if (_service.
substituteUid()) {
00445
if (_service.
terminal())
00446 result <<
"su";
00447
else
00448 result <<
"kdesu" <<
"-u";
00449 result << _service.
username() <<
"-c";
00450
KShell::splitArgs(exec, KShell::AbortOnMeta, &err);
00451
if (err == KShell::FoundMeta) {
00452
shellQuote( exec );
00453 exec.prepend(
"/bin/sh -c " );
00454 }
else if (err != KShell::NoError)
00455
goto synerr;
00456
if (has_shell)
00457
shellQuote( exec );
00458 result << exec;
00459 }
else {
00460
if (has_shell) {
00461
if (_service.
terminal()) {
00462
KShell::splitArgs(exec, KShell::AbortOnMeta, &err);
00463
if (err == KShell::FoundMeta) {
00464
shellQuote( exec );
00465 exec.prepend(
"/bin/sh -c " );
00466 }
else if (err != KShell::NoError)
00467
goto synerr;
00468 }
00469 result << exec;
00470 }
else {
00471 result +=
KShell::splitArgs(exec, KShell::AbortOnMeta, &err);
00472
if (err == KShell::FoundMeta)
00473 result <<
"/bin/sh" <<
"-c" << exec;
00474
else if (err != KShell::NoError)
00475
goto synerr;
00476 }
00477 }
00478
00479
return result;
00480
00481 synerr:
00482
kdWarning() <<
"KRun: syntax error in command `" << _service.
exec() <<
"', service `" << _service.
name() <<
"'" <<
endl;
00483
return QStringList();
00484 }
00485
00486
00487 QString KRun::binaryName(
const QString & execLine,
bool removePath )
00488 {
00489
00490
QStringList args =
KShell::splitArgs( execLine );
00491
for (QStringList::ConstIterator it = args.begin(); it != args.end(); ++it)
00492
if (!(*it).contains(
'='))
00493
00494
return removePath ? (*it).mid((*it).findRev(
'/') + 1) : *it;
00495
return QString::null;
00496 }
00497
00498
static pid_t runCommandInternal(
KProcess* proc,
const KService* service,
const QString& binName,
00499
const QString &execName,
const QString & iconName )
00500 {
00501
if ( service && !KDesktopFile::isAuthorizedDesktopFile( service->
desktopEntryPath() ))
00502 {
00503 KMessageBox::sorry(0, i18n(
"You are not authorized to execute this file."));
00504
return 0;
00505 }
00506
QString bin =
KRun::binaryName( binName,
true );
00507
#ifdef Q_WS_X11 // Startup notification doesn't work with QT/E, service isn't needed without Startup notification
00508
bool startup_notify =
false;
00509
QCString wmclass;
00510
KStartupInfoId id;
00511
if( service && service->
property(
"StartupNotify" ).isValid())
00512 {
00513 startup_notify = service->
property(
"StartupNotify" ).toBool();
00514 wmclass = service->
property(
"StartupWMClass" ).toString().latin1();
00515 }
00516
else if( service && service->
property(
"X-KDE-StartupNotify" ).isValid())
00517 {
00518 startup_notify = service->
property(
"X-KDE-StartupNotify" ).toBool();
00519 wmclass = service->
property(
"X-KDE-WMClass" ).toString().latin1();
00520 }
00521
else
00522 {
00523
if( service && service->
type() ==
"Application" )
00524 {
00525 startup_notify =
true;
00526 wmclass =
"0";
00527 }
00528 }
00529
if( startup_notify )
00530 {
00531
id.initId();
00532
id.setupStartupEnv();
00533
KStartupInfoData data;
00534 data.
setHostname();
00535 data.
setBin( bin );
00536 data.
setName( execName.isEmpty() ? service->
name() : execName );
00537 data.
setDescription( i18n(
"Launching %1" ).arg( data.
name()));
00538 data.
setIcon( iconName.isEmpty() ? service->
icon() : iconName );
00539
#ifdef Q_WS_X11
00540
data.
setTimestamp( qt_x_user_time );
00541
#endif
00542
if( !wmclass.isEmpty())
00543 data.
setWMClass( wmclass );
00544 data.
setDesktop( KWin::currentDesktop());
00545
KStartupInfo::sendStartup(
id, data );
00546 }
00547 pid_t pid = KProcessRunner::run( proc, binName,
id );
00548
if( startup_notify && pid )
00549 {
00550
KStartupInfoData data;
00551 data.
addPid( pid );
00552
KStartupInfo::sendChange(
id, data );
00553
KStartupInfo::resetStartupEnv();
00554 }
00555
return pid;
00556
#else
00557
Q_UNUSED( execName );
00558 Q_UNUSED( iconName );
00559
return KProcessRunner::run( proc, bin );
00560
#endif
00561
}
00562
00563
static pid_t runTempService(
const KService& _service,
const KURL::List& _urls,
bool tempFiles )
00564 {
00565
if (!_urls.isEmpty()) {
00566
kdDebug(7010) <<
"runTempService: first url " << _urls.first().url() <<
endl;
00567 }
00568
00569
QStringList args;
00570
if ((_urls.count() > 1) && !_service.
allowMultipleFiles())
00571 {
00572
00573
00574
00575
00576
00577 KURL::List::ConstIterator it = _urls.begin();
00578
while(++it != _urls.end())
00579 {
00580
KURL::List singleUrl;
00581 singleUrl.append(*it);
00582 runTempService( _service, singleUrl, tempFiles );
00583 }
00584
KURL::List singleUrl;
00585 singleUrl.append(_urls.first());
00586 args =
KRun::processDesktopExec(_service, singleUrl,
false, tempFiles);
00587 }
00588
else
00589 {
00590 args =
KRun::processDesktopExec(_service, _urls,
false, tempFiles);
00591 }
00592
kdDebug(7010) <<
"runTempService: KProcess args=" << args <<
endl;
00593
00594
KProcess * proc =
new KProcess;
00595 *proc << args;
00596
00597
if (!_service.
path().isEmpty())
00598 proc->
setWorkingDirectory(_service.
path());
00599
00600
return runCommandInternal( proc, &_service, _service.
exec(), _service.
name(), _service.
icon() );
00601 }
00602
00603
00604 pid_t
KRun::run(
const KService& _service,
const KURL::List& _urls )
00605 {
00606
return run( _service, _urls,
false );
00607 }
00608
00609 pid_t
KRun::run(
const KService& _service,
const KURL::List& _urls,
bool tempFiles )
00610 {
00611
if (!_service.
desktopEntryPath().isEmpty() &&
00612 !KDesktopFile::isAuthorizedDesktopFile( _service.
desktopEntryPath()))
00613 {
00614 KMessageBox::sorry(0, i18n(
"You are not authorized to execute this service."));
00615
return 0;
00616 }
00617
00618
if ( !tempFiles )
00619 {
00620
00621 KURL::List::ConstIterator it = _urls.begin();
00622
for(; it != _urls.end(); ++it) {
00623
00624 KRecentDocument::add( *it, _service.
desktopEntryName() );
00625 }
00626 }
00627
00628
if ( tempFiles || _service.
desktopEntryPath().isEmpty())
00629 {
00630
return runTempService(_service, _urls, tempFiles);
00631 }
00632
00633
kdDebug(7010) <<
"KRun::run " << _service.
desktopEntryPath() <<
endl;
00634
00635
if (!_urls.isEmpty()) {
00636
kdDebug(7010) <<
"First url " << _urls.first().url() <<
endl;
00637 }
00638
00639
QString error;
00640
int pid = 0;
00641
00642
int i = KApplication::startServiceByDesktopPath(
00643 _service.
desktopEntryPath(), _urls.
toStringList(), &error, 0L, &pid
00644 );
00645
00646
if (i != 0)
00647 {
00648
kdDebug(7010) << error <<
endl;
00649 KMessageBox::sorry( 0L, error );
00650
return 0;
00651 }
00652
00653
kdDebug(7010) <<
"startServiceByDesktopPath worked fine" <<
endl;
00654
return (pid_t) pid;
00655 }
00656
00657
00658 pid_t
KRun::run(
const QString& _exec,
const KURL::List& _urls,
const QString& _name,
00659
const QString& _icon,
const QString&,
const QString&)
00660 {
00661
KService::Ptr service =
new KService(_name, _exec, _icon);
00662
00663
return run(*service, _urls);
00664 }
00665
00666 pid_t
KRun::runCommand(
QString cmd )
00667 {
00668
return KRun::runCommand( cmd, QString::null, QString::null );
00669 }
00670
00671 pid_t
KRun::runCommand(
const QString& cmd,
const QString &execName,
const QString & iconName )
00672 {
00673
kdDebug(7010) <<
"runCommand " << cmd <<
"," << execName <<
endl;
00674
KProcess * proc =
new KProcess;
00675 proc->
setUseShell(
true);
00676 *proc << cmd;
00677
KService::Ptr service = KService::serviceByDesktopName(
binaryName( cmd,
true ));
00678
return runCommandInternal( proc, service.
data(),
binaryName( cmd,
false ), execName, iconName );
00679 }
00680
00681 KRun::KRun(
const KURL& url, mode_t mode,
bool isLocalFile,
bool showProgressInfo )
00682 :m_timer(0,"
KRun::timer")
00683 {
00684 init (url, 0, mode, isLocalFile, showProgressInfo);
00685 }
00686
00687 KRun::KRun(
const KURL& url,
QWidget* window, mode_t mode,
bool isLocalFile,
00688
bool showProgressInfo )
00689 :m_timer(0,"
KRun::timer")
00690 {
00691 init (url, window, mode, isLocalFile, showProgressInfo);
00692 }
00693
00694
void KRun::init (
const KURL& url,
QWidget* window, mode_t mode,
bool isLocalFile,
00695
bool showProgressInfo )
00696 {
00697 m_bFault =
false;
00698 m_bAutoDelete =
true;
00699 m_bProgressInfo = showProgressInfo;
00700 m_bFinished =
false;
00701 m_job = 0L;
00702 m_strURL = url;
00703 m_bScanFile =
false;
00704 m_bIsDirectory =
false;
00705 m_bIsLocalFile = isLocalFile;
00706 m_mode = mode;
00707 d =
new KRunPrivate;
00708 d->m_runExecutables =
true;
00709 d->m_window = window;
00710
00711
00712
00713
00714 m_bInit =
true;
00715 connect( &m_timer, SIGNAL( timeout() ),
this, SLOT( slotTimeout() ) );
00716 m_timer.start( 0,
true );
00717
kdDebug(7010) <<
" new KRun " <<
this <<
" " << url.prettyURL() <<
" timer=" << &m_timer <<
endl;
00718
00719 kapp->ref();
00720 }
00721
00722
void KRun::init()
00723 {
00724
kdDebug(7010) <<
"INIT called" <<
endl;
00725
if ( !m_strURL.
isValid() )
00726 {
00727 d->m_showingError =
true;
00728
KMessageBoxWrapper::error( d->m_window, i18n(
"Malformed URL\n%1" ).arg( m_strURL.
url() ) );
00729 d->m_showingError =
false;
00730 m_bFault =
true;
00731 m_bFinished =
true;
00732 m_timer.start( 0,
true );
00733
return;
00734 }
00735
if ( !kapp->authorizeURLAction(
"open",
KURL(), m_strURL))
00736 {
00737
QString msg =
KIO::buildErrorString(KIO::ERR_ACCESS_DENIED, m_strURL.
prettyURL());
00738 d->m_showingError =
true;
00739
KMessageBoxWrapper::error( d->m_window, msg );
00740 d->m_showingError =
false;
00741 m_bFault =
true;
00742 m_bFinished =
true;
00743 m_timer.start( 0,
true );
00744
return;
00745 }
00746
00747
if ( !m_bIsLocalFile && m_strURL.
isLocalFile() )
00748
00749 m_bIsLocalFile =
true;
00750
00751
if ( m_bIsLocalFile )
00752 {
00753
if ( m_mode == 0 )
00754 {
00755
struct stat buff;
00756
if (
stat( QFile::encodeName(m_strURL.
path()), &buff ) == -1 )
00757 {
00758 d->m_showingError =
true;
00759
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() ) );
00760 d->m_showingError =
false;
00761 m_bFault =
true;
00762 m_bFinished =
true;
00763 m_timer.start( 0,
true );
00764
return;
00765 }
00766 m_mode = buff.st_mode;
00767 }
00768
00769 KMimeType::Ptr mime =
KMimeType::findByURL( m_strURL, m_mode, m_bIsLocalFile );
00770 assert( mime != 0L );
00771
kdDebug(7010) <<
"MIME TYPE is " << mime->name() <<
endl;
00772
foundMimeType( mime->name() );
00773
return;
00774 }
00775
else if (
KProtocolInfo::isHelperProtocol( m_strURL ) ) {
00776
kdDebug(7010) <<
"Helper protocol" <<
endl;
00777
00778
KURL::List urls;
00779 urls.append( m_strURL );
00780
QString exec =
KProtocolInfo::exec( m_strURL.
protocol() );
00781
run( exec, urls );
00782
00783 m_bFinished =
true;
00784
00785 m_timer.start( 0,
true );
00786
return;
00787 }
00788
00789
00790
if ( S_ISDIR( m_mode ) )
00791 {
00792
foundMimeType(
"inode/directory" );
00793
return;
00794 }
00795
00796
00797
00798
if ( !
KProtocolInfo::supportsListing( m_strURL ) )
00799 {
00800
00801
00802 scanFile();
00803
return;
00804 }
00805
00806
kdDebug(7010) <<
"Testing directory (stating)" <<
endl;
00807
00808
00809
KIO::StatJob *job =
KIO::stat( m_strURL,
true, 0 , m_bProgressInfo );
00810 job->
setWindow (d->m_window);
00811 connect( job, SIGNAL( result(
KIO::Job * ) ),
00812
this, SLOT( slotStatResult(
KIO::Job * ) ) );
00813 m_job = job;
00814
kdDebug(7010) <<
" Job " << job <<
" is about stating " << m_strURL.
url() <<
endl;
00815 }
00816
00817 KRun::~KRun()
00818 {
00819
kdDebug(7010) <<
"KRun::~KRun() " <<
this <<
endl;
00820 m_timer.stop();
00821 killJob();
00822 kapp->deref();
00823
kdDebug(7010) <<
"KRun::~KRun() done " <<
this <<
endl;
00824
delete d;
00825 }
00826
00827
void KRun::scanFile()
00828 {
00829
kdDebug(7010) <<
"###### KRun::scanFile " << m_strURL.
url() <<
endl;
00830
00831
00832
if ( m_strURL.
query().isEmpty() )
00833 {
00834 KMimeType::Ptr mime = KMimeType::findByURL( m_strURL );
00835 assert( mime != 0L );
00836
if ( mime->name() !=
"application/octet-stream" || m_bIsLocalFile )
00837 {
00838
kdDebug(7010) <<
"Scanfile: MIME TYPE is " << mime->name() <<
endl;
00839 foundMimeType( mime->name() );
00840
return;
00841 }
00842 }
00843
00844
00845
00846
00847
00848
if ( !
KProtocolInfo::supportsReading( m_strURL ) )
00849 {
00850
kdError(7010) <<
"#### NO SUPPORT FOR READING!" <<
endl;
00851 m_bFault =
true;
00852 m_bFinished =
true;
00853 m_timer.start( 0,
true );
00854
return;
00855 }
00856
kdDebug(7010) <<
this <<
" Scanning file " << m_strURL.
url() <<
endl;
00857
00858
KIO::TransferJob *job =
KIO::get( m_strURL,
false , m_bProgressInfo );
00859 job->
setWindow (d->m_window);
00860 connect(job, SIGNAL( result(
KIO::Job *)),
00861
this, SLOT( slotScanFinished(
KIO::Job *)));
00862 connect(job, SIGNAL(
mimetype(
KIO::Job *,
const QString &)),
00863
this, SLOT( slotScanMimeType(
KIO::Job *,
const QString &)));
00864 m_job = job;
00865
kdDebug(7010) <<
" Job " << job <<
" is about getting from " << m_strURL.
url() <<
endl;
00866 }
00867
00868
void KRun::slotTimeout()
00869 {
00870
kdDebug(7010) <<
this <<
" slotTimeout called" <<
endl;
00871
if (
m_bInit )
00872 {
00873
m_bInit =
false;
00874 init();
00875
return;
00876 }
00877
00878
if ( m_bFault ){
00879 emit
error();
00880 }
00881
if ( m_bFinished ){
00882 emit
finished();
00883 }
00884
00885
if (
m_bScanFile )
00886 {
00887
m_bScanFile =
false;
00888 scanFile();
00889
return;
00890 }
00891
else if ( m_bIsDirectory )
00892 {
00893 m_bIsDirectory =
false;
00894
foundMimeType(
"inode/directory" );
00895
return;
00896 }
00897
00898
if ( m_bAutoDelete )
00899 {
00900
delete this;
00901
return;
00902 }
00903 }
00904
00905
void KRun::slotStatResult(
KIO::Job * job )
00906 {
00907 m_job = 0L;
00908
if (job->
error())
00909 {
00910 d->m_showingError =
true;
00911
kdError(7010) <<
this <<
" ERROR " << job->
error() <<
" " << job->
errorString() <<
endl;
00912 job->
showErrorDialog();
00913
00914 d->m_showingError =
false;
00915
00916 m_bFault =
true;
00917 m_bFinished =
true;
00918
00919
00920 m_timer.start( 0,
true );
00921
00922 }
else {
00923
00924
kdDebug(7010) <<
"Finished" <<
endl;
00925
if(!dynamic_cast<KIO::StatJob*>(job))
00926
kdFatal() <<
"job is a " <<
typeid(*job).name() <<
" should be a StatJob" <<
endl;
00927
00928
KIO::UDSEntry entry = ((
KIO::StatJob*)job)->statResult();
00929 KIO::UDSEntry::ConstIterator it = entry.begin();
00930
for( ; it != entry.end(); it++ ) {
00931
if ( (*it).m_uds == KIO::UDS_FILE_TYPE )
00932 {
00933
if ( S_ISDIR( (mode_t)((*it).m_long) ) )
00934 m_bIsDirectory =
true;
00935
else
00936
m_bScanFile =
true;
00937
break;
00938 }
00939 }
00940
00941 assert ( m_bScanFile || m_bIsDirectory );
00942
00943
00944
00945
00946 m_timer.start( 0,
true );
00947 }
00948 }
00949
00950
void KRun::slotScanMimeType(
KIO::Job *,
const QString &mimetype )
00951 {
00952
if (
mimetype.isEmpty() )
00953
kdWarning(7010) <<
"KRun::slotScanFinished : MimetypeJob didn't find a mimetype! Probably a kioslave bug." <<
endl;
00954
foundMimeType( mimetype );
00955 m_job = 0;
00956 }
00957
00958
void KRun::slotScanFinished(
KIO::Job *job )
00959 {
00960 m_job = 0;
00961
if (job->
error())
00962 {
00963 d->m_showingError =
true;
00964
kdError(7010) <<
this <<
" ERROR (stat) : " << job->
error() <<
" " << job->
errorString() <<
endl;
00965 job->
showErrorDialog();
00966
00967 d->m_showingError =
false;
00968
00969 m_bFault =
true;
00970 m_bFinished =
true;
00971
00972
00973 m_timer.start( 0,
true );
00974 }
00975 }
00976
00977 void KRun::foundMimeType(
const QString& type )
00978 {
00979
kdDebug(7010) <<
"Resulting mime type is " << type <<
endl;
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
if (m_job && m_job->inherits(
"KIO::TransferJob"))
01034 {
01035
KIO::TransferJob *job = static_cast<KIO::TransferJob *>(m_job);
01036 job->
putOnHold();
01037
KIO::Scheduler::publishSlaveOnHold();
01038 m_job = 0;
01039 }
01040
01041 Q_ASSERT( !m_bFinished );
01042
01043
01044
if ( !d->m_preferredService.isEmpty() ) {
01045
kdDebug(7010) <<
"Attempting to open with preferred service: " << d->m_preferredService <<
endl;
01046
KService::Ptr serv = KService::serviceByDesktopName( d->m_preferredService );
01047
if ( serv && serv->hasServiceType( type ) )
01048 {
01049
KURL::List lst;
01050 lst.append( m_strURL );
01051 m_bFinished =
KRun::run( *serv, lst );
01056 }
01057 }
01058
01059
if (!m_bFinished &&
KRun::runURL( m_strURL, type,
false, d->m_runExecutables )){
01060 m_bFinished =
true;
01061 }
01062
else{
01063 m_bFinished =
true;
01064 m_bFault =
true;
01065 }
01066
01067 m_timer.start( 0,
true );
01068 }
01069
01070
void KRun::killJob()
01071 {
01072
if ( m_job )
01073 {
01074
kdDebug(7010) <<
"KRun::killJob run=" <<
this <<
" m_job=" << m_job <<
endl;
01075 m_job->
kill();
01076 m_job = 0L;
01077 }
01078 }
01079
01080 void KRun::abort()
01081 {
01082
kdDebug(7010) <<
"KRun::abort " <<
this <<
" m_showingError=" << d->m_showingError <<
endl;
01083 killJob();
01084
01085
01086
if ( d->m_showingError )
01087
return;
01088 m_bFault =
true;
01089 m_bFinished =
true;
01090
m_bInit =
false;
01091
m_bScanFile =
false;
01092
01093
01094 m_timer.start( 0,
true );
01095 }
01096
01097 void KRun::setPreferredService(
const QString& desktopEntryName )
01098 {
01099 d->m_preferredService = desktopEntryName;
01100 }
01101
01102 void KRun::setRunExecutables(
bool b)
01103 {
01104 d->m_runExecutables = b;
01105 }
01106
01107 bool KRun::isExecutable(
const QString& serviceType )
01108 {
01109
return ( serviceType ==
"application/x-desktop" ||
01110 serviceType ==
"application/x-executable" ||
01111 serviceType ==
"application/x-msdos-program" ||
01112 serviceType ==
"application/x-shellscript" );
01113 }
01114
01115
01116
01117 pid_t
01118 KProcessRunner::run(
KProcess * p,
const QString & binName)
01119 {
01120
return (
new KProcessRunner(p, binName))->pid();
01121 }
01122
01123
#ifdef Q_WS_X11
01124
pid_t
01125 KProcessRunner::run(
KProcess * p,
const QString & binName,
const KStartupInfoId&
id )
01126 {
01127
return (
new KProcessRunner(p, binName,
id))->pid();
01128 }
01129
#endif
01130
01131 KProcessRunner::KProcessRunner(
KProcess * p,
const QString & _binName )
01132 :
QObject(),
01133 process_(p),
01134 binName( _binName )
01135 {
01136 QObject::connect(
01137 process_, SIGNAL(processExited(
KProcess *)),
01138
this, SLOT(slotProcessExited(
KProcess *)));
01139
01140 process_->start();
01141
if ( !process_->pid() )
01142 slotProcessExited( process_ );
01143 }
01144
01145
#ifdef Q_WS_X11
01146
KProcessRunner::KProcessRunner(
KProcess * p,
const QString & _binName,
const KStartupInfoId&
id )
01147 :
QObject(),
01148 process_(p),
01149 binName( _binName ),
01150 id_( id )
01151 {
01152 QObject::connect(
01153 process_, SIGNAL(processExited(
KProcess *)),
01154
this, SLOT(slotProcessExited(
KProcess *)));
01155
01156 process_->start();
01157
if ( !process_->pid() )
01158 slotProcessExited( process_ );
01159 }
01160
#endif
01161
01162 KProcessRunner::~KProcessRunner()
01163 {
01164
delete process_;
01165 }
01166
01167 pid_t
01168 KProcessRunner::pid()
const
01169
{
01170
return process_->pid();
01171 }
01172
01173
void
01174 KProcessRunner::slotProcessExited(
KProcess * p)
01175 {
01176
if (p != process_)
01177
return;
01178
01179
kdDebug(7010) <<
"slotProcessExited " << binName <<
endl;
01180
kdDebug(7010) <<
"normalExit " << process_->normalExit() <<
endl;
01181
kdDebug(7010) <<
"exitStatus " << process_->exitStatus() <<
endl;
01182
bool showErr = process_->normalExit()
01183 && ( process_->exitStatus() == 127 || process_->exitStatus() == 1 );
01184
if ( !binName.isEmpty() && ( showErr || process_->pid() == 0 ) )
01185 {
01186
01187
01188
01189
01190
if ( !
QFile( binName ).exists() &&
KStandardDirs::findExe( binName ).isEmpty() )
01191 {
01192 kapp->ref();
01193
KMessageBox::sorry( 0L, i18n(
"Couldn't find the program '%1'").arg( binName ) );
01194 kapp->deref();
01195 }
01196 }
01197
#ifdef Q_WS_X11
01198
if( !id_.none())
01199 {
01200
KStartupInfoData data;
01201 data.
addPid( pid());
01202 data.
setHostname();
01203
KStartupInfo::sendFinish( id_, data );
01204 }
01205
#endif
01206
delete this;
01207 }
01208
01209
void KRun::virtual_hook(
int,
void* )
01210 { }
01211
01212
#include "krun.moc"