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