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