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

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

Skip menu "kdelibs"
  • 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
Generated for kdelibs by doxygen 1.7.5.1
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal