• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.14.38 API Reference
  • KDE Home
  • Contact Us
 

KDECore

  • kdecore
  • kernel
kstandarddirs.cpp
Go to the documentation of this file.
1/* This file is part of the KDE libraries
2 Copyright (C) 1999 Sirtaj Singh Kang <taj@kde.org>
3 Copyright (C) 1999,2007 Stephan Kulow <coolo@kde.org>
4 Copyright (C) 1999 Waldo Bastian <bastian@kde.org>
5 Copyright (C) 2009 David Faure <faure@kde.org>
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public
9 License version 2 as published by the Free Software Foundation.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20*/
21
22/*
23 * Author: Stephan Kulow <coolo@kde.org> and Sirtaj Singh Kang <taj@kde.org>
24 * Generated: Thu Mar 5 16:05:28 EST 1998
25 */
26
27#include "kstandarddirs.h"
28#include "kconfig.h"
29#include "kconfiggroup.h"
30#include "kdebug.h"
31#include "kcomponentdata.h"
32#include "kshell.h"
33#include "kuser.h"
34#include "kde_file.h"
35#include "kkernel_win.h"
36#include "kkernel_mac.h"
37#include "klocale.h"
38
39#include <config.h>
40#include <config-prefix.h>
41#include <config-kstandarddirs.h>
42
43#include <stdlib.h>
44#include <assert.h>
45#include <errno.h>
46#ifdef HAVE_SYS_STAT_H
47#include <sys/stat.h>
48#endif
49#ifdef HAVE_UNISTD_H
50#include <unistd.h>
51#endif
52#include <sys/param.h>
53#include <sys/types.h>
54#include <dirent.h>
55#include <pwd.h>
56#include <grp.h>
57#ifdef Q_WS_WIN
58#include <windows.h>
59#ifdef _WIN32_WCE
60#include <basetyps.h>
61#endif
62#ifdef Q_WS_WIN64
63// FIXME: did not find a reliable way to fix with kdewin mingw header
64#define interface struct
65#endif
66#include <shlobj.h>
67#include <QtCore/QVarLengthArray>
68#endif
69
70#include <QtCore/QMutex>
71#include <QtCore/QRegExp>
72#include <QtCore/QDir>
73#include <QtCore/QFileInfo>
74#include <QtCore/QSettings>
75
76#ifdef Q_OS_WIN
77static Qt::CaseSensitivity cs = Qt::CaseInsensitive;
78#else
79static Qt::CaseSensitivity cs = Qt::CaseSensitive;
80#endif
81
82class KStandardDirs::KStandardDirsPrivate
83{
84public:
85 KStandardDirsPrivate(KStandardDirs* qq)
86 : m_restrictionsActive(false),
87 m_checkRestrictions(true),
88 m_cacheMutex(QMutex::Recursive), // resourceDirs is recursive
89 q(qq)
90 { }
91
92 bool hasDataRestrictions(const QString &relPath) const;
93 QStringList resourceDirs(const char* type, const QString& subdirForRestrictions);
94 void createSpecialResource(const char*);
95
96 bool m_restrictionsActive : 1;
97 bool m_checkRestrictions : 1;
98 QMap<QByteArray, bool> m_restrictions;
99
100 QStringList xdgdata_prefixes;
101 QStringList xdgconf_prefixes;
102 QStringList m_prefixes;
103
104 // Directory dictionaries
105 QMap<QByteArray, QStringList> m_absolutes; // For each resource type, the list of absolute paths, from most local (most priority) to most global
106 QMap<QByteArray, QStringList> m_relatives; // Same with relative paths
107 // The search path is "all relative paths" < "all absolute paths", from most priority to least priority.
108
109 // Caches (protected by mutex in const methods, cf ctor docu)
110 QMap<QByteArray, QStringList> m_dircache;
111 QMap<QByteArray, QString> m_savelocations;
112 QMutex m_cacheMutex;
113
114 KStandardDirs* q;
115};
116
117/* If you add a new resource type here, make sure to
118 * 1) regenerate using "kdesdk/scripts/generate_string_table.pl types < tmpfile" with the data below in tmpfile.
119 * 2) update the KStandardDirs class documentation
120 * 3) update the list in kde-config.cpp
121
122data
123share/apps
124html
125share/doc/HTML
126icon
127share/icons
128config
129share/config
130pixmap
131share/pixmaps
132apps
133share/applnk
134sound
135share/sounds
136locale
137share/locale
138services
139share/kde4/services
140servicetypes
141share/kde4/servicetypes
142mime
143share/mimelnk
144cgi
145cgi-bin
146wallpaper
147share/wallpapers
148templates
149share/templates
150exe
151bin
152module
153%lib/kde4
154qtplugins
155%lib/kde4/plugins
156kcfg
157share/config.kcfg
158emoticons
159share/emoticons
160xdgdata-apps
161applications
162xdgdata-icon
163icons
164xdgdata-pixmap
165pixmaps
166xdgdata-dirs
167desktop-directories
168xdgdata-mime
169mime
170xdgconf-menu
171menus
172xdgconf-autostart
173autostart
174*/
175
176static const char types_string[] =
177 "data\0"
178 "share/apps\0"
179 "html\0"
180 "share/doc/HTML\0"
181 "icon\0"
182 "share/icons\0"
183 "config\0"
184 "share/config\0"
185 "pixmap\0"
186 "share/pixmaps\0"
187 "apps\0"
188 "share/applnk\0"
189 "sound\0"
190 "share/sounds\0"
191 "locale\0"
192 "share/locale\0"
193 "services\0"
194 "share/kde4/services\0"
195 "servicetypes\0"
196 "share/kde4/servicetypes\0"
197 "mime\0"
198 "share/mimelnk\0"
199 "cgi\0"
200 "cgi-bin\0"
201 "wallpaper\0"
202 "share/wallpapers\0"
203 "templates\0"
204 "share/templates\0"
205 "exe\0"
206 "bin\0"
207 "module\0"
208 "%lib/kde4\0"
209 "qtplugins\0"
210 "%lib/kde4/plugins\0"
211 "kcfg\0"
212 "share/config.kcfg\0"
213 "emoticons\0"
214 "share/emoticons\0"
215 "xdgdata-apps\0"
216 "applications\0"
217 "xdgdata-icon\0"
218 "icons\0"
219 "xdgdata-pixmap\0"
220 "pixmaps\0"
221 "xdgdata-dirs\0"
222 "desktop-directories\0"
223 "xdgdata-mime\0"
224 "xdgconf-menu\0"
225 "menus\0"
226 "xdgconf-autostart\0"
227 "autostart\0"
228 "\0";
229
230static const int types_indices[] = {
231 0, 5, 16, 21, 36, 41, 53, 60,
232 73, 80, 94, 99, 112, 118, 131, 138,
233 151, 160, 180, 193, 217, 222, 236, 240,
234 248, 258, 275, 285, 301, 305, 309, 316,
235 326, 336, 354, 359, 377, 387, 403, 416,
236 429, 442, 448, 463, 471, 484, 504, 217,
237 517, 530, 536, 554, -1
238};
239
240static void tokenize(QStringList& token, const QString& str,
241 const QString& delim);
242
243KStandardDirs::KStandardDirs()
244 : d(new KStandardDirsPrivate(this))
245{
246 addKDEDefaults();
247}
248
249KStandardDirs::~KStandardDirs()
250{
251 delete d;
252}
253
254bool KStandardDirs::isRestrictedResource(const char *type, const QString& relPath) const
255{
256 if (!d->m_restrictionsActive)
257 return false;
258
259 if (d->m_restrictions.value(type, false))
260 return true;
261
262 if (strcmp(type, "data")==0 && d->hasDataRestrictions(relPath))
263 return true;
264
265 return false;
266}
267
268bool KStandardDirs::KStandardDirsPrivate::hasDataRestrictions(const QString &relPath) const
269{
270 QString key;
271 const int i = relPath.indexOf(QLatin1Char('/'));
272 if (i != -1)
273 key = QString::fromLatin1("data_") + relPath.left(i);
274 else
275 key = QString::fromLatin1("data_") + relPath;
276
277 return m_restrictions.value(key.toLatin1(), false);
278}
279
280
281QStringList KStandardDirs::allTypes() const
282{
283 QStringList list;
284 for (int i = 0; types_indices[i] != -1; i += 2)
285 list.append(QLatin1String(types_string + types_indices[i]));
286 // Those are added manually by addKDEDefaults
287 list.append(QString::fromLatin1("lib"));
288 //list.append(QString::fromLatin1("home")); // undocumented on purpose, said Waldo in r113855.
289
290 // Those are handled by resourceDirs() itself
291 list.append(QString::fromLatin1("socket"));
292 list.append(QString::fromLatin1("tmp"));
293 list.append(QString::fromLatin1("cache"));
294 // Those are handled by installPath()
295 list.append(QString::fromLatin1("include"));
296
297 // If you add anything here, make sure kde-config.cpp has a description for it.
298
299 return list;
300}
301
302static void priorityAdd(QStringList &prefixes, const QString& dir, bool priority)
303{
304 if (priority && !prefixes.isEmpty())
305 {
306 // Add in front but behind $KDEHOME
307 QStringList::iterator it = prefixes.begin();
308 ++it;
309 prefixes.insert(it, dir);
310 }
311 else
312 {
313 prefixes.append(dir);
314 }
315}
316
317void KStandardDirs::addPrefix( const QString& _dir )
318{
319 addPrefix(_dir, false);
320}
321
322void KStandardDirs::addPrefix( const QString& _dir, bool priority )
323{
324 if (_dir.isEmpty())
325 return;
326
327 QString dir = _dir;
328 if (dir.at(dir.length() - 1) != QLatin1Char('/'))
329 dir += QLatin1Char('/');
330
331 if (!d->m_prefixes.contains(dir, cs)) {
332 priorityAdd(d->m_prefixes, dir, priority);
333 d->m_dircache.clear();
334 }
335}
336
337void KStandardDirs::addXdgConfigPrefix( const QString& _dir )
338{
339 addXdgConfigPrefix(_dir, false);
340}
341
342void KStandardDirs::addXdgConfigPrefix( const QString& _dir, bool priority )
343{
344 if (_dir.isEmpty())
345 return;
346
347 QString dir = _dir;
348 if (dir.at(dir.length() - 1) != QLatin1Char('/'))
349 dir += QLatin1Char('/');
350
351 if (!d->xdgconf_prefixes.contains(dir, cs)) {
352 priorityAdd(d->xdgconf_prefixes, dir, priority);
353 d->m_dircache.clear();
354 }
355}
356
357void KStandardDirs::addXdgDataPrefix( const QString& _dir )
358{
359 addXdgDataPrefix(_dir, false);
360}
361
362void KStandardDirs::addXdgDataPrefix( const QString& _dir, bool priority )
363{
364 if (_dir.isEmpty())
365 return;
366
367 QString dir = _dir;
368 if (dir.at(dir.length() - 1) != QLatin1Char('/'))
369 dir += QLatin1Char('/');
370
371 if (!d->xdgdata_prefixes.contains(dir, cs)) {
372 priorityAdd(d->xdgdata_prefixes, dir, priority);
373 d->m_dircache.clear();
374 }
375}
376
377QString KStandardDirs::kfsstnd_prefixes()
378{
379 return d->m_prefixes.join(QString(QLatin1Char(KPATH_SEPARATOR)));
380}
381
382QString KStandardDirs::kfsstnd_xdg_conf_prefixes()
383{
384 return d->xdgconf_prefixes.join(QString(QLatin1Char(KPATH_SEPARATOR)));
385}
386
387QString KStandardDirs::kfsstnd_xdg_data_prefixes()
388{
389 return d->xdgdata_prefixes.join(QString(QLatin1Char(KPATH_SEPARATOR)));
390}
391
392#ifndef KDE_NO_DEPRECATED
393bool KStandardDirs::addResourceType( const char *type,
394 const QString& relativename,
395 bool priority )
396{
397 return addResourceType( type, 0, relativename, priority);
398}
399#endif
400
401bool KStandardDirs::addResourceType( const char *type,
402 const char *basetype,
403 const QString& relativename,
404 bool priority )
405{
406 if (relativename.isEmpty())
407 return false;
408
409 QString copy = relativename;
410 if (basetype)
411 copy = QLatin1Char('%') + QString::fromLatin1(basetype) + QLatin1Char('/') + relativename;
412
413 if (!copy.endsWith(QLatin1Char('/')))
414 copy += QLatin1Char('/');
415
416 QByteArray typeBa = type;
417 QStringList& rels = d->m_relatives[typeBa]; // find or insert
418
419 if (!rels.contains(copy, cs)) {
420 if (priority)
421 rels.prepend(copy);
422 else
423 rels.append(copy);
424 // clean the caches
425 d->m_dircache.remove(typeBa);
426 d->m_savelocations.remove(typeBa);
427 return true;
428 }
429 return false;
430}
431
432bool KStandardDirs::addResourceDir( const char *type,
433 const QString& absdir,
434 bool priority)
435{
436 if (absdir.isEmpty() || !type)
437 return false;
438 // find or insert entry in the map
439 QString copy = absdir;
440 if (copy.at(copy.length() - 1) != QLatin1Char('/'))
441 copy += QLatin1Char('/');
442
443 QByteArray typeBa = type;
444 QStringList &paths = d->m_absolutes[typeBa];
445 if (!paths.contains(copy, cs)) {
446 if (priority)
447 paths.prepend(copy);
448 else
449 paths.append(copy);
450 // clean the caches
451 d->m_dircache.remove(typeBa);
452 d->m_savelocations.remove(typeBa);
453 return true;
454 }
455 return false;
456}
457
458QString KStandardDirs::findResource( const char *type,
459 const QString& _filename ) const
460{
461 if (!QDir::isRelativePath(_filename))
462 return !KGlobal::hasLocale() ? _filename // absolute dirs are absolute dirs, right? :-/
463 : KGlobal::locale()->localizedFilePath(_filename); // -- almost.
464
465#if 0
466 kDebug(180) << "Find resource: " << type;
467 for (QStringList::ConstIterator pit = m_prefixes.begin();
468 pit != m_prefixes.end();
469 ++pit)
470 {
471 kDebug(180) << "Prefix: " << *pit;
472 }
473#endif
474
475 QString filename(_filename);
476#ifdef Q_OS_WIN
477 if(strcmp(type, "exe") == 0) {
478 if(!filename.endsWith(QLatin1String(".exe"), Qt::CaseInsensitive))
479 filename += QLatin1String(".exe");
480 }
481#endif
482 const QString dir = findResourceDir(type, filename);
483 if (dir.isEmpty())
484 return dir;
485 else
486 return !KGlobal::hasLocale() ? dir + filename
487 : KGlobal::locale()->localizedFilePath(dir + filename);
488}
489
490static quint32 updateHash(const QString &file, quint32 hash)
491{
492 KDE_struct_stat buff;
493 if ((KDE::access(file, R_OK) == 0) && (KDE::stat(file, &buff) == 0) && (S_ISREG(buff.st_mode))) {
494 hash = hash + static_cast<quint32>(buff.st_ctime);
495 }
496 return hash;
497}
498
499quint32 KStandardDirs::calcResourceHash( const char *type,
500 const QString& filename,
501 SearchOptions options ) const
502{
503 quint32 hash = 0;
504
505 if (!QDir::isRelativePath(filename))
506 {
507 // absolute dirs are absolute dirs, right? :-/
508 return updateHash(filename, hash);
509 }
510 QStringList candidates = d->resourceDirs(type, filename);
511
512 foreach ( const QString& candidate, candidates )
513 {
514 hash = updateHash(candidate + filename, hash);
515 if ( !( options & Recursive ) && hash ) {
516 return hash;
517 }
518 }
519 return hash;
520}
521
522
523QStringList KStandardDirs::findDirs( const char *type,
524 const QString& reldir ) const
525{
526 QDir testdir;
527 QStringList list;
528 if (!QDir::isRelativePath(reldir))
529 {
530 testdir.setPath(reldir);
531 if (testdir.exists())
532 {
533 if (reldir.endsWith(QLatin1Char('/')))
534 list.append(reldir);
535 else
536 list.append(reldir+QLatin1Char('/'));
537 }
538 return list;
539 }
540
541 const QStringList candidates = d->resourceDirs(type, reldir);
542
543 for (QStringList::ConstIterator it = candidates.begin();
544 it != candidates.end(); ++it) {
545 testdir.setPath(*it + reldir);
546 if (testdir.exists())
547 list.append(testdir.absolutePath() + QLatin1Char('/'));
548 }
549
550 return list;
551}
552
553QString KStandardDirs::findResourceDir( const char *type,
554 const QString& _filename) const
555{
556#ifndef NDEBUG
557 if (_filename.isEmpty()) {
558 kWarning() << "filename for type " << type << " in KStandardDirs::findResourceDir is not supposed to be empty!!";
559 return QString();
560 }
561#endif
562
563 QString filename(_filename);
564#ifdef Q_OS_WIN
565 if(strcmp(type, "exe") == 0) {
566 if(!filename.endsWith(QLatin1String(".exe"), Qt::CaseInsensitive))
567 filename += QLatin1String(".exe");
568 }
569#endif
570 const QStringList candidates = d->resourceDirs(type, filename);
571
572 for (QStringList::ConstIterator it = candidates.begin();
573 it != candidates.end(); ++it) {
574 if (exists(*it + filename)) {
575 return *it;
576 }
577 }
578
579#ifndef NDEBUG
580 if(false && strcmp(type, "locale"))
581 kDebug(180) << "KStdDirs::findResDir(): can't find \"" << filename << "\" in type \"" << type << "\".";
582#endif
583
584 return QString();
585}
586
587bool KStandardDirs::exists(const QString &fullPath)
588{
589#ifdef Q_OS_WIN
590 // access() and stat() give a stupid error message to the user
591 // if the path is not accessible at all (e.g. no disk in A:/ and
592 // we do stat("A:/.directory")
593 if (fullPath.endsWith(QLatin1Char('/')))
594 return QDir(fullPath).exists();
595 return QFileInfo(fullPath).exists();
596#else
597 KDE_struct_stat buff;
598 QByteArray cFullPath = QFile::encodeName(fullPath);
599 if (access(cFullPath, R_OK) == 0 && KDE_stat( cFullPath, &buff ) == 0) {
600 if (!fullPath.endsWith(QLatin1Char('/'))) {
601 if (S_ISREG( buff.st_mode ))
602 return true;
603 } else
604 if (S_ISDIR( buff.st_mode ))
605 return true;
606 }
607 return false;
608#endif
609}
610
611static void lookupDirectory(const QString& path, const QString &relPart,
612 const QRegExp &regexp,
613 QStringList& list,
614 QStringList& relList,
615 bool recursive, bool unique)
616{
617 const QString pattern = regexp.pattern();
618 if (recursive || pattern.contains(QLatin1Char('?')) || pattern.contains(QLatin1Char('*')))
619 {
620 if (path.isEmpty()) //for sanity
621 return;
622#ifdef Q_WS_WIN
623 QString path_ = path + QLatin1String( "*.*" );
624 WIN32_FIND_DATA findData;
625 HANDLE hFile = FindFirstFile( (LPWSTR)path_.utf16(), &findData );
626 if( hFile == INVALID_HANDLE_VALUE )
627 return;
628 do {
629 const int len = wcslen( findData.cFileName );
630 if (!( findData.cFileName[0] == '.' &&
631 findData.cFileName[1] == '\0' ) &&
632 !( findData.cFileName[0] == '.' &&
633 findData.cFileName[1] == '.' &&
634 findData.cFileName[2] == '\0' ) &&
635 ( findData.cFileName[len-1] != '~' ) ) {
636 QString fn = QString::fromUtf16( (const unsigned short*)findData.cFileName );
637 if (!recursive && !regexp.exactMatch(fn))
638 continue; // No match
639 QString pathfn = path + fn;
640 bool bIsDir = ( ( findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) == FILE_ATTRIBUTE_DIRECTORY );
641 if ( recursive ) {
642 if ( bIsDir ) {
643 lookupDirectory(pathfn + QLatin1Char('/'),
644 relPart + fn + QLatin1Char('/'),
645 regexp, list, relList, recursive, unique);
646 }
647 if (!regexp.exactMatch(fn))
648 continue; // No match
649 }
650 if ( !bIsDir )
651 {
652 if ( !unique || !relList.contains(relPart + fn, cs) )
653 {
654 list.append( pathfn );
655 relList.append( relPart + fn );
656 }
657 }
658 }
659 } while( FindNextFile( hFile, &findData ) != 0 );
660 FindClose( hFile );
661#else
662 // We look for a set of files.
663 DIR *dp = opendir( QFile::encodeName(path));
664 if (!dp)
665 return;
666
667 assert(path.endsWith(QLatin1Char('/')));
668
669 struct dirent *ep;
670
671 while( ( ep = readdir( dp ) ) != 0L )
672 {
673 QString fn( QFile::decodeName(ep->d_name));
674 if (fn == QString::fromLatin1(".") || fn == QString::fromLatin1("..") || fn.at(fn.length() - 1) == QLatin1Char('~'))
675 continue;
676
677 if (!recursive && !regexp.exactMatch(fn))
678 continue; // No match
679
680 bool isDir;
681 bool isReg;
682
683 QString pathfn = path + fn;
684#ifdef HAVE_DIRENT_D_TYPE
685 isDir = ep->d_type == DT_DIR;
686 isReg = ep->d_type == DT_REG;
687
688 if (ep->d_type == DT_UNKNOWN || ep->d_type == DT_LNK)
689#endif
690 {
691 KDE_struct_stat buff;
692 if ( KDE::stat( pathfn, &buff ) != 0 ) {
693 kDebug(180) << "Error stat'ing " << pathfn << " : " << perror;
694 continue; // Couldn't stat (e.g. no read permissions)
695 }
696 isReg = S_ISREG (buff.st_mode);
697 isDir = S_ISDIR (buff.st_mode);
698 }
699
700 if ( recursive ) {
701 if ( isDir ) {
702 lookupDirectory(pathfn + QLatin1Char('/'), relPart + fn + QLatin1Char('/'), regexp, list, relList, recursive, unique);
703 }
704 if (!regexp.exactMatch(fn))
705 continue; // No match
706 }
707 if ( isReg )
708 {
709 if (!unique || !relList.contains(relPart + fn, cs))
710 {
711 list.append( pathfn );
712 relList.append( relPart + fn );
713 }
714 }
715 }
716 closedir( dp );
717#endif
718 }
719 else
720 {
721 // We look for a single file.
722 QString fn = pattern;
723 QString pathfn = path + fn;
724 KDE_struct_stat buff;
725 if ( KDE::stat( pathfn, &buff ) != 0 )
726 return; // File not found
727 if ( S_ISREG( buff.st_mode))
728 {
729 if (!unique || !relList.contains(relPart + fn, cs))
730 {
731 list.append( pathfn );
732 relList.append( relPart + fn );
733 }
734 }
735 }
736}
737
738static void lookupPrefix(const QString& prefix, const QString& relpath,
739 const QString& relPart,
740 const QRegExp &regexp,
741 QStringList& list,
742 QStringList& relList,
743 bool recursive, bool unique)
744{
745 if (relpath.isEmpty()) {
746 if (recursive)
747 Q_ASSERT(prefix != QLatin1String("/")); // we don't want to recursively list the whole disk!
748 lookupDirectory(prefix, relPart, regexp, list,
749 relList, recursive, unique);
750 return;
751 }
752 QString path;
753 QString rest;
754
755 int slash = relpath.indexOf(QLatin1Char('/'));
756 if (slash < 0)
757 rest = relpath.left(relpath.length() - 1);
758 else {
759 path = relpath.left(slash);
760 rest = relpath.mid(slash + 1);
761 }
762
763 if (prefix.isEmpty()) //for sanity
764 return;
765#ifndef Q_WS_WIN
766 // what does this assert check ?
767 assert(prefix.endsWith(QLatin1Char('/')));
768#endif
769 if (path.contains(QLatin1Char('*')) || path.contains(QLatin1Char('?'))) {
770
771 QRegExp pathExp(path, Qt::CaseSensitive, QRegExp::Wildcard);
772
773#ifdef Q_WS_WIN
774 QString prefix_ = prefix + QLatin1String( "*.*" );
775 WIN32_FIND_DATA findData;
776 HANDLE hFile = FindFirstFile( (LPWSTR)prefix_.utf16(), &findData );
777 if( hFile == INVALID_HANDLE_VALUE )
778 return;
779 do {
780 const int len = wcslen( findData.cFileName );
781 if (!( findData.cFileName[0] == '.' &&
782 findData.cFileName[1] == '\0' ) &&
783 !( findData.cFileName[0] == '.' &&
784 findData.cFileName[1] == '.' &&
785 findData.cFileName[2] == '\0' ) &&
786 ( findData.cFileName[len-1] != '~' ) ) {
787 const QString fn = QString::fromUtf16( (const unsigned short*)findData.cFileName );
788 if ( !pathExp.exactMatch(fn) )
789 continue; // No match
790 if ( ( findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) == FILE_ATTRIBUTE_DIRECTORY )
791 lookupPrefix(prefix + fn + QLatin1Char('/'),
792 rest, relPart + fn + QLatin1Char('/'),
793 regexp, list, relList, recursive, unique);
794 }
795 } while( FindNextFile( hFile, &findData ) != 0 );
796 FindClose( hFile );
797#else
798 DIR *dp = opendir( QFile::encodeName(prefix) );
799 if (!dp) {
800 return;
801 }
802
803 struct dirent *ep;
804
805 while( ( ep = readdir( dp ) ) != 0L )
806 {
807 QString fn( QFile::decodeName(ep->d_name));
808 if (fn == QLatin1String(".") || fn == QLatin1String("..") || fn.at(fn.length() - 1) == QLatin1Char('~'))
809 continue;
810
811 if ( !pathExp.exactMatch(fn) )
812 continue; // No match
813 QString rfn = relPart+fn;
814 fn = prefix + fn;
815
816 bool isDir;
817
818#ifdef HAVE_DIRENT_D_TYPE
819 isDir = ep->d_type == DT_DIR;
820
821 if (ep->d_type == DT_UNKNOWN || ep->d_type == DT_LNK)
822#endif
823 {
824 QString pathfn = path + fn;
825 KDE_struct_stat buff;
826 if ( KDE::stat( fn, &buff ) != 0 ) {
827 kDebug(180) << "Error stat'ing " << fn << " : " << perror;
828 continue; // Couldn't stat (e.g. no read permissions)
829 }
830 isDir = S_ISDIR (buff.st_mode);
831 }
832 if ( isDir )
833 lookupPrefix(fn + QLatin1Char('/'), rest, rfn + QLatin1Char('/'), regexp, list, relList, recursive, unique);
834 }
835
836 closedir( dp );
837#endif
838 } else {
839 // Don't stat, if the dir doesn't exist we will find out
840 // when we try to open it.
841 lookupPrefix(prefix + path + QLatin1Char('/'), rest,
842 relPart + path + QLatin1Char('/'), regexp, list,
843 relList, recursive, unique);
844 }
845}
846
847QStringList
848KStandardDirs::findAllResources( const char *type,
849 const QString& filter,
850 SearchOptions options,
851 QStringList &relList) const
852{
853 QString filterPath;
854 QString filterFile;
855
856 if ( !filter.isEmpty() )
857 {
858 int slash = filter.lastIndexOf(QLatin1Char('/'));
859 if (slash < 0) {
860 filterFile = filter;
861 } else {
862 filterPath = filter.left(slash + 1);
863 filterFile = filter.mid(slash + 1);
864 }
865 }
866
867 QStringList candidates;
868 if ( !QDir::isRelativePath(filter) ) // absolute path
869 {
870#ifdef Q_OS_WIN
871 candidates << filterPath.left(3); //e.g. "C:\"
872 filterPath = filterPath.mid(3);
873#else
874 candidates << QString::fromLatin1("/");
875 filterPath = filterPath.mid(1);
876#endif
877 }
878 else
879 {
880 candidates = d->resourceDirs(type, filter);
881 }
882
883 if (filterFile.isEmpty()) {
884 filterFile = QString(QLatin1Char('*'));
885 }
886
887 QRegExp regExp(filterFile, Qt::CaseSensitive, QRegExp::Wildcard);
888
889 QStringList list;
890 foreach ( const QString& candidate, candidates )
891 {
892 lookupPrefix(candidate, filterPath, QString(), regExp, list,
893 relList, options & Recursive, options & NoDuplicates);
894 }
895
896 return list;
897}
898
899QStringList
900KStandardDirs::findAllResources( const char *type,
901 const QString& filter,
902 SearchOptions options ) const
903{
904 QStringList relList;
905 return findAllResources(type, filter, options, relList);
906}
907
908// ####### KDE4: should this be removed, in favor of QDir::canonicalPath()?
909// aseigo: QDir::canonicalPath returns QString() if the dir doesn't exist
910// and this method is often used with the expectation for it to work
911// even if the directory doesn't exist. so ... no, we can't drop this
912// yet
913QString
914KStandardDirs::realPath(const QString &dirname)
915{
916#ifdef Q_WS_WIN
917 const QString strRet = realFilePath(dirname);
918 if (!strRet.endsWith(QLatin1Char('/')))
919 return strRet + QLatin1Char('/');
920 return strRet;
921#else
922 if (dirname.isEmpty() || (dirname.size() == 1 && dirname.at(0) == QLatin1Char('/')))
923 return dirname;
924
925 if (dirname.at(0) != QLatin1Char('/')) {
926 qWarning("realPath called with a relative path '%s', please fix", qPrintable(dirname));
927 return dirname;
928 }
929
930 char realpath_buffer[MAXPATHLEN + 1];
931 memset(realpath_buffer, 0, MAXPATHLEN + 1);
932
933 /* If the path contains symlinks, get the real name */
934 if (realpath( QFile::encodeName(dirname).constData(), realpath_buffer) != 0) {
935 // success, use result from realpath
936 int len = strlen(realpath_buffer);
937 realpath_buffer[len] = '/';
938 realpath_buffer[len+1] = 0;
939 return QFile::decodeName(realpath_buffer);
940 }
941
942 // Does not exist yet; resolve symlinks in parent dirs then.
943 // This ensures that once the directory exists, it will still be resolved
944 // the same way, so that the general rule that KStandardDirs always returns
945 // canonical paths stays true, and app code can compare paths more easily.
946 QString dir = dirname;
947 if (!dir.endsWith(QLatin1Char('/')))
948 dir += QLatin1Char('/');
949 QString relative;
950 while (!KStandardDirs::exists(dir)) {
951 //qDebug() << "does not exist:" << dir;
952 const int pos = dir.lastIndexOf(QLatin1Char('/'), -2);
953 Q_ASSERT(pos >= 0); // what? even "/" doesn't exist?
954 relative.prepend(dir.mid(pos+1)); // keep "subdir/"
955 dir = dir.left(pos+1);
956 Q_ASSERT(dir.endsWith(QLatin1Char('/')));
957 }
958 Q_ASSERT(!relative.isEmpty()); // infinite recursion ahead
959 if (!relative.isEmpty()) {
960 //qDebug() << "done, resolving" << dir << "and adding" << relative;
961 dir = realPath(dir) + relative;
962 }
963 return dir;
964#endif
965}
966
967// ####### KDE4: should this be removed, in favor of QDir::canonicalPath()?
968// aseigo: QDir::canonicalPath returns QString() if the dir doesn't exist
969// and this method is often used with the expectation for it to work
970// even if the directory doesn't exist. so ... no, we can't drop this
971// yet
972QString
973KStandardDirs::realFilePath(const QString &filename)
974{
975#ifdef Q_WS_WIN
976 LPCWSTR lpIn = (LPCWSTR)filename.utf16();
977 QVarLengthArray<WCHAR, MAX_PATH> buf(MAX_PATH);
978 DWORD len = GetFullPathNameW(lpIn, buf.size(), buf.data(), NULL);
979 if (len > (DWORD)buf.size()) {
980 buf.resize(len);
981 len = GetFullPathNameW(lpIn, buf.size(), buf.data(), NULL);
982 }
983 if (len == 0)
984 return QString();
985 return QString::fromUtf16((const unsigned short*)buf.data()).replace(QLatin1Char('\\'),QLatin1Char('/'));
986#else
987 char realpath_buffer[MAXPATHLEN + 1];
988 memset(realpath_buffer, 0, MAXPATHLEN + 1);
989
990 /* If the path contains symlinks, get the real name */
991 if (realpath( QFile::encodeName(filename).constData(), realpath_buffer) != 0) {
992 // success, use result from realpath
993 return QFile::decodeName(realpath_buffer);
994 }
995
996 return filename;
997#endif
998}
999
1000
1001void KStandardDirs::KStandardDirsPrivate::createSpecialResource(const char *type)
1002{
1003 char hostname[256];
1004 hostname[0] = 0;
1005 gethostname(hostname, 255);
1006 const QString localkdedir = m_prefixes.first();
1007 QString dir = localkdedir + QString::fromLatin1(type) + QLatin1Char('-') + QString::fromLocal8Bit(hostname);
1008 char link[1024];
1009 link[1023] = 0;
1010 int result = readlink(QFile::encodeName(dir).constData(), link, 1023);
1011 bool relink = (result == -1) && (errno == ENOENT);
1012 if (result > 0)
1013 {
1014 link[result] = 0;
1015 if (!QDir::isRelativePath(QFile::decodeName(link)))
1016 {
1017 KDE_struct_stat stat_buf;
1018 int res = KDE::lstat(QFile::decodeName(link), &stat_buf);
1019 if ((res == -1) && (errno == ENOENT))
1020 {
1021 relink = true;
1022 }
1023 else if ((res == -1) || (!S_ISDIR(stat_buf.st_mode)))
1024 {
1025 fprintf(stderr, "Error: \"%s\" is not a directory.\n", link);
1026 relink = true;
1027 }
1028 else if (stat_buf.st_uid != getuid())
1029 {
1030 fprintf(stderr, "Error: \"%s\" is owned by uid %d instead of uid %d.\n", link, stat_buf.st_uid, getuid());
1031 relink = true;
1032 }
1033 }
1034 }
1035#ifdef Q_WS_WIN
1036 if (relink)
1037 {
1038 if (!makeDir(dir, 0700))
1039 fprintf(stderr, "failed to create \"%s\"", qPrintable(dir));
1040 else
1041 result = readlink(QFile::encodeName(dir).constData(), link, 1023);
1042 }
1043#else //UNIX
1044 if (relink)
1045 {
1046 QString srv = findExe(QLatin1String("lnusertemp"), installPath("libexec"));
1047 if (srv.isEmpty())
1048 srv = findExe(QLatin1String("lnusertemp"));
1049 if (!srv.isEmpty())
1050 {
1051 if (system(QByteArray(QFile::encodeName(srv) + ' ' + type)) == -1) {
1052 fprintf(stderr, "Error: unable to launch lnusertemp command" );
1053 }
1054 result = readlink(QFile::encodeName(dir).constData(), link, 1023);
1055 }
1056 }
1057 if (result > 0)
1058 {
1059 link[result] = 0;
1060 if (link[0] == '/')
1061 dir = QFile::decodeName(link);
1062 else
1063 dir = QDir::cleanPath(dir + QFile::decodeName(link));
1064 }
1065#endif
1066 q->addResourceDir(type, dir + QLatin1Char('/'), false);
1067}
1068
1069QStringList KStandardDirs::resourceDirs(const char *type) const
1070{
1071 return d->resourceDirs(type, QString());
1072}
1073
1074QStringList KStandardDirs::KStandardDirsPrivate::resourceDirs(const char* type, const QString& subdirForRestrictions)
1075{
1076 QMutexLocker lock(&m_cacheMutex);
1077 const bool dataRestrictionActive = m_restrictionsActive
1078 && (strcmp(type, "data") == 0)
1079 && hasDataRestrictions(subdirForRestrictions);
1080
1081 QMap<QByteArray, QStringList>::const_iterator dirCacheIt = m_dircache.constFind(type);
1082
1083 QStringList candidates;
1084
1085 if (dirCacheIt != m_dircache.constEnd() && !dataRestrictionActive) {
1086 //qDebug() << this << "resourceDirs(" << type << "), in cache already";
1087 candidates = *dirCacheIt;
1088 }
1089 else // filling cache
1090 {
1091 //qDebug() << this << "resourceDirs(" << type << "), not in cache";
1092 if (strcmp(type, "socket") == 0)
1093 createSpecialResource(type);
1094 else if (strcmp(type, "tmp") == 0)
1095 createSpecialResource(type);
1096 else if (strcmp(type, "cache") == 0)
1097 createSpecialResource(type);
1098
1099 QDir testdir;
1100
1101 bool restrictionActive = false;
1102 if (m_restrictionsActive) {
1103 if (dataRestrictionActive)
1104 restrictionActive = true;
1105 if (m_restrictions.value("all", false))
1106 restrictionActive = true;
1107 else if (m_restrictions.value(type, false))
1108 restrictionActive = true;
1109 }
1110
1111 const QStringList dirs = m_relatives.value(type);
1112 const QString typeInstallPath = installPath(type); // could be empty
1113 const QString installdir = typeInstallPath.isEmpty() ? QString() : realPath(typeInstallPath);
1114 const QString installprefix = installPath("kdedir");
1115 if (!dirs.isEmpty())
1116 {
1117 bool local = true;
1118
1119 for (QStringList::ConstIterator it = dirs.constBegin();
1120 it != dirs.constEnd(); ++it)
1121 {
1122 if ((*it).startsWith(QLatin1Char('%'))) {
1123 // grab the "data" from "%data/apps"
1124 const int pos = (*it).indexOf(QLatin1Char('/'));
1125 QString rel = (*it).mid(1, pos - 1);
1126 QString rest = (*it).mid(pos + 1);
1127 const QStringList basedirs = resourceDirs(rel.toUtf8().constData(), subdirForRestrictions);
1128 for (QStringList::ConstIterator it2 = basedirs.begin();
1129 it2 != basedirs.end(); ++it2)
1130 {
1131 const QString path = realPath( *it2 + rest );
1132 testdir.setPath(path);
1133 if ((local || testdir.exists()) && !candidates.contains(path, cs))
1134 candidates.append(path);
1135 local = false;
1136 }
1137 }
1138 }
1139
1140 const QStringList *prefixList = 0;
1141 if (strncmp(type, "xdgdata-", 8) == 0)
1142 prefixList = &(xdgdata_prefixes);
1143 else if (strncmp(type, "xdgconf-", 8) == 0)
1144 prefixList = &(xdgconf_prefixes);
1145 else
1146 prefixList = &m_prefixes;
1147
1148 for (QStringList::ConstIterator pit = prefixList->begin();
1149 pit != prefixList->end();
1150 ++pit)
1151 {
1152 // "exe" never has a custom install path, and the check triggers a false positive due to the libexecdir patch
1153 if((*pit).compare(installprefix, cs) != 0 || installdir.isEmpty() || !strcmp("exe", type))
1154 {
1155 for (QStringList::ConstIterator it = dirs.constBegin();
1156 it != dirs.constEnd(); ++it)
1157 {
1158 if ((*it).startsWith(QLatin1Char('%')))
1159 continue;
1160 const QString path = realPath( *pit + *it );
1161 testdir.setPath(path);
1162 if (local && restrictionActive)
1163 continue;
1164 if ((local || testdir.exists()) && !candidates.contains(path, cs))
1165 candidates.append(path);
1166 }
1167 // special-case "config" (forward porting Chris Cheney's
1168 // hack) - we want /etc/kde after the local config paths
1169 // and before the ones in /usr (including kde-profile)
1170 if (local && !strcmp("config", type))
1171 candidates.append(QLatin1String("/etc/kde/"));
1172 local = false;
1173 }
1174 else
1175 {
1176 // we have a custom install path, so use this instead of <installprefix>/<relative dir>
1177 testdir.setPath(installdir);
1178 if(testdir.exists() && ! candidates.contains(installdir, cs))
1179 candidates.append(installdir);
1180 }
1181 }
1182 }
1183
1184 // make sure we find the path where it's installed
1185 if (!installdir.isEmpty()) {
1186 bool ok = true;
1187 foreach (const QString &s, candidates) {
1188 if (installdir.startsWith(s, cs)) {
1189 ok = false;
1190 break;
1191 }
1192 }
1193 if (ok)
1194 candidates.append(installdir);
1195 }
1196
1197 const QStringList absDirs = m_absolutes.value(type);
1198 for (QStringList::ConstIterator it = absDirs.constBegin();
1199 it != absDirs.constEnd(); ++it)
1200 {
1201 testdir.setPath(*it);
1202 if (testdir.exists()) {
1203 const QString filename = realPath( *it );
1204 if (!candidates.contains(filename, cs)) {
1205 candidates.append(filename);
1206 }
1207 }
1208 }
1209
1210 // Insert result into the cache for next time.
1211 // Exception: data_subdir restrictions are per-subdir, so we can't store such results
1212 if (!dataRestrictionActive) {
1213 //kDebug() << this << "Inserting" << type << candidates << "into dircache";
1214 m_dircache.insert(type, candidates);
1215 }
1216 }
1217
1218#if 0
1219 kDebug(180) << "found dirs for resource" << type << ":" << candidates;
1220#endif
1221
1222 return candidates;
1223}
1224
1225#ifdef Q_OS_WIN
1226static QStringList executableExtensions()
1227{
1228 QStringList ret = QString::fromLocal8Bit(qgetenv("PATHEXT")).split(QLatin1Char(';'));
1229 if (!ret.contains(QLatin1String(".exe"), Qt::CaseInsensitive)) {
1230 // If %PATHEXT% does not contain .exe, it is either empty, malformed, or distorted in ways that we cannot support, anyway.
1231 ret.clear();
1232 ret << QLatin1String(".exe")
1233 << QLatin1String(".com")
1234 << QLatin1String(".bat")
1235 << QLatin1String(".cmd");
1236 }
1237 return ret;
1238}
1239#endif
1240
1241QStringList KStandardDirs::systemPaths( const QString& pstr )
1242{
1243 QStringList tokens;
1244 QString p = pstr;
1245
1246 if( p.isEmpty() )
1247 {
1248 p = QString::fromLocal8Bit( qgetenv( "PATH" ) );
1249 }
1250
1251 QString delimiters(QLatin1Char(KPATH_SEPARATOR));
1252 delimiters += QLatin1Char('\b');
1253 tokenize( tokens, p, delimiters );
1254
1255 QStringList exePaths;
1256
1257 // split path using : or \b as delimiters
1258 for( int i = 0; i < tokens.count(); i++ )
1259 {
1260 exePaths << KShell::tildeExpand( tokens[ i ] );
1261 }
1262
1263 return exePaths;
1264}
1265
1266#ifdef Q_WS_MAC
1267static QString getBundle( const QString& path, bool ignore )
1268{
1269 //kDebug(180) << "getBundle(" << path << ", " << ignore << ") called";
1270 QFileInfo info;
1271 QString bundle = path;
1272 bundle += QLatin1String(".app/Contents/MacOS/") + bundle.section(QLatin1Char('/'), -1);
1273 info.setFile( bundle );
1274 FILE *file;
1275 if (file = fopen(info.absoluteFilePath().toUtf8().constData(), "r")) {
1276 fclose(file);
1277 struct stat _stat;
1278 if ((stat(info.absoluteFilePath().toUtf8().constData(), &_stat)) < 0) {
1279 return QString();
1280 }
1281 if ( ignore || (_stat.st_mode & S_IXUSR) ) {
1282 if ( ((_stat.st_mode & S_IFMT) == S_IFREG) || ((_stat.st_mode & S_IFMT) == S_IFLNK) ) {
1283 //kDebug(180) << "getBundle(): returning " << bundle;
1284 return bundle;
1285 }
1286 }
1287 }
1288 return QString();
1289}
1290#endif
1291
1292static QString checkExecutable( const QString& path, bool ignoreExecBit )
1293{
1294#ifdef Q_WS_MAC
1295 QString bundle = getBundle( path, ignoreExecBit );
1296 if ( !bundle.isEmpty() ) {
1297 //kDebug(180) << "findExe(): returning " << bundle;
1298 return bundle;
1299 }
1300#endif
1301 QFileInfo info( path );
1302 QFileInfo orig = info;
1303#if defined(Q_OS_DARWIN) || defined(Q_OS_MAC)
1304 FILE *file;
1305 if (file = fopen(orig.absoluteFilePath().toUtf8().constData(), "r")) {
1306 fclose(file);
1307 struct stat _stat;
1308 if ((stat(orig.absoluteFilePath().toUtf8().constData(), &_stat)) < 0) {
1309 return QString();
1310 }
1311 if ( ignoreExecBit || (_stat.st_mode & S_IXUSR) ) {
1312 if ( ((_stat.st_mode & S_IFMT) == S_IFREG) || ((_stat.st_mode & S_IFMT) == S_IFLNK) ) {
1313 orig.makeAbsolute();
1314 return orig.filePath();
1315 }
1316 }
1317 }
1318 return QString();
1319#else
1320 if( info.exists() && info.isSymLink() )
1321 info = QFileInfo( info.canonicalFilePath() );
1322 if( info.exists() && ( ignoreExecBit || info.isExecutable() ) && info.isFile() ) {
1323 // return absolute path, but without symlinks resolved in order to prevent
1324 // problems with executables that work differently depending on name they are
1325 // run as (for example gunzip)
1326 orig.makeAbsolute();
1327 return orig.filePath();
1328 }
1329 //kDebug(180) << "checkExecutable(): failed, returning empty string";
1330 return QString();
1331#endif
1332}
1333
1334QString KStandardDirs::findExe( const QString& appname,
1335 const QString& pstr,
1336 SearchOptions options )
1337{
1338 //kDebug(180) << "findExe(" << appname << ", pstr, " << ignoreExecBit << ") called";
1339
1340#ifdef Q_OS_WIN
1341 QStringList executable_extensions = executableExtensions();
1342 if (!executable_extensions.contains(appname.section(QLatin1Char('.'), -1, -1, QString::SectionIncludeLeadingSep), Qt::CaseInsensitive)) {
1343 QString found_exe;
1344 foreach (const QString& extension, executable_extensions) {
1345 found_exe = findExe(appname + extension, pstr, options);
1346 if (!found_exe.isEmpty()) {
1347 return found_exe;
1348 }
1349 }
1350 return QString();
1351 }
1352#endif
1353 QFileInfo info;
1354
1355 // absolute or relative path?
1356 if (appname.contains(QDir::separator()))
1357 {
1358 //kDebug(180) << "findExe(): absolute path given";
1359 QString path = checkExecutable(appname, options & IgnoreExecBit);
1360 return path;
1361 }
1362
1363 //kDebug(180) << "findExe(): relative path given";
1364
1365 QString p = installPath("libexec") + appname;
1366 QString result = checkExecutable(p, options & IgnoreExecBit);
1367 if (!result.isEmpty()) {
1368 //kDebug(180) << "findExe(): returning " << result;
1369 return result;
1370 }
1371
1372 //kDebug(180) << "findExe(): checking system paths";
1373 const QStringList exePaths = systemPaths( pstr );
1374 for (QStringList::ConstIterator it = exePaths.begin(); it != exePaths.end(); ++it)
1375 {
1376 p = (*it) + QLatin1Char('/');
1377 p += appname;
1378
1379 // Check for executable in this tokenized path
1380 result = checkExecutable(p, options & IgnoreExecBit);
1381 if (!result.isEmpty()) {
1382 //kDebug(180) << "findExe(): returning " << result;
1383 return result;
1384 }
1385 }
1386
1387 // Not found in PATH, look into the KDE-specific bin dir ("exe" resource)
1388 p = installPath("exe");
1389 p += appname;
1390 result = checkExecutable(p, options & IgnoreExecBit);
1391 if (!result.isEmpty()) {
1392 //kDebug(180) << "findExe(): returning " << result;
1393 return result;
1394 }
1395
1396 // If we reach here, the executable wasn't found.
1397 // So return empty string.
1398
1399 //kDebug(180) << "findExe(): failed, nothing matched";
1400 return QString();
1401}
1402
1403int KStandardDirs::findAllExe( QStringList& list, const QString& appname,
1404 const QString& pstr, SearchOptions options )
1405{
1406#ifdef Q_OS_WIN
1407 QStringList executable_extensions = executableExtensions();
1408 if (!executable_extensions.contains(appname.section(QLatin1Char('.'), -1, -1, QString::SectionIncludeLeadingSep), Qt::CaseInsensitive)) {
1409 int total = 0;
1410 foreach (const QString& extension, executable_extensions) {
1411 total += findAllExe (list, appname + extension, pstr, options);
1412 }
1413 return total;
1414 }
1415#endif
1416 QFileInfo info;
1417 QString p;
1418 list.clear();
1419
1420 const QStringList exePaths = systemPaths( pstr );
1421 for (QStringList::ConstIterator it = exePaths.begin(); it != exePaths.end(); ++it)
1422 {
1423 p = (*it) + QLatin1Char('/');
1424 p += appname;
1425
1426#ifdef Q_WS_MAC
1427 QString bundle = getBundle( p, (options & IgnoreExecBit) );
1428 if ( !bundle.isEmpty() ) {
1429 //kDebug(180) << "findExe(): returning " << bundle;
1430 list.append( bundle );
1431 }
1432#endif
1433
1434 info.setFile( p );
1435
1436 if( info.exists() && ( ( options & IgnoreExecBit ) || info.isExecutable())
1437 && info.isFile() ) {
1438 list.append( p );
1439 }
1440 }
1441
1442 return list.count();
1443}
1444
1445static inline QString equalizePath(QString &str)
1446{
1447#ifdef Q_WS_WIN
1448 // filter pathes through QFileInfo to have always
1449 // the same case for drive letters
1450 QFileInfo f(str);
1451 if (f.isAbsolute())
1452 return f.absoluteFilePath();
1453 else
1454#endif
1455 return str;
1456}
1457
1458static void tokenize(QStringList& tokens, const QString& str,
1459 const QString& delim)
1460{
1461 const int len = str.length();
1462 QString token;
1463
1464 for(int index = 0; index < len; index++) {
1465 if (delim.contains(str[index])) {
1466 tokens.append(equalizePath(token));
1467 token.clear();
1468 } else {
1469 token += str[index];
1470 }
1471 }
1472 if (!token.isEmpty()) {
1473 tokens.append(equalizePath(token));
1474 }
1475}
1476
1477#ifndef KDE_NO_DEPRECATED
1478QString KStandardDirs::kde_default(const char *type)
1479{
1480 return QString(QLatin1Char('%')) + QString::fromLatin1(type) + QLatin1Char('/');
1481}
1482#endif
1483
1484QString KStandardDirs::saveLocation(const char *type,
1485 const QString& suffix,
1486 bool create) const
1487{
1488 QMutexLocker lock(&d->m_cacheMutex);
1489 QString path = d->m_savelocations.value(type);
1490 if (path.isEmpty())
1491 {
1492 QStringList dirs = d->m_relatives.value(type);
1493 if (dirs.isEmpty() && (
1494 (strcmp(type, "socket") == 0) ||
1495 (strcmp(type, "tmp") == 0) ||
1496 (strcmp(type, "cache") == 0) ))
1497 {
1498 (void) resourceDirs(type); // Generate socket|tmp|cache resource.
1499 dirs = d->m_relatives.value(type); // Search again.
1500 }
1501 if (!dirs.isEmpty())
1502 {
1503 path = dirs.first();
1504
1505 if (path.startsWith(QLatin1Char('%'))) {
1506 // grab the "data" from "%data/apps"
1507 const int pos = path.indexOf(QLatin1Char('/'));
1508 QString rel = path.mid(1, pos - 1);
1509 QString rest = path.mid(pos + 1);
1510 QString basepath = saveLocation(rel.toUtf8().constData());
1511 path = basepath + rest;
1512 } else
1513
1514 // Check for existence of typed directory + suffix
1515 if (strncmp(type, "xdgdata-", 8) == 0) {
1516 path = realPath( localxdgdatadir() + path ) ;
1517 } else if (strncmp(type, "xdgconf-", 8) == 0) {
1518 path = realPath( localxdgconfdir() + path );
1519 } else {
1520 path = realPath( localkdedir() + path );
1521 }
1522 }
1523 else {
1524 dirs = d->m_absolutes.value(type);
1525 if (dirs.isEmpty()) {
1526 qFatal("KStandardDirs: The resource type %s is not registered", type);
1527 } else {
1528 path = realPath(dirs.first());
1529 }
1530 }
1531
1532 d->m_savelocations.insert(type, path.endsWith(QLatin1Char('/')) ? path : path + QLatin1Char('/'));
1533 }
1534 QString fullPath = path + suffix;
1535
1536 KDE_struct_stat st;
1537 if (KDE::stat(fullPath, &st) != 0 || !(S_ISDIR(st.st_mode))) {
1538 if(!create) {
1539#ifndef NDEBUG
1540 // Too much noise from kbuildsycoca4 -- it's fine if this happens from KConfig
1541 // when parsing global files without a local equivalent.
1542 //kDebug(180) << QString("save location %1 doesn't exist").arg(fullPath);
1543#endif
1544 return fullPath;
1545 }
1546 if(!makeDir(fullPath, 0700)) {
1547 return fullPath;
1548 }
1549 d->m_dircache.remove(type);
1550 }
1551 if (!fullPath.endsWith(QLatin1Char('/')))
1552 fullPath += QLatin1Char('/');
1553 return fullPath;
1554}
1555
1556// KDE5: make the method const
1557QString KStandardDirs::relativeLocation(const char *type, const QString &absPath)
1558{
1559 QString fullPath = absPath;
1560 int i = absPath.lastIndexOf(QLatin1Char('/'));
1561 if (i != -1) {
1562 fullPath = realFilePath(absPath); // Normalize
1563 }
1564
1565 const QStringList candidates = resourceDirs(type);
1566
1567 for (QStringList::ConstIterator it = candidates.begin();
1568 it != candidates.end(); ++it) {
1569 if (fullPath.startsWith(*it, cs)) {
1570 return fullPath.mid((*it).length());
1571 }
1572 }
1573 return absPath;
1574}
1575
1576
1577bool KStandardDirs::makeDir(const QString& dir, int mode)
1578{
1579 // we want an absolute path
1580 if (QDir::isRelativePath(dir))
1581 return false;
1582
1583#ifdef Q_WS_WIN
1584 return QDir().mkpath(dir);
1585#else
1586 QString target = dir;
1587 uint len = target.length();
1588
1589 // append trailing slash if missing
1590 if (dir.at(len - 1) != QLatin1Char('/'))
1591 target += QLatin1Char('/');
1592
1593 QString base;
1594 uint i = 1;
1595
1596 while( i < len )
1597 {
1598 KDE_struct_stat st;
1599 int pos = target.indexOf(QLatin1Char('/'), i);
1600 base += target.mid(i - 1, pos - i + 1);
1601 QByteArray baseEncoded = QFile::encodeName(base);
1602 // bail out if we encountered a problem
1603 if (KDE_stat(baseEncoded, &st) != 0)
1604 {
1605 // Directory does not exist....
1606 // Or maybe a dangling symlink ?
1607 if (KDE_lstat(baseEncoded, &st) == 0)
1608 (void)unlink(baseEncoded); // try removing
1609
1610 if (KDE_mkdir(baseEncoded, static_cast<mode_t>(mode)) != 0) {
1611 baseEncoded.prepend( "trying to create local folder " );
1612 perror(baseEncoded.constData());
1613 return false; // Couldn't create it :-(
1614 }
1615 }
1616 i = pos + 1;
1617 }
1618 return true;
1619#endif
1620}
1621
1622static QString readEnvPath(const char *env)
1623{
1624 QByteArray c_path;
1625#ifndef _WIN32_WCE
1626 c_path = qgetenv(env);
1627 if (c_path.isEmpty())
1628 return QString();
1629#else
1630 bool ok;
1631 QString retval = getWin32RegistryValue(HKEY_LOCAL_MACHINE, "Software\\kde", "KDEDIRS", &ok);
1632 if (!ok){
1633 return QString();
1634 } else {
1635 c_path = retval.toLatin1();
1636 }
1637#endif
1638 return QDir::fromNativeSeparators(QFile::decodeName(c_path));
1639}
1640
1641#ifdef __linux__
1642static QString executablePrefix()
1643{
1644 char path_buffer[MAXPATHLEN + 1];
1645 path_buffer[MAXPATHLEN] = 0;
1646 int length = readlink ("/proc/self/exe", path_buffer, MAXPATHLEN);
1647 if (length == -1)
1648 return QString();
1649
1650 path_buffer[length] = '\0';
1651
1652 QString path = QFile::decodeName(path_buffer);
1653
1654 if(path.isEmpty())
1655 return QString();
1656
1657 int pos = path.lastIndexOf(QLatin1Char('/')); // Skip filename
1658 if(pos <= 0)
1659 return QString();
1660 pos = path.lastIndexOf(QLatin1Char('/'), pos - 1); // Skip last directory
1661 if(pos <= 0)
1662 return QString();
1663
1664 return path.left(pos);
1665}
1666#endif
1667
1668void KStandardDirs::addResourcesFrom_krcdirs()
1669{
1670 QString localFile = QDir::currentPath() + QLatin1String("/.krcdirs");
1671 if (!QFile::exists(localFile))
1672 return;
1673
1674 QSettings iniFile(localFile, QSettings::IniFormat);
1675 iniFile.beginGroup(QString::fromLatin1("KStandardDirs"));
1676 const QStringList resources = iniFile.allKeys();
1677 foreach(const QString &key, resources)
1678 {
1679 QDir path(iniFile.value(key).toString());
1680 if (!path.exists())
1681 continue;
1682
1683 if(path.makeAbsolute())
1684 addResourceDir(key.toLatin1(), path.path(), false);
1685 }
1686}
1687
1688void KStandardDirs::addKDEDefaults()
1689{
1690 addResourcesFrom_krcdirs();
1691
1692 QStringList kdedirList;
1693 // begin KDEDIRS
1694 QString kdedirs = readEnvPath("KDEDIRS");
1695
1696 if (!kdedirs.isEmpty())
1697 {
1698 tokenize(kdedirList, kdedirs, QString(QLatin1Char(KPATH_SEPARATOR)));
1699 }
1700 kdedirList.append(installPath("kdedir"));
1701
1702 QString execPrefix(QFile::decodeName(EXEC_INSTALL_PREFIX));
1703 if (!execPrefix.isEmpty() && !kdedirList.contains(execPrefix, cs))
1704 kdedirList.append(execPrefix);
1705#ifdef __linux__
1706 const QString linuxExecPrefix = executablePrefix();
1707 if ( !linuxExecPrefix.isEmpty() )
1708 kdedirList.append( linuxExecPrefix );
1709#endif
1710
1711 // We treat root differently to prevent a "su" shell messing up the
1712 // file permissions in the user's home directory.
1713 QString localKdeDir = readEnvPath(getuid() ? "KDEHOME" : "KDEROOTHOME");
1714 if (!localKdeDir.isEmpty()) {
1715 if (!localKdeDir.endsWith(QLatin1Char('/')))
1716 localKdeDir += QLatin1Char('/');
1717 } else {
1718 // TODO KDE5: make localKdeDir equal to localXdgDir (which is determined further below and
1719 // defaults to ~/.config) + '/' + $KDECONFIG (which would default to e.g. "KDE")
1720 // This would mean ~/.config/KDE/ by default, more xdg-compliant.
1721
1722#if defined(Q_WS_MACX)
1723 localKdeDir = QDir::homePath() + QLatin1String("/Library/Preferences/KDE/");
1724#elif defined(Q_WS_WIN)
1725#ifndef _WIN32_WCE
1726 WCHAR wPath[MAX_PATH+1];
1727 if ( SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, wPath) == S_OK) {
1728 localKdeDir = QDir::fromNativeSeparators(QString::fromUtf16((const ushort *) wPath)) + QLatin1Char('/') + QString::fromLatin1(KDE_DEFAULT_HOME) + QLatin1Char('/');
1729 } else {
1730#endif
1731 localKdeDir = QDir::homePath() + QLatin1Char('/') + QString::fromLatin1(KDE_DEFAULT_HOME) + QLatin1Char('/');
1732#ifndef _WIN32_WCE
1733 }
1734#endif
1735#else
1736 localKdeDir = QDir::homePath() + QLatin1Char('/') + QString::fromLatin1(KDE_DEFAULT_HOME) + QLatin1Char('/');
1737#endif
1738 }
1739
1740 if (localKdeDir != QLatin1String("-/"))
1741 {
1742 localKdeDir = KShell::tildeExpand(localKdeDir);
1743 addPrefix(localKdeDir);
1744 }
1745
1746#ifdef Q_WS_MACX
1747 // Adds the "Contents" directory of the current application bundle to
1748 // the search path. This way bundled resources can be found.
1749 QDir bundleDir(mac_app_filename());
1750 if (bundleDir.dirName() == QLatin1String("MacOS")) { // just to be sure we're in a bundle
1751 bundleDir.cdUp();
1752 // now dirName should be "Contents". In there we can find our normal
1753 // dir-structure, beginning with "share"
1754 addPrefix(bundleDir.absolutePath());
1755 }
1756#endif
1757
1758 QStringList::ConstIterator end(kdedirList.end());
1759 for (QStringList::ConstIterator it = kdedirList.constBegin();
1760 it != kdedirList.constEnd(); ++it)
1761 {
1762 const QString dir = KShell::tildeExpand(*it);
1763 addPrefix(dir);
1764 }
1765 // end KDEDIRS
1766
1767 // begin XDG_CONFIG_XXX
1768 QStringList xdgdirList;
1769 QString xdgdirs = readEnvPath("XDG_CONFIG_DIRS");
1770 if (!xdgdirs.isEmpty())
1771 {
1772 tokenize(xdgdirList, xdgdirs, QString(QLatin1Char(KPATH_SEPARATOR)));
1773 }
1774 else
1775 {
1776 xdgdirList.clear();
1777 xdgdirList.append(QString::fromLatin1("/etc/xdg"));
1778#ifdef Q_WS_WIN
1779 xdgdirList.append(installPath("kdedir") + QString::fromLatin1("etc/xdg"));
1780#else
1781 xdgdirList.append(QFile::decodeName(KDESYSCONFDIR "/xdg"));
1782#endif
1783 }
1784
1785 QString localXdgDir = readEnvPath("XDG_CONFIG_HOME");
1786 if (!localXdgDir.isEmpty()) {
1787 if (!localXdgDir.endsWith(QLatin1Char('/')))
1788 localXdgDir += QLatin1Char('/');
1789 } else {
1790#ifdef Q_WS_MACX
1791 localXdgDir = QDir::homePath() + QString::fromLatin1("/Library/Preferences/XDG/");
1792#else
1793 localXdgDir = QDir::homePath() + QString::fromLatin1("/.config/");
1794#endif
1795 }
1796
1797 localXdgDir = KShell::tildeExpand(localXdgDir);
1798 addXdgConfigPrefix(localXdgDir);
1799
1800 for (QStringList::ConstIterator it = xdgdirList.constBegin();
1801 it != xdgdirList.constEnd(); ++it)
1802 {
1803 QString dir = KShell::tildeExpand(*it);
1804 addXdgConfigPrefix(dir);
1805 }
1806 // end XDG_CONFIG_XXX
1807
1808 // begin XDG_DATA_XXX
1809 QStringList kdedirDataDirs;
1810 for (QStringList::ConstIterator it = kdedirList.constBegin();
1811 it != kdedirList.constEnd(); ++it) {
1812 QString dir = *it;
1813 if (!dir.endsWith(QLatin1Char('/')))
1814 dir += QLatin1Char('/');
1815 kdedirDataDirs.append(dir + QLatin1String("share/"));
1816 }
1817
1818 xdgdirs = readEnvPath("XDG_DATA_DIRS");
1819 if (!xdgdirs.isEmpty()) {
1820 tokenize(xdgdirList, xdgdirs, QString(QLatin1Char(KPATH_SEPARATOR)));
1821 // Ensure the kdedirDataDirs are in there too,
1822 // otherwise resourceDirs() will add kdedir/share/applications/kde4
1823 // as returned by installPath(), and that's incorrect.
1824 Q_FOREACH(const QString& dir, kdedirDataDirs) {
1825 if (!xdgdirList.contains(dir, cs))
1826 xdgdirList.append(dir);
1827 }
1828 } else {
1829 xdgdirList = kdedirDataDirs;
1830#ifndef Q_WS_WIN
1831 xdgdirList.append(QString::fromLatin1("/usr/local/share/"));
1832 xdgdirList.append(QString::fromLatin1("/usr/share/"));
1833#endif
1834 }
1835
1836 localXdgDir = readEnvPath("XDG_DATA_HOME");
1837 if (!localXdgDir.isEmpty())
1838 {
1839 if (localXdgDir[localXdgDir.length()-1] != QLatin1Char('/'))
1840 localXdgDir += QLatin1Char('/');
1841 }
1842 else
1843 {
1844 localXdgDir = QDir::homePath() + QLatin1String("/.local/share/");
1845 }
1846
1847 localXdgDir = KShell::tildeExpand(localXdgDir);
1848 addXdgDataPrefix(localXdgDir);
1849
1850 for (QStringList::ConstIterator it = xdgdirList.constBegin();
1851 it != xdgdirList.constEnd(); ++it)
1852 {
1853 QString dir = KShell::tildeExpand(*it);
1854 addXdgDataPrefix(dir);
1855 }
1856 // end XDG_DATA_XXX
1857
1858
1859 addResourceType("lib", 0, "lib" KDELIBSUFF "/");
1860
1861 addResourceType("qtplugins", "lib", "plugins");
1862
1863 uint index = 0;
1864 while (types_indices[index] != -1) {
1865 addResourceType(types_string + types_indices[index], 0, types_string + types_indices[index+1], true);
1866 index+=2;
1867 }
1868 addResourceType("exe", 0, "libexec/kde4", true );
1869
1870 addResourceDir("home", QDir::homePath(), false);
1871
1872 addResourceType("autostart", "xdgconf-autostart", "/"); // merge them, start with xdg autostart
1873 addResourceType("autostart", NULL, "share/autostart"); // KDE ones are higher priority
1874}
1875
1876static QStringList lookupProfiles(const QString &mapFile)
1877{
1878 QStringList profiles;
1879
1880 if (mapFile.isEmpty() || !QFile::exists(mapFile))
1881 {
1882 profiles << QString::fromLatin1("default");
1883 return profiles;
1884 }
1885
1886 struct passwd *pw = getpwuid(geteuid());
1887 if (!pw)
1888 {
1889 profiles << QString::fromLatin1("default");
1890 return profiles; // Not good
1891 }
1892
1893 QByteArray user = pw->pw_name;
1894
1895 gid_t sup_gids[512];
1896 int sup_gids_nr = getgroups(512, sup_gids);
1897
1898 KConfig mapCfgFile(mapFile);
1899 KConfigGroup mapCfg(&mapCfgFile, "Users");
1900 if (mapCfg.hasKey(user.constData()))
1901 {
1902 profiles = mapCfg.readEntry(user.constData(), QStringList());
1903 return profiles;
1904 }
1905
1906 const KConfigGroup generalGrp(&mapCfgFile, "General");
1907 const QStringList groups = generalGrp.readEntry("groups", QStringList());
1908
1909 const KConfigGroup groupsGrp(&mapCfgFile, "Groups");
1910
1911 for( QStringList::ConstIterator it = groups.begin();
1912 it != groups.end(); ++it )
1913 {
1914 QByteArray grp = (*it).toUtf8();
1915 // Check if user is in this group
1916 struct group *grp_ent = getgrnam(grp);
1917 if (!grp_ent) continue;
1918 gid_t gid = grp_ent->gr_gid;
1919 if (pw->pw_gid == gid)
1920 {
1921 // User is in this group --> add profiles
1922 profiles += groupsGrp.readEntry(*it, QStringList());
1923 }
1924 else
1925 {
1926 for(int i = 0; i < sup_gids_nr; i++)
1927 {
1928 if (sup_gids[i] == gid)
1929 {
1930 // User is in this group --> add profiles
1931 profiles += groupsGrp.readEntry(*it, QStringList());
1932 break;
1933 }
1934 }
1935 }
1936 }
1937
1938 if (profiles.isEmpty())
1939 profiles << QString::fromLatin1("default");
1940 return profiles;
1941}
1942
1943extern bool kde_kiosk_admin;
1944
1945bool KStandardDirs::addCustomized(KConfig *config)
1946{
1947 if (!d->m_checkRestrictions) // there are already customized entries
1948 return false; // we just quit and hope they are the right ones
1949
1950 // save the numbers of config directories. If this changes,
1951 // we will return true to give KConfig a chance to reparse
1952 int configdirs = resourceDirs("config").count();
1953
1954 if (true)
1955 {
1956 // reading the prefixes in
1957 QString group = QLatin1String("Directories");
1958 KConfigGroup cg(config, group);
1959
1960 QString kioskAdmin = cg.readEntry("kioskAdmin");
1961 if (!kioskAdmin.isEmpty() && !kde_kiosk_admin)
1962 {
1963 int i = kioskAdmin.indexOf(QLatin1Char(':'));
1964 QString user = kioskAdmin.left(i);
1965 QString host = kioskAdmin.mid(i+1);
1966
1967 KUser thisUser;
1968 char hostname[ 256 ];
1969 hostname[ 0 ] = '\0';
1970 if (!gethostname( hostname, 255 ))
1971 hostname[sizeof(hostname)-1] = '\0';
1972
1973 if ((user == thisUser.loginName()) &&
1974 (host.isEmpty() || (host == QLatin1String(hostname))))
1975 {
1976 kde_kiosk_admin = true;
1977 }
1978 }
1979
1980 bool readProfiles = true;
1981
1982 if (kde_kiosk_admin && !qgetenv("KDE_KIOSK_NO_PROFILES").isEmpty())
1983 readProfiles = false;
1984
1985 QString userMapFile = cg.readEntry("userProfileMapFile");
1986 QString profileDirsPrefix = cg.readEntry("profileDirsPrefix");
1987 if (!profileDirsPrefix.isEmpty() && !profileDirsPrefix.endsWith(QLatin1Char('/')))
1988 profileDirsPrefix.append(QLatin1Char('/'));
1989
1990 QStringList profiles;
1991 if (readProfiles)
1992 profiles = lookupProfiles(userMapFile);
1993 QString profile;
1994
1995 bool priority = false;
1996 while(true)
1997 {
1998 KConfigGroup cg(config, group);
1999 const QStringList list = cg.readEntry("prefixes", QStringList());
2000 for (QStringList::ConstIterator it = list.begin(); it != list.end(); ++it)
2001 {
2002 addPrefix(*it, priority);
2003 addXdgConfigPrefix(*it + QLatin1String("/etc/xdg"), priority);
2004 addXdgDataPrefix(*it + QLatin1String("/share"), priority);
2005 }
2006 // If there are no prefixes defined, check if there is a directory
2007 // for this profile under <profileDirsPrefix>
2008 if (list.isEmpty() && !profile.isEmpty() && !profileDirsPrefix.isEmpty())
2009 {
2010 QString dir = profileDirsPrefix + profile;
2011 addPrefix(dir, priority);
2012 addXdgConfigPrefix(dir + QLatin1String("/etc/xdg"), priority);
2013 addXdgDataPrefix(dir + QLatin1String("/share"), priority);
2014 }
2015
2016 // iterating over all entries in the group Directories
2017 // to find entries that start with dir_$type
2018 const QMap<QString, QString> entries = config->entryMap(group);
2019 for (QMap<QString, QString>::ConstIterator it2 = entries.begin();
2020 it2 != entries.end(); ++it2)
2021 {
2022 const QString key = it2.key();
2023 if (key.startsWith(QLatin1String("dir_"))) {
2024 // generate directory list, there may be more than 1.
2025 const QStringList dirs = (*it2).split(QString(QLatin1Char(',')));
2026 QStringList::ConstIterator sIt(dirs.begin());
2027 QString resType = key.mid(4);
2028 for (; sIt != dirs.end(); ++sIt)
2029 {
2030 addResourceDir(resType.toLatin1(), *sIt, priority);
2031 }
2032 }
2033 }
2034 if (profiles.isEmpty())
2035 break;
2036 profile = profiles.back();
2037 group = QString::fromLatin1("Directories-%1").arg(profile);
2038 profiles.pop_back();
2039 priority = true;
2040 }
2041 }
2042
2043 // Process KIOSK restrictions.
2044 if (!kde_kiosk_admin || qgetenv("KDE_KIOSK_NO_RESTRICTIONS").isEmpty())
2045 {
2046 KConfigGroup cg(config, "KDE Resource Restrictions");
2047 const QMap<QString, QString> entries = cg.entryMap();
2048 for (QMap<QString, QString>::ConstIterator it2 = entries.begin();
2049 it2 != entries.end(); ++it2)
2050 {
2051 const QString key = it2.key();
2052 if (!cg.readEntry(key, true))
2053 {
2054 d->m_restrictionsActive = true;
2055 const QByteArray cKey = key.toLatin1();
2056 d->m_restrictions.insert(cKey, true);
2057 d->m_dircache.remove(cKey);
2058 d->m_savelocations.remove(cKey);
2059 }
2060 }
2061 }
2062
2063 // check if the number of config dirs changed
2064 bool configDirsChanged = (resourceDirs("config").count() != configdirs);
2065 // If the config dirs changed, we check kiosk restrictions again.
2066 d->m_checkRestrictions = configDirsChanged;
2067 // return true if the number of config dirs changed: reparse config file
2068 return configDirsChanged;
2069}
2070
2071QString KStandardDirs::localkdedir() const
2072{
2073 // Return the prefix to use for saving
2074 return d->m_prefixes.first();
2075}
2076
2077QString KStandardDirs::localxdgdatadir() const
2078{
2079 // Return the prefix to use for saving
2080 return d->xdgdata_prefixes.first();
2081}
2082
2083QString KStandardDirs::localxdgconfdir() const
2084{
2085 // Return the prefix to use for saving
2086 return d->xdgconf_prefixes.first();
2087}
2088
2089
2090// just to make code more readable without macros
2091QString KStandardDirs::locate( const char *type,
2092 const QString& filename, const KComponentData &cData)
2093{
2094 return cData.dirs()->findResource(type, filename);
2095}
2096
2097QString KStandardDirs::locateLocal( const char *type,
2098 const QString& filename, const KComponentData &cData)
2099{
2100 return locateLocal(type, filename, true, cData);
2101}
2102
2103QString KStandardDirs::locateLocal( const char *type,
2104 const QString& filename, bool createDir,
2105 const KComponentData &cData)
2106{
2107 // try to find slashes. If there are some, we have to
2108 // create the subdir first
2109 int slash = filename.lastIndexOf(QLatin1Char('/')) + 1;
2110 if (!slash) { // only one filename
2111 return cData.dirs()->saveLocation(type, QString(), createDir) + filename;
2112 }
2113
2114 // split path from filename
2115 QString dir = filename.left(slash);
2116 QString file = filename.mid(slash);
2117 return cData.dirs()->saveLocation(type, dir, createDir) + file;
2118}
2119
2120bool KStandardDirs::checkAccess(const QString& pathname, int mode)
2121{
2122 int accessOK = KDE::access( pathname, mode );
2123 if ( accessOK == 0 )
2124 return true; // OK, I can really access the file
2125
2126 // else
2127 // if we want to write the file would be created. Check, if the
2128 // user may write to the directory to create the file.
2129 if ( (mode & W_OK) == 0 )
2130 return false; // Check for write access is not part of mode => bail out
2131
2132
2133 if (!KDE::access( pathname, F_OK)) // if it already exists
2134 return false;
2135
2136 //strip the filename (everything until '/' from the end
2137 QString dirName(pathname);
2138 int pos = dirName.lastIndexOf(QLatin1Char('/'));
2139 if ( pos == -1 )
2140 return false; // No path in argument. This is evil, we won't allow this
2141 else if ( pos == 0 ) // don't turn e.g. /root into an empty string
2142 pos = 1;
2143
2144 dirName.truncate(pos); // strip everything starting from the last '/'
2145
2146 accessOK = KDE::access( dirName, W_OK );
2147 // -?- Can I write to the accessed diretory
2148 if ( accessOK == 0 )
2149 return true; // Yes
2150 else
2151 return false; // No
2152}
2153
KComponentData
Per component data.
Definition: kcomponentdata.h:47
KComponentData::dirs
KStandardDirs * dirs() const
Returns the application standard dirs object.
Definition: kcomponentdata.cpp:193
KConfigGroup
A class for one specific group in a KConfig object.
Definition: kconfiggroup.h:54
KConfigGroup::readEntry
T readEntry(const QString &key, const T &aDefault) const
Reads the value of an entry specified by pKey in the current group.
Definition: kconfiggroup.h:248
KConfigGroup::hasKey
bool hasKey(const QString &key) const
Checks whether the key has an entry in this group.
Definition: kconfiggroup.cpp:1155
KConfigGroup::entryMap
QMap< QString, QString > entryMap() const
Returns a map (tree) of entries for all entries in this group.
Definition: kconfiggroup.cpp:603
KConfig
The central class of the KDE configuration data system.
Definition: kconfig.h:71
KConfig::entryMap
QMap< QString, QString > entryMap(const QString &aGroup=QString()) const
Returns a map (tree) of entries in a particular group.
Definition: kconfig.cpp:356
KLocale::localizedFilePath
QString localizedFilePath(const QString &filePath) const
Definition: klocale.cpp:744
KStandardDirs
Site-independent access to standard KDE directories.
Definition: kstandarddirs.h:172
KStandardDirs::localkdedir
QString localkdedir() const
Returns the toplevel directory in which KStandardDirs will store things.
Definition: kstandarddirs.cpp:2071
KStandardDirs::KStandardDirs
KStandardDirs()
KStandardDirs' constructor.
Definition: kstandarddirs.cpp:243
KStandardDirs::addXdgConfigPrefix
void addXdgConfigPrefix(const QString &dir)
Adds another search dir to front of the XDG_CONFIG_XXX list of prefixes.
Definition: kstandarddirs.cpp:337
KStandardDirs::localxdgconfdir
QString localxdgconfdir() const
Definition: kstandarddirs.cpp:2083
KStandardDirs::findExe
static QString findExe(const QString &appname, const QString &pathstr=QString(), SearchOptions options=NoSearchOptions)
Finds the executable in the system path.
Definition: kstandarddirs.cpp:1334
KStandardDirs::relativeLocation
QString relativeLocation(const char *type, const QString &absPath)
Converts an absolute path to a path relative to a certain resource.
Definition: kstandarddirs.cpp:1557
KStandardDirs::exists
static bool exists(const QString &fullPath)
Checks for existence and accessability of a file or directory.
Definition: kstandarddirs.cpp:587
KStandardDirs::Recursive
@ Recursive
Definition: kstandarddirs.h:191
KStandardDirs::IgnoreExecBit
@ IgnoreExecBit
Definition: kstandarddirs.h:193
KStandardDirs::NoDuplicates
@ NoDuplicates
Definition: kstandarddirs.h:192
KStandardDirs::checkAccess
static bool checkAccess(const QString &pathname, int mode)
Check, if a file may be accessed in a given mode.
Definition: kstandarddirs.cpp:2120
KStandardDirs::kde_default
static QString kde_default(const char *type)
This returns a default relative path for the standard KDE resource types.
Definition: kstandarddirs.cpp:1478
KStandardDirs::allTypes
QStringList allTypes() const
This function will return a list of all the types that KStandardDirs supports.
Definition: kstandarddirs.cpp:281
KStandardDirs::installPath
static QString installPath(const char *type)
Definition: kstandarddirs_unix.cpp:25
KStandardDirs::makeDir
static bool makeDir(const QString &dir, int mode=0755)
Recursively creates still-missing directories in the given path.
Definition: kstandarddirs.cpp:1577
KStandardDirs::findAllExe
static int findAllExe(QStringList &list, const QString &appname, const QString &pathstr=QString(), SearchOptions options=NoSearchOptions)
Finds all occurrences of an executable in the system path.
Definition: kstandarddirs.cpp:1403
KStandardDirs::findResourceDir
QString findResourceDir(const char *type, const QString &filename) const
Tries to find the directory the file is in.
Definition: kstandarddirs.cpp:553
KStandardDirs::kfsstnd_prefixes
QString kfsstnd_prefixes()
Definition: kstandarddirs.cpp:377
KStandardDirs::saveLocation
QString saveLocation(const char *type, const QString &suffix=QString(), bool create=true) const
Finds a location to save files into for the given type in the user's home directory.
Definition: kstandarddirs.cpp:1484
KStandardDirs::findAllResources
QStringList findAllResources(const char *type, const QString &filter=QString(), SearchOptions options=NoSearchOptions) const
Tries to find all resources with the specified type.
Definition: kstandarddirs.cpp:900
KStandardDirs::findDirs
QStringList findDirs(const char *type, const QString &reldir) const
Tries to find all directories whose names consist of the specified type and a relative path.
Definition: kstandarddirs.cpp:523
KStandardDirs::locateLocal
static QString locateLocal(const char *type, const QString &filename, const KComponentData &cData=KGlobal::mainComponent())
This function is much like locate.
Definition: kstandarddirs.cpp:2097
KStandardDirs::~KStandardDirs
virtual ~KStandardDirs()
KStandardDirs' destructor.
Definition: kstandarddirs.cpp:249
KStandardDirs::addResourceDir
bool addResourceDir(const char *type, const QString &absdir, bool priority=true)
Adds absolute path at the beginning of the search path for particular types (for example in case of i...
Definition: kstandarddirs.cpp:432
KStandardDirs::kfsstnd_xdg_data_prefixes
QString kfsstnd_xdg_data_prefixes()
Definition: kstandarddirs.cpp:387
KStandardDirs::locate
static QString locate(const char *type, const QString &filename, const KComponentData &cData=KGlobal::mainComponent())
This function is just for convenience.
Definition: kstandarddirs.cpp:2091
KStandardDirs::addResourceType
bool addResourceType(const char *type, const QString &relativename, bool priority=true)
Adds suffixes for types.
Definition: kstandarddirs.cpp:393
KStandardDirs::addPrefix
void addPrefix(const QString &dir)
Adds another search dir to front of the fsstnd list.
Definition: kstandarddirs.cpp:317
KStandardDirs::realPath
static QString realPath(const QString &dirname)
Expands all symbolic links and resolves references to '/.
Definition: kstandarddirs.cpp:914
KStandardDirs::addXdgDataPrefix
void addXdgDataPrefix(const QString &dir)
Adds another search dir to front of the XDG_DATA_XXX list of prefixes.
Definition: kstandarddirs.cpp:357
KStandardDirs::systemPaths
static QStringList systemPaths(const QString &pstr=QString())
Returns a QStringList list of pathnames in the system path.
Definition: kstandarddirs.cpp:1241
KStandardDirs::addCustomized
bool addCustomized(KConfig *config)
Reads customized entries out of the given config object and add them via addResourceDirs().
Definition: kstandarddirs.cpp:1945
KStandardDirs::realFilePath
static QString realFilePath(const QString &filename)
Expands all symbolic links and resolves references to '/.
Definition: kstandarddirs.cpp:973
KStandardDirs::findResource
QString findResource(const char *type, const QString &filename) const
Tries to find a resource in the following order:
Definition: kstandarddirs.cpp:458
KStandardDirs::localxdgdatadir
QString localxdgdatadir() const
Definition: kstandarddirs.cpp:2077
KStandardDirs::isRestrictedResource
bool isRestrictedResource(const char *type, const QString &relPath=QString()) const
Checks whether a resource is restricted as part of the KIOSK framework.
Definition: kstandarddirs.cpp:254
KStandardDirs::calcResourceHash
quint32 calcResourceHash(const char *type, const QString &filename, SearchOptions options=NoSearchOptions) const
Returns a number that identifies this version of the resource.
Definition: kstandarddirs.cpp:499
KStandardDirs::kfsstnd_xdg_conf_prefixes
QString kfsstnd_xdg_conf_prefixes()
Definition: kstandarddirs.cpp:382
KStandardDirs::resourceDirs
QStringList resourceDirs(const char *type) const
This function is used internally by almost all other function as it serves and fills the directories ...
Definition: kstandarddirs.cpp:1069
KUser
Represents a user on your system.
Definition: kuser.h:59
KUser::loginName
QString loginName() const
The login name of the user.
Definition: kuser_unix.cpp:144
QMap
QStringList
QString
quint32
kDebug
#define kDebug
Definition: kdebug.h:316
kWarning
#define kWarning
Definition: kdebug.h:322
kde_kiosk_admin
bool kde_kiosk_admin
Definition: kcomponentdata.cpp:163
kcomponentdata.h
kconfig.h
kconfiggroup.h
perror
QDebug perror(QDebug s, KDebugTag)
Definition: kdebug.cpp:779
kdebug.h
mac_app_filename
QString mac_app_filename()
Get the application name.
Definition: kkernel_mac.cpp:188
kkernel_mac.h
getWin32RegistryValue
QString getWin32RegistryValue(HKEY key, const QString &subKey, const QString &item, bool *ok)
Definition: kkernel_win.cpp:180
kkernel_win.h
klocale.h
cs
static Qt::CaseSensitivity cs
Definition: kmountpoint.cpp:37
kshell.h
cs
static Qt::CaseSensitivity cs
Definition: kstandarddirs.cpp:77
priorityAdd
static void priorityAdd(QStringList &prefixes, const QString &dir, bool priority)
Definition: kstandarddirs.cpp:302
lookupDirectory
static void lookupDirectory(const QString &path, const QString &relPart, const QRegExp &regexp, QStringList &list, QStringList &relList, bool recursive, bool unique)
Definition: kstandarddirs.cpp:611
updateHash
static quint32 updateHash(const QString &file, quint32 hash)
Definition: kstandarddirs.cpp:490
executableExtensions
static QStringList executableExtensions()
Definition: kstandarddirs.cpp:1226
types_indices
static const int types_indices[]
Definition: kstandarddirs.cpp:230
equalizePath
static QString equalizePath(QString &str)
Definition: kstandarddirs.cpp:1445
getBundle
static QString getBundle(const QString &path, bool ignore)
Definition: kstandarddirs.cpp:1267
tokenize
static void tokenize(QStringList &token, const QString &str, const QString &delim)
Definition: kstandarddirs.cpp:1458
kde_kiosk_admin
bool kde_kiosk_admin
Definition: kcomponentdata.cpp:163
checkExecutable
static QString checkExecutable(const QString &path, bool ignoreExecBit)
Definition: kstandarddirs.cpp:1292
lookupPrefix
static void lookupPrefix(const QString &prefix, const QString &relpath, const QString &relPart, const QRegExp &regexp, QStringList &list, QStringList &relList, bool recursive, bool unique)
Definition: kstandarddirs.cpp:738
types_string
static const char types_string[]
Definition: kstandarddirs.cpp:176
readEnvPath
static QString readEnvPath(const char *env)
Definition: kstandarddirs.cpp:1622
lookupProfiles
static QStringList lookupProfiles(const QString &mapFile)
Definition: kstandarddirs.cpp:1876
kstandarddirs.h
prefix
QString prefix()
Definition: kstandarddirs_win.cpp:28
kuser.h
KDE::lstat
int lstat(const QString &path, KDE_struct_stat *buf)
Definition: kde_file_win.cpp:148
KDE::stat
int stat(const QString &path, KDE_struct_stat *buf)
Definition: kde_file_win.cpp:175
KDE::access
int access(const QString &path, int mode)
Definition: kde_file_win.cpp:123
KGlobal::dirs
KStandardDirs * dirs()
Returns the application standard dirs object.
KGlobal::locale
KLocale * locale()
Returns the global locale object.
Definition: kglobal.cpp:170
KGlobal::hasLocale
bool hasLocale()
Definition: kglobal.cpp:205
KShell::tildeExpand
QString tildeExpand(const QString &path)
Performs tilde expansion on path.
Definition: kshell.cpp:55
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDECore

Skip menu "KDECore"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal