• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.9.5 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         const QStringList dirs = m_relatives.value(type);
01106         const QString typeInstallPath = installPath(type); // could be empty
01107 // better #ifdef incasesensitive_filesystem
01108 #ifdef Q_WS_WIN
01109         const QString installdir = typeInstallPath.isEmpty() ? QString() : realPath(typeInstallPath).toLower();
01110         const QString installprefix = installPath("kdedir").toLower();
01111 #else
01112         const QString installdir = typeInstallPath.isEmpty() ? QString() : realPath(typeInstallPath);
01113         const QString installprefix = installPath("kdedir");
01114 #endif
01115         if (!dirs.isEmpty())
01116         {
01117             bool local = true;
01118 
01119             for (QStringList::ConstIterator it = dirs.constBegin();
01120                  it != dirs.constEnd(); ++it)
01121             {
01122                 if ((*it).startsWith(QLatin1Char('%'))) {
01123                     // grab the "data" from "%data/apps"
01124                     const int pos = (*it).indexOf(QLatin1Char('/'));
01125                     QString rel = (*it).mid(1, pos - 1);
01126                     QString rest = (*it).mid(pos + 1);
01127                     const QStringList basedirs = resourceDirs(rel.toUtf8().constData(), subdirForRestrictions);
01128                     for (QStringList::ConstIterator it2 = basedirs.begin();
01129                          it2 != basedirs.end(); ++it2)
01130                     {
01131 #ifdef Q_WS_WIN
01132                         const QString path = realPath( *it2 + rest ).toLower();
01133 #else
01134                         const QString path = realPath( *it2 + rest );
01135 #endif
01136                         testdir.setPath(path);
01137                         if ((local || testdir.exists()) && !candidates.contains(path))
01138                             candidates.append(path);
01139                         local = false;
01140                     }
01141                 }
01142             }
01143 
01144             const QStringList *prefixList = 0;
01145             if (strncmp(type, "xdgdata-", 8) == 0)
01146                 prefixList = &(xdgdata_prefixes);
01147             else if (strncmp(type, "xdgconf-", 8) == 0)
01148                 prefixList = &(xdgconf_prefixes);
01149             else
01150                 prefixList = &m_prefixes;
01151 
01152             for (QStringList::ConstIterator pit = prefixList->begin();
01153                  pit != prefixList->end();
01154                  ++pit)
01155             {
01156             if((*pit)!=installprefix||installdir.isEmpty())
01157             {
01158                     for (QStringList::ConstIterator it = dirs.constBegin();
01159                          it != dirs.constEnd(); ++it)
01160                     {
01161                         if ((*it).startsWith(QLatin1Char('%')))
01162                             continue;
01163 #ifdef Q_WS_WIN
01164                         const QString path = realPath( *pit + *it ).toLower();
01165 #else
01166                         const QString path = realPath( *pit + *it );
01167 #endif
01168                         testdir.setPath(path);
01169                         if (local && restrictionActive)
01170                             continue;
01171                         if ((local || testdir.exists()) && !candidates.contains(path))
01172                             candidates.append(path);
01173                     }
01174                     local = false;
01175                 }
01176             else
01177             {
01178                     // we have a custom install path, so use this instead of <installprefix>/<relative dir>
01179                 testdir.setPath(installdir);
01180                     if(testdir.exists() && ! candidates.contains(installdir))
01181                         candidates.append(installdir);
01182             }
01183         }
01184         }
01185 
01186         // make sure we find the path where it's installed
01187         if (!installdir.isEmpty()) {
01188             bool ok = true;
01189             foreach (const QString &s, candidates) {
01190                 if (installdir.startsWith(s)) {
01191                     ok = false;
01192                     break;
01193                 }
01194             }
01195             if (ok)
01196                 candidates.append(installdir);
01197         }
01198 
01199         const QStringList absDirs = m_absolutes.value(type);
01200         for (QStringList::ConstIterator it = absDirs.constBegin();
01201              it != absDirs.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     //kDebug(180) << "findExe(): checking system paths";
01379     const QStringList exePaths = systemPaths( pstr );
01380     for (QStringList::ConstIterator it = exePaths.begin(); it != exePaths.end(); ++it)
01381     {
01382         p = (*it) + QLatin1Char('/');
01383         p += appname;
01384 
01385         // Check for executable in this tokenized path
01386         result = checkExecutable(p, options & IgnoreExecBit);
01387         if (!result.isEmpty()) {
01388             //kDebug(180) << "findExe(): returning " << result;
01389             return result;
01390         }
01391     }
01392 
01393     // Not found in PATH, look into the KDE-specific bin dir ("exe" resource)
01394     p = installPath("exe");
01395     p += appname;
01396     result = checkExecutable(p, options & IgnoreExecBit);
01397     if (!result.isEmpty()) {
01398         //kDebug(180) << "findExe(): returning " << result;
01399         return result;
01400     }
01401 
01402     // If we reach here, the executable wasn't found.
01403     // So return empty string.
01404 
01405     //kDebug(180) << "findExe(): failed, nothing matched";
01406     return QString();
01407 }
01408 
01409 int KStandardDirs::findAllExe( QStringList& list, const QString& appname,
01410                                const QString& pstr, SearchOptions options )
01411 {
01412 #ifdef Q_OS_WIN
01413     QStringList executable_extensions = executableExtensions();
01414     if (!executable_extensions.contains(appname.section(QLatin1Char('.'), -1, -1, QString::SectionIncludeLeadingSep), Qt::CaseInsensitive)) {
01415         int total = 0;
01416         foreach (const QString& extension, executable_extensions) {
01417             total += findAllExe (list, appname + extension, pstr, options);
01418         }
01419         return total;
01420     }
01421 #endif
01422     QFileInfo info;
01423     QString p;
01424     list.clear();
01425 
01426     const QStringList exePaths = systemPaths( pstr );
01427     for (QStringList::ConstIterator it = exePaths.begin(); it != exePaths.end(); ++it)
01428     {
01429         p = (*it) + QLatin1Char('/');
01430         p += appname;
01431 
01432 #ifdef Q_WS_MAC
01433         QString bundle = getBundle( p, (options & IgnoreExecBit) );
01434         if ( !bundle.isEmpty() ) {
01435             //kDebug(180) << "findExe(): returning " << bundle;
01436             list.append( bundle );
01437         }
01438 #endif
01439 
01440         info.setFile( p );
01441 
01442         if( info.exists() && ( ( options & IgnoreExecBit ) || info.isExecutable())
01443             && info.isFile() ) {
01444             list.append( p );
01445         }
01446     }
01447 
01448     return list.count();
01449 }
01450 
01451 static inline QString equalizePath(QString &str)
01452 {
01453 #ifdef Q_WS_WIN
01454     // filter pathes through QFileInfo to have always
01455     // the same case for drive letters
01456     QFileInfo f(str);
01457     if (f.isAbsolute())
01458         return f.absoluteFilePath();
01459     else
01460 #endif
01461         return str;
01462 }
01463 
01464 static void tokenize(QStringList& tokens, const QString& str,
01465                     const QString& delim)
01466 {
01467     const int len = str.length();
01468     QString token;
01469 
01470     for(int index = 0; index < len; index++) {
01471         if (delim.contains(str[index])) {
01472             tokens.append(equalizePath(token));
01473             token.clear();
01474         } else {
01475             token += str[index];
01476         }
01477     }
01478     if (!token.isEmpty()) {
01479         tokens.append(equalizePath(token));
01480     }
01481 }
01482 
01483 #ifndef KDE_NO_DEPRECATED
01484 QString KStandardDirs::kde_default(const char *type)
01485 {
01486     return QString(QLatin1Char('%')) + QString::fromLatin1(type) + QLatin1Char('/');
01487 }
01488 #endif
01489 
01490 QString KStandardDirs::saveLocation(const char *type,
01491                                     const QString& suffix,
01492                                     bool create) const
01493 {
01494     QMutexLocker lock(&d->m_cacheMutex);
01495     QString path = d->m_savelocations.value(type);
01496     if (path.isEmpty())
01497     {
01498         QStringList dirs = d->m_relatives.value(type);
01499         if (dirs.isEmpty() && (
01500                 (strcmp(type, "socket") == 0) ||
01501                 (strcmp(type, "tmp") == 0) ||
01502                 (strcmp(type, "cache") == 0) ))
01503         {
01504             (void) resourceDirs(type); // Generate socket|tmp|cache resource.
01505             dirs = d->m_relatives.value(type); // Search again.
01506         }
01507         if (!dirs.isEmpty())
01508         {
01509             path = dirs.first();
01510 
01511             if (path.startsWith(QLatin1Char('%'))) {
01512                 // grab the "data" from "%data/apps"
01513                 const int pos = path.indexOf(QLatin1Char('/'));
01514                 QString rel = path.mid(1, pos - 1);
01515                 QString rest = path.mid(pos + 1);
01516                 QString basepath = saveLocation(rel.toUtf8().constData());
01517                 path = basepath + rest;
01518             } else
01519 
01520                 // Check for existence of typed directory + suffix
01521                 if (strncmp(type, "xdgdata-", 8) == 0) {
01522                     path = realPath( localxdgdatadir() + path ) ;
01523                 } else if (strncmp(type, "xdgconf-", 8) == 0) {
01524                     path = realPath( localxdgconfdir() + path );
01525                 } else {
01526                     path = realPath( localkdedir() + path );
01527                 }
01528         }
01529         else {
01530             dirs = d->m_absolutes.value(type);
01531             if (dirs.isEmpty()) {
01532                 qFatal("KStandardDirs: The resource type %s is not registered", type);
01533             } else {
01534                 path = realPath(dirs.first());
01535             }
01536         }
01537 
01538         d->m_savelocations.insert(type, path.endsWith(QLatin1Char('/')) ? path : path + QLatin1Char('/'));
01539     }
01540     QString fullPath = path + suffix;
01541 
01542     KDE_struct_stat st;
01543     if (KDE::stat(fullPath, &st) != 0 || !(S_ISDIR(st.st_mode))) {
01544         if(!create) {
01545 #ifndef NDEBUG
01546             // Too much noise from kbuildsycoca4 -- it's fine if this happens from KConfig
01547             // when parsing global files without a local equivalent.
01548             //kDebug(180) << QString("save location %1 doesn't exist").arg(fullPath);
01549 #endif
01550             return fullPath;
01551         }
01552         if(!makeDir(fullPath, 0700)) {
01553             return fullPath;
01554         }
01555         d->m_dircache.remove(type);
01556     }
01557     if (!fullPath.endsWith(QLatin1Char('/')))
01558         fullPath += QLatin1Char('/');
01559     return fullPath;
01560 }
01561 
01562 // KDE5: make the method const
01563 QString KStandardDirs::relativeLocation(const char *type, const QString &absPath)
01564 {
01565     QString fullPath = absPath;
01566     int i = absPath.lastIndexOf(QLatin1Char('/'));
01567     if (i != -1) {
01568         fullPath = realFilePath(absPath); // Normalize
01569     }
01570 
01571     const QStringList candidates = resourceDirs(type);
01572 
01573     for (QStringList::ConstIterator it = candidates.begin();
01574          it != candidates.end(); ++it) {
01575         if (fullPath.startsWith(*it)) {
01576             return fullPath.mid((*it).length());
01577         }
01578     }
01579     return absPath;
01580 }
01581 
01582 
01583 bool KStandardDirs::makeDir(const QString& dir, int mode)
01584 {
01585     // we want an absolute path
01586     if (QDir::isRelativePath(dir))
01587         return false;
01588 
01589 #ifdef Q_WS_WIN
01590     return QDir().mkpath(dir);
01591 #else
01592     QString target = dir;
01593     uint len = target.length();
01594 
01595     // append trailing slash if missing
01596     if (dir.at(len - 1) != QLatin1Char('/'))
01597         target += QLatin1Char('/');
01598 
01599     QString base;
01600     uint i = 1;
01601 
01602     while( i < len )
01603     {
01604         KDE_struct_stat st;
01605         int pos = target.indexOf(QLatin1Char('/'), i);
01606         base += target.mid(i - 1, pos - i + 1);
01607         QByteArray baseEncoded = QFile::encodeName(base);
01608         // bail out if we encountered a problem
01609         if (KDE_stat(baseEncoded, &st) != 0)
01610         {
01611             // Directory does not exist....
01612             // Or maybe a dangling symlink ?
01613             if (KDE_lstat(baseEncoded, &st) == 0)
01614                 (void)unlink(baseEncoded); // try removing
01615 
01616             if (KDE_mkdir(baseEncoded, static_cast<mode_t>(mode)) != 0) {
01617                 baseEncoded.prepend( "trying to create local folder " );
01618                 perror(baseEncoded.constData());
01619                 return false; // Couldn't create it :-(
01620             }
01621         }
01622         i = pos + 1;
01623     }
01624     return true;
01625 #endif
01626 }
01627 
01628 static QString readEnvPath(const char *env)
01629 {
01630     QByteArray c_path;
01631 #ifndef _WIN32_WCE
01632     c_path = qgetenv(env);
01633     if (c_path.isEmpty())
01634         return QString();
01635 #else
01636     bool ok;
01637     QString retval = getWin32RegistryValue(HKEY_LOCAL_MACHINE, "Software\\kde", "KDEDIRS", &ok);
01638     if (!ok){
01639         return QString();
01640     } else {
01641         c_path = retval.toAscii();
01642     }
01643 #endif
01644     return QDir::fromNativeSeparators(QFile::decodeName(c_path));
01645 }
01646 
01647 #ifdef __linux__
01648 static QString executablePrefix()
01649 {
01650     char path_buffer[MAXPATHLEN + 1];
01651     path_buffer[MAXPATHLEN] = 0;
01652     int length = readlink ("/proc/self/exe", path_buffer, MAXPATHLEN);
01653     if (length == -1)
01654         return QString();
01655 
01656     path_buffer[length] = '\0';
01657 
01658     QString path = QFile::decodeName(path_buffer);
01659 
01660     if(path.isEmpty())
01661         return QString();
01662 
01663     int pos = path.lastIndexOf(QLatin1Char('/')); // Skip filename
01664     if(pos <= 0)
01665         return QString();
01666     pos = path.lastIndexOf(QLatin1Char('/'), pos - 1); // Skip last directory
01667     if(pos <= 0)
01668         return QString();
01669 
01670     return path.left(pos);
01671 }
01672 #endif
01673 
01674 void KStandardDirs::addResourcesFrom_krcdirs()
01675 {
01676     QString localFile = QDir::currentPath() + QLatin1String("/.krcdirs");
01677     if (!QFile::exists(localFile))
01678         return;
01679 
01680     QSettings iniFile(localFile, QSettings::IniFormat);
01681     iniFile.beginGroup(QString::fromLatin1("KStandardDirs"));
01682     const QStringList resources = iniFile.allKeys();
01683     foreach(const QString &key, resources)
01684     {
01685         QDir path(iniFile.value(key).toString());
01686         if (!path.exists())
01687             continue;
01688 
01689         if(path.makeAbsolute())
01690             addResourceDir(key.toAscii(), path.path(), false);
01691     }
01692 }
01693 
01694 void KStandardDirs::addKDEDefaults()
01695 {
01696     addResourcesFrom_krcdirs();
01697 
01698     QStringList kdedirList;
01699     // begin KDEDIRS
01700     QString kdedirs = readEnvPath("KDEDIRS");
01701 
01702     if (!kdedirs.isEmpty())
01703     {
01704         tokenize(kdedirList, kdedirs, QString(QLatin1Char(KPATH_SEPARATOR)));
01705     }
01706     kdedirList.append(installPath("kdedir"));
01707 
01708     QString execPrefix(QFile::decodeName(EXEC_INSTALL_PREFIX));
01709     if (!execPrefix.isEmpty() && !kdedirList.contains(execPrefix))
01710         kdedirList.append(execPrefix);
01711 #ifdef __linux__
01712     const QString linuxExecPrefix = executablePrefix();
01713     if ( !linuxExecPrefix.isEmpty() )
01714         kdedirList.append( linuxExecPrefix );
01715 #endif
01716 
01717     // We treat root differently to prevent a "su" shell messing up the
01718     // file permissions in the user's home directory.
01719     QString localKdeDir = readEnvPath(getuid() ? "KDEHOME" : "KDEROOTHOME");
01720     if (!localKdeDir.isEmpty()) {
01721         if (!localKdeDir.endsWith(QLatin1Char('/')))
01722             localKdeDir += QLatin1Char('/');
01723     } else {
01724         // TODO KDE5: make localKdeDir equal to localXdgDir (which is determined further below and
01725         // defaults to ~/.config) + '/' + $KDECONFIG (which would default to e.g. "KDE")
01726         // This would mean ~/.config/KDE/ by default, more xdg-compliant.
01727 
01728 #if defined(Q_WS_MACX)
01729         localKdeDir =  QDir::homePath() + QLatin1String("/Library/Preferences/KDE/");
01730 #elif defined(Q_WS_WIN)
01731 #ifndef _WIN32_WCE
01732         WCHAR wPath[MAX_PATH+1];
01733         if ( SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, wPath) == S_OK) {
01734           localKdeDir = QDir::fromNativeSeparators(QString::fromUtf16((const ushort *) wPath)) + QLatin1Char('/') + QString::fromLatin1(KDE_DEFAULT_HOME) + QLatin1Char('/');
01735         } else {
01736 #endif
01737           localKdeDir =  QDir::homePath() + QLatin1Char('/') + QString::fromLatin1(KDE_DEFAULT_HOME) + QLatin1Char('/');
01738 #ifndef _WIN32_WCE
01739         }
01740 #endif
01741 #else
01742         localKdeDir =  QDir::homePath() + QLatin1Char('/') + QString::fromLatin1(KDE_DEFAULT_HOME) + QLatin1Char('/');
01743 #endif
01744     }
01745 
01746     if (localKdeDir != QLatin1String("-/"))
01747     {
01748         localKdeDir = KShell::tildeExpand(localKdeDir);
01749         addPrefix(localKdeDir);
01750     }
01751 
01752 #ifdef Q_WS_MACX
01753     // Adds the "Contents" directory of the current application bundle to
01754     // the search path. This way bundled resources can be found.
01755     QDir bundleDir(mac_app_filename());
01756     if (bundleDir.dirName() == QLatin1String("MacOS")) { // just to be sure we're in a bundle
01757         bundleDir.cdUp();
01758         // now dirName should be "Contents". In there we can find our normal
01759         // dir-structure, beginning with "share"
01760         addPrefix(bundleDir.absolutePath());
01761     }
01762 #endif
01763 
01764     QStringList::ConstIterator end(kdedirList.end());
01765     for (QStringList::ConstIterator it = kdedirList.constBegin();
01766          it != kdedirList.constEnd(); ++it)
01767     {
01768         const QString dir = KShell::tildeExpand(*it);
01769         addPrefix(dir);
01770     }
01771     // end KDEDIRS
01772 
01773     // begin XDG_CONFIG_XXX
01774     QStringList xdgdirList;
01775     QString xdgdirs = readEnvPath("XDG_CONFIG_DIRS");
01776     if (!xdgdirs.isEmpty())
01777     {
01778         tokenize(xdgdirList, xdgdirs, QString(QLatin1Char(KPATH_SEPARATOR)));
01779     }
01780     else
01781     {
01782         xdgdirList.clear();
01783         xdgdirList.append(QString::fromLatin1("/etc/xdg"));
01784 #ifdef Q_WS_WIN
01785         xdgdirList.append(installPath("kdedir") + QString::fromLatin1("etc/xdg"));
01786 #else
01787         xdgdirList.append(QFile::decodeName(KDESYSCONFDIR "/xdg"));
01788 #endif
01789     }
01790 
01791     QString localXdgDir = readEnvPath("XDG_CONFIG_HOME");
01792     if (!localXdgDir.isEmpty()) {
01793         if (!localXdgDir.endsWith(QLatin1Char('/')))
01794             localXdgDir += QLatin1Char('/');
01795     } else {
01796 #ifdef Q_WS_MACX
01797         localXdgDir = QDir::homePath() + QString::fromLatin1("/Library/Preferences/XDG/");
01798 #else
01799         localXdgDir = QDir::homePath() + QString::fromLatin1("/.config/");
01800 #endif
01801     }
01802 
01803     localXdgDir = KShell::tildeExpand(localXdgDir);
01804     addXdgConfigPrefix(localXdgDir);
01805 
01806     for (QStringList::ConstIterator it = xdgdirList.constBegin();
01807          it != xdgdirList.constEnd(); ++it)
01808     {
01809         QString dir = KShell::tildeExpand(*it);
01810         addXdgConfigPrefix(dir);
01811     }
01812     // end XDG_CONFIG_XXX
01813 
01814     // begin XDG_DATA_XXX
01815     QStringList kdedirDataDirs;
01816     for (QStringList::ConstIterator it = kdedirList.constBegin();
01817          it != kdedirList.constEnd(); ++it) {
01818         QString dir = *it;
01819         if (!dir.endsWith(QLatin1Char('/')))
01820             dir += QLatin1Char('/');
01821         kdedirDataDirs.append(dir + QLatin1String("share/"));
01822     }
01823 
01824     xdgdirs = readEnvPath("XDG_DATA_DIRS");
01825     if (!xdgdirs.isEmpty()) {
01826         tokenize(xdgdirList, xdgdirs, QString(QLatin1Char(KPATH_SEPARATOR)));
01827         // Ensure the kdedirDataDirs are in there too,
01828         // otherwise resourceDirs() will add kdedir/share/applications/kde4
01829         // as returned by installPath(), and that's incorrect.
01830         Q_FOREACH(const QString& dir, kdedirDataDirs) {
01831             if (!xdgdirList.contains(dir))
01832                 xdgdirList.append(dir);
01833         }
01834     } else {
01835         xdgdirList = kdedirDataDirs;
01836 #ifndef Q_WS_WIN
01837         xdgdirList.append(QString::fromLatin1("/usr/local/share/"));
01838         xdgdirList.append(QString::fromLatin1("/usr/share/"));
01839 #endif
01840     }
01841 
01842     localXdgDir = readEnvPath("XDG_DATA_HOME");
01843     if (!localXdgDir.isEmpty())
01844     {
01845         if (localXdgDir[localXdgDir.length()-1] != QLatin1Char('/'))
01846             localXdgDir += QLatin1Char('/');
01847     }
01848     else
01849     {
01850         localXdgDir = QDir::homePath() + QLatin1String("/.local/share/");
01851     }
01852 
01853     localXdgDir = KShell::tildeExpand(localXdgDir);
01854     addXdgDataPrefix(localXdgDir);
01855 
01856     for (QStringList::ConstIterator it = xdgdirList.constBegin();
01857          it != xdgdirList.constEnd(); ++it)
01858     {
01859         QString dir = KShell::tildeExpand(*it);
01860         addXdgDataPrefix(dir);
01861     }
01862     // end XDG_DATA_XXX
01863 
01864 
01865     addResourceType("lib", 0, "lib" KDELIBSUFF "/");
01866 
01867     addResourceType("qtplugins", "lib", "plugins");
01868 
01869     uint index = 0;
01870     while (types_indices[index] != -1) {
01871         addResourceType(types_string + types_indices[index], 0, types_string + types_indices[index+1], true);
01872         index+=2;
01873     }
01874     addResourceType("exe", "lib", "kde4/libexec", true );
01875 
01876     addResourceDir("home", QDir::homePath(), false);
01877 
01878     addResourceType("autostart", "xdgconf-autostart", "/"); // merge them, start with xdg autostart
01879     addResourceType("autostart", NULL, "share/autostart"); // KDE ones are higher priority
01880 }
01881 
01882 static QStringList lookupProfiles(const QString &mapFile)
01883 {
01884     QStringList profiles;
01885 
01886     if (mapFile.isEmpty() || !QFile::exists(mapFile))
01887     {
01888         profiles << QString::fromLatin1("default");
01889         return profiles;
01890     }
01891 
01892     struct passwd *pw = getpwuid(geteuid());
01893     if (!pw)
01894     {
01895         profiles << QString::fromLatin1("default");
01896         return profiles; // Not good
01897     }
01898 
01899     QByteArray user = pw->pw_name;
01900 
01901     gid_t sup_gids[512];
01902     int sup_gids_nr = getgroups(512, sup_gids);
01903 
01904     KConfig mapCfgFile(mapFile);
01905     KConfigGroup mapCfg(&mapCfgFile, "Users");
01906     if (mapCfg.hasKey(user.constData()))
01907     {
01908         profiles = mapCfg.readEntry(user.constData(), QStringList());
01909         return profiles;
01910     }
01911 
01912     const KConfigGroup generalGrp(&mapCfgFile, "General");
01913     const QStringList groups = generalGrp.readEntry("groups", QStringList());
01914 
01915     const KConfigGroup groupsGrp(&mapCfgFile, "Groups");
01916 
01917     for( QStringList::ConstIterator it = groups.begin();
01918          it != groups.end(); ++it )
01919     {
01920         QByteArray grp = (*it).toUtf8();
01921         // Check if user is in this group
01922         struct group *grp_ent = getgrnam(grp);
01923         if (!grp_ent) continue;
01924         gid_t gid = grp_ent->gr_gid;
01925         if (pw->pw_gid == gid)
01926         {
01927             // User is in this group --> add profiles
01928             profiles += groupsGrp.readEntry(*it, QStringList());
01929         }
01930         else
01931         {
01932             for(int i = 0; i < sup_gids_nr; i++)
01933             {
01934                 if (sup_gids[i] == gid)
01935                 {
01936                     // User is in this group --> add profiles
01937                     profiles += groupsGrp.readEntry(*it, QStringList());
01938                     break;
01939                 }
01940             }
01941         }
01942     }
01943 
01944     if (profiles.isEmpty())
01945         profiles << QString::fromLatin1("default");
01946     return profiles;
01947 }
01948 
01949 extern bool kde_kiosk_admin;
01950 
01951 bool KStandardDirs::addCustomized(KConfig *config)
01952 {
01953     if (!d->m_checkRestrictions) // there are already customized entries
01954         return false; // we just quit and hope they are the right ones
01955 
01956     // save the numbers of config directories. If this changes,
01957     // we will return true to give KConfig a chance to reparse
01958     int configdirs = resourceDirs("config").count();
01959 
01960     if (true)
01961     {
01962         // reading the prefixes in
01963         QString group = QLatin1String("Directories");
01964         KConfigGroup cg(config, group);
01965 
01966         QString kioskAdmin = cg.readEntry("kioskAdmin");
01967         if (!kioskAdmin.isEmpty() && !kde_kiosk_admin)
01968         {
01969             int i = kioskAdmin.indexOf(QLatin1Char(':'));
01970             QString user = kioskAdmin.left(i);
01971             QString host = kioskAdmin.mid(i+1);
01972 
01973             KUser thisUser;
01974             char hostname[ 256 ];
01975             hostname[ 0 ] = '\0';
01976             if (!gethostname( hostname, 255 ))
01977                 hostname[sizeof(hostname)-1] = '\0';
01978 
01979             if ((user == thisUser.loginName()) &&
01980                 (host.isEmpty() || (host == QLatin1String(hostname))))
01981             {
01982                 kde_kiosk_admin = true;
01983             }
01984         }
01985 
01986         bool readProfiles = true;
01987 
01988         if (kde_kiosk_admin && !qgetenv("KDE_KIOSK_NO_PROFILES").isEmpty())
01989             readProfiles = false;
01990 
01991         QString userMapFile = cg.readEntry("userProfileMapFile");
01992         QString profileDirsPrefix = cg.readEntry("profileDirsPrefix");
01993         if (!profileDirsPrefix.isEmpty() && !profileDirsPrefix.endsWith(QLatin1Char('/')))
01994             profileDirsPrefix.append(QLatin1Char('/'));
01995 
01996         QStringList profiles;
01997         if (readProfiles)
01998             profiles = lookupProfiles(userMapFile);
01999         QString profile;
02000 
02001         bool priority = false;
02002         while(true)
02003         {
02004             KConfigGroup cg(config, group);
02005             const QStringList list = cg.readEntry("prefixes", QStringList());
02006             for (QStringList::ConstIterator it = list.begin(); it != list.end(); ++it)
02007             {
02008                 addPrefix(*it, priority);
02009                 addXdgConfigPrefix(*it + QLatin1String("/etc/xdg"), priority);
02010                 addXdgDataPrefix(*it + QLatin1String("/share"), priority);
02011             }
02012             // If there are no prefixes defined, check if there is a directory
02013             // for this profile under <profileDirsPrefix>
02014             if (list.isEmpty() && !profile.isEmpty() && !profileDirsPrefix.isEmpty())
02015             {
02016                 QString dir = profileDirsPrefix + profile;
02017                 addPrefix(dir, priority);
02018                 addXdgConfigPrefix(dir + QLatin1String("/etc/xdg"), priority);
02019                 addXdgDataPrefix(dir + QLatin1String("/share"), priority);
02020             }
02021 
02022             // iterating over all entries in the group Directories
02023             // to find entries that start with dir_$type
02024             const QMap<QString, QString> entries = config->entryMap(group);
02025             for (QMap<QString, QString>::ConstIterator it2 = entries.begin();
02026                  it2 != entries.end(); ++it2)
02027             {
02028                 const QString key = it2.key();
02029                 if (key.startsWith(QLatin1String("dir_"))) {
02030                     // generate directory list, there may be more than 1.
02031                     const QStringList dirs = (*it2).split(QString(QLatin1Char(',')));
02032                     QStringList::ConstIterator sIt(dirs.begin());
02033                     QString resType = key.mid(4);
02034                     for (; sIt != dirs.end(); ++sIt)
02035                     {
02036                         addResourceDir(resType.toLatin1(), *sIt, priority);
02037                     }
02038                 }
02039             }
02040             if (profiles.isEmpty())
02041                 break;
02042             profile = profiles.back();
02043             group = QString::fromLatin1("Directories-%1").arg(profile);
02044             profiles.pop_back();
02045             priority = true;
02046         }
02047     }
02048 
02049     // Process KIOSK restrictions.
02050     if (!kde_kiosk_admin || qgetenv("KDE_KIOSK_NO_RESTRICTIONS").isEmpty())
02051     {
02052         KConfigGroup cg(config, "KDE Resource Restrictions");
02053         const QMap<QString, QString> entries = cg.entryMap();
02054         for (QMap<QString, QString>::ConstIterator it2 = entries.begin();
02055              it2 != entries.end(); ++it2)
02056         {
02057             const QString key = it2.key();
02058             if (!cg.readEntry(key, true))
02059             {
02060                 d->m_restrictionsActive = true;
02061                 const QByteArray cKey = key.toLatin1();
02062                 d->m_restrictions.insert(cKey, true);
02063                 d->m_dircache.remove(cKey);
02064                 d->m_savelocations.remove(cKey);
02065             }
02066         }
02067     }
02068 
02069     // check if the number of config dirs changed
02070     bool configDirsChanged = (resourceDirs("config").count() != configdirs);
02071     // If the config dirs changed, we check kiosk restrictions again.
02072     d->m_checkRestrictions = configDirsChanged;
02073     // return true if the number of config dirs changed: reparse config file
02074     return configDirsChanged;
02075 }
02076 
02077 QString KStandardDirs::localkdedir() const
02078 {
02079     // Return the prefix to use for saving
02080     return d->m_prefixes.first();
02081 }
02082 
02083 QString KStandardDirs::localxdgdatadir() const
02084 {
02085     // Return the prefix to use for saving
02086     return d->xdgdata_prefixes.first();
02087 }
02088 
02089 QString KStandardDirs::localxdgconfdir() const
02090 {
02091     // Return the prefix to use for saving
02092     return d->xdgconf_prefixes.first();
02093 }
02094 
02095 
02096 // just to make code more readable without macros
02097 QString KStandardDirs::locate( const char *type,
02098                                const QString& filename, const KComponentData &cData)
02099 {
02100     return cData.dirs()->findResource(type, filename);
02101 }
02102 
02103 QString KStandardDirs::locateLocal( const char *type,
02104                                     const QString& filename, const KComponentData &cData)
02105 {
02106     return locateLocal(type, filename, true, cData);
02107 }
02108 
02109 QString KStandardDirs::locateLocal( const char *type,
02110                                     const QString& filename, bool createDir,
02111                                     const KComponentData &cData)
02112 {
02113     // try to find slashes. If there are some, we have to
02114     // create the subdir first
02115     int slash = filename.lastIndexOf(QLatin1Char('/')) + 1;
02116     if (!slash) { // only one filename
02117         return cData.dirs()->saveLocation(type, QString(), createDir) + filename;
02118     }
02119 
02120     // split path from filename
02121     QString dir = filename.left(slash);
02122     QString file = filename.mid(slash);
02123     return cData.dirs()->saveLocation(type, dir, createDir) + file;
02124 }
02125 
02126 bool KStandardDirs::checkAccess(const QString& pathname, int mode)
02127 {
02128     int accessOK = KDE::access( pathname, mode );
02129     if ( accessOK == 0 )
02130         return true;  // OK, I can really access the file
02131 
02132     // else
02133     // if we want to write the file would be created. Check, if the
02134     // user may write to the directory to create the file.
02135     if ( (mode & W_OK) == 0 )
02136         return false;   // Check for write access is not part of mode => bail out
02137 
02138 
02139     if (!KDE::access( pathname, F_OK)) // if it already exists
02140         return false;
02141 
02142     //strip the filename (everything until '/' from the end
02143     QString dirName(pathname);
02144     int pos = dirName.lastIndexOf(QLatin1Char('/'));
02145     if ( pos == -1 )
02146         return false;   // No path in argument. This is evil, we won't allow this
02147     else if ( pos == 0 ) // don't turn e.g. /root into an empty string
02148         pos = 1;
02149 
02150     dirName.truncate(pos); // strip everything starting from the last '/'
02151 
02152     accessOK = KDE::access( dirName, W_OK );
02153     // -?- Can I write to the accessed diretory
02154     if ( accessOK == 0 )
02155         return true;  // Yes
02156     else
02157         return false; // No
02158 }
02159 
This file is part of the KDE documentation.
Documentation copyright © 1996-2019 The KDE developers.
Generated on Mon Jan 21 2019 12:28:12 by doxygen 1.7.5.1 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.9.5 API Reference

Skip menu "kdelibs-4.9.5 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