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