00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
#include "config.h"
00028
00029
#include <stdlib.h>
00030
#include <assert.h>
00031
#include <errno.h>
00032
#ifdef HAVE_SYS_STAT_H
00033
#include <sys/stat.h>
00034
#endif
00035
#include <sys/types.h>
00036
#include <dirent.h>
00037
#include <pwd.h>
00038
#include <grp.h>
00039
00040
#include <qregexp.h>
00041
#include <qasciidict.h>
00042
#include <qdict.h>
00043
#include <qdir.h>
00044
#include <qfileinfo.h>
00045
#include <qstring.h>
00046
#include <qstringlist.h>
00047
00048
#include "kstandarddirs.h"
00049
#include "kconfig.h"
00050
#include "kdebug.h"
00051
#include "kinstance.h"
00052
#include "kshell.h"
00053
#include "ksimpleconfig.h"
00054
#include "kuser.h"
00055
#include <sys/param.h>
00056
#include <unistd.h>
00057
00058
template class QDict<QStringList>;
00059
00060
class KStandardDirs::KStandardDirsPrivate
00061 {
00062
public:
00063 KStandardDirsPrivate()
00064 : restrictionsActive(false),
00065 dataRestrictionActive(false)
00066 { }
00067
00068
bool restrictionsActive;
00069
bool dataRestrictionActive;
00070
QAsciiDict<bool> restrictions;
00071
QStringList xdgdata_prefixes;
00072
QStringList xdgconf_prefixes;
00073 };
00074
00075
static const char*
const types[] = {
"html",
"icon",
"apps",
"sound",
00076
"data",
"locale",
"services",
"mime",
00077
"servicetypes",
"config",
"exe",
00078
"wallpaper",
"lib",
"pixmap",
"templates",
00079
"module",
"qtplugins",
00080
"xdgdata-apps",
"xdgdata-dirs",
"xdgconf-menu",
00081
"kcfg", 0 };
00082
00083
static int tokenize(
QStringList& token,
const QString& str,
00084
const QString& delim );
00085
00086 KStandardDirs::KStandardDirs( ) : addedCustoms(false)
00087 {
00088 d =
new KStandardDirsPrivate;
00089 dircache.
setAutoDelete(
true);
00090 relatives.
setAutoDelete(
true);
00091 absolutes.
setAutoDelete(
true);
00092 savelocations.
setAutoDelete(
true);
00093
addKDEDefaults();
00094 }
00095
00096 KStandardDirs::~KStandardDirs()
00097 {
00098
delete d;
00099 }
00100
00101 bool KStandardDirs::isRestrictedResource(
const char *type,
const QString& relPath)
const
00102
{
00103
if (!d || !d->restrictionsActive)
00104
return false;
00105
00106
if (d->restrictions[type])
00107
return true;
00108
00109
if (strcmp(type,
"data")==0)
00110 {
00111 applyDataRestrictions(relPath);
00112
if (d->dataRestrictionActive)
00113 {
00114 d->dataRestrictionActive =
false;
00115
return true;
00116 }
00117 }
00118
return false;
00119 }
00120
00121
void KStandardDirs::applyDataRestrictions(
const QString &relPath)
const
00122
{
00123
QString key;
00124
int i = relPath.
find(
'/');
00125
if (i != -1)
00126 key =
"data_"+relPath.
left(i);
00127
else
00128 key =
"data_"+relPath;
00129
00130
if (d && d->restrictions[key.latin1()])
00131 d->dataRestrictionActive =
true;
00132 }
00133
00134
00135 QStringList KStandardDirs::allTypes()
const
00136
{
00137
QStringList list;
00138
for (
int i = 0; types[i] != 0; ++i)
00139 list.append(QString::fromLatin1(types[i]));
00140
return list;
00141 }
00142
00143
static void priorityAdd(
QStringList &prefixes,
const QString& dir,
bool priority)
00144 {
00145
if (priority && !prefixes.isEmpty())
00146 {
00147
00148 QStringList::iterator it = prefixes.begin();
00149 it++;
00150 prefixes.insert(it, 1, dir);
00151 }
00152
else
00153 {
00154 prefixes.append(dir);
00155 }
00156 }
00157
00158 void KStandardDirs::addPrefix(
const QString& _dir )
00159 {
00160
addPrefix(_dir,
false);
00161 }
00162
00163
void KStandardDirs::addPrefix(
const QString& _dir,
bool priority )
00164 {
00165
if (_dir.
isNull())
00166
return;
00167
00168
QString dir = _dir;
00169
if (dir.
at(dir.
length() - 1) !=
'/')
00170 dir +=
'/';
00171
00172
if (!prefixes.contains(dir)) {
00173 priorityAdd(prefixes, dir, priority);
00174 dircache.
clear();
00175 }
00176 }
00177
00178 void KStandardDirs::addXdgConfigPrefix(
const QString& _dir )
00179 {
00180
addXdgConfigPrefix(_dir,
false);
00181 }
00182
00183
void KStandardDirs::addXdgConfigPrefix(
const QString& _dir,
bool priority )
00184 {
00185
if (_dir.
isNull())
00186
return;
00187
00188
QString dir = _dir;
00189
if (dir.
at(dir.
length() - 1) !=
'/')
00190 dir +=
'/';
00191
00192
if (!d->xdgconf_prefixes.contains(dir)) {
00193 priorityAdd(d->xdgconf_prefixes, dir, priority);
00194 dircache.
clear();
00195 }
00196 }
00197
00198 void KStandardDirs::addXdgDataPrefix(
const QString& _dir )
00199 {
00200
addXdgDataPrefix(_dir,
false);
00201 }
00202
00203
void KStandardDirs::addXdgDataPrefix(
const QString& _dir,
bool priority )
00204 {
00205
if (_dir.
isNull())
00206
return;
00207
00208
QString dir = _dir;
00209
if (dir.
at(dir.
length() - 1) !=
'/')
00210 dir +=
'/';
00211
00212
if (!d->xdgdata_prefixes.contains(dir)) {
00213 priorityAdd(d->xdgdata_prefixes, dir, priority);
00214 dircache.
clear();
00215 }
00216 }
00217
00218
QString KStandardDirs::kfsstnd_prefixes()
00219 {
00220
return prefixes.
join(
":");
00221 }
00222
00223 bool KStandardDirs::addResourceType(
const char *type,
00224
const QString& relativename )
00225 {
00226
return addResourceType(type, relativename,
true);
00227 }
00228
00229
bool KStandardDirs::addResourceType(
const char *type,
00230
const QString& relativename,
00231
bool priority )
00232 {
00233
if (relativename.
isNull())
00234
return false;
00235
00236
QStringList *rels = relatives.
find(type);
00237
if (!rels) {
00238 rels =
new QStringList();
00239 relatives.
insert(type, rels);
00240 }
00241
QString copy = relativename;
00242
if (
copy.at(
copy.length() - 1) !=
'/')
00243
copy +=
'/';
00244
if (!rels->contains(copy)) {
00245
if (priority)
00246 rels->prepend(copy);
00247
else
00248 rels->append(copy);
00249 dircache.
remove(type);
00250
return true;
00251 }
00252
return false;
00253 }
00254
00255 bool KStandardDirs::addResourceDir(
const char *type,
00256
const QString& absdir)
00257 {
00258
00259
return addResourceDir(type, absdir,
false);
00260 }
00261
00262
bool KStandardDirs::addResourceDir(
const char *type,
00263
const QString& absdir,
00264
bool priority)
00265 {
00266
QStringList *paths = absolutes.
find(type);
00267
if (!paths) {
00268 paths =
new QStringList();
00269 absolutes.
insert(type, paths);
00270 }
00271
QString copy = absdir;
00272
if (
copy.at(
copy.length() - 1) !=
'/')
00273
copy +=
'/';
00274
00275
if (!paths->contains(copy)) {
00276
if (priority)
00277 paths->prepend(copy);
00278
else
00279 paths->append(copy);
00280 dircache.
remove(type);
00281
return true;
00282 }
00283
return false;
00284 }
00285
00286 QString KStandardDirs::findResource(
const char *type,
00287
const QString& filename )
const
00288
{
00289
if (filename.
at(0) ==
'/')
00290
return filename;
00291
00292
#if 0
00293
kdDebug() <<
"Find resource: " << type <<
endl;
00294
for (QStringList::ConstIterator pit = prefixes.begin();
00295 pit != prefixes.end();
00296 pit++)
00297 {
00298 kdDebug() <<
"Prefix: " << *pit <<
endl;
00299 }
00300
#endif
00301
00302
QString dir =
findResourceDir(type, filename);
00303
if (dir.
isNull())
00304
return dir;
00305
else return dir + filename;
00306 }
00307
00308
static Q_UINT32 updateHash(
const QString &file, Q_UINT32 hash)
00309 {
00310
QCString cFile = QFile::encodeName(file);
00311
struct stat buff;
00312
if ((access(cFile, R_OK) == 0) &&
00313 (stat( cFile, &buff ) == 0) &&
00314 (S_ISREG( buff.st_mode )))
00315 {
00316 hash = hash + (Q_UINT32) buff.st_ctime;
00317 }
00318
return hash;
00319 }
00320
00321 Q_UINT32
KStandardDirs::calcResourceHash(
const char *type,
00322
const QString& filename,
bool deep)
const
00323
{
00324 Q_UINT32 hash = 0;
00325
00326
if (filename.
at(0) ==
'/')
00327 {
00328
00329
return updateHash(filename, hash);
00330 }
00331
if (d && d->restrictionsActive && (strcmp(type,
"data")==0))
00332 applyDataRestrictions(filename);
00333
QStringList candidates =
resourceDirs(type);
00334
QString fullPath;
00335
00336
for (QStringList::ConstIterator it = candidates.begin();
00337 it != candidates.end(); it++)
00338 {
00339 hash = updateHash(*it + filename, hash);
00340
if (!deep && hash)
00341
return hash;
00342 }
00343
return hash;
00344 }
00345
00346
00347 QStringList KStandardDirs::findDirs(
const char *type,
00348
const QString& reldir )
const
00349
{
00350
QDir testdir;
00351
QStringList list;
00352
if (reldir.
startsWith(
"/"))
00353 {
00354 testdir.
setPath(reldir);
00355
if (testdir.
exists())
00356 {
00357
if (reldir.
endsWith(
"/"))
00358 list.append(reldir);
00359
else
00360 list.append(reldir+
'/');
00361 }
00362
return list;
00363 }
00364
00365 checkConfig();
00366
00367
if (d && d->restrictionsActive && (strcmp(type,
"data")==0))
00368 applyDataRestrictions(reldir);
00369
QStringList candidates =
resourceDirs(type);
00370
00371
for (QStringList::ConstIterator it = candidates.begin();
00372 it != candidates.end(); it++) {
00373 testdir.
setPath(*it + reldir);
00374
if (testdir.
exists())
00375 list.append(testdir.
absPath() +
'/');
00376 }
00377
00378
return list;
00379 }
00380
00381 QString KStandardDirs::findResourceDir(
const char *type,
00382
const QString& filename)
const
00383
{
00384
#ifndef NDEBUG
00385
if (filename.
isEmpty()) {
00386 kdWarning() <<
"filename for type " << type <<
" in KStandardDirs::findResourceDir is not supposed to be empty!!" <<
endl;
00387
return QString::null;
00388 }
00389
#endif
00390
00391
if (d && d->restrictionsActive && (strcmp(type,
"data")==0))
00392 applyDataRestrictions(filename);
00393
QStringList candidates =
resourceDirs(type);
00394
QString fullPath;
00395
00396
for (QStringList::ConstIterator it = candidates.begin();
00397 it != candidates.end(); it++)
00398
if (
exists(*it + filename))
00399
return *it;
00400
00401
#ifndef NDEBUG
00402
if(
false && type !=
"locale")
00403 kdDebug() <<
"KStdDirs::findResDir(): can't find \"" << filename <<
"\" in type \"" << type <<
"\"." <<
endl;
00404
#endif
00405
00406
return QString::null;
00407 }
00408
00409 bool KStandardDirs::exists(
const QString &fullPath)
00410 {
00411
struct stat buff;
00412
if (access(QFile::encodeName(fullPath), R_OK) == 0 && stat( QFile::encodeName(fullPath), &buff ) == 0)
00413
if (fullPath.at(fullPath.length() - 1) !=
'/') {
00414
if (S_ISREG( buff.st_mode ))
00415
return true;
00416 }
else
00417
if (S_ISDIR( buff.st_mode ))
00418
return true;
00419
return false;
00420 }
00421
00422
static void lookupDirectory(
const QString& path,
const QString &relPart,
00423
const QRegExp ®exp,
00424
QStringList& list,
00425
QStringList& relList,
00426
bool recursive,
bool unique)
00427 {
00428
QString pattern = regexp.
pattern();
00429
if (recursive || pattern.
contains(
'?') || pattern.
contains(
'*'))
00430 {
00431
00432 DIR *dp = opendir( QFile::encodeName(path));
00433
if (!dp)
00434
return;
00435
00436 assert(path.
at(path.
length() - 1) ==
'/');
00437
00438
struct dirent *ep;
00439
struct stat buff;
00440
00441
QString _dot(
".");
00442
QString _dotdot(
"..");
00443
00444
while( ( ep = readdir( dp ) ) != 0L )
00445 {
00446
QString fn( QFile::decodeName(ep->d_name));
00447
if (fn == _dot || fn == _dotdot || fn.
at(fn.
length() - 1).latin1() ==
'~')
00448
continue;
00449
00450
if (!recursive && !regexp.
exactMatch(fn))
00451
continue;
00452
00453
QString pathfn = path + fn;
00454
if ( stat( QFile::encodeName(pathfn), &buff ) != 0 ) {
00455 kdDebug() <<
"Error stat'ing " << pathfn <<
" : " << perror <<
endl;
00456
continue;
00457 }
00458
if ( recursive ) {
00459
if ( S_ISDIR( buff.st_mode )) {
00460 lookupDirectory(pathfn +
'/', relPart + fn +
'/', regexp, list, relList, recursive, unique);
00461 }
00462
if (!regexp.
exactMatch(fn))
00463
continue;
00464 }
00465
if ( S_ISREG( buff.st_mode))
00466 {
00467
if (!unique || !relList.contains(relPart + fn))
00468 {
00469 list.append( pathfn );
00470 relList.append( relPart + fn );
00471 }
00472 }
00473 }
00474 closedir( dp );
00475 }
00476
else
00477 {
00478
00479
QString fn = pattern;
00480
QString pathfn = path + fn;
00481
struct stat buff;
00482
if (
stat( QFile::encodeName(pathfn), &buff ) != 0 )
00483
return;
00484
if ( S_ISREG( buff.st_mode))
00485 {
00486
if (!unique || !relList.contains(relPart + fn))
00487 {
00488 list.append( pathfn );
00489 relList.append( relPart + fn );
00490 }
00491 }
00492 }
00493 }
00494
00495
static void lookupPrefix(
const QString& prefix,
const QString& relpath,
00496
const QString& relPart,
00497
const QRegExp ®exp,
00498
QStringList& list,
00499
QStringList& relList,
00500
bool recursive,
bool unique)
00501 {
00502
if (relpath.
isNull()) {
00503 lookupDirectory(prefix, relPart, regexp, list,
00504 relList, recursive, unique);
00505
return;
00506 }
00507
QString path;
00508
QString rest;
00509
00510
if (relpath.
length())
00511 {
00512
int slash = relpath.
find(
'/');
00513
if (slash < 0)
00514 rest = relpath.
left(relpath.
length() - 1);
00515
else {
00516 path = relpath.
left(slash);
00517 rest = relpath.
mid(slash + 1);
00518 }
00519 }
00520
00521 assert(prefix.
at(prefix.
length() - 1) ==
'/');
00522
00523
struct stat buff;
00524
00525
if (path.
contains(
'*') || path.
contains(
'?')) {
00526
00527
QRegExp pathExp(path,
true,
true);
00528 DIR *dp = opendir( QFile::encodeName(prefix) );
00529
if (!dp) {
00530
return;
00531 }
00532
00533
struct dirent *ep;
00534
00535
QString _dot(
".");
00536
QString _dotdot(
"..");
00537
00538
while( ( ep = readdir( dp ) ) != 0L )
00539 {
00540
QString fn( QFile::decodeName(ep->d_name));
00541
if (fn == _dot || fn == _dotdot || fn.
at(fn.
length() - 1) ==
'~')
00542
continue;
00543
00544
if (pathExp.
search(fn) == -1)
00545
continue;
00546
QString rfn = relPart+fn;
00547 fn = prefix + fn;
00548
if (
stat( QFile::encodeName(fn), &buff ) != 0 ) {
00549 kdDebug() <<
"Error statting " << fn <<
" : " << perror <<
endl;
00550
continue;
00551 }
00552
if ( S_ISDIR( buff.st_mode ))
00553 lookupPrefix(fn +
'/', rest, rfn +
'/', regexp, list, relList, recursive, unique);
00554 }
00555
00556 closedir( dp );
00557 }
else {
00558
00559
00560 lookupPrefix(prefix + path +
'/', rest,
00561 relPart + path +
'/', regexp, list,
00562 relList, recursive, unique);
00563 }
00564 }
00565
00566
QStringList
00567 KStandardDirs::findAllResources(
const char *type,
00568
const QString& filter,
00569
bool recursive,
00570
bool unique,
00571
QStringList &relList)
const
00572
{
00573
QStringList list;
00574
QString filterPath;
00575
QString filterFile;
00576
00577
if (filter.
length())
00578 {
00579
int slash = filter.
findRev(
'/');
00580
if (slash < 0)
00581 filterFile = filter;
00582
else {
00583 filterPath = filter.
left(slash + 1);
00584 filterFile = filter.
mid(slash + 1);
00585 }
00586 }
00587
00588 checkConfig();
00589
00590
QStringList candidates;
00591
if (filterPath.
startsWith(
"/"))
00592 {
00593 filterPath = filterPath.
mid(1);
00594 candidates <<
"/";
00595 }
00596
else
00597 {
00598
if (d && d->restrictionsActive && (strcmp(type,
"data")==0))
00599 applyDataRestrictions(filter);
00600 candidates =
resourceDirs(type);
00601 }
00602
if (filterFile.
isEmpty())
00603 filterFile =
"*";
00604
00605
QRegExp regExp(filterFile,
true,
true);
00606
00607
for (QStringList::ConstIterator it = candidates.begin();
00608 it != candidates.end(); it++)
00609 {
00610 lookupPrefix(*it, filterPath,
"", regExp, list,
00611 relList, recursive, unique);
00612 }
00613
00614
return list;
00615 }
00616
00617
QStringList
00618 KStandardDirs::findAllResources(
const char *type,
00619
const QString& filter,
00620
bool recursive,
00621
bool unique)
const
00622
{
00623
QStringList relList;
00624
return findAllResources(type, filter, recursive, unique, relList);
00625 }
00626
00627
QString
00628 KStandardDirs::realPath(
const QString &dirname)
00629 {
00630
char realpath_buffer[MAXPATHLEN + 1];
00631 memset(realpath_buffer, 0, MAXPATHLEN + 1);
00632
00633
00634
if (realpath( QFile::encodeName(dirname).data(), realpath_buffer) != 0) {
00635
00636
int len = strlen(realpath_buffer);
00637 realpath_buffer[len] =
'/';
00638 realpath_buffer[len+1] = 0;
00639
return QFile::decodeName(realpath_buffer);
00640 }
00641
00642
return dirname;
00643 }
00644
00645
void KStandardDirs::createSpecialResource(
const char *type)
00646 {
00647
char hostname[256];
00648 hostname[0] = 0;
00649 gethostname(hostname, 255);
00650
QString dir =
QString(
"%1%2-%3").arg(
localkdedir()).arg(type).arg(hostname);
00651
char link[1024];
00652 link[1023] = 0;
00653
int result = readlink(QFile::encodeName(dir).data(), link, 1023);
00654
if ((result == -1) && (errno == ENOENT))
00655 {
00656 QString srv = findExe(QString::fromLatin1(
"lnusertemp"), KDEDIR+QString::fromLatin1(
"/bin"));
00657
if (srv.
isEmpty())
00658 srv = findExe(QString::fromLatin1(
"lnusertemp"));
00659
if (!srv.
isEmpty())
00660 {
00661 system(QFile::encodeName(srv)+
" "+type);
00662 result = readlink(QFile::encodeName(dir).data(), link, 1023);
00663 }
00664 }
00665
if (result > 0)
00666 {
00667
link[result] = 0;
00668
if (
link[0] ==
'/')
00669 dir =
QFile::decodeName(link);
00670
else
00671 dir =
QDir::cleanDirPath(dir+QFile::decodeName(link));
00672 }
00673
addResourceDir(type, dir+
'/');
00674 }
00675
00676 QStringList KStandardDirs::resourceDirs(
const char *type)
const
00677
{
00678
QStringList *candidates = dircache.
find(type);
00679
00680
if (!candidates) {
00681
if (strcmp(type,
"socket") == 0)
00682 const_cast<KStandardDirs *>(
this)->createSpecialResource(type);
00683
else if (strcmp(type,
"tmp") == 0)
00684 const_cast<KStandardDirs *>(
this)->createSpecialResource(type);
00685
else if (strcmp(type,
"cache") == 0)
00686 const_cast<KStandardDirs *>(
this)->createSpecialResource(type);
00687
00688
QDir testdir;
00689
00690 candidates =
new QStringList();
00691 QStringList *dirs;
00692
00693
bool restrictionActive =
false;
00694
if (d && d->restrictionsActive)
00695 {
00696
if (d->dataRestrictionActive)
00697 restrictionActive =
true;
00698
else if (d->restrictions[
"all"])
00699 restrictionActive =
true;
00700
else if (d->restrictions[type])
00701 restrictionActive =
true;
00702 d->dataRestrictionActive =
false;
00703 }
00704
00705 dirs = relatives.
find(type);
00706
if (dirs)
00707 {
00708
bool local =
true;
00709
const QStringList *prefixList = 0;
00710
if (strncmp(type,
"xdgdata-", 8) == 0)
00711 prefixList = &(d->xdgdata_prefixes);
00712
else if (strncmp(type,
"xdgconf-", 8) == 0)
00713 prefixList = &(d->xdgconf_prefixes);
00714
else
00715 prefixList = &prefixes;
00716
00717
for (QStringList::ConstIterator pit = prefixList->begin();
00718 pit != prefixList->end();
00719 pit++)
00720 {
00721
for (QStringList::ConstIterator it = dirs->begin();
00722 it != dirs->end(); ++it) {
00723 QString path =
realPath(*pit + *it);
00724 testdir.
setPath(path);
00725
if (local && restrictionActive)
00726
continue;
00727
if ((local || testdir.
exists()) && !candidates->contains(path))
00728 candidates->append(path);
00729 }
00730
00731
if (local && (
"config" == type))
00732 candidates->append(
"/etc/kde3/");
00733
00734 local =
false;
00735 }
00736 }
00737 dirs = absolutes.
find(type);
00738
if (dirs)
00739
for (QStringList::ConstIterator it = dirs->begin();
00740 it != dirs->end(); ++it)
00741 {
00742 testdir.
setPath(*it);
00743
if (testdir.
exists())
00744 {
00745 QString filename =
realPath(*it);
00746
if (!candidates->contains(filename))
00747 candidates->append(filename);
00748 }
00749 }
00750 dircache.
insert(type, candidates);
00751 }
00752
00753
#if 0
00754
kdDebug() <<
"found dirs for resource " << type <<
":" <<
endl;
00755
for (QStringList::ConstIterator pit = candidates->begin();
00756 pit != candidates->end();
00757 pit++)
00758 {
00759 fprintf(stderr,
"%s\n", (*pit).latin1());
00760 }
00761
#endif
00762
00763
00764
return *candidates;
00765 }
00766
00767 QStringList KStandardDirs::systemPaths(
const QString& pstr )
00768 {
00769
QStringList tokens;
00770 QString p = pstr;
00771
00772
if( p.
isNull() )
00773 {
00774 p = getenv(
"PATH" );
00775 }
00776
00777 tokenize( tokens, p,
":\b" );
00778
00779
QStringList exePaths;
00780
00781
00782
for(
unsigned i = 0; i < tokens.count(); i++ )
00783 {
00784 p = tokens[ i ];
00785
00786
if ( p[ 0 ] ==
'~' )
00787 {
00788
int len = p.
find(
'/' );
00789
if ( len == -1 )
00790 len = p.
length();
00791
if ( len == 1 )
00792 {
00793 p.
replace( 0, 1, QDir::homeDirPath() );
00794 }
00795
else
00796 {
00797 QString user = p.
mid( 1, len - 1 );
00798
struct passwd *dir = getpwnam( user.
local8Bit().data() );
00799
if ( dir && strlen( dir->pw_dir ) )
00800 p.
replace( 0, len, QString::fromLocal8Bit( dir->pw_dir ) );
00801 }
00802 }
00803
00804 exePaths << p;
00805 }
00806
00807
return exePaths;
00808 }
00809
00810
00811 QString
KStandardDirs::findExe(
const QString& appname,
00812
const QString& pstr,
bool ignore)
00813 {
00814
QFileInfo info;
00815
00816
00817
if (appname.
startsWith(QString::fromLatin1(
"/")))
00818 {
00819 info.
setFile( appname );
00820
if( info.
exists() && ( ignore || info.
isExecutable() )
00821 && info.
isFile() ) {
00822
return appname;
00823 }
00824
return QString::null;
00825 }
00826
00827 QString p = QString(
"%1/%2").
arg(__KDE_BINDIR).arg(appname);
00828 info.
setFile( p );
00829
if( info.
exists() && ( ignore || info.
isExecutable() )
00830 && ( info.
isFile() || info.
isSymLink() ) ) {
00831
return p;
00832 }
00833
00834
QStringList exePaths =
systemPaths( pstr );
00835
for (QStringList::ConstIterator it = exePaths.begin(); it != exePaths.end(); it++)
00836 {
00837 p = (*it) +
"/";
00838 p += appname;
00839
00840
00841 info.
setFile( p );
00842
00843
if( info.
exists() && ( ignore || info.
isExecutable() )
00844 && ( info.
isFile() || info.
isSymLink() ) ) {
00845
return p;
00846 }
00847 }
00848
00849
00850
00851
00852
return QString::null;
00853 }
00854
00855 int KStandardDirs::findAllExe(
QStringList& list,
const QString& appname,
00856
const QString& pstr,
bool ignore )
00857 {
00858
QFileInfo info;
00859 QString p;
00860 list.clear();
00861
00862
QStringList exePaths =
systemPaths( pstr );
00863
for (QStringList::ConstIterator it = exePaths.begin(); it != exePaths.end(); it++)
00864 {
00865 p = (*it) +
"/";
00866 p += appname;
00867
00868 info.
setFile( p );
00869
00870
if( info.
exists() && (ignore || info.
isExecutable())
00871 && info.
isFile() ) {
00872 list.append( p );
00873 }
00874 }
00875
00876
return list.count();
00877 }
00878
00879
static int tokenize(
QStringList& tokens,
const QString& str,
00880
const QString& delim )
00881 {
00882
int len = str.
length();
00883 QString token =
"";
00884
00885
for(
int index = 0; index < len; index++)
00886 {
00887
if ( delim.
find( str[ index ] ) >= 0 )
00888 {
00889 tokens.append( token );
00890 token =
"";
00891 }
00892
else
00893 {
00894 token += str[ index ];
00895 }
00896 }
00897
if ( token.
length() > 0 )
00898 {
00899 tokens.append( token );
00900 }
00901
00902
return tokens.count();
00903 }
00904
00905 QString
KStandardDirs::kde_default(
const char *type) {
00906
if (!strcmp(type,
"data"))
00907
return "share/apps/";
00908
if (!strcmp(type,
"html"))
00909
return "share/doc/kde/HTML/";
00910
if (!strcmp(type,
"icon"))
00911
return "share/icons/";
00912
if (!strcmp(type,
"config"))
00913
return "share/config/";
00914
if (!strcmp(type,
"pixmap"))
00915
return "share/pixmaps/";
00916
if (!strcmp(type,
"apps"))
00917
return "share/applnk/";
00918
if (!strcmp(type,
"sound"))
00919
return "share/sounds/";
00920
if (!strcmp(type,
"locale"))
00921
return "share/locale/";
00922
if (!strcmp(type,
"services"))
00923
return "share/services/";
00924
if (!strcmp(type,
"servicetypes"))
00925
return "share/servicetypes/";
00926
if (!strcmp(type,
"mime"))
00927
return "share/mimelnk/";
00928
if (!strcmp(type,
"cgi"))
00929
return "lib/cgi-bin/";
00930
if (!strcmp(type,
"wallpaper"))
00931
return "share/wallpapers/";
00932
if (!strcmp(type,
"templates"))
00933
return "share/templates/";
00934
if (!strcmp(type,
"exe"))
00935
return "bin/";
00936
if (!strcmp(type,
"lib"))
00937
return "lib/";
00938
if (!strcmp(type,
"module"))
00939
return "lib/kde3/";
00940
if (!strcmp(type,
"qtplugins"))
00941
return "lib/kde3/plugins";
00942
if (!strcmp(type,
"xdgdata-apps"))
00943
return "applications/";
00944
if (!strcmp(type,
"xdgdata-dirs"))
00945
return "desktop-directories/";
00946
if (!strcmp(type,
"xdgconf-menu"))
00947
return "menus/";
00948
if (!strcmp(type,
"kcfg"))
00949
return "share/config.kcfg";
00950 qFatal(
"unknown resource type %s", type);
00951
return QString::null;
00952 }
00953
00954 QString
KStandardDirs::saveLocation(
const char *type,
00955
const QString& suffix,
00956
bool create)
const
00957
{
00958 checkConfig();
00959
00960 QString *pPath = savelocations.
find(type);
00961
if (!pPath)
00962 {
00963
QStringList *dirs = relatives.
find(type);
00964
if (!dirs && (
00965 (strcmp(type,
"socket") == 0) ||
00966 (strcmp(type,
"tmp") == 0) ||
00967 (strcmp(type,
"cache") == 0) ))
00968 {
00969 (
void)
resourceDirs(type);
00970 dirs = relatives.
find(type);
00971 }
00972
if (dirs)
00973 {
00974
00975
if (strncmp(type,
"xdgdata-", 8) == 0)
00976 pPath =
new QString(
realPath(
localxdgdatadir() + dirs->last()));
00977
else if (strncmp(type,
"xdgconf-", 8) == 0)
00978 pPath =
new QString(
realPath(
localxdgconfdir() + dirs->last()));
00979
else
00980 pPath =
new QString(
realPath(
localkdedir() + dirs->last()));
00981 }
00982
else {
00983 dirs = absolutes.
find(type);
00984
if (!dirs)
00985 qFatal(
"KStandardDirs: The resource type %s is not registered", type);
00986 pPath =
new QString(
realPath(dirs->last()));
00987 }
00988
00989 savelocations.
insert(type, pPath);
00990 }
00991 QString fullPath = *pPath + suffix;
00992
00993
struct stat st;
00994
if (stat(QFile::encodeName(fullPath), &st) != 0 || !(S_ISDIR(st.st_mode))) {
00995
if(!create) {
00996
#ifndef NDEBUG
00997
qDebug(
"save location %s doesn't exist", fullPath.latin1());
00998
#endif
00999
return fullPath;
01000 }
01001
if(!
makeDir(fullPath, 0700)) {
01002 qWarning(
"failed to create %s", fullPath.latin1());
01003
return fullPath;
01004 }
01005 dircache.
remove(type);
01006 }
01007
return fullPath;
01008 }
01009
01010 QString
KStandardDirs::relativeLocation(
const char *type,
const QString &absPath)
01011 {
01012 QString fullPath = absPath;
01013
int i = absPath.
findRev(
'/');
01014
if (i != -1)
01015 {
01016 fullPath =
realPath(absPath.
left(i+1))+absPath.
mid(i+1);
01017 }
01018
01019
QStringList candidates =
resourceDirs(type);
01020
01021
for (QStringList::ConstIterator it = candidates.begin();
01022 it != candidates.end(); it++)
01023
if (fullPath.
startsWith(*it))
01024 {
01025
return fullPath.
mid((*it).length());
01026 }
01027
01028
return absPath;
01029 }
01030
01031
01032 bool KStandardDirs::makeDir(
const QString& dir,
int mode)
01033 {
01034
01035
if (dir.
at(0) !=
'/')
01036
return false;
01037
01038 QString target = dir;
01039 uint len = target.
length();
01040
01041
01042
if (dir.
at(len - 1) !=
'/')
01043 target +=
'/';
01044
01045 QString base(
"");
01046 uint i = 1;
01047
01048
while( i < len )
01049 {
01050
struct stat st;
01051
int pos = target.
find(
'/', i);
01052 base += target.
mid(i - 1, pos - i + 1);
01053
QCString baseEncoded = QFile::encodeName(base);
01054
01055
if (stat(baseEncoded, &st) != 0)
01056 {
01057
01058
01059
if (lstat(baseEncoded, &st) == 0)
01060 (
void)unlink(baseEncoded);
01061
01062
if ( mkdir(baseEncoded, (mode_t) mode) != 0) {
01063 perror(
"trying to create local folder");
01064
return false;
01065 }
01066 }
01067 i = pos + 1;
01068 }
01069
return true;
01070 }
01071
01072
static QString readEnvPath(
const char *env)
01073 {
01074
QCString c_path = getenv(env);
01075
if (c_path.
isEmpty())
01076
return QString::null;
01077
return QFile::decodeName(c_path);
01078 }
01079
01080 void KStandardDirs::addKDEDefaults()
01081 {
01082
QStringList kdedirList;
01083
01084
01085 QString kdedirs = readEnvPath(
"KDEDIRS");
01086
if (!kdedirs.
isEmpty())
01087 {
01088 tokenize(kdedirList, kdedirs,
":");
01089 }
01090
else
01091 {
01092 QString kdedir = readEnvPath(
"KDEDIR");
01093
if (!kdedir.
isEmpty())
01094 {
01095 kdedir =
KShell::tildeExpand(kdedir);
01096 kdedirList.append(kdedir);
01097 }
01098 }
01099
01100 kdedirList.append(
"/usr/local");
01101
01102 kdedirList.append(KDEDIR);
01103
01104
#ifdef __KDE_EXECPREFIX
01105
QString execPrefix(__KDE_EXECPREFIX);
01106
if (execPrefix!=
"NONE")
01107 kdedirList.append(execPrefix);
01108
#endif
01109
01110
01111
01112 QString localKdeDir = readEnvPath(getuid() ?
"KDEHOME" :
"KDEROOTHOME");
01113
if (!localKdeDir.
isEmpty())
01114 {
01115
if (localKdeDir[localKdeDir.
length()-1] !=
'/')
01116 localKdeDir +=
'/';
01117 }
01118
else
01119 {
01120 localKdeDir =
QDir::homeDirPath() +
"/.kde/";
01121 }
01122
01123
if (localKdeDir !=
"-/")
01124 {
01125 localKdeDir =
KShell::tildeExpand(localKdeDir);
01126
addPrefix(localKdeDir);
01127 }
01128
01129
for (QStringList::ConstIterator it = kdedirList.begin();
01130 it != kdedirList.end(); it++)
01131 {
01132 QString dir =
KShell::tildeExpand(*it);
01133
addPrefix(dir);
01134 }
01135
01136
01137
01138
QStringList xdgdirList;
01139 QString xdgdirs = readEnvPath(
"XDG_CONFIG_DIRS");
01140
if (!xdgdirs.
isEmpty())
01141 {
01142 tokenize(xdgdirList, xdgdirs,
":");
01143 }
01144
else
01145 {
01146 xdgdirList.clear();
01147 xdgdirList.append(
"/etc/xdg");
01148 xdgdirList.append(KDESYSCONFDIR
"/xdg");
01149 }
01150
01151 QString localXdgDir = readEnvPath(
"XDG_CONFIG_HOME");
01152
if (!localXdgDir.
isEmpty())
01153 {
01154
if (localXdgDir[localXdgDir.
length()-1] !=
'/')
01155 localXdgDir +=
'/';
01156 }
01157
else
01158 {
01159 localXdgDir =
QDir::homeDirPath() +
"/.config/";
01160 }
01161
01162 localXdgDir =
KShell::tildeExpand(localXdgDir);
01163
addXdgConfigPrefix(localXdgDir);
01164
01165
for (QStringList::ConstIterator it = xdgdirList.begin();
01166 it != xdgdirList.end(); it++)
01167 {
01168 QString dir =
KShell::tildeExpand(*it);
01169
addXdgConfigPrefix(dir);
01170 }
01171
01172
01173
01174 xdgdirs = readEnvPath(
"XDG_DATA_DIRS");
01175
if (!xdgdirs.
isEmpty())
01176 {
01177 tokenize(xdgdirList, xdgdirs,
":");
01178 }
01179
else
01180 {
01181 xdgdirList.clear();
01182
for (QStringList::ConstIterator it = kdedirList.begin();
01183 it != kdedirList.end(); it++)
01184 {
01185 QString dir = *it;
01186
if (dir[dir.
length()-1] !=
'/')
01187 dir +=
'/';
01188 xdgdirList.append(dir+
"share/");
01189 }
01190
01191 xdgdirList.append(
"/usr/local/share/");
01192 xdgdirList.append(
"/usr/share/");
01193 }
01194
01195 localXdgDir = readEnvPath(
"XDG_DATA_HOME");
01196
if (!localXdgDir.
isEmpty())
01197 {
01198
if (localXdgDir[localXdgDir.
length()-1] !=
'/')
01199 localXdgDir +=
'/';
01200 }
01201
else
01202 {
01203 localXdgDir =
QDir::homeDirPath() +
"/.local/share/";
01204 }
01205
01206 localXdgDir =
KShell::tildeExpand(localXdgDir);
01207
addXdgDataPrefix(localXdgDir);
01208
01209
for (QStringList::ConstIterator it = xdgdirList.begin();
01210 it != xdgdirList.end(); it++)
01211 {
01212 QString dir =
KShell::tildeExpand(*it);
01213
addXdgDataPrefix(dir);
01214 }
01215
01216
01217
01218 uint index = 0;
01219
while (types[index] != 0) {
01220
addResourceType(types[index],
kde_default(types[index]));
01221 index++;
01222 }
01223
01224
addResourceDir(
"home", QDir::homeDirPath());
01225 }
01226
01227
void KStandardDirs::checkConfig()
const
01228
{
01229
if (!addedCustoms && KGlobal::_instance && KGlobal::_instance->
_config)
01230 const_cast<KStandardDirs*>(
this)->addCustomized(KGlobal::_instance->_config);
01231 }
01232
01233
static QStringList lookupProfiles(
const QString &mapFile)
01234 {
01235
QStringList profiles;
01236
01237
if (mapFile.
isEmpty() || !
QFile::exists(mapFile))
01238 {
01239 profiles <<
"default";
01240
return profiles;
01241 }
01242
01243
struct passwd *pw = getpwuid(geteuid());
01244
if (!pw)
01245 {
01246 profiles <<
"default";
01247
return profiles;
01248 }
01249
01250
QCString user = pw->pw_name;
01251
01252
KSimpleConfig mapCfg(mapFile,
true);
01253 mapCfg.
setGroup(
"Users");
01254
if (mapCfg.
hasKey(user.data()))
01255 {
01256 profiles = mapCfg.
readListEntry(user.data());
01257
return profiles;
01258 }
01259
01260 mapCfg.
setGroup(
"General");
01261
QStringList groups = mapCfg.
readListEntry(
"groups");
01262
01263 mapCfg.
setGroup(
"Groups");
01264
01265
for( QStringList::ConstIterator it = groups.begin();
01266 it != groups.end(); ++it )
01267 {
01268
QCString grp = (*it).utf8();
01269
01270
struct group *grp_ent = getgrnam(grp);
01271
if (!grp_ent)
continue;
01272
01273
char ** members = grp_ent->gr_mem;
01274
for(
char * member; (member = *members); ++members)
01275 {
01276
if (user == member)
01277 {
01278
01279 profiles += mapCfg.
readListEntry(*it);
01280
break;
01281 }
01282 }
01283 }
01284
01285
if (profiles.isEmpty())
01286 profiles <<
"default";
01287
return profiles;
01288 }
01289
01290
extern bool kde_kiosk_admin;
01291
01292 bool KStandardDirs::addCustomized(
KConfig *config)
01293 {
01294
if (addedCustoms)
01295
return false;
01296
01297
01298 addedCustoms =
true;
01299
01300
01301
01302 uint configdirs =
resourceDirs(
"config").count();
01303
01304
01305 QString oldGroup = config->
group();
01306 QString group = QString::fromLatin1(
"Directories");
01307 config->
setGroup(group);
01308
01309 QString kioskAdmin = config->
readEntry(
"kioskAdmin");
01310
if (!kioskAdmin.
isEmpty() && !kde_kiosk_admin)
01311 {
01312
int i = kioskAdmin.
find(
':');
01313 QString user = kioskAdmin.
left(i);
01314 QString host = kioskAdmin.
mid(i+1);
01315
01316
KUser thisUser;
01317
char hostname[ 256 ];
01318 hostname[ 0 ] =
'\0';
01319
if (!gethostname( hostname, 255 ))
01320 hostname[
sizeof(hostname)-1] =
'\0';
01321
01322
if ((user == thisUser.
loginName()) &&
01323 (host.
isEmpty() || (host == hostname)))
01324 {
01325 kde_kiosk_admin =
true;
01326 }
01327 }
01328
01329
bool readProfiles =
true;
01330
01331
if (kde_kiosk_admin && !
QCString(getenv(
"KDE_KIOSK_NO_PROFILES")).isEmpty())
01332 readProfiles =
false;
01333
01334 QString userMapFile = config->
readEntry(
"userProfileMapFile");
01335
01336
QStringList profiles;
01337
if (readProfiles)
01338 profiles = lookupProfiles(userMapFile);
01339
01340
bool priority =
false;
01341
while(
true)
01342 {
01343 config->
setGroup(group);
01344
QStringList list = config->
readListEntry(
"prefixes");
01345
for (QStringList::ConstIterator it = list.begin(); it != list.end(); it++)
01346 {
01347
addPrefix(*it, priority);
01348
addXdgConfigPrefix(*it+
"/etc/xdg", priority);
01349 }
01350
01351
01352
01353
QMap<QString, QString> entries = config->
entryMap(group);
01354
for (
QMap<QString, QString>::ConstIterator it2 = entries.
begin();
01355 it2 != entries.
end(); it2++)
01356 {
01357 QString key = it2.key();
01358
if (key.startsWith(
"dir_")) {
01359
01360
QStringList dirs = QStringList::split(
',',
01361 *it2);
01362 QStringList::Iterator sIt(dirs.begin());
01363 QString resType = key.mid(4, key.length());
01364
for (; sIt != dirs.end(); ++sIt) {
01365
addResourceDir(resType.
latin1(), *sIt, priority);
01366 }
01367 }
01368 }
01369
if (profiles.isEmpty())
01370
break;
01371 group = QString::fromLatin1(
"Directories-%1").arg(profiles.back());
01372 profiles.pop_back();
01373 priority =
true;
01374 }
01375
01376
01377
if (!kde_kiosk_admin ||
QCString(getenv(
"KDE_KIOSK_NO_RESTRICTIONS")).isEmpty())
01378 {
01379 config->
setGroup(
"KDE Resource Restrictions");
01380
QMap<QString, QString> entries = config->
entryMap(
"KDE Resource Restrictions");
01381
for (
QMap<QString, QString>::ConstIterator it2 = entries.
begin();
01382 it2 != entries.
end(); it2++)
01383 {
01384 QString key = it2.key();
01385
if (!config->
readBoolEntry(key,
true))
01386 {
01387 d->restrictionsActive =
true;
01388 d->restrictions.insert(key.latin1(), &d->restrictionsActive);
01389 dircache.
remove(key.latin1());
01390 }
01391 }
01392 }
01393
01394 config->
setGroup(oldGroup);
01395
01396
01397
return (resourceDirs(
"config").count() != configdirs);
01398 }
01399
01400 QString
KStandardDirs::localkdedir()
const
01401
{
01402
01403
return prefixes.first();
01404 }
01405
01406 QString
KStandardDirs::localxdgdatadir()
const
01407
{
01408
01409
return d->xdgdata_prefixes.first();
01410 }
01411
01412 QString
KStandardDirs::localxdgconfdir()
const
01413
{
01414
01415
return d->xdgconf_prefixes.first();
01416 }
01417
01418
01419 QString locate(
const char *type,
01420
const QString& filename,
const KInstance* inst )
01421 {
01422
return inst->
dirs()->
findResource(type, filename);
01423 }
01424
01425 QString locateLocal(
const char *type,
01426
const QString& filename,
const KInstance* inst )
01427 {
01428
return locateLocal(type, filename,
true, inst);
01429 }
01430
01431 QString locateLocal(
const char *type,
01432
const QString& filename,
bool createDir,
const KInstance* inst )
01433 {
01434
01435
01436
int slash = filename.
findRev(
'/')+1;
01437
if (!slash)
01438
return inst->
dirs()->
saveLocation(type, QString::null, createDir) + filename;
01439
01440
01441 QString dir = filename.
left(slash);
01442 QString file = filename.
mid(slash);
01443
return inst->
dirs()->
saveLocation(type, dir, createDir) + file;
01444 }