kdecore Library API Documentation

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