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
01000
01001 if((*pit)!=installprefix||installdir.isEmpty()||!strcmp("exe", type))
01002 {
01003 for (QStringList::ConstIterator it = dirs.begin();
01004 it != dirs.end(); ++it)
01005 {
01006 if ( (*it).startsWith('%'))
01007 continue;
01008 QString path = realPath( *pit + *it );
01009 testdir.setPath(path);
01010 if (local && restrictionActive)
01011 continue;
01012 if ((local || testdir.exists()) && !candidates.contains(path))
01013 candidates.append(path);
01014 }
01015
01016
01017
01018 if (local && !strcmp("config", type))
01019 candidates.append("/etc/kde/");
01020 local = false;
01021 }
01022 else
01023 {
01024
01025 testdir.setPath(installdir);
01026 if(testdir.exists() && ! candidates.contains(installdir))
01027 candidates.append(installdir);
01028 }
01029 }
01030 }
01031
01032
01033 if (!installdir.isEmpty()) {
01034 bool ok = true;
01035 foreach (const QString &s, candidates) {
01036 if (installdir.startsWith(s)) {
01037 ok = false;
01038 break;
01039 }
01040 }
01041 if (ok)
01042 candidates.append(installdir);
01043 }
01044
01045 dirs = d->absolutes.value(type);
01046 if (!dirs.isEmpty())
01047 for (QStringList::ConstIterator it = dirs.begin();
01048 it != dirs.end(); ++it)
01049 {
01050 testdir.setPath(*it);
01051 if (testdir.exists()) {
01052 QString filename = realPath( *it );
01053 if (!candidates.contains(filename)) {
01054 candidates.append(filename);
01055 }
01056 }
01057 }
01058
01059 d->dircache.insert(type, candidates);
01060 }
01061
01062 #if 0
01063 kDebug(180) << "found dirs for resource " << type << ":";
01064 for (QStringList::ConstIterator pit = candidates.begin();
01065 pit != candidates.end();
01066 ++pit)
01067 {
01068 fprintf(stderr, "%s\n", qPrintable(*pit));
01069 }
01070 #endif
01071
01072 return candidates;
01073 }
01074
01075 QStringList KStandardDirs::systemPaths( const QString& pstr )
01076 {
01077 QStringList tokens;
01078 QString p = pstr;
01079
01080 if( p.isEmpty() )
01081 {
01082 p = QString::fromLocal8Bit( qgetenv( "PATH" ) );
01083 }
01084
01085 QString delimiters(QChar(KPATH_SEPARATOR));
01086 delimiters += "\b";
01087 tokenize( tokens, p, delimiters );
01088
01089 QStringList exePaths;
01090
01091
01092 for( int i = 0; i < tokens.count(); i++ )
01093 {
01094 exePaths << KShell::tildeExpand( tokens[ i ] );
01095 }
01096
01097 return exePaths;
01098 }
01099
01100 #ifdef Q_WS_MAC
01101 static QString getBundle( const QString& path, bool ignore )
01102 {
01103 kDebug(180) << "getBundle(" << path << ", " << ignore << ") called";
01104 QFileInfo info;
01105 QString bundle = path;
01106 bundle += ".app/Contents/MacOS/" + bundle.section('/', -1);
01107 info.setFile( bundle );
01108 if ( info.exists() && ( ignore || info.isExecutable() )
01109 && ( info.isFile() || info.isSymLink() ) ) {
01110 kDebug(180) << "getBundle(): returning " << bundle;
01111 return bundle;
01112 }
01113 return QString();
01114 }
01115 #endif
01116
01117 static QString checkExecutable( const QString& path, bool ignoreExecBit )
01118 {
01119 #ifdef Q_WS_MAC
01120 QString bundle = getBundle( path, ignoreExecBit );
01121 if ( !bundle.isEmpty() ) {
01122
01123 return bundle;
01124 }
01125 #endif
01126 QFileInfo info( path );
01127 QFileInfo orig = info;
01128 if( info.exists() && info.isSymLink() )
01129 info = QFileInfo( info.canonicalFilePath() );
01130 if( info.exists() && ( ignoreExecBit || info.isExecutable() ) && info.isFile() ) {
01131
01132
01133
01134 orig.makeAbsolute();
01135 return orig.filePath();
01136 }
01137
01138 return QString();
01139 }
01140
01141 QString KStandardDirs::findExe( const QString& appname,
01142 const QString& pstr,
01143 SearchOptions options )
01144 {
01145
01146
01147 #ifdef Q_WS_WIN
01148 QString real_appname = appname + ".exe";
01149 #else
01150 QString real_appname = appname;
01151 #endif
01152 QFileInfo info;
01153
01154
01155 if (real_appname.contains(QDir::separator()))
01156 {
01157
01158 QString path = checkExecutable(real_appname, options & IgnoreExecBit);
01159 return path;
01160 }
01161
01162
01163
01164
01165
01166 QString p = installPath("libexec") + real_appname;
01167 QString result = checkExecutable(p, options & IgnoreExecBit);
01168 if (!result.isEmpty()) {
01169
01170 return result;
01171 }
01172
01173 p = installPath("exe") + real_appname;
01174 result = checkExecutable(p, options & IgnoreExecBit);
01175 if (!result.isEmpty()) {
01176
01177 return result;
01178 }
01179
01180
01181 const QStringList exePaths = systemPaths( pstr );
01182 for (QStringList::ConstIterator it = exePaths.begin(); it != exePaths.end(); ++it)
01183 {
01184 p = (*it) + '/';
01185 p += real_appname;
01186
01187
01188 result = checkExecutable(p, options & IgnoreExecBit);
01189 if (!result.isEmpty()) {
01190
01191 return result;
01192 }
01193 }
01194
01195
01196
01197
01198
01199 return QString();
01200 }
01201
01202 int KStandardDirs::findAllExe( QStringList& list, const QString& appname,
01203 const QString& pstr, SearchOptions options )
01204 {
01205 #ifdef Q_WS_WIN
01206 QString real_appname = appname + ".exe";
01207 #else
01208 QString real_appname = appname;
01209 #endif
01210 QFileInfo info;
01211 QString p;
01212 list.clear();
01213
01214 const QStringList exePaths = systemPaths( pstr );
01215 for (QStringList::ConstIterator it = exePaths.begin(); it != exePaths.end(); ++it)
01216 {
01217 p = (*it) + '/';
01218 p += real_appname;
01219
01220 #ifdef Q_WS_MAC
01221 QString bundle = getBundle( p, (options & IgnoreExecBit) );
01222 if ( !bundle.isEmpty() ) {
01223
01224 list.append( bundle );
01225 }
01226 #endif
01227
01228 info.setFile( p );
01229
01230 if( info.exists() && ( ( options & IgnoreExecBit ) || info.isExecutable())
01231 && info.isFile() ) {
01232 list.append( p );
01233 }
01234 }
01235
01236 return list.count();
01237 }
01238
01239 static inline QString equalizePath(QString &str)
01240 {
01241 #ifdef Q_WS_WIN
01242
01243
01244 QFileInfo f(str);
01245 if (f.isAbsolute())
01246 return f.absoluteFilePath();
01247 else
01248 #endif
01249 return str;
01250 }
01251
01252 static int tokenize( QStringList& tokens, const QString& str,
01253 const QString& delim )
01254 {
01255 int len = str.length();
01256 QString token = "";
01257
01258 for( int index = 0; index < len; index++)
01259 {
01260 if ( delim.contains( str[ index ] ) )
01261 {
01262 tokens.append( equalizePath(token) );
01263 token = "";
01264 }
01265 else
01266 {
01267 token += str[ index ];
01268 }
01269 }
01270 if ( !token.isEmpty() )
01271 {
01272 tokens.append( equalizePath(token) );
01273 }
01274
01275 return tokens.count();
01276 }
01277
01278 QString KStandardDirs::kde_default(const char *type)
01279 {
01280 return QString('%') + type + '/';
01281 }
01282
01283 QString KStandardDirs::saveLocation(const char *type,
01284 const QString& suffix,
01285 bool create) const
01286 {
01287 QString path = d->savelocations.value(type);
01288 if (path.isEmpty())
01289 {
01290 QStringList dirs = d->relatives.value(type);
01291 if (dirs.isEmpty() && (
01292 (strcmp(type, "socket") == 0) ||
01293 (strcmp(type, "tmp") == 0) ||
01294 (strcmp(type, "cache") == 0) ))
01295 {
01296 (void) resourceDirs(type);
01297 dirs = d->relatives.value(type);
01298 }
01299 if (!dirs.isEmpty())
01300 {
01301 path = dirs.last();
01302
01303 if ( path.startsWith('%'))
01304 {
01305
01306 QString rel = path.mid(1, path.indexOf('/') - 1);
01307 QString rest = path.mid(path.indexOf('/') + 1);
01308 QString basepath = saveLocation(rel.toUtf8().constData());
01309 path = basepath + rest;
01310 } else
01311
01312
01313 if (strncmp(type, "xdgdata-", 8) == 0) {
01314 path = realPath( localxdgdatadir() + path ) ;
01315 } else if (strncmp(type, "xdgconf-", 8) == 0) {
01316 path = realPath( localxdgconfdir() + path );
01317 } else {
01318 path = realPath( localkdedir() + path );
01319 }
01320 }
01321 else {
01322 dirs = d->absolutes.value(type);
01323 if (dirs.isEmpty()) {
01324 qFatal("KStandardDirs: The resource type %s is not registered", type);
01325 }
01326 path = realPath(dirs.last());
01327 }
01328
01329 d->savelocations.insert(type, path.endsWith('/') ? path : path + '/');
01330 }
01331 QString fullPath = path + suffix;
01332
01333 KDE_struct_stat st;
01334 if (KDE_stat(QFile::encodeName(fullPath), &st) != 0 || !(S_ISDIR(st.st_mode))) {
01335 if(!create) {
01336 #ifndef NDEBUG
01337 kDebug(180) << QString("save location %1 doesn't exist").arg(fullPath);
01338 #endif
01339 return fullPath;
01340 }
01341 if(!makeDir(fullPath, 0700)) {
01342 return fullPath;
01343 }
01344 d->dircache.remove(type);
01345 }
01346 if (!fullPath.endsWith('/'))
01347 fullPath += '/';
01348 return fullPath;
01349 }
01350
01351 QString KStandardDirs::relativeLocation(const char *type, const QString &absPath)
01352 {
01353 QString fullPath = absPath;
01354 int i = absPath.lastIndexOf('/');
01355 if (i != -1) {
01356 fullPath = realFilePath(absPath);
01357 }
01358
01359 const QStringList candidates = resourceDirs(type);
01360
01361 for (QStringList::ConstIterator it = candidates.begin();
01362 it != candidates.end(); ++it) {
01363 if (fullPath.startsWith(*it)) {
01364 return fullPath.mid((*it).length());
01365 }
01366 }
01367 return absPath;
01368 }
01369
01370
01371 bool KStandardDirs::makeDir(const QString& dir, int mode)
01372 {
01373
01374 if (QDir::isRelativePath(dir))
01375 return false;
01376
01377 QString target = dir;
01378 uint len = target.length();
01379
01380
01381 if (dir.at(len - 1) != '/')
01382 target += '/';
01383
01384 QString base("");
01385 uint i = 1;
01386
01387 while( i < len )
01388 {
01389 KDE_struct_stat st;
01390 int pos = target.indexOf('/', i);
01391 base += target.mid(i - 1, pos - i + 1);
01392 QByteArray baseEncoded = QFile::encodeName(base);
01393
01394 if (KDE_stat(baseEncoded, &st) != 0)
01395 {
01396
01397
01398 if (KDE_lstat(baseEncoded, &st) == 0)
01399 (void)unlink(baseEncoded);
01400
01401 if (KDE_mkdir(baseEncoded, static_cast<mode_t>(mode)) != 0) {
01402 baseEncoded.prepend( "trying to create local folder " );
01403 perror(baseEncoded.constData());
01404 return false;
01405 }
01406 }
01407 i = pos + 1;
01408 }
01409 return true;
01410 }
01411
01412 static QString readEnvPath(const char *env)
01413 {
01414 QByteArray c_path = qgetenv(env);
01415 if (c_path.isEmpty())
01416 return QString();
01417 return QDir::fromNativeSeparators(QFile::decodeName(c_path));
01418 }
01419
01420 #ifdef __linux__
01421 static QString executablePrefix()
01422 {
01423 char path_buffer[MAXPATHLEN + 1];
01424 path_buffer[MAXPATHLEN] = 0;
01425 int length = readlink ("/proc/self/exe", path_buffer, MAXPATHLEN);
01426 if (length == -1)
01427 return QString();
01428
01429 path_buffer[length] = '\0';
01430
01431 QString path = QFile::decodeName(path_buffer);
01432
01433 if(path.isEmpty())
01434 return QString();
01435
01436 int pos = path.lastIndexOf('/');
01437 if(pos <= 0)
01438 return QString();
01439 pos = path.lastIndexOf('/', pos - 1);
01440 if(pos <= 0)
01441 return QString();
01442
01443 return path.left(pos);
01444 }
01445 #endif
01446
01447 void KStandardDirs::addResourcesFrom_krcdirs()
01448 {
01449 QString localFile = QDir::currentPath() + QDir::separator() + ".krcdirs";
01450 if (!QFile::exists(localFile))
01451 return;
01452
01453 QSettings iniFile(localFile, QSettings::IniFormat);
01454 iniFile.beginGroup("KStandardDirs");
01455 const QStringList resources = iniFile.allKeys();
01456 foreach(const QString &key, resources)
01457 {
01458 QDir path(iniFile.value(key).toString());
01459 if (!path.exists())
01460 continue;
01461
01462 if(path.makeAbsolute())
01463 addResourceDir(key.toAscii(), path.path(), false);
01464 }
01465 }
01466
01467 void KStandardDirs::addKDEDefaults()
01468 {
01469 addResourcesFrom_krcdirs();
01470
01471 QStringList kdedirList;
01472
01473
01474 QString kdedirs = readEnvPath("KDEDIRS");
01475 if (!kdedirs.isEmpty())
01476 {
01477 tokenize(kdedirList, kdedirs, QString(QChar(KPATH_SEPARATOR)));
01478 }
01479 kdedirList.append(installPath("kdedir"));
01480
01481 QString execPrefix(EXEC_INSTALL_PREFIX);
01482 if (!execPrefix.isEmpty() && !kdedirList.contains(execPrefix))
01483 kdedirList.append(execPrefix);
01484 #ifdef __linux__
01485 const QString linuxExecPrefix = executablePrefix();
01486 if ( !linuxExecPrefix.isEmpty() )
01487 kdedirList.append( linuxExecPrefix );
01488 #endif
01489
01490
01491
01492 QString localKdeDir = readEnvPath(getuid() ? "KDEHOME" : "KDEROOTHOME");
01493 if (!localKdeDir.isEmpty())
01494 {
01495 if (localKdeDir[localKdeDir.length()-1] != '/')
01496 localKdeDir += '/';
01497 }
01498 else
01499 {
01500 #ifdef Q_WS_MACX
01501 localKdeDir = QDir::homePath() + QLatin1String("/Library/Preferences/KDE/");
01502 #else
01503 localKdeDir = QDir::homePath() + QLatin1Char('/') + KDE_DEFAULT_HOME + QLatin1Char('/');
01504 #endif
01505 }
01506
01507 if (localKdeDir != "-/")
01508 {
01509 localKdeDir = KShell::tildeExpand(localKdeDir);
01510 addPrefix(localKdeDir);
01511 }
01512
01513 #ifdef Q_WS_MACX
01514
01515
01516 QDir bundleDir(mac_app_filename());
01517 if (bundleDir.dirName() == "MacOS") {
01518 bundleDir.cdUp();
01519
01520
01521 addPrefix(bundleDir.absolutePath());
01522 }
01523 #endif
01524
01525 QStringList::ConstIterator end(kdedirList.end());
01526 for (QStringList::ConstIterator it = kdedirList.begin();
01527 it != end; ++it)
01528 {
01529 const QString dir = KShell::tildeExpand(*it);
01530 addPrefix(dir);
01531 }
01532
01533
01534
01535 QStringList xdgdirList;
01536 QString xdgdirs = readEnvPath("XDG_CONFIG_DIRS");
01537 if (!xdgdirs.isEmpty())
01538 {
01539 tokenize(xdgdirList, xdgdirs, QString(QChar(KPATH_SEPARATOR)));
01540 }
01541 else
01542 {
01543 xdgdirList.clear();
01544 xdgdirList.append("/etc/xdg");
01545 #ifdef Q_WS_WIN
01546 xdgdirList.append(installPath("kdedir") + "etc/xdg");
01547 #else
01548 xdgdirList.append(KDESYSCONFDIR "/xdg");
01549 #endif
01550 }
01551
01552 QString localXdgDir = readEnvPath("XDG_CONFIG_HOME");
01553 if (!localXdgDir.isEmpty())
01554 {
01555 if (localXdgDir[localXdgDir.length()-1] != '/')
01556 localXdgDir += '/';
01557 }
01558 else
01559 {
01560 #ifdef Q_WS_MACX
01561 localXdgDir = QDir::homePath() + "/Library/Preferences/XDG/";
01562 #else
01563 localXdgDir = QDir::homePath() + "/.config/";
01564 #endif
01565 }
01566
01567 localXdgDir = KShell::tildeExpand(localXdgDir);
01568 addXdgConfigPrefix(localXdgDir);
01569
01570 for (QStringList::ConstIterator it = xdgdirList.begin();
01571 it != xdgdirList.end(); ++it)
01572 {
01573 QString dir = KShell::tildeExpand(*it);
01574 addXdgConfigPrefix(dir);
01575 }
01576
01577
01578
01579 QStringList kdedirDataDirs;
01580 for (QStringList::ConstIterator it = kdedirList.begin();
01581 it != kdedirList.end(); ++it) {
01582 QString dir = *it;
01583 if (!dir.endsWith('/'))
01584 dir += '/';
01585 kdedirDataDirs.append(dir+"share/");
01586 }
01587
01588 xdgdirs = readEnvPath("XDG_DATA_DIRS");
01589 if (!xdgdirs.isEmpty()) {
01590 tokenize(xdgdirList, xdgdirs, QString(QChar(KPATH_SEPARATOR)));
01591
01592
01593
01594 Q_FOREACH(const QString& dir, kdedirDataDirs) {
01595 if (!xdgdirList.contains(dir))
01596 xdgdirList.append(dir);
01597 }
01598 } else {
01599 xdgdirList = kdedirDataDirs;
01600 xdgdirList.append("/usr/local/share/");
01601 xdgdirList.append("/usr/share/");
01602 }
01603
01604 localXdgDir = readEnvPath("XDG_DATA_HOME");
01605 if (!localXdgDir.isEmpty())
01606 {
01607 if (localXdgDir[localXdgDir.length()-1] != '/')
01608 localXdgDir += '/';
01609 }
01610 else
01611 {
01612 localXdgDir = QDir::homePath() + "/.local/share/";
01613 }
01614
01615 localXdgDir = KShell::tildeExpand(localXdgDir);
01616 addXdgDataPrefix(localXdgDir);
01617
01618 for (QStringList::ConstIterator it = xdgdirList.begin();
01619 it != xdgdirList.end(); ++it)
01620 {
01621 QString dir = KShell::tildeExpand(*it);
01622 addXdgDataPrefix(dir);
01623 }
01624
01625
01626
01627 addResourceType("lib", 0, "lib" KDELIBSUFF "/");
01628
01629 uint index = 0;
01630 while (types_indices[index] != -1) {
01631 addResourceType(types_string + types_indices[index], 0, types_string + types_indices[index+1], true);
01632 index+=2;
01633 }
01634 addResourceType("exe", 0, "libexec/kde4", true );
01635
01636 addResourceDir("home", QDir::homePath(), false);
01637 }
01638
01639 static QStringList lookupProfiles(const QString &mapFile)
01640 {
01641 QStringList profiles;
01642
01643 if (mapFile.isEmpty() || !QFile::exists(mapFile))
01644 {
01645 profiles << "default";
01646 return profiles;
01647 }
01648
01649 struct passwd *pw = getpwuid(geteuid());
01650 if (!pw)
01651 {
01652 profiles << "default";
01653 return profiles;
01654 }
01655
01656 QByteArray user = pw->pw_name;
01657
01658 gid_t sup_gids[512];
01659 int sup_gids_nr = getgroups(512, sup_gids);
01660
01661 KConfig mapCfgFile(mapFile);
01662 KConfigGroup mapCfg(&mapCfgFile, "Users");
01663 if (mapCfg.hasKey(user.constData()))
01664 {
01665 profiles = mapCfg.readEntry(user.constData(), QStringList());
01666 return profiles;
01667 }
01668
01669 const KConfigGroup generalGrp(&mapCfgFile, "General");
01670 const QStringList groups = generalGrp.readEntry("groups", QStringList());
01671
01672 const KConfigGroup groupsGrp(&mapCfgFile, "Groups");
01673
01674 for( QStringList::ConstIterator it = groups.begin();
01675 it != groups.end(); ++it )
01676 {
01677 QByteArray grp = (*it).toUtf8();
01678
01679 struct group *grp_ent = getgrnam(grp);
01680 if (!grp_ent) continue;
01681 gid_t gid = grp_ent->gr_gid;
01682 if (pw->pw_gid == gid)
01683 {
01684
01685 profiles += groupsGrp.readEntry(*it, QStringList());
01686 }
01687 else
01688 {
01689 for(int i = 0; i < sup_gids_nr; i++)
01690 {
01691 if (sup_gids[i] == gid)
01692 {
01693
01694 profiles += groupsGrp.readEntry(*it, QStringList());
01695 break;
01696 }
01697 }
01698 }
01699 }
01700
01701 if (profiles.isEmpty())
01702 profiles << "default";
01703 return profiles;
01704 }
01705
01706 extern bool kde_kiosk_admin;
01707
01708 bool KStandardDirs::addCustomized(KConfig *config)
01709 {
01710 if (!d->checkRestrictions)
01711 return false;
01712
01713
01714
01715 int configdirs = resourceDirs("config").count();
01716
01717 if (true)
01718 {
01719
01720 QString group = QLatin1String("Directories");
01721 KConfigGroup cg(config, group);
01722
01723 QString kioskAdmin = cg.readEntry("kioskAdmin");
01724 if (!kioskAdmin.isEmpty() && !kde_kiosk_admin)
01725 {
01726 int i = kioskAdmin.indexOf(':');
01727 QString user = kioskAdmin.left(i);
01728 QString host = kioskAdmin.mid(i+1);
01729
01730 KUser thisUser;
01731 char hostname[ 256 ];
01732 hostname[ 0 ] = '\0';
01733 if (!gethostname( hostname, 255 ))
01734 hostname[sizeof(hostname)-1] = '\0';
01735
01736 if ((user == thisUser.loginName()) &&
01737 (host.isEmpty() || (host == hostname)))
01738 {
01739 kde_kiosk_admin = true;
01740 }
01741 }
01742
01743 bool readProfiles = true;
01744
01745 if (kde_kiosk_admin && !qgetenv("KDE_KIOSK_NO_PROFILES").isEmpty())
01746 readProfiles = false;
01747
01748 QString userMapFile = cg.readEntry("userProfileMapFile");
01749 QString profileDirsPrefix = cg.readEntry("profileDirsPrefix");
01750 if (!profileDirsPrefix.isEmpty() && !profileDirsPrefix.endsWith('/'))
01751 profileDirsPrefix.append("/");
01752
01753 QStringList profiles;
01754 if (readProfiles)
01755 profiles = lookupProfiles(userMapFile);
01756 QString profile;
01757
01758 bool priority = false;
01759 while(true)
01760 {
01761 KConfigGroup cg(config, group);
01762 const QStringList list = cg.readEntry("prefixes", QStringList());
01763 for (QStringList::ConstIterator it = list.begin(); it != list.end(); ++it)
01764 {
01765 addPrefix(*it, priority);
01766 addXdgConfigPrefix(*it+"/etc/xdg", priority);
01767 addXdgDataPrefix(*it+"/share", priority);
01768 }
01769
01770
01771 if (list.isEmpty() && !profile.isEmpty() && !profileDirsPrefix.isEmpty())
01772 {
01773 QString dir = profileDirsPrefix + profile;
01774 addPrefix(dir, priority);
01775 addXdgConfigPrefix(dir+"/etc/xdg", priority);
01776 addXdgDataPrefix(dir+"/share", priority);
01777 }
01778
01779
01780
01781 const QMap<QString, QString> entries = config->entryMap(group);
01782 for (QMap<QString, QString>::ConstIterator it2 = entries.begin();
01783 it2 != entries.end(); it2++)
01784 {
01785 const QString key = it2.key();
01786 if (key.startsWith("dir_")) {
01787
01788 QStringList dirs = (*it2).split(',');
01789 QStringList::Iterator sIt(dirs.begin());
01790 QString resType = key.mid(4);
01791 for (; sIt != dirs.end(); ++sIt)
01792 {
01793 addResourceDir(resType.toLatin1(), *sIt, priority);
01794 }
01795 }
01796 }
01797 if (profiles.isEmpty())
01798 break;
01799 profile = profiles.back();
01800 group = QString::fromLatin1("Directories-%1").arg(profile);
01801 profiles.pop_back();
01802 priority = true;
01803 }
01804 }
01805
01806
01807 if (!kde_kiosk_admin || qgetenv("KDE_KIOSK_NO_RESTRICTIONS").isEmpty())
01808 {
01809 KConfigGroup cg(config, "KDE Resource Restrictions");
01810 const QMap<QString, QString> entries = cg.entryMap();
01811 for (QMap<QString, QString>::ConstIterator it2 = entries.begin();
01812 it2 != entries.end(); it2++)
01813 {
01814 const QString key = it2.key();
01815 if (!cg.readEntry(key, true))
01816 {
01817 d->restrictionsActive = true;
01818 d->restrictions.insert(key.toLatin1(), true);
01819 d->dircache.remove(key.toLatin1());
01820 }
01821 }
01822 }
01823
01824
01825 bool configDirsChanged = (resourceDirs("config").count() != configdirs);
01826
01827 d->checkRestrictions = configDirsChanged;
01828
01829 return configDirsChanged;
01830 }
01831
01832 QString KStandardDirs::localkdedir() const
01833 {
01834
01835 return d->prefixes.first();
01836 }
01837
01838 QString KStandardDirs::localxdgdatadir() const
01839 {
01840
01841 return d->xdgdata_prefixes.first();
01842 }
01843
01844 QString KStandardDirs::localxdgconfdir() const
01845 {
01846
01847 return d->xdgconf_prefixes.first();
01848 }
01849
01850
01851
01852 QString KStandardDirs::locate( const char *type,
01853 const QString& filename, const KComponentData &cData)
01854 {
01855 return cData.dirs()->findResource(type, filename);
01856 }
01857
01858 QString KStandardDirs::locateLocal( const char *type,
01859 const QString& filename, const KComponentData &cData)
01860 {
01861 return locateLocal(type, filename, true, cData);
01862 }
01863
01864 QString KStandardDirs::locateLocal( const char *type,
01865 const QString& filename, bool createDir,
01866 const KComponentData &cData)
01867 {
01868
01869
01870 int slash = filename.lastIndexOf('/')+1;
01871 if (!slash) {
01872 return cData.dirs()->saveLocation(type, QString(), createDir) + filename;
01873 }
01874
01875
01876 QString dir = filename.left(slash);
01877 QString file = filename.mid(slash);
01878 return cData.dirs()->saveLocation(type, dir, createDir) + file;
01879 }
01880
01881 bool KStandardDirs::checkAccess(const QString& pathname, int mode)
01882 {
01883 int accessOK = access( QFile::encodeName(pathname), mode );
01884 if ( accessOK == 0 )
01885 return true;
01886
01887
01888
01889
01890 if ( (mode & W_OK) == 0 )
01891 return false;
01892
01893
01894 if (!access( QFile::encodeName(pathname), F_OK))
01895 return false;
01896
01897
01898 QString dirName(pathname);
01899 int pos = dirName.lastIndexOf('/');
01900 if ( pos == -1 )
01901 return false;
01902 else if ( pos == 0 )
01903 pos = 1;
01904
01905 dirName.truncate(pos);
01906
01907 accessOK = access( QFile::encodeName(dirName), W_OK );
01908
01909 if ( accessOK == 0 )
01910 return true;
01911 else
01912 return false;
01913 }
01914