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 #include "kstandarddirs.h"
00027 #include "kconfig.h"
00028 #include "kconfiggroup.h"
00029 #include "kdebug.h"
00030 #include "kcomponentdata.h"
00031 #include "kshell.h"
00032 #include "kuser.h"
00033 #include "kde_file.h"
00034 #include "kkernel_win.h"
00035 #include "kkernel_mac.h"
00036 #include "klocale.h"
00037
00038 #include <config.h>
00039 #include <config-prefix.h>
00040 #include <config-kstandarddirs.h>
00041
00042 #include <stdlib.h>
00043 #include <assert.h>
00044 #include <errno.h>
00045 #ifdef HAVE_SYS_STAT_H
00046 #include <sys/stat.h>
00047 #endif
00048 #ifdef HAVE_UNISTD_H
00049 #include <unistd.h>
00050 #endif
00051 #include <sys/param.h>
00052 #include <sys/types.h>
00053 #include <dirent.h>
00054 #include <pwd.h>
00055 #include <grp.h>
00056 #ifdef Q_WS_WIN
00057 #include <windows.h>
00058 #define _WIN32_IE 0x0500
00059 #include <shlobj.h>
00060 #endif
00061
00062 #include <QtCore/QRegExp>
00063 #include <QtCore/QDir>
00064 #include <QtCore/QFileInfo>
00065 #include <QtCore/QSettings>
00066 #include <QtCore/QCharRef>
00067 #include <QtCore/QMutableStringListIterator>
00068
00069 class KStandardDirs::KStandardDirsPrivate
00070 {
00071 public:
00072 KStandardDirsPrivate()
00073 : restrictionsActive(false),
00074 dataRestrictionActive(false),
00075 checkRestrictions(true)
00076 { }
00077
00078 bool restrictionsActive : 1;
00079 bool dataRestrictionActive : 1;
00080 bool checkRestrictions : 1;
00081 QMap<QByteArray, bool> restrictions;
00082 QStringList xdgdata_prefixes;
00083 QStringList xdgconf_prefixes;
00084
00085 QStringList prefixes;
00086
00087
00088 QMap<QByteArray, QStringList> absolutes;
00089 QMap<QByteArray, QStringList> relatives;
00090
00091 mutable QMap<QByteArray, QStringList> dircache;
00092 mutable QMap<QByteArray, QString> savelocations;
00093 };
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154 static const char types_string[] =
00155 "data\0"
00156 "share/apps\0"
00157 "html\0"
00158 "share/doc/HTML\0"
00159 "icon\0"
00160 "share/icons\0"
00161 "config\0"
00162 "share/config\0"
00163 "pixmap\0"
00164 "share/pixmaps\0"
00165 "apps\0"
00166 "share/applnk\0"
00167 "sound\0"
00168 "share/sounds\0"
00169 "locale\0"
00170 "share/locale\0"
00171 "services\0"
00172 "share/kde4/services\0"
00173 "servicetypes\0"
00174 "share/kde4/servicetypes\0"
00175 "mime\0"
00176 "share/mimelnk\0"
00177 "cgi\0"
00178 "cgi-bin\0"
00179 "wallpaper\0"
00180 "share/wallpapers\0"
00181 "templates\0"
00182 "share/templates\0"
00183 "exe\0"
00184 "bin\0"
00185 "module\0"
00186 "%lib/kde4\0"
00187 "qtplugins\0"
00188 "%lib/kde4/plugins\0"
00189 "kcfg\0"
00190 "share/config.kcfg\0"
00191 "emoticons\0"
00192 "share/emoticons\0"
00193 "xdgdata-apps\0"
00194 "applications\0"
00195 "xdgdata-icon\0"
00196 "icons\0"
00197 "xdgdata-pixmap\0"
00198 "pixmaps\0"
00199 "xdgdata-dirs\0"
00200 "desktop-directories\0"
00201 "xdgdata-mime\0"
00202 "xdgconf-menu\0"
00203 "menus\0"
00204 "\0";
00205
00206 static const int types_indices[] = {
00207 0, 5, 16, 21, 36, 41, 53, 60,
00208 73, 80, 94, 99, 112, 118, 131, 138,
00209 151, 160, 180, 193, 217, 222, 236, 240,
00210 248, 258, 275, 285, 301, 305, 309, 316,
00211 326, 336, 354, 359, 377, 387, 403, 416,
00212 429, 442, 448, 463, 471, 484, 504, 217,
00213 517, 530, -1
00214 };
00215
00216 static int tokenize( QStringList& token, const QString& str,
00217 const QString& delim );
00218
00219 KStandardDirs::KStandardDirs()
00220 : d(new KStandardDirsPrivate())
00221 {
00222 addKDEDefaults();
00223 }
00224
00225 KStandardDirs::~KStandardDirs()
00226 {
00227 delete d;
00228 }
00229
00230 bool KStandardDirs::isRestrictedResource(const char *type, const QString& relPath) const
00231 {
00232 if (!d->restrictionsActive)
00233 return false;
00234
00235 if (d->restrictions.value(type, false))
00236 return true;
00237
00238 if (strcmp(type, "data")==0)
00239 {
00240 applyDataRestrictions(relPath);
00241 if (d->dataRestrictionActive)
00242 {
00243 d->dataRestrictionActive = false;
00244 return true;
00245 }
00246 }
00247 return false;
00248 }
00249
00250 void KStandardDirs::applyDataRestrictions(const QString &relPath) const
00251 {
00252 QString key;
00253 int i = relPath.indexOf('/');
00254 if (i != -1)
00255 key = "data_"+relPath.left(i);
00256 else
00257 key = "data_"+relPath;
00258
00259 if (d->restrictions.value(key.toLatin1(), false))
00260 d->dataRestrictionActive = true;
00261 }
00262
00263
00264 QStringList KStandardDirs::allTypes() const
00265 {
00266 QStringList list;
00267 for (int i = 0; types_indices[i] != -1; i += 2)
00268 list.append(QLatin1String(types_string + types_indices[i]));
00269
00270 list.append("lib");
00271
00272
00273
00274 list.append("socket");
00275 list.append("tmp");
00276 list.append("cache");
00277
00278 list.append("include");
00279
00280
00281
00282 return list;
00283 }
00284
00285 static void priorityAdd(QStringList &prefixes, const QString& dir, bool priority)
00286 {
00287 if (priority && !prefixes.isEmpty())
00288 {
00289
00290 QStringList::iterator it = prefixes.begin();
00291 it++;
00292 prefixes.insert(it, dir);
00293 }
00294 else
00295 {
00296 prefixes.append(dir);
00297 }
00298 }
00299
00300 void KStandardDirs::addPrefix( const QString& _dir )
00301 {
00302 addPrefix(_dir, false);
00303 }
00304
00305 void KStandardDirs::addPrefix( const QString& _dir, bool priority )
00306 {
00307 if (_dir.isEmpty())
00308 return;
00309
00310 QString dir = _dir;
00311 if (dir.at(dir.length() - 1) != '/')
00312 dir += '/';
00313
00314 if (!d->prefixes.contains(dir)) {
00315 priorityAdd(d->prefixes, dir, priority);
00316 d->dircache.clear();
00317 }
00318 }
00319
00320 void KStandardDirs::addXdgConfigPrefix( const QString& _dir )
00321 {
00322 addXdgConfigPrefix(_dir, false);
00323 }
00324
00325 void KStandardDirs::addXdgConfigPrefix( const QString& _dir, bool priority )
00326 {
00327 if (_dir.isEmpty())
00328 return;
00329
00330 QString dir = _dir;
00331 if (dir.at(dir.length() - 1) != '/')
00332 dir += '/';
00333
00334 if (!d->xdgconf_prefixes.contains(dir)) {
00335 priorityAdd(d->xdgconf_prefixes, dir, priority);
00336 d->dircache.clear();
00337 }
00338 }
00339
00340 void KStandardDirs::addXdgDataPrefix( const QString& _dir )
00341 {
00342 addXdgDataPrefix(_dir, false);
00343 }
00344
00345 void KStandardDirs::addXdgDataPrefix( const QString& _dir, bool priority )
00346 {
00347 if (_dir.isEmpty())
00348 return;
00349
00350 QString dir = _dir;
00351 if (dir.at(dir.length() - 1) != '/')
00352 dir += '/';
00353
00354 if (!d->xdgdata_prefixes.contains(dir)) {
00355 priorityAdd(d->xdgdata_prefixes, dir, priority);
00356 d->dircache.clear();
00357 }
00358 }
00359
00360 QString KStandardDirs::kfsstnd_prefixes()
00361 {
00362 return d->prefixes.join(QString(QChar(KPATH_SEPARATOR)));
00363 }
00364
00365 QString KStandardDirs::kfsstnd_xdg_conf_prefixes()
00366 {
00367 return d->xdgconf_prefixes.join(QString(QChar(KPATH_SEPARATOR)));
00368 }
00369
00370 QString KStandardDirs::kfsstnd_xdg_data_prefixes()
00371 {
00372 return d->xdgdata_prefixes.join(QString(QChar(KPATH_SEPARATOR)));
00373 }
00374
00375 bool KStandardDirs::addResourceType( const char *type,
00376 const QString& relativename,
00377 bool priority )
00378 {
00379 return addResourceType( type, 0, relativename, priority);
00380 }
00381
00382 bool KStandardDirs::addResourceType( const char *type,
00383 const char *basetype,
00384 const QString& relativename,
00385 bool priority )
00386 {
00387 if (relativename.isEmpty())
00388 return false;
00389
00390 QString copy = relativename;
00391 if (basetype)
00392 copy = QString('%') + basetype + '/' + relativename;
00393
00394 if (copy.at(copy.length() - 1) != '/')
00395 copy += '/';
00396
00397 QStringList& rels = d->relatives[type];
00398
00399 if (!rels.contains(copy)) {
00400 if (priority)
00401 rels.prepend(copy);
00402 else
00403 rels.append(copy);
00404 d->dircache.remove(type);
00405 return true;
00406 }
00407 return false;
00408 }
00409
00410 bool KStandardDirs::addResourceDir( const char *type,
00411 const QString& absdir,
00412 bool priority)
00413 {
00414 if (absdir.isEmpty() || !type)
00415 return false;
00416
00417 QString copy = absdir;
00418 if (copy.at(copy.length() - 1) != '/')
00419 copy += '/';
00420
00421 QStringList &paths = d->absolutes[type];
00422 if (!paths.contains(copy)) {
00423 if (priority)
00424 paths.prepend(copy);
00425 else
00426 paths.append(copy);
00427 d->dircache.remove(type);
00428 return true;
00429 }
00430 return false;
00431 }
00432
00433 QString KStandardDirs::findResource( const char *type,
00434 const QString& _filename ) const
00435 {
00436 if (!QDir::isRelativePath(_filename))
00437 return !KGlobal::hasLocale() ? _filename
00438 : KGlobal::locale()->localizedFilePath(_filename);
00439
00440 #if 0
00441 kDebug(180) << "Find resource: " << type;
00442 for (QStringList::ConstIterator pit = prefixes.begin();
00443 pit != prefixes.end();
00444 ++pit)
00445 {
00446 kDebug(180) << "Prefix: " << *pit;
00447 }
00448 #endif
00449
00450 QString filename(_filename);
00451 #ifdef Q_OS_WIN
00452 if(strcmp(type, "exe") == 0) {
00453 if(!filename.endsWith(QLatin1String(".exe")))
00454 filename += QLatin1String(".exe");
00455 }
00456 #endif
00457 const QString dir = findResourceDir(type, filename);
00458 if (dir.isEmpty())
00459 return dir;
00460 else
00461 return !KGlobal::hasLocale() ? dir + filename
00462 : KGlobal::locale()->localizedFilePath(dir + filename);
00463 }
00464
00465 static quint32 updateHash(const QString &file, quint32 hash)
00466 {
00467 QByteArray cFile = QFile::encodeName(file);
00468 KDE_struct_stat buff;
00469 if ((access(cFile, R_OK) == 0) && (KDE_stat(cFile, &buff) == 0) && (S_ISREG(buff.st_mode))) {
00470 hash = hash + static_cast<quint32>(buff.st_ctime);
00471 }
00472 return hash;
00473 }
00474
00475 quint32 KStandardDirs::calcResourceHash( const char *type,
00476 const QString& filename,
00477 SearchOptions options ) const
00478 {
00479 quint32 hash = 0;
00480
00481 if (!QDir::isRelativePath(filename))
00482 {
00483
00484 return updateHash(filename, hash);
00485 }
00486 if (d->restrictionsActive && (strcmp(type, "data")==0))
00487 applyDataRestrictions(filename);
00488 QStringList candidates = resourceDirs(type);
00489 QString fullPath;
00490
00491 foreach ( const QString& candidate, candidates )
00492 {
00493 hash = updateHash(candidate + filename, hash);
00494 if ( !( options & Recursive ) && hash ) {
00495 return hash;
00496 }
00497 }
00498 return hash;
00499 }
00500
00501
00502 QStringList KStandardDirs::findDirs( const char *type,
00503 const QString& reldir ) const
00504 {
00505 QDir testdir;
00506 QStringList list;
00507 if (!QDir::isRelativePath(reldir))
00508 {
00509 testdir.setPath(reldir);
00510 if (testdir.exists())
00511 {
00512 if (reldir.endsWith('/'))
00513 list.append(reldir);
00514 else
00515 list.append(reldir+'/');
00516 }
00517 return list;
00518 }
00519
00520 if (d->restrictionsActive && (strcmp(type, "data")==0))
00521 applyDataRestrictions(reldir);
00522 const QStringList candidates = resourceDirs(type);
00523
00524 for (QStringList::ConstIterator it = candidates.begin();
00525 it != candidates.end(); ++it) {
00526 testdir.setPath(*it + reldir);
00527 if (testdir.exists())
00528 list.append(testdir.absolutePath() + '/');
00529 }
00530
00531 return list;
00532 }
00533
00534 QString KStandardDirs::findResourceDir( const char *type,
00535 const QString& _filename) const
00536 {
00537 #ifndef NDEBUG
00538 if (_filename.isEmpty()) {
00539 kWarning() << "filename for type " << type << " in KStandardDirs::findResourceDir is not supposed to be empty!!";
00540 return QString();
00541 }
00542 #endif
00543
00544 QString filename(_filename);
00545 #ifdef Q_OS_WIN
00546 if(strcmp(type, "exe") == 0) {
00547 if(!filename.endsWith(QLatin1String(".exe")))
00548 filename += QLatin1String(".exe");
00549 }
00550 #endif
00551 if (d->restrictionsActive && (strcmp(type, "data")==0))
00552 applyDataRestrictions(filename);
00553 const QStringList candidates = resourceDirs(type);
00554 QString fullPath;
00555
00556 for (QStringList::ConstIterator it = candidates.begin();
00557 it != candidates.end(); ++it) {
00558 if (exists(*it + filename)) {
00559 return *it;
00560 }
00561 }
00562
00563 #ifndef NDEBUG
00564 if(false && strcmp(type, "locale"))
00565 kDebug(180) << "KStdDirs::findResDir(): can't find \"" << filename << "\" in type \"" << type << "\".";
00566 #endif
00567
00568 return QString();
00569 }
00570
00571 bool KStandardDirs::exists(const QString &fullPath)
00572 {
00573 #ifdef Q_OS_WIN
00574
00575
00576
00577 if (fullPath.endsWith('/'))
00578 return QDir(fullPath).exists();
00579 return QFileInfo(fullPath).exists();
00580 #else
00581 KDE_struct_stat buff;
00582 QByteArray cFullPath = QFile::encodeName(fullPath);
00583 if (access(cFullPath, R_OK) == 0 && KDE_stat( cFullPath, &buff ) == 0) {
00584 if (!fullPath.endsWith('/')) {
00585 if (S_ISREG( buff.st_mode ))
00586 return true;
00587 } else
00588 if (S_ISDIR( buff.st_mode ))
00589 return true;
00590 }
00591 return false;
00592 #endif
00593 }
00594
00595 static void lookupDirectory(const QString& path, const QString &relPart,
00596 const QRegExp ®exp,
00597 QStringList& list,
00598 QStringList& relList,
00599 bool recursive, bool unique)
00600 {
00601 const QString pattern = regexp.pattern();
00602 if (recursive || pattern.contains('?') || pattern.contains('*'))
00603 {
00604 if (path.isEmpty())
00605 return;
00606
00607 DIR *dp = opendir( QFile::encodeName(path));
00608 if (!dp)
00609 return;
00610
00611 #ifdef Q_WS_WIN
00612 assert(path.at(path.length() - 1) == '/' || path.at(path.length() - 1) == '\\');
00613 #else
00614 assert(path.at(path.length() - 1) == '/');
00615 #endif
00616
00617 struct dirent *ep;
00618
00619 while( ( ep = readdir( dp ) ) != 0L )
00620 {
00621 QString fn( QFile::decodeName(ep->d_name));
00622 if (fn == "." || fn == ".." || fn.at(fn.length() - 1).toLatin1() == '~')
00623 continue;
00624
00625 if (!recursive && !regexp.exactMatch(fn))
00626 continue;
00627
00628 bool isDir;
00629 bool isReg;
00630
00631 QString pathfn = path + fn;
00632 #ifdef HAVE_DIRENT_D_TYPE
00633 isDir = ep->d_type == DT_DIR;
00634 isReg = ep->d_type == DT_REG;
00635
00636 if (ep->d_type == DT_UNKNOWN || ep->d_type == DT_LNK)
00637 #endif
00638 {
00639 KDE_struct_stat buff;
00640 if ( KDE_stat( QFile::encodeName(pathfn), &buff ) != 0 ) {
00641 kDebug(180) << "Error stat'ing " << pathfn << " : " << perror;
00642 continue;
00643 }
00644 isReg = S_ISREG (buff.st_mode);
00645 isDir = S_ISDIR (buff.st_mode);
00646 }
00647
00648 if ( recursive ) {
00649 if ( isDir ) {
00650 lookupDirectory(pathfn + '/', relPart + fn + '/', regexp, list, relList, recursive, unique);
00651 }
00652 if (!regexp.exactMatch(fn))
00653 continue;
00654 }
00655 if ( isReg )
00656 {
00657 if (!unique || !relList.contains(relPart + fn))
00658 {
00659 list.append( pathfn );
00660 relList.append( relPart + fn );
00661 }
00662 }
00663 }
00664 closedir( dp );
00665 }
00666 else
00667 {
00668
00669 QString fn = pattern;
00670 QString pathfn = path + fn;
00671 KDE_struct_stat buff;
00672 if ( KDE_stat( QFile::encodeName(pathfn), &buff ) != 0 )
00673 return;
00674 if ( S_ISREG( buff.st_mode))
00675 {
00676 if (!unique || !relList.contains(relPart + fn))
00677 {
00678 list.append( pathfn );
00679 relList.append( relPart + fn );
00680 }
00681 }
00682 }
00683 }
00684
00685 static void lookupPrefix(const QString& prefix, const QString& relpath,
00686 const QString& relPart,
00687 const QRegExp ®exp,
00688 QStringList& list,
00689 QStringList& relList,
00690 bool recursive, bool unique)
00691 {
00692 if (relpath.isEmpty()) {
00693 if (recursive)
00694 Q_ASSERT(prefix != "/");
00695 lookupDirectory(prefix, relPart, regexp, list,
00696 relList, recursive, unique);
00697 return;
00698 }
00699 QString path;
00700 QString rest;
00701
00702 int slash = relpath.indexOf('/');
00703 if (slash < 0)
00704 rest = relpath.left(relpath.length() - 1);
00705 else {
00706 path = relpath.left(slash);
00707 rest = relpath.mid(slash + 1);
00708 }
00709
00710 if (prefix.isEmpty())
00711 return;
00712 #ifdef Q_WS_WIN
00713 assert(prefix.at(prefix.length() - 1) == '/' || prefix.at(prefix.length() - 1) == '\\');
00714 #else
00715 assert(prefix.at(prefix.length() - 1) == '/');
00716 #endif
00717 if (path.contains('*') || path.contains('?')) {
00718
00719 QRegExp pathExp(path, Qt::CaseSensitive, QRegExp::Wildcard);
00720 DIR *dp = opendir( QFile::encodeName(prefix) );
00721 if (!dp) {
00722 return;
00723 }
00724
00725 struct dirent *ep;
00726
00727 while( ( ep = readdir( dp ) ) != 0L )
00728 {
00729 QString fn( QFile::decodeName(ep->d_name));
00730 if (fn == "." || fn == ".." || fn.at(fn.length() - 1) == '~')
00731 continue;
00732
00733 if ( !pathExp.exactMatch(fn) )
00734 continue;
00735 QString rfn = relPart+fn;
00736 fn = prefix + fn;
00737
00738 bool isDir;
00739
00740 #ifdef HAVE_DIRENT_D_TYPE
00741 isDir = ep->d_type == DT_DIR;
00742
00743 if (ep->d_type == DT_UNKNOWN || ep->d_type == DT_LNK)
00744 #endif
00745 {
00746 QString pathfn = path + fn;
00747 KDE_struct_stat buff;
00748 if ( KDE_stat( QFile::encodeName(fn), &buff ) != 0 ) {
00749 kDebug(180) << "Error stat'ing " << fn << " : " << perror;
00750 continue;
00751 }
00752 isDir = S_ISDIR (buff.st_mode);
00753 }
00754 if ( isDir )
00755 lookupPrefix(fn + '/', rest, rfn + '/', regexp, list, relList, recursive, unique);
00756 }
00757
00758 closedir( dp );
00759 } else {
00760
00761
00762 lookupPrefix(prefix + path + '/', rest,
00763 relPart + path + '/', regexp, list,
00764 relList, recursive, unique);
00765 }
00766 }
00767
00768 QStringList
00769 KStandardDirs::findAllResources( const char *type,
00770 const QString& filter,
00771 SearchOptions options,
00772 QStringList &relList) const
00773 {
00774 QString filterPath;
00775 QString filterFile;
00776
00777 if ( !filter.isEmpty() )
00778 {
00779 int slash = filter.lastIndexOf('/');
00780 if (slash < 0) {
00781 filterFile = filter;
00782 } else {
00783 filterPath = filter.left(slash + 1);
00784 filterFile = filter.mid(slash + 1);
00785 }
00786 }
00787
00788 QStringList candidates;
00789 if ( !QDir::isRelativePath(filter) )
00790 {
00791 #ifdef Q_OS_WIN
00792 candidates << filterPath.left(3);
00793 filterPath = filterPath.mid(3);
00794 #else
00795 candidates << "/";
00796 filterPath = filterPath.mid(1);
00797 #endif
00798 }
00799 else
00800 {
00801 if (d->restrictionsActive && (strcmp(type, "data")==0)) {
00802 applyDataRestrictions(filter);
00803 }
00804 candidates = resourceDirs(type);
00805 }
00806
00807 if (filterFile.isEmpty()) {
00808 filterFile = "*";
00809 }
00810
00811 QRegExp regExp(filterFile, Qt::CaseSensitive, QRegExp::Wildcard);
00812
00813 QStringList list;
00814 foreach ( const QString& candidate, candidates )
00815 {
00816 lookupPrefix(candidate, filterPath, "", regExp, list,
00817 relList, options & Recursive, options & NoDuplicates);
00818 }
00819
00820 return list;
00821 }
00822
00823 QStringList
00824 KStandardDirs::findAllResources( const char *type,
00825 const QString& filter,
00826 SearchOptions options ) const
00827 {
00828 QStringList relList;
00829 return findAllResources(type, filter, options, relList);
00830 }
00831
00832
00833
00834
00835
00836
00837 QString
00838 KStandardDirs::realPath(const QString &dirname)
00839 {
00840 char realpath_buffer[MAXPATHLEN + 1];
00841 memset(realpath_buffer, 0, MAXPATHLEN + 1);
00842
00843
00844 if (realpath( QFile::encodeName(dirname).constData(), realpath_buffer) != 0) {
00845
00846 int len = strlen(realpath_buffer);
00847 realpath_buffer[len] = '/';
00848 realpath_buffer[len+1] = 0;
00849 return QFile::decodeName(realpath_buffer);
00850 }
00851
00852 if ( !dirname.endsWith('/') )
00853 return dirname + '/';
00854 return dirname;
00855 }
00856
00857
00858
00859
00860
00861
00862 QString
00863 KStandardDirs::realFilePath(const QString &filename)
00864 {
00865 char realpath_buffer[MAXPATHLEN + 1];
00866 memset(realpath_buffer, 0, MAXPATHLEN + 1);
00867
00868
00869 if (realpath( QFile::encodeName(filename).constData(), realpath_buffer) != 0) {
00870
00871 return QFile::decodeName(realpath_buffer);
00872 }
00873
00874 return filename;
00875 }
00876
00877
00878 void KStandardDirs::createSpecialResource(const char *type)
00879 {
00880 char hostname[256];
00881 hostname[0] = 0;
00882 gethostname(hostname, 255);
00883 QString dir = QString("%1%2-%3").arg(localkdedir()).arg(type).arg(hostname);
00884 char link[1024];
00885 link[1023] = 0;
00886 int result = readlink(QFile::encodeName(dir).constData(), link, 1023);
00887 bool relink = (result == -1) && (errno == ENOENT);
00888 if (result > 0)
00889 {
00890 link[result] = 0;
00891 if (!QDir::isRelativePath(link))
00892 {
00893 KDE_struct_stat stat_buf;
00894 int res = KDE_lstat(link, &stat_buf);
00895 if ((res == -1) && (errno == ENOENT))
00896 {
00897 relink = true;
00898 }
00899 else if ((res == -1) || (!S_ISDIR(stat_buf.st_mode)))
00900 {
00901 fprintf(stderr, "Error: \"%s\" is not a directory.\n", link);
00902 relink = true;
00903 }
00904 else if (stat_buf.st_uid != getuid())
00905 {
00906 fprintf(stderr, "Error: \"%s\" is owned by uid %d instead of uid %d.\n", link, stat_buf.st_uid, getuid());
00907 relink = true;
00908 }
00909 }
00910 }
00911 #ifdef Q_WS_WIN
00912 if (relink)
00913 {
00914 if (!makeDir(dir, 0700))
00915 fprintf(stderr, "failed to create \"%s\"", qPrintable(dir));
00916 else
00917 result = readlink(QFile::encodeName(dir).data(), link, 1023);
00918 }
00919 #else //UNIX
00920 if (relink)
00921 {
00922 QString srv = findExe(QLatin1String("lnusertemp"), installPath("libexec"));
00923 if (srv.isEmpty())
00924 srv = findExe(QLatin1String("lnusertemp"));
00925 if (!srv.isEmpty())
00926 {
00927 if (system(QFile::encodeName(srv) + ' ' + type) == -1) {
00928 fprintf(stderr, "Error: unable to launch lnusertemp command" );
00929 }
00930 result = readlink(QFile::encodeName(dir).constData(), link, 1023);
00931 }
00932 }
00933 if (result > 0)
00934 {
00935 link[result] = 0;
00936 if (link[0] == '/')
00937 dir = QFile::decodeName(link);
00938 else
00939 dir = QDir::cleanPath(dir+QFile::decodeName(link));
00940 }
00941 #endif
00942 addResourceDir(type, dir+'/', false);
00943 }
00944
00945 QStringList KStandardDirs::resourceDirs(const char *type) const
00946 {
00947 QMap<QByteArray, QStringList>::const_iterator dirCacheIt = d->dircache.constFind(type);
00948
00949 QStringList candidates;
00950
00951 if (dirCacheIt != d->dircache.constEnd())
00952 {
00953 candidates = *dirCacheIt;
00954 }
00955 else
00956 {
00957 if (strcmp(type, "socket") == 0)
00958 const_cast<KStandardDirs *>(this)->createSpecialResource(type);
00959 else if (strcmp(type, "tmp") == 0)
00960 const_cast<KStandardDirs *>(this)->createSpecialResource(type);
00961 else if (strcmp(type, "cache") == 0)
00962 const_cast<KStandardDirs *>(this)->createSpecialResource(type);
00963
00964 QDir testdir;
00965
00966 bool restrictionActive = false;
00967 if (d->restrictionsActive)
00968 {
00969 if (d->dataRestrictionActive)
00970 restrictionActive = true;
00971 else if (d->restrictions.value("all", false))
00972 restrictionActive = true;
00973 else if (d->restrictions.value(type, false))
00974 restrictionActive = true;
00975 d->dataRestrictionActive = false;
00976 }
00977
00978 QStringList dirs;
00979 dirs = d->relatives.value(type);
00980 QString installdir = installPath( type );
00981 QString installprefix = installPath("kdedir");
00982
00983 if (!dirs.isEmpty())
00984 {
00985 bool local = true;
00986
00987 for (QStringList::ConstIterator it = dirs.constBegin();
00988 it != dirs.constEnd(); ++it)
00989 {
00990 if ( (*it).startsWith('%'))
00991 {
00992
00993 QString rel = (*it).mid(1, (*it).indexOf('/') - 1);
00994 QString rest = (*it).mid((*it).indexOf('/') + 1);
00995 const QStringList basedirs = resourceDirs(rel.toUtf8().constData());
00996 for (QStringList::ConstIterator it2 = basedirs.begin();
00997 it2 != basedirs.end(); ++it2)
00998 {
00999 QString path = realPath( *it2 + rest );
01000 testdir.setPath(path);
01001 if ((local || testdir.exists()) && !candidates.contains(path))
01002 candidates.append(path);
01003 local = false;
01004 }
01005 }
01006 }
01007
01008 const QStringList *prefixList = 0;
01009 if (strncmp(type, "xdgdata-", 8) == 0)
01010 prefixList = &(d->xdgdata_prefixes);
01011 else if (strncmp(type, "xdgconf-", 8) == 0)
01012 prefixList = &(d->xdgconf_prefixes);
01013 else
01014 prefixList = &d->prefixes;
01015
01016 for (QStringList::ConstIterator pit = prefixList->begin();
01017 pit != prefixList->end();
01018 ++pit)
01019 {
01020 if((*pit)!=installprefix||installdir.isEmpty())
01021 {
01022 for (QStringList::ConstIterator it = dirs.constBegin();
01023 it != dirs.constEnd(); ++it)
01024 {
01025 if ( (*it).startsWith('%'))
01026 continue;
01027 QString path = realPath( *pit + *it );
01028 testdir.setPath(path);
01029 if (local && restrictionActive)
01030 continue;
01031 if ((local || testdir.exists()) && !candidates.contains(path))
01032 candidates.append(path);
01033 }
01034 local = false;
01035 }
01036 else
01037 {
01038
01039 testdir.setPath(installdir);
01040 if(testdir.exists() && ! candidates.contains(installdir))
01041 candidates.append(installdir);
01042 }
01043 }
01044 }
01045
01046
01047 if (!installdir.isEmpty()) {
01048 bool ok = true;
01049 foreach (const QString &s, candidates) {
01050 if (installdir.startsWith(s)) {
01051 ok = false;
01052 break;
01053 }
01054 }
01055 if (ok)
01056 candidates.append(installdir);
01057 }
01058
01059 dirs = d->absolutes.value(type);
01060 if (!dirs.isEmpty())
01061 for (QStringList::ConstIterator it = dirs.constBegin();
01062 it != dirs.constEnd(); ++it)
01063 {
01064 testdir.setPath(*it);
01065 if (testdir.exists()) {
01066 QString filename = realPath( *it );
01067 if (!candidates.contains(filename)) {
01068 candidates.append(filename);
01069 }
01070 }
01071 }
01072
01073 d->dircache.insert(type, candidates);
01074 }
01075
01076 #if 0
01077 kDebug(180) << "found dirs for resource " << type << ":";
01078 for (QStringList::ConstIterator pit = candidates.begin();
01079 pit != candidates.end();
01080 ++pit)
01081 {
01082 fprintf(stderr, "%s\n", qPrintable(*pit));
01083 }
01084 #endif
01085
01086 return candidates;
01087 }
01088
01089 QStringList KStandardDirs::systemPaths( const QString& pstr )
01090 {
01091 QStringList tokens;
01092 QString p = pstr;
01093
01094 if( p.isEmpty() )
01095 {
01096 p = QString::fromLocal8Bit( qgetenv( "PATH" ) );
01097 }
01098
01099 QString delimiters(QChar(KPATH_SEPARATOR));
01100 delimiters += "\b";
01101 tokenize( tokens, p, delimiters );
01102
01103 QStringList exePaths;
01104
01105
01106 for( int i = 0; i < tokens.count(); i++ )
01107 {
01108 exePaths << KShell::tildeExpand( tokens[ i ] );
01109 }
01110
01111 return exePaths;
01112 }
01113
01114 #ifdef Q_WS_MAC
01115 static QString getBundle( const QString& path, bool ignore )
01116 {
01117 kDebug(180) << "getBundle(" << path << ", " << ignore << ") called";
01118 QFileInfo info;
01119 QString bundle = path;
01120 bundle += ".app/Contents/MacOS/" + bundle.section('/', -1);
01121 info.setFile( bundle );
01122 if ( info.exists() && ( ignore || info.isExecutable() )
01123 && ( info.isFile() || info.isSymLink() ) ) {
01124 kDebug(180) << "getBundle(): returning " << bundle;
01125 return bundle;
01126 }
01127 return QString();
01128 }
01129 #endif
01130
01131 static QString checkExecutable( const QString& path, bool ignoreExecBit )
01132 {
01133 #ifdef Q_WS_MAC
01134 QString bundle = getBundle( path, ignoreExecBit );
01135 if ( !bundle.isEmpty() ) {
01136
01137 return bundle;
01138 }
01139 #endif
01140 QFileInfo info( path );
01141 QFileInfo orig = info;
01142 if( info.exists() && info.isSymLink() )
01143 info = QFileInfo( info.canonicalFilePath() );
01144 if( info.exists() && ( ignoreExecBit || info.isExecutable() ) && info.isFile() ) {
01145
01146
01147
01148 orig.makeAbsolute();
01149 return orig.filePath();
01150 }
01151
01152 return QString();
01153 }
01154
01155 QString KStandardDirs::findExe( const QString& appname,
01156 const QString& pstr,
01157 SearchOptions options )
01158 {
01159
01160
01161 #ifdef Q_WS_WIN
01162 QString real_appname = appname + ".exe";
01163 #else
01164 QString real_appname = appname;
01165 #endif
01166 QFileInfo info;
01167
01168
01169 if (real_appname.contains(QDir::separator()))
01170 {
01171
01172 QString path = checkExecutable(real_appname, options & IgnoreExecBit);
01173 return path;
01174 }
01175
01176
01177
01178
01179
01180 QString p = installPath("libexec") + real_appname;
01181 QString result = checkExecutable(p, options & IgnoreExecBit);
01182 if (!result.isEmpty()) {
01183
01184 return result;
01185 }
01186
01187 p = installPath("exe") + real_appname;
01188 result = checkExecutable(p, options & IgnoreExecBit);
01189 if (!result.isEmpty()) {
01190
01191 return result;
01192 }
01193
01194
01195 const QStringList exePaths = systemPaths( pstr );
01196 for (QStringList::ConstIterator it = exePaths.begin(); it != exePaths.end(); ++it)
01197 {
01198 p = (*it) + '/';
01199 p += real_appname;
01200
01201
01202 result = checkExecutable(p, options & IgnoreExecBit);
01203 if (!result.isEmpty()) {
01204
01205 return result;
01206 }
01207 }
01208
01209
01210
01211
01212
01213 return QString();
01214 }
01215
01216 int KStandardDirs::findAllExe( QStringList& list, const QString& appname,
01217 const QString& pstr, SearchOptions options )
01218 {
01219 #ifdef Q_WS_WIN
01220 QString real_appname = appname + ".exe";
01221 #else
01222 QString real_appname = appname;
01223 #endif
01224 QFileInfo info;
01225 QString p;
01226 list.clear();
01227
01228 const QStringList exePaths = systemPaths( pstr );
01229 for (QStringList::ConstIterator it = exePaths.begin(); it != exePaths.end(); ++it)
01230 {
01231 p = (*it) + '/';
01232 p += real_appname;
01233
01234 #ifdef Q_WS_MAC
01235 QString bundle = getBundle( p, (options & IgnoreExecBit) );
01236 if ( !bundle.isEmpty() ) {
01237
01238 list.append( bundle );
01239 }
01240 #endif
01241
01242 info.setFile( p );
01243
01244 if( info.exists() && ( ( options & IgnoreExecBit ) || info.isExecutable())
01245 && info.isFile() ) {
01246 list.append( p );
01247 }
01248 }
01249
01250 return list.count();
01251 }
01252
01253 static inline QString equalizePath(QString &str)
01254 {
01255 #ifdef Q_WS_WIN
01256
01257
01258 QFileInfo f(str);
01259 if (f.isAbsolute())
01260 return f.absoluteFilePath();
01261 else
01262 #endif
01263 return str;
01264 }
01265
01266 static int tokenize( QStringList& tokens, const QString& str,
01267 const QString& delim )
01268 {
01269 int len = str.length();
01270 QString token;
01271
01272 for( int index = 0; index < len; index++)
01273 {
01274 if ( delim.contains( str[ index ] ) )
01275 {
01276 tokens.append( equalizePath(token) );
01277 token.clear();
01278 }
01279 else
01280 {
01281 token += str[ index ];
01282 }
01283 }
01284 if ( !token.isEmpty() )
01285 {
01286 tokens.append( equalizePath(token) );
01287 }
01288
01289 return tokens.count();
01290 }
01291
01292 QString KStandardDirs::kde_default(const char *type)
01293 {
01294 return QString('%') + type + '/';
01295 }
01296
01297 QString KStandardDirs::saveLocation(const char *type,
01298 const QString& suffix,
01299 bool create) const
01300 {
01301 QString path = d->savelocations.value(type);
01302 if (path.isEmpty())
01303 {
01304 QStringList dirs = d->relatives.value(type);
01305 if (dirs.isEmpty() && (
01306 (strcmp(type, "socket") == 0) ||
01307 (strcmp(type, "tmp") == 0) ||
01308 (strcmp(type, "cache") == 0) ))
01309 {
01310 (void) resourceDirs(type);
01311 dirs = d->relatives.value(type);
01312 }
01313 if (!dirs.isEmpty())
01314 {
01315 path = dirs.last();
01316
01317 if ( path.startsWith('%'))
01318 {
01319
01320 QString rel = path.mid(1, path.indexOf('/') - 1);
01321 QString rest = path.mid(path.indexOf('/') + 1);
01322 QString basepath = saveLocation(rel.toUtf8().constData());
01323 path = basepath + rest;
01324 } else
01325
01326
01327 if (strncmp(type, "xdgdata-", 8) == 0) {
01328 path = realPath( localxdgdatadir() + path ) ;
01329 } else if (strncmp(type, "xdgconf-", 8) == 0) {
01330 path = realPath( localxdgconfdir() + path );
01331 } else {
01332 path = realPath( localkdedir() + path );
01333 }
01334 }
01335 else {
01336 dirs = d->absolutes.value(type);
01337 if (dirs.isEmpty()) {
01338 qFatal("KStandardDirs: The resource type %s is not registered", type);
01339 }
01340 path = realPath(dirs.last());
01341 }
01342
01343 d->savelocations.insert(type, path.endsWith('/') ? path : path + '/');
01344 }
01345 QString fullPath = path + suffix;
01346
01347 KDE_struct_stat st;
01348 if (KDE_stat(QFile::encodeName(fullPath), &st) != 0 || !(S_ISDIR(st.st_mode))) {
01349 if(!create) {
01350 #ifndef NDEBUG
01351
01352
01353
01354 #endif
01355 return fullPath;
01356 }
01357 if(!makeDir(fullPath, 0700)) {
01358 return fullPath;
01359 }
01360 d->dircache.remove(type);
01361 }
01362 if (!fullPath.endsWith('/'))
01363 fullPath += '/';
01364 return fullPath;
01365 }
01366
01367 QString KStandardDirs::relativeLocation(const char *type, const QString &absPath)
01368 {
01369 QString fullPath = absPath;
01370 int i = absPath.lastIndexOf('/');
01371 if (i != -1) {
01372 fullPath = realFilePath(absPath);
01373 }
01374
01375 const QStringList candidates = resourceDirs(type);
01376
01377 for (QStringList::ConstIterator it = candidates.begin();
01378 it != candidates.end(); ++it) {
01379 if (fullPath.startsWith(*it)) {
01380 return fullPath.mid((*it).length());
01381 }
01382 }
01383 return absPath;
01384 }
01385
01386
01387 bool KStandardDirs::makeDir(const QString& dir, int mode)
01388 {
01389
01390 if (QDir::isRelativePath(dir))
01391 return false;
01392
01393 QString target = dir;
01394 uint len = target.length();
01395
01396
01397 if (dir.at(len - 1) != '/')
01398 target += '/';
01399
01400 QString base;
01401 uint i = 1;
01402
01403 while( i < len )
01404 {
01405 KDE_struct_stat st;
01406 int pos = target.indexOf('/', i);
01407 base += target.mid(i - 1, pos - i + 1);
01408 QByteArray baseEncoded = QFile::encodeName(base);
01409
01410 if (KDE_stat(baseEncoded, &st) != 0)
01411 {
01412
01413
01414 if (KDE_lstat(baseEncoded, &st) == 0)
01415 (void)unlink(baseEncoded);
01416
01417 if (KDE_mkdir(baseEncoded, static_cast<mode_t>(mode)) != 0) {
01418 baseEncoded.prepend( "trying to create local folder " );
01419 perror(baseEncoded.constData());
01420 return false;
01421 }
01422 }
01423 i = pos + 1;
01424 }
01425 return true;
01426 }
01427
01428 static QString readEnvPath(const char *env)
01429 {
01430 QByteArray c_path = qgetenv(env);
01431 if (c_path.isEmpty())
01432 return QString();
01433 return QDir::fromNativeSeparators(QFile::decodeName(c_path));
01434 }
01435
01436 #ifdef __linux__
01437 static QString executablePrefix()
01438 {
01439 char path_buffer[MAXPATHLEN + 1];
01440 path_buffer[MAXPATHLEN] = 0;
01441 int length = readlink ("/proc/self/exe", path_buffer, MAXPATHLEN);
01442 if (length == -1)
01443 return QString();
01444
01445 path_buffer[length] = '\0';
01446
01447 QString path = QFile::decodeName(path_buffer);
01448
01449 if(path.isEmpty())
01450 return QString();
01451
01452 int pos = path.lastIndexOf('/');
01453 if(pos <= 0)
01454 return QString();
01455 pos = path.lastIndexOf('/', pos - 1);
01456 if(pos <= 0)
01457 return QString();
01458
01459 return path.left(pos);
01460 }
01461 #endif
01462
01463 void KStandardDirs::addResourcesFrom_krcdirs()
01464 {
01465 QString localFile = QDir::currentPath() + QDir::separator() + ".krcdirs";
01466 if (!QFile::exists(localFile))
01467 return;
01468
01469 QSettings iniFile(localFile, QSettings::IniFormat);
01470 iniFile.beginGroup("KStandardDirs");
01471 const QStringList resources = iniFile.allKeys();
01472 foreach(const QString &key, resources)
01473 {
01474 QDir path(iniFile.value(key).toString());
01475 if (!path.exists())
01476 continue;
01477
01478 if(path.makeAbsolute())
01479 addResourceDir(key.toAscii(), path.path(), false);
01480 }
01481 }
01482
01483 void KStandardDirs::addKDEDefaults()
01484 {
01485 addResourcesFrom_krcdirs();
01486
01487 QStringList kdedirList;
01488
01489
01490 QString kdedirs = readEnvPath("KDEDIRS");
01491 if (!kdedirs.isEmpty())
01492 {
01493 tokenize(kdedirList, kdedirs, QString(QChar(KPATH_SEPARATOR)));
01494 }
01495 kdedirList.append(installPath("kdedir"));
01496
01497 QString execPrefix(EXEC_INSTALL_PREFIX);
01498 if (!execPrefix.isEmpty() && !kdedirList.contains(execPrefix))
01499 kdedirList.append(execPrefix);
01500 #ifdef __linux__
01501 const QString linuxExecPrefix = executablePrefix();
01502 if ( !linuxExecPrefix.isEmpty() )
01503 kdedirList.append( linuxExecPrefix );
01504 #endif
01505
01506
01507
01508 QString localKdeDir = readEnvPath(getuid() ? "KDEHOME" : "KDEROOTHOME");
01509 if (!localKdeDir.isEmpty())
01510 {
01511 if (localKdeDir[localKdeDir.length()-1] != '/')
01512 localKdeDir += '/';
01513 }
01514 else
01515 {
01516 #if defined(Q_WS_MACX)
01517 localKdeDir = QDir::homePath() + QLatin1String("/Library/Preferences/KDE/");
01518 #elif defined(Q_WS_WIN)
01519 WCHAR wPath[MAX_PATH+1];
01520 if ( SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, wPath) == S_OK) {
01521 localKdeDir = QDir::fromNativeSeparators(QString::fromUtf16((const ushort *) wPath)) + QLatin1Char('/') + KDE_DEFAULT_HOME + QLatin1Char('/');
01522 } else {
01523 localKdeDir = QDir::homePath() + QLatin1Char('/') + KDE_DEFAULT_HOME + QLatin1Char('/');
01524 }
01525 #else
01526 localKdeDir = QDir::homePath() + QLatin1Char('/') + KDE_DEFAULT_HOME + QLatin1Char('/');
01527 #endif
01528 }
01529
01530 if (localKdeDir != "-/")
01531 {
01532 localKdeDir = KShell::tildeExpand(localKdeDir);
01533 addPrefix(localKdeDir);
01534 }
01535
01536 #ifdef Q_WS_MACX
01537
01538
01539 QDir bundleDir(mac_app_filename());
01540 if (bundleDir.dirName() == "MacOS") {
01541 bundleDir.cdUp();
01542
01543
01544 addPrefix(bundleDir.absolutePath());
01545 }
01546 #endif
01547
01548 QStringList::ConstIterator end(kdedirList.end());
01549 for (QStringList::ConstIterator it = kdedirList.constBegin();
01550 it != kdedirList.constEnd(); ++it)
01551 {
01552 const QString dir = KShell::tildeExpand(*it);
01553 addPrefix(dir);
01554 }
01555
01556
01557
01558 QStringList xdgdirList;
01559 QString xdgdirs = readEnvPath("XDG_CONFIG_DIRS");
01560 if (!xdgdirs.isEmpty())
01561 {
01562 tokenize(xdgdirList, xdgdirs, QString(QChar(KPATH_SEPARATOR)));
01563 }
01564 else
01565 {
01566 xdgdirList.clear();
01567 xdgdirList.append("/etc/xdg");
01568 #ifdef Q_WS_WIN
01569 xdgdirList.append(installPath("kdedir") + "etc/xdg");
01570 #else
01571 xdgdirList.append(KDESYSCONFDIR "/xdg");
01572 #endif
01573 }
01574
01575 QString localXdgDir = readEnvPath("XDG_CONFIG_HOME");
01576 if (!localXdgDir.isEmpty())
01577 {
01578 if (localXdgDir[localXdgDir.length()-1] != '/')
01579 localXdgDir += '/';
01580 }
01581 else
01582 {
01583 #ifdef Q_WS_MACX
01584 localXdgDir = QDir::homePath() + "/Library/Preferences/XDG/";
01585 #else
01586 localXdgDir = QDir::homePath() + "/.config/";
01587 #endif
01588 }
01589
01590 localXdgDir = KShell::tildeExpand(localXdgDir);
01591 addXdgConfigPrefix(localXdgDir);
01592
01593 for (QStringList::ConstIterator it = xdgdirList.constBegin();
01594 it != xdgdirList.constEnd(); ++it)
01595 {
01596 QString dir = KShell::tildeExpand(*it);
01597 addXdgConfigPrefix(dir);
01598 }
01599
01600
01601
01602 QStringList kdedirDataDirs;
01603 for (QStringList::ConstIterator it = kdedirList.constBegin();
01604 it != kdedirList.constEnd(); ++it) {
01605 QString dir = *it;
01606 if (!dir.endsWith('/'))
01607 dir += '/';
01608 kdedirDataDirs.append(dir+"share/");
01609 }
01610
01611 xdgdirs = readEnvPath("XDG_DATA_DIRS");
01612 if (!xdgdirs.isEmpty()) {
01613 tokenize(xdgdirList, xdgdirs, QString(QChar(KPATH_SEPARATOR)));
01614
01615
01616
01617 Q_FOREACH(const QString& dir, kdedirDataDirs) {
01618 if (!xdgdirList.contains(dir))
01619 xdgdirList.append(dir);
01620 }
01621 } else {
01622 xdgdirList = kdedirDataDirs;
01623 #ifndef Q_WS_WIN
01624 xdgdirList.append("/usr/local/share/");
01625 xdgdirList.append("/usr/share/");
01626 #endif
01627 }
01628
01629 localXdgDir = readEnvPath("XDG_DATA_HOME");
01630 if (!localXdgDir.isEmpty())
01631 {
01632 if (localXdgDir[localXdgDir.length()-1] != '/')
01633 localXdgDir += '/';
01634 }
01635 else
01636 {
01637 localXdgDir = QDir::homePath() + "/.local/share/";
01638 }
01639
01640 localXdgDir = KShell::tildeExpand(localXdgDir);
01641 addXdgDataPrefix(localXdgDir);
01642
01643 for (QStringList::ConstIterator it = xdgdirList.constBegin();
01644 it != xdgdirList.constEnd(); ++it)
01645 {
01646 QString dir = KShell::tildeExpand(*it);
01647 addXdgDataPrefix(dir);
01648 }
01649
01650
01651
01652 addResourceType("lib", 0, "lib" KDELIBSUFF "/");
01653
01654 uint index = 0;
01655 while (types_indices[index] != -1) {
01656 addResourceType(types_string + types_indices[index], 0, types_string + types_indices[index+1], true);
01657 index+=2;
01658 }
01659 addResourceType("exe", "lib", "kde4/libexec", true );
01660
01661 addResourceDir("home", QDir::homePath(), false);
01662 }
01663
01664 static QStringList lookupProfiles(const QString &mapFile)
01665 {
01666 QStringList profiles;
01667
01668 if (mapFile.isEmpty() || !QFile::exists(mapFile))
01669 {
01670 profiles << "default";
01671 return profiles;
01672 }
01673
01674 struct passwd *pw = getpwuid(geteuid());
01675 if (!pw)
01676 {
01677 profiles << "default";
01678 return profiles;
01679 }
01680
01681 QByteArray user = pw->pw_name;
01682
01683 gid_t sup_gids[512];
01684 int sup_gids_nr = getgroups(512, sup_gids);
01685
01686 KConfig mapCfgFile(mapFile);
01687 KConfigGroup mapCfg(&mapCfgFile, "Users");
01688 if (mapCfg.hasKey(user.constData()))
01689 {
01690 profiles = mapCfg.readEntry(user.constData(), QStringList());
01691 return profiles;
01692 }
01693
01694 const KConfigGroup generalGrp(&mapCfgFile, "General");
01695 const QStringList groups = generalGrp.readEntry("groups", QStringList());
01696
01697 const KConfigGroup groupsGrp(&mapCfgFile, "Groups");
01698
01699 for( QStringList::ConstIterator it = groups.begin();
01700 it != groups.end(); ++it )
01701 {
01702 QByteArray grp = (*it).toUtf8();
01703
01704 struct group *grp_ent = getgrnam(grp);
01705 if (!grp_ent) continue;
01706 gid_t gid = grp_ent->gr_gid;
01707 if (pw->pw_gid == gid)
01708 {
01709
01710 profiles += groupsGrp.readEntry(*it, QStringList());
01711 }
01712 else
01713 {
01714 for(int i = 0; i < sup_gids_nr; i++)
01715 {
01716 if (sup_gids[i] == gid)
01717 {
01718
01719 profiles += groupsGrp.readEntry(*it, QStringList());
01720 break;
01721 }
01722 }
01723 }
01724 }
01725
01726 if (profiles.isEmpty())
01727 profiles << "default";
01728 return profiles;
01729 }
01730
01731 extern bool kde_kiosk_admin;
01732
01733 bool KStandardDirs::addCustomized(KConfig *config)
01734 {
01735 if (!d->checkRestrictions)
01736 return false;
01737
01738
01739
01740 int configdirs = resourceDirs("config").count();
01741
01742 if (true)
01743 {
01744
01745 QString group = QLatin1String("Directories");
01746 KConfigGroup cg(config, group);
01747
01748 QString kioskAdmin = cg.readEntry("kioskAdmin");
01749 if (!kioskAdmin.isEmpty() && !kde_kiosk_admin)
01750 {
01751 int i = kioskAdmin.indexOf(':');
01752 QString user = kioskAdmin.left(i);
01753 QString host = kioskAdmin.mid(i+1);
01754
01755 KUser thisUser;
01756 char hostname[ 256 ];
01757 hostname[ 0 ] = '\0';
01758 if (!gethostname( hostname, 255 ))
01759 hostname[sizeof(hostname)-1] = '\0';
01760
01761 if ((user == thisUser.loginName()) &&
01762 (host.isEmpty() || (host == hostname)))
01763 {
01764 kde_kiosk_admin = true;
01765 }
01766 }
01767
01768 bool readProfiles = true;
01769
01770 if (kde_kiosk_admin && !qgetenv("KDE_KIOSK_NO_PROFILES").isEmpty())
01771 readProfiles = false;
01772
01773 QString userMapFile = cg.readEntry("userProfileMapFile");
01774 QString profileDirsPrefix = cg.readEntry("profileDirsPrefix");
01775 if (!profileDirsPrefix.isEmpty() && !profileDirsPrefix.endsWith('/'))
01776 profileDirsPrefix.append("/");
01777
01778 QStringList profiles;
01779 if (readProfiles)
01780 profiles = lookupProfiles(userMapFile);
01781 QString profile;
01782
01783 bool priority = false;
01784 while(true)
01785 {
01786 KConfigGroup cg(config, group);
01787 const QStringList list = cg.readEntry("prefixes", QStringList());
01788 for (QStringList::ConstIterator it = list.begin(); it != list.end(); ++it)
01789 {
01790 addPrefix(*it, priority);
01791 addXdgConfigPrefix(*it+"/etc/xdg", priority);
01792 addXdgDataPrefix(*it+"/share", priority);
01793 }
01794
01795
01796 if (list.isEmpty() && !profile.isEmpty() && !profileDirsPrefix.isEmpty())
01797 {
01798 QString dir = profileDirsPrefix + profile;
01799 addPrefix(dir, priority);
01800 addXdgConfigPrefix(dir+"/etc/xdg", priority);
01801 addXdgDataPrefix(dir+"/share", priority);
01802 }
01803
01804
01805
01806 const QMap<QString, QString> entries = config->entryMap(group);
01807 for (QMap<QString, QString>::ConstIterator it2 = entries.begin();
01808 it2 != entries.end(); ++it2)
01809 {
01810 const QString key = it2.key();
01811 if (key.startsWith("dir_")) {
01812
01813 QStringList dirs = (*it2).split(',');
01814 QStringList::Iterator sIt(dirs.begin());
01815 QString resType = key.mid(4);
01816 for (; sIt != dirs.end(); ++sIt)
01817 {
01818 addResourceDir(resType.toLatin1(), *sIt, priority);
01819 }
01820 }
01821 }
01822 if (profiles.isEmpty())
01823 break;
01824 profile = profiles.back();
01825 group = QString::fromLatin1("Directories-%1").arg(profile);
01826 profiles.pop_back();
01827 priority = true;
01828 }
01829 }
01830
01831
01832 if (!kde_kiosk_admin || qgetenv("KDE_KIOSK_NO_RESTRICTIONS").isEmpty())
01833 {
01834 KConfigGroup cg(config, "KDE Resource Restrictions");
01835 const QMap<QString, QString> entries = cg.entryMap();
01836 for (QMap<QString, QString>::ConstIterator it2 = entries.begin();
01837 it2 != entries.end(); ++it2)
01838 {
01839 const QString key = it2.key();
01840 if (!cg.readEntry(key, true))
01841 {
01842 d->restrictionsActive = true;
01843 d->restrictions.insert(key.toLatin1(), true);
01844 d->dircache.remove(key.toLatin1());
01845 }
01846 }
01847 }
01848
01849
01850 bool configDirsChanged = (resourceDirs("config").count() != configdirs);
01851
01852 d->checkRestrictions = configDirsChanged;
01853
01854 return configDirsChanged;
01855 }
01856
01857 QString KStandardDirs::localkdedir() const
01858 {
01859
01860 return d->prefixes.first();
01861 }
01862
01863 QString KStandardDirs::localxdgdatadir() const
01864 {
01865
01866 return d->xdgdata_prefixes.first();
01867 }
01868
01869 QString KStandardDirs::localxdgconfdir() const
01870 {
01871
01872 return d->xdgconf_prefixes.first();
01873 }
01874
01875
01876
01877 QString KStandardDirs::locate( const char *type,
01878 const QString& filename, const KComponentData &cData)
01879 {
01880 return cData.dirs()->findResource(type, filename);
01881 }
01882
01883 QString KStandardDirs::locateLocal( const char *type,
01884 const QString& filename, const KComponentData &cData)
01885 {
01886 return locateLocal(type, filename, true, cData);
01887 }
01888
01889 QString KStandardDirs::locateLocal( const char *type,
01890 const QString& filename, bool createDir,
01891 const KComponentData &cData)
01892 {
01893
01894
01895 int slash = filename.lastIndexOf('/')+1;
01896 if (!slash) {
01897 return cData.dirs()->saveLocation(type, QString(), createDir) + filename;
01898 }
01899
01900
01901 QString dir = filename.left(slash);
01902 QString file = filename.mid(slash);
01903 return cData.dirs()->saveLocation(type, dir, createDir) + file;
01904 }
01905
01906 bool KStandardDirs::checkAccess(const QString& pathname, int mode)
01907 {
01908 QByteArray cPathname = QFile::encodeName(pathname);
01909 int accessOK = access( cPathname, mode );
01910 if ( accessOK == 0 )
01911 return true;
01912
01913
01914
01915
01916 if ( (mode & W_OK) == 0 )
01917 return false;
01918
01919
01920 if (!access( cPathname, F_OK))
01921 return false;
01922
01923
01924 QString dirName(pathname);
01925 int pos = dirName.lastIndexOf('/');
01926 if ( pos == -1 )
01927 return false;
01928 else if ( pos == 0 )
01929 pos = 1;
01930
01931 dirName.truncate(pos);
01932
01933 accessOK = access( QFile::encodeName(dirName), W_OK );
01934
01935 if ( accessOK == 0 )
01936 return true;
01937 else
01938 return false;
01939 }
01940