kdecore Library API Documentation

kstandarddirs.cpp

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