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 QStringList KStandardDirs::resourceDirs(const char *type) const
00541 {
00542 QStringList *candidates = dircache.find(type);
00543
00544 if (!candidates) {
00545 if (strcmp(type, "socket") == 0)
00546 {
00547 char hostname[256];
00548 hostname[0] = 0;
00549 gethostname(hostname, 255);
00550 QString dir = QString("%1socket-%2").arg(localkdedir()).arg(hostname);
00551 char link[1024];
00552 link[1023] = 0;
00553 int result = readlink(QFile::encodeName(dir).data(), link, 1023);
00554 if ((result == -1) && (errno == ENOENT))
00555 {
00556 QString srv = findExe(QString::fromLatin1("lnusertemp"), KDEDIR+QString::fromLatin1("/bin"));
00557 if (srv.isEmpty())
00558 srv = findExe(QString::fromLatin1("lnusertemp"));
00559 if (!srv.isEmpty())
00560 {
00561 system(QFile::encodeName(srv)+" socket");
00562 result = readlink(QFile::encodeName(dir).data(), link, 1023);
00563 }
00564 }
00565 if (result > 0)
00566 {
00567 link[result] = 0;
00568 if (link[0] == '/')
00569 dir = QFile::decodeName(link);
00570 else
00571 dir = QDir::cleanDirPath(dir+QFile::decodeName(link));
00572 }
00573 const_cast<KStandardDirs *>(this)->addResourceDir("socket", dir+'/');
00574 }
00575 if (strcmp(type, "tmp") == 0)
00576 {
00577 char hostname[256];
00578 hostname[0] = 0;
00579 gethostname(hostname, 255);
00580 QString dir = QString("%1tmp-%2").arg(localkdedir()).arg(hostname);
00581 char link[1024];
00582 link[1023] = 0;
00583 int result = readlink(QFile::encodeName(dir).data(), link, 1023);
00584 if ((result == -1) && (errno == ENOENT))
00585 {
00586 QString srv = findExe(QString::fromLatin1("lnusertemp"), KDEDIR+QString::fromLatin1("/bin"));
00587 if (srv.isEmpty())
00588 srv = findExe(QString::fromLatin1("lnusertemp"));
00589 if (!srv.isEmpty())
00590 {
00591 system(QFile::encodeName(srv)+" tmp");
00592 result = readlink(QFile::encodeName(dir).data(), link, 1023);
00593 }
00594 }
00595 if (result > 0)
00596 {
00597 link[result] = 0;
00598 if (link[0] == '/')
00599 dir = QFile::decodeName(link);
00600 else
00601 dir = QDir::cleanDirPath(dir+QFile::decodeName(link));
00602 }
00603 const_cast<KStandardDirs *>(this)->addResourceDir("tmp", dir+'/');
00604 }
00605 QDir testdir;
00606
00607 candidates = new QStringList();
00608 QStringList *dirs;
00609
00610 bool restrictionActive = false;
00611 if (d && d->restrictionsActive)
00612 {
00613 if (d->dataRestrictionActive)
00614 restrictionActive = true;
00615 else if (d->restrictions["all"])
00616 restrictionActive = true;
00617 else if (d->restrictions[type])
00618 restrictionActive = true;
00619 d->dataRestrictionActive = false;
00620 }
00621
00622 dirs = relatives.find(type);
00623 if (dirs)
00624 {
00625 bool local = true;
00626 for (QStringList::ConstIterator pit = prefixes.begin();
00627 pit != prefixes.end();
00628 pit++)
00629 {
00630 for (QStringList::ConstIterator it = dirs->begin();
00631 it != dirs->end(); ++it) {
00632 QString path = realPath(*pit + *it);
00633 testdir.setPath(path);
00634 if (local && restrictionActive)
00635 continue;
00636 if ((local || testdir.exists()) && !candidates->contains(path))
00637 candidates->append(path);
00638 }
00639 local = false;
00640 }
00641 }
00642 dirs = absolutes.find(type);
00643 if (dirs)
00644 for (QStringList::ConstIterator it = dirs->begin();
00645 it != dirs->end(); ++it)
00646 {
00647 testdir.setPath(*it);
00648 if (testdir.exists())
00649 {
00650 QString filename = realPath(*it);
00651 if (!candidates->contains(filename))
00652 candidates->append(filename);
00653 }
00654 }
00655 dircache.insert(type, candidates);
00656 }
00657
00658 #if 0
00659 kdDebug() << "found dirs for resource " << type << ":" << endl;
00660 for (QStringList::ConstIterator pit = candidates->begin();
00661 pit != candidates->end();
00662 pit++)
00663 {
00664 fprintf(stderr, "%s\n", (*pit).latin1());
00665 }
00666 #endif
00667
00668
00669 return *candidates;
00670 }
00671
00672 QString KStandardDirs::findExe( const QString& appname,
00673 const QString& pstr, bool ignore)
00674 {
00675 QFileInfo info;
00676
00677
00678 if (appname.startsWith(QString::fromLatin1("/")))
00679 {
00680 info.setFile( appname );
00681 if( info.exists() && ( ignore || info.isExecutable() )
00682 && info.isFile() ) {
00683 return appname;
00684 }
00685 return QString::null;
00686 }
00687
00688 QString p = QString("%1/%2").arg(__KDE_BINDIR).arg(appname);
00689 info.setFile( p );
00690 if( info.exists() && ( ignore || info.isExecutable() )
00691 && ( info.isFile() || info.isSymLink() ) ) {
00692 return p;
00693 }
00694
00695 QStringList tokens;
00696 p = pstr;
00697
00698 if( p == QString::null ) {
00699 p = getenv( "PATH" );
00700 }
00701
00702 tokenize( tokens, p, ":\b" );
00703
00704
00705 for( unsigned i = 0; i < tokens.count(); i++ ) {
00706 p = tokens[ i ];
00707
00708 if ( p[ 0 ] == '~' )
00709 {
00710 int len = p.find( '/' );
00711 if ( len == -1 )
00712 len = p.length();
00713 if ( len == 1 )
00714 p.replace( 0, 1, QDir::homeDirPath() );
00715 else
00716 {
00717 QString user = p.mid( 1, len - 1 );
00718 struct passwd *dir = getpwnam( user.local8Bit().data() );
00719 if ( dir && strlen( dir->pw_dir ) )
00720 p.replace( 0, len, QString::fromLocal8Bit( dir->pw_dir ) );
00721 }
00722 }
00723
00724 p += "/";
00725 p += appname;
00726
00727
00728 info.setFile( p );
00729
00730 if( info.exists() && ( ignore || info.isExecutable() )
00731 && ( info.isFile() || info.isSymLink() ) ) {
00732 return p;
00733 }
00734 }
00735
00736
00737
00738
00739 return QString::null;
00740 }
00741
00742 int KStandardDirs::findAllExe( QStringList& list, const QString& appname,
00743 const QString& pstr, bool ignore )
00744 {
00745 QString p = pstr;
00746 QFileInfo info;
00747 QStringList tokens;
00748
00749 if( p == QString::null ) {
00750 p = getenv( "PATH" );
00751 }
00752
00753 list.clear();
00754 tokenize( tokens, p, ":\b" );
00755
00756 for ( unsigned i = 0; i < tokens.count(); i++ ) {
00757 p = tokens[ i ];
00758 p += "/";
00759 p += appname;
00760
00761 info.setFile( p );
00762
00763 if( info.exists() && (ignore || info.isExecutable())
00764 && info.isFile() ) {
00765 list.append( p );
00766 }
00767
00768 }
00769
00770 return list.count();
00771 }
00772
00773 static int tokenize( QStringList& tokens, const QString& str,
00774 const QString& delim )
00775 {
00776 int len = str.length();
00777 QString token = "";
00778
00779 for( int index = 0; index < len; index++)
00780 {
00781 if ( delim.find( str[ index ] ) >= 0 )
00782 {
00783 tokens.append( token );
00784 token = "";
00785 }
00786 else
00787 {
00788 token += str[ index ];
00789 }
00790 }
00791 if ( token.length() > 0 )
00792 {
00793 tokens.append( token );
00794 }
00795
00796 return tokens.count();
00797 }
00798
00799 QString KStandardDirs::kde_default(const char *type) {
00800 if (!strcmp(type, "data"))
00801 return "share/apps/";
00802 if (!strcmp(type, "html"))
00803 return "share/doc/HTML/";
00804 if (!strcmp(type, "icon"))
00805 return "share/icons/";
00806 if (!strcmp(type, "config"))
00807 return "share/config/";
00808 if (!strcmp(type, "pixmap"))
00809 return "share/pixmaps/";
00810 if (!strcmp(type, "apps"))
00811 return "share/applnk/";
00812 if (!strcmp(type, "sound"))
00813 return "share/sounds/";
00814 if (!strcmp(type, "locale"))
00815 return "share/locale/";
00816 if (!strcmp(type, "services"))
00817 return "share/services/";
00818 if (!strcmp(type, "servicetypes"))
00819 return "share/servicetypes/";
00820 if (!strcmp(type, "mime"))
00821 return "share/mimelnk/";
00822 if (!strcmp(type, "cgi"))
00823 return "cgi-bin/";
00824 if (!strcmp(type, "wallpaper"))
00825 return "share/wallpapers/";
00826 if (!strcmp(type, "templates"))
00827 return "share/templates/";
00828 if (!strcmp(type, "exe"))
00829 return "bin/";
00830 if (!strcmp(type, "lib"))
00831 return "lib/";
00832 if (!strcmp(type, "module"))
00833 return "lib/kde3/";
00834 if (!strcmp(type, "qtplugins"))
00835 return "lib/kde3/plugins";
00836 qFatal("unknown resource type %s", type);
00837 return QString::null;
00838 }
00839
00840 QString KStandardDirs::saveLocation(const char *type,
00841 const QString& suffix,
00842 bool create) const
00843 {
00844 checkConfig();
00845
00846 QString *pPath = savelocations.find(type);
00847 if (!pPath)
00848 {
00849 QStringList *dirs = relatives.find(type);
00850 if (!dirs && ((strcmp(type, "socket") == 0) || (strcmp(type, "tmp") == 0)))
00851 {
00852 (void) resourceDirs(type);
00853 dirs = relatives.find(type);
00854 }
00855 if (dirs)
00856 {
00857
00858 pPath = new QString(realPath(localkdedir() + dirs->last()));
00859 }
00860 else {
00861 dirs = absolutes.find(type);
00862 if (!dirs)
00863 qFatal("KStandardDirs: The resource type %s is not registered", type);
00864 pPath = new QString(realPath(dirs->last()));
00865 }
00866
00867 savelocations.insert(type, pPath);
00868 }
00869 QString fullPath = *pPath + suffix;
00870
00871 struct stat st;
00872 if (stat(QFile::encodeName(fullPath), &st) != 0 || !(S_ISDIR(st.st_mode))) {
00873 if(!create) {
00874 #ifndef NDEBUG
00875 qDebug("save location %s doesn't exist", fullPath.latin1());
00876 #endif
00877 return localkdedir()+suffix;
00878 }
00879 if(!makeDir(fullPath, 0700)) {
00880 qWarning("failed to create %s", fullPath.latin1());
00881 return localkdedir()+suffix;
00882 }
00883 dircache.remove(type);
00884 }
00885 return fullPath;
00886 }
00887
00888 QString KStandardDirs::relativeLocation(const char *type, const QString &absPath)
00889 {
00890 QString fullPath = absPath;
00891 int i = absPath.findRev('/');
00892 if (i != -1)
00893 {
00894 fullPath = realPath(absPath.left(i+1))+absPath.mid(i+1);
00895 }
00896
00897 QStringList candidates = resourceDirs(type);
00898
00899 for (QStringList::ConstIterator it = candidates.begin();
00900 it != candidates.end(); it++)
00901 if (fullPath.startsWith(*it))
00902 {
00903 return fullPath.mid((*it).length());
00904 }
00905
00906 return absPath;
00907 }
00908
00909
00910 bool KStandardDirs::makeDir(const QString& dir, int mode)
00911 {
00912
00913 if (dir.at(0) != '/')
00914 return false;
00915
00916 QString target = dir;
00917 uint len = target.length();
00918
00919
00920 if (dir.at(len - 1) != '/')
00921 target += '/';
00922
00923 QString base("");
00924 uint i = 1;
00925
00926 while( i < len )
00927 {
00928 struct stat st;
00929 int pos = target.find('/', i);
00930 base += target.mid(i - 1, pos - i + 1);
00931 QCString baseEncoded = QFile::encodeName(base);
00932
00933 if (stat(baseEncoded, &st) != 0)
00934 {
00935
00936
00937 if (lstat(baseEncoded, &st) == 0)
00938 (void)unlink(baseEncoded);
00939
00940 if ( mkdir(baseEncoded, (mode_t) mode) != 0) {
00941 perror("trying to create local folder");
00942 return false;
00943 }
00944 }
00945 i = pos + 1;
00946 }
00947 return true;
00948 }
00949
00950 static QString readEnvPath(const char *env)
00951 {
00952 QCString c_path = getenv(env);
00953 if (c_path.isEmpty())
00954 return QString::null;
00955 return QFile::decodeName(c_path);
00956 }
00957
00958 static void fixHomeDir(QString &dir)
00959 {
00960 if (dir[0] == '~')
00961 {
00962 dir = QDir::homeDirPath() + dir.mid(1);
00963 }
00964 }
00965
00966 void KStandardDirs::addKDEDefaults()
00967 {
00968 QStringList kdedirList;
00969
00970 QString kdedirs = readEnvPath("KDEDIRS");
00971 if (!kdedirs.isEmpty())
00972 {
00973 tokenize(kdedirList, kdedirs, ":");
00974 }
00975 else
00976 {
00977 QString kdedir = readEnvPath("KDEDIR");
00978 if (!kdedir.isEmpty())
00979 {
00980 fixHomeDir(kdedir);
00981 kdedirList.append(kdedir);
00982 }
00983 }
00984 kdedirList.append(KDEDIR);
00985
00986 #ifdef __KDE_EXECPREFIX
00987 QString execPrefix(__KDE_EXECPREFIX);
00988 if (execPrefix!="NONE")
00989 kdedirList.append(execPrefix);
00990 #endif
00991
00992 QString localKdeDir;
00993 if (getuid())
00994 {
00995 localKdeDir = readEnvPath("KDEHOME");
00996 if (!localKdeDir.isEmpty())
00997 {
00998 if (localKdeDir[localKdeDir.length()-1] != '/')
00999 localKdeDir += '/';
01000 }
01001 else
01002 {
01003 localKdeDir = QDir::homeDirPath() + "/.kde/";
01004 }
01005 }
01006 else
01007 {
01008
01009
01010 localKdeDir = readEnvPath("KDEROOTHOME");
01011 if (!localKdeDir.isEmpty())
01012 {
01013 if (localKdeDir[localKdeDir.length()-1] != '/')
01014 localKdeDir += '/';
01015 }
01016 else
01017 {
01018 struct passwd *pw = getpwuid(0);
01019 localKdeDir = QFile::decodeName((pw && pw->pw_dir) ? pw->pw_dir : "/root") + "/.kde/";
01020 }
01021
01022 }
01023
01024 if (localKdeDir != "-/")
01025 {
01026 fixHomeDir(localKdeDir);
01027 addPrefix(localKdeDir);
01028 }
01029
01030 for (QStringList::ConstIterator it = kdedirList.begin();
01031 it != kdedirList.end(); it++)
01032 {
01033 QString dir = *it;
01034 fixHomeDir(dir);
01035 addPrefix(dir);
01036 }
01037
01038 uint index = 0;
01039 while (types[index] != 0) {
01040 addResourceType(types[index], kde_default(types[index]));
01041 index++;
01042 }
01043
01044 QString dir = QString("%1share/cache/").arg(localKdeDir);
01045 addResourceDir("cache", dir);
01046
01047 addResourceDir("home", QDir::homeDirPath());
01048 }
01049
01050 void KStandardDirs::checkConfig() const
01051 {
01052 if (!addedCustoms && KGlobal::_instance && KGlobal::_instance->_config)
01053 const_cast<KStandardDirs*>(this)->addCustomized(KGlobal::_instance->_config);
01054 }
01055
01056 bool KStandardDirs::addCustomized(KConfig *config)
01057 {
01058 if (addedCustoms)
01059 return false;
01060
01061
01062
01063 uint configdirs = resourceDirs("config").count();
01064
01065
01066 QString oldGroup = config->group();
01067 config->setGroup("Directories");
01068
01069 QStringList list;
01070 QStringList::ConstIterator it;
01071 list = config->readListEntry("prefixes");
01072 for (it = list.begin(); it != list.end(); it++)
01073 addPrefix(*it);
01074
01075
01076
01077 QMap<QString, QString> entries = config->entryMap("Directories");
01078
01079 QMap<QString, QString>::ConstIterator it2;
01080 for (it2 = entries.begin(); it2 != entries.end(); it2++)
01081 {
01082 QString key = it2.key();
01083 if (key.left(4) == "dir_") {
01084
01085 QStringList dirs = QStringList::split(',',
01086 *it2);
01087 QStringList::Iterator sIt(dirs.begin());
01088 QString resType = key.mid(4, key.length());
01089 for (; sIt != dirs.end(); ++sIt) {
01090 addResourceDir(resType.latin1(), *sIt);
01091 }
01092 }
01093 }
01094
01095
01096 config->setGroup("KDE Resource Restrictions");
01097 entries = config->entryMap("KDE Resource Restrictions");
01098 for (it2 = entries.begin(); it2 != entries.end(); it2++)
01099 {
01100 QString key = it2.key();
01101 if (!config->readBoolEntry(key, true))
01102 {
01103 if (!d)
01104 {
01105 d = new KStandardDirsPrivate;
01106 d->restrictionsActive = true;
01107 }
01108 d->restrictions.insert(key.latin1(), &d->restrictionsActive);
01109 dircache.remove(key.latin1());
01110 }
01111 }
01112
01113
01114 addedCustoms = true;
01115 config->setGroup(oldGroup);
01116
01117
01118 return (resourceDirs("config").count() != configdirs);
01119 }
01120
01121 QString KStandardDirs::localkdedir() const
01122 {
01123
01124 return prefixes.first();
01125 }
01126
01127
01128 QString locate( const char *type,
01129 const QString& filename, const KInstance* inst )
01130 {
01131 return inst->dirs()->findResource(type, filename);
01132 }
01133
01134 QString locateLocal( const char *type,
01135 const QString& filename, const KInstance* inst )
01136 {
01137
01138
01139 int slash = filename.findRev('/')+1;
01140 if (!slash)
01141 return inst->dirs()->saveLocation(type) + filename;
01142
01143
01144 QString dir = filename.left(slash);
01145 QString file = filename.mid(slash);
01146 return inst->dirs()->saveLocation(type, dir) + file;
01147 }