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 // UGLY HACK - Chris CHeney 00838 if (local && (!strcmp("config", type))) 00839 candidates->append("/etc/kde/"); 00840 // 00841 local = false; 00842 } 00843 } 00844 dirs = absolutes.find(type); 00845 if (dirs) 00846 for (QStringList::ConstIterator it = dirs->begin(); 00847 it != dirs->end(); ++it) 00848 { 00849 testdir.setPath(*it); 00850 if (testdir.exists()) 00851 { 00852 QString filename = realPath(*it); 00853 if (!candidates->contains(filename)) 00854 candidates->append(filename); 00855 } 00856 } 00857 dircache.insert(type, candidates); 00858 } 00859 00860 #if 0 00861 kdDebug() << "found dirs for resource " << type << ":" << endl; 00862 for (QStringList::ConstIterator pit = candidates->begin(); 00863 pit != candidates->end(); 00864 pit++) 00865 { 00866 fprintf(stderr, "%s\n", (*pit).latin1()); 00867 } 00868 #endif 00869 00870 00871 return *candidates; 00872 } 00873 00874 QStringList KStandardDirs::systemPaths( const QString& pstr ) 00875 { 00876 QStringList tokens; 00877 QString p = pstr; 00878 00879 if( p.isNull() ) 00880 { 00881 p = getenv( "PATH" ); 00882 } 00883 00884 QString delimiters(QChar(KPATH_SEPARATOR)); 00885 delimiters += "\b"; 00886 tokenize( tokens, p, delimiters ); 00887 00888 QStringList exePaths; 00889 00890 // split path using : or \b as delimiters 00891 for( unsigned i = 0; i < tokens.count(); i++ ) 00892 { 00893 p = tokens[ i ]; 00894 00895 if ( p[ 0 ] == '~' ) 00896 { 00897 int len = p.find( '/' ); 00898 if ( len == -1 ) 00899 len = p.length(); 00900 if ( len == 1 ) 00901 { 00902 p.replace( 0, 1, QDir::homeDirPath() ); 00903 } 00904 else 00905 { 00906 QString user = p.mid( 1, len - 1 ); 00907 struct passwd *dir = getpwnam( user.local8Bit().data() ); 00908 if ( dir && strlen( dir->pw_dir ) ) 00909 p.replace( 0, len, QString::fromLocal8Bit( dir->pw_dir ) ); 00910 } 00911 } 00912 00913 exePaths << p; 00914 } 00915 00916 return exePaths; 00917 } 00918 00919 00920 QString KStandardDirs::findExe( const QString& appname, 00921 const QString& pstr, bool ignore) 00922 { 00923 #ifdef Q_WS_WIN 00924 QString real_appname = appname + ".exe"; 00925 #else 00926 QString real_appname = appname; 00927 #endif 00928 QFileInfo info; 00929 00930 // absolute or relative path given 00931 if (real_appname.find(QDir::separator()) >= 0) 00932 { 00933 info.setFile( real_appname ); 00934 if( info.exists() && ( ignore || info.isExecutable() ) 00935 && info.isFile() ) { 00936 return info.absFilePath(); 00937 } 00938 return QString::null; 00939 } 00940 00941 QString p = QString("%1/%2").arg(kfsstnd_defaultbindir()).arg(real_appname); 00942 info.setFile( p ); 00943 if( info.exists() && ( ignore || info.isExecutable() ) 00944 && ( info.isFile() || info.isSymLink() ) ) { 00945 return p; 00946 } 00947 00948 QStringList exePaths = systemPaths( pstr ); 00949 for (QStringList::ConstIterator it = exePaths.begin(); it != exePaths.end(); ++it) 00950 { 00951 p = (*it) + "/"; 00952 p += real_appname; 00953 00954 // Check for executable in this tokenized path 00955 info.setFile( p ); 00956 00957 if( info.exists() && ( ignore || info.isExecutable() ) 00958 && ( info.isFile() || info.isSymLink() ) ) { 00959 return p; 00960 } 00961 } 00962 00963 // If we reach here, the executable wasn't found. 00964 // So return empty string. 00965 00966 return QString::null; 00967 } 00968 00969 int KStandardDirs::findAllExe( QStringList& list, const QString& appname, 00970 const QString& pstr, bool ignore ) 00971 { 00972 #ifdef Q_WS_WIN 00973 QString real_appname = appname + ".exe"; 00974 #else 00975 QString real_appname = appname; 00976 #endif 00977 QFileInfo info; 00978 QString p; 00979 list.clear(); 00980 00981 QStringList exePaths = systemPaths( pstr ); 00982 for (QStringList::ConstIterator it = exePaths.begin(); it != exePaths.end(); ++it) 00983 { 00984 p = (*it) + "/"; 00985 p += real_appname; 00986 00987 info.setFile( p ); 00988 00989 if( info.exists() && (ignore || info.isExecutable()) 00990 && info.isFile() ) { 00991 list.append( p ); 00992 } 00993 } 00994 00995 return list.count(); 00996 } 00997 00998 static int tokenize( QStringList& tokens, const QString& str, 00999 const QString& delim ) 01000 { 01001 int len = str.length(); 01002 QString token = ""; 01003 01004 for( int index = 0; index < len; index++) 01005 { 01006 if ( delim.find( str[ index ] ) >= 0 ) 01007 { 01008 tokens.append( token ); 01009 token = ""; 01010 } 01011 else 01012 { 01013 token += str[ index ]; 01014 } 01015 } 01016 if ( token.length() > 0 ) 01017 { 01018 tokens.append( token ); 01019 } 01020 01021 return tokens.count(); 01022 } 01023 01024 QString KStandardDirs::kde_default(const char *type) { 01025 if (!strcmp(type, "data")) 01026 return "share/apps/"; 01027 if (!strcmp(type, "html")) 01028 return "share/doc/HTML/"; 01029 if (!strcmp(type, "icon")) 01030 return "share/icons/"; 01031 if (!strcmp(type, "config")) 01032 return "share/config/"; 01033 if (!strcmp(type, "pixmap")) 01034 return "share/pixmaps/"; 01035 if (!strcmp(type, "apps")) 01036 return "share/applnk/"; 01037 if (!strcmp(type, "sound")) 01038 return "share/sounds/"; 01039 if (!strcmp(type, "locale")) 01040 return "share/locale/"; 01041 if (!strcmp(type, "services")) 01042 return "share/services/"; 01043 if (!strcmp(type, "servicetypes")) 01044 return "share/servicetypes/"; 01045 if (!strcmp(type, "mime")) 01046 return "share/mimelnk/"; 01047 if (!strcmp(type, "cgi")) 01048 return "cgi-bin/"; 01049 if (!strcmp(type, "wallpaper")) 01050 return "share/wallpapers/"; 01051 if (!strcmp(type, "templates")) 01052 return "share/templates/"; 01053 if (!strcmp(type, "exe")) 01054 return "bin/"; 01055 if (!strcmp(type, "lib")) 01056 return "lib" KDELIBSUFF "/"; 01057 if (!strcmp(type, "module")) 01058 return "lib" KDELIBSUFF "/kde3/"; 01059 if (!strcmp(type, "qtplugins")) 01060 return "lib" KDELIBSUFF "/kde3/plugins"; 01061 if (!strcmp(type, "xdgdata-apps")) 01062 return "applications/"; 01063 if (!strcmp(type, "xdgdata-icon")) 01064 return "icons/"; 01065 if (!strcmp(type, "xdgdata-pixmap")) 01066 return "pixmaps/"; 01067 if (!strcmp(type, "xdgdata-dirs")) 01068 return "desktop-directories/"; 01069 if (!strcmp(type, "xdgconf-menu")) 01070 return "menus/"; 01071 if (!strcmp(type, "kcfg")) 01072 return "share/config.kcfg"; 01073 if (!strcmp(type, "emoticons")) 01074 return "share/emoticons"; 01075 01076 01077 qFatal("unknown resource type %s", type); 01078 return QString::null; 01079 } 01080 01081 QString KStandardDirs::saveLocation(const char *type, 01082 const QString& suffix, 01083 bool create) const 01084 { 01085 checkConfig(); 01086 01087 QString *pPath = savelocations.find(type); 01088 if (!pPath) 01089 { 01090 QStringList *dirs = relatives.find(type); 01091 if (!dirs && ( 01092 (strcmp(type, "socket") == 0) || 01093 (strcmp(type, "tmp") == 0) || 01094 (strcmp(type, "cache") == 0) )) 01095 { 01096 (void) resourceDirs(type); // Generate socket|tmp|cache resource. 01097 dirs = relatives.find(type); // Search again. 01098 } 01099 if (dirs) 01100 { 01101 // Check for existence of typed directory + suffix 01102 if (strncmp(type, "xdgdata-", 8) == 0) 01103 pPath = new QString(realPath(localxdgdatadir() + dirs->last())); 01104 else if (strncmp(type, "xdgconf-", 8) == 0) 01105 pPath = new QString(realPath(localxdgconfdir() + dirs->last())); 01106 else 01107 pPath = new QString(realPath(localkdedir() + dirs->last())); 01108 } 01109 else { 01110 dirs = absolutes.find(type); 01111 if (!dirs) 01112 qFatal("KStandardDirs: The resource type %s is not registered", type); 01113 pPath = new QString(realPath(dirs->last())); 01114 } 01115 01116 savelocations.insert(type, pPath); 01117 } 01118 QString fullPath = *pPath + (pPath->endsWith("/") ? "" : "/") + suffix; 01119 01120 KDE_struct_stat st; 01121 if (KDE_stat(QFile::encodeName(fullPath), &st) != 0 || !(S_ISDIR(st.st_mode))) { 01122 if(!create) { 01123 #ifndef NDEBUG 01124 kdDebug() << QString("save location %1 doesn't exist").arg(fullPath) << endl; 01125 #endif 01126 return fullPath; 01127 } 01128 if(!makeDir(fullPath, 0700)) { 01129 return fullPath; 01130 } 01131 dircache.remove(type); 01132 } 01133 if (!fullPath.endsWith("/")) 01134 fullPath += "/"; 01135 return fullPath; 01136 } 01137 01138 QString KStandardDirs::relativeLocation(const char *type, const QString &absPath) 01139 { 01140 QString fullPath = absPath; 01141 int i = absPath.findRev('/'); 01142 if (i != -1) 01143 { 01144 fullPath = realPath(absPath.left(i+1))+absPath.mid(i+1); // Normalize 01145 } 01146 01147 QStringList candidates = resourceDirs(type); 01148 01149 for (QStringList::ConstIterator it = candidates.begin(); 01150 it != candidates.end(); ++it) 01151 if (fullPath.startsWith(*it)) 01152 { 01153 return fullPath.mid((*it).length()); 01154 } 01155 01156 return absPath; 01157 } 01158 01159 01160 bool KStandardDirs::makeDir(const QString& dir, int mode) 01161 { 01162 // we want an absolute path 01163 if (QDir::isRelativePath(dir)) 01164 return false; 01165 01166 QString target = dir; 01167 uint len = target.length(); 01168 01169 // append trailing slash if missing 01170 if (dir.at(len - 1) != '/') 01171 target += '/'; 01172 01173 QString base(""); 01174 uint i = 1; 01175 01176 while( i < len ) 01177 { 01178 KDE_struct_stat st; 01179 int pos = target.find('/', i); 01180 base += target.mid(i - 1, pos - i + 1); 01181 QCString baseEncoded = QFile::encodeName(base); 01182 // bail out if we encountered a problem 01183 if (KDE_stat(baseEncoded, &st) != 0) 01184 { 01185 // Directory does not exist.... 01186 // Or maybe a dangling symlink ? 01187 if (KDE_lstat(baseEncoded, &st) == 0) 01188 (void)unlink(baseEncoded); // try removing 01189 01190 if ( KDE_mkdir(baseEncoded, (mode_t) mode) != 0) { 01191 baseEncoded.prepend( "trying to create local folder " ); 01192 perror(baseEncoded.data()); 01193 return false; // Couldn't create it :-( 01194 } 01195 } 01196 i = pos + 1; 01197 } 01198 return true; 01199 } 01200 01201 static QString readEnvPath(const char *env) 01202 { 01203 QCString c_path = getenv(env); 01204 if (c_path.isEmpty()) 01205 return QString::null; 01206 #ifdef Q_OS_WIN 01207 //win32 paths are case-insensitive: avoid duplicates on various dir lists 01208 return QFile::decodeName(c_path).lower(); 01209 #else 01210 return QFile::decodeName(c_path); 01211 #endif 01212 } 01213 01214 #ifdef __linux__ 01215 static QString executablePrefix() 01216 { 01217 char path_buffer[MAXPATHLEN + 1]; 01218 path_buffer[MAXPATHLEN] = 0; 01219 int length = readlink ("/proc/self/exe", path_buffer, MAXPATHLEN); 01220 if (length == -1) 01221 return QString::null; 01222 01223 path_buffer[length] = '\0'; 01224 01225 QString path = QFile::decodeName(path_buffer); 01226 01227 if(path.isEmpty()) 01228 return QString::null; 01229 01230 int pos = path.findRev('/'); // Skip filename 01231 if(pos <= 0) 01232 return QString::null; 01233 pos = path.findRev('/', pos - 1); // Skip last directory 01234 if(pos <= 0) 01235 return QString::null; 01236 01237 return path.left(pos); 01238 } 01239 #endif 01240 01241 QString KStandardDirs::kfsstnd_defaultprefix() 01242 { 01243 KStandardDirsSingleton* s = KStandardDirsSingleton::self(); 01244 if (!s->defaultprefix.isEmpty()) 01245 return s->defaultprefix; 01246 #ifdef Q_WS_WIN 01247 s->defaultprefix = readEnvPath("KDEDIR"); 01248 if (s->defaultprefix.isEmpty()) { 01249 s->defaultprefix = QFile::decodeName("c:\\kde"); 01250 //TODO: find other location (the Registry?) 01251 } 01252 #else //UNIX 01253 s->defaultprefix = KDEDIR; 01254 #endif 01255 if (s->defaultprefix.isEmpty()) 01256 kdWarning() << "KStandardDirs::kfsstnd_defaultprefix(): default KDE prefix not found!" << endl; 01257 return s->defaultprefix; 01258 } 01259 01260 QString KStandardDirs::kfsstnd_defaultbindir() 01261 { 01262 KStandardDirsSingleton* s = KStandardDirsSingleton::self(); 01263 if (!s->defaultbindir.isEmpty()) 01264 return s->defaultbindir; 01265 #ifdef Q_WS_WIN 01266 s->defaultbindir = kfsstnd_defaultprefix() + QString::fromLatin1("/bin"); 01267 #else //UNIX 01268 s->defaultbindir = __KDE_BINDIR; 01269 if (s->defaultbindir.isEmpty()) 01270 s->defaultbindir = kfsstnd_defaultprefix() + QString::fromLatin1("/bin"); 01271 #endif 01272 if (s->defaultbindir.isEmpty()) 01273 kdWarning() << "KStandardDirs::kfsstnd_defaultbindir(): default binary KDE dir not found!" << endl; 01274 return s->defaultbindir; 01275 } 01276 01277 void KStandardDirs::addKDEDefaults() 01278 { 01279 QStringList kdedirList; 01280 01281 // begin KDEDIRS 01282 QString kdedirs = readEnvPath("KDEDIRS"); 01283 if (!kdedirs.isEmpty()) 01284 { 01285 tokenize(kdedirList, kdedirs, QChar(KPATH_SEPARATOR)); 01286 } 01287 else 01288 { 01289 QString kdedir = readEnvPath("KDEDIR"); 01290 if (!kdedir.isEmpty()) 01291 { 01292 kdedir = KShell::tildeExpand(kdedir); 01293 kdedirList.append(kdedir); 01294 } 01295 } 01296 01297 #ifndef Q_OS_WIN //no default KDEDIR on win32 defined 01298 kdedirList.append(KDEDIR); 01299 #endif 01300 01301 #ifdef __KDE_EXECPREFIX 01302 QString execPrefix(__KDE_EXECPREFIX); 01303 if (execPrefix!="NONE") 01304 kdedirList.append(execPrefix); 01305 #endif 01306 #ifdef __linux__ 01307 const QString linuxExecPrefix = executablePrefix(); 01308 if ( !linuxExecPrefix.isEmpty() ) 01309 kdedirList.append( linuxExecPrefix ); 01310 #endif 01311 01312 // We treat root differently to prevent a "su" shell messing up the 01313 // file permissions in the user's home directory. 01314 QString localKdeDir = readEnvPath(getuid() ? "KDEHOME" : "KDEROOTHOME"); 01315 if (!localKdeDir.isEmpty()) 01316 { 01317 if (localKdeDir[localKdeDir.length()-1] != '/') 01318 localKdeDir += '/'; 01319 } 01320 else 01321 { 01322 localKdeDir = QDir::homeDirPath() + "/.kde/"; 01323 } 01324 01325 if (localKdeDir != "-/") 01326 { 01327 localKdeDir = KShell::tildeExpand(localKdeDir); 01328 addPrefix(localKdeDir); 01329 } 01330 01331 QStringList::ConstIterator end(kdedirList.end()); 01332 for (QStringList::ConstIterator it = kdedirList.begin(); 01333 it != end; ++it) 01334 { 01335 QString dir = KShell::tildeExpand(*it); 01336 addPrefix(dir); 01337 } 01338 // end KDEDIRS 01339 01340 // begin XDG_CONFIG_XXX 01341 QStringList xdgdirList; 01342 QString xdgdirs = readEnvPath("XDG_CONFIG_DIRS"); 01343 if (!xdgdirs.isEmpty()) 01344 { 01345 tokenize(xdgdirList, xdgdirs, QChar(KPATH_SEPARATOR)); 01346 } 01347 else 01348 { 01349 xdgdirList.clear(); 01350 xdgdirList.append("/etc/xdg"); 01351 #ifdef Q_WS_WIN 01352 xdgdirList.append(kfsstnd_defaultprefix() + "/etc/xdg"); 01353 #else 01354 xdgdirList.append(KDESYSCONFDIR "/xdg"); 01355 #endif 01356 } 01357 01358 QString localXdgDir = readEnvPath("XDG_CONFIG_HOME"); 01359 if (!localXdgDir.isEmpty()) 01360 { 01361 if (localXdgDir[localXdgDir.length()-1] != '/') 01362 localXdgDir += '/'; 01363 } 01364 else 01365 { 01366 localXdgDir = QDir::homeDirPath() + "/.config/"; 01367 } 01368 01369 localXdgDir = KShell::tildeExpand(localXdgDir); 01370 addXdgConfigPrefix(localXdgDir); 01371 01372 for (QStringList::ConstIterator it = xdgdirList.begin(); 01373 it != xdgdirList.end(); ++it) 01374 { 01375 QString dir = KShell::tildeExpand(*it); 01376 addXdgConfigPrefix(dir); 01377 } 01378 // end XDG_CONFIG_XXX 01379 01380 // begin XDG_DATA_XXX 01381 xdgdirs = readEnvPath("XDG_DATA_DIRS"); 01382 if (!xdgdirs.isEmpty()) 01383 { 01384 tokenize(xdgdirList, xdgdirs, QChar(KPATH_SEPARATOR)); 01385 } 01386 else 01387 { 01388 xdgdirList.clear(); 01389 for (QStringList::ConstIterator it = kdedirList.begin(); 01390 it != kdedirList.end(); ++it) 01391 { 01392 QString dir = *it; 01393 if (dir[dir.length()-1] != '/') 01394 dir += '/'; 01395 xdgdirList.append(dir+"share/"); 01396 } 01397 01398 xdgdirList.append("/usr/local/share/"); 01399 xdgdirList.append("/usr/share/"); 01400 } 01401 01402 localXdgDir = readEnvPath("XDG_DATA_HOME"); 01403 if (!localXdgDir.isEmpty()) 01404 { 01405 if (localXdgDir[localXdgDir.length()-1] != '/') 01406 localXdgDir += '/'; 01407 } 01408 else 01409 { 01410 localXdgDir = QDir::homeDirPath() + "/.local/share/"; 01411 } 01412 01413 localXdgDir = KShell::tildeExpand(localXdgDir); 01414 addXdgDataPrefix(localXdgDir); 01415 01416 for (QStringList::ConstIterator it = xdgdirList.begin(); 01417 it != xdgdirList.end(); ++it) 01418 { 01419 QString dir = KShell::tildeExpand(*it); 01420 addXdgDataPrefix(dir); 01421 } 01422 // end XDG_DATA_XXX 01423 01424 01425 uint index = 0; 01426 while (types[index] != 0) { 01427 addResourceType(types[index], kde_default(types[index])); 01428 index++; 01429 } 01430 01431 addResourceDir("home", QDir::homeDirPath()); 01432 } 01433 01434 void KStandardDirs::checkConfig() const 01435 { 01436 if (!addedCustoms && KGlobal::_instance && KGlobal::_instance->_config) 01437 const_cast<KStandardDirs*>(this)->addCustomized(KGlobal::_instance->_config); 01438 } 01439 01440 static QStringList lookupProfiles(const QString &mapFile) 01441 { 01442 QStringList profiles; 01443 01444 if (mapFile.isEmpty() || !QFile::exists(mapFile)) 01445 { 01446 profiles << "default"; 01447 return profiles; 01448 } 01449 01450 struct passwd *pw = getpwuid(geteuid()); 01451 if (!pw) 01452 { 01453 profiles << "default"; 01454 return profiles; // Not good 01455 } 01456 01457 QCString user = pw->pw_name; 01458 01459 gid_t sup_gids[512]; 01460 int sup_gids_nr = getgroups(512, sup_gids); 01461 01462 KSimpleConfig mapCfg(mapFile, true); 01463 mapCfg.setGroup("Users"); 01464 if (mapCfg.hasKey(user.data())) 01465 { 01466 profiles = mapCfg.readListEntry(user.data()); 01467 return profiles; 01468 } 01469 01470 mapCfg.setGroup("General"); 01471 QStringList groups = mapCfg.readListEntry("groups"); 01472 01473 mapCfg.setGroup("Groups"); 01474 01475 for( QStringList::ConstIterator it = groups.begin(); 01476 it != groups.end(); ++it ) 01477 { 01478 QCString grp = (*it).utf8(); 01479 // Check if user is in this group 01480 struct group *grp_ent = getgrnam(grp); 01481 if (!grp_ent) continue; 01482 gid_t gid = grp_ent->gr_gid; 01483 if (pw->pw_gid == gid) 01484 { 01485 // User is in this group --> add profiles 01486 profiles += mapCfg.readListEntry(*it); 01487 } 01488 else 01489 { 01490 for(int i = 0; i < sup_gids_nr; i++) 01491 { 01492 if (sup_gids[i] == gid) 01493 { 01494 // User is in this group --> add profiles 01495 profiles += mapCfg.readListEntry(*it); 01496 break; 01497 } 01498 } 01499 } 01500 } 01501 01502 if (profiles.isEmpty()) 01503 profiles << "default"; 01504 return profiles; 01505 } 01506 01507 extern bool kde_kiosk_admin; 01508 01509 bool KStandardDirs::addCustomized(KConfig *config) 01510 { 01511 if (addedCustoms && !d->checkRestrictions) // there are already customized entries 01512 return false; // we just quit and hope they are the right ones 01513 01514 // save the numbers of config directories. If this changes, 01515 // we will return true to give KConfig a chance to reparse 01516 uint configdirs = resourceDirs("config").count(); 01517 01518 // Remember original group 01519 QString oldGroup = config->group(); 01520 01521 if (!addedCustoms) 01522 { 01523 // We only add custom entries once 01524 addedCustoms = true; 01525 01526 // reading the prefixes in 01527 QString group = QString::fromLatin1("Directories"); 01528 config->setGroup(group); 01529 01530 QString kioskAdmin = config->readEntry("kioskAdmin"); 01531 if (!kioskAdmin.isEmpty() && !kde_kiosk_admin) 01532 { 01533 int i = kioskAdmin.find(':'); 01534 QString user = kioskAdmin.left(i); 01535 QString host = kioskAdmin.mid(i+1); 01536 01537 KUser thisUser; 01538 char hostname[ 256 ]; 01539 hostname[ 0 ] = '\0'; 01540 if (!gethostname( hostname, 255 )) 01541 hostname[sizeof(hostname)-1] = '\0'; 01542 01543 if ((user == thisUser.loginName()) && 01544 (host.isEmpty() || (host == hostname))) 01545 { 01546 kde_kiosk_admin = true; 01547 } 01548 } 01549 01550 bool readProfiles = true; 01551 01552 if (kde_kiosk_admin && !QCString(getenv("KDE_KIOSK_NO_PROFILES")).isEmpty()) 01553 readProfiles = false; 01554 01555 QString userMapFile = config->readEntry("userProfileMapFile"); 01556 QString profileDirsPrefix = config->readEntry("profileDirsPrefix"); 01557 if (!profileDirsPrefix.isEmpty() && !profileDirsPrefix.endsWith("/")) 01558 profileDirsPrefix.append('/'); 01559 01560 QStringList profiles; 01561 if (readProfiles) 01562 profiles = lookupProfiles(userMapFile); 01563 QString profile; 01564 01565 bool priority = false; 01566 while(true) 01567 { 01568 config->setGroup(group); 01569 QStringList list = config->readListEntry("prefixes"); 01570 for (QStringList::ConstIterator it = list.begin(); it != list.end(); ++it) 01571 { 01572 addPrefix(*it, priority); 01573 addXdgConfigPrefix(*it+"/etc/xdg", priority); 01574 addXdgDataPrefix(*it+"/share", priority); 01575 } 01576 // If there are no prefixes defined, check if there is a directory 01577 // for this profile under <profileDirsPrefix> 01578 if (list.isEmpty() && !profile.isEmpty() && !profileDirsPrefix.isEmpty()) 01579 { 01580 QString dir = profileDirsPrefix + profile; 01581 addPrefix(dir, priority); 01582 addXdgConfigPrefix(dir+"/etc/xdg", priority); 01583 addXdgDataPrefix(dir+"/share", priority); 01584 } 01585 01586 // iterating over all entries in the group Directories 01587 // to find entries that start with dir_$type 01588 QMap<QString, QString> entries = config->entryMap(group); 01589 for (QMap<QString, QString>::ConstIterator it2 = entries.begin(); 01590 it2 != entries.end(); it2++) 01591 { 01592 QString key = it2.key(); 01593 if (key.startsWith("dir_")) { 01594 // generate directory list, there may be more than 1. 01595 QStringList dirs = QStringList::split(',', *it2); 01596 QStringList::Iterator sIt(dirs.begin()); 01597 QString resType = key.mid(4, key.length()); 01598 for (; sIt != dirs.end(); ++sIt) 01599 { 01600 addResourceDir(resType.latin1(), *sIt, priority); 01601 } 01602 } 01603 } 01604 if (profiles.isEmpty()) 01605 break; 01606 profile = profiles.back(); 01607 group = QString::fromLatin1("Directories-%1").arg(profile); 01608 profiles.pop_back(); 01609 priority = true; 01610 } 01611 } 01612 01613 // Process KIOSK restrictions. 01614 if (!kde_kiosk_admin || QCString(getenv("KDE_KIOSK_NO_RESTRICTIONS")).isEmpty()) 01615 { 01616 config->setGroup("KDE Resource Restrictions"); 01617 QMap<QString, QString> entries = config->entryMap("KDE Resource Restrictions"); 01618 for (QMap<QString, QString>::ConstIterator it2 = entries.begin(); 01619 it2 != entries.end(); it2++) 01620 { 01621 QString key = it2.key(); 01622 if (!config->readBoolEntry(key, true)) 01623 { 01624 d->restrictionsActive = true; 01625 d->restrictions.insert(key.latin1(), &d->restrictionsActive); // Anything will do 01626 dircache.remove(key.latin1()); 01627 } 01628 } 01629 } 01630 01631 config->setGroup(oldGroup); 01632 01633 // check if the number of config dirs changed 01634 bool configDirsChanged = (resourceDirs("config").count() != configdirs); 01635 // If the config dirs changed, we check kiosk restrictions again. 01636 d->checkRestrictions = configDirsChanged; 01637 // return true if the number of config dirs changed: reparse config file 01638 return configDirsChanged; 01639 } 01640 01641 QString KStandardDirs::localkdedir() const 01642 { 01643 // Return the prefix to use for saving 01644 return prefixes.first(); 01645 } 01646 01647 QString KStandardDirs::localxdgdatadir() const 01648 { 01649 // Return the prefix to use for saving 01650 return d->xdgdata_prefixes.first(); 01651 } 01652 01653 QString KStandardDirs::localxdgconfdir() const 01654 { 01655 // Return the prefix to use for saving 01656 return d->xdgconf_prefixes.first(); 01657 } 01658 01659 01660 // just to make code more readable without macros 01661 QString locate( const char *type, 01662 const QString& filename, const KInstance* inst ) 01663 { 01664 return inst->dirs()->findResource(type, filename); 01665 } 01666 01667 QString locateLocal( const char *type, 01668 const QString& filename, const KInstance* inst ) 01669 { 01670 return locateLocal(type, filename, true, inst); 01671 } 01672 01673 QString locateLocal( const char *type, 01674 const QString& filename, bool createDir, const KInstance* inst ) 01675 { 01676 // try to find slashes. If there are some, we have to 01677 // create the subdir first 01678 int slash = filename.findRev('/')+1; 01679 if (!slash) // only one filename 01680 return inst->dirs()->saveLocation(type, QString::null, createDir) + filename; 01681 01682 // split path from filename 01683 QString dir = filename.left(slash); 01684 QString file = filename.mid(slash); 01685 return inst->dirs()->saveLocation(type, dir, createDir) + file; 01686 }