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