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