kdesktopfile.cpp

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 // $Id: kdesktopfile.cpp 465272 2005-09-29 09:47:40Z mueller $
00023 
00024 #include <stdlib.h>
00025 #include <unistd.h>
00026 
00027 #include <qfile.h>
00028 #include <qdir.h>
00029 #include <qtextstream.h>
00030 
00031 #include <kdebug.h>
00032 #include "kurl.h"
00033 #include "kconfigbackend.h"
00034 #include "kapplication.h"
00035 #include "kstandarddirs.h"
00036 #include "kmountpoint.h"
00037 #include "klocale.h"
00038 
00039 #include "kdesktopfile.h"
00040 #include "kdesktopfile.moc"
00041 
00042 KDesktopFile::KDesktopFile(const QString &fileName, bool bReadOnly,
00043                const char * resType)
00044   : KConfig(QString::fromLatin1(""), bReadOnly, false)
00045 {
00046   // KConfigBackEnd will try to locate the filename that is provided
00047   // based on the resource type specified, _only_ if the filename
00048   // is not an absolute path.
00049   backEnd->changeFileName(fileName, resType, false);
00050   setReadOnly(bReadOnly);
00051   reparseConfiguration();
00052   setDesktopGroup();
00053 }
00054 
00055 KDesktopFile::~KDesktopFile()
00056 {
00057   // no need to do anything
00058 }
00059 
00060 QString KDesktopFile::locateLocal(const QString &path)
00061 {
00062   QString local;
00063   if (path.endsWith(".directory"))
00064   {
00065     local = path;
00066     if (!QDir::isRelativePath(local))
00067     {
00068       // Relative wrt apps?
00069       local = KGlobal::dirs()->relativeLocation("apps", path);
00070     }
00071 
00072     if (QDir::isRelativePath(local))
00073     {
00074       local = ::locateLocal("apps", local); // Relative to apps
00075     }
00076     else
00077     {
00078       // XDG Desktop menu items come with absolute paths, we need to 
00079       // extract their relative path and then build a local path.
00080       local = KGlobal::dirs()->relativeLocation("xdgdata-dirs", local);
00081       if (!QDir::isRelativePath(local))
00082       {
00083         // Hm, that didn't work...
00084         // What now? Use filename only and hope for the best.
00085         local = path.mid(path.findRev('/')+1);
00086       }
00087       local = ::locateLocal("xdgdata-dirs", local);
00088     }
00089   }
00090   else
00091   {
00092     if (QDir::isRelativePath(path))
00093     {
00094       local = ::locateLocal("apps", path); // 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-apps", path);
00101       if (!QDir::isRelativePath(local))
00102       {
00103         // What now? Use filename only and hope for the best.
00104         local = path.mid(path.findRev('/')+1);
00105       }
00106       local = ::locateLocal("xdgdata-apps", local);
00107     }
00108   }
00109   return local;
00110 }
00111 
00112 bool KDesktopFile::isDesktopFile(const QString& path)
00113 {
00114   int len = path.length();
00115 
00116   if(len > 8 && path.right(8) == QString::fromLatin1(".desktop"))
00117     return true;
00118   else if(len > 7 && path.right(7) == QString::fromLatin1(".kdelnk"))
00119     return true;
00120   else
00121     return false;
00122 }
00123 
00124 bool KDesktopFile::isAuthorizedDesktopFile(const QString& path)
00125 {
00126   if (!kapp || kapp->authorize("run_desktop_files"))
00127      return true;
00128 
00129   if (path.isEmpty())
00130      return false; // Empty paths are not ok.
00131   
00132   if (QDir::isRelativePath(path))
00133      return true; // Relative paths are ok.
00134      
00135   KStandardDirs *dirs = KGlobal::dirs();
00136   if (QDir::isRelativePath( dirs->relativeLocation("apps", path) ))
00137      return true;
00138   if (QDir::isRelativePath( dirs->relativeLocation("xdgdata-apps", path) ))
00139      return true;
00140   if (QDir::isRelativePath( dirs->relativeLocation("services", path) ))
00141      return true;
00142   if (dirs->relativeLocation("data", path).startsWith("kdesktop/Desktop"))
00143      return true;
00144      
00145   kdWarning() << "Access to '" << path << "' denied because of 'run_desktop_files' restriction." << endl;
00146   return false;
00147 }
00148 
00149 QString KDesktopFile::readType() const
00150 {
00151   return readEntry("Type");
00152 }
00153 
00154 QString KDesktopFile::readIcon() const
00155 {
00156   return readEntry("Icon");
00157 }
00158 
00159 QString KDesktopFile::readName() const
00160 {
00161   QString englishName = readEntryUntranslated("Name");
00162   QString translateName = readEntry("Name");
00163   if(englishName == translateName)
00164   {
00165     KGlobal::locale()->insertCatalogue("menu-messages");
00166     QString newName = i18n(englishName.latin1());
00167     return newName;
00168   }
00169   else
00170     return translateName;
00171 }
00172 
00173 QString KDesktopFile::readComment() const
00174 {
00175   return readEntry("Comment");
00176 }
00177 
00178 QString KDesktopFile::readGenericName() const
00179 {
00180   return readEntry("GenericName");
00181 }
00182 
00183 QString KDesktopFile::readPath() const
00184 {
00185   return readPathEntry("Path");
00186 }
00187 
00188 QString KDesktopFile::readDevice() const
00189 {
00190   return readEntry("Dev");
00191 }
00192 
00193 QString KDesktopFile::readURL() const
00194 {
00195     if (hasDeviceType()) {
00196         QString device = readDevice();
00197         KMountPoint::List mountPoints = KMountPoint::possibleMountPoints();
00198     
00199         for(KMountPoint::List::ConstIterator it = mountPoints.begin();
00200             it != mountPoints.end(); ++it)
00201         {
00202             KMountPoint *mp = *it;
00203             if (mp->mountedFrom() == device)
00204             {
00205                 KURL u;
00206                 u.setPath( mp->mountPoint() );
00207                 return u.url();
00208             }
00209         }
00210         return QString::null;
00211     } else {
00212     QString url = readPathEntry("URL");
00213         if ( !url.isEmpty() && !QDir::isRelativePath(url) )
00214         {
00215             // Handle absolute paths as such (i.e. we need to escape them)
00216             KURL u;
00217             u.setPath( url );
00218             return u.url();
00219         }
00220         return url;
00221     }
00222 }
00223 
00224 QStringList KDesktopFile::readActions() const
00225 {
00226     return readListEntry("Actions", ';');
00227 }
00228 
00229 void KDesktopFile::setActionGroup(const QString &group)
00230 {
00231     setGroup(QString::fromLatin1("Desktop Action ") + group);
00232 }
00233 
00234 bool KDesktopFile::hasActionGroup(const QString &group) const
00235 {
00236   return hasGroup(QString::fromLatin1("Desktop Action ") + group);
00237 }
00238 
00239 bool KDesktopFile::hasLinkType() const
00240 {
00241   return readEntry("Type") == QString::fromLatin1("Link");
00242 }
00243 
00244 bool KDesktopFile::hasApplicationType() const
00245 {
00246   return readEntry("Type") == QString::fromLatin1("Application");
00247 }
00248 
00249 bool KDesktopFile::hasMimeTypeType() const
00250 {
00251   return readEntry("Type") == QString::fromLatin1("MimeType");
00252 }
00253 
00254 bool KDesktopFile::hasDeviceType() const
00255 {
00256   return readEntry("Type") == QString::fromLatin1("FSDev") ||
00257          readEntry("Type") == QString::fromLatin1("FSDevice");
00258 }
00259 
00260 bool KDesktopFile::tryExec() const
00261 {
00262   // Test for TryExec and "X-KDE-AuthorizeAction" 
00263   QString te = readPathEntry("TryExec");
00264 
00265   if (!te.isEmpty()) {
00266     if (!QDir::isRelativePath(te)) {
00267       if (::access(QFile::encodeName(te), X_OK))
00268     return false;
00269     } else {
00270       // !!! Sergey A. Sukiyazov <corwin@micom.don.ru> !!!
00271       // Environment PATH may contain filenames in 8bit locale cpecified
00272       // encoding (Like a filenames).
00273       QStringList dirs = QStringList::split(':', QFile::decodeName(::getenv("PATH")));
00274       QStringList::Iterator it(dirs.begin());
00275       bool match = false;
00276       for (; it != dirs.end(); ++it) {
00277     QString fName = *it + "/" + te;
00278     if (::access(QFile::encodeName(fName), X_OK) == 0)
00279     {
00280       match = true;
00281       break;
00282     }
00283       }
00284       // didn't match at all
00285       if (!match)
00286         return false;
00287     }
00288   }
00289   QStringList list = readListEntry("X-KDE-AuthorizeAction");
00290   if (kapp && !list.isEmpty())
00291   {
00292      for(QStringList::ConstIterator it = list.begin();
00293          it != list.end();
00294          ++it)
00295      {
00296         if (!kapp->authorize((*it).stripWhiteSpace()))
00297            return false;
00298      }
00299   }
00300   
00301   // See also KService::username()
00302   bool su = readBoolEntry("X-KDE-SubstituteUID");
00303   if (su)
00304   {
00305       QString user = readEntry("X-KDE-Username");
00306       if (user.isEmpty())
00307         user = ::getenv("ADMIN_ACCOUNT");
00308       if (user.isEmpty())
00309         user = "root";
00310       if (!kapp->authorize("user/"+user))
00311         return false;
00312   }
00313   
00314   return true;
00315 }
00316 
00320 QString
00321 KDesktopFile::fileName() const { return backEnd->fileName(); }
00322 
00326 QString
00327 KDesktopFile::resource() const { return backEnd->resource(); }
00328 
00329 QStringList
00330 KDesktopFile::sortOrder() const
00331 {
00332   return readListEntry("SortOrder");
00333 }
00334 
00335 void KDesktopFile::virtual_hook( int id, void* data )
00336 { KConfig::virtual_hook( id, data ); }
00337 
00338 QString KDesktopFile::readDocPath() const
00339 {
00340   // Depreciated, remove in KDE4 or 5?
00341   // See: http://www.freedesktop.org/Standards/desktop-entry-spec
00342   if(hasKey( "DocPath" ))
00343     return readPathEntry( "DocPath" );
00344 
00345   return readPathEntry( "X-DocPath" );
00346 }
00347 
00348 KDesktopFile* KDesktopFile::copyTo(const QString &file) const
00349 {
00350   KDesktopFile *config = new KDesktopFile(QString::null, false);
00351   KConfig::copyTo(file, config);
00352   config->setDesktopGroup();
00353   return config;
00354 }
00355 
00356 
KDE Home | KDE Accessibility Home | Description of Access Keys