KDECore
kdesktopfile.cpp
Go to the documentation of this file.
00001 /* 00002 This file is part of the KDE libraries 00003 Copyright (c) 1999 Pietro Iglio <iglio@kde.org> 00004 Copyright (c) 1999 Preston Brown <pbrown@kde.org> 00005 00006 This library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Library General Public 00008 License as published by the Free Software Foundation; either 00009 version 2 of the License, or (at your option) any later version. 00010 00011 This library is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 Library General Public License for more details. 00015 00016 You should have received a copy of the GNU Library General Public License 00017 along with this library; see the file COPYING.LIB. If not, write to 00018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00019 Boston, MA 02110-1301, USA. 00020 */ 00021 00022 #include "kdesktopfile.h" 00023 00024 #include <unistd.h> 00025 00026 #include <QtCore/QDir> 00027 #include <QtCore/QFileInfo> 00028 00029 #include <config.h> 00030 #include "kconfig_p.h" 00031 #include "kdebug.h" 00032 #include "kurl.h" 00033 #include "kconfiggroup.h" 00034 #include "kauthorized.h" 00035 #include "kstandarddirs.h" 00036 #include "kconfigini_p.h" 00037 #include "kde_file.h" 00038 00039 class KDesktopFilePrivate : public KConfigPrivate 00040 { 00041 public: 00042 KDesktopFilePrivate(const char * resourceType, const QString &fileName); 00043 KConfigGroup desktopGroup; 00044 }; 00045 00046 KDesktopFilePrivate::KDesktopFilePrivate(const char * resourceType, const QString &fileName) 00047 : KConfigPrivate(KGlobal::mainComponent(), KConfig::NoGlobals, resourceType) 00048 { 00049 mBackend = new KConfigIniBackend(); 00050 bDynamicBackend = false; 00051 changeFileName(fileName, resourceType); 00052 } 00053 00054 KDesktopFile::KDesktopFile(const char * resourceType, const QString &fileName) 00055 : KConfig(*new KDesktopFilePrivate(resourceType, fileName)) 00056 { 00057 Q_D(KDesktopFile); 00058 reparseConfiguration(); 00059 d->desktopGroup = KConfigGroup(this, "Desktop Entry"); 00060 } 00061 00062 KDesktopFile::KDesktopFile(const QString &fileName) 00063 : KConfig(*new KDesktopFilePrivate("apps", fileName)) // TODO KDE5: default to xdgdata-apps instead of apps 00064 { 00065 Q_D(KDesktopFile); 00066 reparseConfiguration(); 00067 d->desktopGroup = KConfigGroup(this, "Desktop Entry"); 00068 } 00069 00070 KDesktopFile::~KDesktopFile() 00071 { 00072 } 00073 00074 KConfigGroup KDesktopFile::desktopGroup() const 00075 { 00076 Q_D(const KDesktopFile); 00077 return d->desktopGroup; 00078 } 00079 00080 QString KDesktopFile::locateLocal(const QString &path) 00081 { 00082 QString local; 00083 if (path.endsWith(QLatin1String(".directory"))) 00084 { 00085 local = path; 00086 if (!QDir::isRelativePath(local)) 00087 { 00088 // Relative wrt apps? 00089 local = KGlobal::dirs()->relativeLocation("apps", path); 00090 } 00091 00092 if (QDir::isRelativePath(local)) 00093 { 00094 local = KStandardDirs::locateLocal("apps", local); // Relative to apps 00095 } 00096 else 00097 { 00098 // XDG Desktop menu items come with absolute paths, we need to 00099 // extract their relative path and then build a local path. 00100 local = KGlobal::dirs()->relativeLocation("xdgdata-dirs", local); 00101 if (!QDir::isRelativePath(local)) 00102 { 00103 // Hm, that didn't work... 00104 // What now? Use filename only and hope for the best. 00105 local = path.mid(path.lastIndexOf(QLatin1Char('/'))+1); 00106 } 00107 local = KStandardDirs::locateLocal("xdgdata-dirs", local); 00108 } 00109 } 00110 else 00111 { 00112 if (QDir::isRelativePath(path)) 00113 { 00114 local = KStandardDirs::locateLocal("apps", path); // Relative to apps 00115 } 00116 else 00117 { 00118 // XDG Desktop menu items come with absolute paths, we need to 00119 // extract their relative path and then build a local path. 00120 local = KGlobal::dirs()->relativeLocation("xdgdata-apps", path); 00121 if (!QDir::isRelativePath(local)) 00122 { 00123 // What now? Use filename only and hope for the best. 00124 local = path.mid(path.lastIndexOf(QLatin1Char('/'))+1); 00125 } 00126 local = KStandardDirs::locateLocal("xdgdata-apps", local); 00127 } 00128 } 00129 return local; 00130 } 00131 00132 bool KDesktopFile::isDesktopFile(const QString& path) 00133 { 00134 return (path.length() > 8 00135 && path.endsWith(QLatin1String(".desktop"))); 00136 } 00137 00138 bool KDesktopFile::isAuthorizedDesktopFile(const QString& path) 00139 { 00140 if (path.isEmpty()) 00141 return false; // Empty paths are not ok. 00142 00143 if (QDir::isRelativePath(path)) 00144 return true; // Relative paths are ok. 00145 00146 KStandardDirs *dirs = KGlobal::dirs(); 00147 QStringList kdePrefixes; 00148 kdePrefixes += dirs->resourceDirs("apps"); 00149 kdePrefixes += dirs->resourceDirs("services"); 00150 kdePrefixes += dirs->resourceDirs("xdgdata-apps"); 00151 kdePrefixes += dirs->resourceDirs("autostart"); 00152 00153 const QString realPath = KStandardDirs::realPath(path); 00154 00155 // Check if the .desktop file is installed as part of KDE or XDG. 00156 foreach (const QString &prefix, kdePrefixes) { 00157 if (realPath.startsWith(prefix)) 00158 return true; 00159 } 00160 00161 // Forbid desktop files outside of standard locations if kiosk is set so 00162 if (!KAuthorized::authorize(QLatin1String("run_desktop_files"))) { 00163 kWarning() << "Access to '" << path << "' denied because of 'run_desktop_files' restriction." << endl; 00164 return false; 00165 } 00166 00167 // Not otherwise permitted, so only allow if the file is executable, or if 00168 // owned by root (uid == 0) 00169 QFileInfo entryInfo( path ); 00170 if (entryInfo.isExecutable() || entryInfo.ownerId() == 0) 00171 return true; 00172 00173 kWarning() << "Access to '" << path << "' denied, not owned by root, executable flag not set." << endl; 00174 return false; 00175 } 00176 00177 QString KDesktopFile::readType() const 00178 { 00179 Q_D(const KDesktopFile); 00180 return d->desktopGroup.readEntry("Type", QString()); 00181 } 00182 00183 QString KDesktopFile::readIcon() const 00184 { 00185 Q_D(const KDesktopFile); 00186 return d->desktopGroup.readEntry("Icon", QString()); 00187 } 00188 00189 QString KDesktopFile::readName() const 00190 { 00191 Q_D(const KDesktopFile); 00192 return d->desktopGroup.readEntry("Name", QString()); 00193 } 00194 00195 QString KDesktopFile::readComment() const 00196 { 00197 Q_D(const KDesktopFile); 00198 return d->desktopGroup.readEntry("Comment", QString()); 00199 } 00200 00201 QString KDesktopFile::readGenericName() const 00202 { 00203 Q_D(const KDesktopFile); 00204 return d->desktopGroup.readEntry("GenericName", QString()); 00205 } 00206 00207 QString KDesktopFile::readPath() const 00208 { 00209 Q_D(const KDesktopFile); 00210 // NOT readPathEntry, it is not XDG-compliant. Path entries written by 00211 // KDE4 will be still treated as such, though. 00212 return d->desktopGroup.readEntry("Path", QString()); 00213 } 00214 00215 QString KDesktopFile::readDevice() const 00216 { 00217 Q_D(const KDesktopFile); 00218 return d->desktopGroup.readEntry("Dev", QString()); 00219 } 00220 00221 QString KDesktopFile::readUrl() const 00222 { 00223 Q_D(const KDesktopFile); 00224 if (hasDeviceType()) { 00225 return d->desktopGroup.readEntry("MountPoint", QString()); 00226 } else { 00227 // NOT readPathEntry (see readPath()) 00228 QString url = d->desktopGroup.readEntry("URL", QString()); 00229 if ( !url.isEmpty() && !QDir::isRelativePath(url) ) 00230 { 00231 // Handle absolute paths as such (i.e. we need to escape them) 00232 return KUrl(url).url(); 00233 } 00234 return url; 00235 } 00236 } 00237 00238 QStringList KDesktopFile::readActions() const 00239 { 00240 Q_D(const KDesktopFile); 00241 return d->desktopGroup.readXdgListEntry("Actions"); 00242 } 00243 00244 KConfigGroup KDesktopFile::actionGroup(const QString &group) 00245 { 00246 return KConfigGroup(this, QLatin1String("Desktop Action ") + group); 00247 } 00248 00249 const KConfigGroup KDesktopFile::actionGroup(const QString& group) const 00250 { 00251 return const_cast<KDesktopFile*>(this)->actionGroup(group); 00252 } 00253 00254 bool KDesktopFile::hasActionGroup(const QString &group) const 00255 { 00256 return hasGroup(QString(QLatin1String("Desktop Action ") + group).toUtf8().constData()); 00257 } 00258 00259 bool KDesktopFile::hasLinkType() const 00260 { 00261 return readType() == QLatin1String("Link"); 00262 } 00263 00264 bool KDesktopFile::hasApplicationType() const 00265 { 00266 return readType() == QLatin1String("Application"); 00267 } 00268 00269 bool KDesktopFile::hasMimeTypeType() const 00270 { 00271 return readType() == QLatin1String("MimeType"); 00272 } 00273 00274 bool KDesktopFile::hasDeviceType() const 00275 { 00276 return readType() == QLatin1String("FSDevice"); 00277 } 00278 00279 bool KDesktopFile::tryExec() const 00280 { 00281 Q_D(const KDesktopFile); 00282 // Test for TryExec and "X-KDE-AuthorizeAction" 00283 // NOT readPathEntry (see readPath()) 00284 QString te = d->desktopGroup.readEntry("TryExec", QString()); 00285 00286 if (!te.isEmpty()) { 00287 if (!QDir::isRelativePath(te)) { 00288 if (KDE::access(te, X_OK)) 00289 return false; 00290 } else { 00291 // !!! Sergey A. Sukiyazov <corwin@micom.don.ru> !!! 00292 // Environment PATH may contain filenames in 8bit locale specified 00293 // encoding (Like a filenames). 00294 const QStringList dirs = QFile::decodeName(qgetenv("PATH")) 00295 .split(QLatin1Char(KPATH_SEPARATOR), QString::SkipEmptyParts); 00296 QStringList::ConstIterator it(dirs.begin()); 00297 bool match = false; 00298 for (; it != dirs.end(); ++it) { 00299 QString fName = *it + QLatin1Char(KDIR_SEPARATOR) + te; 00300 if (KDE::access(fName, X_OK) == 0) 00301 { 00302 match = true; 00303 break; 00304 } 00305 } 00306 // didn't match at all 00307 if (!match) 00308 return false; 00309 } 00310 } 00311 const QStringList list = d->desktopGroup.readEntry("X-KDE-AuthorizeAction", QStringList()); 00312 if (!list.isEmpty()) 00313 { 00314 for(QStringList::ConstIterator it = list.begin(); 00315 it != list.end(); 00316 ++it) 00317 { 00318 if (!KAuthorized::authorize((*it).trimmed())) 00319 return false; 00320 } 00321 } 00322 00323 // See also KService::username() 00324 bool su = d->desktopGroup.readEntry("X-KDE-SubstituteUID", false); 00325 if (su) 00326 { 00327 QString user = d->desktopGroup.readEntry("X-KDE-Username", QString()); 00328 if (user.isEmpty()) 00329 user = QString::fromLocal8Bit(qgetenv("ADMIN_ACCOUNT")); 00330 if (user.isEmpty()) 00331 user = QString::fromLatin1("root"); 00332 if (!KAuthorized::authorize(QString::fromLatin1("user/")+user)) 00333 return false; 00334 } 00335 00336 return true; 00337 } 00338 00342 //QString KDesktopFile::fileName() const { return backEnd->fileName(); } 00343 00347 //QString 00348 //KDesktopFile::resource() const { return backEnd->resource(); } 00349 00350 QStringList 00351 KDesktopFile::sortOrder() const 00352 { 00353 Q_D(const KDesktopFile); 00354 return d->desktopGroup.readEntry("SortOrder", QStringList()); 00355 } 00356 00357 //void KDesktopFile::virtual_hook( int id, void* data ) 00358 //{ KConfig::virtual_hook( id, data ); } 00359 00360 QString KDesktopFile::readDocPath() const 00361 { 00362 Q_D(const KDesktopFile); 00363 //legacy entry in kde3 apps 00364 if(d->desktopGroup.hasKey( "DocPath" )) 00365 return d->desktopGroup.readPathEntry( "DocPath", QString() ); 00366 return d->desktopGroup.readPathEntry( "X-DocPath", QString() ); 00367 } 00368 00369 KDesktopFile* KDesktopFile::copyTo(const QString &file) const 00370 { 00371 KDesktopFile *config = new KDesktopFile(QString()); 00372 this->KConfig::copyTo(file, config); 00373 // config->setDesktopGroup(); 00374 return config; 00375 } 00376 00377 const char *KDesktopFile::resource() const 00378 { 00379 Q_D(const KDesktopFile); 00380 return d->resourceType; 00381 } 00382 00383 QString KDesktopFile::fileName() const 00384 { 00385 return name(); 00386 } 00387 00388 bool KDesktopFile::noDisplay() const 00389 { 00390 Q_D(const KDesktopFile); 00391 if (d->desktopGroup.readEntry("NoDisplay", false)) { 00392 return true; 00393 } 00394 if (d->desktopGroup.hasKey("OnlyShowIn")) { 00395 if (!d->desktopGroup.readXdgListEntry("OnlyShowIn").contains(QLatin1String("KDE"))) 00396 return true; 00397 } 00398 if (d->desktopGroup.hasKey("NotShowIn")) { 00399 if (d->desktopGroup.readXdgListEntry("NotShowIn").contains(QLatin1String("KDE"))) 00400 return true; 00401 } 00402 return false; 00403 }
KDE 4.6 API Reference