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