• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.8.3 API Reference
  • KDE Home
  • Contact Us
 

KDECore

kstandarddirs.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE libraries
00002    Copyright (C) 1999 Sirtaj Singh Kang <taj@kde.org>
00003    Copyright (C) 1999,2007 Stephan Kulow <coolo@kde.org>
00004    Copyright (C) 1999 Waldo Bastian <bastian@kde.org>
00005    Copyright (C) 2009 David Faure <faure@kde.org>
00006 
00007    This library is free software; you can redistribute it and/or
00008    modify it under the terms of the GNU Library General Public
00009    License version 2 as published by the Free Software Foundation.
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 /*
00023  * Author: Stephan Kulow <coolo@kde.org> and Sirtaj Singh Kang <taj@kde.org>
00024  * Generated: Thu Mar  5 16:05:28 EST 1998
00025  */
00026 
00027 #include "kstandarddirs.h"
00028 #include "kconfig.h"
00029 #include "kconfiggroup.h"
00030 #include "kdebug.h"
00031 #include "kcomponentdata.h"
00032 #include "kshell.h"
00033 #include "kuser.h"
00034 #include "kde_file.h"
00035 #include "kkernel_win.h"
00036 #include "kkernel_mac.h"
00037 #include "klocale.h"
00038 
00039 #include <config.h>
00040 #include <config-prefix.h>
00041 #include <config-kstandarddirs.h>
00042 
00043 #include <stdlib.h>
00044 #include <assert.h>
00045 #include <errno.h>
00046 #ifdef HAVE_SYS_STAT_H
00047 #include <sys/stat.h>
00048 #endif
00049 #ifdef HAVE_UNISTD_H
00050 #include <unistd.h>
00051 #endif
00052 #include <sys/param.h>
00053 #include <sys/types.h>
00054 #include <dirent.h>
00055 #include <pwd.h>
00056 #include <grp.h>
00057 #ifdef Q_WS_WIN
00058 #include <windows.h>
00059 #ifdef _WIN32_WCE
00060 #include <basetyps.h>
00061 #endif
00062 #ifdef Q_WS_WIN64
00063 // FIXME: did not find a reliable way to fix with kdewin mingw header
00064 #define interface struct
00065 #endif
00066 #include <shlobj.h>
00067 #include <QtCore/QVarLengthArray>
00068 #endif
00069 
00070 #include <QtCore/QMutex>
00071 #include <QtCore/QRegExp>
00072 #include <QtCore/QDir>
00073 #include <QtCore/QFileInfo>
00074 #include <QtCore/QSettings>
00075 
00076 class KStandardDirs::KStandardDirsPrivate
00077 {
00078 public:
00079     KStandardDirsPrivate(KStandardDirs* qq)
00080         : m_restrictionsActive(false),
00081           m_checkRestrictions(true),
00082           m_cacheMutex(QMutex::Recursive), // resourceDirs is recursive
00083           q(qq)
00084     { }
00085 
00086     bool hasDataRestrictions(const QString &relPath) const;
00087     QStringList resourceDirs(const char* type, const QString& subdirForRestrictions);
00088     void createSpecialResource(const char*);
00089 
00090     bool m_restrictionsActive : 1;
00091     bool m_checkRestrictions : 1;
00092     QMap<QByteArray, bool> m_restrictions;
00093 
00094     QStringList xdgdata_prefixes;
00095     QStringList xdgconf_prefixes;
00096     QStringList m_prefixes;
00097 
00098     // Directory dictionaries
00099     QMap<QByteArray, QStringList> m_absolutes; // For each resource type, the list of absolute paths, from most local (most priority) to most global
00100     QMap<QByteArray, QStringList> m_relatives; // Same with relative paths
00101     // The search path is "all relative paths" < "all absolute paths", from most priority to least priority.
00102 
00103     // Caches (protected by mutex in const methods, cf ctor docu)
00104     QMap<QByteArray, QStringList> m_dircache;
00105     QMap<QByteArray, QString> m_savelocations;
00106     QMutex m_cacheMutex;
00107 
00108     KStandardDirs* q;
00109 };
00110 
00111 /* If you add a new resource type here, make sure to
00112  * 1) regenerate using "kdesdk/scripts/generate_string_table.pl types < tmpfile" with the data below in tmpfile.
00113  * 2) update the KStandardDirs class documentation
00114  * 3) update the list in kde-config.cpp
00115 
00116 data
00117 share/apps
00118 html
00119 share/doc/HTML
00120 icon
00121 share/icons
00122 config
00123 share/config
00124 pixmap
00125 share/pixmaps
00126 apps
00127 share/applnk
00128 sound
00129 share/sounds
00130 locale
00131 share/locale
00132 services
00133 share/kde4/services
00134 servicetypes
00135 share/kde4/servicetypes
00136 mime
00137 share/mimelnk
00138 cgi
00139 cgi-bin
00140 wallpaper
00141 share/wallpapers
00142 templates
00143 share/templates
00144 exe
00145 bin
00146 module
00147 %lib/kde4
00148 qtplugins
00149 %lib/kde4/plugins
00150 kcfg
00151 share/config.kcfg
00152 emoticons
00153 share/emoticons
00154 xdgdata-apps
00155 applications
00156 xdgdata-icon
00157 icons
00158 xdgdata-pixmap
00159 pixmaps
00160 xdgdata-dirs
00161 desktop-directories
00162 xdgdata-mime
00163 mime
00164 xdgconf-menu
00165 menus
00166 xdgconf-autostart
00167 autostart
00168 */
00169 
00170 static const char types_string[] =
00171     "data\0"
00172     "share/apps\0"
00173     "html\0"
00174     "share/doc/HTML\0"
00175     "icon\0"
00176     "share/icons\0"
00177     "config\0"
00178     "share/config\0"
00179     "pixmap\0"
00180     "share/pixmaps\0"
00181     "apps\0"
00182     "share/applnk\0"
00183     "sound\0"
00184     "share/sounds\0"
00185     "locale\0"
00186     "share/locale\0"
00187     "services\0"
00188     "share/kde4/services\0"
00189     "servicetypes\0"
00190     "share/kde4/servicetypes\0"
00191     "mime\0"
00192     "share/mimelnk\0"
00193     "cgi\0"
00194     "cgi-bin\0"
00195     "wallpaper\0"
00196     "share/wallpapers\0"
00197     "templates\0"
00198     "share/templates\0"
00199     "exe\0"
00200     "bin\0"
00201     "module\0"
00202     "%lib/kde4\0"
00203     "qtplugins\0"
00204     "%lib/kde4/plugins\0"
00205     "kcfg\0"
00206     "share/config.kcfg\0"
00207     "emoticons\0"
00208     "share/emoticons\0"
00209     "xdgdata-apps\0"
00210     "applications\0"
00211     "xdgdata-icon\0"
00212     "icons\0"
00213     "xdgdata-pixmap\0"
00214     "pixmaps\0"
00215     "xdgdata-dirs\0"
00216     "desktop-directories\0"
00217     "xdgdata-mime\0"
00218     "xdgconf-menu\0"
00219     "menus\0"
00220     "xdgconf-autostart\0"
00221     "autostart\0"
00222     "\0";
00223 
00224 static const int types_indices[] = {
00225     0,    5,   16,   21,   36,   41,   53,   60,
00226     73,   80,   94,   99,  112,  118,  131,  138,
00227     151,  160,  180,  193,  217,  222,  236,  240,
00228     248,  258,  275,  285,  301,  305,  309,  316,
00229     326,  336,  354,  359,  377,  387,  403,  416,
00230     429,  442,  448,  463,  471,  484,  504,  217,
00231     517,  530,  536,  554,  -1
00232 };
00233 
00234 static void tokenize(QStringList& token, const QString& str,
00235                      const QString& delim);
00236 
00237 KStandardDirs::KStandardDirs()
00238     : d(new KStandardDirsPrivate(this))
00239 {
00240     addKDEDefaults();
00241 }
00242 
00243 KStandardDirs::~KStandardDirs()
00244 {
00245     delete d;
00246 }
00247 
00248 bool KStandardDirs::isRestrictedResource(const char *type, const QString& relPath) const
00249 {
00250     if (!d->m_restrictionsActive)
00251         return false;
00252 
00253     if (d->m_restrictions.value(type, false))
00254         return true;
00255 
00256     if (strcmp(type, "data")==0 && d->hasDataRestrictions(relPath))
00257         return true;
00258 
00259     return false;
00260 }
00261 
00262 bool KStandardDirs::KStandardDirsPrivate::hasDataRestrictions(const QString &relPath) const
00263 {
00264     QString key;
00265     const int i = relPath.indexOf(QLatin1Char('/'));
00266     if (i != -1)
00267         key = QString::fromLatin1("data_") + relPath.left(i);
00268     else
00269         key = QString::fromLatin1("data_") + relPath;
00270 
00271     return m_restrictions.value(key.toLatin1(), false);
00272 }
00273 
00274 
00275 QStringList KStandardDirs::allTypes() const
00276 {
00277     QStringList list;
00278     for (int i = 0; types_indices[i] != -1; i += 2)
00279         list.append(QLatin1String(types_string + types_indices[i]));
00280     // Those are added manually by addKDEDefaults
00281     list.append(QString::fromLatin1("lib"));
00282     //list.append(QString::fromLatin1("home")); // undocumented on purpose, said Waldo in r113855.
00283 
00284     // Those are handled by resourceDirs() itself
00285     list.append(QString::fromLatin1("socket"));
00286     list.append(QString::fromLatin1("tmp"));
00287     list.append(QString::fromLatin1("cache"));
00288     // Those are handled by installPath()
00289     list.append(QString::fromLatin1("include"));
00290 
00291     // If you add anything here, make sure kde-config.cpp has a description for it.
00292 
00293     return list;
00294 }
00295 
00296 static void priorityAdd(QStringList &prefixes, const QString& dir, bool priority)
00297 {
00298     if (priority && !prefixes.isEmpty())
00299     {
00300         // Add in front but behind $KDEHOME
00301         QStringList::iterator it = prefixes.begin();
00302         it++;
00303         prefixes.insert(it, dir);
00304     }
00305     else
00306     {
00307         prefixes.append(dir);
00308     }
00309 }
00310 
00311 void KStandardDirs::addPrefix( const QString& _dir )
00312 {
00313     addPrefix(_dir, false);
00314 }
00315 
00316 void KStandardDirs::addPrefix( const QString& _dir, bool priority )
00317 {
00318     if (_dir.isEmpty())
00319         return;
00320 
00321     QString dir = _dir;
00322     if (dir.at(dir.length() - 1) != QLatin1Char('/'))
00323         dir += QLatin1Char('/');
00324 
00325     if (!d->m_prefixes.contains(dir)) {
00326         priorityAdd(d->m_prefixes, dir, priority);
00327         d->m_dircache.clear();
00328     }
00329 }
00330 
00331 void KStandardDirs::addXdgConfigPrefix( const QString& _dir )
00332 {
00333     addXdgConfigPrefix(_dir, false);
00334 }
00335 
00336 void KStandardDirs::addXdgConfigPrefix( const QString& _dir, bool priority )
00337 {
00338     if (_dir.isEmpty())
00339         return;
00340 
00341     QString dir = _dir;
00342     if (dir.at(dir.length() - 1) != QLatin1Char('/'))
00343         dir += QLatin1Char('/');
00344 
00345     if (!d->xdgconf_prefixes.contains(dir)) {
00346         priorityAdd(d->xdgconf_prefixes, dir, priority);
00347         d->m_dircache.clear();
00348     }
00349 }
00350 
00351 void KStandardDirs::addXdgDataPrefix( const QString& _dir )
00352 {
00353     addXdgDataPrefix(_dir, false);
00354 }
00355 
00356 void KStandardDirs::addXdgDataPrefix( const QString& _dir, bool priority )
00357 {
00358     if (_dir.isEmpty())
00359         return;
00360 
00361     QString dir = _dir;
00362     if (dir.at(dir.length() - 1) != QLatin1Char('/'))
00363         dir += QLatin1Char('/');
00364 
00365     if (!d->xdgdata_prefixes.contains(dir)) {
00366         priorityAdd(d->xdgdata_prefixes, dir, priority);
00367         d->m_dircache.clear();
00368     }
00369 }
00370 
00371 QString KStandardDirs::kfsstnd_prefixes()
00372 {
00373     return d->m_prefixes.join(QString(QLatin1Char(KPATH_SEPARATOR)));
00374 }
00375 
00376 QString KStandardDirs::kfsstnd_xdg_conf_prefixes()
00377 {
00378     return d->xdgconf_prefixes.join(QString(QLatin1Char(KPATH_SEPARATOR)));
00379 }
00380 
00381 QString KStandardDirs::kfsstnd_xdg_data_prefixes()
00382 {
00383     return d->xdgdata_prefixes.join(QString(QLatin1Char(KPATH_SEPARATOR)));
00384 }
00385 
00386 #ifndef KDE_NO_DEPRECATED
00387 bool KStandardDirs::addResourceType( const char *type,
00388                                      const QString& relativename,
00389                                      bool priority )
00390 {
00391     return addResourceType( type, 0, relativename, priority);
00392 }
00393 #endif
00394 
00395 bool KStandardDirs::addResourceType( const char *type,
00396                                      const char *basetype,
00397                                      const QString& relativename,
00398                                      bool priority )
00399 {
00400     if (relativename.isEmpty())
00401         return false;
00402 
00403     QString copy = relativename;
00404     if (basetype)
00405         copy = QLatin1Char('%') + QString::fromLatin1(basetype) + QLatin1Char('/') + relativename;
00406 
00407     if (!copy.endsWith(QLatin1Char('/')))
00408         copy += QLatin1Char('/');
00409 
00410     QByteArray typeBa = type;
00411     QStringList& rels = d->m_relatives[typeBa]; // find or insert
00412 
00413     if (!rels.contains(copy)) {
00414         if (priority)
00415             rels.prepend(copy);
00416         else
00417             rels.append(copy);
00418         // clean the caches
00419         d->m_dircache.remove(typeBa);
00420         d->m_savelocations.remove(typeBa);
00421         return true;
00422     }
00423     return false;
00424 }
00425 
00426 bool KStandardDirs::addResourceDir( const char *type,
00427                                     const QString& absdir,
00428                                     bool priority)
00429 {
00430     if (absdir.isEmpty() || !type)
00431       return false;
00432     // find or insert entry in the map
00433     QString copy = absdir;
00434     if (copy.at(copy.length() - 1) != QLatin1Char('/'))
00435         copy += QLatin1Char('/');
00436 
00437     QByteArray typeBa = type;
00438     QStringList &paths = d->m_absolutes[typeBa];
00439     if (!paths.contains(copy)) {
00440         if (priority)
00441             paths.prepend(copy);
00442         else
00443             paths.append(copy);
00444         // clean the caches
00445         d->m_dircache.remove(typeBa);
00446         d->m_savelocations.remove(typeBa);
00447         return true;
00448     }
00449     return false;
00450 }
00451 
00452 QString KStandardDirs::findResource( const char *type,
00453                                      const QString& _filename ) const
00454 {
00455     if (!QDir::isRelativePath(_filename))
00456       return !KGlobal::hasLocale() ? _filename // absolute dirs are absolute dirs, right? :-/
00457                                    : KGlobal::locale()->localizedFilePath(_filename); // -- almost.
00458 
00459 #if 0
00460     kDebug(180) << "Find resource: " << type;
00461     for (QStringList::ConstIterator pit = m_prefixes.begin();
00462          pit != m_prefixes.end();
00463          ++pit)
00464     {
00465         kDebug(180) << "Prefix: " << *pit;
00466     }
00467 #endif
00468 
00469     QString filename(_filename);
00470 #ifdef Q_OS_WIN
00471     if(strcmp(type, "exe") == 0) {
00472       if(!filename.endsWith(QLatin1String(".exe")))
00473         filename += QLatin1String(".exe");
00474     }
00475 #endif
00476     const QString dir = findResourceDir(type, filename);
00477     if (dir.isEmpty())
00478       return dir;
00479     else
00480       return !KGlobal::hasLocale() ? dir + filename
00481                                    : KGlobal::locale()->localizedFilePath(dir + filename);
00482 }
00483 
00484 static quint32 updateHash(const QString &file, quint32 hash)
00485 {
00486     KDE_struct_stat buff;
00487     if ((KDE::access(file, R_OK) == 0) && (KDE::stat(file, &buff) == 0) && (S_ISREG(buff.st_mode))) {
00488         hash = hash + static_cast<quint32>(buff.st_ctime);
00489     }
00490     return hash;
00491 }
00492 
00493 quint32 KStandardDirs::calcResourceHash( const char *type,
00494                                          const QString& filename,
00495                                          SearchOptions options ) const
00496 {
00497     quint32 hash = 0;
00498 
00499     if (!QDir::isRelativePath(filename))
00500     {
00501         // absolute dirs are absolute dirs, right? :-/
00502         return updateHash(filename, hash);
00503     }
00504     QStringList candidates = d->resourceDirs(type, filename);
00505 
00506     foreach ( const QString& candidate, candidates )
00507     {
00508         hash = updateHash(candidate + filename, hash);
00509         if (  !( options & Recursive ) && hash ) {
00510             return hash;
00511         }
00512     }
00513     return hash;
00514 }
00515 
00516 
00517 QStringList KStandardDirs::findDirs( const char *type,
00518                                      const QString& reldir ) const
00519 {
00520     QDir testdir;
00521     QStringList list;
00522     if (!QDir::isRelativePath(reldir))
00523     {
00524         testdir.setPath(reldir);
00525         if (testdir.exists())
00526         {
00527             if (reldir.endsWith(QLatin1Char('/')))
00528                 list.append(reldir);
00529             else
00530                 list.append(reldir+QLatin1Char('/'));
00531         }
00532         return list;
00533     }
00534 
00535     const QStringList candidates = d->resourceDirs(type, reldir);
00536 
00537     for (QStringList::ConstIterator it = candidates.begin();
00538          it != candidates.end(); ++it) {
00539         testdir.setPath(*it + reldir);
00540         if (testdir.exists())
00541             list.append(testdir.absolutePath() + QLatin1Char('/'));
00542     }
00543 
00544     return list;
00545 }
00546 
00547 QString KStandardDirs::findResourceDir( const char *type,
00548                                         const QString& _filename) const
00549 {
00550 #ifndef NDEBUG
00551     if (_filename.isEmpty()) {
00552         kWarning() << "filename for type " << type << " in KStandardDirs::findResourceDir is not supposed to be empty!!";
00553         return QString();
00554     }
00555 #endif
00556 
00557     QString filename(_filename);
00558 #ifdef Q_OS_WIN
00559     if(strcmp(type, "exe") == 0) {
00560       if(!filename.endsWith(QLatin1String(".exe")))
00561         filename += QLatin1String(".exe");
00562     }
00563 #endif
00564     const QStringList candidates = d->resourceDirs(type, filename);
00565 
00566     for (QStringList::ConstIterator it = candidates.begin();
00567          it != candidates.end(); ++it) {
00568         if (exists(*it + filename)) {
00569             return *it;
00570         }
00571     }
00572 
00573 #ifndef NDEBUG
00574     if(false && strcmp(type, "locale"))
00575         kDebug(180) << "KStdDirs::findResDir(): can't find \"" << filename << "\" in type \"" << type << "\".";
00576 #endif
00577 
00578     return QString();
00579 }
00580 
00581 bool KStandardDirs::exists(const QString &fullPath)
00582 {
00583 #ifdef Q_OS_WIN
00584     // access() and stat() give a stupid error message to the user
00585     // if the path is not accessible at all (e.g. no disk in A:/ and
00586     // we do stat("A:/.directory")
00587     if (fullPath.endsWith(QLatin1Char('/')))
00588         return QDir(fullPath).exists();
00589     return QFileInfo(fullPath).exists();
00590 #else
00591     KDE_struct_stat buff;
00592     QByteArray cFullPath = QFile::encodeName(fullPath);
00593     if (access(cFullPath, R_OK) == 0 && KDE_stat( cFullPath, &buff ) == 0) {
00594         if (!fullPath.endsWith(QLatin1Char('/'))) {
00595             if (S_ISREG( buff.st_mode ))
00596                 return true;
00597         } else
00598             if (S_ISDIR( buff.st_mode ))
00599                 return true;
00600     }
00601     return false;
00602 #endif
00603 }
00604 
00605 static void lookupDirectory(const QString& path, const QString &relPart,
00606                             const QRegExp &regexp,
00607                             QStringList& list,
00608                             QStringList& relList,
00609                             bool recursive, bool unique)
00610 {
00611     const QString pattern = regexp.pattern();
00612     if (recursive || pattern.contains(QLatin1Char('?')) || pattern.contains(QLatin1Char('*')))
00613     {
00614         if (path.isEmpty()) //for sanity
00615             return;
00616 #ifdef Q_WS_WIN
00617         QString path_ = path + QLatin1String( "*.*" );
00618         WIN32_FIND_DATA findData;
00619         HANDLE hFile = FindFirstFile( (LPWSTR)path_.utf16(), &findData );
00620         if( hFile == INVALID_HANDLE_VALUE )
00621             return;
00622         do {
00623             const int len = wcslen( findData.cFileName );
00624             if (!( findData.cFileName[0] == '.' &&
00625                    findData.cFileName[1] == '\0' ) &&
00626                 !( findData.cFileName[0] == '.' &&
00627                    findData.cFileName[1] == '.' &&
00628                    findData.cFileName[2] == '\0' ) &&
00629                  ( findData.cFileName[len-1] != '~' ) ) {
00630                 QString fn = QString::fromUtf16( (const unsigned short*)findData.cFileName );
00631                 if (!recursive && !regexp.exactMatch(fn))
00632                     continue; // No match
00633                 QString pathfn = path + fn;
00634                 bool bIsDir = ( ( findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) == FILE_ATTRIBUTE_DIRECTORY );
00635                 if ( recursive ) {
00636                     if ( bIsDir ) {
00637                         lookupDirectory(pathfn + QLatin1Char('/'),
00638                                         relPart + fn + QLatin1Char('/'),
00639                                         regexp, list, relList, recursive, unique);
00640                     }
00641                     if (!regexp.exactMatch(fn))
00642                         continue; // No match
00643                 }
00644                 if ( !bIsDir )
00645                 {
00646                     if ( !unique || !relList.contains(relPart + fn) )
00647                     {
00648                         list.append( pathfn );
00649                         relList.append( relPart + fn );
00650                     }
00651                 }
00652             }
00653         } while( FindNextFile( hFile, &findData ) != 0 );
00654         FindClose( hFile );
00655 #else
00656         // We look for a set of files.
00657         DIR *dp = opendir( QFile::encodeName(path));
00658         if (!dp)
00659             return;
00660 
00661         assert(path.endsWith(QLatin1Char('/')));
00662 
00663         struct dirent *ep;
00664 
00665         while( ( ep = readdir( dp ) ) != 0L )
00666         {
00667             QString fn( QFile::decodeName(ep->d_name));
00668             if (fn == QString::fromLatin1(".") || fn == QString::fromLatin1("..") || fn.at(fn.length() - 1) == QLatin1Char('~'))
00669                 continue;
00670 
00671             if (!recursive && !regexp.exactMatch(fn))
00672                 continue; // No match
00673 
00674             bool isDir;
00675             bool isReg;
00676 
00677             QString pathfn = path + fn;
00678 #ifdef HAVE_DIRENT_D_TYPE
00679             isDir = ep->d_type == DT_DIR;
00680             isReg = ep->d_type == DT_REG;
00681 
00682             if (ep->d_type == DT_UNKNOWN || ep->d_type == DT_LNK)
00683 #endif
00684             {
00685                 KDE_struct_stat buff;
00686                 if ( KDE::stat( pathfn, &buff ) != 0 ) {
00687                     kDebug(180) << "Error stat'ing " << pathfn << " : " << perror;
00688                     continue; // Couldn't stat (e.g. no read permissions)
00689                 }
00690                 isReg = S_ISREG (buff.st_mode);
00691                 isDir = S_ISDIR (buff.st_mode);
00692             }
00693 
00694             if ( recursive ) {
00695                 if ( isDir ) {
00696                     lookupDirectory(pathfn + QLatin1Char('/'), relPart + fn + QLatin1Char('/'), regexp, list, relList, recursive, unique);
00697                 }
00698                 if (!regexp.exactMatch(fn))
00699                     continue; // No match
00700             }
00701             if ( isReg )
00702             {
00703                 if (!unique || !relList.contains(relPart + fn))
00704                 {
00705                     list.append( pathfn );
00706                     relList.append( relPart + fn );
00707                 }
00708             }
00709         }
00710         closedir( dp );
00711 #endif
00712     }
00713     else
00714     {
00715         // We look for a single file.
00716         QString fn = pattern;
00717         QString pathfn = path + fn;
00718         KDE_struct_stat buff;
00719         if ( KDE::stat( pathfn, &buff ) != 0 )
00720             return; // File not found
00721         if ( S_ISREG( buff.st_mode))
00722         {
00723             if (!unique || !relList.contains(relPart + fn))
00724             {
00725                 list.append( pathfn );
00726                 relList.append( relPart + fn );
00727             }
00728         }
00729     }
00730 }
00731 
00732 static void lookupPrefix(const QString& prefix, const QString& relpath,
00733                          const QString& relPart,
00734                          const QRegExp &regexp,
00735                          QStringList& list,
00736                          QStringList& relList,
00737                          bool recursive, bool unique)
00738 {
00739     if (relpath.isEmpty()) {
00740         if (recursive)
00741             Q_ASSERT(prefix != QLatin1String("/")); // we don't want to recursively list the whole disk!
00742         lookupDirectory(prefix, relPart, regexp, list,
00743                         relList, recursive, unique);
00744         return;
00745     }
00746     QString path;
00747     QString rest;
00748 
00749     int slash = relpath.indexOf(QLatin1Char('/'));
00750     if (slash < 0)
00751         rest = relpath.left(relpath.length() - 1);
00752     else {
00753         path = relpath.left(slash);
00754         rest = relpath.mid(slash + 1);
00755     }
00756 
00757     if (prefix.isEmpty()) //for sanity
00758         return;
00759 #ifndef Q_WS_WIN
00760     // what does this assert check ?
00761     assert(prefix.endsWith(QLatin1Char('/')));
00762 #endif
00763     if (path.contains(QLatin1Char('*')) || path.contains(QLatin1Char('?'))) {
00764 
00765         QRegExp pathExp(path, Qt::CaseSensitive, QRegExp::Wildcard);
00766 
00767 #ifdef Q_WS_WIN
00768         QString prefix_ = prefix + QLatin1String( "*.*" );
00769         WIN32_FIND_DATA findData;
00770         HANDLE hFile = FindFirstFile( (LPWSTR)prefix_.utf16(), &findData );
00771         if( hFile == INVALID_HANDLE_VALUE )
00772             return;
00773         do {
00774             const int len = wcslen( findData.cFileName );
00775             if (!( findData.cFileName[0] == '.' &&
00776                    findData.cFileName[1] == '\0' ) &&
00777                 !( findData.cFileName[0] == '.' &&
00778                    findData.cFileName[1] == '.' &&
00779                    findData.cFileName[2] == '\0' ) &&
00780                  ( findData.cFileName[len-1] != '~' ) ) {
00781                 const QString fn = QString::fromUtf16( (const unsigned short*)findData.cFileName );
00782                 if ( !pathExp.exactMatch(fn) )
00783                     continue; // No match
00784                 if ( ( findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) == FILE_ATTRIBUTE_DIRECTORY )
00785                     lookupPrefix(prefix + fn + QLatin1Char('/'),
00786                                  rest, relPart + fn + QLatin1Char('/'),
00787                                  regexp, list, relList, recursive, unique);
00788             }
00789         } while( FindNextFile( hFile, &findData ) != 0 );
00790         FindClose( hFile );
00791 #else
00792         DIR *dp = opendir( QFile::encodeName(prefix) );
00793         if (!dp) {
00794             return;
00795         }
00796 
00797         struct dirent *ep;
00798 
00799         while( ( ep = readdir( dp ) ) != 0L )
00800         {
00801             QString fn( QFile::decodeName(ep->d_name));
00802             if (fn == QLatin1String(".") || fn == QLatin1String("..") || fn.at(fn.length() - 1) == QLatin1Char('~'))
00803                 continue;
00804 
00805             if ( !pathExp.exactMatch(fn) )
00806                 continue; // No match
00807             QString rfn = relPart+fn;
00808             fn = prefix + fn;
00809 
00810             bool isDir;
00811 
00812 #ifdef HAVE_DIRENT_D_TYPE
00813             isDir = ep->d_type == DT_DIR;
00814 
00815             if (ep->d_type == DT_UNKNOWN || ep->d_type == DT_LNK)
00816 #endif
00817             {
00818                 QString pathfn = path + fn;
00819                 KDE_struct_stat buff;
00820                 if ( KDE::stat( fn, &buff ) != 0 ) {
00821                     kDebug(180) << "Error stat'ing " << fn << " : " << perror;
00822                     continue; // Couldn't stat (e.g. no read permissions)
00823                 }
00824                 isDir = S_ISDIR (buff.st_mode);
00825             }
00826             if ( isDir )
00827                 lookupPrefix(fn + QLatin1Char('/'), rest, rfn + QLatin1Char('/'), regexp, list, relList, recursive, unique);
00828         }
00829 
00830         closedir( dp );
00831 #endif
00832     } else {
00833         // Don't stat, if the dir doesn't exist we will find out
00834         // when we try to open it.
00835         lookupPrefix(prefix + path + QLatin1Char('/'), rest,
00836                      relPart + path + QLatin1Char('/'), regexp, list,
00837                      relList, recursive, unique);
00838     }
00839 }
00840 
00841 QStringList
00842 KStandardDirs::findAllResources( const char *type,
00843                                  const QString& filter,
00844                                  SearchOptions options,
00845                                  QStringList &relList) const
00846 {
00847     QString filterPath;
00848     QString filterFile;
00849 
00850     if ( !filter.isEmpty() )
00851     {
00852         int slash = filter.lastIndexOf(QLatin1Char('/'));
00853         if (slash < 0) {
00854             filterFile = filter;
00855         } else {
00856             filterPath = filter.left(slash + 1);
00857             filterFile = filter.mid(slash + 1);
00858         }
00859     }
00860 
00861     QStringList candidates;
00862     if ( !QDir::isRelativePath(filter) ) // absolute path
00863     {
00864 #ifdef Q_OS_WIN
00865         candidates << filterPath.left(3); //e.g. "C:\"
00866         filterPath = filterPath.mid(3);
00867 #else
00868         candidates << QString::fromLatin1("/");
00869         filterPath = filterPath.mid(1);
00870 #endif
00871     }
00872     else
00873     {
00874         candidates = d->resourceDirs(type, filter);
00875     }
00876 
00877     if (filterFile.isEmpty()) {
00878         filterFile = QString(QLatin1Char('*'));
00879     }
00880 
00881     QRegExp regExp(filterFile, Qt::CaseSensitive, QRegExp::Wildcard);
00882 
00883     QStringList list;
00884     foreach ( const QString& candidate, candidates )
00885     {
00886         lookupPrefix(candidate, filterPath, QString(), regExp, list,
00887                      relList, options & Recursive, options & NoDuplicates);
00888     }
00889 
00890     return list;
00891 }
00892 
00893 QStringList
00894 KStandardDirs::findAllResources( const char *type,
00895                                  const QString& filter,
00896                                  SearchOptions options ) const
00897 {
00898     QStringList relList;
00899     return findAllResources(type, filter, options, relList);
00900 }
00901 
00902 // ####### KDE4: should this be removed, in favor of QDir::canonicalPath()?
00903 // aseigo: QDir::canonicalPath returns QString() if the dir doesn't exist
00904 //         and this method is often used with the expectation for it to work
00905 //         even if the directory doesn't exist. so ... no, we can't drop this
00906 //         yet
00907 QString
00908 KStandardDirs::realPath(const QString &dirname)
00909 {
00910 #ifdef Q_WS_WIN
00911     const QString strRet = realFilePath(dirname);
00912     if (!strRet.endsWith(QLatin1Char('/')))
00913         return strRet + QLatin1Char('/');
00914     return strRet;
00915 #else
00916     if (dirname.isEmpty() || (dirname.size() == 1 && dirname.at(0) == QLatin1Char('/')))
00917        return dirname;
00918 
00919     if (dirname.at(0) != QLatin1Char('/')) {
00920         qWarning("realPath called with a relative path '%s', please fix", qPrintable(dirname));
00921         return dirname;
00922     }
00923 
00924     char realpath_buffer[MAXPATHLEN + 1];
00925     memset(realpath_buffer, 0, MAXPATHLEN + 1);
00926 
00927     /* If the path contains symlinks, get the real name */
00928     if (realpath( QFile::encodeName(dirname).constData(), realpath_buffer) != 0) {
00929         // success, use result from realpath
00930         int len = strlen(realpath_buffer);
00931         realpath_buffer[len] = '/';
00932         realpath_buffer[len+1] = 0;
00933         return QFile::decodeName(realpath_buffer);
00934     }
00935 
00936     // Does not exist yet; resolve symlinks in parent dirs then.
00937     // This ensures that once the directory exists, it will still be resolved
00938     // the same way, so that the general rule that KStandardDirs always returns
00939     // canonical paths stays true, and app code can compare paths more easily.
00940     QString dir = dirname;
00941     if (!dir.endsWith(QLatin1Char('/')))
00942         dir += QLatin1Char('/');
00943     QString relative;
00944     while (!KStandardDirs::exists(dir)) {
00945         //qDebug() << "does not exist:" << dir;
00946         const int pos = dir.lastIndexOf(QLatin1Char('/'), -2);
00947         Q_ASSERT(pos >= 0); // what? even "/" doesn't exist?
00948         relative.prepend(dir.mid(pos+1)); // keep "subdir/"
00949         dir = dir.left(pos+1);
00950         Q_ASSERT(dir.endsWith(QLatin1Char('/')));
00951     }
00952     Q_ASSERT(!relative.isEmpty()); // infinite recursion ahead
00953     if (!relative.isEmpty()) {
00954         //qDebug() << "done, resolving" << dir << "and adding" << relative;
00955         dir = realPath(dir) + relative;
00956     }
00957     return dir;
00958 #endif
00959 }
00960 
00961 // ####### KDE4: should this be removed, in favor of QDir::canonicalPath()?
00962 // aseigo: QDir::canonicalPath returns QString() if the dir doesn't exist
00963 //         and this method is often used with the expectation for it to work
00964 //         even if the directory doesn't exist. so ... no, we can't drop this
00965 //         yet
00966 QString
00967 KStandardDirs::realFilePath(const QString &filename)
00968 {
00969 #ifdef Q_WS_WIN
00970     LPCWSTR lpIn = (LPCWSTR)filename.utf16();
00971     QVarLengthArray<WCHAR, MAX_PATH> buf(MAX_PATH);
00972     DWORD len = GetFullPathNameW(lpIn, buf.size(), buf.data(), NULL);
00973     if (len > (DWORD)buf.size()) {
00974         buf.resize(len);
00975         len = GetFullPathNameW(lpIn, buf.size(), buf.data(), NULL);
00976     }
00977     if (len == 0)
00978         return QString();
00979     return QString::fromUtf16((const unsigned short*)buf.data()).replace(QLatin1Char('\\'),QLatin1Char('/')).toLower();
00980 #else
00981     char realpath_buffer[MAXPATHLEN + 1];
00982     memset(realpath_buffer, 0, MAXPATHLEN + 1);
00983 
00984     /* If the path contains symlinks, get the real name */
00985     if (realpath( QFile::encodeName(filename).constData(), realpath_buffer) != 0) {
00986         // success, use result from realpath
00987         return QFile::decodeName(realpath_buffer);
00988     }
00989 
00990     return filename;
00991 #endif
00992 }
00993 
00994 
00995 void KStandardDirs::KStandardDirsPrivate::createSpecialResource(const char *type)
00996 {
00997     char hostname[256];
00998     hostname[0] = 0;
00999     gethostname(hostname, 255);
01000     const QString localkdedir = m_prefixes.first();
01001     QString dir = localkdedir + QString::fromLatin1(type) + QLatin1Char('-') + QString::fromLocal8Bit(hostname);
01002     char link[1024];
01003     link[1023] = 0;
01004     int result = readlink(QFile::encodeName(dir).constData(), link, 1023);
01005     bool relink = (result == -1) && (errno == ENOENT);
01006     if (result > 0)
01007     {
01008         link[result] = 0;
01009         if (!QDir::isRelativePath(QFile::decodeName(link)))
01010         {
01011             KDE_struct_stat stat_buf;
01012             int res = KDE::lstat(QFile::decodeName(link), &stat_buf);
01013             if ((res == -1) && (errno == ENOENT))
01014             {
01015                 relink = true;
01016             }
01017             else if ((res == -1) || (!S_ISDIR(stat_buf.st_mode)))
01018             {
01019                 fprintf(stderr, "Error: \"%s\" is not a directory.\n", link);
01020                 relink = true;
01021             }
01022             else if (stat_buf.st_uid != getuid())
01023             {
01024                 fprintf(stderr, "Error: \"%s\" is owned by uid %d instead of uid %d.\n", link, stat_buf.st_uid, getuid());
01025                 relink = true;
01026             }
01027         }
01028     }
01029 #ifdef Q_WS_WIN
01030     if (relink)
01031     {
01032         if (!makeDir(dir, 0700))
01033             fprintf(stderr, "failed to create \"%s\"", qPrintable(dir));
01034         else
01035             result = readlink(QFile::encodeName(dir).constData(), link, 1023);
01036     }
01037 #else //UNIX
01038     if (relink)
01039     {
01040         QString srv = findExe(QLatin1String("lnusertemp"), installPath("libexec"));
01041         if (srv.isEmpty())
01042             srv = findExe(QLatin1String("lnusertemp"));
01043         if (!srv.isEmpty())
01044         {
01045             if (system(QByteArray(QFile::encodeName(srv) + ' ' + type)) == -1) {
01046                 fprintf(stderr, "Error: unable to launch lnusertemp command" );
01047             }
01048             result = readlink(QFile::encodeName(dir).constData(), link, 1023);
01049         }
01050     }
01051     if (result > 0)
01052     {
01053         link[result] = 0;
01054         if (link[0] == '/')
01055             dir = QFile::decodeName(link);
01056         else
01057             dir = QDir::cleanPath(dir + QFile::decodeName(link));
01058     }
01059 #endif
01060     q->addResourceDir(type, dir + QLatin1Char('/'), false);
01061 }
01062 
01063 QStringList KStandardDirs::resourceDirs(const char *type) const
01064 {
01065     return d->resourceDirs(type, QString());
01066 }
01067 
01068 QStringList KStandardDirs::KStandardDirsPrivate::resourceDirs(const char* type, const QString& subdirForRestrictions)
01069 {
01070     QMutexLocker lock(&m_cacheMutex);
01071     const bool dataRestrictionActive = m_restrictionsActive
01072                                        && (strcmp(type, "data") == 0)
01073                                        && hasDataRestrictions(subdirForRestrictions);
01074 
01075     QMap<QByteArray, QStringList>::const_iterator dirCacheIt = m_dircache.constFind(type);
01076 
01077     QStringList candidates;
01078 
01079     if (dirCacheIt != m_dircache.constEnd() && !dataRestrictionActive) {
01080         //qDebug() << this << "resourceDirs(" << type << "), in cache already";
01081         candidates = *dirCacheIt;
01082     }
01083     else // filling cache
01084     {
01085         //qDebug() << this << "resourceDirs(" << type << "), not in cache";
01086         if (strcmp(type, "socket") == 0)
01087             createSpecialResource(type);
01088         else if (strcmp(type, "tmp") == 0)
01089             createSpecialResource(type);
01090         else if (strcmp(type, "cache") == 0)
01091             createSpecialResource(type);
01092 
01093         QDir testdir;
01094 
01095         bool restrictionActive = false;
01096         if (m_restrictionsActive) {
01097             if (dataRestrictionActive)
01098                 restrictionActive = true;
01099             if (m_restrictions.value("all", false))
01100                 restrictionActive = true;
01101             else if (m_restrictions.value(type, false))
01102                 restrictionActive = true;
01103         }
01104 
01105         QStringList dirs;
01106         dirs = m_relatives.value(type);
01107         const QString typeInstallPath = installPath(type); // could be empty
01108 // better #ifdef incasesensitive_filesystem
01109 #ifdef Q_WS_WIN
01110         const QString installdir = typeInstallPath.isEmpty() ? QString() : realPath(typeInstallPath).toLower();
01111         const QString installprefix = installPath("kdedir").toLower();
01112 #else
01113         const QString installdir = typeInstallPath.isEmpty() ? QString() : realPath(typeInstallPath);
01114         const QString installprefix = installPath("kdedir");
01115 #endif
01116         if (!dirs.isEmpty())
01117         {
01118             bool local = true;
01119 
01120             for (QStringList::ConstIterator it = dirs.constBegin();
01121                  it != dirs.constEnd(); ++it)
01122             {
01123                 if ((*it).startsWith(QLatin1Char('%'))) {
01124                     // grab the "data" from "%data/apps"
01125                     const int pos = (*it).indexOf(QLatin1Char('/'));
01126                     QString rel = (*it).mid(1, pos - 1);
01127                     QString rest = (*it).mid(pos + 1);
01128                     const QStringList basedirs = resourceDirs(rel.toUtf8().constData(), subdirForRestrictions);
01129                     for (QStringList::ConstIterator it2 = basedirs.begin();
01130                          it2 != basedirs.end(); ++it2)
01131                     {
01132 #ifdef Q_WS_WIN
01133                         const QString path = realPath( *it2 + rest ).toLower();
01134 #else
01135                         const QString path = realPath( *it2 + rest );
01136 #endif
01137                         testdir.setPath(path);
01138                         if ((local || testdir.exists()) && !candidates.contains(path))
01139                             candidates.append(path);
01140                         local = false;
01141                     }
01142                 }
01143             }
01144 
01145             const QStringList *prefixList = 0;
01146             if (strncmp(type, "xdgdata-", 8) == 0)
01147                 prefixList = &(xdgdata_prefixes);
01148             else if (strncmp(type, "xdgconf-", 8) == 0)
01149                 prefixList = &(xdgconf_prefixes);
01150             else
01151                 prefixList = &m_prefixes;
01152 
01153             for (QStringList::ConstIterator pit = prefixList->begin();
01154                  pit != prefixList->end();
01155                  ++pit)
01156             {
01157             // "exe" never has a custom install path, and the check triggers
01158             // a false positive due to the libexecdir patch
01159             if((*pit)!=installprefix||installdir.isEmpty()||!strcmp("exe", type))
01160             {
01161                     for (QStringList::ConstIterator it = dirs.constBegin();
01162                          it != dirs.constEnd(); ++it)
01163                     {
01164                         if ((*it).startsWith(QLatin1Char('%')))
01165                             continue;
01166 #ifdef Q_WS_WIN
01167                         const QString path = realPath( *pit + *it ).toLower();
01168 #else
01169                         const QString path = realPath( *pit + *it );
01170 #endif
01171                         testdir.setPath(path);
01172                         if (local && restrictionActive)
01173                             continue;
01174                         if ((local || testdir.exists()) && !candidates.contains(path))
01175                             candidates.append(path);
01176                     }
01177                     // special-case "config" (forward porting Chris Cheney's
01178                     // hack) - we want /etc/kde after the local config paths
01179                     // and before the ones in /usr (including kde-profile)
01180                     if (local && !strcmp("config", type))
01181                        candidates.append(QLatin1String("/etc/kde/"));
01182                     local = false;
01183                 }
01184             else
01185             {
01186                     // we have a custom install path, so use this instead of <installprefix>/<relative dir>
01187                 testdir.setPath(installdir);
01188                     if(testdir.exists() && ! candidates.contains(installdir))
01189                         candidates.append(installdir);
01190             }
01191         }
01192         }
01193 
01194         // make sure we find the path where it's installed
01195         if (!installdir.isEmpty()) {
01196             bool ok = true;
01197             foreach (const QString &s, candidates) {
01198                 if (installdir.startsWith(s)) {
01199                     ok = false;
01200                     break;
01201                 }
01202             }
01203             if (ok)
01204                 candidates.append(installdir);
01205         }
01206 
01207         dirs = m_absolutes.value(type);
01208         if (!dirs.isEmpty())
01209             for (QStringList::ConstIterator it = dirs.constBegin();
01210                  it != dirs.constEnd(); ++it)
01211             {
01212                 testdir.setPath(*it);
01213                 if (testdir.exists()) {
01214 #ifdef Q_WS_WIN
01215                     const QString filename = realPath( *it ).toLower();
01216 #else
01217                     const QString filename = realPath( *it );
01218 #endif
01219                     if (!candidates.contains(filename)) {
01220                         candidates.append(filename);
01221                     }
01222                 }
01223             }
01224 
01225         // Insert result into the cache for next time.
01226         // Exception: data_subdir restrictions are per-subdir, so we can't store such results
01227         if (!dataRestrictionActive) {
01228             //kDebug() << this << "Inserting" << type << candidates << "into dircache";
01229             m_dircache.insert(type, candidates);
01230         }
01231     }
01232 
01233 #if 0
01234     kDebug(180) << "found dirs for resource" << type << ":" << candidates;
01235 #endif
01236 
01237     return candidates;
01238 }
01239 
01240 #ifdef Q_OS_WIN
01241 static QStringList executableExtensions()
01242 {
01243     QStringList ret = QString::fromLocal8Bit(qgetenv("PATHEXT")).split(QLatin1Char(';'));
01244     if (!ret.contains(QLatin1String(".exe"), Qt::CaseInsensitive)) {
01245         // If %PATHEXT% does not contain .exe, it is either empty, malformed, or distorted in ways that we cannot support, anyway.
01246         ret.clear();
01247         ret << QLatin1String(".exe")
01248             << QLatin1String(".com")
01249             << QLatin1String(".bat")
01250             << QLatin1String(".cmd");
01251     }
01252     return ret;
01253 }
01254 #endif
01255 
01256 QStringList KStandardDirs::systemPaths( const QString& pstr )
01257 {
01258     QStringList tokens;
01259     QString p = pstr;
01260 
01261     if( p.isEmpty() )
01262     {
01263         p = QString::fromLocal8Bit( qgetenv( "PATH" ) );
01264     }
01265 
01266     QString delimiters(QLatin1Char(KPATH_SEPARATOR));
01267     delimiters += QLatin1Char('\b');
01268     tokenize( tokens, p, delimiters );
01269 
01270     QStringList exePaths;
01271 
01272     // split path using : or \b as delimiters
01273     for( int i = 0; i < tokens.count(); i++ )
01274     {
01275         exePaths << KShell::tildeExpand( tokens[ i ] );
01276     }
01277 
01278     return exePaths;
01279 }
01280 
01281 #ifdef Q_WS_MAC
01282 static QString getBundle( const QString& path, bool ignore )
01283 {
01284     //kDebug(180) << "getBundle(" << path << ", " << ignore << ") called";
01285     QFileInfo info;
01286     QString bundle = path;
01287     bundle += QLatin1String(".app/Contents/MacOS/") + bundle.section(QLatin1Char('/'), -1);
01288     info.setFile( bundle );
01289     FILE *file;
01290     if (file = fopen(info.absoluteFilePath().toUtf8().constData(), "r")) {
01291         fclose(file);
01292         struct stat _stat;
01293         if ((stat(info.absoluteFilePath().toUtf8().constData(), &_stat)) < 0) {
01294             return QString();
01295         }
01296         if ( ignore || (_stat.st_mode & S_IXUSR) ) {
01297             if ( ((_stat.st_mode & S_IFMT) == S_IFREG) || ((_stat.st_mode & S_IFMT) == S_IFLNK) ) {
01298                 //kDebug(180) << "getBundle(): returning " << bundle;
01299                 return bundle;
01300             }
01301         }
01302     }
01303     return QString();
01304 }
01305 #endif
01306 
01307 static QString checkExecutable( const QString& path, bool ignoreExecBit )
01308 {
01309 #ifdef Q_WS_MAC
01310     QString bundle = getBundle( path, ignoreExecBit );
01311     if ( !bundle.isEmpty() ) {
01312         //kDebug(180) << "findExe(): returning " << bundle;
01313         return bundle;
01314     }
01315 #endif
01316     QFileInfo info( path );
01317     QFileInfo orig = info;
01318 #if defined(Q_OS_DARWIN) || defined(Q_OS_MAC)
01319     FILE *file;
01320     if (file = fopen(orig.absoluteFilePath().toUtf8().constData(), "r")) {
01321         fclose(file);
01322         struct stat _stat;
01323         if ((stat(orig.absoluteFilePath().toUtf8().constData(), &_stat)) < 0) {
01324             return QString();
01325         }
01326         if ( ignoreExecBit || (_stat.st_mode & S_IXUSR) ) {
01327             if ( ((_stat.st_mode & S_IFMT) == S_IFREG) || ((_stat.st_mode & S_IFMT) == S_IFLNK) ) {
01328                 orig.makeAbsolute();
01329                 return orig.filePath();
01330             }
01331         }
01332     }
01333     return QString();
01334 #else
01335     if( info.exists() && info.isSymLink() )
01336         info = QFileInfo( info.canonicalFilePath() );
01337     if( info.exists() && ( ignoreExecBit || info.isExecutable() ) && info.isFile() ) {
01338         // return absolute path, but without symlinks resolved in order to prevent
01339         // problems with executables that work differently depending on name they are
01340         // run as (for example gunzip)
01341         orig.makeAbsolute();
01342         return orig.filePath();
01343     }
01344     //kDebug(180) << "checkExecutable(): failed, returning empty string";
01345     return QString();
01346 #endif
01347 }
01348 
01349 QString KStandardDirs::findExe( const QString& appname,
01350                                 const QString& pstr,
01351                                 SearchOptions options )
01352 {
01353     //kDebug(180) << "findExe(" << appname << ", pstr, " << ignoreExecBit << ") called";
01354 
01355 #ifdef Q_OS_WIN
01356     QStringList executable_extensions = executableExtensions();
01357     if (!executable_extensions.contains(appname.section(QLatin1Char('.'), -1, -1, QString::SectionIncludeLeadingSep), Qt::CaseInsensitive)) {
01358         QString found_exe;
01359         foreach (const QString& extension, executable_extensions) {
01360             found_exe = findExe(appname + extension, pstr, options);
01361             if (!found_exe.isEmpty()) {
01362                 return found_exe;
01363             }
01364         }
01365         return QString();
01366     }
01367 #endif
01368     QFileInfo info;
01369 
01370     // absolute or relative path?
01371     if (appname.contains(QDir::separator()))
01372     {
01373         //kDebug(180) << "findExe(): absolute path given";
01374         QString path = checkExecutable(appname, options & IgnoreExecBit);
01375         return path;
01376     }
01377 
01378     //kDebug(180) << "findExe(): relative path given";
01379 
01380     QString p = installPath("libexec") + appname;
01381     QString result = checkExecutable(p, options & IgnoreExecBit);
01382     if (!result.isEmpty()) {
01383         //kDebug(180) << "findExe(): returning " << result;
01384         return result;
01385     }
01386 
01387     //kDebug(180) << "findExe(): checking system paths";
01388     const QStringList exePaths = systemPaths( pstr );
01389     for (QStringList::ConstIterator it = exePaths.begin(); it != exePaths.end(); ++it)
01390     {
01391         p = (*it) + QLatin1Char('/');
01392         p += appname;
01393 
01394         // Check for executable in this tokenized path
01395         result = checkExecutable(p, options & IgnoreExecBit);
01396         if (!result.isEmpty()) {
01397             //kDebug(180) << "findExe(): returning " << result;
01398             return result;
01399         }
01400     }
01401 
01402     // Not found in PATH, look into the KDE-specific bin dir ("exe" resource)
01403     p = installPath("exe");
01404     p += appname;
01405     result = checkExecutable(p, options & IgnoreExecBit);
01406     if (!result.isEmpty()) {
01407         //kDebug(180) << "findExe(): returning " << result;
01408         return result;
01409     }
01410 
01411     // If we reach here, the executable wasn't found.
01412     // So return empty string.
01413 
01414     //kDebug(180) << "findExe(): failed, nothing matched";
01415     return QString();
01416 }
01417 
01418 int KStandardDirs::findAllExe( QStringList& list, const QString& appname,
01419                                const QString& pstr, SearchOptions options )
01420 {
01421 #ifdef Q_OS_WIN
01422     QStringList executable_extensions = executableExtensions();
01423     if (!executable_extensions.contains(appname.section(QLatin1Char('.'), -1, -1, QString::SectionIncludeLeadingSep), Qt::CaseInsensitive)) {
01424         int total = 0;
01425         foreach (const QString& extension, executable_extensions) {
01426             total += findAllExe (list, appname + extension, pstr, options);
01427         }
01428         return total;
01429     }
01430 #endif
01431     QFileInfo info;
01432     QString p;
01433     list.clear();
01434 
01435     const QStringList exePaths = systemPaths( pstr );
01436     for (QStringList::ConstIterator it = exePaths.begin(); it != exePaths.end(); ++it)
01437     {
01438         p = (*it) + QLatin1Char('/');
01439         p += appname;
01440 
01441 #ifdef Q_WS_MAC
01442         QString bundle = getBundle( p, (options & IgnoreExecBit) );
01443         if ( !bundle.isEmpty() ) {
01444             //kDebug(180) << "findExe(): returning " << bundle;
01445             list.append( bundle );
01446         }
01447 #endif
01448 
01449         info.setFile( p );
01450 
01451         if( info.exists() && ( ( options & IgnoreExecBit ) || info.isExecutable())
01452             && info.isFile() ) {
01453             list.append( p );
01454         }
01455     }
01456 
01457     return list.count();
01458 }
01459 
01460 static inline QString equalizePath(QString &str)
01461 {
01462 #ifdef Q_WS_WIN
01463     // filter pathes through QFileInfo to have always
01464     // the same case for drive letters
01465     QFileInfo f(str);
01466     if (f.isAbsolute())
01467         return f.absoluteFilePath();
01468     else
01469 #endif
01470         return str;
01471 }
01472 
01473 static void tokenize(QStringList& tokens, const QString& str,
01474                     const QString& delim)
01475 {
01476     const int len = str.length();
01477     QString token;
01478 
01479     for(int index = 0; index < len; index++) {
01480         if (delim.contains(str[index])) {
01481             tokens.append(equalizePath(token));
01482             token.clear();
01483         } else {
01484             token += str[index];
01485         }
01486     }
01487     if (!token.isEmpty()) {
01488         tokens.append(equalizePath(token));
01489     }
01490 }
01491 
01492 #ifndef KDE_NO_DEPRECATED
01493 QString KStandardDirs::kde_default(const char *type)
01494 {
01495     return QString(QLatin1Char('%')) + QString::fromLatin1(type) + QLatin1Char('/');
01496 }
01497 #endif
01498 
01499 QString KStandardDirs::saveLocation(const char *type,
01500                                     const QString& suffix,
01501                                     bool create) const
01502 {
01503     QMutexLocker lock(&d->m_cacheMutex);
01504     QString path = d->m_savelocations.value(type);
01505     if (path.isEmpty())
01506     {
01507         QStringList dirs = d->m_relatives.value(type);
01508         if (dirs.isEmpty() && (
01509                 (strcmp(type, "socket") == 0) ||
01510                 (strcmp(type, "tmp") == 0) ||
01511                 (strcmp(type, "cache") == 0) ))
01512         {
01513             (void) resourceDirs(type); // Generate socket|tmp|cache resource.
01514             dirs = d->m_relatives.value(type); // Search again.
01515         }
01516         if (!dirs.isEmpty())
01517         {
01518             path = dirs.first();
01519 
01520             if (path.startsWith(QLatin1Char('%'))) {
01521                 // grab the "data" from "%data/apps"
01522                 const int pos = path.indexOf(QLatin1Char('/'));
01523                 QString rel = path.mid(1, pos - 1);
01524                 QString rest = path.mid(pos + 1);
01525                 QString basepath = saveLocation(rel.toUtf8().constData());
01526                 path = basepath + rest;
01527             } else
01528 
01529                 // Check for existence of typed directory + suffix
01530                 if (strncmp(type, "xdgdata-", 8) == 0) {
01531                     path = realPath( localxdgdatadir() + path ) ;
01532                 } else if (strncmp(type, "xdgconf-", 8) == 0) {
01533                     path = realPath( localxdgconfdir() + path );
01534                 } else {
01535                     path = realPath( localkdedir() + path );
01536                 }
01537         }
01538         else {
01539             dirs = d->m_absolutes.value(type);
01540             if (dirs.isEmpty()) {
01541                 qFatal("KStandardDirs: The resource type %s is not registered", type);
01542             } else {
01543                 path = realPath(dirs.first());
01544             }
01545         }
01546 
01547         d->m_savelocations.insert(type, path.endsWith(QLatin1Char('/')) ? path : path + QLatin1Char('/'));
01548     }
01549     QString fullPath = path + suffix;
01550 
01551     KDE_struct_stat st;
01552     if (KDE::stat(fullPath, &st) != 0 || !(S_ISDIR(st.st_mode))) {
01553         if(!create) {
01554 #ifndef NDEBUG
01555             // Too much noise from kbuildsycoca4 -- it's fine if this happens from KConfig
01556             // when parsing global files without a local equivalent.
01557             //kDebug(180) << QString("save location %1 doesn't exist").arg(fullPath);
01558 #endif
01559             return fullPath;
01560         }
01561         if(!makeDir(fullPath, 0700)) {
01562             return fullPath;
01563         }
01564         d->m_dircache.remove(type);
01565     }
01566     if (!fullPath.endsWith(QLatin1Char('/')))
01567         fullPath += QLatin1Char('/');
01568     return fullPath;
01569 }
01570 
01571 // KDE5: make the method const
01572 QString KStandardDirs::relativeLocation(const char *type, const QString &absPath)
01573 {
01574     QString fullPath = absPath;
01575     int i = absPath.lastIndexOf(QLatin1Char('/'));
01576     if (i != -1) {
01577         fullPath = realFilePath(absPath); // Normalize
01578     }
01579 
01580     const QStringList candidates = resourceDirs(type);
01581 
01582     for (QStringList::ConstIterator it = candidates.begin();
01583          it != candidates.end(); ++it) {
01584         if (fullPath.startsWith(*it)) {
01585             return fullPath.mid((*it).length());
01586         }
01587     }
01588     return absPath;
01589 }
01590 
01591 
01592 bool KStandardDirs::makeDir(const QString& dir, int mode)
01593 {
01594     // we want an absolute path
01595     if (QDir::isRelativePath(dir))
01596         return false;
01597 
01598 #ifdef Q_WS_WIN
01599     return QDir().mkpath(dir);
01600 #else
01601     QString target = dir;
01602     uint len = target.length();
01603 
01604     // append trailing slash if missing
01605     if (dir.at(len - 1) != QLatin1Char('/'))
01606         target += QLatin1Char('/');
01607 
01608     QString base;
01609     uint i = 1;
01610 
01611     while( i < len )
01612     {
01613         KDE_struct_stat st;
01614         int pos = target.indexOf(QLatin1Char('/'), i);
01615         base += target.mid(i - 1, pos - i + 1);
01616         QByteArray baseEncoded = QFile::encodeName(base);
01617         // bail out if we encountered a problem
01618         if (KDE_stat(baseEncoded, &st) != 0)
01619         {
01620             // Directory does not exist....
01621             // Or maybe a dangling symlink ?
01622             if (KDE_lstat(baseEncoded, &st) == 0)
01623                 (void)unlink(baseEncoded); // try removing
01624 
01625             if (KDE_mkdir(baseEncoded, static_cast<mode_t>(mode)) != 0) {
01626                 baseEncoded.prepend( "trying to create local folder " );
01627                 perror(baseEncoded.constData());
01628                 return false; // Couldn't create it :-(
01629             }
01630         }
01631         i = pos + 1;
01632     }
01633     return true;
01634 #endif
01635 }
01636 
01637 static QString readEnvPath(const char *env)
01638 {
01639     QByteArray c_path;
01640 #ifndef _WIN32_WCE
01641     c_path = qgetenv(env);
01642     if (c_path.isEmpty())
01643         return QString();
01644 #else
01645     bool ok;
01646     QString retval = getWin32RegistryValue(HKEY_LOCAL_MACHINE, "Software\\kde", "KDEDIRS", &ok);
01647     if (!ok){
01648         return QString();
01649     } else {
01650         c_path = retval.toAscii();
01651     }
01652 #endif
01653     return QDir::fromNativeSeparators(QFile::decodeName(c_path));
01654 }
01655 
01656 #ifdef __linux__
01657 static QString executablePrefix()
01658 {
01659     char path_buffer[MAXPATHLEN + 1];
01660     path_buffer[MAXPATHLEN] = 0;
01661     int length = readlink ("/proc/self/exe", path_buffer, MAXPATHLEN);
01662     if (length == -1)
01663         return QString();
01664 
01665     path_buffer[length] = '\0';
01666 
01667     QString path = QFile::decodeName(path_buffer);
01668 
01669     if(path.isEmpty())
01670         return QString();
01671 
01672     int pos = path.lastIndexOf(QLatin1Char('/')); // Skip filename
01673     if(pos <= 0)
01674         return QString();
01675     pos = path.lastIndexOf(QLatin1Char('/'), pos - 1); // Skip last directory
01676     if(pos <= 0)
01677         return QString();
01678 
01679     return path.left(pos);
01680 }
01681 #endif
01682 
01683 void KStandardDirs::addResourcesFrom_krcdirs()
01684 {
01685     QString localFile = QDir::currentPath() + QLatin1String("/.krcdirs");
01686     if (!QFile::exists(localFile))
01687         return;
01688 
01689     QSettings iniFile(localFile, QSettings::IniFormat);
01690     iniFile.beginGroup(QString::fromLatin1("KStandardDirs"));
01691     const QStringList resources = iniFile.allKeys();
01692     foreach(const QString &key, resources)
01693     {
01694         QDir path(iniFile.value(key).toString());
01695         if (!path.exists())
01696             continue;
01697 
01698         if(path.makeAbsolute())
01699             addResourceDir(key.toAscii(), path.path(), false);
01700     }
01701 }
01702 
01703 void KStandardDirs::addKDEDefaults()
01704 {
01705     addResourcesFrom_krcdirs();
01706 
01707     QStringList kdedirList;
01708     // begin KDEDIRS
01709     QString kdedirs = readEnvPath("KDEDIRS");
01710 
01711     if (!kdedirs.isEmpty())
01712     {
01713         tokenize(kdedirList, kdedirs, QString(QLatin1Char(KPATH_SEPARATOR)));
01714     }
01715     kdedirList.append(installPath("kdedir"));
01716 
01717     QString execPrefix(QFile::decodeName(EXEC_INSTALL_PREFIX));
01718     if (!execPrefix.isEmpty() && !kdedirList.contains(execPrefix))
01719         kdedirList.append(execPrefix);
01720 #ifdef __linux__
01721     const QString linuxExecPrefix = executablePrefix();
01722     if ( !linuxExecPrefix.isEmpty() )
01723         kdedirList.append( linuxExecPrefix );
01724 #endif
01725 
01726     // We treat root differently to prevent a "su" shell messing up the
01727     // file permissions in the user's home directory.
01728     QString localKdeDir = readEnvPath(getuid() ? "KDEHOME" : "KDEROOTHOME");
01729     if (!localKdeDir.isEmpty()) {
01730         if (!localKdeDir.endsWith(QLatin1Char('/')))
01731             localKdeDir += QLatin1Char('/');
01732     } else {
01733         // TODO KDE5: make localKdeDir equal to localXdgDir (which is determined further below and
01734         // defaults to ~/.config) + '/' + $KDECONFIG (which would default to e.g. "KDE")
01735         // This would mean ~/.config/KDE/ by default, more xdg-compliant.
01736 
01737 #if defined(Q_WS_MACX)
01738         localKdeDir =  QDir::homePath() + QLatin1String("/Library/Preferences/KDE/");
01739 #elif defined(Q_WS_WIN)
01740 #ifndef _WIN32_WCE
01741         WCHAR wPath[MAX_PATH+1];
01742         if ( SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, wPath) == S_OK) {
01743           localKdeDir = QDir::fromNativeSeparators(QString::fromUtf16((const ushort *) wPath)) + QLatin1Char('/') + QString::fromLatin1(KDE_DEFAULT_HOME) + QLatin1Char('/');
01744         } else {
01745 #endif
01746           localKdeDir =  QDir::homePath() + QLatin1Char('/') + QString::fromLatin1(KDE_DEFAULT_HOME) + QLatin1Char('/');
01747 #ifndef _WIN32_WCE
01748         }
01749 #endif
01750 #else
01751         localKdeDir =  QDir::homePath() + QLatin1Char('/') + QString::fromLatin1(KDE_DEFAULT_HOME) + QLatin1Char('/');
01752 #endif
01753     }
01754 
01755     if (localKdeDir != QLatin1String("-/"))
01756     {
01757         localKdeDir = KShell::tildeExpand(localKdeDir);
01758         addPrefix(localKdeDir);
01759     }
01760 
01761 #ifdef Q_WS_MACX
01762     // Adds the "Contents" directory of the current application bundle to
01763     // the search path. This way bundled resources can be found.
01764     QDir bundleDir(mac_app_filename());
01765     if (bundleDir.dirName() == QLatin1String("MacOS")) { // just to be sure we're in a bundle
01766         bundleDir.cdUp();
01767         // now dirName should be "Contents". In there we can find our normal
01768         // dir-structure, beginning with "share"
01769         addPrefix(bundleDir.absolutePath());
01770     }
01771 #endif
01772 
01773     QStringList::ConstIterator end(kdedirList.end());
01774     for (QStringList::ConstIterator it = kdedirList.constBegin();
01775          it != kdedirList.constEnd(); ++it)
01776     {
01777         const QString dir = KShell::tildeExpand(*it);
01778         addPrefix(dir);
01779     }
01780     // end KDEDIRS
01781 
01782     // begin XDG_CONFIG_XXX
01783     QStringList xdgdirList;
01784     QString xdgdirs = readEnvPath("XDG_CONFIG_DIRS");
01785     if (!xdgdirs.isEmpty())
01786     {
01787         tokenize(xdgdirList, xdgdirs, QString(QLatin1Char(KPATH_SEPARATOR)));
01788     }
01789     else
01790     {
01791         xdgdirList.clear();
01792         xdgdirList.append(QString::fromLatin1("/etc/xdg"));
01793 #ifdef Q_WS_WIN
01794         xdgdirList.append(installPath("kdedir") + QString::fromLatin1("etc/xdg"));
01795 #else
01796         xdgdirList.append(QFile::decodeName(KDESYSCONFDIR "/xdg"));
01797 #endif
01798     }
01799 
01800     QString localXdgDir = readEnvPath("XDG_CONFIG_HOME");
01801     if (!localXdgDir.isEmpty()) {
01802         if (!localXdgDir.endsWith(QLatin1Char('/')))
01803             localXdgDir += QLatin1Char('/');
01804     } else {
01805 #ifdef Q_WS_MACX
01806         localXdgDir = QDir::homePath() + QString::fromLatin1("/Library/Preferences/XDG/");
01807 #else
01808         localXdgDir = QDir::homePath() + QString::fromLatin1("/.config/");
01809 #endif
01810     }
01811 
01812     localXdgDir = KShell::tildeExpand(localXdgDir);
01813     addXdgConfigPrefix(localXdgDir);
01814 
01815     for (QStringList::ConstIterator it = xdgdirList.constBegin();
01816          it != xdgdirList.constEnd(); ++it)
01817     {
01818         QString dir = KShell::tildeExpand(*it);
01819         addXdgConfigPrefix(dir);
01820     }
01821     // end XDG_CONFIG_XXX
01822 
01823     // begin XDG_DATA_XXX
01824     QStringList kdedirDataDirs;
01825     for (QStringList::ConstIterator it = kdedirList.constBegin();
01826          it != kdedirList.constEnd(); ++it) {
01827         QString dir = *it;
01828         if (!dir.endsWith(QLatin1Char('/')))
01829             dir += QLatin1Char('/');
01830         kdedirDataDirs.append(dir + QLatin1String("share/"));
01831     }
01832 
01833     xdgdirs = readEnvPath("XDG_DATA_DIRS");
01834     if (!xdgdirs.isEmpty()) {
01835         tokenize(xdgdirList, xdgdirs, QString(QLatin1Char(KPATH_SEPARATOR)));
01836         // Ensure the kdedirDataDirs are in there too,
01837         // otherwise resourceDirs() will add kdedir/share/applications/kde4
01838         // as returned by installPath(), and that's incorrect.
01839         Q_FOREACH(const QString& dir, kdedirDataDirs) {
01840             if (!xdgdirList.contains(dir))
01841                 xdgdirList.append(dir);
01842         }
01843     } else {
01844         xdgdirList = kdedirDataDirs;
01845 #ifndef Q_WS_WIN
01846         xdgdirList.append(QString::fromLatin1("/usr/local/share/"));
01847         xdgdirList.append(QString::fromLatin1("/usr/share/"));
01848 #endif
01849     }
01850 
01851     localXdgDir = readEnvPath("XDG_DATA_HOME");
01852     if (!localXdgDir.isEmpty())
01853     {
01854         if (localXdgDir[localXdgDir.length()-1] != QLatin1Char('/'))
01855             localXdgDir += QLatin1Char('/');
01856     }
01857     else
01858     {
01859         localXdgDir = QDir::homePath() + QLatin1String("/.local/share/");
01860     }
01861 
01862     localXdgDir = KShell::tildeExpand(localXdgDir);
01863     addXdgDataPrefix(localXdgDir);
01864 
01865     for (QStringList::ConstIterator it = xdgdirList.constBegin();
01866          it != xdgdirList.constEnd(); ++it)
01867     {
01868         QString dir = KShell::tildeExpand(*it);
01869         addXdgDataPrefix(dir);
01870     }
01871     // end XDG_DATA_XXX
01872 
01873 
01874     addResourceType("lib", 0, "lib" KDELIBSUFF "/");
01875 
01876     uint index = 0;
01877     while (types_indices[index] != -1) {
01878         addResourceType(types_string + types_indices[index], 0, types_string + types_indices[index+1], true);
01879         index+=2;
01880     }
01881     addResourceType("exe", 0, "libexec/kde4", true );
01882 
01883     addResourceDir("home", QDir::homePath(), false);
01884 
01885     addResourceType("autostart", "xdgconf-autostart", "/"); // merge them, start with xdg autostart
01886     addResourceType("autostart", NULL, "share/autostart"); // KDE ones are higher priority
01887 }
01888 
01889 static QStringList lookupProfiles(const QString &mapFile)
01890 {
01891     QStringList profiles;
01892 
01893     if (mapFile.isEmpty() || !QFile::exists(mapFile))
01894     {
01895         profiles << QString::fromLatin1("default");
01896         return profiles;
01897     }
01898 
01899     struct passwd *pw = getpwuid(geteuid());
01900     if (!pw)
01901     {
01902         profiles << QString::fromLatin1("default");
01903         return profiles; // Not good
01904     }
01905 
01906     QByteArray user = pw->pw_name;
01907 
01908     gid_t sup_gids[512];
01909     int sup_gids_nr = getgroups(512, sup_gids);
01910 
01911     KConfig mapCfgFile(mapFile);
01912     KConfigGroup mapCfg(&mapCfgFile, "Users");
01913     if (mapCfg.hasKey(user.constData()))
01914     {
01915         profiles = mapCfg.readEntry(user.constData(), QStringList());
01916         return profiles;
01917     }
01918 
01919     const KConfigGroup generalGrp(&mapCfgFile, "General");
01920     const QStringList groups = generalGrp.readEntry("groups", QStringList());
01921 
01922     const KConfigGroup groupsGrp(&mapCfgFile, "Groups");
01923 
01924     for( QStringList::ConstIterator it = groups.begin();
01925          it != groups.end(); ++it )
01926     {
01927         QByteArray grp = (*it).toUtf8();
01928         // Check if user is in this group
01929         struct group *grp_ent = getgrnam(grp);
01930         if (!grp_ent) continue;
01931         gid_t gid = grp_ent->gr_gid;
01932         if (pw->pw_gid == gid)
01933         {
01934             // User is in this group --> add profiles
01935             profiles += groupsGrp.readEntry(*it, QStringList());
01936         }
01937         else
01938         {
01939             for(int i = 0; i < sup_gids_nr; i++)
01940             {
01941                 if (sup_gids[i] == gid)
01942                 {
01943                     // User is in this group --> add profiles
01944                     profiles += groupsGrp.readEntry(*it, QStringList());
01945                     break;
01946                 }
01947             }
01948         }
01949     }
01950 
01951     if (profiles.isEmpty())
01952         profiles << QString::fromLatin1("default");
01953     return profiles;
01954 }
01955 
01956 extern bool kde_kiosk_admin;
01957 
01958 bool KStandardDirs::addCustomized(KConfig *config)
01959 {
01960     if (!d->m_checkRestrictions) // there are already customized entries
01961         return false; // we just quit and hope they are the right ones
01962 
01963     // save the numbers of config directories. If this changes,
01964     // we will return true to give KConfig a chance to reparse
01965     int configdirs = resourceDirs("config").count();
01966 
01967     if (true)
01968     {
01969         // reading the prefixes in
01970         QString group = QLatin1String("Directories");
01971         KConfigGroup cg(config, group);
01972 
01973         QString kioskAdmin = cg.readEntry("kioskAdmin");
01974         if (!kioskAdmin.isEmpty() && !kde_kiosk_admin)
01975         {
01976             int i = kioskAdmin.indexOf(QLatin1Char(':'));
01977             QString user = kioskAdmin.left(i);
01978             QString host = kioskAdmin.mid(i+1);
01979 
01980             KUser thisUser;
01981             char hostname[ 256 ];
01982             hostname[ 0 ] = '\0';
01983             if (!gethostname( hostname, 255 ))
01984                 hostname[sizeof(hostname)-1] = '\0';
01985 
01986             if ((user == thisUser.loginName()) &&
01987                 (host.isEmpty() || (host == QLatin1String(hostname))))
01988             {
01989                 kde_kiosk_admin = true;
01990             }
01991         }
01992 
01993         bool readProfiles = true;
01994 
01995         if (kde_kiosk_admin && !qgetenv("KDE_KIOSK_NO_PROFILES").isEmpty())
01996             readProfiles = false;
01997 
01998         QString userMapFile = cg.readEntry("userProfileMapFile");
01999         QString profileDirsPrefix = cg.readEntry("profileDirsPrefix");
02000         if (!profileDirsPrefix.isEmpty() && !profileDirsPrefix.endsWith(QLatin1Char('/')))
02001             profileDirsPrefix.append(QLatin1Char('/'));
02002 
02003         QStringList profiles;
02004         if (readProfiles)
02005             profiles = lookupProfiles(userMapFile);
02006         QString profile;
02007 
02008         bool priority = false;
02009         while(true)
02010         {
02011             KConfigGroup cg(config, group);
02012             const QStringList list = cg.readEntry("prefixes", QStringList());
02013             for (QStringList::ConstIterator it = list.begin(); it != list.end(); ++it)
02014             {
02015                 addPrefix(*it, priority);
02016                 addXdgConfigPrefix(*it + QLatin1String("/etc/xdg"), priority);
02017                 addXdgDataPrefix(*it + QLatin1String("/share"), priority);
02018             }
02019             // If there are no prefixes defined, check if there is a directory
02020             // for this profile under <profileDirsPrefix>
02021             if (list.isEmpty() && !profile.isEmpty() && !profileDirsPrefix.isEmpty())
02022             {
02023                 QString dir = profileDirsPrefix + profile;
02024                 addPrefix(dir, priority);
02025                 addXdgConfigPrefix(dir + QLatin1String("/etc/xdg"), priority);
02026                 addXdgDataPrefix(dir + QLatin1String("/share"), priority);
02027             }
02028 
02029             // iterating over all entries in the group Directories
02030             // to find entries that start with dir_$type
02031             const QMap<QString, QString> entries = config->entryMap(group);
02032             for (QMap<QString, QString>::ConstIterator it2 = entries.begin();
02033                  it2 != entries.end(); ++it2)
02034             {
02035                 const QString key = it2.key();
02036                 if (key.startsWith(QLatin1String("dir_"))) {
02037                     // generate directory list, there may be more than 1.
02038                     const QStringList dirs = (*it2).split(QString(QLatin1Char(',')));
02039                     QStringList::ConstIterator sIt(dirs.begin());
02040                     QString resType = key.mid(4);
02041                     for (; sIt != dirs.end(); ++sIt)
02042                     {
02043                         addResourceDir(resType.toLatin1(), *sIt, priority);
02044                     }
02045                 }
02046             }
02047             if (profiles.isEmpty())
02048                 break;
02049             profile = profiles.back();
02050             group = QString::fromLatin1("Directories-%1").arg(profile);
02051             profiles.pop_back();
02052             priority = true;
02053         }
02054     }
02055 
02056     // Process KIOSK restrictions.
02057     if (!kde_kiosk_admin || qgetenv("KDE_KIOSK_NO_RESTRICTIONS").isEmpty())
02058     {
02059         KConfigGroup cg(config, "KDE Resource Restrictions");
02060         const QMap<QString, QString> entries = cg.entryMap();
02061         for (QMap<QString, QString>::ConstIterator it2 = entries.begin();
02062              it2 != entries.end(); ++it2)
02063         {
02064             const QString key = it2.key();
02065             if (!cg.readEntry(key, true))
02066             {
02067                 d->m_restrictionsActive = true;
02068                 const QByteArray cKey = key.toLatin1();
02069                 d->m_restrictions.insert(cKey, true);
02070                 d->m_dircache.remove(cKey);
02071                 d->m_savelocations.remove(cKey);
02072             }
02073         }
02074     }
02075 
02076     // check if the number of config dirs changed
02077     bool configDirsChanged = (resourceDirs("config").count() != configdirs);
02078     // If the config dirs changed, we check kiosk restrictions again.
02079     d->m_checkRestrictions = configDirsChanged;
02080     // return true if the number of config dirs changed: reparse config file
02081     return configDirsChanged;
02082 }
02083 
02084 QString KStandardDirs::localkdedir() const
02085 {
02086     // Return the prefix to use for saving
02087     return d->m_prefixes.first();
02088 }
02089 
02090 QString KStandardDirs::localxdgdatadir() const
02091 {
02092     // Return the prefix to use for saving
02093     return d->xdgdata_prefixes.first();
02094 }
02095 
02096 QString KStandardDirs::localxdgconfdir() const
02097 {
02098     // Return the prefix to use for saving
02099     return d->xdgconf_prefixes.first();
02100 }
02101 
02102 
02103 // just to make code more readable without macros
02104 QString KStandardDirs::locate( const char *type,
02105                                const QString& filename, const KComponentData &cData)
02106 {
02107     return cData.dirs()->findResource(type, filename);
02108 }
02109 
02110 QString KStandardDirs::locateLocal( const char *type,
02111                                     const QString& filename, const KComponentData &cData)
02112 {
02113     return locateLocal(type, filename, true, cData);
02114 }
02115 
02116 QString KStandardDirs::locateLocal( const char *type,
02117                                     const QString& filename, bool createDir,
02118                                     const KComponentData &cData)
02119 {
02120     // try to find slashes. If there are some, we have to
02121     // create the subdir first
02122     int slash = filename.lastIndexOf(QLatin1Char('/')) + 1;
02123     if (!slash) { // only one filename
02124         return cData.dirs()->saveLocation(type, QString(), createDir) + filename;
02125     }
02126 
02127     // split path from filename
02128     QString dir = filename.left(slash);
02129     QString file = filename.mid(slash);
02130     return cData.dirs()->saveLocation(type, dir, createDir) + file;
02131 }
02132 
02133 bool KStandardDirs::checkAccess(const QString& pathname, int mode)
02134 {
02135     int accessOK = KDE::access( pathname, mode );
02136     if ( accessOK == 0 )
02137         return true;  // OK, I can really access the file
02138 
02139     // else
02140     // if we want to write the file would be created. Check, if the
02141     // user may write to the directory to create the file.
02142     if ( (mode & W_OK) == 0 )
02143         return false;   // Check for write access is not part of mode => bail out
02144 
02145 
02146     if (!KDE::access( pathname, F_OK)) // if it already exists
02147         return false;
02148 
02149     //strip the filename (everything until '/' from the end
02150     QString dirName(pathname);
02151     int pos = dirName.lastIndexOf(QLatin1Char('/'));
02152     if ( pos == -1 )
02153         return false;   // No path in argument. This is evil, we won't allow this
02154     else if ( pos == 0 ) // don't turn e.g. /root into an empty string
02155         pos = 1;
02156 
02157     dirName.truncate(pos); // strip everything starting from the last '/'
02158 
02159     accessOK = KDE::access( dirName, W_OK );
02160     // -?- Can I write to the accessed diretory
02161     if ( accessOK == 0 )
02162         return true;  // Yes
02163     else
02164         return false; // No
02165 }
02166 
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Thu May 10 2012 20:49:32 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDECore

Skip menu "KDECore"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs-4.8.3 API Reference

Skip menu "kdelibs-4.8.3 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal