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 759452 2008-01-10 16:01:57Z 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", "xdgdata-pixmap", 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 && strcmp(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 ®exp, 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 ®exp, 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 // success, 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 // success, 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 or relative path given 00927 if (real_appname.find(QDir::separator()) >= 0) 00928 { 00929 info.setFile( real_appname ); 00930 if( info.exists() && ( ignore || info.isExecutable() ) 00931 && info.isFile() ) { 00932 return info.absFilePath(); 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-pixmap")) 01062 return "pixmaps/"; 01063 if (!strcmp(type, "xdgdata-dirs")) 01064 return "desktop-directories/"; 01065 if (!strcmp(type, "xdgconf-menu")) 01066 return "menus/"; 01067 if (!strcmp(type, "kcfg")) 01068 return "share/config.kcfg"; 01069 if (!strcmp(type, "emoticons")) 01070 return "share/emoticons"; 01071 01072 01073 qFatal("unknown resource type %s", type); 01074 return QString::null; 01075 } 01076 01077 QString KStandardDirs::saveLocation(const char *type, 01078 const QString& suffix, 01079 bool create) const 01080 { 01081 checkConfig(); 01082 01083 QString *pPath = savelocations.find(type); 01084 if (!pPath) 01085 { 01086 QStringList *dirs = relatives.find(type); 01087 if (!dirs && ( 01088 (strcmp(type, "socket") == 0) || 01089 (strcmp(type, "tmp") == 0) || 01090 (strcmp(type, "cache") == 0) )) 01091 { 01092 (void) resourceDirs(type); // Generate socket|tmp|cache resource. 01093 dirs = relatives.find(type); // Search again. 01094 } 01095 if (dirs) 01096 { 01097 // Check for existence of typed directory + suffix 01098 if (strncmp(type, "xdgdata-", 8) == 0) 01099 pPath = new QString(realPath(localxdgdatadir() + dirs->last())); 01100 else if (strncmp(type, "xdgconf-", 8) == 0) 01101 pPath = new QString(realPath(localxdgconfdir() + dirs->last())); 01102 else 01103 pPath = new QString(realPath(localkdedir() + dirs->last())); 01104 } 01105 else { 01106 dirs = absolutes.find(type); 01107 if (!dirs) 01108 qFatal("KStandardDirs: The resource type %s is not registered", type); 01109 pPath = new QString(realPath(dirs->last())); 01110 } 01111 01112 savelocations.insert(type, pPath); 01113 } 01114 QString fullPath = *pPath + (pPath->endsWith("/") ? "" : "/") + suffix; 01115 01116 KDE_struct_stat st; 01117 if (KDE_stat(QFile::encodeName(fullPath), &st) != 0 || !(S_ISDIR(st.st_mode))) { 01118 if(!create) { 01119 #ifndef NDEBUG 01120 kdDebug() << QString("save location %1 doesn't exist").arg(fullPath) << endl; 01121 #endif 01122 return fullPath; 01123 } 01124 if(!makeDir(fullPath, 0700)) { 01125 return fullPath; 01126 } 01127 dircache.remove(type); 01128 } 01129 if (!fullPath.endsWith("/")) 01130 fullPath += "/"; 01131 return fullPath; 01132 } 01133 01134 QString KStandardDirs::relativeLocation(const char *type, const QString &absPath) 01135 { 01136 QString fullPath = absPath; 01137 int i = absPath.findRev('/'); 01138 if (i != -1) 01139 { 01140 fullPath = realPath(absPath.left(i+1))+absPath.mid(i+1); // Normalize 01141 } 01142 01143 QStringList candidates = resourceDirs(type); 01144 01145 for (QStringList::ConstIterator it = candidates.begin(); 01146 it != candidates.end(); ++it) 01147 if (fullPath.startsWith(*it)) 01148 { 01149 return fullPath.mid((*it).length()); 01150 } 01151 01152 return absPath; 01153 } 01154 01155 01156 bool KStandardDirs::makeDir(const QString& dir, int mode) 01157 { 01158 // we want an absolute path 01159 if (QDir::isRelativePath(dir)) 01160 return false; 01161 01162 QString target = dir; 01163 uint len = target.length(); 01164 01165 // append trailing slash if missing 01166 if (dir.at(len - 1) != '/') 01167 target += '/'; 01168 01169 QString base(""); 01170 uint i = 1; 01171 01172 while( i < len ) 01173 { 01174 KDE_struct_stat st; 01175 int pos = target.find('/', i); 01176 base += target.mid(i - 1, pos - i + 1); 01177 QCString baseEncoded = QFile::encodeName(base); 01178 // bail out if we encountered a problem 01179 if (KDE_stat(baseEncoded, &st) != 0) 01180 { 01181 // Directory does not exist.... 01182 // Or maybe a dangling symlink ? 01183 if (KDE_lstat(baseEncoded, &st) == 0) 01184 (void)unlink(baseEncoded); // try removing 01185 01186 if ( KDE_mkdir(baseEncoded, (mode_t) mode) != 0) { 01187 baseEncoded.prepend( "trying to create local folder " ); 01188 perror(baseEncoded.data()); 01189 return false; // Couldn't create it :-( 01190 } 01191 } 01192 i = pos + 1; 01193 } 01194 return true; 01195 } 01196 01197 static QString readEnvPath(const char *env) 01198 { 01199 QCString c_path = getenv(env); 01200 if (c_path.isEmpty()) 01201 return QString::null; 01202 #ifdef Q_OS_WIN 01203 //win32 paths are case-insensitive: avoid duplicates on various dir lists 01204 return QFile::decodeName(c_path).lower(); 01205 #else 01206 return QFile::decodeName(c_path); 01207 #endif 01208 } 01209 01210 #ifdef __linux__ 01211 static QString executablePrefix() 01212 { 01213 char path_buffer[MAXPATHLEN + 1]; 01214 path_buffer[MAXPATHLEN] = 0; 01215 int length = readlink ("/proc/self/exe", path_buffer, MAXPATHLEN); 01216 if (length == -1) 01217 return QString::null; 01218 01219 path_buffer[length] = '\0'; 01220 01221 QString path = QFile::decodeName(path_buffer); 01222 01223 if(path.isEmpty()) 01224 return QString::null; 01225 01226 int pos = path.findRev('/'); // Skip filename 01227 if(pos <= 0) 01228 return QString::null; 01229 pos = path.findRev('/', pos - 1); // Skip last directory 01230 if(pos <= 0) 01231 return QString::null; 01232 01233 return path.left(pos); 01234 } 01235 #endif 01236 01237 QString KStandardDirs::kfsstnd_defaultprefix() 01238 { 01239 KStandardDirsSingleton* s = KStandardDirsSingleton::self(); 01240 if (!s->defaultprefix.isEmpty()) 01241 return s->defaultprefix; 01242 #ifdef Q_WS_WIN 01243 s->defaultprefix = readEnvPath("KDEDIR"); 01244 if (s->defaultprefix.isEmpty()) { 01245 s->defaultprefix = QFile::decodeName("c:\\kde"); 01246 //TODO: find other location (the Registry?) 01247 } 01248 #else //UNIX 01249 s->defaultprefix = KDEDIR; 01250 #endif 01251 if (s->defaultprefix.isEmpty()) 01252 kdWarning() << "KStandardDirs::kfsstnd_defaultprefix(): default KDE prefix not found!" << endl; 01253 return s->defaultprefix; 01254 } 01255 01256 QString KStandardDirs::kfsstnd_defaultbindir() 01257 { 01258 KStandardDirsSingleton* s = KStandardDirsSingleton::self(); 01259 if (!s->defaultbindir.isEmpty()) 01260 return s->defaultbindir; 01261 #ifdef Q_WS_WIN 01262 s->defaultbindir = kfsstnd_defaultprefix() + QString::fromLatin1("/bin"); 01263 #else //UNIX 01264 s->defaultbindir = __KDE_BINDIR; 01265 if (s->defaultbindir.isEmpty()) 01266 s->defaultbindir = kfsstnd_defaultprefix() + QString::fromLatin1("/bin"); 01267 #endif 01268 if (s->defaultbindir.isEmpty()) 01269 kdWarning() << "KStandardDirs::kfsstnd_defaultbindir(): default binary KDE dir not found!" << endl; 01270 return s->defaultbindir; 01271 } 01272 01273 void KStandardDirs::addKDEDefaults() 01274 { 01275 QStringList kdedirList; 01276 01277 // begin KDEDIRS 01278 QString kdedirs = readEnvPath("KDEDIRS"); 01279 if (!kdedirs.isEmpty()) 01280 { 01281 tokenize(kdedirList, kdedirs, QChar(KPATH_SEPARATOR)); 01282 } 01283 else 01284 { 01285 QString kdedir = readEnvPath("KDEDIR"); 01286 if (!kdedir.isEmpty()) 01287 { 01288 kdedir = KShell::tildeExpand(kdedir); 01289 kdedirList.append(kdedir); 01290 } 01291 } 01292 01293 #ifndef Q_OS_WIN //no default KDEDIR on win32 defined 01294 kdedirList.append(KDEDIR); 01295 #endif 01296 01297 #ifdef __KDE_EXECPREFIX 01298 QString execPrefix(__KDE_EXECPREFIX); 01299 if (execPrefix!="NONE") 01300 kdedirList.append(execPrefix); 01301 #endif 01302 #ifdef __linux__ 01303 const QString linuxExecPrefix = executablePrefix(); 01304 if ( !linuxExecPrefix.isEmpty() ) 01305 kdedirList.append( linuxExecPrefix ); 01306 #endif 01307 01308 // We treat root differently to prevent a "su" shell messing up the 01309 // file permissions in the user's home directory. 01310 QString localKdeDir = readEnvPath(getuid() ? "KDEHOME" : "KDEROOTHOME"); 01311 if (!localKdeDir.isEmpty()) 01312 { 01313 if (localKdeDir[localKdeDir.length()-1] != '/') 01314 localKdeDir += '/'; 01315 } 01316 else 01317 { 01318 localKdeDir = QDir::homeDirPath() + "/.kde/"; 01319 } 01320 01321 if (localKdeDir != "-/") 01322 { 01323 localKdeDir = KShell::tildeExpand(localKdeDir); 01324 addPrefix(localKdeDir); 01325 } 01326 01327 QStringList::ConstIterator end(kdedirList.end()); 01328 for (QStringList::ConstIterator it = kdedirList.begin(); 01329 it != end; ++it) 01330 { 01331 QString dir = KShell::tildeExpand(*it); 01332 addPrefix(dir); 01333 } 01334 // end KDEDIRS 01335 01336 // begin XDG_CONFIG_XXX 01337 QStringList xdgdirList; 01338 QString xdgdirs = readEnvPath("XDG_CONFIG_DIRS"); 01339 if (!xdgdirs.isEmpty()) 01340 { 01341 tokenize(xdgdirList, xdgdirs, QChar(KPATH_SEPARATOR)); 01342 } 01343 else 01344 { 01345 xdgdirList.clear(); 01346 xdgdirList.append("/etc/xdg"); 01347 #ifdef Q_WS_WIN 01348 xdgdirList.append(kfsstnd_defaultprefix() + "/etc/xdg"); 01349 #else 01350 xdgdirList.append(KDESYSCONFDIR "/xdg"); 01351 #endif 01352 } 01353 01354 QString localXdgDir = readEnvPath("XDG_CONFIG_HOME"); 01355 if (!localXdgDir.isEmpty()) 01356 { 01357 if (localXdgDir[localXdgDir.length()-1] != '/') 01358 localXdgDir += '/'; 01359 } 01360 else 01361 { 01362 localXdgDir = QDir::homeDirPath() + "/.config/"; 01363 } 01364 01365 localXdgDir = KShell::tildeExpand(localXdgDir); 01366 addXdgConfigPrefix(localXdgDir); 01367 01368 for (QStringList::ConstIterator it = xdgdirList.begin(); 01369 it != xdgdirList.end(); ++it) 01370 { 01371 QString dir = KShell::tildeExpand(*it); 01372 addXdgConfigPrefix(dir); 01373 } 01374 // end XDG_CONFIG_XXX 01375 01376 // begin XDG_DATA_XXX 01377 xdgdirs = readEnvPath("XDG_DATA_DIRS"); 01378 if (!xdgdirs.isEmpty()) 01379 { 01380 tokenize(xdgdirList, xdgdirs, QChar(KPATH_SEPARATOR)); 01381 } 01382 else 01383 { 01384 xdgdirList.clear(); 01385 for (QStringList::ConstIterator it = kdedirList.begin(); 01386 it != kdedirList.end(); ++it) 01387 { 01388 QString dir = *it; 01389 if (dir[dir.length()-1] != '/') 01390 dir += '/'; 01391 xdgdirList.append(dir+"share/"); 01392 } 01393 01394 xdgdirList.append("/usr/local/share/"); 01395 xdgdirList.append("/usr/share/"); 01396 } 01397 01398 localXdgDir = readEnvPath("XDG_DATA_HOME"); 01399 if (!localXdgDir.isEmpty()) 01400 { 01401 if (localXdgDir[localXdgDir.length()-1] != '/') 01402 localXdgDir += '/'; 01403 } 01404 else 01405 { 01406 localXdgDir = QDir::homeDirPath() + "/.local/share/"; 01407 } 01408 01409 localXdgDir = KShell::tildeExpand(localXdgDir); 01410 addXdgDataPrefix(localXdgDir); 01411 01412 for (QStringList::ConstIterator it = xdgdirList.begin(); 01413 it != xdgdirList.end(); ++it) 01414 { 01415 QString dir = KShell::tildeExpand(*it); 01416 addXdgDataPrefix(dir); 01417 } 01418 // end XDG_DATA_XXX 01419 01420 01421 uint index = 0; 01422 while (types[index] != 0) { 01423 addResourceType(types[index], kde_default(types[index])); 01424 index++; 01425 } 01426 01427 addResourceDir("home", QDir::homeDirPath()); 01428 } 01429 01430 void KStandardDirs::checkConfig() const 01431 { 01432 if (!addedCustoms && KGlobal::_instance && KGlobal::_instance->_config) 01433 const_cast<KStandardDirs*>(this)->addCustomized(KGlobal::_instance->_config); 01434 } 01435 01436 static QStringList lookupProfiles(const QString &mapFile) 01437 { 01438 QStringList profiles; 01439 01440 if (mapFile.isEmpty() || !QFile::exists(mapFile)) 01441 { 01442 profiles << "default"; 01443 return profiles; 01444 } 01445 01446 struct passwd *pw = getpwuid(geteuid()); 01447 if (!pw) 01448 { 01449 profiles << "default"; 01450 return profiles; // Not good 01451 } 01452 01453 QCString user = pw->pw_name; 01454 01455 gid_t sup_gids[512]; 01456 int sup_gids_nr = getgroups(512, sup_gids); 01457 01458 KSimpleConfig mapCfg(mapFile, true); 01459 mapCfg.setGroup("Users"); 01460 if (mapCfg.hasKey(user.data())) 01461 { 01462 profiles = mapCfg.readListEntry(user.data()); 01463 return profiles; 01464 } 01465 01466 mapCfg.setGroup("General"); 01467 QStringList groups = mapCfg.readListEntry("groups"); 01468 01469 mapCfg.setGroup("Groups"); 01470 01471 for( QStringList::ConstIterator it = groups.begin(); 01472 it != groups.end(); ++it ) 01473 { 01474 QCString grp = (*it).utf8(); 01475 // Check if user is in this group 01476 struct group *grp_ent = getgrnam(grp); 01477 if (!grp_ent) continue; 01478 gid_t gid = grp_ent->gr_gid; 01479 if (pw->pw_gid == gid) 01480 { 01481 // User is in this group --> add profiles 01482 profiles += mapCfg.readListEntry(*it); 01483 } 01484 else 01485 { 01486 for(int i = 0; i < sup_gids_nr; i++) 01487 { 01488 if (sup_gids[i] == gid) 01489 { 01490 // User is in this group --> add profiles 01491 profiles += mapCfg.readListEntry(*it); 01492 break; 01493 } 01494 } 01495 } 01496 } 01497 01498 if (profiles.isEmpty()) 01499 profiles << "default"; 01500 return profiles; 01501 } 01502 01503 extern bool kde_kiosk_admin; 01504 01505 bool KStandardDirs::addCustomized(KConfig *config) 01506 { 01507 if (addedCustoms && !d->checkRestrictions) // there are already customized entries 01508 return false; // we just quit and hope they are the right ones 01509 01510 // save the numbers of config directories. If this changes, 01511 // we will return true to give KConfig a chance to reparse 01512 uint configdirs = resourceDirs("config").count(); 01513 01514 // Remember original group 01515 QString oldGroup = config->group(); 01516 01517 if (!addedCustoms) 01518 { 01519 // We only add custom entries once 01520 addedCustoms = true; 01521 01522 // reading the prefixes in 01523 QString group = QString::fromLatin1("Directories"); 01524 config->setGroup(group); 01525 01526 QString kioskAdmin = config->readEntry("kioskAdmin"); 01527 if (!kioskAdmin.isEmpty() && !kde_kiosk_admin) 01528 { 01529 int i = kioskAdmin.find(':'); 01530 QString user = kioskAdmin.left(i); 01531 QString host = kioskAdmin.mid(i+1); 01532 01533 KUser thisUser; 01534 char hostname[ 256 ]; 01535 hostname[ 0 ] = '\0'; 01536 if (!gethostname( hostname, 255 )) 01537 hostname[sizeof(hostname)-1] = '\0'; 01538 01539 if ((user == thisUser.loginName()) && 01540 (host.isEmpty() || (host == hostname))) 01541 { 01542 kde_kiosk_admin = true; 01543 } 01544 } 01545 01546 bool readProfiles = true; 01547 01548 if (kde_kiosk_admin && !QCString(getenv("KDE_KIOSK_NO_PROFILES")).isEmpty()) 01549 readProfiles = false; 01550 01551 QString userMapFile = config->readEntry("userProfileMapFile"); 01552 QString profileDirsPrefix = config->readEntry("profileDirsPrefix"); 01553 if (!profileDirsPrefix.isEmpty() && !profileDirsPrefix.endsWith("/")) 01554 profileDirsPrefix.append('/'); 01555 01556 QStringList profiles; 01557 if (readProfiles) 01558 profiles = lookupProfiles(userMapFile); 01559 QString profile; 01560 01561 bool priority = false; 01562 while(true) 01563 { 01564 config->setGroup(group); 01565 QStringList list = config->readListEntry("prefixes"); 01566 for (QStringList::ConstIterator it = list.begin(); it != list.end(); ++it) 01567 { 01568 addPrefix(*it, priority); 01569 addXdgConfigPrefix(*it+"/etc/xdg", priority); 01570 addXdgDataPrefix(*it+"/share", priority); 01571 } 01572 // If there are no prefixes defined, check if there is a directory 01573 // for this profile under <profileDirsPrefix> 01574 if (list.isEmpty() && !profile.isEmpty() && !profileDirsPrefix.isEmpty()) 01575 { 01576 QString dir = profileDirsPrefix + profile; 01577 addPrefix(dir, priority); 01578 addXdgConfigPrefix(dir+"/etc/xdg", priority); 01579 addXdgDataPrefix(dir+"/share", priority); 01580 } 01581 01582 // iterating over all entries in the group Directories 01583 // to find entries that start with dir_$type 01584 QMap<QString, QString> entries = config->entryMap(group); 01585 for (QMap<QString, QString>::ConstIterator it2 = entries.begin(); 01586 it2 != entries.end(); it2++) 01587 { 01588 QString key = it2.key(); 01589 if (key.startsWith("dir_")) { 01590 // generate directory list, there may be more than 1. 01591 QStringList dirs = QStringList::split(',', *it2); 01592 QStringList::Iterator sIt(dirs.begin()); 01593 QString resType = key.mid(4, key.length()); 01594 for (; sIt != dirs.end(); ++sIt) 01595 { 01596 addResourceDir(resType.latin1(), *sIt, priority); 01597 } 01598 } 01599 } 01600 if (profiles.isEmpty()) 01601 break; 01602 profile = profiles.back(); 01603 group = QString::fromLatin1("Directories-%1").arg(profile); 01604 profiles.pop_back(); 01605 priority = true; 01606 } 01607 } 01608 01609 // Process KIOSK restrictions. 01610 if (!kde_kiosk_admin || QCString(getenv("KDE_KIOSK_NO_RESTRICTIONS")).isEmpty()) 01611 { 01612 config->setGroup("KDE Resource Restrictions"); 01613 QMap<QString, QString> entries = config->entryMap("KDE Resource Restrictions"); 01614 for (QMap<QString, QString>::ConstIterator it2 = entries.begin(); 01615 it2 != entries.end(); it2++) 01616 { 01617 QString key = it2.key(); 01618 if (!config->readBoolEntry(key, true)) 01619 { 01620 d->restrictionsActive = true; 01621 d->restrictions.insert(key.latin1(), &d->restrictionsActive); // Anything will do 01622 dircache.remove(key.latin1()); 01623 } 01624 } 01625 } 01626 01627 config->setGroup(oldGroup); 01628 01629 // check if the number of config dirs changed 01630 bool configDirsChanged = (resourceDirs("config").count() != configdirs); 01631 // If the config dirs changed, we check kiosk restrictions again. 01632 d->checkRestrictions = configDirsChanged; 01633 // return true if the number of config dirs changed: reparse config file 01634 return configDirsChanged; 01635 } 01636 01637 QString KStandardDirs::localkdedir() const 01638 { 01639 // Return the prefix to use for saving 01640 return prefixes.first(); 01641 } 01642 01643 QString KStandardDirs::localxdgdatadir() const 01644 { 01645 // Return the prefix to use for saving 01646 return d->xdgdata_prefixes.first(); 01647 } 01648 01649 QString KStandardDirs::localxdgconfdir() const 01650 { 01651 // Return the prefix to use for saving 01652 return d->xdgconf_prefixes.first(); 01653 } 01654 01655 01656 // just to make code more readable without macros 01657 QString locate( const char *type, 01658 const QString& filename, const KInstance* inst ) 01659 { 01660 return inst->dirs()->findResource(type, filename); 01661 } 01662 01663 QString locateLocal( const char *type, 01664 const QString& filename, const KInstance* inst ) 01665 { 01666 return locateLocal(type, filename, true, inst); 01667 } 01668 01669 QString locateLocal( const char *type, 01670 const QString& filename, bool createDir, const KInstance* inst ) 01671 { 01672 // try to find slashes. If there are some, we have to 01673 // create the subdir first 01674 int slash = filename.findRev('/')+1; 01675 if (!slash) // only one filename 01676 return inst->dirs()->saveLocation(type, QString::null, createDir) + filename; 01677 01678 // split path from filename 01679 QString dir = filename.left(slash); 01680 QString file = filename.mid(slash); 01681 return inst->dirs()->saveLocation(type, dir, createDir) + file; 01682 }

