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