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