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",
"konsole");
00420
if (terminal ==
"konsole")
00421 terminal +=
" -caption=%c %i %m";
00422 terminal +=
" ";
00423 terminal += _service.
terminalOptions();
00424
if( !mx1.expandMacrosShellQuote( terminal ) ) {
00425
kdWarning() <<
"KRun: syntax error in command `" << terminal <<
"', service `" << _service.
name() <<
"'" <<
endl;
00426
return QStringList();
00427 }
00428 mx2.expandMacrosShellQuote( terminal );
00429
if (has_shell)
00430 result << terminal;
00431
else
00432 result =
KShell::splitArgs( terminal );
00433 result <<
"-e";
00434 }
00435
00436
int err;
00437
if (_service.
substituteUid()) {
00438
if (_service.
terminal())
00439 result <<
"su";
00440
else
00441 result <<
"kdesu" <<
"-u";
00442 result << _service.
username() <<
"-c";
00443
KShell::splitArgs(exec, KShell::AbortOnMeta, &err);
00444
if (err == KShell::FoundMeta) {
00445
shellQuote( exec );
00446 exec.
prepend(
"/bin/sh -c " );
00447 }
else if (err != KShell::NoError)
00448
goto synerr;
00449
if (has_shell)
00450
shellQuote( exec );
00451 result << exec;
00452 }
else {
00453
if (has_shell) {
00454
if (_service.
terminal()) {
00455
KShell::splitArgs(exec, KShell::AbortOnMeta, &err);
00456
if (err == KShell::FoundMeta) {
00457
shellQuote( exec );
00458 exec.
prepend(
"/bin/sh -c " );
00459 }
else if (err != KShell::NoError)
00460
goto synerr;
00461 }
00462 result << exec;
00463 }
else {
00464 result +=
KShell::splitArgs(exec, KShell::AbortOnMeta, &err);
00465
if (err == KShell::FoundMeta)
00466 result <<
"/bin/sh" <<
"-c" << exec;
00467
else if (err != KShell::NoError)
00468
goto synerr;
00469 }
00470 }
00471
00472
return result;
00473
00474 synerr:
00475
kdWarning() <<
"KRun: syntax error in command `" << _service.
exec() <<
"', service `" << _service.
name() <<
"'" <<
endl;
00476
return QStringList();
00477 }
00478
00479
00480 QString KRun::binaryName(
const QString & execLine,
bool removePath )
00481 {
00482
00483
QStringList args =
KShell::splitArgs( execLine );
00484
for (QStringList::ConstIterator it = args.begin(); it != args.end(); ++it)
00485
if (!(*it).contains(
'='))
00486
00487
return removePath ? (*it).mid((*it).findRev(
'/') + 1) : *it;
00488
return QString::null;
00489 }
00490
00491
static pid_t runCommandInternal(
KProcess* proc,
const KService* service,
const QString& binName,
00492
const QString &execName,
const QString & iconName )
00493 {
00494
if ( service && !
KDesktopFile::isAuthorizedDesktopFile( service->
desktopEntryPath() ))
00495 {
00496
KMessageBox::sorry(0, i18n(
"You are not authorized to execute this file."));
00497
return 0;
00498 }
00499
QString bin =
KRun::binaryName( binName,
true );
00500
#ifdef Q_WS_X11 // Startup notification doesn't work with QT/E, service isn't needed without Startup notification
00501
bool startup_notify =
false;
00502
QCString wmclass;
00503
KStartupInfoId id;
00504
if( service && service->
property(
"StartupNotify" ).
isValid())
00505 {
00506 startup_notify = service->
property(
"StartupNotify" ).
toBool();
00507 wmclass = service->
property(
"StartupWMClass" ).
toString().latin1();
00508 }
00509
else if( service && service->
property(
"X-KDE-StartupNotify" ).
isValid())
00510 {
00511 startup_notify = service->
property(
"X-KDE-StartupNotify" ).
toBool();
00512 wmclass = service->
property(
"X-KDE-WMClass" ).
toString().latin1();
00513 }
00514
else
00515 {
00516
if( service && service->
type() ==
"Application" )
00517 {
00518 startup_notify =
true;
00519 wmclass =
"0";
00520 }
00521 }
00522
if( startup_notify )
00523 {
00524
id.initId();
00525
id.setupStartupEnv();
00526
KStartupInfoData data;
00527 data.
setHostname();
00528 data.
setBin( bin );
00529 data.
setName( execName.
isEmpty() ? service->
name() : execName );
00530 data.
setDescription( i18n(
"Launching %1" ).arg( data.
name()));
00531 data.
setIcon( iconName.
isEmpty() ? service->
icon() : iconName );
00532
#ifdef Q_WS_X11
00533
data.
setTimestamp( qt_x_user_time );
00534
#endif
00535
if( !wmclass.
isEmpty())
00536 data.
setWMClass( wmclass );
00537 data.
setDesktop( KWin::currentDesktop());
00538
KStartupInfo::sendStartup(
id, data );
00539 }
00540 pid_t pid = KProcessRunner::run( proc, binName,
id );
00541
if( startup_notify && pid )
00542 {
00543
KStartupInfoData data;
00544 data.
addPid( pid );
00545
KStartupInfo::sendChange(
id, data );
00546
KStartupInfo::resetStartupEnv();
00547 }
00548
return pid;
00549
#else
00550
Q_UNUSED( execName );
00551 Q_UNUSED( iconName );
00552
return KProcessRunner::run( proc, bin );
00553
#endif
00554
}
00555
00556
static pid_t runTempService(
const KService& _service,
const KURL::List& _urls,
bool tempFiles )
00557 {
00558
if (!_urls.
isEmpty()) {
00559
kdDebug(7010) <<
"runTempService: first url " << _urls.
first().url() <<
endl;
00560 }
00561
00562
QStringList args;
00563
if ((_urls.
count() > 1) && !_service.
allowMultipleFiles())
00564 {
00565
00566
00567
00568
00569
00570
KURL::List::ConstIterator it = _urls.
begin();
00571
while(++it != _urls.
end())
00572 {
00573
KURL::List singleUrl;
00574 singleUrl.
append(*it);
00575 runTempService( _service, singleUrl, tempFiles );
00576 }
00577
KURL::List singleUrl;
00578 singleUrl.
append(_urls.
first());
00579 args =
KRun::processDesktopExec(_service, singleUrl,
false, tempFiles);
00580 }
00581
else
00582 {
00583 args =
KRun::processDesktopExec(_service, _urls,
false, tempFiles);
00584 }
00585
kdDebug(7010) <<
"runTempService: KProcess args=" << args <<
endl;
00586
00587
KProcess * proc =
new KProcess;
00588 *proc << args;
00589
00590
if (!_service.
path().
isEmpty())
00591 proc->
setWorkingDirectory(_service.
path());
00592
00593
return runCommandInternal( proc, &_service, _service.
exec(), _service.
name(), _service.
icon() );
00594 }
00595
00596
00597 pid_t
KRun::run(
const KService& _service,
const KURL::List& _urls )
00598 {
00599
return run( _service, _urls,
false );
00600 }
00601
00602 pid_t
KRun::run(
const KService& _service,
const KURL::List& _urls,
bool tempFiles )
00603 {
00604
if (!_service.
desktopEntryPath().
isEmpty() &&
00605 !
KDesktopFile::isAuthorizedDesktopFile( _service.
desktopEntryPath()))
00606 {
00607
KMessageBox::sorry(0, i18n(
"You are not authorized to execute this service."));
00608
return 0;
00609 }
00610
00611
if ( !tempFiles )
00612 {
00613
00614 KURL::List::ConstIterator it = _urls.
begin();
00615
for(; it != _urls.
end(); ++it) {
00616
00617
KRecentDocument::add( *it, _service.
desktopEntryName() );
00618 }
00619 }
00620
00621
if ( tempFiles || _service.
desktopEntryPath().
isEmpty())
00622 {
00623
return runTempService(_service, _urls, tempFiles);
00624 }
00625
00626
kdDebug(7010) <<
"KRun::run " << _service.
desktopEntryPath() <<
endl;
00627
00628
if (!_urls.
isEmpty()) {
00629
kdDebug(7010) <<
"First url " << _urls.
first().url() <<
endl;
00630 }
00631
00632
QString error;
00633
int pid = 0;
00634
00635
int i =
KApplication::startServiceByDesktopPath(
00636 _service.
desktopEntryPath(), _urls.
toStringList(), &error, 0L, &pid
00637 );
00638
00639
if (i != 0)
00640 {
00641
kdDebug(7010) << error <<
endl;
00642
KMessageBox::sorry( 0L, error );
00643
return 0;
00644 }
00645
00646
kdDebug(7010) <<
"startServiceByDesktopPath worked fine" <<
endl;
00647
return (pid_t) pid;
00648 }
00649
00650
00651 pid_t
KRun::run(
const QString& _exec,
const KURL::List& _urls,
const QString& _name,
00652
const QString& _icon,
const QString&,
const QString&)
00653 {
00654
KService::Ptr service =
new KService(_name, _exec, _icon);
00655
00656
return run(*service, _urls);
00657 }
00658
00659 pid_t
KRun::runCommand(
QString cmd )
00660 {
00661
return KRun::runCommand( cmd, QString::null, QString::null );
00662 }
00663
00664 pid_t
KRun::runCommand(
const QString& cmd,
const QString &execName,
const QString & iconName )
00665 {
00666
kdDebug(7010) <<
"runCommand " << cmd <<
"," << execName <<
endl;
00667
KProcess * proc =
new KProcess;
00668 proc->
setUseShell(
true);
00669 *proc << cmd;
00670
KService::Ptr service =
KService::serviceByDesktopName(
binaryName( cmd,
true ));
00671
return runCommandInternal( proc, service.
data(),
binaryName( cmd,
false ), execName, iconName );
00672 }
00673
00674 KRun::KRun(
const KURL& url, mode_t mode,
bool isLocalFile,
bool showProgressInfo )
00675 :m_timer(0,
"KRun::timer")
00676 {
00677 init (url, 0, mode, isLocalFile, showProgressInfo);
00678 }
00679
00680 KRun::KRun(
const KURL& url,
QWidget* window, mode_t mode,
bool isLocalFile,
00681
bool showProgressInfo )
00682 :m_timer(0,
"KRun::timer")
00683 {
00684 init (url, window, mode, isLocalFile, showProgressInfo);
00685 }
00686
00687
void KRun::init (
const KURL& url,
QWidget* window, mode_t mode,
bool isLocalFile,
00688
bool showProgressInfo )
00689 {
00690 m_bFault =
false;
00691 m_bAutoDelete =
true;
00692 m_bProgressInfo = showProgressInfo;
00693 m_bFinished =
false;
00694 m_job = 0L;
00695 m_strURL = url;
00696 m_bScanFile =
false;
00697 m_bIsDirectory =
false;
00698 m_bIsLocalFile = isLocalFile;
00699 m_mode = mode;
00700 d =
new KRunPrivate;
00701 d->m_runExecutables =
true;
00702 d->m_window = window;
00703
00704
00705
00706
00707 m_bInit =
true;
00708
connect( &m_timer, SIGNAL( timeout() ),
this, SLOT( slotTimeout() ) );
00709 m_timer.
start( 0,
true );
00710
kdDebug(7010) <<
" new KRun " <<
this <<
" " << url.prettyURL() <<
" timer=" << &m_timer <<
endl;
00711
00712 kapp->ref();
00713 }
00714
00715
void KRun::init()
00716 {
00717
kdDebug(7010) <<
"INIT called" <<
endl;
00718
if ( !m_strURL.
isValid() )
00719 {
00720 d->m_showingError =
true;
00721
KMessageBoxWrapper::error( d->m_window, i18n(
"Malformed URL\n%1" ).arg( m_strURL.
url() ) );
00722 d->m_showingError =
false;
00723 m_bFault =
true;
00724 m_bFinished =
true;
00725 m_timer.
start( 0,
true );
00726
return;
00727 }
00728
if ( !kapp->authorizeURLAction(
"open",
KURL(), m_strURL))
00729 {
00730
QString msg =
KIO::buildErrorString(KIO::ERR_ACCESS_DENIED, m_strURL.
prettyURL());
00731 d->m_showingError =
true;
00732
KMessageBoxWrapper::error( d->m_window, msg );
00733 d->m_showingError =
false;
00734 m_bFault =
true;
00735 m_bFinished =
true;
00736 m_timer.
start( 0,
true );
00737
return;
00738 }
00739
00740
if ( !m_bIsLocalFile && m_strURL.
isLocalFile() )
00741
00742 m_bIsLocalFile =
true;
00743
00744
if ( m_bIsLocalFile )
00745 {
00746
if ( m_mode == 0 )
00747 {
00748
struct stat buff;
00749
if (
stat( QFile::encodeName(m_strURL.
path()), &buff ) == -1 )
00750 {
00751 d->m_showingError =
true;
00752
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() ) );
00753 d->m_showingError =
false;
00754 m_bFault =
true;
00755 m_bFinished =
true;
00756 m_timer.
start( 0,
true );
00757
return;
00758 }
00759 m_mode = buff.st_mode;
00760 }
00761
00762 KMimeType::Ptr mime =
KMimeType::findByURL( m_strURL, m_mode, m_bIsLocalFile );
00763 assert( mime != 0L );
00764
kdDebug(7010) <<
"MIME TYPE is " << mime->name() <<
endl;
00765
foundMimeType( mime->name() );
00766
return;
00767 }
00768
else if (
KProtocolInfo::isHelperProtocol( m_strURL ) ) {
00769
kdDebug(7010) <<
"Helper protocol" <<
endl;
00770
00771
KURL::List urls;
00772 urls.
append( m_strURL );
00773
QString exec =
KProtocolInfo::exec( m_strURL.
protocol() );
00774
run( exec, urls );
00775
00776 m_bFinished =
true;
00777
00778 m_timer.
start( 0,
true );
00779
return;
00780 }
00781
00782
00783
if ( S_ISDIR( m_mode ) )
00784 {
00785
foundMimeType(
"inode/directory" );
00786
return;
00787 }
00788
00789
00790
00791
if ( !
KProtocolInfo::supportsListing( m_strURL ) )
00792 {
00793
00794
00795 scanFile();
00796
return;
00797 }
00798
00799
kdDebug(7010) <<
"Testing directory (stating)" <<
endl;
00800
00801
00802
KIO::StatJob *job =
KIO::stat( m_strURL,
true, 0 , m_bProgressInfo );
00803 job->
setWindow (d->m_window);
00804
connect( job, SIGNAL( result(
KIO::Job * ) ),
00805
this, SLOT( slotStatResult(
KIO::Job * ) ) );
00806 m_job = job;
00807
kdDebug(7010) <<
" Job " << job <<
" is about stating " << m_strURL.
url() <<
endl;
00808 }
00809
00810 KRun::~KRun()
00811 {
00812
kdDebug(7010) <<
"KRun::~KRun() " <<
this <<
endl;
00813 m_timer.
stop();
00814 killJob();
00815 kapp->deref();
00816
kdDebug(7010) <<
"KRun::~KRun() done " <<
this <<
endl;
00817
delete d;
00818 }
00819
00820
void KRun::scanFile()
00821 {
00822
kdDebug(7010) <<
"###### KRun::scanFile " << m_strURL.
url() <<
endl;
00823
00824
00825
if ( m_strURL.
query().
isEmpty() )
00826 {
00827 KMimeType::Ptr mime =
KMimeType::findByURL( m_strURL );
00828 assert( mime != 0L );
00829
if ( mime->name() !=
"application/octet-stream" || m_bIsLocalFile )
00830 {
00831
kdDebug(7010) <<
"Scanfile: MIME TYPE is " << mime->name() <<
endl;
00832
foundMimeType( mime->name() );
00833
return;
00834 }
00835 }
00836
00837
00838
00839
00840
00841
if ( !
KProtocolInfo::supportsReading( m_strURL ) )
00842 {
00843
kdError(7010) <<
"#### NO SUPPORT FOR READING!" <<
endl;
00844 m_bFault =
true;
00845 m_bFinished =
true;
00846 m_timer.
start( 0,
true );
00847
return;
00848 }
00849
kdDebug(7010) <<
this <<
" Scanning file " << m_strURL.
url() <<
endl;
00850
00851
KIO::TransferJob *job =
KIO::get( m_strURL,
false , m_bProgressInfo );
00852 job->
setWindow (d->m_window);
00853
connect(job, SIGNAL( result(
KIO::Job *)),
00854
this, SLOT( slotScanFinished(
KIO::Job *)));
00855
connect(job, SIGNAL(
mimetype(
KIO::Job *,
const QString &)),
00856
this, SLOT( slotScanMimeType(
KIO::Job *,
const QString &)));
00857 m_job = job;
00858
kdDebug(7010) <<
" Job " << job <<
" is about getting from " << m_strURL.
url() <<
endl;
00859 }
00860
00861
void KRun::slotTimeout()
00862 {
00863
kdDebug(7010) <<
this <<
" slotTimeout called" <<
endl;
00864
if (
m_bInit )
00865 {
00866
m_bInit =
false;
00867 init();
00868
return;
00869 }
00870
00871
if ( m_bFault ){
00872 emit
error();
00873 }
00874
if ( m_bFinished ){
00875 emit
finished();
00876 }
00877
00878
if (
m_bScanFile )
00879 {
00880
m_bScanFile =
false;
00881 scanFile();
00882
return;
00883 }
00884
else if ( m_bIsDirectory )
00885 {
00886 m_bIsDirectory =
false;
00887
foundMimeType(
"inode/directory" );
00888
return;
00889 }
00890
00891
if ( m_bAutoDelete )
00892 {
00893
delete this;
00894
return;
00895 }
00896 }
00897
00898
void KRun::slotStatResult(
KIO::Job * job )
00899 {
00900 m_job = 0L;
00901
if (job->
error())
00902 {
00903 d->m_showingError =
true;
00904
kdError(7010) <<
this <<
" ERROR " << job->
error() <<
" " << job->
errorString() <<
endl;
00905 job->
showErrorDialog();
00906
00907 d->m_showingError =
false;
00908
00909 m_bFault =
true;
00910 m_bFinished =
true;
00911
00912
00913 m_timer.
start( 0,
true );
00914
00915 }
else {
00916
00917
kdDebug(7010) <<
"Finished" <<
endl;
00918
if(!dynamic_cast<KIO::StatJob*>(job))
00919
kdFatal() <<
"job is a " <<
typeid(*job).name() <<
" should be a StatJob" <<
endl;
00920
00921
KIO::UDSEntry entry = ((
KIO::StatJob*)job)->statResult();
00922 KIO::UDSEntry::ConstIterator it = entry.
begin();
00923
for( ; it != entry.
end(); it++ ) {
00924
if ( (*it).m_uds == KIO::UDS_FILE_TYPE )
00925 {
00926
if ( S_ISDIR( (mode_t)((*it).m_long) ) )
00927 m_bIsDirectory =
true;
00928
else
00929
m_bScanFile =
true;
00930
break;
00931 }
00932 }
00933
00934 assert ( m_bScanFile || m_bIsDirectory );
00935
00936
00937
00938
00939 m_timer.
start( 0,
true );
00940 }
00941 }
00942
00943
void KRun::slotScanMimeType(
KIO::Job *,
const QString &mimetype )
00944 {
00945
if (
mimetype.isEmpty() )
00946
kdWarning(7010) <<
"KRun::slotScanFinished : MimetypeJob didn't find a mimetype! Probably a kioslave bug." <<
endl;
00947
foundMimeType( mimetype );
00948 m_job = 0;
00949 }
00950
00951
void KRun::slotScanFinished(
KIO::Job *job )
00952 {
00953 m_job = 0;
00954
if (job->
error())
00955 {
00956 d->m_showingError =
true;
00957
kdError(7010) <<
this <<
" ERROR (stat) : " << job->
error() <<
" " << job->
errorString() <<
endl;
00958 job->
showErrorDialog();
00959
00960 d->m_showingError =
false;
00961
00962 m_bFault =
true;
00963 m_bFinished =
true;
00964
00965
00966 m_timer.
start( 0,
true );
00967 }
00968 }
00969
00970 void KRun::foundMimeType(
const QString& type )
00971 {
00972
kdDebug(7010) <<
"Resulting mime type is " << type <<
endl;
00973
00974
00975
00976
00977
00978
00979
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
if (m_job && m_job->
inherits(
"KIO::TransferJob"))
01027 {
01028
KIO::TransferJob *job = static_cast<KIO::TransferJob *>(m_job);
01029 job->
putOnHold();
01030
KIO::Scheduler::publishSlaveOnHold();
01031 m_job = 0;
01032 }
01033
01034 Q_ASSERT( !m_bFinished );
01035
01036
01037
if ( !d->m_preferredService.isEmpty() ) {
01038
kdDebug(7010) <<
"Attempting to open with preferred service: " << d->m_preferredService <<
endl;
01039
KService::Ptr serv =
KService::serviceByDesktopName( d->m_preferredService );
01040
if ( serv && serv->hasServiceType( type ) )
01041 {
01042
KURL::List lst;
01043 lst.
append( m_strURL );
01044 m_bFinished =
KRun::run( *serv, lst );
01049 }
01050 }
01051
01052
if (!m_bFinished &&
KRun::runURL( m_strURL, type,
false, d->m_runExecutables )){
01053 m_bFinished =
true;
01054 }
01055
else{
01056 m_bFinished =
true;
01057 m_bFault =
true;
01058 }
01059
01060 m_timer.
start( 0,
true );
01061 }
01062
01063
void KRun::killJob()
01064 {
01065
if ( m_job )
01066 {
01067
kdDebug(7010) <<
"KRun::killJob run=" <<
this <<
" m_job=" << m_job <<
endl;
01068 m_job->
kill();
01069 m_job = 0L;
01070 }
01071 }
01072
01073 void KRun::abort()
01074 {
01075
kdDebug(7010) <<
"KRun::abort " <<
this <<
" m_showingError=" << d->m_showingError <<
endl;
01076 killJob();
01077
01078
01079
if ( d->m_showingError )
01080
return;
01081 m_bFault =
true;
01082 m_bFinished =
true;
01083
m_bInit =
false;
01084
m_bScanFile =
false;
01085
01086
01087 m_timer.
start( 0,
true );
01088 }
01089
01090 void KRun::setPreferredService(
const QString& desktopEntryName )
01091 {
01092 d->m_preferredService = desktopEntryName;
01093 }
01094
01095 void KRun::setRunExecutables(
bool b)
01096 {
01097 d->m_runExecutables = b;
01098 }
01099
01100 bool KRun::isExecutable(
const QString& serviceType )
01101 {
01102
return ( serviceType ==
"application/x-desktop" ||
01103 serviceType ==
"application/x-executable" ||
01104 serviceType ==
"application/x-msdos-program" ||
01105 serviceType ==
"application/x-shellscript" );
01106 }
01107
01108
01109
01110 pid_t
01111 KProcessRunner::run(
KProcess * p,
const QString & binName)
01112 {
01113
return (
new KProcessRunner(p, binName))->pid();
01114 }
01115
01116
#ifdef Q_WS_X11
01117
pid_t
01118 KProcessRunner::run(
KProcess * p,
const QString & binName,
const KStartupInfoId&
id )
01119 {
01120
return (
new KProcessRunner(p, binName,
id))->pid();
01121 }
01122
#endif
01123
01124 KProcessRunner::KProcessRunner(
KProcess * p,
const QString & _binName )
01125 :
QObject(),
01126 process_(p),
01127 binName( _binName )
01128 {
01129
QObject::connect(
01130 process_, SIGNAL(processExited(
KProcess *)),
01131
this, SLOT(slotProcessExited(
KProcess *)));
01132
01133 process_->start();
01134
if ( !process_->pid() )
01135 slotProcessExited( process_ );
01136 }
01137
01138
#ifdef Q_WS_X11
01139
KProcessRunner::KProcessRunner(
KProcess * p,
const QString & _binName,
const KStartupInfoId&
id )
01140 :
QObject(),
01141 process_(p),
01142 binName( _binName ),
01143 id_( id )
01144 {
01145
QObject::connect(
01146 process_, SIGNAL(processExited(
KProcess *)),
01147
this, SLOT(slotProcessExited(
KProcess *)));
01148
01149 process_->start();
01150
if ( !process_->pid() )
01151 slotProcessExited( process_ );
01152 }
01153
#endif
01154
01155 KProcessRunner::~KProcessRunner()
01156 {
01157
delete process_;
01158 }
01159
01160 pid_t
01161 KProcessRunner::pid()
const
01162
{
01163
return process_->pid();
01164 }
01165
01166
void
01167 KProcessRunner::slotProcessExited(
KProcess * p)
01168 {
01169
if (p != process_)
01170
return;
01171
01172
kdDebug(7010) <<
"slotProcessExited " << binName <<
endl;
01173
kdDebug(7010) <<
"normalExit " << process_->normalExit() <<
endl;
01174
kdDebug(7010) <<
"exitStatus " << process_->exitStatus() <<
endl;
01175
bool showErr = process_->normalExit()
01176 && ( process_->exitStatus() == 127 || process_->exitStatus() == 1 );
01177
if ( !binName.
isEmpty() && ( showErr || process_->pid() == 0 ) )
01178 {
01179
01180
01181
01182
01183
if ( !
QFile( binName ).exists() &&
KStandardDirs::findExe( binName ).
isEmpty() )
01184 {
01185 kapp->ref();
01186
KMessageBox::sorry( 0L, i18n(
"Couldn't find the program '%1'").arg( binName ) );
01187 kapp->deref();
01188 }
01189 }
01190
#ifdef Q_WS_X11
01191
if( !id_.none())
01192 {
01193
KStartupInfoData data;
01194 data.
addPid( pid());
01195 data.
setHostname();
01196
KStartupInfo::sendFinish( id_, data );
01197 }
01198
#endif
01199
delete this;
01200 }
01201
01202
void KRun::virtual_hook(
int,
void* )
01203 { }
01204
01205
#include "krun.moc"