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