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

KDECore

  • sources
  • kde-4.12
  • kdelibs
  • 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  if((*pit).compare(installprefix, cs) != 0 || installdir.isEmpty())
1153  {
1154  for (QStringList::ConstIterator it = dirs.constBegin();
1155  it != dirs.constEnd(); ++it)
1156  {
1157  if ((*it).startsWith(QLatin1Char('%')))
1158  continue;
1159  const QString path = realPath( *pit + *it );
1160  testdir.setPath(path);
1161  if (local && restrictionActive)
1162  continue;
1163  if ((local || testdir.exists()) && !candidates.contains(path, cs))
1164  candidates.append(path);
1165  }
1166  local = false;
1167  }
1168  else
1169  {
1170  // we have a custom install path, so use this instead of <installprefix>/<relative dir>
1171  testdir.setPath(installdir);
1172  if(testdir.exists() && ! candidates.contains(installdir, cs))
1173  candidates.append(installdir);
1174  }
1175  }
1176  }
1177 
1178  // make sure we find the path where it's installed
1179  if (!installdir.isEmpty()) {
1180  bool ok = true;
1181  foreach (const QString &s, candidates) {
1182  if (installdir.startsWith(s, cs)) {
1183  ok = false;
1184  break;
1185  }
1186  }
1187  if (ok)
1188  candidates.append(installdir);
1189  }
1190 
1191  const QStringList absDirs = m_absolutes.value(type);
1192  for (QStringList::ConstIterator it = absDirs.constBegin();
1193  it != absDirs.constEnd(); ++it)
1194  {
1195  testdir.setPath(*it);
1196  if (testdir.exists()) {
1197  const QString filename = realPath( *it );
1198  if (!candidates.contains(filename, cs)) {
1199  candidates.append(filename);
1200  }
1201  }
1202  }
1203 
1204  // Insert result into the cache for next time.
1205  // Exception: data_subdir restrictions are per-subdir, so we can't store such results
1206  if (!dataRestrictionActive) {
1207  //kDebug() << this << "Inserting" << type << candidates << "into dircache";
1208  m_dircache.insert(type, candidates);
1209  }
1210  }
1211 
1212 #if 0
1213  kDebug(180) << "found dirs for resource" << type << ":" << candidates;
1214 #endif
1215 
1216  return candidates;
1217 }
1218 
1219 #ifdef Q_OS_WIN
1220 static QStringList executableExtensions()
1221 {
1222  QStringList ret = QString::fromLocal8Bit(qgetenv("PATHEXT")).split(QLatin1Char(';'));
1223  if (!ret.contains(QLatin1String(".exe"), Qt::CaseInsensitive)) {
1224  // If %PATHEXT% does not contain .exe, it is either empty, malformed, or distorted in ways that we cannot support, anyway.
1225  ret.clear();
1226  ret << QLatin1String(".exe")
1227  << QLatin1String(".com")
1228  << QLatin1String(".bat")
1229  << QLatin1String(".cmd");
1230  }
1231  return ret;
1232 }
1233 #endif
1234 
1235 QStringList KStandardDirs::systemPaths( const QString& pstr )
1236 {
1237  QStringList tokens;
1238  QString p = pstr;
1239 
1240  if( p.isEmpty() )
1241  {
1242  p = QString::fromLocal8Bit( qgetenv( "PATH" ) );
1243  }
1244 
1245  QString delimiters(QLatin1Char(KPATH_SEPARATOR));
1246  delimiters += QLatin1Char('\b');
1247  tokenize( tokens, p, delimiters );
1248 
1249  QStringList exePaths;
1250 
1251  // split path using : or \b as delimiters
1252  for( int i = 0; i < tokens.count(); i++ )
1253  {
1254  exePaths << KShell::tildeExpand( tokens[ i ] );
1255  }
1256 
1257  return exePaths;
1258 }
1259 
1260 #ifdef Q_WS_MAC
1261 static QString getBundle( const QString& path, bool ignore )
1262 {
1263  //kDebug(180) << "getBundle(" << path << ", " << ignore << ") called";
1264  QFileInfo info;
1265  QString bundle = path;
1266  bundle += QLatin1String(".app/Contents/MacOS/") + bundle.section(QLatin1Char('/'), -1);
1267  info.setFile( bundle );
1268  FILE *file;
1269  if (file = fopen(info.absoluteFilePath().toUtf8().constData(), "r")) {
1270  fclose(file);
1271  struct stat _stat;
1272  if ((stat(info.absoluteFilePath().toUtf8().constData(), &_stat)) < 0) {
1273  return QString();
1274  }
1275  if ( ignore || (_stat.st_mode & S_IXUSR) ) {
1276  if ( ((_stat.st_mode & S_IFMT) == S_IFREG) || ((_stat.st_mode & S_IFMT) == S_IFLNK) ) {
1277  //kDebug(180) << "getBundle(): returning " << bundle;
1278  return bundle;
1279  }
1280  }
1281  }
1282  return QString();
1283 }
1284 #endif
1285 
1286 static QString checkExecutable( const QString& path, bool ignoreExecBit )
1287 {
1288 #ifdef Q_WS_MAC
1289  QString bundle = getBundle( path, ignoreExecBit );
1290  if ( !bundle.isEmpty() ) {
1291  //kDebug(180) << "findExe(): returning " << bundle;
1292  return bundle;
1293  }
1294 #endif
1295  QFileInfo info( path );
1296  QFileInfo orig = info;
1297 #if defined(Q_OS_DARWIN) || defined(Q_OS_MAC)
1298  FILE *file;
1299  if (file = fopen(orig.absoluteFilePath().toUtf8().constData(), "r")) {
1300  fclose(file);
1301  struct stat _stat;
1302  if ((stat(orig.absoluteFilePath().toUtf8().constData(), &_stat)) < 0) {
1303  return QString();
1304  }
1305  if ( ignoreExecBit || (_stat.st_mode & S_IXUSR) ) {
1306  if ( ((_stat.st_mode & S_IFMT) == S_IFREG) || ((_stat.st_mode & S_IFMT) == S_IFLNK) ) {
1307  orig.makeAbsolute();
1308  return orig.filePath();
1309  }
1310  }
1311  }
1312  return QString();
1313 #else
1314  if( info.exists() && info.isSymLink() )
1315  info = QFileInfo( info.canonicalFilePath() );
1316  if( info.exists() && ( ignoreExecBit || info.isExecutable() ) && info.isFile() ) {
1317  // return absolute path, but without symlinks resolved in order to prevent
1318  // problems with executables that work differently depending on name they are
1319  // run as (for example gunzip)
1320  orig.makeAbsolute();
1321  return orig.filePath();
1322  }
1323  //kDebug(180) << "checkExecutable(): failed, returning empty string";
1324  return QString();
1325 #endif
1326 }
1327 
1328 QString KStandardDirs::findExe( const QString& appname,
1329  const QString& pstr,
1330  SearchOptions options )
1331 {
1332  //kDebug(180) << "findExe(" << appname << ", pstr, " << ignoreExecBit << ") called";
1333 
1334 #ifdef Q_OS_WIN
1335  QStringList executable_extensions = executableExtensions();
1336  if (!executable_extensions.contains(appname.section(QLatin1Char('.'), -1, -1, QString::SectionIncludeLeadingSep), Qt::CaseInsensitive)) {
1337  QString found_exe;
1338  foreach (const QString& extension, executable_extensions) {
1339  found_exe = findExe(appname + extension, pstr, options);
1340  if (!found_exe.isEmpty()) {
1341  return found_exe;
1342  }
1343  }
1344  return QString();
1345  }
1346 #endif
1347  QFileInfo info;
1348 
1349  // absolute or relative path?
1350  if (appname.contains(QDir::separator()))
1351  {
1352  //kDebug(180) << "findExe(): absolute path given";
1353  QString path = checkExecutable(appname, options & IgnoreExecBit);
1354  return path;
1355  }
1356 
1357  //kDebug(180) << "findExe(): relative path given";
1358 
1359  QString p = installPath("libexec") + appname;
1360  QString result = checkExecutable(p, options & IgnoreExecBit);
1361  if (!result.isEmpty()) {
1362  //kDebug(180) << "findExe(): returning " << result;
1363  return result;
1364  }
1365 
1366  //kDebug(180) << "findExe(): checking system paths";
1367  const QStringList exePaths = systemPaths( pstr );
1368  for (QStringList::ConstIterator it = exePaths.begin(); it != exePaths.end(); ++it)
1369  {
1370  p = (*it) + QLatin1Char('/');
1371  p += appname;
1372 
1373  // Check for executable in this tokenized path
1374  result = checkExecutable(p, options & IgnoreExecBit);
1375  if (!result.isEmpty()) {
1376  //kDebug(180) << "findExe(): returning " << result;
1377  return result;
1378  }
1379  }
1380 
1381  // Not found in PATH, look into the KDE-specific bin dir ("exe" resource)
1382  p = installPath("exe");
1383  p += appname;
1384  result = checkExecutable(p, options & IgnoreExecBit);
1385  if (!result.isEmpty()) {
1386  //kDebug(180) << "findExe(): returning " << result;
1387  return result;
1388  }
1389 
1390  // If we reach here, the executable wasn't found.
1391  // So return empty string.
1392 
1393  //kDebug(180) << "findExe(): failed, nothing matched";
1394  return QString();
1395 }
1396 
1397 int KStandardDirs::findAllExe( QStringList& list, const QString& appname,
1398  const QString& pstr, SearchOptions options )
1399 {
1400 #ifdef Q_OS_WIN
1401  QStringList executable_extensions = executableExtensions();
1402  if (!executable_extensions.contains(appname.section(QLatin1Char('.'), -1, -1, QString::SectionIncludeLeadingSep), Qt::CaseInsensitive)) {
1403  int total = 0;
1404  foreach (const QString& extension, executable_extensions) {
1405  total += findAllExe (list, appname + extension, pstr, options);
1406  }
1407  return total;
1408  }
1409 #endif
1410  QFileInfo info;
1411  QString p;
1412  list.clear();
1413 
1414  const QStringList exePaths = systemPaths( pstr );
1415  for (QStringList::ConstIterator it = exePaths.begin(); it != exePaths.end(); ++it)
1416  {
1417  p = (*it) + QLatin1Char('/');
1418  p += appname;
1419 
1420 #ifdef Q_WS_MAC
1421  QString bundle = getBundle( p, (options & IgnoreExecBit) );
1422  if ( !bundle.isEmpty() ) {
1423  //kDebug(180) << "findExe(): returning " << bundle;
1424  list.append( bundle );
1425  }
1426 #endif
1427 
1428  info.setFile( p );
1429 
1430  if( info.exists() && ( ( options & IgnoreExecBit ) || info.isExecutable())
1431  && info.isFile() ) {
1432  list.append( p );
1433  }
1434  }
1435 
1436  return list.count();
1437 }
1438 
1439 static inline QString equalizePath(QString &str)
1440 {
1441 #ifdef Q_WS_WIN
1442  // filter pathes through QFileInfo to have always
1443  // the same case for drive letters
1444  QFileInfo f(str);
1445  if (f.isAbsolute())
1446  return f.absoluteFilePath();
1447  else
1448 #endif
1449  return str;
1450 }
1451 
1452 static void tokenize(QStringList& tokens, const QString& str,
1453  const QString& delim)
1454 {
1455  const int len = str.length();
1456  QString token;
1457 
1458  for(int index = 0; index < len; index++) {
1459  if (delim.contains(str[index])) {
1460  tokens.append(equalizePath(token));
1461  token.clear();
1462  } else {
1463  token += str[index];
1464  }
1465  }
1466  if (!token.isEmpty()) {
1467  tokens.append(equalizePath(token));
1468  }
1469 }
1470 
1471 #ifndef KDE_NO_DEPRECATED
1472 QString KStandardDirs::kde_default(const char *type)
1473 {
1474  return QString(QLatin1Char('%')) + QString::fromLatin1(type) + QLatin1Char('/');
1475 }
1476 #endif
1477 
1478 QString KStandardDirs::saveLocation(const char *type,
1479  const QString& suffix,
1480  bool create) const
1481 {
1482  QMutexLocker lock(&d->m_cacheMutex);
1483  QString path = d->m_savelocations.value(type);
1484  if (path.isEmpty())
1485  {
1486  QStringList dirs = d->m_relatives.value(type);
1487  if (dirs.isEmpty() && (
1488  (strcmp(type, "socket") == 0) ||
1489  (strcmp(type, "tmp") == 0) ||
1490  (strcmp(type, "cache") == 0) ))
1491  {
1492  (void) resourceDirs(type); // Generate socket|tmp|cache resource.
1493  dirs = d->m_relatives.value(type); // Search again.
1494  }
1495  if (!dirs.isEmpty())
1496  {
1497  path = dirs.first();
1498 
1499  if (path.startsWith(QLatin1Char('%'))) {
1500  // grab the "data" from "%data/apps"
1501  const int pos = path.indexOf(QLatin1Char('/'));
1502  QString rel = path.mid(1, pos - 1);
1503  QString rest = path.mid(pos + 1);
1504  QString basepath = saveLocation(rel.toUtf8().constData());
1505  path = basepath + rest;
1506  } else
1507 
1508  // Check for existence of typed directory + suffix
1509  if (strncmp(type, "xdgdata-", 8) == 0) {
1510  path = realPath( localxdgdatadir() + path ) ;
1511  } else if (strncmp(type, "xdgconf-", 8) == 0) {
1512  path = realPath( localxdgconfdir() + path );
1513  } else {
1514  path = realPath( localkdedir() + path );
1515  }
1516  }
1517  else {
1518  dirs = d->m_absolutes.value(type);
1519  if (dirs.isEmpty()) {
1520  qFatal("KStandardDirs: The resource type %s is not registered", type);
1521  } else {
1522  path = realPath(dirs.first());
1523  }
1524  }
1525 
1526  d->m_savelocations.insert(type, path.endsWith(QLatin1Char('/')) ? path : path + QLatin1Char('/'));
1527  }
1528  QString fullPath = path + suffix;
1529 
1530  KDE_struct_stat st;
1531  if (KDE::stat(fullPath, &st) != 0 || !(S_ISDIR(st.st_mode))) {
1532  if(!create) {
1533 #ifndef NDEBUG
1534  // Too much noise from kbuildsycoca4 -- it's fine if this happens from KConfig
1535  // when parsing global files without a local equivalent.
1536  //kDebug(180) << QString("save location %1 doesn't exist").arg(fullPath);
1537 #endif
1538  return fullPath;
1539  }
1540  if(!makeDir(fullPath, 0700)) {
1541  return fullPath;
1542  }
1543  d->m_dircache.remove(type);
1544  }
1545  if (!fullPath.endsWith(QLatin1Char('/')))
1546  fullPath += QLatin1Char('/');
1547  return fullPath;
1548 }
1549 
1550 // KDE5: make the method const
1551 QString KStandardDirs::relativeLocation(const char *type, const QString &absPath)
1552 {
1553  QString fullPath = absPath;
1554  int i = absPath.lastIndexOf(QLatin1Char('/'));
1555  if (i != -1) {
1556  fullPath = realFilePath(absPath); // Normalize
1557  }
1558 
1559  const QStringList candidates = resourceDirs(type);
1560 
1561  for (QStringList::ConstIterator it = candidates.begin();
1562  it != candidates.end(); ++it) {
1563  if (fullPath.startsWith(*it, cs)) {
1564  return fullPath.mid((*it).length());
1565  }
1566  }
1567  return absPath;
1568 }
1569 
1570 
1571 bool KStandardDirs::makeDir(const QString& dir, int mode)
1572 {
1573  // we want an absolute path
1574  if (QDir::isRelativePath(dir))
1575  return false;
1576 
1577 #ifdef Q_WS_WIN
1578  return QDir().mkpath(dir);
1579 #else
1580  QString target = dir;
1581  uint len = target.length();
1582 
1583  // append trailing slash if missing
1584  if (dir.at(len - 1) != QLatin1Char('/'))
1585  target += QLatin1Char('/');
1586 
1587  QString base;
1588  uint i = 1;
1589 
1590  while( i < len )
1591  {
1592  KDE_struct_stat st;
1593  int pos = target.indexOf(QLatin1Char('/'), i);
1594  base += target.mid(i - 1, pos - i + 1);
1595  QByteArray baseEncoded = QFile::encodeName(base);
1596  // bail out if we encountered a problem
1597  if (KDE_stat(baseEncoded, &st) != 0)
1598  {
1599  // Directory does not exist....
1600  // Or maybe a dangling symlink ?
1601  if (KDE_lstat(baseEncoded, &st) == 0)
1602  (void)unlink(baseEncoded); // try removing
1603 
1604  if (KDE_mkdir(baseEncoded, static_cast<mode_t>(mode)) != 0) {
1605  baseEncoded.prepend( "trying to create local folder " );
1606  perror(baseEncoded.constData());
1607  return false; // Couldn't create it :-(
1608  }
1609  }
1610  i = pos + 1;
1611  }
1612  return true;
1613 #endif
1614 }
1615 
1616 static QString readEnvPath(const char *env)
1617 {
1618  QByteArray c_path;
1619 #ifndef _WIN32_WCE
1620  c_path = qgetenv(env);
1621  if (c_path.isEmpty())
1622  return QString();
1623 #else
1624  bool ok;
1625  QString retval = getWin32RegistryValue(HKEY_LOCAL_MACHINE, "Software\\kde", "KDEDIRS", &ok);
1626  if (!ok){
1627  return QString();
1628  } else {
1629  c_path = retval.toLatin1();
1630  }
1631 #endif
1632  return QDir::fromNativeSeparators(QFile::decodeName(c_path));
1633 }
1634 
1635 #ifdef __linux__
1636 static QString executablePrefix()
1637 {
1638  char path_buffer[MAXPATHLEN + 1];
1639  path_buffer[MAXPATHLEN] = 0;
1640  int length = readlink ("/proc/self/exe", path_buffer, MAXPATHLEN);
1641  if (length == -1)
1642  return QString();
1643 
1644  path_buffer[length] = '\0';
1645 
1646  QString path = QFile::decodeName(path_buffer);
1647 
1648  if(path.isEmpty())
1649  return QString();
1650 
1651  int pos = path.lastIndexOf(QLatin1Char('/')); // Skip filename
1652  if(pos <= 0)
1653  return QString();
1654  pos = path.lastIndexOf(QLatin1Char('/'), pos - 1); // Skip last directory
1655  if(pos <= 0)
1656  return QString();
1657 
1658  return path.left(pos);
1659 }
1660 #endif
1661 
1662 void KStandardDirs::addResourcesFrom_krcdirs()
1663 {
1664  QString localFile = QDir::currentPath() + QLatin1String("/.krcdirs");
1665  if (!QFile::exists(localFile))
1666  return;
1667 
1668  QSettings iniFile(localFile, QSettings::IniFormat);
1669  iniFile.beginGroup(QString::fromLatin1("KStandardDirs"));
1670  const QStringList resources = iniFile.allKeys();
1671  foreach(const QString &key, resources)
1672  {
1673  QDir path(iniFile.value(key).toString());
1674  if (!path.exists())
1675  continue;
1676 
1677  if(path.makeAbsolute())
1678  addResourceDir(key.toLatin1(), path.path(), false);
1679  }
1680 }
1681 
1682 void KStandardDirs::addKDEDefaults()
1683 {
1684  addResourcesFrom_krcdirs();
1685 
1686  QStringList kdedirList;
1687  // begin KDEDIRS
1688  QString kdedirs = readEnvPath("KDEDIRS");
1689 
1690  if (!kdedirs.isEmpty())
1691  {
1692  tokenize(kdedirList, kdedirs, QString(QLatin1Char(KPATH_SEPARATOR)));
1693  }
1694  kdedirList.append(installPath("kdedir"));
1695 
1696  QString execPrefix(QFile::decodeName(EXEC_INSTALL_PREFIX));
1697  if (!execPrefix.isEmpty() && !kdedirList.contains(execPrefix, cs))
1698  kdedirList.append(execPrefix);
1699 #ifdef __linux__
1700  const QString linuxExecPrefix = executablePrefix();
1701  if ( !linuxExecPrefix.isEmpty() )
1702  kdedirList.append( linuxExecPrefix );
1703 #endif
1704 
1705  // We treat root differently to prevent a "su" shell messing up the
1706  // file permissions in the user's home directory.
1707  QString localKdeDir = readEnvPath(getuid() ? "KDEHOME" : "KDEROOTHOME");
1708  if (!localKdeDir.isEmpty()) {
1709  if (!localKdeDir.endsWith(QLatin1Char('/')))
1710  localKdeDir += QLatin1Char('/');
1711  } else {
1712  // TODO KDE5: make localKdeDir equal to localXdgDir (which is determined further below and
1713  // defaults to ~/.config) + '/' + $KDECONFIG (which would default to e.g. "KDE")
1714  // This would mean ~/.config/KDE/ by default, more xdg-compliant.
1715 
1716 #if defined(Q_WS_MACX)
1717  localKdeDir = QDir::homePath() + QLatin1String("/Library/Preferences/KDE/");
1718 #elif defined(Q_WS_WIN)
1719 #ifndef _WIN32_WCE
1720  WCHAR wPath[MAX_PATH+1];
1721  if ( SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, wPath) == S_OK) {
1722  localKdeDir = QDir::fromNativeSeparators(QString::fromUtf16((const ushort *) wPath)) + QLatin1Char('/') + QString::fromLatin1(KDE_DEFAULT_HOME) + QLatin1Char('/');
1723  } else {
1724 #endif
1725  localKdeDir = QDir::homePath() + QLatin1Char('/') + QString::fromLatin1(KDE_DEFAULT_HOME) + QLatin1Char('/');
1726 #ifndef _WIN32_WCE
1727  }
1728 #endif
1729 #else
1730  localKdeDir = QDir::homePath() + QLatin1Char('/') + QString::fromLatin1(KDE_DEFAULT_HOME) + QLatin1Char('/');
1731 #endif
1732  }
1733 
1734  if (localKdeDir != QLatin1String("-/"))
1735  {
1736  localKdeDir = KShell::tildeExpand(localKdeDir);
1737  addPrefix(localKdeDir);
1738  }
1739 
1740 #ifdef Q_WS_MACX
1741  // Adds the "Contents" directory of the current application bundle to
1742  // the search path. This way bundled resources can be found.
1743  QDir bundleDir(mac_app_filename());
1744  if (bundleDir.dirName() == QLatin1String("MacOS")) { // just to be sure we're in a bundle
1745  bundleDir.cdUp();
1746  // now dirName should be "Contents". In there we can find our normal
1747  // dir-structure, beginning with "share"
1748  addPrefix(bundleDir.absolutePath());
1749  }
1750 #endif
1751 
1752  QStringList::ConstIterator end(kdedirList.end());
1753  for (QStringList::ConstIterator it = kdedirList.constBegin();
1754  it != kdedirList.constEnd(); ++it)
1755  {
1756  const QString dir = KShell::tildeExpand(*it);
1757  addPrefix(dir);
1758  }
1759  // end KDEDIRS
1760 
1761  // begin XDG_CONFIG_XXX
1762  QStringList xdgdirList;
1763  QString xdgdirs = readEnvPath("XDG_CONFIG_DIRS");
1764  if (!xdgdirs.isEmpty())
1765  {
1766  tokenize(xdgdirList, xdgdirs, QString(QLatin1Char(KPATH_SEPARATOR)));
1767  }
1768  else
1769  {
1770  xdgdirList.clear();
1771  xdgdirList.append(QString::fromLatin1("/etc/xdg"));
1772 #ifdef Q_WS_WIN
1773  xdgdirList.append(installPath("kdedir") + QString::fromLatin1("etc/xdg"));
1774 #else
1775  xdgdirList.append(QFile::decodeName(KDESYSCONFDIR "/xdg"));
1776 #endif
1777  }
1778 
1779  QString localXdgDir = readEnvPath("XDG_CONFIG_HOME");
1780  if (!localXdgDir.isEmpty()) {
1781  if (!localXdgDir.endsWith(QLatin1Char('/')))
1782  localXdgDir += QLatin1Char('/');
1783  } else {
1784 #ifdef Q_WS_MACX
1785  localXdgDir = QDir::homePath() + QString::fromLatin1("/Library/Preferences/XDG/");
1786 #else
1787  localXdgDir = QDir::homePath() + QString::fromLatin1("/.config/");
1788 #endif
1789  }
1790 
1791  localXdgDir = KShell::tildeExpand(localXdgDir);
1792  addXdgConfigPrefix(localXdgDir);
1793 
1794  for (QStringList::ConstIterator it = xdgdirList.constBegin();
1795  it != xdgdirList.constEnd(); ++it)
1796  {
1797  QString dir = KShell::tildeExpand(*it);
1798  addXdgConfigPrefix(dir);
1799  }
1800  // end XDG_CONFIG_XXX
1801 
1802  // begin XDG_DATA_XXX
1803  QStringList kdedirDataDirs;
1804  for (QStringList::ConstIterator it = kdedirList.constBegin();
1805  it != kdedirList.constEnd(); ++it) {
1806  QString dir = *it;
1807  if (!dir.endsWith(QLatin1Char('/')))
1808  dir += QLatin1Char('/');
1809  kdedirDataDirs.append(dir + QLatin1String("share/"));
1810  }
1811 
1812  xdgdirs = readEnvPath("XDG_DATA_DIRS");
1813  if (!xdgdirs.isEmpty()) {
1814  tokenize(xdgdirList, xdgdirs, QString(QLatin1Char(KPATH_SEPARATOR)));
1815  // Ensure the kdedirDataDirs are in there too,
1816  // otherwise resourceDirs() will add kdedir/share/applications/kde4
1817  // as returned by installPath(), and that's incorrect.
1818  Q_FOREACH(const QString& dir, kdedirDataDirs) {
1819  if (!xdgdirList.contains(dir, cs))
1820  xdgdirList.append(dir);
1821  }
1822  } else {
1823  xdgdirList = kdedirDataDirs;
1824 #ifndef Q_WS_WIN
1825  xdgdirList.append(QString::fromLatin1("/usr/local/share/"));
1826  xdgdirList.append(QString::fromLatin1("/usr/share/"));
1827 #endif
1828  }
1829 
1830  localXdgDir = readEnvPath("XDG_DATA_HOME");
1831  if (!localXdgDir.isEmpty())
1832  {
1833  if (localXdgDir[localXdgDir.length()-1] != QLatin1Char('/'))
1834  localXdgDir += QLatin1Char('/');
1835  }
1836  else
1837  {
1838  localXdgDir = QDir::homePath() + QLatin1String("/.local/share/");
1839  }
1840 
1841  localXdgDir = KShell::tildeExpand(localXdgDir);
1842  addXdgDataPrefix(localXdgDir);
1843 
1844  for (QStringList::ConstIterator it = xdgdirList.constBegin();
1845  it != xdgdirList.constEnd(); ++it)
1846  {
1847  QString dir = KShell::tildeExpand(*it);
1848  addXdgDataPrefix(dir);
1849  }
1850  // end XDG_DATA_XXX
1851 
1852 
1853  addResourceType("lib", 0, "lib" KDELIBSUFF "/");
1854 
1855  addResourceType("qtplugins", "lib", "plugins");
1856 
1857  uint index = 0;
1858  while (types_indices[index] != -1) {
1859  addResourceType(types_string + types_indices[index], 0, types_string + types_indices[index+1], true);
1860  index+=2;
1861  }
1862  addResourceType("exe", "lib", "kde4/libexec", true );
1863 
1864  addResourceDir("home", QDir::homePath(), false);
1865 
1866  addResourceType("autostart", "xdgconf-autostart", "/"); // merge them, start with xdg autostart
1867  addResourceType("autostart", NULL, "share/autostart"); // KDE ones are higher priority
1868 }
1869 
1870 static QStringList lookupProfiles(const QString &mapFile)
1871 {
1872  QStringList profiles;
1873 
1874  if (mapFile.isEmpty() || !QFile::exists(mapFile))
1875  {
1876  profiles << QString::fromLatin1("default");
1877  return profiles;
1878  }
1879 
1880  struct passwd *pw = getpwuid(geteuid());
1881  if (!pw)
1882  {
1883  profiles << QString::fromLatin1("default");
1884  return profiles; // Not good
1885  }
1886 
1887  QByteArray user = pw->pw_name;
1888 
1889  gid_t sup_gids[512];
1890  int sup_gids_nr = getgroups(512, sup_gids);
1891 
1892  KConfig mapCfgFile(mapFile);
1893  KConfigGroup mapCfg(&mapCfgFile, "Users");
1894  if (mapCfg.hasKey(user.constData()))
1895  {
1896  profiles = mapCfg.readEntry(user.constData(), QStringList());
1897  return profiles;
1898  }
1899 
1900  const KConfigGroup generalGrp(&mapCfgFile, "General");
1901  const QStringList groups = generalGrp.readEntry("groups", QStringList());
1902 
1903  const KConfigGroup groupsGrp(&mapCfgFile, "Groups");
1904 
1905  for( QStringList::ConstIterator it = groups.begin();
1906  it != groups.end(); ++it )
1907  {
1908  QByteArray grp = (*it).toUtf8();
1909  // Check if user is in this group
1910  struct group *grp_ent = getgrnam(grp);
1911  if (!grp_ent) continue;
1912  gid_t gid = grp_ent->gr_gid;
1913  if (pw->pw_gid == gid)
1914  {
1915  // User is in this group --> add profiles
1916  profiles += groupsGrp.readEntry(*it, QStringList());
1917  }
1918  else
1919  {
1920  for(int i = 0; i < sup_gids_nr; i++)
1921  {
1922  if (sup_gids[i] == gid)
1923  {
1924  // User is in this group --> add profiles
1925  profiles += groupsGrp.readEntry(*it, QStringList());
1926  break;
1927  }
1928  }
1929  }
1930  }
1931 
1932  if (profiles.isEmpty())
1933  profiles << QString::fromLatin1("default");
1934  return profiles;
1935 }
1936 
1937 extern bool kde_kiosk_admin;
1938 
1939 bool KStandardDirs::addCustomized(KConfig *config)
1940 {
1941  if (!d->m_checkRestrictions) // there are already customized entries
1942  return false; // we just quit and hope they are the right ones
1943 
1944  // save the numbers of config directories. If this changes,
1945  // we will return true to give KConfig a chance to reparse
1946  int configdirs = resourceDirs("config").count();
1947 
1948  if (true)
1949  {
1950  // reading the prefixes in
1951  QString group = QLatin1String("Directories");
1952  KConfigGroup cg(config, group);
1953 
1954  QString kioskAdmin = cg.readEntry("kioskAdmin");
1955  if (!kioskAdmin.isEmpty() && !kde_kiosk_admin)
1956  {
1957  int i = kioskAdmin.indexOf(QLatin1Char(':'));
1958  QString user = kioskAdmin.left(i);
1959  QString host = kioskAdmin.mid(i+1);
1960 
1961  KUser thisUser;
1962  char hostname[ 256 ];
1963  hostname[ 0 ] = '\0';
1964  if (!gethostname( hostname, 255 ))
1965  hostname[sizeof(hostname)-1] = '\0';
1966 
1967  if ((user == thisUser.loginName()) &&
1968  (host.isEmpty() || (host == QLatin1String(hostname))))
1969  {
1970  kde_kiosk_admin = true;
1971  }
1972  }
1973 
1974  bool readProfiles = true;
1975 
1976  if (kde_kiosk_admin && !qgetenv("KDE_KIOSK_NO_PROFILES").isEmpty())
1977  readProfiles = false;
1978 
1979  QString userMapFile = cg.readEntry("userProfileMapFile");
1980  QString profileDirsPrefix = cg.readEntry("profileDirsPrefix");
1981  if (!profileDirsPrefix.isEmpty() && !profileDirsPrefix.endsWith(QLatin1Char('/')))
1982  profileDirsPrefix.append(QLatin1Char('/'));
1983 
1984  QStringList profiles;
1985  if (readProfiles)
1986  profiles = lookupProfiles(userMapFile);
1987  QString profile;
1988 
1989  bool priority = false;
1990  while(true)
1991  {
1992  KConfigGroup cg(config, group);
1993  const QStringList list = cg.readEntry("prefixes", QStringList());
1994  for (QStringList::ConstIterator it = list.begin(); it != list.end(); ++it)
1995  {
1996  addPrefix(*it, priority);
1997  addXdgConfigPrefix(*it + QLatin1String("/etc/xdg"), priority);
1998  addXdgDataPrefix(*it + QLatin1String("/share"), priority);
1999  }
2000  // If there are no prefixes defined, check if there is a directory
2001  // for this profile under <profileDirsPrefix>
2002  if (list.isEmpty() && !profile.isEmpty() && !profileDirsPrefix.isEmpty())
2003  {
2004  QString dir = profileDirsPrefix + profile;
2005  addPrefix(dir, priority);
2006  addXdgConfigPrefix(dir + QLatin1String("/etc/xdg"), priority);
2007  addXdgDataPrefix(dir + QLatin1String("/share"), priority);
2008  }
2009 
2010  // iterating over all entries in the group Directories
2011  // to find entries that start with dir_$type
2012  const QMap<QString, QString> entries = config->entryMap(group);
2013  for (QMap<QString, QString>::ConstIterator it2 = entries.begin();
2014  it2 != entries.end(); ++it2)
2015  {
2016  const QString key = it2.key();
2017  if (key.startsWith(QLatin1String("dir_"))) {
2018  // generate directory list, there may be more than 1.
2019  const QStringList dirs = (*it2).split(QString(QLatin1Char(',')));
2020  QStringList::ConstIterator sIt(dirs.begin());
2021  QString resType = key.mid(4);
2022  for (; sIt != dirs.end(); ++sIt)
2023  {
2024  addResourceDir(resType.toLatin1(), *sIt, priority);
2025  }
2026  }
2027  }
2028  if (profiles.isEmpty())
2029  break;
2030  profile = profiles.back();
2031  group = QString::fromLatin1("Directories-%1").arg(profile);
2032  profiles.pop_back();
2033  priority = true;
2034  }
2035  }
2036 
2037  // Process KIOSK restrictions.
2038  if (!kde_kiosk_admin || qgetenv("KDE_KIOSK_NO_RESTRICTIONS").isEmpty())
2039  {
2040  KConfigGroup cg(config, "KDE Resource Restrictions");
2041  const QMap<QString, QString> entries = cg.entryMap();
2042  for (QMap<QString, QString>::ConstIterator it2 = entries.begin();
2043  it2 != entries.end(); ++it2)
2044  {
2045  const QString key = it2.key();
2046  if (!cg.readEntry(key, true))
2047  {
2048  d->m_restrictionsActive = true;
2049  const QByteArray cKey = key.toLatin1();
2050  d->m_restrictions.insert(cKey, true);
2051  d->m_dircache.remove(cKey);
2052  d->m_savelocations.remove(cKey);
2053  }
2054  }
2055  }
2056 
2057  // check if the number of config dirs changed
2058  bool configDirsChanged = (resourceDirs("config").count() != configdirs);
2059  // If the config dirs changed, we check kiosk restrictions again.
2060  d->m_checkRestrictions = configDirsChanged;
2061  // return true if the number of config dirs changed: reparse config file
2062  return configDirsChanged;
2063 }
2064 
2065 QString KStandardDirs::localkdedir() const
2066 {
2067  // Return the prefix to use for saving
2068  return d->m_prefixes.first();
2069 }
2070 
2071 QString KStandardDirs::localxdgdatadir() const
2072 {
2073  // Return the prefix to use for saving
2074  return d->xdgdata_prefixes.first();
2075 }
2076 
2077 QString KStandardDirs::localxdgconfdir() const
2078 {
2079  // Return the prefix to use for saving
2080  return d->xdgconf_prefixes.first();
2081 }
2082 
2083 
2084 // just to make code more readable without macros
2085 QString KStandardDirs::locate( const char *type,
2086  const QString& filename, const KComponentData &cData)
2087 {
2088  return cData.dirs()->findResource(type, filename);
2089 }
2090 
2091 QString KStandardDirs::locateLocal( const char *type,
2092  const QString& filename, const KComponentData &cData)
2093 {
2094  return locateLocal(type, filename, true, cData);
2095 }
2096 
2097 QString KStandardDirs::locateLocal( const char *type,
2098  const QString& filename, bool createDir,
2099  const KComponentData &cData)
2100 {
2101  // try to find slashes. If there are some, we have to
2102  // create the subdir first
2103  int slash = filename.lastIndexOf(QLatin1Char('/')) + 1;
2104  if (!slash) { // only one filename
2105  return cData.dirs()->saveLocation(type, QString(), createDir) + filename;
2106  }
2107 
2108  // split path from filename
2109  QString dir = filename.left(slash);
2110  QString file = filename.mid(slash);
2111  return cData.dirs()->saveLocation(type, dir, createDir) + file;
2112 }
2113 
2114 bool KStandardDirs::checkAccess(const QString& pathname, int mode)
2115 {
2116  int accessOK = KDE::access( pathname, mode );
2117  if ( accessOK == 0 )
2118  return true; // OK, I can really access the file
2119 
2120  // else
2121  // if we want to write the file would be created. Check, if the
2122  // user may write to the directory to create the file.
2123  if ( (mode & W_OK) == 0 )
2124  return false; // Check for write access is not part of mode => bail out
2125 
2126 
2127  if (!KDE::access( pathname, F_OK)) // if it already exists
2128  return false;
2129 
2130  //strip the filename (everything until '/' from the end
2131  QString dirName(pathname);
2132  int pos = dirName.lastIndexOf(QLatin1Char('/'));
2133  if ( pos == -1 )
2134  return false; // No path in argument. This is evil, we won't allow this
2135  else if ( pos == 0 ) // don't turn e.g. /root into an empty string
2136  pos = 1;
2137 
2138  dirName.truncate(pos); // strip everything starting from the last '/'
2139 
2140  accessOK = KDE::access( dirName, W_OK );
2141  // -?- Can I write to the accessed diretory
2142  if ( accessOK == 0 )
2143  return true; // Yes
2144  else
2145  return false; // No
2146 }
2147 
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:1478
KStandardDirs::kfsstnd_xdg_conf_prefixes
QString kfsstnd_xdg_conf_prefixes()
Definition: kstandarddirs.cpp:382
lookupProfiles
static QStringList lookupProfiles(const QString &mapFile)
Definition: kstandarddirs.cpp:1870
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:1439
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 '/.
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' 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:2085
kconfig.h
executableExtensions
static QStringList executableExtensions()
Definition: kstandarddirs.cpp:1220
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:2114
KStandardDirs::IgnoreExecBit
Definition: kstandarddirs.h:193
quint32
readEnvPath
static QString readEnvPath(const char *env)
Definition: kstandarddirs.cpp:1616
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' 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:138
KStandardDirs::makeDir
static bool makeDir(const QString &dir, int mode=0755)
Recursively creates still-missing directories in the given path.
Definition: kstandarddirs.cpp:1571
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:382
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:1235
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:1551
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:1397
KStandardDirs::localxdgdatadir
QString localxdgdatadir() const
Definition: kstandarddirs.cpp:2071
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:2077
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:1261
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:1156
KGlobal::locale
KLocale * locale()
Returns the global locale object.
Definition: kglobal.cpp:169
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:1452
checkExecutable
static QString checkExecutable(const QString &path, bool ignoreExecBit)
Definition: kstandarddirs.cpp:1286
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:2091
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:1328
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:2065
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:1939
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:204
KComponentData
Per component data.
Definition: kcomponentdata.h:46
KStandardDirs::realPath
static QString realPath(const QString &dirname)
Expands all symbolic links and resolves references to '/.
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:1472
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-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:47:09 by doxygen 1.8.7 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 API Reference

Skip menu "kdelibs 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
  • kjsembed
  •   WTF
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Nepomuk-Core
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



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