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

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