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

KDECore

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

KDE's Doxygen guidelines are available online.

KDECore

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

kdelibs-4.14.3 API Reference

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