00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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
00039 #include <qregexp.h>
00040 #include <qasciidict.h>
00041 #include <qdict.h>
00042 #include <qdir.h>
00043 #include <qfileinfo.h>
00044 #include <qstring.h>
00045 #include <qstringlist.h>
00046
00047 #include "kstandarddirs.h"
00048 #include "kconfig.h"
00049 #include "kdebug.h"
00050 #include "kinstance.h"
00051 #include <sys/param.h>
00052 #include <unistd.h>
00053
00054 template class QDict<QStringList>;
00055
00056 class KStandardDirs::KStandardDirsPrivate
00057 {
00058 public:
00059 KStandardDirsPrivate()
00060 : restrictionsActive(false),
00061 dataRestrictionActive(false)
00062 { }
00063
00064 bool restrictionsActive;
00065 bool dataRestrictionActive;
00066 QAsciiDict<bool> restrictions;
00067 };
00068
00069 static const char* const types[] = {"html", "icon", "apps", "sound",
00070 "data", "locale", "services", "mime",
00071 "servicetypes", "config", "exe",
00072 "wallpaper", "lib", "pixmap", "templates", "module", "qtplugins", 0 };
00073
00074 static int tokenize( QStringList& token, const QString& str,
00075 const QString& delim );
00076
00077 KStandardDirs::KStandardDirs( ) : addedCustoms(false), d(0)
00078 {
00079 dircache.setAutoDelete(true);
00080 relatives.setAutoDelete(true);
00081 absolutes.setAutoDelete(true);
00082 savelocations.setAutoDelete(true);
00083 addKDEDefaults();
00084 }
00085
00086 KStandardDirs::~KStandardDirs()
00087 {
00088 delete d;
00089 d = 0L;
00090 }
00091
00092 bool KStandardDirs::isRestrictedResource(const char *type, const QString& relPath) const
00093 {
00094 if (!d || !d->restrictionsActive)
00095 return false;
00096
00097 if (d->restrictions[type])
00098 return true;
00099
00100 if (strcmp(type, "data")==0)
00101 {
00102 applyDataRestrictions(relPath);
00103 if (d->dataRestrictionActive)
00104 {
00105 d->dataRestrictionActive = false;
00106 return true;
00107 }
00108 }
00109 return false;
00110 }
00111
00112 void KStandardDirs::applyDataRestrictions(const QString &relPath) const
00113 {
00114 QString key;
00115 int i = relPath.find('/');
00116 if (i != -1)
00117 key = "data_"+relPath.left(i);
00118 else
00119 key = "data_"+relPath;
00120
00121 if (d && d->restrictions[key.latin1()])
00122 d->dataRestrictionActive = true;
00123 }
00124
00125
00126 QStringList KStandardDirs::allTypes() const
00127 {
00128 QStringList list;
00129 for (int i = 0; types[i] != 0; ++i)
00130 list.append(QString::fromLatin1(types[i]));
00131 return list;
00132 }
00133
00134 void KStandardDirs::addPrefix( const QString& _dir )
00135 {
00136 if (_dir.isNull())
00137 return;
00138
00139 QString dir = _dir;
00140 if (dir.at(dir.length() - 1) != '/')
00141 dir += '/';
00142
00143 if (!prefixes.contains(dir)) {
00144 prefixes.append(dir);
00145 dircache.clear();
00146 }
00147 }
00148
00149 QString KStandardDirs::kfsstnd_prefixes()
00150 {
00151 return prefixes.join(":");
00152 }
00153
00154 bool KStandardDirs::addResourceType( const char *type,
00155 const QString& relativename )
00156 {
00157 if (relativename.isNull())
00158 return false;
00159
00160 QStringList *rels = relatives.find(type);
00161 if (!rels) {
00162 rels = new QStringList();
00163 relatives.insert(type, rels);
00164 }
00165 QString copy = relativename;
00166 if (copy.at(copy.length() - 1) != '/')
00167 copy += '/';
00168 if (!rels->contains(copy)) {
00169 rels->prepend(copy);
00170 dircache.remove(type);
00171 return true;
00172 }
00173 return false;
00174 }
00175
00176 bool KStandardDirs::addResourceDir( const char *type,
00177 const QString& absdir)
00178 {
00179 QStringList *paths = absolutes.find(type);
00180 if (!paths) {
00181 paths = new QStringList();
00182 absolutes.insert(type, paths);
00183 }
00184 QString copy = absdir;
00185 if (copy.at(copy.length() - 1) != '/')
00186 copy += '/';
00187
00188 if (!paths->contains(copy)) {
00189 paths->append(copy);
00190 dircache.remove(type);
00191 return true;
00192 }
00193 return false;
00194 }
00195
00196 QString KStandardDirs::findResource( const char *type,
00197 const QString& filename ) const
00198 {
00199 if (filename.at(0) == '/')
00200 return filename;
00201
00202 #if 0
00203 kdDebug() << "Find resource: " << type << endl;
00204 for (QStringList::ConstIterator pit = prefixes.begin();
00205 pit != prefixes.end();
00206 pit++)
00207 {
00208 kdDebug() << "Prefix: " << *pit << endl;
00209 }
00210 #endif
00211
00212 QString dir = findResourceDir(type, filename);
00213 if (dir.isNull())
00214 return dir;
00215 else return dir + filename;
00216 }
00217
00218 static Q_UINT32 updateHash(const QString &file, Q_UINT32 hash)
00219 {
00220 QCString cFile = QFile::encodeName(file);
00221 struct stat buff;
00222 if ((access(cFile, R_OK) == 0) &&
00223 (stat( cFile, &buff ) == 0) &&
00224 (S_ISREG( buff.st_mode )))
00225 {
00226 hash = hash + (Q_UINT32) buff.st_ctime;
00227 }
00228 return hash;
00229 }
00230
00231 Q_UINT32 KStandardDirs::calcResourceHash( const char *type,
00232 const QString& filename, bool deep) const
00233 {
00234 Q_UINT32 hash = 0;
00235
00236 if (filename.at(0) == '/')
00237 {
00238
00239 return updateHash(filename, hash);
00240 }
00241 if (d && d->restrictionsActive && (strcmp(type, "data")==0))
00242 applyDataRestrictions(filename);
00243 QStringList candidates = resourceDirs(type);
00244 QString fullPath;
00245
00246 for (QStringList::ConstIterator it = candidates.begin();
00247 it != candidates.end(); it++)
00248 {
00249 hash = updateHash(*it + filename, hash);
00250 if (!deep && hash)
00251 return hash;
00252 }
00253 return hash;
00254 }
00255
00256
00257 QStringList KStandardDirs::findDirs( const char *type,
00258 const QString& reldir ) const
00259 {
00260 QStringList list;
00261
00262 checkConfig();
00263
00264 if (d && d->restrictionsActive && (strcmp(type, "data")==0))
00265 applyDataRestrictions(reldir);
00266 QStringList candidates = resourceDirs(type);
00267 QDir testdir;
00268
00269 for (QStringList::ConstIterator it = candidates.begin();
00270 it != candidates.end(); it++) {
00271 testdir.setPath(*it + reldir);
00272 if (testdir.exists())
00273 list.append(testdir.absPath() + '/');
00274 }
00275
00276 return list;
00277 }
00278
00279 QString KStandardDirs::findResourceDir( const char *type,
00280 const QString& filename) const
00281 {
00282 #ifndef NDEBUG
00283 if (filename.isEmpty()) {
00284 kdWarning() << "filename for type " << type << " in KStandardDirs::findResourceDir is not supposed to be empty!!" << endl;
00285 return QString::null;
00286 }
00287 #endif
00288
00289 if (d && d->restrictionsActive && (strcmp(type, "data")==0))
00290 applyDataRestrictions(filename);
00291 QStringList candidates = resourceDirs(type);
00292 QString fullPath;
00293
00294 for (QStringList::ConstIterator it = candidates.begin();
00295 it != candidates.end(); it++)
00296 if (exists(*it + filename))
00297 return *it;
00298
00299 #ifndef NDEBUG
00300 if(false && type != "locale")
00301 kdDebug() << "KStdDirs::findResDir(): can't find \"" << filename << "\" in type \"" << type << "\"." << endl;
00302 #endif
00303
00304 return QString::null;
00305 }
00306
00307 bool KStandardDirs::exists(const QString &fullPath)
00308 {
00309 struct stat buff;
00310 if (access(QFile::encodeName(fullPath), R_OK) == 0 && stat( QFile::encodeName(fullPath), &buff ) == 0)
00311 if (fullPath.at(fullPath.length() - 1) != '/') {
00312 if (S_ISREG( buff.st_mode ))
00313 return true;
00314 } else
00315 if (S_ISDIR( buff.st_mode ))
00316 return true;
00317 return false;
00318 }
00319
00320 static void lookupDirectory(const QString& path, const QString &relPart,
00321 const QRegExp ®exp,
00322 QStringList& list,
00323 QStringList& relList,
00324 bool recursive, bool uniq)
00325 {
00326 QString pattern = regexp.pattern();
00327 if (recursive || pattern.contains('?') || pattern.contains('*'))
00328 {
00329
00330 DIR *dp = opendir( QFile::encodeName(path));
00331 if (!dp)
00332 return;
00333
00334 assert(path.at(path.length() - 1) == '/');
00335
00336 struct dirent *ep;
00337 struct stat buff;
00338
00339 QString _dot(".");
00340 QString _dotdot("..");
00341
00342 while( ( ep = readdir( dp ) ) != 0L )
00343 {
00344 QString fn( QFile::decodeName(ep->d_name));
00345 if (fn == _dot || fn == _dotdot || fn.at(fn.length() - 1).latin1() == '~')
00346 continue;
00347
00348 if (!recursive && !regexp.exactMatch(fn))
00349 continue;
00350
00351 QString pathfn = path + fn;
00352 if ( stat( QFile::encodeName(pathfn), &buff ) != 0 ) {
00353 kdDebug() << "Error stat'ing " << pathfn << " : " << perror << endl;
00354 continue;
00355 }
00356 if ( recursive ) {
00357 if ( S_ISDIR( buff.st_mode )) {
00358 lookupDirectory(pathfn + '/', relPart + fn + '/', regexp, list, relList, recursive, uniq);
00359 }
00360 if (!regexp.exactMatch(fn))
00361 continue;
00362 }
00363 if ( S_ISREG( buff.st_mode))
00364 {
00365 if (!uniq || !relList.contains(relPart + fn))
00366 {
00367 list.append( pathfn );
00368 relList.append( relPart + fn );
00369 }
00370 }
00371 }
00372 closedir( dp );
00373 }
00374 else
00375 {
00376
00377 QString fn = pattern;
00378 QString pathfn = path + fn;
00379 struct stat buff;
00380 if ( stat( QFile::encodeName(pathfn), &buff ) != 0 )
00381 return;
00382 if ( S_ISREG( buff.st_mode))
00383 {
00384 if (!uniq || !relList.contains(relPart + fn))
00385 {
00386 list.append( pathfn );
00387 relList.append( relPart + fn );
00388 }
00389 }
00390 }
00391 }
00392
00393 static void lookupPrefix(const QString& prefix, const QString& relpath,
00394 const QString& relPart,
00395 const QRegExp ®exp,
00396 QStringList& list,
00397 QStringList& relList,
00398 bool recursive, bool uniq)
00399 {
00400 if (relpath.isNull()) {
00401 lookupDirectory(prefix, relPart, regexp, list,
00402 relList, recursive, uniq);
00403 return;
00404 }
00405 QString path;
00406 QString rest;
00407
00408 if (relpath.length())
00409 {
00410 int slash = relpath.find('/');
00411 if (slash < 0)
00412 rest = relpath.left(relpath.length() - 1);
00413 else {
00414 path = relpath.left(slash);
00415 rest = relpath.mid(slash + 1);
00416 }
00417 }
00418
00419 assert(prefix.at(prefix.length() - 1) == '/');
00420
00421 struct stat buff;
00422
00423 if (path.contains('*') || path.contains('?')) {
00424
00425 QRegExp pathExp(path, true, true);
00426 DIR *dp = opendir( QFile::encodeName(prefix) );
00427 if (!dp) {
00428 return;
00429 }
00430
00431 struct dirent *ep;
00432
00433 QString _dot(".");
00434 QString _dotdot("..");
00435
00436 while( ( ep = readdir( dp ) ) != 0L )
00437 {
00438 QString fn( QFile::decodeName(ep->d_name));
00439 if (fn == _dot || fn == _dotdot || fn.at(fn.length() - 1) == '~')
00440 continue;
00441
00442 if (pathExp.search(fn) == -1)
00443 continue;
00444 QString rfn = relPart+fn;
00445 fn = prefix + fn;
00446 if ( stat( QFile::encodeName(fn), &buff ) != 0 ) {
00447 kdDebug() << "Error statting " << fn << " : " << perror << endl;
00448 continue;
00449 }
00450 if ( S_ISDIR( buff.st_mode ))
00451 lookupPrefix(fn + '/', rest, rfn + '/', regexp, list, relList, recursive, uniq);
00452 }
00453
00454 closedir( dp );
00455 } else {
00456
00457
00458 lookupPrefix(prefix + path + '/', rest,
00459 relPart + path + '/', regexp, list,
00460 relList, recursive, uniq);
00461 }
00462 }
00463
00464 QStringList
00465 KStandardDirs::findAllResources( const char *type,
00466 const QString& filter,
00467 bool recursive,
00468 bool uniq,
00469 QStringList &relList) const
00470 {
00471 QStringList list;
00472 if (filter.at(0) == '/')
00473 {
00474 list.append( filter);
00475 return list;
00476 }
00477
00478 QString filterPath;
00479 QString filterFile;
00480
00481 if (filter.length())
00482 {
00483 int slash = filter.findRev('/');
00484 if (slash < 0)
00485 filterFile = filter;
00486 else {
00487 filterPath = filter.left(slash + 1);
00488 filterFile = filter.mid(slash + 1);
00489 }
00490 }
00491
00492 checkConfig();
00493
00494 if (d && d->restrictionsActive && (strcmp(type, "data")==0))
00495 applyDataRestrictions(filter);
00496 QStringList candidates = resourceDirs(type);
00497 if (filterFile.isEmpty())
00498 filterFile = "*";
00499
00500 QRegExp regExp(filterFile, true, true);
00501
00502 for (QStringList::ConstIterator it = candidates.begin();
00503 it != candidates.end(); it++)
00504 {
00505 lookupPrefix(*it, filterPath, "", regExp, list,
00506 relList, recursive, uniq);
00507 }
00508
00509 return list;
00510 }
00511
00512 QStringList
00513 KStandardDirs::findAllResources( const char *type,
00514 const QString& filter,
00515 bool recursive,
00516 bool uniq) const
00517 {
00518 QStringList relList;
00519 return findAllResources(type, filter, recursive, uniq, relList);
00520 }
00521
00522 QString
00523 KStandardDirs::realPath(const QString &dirname)
00524 {
00525 char realpath_buffer[MAXPATHLEN + 1];
00526 memset(realpath_buffer, 0, MAXPATHLEN + 1);
00527
00528
00529 if (realpath( QFile::encodeName(dirname).data(), realpath_buffer) != 0) {
00530
00531 int len = strlen(realpath_buffer);
00532 realpath_buffer[len] = '/';
00533 realpath_buffer[len+1] = 0;
00534 return QFile::decodeName(realpath_buffer);
00535 }
00536
00537 return dirname;
00538 }
00539
00540 void KStandardDirs::createSpecialResource(const char *type)
00541 {
00542 char hostname[256];
00543 hostname[0] = 0;
00544 gethostname(hostname, 255);
00545 QString dir = QString("%1%2-%3").arg(localkdedir()).arg(type).arg(hostname);
00546 char link[1024];
00547 link[1023] = 0;
00548 int result = readlink(QFile::encodeName(dir).data(), link, 1023);
00549 bool relink = (result == -1) && (errno == ENOENT);
00550 if ((result > 0) && (link[0] == '/'))
00551 {
00552 link[result] = 0;
00553 struct stat stat_buf;
00554 int res = lstat(link, &stat_buf);
00555 if ((res == -1) && (errno == ENOENT))
00556 {
00557 relink = true;
00558 }
00559 else if ((res == -1) || (!S_ISDIR(stat_buf.st_mode)))
00560 {
00561 fprintf(stderr, "Error: \"%s\" is not a directory.\n", link);
00562 relink = true;
00563 }
00564 else if (stat_buf.st_uid != getuid())
00565 {
00566 fprintf(stderr, "Error: \"%s\" is owned by uid %d instead of uid %d.\n", link, stat_buf.st_uid, getuid());
00567 relink = true;
00568 }
00569 }
00570 if (relink)
00571 {
00572 QString srv = findExe(QString::fromLatin1("lnusertemp"), KDEDIR+QString::fromLatin1("/bin"));
00573 if (srv.isEmpty())
00574 srv = findExe(QString::fromLatin1("lnusertemp"));
00575 if (!srv.isEmpty())
00576 {
00577 system(QFile::encodeName(srv)+" "+type);
00578 result = readlink(QFile::encodeName(dir).data(), link, 1023);
00579 }
00580 }
00581 if (result > 0)
00582 {
00583 link[result] = 0;
00584 if (link[0] == '/')
00585 dir = QFile::decodeName(link);
00586 else
00587 dir = QDir::cleanDirPath(dir+QFile::decodeName(link));
00588 }
00589 addResourceDir(type, dir+'/');
00590 }
00591
00592 QStringList KStandardDirs::resourceDirs(const char *type) const
00593 {
00594 QStringList *candidates = dircache.find(type);
00595
00596 if (!candidates) {
00597 if (strcmp(type, "socket") == 0)
00598 const_cast<KStandardDirs *>(this)->createSpecialResource(type);
00599 else if (strcmp(type, "tmp") == 0)
00600 const_cast<KStandardDirs *>(this)->createSpecialResource(type);
00601
00602 QDir testdir;
00603
00604 candidates = new QStringList();
00605 QStringList *dirs;
00606
00607 bool restrictionActive = false;
00608 if (d && d->restrictionsActive)
00609 {
00610 if (d->dataRestrictionActive)
00611 restrictionActive = true;
00612 else if (d->restrictions["all"])
00613 restrictionActive = true;
00614 else if (d->restrictions[type])
00615 restrictionActive = true;
00616 d->dataRestrictionActive = false;
00617 }
00618
00619 dirs = relatives.find(type);
00620 if (dirs)
00621 {
00622 bool local = true;
00623 for (QStringList::ConstIterator pit = prefixes.begin();
00624 pit != prefixes.end();
00625 pit++)
00626 {
00627 for (QStringList::ConstIterator it = dirs->begin();
00628 it != dirs->end(); ++it) {
00629 QString path = realPath(*pit + *it);
00630 testdir.setPath(path);
00631 if (local && restrictionActive)
00632 continue;
00633 if ((local || testdir.exists()) && !candidates->contains(path))
00634 candidates->append(path);
00635 }
00636 local = false;
00637 }
00638 }
00639 dirs = absolutes.find(type);
00640 if (dirs)
00641 for (QStringList::ConstIterator it = dirs->begin();
00642 it != dirs->end(); ++it)
00643 {
00644 testdir.setPath(*it);
00645 if (testdir.exists())
00646 {
00647 QString filename = realPath(*it);
00648 if (!candidates->contains(filename))
00649 candidates->append(filename);
00650 }
00651 }
00652 dircache.insert(type, candidates);
00653 }
00654
00655 #if 0
00656 kdDebug() << "found dirs for resource " << type << ":" << endl;
00657 for (QStringList::ConstIterator pit = candidates->begin();
00658 pit != candidates->end();
00659 pit++)
00660 {
00661 fprintf(stderr, "%s\n", (*pit).latin1());
00662 }
00663 #endif
00664
00665
00666 return *candidates;
00667 }
00668
00669 QString KStandardDirs::findExe( const QString& appname,
00670 const QString& pstr, bool ignore)
00671 {
00672 QFileInfo info;
00673
00674
00675 if (appname.startsWith(QString::fromLatin1("/")))
00676 {
00677 info.setFile( appname );
00678 if( info.exists() && ( ignore || info.isExecutable() )
00679 && info.isFile() ) {
00680 return appname;
00681 }
00682 return QString::null;
00683 }
00684
00685 QString p = QString("%1/%2").arg(__KDE_BINDIR).arg(appname);
00686 info.setFile( p );
00687 if( info.exists() && ( ignore || info.isExecutable() )
00688 && ( info.isFile() || info.isSymLink() ) ) {
00689 return p;
00690 }
00691
00692 QStringList tokens;
00693 p = pstr;
00694
00695 if( p == QString::null ) {
00696 p = getenv( "PATH" );
00697 }
00698
00699 tokenize( tokens, p, ":\b" );
00700
00701
00702 for( unsigned i = 0; i < tokens.count(); i++ ) {
00703 p = tokens[ i ];
00704
00705 if ( p[ 0 ] == '~' )
00706 {
00707 int len = p.find( '/' );
00708 if ( len == -1 )
00709 len = p.length();
00710 if ( len == 1 )
00711 p.replace( 0, 1, QDir::homeDirPath() );
00712 else
00713 {
00714 QString user = p.mid( 1, len - 1 );
00715 struct passwd *dir = getpwnam( user.local8Bit().data() );
00716 if ( dir && strlen( dir->pw_dir ) )
00717 p.replace( 0, len, QString::fromLocal8Bit( dir->pw_dir ) );
00718 }
00719 }
00720
00721 p += "/";
00722 p += appname;
00723
00724
00725 info.setFile( p );
00726
00727 if( info.exists() && ( ignore || info.isExecutable() )
00728 && ( info.isFile() || info.isSymLink() ) ) {
00729 return p;
00730 }
00731 }
00732
00733
00734
00735
00736 return QString::null;
00737 }
00738
00739 int KStandardDirs::findAllExe( QStringList& list, const QString& appname,
00740 const QString& pstr, bool ignore )
00741 {
00742 QString p = pstr;
00743 QFileInfo info;
00744 QStringList tokens;
00745
00746 if( p == QString::null ) {
00747 p = getenv( "PATH" );
00748 }
00749
00750 list.clear();
00751 tokenize( tokens, p, ":\b" );
00752
00753 for ( unsigned i = 0; i < tokens.count(); i++ ) {
00754 p = tokens[ i ];
00755 p += "/";
00756 p += appname;
00757
00758 info.setFile( p );
00759
00760 if( info.exists() && (ignore || info.isExecutable())
00761 && info.isFile() ) {
00762 list.append( p );
00763 }
00764
00765 }
00766
00767 return list.count();
00768 }
00769
00770 static int tokenize( QStringList& tokens, const QString& str,
00771 const QString& delim )
00772 {
00773 int len = str.length();
00774 QString token = "";
00775
00776 for( int index = 0; index < len; index++)
00777 {
00778 if ( delim.find( str[ index ] ) >= 0 )
00779 {
00780 tokens.append( token );
00781 token = "";
00782 }
00783 else
00784 {
00785 token += str[ index ];
00786 }
00787 }
00788 if ( token.length() > 0 )
00789 {
00790 tokens.append( token );
00791 }
00792
00793 return tokens.count();
00794 }
00795
00796 QString KStandardDirs::kde_default(const char *type) {
00797 if (!strcmp(type, "data"))
00798 return "share/apps/";
00799 if (!strcmp(type, "html"))
00800 return "share/doc/HTML/";
00801 if (!strcmp(type, "icon"))
00802 return "share/icons/";
00803 if (!strcmp(type, "config"))
00804 return "share/config/";
00805 if (!strcmp(type, "pixmap"))
00806 return "share/pixmaps/";
00807 if (!strcmp(type, "apps"))
00808 return "share/applnk/";
00809 if (!strcmp(type, "sound"))
00810 return "share/sounds/";
00811 if (!strcmp(type, "locale"))
00812 return "share/locale/";
00813 if (!strcmp(type, "services"))
00814 return "share/services/";
00815 if (!strcmp(type, "servicetypes"))
00816 return "share/servicetypes/";
00817 if (!strcmp(type, "mime"))
00818 return "share/mimelnk/";
00819 if (!strcmp(type, "cgi"))
00820 return "cgi-bin/";
00821 if (!strcmp(type, "wallpaper"))
00822 return "share/wallpapers/";
00823 if (!strcmp(type, "templates"))
00824 return "share/templates/";
00825 if (!strcmp(type, "exe"))
00826 return "bin/";
00827 if (!strcmp(type, "lib"))
00828 return "lib/";
00829 if (!strcmp(type, "module"))
00830 return "lib/kde3/";
00831 if (!strcmp(type, "qtplugins"))
00832 return "lib/kde3/plugins";
00833 qFatal("unknown resource type %s", type);
00834 return QString::null;
00835 }
00836
00837 QString KStandardDirs::saveLocation(const char *type,
00838 const QString& suffix,
00839 bool create) const
00840 {
00841 checkConfig();
00842
00843 QString *pPath = savelocations.find(type);
00844 if (!pPath)
00845 {
00846 QStringList *dirs = relatives.find(type);
00847 if (!dirs && ((strcmp(type, "socket") == 0) || (strcmp(type, "tmp") == 0)))
00848 {
00849 (void) resourceDirs(type);
00850 dirs = relatives.find(type);
00851 }
00852 if (dirs)
00853 {
00854
00855 pPath = new QString(realPath(localkdedir() + dirs->last()));
00856 }
00857 else {
00858 dirs = absolutes.find(type);
00859 if (!dirs)
00860 qFatal("KStandardDirs: The resource type %s is not registered", type);
00861 pPath = new QString(realPath(dirs->last()));
00862 }
00863
00864 savelocations.insert(type, pPath);
00865 }
00866 QString fullPath = *pPath + suffix;
00867
00868 struct stat st;
00869 if (stat(QFile::encodeName(fullPath), &st) != 0 || !(S_ISDIR(st.st_mode))) {
00870 if(!create) {
00871 #ifndef NDEBUG
00872 qDebug("save location %s doesn't exist", fullPath.latin1());
00873 #endif
00874 return localkdedir()+suffix;
00875 }
00876 if(!makeDir(fullPath, 0700)) {
00877 qWarning("failed to create %s", fullPath.latin1());
00878 return localkdedir()+suffix;
00879 }
00880 dircache.remove(type);
00881 }
00882 return fullPath;
00883 }
00884
00885 QString KStandardDirs::relativeLocation(const char *type, const QString &absPath)
00886 {
00887 QString fullPath = absPath;
00888 int i = absPath.findRev('/');
00889 if (i != -1)
00890 {
00891 fullPath = realPath(absPath.left(i+1))+absPath.mid(i+1);
00892 }
00893
00894 QStringList candidates = resourceDirs(type);
00895
00896 for (QStringList::ConstIterator it = candidates.begin();
00897 it != candidates.end(); it++)
00898 if (fullPath.startsWith(*it))
00899 {
00900 return fullPath.mid((*it).length());
00901 }
00902
00903 return absPath;
00904 }
00905
00906
00907 bool KStandardDirs::makeDir(const QString& dir, int mode)
00908 {
00909
00910 if (dir.at(0) != '/')
00911 return false;
00912
00913 QString target = dir;
00914 uint len = target.length();
00915
00916
00917 if (dir.at(len - 1) != '/')
00918 target += '/';
00919
00920 QString base("");
00921 uint i = 1;
00922
00923 while( i < len )
00924 {
00925 struct stat st;
00926 int pos = target.find('/', i);
00927 base += target.mid(i - 1, pos - i + 1);
00928 QCString baseEncoded = QFile::encodeName(base);
00929
00930 if (stat(baseEncoded, &st) != 0)
00931 {
00932
00933
00934 if (lstat(baseEncoded, &st) == 0)
00935 (void)unlink(baseEncoded);
00936
00937 if ( mkdir(baseEncoded, (mode_t) mode) != 0) {
00938 perror("trying to create local folder");
00939 return false;
00940 }
00941 }
00942 i = pos + 1;
00943 }
00944 return true;
00945 }
00946
00947 static QString readEnvPath(const char *env)
00948 {
00949 QCString c_path = getenv(env);
00950 if (c_path.isEmpty())
00951 return QString::null;
00952 return QFile::decodeName(c_path);
00953 }
00954
00955 static void fixHomeDir(QString &dir)
00956 {
00957 if (dir[0] == '~')
00958 {
00959 dir = QDir::homeDirPath() + dir.mid(1);
00960 }
00961 }
00962
00963 void KStandardDirs::addKDEDefaults()
00964 {
00965 QStringList kdedirList;
00966
00967 QString kdedirs = readEnvPath("KDEDIRS");
00968 if (!kdedirs.isEmpty())
00969 {
00970 tokenize(kdedirList, kdedirs, ":");
00971 }
00972 else
00973 {
00974 QString kdedir = readEnvPath("KDEDIR");
00975 if (!kdedir.isEmpty())
00976 {
00977 fixHomeDir(kdedir);
00978 kdedirList.append(kdedir);
00979 }
00980 }
00981 kdedirList.append(KDEDIR);
00982
00983 #ifdef __KDE_EXECPREFIX
00984 QString execPrefix(__KDE_EXECPREFIX);
00985 if (execPrefix!="NONE")
00986 kdedirList.append(execPrefix);
00987 #endif
00988
00989 QString localKdeDir;
00990 if (getuid())
00991 {
00992 localKdeDir = readEnvPath("KDEHOME");
00993 if (!localKdeDir.isEmpty())
00994 {
00995 if (localKdeDir[localKdeDir.length()-1] != '/')
00996 localKdeDir += '/';
00997 }
00998 else
00999 {
01000 localKdeDir = QDir::homeDirPath() + "/.kde/";
01001 }
01002 }
01003 else
01004 {
01005
01006
01007 localKdeDir = readEnvPath("KDEROOTHOME");
01008 if (!localKdeDir.isEmpty())
01009 {
01010 if (localKdeDir[localKdeDir.length()-1] != '/')
01011 localKdeDir += '/';
01012 }
01013 else
01014 {
01015 struct passwd *pw = getpwuid(0);
01016 localKdeDir = QFile::decodeName((pw && pw->pw_dir) ? pw->pw_dir : "/root") + "/.kde/";
01017 }
01018
01019 }
01020
01021 if (localKdeDir != "-/")
01022 {
01023 fixHomeDir(localKdeDir);
01024 addPrefix(localKdeDir);
01025 }
01026
01027 for (QStringList::ConstIterator it = kdedirList.begin();
01028 it != kdedirList.end(); it++)
01029 {
01030 QString dir = *it;
01031 fixHomeDir(dir);
01032 addPrefix(dir);
01033 }
01034
01035 uint index = 0;
01036 while (types[index] != 0) {
01037 addResourceType(types[index], kde_default(types[index]));
01038 index++;
01039 }
01040
01041 QString dir = QString("%1share/cache/").arg(localKdeDir);
01042 addResourceDir("cache", dir);
01043
01044 addResourceDir("home", QDir::homeDirPath());
01045 }
01046
01047 void KStandardDirs::checkConfig() const
01048 {
01049 if (!addedCustoms && KGlobal::_instance && KGlobal::_instance->_config)
01050 const_cast<KStandardDirs*>(this)->addCustomized(KGlobal::_instance->_config);
01051 }
01052
01053 bool KStandardDirs::addCustomized(KConfig *config)
01054 {
01055 if (addedCustoms)
01056 return false;
01057
01058
01059
01060 uint configdirs = resourceDirs("config").count();
01061
01062
01063 QString oldGroup = config->group();
01064 config->setGroup("Directories");
01065
01066 QStringList list;
01067 QStringList::ConstIterator it;
01068 list = config->readListEntry("prefixes");
01069 for (it = list.begin(); it != list.end(); it++)
01070 addPrefix(*it);
01071
01072
01073
01074 QMap<QString, QString> entries = config->entryMap("Directories");
01075
01076 QMap<QString, QString>::ConstIterator it2;
01077 for (it2 = entries.begin(); it2 != entries.end(); it2++)
01078 {
01079 QString key = it2.key();
01080 if (key.left(4) == "dir_") {
01081
01082 QStringList dirs = QStringList::split(',',
01083 *it2);
01084 QStringList::Iterator sIt(dirs.begin());
01085 QString resType = key.mid(4, key.length());
01086 for (; sIt != dirs.end(); ++sIt) {
01087 addResourceDir(resType.latin1(), *sIt);
01088 }
01089 }
01090 }
01091
01092
01093 config->setGroup("KDE Resource Restrictions");
01094 entries = config->entryMap("KDE Resource Restrictions");
01095 for (it2 = entries.begin(); it2 != entries.end(); it2++)
01096 {
01097 QString key = it2.key();
01098 if (!config->readBoolEntry(key, true))
01099 {
01100 if (!d)
01101 {
01102 d = new KStandardDirsPrivate;
01103 d->restrictionsActive = true;
01104 }
01105 d->restrictions.insert(key.latin1(), &d->restrictionsActive);
01106 dircache.remove(key.latin1());
01107 }
01108 }
01109
01110
01111 addedCustoms = true;
01112 config->setGroup(oldGroup);
01113
01114
01115 return (resourceDirs("config").count() != configdirs);
01116 }
01117
01118 QString KStandardDirs::localkdedir() const
01119 {
01120
01121 return prefixes.first();
01122 }
01123
01124
01125 QString locate( const char *type,
01126 const QString& filename, const KInstance* inst )
01127 {
01128 return inst->dirs()->findResource(type, filename);
01129 }
01130
01131 QString locateLocal( const char *type,
01132 const QString& filename, const KInstance* inst )
01133 {
01134
01135
01136 int slash = filename.findRev('/')+1;
01137 if (!slash)
01138 return inst->dirs()->saveLocation(type) + filename;
01139
01140
01141 QString dir = filename.left(slash);
01142 QString file = filename.mid(slash);
01143 return inst->dirs()->saveLocation(type, dir) + file;
01144 }