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

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