00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <config.h>
00023
00024 #include "kservice.h"
00025 #include <sys/types.h>
00026 #include <sys/stat.h>
00027
00028 #include <stddef.h>
00029 #include <unistd.h>
00030 #include <stdlib.h>
00031
00032 #include <qstring.h>
00033 #include <qfile.h>
00034 #include <qtl.h>
00035 #include <qfile.h>
00036
00037 #include <ksimpleconfig.h>
00038 #include <kstddirs.h>
00039 #include <kapplication.h>
00040 #include <kdebug.h>
00041 #include <kdesktopfile.h>
00042 #include <kglobal.h>
00043 #include <kiconloader.h>
00044 #include <klocale.h>
00045 #include <kconfigbase.h>
00046 #include <dcopclient.h>
00047
00048 #include "kservicefactory.h"
00049 #include "kservicetypefactory.h"
00050 #include "kservicetype.h"
00051 #include "kuserprofile.h"
00052 #include "ksycoca.h"
00053
00054 class KService::KServicePrivate
00055 {
00056 public:
00057 QStringList categories;
00058 };
00059
00060 KService::KService( const QString & _name, const QString &_exec, const QString &_icon)
00061 : KSycocaEntry( QString::null)
00062 {
00063 d = new KServicePrivate;
00064 m_bValid = true;
00065 m_bDeleted = false;
00066 m_strType = "Application";
00067 m_strName = _name;
00068 m_strExec = _exec;
00069 m_strIcon = _icon;
00070 m_bTerminal = false;
00071 m_bAllowAsDefault = true;
00072 m_initialPreference = 10;
00073 }
00074
00075
00076 KService::KService( const QString & _fullpath )
00077 : KSycocaEntry( _fullpath)
00078 {
00079 d = new KServicePrivate;
00080 KDesktopFile config( _fullpath );
00081
00082 init(&config);
00083 }
00084
00085 KService::KService( KDesktopFile *config )
00086 : KSycocaEntry( config->filename())
00087 {
00088 init(config);
00089 }
00090
00091 void
00092 KService::init( KDesktopFile *config )
00093 {
00094 d = new KServicePrivate;
00095 m_bValid = true;
00096
00097 bool absPath = (entryPath()[0] == '/');
00098
00099 config->setDesktopGroup();
00100 config->setDollarExpansion( true );
00101 if(absPath && access(QFile::encodeName(entryPath()), R_OK))
00102 {
00103 m_bValid = false;
00104 return;
00105 } else if(!absPath) {
00106 QStringList list=KGlobal::dirs()->findAllResources(QFile::encodeName(config->resource()), entryPath());
00107 bool ok=false;
00108 for(QStringList::ConstIterator it=list.fromLast(); !ok && it!=list.end(); it--) {
00109 if(!access(QFile::encodeName(*it), R_OK))
00110 ok=true;
00111 }
00112 if(!ok) {
00113 m_bValid = false;
00114 return;
00115 }
00116 }
00117 QMap<QString, QString> entryMap = config->entryMap(config->group());
00118
00119 entryMap.remove("Encoding");
00120 entryMap.remove("Version");
00121
00122 m_bDeleted = config->readBoolEntry( "Hidden", false );
00123 entryMap.remove("Hidden");
00124 if (m_bDeleted)
00125 {
00126 m_bValid = false;
00127 return;
00128 }
00129 m_strType = config->readEntry( "Type" );
00130 entryMap.remove("Type");
00131 if ( m_strType.isEmpty() )
00132 {
00133
00134
00135
00136
00137
00138 m_strType = "Application";
00139 } else if ( m_strType != "Application" && m_strType != "Service" )
00140 {
00141 kdWarning(7012) << "The desktop entry file " << entryPath()
00142 << " has Type=" << m_strType
00143 << " instead of \"Application\" or \"Service\"" << endl;
00144 m_bValid = false;
00145 return;
00146 }
00147
00148
00149 if (!config->tryExec()) {
00150 m_bDeleted = true;
00151 m_bValid = false;
00152 return;
00153 }
00154
00155 QString resource = config->resource();
00156
00157 if ( (m_strType == "Application") &&
00158 (!resource.isEmpty()) &&
00159 (resource != "apps") &&
00160 !absPath)
00161 {
00162 kdWarning(7012) << "The desktop entry file " << entryPath()
00163 << " has Type=" << m_strType << " but is located under \"" << resource
00164 << "\" instead of \"apps\"" << endl;
00165 m_bValid = false;
00166 return;
00167 }
00168
00169 if ( (m_strType == "Service") &&
00170 (!resource.isEmpty()) &&
00171 (resource != "services") &&
00172 !absPath)
00173 {
00174 kdWarning(7012) << "The desktop entry file " << entryPath()
00175 << " has Type=" << m_strType << " but is located under \"" << resource
00176 << "\" instead of \"services\"" << endl;
00177 m_bValid = false;
00178 return;
00179 }
00180
00181 QString name = entryPath();
00182 int pos = name.findRev('/');
00183 if (pos != -1)
00184 name = name.mid(pos+1);
00185 pos = name.find('.');
00186 if (pos != -1)
00187 name = name.left(pos);
00188
00189 m_strExec = config->readEntry( "Exec" );
00190 entryMap.remove("Exec");
00191 m_strName = config->readEntry( "Name" );
00192
00193 entryMap.remove("Name");
00194 if ( m_strName.isEmpty() )
00195 {
00196 m_bValid = false;
00197 return;
00198 }
00199
00200 m_strIcon = config->readEntry( "Icon", "unknown" );
00201 entryMap.remove("Icon");
00202 m_bTerminal = (config->readBoolEntry( "Terminal" ));
00203 entryMap.remove("Terminal");
00204 m_strTerminalOptions = config->readEntry( "TerminalOptions" );
00205 entryMap.remove("TerminalOptions");
00206 m_strPath = config->readEntry( "Path" );
00207 entryMap.remove("Path");
00208 m_strComment = config->readEntry( "Comment" );
00209 entryMap.remove("Comment");
00210 m_strGenName = config->readEntry( "GenericName" );
00211 entryMap.remove("GenericName");
00212 m_lstKeywords = config->readListEntry("Keywords");
00213 entryMap.remove("Keywords");
00214 d->categories = config->readListEntry("Categories", ';');
00215 entryMap.remove("Categories");
00216 m_strLibrary = config->readEntry( "X-KDE-Library" );
00217 entryMap.remove("X-KDE-Library");
00218 m_strInit = config->readEntry("X-KDE-Init" );
00219 entryMap.remove("X-KDE-Init");
00220
00221 m_lstServiceTypes = config->readListEntry( "ServiceTypes" );
00222 entryMap.remove("ServiceTypes");
00223
00224 m_lstServiceTypes += config->readListEntry( "MimeType", ';' );
00225 entryMap.remove("MimeType");
00226
00227 if ( m_strType == "Application" && !m_lstServiceTypes.contains("Application") )
00228
00229 m_lstServiceTypes += "Application";
00230
00231 QString dcopServiceType = config->readEntry("X-DCOP-ServiceType").lower();
00232 entryMap.remove("X-DCOP-ServiceType");
00233 if (dcopServiceType == "unique")
00234 m_DCOPServiceType = DCOP_Unique;
00235 else if (dcopServiceType == "multi")
00236 m_DCOPServiceType = DCOP_Multi;
00237 else if (dcopServiceType == "wait")
00238 m_DCOPServiceType = DCOP_Wait;
00239 else
00240 m_DCOPServiceType = DCOP_None;
00241
00242 m_strDesktopEntryName = name.lower();
00243
00244 m_bAllowAsDefault = config->readBoolEntry( "AllowDefault", true );
00245 entryMap.remove("AllowDefault");
00246
00247 m_initialPreference = config->readNumEntry( "InitialPreference", 1 );
00248 entryMap.remove("InitialPreference");
00249
00250
00251
00252
00253
00254 QMap<QString,QString>::ConstIterator it = entryMap.begin();
00255 for( ; it != entryMap.end();++it)
00256 {
00257
00258 m_mapProps.insert( it.key(), QVariant( it.data()));
00259 }
00260 }
00261
00262 KService::KService( QDataStream& _str, int offset ) : KSycocaEntry( _str, offset )
00263 {
00264 d = new KServicePrivate;
00265 load( _str );
00266 }
00267
00268 KService::~KService()
00269 {
00270
00271 delete d;
00272 }
00273
00274 QPixmap KService::pixmap( KIcon::Group _group, int _force_size, int _state, QString * _path ) const
00275 {
00276 KIconLoader *iconLoader=KGlobal::iconLoader();
00277 if (!iconLoader->extraDesktopThemesAdded())
00278 {
00279 QPixmap pixmap=iconLoader->loadIcon( m_strIcon, _group, _force_size, _state, _path, true );
00280 if (!pixmap.isNull() ) return pixmap;
00281
00282 iconLoader->addExtraDesktopThemes();
00283 }
00284
00285 return iconLoader->loadIcon( m_strIcon, _group, _force_size, _state, _path );
00286 }
00287
00288 void KService::load( QDataStream& s )
00289 {
00290
00291
00292
00293 Q_INT8 def, term, dummy1, dummy2;
00294 Q_INT8 dst, initpref;
00295 QString dummyStr1, dummyStr2;
00296 int dummyI1, dummyI2;
00297 Q_UINT32 dummyUI32;
00298
00299
00300
00301
00302
00303 s >> m_strType >> m_strName >> m_strExec >> m_strIcon
00304 >> term >> m_strTerminalOptions
00305 >> m_strPath >> m_strComment >> m_lstServiceTypes >> def >> m_mapProps
00306 >> m_strLibrary >> dummyI1 >> dummyI2
00307 >> dst
00308 >> m_strDesktopEntryName
00309 >> dummy1 >> dummyStr1 >> initpref >> dummyStr2 >> dummy2
00310 >> m_lstKeywords >> m_strInit >> dummyUI32 >> m_strGenName
00311 >> d->categories;
00312
00313 m_bAllowAsDefault = def;
00314 m_bTerminal = term;
00315 m_DCOPServiceType = (DCOPServiceType_t) dst;
00316 m_initialPreference = initpref;
00317
00318 m_bValid = true;
00319 }
00320
00321 void KService::save( QDataStream& s )
00322 {
00323 KSycocaEntry::save( s );
00324 Q_INT8 def = m_bAllowAsDefault, initpref = m_initialPreference;
00325 Q_INT8 term = m_bTerminal;
00326 Q_INT8 dst = (Q_INT8) m_DCOPServiceType;
00327 Q_INT8 dummy1 = 0, dummy2 = 0;
00328 QString dummyStr1, dummyStr2;
00329 int dummyI1 = 0, dummyI2 = 0;
00330 Q_UINT32 dummyUI32 = 0;
00331
00332
00333
00334
00335
00336 s << m_strType << m_strName << m_strExec << m_strIcon
00337 << term << m_strTerminalOptions
00338 << m_strPath << m_strComment << m_lstServiceTypes << def << m_mapProps
00339 << m_strLibrary << dummyI1 << dummyI2
00340 << dst
00341 << m_strDesktopEntryName
00342 << dummy1 << dummyStr1 << initpref << dummyStr2 << dummy2
00343 << m_lstKeywords << m_strInit << dummyUI32 << m_strGenName
00344 << d->categories;
00345 }
00346
00347 bool KService::hasServiceType( const QString& _servicetype ) const
00348 {
00349 if (!m_bValid) return false;
00350
00351
00352
00353
00354
00355 QStringList::ConstIterator it = m_lstServiceTypes.begin();
00356 for( ; it != m_lstServiceTypes.end(); ++it )
00357 {
00358
00359 KServiceType::Ptr ptr = KServiceType::serviceType( *it );
00360 if ( ptr && ptr->inherits( _servicetype ) )
00361 return true;
00362 }
00363 return false;
00364 }
00365
00366 class KServiceReadProperty : public KConfigBase
00367 {
00368 public:
00369 KServiceReadProperty(const QString &_key, const QCString &_value)
00370 : key(_key), value(_value) { }
00371
00372 bool internalHasGroup(const QCString &) const { return false; }
00373
00374 QStringList groupList() const { return QStringList(); }
00375
00376 QMap<QString,QString> entryMap(const QString &) const
00377 { return QMap<QString,QString>(); }
00378
00379 void reparseConfiguration() { }
00380
00381 KEntryMap internalEntryMap( const QString &) const { return KEntryMap(); }
00382
00383 KEntryMap internalEntryMap() const { return KEntryMap(); }
00384
00385 void putData(const KEntryKey &, const KEntry&, bool) { }
00386
00387 KEntry lookupData(const KEntryKey &) const
00388 { KEntry entry; entry.mValue = value; return entry; }
00389 protected:
00390 QString key;
00391 QCString value;
00392 };
00393
00394 QVariant KService::property( const QString& _name ) const
00395 {
00396 if ( _name == "Type" )
00397 return QVariant( m_strType );
00398 else if ( _name == "Name" )
00399 return QVariant( m_strName );
00400 else if ( _name == "Exec" )
00401 return QVariant( m_strExec );
00402 else if ( _name == "Icon" )
00403 return QVariant( m_strIcon );
00404 else if ( _name == "Terminal" )
00405 return QVariant( static_cast<int>(m_bTerminal) );
00406 else if ( _name == "TerminalOptions" )
00407 return QVariant( m_strTerminalOptions );
00408 else if ( _name == "Path" )
00409 return QVariant( m_strPath );
00410 else if ( _name == "Comment" )
00411 return QVariant( m_strComment );
00412 else if ( _name == "GenericName" )
00413 return QVariant( m_strGenName );
00414 else if ( _name == "ServiceTypes" )
00415 return QVariant( m_lstServiceTypes );
00416 else if ( _name == "AllowAsDefault" )
00417 return QVariant( static_cast<int>(m_bAllowAsDefault) );
00418 else if ( _name == "InitialPreference" )
00419 return QVariant( m_initialPreference );
00420 else if ( _name == "Library" )
00421 return QVariant( m_strLibrary );
00422 else if ( _name == "DesktopEntryPath" )
00423 return QVariant( entryPath() );
00424 else if ( _name == "DesktopEntryName")
00425 return QVariant( m_strDesktopEntryName );
00426 else if ( _name == "Categories")
00427 return QVariant( d->categories );
00428 else if ( _name == "Keywords")
00429 return QVariant( m_lstKeywords );
00430
00431
00432
00433
00434
00435
00436
00437 QVariant::Type t = KServiceTypeFactory::self()->findPropertyTypeByName(_name);
00438 if (t == QVariant::Invalid)
00439 {
00440 kdDebug(7012) << "Request for unknown property '" << _name << "'\n";
00441 return QVariant();
00442 }
00443
00444 QMap<QString,QVariant>::ConstIterator it = m_mapProps.find( _name );
00445 if ( (it == m_mapProps.end()) || (!it.data().isValid()))
00446 {
00447
00448 return QVariant();
00449 }
00450
00451 switch(t)
00452 {
00453 case QVariant::String:
00454 return it.data();
00455 case QVariant::Bool:
00456 case QVariant::Int:
00457 {
00458 QString aValue = it.data().toString();
00459 int val = 0;
00460 if (aValue == "true" || aValue == "on" || aValue == "yes")
00461 val = 1;
00462 else
00463 {
00464 bool bOK;
00465 val = aValue.toInt( &bOK );
00466 if( !bOK )
00467 val = 0;
00468 }
00469 if (t == QVariant::Bool)
00470 {
00471 if (val)
00472 return QVariant(true);
00473 else
00474 return QVariant(false);
00475 }
00476 return QVariant(val);
00477 }
00478 default:
00479
00480 KServiceReadProperty ksrp(_name, it.data().toString().utf8());
00481 return ksrp.readPropertyEntry(_name, t);
00482 }
00483 }
00484
00485 QStringList KService::propertyNames() const
00486 {
00487 QStringList res;
00488
00489 QMap<QString,QVariant>::ConstIterator it = m_mapProps.begin();
00490 for( ; it != m_mapProps.end(); ++it )
00491 res.append( it.key() );
00492
00493 res.append( "Type" );
00494 res.append( "Name" );
00495 res.append( "Comment" );
00496 res.append( "GenericName" );
00497 res.append( "Icon" );
00498 res.append( "Exec" );
00499 res.append( "Terminal" );
00500 res.append( "TerminalOptions" );
00501 res.append( "Path" );
00502 res.append( "ServiceTypes" );
00503 res.append( "AllowAsDefault" );
00504 res.append( "InitialPreference" );
00505 res.append( "Library" );
00506 res.append( "DesktopEntryPath" );
00507 res.append( "DesktopEntryName" );
00508 res.append( "Keywords" );
00509 res.append( "Categories" );
00510
00511 return res;
00512 }
00513
00514 KService::List KService::allServices()
00515 {
00516 return KServiceFactory::self()->allServices();
00517 }
00518
00519 KService::Ptr KService::serviceByName( const QString& _name )
00520 {
00521 KService * s = KServiceFactory::self()->findServiceByName( _name );
00522 return KService::Ptr( s );
00523 }
00524
00525 KService::Ptr KService::serviceByDesktopPath( const QString& _name )
00526 {
00527 KService * s = KServiceFactory::self()->findServiceByDesktopPath( _name );
00528 return KService::Ptr( s );
00529 }
00530
00531 KService::Ptr KService::serviceByDesktopName( const QString& _name )
00532 {
00533 KService * s = KServiceFactory::self()->findServiceByDesktopName( _name );
00534 return KService::Ptr( s );
00535 }
00536
00537 KService::List KService::allInitServices()
00538 {
00539 return KServiceFactory::self()->allInitServices();
00540 }
00541
00542 bool KService::substituteUid() const {
00543 QVariant v = property("X-KDE-SubstituteUID");
00544 return v.isValid() && v.toBool();
00545 }
00546
00547 QString KService::username() const {
00548
00549 QString user;
00550 QVariant v = property("X-KDE-Username");
00551 user = v.isValid() ? v.toString() : QString::null;
00552 if (user.isEmpty())
00553 user = ::getenv("ADMIN_ACCOUNT");
00554 if (user.isEmpty())
00555 user = "root";
00556 return user;
00557 }
00558
00559 bool KService::noDisplay() const {
00560 QMap<QString,QVariant>::ConstIterator it = m_mapProps.find( "NoDisplay" );
00561 if ( (it == m_mapProps.end()) || (!it.data().isValid()))
00562 {
00563 return false;
00564 }
00565
00566 QString aValue = it.data().toString();
00567 if (aValue == "true" || aValue == "on" || aValue == "yes")
00568 return true;
00569 else
00570 return false;
00571 }
00572
00573 QString KService::parentApp() const {
00574 QMap<QString,QVariant>::ConstIterator it = m_mapProps.find( "X-KDE-ParentApp" );
00575 if ( (it == m_mapProps.end()) || (!it.data().isValid()))
00576 {
00577 return QString::null;
00578 }
00579
00580 return it.data().toString();
00581 }
00582
00583 bool KService::allowMultipleFiles() const {
00584
00585 if ( m_strExec.find( "%F" ) != -1 || m_strExec.find( "%U" ) != -1 ||
00586 m_strExec.find( "%N" ) != -1 || m_strExec.find( "%D" ) != -1 )
00587 return true;
00588 else
00589 return false;
00590 }
00591
00592 QStringList KService::categories() const
00593 {
00594 return d->categories;
00595 }
00596
00597
00598 void KService::virtual_hook( int id, void* data )
00599 { KSycocaEntry::virtual_hook( id, data ); }
00600