# kdecore Library API Documentation

Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# kstandarddirs.cpp

    00001 /* This file is part of the KDE libraries
    00002    Copyright (C) 1999 Sirtaj Singh Kang <taj@kde.org>
    00003    Copyright (C) 1999 Stephan Kulow <coolo@kde.org>
    00004    Copyright (C) 1999 Waldo Bastian <bastian@kde.org>
    00005
    00006    This library is free software; you can redistribute it and/or
    00007    modify it under the terms of the GNU Library General Public
    00008    License version 2 as published by the Free Software Foundation.
    00009
    00010    This library is distributed in the hope that it will be useful,
    00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
    00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00013    Library General Public License for more details.
    00014
    00015    You should have received a copy of the GNU Library General Public License
    00016    along with this library; see the file COPYING.LIB.  If not, write to
    00017    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    00018    Boston, MA 02111-1307, USA.
    00019 */
    00020
    00021 /*
    00022  * Author: Stephan Kulow <coolo@kde.org> and Sirtaj Singh Kang <taj@kde.org>
    00023  * Version: $Id: kstandarddirs.cpp 376464 2005-01-08 13:34:50Z ogoffart $
    00024  * Generated:   Thu Mar  5 16:05:28 EST 1998
    00025  */
    00026
    00027 #include "config.h"
    00028
    00029 #include <stdlib.h>
    00030 #include <assert.h>
    00031 #include <errno.h>
    00032 #ifdef HAVE_SYS_STAT_H
    00033 #include <sys/stat.h>
    00034 #endif
    00035 #include <sys/param.h>
    00036 #include <sys/types.h>
    00037 #include <dirent.h>
    00038 #include <pwd.h>
    00039 #include <grp.h>
    00040
    00041 #include <qregexp.h>
    00042 #include <qasciidict.h>
    00043 #include <qdict.h>
    00044 #include <qdir.h>
    00045 #include <qfileinfo.h>
    00046 #include <qstring.h>
    00047 #include <qstringlist.h>
    00048
    00049 #include "kstandarddirs.h"
    00050 #include "kconfig.h"
    00051 #include "kdebug.h"
    00052 #include "kinstance.h"
    00053 #include "kshell.h"
    00054 #include "ksimpleconfig.h"
    00055 #include "kuser.h"
    00056 #include "kstaticdeleter.h"
    00057 #include <kde_file.h>
    00058
    00059 template class QDict<QStringList>;
    00060
    00061 class KStandardDirs::KStandardDirsPrivate
    00062 {
    00063 public:
    00064    KStandardDirsPrivate()
    00065     : restrictionsActive(false),
    00066       dataRestrictionActive(false),
    00067       checkRestrictions(true)
    00068    { }
    00069
    00070    bool restrictionsActive;
    00071    bool dataRestrictionActive;
    00072    bool checkRestrictions;
    00073    QAsciiDict<bool> restrictions;
    00074    QStringList xdgdata_prefixes;
    00075    QStringList xdgconf_prefixes;
    00076 };
    00077
    00078 // Singleton, with data shared by all kstandarddirs instances.
    00079 // Used in static methods like findExe()
    00080 class KStandardDirsSingleton
    00081 {
    00082 public:
    00083    QString defaultprefix;
    00084    QString defaultbindir;
    00085    static KStandardDirsSingleton* self();
    00086 private:
    00087    static KStandardDirsSingleton* s_self;
    00088 };
    00089 static KStaticDeleter<KStandardDirsSingleton> kstds_sd;
    00090 KStandardDirsSingleton* KStandardDirsSingleton::s_self = 0;
    00091 KStandardDirsSingleton* KStandardDirsSingleton::self() {
    00092     if ( !s_self )
    00093         kstds_sd.setObject( s_self, new KStandardDirsSingleton );
    00094     return s_self;
    00095 }
    00096
    00097 static const char* const types[] = {"html", "icon", "apps", "sound",
    00098                   "data", "locale", "services", "mime",
    00099                   "servicetypes", "config", "exe",
    00100                   "wallpaper", "lib", "pixmap", "templates",
    00101                   "module", "qtplugins",
    00102                   "xdgdata-apps", "xdgdata-dirs", "xdgconf-menu",
    00103                   "kcfg", "emoticons", 0 };
    00104
    00105 static int tokenize( QStringList& token, const QString& str,
    00106         const QString& delim );
    00107
    00108 KStandardDirs::KStandardDirs( ) : addedCustoms(false)
    00109 {
    00110     d = new KStandardDirsPrivate;
    00111     dircache.setAutoDelete(true);
    00112     relatives.setAutoDelete(true);
    00113     absolutes.setAutoDelete(true);
    00114     savelocations.setAutoDelete(true);
    00115     addKDEDefaults();
    00116 }
    00117
    00118 KStandardDirs::~KStandardDirs()
    00119 {
    00120     delete d;
    00121 }
    00122
    00123 bool KStandardDirs::isRestrictedResource(const char *type, const QString& relPath) const
    00124 {
    00125    if (!d || !d->restrictionsActive)
    00126       return false;
    00127
    00128    if (d->restrictions[type])
    00129       return true;
    00130
    00131    if (strcmp(type, "data")==0)
    00132    {
    00133       applyDataRestrictions(relPath);
    00134       if (d->dataRestrictionActive)
    00135       {
    00136          d->dataRestrictionActive = false;
    00137          return true;
    00138       }
    00139    }
    00140    return false;
    00141 }
    00142
    00143 void KStandardDirs::applyDataRestrictions(const QString &relPath) const
    00144 {
    00145    QString key;
    00146    int i = relPath.find('/');
    00147    if (i != -1)
    00148       key = "data_"+relPath.left(i);
    00149    else
    00150       key = "data_"+relPath;
    00151
    00152    if (d && d->restrictions[key.latin1()])
    00153       d->dataRestrictionActive = true;
    00154 }
    00155
    00156
    00157 QStringList KStandardDirs::allTypes() const
    00158 {
    00159     QStringList list;
    00160     for (int i = 0; types[i] != 0; ++i)
    00161         list.append(QString::fromLatin1(types[i]));
    00162     return list;
    00163 }
    00164
    00165 static void priorityAdd(QStringList &prefixes, const QString& dir, bool priority)
    00166 {
    00167     if (priority && !prefixes.isEmpty())
    00168     {
    00169         // Add in front but behind $KDEHOME
    00170         QStringList::iterator it = prefixes.begin();
    00171         it++;
    00172         prefixes.insert(it, 1, dir);
    00173     }
    00174     else
    00175     {
    00176         prefixes.append(dir);
    00177     }
    00178 }
    00179
    00180 void KStandardDirs::addPrefix( const QString& _dir )
    00181 {
    00182     addPrefix(_dir, false);
    00183 }
    00184
    00185 void KStandardDirs::addPrefix( const QString& _dir, bool priority )
    00186 {
    00187     if (_dir.isEmpty())
    00188     return;
    00189
    00190     QString dir = _dir;
    00191     if (dir.at(dir.length() - 1) != '/')
    00192     dir += '/';
    00193
    00194     if (!prefixes.contains(dir)) {
    00195         priorityAdd(prefixes, dir, priority);
    00196     dircache.clear();
    00197     }
    00198 }
    00199
    00200 void KStandardDirs::addXdgConfigPrefix( const QString& _dir )
    00201 {
    00202     addXdgConfigPrefix(_dir, false);
    00203 }
    00204
    00205 void KStandardDirs::addXdgConfigPrefix( const QString& _dir, bool priority )
    00206 {
    00207     if (_dir.isEmpty())
    00208     return;
    00209
    00210     QString dir = _dir;
    00211     if (dir.at(dir.length() - 1) != '/')
    00212     dir += '/';
    00213
    00214     if (!d->xdgconf_prefixes.contains(dir)) {
    00215         priorityAdd(d->xdgconf_prefixes, dir, priority);
    00216     dircache.clear();
    00217     }
    00218 }
    00219
    00220 void KStandardDirs::addXdgDataPrefix( const QString& _dir )
    00221 {
    00222     addXdgDataPrefix(_dir, false);
    00223 }
    00224
    00225 void KStandardDirs::addXdgDataPrefix( const QString& _dir, bool priority )
    00226 {
    00227     if (_dir.isEmpty())
    00228     return;
    00229
    00230     QString dir = _dir;
    00231     if (dir.at(dir.length() - 1) != '/')
    00232     dir += '/';
    00233
    00234     if (!d->xdgdata_prefixes.contains(dir)) {
    00235     priorityAdd(d->xdgdata_prefixes, dir, priority);
    00236     dircache.clear();
    00237     }
    00238 }
    00239
    00240 QString KStandardDirs::kfsstnd_prefixes()
    00241 {
    00242    return prefixes.join(QChar(KPATH_SEPARATOR));
    00243 }
    00244
    00245 QString KStandardDirs::kfsstnd_xdg_conf_prefixes()
    00246 {
    00247    return d->xdgconf_prefixes.join(QChar(KPATH_SEPARATOR));
    00248 }
    00249
    00250 QString KStandardDirs::kfsstnd_xdg_data_prefixes()
    00251 {
    00252    return d->xdgdata_prefixes.join(QChar(KPATH_SEPARATOR));
    00253 }
    00254
    00255 bool KStandardDirs::addResourceType( const char *type,
    00256                      const QString& relativename )
    00257 {
    00258     return addResourceType(type, relativename, true);
    00259 }
    00260 bool KStandardDirs::addResourceType( const char *type,
    00261                      const QString& relativename,
    00262                      bool priority )
    00263 {
    00264     if (relativename.isEmpty())
    00265        return false;
    00266
    00267     QStringList *rels = relatives.find(type);
    00268     if (!rels) {
    00269     rels = new QStringList();
    00270     relatives.insert(type, rels);
    00271     }
    00272     QString copy = relativename;
    00273     if (copy.at(copy.length() - 1) != '/')
    00274     copy += '/';
    00275     if (!rels->contains(copy)) {
    00276         if (priority)
    00277         rels->prepend(copy);
    00278     else
    00279         rels->append(copy);
    00280     dircache.remove(type); // clean the cache
    00281     return true;
    00282     }
    00283     return false;
    00284 }
    00285
    00286 bool KStandardDirs::addResourceDir( const char *type,
    00287                     const QString& absdir)
    00288 {
    00289     // KDE4: change priority to bring in line with addResourceType
    00290     return addResourceDir(type, absdir, false);
    00291 }
    00292
    00293 bool KStandardDirs::addResourceDir( const char *type,
    00294                     const QString& absdir,
    00295                     bool priority)
    00296 {
    00297     QStringList *paths = absolutes.find(type);
    00298     if (!paths) {
    00299     paths = new QStringList();
    00300     absolutes.insert(type, paths);
    00301     }
    00302     QString copy = absdir;
    00303     if (copy.at(copy.length() - 1) != '/')
    00304       copy += '/';
    00305
    00306     if (!paths->contains(copy)) {
    00307         if (priority)
    00308             paths->prepend(copy);
    00309         else
    00310         paths->append(copy);
    00311     dircache.remove(type); // clean the cache
    00312     return true;
    00313     }
    00314     return false;
    00315 }
    00316
    00317 QString KStandardDirs::findResource( const char *type,
    00318                      const QString& filename ) const
    00319 {
    00320     if (!QDir::isRelativePath(filename))
    00321     return filename; // absolute dirs are absolute dirs, right? :-/
    00322
    00323 #if 0
    00324 kdDebug() << "Find resource: " << type << endl;
    00325 for (QStringList::ConstIterator pit = prefixes.begin();
    00326      pit != prefixes.end();
    00327      pit++)
    00328 {
    00329   kdDebug() << "Prefix: " << *pit << endl;
    00330 }
    00331 #endif
    00332
    00333     QString dir = findResourceDir(type, filename);
    00334     if (dir.isEmpty())
    00335     return dir;
    00336     else return dir + filename;
    00337 }
    00338
    00339 static Q_UINT32 updateHash(const QString &file, Q_UINT32 hash)
    00340 {
    00341     QCString cFile = QFile::encodeName(file);
    00342     KDE_struct_stat buff;
    00343     if ((access(cFile, R_OK) == 0) &&
    00344         (KDE_stat( cFile, &buff ) == 0) &&
    00345         (S_ISREG( buff.st_mode )))
    00346     {
    00347        hash = hash + (Q_UINT32) buff.st_ctime;
    00348     }
    00349     return hash;
    00350 }
    00351
    00352 Q_UINT32 KStandardDirs::calcResourceHash( const char *type,
    00353                   const QString& filename, bool deep) const
    00354 {
    00355     Q_UINT32 hash = 0;
    00356
    00357     if (!QDir::isRelativePath(filename))
    00358     {
    00359         // absolute dirs are absolute dirs, right? :-/
    00360     return updateHash(filename, hash);
    00361     }
    00362     if (d && d->restrictionsActive && (strcmp(type, "data")==0))
    00363        applyDataRestrictions(filename);
    00364     QStringList candidates = resourceDirs(type);
    00365     QString fullPath;
    00366
    00367     for (QStringList::ConstIterator it = candidates.begin();
    00368      it != candidates.end(); it++)
    00369     {
    00370         hash = updateHash(*it + filename, hash);
    00371         if (!deep && hash)
    00372            return hash;
    00373     }
    00374     return hash;
    00375 }
    00376
    00377
    00378 QStringList KStandardDirs::findDirs( const char *type,
    00379                                      const QString& reldir ) const
    00380 {
    00381     QDir testdir;
    00382     QStringList list;
    00383     if (!QDir::isRelativePath(reldir))
    00384     {
    00385         testdir.setPath(reldir);
    00386         if (testdir.exists())
    00387         {
    00388             if (reldir.endsWith("/"))
    00389                list.append(reldir);
    00390             else
    00391                list.append(reldir+'/');
    00392         }
    00393         return list;
    00394     }
    00395
    00396     checkConfig();
    00397
    00398     if (d && d->restrictionsActive && (strcmp(type, "data")==0))
    00399        applyDataRestrictions(reldir);
    00400     QStringList candidates = resourceDirs(type);
    00401
    00402     for (QStringList::ConstIterator it = candidates.begin();
    00403          it != candidates.end(); it++) {
    00404         testdir.setPath(*it + reldir);
    00405         if (testdir.exists())
    00406             list.append(testdir.absPath() + '/');
    00407     }
    00408
    00409     return list;
    00410 }
    00411
    00412 QString KStandardDirs::findResourceDir( const char *type,
    00413                     const QString& filename) const
    00414 {
    00415 #ifndef NDEBUG
    00416     if (filename.isEmpty()) {
    00417       kdWarning() << "filename for type " << type << " in KStandardDirs::findResourceDir is not supposed to be empty!!" << endl;
    00418       return QString::null;
    00419     }
    00420 #endif
    00421
    00422     if (d && d->restrictionsActive && (strcmp(type, "data")==0))
    00423        applyDataRestrictions(filename);
    00424     QStringList candidates = resourceDirs(type);
    00425     QString fullPath;
    00426
    00427     for (QStringList::ConstIterator it = candidates.begin();
    00428       it != candidates.end(); it++) {
    00429       if (exists(*it + filename)) {
    00430 #ifdef Q_WS_WIN //this ensures we're using installed .la files
    00431           if ((*it).isEmpty() && filename.right(3)==".la") {
    00432 #ifndef NDEBUG
    00433               kdDebug() << "KStandardDirs::findResourceDir() found .la in cwd: skipping. (fname=" << filename  << ")" << endl;
    00434 #endif
    00435               continue;
    00436           }
    00437 #endif //Q_WS_WIN
    00438           return *it;
    00439       }
    00440     }
    00441
    00442 #ifndef NDEBUG
    00443     if(false && type != "locale")
    00444       kdDebug() << "KStdDirs::findResDir(): can't find \"" << filename << "\" in type \"" << type << "\"." << endl;
    00445 #endif
    00446
    00447     return QString::null;
    00448 }
    00449
    00450 bool KStandardDirs::exists(const QString &fullPath)
    00451 {
    00452     KDE_struct_stat buff;
    00453     if (access(QFile::encodeName(fullPath), R_OK) == 0 && KDE_stat( QFile::encodeName(fullPath), &buff ) == 0)
    00454     if (fullPath.at(fullPath.length() - 1) != '/') {
    00455         if (S_ISREG( buff.st_mode ))
    00456         return true;
    00457     } else
    00458         if (S_ISDIR( buff.st_mode ))
    00459         return true;
    00460     return false;
    00461 }
    00462
    00463 static void lookupDirectory(const QString& path, const QString &relPart,
    00464                 const QRegExp &regexp,
    00465                 QStringList& list,
    00466                 QStringList& relList,
    00467                 bool recursive, bool unique)
    00468 {
    00469   QString pattern = regexp.pattern();
    00470   if (recursive || pattern.contains('?') || pattern.contains('*'))
    00471   {
    00472     if (path.isEmpty()) //for sanity
    00473       return;
    00474     // We look for a set of files.
    00475     DIR *dp = opendir( QFile::encodeName(path));
    00476     if (!dp)
    00477       return;
    00478
    00479 #ifdef Q_WS_WIN
    00480     assert(path.at(path.length() - 1) == '/' || path.at(path.length() - 1) == '\\');
    00481 #else
    00482     assert(path.at(path.length() - 1) == '/');
    00483 #endif
    00484
    00485     struct dirent *ep;
    00486     KDE_struct_stat buff;
    00487
    00488     QString _dot(".");
    00489     QString _dotdot("..");
    00490
    00491     while( ( ep = readdir( dp ) ) != 0L )
    00492     {
    00493       QString fn( QFile::decodeName(ep->d_name));
    00494       if (fn == _dot || fn == _dotdot || fn.at(fn.length() - 1).latin1() == '~')
    00495     continue;
    00496
    00497       if (!recursive && !regexp.exactMatch(fn))
    00498     continue; // No match
    00499
    00500       QString pathfn = path + fn;
    00501       if ( KDE_stat( QFile::encodeName(pathfn), &buff ) != 0 ) {
    00502     kdDebug() << "Error stat'ing " << pathfn << " : " << perror << endl;
    00503     continue; // Couldn't stat (e.g. no read permissions)
    00504       }
    00505       if ( recursive ) {
    00506     if ( S_ISDIR( buff.st_mode )) {
    00507       lookupDirectory(pathfn + '/', relPart + fn + '/', regexp, list, relList, recursive, unique);
    00508     }
    00509         if (!regexp.exactMatch(fn))
    00510       continue; // No match
    00511       }
    00512       if ( S_ISREG( buff.st_mode))
    00513       {
    00514         if (!unique || !relList.contains(relPart + fn))
    00515         {
    00516         list.append( pathfn );
    00517         relList.append( relPart + fn );
    00518         }
    00519       }
    00520     }
    00521     closedir( dp );
    00522   }
    00523   else
    00524   {
    00525      // We look for a single file.
    00526      QString fn = pattern;
    00527      QString pathfn = path + fn;
    00528      KDE_struct_stat buff;
    00529      if ( KDE_stat( QFile::encodeName(pathfn), &buff ) != 0 )
    00530         return; // File not found
    00531      if ( S_ISREG( buff.st_mode))
    00532      {
    00533        if (!unique || !relList.contains(relPart + fn))
    00534        {
    00535          list.append( pathfn );
    00536          relList.append( relPart + fn );
    00537        }
    00538      }
    00539   }
    00540 }
    00541
    00542 static void lookupPrefix(const QString& prefix, const QString& relpath,
    00543                          const QString& relPart,
    00544              const QRegExp &regexp,
    00545              QStringList& list,
    00546              QStringList& relList,
    00547              bool recursive, bool unique)
    00548 {
    00549     if (relpath.isEmpty()) {
    00550        lookupDirectory(prefix, relPart, regexp, list,
    00551                relList, recursive, unique);
    00552        return;
    00553     }
    00554     QString path;
    00555     QString rest;
    00556
    00557     if (relpath.length())
    00558     {
    00559        int slash = relpath.find('/');
    00560        if (slash < 0)
    00561        rest = relpath.left(relpath.length() - 1);
    00562        else {
    00563        path = relpath.left(slash);
    00564        rest = relpath.mid(slash + 1);
    00565        }
    00566     }
    00567
    00568     if (prefix.isEmpty()) //for sanity
    00569       return;
    00570 #ifdef Q_WS_WIN
    00571     assert(prefix.at(prefix.length() - 1) == '/' || prefix.at(prefix.length() - 1) == '\\');
    00572 #else
    00573     assert(prefix.at(prefix.length() - 1) == '/');
    00574 #endif
    00575     KDE_struct_stat buff;
    00576
    00577     if (path.contains('*') || path.contains('?')) {
    00578
    00579     QRegExp pathExp(path, true, true);
    00580     DIR *dp = opendir( QFile::encodeName(prefix) );
    00581     if (!dp) {
    00582         return;
    00583     }
    00584
    00585     struct dirent *ep;
    00586
    00587         QString _dot(".");
    00588         QString _dotdot("..");
    00589
    00590     while( ( ep = readdir( dp ) ) != 0L )
    00591         {
    00592         QString fn( QFile::decodeName(ep->d_name));
    00593         if (fn == _dot || fn == _dotdot || fn.at(fn.length() - 1) == '~')
    00594             continue;
    00595
    00596         if ( !pathExp.exactMatch(fn) )
    00597             continue; // No match
    00598         QString rfn = relPart+fn;
    00599         fn = prefix + fn;
    00600         if ( KDE_stat( QFile::encodeName(fn), &buff ) != 0 ) {
    00601             kdDebug() << "Error statting " << fn << " : " << perror << endl;
    00602             continue; // Couldn't stat (e.g. no permissions)
    00603         }
    00604         if ( S_ISDIR( buff.st_mode ))
    00605             lookupPrefix(fn + '/', rest, rfn + '/', regexp, list, relList, recursive, unique);
    00606         }
    00607
    00608     closedir( dp );
    00609     } else {
    00610         // Don't stat, if the dir doesn't exist we will find out
    00611         // when we try to open it.
    00612         lookupPrefix(prefix + path + '/', rest,
    00613                      relPart + path + '/', regexp, list,
    00614                      relList, recursive, unique);
    00615     }
    00616 }
    00617
    00618 QStringList
    00619 KStandardDirs::findAllResources( const char *type,
    00620                      const QString& filter,
    00621                  bool recursive,
    00622                      bool unique,
    00623                                  QStringList &relList) const
    00624 {
    00625     QStringList list;
    00626     QString filterPath;
    00627     QString filterFile;
    00628
    00629     if (filter.length())
    00630     {
    00631        int slash = filter.findRev('/');
    00632        if (slash < 0)
    00633        filterFile = filter;
    00634        else {
    00635        filterPath = filter.left(slash + 1);
    00636        filterFile = filter.mid(slash + 1);
    00637        }
    00638     }
    00639
    00640     checkConfig();
    00641
    00642     QStringList candidates;
    00643     if (!QDir::isRelativePath(filter)) // absolute path
    00644     {
    00645 #ifdef Q_OS_WIN
    00646         candidates << filterPath.left(3); //e.g. "C:\"
    00647         filterPath = filterPath.mid(3);
    00648 #else
    00649         candidates << "/";
    00650         filterPath = filterPath.mid(1);
    00651 #endif
    00652     }
    00653     else
    00654     {
    00655         if (d && d->restrictionsActive && (strcmp(type, "data")==0))
    00656             applyDataRestrictions(filter);
    00657         candidates = resourceDirs(type);
    00658     }
    00659     if (filterFile.isEmpty())
    00660     filterFile = "*";
    00661
    00662     QRegExp regExp(filterFile, true, true);
    00663
    00664     for (QStringList::ConstIterator it = candidates.begin();
    00665          it != candidates.end(); it++)
    00666     {
    00667         lookupPrefix(*it, filterPath, "", regExp, list,
    00668                      relList, recursive, unique);
    00669     }
    00670
    00671     return list;
    00672 }
    00673
    00674 QStringList
    00675 KStandardDirs::findAllResources( const char *type,
    00676                      const QString& filter,
    00677                  bool recursive,
    00678                      bool unique) const
    00679 {
    00680     QStringList relList;
    00681     return findAllResources(type, filter, recursive, unique, relList);
    00682 }
    00683
    00684 QString
    00685 KStandardDirs::realPath(const QString &dirname)
    00686 {
    00687     char realpath_buffer[MAXPATHLEN + 1];
    00688     memset(realpath_buffer, 0, MAXPATHLEN + 1);
    00689
    00690     /* If the path contains symlinks, get the real name */
    00691     if (realpath( QFile::encodeName(dirname).data(), realpath_buffer) != 0) {
    00692         // succes, use result from realpath
    00693         int len = strlen(realpath_buffer);
    00694         realpath_buffer[len] = '/';
    00695         realpath_buffer[len+1] = 0;
    00696         return QFile::decodeName(realpath_buffer);
    00697     }
    00698
    00699     return dirname;
    00700 }
    00701
    00702 QString
    00703 KStandardDirs::realFilePath(const QString &filename)
    00704 {
    00705     char realpath_buffer[MAXPATHLEN + 1];
    00706     memset(realpath_buffer, 0, MAXPATHLEN + 1);
    00707
    00708     /* If the path contains symlinks, get the real name */
    00709     if (realpath( QFile::encodeName(filename).data(), realpath_buffer) != 0) {
    00710         // succes, use result from realpath
    00711         return QFile::decodeName(realpath_buffer);
    00712     }
    00713
    00714     return filename;
    00715 }
    00716
    00717 void KStandardDirs::createSpecialResource(const char *type)
    00718 {
    00719    char hostname[256];
    00720    hostname[0] = 0;
    00721    gethostname(hostname, 255);
    00722    QString dir = QString("%1%2-%3").arg(localkdedir()).arg(type).arg(hostname);
    00723    char link[1024];
    00724    link[1023] = 0;
    00725    int result = readlink(QFile::encodeName(dir).data(), link, 1023);
    00726    bool relink = (result == -1) && (errno == ENOENT);
    00727    if (result > 0)
    00728    {
    00729       link[result] = 0;
    00730       if (!QDir::isRelativePath(link))
    00731       {
    00732          KDE_struct_stat stat_buf;
    00733          int res = KDE_lstat(link, &stat_buf);
    00734          if ((res == -1) && (errno == ENOENT))
    00735          {
    00736             relink = true;
    00737          }
    00738          else if ((res == -1) || (!S_ISDIR(stat_buf.st_mode)))
    00739          {
    00740             fprintf(stderr, "Error: \"%s\" is not a directory.\n", link);
    00741             relink = true;
    00742          }
    00743          else if (stat_buf.st_uid != getuid())
    00744          {
    00745             fprintf(stderr, "Error: \"%s\" is owned by uid %d instead of uid %d.\n", link, stat_buf.st_uid, getuid());
    00746             relink = true;
    00747          }
    00748       }
    00749    }
    00750 #ifdef Q_WS_WIN
    00751    if (relink)
    00752    {
    00753       if (!makeDir(dir, 0700))
    00754          fprintf(stderr, "failed to create \"%s\"", dir.latin1());
    00755       else
    00756          result = readlink(QFile::encodeName(dir).data(), link, 1023);
    00757    }
    00758 #else //UNIX
    00759    if (relink)
    00760    {
    00761       QString srv = findExe(QString::fromLatin1("lnusertemp"), kfsstnd_defaultbindir());
    00762       if (srv.isEmpty())
    00763          srv = findExe(QString::fromLatin1("lnusertemp"));
    00764       if (!srv.isEmpty())
    00765       {
    00766          system(QFile::encodeName(srv)+" "+type);
    00767          result = readlink(QFile::encodeName(dir).data(), link, 1023);
    00768       }
    00769    }
    00770    if (result > 0)
    00771    {
    00772       link[result] = 0;
    00773       if (link[0] == '/')
    00774          dir = QFile::decodeName(link);
    00775       else
    00776          dir = QDir::cleanDirPath(dir+QFile::decodeName(link));
    00777    }
    00778 #endif
    00779    addResourceDir(type, dir+'/');
    00780 }
    00781
    00782 QStringList KStandardDirs::resourceDirs(const char *type) const
    00783 {
    00784     QStringList *candidates = dircache.find(type);
    00785
    00786     if (!candidates) { // filling cache
    00787         if (strcmp(type, "socket") == 0)
    00788            const_cast<KStandardDirs *>(this)->createSpecialResource(type);
    00789         else if (strcmp(type, "tmp") == 0)
    00790            const_cast<KStandardDirs *>(this)->createSpecialResource(type);
    00791         else if (strcmp(type, "cache") == 0)
    00792            const_cast<KStandardDirs *>(this)->createSpecialResource(type);
    00793
    00794         QDir testdir;
    00795
    00796         candidates = new QStringList();
    00797         QStringList *dirs;
    00798
    00799         bool restrictionActive = false;
    00800         if (d && d->restrictionsActive)
    00801         {
    00802            if (d->dataRestrictionActive)
    00803               restrictionActive = true;
    00804            else if (d->restrictions["all"])
    00805               restrictionActive = true;
    00806            else if (d->restrictions[type])
    00807               restrictionActive = true;
    00808            d->dataRestrictionActive = false; // Reset
    00809         }
    00810
    00811         dirs = relatives.find(type);
    00812         if (dirs)
    00813         {
    00814             bool local = true;
    00815             const QStringList *prefixList = 0;
    00816             if (strncmp(type, "xdgdata-", 8) == 0)
    00817                 prefixList = &(d->xdgdata_prefixes);
    00818             else if (strncmp(type, "xdgconf-", 8) == 0)
    00819                 prefixList = &(d->xdgconf_prefixes);
    00820             else
    00821                 prefixList = &prefixes;
    00822
    00823             for (QStringList::ConstIterator pit = prefixList->begin();
    00824                  pit != prefixList->end();
    00825                  pit++)
    00826             {
    00827                 for (QStringList::ConstIterator it = dirs->begin();
    00828                      it != dirs->end(); ++it) {
    00829                     QString path = realPath(*pit + *it);
    00830                     testdir.setPath(path);
    00831                     if (local && restrictionActive)
    00832                        continue;
    00833                     if ((local || testdir.exists()) && !candidates->contains(path))
    00834                         candidates->append(path);
    00835                 }
    00836                 local = false;
    00837             }
    00838         }
    00839         dirs = absolutes.find(type);
    00840         if (dirs)
    00841             for (QStringList::ConstIterator it = dirs->begin();
    00842                  it != dirs->end(); ++it)
    00843             {
    00844                 testdir.setPath(*it);
    00845                 if (testdir.exists())
    00846                 {
    00847                     QString filename = realPath(*it);
    00848                     if (!candidates->contains(filename))
    00849                         candidates->append(filename);
    00850                 }
    00851             }
    00852         dircache.insert(type, candidates);
    00853     }
    00854
    00855 #if 0
    00856     kdDebug() << "found dirs for resource " << type << ":" << endl;
    00857     for (QStringList::ConstIterator pit = candidates->begin();
    00858      pit != candidates->end();
    00859      pit++)
    00860     {
    00861     fprintf(stderr, "%s\n", (*pit).latin1());
    00862     }
    00863 #endif
    00864
    00865
    00866   return *candidates;
    00867 }
    00868
    00869 QStringList KStandardDirs::systemPaths( const QString& pstr )
    00870 {
    00871     QStringList tokens;
    00872     QString p = pstr;
    00873
    00874     if( p.isNull() )
    00875     {
    00876     p = getenv( "PATH" );
    00877     }
    00878
    00879     QString delimiters(QChar(KPATH_SEPARATOR));
    00880     delimiters += "\b";
    00881     tokenize( tokens, p, delimiters );
    00882
    00883     QStringList exePaths;
    00884
    00885     // split path using : or \b as delimiters
    00886     for( unsigned i = 0; i < tokens.count(); i++ )
    00887     {
    00888     p = tokens[ i ];
    00889
    00890         if ( p[ 0 ] == '~' )
    00891         {
    00892             int len = p.find( '/' );
    00893             if ( len == -1 )
    00894                 len = p.length();
    00895             if ( len == 1 )
    00896             {
    00897                 p.replace( 0, 1, QDir::homeDirPath() );
    00898             }
    00899             else
    00900             {
    00901                 QString user = p.mid( 1, len - 1 );
    00902                 struct passwd *dir = getpwnam( user.local8Bit().data() );
    00903                 if ( dir && strlen( dir->pw_dir ) )
    00904                     p.replace( 0, len, QString::fromLocal8Bit( dir->pw_dir ) );
    00905             }
    00906         }
    00907
    00908     exePaths << p;
    00909     }
    00910
    00911     return exePaths;
    00912 }
    00913
    00914
    00915 QString KStandardDirs::findExe( const QString& appname,
    00916                 const QString& pstr, bool ignore)
    00917 {
    00918 #ifdef Q_WS_WIN
    00919     QString real_appname = appname + ".exe";
    00920 #else
    00921     QString real_appname = appname;
    00922 #endif
    00923     QFileInfo info;
    00924
    00925     // absolute path ?
    00926     if (!QDir::isRelativePath(real_appname))
    00927     {
    00928         info.setFile( real_appname );
    00929         if( info.exists() && ( ignore || info.isExecutable() )
    00930             && info.isFile() ) {
    00931             return real_appname;
    00932         }
    00933         return QString::null;
    00934     }
    00935
    00936     QString p = QString("%1/%2").arg(kfsstnd_defaultbindir()).arg(real_appname);
    00937     info.setFile( p );
    00938     if( info.exists() && ( ignore || info.isExecutable() )
    00939          && ( info.isFile() || info.isSymLink() )  ) {
    00940          return p;
    00941     }
    00942
    00943     QStringList exePaths = systemPaths( pstr );
    00944     for (QStringList::ConstIterator it = exePaths.begin(); it != exePaths.end(); it++)
    00945     {
    00946     p = (*it) + "/";
    00947     p += real_appname;
    00948
    00949     // Check for executable in this tokenized path
    00950     info.setFile( p );
    00951
    00952     if( info.exists() && ( ignore || info.isExecutable() )
    00953            && ( info.isFile() || info.isSymLink() )  ) {
    00954         return p;
    00955     }
    00956     }
    00957
    00958     // If we reach here, the executable wasn't found.
    00959     // So return empty string.
    00960
    00961     return QString::null;
    00962 }
    00963
    00964 int KStandardDirs::findAllExe( QStringList& list, const QString& appname,
    00965             const QString& pstr, bool ignore )
    00966 {
    00967 #ifdef Q_WS_WIN
    00968     QString real_appname = appname + ".exe";
    00969 #else
    00970     QString real_appname = appname;
    00971 #endif
    00972     QFileInfo info;
    00973     QString p;
    00974     list.clear();
    00975
    00976     QStringList exePaths = systemPaths( pstr );
    00977     for (QStringList::ConstIterator it = exePaths.begin(); it != exePaths.end(); it++)
    00978     {
    00979     p = (*it) + "/";
    00980     p += real_appname;
    00981
    00982     info.setFile( p );
    00983
    00984     if( info.exists() && (ignore || info.isExecutable())
    00985         && info.isFile() ) {
    00986         list.append( p );
    00987     }
    00988     }
    00989
    00990     return list.count();
    00991 }
    00992
    00993 static int tokenize( QStringList& tokens, const QString& str,
    00994              const QString& delim )
    00995 {
    00996     int len = str.length();
    00997     QString token = "";
    00998
    00999     for( int index = 0; index < len; index++)
    01000     {
    01001     if ( delim.find( str[ index ] ) >= 0 )
    01002     {
    01003         tokens.append( token );
    01004         token = "";
    01005     }
    01006     else
    01007     {
    01008         token += str[ index ];
    01009     }
    01010     }
    01011     if ( token.length() > 0 )
    01012     {
    01013     tokens.append( token );
    01014     }
    01015
    01016     return tokens.count();
    01017 }
    01018
    01019 QString KStandardDirs::kde_default(const char *type) {
    01020     if (!strcmp(type, "data"))
    01021     return "share/apps/";
    01022     if (!strcmp(type, "html"))
    01023     return "share/doc/HTML/";
    01024     if (!strcmp(type, "icon"))
    01025     return "share/icons/";
    01026     if (!strcmp(type, "config"))
    01027     return "share/config/";
    01028     if (!strcmp(type, "pixmap"))
    01029     return "share/pixmaps/";
    01030     if (!strcmp(type, "apps"))
    01031     return "share/applnk/";
    01032     if (!strcmp(type, "sound"))
    01033     return "share/sounds/";
    01034     if (!strcmp(type, "locale"))
    01035     return "share/locale/";
    01036     if (!strcmp(type, "services"))
    01037     return "share/services/";
    01038     if (!strcmp(type, "servicetypes"))
    01039     return "share/servicetypes/";
    01040     if (!strcmp(type, "mime"))
    01041     return "share/mimelnk/";
    01042     if (!strcmp(type, "cgi"))
    01043     return "cgi-bin/";
    01044     if (!strcmp(type, "wallpaper"))
    01045     return "share/wallpapers/";
    01046     if (!strcmp(type, "templates"))
    01047     return "share/templates/";
    01048     if (!strcmp(type, "exe"))
    01049     return "bin/";
    01050     if (!strcmp(type, "lib"))
    01051     return "lib" KDELIBSUFF "/";
    01052     if (!strcmp(type, "module"))
    01053     return "lib" KDELIBSUFF "/kde3/";
    01054     if (!strcmp(type, "qtplugins"))
    01055         return "lib" KDELIBSUFF "/kde3/plugins";
    01056     if (!strcmp(type, "xdgdata-apps"))
    01057         return "applications/";
    01058     if (!strcmp(type, "xdgdata-dirs"))
    01059         return "desktop-directories/";
    01060     if (!strcmp(type, "xdgconf-menu"))
    01061         return "menus/";
    01062     if (!strcmp(type, "kcfg"))
    01063     return "share/config.kcfg";
    01064     if (!strcmp(type, "emoticons"))
    01065             return "share/emoticons";
    01066
    01067
    01068     qFatal("unknown resource type %s", type);
    01069     return QString::null;
    01070 }
    01071
    01072 QString KStandardDirs::saveLocation(const char *type,
    01073                     const QString& suffix,
    01074                     bool create) const
    01075 {
    01076     checkConfig();
    01077
    01078     QString *pPath = savelocations.find(type);
    01079     if (!pPath)
    01080     {
    01081        QStringList *dirs = relatives.find(type);
    01082        if (!dirs && (
    01083                      (strcmp(type, "socket") == 0) ||
    01084                      (strcmp(type, "tmp") == 0) ||
    01085                      (strcmp(type, "cache") == 0) ))
    01086        {
    01087           (void) resourceDirs(type); // Generate socket|tmp|cache resource.
    01088           dirs = relatives.find(type); // Search again.
    01089        }
    01090        if (dirs)
    01091        {
    01092           // Check for existence of typed directory + suffix
    01093           if (strncmp(type, "xdgdata-", 8) == 0)
    01094              pPath = new QString(realPath(localxdgdatadir() + dirs->last()));
    01095           else if (strncmp(type, "xdgconf-", 8) == 0)
    01096              pPath = new QString(realPath(localxdgconfdir() + dirs->last()));
    01097           else
    01098              pPath = new QString(realPath(localkdedir() + dirs->last()));
    01099        }
    01100        else {
    01101           dirs = absolutes.find(type);
    01102           if (!dirs)
    01103              qFatal("KStandardDirs: The resource type %s is not registered", type);
    01104           pPath = new QString(realPath(dirs->last()));
    01105        }
    01106
    01107        savelocations.insert(type, pPath);
    01108     }
    01109     QString fullPath = *pPath + (pPath->endsWith("/") ? "" : "/") + suffix;
    01110
    01111     KDE_struct_stat st;
    01112     if (KDE_stat(QFile::encodeName(fullPath), &st) != 0 || !(S_ISDIR(st.st_mode))) {
    01113     if(!create) {
    01114 #ifndef NDEBUG
    01115         kdDebug() << QString("save location %1 doesn't exist").arg(fullPath) << endl;
    01116 #endif
    01117         return fullPath;
    01118     }
    01119     if(!makeDir(fullPath, 0700)) {
    01120         return fullPath;
    01121     }
    01122         dircache.remove(type);
    01123     }
    01124     if (!fullPath.endsWith("/"))
    01125         fullPath += "/";
    01126     return fullPath;
    01127 }
    01128
    01129 QString KStandardDirs::relativeLocation(const char *type, const QString &absPath)
    01130 {
    01131     QString fullPath = absPath;
    01132     int i = absPath.findRev('/');
    01133     if (i != -1)
    01134     {
    01135        fullPath = realPath(absPath.left(i+1))+absPath.mid(i+1); // Normalize
    01136     }
    01137
    01138     QStringList candidates = resourceDirs(type);
    01139
    01140     for (QStringList::ConstIterator it = candidates.begin();
    01141      it != candidates.end(); it++)
    01142       if (fullPath.startsWith(*it))
    01143       {
    01144     return fullPath.mid((*it).length());
    01145       }
    01146
    01147     return absPath;
    01148 }
    01149
    01150
    01151 bool KStandardDirs::makeDir(const QString& dir, int mode)
    01152 {
    01153     // we want an absolute path
    01154     if (QDir::isRelativePath(dir))
    01155         return false;
    01156
    01157     QString target = dir;
    01158     uint len = target.length();
    01159
    01160     // append trailing slash if missing
    01161     if (dir.at(len - 1) != '/')
    01162         target += '/';
    01163
    01164     QString base("");
    01165     uint i = 1;
    01166
    01167     while( i < len )
    01168     {
    01169         KDE_struct_stat st;
    01170         int pos = target.find('/', i);
    01171         base += target.mid(i - 1, pos - i + 1);
    01172         QCString baseEncoded = QFile::encodeName(base);
    01173         // bail out if we encountered a problem
    01174         if (KDE_stat(baseEncoded, &st) != 0)
    01175         {
    01176           // Directory does not exist....
    01177           // Or maybe a dangling symlink ?
    01178           if (KDE_lstat(baseEncoded, &st) == 0)
    01179               (void)unlink(baseEncoded); // try removing
    01180
    01181       if ( mkdir(baseEncoded, (mode_t) mode) != 0) {
    01182             baseEncoded.prepend( "trying to create local folder " );
    01183         perror(baseEncoded.data());
    01184         return false; // Couldn't create it :-(
    01185       }
    01186         }
    01187         i = pos + 1;
    01188     }
    01189     return true;
    01190 }
    01191
    01192 static QString readEnvPath(const char *env)
    01193 {
    01194    QCString c_path = getenv(env);
    01195    if (c_path.isEmpty())
    01196       return QString::null;
    01197 #ifdef Q_OS_WIN
    01198    //win32 paths are case-insensitive: avoid duplicates on various dir lists
    01199    return QFile::decodeName(c_path).lower();
    01200 #else
    01201    return QFile::decodeName(c_path);
    01202 #endif
    01203 }
    01204
    01205 #ifdef __linux__
    01206 static QString executablePrefix()
    01207 {
    01208    char path_buffer[MAXPATHLEN + 1];
    01209    path_buffer[MAXPATHLEN] = 0;
    01210    int length = readlink ("/proc/self/exe", path_buffer, MAXPATHLEN);
    01211    if (length == -1)
    01212       return QString::null;
    01213
    01214    path_buffer[length] = '\0';
    01215
    01216    QString path = QFile::decodeName(path_buffer);
    01217
    01218    if(path.isEmpty())
    01219       return QString::null;
    01220
    01221    int pos = path.findRev('/'); // Skip filename
    01222    if(pos <= 0)
    01223       return QString::null;
    01224    pos = path.findRev('/', pos - 1); // Skip last directory
    01225    if(pos <= 0)
    01226       return QString::null;
    01227
    01228    return path.left(pos);
    01229 }
    01230 #endif
    01231
    01232 QString KStandardDirs::kfsstnd_defaultprefix()
    01233 {
    01234    KStandardDirsSingleton* s = KStandardDirsSingleton::self();
    01235    if (!s->defaultprefix.isEmpty())
    01236       return s->defaultprefix;
    01237 #ifdef Q_WS_WIN
    01238    s->defaultprefix = readEnvPath("KDEDIR");
    01239    if (s->defaultprefix.isEmpty()) {
    01240       s->defaultprefix = QFile::decodeName("c:\\kde");
    01241       //TODO: find other location (the Registry?)
    01242    }
    01243 #else //UNIX
    01244    s->defaultprefix = KDEDIR;
    01245 #endif
    01246    if (s->defaultprefix.isEmpty())
    01247       kdWarning() << "KStandardDirs::kfsstnd_defaultprefix(): default KDE prefix not found!" << endl;
    01248    return s->defaultprefix;
    01249 }
    01250
    01251 QString KStandardDirs::kfsstnd_defaultbindir()
    01252 {
    01253    KStandardDirsSingleton* s = KStandardDirsSingleton::self();
    01254    if (!s->defaultbindir.isEmpty())
    01255       return s->defaultbindir;
    01256 #ifdef Q_WS_WIN
    01257    s->defaultbindir = kfsstnd_defaultprefix() + QString::fromLatin1("/bin");
    01258 #else //UNIX
    01259    s->defaultbindir = __KDE_BINDIR;
    01260    if (s->defaultbindir.isEmpty())
    01261       s->defaultbindir = kfsstnd_defaultprefix() + QString::fromLatin1("/bin");
    01262 #endif
    01263    if (s->defaultbindir.isEmpty())
    01264       kdWarning() << "KStandardDirs::kfsstnd_defaultbindir(): default binary KDE dir not found!" << endl;
    01265   return s->defaultbindir;
    01266 }
    01267
    01268 void KStandardDirs::addKDEDefaults()
    01269 {
    01270     QStringList kdedirList;
    01271
    01272     // begin KDEDIRS
    01273     QString kdedirs = readEnvPath("KDEDIRS");
    01274     if (!kdedirs.isEmpty())
    01275     {
    01276         tokenize(kdedirList, kdedirs, QChar(KPATH_SEPARATOR));
    01277     }
    01278     else
    01279     {
    01280         QString kdedir = readEnvPath("KDEDIR");
    01281         if (!kdedir.isEmpty())
    01282         {
    01283            kdedir = KShell::tildeExpand(kdedir);
    01284            kdedirList.append(kdedir);
    01285         }
    01286     }
    01287 #ifndef Q_OS_WIN //no default KDEDIR on win32 defined
    01288     kdedirList.append(KDEDIR);
    01289 #endif
    01290
    01291 #ifdef __KDE_EXECPREFIX
    01292     QString execPrefix(__KDE_EXECPREFIX);
    01293     if (execPrefix!="NONE")
    01294        kdedirList.append(execPrefix);
    01295 #endif
    01296 #ifdef __linux__
    01297     kdedirList.append(executablePrefix());
    01298 #endif
    01299
    01300     // We treat root differently to prevent a "su" shell messing up the
    01301     // file permissions in the user's home directory.
    01302     QString localKdeDir = readEnvPath(getuid() ? "KDEHOME" : "KDEROOTHOME");
    01303     if (!localKdeDir.isEmpty())
    01304     {
    01305        if (localKdeDir[localKdeDir.length()-1] != '/')
    01306           localKdeDir += '/';
    01307     }
    01308     else
    01309     {
    01310        localKdeDir =  QDir::homeDirPath() + "/.kde/";
    01311     }
    01312
    01313     if (localKdeDir != "-/")
    01314     {
    01315         localKdeDir = KShell::tildeExpand(localKdeDir);
    01316         addPrefix(localKdeDir);
    01317     }
    01318
    01319     for (QStringList::ConstIterator it = kdedirList.begin();
    01320      it != kdedirList.end(); it++)
    01321     {
    01322         QString dir = KShell::tildeExpand(*it);
    01323     addPrefix(dir);
    01324     }
    01325     // end KDEDIRS
    01326
    01327     // begin XDG_CONFIG_XXX
    01328     QStringList xdgdirList;
    01329     QString xdgdirs = readEnvPath("XDG_CONFIG_DIRS");
    01330     if (!xdgdirs.isEmpty())
    01331     {
    01332     tokenize(xdgdirList, xdgdirs, QChar(KPATH_SEPARATOR));
    01333     }
    01334     else
    01335     {
    01336     xdgdirList.clear();
    01337         xdgdirList.append("/etc/xdg");
    01338 #ifdef Q_WS_WIN
    01339         xdgdirList.append(kfsstnd_defaultprefix() + "/etc/xdg");
    01340 #else
    01341         xdgdirList.append(KDESYSCONFDIR "/xdg");
    01342 #endif
    01343     }
    01344
    01345     QString localXdgDir = readEnvPath("XDG_CONFIG_HOME");
    01346     if (!localXdgDir.isEmpty())
    01347     {
    01348        if (localXdgDir[localXdgDir.length()-1] != '/')
    01349           localXdgDir += '/';
    01350     }
    01351     else
    01352     {
    01353        localXdgDir =  QDir::homeDirPath() + "/.config/";
    01354     }
    01355
    01356     localXdgDir = KShell::tildeExpand(localXdgDir);
    01357     addXdgConfigPrefix(localXdgDir);
    01358
    01359     for (QStringList::ConstIterator it = xdgdirList.begin();
    01360      it != xdgdirList.end(); it++)
    01361     {
    01362         QString dir = KShell::tildeExpand(*it);
    01363     addXdgConfigPrefix(dir);
    01364     }
    01365     // end XDG_CONFIG_XXX
    01366
    01367     // begin XDG_DATA_XXX
    01368     xdgdirs = readEnvPath("XDG_DATA_DIRS");
    01369     if (!xdgdirs.isEmpty())
    01370     {
    01371     tokenize(xdgdirList, xdgdirs, QChar(KPATH_SEPARATOR));
    01372     }
    01373     else
    01374     {
    01375     xdgdirList.clear();
    01376         for (QStringList::ConstIterator it = kdedirList.begin();
    01377            it != kdedirList.end(); it++)
    01378         {
    01379            QString dir = *it;
    01380            if (dir[dir.length()-1] != '/')
    01381              dir += '/';
    01382            xdgdirList.append(dir+"share/");
    01383         }
    01384
    01385         xdgdirList.append("/usr/local/share/");
    01386         xdgdirList.append("/usr/share/");
    01387     }
    01388
    01389     localXdgDir = readEnvPath("XDG_DATA_HOME");
    01390     if (!localXdgDir.isEmpty())
    01391     {
    01392        if (localXdgDir[localXdgDir.length()-1] != '/')
    01393           localXdgDir += '/';
    01394     }
    01395     else
    01396     {
    01397        localXdgDir = QDir::homeDirPath() + "/.local/share/";
    01398     }
    01399
    01400     localXdgDir = KShell::tildeExpand(localXdgDir);
    01401     addXdgDataPrefix(localXdgDir);
    01402
    01403     for (QStringList::ConstIterator it = xdgdirList.begin();
    01404      it != xdgdirList.end(); it++)
    01405     {
    01406         QString dir = KShell::tildeExpand(*it);
    01407     addXdgDataPrefix(dir);
    01408     }
    01409     // end XDG_DATA_XXX
    01410
    01411
    01412     uint index = 0;
    01413     while (types[index] != 0) {
    01414     addResourceType(types[index], kde_default(types[index]));
    01415     index++;
    01416     }
    01417
    01418     addResourceDir("home", QDir::homeDirPath());
    01419 }
    01420
    01421 void KStandardDirs::checkConfig() const
    01422 {
    01423     if (!addedCustoms && KGlobal::_instance && KGlobal::_instance->_config)
    01424         const_cast<KStandardDirs*>(this)->addCustomized(KGlobal::_instance->_config);
    01425 }
    01426
    01427 static QStringList lookupProfiles(const QString &mapFile)
    01428 {
    01429     QStringList profiles;
    01430
    01431     if (mapFile.isEmpty() || !QFile::exists(mapFile))
    01432     {
    01433        profiles << "default";
    01434        return profiles;
    01435     }
    01436
    01437     struct passwd *pw = getpwuid(geteuid());
    01438     if (!pw)
    01439     {
    01440         profiles << "default";
    01441         return profiles; // Not good
    01442     }
    01443
    01444     QCString user = pw->pw_name;
    01445
    01446     gid_t sup_gids[512];
    01447     int sup_gids_nr = getgroups(512, sup_gids);
    01448
    01449     KSimpleConfig mapCfg(mapFile, true);
    01450     mapCfg.setGroup("Users");
    01451     if (mapCfg.hasKey(user.data()))
    01452     {
    01453         profiles = mapCfg.readListEntry(user.data());
    01454         return profiles;
    01455     }
    01456
    01457     mapCfg.setGroup("General");
    01458     QStringList groups = mapCfg.readListEntry("groups");
    01459
    01460     mapCfg.setGroup("Groups");
    01461
    01462     for( QStringList::ConstIterator it = groups.begin();
    01463          it != groups.end(); ++it )
    01464     {
    01465         QCString grp = (*it).utf8();
    01466         // Check if user is in this group
    01467         struct group *grp_ent = getgrnam(grp);
    01468         if (!grp_ent) continue;
    01469         gid_t gid = grp_ent->gr_gid;
    01470         if (pw->pw_gid == gid)
    01471         {
    01472             // User is in this group --> add profiles
    01473             profiles += mapCfg.readListEntry(*it);
    01474         }
    01475         else
    01476         {
    01477             for(int i = 0; i < sup_gids_nr; i++)
    01478             {
    01479                 if (sup_gids[i] == gid)
    01480                 {
    01481                     // User is in this group --> add profiles
    01482                     profiles += mapCfg.readListEntry(*it);
    01483                     break;
    01484                 }
    01485             }
    01486         }
    01487     }
    01488
    01489     if (profiles.isEmpty())
    01490         profiles << "default";
    01491     return profiles;
    01492 }
    01493
    01494 extern bool kde_kiosk_admin;
    01495
    01496 bool KStandardDirs::addCustomized(KConfig *config)
    01497 {
    01498     if (addedCustoms && !d->checkRestrictions) // there are already customized entries
    01499         return false; // we just quit and hope they are the right ones
    01500
    01501     // save the numbers of config directories. If this changes,
    01502     // we will return true to give KConfig a chance to reparse
    01503     uint configdirs = resourceDirs("config").count();
    01504
    01505     // Remember original group
    01506     QString oldGroup = config->group();
    01507
    01508     if (!addedCustoms)
    01509     {
    01510         // We only add custom entries once
    01511         addedCustoms = true;
    01512
    01513         // reading the prefixes in
    01514         QString group = QString::fromLatin1("Directories");
    01515         config->setGroup(group);
    01516
    01517         QString kioskAdmin = config->readEntry("kioskAdmin");
    01518         if (!kioskAdmin.isEmpty() && !kde_kiosk_admin)
    01519         {
    01520             int i = kioskAdmin.find(':');
    01521             QString user = kioskAdmin.left(i);
    01522             QString host = kioskAdmin.mid(i+1);
    01523
    01524             KUser thisUser;
    01525             char hostname[ 256 ];
    01526             hostname[ 0 ] = '\0';
    01527             if (!gethostname( hostname, 255 ))
    01528                 hostname[sizeof(hostname)-1] = '\0';
    01529
    01530             if ((user == thisUser.loginName()) &&
    01531                 (host.isEmpty() || (host == hostname)))
    01532             {
    01533                 kde_kiosk_admin = true;
    01534             }
    01535         }
    01536
    01537         bool readProfiles = true;
    01538
    01539         if (kde_kiosk_admin && !QCString(getenv("KDE_KIOSK_NO_PROFILES")).isEmpty())
    01540             readProfiles = false;
    01541
    01542         QString userMapFile = config->readEntry("userProfileMapFile");
    01543         QString profileDirsPrefix = config->readEntry("profileDirsPrefix");
    01544         if (!profileDirsPrefix.isEmpty() && !profileDirsPrefix.endsWith("/"))
    01545             profileDirsPrefix.append('/');
    01546
    01547         QStringList profiles;
    01548         if (readProfiles)
    01549             profiles = lookupProfiles(userMapFile);
    01550         QString profile;
    01551
    01552         bool priority = false;
    01553         while(true)
    01554         {
    01555             config->setGroup(group);
    01556             QStringList list = config->readListEntry("prefixes");
    01557             for (QStringList::ConstIterator it = list.begin(); it != list.end(); it++)
    01558             {
    01559                 addPrefix(*it, priority);
    01560                 addXdgConfigPrefix(*it+"/etc/xdg", priority);
    01561                 addXdgDataPrefix(*it+"/share", priority);
    01562             }
    01563             // If there are no prefixes defined, check if there is a directory
    01564             // for this profile under <profileDirsPrefix>
    01565             if (list.isEmpty() && !profile.isEmpty() && !profileDirsPrefix.isEmpty())
    01566             {
    01567                 QString dir = profileDirsPrefix + profile;
    01568                 addPrefix(dir, priority);
    01569                 addXdgConfigPrefix(dir+"/etc/xdg", priority);
    01570                 addXdgDataPrefix(dir+"/share", priority);
    01571             }
    01572
    01573             // iterating over all entries in the group Directories
    01574             // to find entries that start with dir_$type
    01575             QMap<QString, QString> entries = config->entryMap(group);
    01576             for (QMap<QString, QString>::ConstIterator it2 = entries.begin();
    01577                  it2 != entries.end(); it2++)
    01578             {
    01579                 QString key = it2.key();
    01580                 if (key.startsWith("dir_")) {
    01581                     // generate directory list, there may be more than 1.
    01582                     QStringList dirs = QStringList::split(',', *it2);
    01583                     QStringList::Iterator sIt(dirs.begin());
    01584                     QString resType = key.mid(4, key.length());
    01585                     for (; sIt != dirs.end(); ++sIt)
    01586                     {
    01587                         addResourceDir(resType.latin1(), *sIt, priority);
    01588                     }
    01589                 }
    01590             }
    01591             if (profiles.isEmpty())
    01592                 break;
    01593             profile = profiles.back();
    01594             group = QString::fromLatin1("Directories-%1").arg(profile);
    01595             profiles.pop_back();
    01596             priority = true;
    01597         }
    01598     }
    01599
    01600     // Process KIOSK restrictions.
    01601     if (!kde_kiosk_admin || QCString(getenv("KDE_KIOSK_NO_RESTRICTIONS")).isEmpty())
    01602     {
    01603         config->setGroup("KDE Resource Restrictions");
    01604         QMap<QString, QString> entries = config->entryMap("KDE Resource Restrictions");
    01605         for (QMap<QString, QString>::ConstIterator it2 = entries.begin();
    01606             it2 != entries.end(); it2++)
    01607         {
    01608             QString key = it2.key();
    01609             if (!config->readBoolEntry(key, true))
    01610             {
    01611                 d->restrictionsActive = true;
    01612                 d->restrictions.insert(key.latin1(), &d->restrictionsActive); // Anything will do
    01613                 dircache.remove(key.latin1());
    01614             }
    01615         }
    01616     }
    01617
    01618     config->setGroup(oldGroup);
    01619
    01620     // check if the number of config dirs changed
    01621     bool configDirsChanged = (resourceDirs("config").count() != configdirs);
    01622     // If the config dirs changed, we check kiosk restrictions again.
    01623     d->checkRestrictions = configDirsChanged;
    01624     // return true if the number of config dirs changed: reparse config file
    01625     return configDirsChanged;
    01626 }
    01627
    01628 QString KStandardDirs::localkdedir() const
    01629 {
    01630     // Return the prefix to use for saving
    01631     return prefixes.first();
    01632 }
    01633
    01634 QString KStandardDirs::localxdgdatadir() const
    01635 {
    01636     // Return the prefix to use for saving
    01637     return d->xdgdata_prefixes.first();
    01638 }
    01639
    01640 QString KStandardDirs::localxdgconfdir() const
    01641 {
    01642     // Return the prefix to use for saving
    01643     return d->xdgconf_prefixes.first();
    01644 }
    01645
    01646
    01647 // just to make code more readable without macros
    01648 QString locate( const char *type,
    01649         const QString& filename, const KInstance* inst )
    01650 {
    01651     return inst->dirs()->findResource(type, filename);
    01652 }
    01653
    01654 QString locateLocal( const char *type,
    01655                  const QString& filename, const KInstance* inst )
    01656 {
    01657     return locateLocal(type, filename, true, inst);
    01658 }
    01659
    01660 QString locateLocal( const char *type,
    01661                  const QString& filename, bool createDir, const KInstance* inst )
    01662 {
    01663     // try to find slashes. If there are some, we have to
    01664     // create the subdir first
    01665     int slash = filename.findRev('/')+1;
    01666     if (!slash) // only one filename
    01667     return inst->dirs()->saveLocation(type, QString::null, createDir) + filename;
    01668
    01669     // split path from filename
    01670     QString dir = filename.left(slash);
    01671     QString file = filename.mid(slash);
    01672     return inst->dirs()->saveLocation(type, dir, createDir) + file;
    01673 }

This file is part of the documentation for kdecore Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:18:11 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003