• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.14.30 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
77 static Qt::CaseSensitivity cs = Qt::CaseInsensitive;
78 #else
79 static Qt::CaseSensitivity cs = Qt::CaseSensitive;
80 #endif
81 
82 class KStandardDirs::KStandardDirsPrivate
83 {
84 public:
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 
122 data
123 share/apps
124 html
125 share/doc/HTML
126 icon
127 share/icons
128 config
129 share/config
130 pixmap
131 share/pixmaps
132 apps
133 share/applnk
134 sound
135 share/sounds
136 locale
137 share/locale
138 services
139 share/kde4/services
140 servicetypes
141 share/kde4/servicetypes
142 mime
143 share/mimelnk
144 cgi
145 cgi-bin
146 wallpaper
147 share/wallpapers
148 templates
149 share/templates
150 exe
151 bin
152 module
153 %lib/kde4
154 qtplugins
155 %lib/kde4/plugins
156 kcfg
157 share/config.kcfg
158 emoticons
159 share/emoticons
160 xdgdata-apps
161 applications
162 xdgdata-icon
163 icons
164 xdgdata-pixmap
165 pixmaps
166 xdgdata-dirs
167 desktop-directories
168 xdgdata-mime
169 mime
170 xdgconf-menu
171 menus
172 xdgconf-autostart
173 autostart
174 */
175 
176 static 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 
230 static 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 
240 static void tokenize(QStringList& token, const QString& str,
241  const QString& delim);
242 
243 KStandardDirs::KStandardDirs()
244  : d(new KStandardDirsPrivate(this))
245 {
246  addKDEDefaults();
247 }
248 
249 KStandardDirs::~KStandardDirs()
250 {
251  delete d;
252 }
253 
254 bool 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 
268 bool 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 
281 QStringList 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 
302 static 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 
317 void KStandardDirs::addPrefix( const QString& _dir )
318 {
319  addPrefix(_dir, false);
320 }
321 
322 void 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 
337 void KStandardDirs::addXdgConfigPrefix( const QString& _dir )
338 {
339  addXdgConfigPrefix(_dir, false);
340 }
341 
342 void 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 
357 void KStandardDirs::addXdgDataPrefix( const QString& _dir )
358 {
359  addXdgDataPrefix(_dir, false);
360 }
361 
362 void 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 
377 QString KStandardDirs::kfsstnd_prefixes()
378 {
379  return d->m_prefixes.join(QString(QLatin1Char(KPATH_SEPARATOR)));
380 }
381 
382 QString KStandardDirs::kfsstnd_xdg_conf_prefixes()
383 {
384  return d->xdgconf_prefixes.join(QString(QLatin1Char(KPATH_SEPARATOR)));
385 }
386 
387 QString KStandardDirs::kfsstnd_xdg_data_prefixes()
388 {
389  return d->xdgdata_prefixes.join(QString(QLatin1Char(KPATH_SEPARATOR)));
390 }
391 
392 #ifndef KDE_NO_DEPRECATED
393 bool KStandardDirs::addResourceType( const char *type,
394  const QString& relativename,
395  bool priority )
396 {
397  return addResourceType( type, 0, relativename, priority);
398 }
399 #endif
400 
401 bool 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 
432 bool 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 
458 QString 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 
490 static 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 
499 quint32 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 
523 QStringList 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 
553 QString 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 
587 bool 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 
611 static 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 
738 static 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 
847 QStringList
848 KStandardDirs::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 
899 QStringList
900 KStandardDirs::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
913 QString
914 KStandardDirs::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
972 QString
973 KStandardDirs::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 
1001 void 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 
1069 QStringList KStandardDirs::resourceDirs(const char *type) const
1070 {
1071  return d->resourceDirs(type, QString());
1072 }
1073 
1074 QStringList 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
1226 static 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 
1241 QStringList 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
1267 static 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 
1292 static 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 
1334 QString 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 
1403 int 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 
1445 static 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 
1458 static 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
1478 QString KStandardDirs::kde_default(const char *type)
1479 {
1480  return QString(QLatin1Char('%')) + QString::fromLatin1(type) + QLatin1Char('/');
1481 }
1482 #endif
1483 
1484 QString 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
1557 QString 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 
1577 bool 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 
1622 static 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__
1642 static 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 
1668 void 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 
1688 void 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 
1876 static 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 
1943 extern bool kde_kiosk_admin;
1944 
1945 bool 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 
2071 QString KStandardDirs::localkdedir() const
2072 {
2073  // Return the prefix to use for saving
2074  return d->m_prefixes.first();
2075 }
2076 
2077 QString KStandardDirs::localxdgdatadir() const
2078 {
2079  // Return the prefix to use for saving
2080  return d->xdgdata_prefixes.first();
2081 }
2082 
2083 QString 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
2091 QString KStandardDirs::locate( const char *type,
2092  const QString& filename, const KComponentData &cData)
2093 {
2094  return cData.dirs()->findResource(type, filename);
2095 }
2096 
2097 QString KStandardDirs::locateLocal( const char *type,
2098  const QString& filename, const KComponentData &cData)
2099 {
2100  return locateLocal(type, filename, true, cData);
2101 }
2102 
2103 QString 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 
2120 bool 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 
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&#39;s home directory.
Definition: kstandarddirs.cpp:1484
KStandardDirs::kfsstnd_xdg_conf_prefixes
QString kfsstnd_xdg_conf_prefixes()
Definition: kstandarddirs.cpp:382
lookupProfiles
static QStringList lookupProfiles(const QString &mapFile)
Definition: kstandarddirs.cpp:1876
kuser.h
types_string
static const char types_string[]
Definition: kstandarddirs.cpp:176
updateHash
static quint32 updateHash(const QString &file, quint32 hash)
Definition: kstandarddirs.cpp:490
equalizePath
static QString equalizePath(QString &str)
Definition: kstandarddirs.cpp:1445
perror
QDebug perror(QDebug s, KDebugTag)
Definition: kdebug.cpp:779
KLocale::localizedFilePath
QString localizedFilePath(const QString &filePath) const
Definition: klocale.cpp:744
kdebug.h
KStandardDirs::realFilePath
static QString realFilePath(const QString &filename)
Expands all symbolic links and resolves references to &#39;/.
Definition: kstandarddirs.cpp:973
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
KMacroExpander::group
Definition: kmacroexpander_unix.cpp:34
KStandardDirs::KStandardDirs
KStandardDirs()
KStandardDirs&#39; constructor.
Definition: kstandarddirs.cpp:243
kkernel_mac.h
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::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
kconfig.h
executableExtensions
static QStringList executableExtensions()
Definition: kstandarddirs.cpp:1226
kshell.h
KGlobal::dirs
KStandardDirs * dirs()
Returns the application standard dirs object.
cs
static Qt::CaseSensitivity cs
Definition: kstandarddirs.cpp:77
KDE::stat
int stat(const QString &path, KDE_struct_stat *buf)
Definition: kde_file_win.cpp:175
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::IgnoreExecBit
Definition: kstandarddirs.h:193
quint32
readEnvPath
static QString readEnvPath(const char *env)
Definition: kstandarddirs.cpp:1622
QString
types_indices
static const int types_indices[]
Definition: kstandarddirs.cpp:230
klocale.h
KStandardDirs::exists
static bool exists(const QString &fullPath)
Checks for existence and accessability of a file or directory.
Definition: kstandarddirs.cpp:587
KStandardDirs::~KStandardDirs
virtual ~KStandardDirs()
KStandardDirs&#39; destructor.
Definition: kstandarddirs.cpp:249
prefix
QString prefix()
Definition: kstandarddirs_win.cpp:28
KGlobal::config
KSharedConfigPtr config()
Returns the general config object.
Definition: kglobal.cpp:139
KStandardDirs::makeDir
static bool makeDir(const QString &dir, int mode=0755)
Recursively creates still-missing directories in the given path.
Definition: kstandarddirs.cpp:1577
KUser
Represents a user on your system.
Definition: kuser.h:59
KConfig::entryMap
QMap< QString, QString > entryMap(const QString &aGroup=QString()) const
Returns a map (tree) of entries in a particular group.
Definition: kconfig.cpp:386
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::Recursive
Definition: kstandarddirs.h:191
KStandardDirs
Site-independent access to standard KDE directories.
Definition: kstandarddirs.h:171
KUser::loginName
QString loginName() const
The login name of the user.
Definition: kuser_unix.cpp:144
KStandardDirs::systemPaths
static QStringList systemPaths(const QString &pstr=QString())
Returns a QStringList list of pathnames in the system path.
Definition: kstandarddirs.cpp:1241
QStringList
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::kfsstnd_xdg_data_prefixes
QString kfsstnd_xdg_data_prefixes()
Definition: kstandarddirs.cpp:387
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::localxdgdatadir
QString localxdgdatadir() const
Definition: kstandarddirs.cpp:2077
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
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
mac_app_filename
QString mac_app_filename()
Get the application name.
Definition: kkernel_mac.cpp:188
KStandardDirs::kfsstnd_prefixes
QString kfsstnd_prefixes()
Definition: kstandarddirs.cpp:377
KStandardDirs::localxdgconfdir
QString localxdgconfdir() const
Definition: kstandarddirs.cpp:2083
kkernel_win.h
KStandardDirs::installPath
static QString installPath(const char *type)
Definition: kstandarddirs_unix.cpp:25
KStandardDirs::findResourceDir
QString findResourceDir(const char *type, const QString &filename) const
Tries to find the directory the file is in.
Definition: kstandarddirs.cpp:553
kWarning
#define kWarning
Definition: kdebug.h:322
KStandardDirs::NoDuplicates
Definition: kstandarddirs.h:192
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
getBundle
static QString getBundle(const QString &path, bool ignore)
Definition: kstandarddirs.cpp:1267
KDE::lstat
int lstat(const QString &path, KDE_struct_stat *buf)
Definition: kde_file_win.cpp:148
KConfigGroup::hasKey
bool hasKey(const QString &key) const
Checks whether the key has an entry in this group.
Definition: kconfiggroup.cpp:1155
KGlobal::locale
KLocale * locale()
Returns the global locale object.
Definition: kglobal.cpp:170
KConfigGroup
A class for one specific group in a KConfig object.
Definition: kconfiggroup.h:53
KConfig
The central class of the KDE configuration data system.
Definition: kconfig.h:70
tokenize
static void tokenize(QStringList &token, const QString &str, const QString &delim)
Definition: kstandarddirs.cpp:1458
checkExecutable
static QString checkExecutable(const QString &path, bool ignoreExecBit)
Definition: kstandarddirs.cpp:1292
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
KDE::access
int access(const QString &path, int mode)
Definition: kde_file_win.cpp:123
kstandarddirs.h
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
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::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
priorityAdd
static void priorityAdd(QStringList &prefixes, const QString &dir, bool priority)
Definition: kstandarddirs.cpp:302
KStandardDirs::findResource
QString findResource(const char *type, const QString &filename) const
Tries to find a resource in the following order:
Definition: kstandarddirs.cpp:458
KShell::tildeExpand
QString tildeExpand(const QString &path)
Performs tilde expansion on path.
Definition: kshell.cpp:55
KStandardDirs::localkdedir
QString localkdedir() const
Returns the toplevel directory in which KStandardDirs will store things.
Definition: kstandarddirs.cpp:2071
kde_kiosk_admin
bool kde_kiosk_admin
Definition: kcomponentdata.cpp:163
kDebug
#define kDebug
Definition: kdebug.h:316
KDE::fopen
FILE * fopen(const QString &pathname, const char *mode)
Definition: kde_file_win.cpp:143
KStandardDirs::allTypes
QStringList allTypes() const
This function will return a list of all the types that KStandardDirs supports.
Definition: kstandarddirs.cpp:281
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::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::addXdgConfigPrefix
void addXdgConfigPrefix(const QString &dir)
Adds another search dir to front of the XDG_CONFIG_XXX list of prefixes.
Definition: kstandarddirs.cpp:337
kcomponentdata.h
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
KGlobal::hasLocale
bool hasLocale()
Definition: kglobal.cpp:205
KComponentData
Per component data.
Definition: kcomponentdata.h:46
KStandardDirs::realPath
static QString realPath(const QString &dirname)
Expands all symbolic links and resolves references to &#39;/.
Definition: kstandarddirs.cpp:914
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
KConfigGroup::entryMap
QMap< QString, QString > entryMap() const
Returns a map (tree) of entries for all entries in this group.
Definition: kconfiggroup.cpp:603
getWin32RegistryValue
QString getWin32RegistryValue(HKEY key, const QString &subKey, const QString &item, bool *ok)
Definition: kkernel_win.cpp:180
QMap
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
kconfiggroup.h
KComponentData::dirs
KStandardDirs * dirs() const
Returns the application standard dirs object.
Definition: kcomponentdata.cpp:193
This file is part of the KDE documentation.
Documentation copyright © 1996-2017 The KDE developers.
Generated on Tue May 16 2017 16:18:30 by doxygen 1.8.11 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.30 API Reference

Skip menu "kdelibs-4.14.30 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