KIO

kfileitem.cpp
1 /*
2  This file is part of the KDE project
3  SPDX-FileCopyrightText: 1999-2011 David Faure <[email protected]>
4  SPDX-FileCopyrightText: 2001 Carsten Pfeiffer <[email protected]>
5 
6  SPDX-License-Identifier: LGPL-2.0-or-later
7 */
8 
9 #include "kfileitem.h"
10 
11 #include "kioglobal_p.h"
12 #include "kiocoredebug.h"
13 #include "../pathhelpers_p.h"
14 
15 #include <QDate>
16 #include <QDir>
17 #include <QDirIterator>
18 #include <QFile>
19 #include <QDataStream>
20 #include <QMimeDatabase>
21 #include <QDebug>
22 #include <QLocale>
23 #include <qplatformdefs.h>
24 
25 #include <KLocalizedString>
26 #include <KDesktopFile>
27 #include <kmountpoint.h>
28 #include <KConfigGroup>
29 #ifndef Q_OS_WIN
30 #include <knfsshare.h>
31 #include <ksambashare.h>
32 #endif
33 #include <KFileSystemType>
34 
35 class KFileItemPrivate : public QSharedData
36 {
37 public:
38  KFileItemPrivate(const KIO::UDSEntry &entry,
39  mode_t mode, mode_t permissions,
40  const QUrl &itemOrDirUrl,
41  bool urlIsDirectory,
42  bool delayedMimeTypes,
43  KFileItem::MimeTypeDetermination mimeTypeDetermination)
44  : m_entry(entry),
45  m_url(itemOrDirUrl),
46  m_strName(),
47  m_strText(),
48  m_iconName(),
49  m_strLowerCaseName(),
50  m_mimeType(),
51  m_fileMode(mode),
52  m_permissions(permissions),
53  m_bLink(false),
54  m_bIsLocalUrl(itemOrDirUrl.isLocalFile()),
55  m_bMimeTypeKnown(false),
56  m_delayedMimeTypes(delayedMimeTypes),
57  m_useIconNameCache(false),
58  m_hidden(Auto),
59  m_slow(SlowUnknown),
60  m_bSkipMimeTypeFromContent(mimeTypeDetermination == KFileItem::SkipMimeTypeFromContent),
61  m_bInitCalled(false)
62  {
63  if (entry.count() != 0) {
64  readUDSEntry(urlIsDirectory);
65  } else {
66  Q_ASSERT(!urlIsDirectory);
67  m_strName = itemOrDirUrl.fileName();
68  m_strText = KIO::decodeFileName(m_strName);
69  }
70  }
71 
75  void ensureInitialized() const;
76 
80  void init() const;
81 
82  QString localPath() const;
83  KIO::filesize_t size() const;
84  KIO::filesize_t recursiveSize() const;
85  QDateTime time(KFileItem::FileTimes which) const;
86  void setTime(KFileItem::FileTimes which, uint time_t_val) const;
87  void setTime(KFileItem::FileTimes which, const QDateTime &val) const;
88  bool cmp(const KFileItemPrivate &item) const;
89  bool isSlow() const;
90 
95  void readUDSEntry(bool _urlIsDirectory);
96 
100  QString parsePermissions(mode_t perm) const;
101 
105  void determineMimeTypeHelper(const QUrl &url) const;
106 
110  mutable KIO::UDSEntry m_entry;
114  QUrl m_url;
115 
119  QString m_strName;
120 
125  QString m_strText;
126 
130  mutable QString m_iconName;
131 
135  mutable QString m_strLowerCaseName;
136 
140  mutable QMimeType m_mimeType;
141 
145  mutable mode_t m_fileMode;
149  mutable mode_t m_permissions;
150 
154  mutable bool m_bLink: 1;
158  bool m_bIsLocalUrl: 1;
159 
160  mutable bool m_bMimeTypeKnown: 1;
161  mutable bool m_delayedMimeTypes: 1;
162 
164  mutable bool m_useIconNameCache: 1;
165 
166  // Auto: check leading dot.
167  enum { Auto, Hidden, Shown } m_hidden: 3;
168 
169  // Slow? (nfs/smb/ssh)
170  mutable enum { SlowUnknown, Fast, Slow } m_slow: 3;
171 
175  bool m_bSkipMimeTypeFromContent: 1;
176 
180  mutable bool m_bInitCalled: 1;
181 
182  // For special case like link to dirs over FTP
183  QString m_guessedMimeType;
184  mutable QString m_access;
185 
186 };
187 
188 void KFileItemPrivate::ensureInitialized() const
189 {
190  if (!m_bInitCalled) {
191  init();
192  }
193 }
194 
195 void KFileItemPrivate::init() const
196 {
197  m_access.clear();
198  // metaInfo = KFileMetaInfo();
199 
200  // stat() local files if needed
201  if (m_fileMode == KFileItem::Unknown || m_permissions == KFileItem::Unknown || m_entry.count() == 0) {
202  if (m_url.isLocalFile()) {
203  /* directories may not have a slash at the end if
204  * we want to stat() them; it requires that we
205  * change into it .. which may not be allowed
206  * stat("/is/unaccessible") -> rwx------
207  * stat("/is/unaccessible/") -> EPERM H.Z.
208  * This is the reason for the StripTrailingSlash
209  */
210  QT_STATBUF buf;
211  const QString path = m_url.adjusted(QUrl::StripTrailingSlash).toLocalFile();
212  const QByteArray pathBA = QFile::encodeName(path);
213  if (QT_LSTAT(pathBA.constData(), &buf) == 0) {
214  m_entry.reserve(9);
215  m_entry.replace(KIO::UDSEntry::UDS_DEVICE_ID, buf.st_dev);
216  m_entry.replace(KIO::UDSEntry::UDS_INODE, buf.st_ino);
217 
218  mode_t mode = buf.st_mode;
219  if ((buf.st_mode & QT_STAT_MASK) == QT_STAT_LNK) {
220  m_bLink = true;
221  if (QT_STAT(pathBA.constData(), &buf) == 0) {
222  mode = buf.st_mode;
223  } else {// link pointing to nowhere (see FileProtocol::createUDSEntry() in ioslaves/file/file.cpp)
224  mode = (QT_STAT_MASK - 1) | S_IRWXU | S_IRWXG | S_IRWXO;
225  }
226  }
227  m_entry.replace(KIO::UDSEntry::UDS_SIZE, buf.st_size);
228  m_entry.replace(KIO::UDSEntry::UDS_FILE_TYPE, buf.st_mode & QT_STAT_MASK); // extract file type
229  m_entry.replace(KIO::UDSEntry::UDS_ACCESS, buf.st_mode & 07777); // extract permissions
230  m_entry.replace(KIO::UDSEntry::UDS_MODIFICATION_TIME, buf.st_mtime); // TODO: we could use msecs too...
231  m_entry.replace(KIO::UDSEntry::UDS_ACCESS_TIME, buf.st_atime);
232 #ifndef Q_OS_WIN
233  m_entry.replace(KIO::UDSEntry::UDS_USER, KUser(buf.st_uid).loginName());
234  m_entry.replace(KIO::UDSEntry::UDS_GROUP, KUserGroup(buf.st_gid).name());
235 #endif
236 
237  // TODO: these can be removed, we can use UDS_FILE_TYPE and UDS_ACCESS everywhere
238  if (m_fileMode == KFileItem::Unknown) {
239  m_fileMode = mode & QT_STAT_MASK; // extract file type
240  }
241  if (m_permissions == KFileItem::Unknown) {
242  m_permissions = mode & 07777; // extract permissions
243  }
244  }
245  }
246  }
247 
248  m_bInitCalled = true;
249 }
250 
251 void KFileItemPrivate::readUDSEntry(bool _urlIsDirectory)
252 {
253  // extract fields from the KIO::UDS Entry
254 
255  m_fileMode = m_entry.numberValue(KIO::UDSEntry::UDS_FILE_TYPE, KFileItem::Unknown);
256  m_permissions = m_entry.numberValue(KIO::UDSEntry::UDS_ACCESS, KFileItem::Unknown);
257  m_strName = m_entry.stringValue(KIO::UDSEntry::UDS_NAME);
258 
259  const QString displayName = m_entry.stringValue(KIO::UDSEntry::UDS_DISPLAY_NAME);
260  if (!displayName.isEmpty()) {
261  m_strText = displayName;
262  } else {
263  m_strText = KIO::decodeFileName(m_strName);
264  }
265 
266  const QString urlStr = m_entry.stringValue(KIO::UDSEntry::UDS_URL);
267  const bool UDS_URL_seen = !urlStr.isEmpty();
268  if (UDS_URL_seen) {
269  m_url = QUrl(urlStr);
270  if (m_url.isLocalFile()) {
271  m_bIsLocalUrl = true;
272  }
273  }
274  QMimeDatabase db;
275  const QString mimeTypeStr = m_entry.stringValue(KIO::UDSEntry::UDS_MIME_TYPE);
276  m_bMimeTypeKnown = !mimeTypeStr.isEmpty();
277  if (m_bMimeTypeKnown) {
278  m_mimeType = db.mimeTypeForName(mimeTypeStr);
279  }
280 
281  m_guessedMimeType = m_entry.stringValue(KIO::UDSEntry::UDS_GUESSED_MIME_TYPE);
282  m_bLink = !m_entry.stringValue(KIO::UDSEntry::UDS_LINK_DEST).isEmpty(); // we don't store the link dest
283 
284  const int hiddenVal = m_entry.numberValue(KIO::UDSEntry::UDS_HIDDEN, -1);
285  m_hidden = hiddenVal == 1 ? Hidden : (hiddenVal == 0 ? Shown : Auto);
286 
287  if (_urlIsDirectory && !UDS_URL_seen && !m_strName.isEmpty() && m_strName != QLatin1String(".")) {
288  m_url.setPath(concatPaths(m_url.path(), m_strName));
289  }
290 
291  m_iconName.clear();
292 }
293 
294 inline //because it is used only in one place
295 KIO::filesize_t KFileItemPrivate::size() const
296 {
297  ensureInitialized();
298 
299  // Extract it from the KIO::UDSEntry
300  long long fieldVal = m_entry.numberValue(KIO::UDSEntry::UDS_SIZE, -1);
301  if (fieldVal != -1) {
302  return fieldVal;
303  }
304 
305  // If not in the KIO::UDSEntry, or if UDSEntry empty, use stat() [if local URL]
306  if (m_bIsLocalUrl) {
307  return QFileInfo(m_url.toLocalFile()).size();
308  }
309  return 0;
310 }
311 
312 KIO::filesize_t KFileItemPrivate::recursiveSize() const
313 {
314  // Extract it from the KIO::UDSEntry
315  long long fieldVal = m_entry.numberValue(KIO::UDSEntry::UDS_RECURSIVE_SIZE, -1);
316  if (fieldVal != -1) {
317  return static_cast<KIO::filesize_t>(fieldVal);
318  }
319 
320  return 0;
321 }
322 
323 static uint udsFieldForTime(KFileItem::FileTimes mappedWhich)
324 {
325  switch (mappedWhich) {
326  case KFileItem::ModificationTime:
328  case KFileItem::AccessTime:
330  case KFileItem::CreationTime:
332  }
333  return 0;
334 }
335 
336 void KFileItemPrivate::setTime(KFileItem::FileTimes mappedWhich, uint time_t_val) const
337 {
338  m_entry.replace(udsFieldForTime(mappedWhich), time_t_val);
339 }
340 
341 void KFileItemPrivate::setTime(KFileItem::FileTimes mappedWhich, const QDateTime &val) const
342 {
343  const QDateTime dt = val.toLocalTime(); // #160979
344  setTime(mappedWhich, dt.toSecsSinceEpoch());
345 }
346 
347 QDateTime KFileItemPrivate::time(KFileItem::FileTimes mappedWhich) const
348 {
349  ensureInitialized();
350 
351  // Extract it from the KIO::UDSEntry
352  const uint uds = udsFieldForTime(mappedWhich);
353  if (uds > 0) {
354  const long long fieldVal = m_entry.numberValue(uds, -1);
355  if (fieldVal != -1) {
356  return QDateTime::fromMSecsSinceEpoch(1000 * fieldVal);
357  }
358  }
359 
360  return QDateTime();
361 }
362 
363 inline //because it is used only in one place
364 bool KFileItemPrivate::cmp(const KFileItemPrivate &item) const
365 {
366  if (item.m_bInitCalled) {
367  ensureInitialized();
368  }
369 
370  if (m_bInitCalled) {
371  item.ensureInitialized();
372  }
373 
374 #if 0
375  //qDebug() << "Comparing" << m_url << "and" << item.m_url;
376  //qDebug() << " name" << (m_strName == item.m_strName);
377  //qDebug() << " local" << (m_bIsLocalUrl == item.m_bIsLocalUrl);
378  //qDebug() << " mode" << (m_fileMode == item.m_fileMode);
379  //qDebug() << " perm" << (m_permissions == item.m_permissions);
380  //qDebug() << " UDS_EXTENDED_ACL" << (m_entry.stringValue( KIO::UDSEntry::UDS_EXTENDED_ACL ) == item.m_entry.stringValue( KIO::UDSEntry::UDS_EXTENDED_ACL ));
381  //qDebug() << " UDS_ACL_STRING" << (m_entry.stringValue( KIO::UDSEntry::UDS_ACL_STRING ) == item.m_entry.stringValue( KIO::UDSEntry::UDS_ACL_STRING ));
382  //qDebug() << " UDS_DEFAULT_ACL_STRING" << (m_entry.stringValue( KIO::UDSEntry::UDS_DEFAULT_ACL_STRING ) == item.m_entry.stringValue( KIO::UDSEntry::UDS_DEFAULT_ACL_STRING ));
383  //qDebug() << " m_bLink" << (m_bLink == item.m_bLink);
384  //qDebug() << " m_hidden" << (m_hidden == item.m_hidden);
385  //qDebug() << " size" << (size() == item.size());
386  //qDebug() << " ModificationTime" << m_entry.numberValue(KIO::UDSEntry::UDS_MODIFICATION_TIME) << item.m_entry.numberValue(KIO::UDSEntry::UDS_MODIFICATION_TIME);
387  //qDebug() << " UDS_ICON_NAME" << (m_entry.stringValue( KIO::UDSEntry::UDS_ICON_NAME ) == item.m_entry.stringValue( KIO::UDSEntry::UDS_ICON_NAME ));
388 #endif
389  return (m_strName == item.m_strName
390  && m_bIsLocalUrl == item.m_bIsLocalUrl
391  && m_fileMode == item.m_fileMode
392  && m_permissions == item.m_permissions
393  && m_entry.stringValue(KIO::UDSEntry::UDS_EXTENDED_ACL) == item.m_entry.stringValue(KIO::UDSEntry::UDS_EXTENDED_ACL)
394  && m_entry.stringValue(KIO::UDSEntry::UDS_ACL_STRING) == item.m_entry.stringValue(KIO::UDSEntry::UDS_ACL_STRING)
395  && m_entry.stringValue(KIO::UDSEntry::UDS_DEFAULT_ACL_STRING) == item.m_entry.stringValue(KIO::UDSEntry::UDS_DEFAULT_ACL_STRING)
396  && m_bLink == item.m_bLink
397  && m_hidden == item.m_hidden
398  && size() == item.size()
399  && m_entry.numberValue(KIO::UDSEntry::UDS_MODIFICATION_TIME) == item.m_entry.numberValue(KIO::UDSEntry::UDS_MODIFICATION_TIME)
400  && m_entry.stringValue(KIO::UDSEntry::UDS_ICON_NAME) == item.m_entry.stringValue(KIO::UDSEntry::UDS_ICON_NAME)
401  && m_entry.stringValue(KIO::UDSEntry::UDS_TARGET_URL) == item.m_entry.stringValue(KIO::UDSEntry::UDS_TARGET_URL)
402  && m_entry.stringValue(KIO::UDSEntry::UDS_LOCAL_PATH) == item.m_entry.stringValue(KIO::UDSEntry::UDS_LOCAL_PATH)
403  );
404 
405  // Don't compare the mimetypes here. They might not be known, and we don't want to
406  // do the slow operation of determining them here.
407 }
408 
409 inline //because it is used only in one place
410 QString KFileItemPrivate::parsePermissions(mode_t perm) const
411 {
412  ensureInitialized();
413 
414  static char buffer[ 12 ];
415 
416  char uxbit, gxbit, oxbit;
417 
418  if ((perm & (S_IXUSR | S_ISUID)) == (S_IXUSR | S_ISUID)) {
419  uxbit = 's';
420  } else if ((perm & (S_IXUSR | S_ISUID)) == S_ISUID) {
421  uxbit = 'S';
422  } else if ((perm & (S_IXUSR | S_ISUID)) == S_IXUSR) {
423  uxbit = 'x';
424  } else {
425  uxbit = '-';
426  }
427 
428  if ((perm & (S_IXGRP | S_ISGID)) == (S_IXGRP | S_ISGID)) {
429  gxbit = 's';
430  } else if ((perm & (S_IXGRP | S_ISGID)) == S_ISGID) {
431  gxbit = 'S';
432  } else if ((perm & (S_IXGRP | S_ISGID)) == S_IXGRP) {
433  gxbit = 'x';
434  } else {
435  gxbit = '-';
436  }
437 
438  if ((perm & (S_IXOTH | S_ISVTX)) == (S_IXOTH | S_ISVTX)) {
439  oxbit = 't';
440  } else if ((perm & (S_IXOTH | S_ISVTX)) == S_ISVTX) {
441  oxbit = 'T';
442  } else if ((perm & (S_IXOTH | S_ISVTX)) == S_IXOTH) {
443  oxbit = 'x';
444  } else {
445  oxbit = '-';
446  }
447 
448  // Include the type in the first char like ls does; people are more used to seeing it,
449  // even though it's not really part of the permissions per se.
450  if (m_bLink) {
451  buffer[0] = 'l';
452  } else if (m_fileMode != KFileItem::Unknown) {
453  if ((m_fileMode & QT_STAT_MASK) == QT_STAT_DIR) {
454  buffer[0] = 'd';
455  }
456 #ifdef Q_OS_UNIX
457  else if (S_ISSOCK(m_fileMode)) {
458  buffer[0] = 's';
459  } else if (S_ISCHR(m_fileMode)) {
460  buffer[0] = 'c';
461  } else if (S_ISBLK(m_fileMode)) {
462  buffer[0] = 'b';
463  } else if (S_ISFIFO(m_fileMode)) {
464  buffer[0] = 'p';
465  }
466 #endif // Q_OS_UNIX
467  else {
468  buffer[0] = '-';
469  }
470  } else {
471  buffer[0] = '-';
472  }
473 
474  buffer[1] = (((perm & S_IRUSR) == S_IRUSR) ? 'r' : '-');
475  buffer[2] = (((perm & S_IWUSR) == S_IWUSR) ? 'w' : '-');
476  buffer[3] = uxbit;
477  buffer[4] = (((perm & S_IRGRP) == S_IRGRP) ? 'r' : '-');
478  buffer[5] = (((perm & S_IWGRP) == S_IWGRP) ? 'w' : '-');
479  buffer[6] = gxbit;
480  buffer[7] = (((perm & S_IROTH) == S_IROTH) ? 'r' : '-');
481  buffer[8] = (((perm & S_IWOTH) == S_IWOTH) ? 'w' : '-');
482  buffer[9] = oxbit;
483  // if (hasExtendedACL())
484  if (m_entry.contains(KIO::UDSEntry::UDS_EXTENDED_ACL)) {
485  buffer[10] = '+';
486  buffer[11] = 0;
487  } else {
488  buffer[10] = 0;
489  }
490 
491  return QString::fromLatin1(buffer);
492 }
493 
494 void KFileItemPrivate::determineMimeTypeHelper(const QUrl &url) const
495 {
496  QMimeDatabase db;
497  if (m_bSkipMimeTypeFromContent) {
498  const QString scheme = url.scheme();
499  if (scheme.startsWith(QLatin1String("http")) || scheme == QLatin1String("mailto"))
500  m_mimeType = db.mimeTypeForName(QLatin1String("application/octet-stream"));
501  else
502  m_mimeType = db.mimeTypeForFile(url.path(), QMimeDatabase::MatchMode::MatchExtension);
503  } else {
504  m_mimeType = db.mimeTypeForUrl(url);
505  }
506 }
507 
509 
511  : d(nullptr)
512 {
513 }
514 
515 KFileItem::KFileItem(const KIO::UDSEntry &entry, const QUrl &itemOrDirUrl,
516  bool delayedMimeTypes, bool urlIsDirectory)
517  : d(new KFileItemPrivate(entry, KFileItem::Unknown, KFileItem::Unknown, itemOrDirUrl, urlIsDirectory, delayedMimeTypes, KFileItem::NormalMimeTypeDetermination))
518 {
519 }
520 
521 #if KIOCORE_BUILD_DEPRECATED_SINCE(5, 0)
522 KFileItem::KFileItem(mode_t mode, mode_t permissions, const QUrl &url, bool delayedMimeTypes)
523  : d(new KFileItemPrivate(KIO::UDSEntry(), mode, permissions,
524  url, false, delayedMimeTypes, KFileItem::NormalMimeTypeDetermination))
525 {
526 }
527 #endif
528 
529 KFileItem::KFileItem(const QUrl &url, const QString &mimeType, mode_t mode)
530  : d(new KFileItemPrivate(KIO::UDSEntry(), mode, KFileItem::Unknown,
531  url, false, false, KFileItem::NormalMimeTypeDetermination))
532 {
533  d->m_bMimeTypeKnown = !mimeType.isEmpty();
534  if (d->m_bMimeTypeKnown) {
535  QMimeDatabase db;
536  d->m_mimeType = db.mimeTypeForName(mimeType);
537  }
538 }
539 
540 KFileItem::KFileItem(const QUrl &url, KFileItem::MimeTypeDetermination mimeTypeDetermination)
541  : d(new KFileItemPrivate(KIO::UDSEntry(), KFileItem::Unknown, KFileItem::Unknown,
542  url, false, false, mimeTypeDetermination))
543 {
544 }
545 
546 
547 // Default implementations for:
548 // - Copy constructor
549 // - Move constructor
550 // - Copy assignment
551 // - Move assignment
552 // - Destructor
553 // The compiler will now generate the content of those.
554 KFileItem::KFileItem(const KFileItem&) = default;
555 KFileItem::~KFileItem() = default;
556 KFileItem::KFileItem(KFileItem&&) = default;
557 KFileItem& KFileItem::operator=(const KFileItem&) = default;
559 
561 {
562  if (!d) {
563  qCWarning(KIO_CORE) << "null item";
564  return;
565  }
566 
567  d->m_fileMode = KFileItem::Unknown;
568  d->m_permissions = KFileItem::Unknown;
569  d->m_hidden = KFileItemPrivate::Auto;
570  refreshMimeType();
571 
572  // Basically, we can't trust any information we got while listing.
573  // Everything could have changed...
574  // Clearing m_entry makes it possible to detect changes in the size of the file,
575  // the time information, etc.
576  d->m_entry.clear();
577  d->init(); // re-populates d->m_entry
578 }
579 
581 {
582  if (!d) {
583  return;
584  }
585 
586  d->m_mimeType = QMimeType();
587  d->m_bMimeTypeKnown = false;
588  d->m_iconName.clear();
589 }
590 
592 {
593  if (!d) {
594  return;
595  }
596  d->m_delayedMimeTypes = b;
597 }
598 
599 void KFileItem::setUrl(const QUrl &url)
600 {
601  if (!d) {
602  qCWarning(KIO_CORE) << "null item";
603  return;
604  }
605 
606  d->m_url = url;
607  setName(url.fileName());
608 }
609 
611 {
612  if (!d) {
613  qCWarning(KIO_CORE) << "null item";
614  return;
615  }
616 
617  d->m_entry.replace(KIO::UDSEntry::UDS_LOCAL_PATH, path);
618 }
619 
621 {
622  if (!d) {
623  qCWarning(KIO_CORE) << "null item";
624  return;
625  }
626 
627  d->ensureInitialized();
628 
629  d->m_strName = name;
630  if (!d->m_strName.isEmpty()) {
631  d->m_strText = KIO::decodeFileName(d->m_strName);
632  }
633  if (d->m_entry.contains(KIO::UDSEntry::UDS_NAME)) {
634  d->m_entry.replace(KIO::UDSEntry::UDS_NAME, d->m_strName); // #195385
635  }
636 
637 }
638 
640 {
641  if (!d) {
642  return QString();
643  }
644 
645  d->ensureInitialized();
646 
647  // Extract it from the KIO::UDSEntry
648  const QString linkStr = d->m_entry.stringValue(KIO::UDSEntry::UDS_LINK_DEST);
649  if (!linkStr.isEmpty()) {
650  return linkStr;
651  }
652 
653  // If not in the KIO::UDSEntry, or if UDSEntry empty, use readlink() [if local URL]
654  if (d->m_bIsLocalUrl) {
655  return QFile::symLinkTarget(d->m_url.adjusted(QUrl::StripTrailingSlash).toLocalFile());
656  }
657  return QString();
658 }
659 
660 QString KFileItemPrivate::localPath() const
661 {
662  if (m_bIsLocalUrl) {
663  return m_url.toLocalFile();
664  }
665 
666  ensureInitialized();
667 
668  // Extract the local path from the KIO::UDSEntry
669  return m_entry.stringValue(KIO::UDSEntry::UDS_LOCAL_PATH);
670 }
671 
673 {
674  if (!d) {
675  return QString();
676  }
677 
678  return d->localPath();
679 }
680 
682 {
683  if (!d) {
684  return 0;
685  }
686 
687  return d->size();
688 }
689 
691 {
692  if (!d) {
693  return 0;
694  }
695 
696  return d->recursiveSize();
697 }
698 
700 {
701  if (!d) {
702  return false;
703  }
704 
705  // Check if the field exists; its value doesn't matter
707 }
708 
710 {
711  if (!d) {
712  return KACL();
713  }
714 
715  if (hasExtendedACL()) {
716  // Extract it from the KIO::UDSEntry
717  const QString fieldVal = d->m_entry.stringValue(KIO::UDSEntry::UDS_ACL_STRING);
718  if (!fieldVal.isEmpty()) {
719  return KACL(fieldVal);
720  }
721  }
722 
723  // create one from the basic permissions
724  return KACL(d->m_permissions);
725 }
726 
728 {
729  if (!d) {
730  return KACL();
731  }
732 
733  // Extract it from the KIO::UDSEntry
735  if (!fieldVal.isEmpty()) {
736  return KACL(fieldVal);
737  } else {
738  return KACL();
739  }
740 }
741 
743 {
744  if (!d) {
745  return QDateTime();
746  }
747 
748  return d->time(which);
749 }
750 
752 {
753  if (!d) {
754  return QString();
755  }
756 
758 }
759 
761 {
762  if (!d) {
763  return QString();
764  }
765 
767 }
768 
769 bool KFileItemPrivate::isSlow() const
770 {
771  if (m_slow == SlowUnknown) {
772  const QString path = localPath();
773  if (!path.isEmpty()) {
775  m_slow = (fsType == KFileSystemType::Nfs || fsType == KFileSystemType::Smb) ? Slow : Fast;
776  } else {
777  m_slow = Slow;
778  }
779  }
780  return m_slow == Slow;
781 }
782 
783 bool KFileItem::isSlow() const
784 {
785  if (!d) {
786  return false;
787  }
788 
789  return d->isSlow();
790 }
791 
793 {
794  if (!d) {
795  return QString();
796  }
797 
798  KFileItem *that = const_cast<KFileItem *>(this);
799  return that->determineMimeType().name();
800 }
801 
803 {
804  if (!d) {
805  return QMimeType();
806  }
807 
808  if (!d->m_mimeType.isValid() || !d->m_bMimeTypeKnown) {
809  QMimeDatabase db;
810  if (isDir()) {
811  d->m_mimeType = db.mimeTypeForName(QStringLiteral("inode/directory"));
812  } else {
813  bool isLocalUrl;
814  const QUrl url = mostLocalUrl(&isLocalUrl);
815  d->determineMimeTypeHelper(url);
816 
817  // was: d->m_mimeType = KMimeType::findByUrl( url, d->m_fileMode, isLocalUrl );
818  // => we are no longer using d->m_fileMode for remote URLs.
819  Q_ASSERT(d->m_mimeType.isValid());
820  //qDebug() << d << "finding final mimetype for" << url << ":" << d->m_mimeType.name();
821  }
822  d->m_bMimeTypeKnown = true;
823  }
824 
825  if (d->m_delayedMimeTypes) { // if we delayed getting the iconName up till now, this is the right point in time to do so
826  d->m_delayedMimeTypes = false;
827  d->m_useIconNameCache = false;
828  (void)iconName();
829  }
830 
831  return d->m_mimeType;
832 }
833 
835 {
836  if (!d) {
837  return false;
838  }
839 
840  // The mimetype isn't known if determineMimeType was never called (on-demand determination)
841  // or if this fileitem has a guessed mimetype (e.g. ftp symlink) - in which case
842  // it always remains "not fully determined"
843  return d->m_bMimeTypeKnown && d->m_guessedMimeType.isEmpty();
844 }
845 
846 static bool isDirectoryMounted(const QUrl &url)
847 {
848  // Stating .directory files can cause long freezes when e.g. /home
849  // uses autofs for every user's home directory, i.e. opening /home
850  // in a file dialog will mount every single home directory.
851  // These non-mounted directories can be identified by having 0 size.
852  // There are also other directories with 0 size, such as /proc, that may
853  // be mounted, but those are unlikely to contain .directory (and checking
854  // this would require checking with KMountPoint).
855 
856  // TODO: maybe this could be checked with KFileSystemType instead?
857  QFileInfo info(url.toLocalFile());
858  if (info.isDir() && info.size() == 0) {
859  return false;
860  }
861  return true;
862 }
863 
865 {
866  if (!d) {
867  return false;
868  }
869  return d->m_bMimeTypeKnown && (!d->m_delayedMimeTypes);
870 }
871 
872 // KDE5 TODO: merge with comment()? Need to see what lxr says about the usage of both.
874 {
875  if (!d) {
876  return QString();
877  }
878 
879  const QString displayType = d->m_entry.stringValue(KIO::UDSEntry::UDS_DISPLAY_TYPE);
880  if (!displayType.isEmpty()) {
881  return displayType;
882  }
883 
884  bool isLocalUrl;
885  QUrl url = mostLocalUrl(&isLocalUrl);
886 
887  QMimeType mime = currentMimeType();
888  // This cannot move to kio_file (with UDS_DISPLAY_TYPE) because it needs
889  // the mimetype to be determined, which is done here, and possibly delayed...
890  if (isLocalUrl && !d->isSlow() && mime.inherits(QStringLiteral("application/x-desktop"))) {
891  KDesktopFile cfg(url.toLocalFile());
892  QString comment = cfg.desktopGroup().readEntry("Comment");
893  if (!comment.isEmpty()) {
894  return comment;
895  }
896  }
897 
898  // Support for .directory file in directories
899  if (isLocalUrl && isDir() && !d->isSlow() && isDirectoryMounted(url)) {
900  QUrl u(url);
901  u.setPath(concatPaths(u.path(), QStringLiteral(".directory")));
902  const KDesktopFile cfg(u.toLocalFile());
903  const QString comment = cfg.readComment();
904  if (!comment.isEmpty()) {
905  return comment;
906  }
907  }
908 
909  const QString comment = mime.comment();
910  //qDebug() << "finding comment for " << url.url() << " : " << d->m_mimeType->name();
911  if (!comment.isEmpty()) {
912  return comment;
913  } else {
914  return mime.name();
915  }
916 }
917 
918 static QString iconFromDirectoryFile(const QString &path)
919 {
920  const QString filePath = path + QLatin1String("/.directory");
921  if (!QFileInfo(filePath).isFile()) { // exists -and- is a file
922  return QString();
923  }
924 
925  KDesktopFile cfg(filePath);
926  QString icon = cfg.readIcon();
927 
928  const KConfigGroup group = cfg.desktopGroup();
929  const QString emptyIcon = group.readEntry("EmptyIcon");
930  if (!emptyIcon.isEmpty()) {
931  bool isDirEmpty = true;
933  while (dirIt.hasNext()) {
934  dirIt.next();
935  if (dirIt.fileName() != QLatin1String(".directory")) {
936  isDirEmpty = false;
937  break;
938  }
939  }
940  if (isDirEmpty) {
941  icon = emptyIcon;
942  }
943  }
944 
945  if (icon.startsWith(QLatin1String("./"))) {
946  // path is relative with respect to the location
947  // of the .directory file (#73463)
948  return path + icon.midRef(1);
949  }
950  return icon;
951 }
952 
953 static QString iconFromDesktopFile(const QString &path)
954 {
955  KDesktopFile cfg(path);
956  const QString icon = cfg.readIcon();
957  if (cfg.hasLinkType()) {
958  const KConfigGroup group = cfg.desktopGroup();
959  const QString emptyIcon = group.readEntry("EmptyIcon");
960  if (!emptyIcon.isEmpty()) {
961  const QString u = cfg.readUrl();
962  const QUrl url(u);
963  if (url.scheme() == QLatin1String("trash")) {
964  // We need to find if the trash is empty, preferably without using a KIO job.
965  // So instead kio_trash leaves an entry in its config file for us.
966  KConfig trashConfig(QStringLiteral("trashrc"), KConfig::SimpleConfig);
967  if (trashConfig.group("Status").readEntry("Empty", true)) {
968  return emptyIcon;
969  }
970  }
971  }
972  }
973  return icon;
974 }
975 
977 {
978  if (!d) {
979  return QString();
980  }
981 
982  if (d->m_useIconNameCache && !d->m_iconName.isEmpty()) {
983  return d->m_iconName;
984  }
985 
986  d->m_iconName = d->m_entry.stringValue(KIO::UDSEntry::UDS_ICON_NAME);
987  if (!d->m_iconName.isEmpty()) {
988  d->m_useIconNameCache = d->m_bMimeTypeKnown;
989  return d->m_iconName;
990  }
991 
992  bool isLocalUrl;
993  QUrl url = mostLocalUrl(&isLocalUrl);
994 
995  QMimeDatabase db;
996  QMimeType mime;
997  // Use guessed mimetype for the icon
998  if (!d->m_guessedMimeType.isEmpty()) {
999  mime = db.mimeTypeForName(d->m_guessedMimeType);
1000  } else {
1001  mime = currentMimeType();
1002  }
1003 
1004  const bool delaySlowOperations = d->m_delayedMimeTypes;
1005 
1006  if (isLocalUrl && !delaySlowOperations && mime.inherits(QStringLiteral("application/x-desktop"))) {
1007  d->m_iconName = iconFromDesktopFile(url.toLocalFile());
1008  if (!d->m_iconName.isEmpty()) {
1009  d->m_useIconNameCache = d->m_bMimeTypeKnown;
1010  return d->m_iconName;
1011  }
1012  }
1013 
1014  if (isLocalUrl && !delaySlowOperations && isDir()) {
1015  if (isDirectoryMounted(url)) {
1016  d->m_iconName = iconFromDirectoryFile(url.toLocalFile());
1017  if (!d->m_iconName.isEmpty()) {
1018  d->m_useIconNameCache = d->m_bMimeTypeKnown;
1019  return d->m_iconName;
1020  }
1021  }
1022 
1023  d->m_iconName = KIOPrivate::iconForStandardPath(url.toLocalFile());
1024  if (!d->m_iconName.isEmpty()) {
1025  d->m_useIconNameCache = d->m_bMimeTypeKnown;
1026  return d->m_iconName;
1027  }
1028  }
1029 
1030  d->m_iconName = mime.iconName();
1031  d->m_useIconNameCache = d->m_bMimeTypeKnown;
1032  return d->m_iconName;
1033 }
1034 
1039 static bool checkDesktopFile(const KFileItem &item, bool _determineMimeType)
1040 {
1041  // only local files
1042  bool isLocalUrl;
1043  item.mostLocalUrl(&isLocalUrl);
1044  if (!isLocalUrl) {
1045  return false;
1046  }
1047 
1048  // only regular files
1049  if (!item.isRegularFile()) {
1050  return false;
1051  }
1052 
1053  // only if readable
1054  if (!item.isReadable()) {
1055  return false;
1056  }
1057 
1058  // return true if desktop file
1059  QMimeType mime = _determineMimeType ? item.determineMimeType() : item.currentMimeType();
1060  return mime.inherits(QStringLiteral("application/x-desktop"));
1061 }
1062 
1064 {
1065  if (!d) {
1066  return QStringList();
1067  }
1068 
1069  d->ensureInitialized();
1070 
1071 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
1072  QStringList names = d->m_entry.stringValue(KIO::UDSEntry::UDS_ICON_OVERLAY_NAMES).split(QLatin1Char(','), QString::SkipEmptyParts);
1073 #else
1074  QStringList names = d->m_entry.stringValue(KIO::UDSEntry::UDS_ICON_OVERLAY_NAMES).split(QLatin1Char(','), Qt::SkipEmptyParts);
1075 #endif
1076 
1077  if (d->m_bLink) {
1078  names.append(QStringLiteral("emblem-symbolic-link"));
1079  }
1080 
1081  if (!isReadable()) {
1082  names.append(QStringLiteral("emblem-locked"));
1083  }
1084 
1085  if (checkDesktopFile(*this, false)) {
1086  KDesktopFile cfg(localPath());
1087  const KConfigGroup group = cfg.desktopGroup();
1088 
1089  // Add a warning emblem if this is an executable desktop file
1090  // which is untrusted.
1091  if (group.hasKey("Exec") && !KDesktopFile::isAuthorizedDesktopFile(localPath())) {
1092  names.append(QStringLiteral("emblem-important"));
1093  }
1094 
1095  if (cfg.hasDeviceType()) {
1096  const QString dev = cfg.readDevice();
1097  if (!dev.isEmpty()) {
1099  if (mountPoint) { // mounted?
1100  names.append(QStringLiteral("emblem-mounted"));
1101  }
1102  }
1103  }
1104  }
1105 
1106  if (isHidden()) {
1107  names.append(QStringLiteral("hidden"));
1108  }
1109 #ifndef Q_OS_WIN
1110  if (isDir()) {
1111  bool isLocalUrl;
1112  const QUrl url = mostLocalUrl(&isLocalUrl);
1113  if (isLocalUrl) {
1114  const QString path = url.toLocalFile();
1115  if (KSambaShare::instance()->isDirectoryShared(path)
1116  || KNFSShare::instance()->isDirectoryShared(path)) {
1117  names.append(QStringLiteral("emblem-shared"));
1118  }
1119  }
1120  }
1121 #endif // Q_OS_WIN
1122 
1123  return names;
1124 }
1125 
1127 {
1128  if (!d) {
1129  return QString();
1130  }
1131 
1132  return d->m_entry.stringValue(KIO::UDSEntry::UDS_COMMENT);
1133 }
1134 
1136 {
1137  if (!d) {
1138  return false;
1139  }
1140 
1141  d->ensureInitialized();
1142 
1143  /*
1144  struct passwd * user = getpwuid( geteuid() );
1145  bool isMyFile = (QString::fromLocal8Bit(user->pw_name) == d->m_user);
1146  // This gets ugly for the group....
1147  // Maybe we want a static QString for the user and a static QStringList
1148  // for the groups... then we need to handle the deletion properly...
1149  */
1150 
1151  if (d->m_permissions != KFileItem::Unknown) {
1152  const mode_t readMask = S_IRUSR | S_IRGRP | S_IROTH;
1153  // No read permission at all
1154  if ((d->m_permissions & readMask) == 0) {
1155  return false;
1156  }
1157 
1158  // Read permissions for all: save a stat call
1159  if ((d->m_permissions & readMask) == readMask) {
1160  return true;
1161  }
1162  }
1163 
1164  // Or if we can't read it - not network transparent
1165  if (d->m_bIsLocalUrl && !QFileInfo(d->m_url.toLocalFile()).isReadable()) {
1166  return false;
1167  }
1168 
1169  return true;
1170 }
1171 
1173 {
1174  if (!d) {
1175  return false;
1176  }
1177 
1178  d->ensureInitialized();
1179 
1180  /*
1181  struct passwd * user = getpwuid( geteuid() );
1182  bool isMyFile = (QString::fromLocal8Bit(user->pw_name) == d->m_user);
1183  // This gets ugly for the group....
1184  // Maybe we want a static QString for the user and a static QStringList
1185  // for the groups... then we need to handle the deletion properly...
1186  */
1187 
1188  if (d->m_permissions != KFileItem::Unknown) {
1189  // No write permission at all
1190  if (!(S_IWUSR & d->m_permissions) && !(S_IWGRP & d->m_permissions) && !(S_IWOTH & d->m_permissions)) {
1191  return false;
1192  }
1193  }
1194 
1195  // Or if we can't write it - not network transparent
1196  if (d->m_bIsLocalUrl && !QFileInfo(d->m_url.toLocalFile()).isWritable()) {
1197  return false;
1198  }
1199 
1200  return true;
1201 }
1202 
1204 {
1205  if (!d) {
1206  return false;
1207  }
1208 
1209  // The kioslave can specify explicitly that a file is hidden or shown
1210  if (d->m_hidden != KFileItemPrivate::Auto) {
1211  return d->m_hidden == KFileItemPrivate::Hidden;
1212  }
1213 
1214  // Prefer the filename that is part of the URL, in case the display name is different.
1215  QString fileName = d->m_url.fileName();
1216  if (fileName.isEmpty()) { // e.g. "trash:/"
1217  fileName = d->m_strName;
1218  }
1219  return fileName.length() > 1 && fileName[0] == QLatin1Char('.'); // Just "." is current directory, not hidden.
1220 }
1221 
1222 void KFileItem::setHidden()
1223 {
1224  if (d) {
1225  d->m_hidden = KFileItemPrivate::Hidden;
1226  }
1227 }
1228 
1229 bool KFileItem::isDir() const
1230 {
1231  if (!d) {
1232  return false;
1233  }
1234 
1235  if (d->m_bSkipMimeTypeFromContent) {
1236  return false;
1237  }
1238 
1239  d->ensureInitialized();
1240 
1241  if (d->m_fileMode == KFileItem::Unknown) {
1242  // Probably the file was deleted already, and KDirLister hasn't told the world yet.
1243  //qDebug() << d << url() << "can't say -> false";
1244  return false; // can't say for sure, so no
1245  }
1246  return (d->m_fileMode & QT_STAT_MASK) == QT_STAT_DIR;
1247 }
1248 
1249 bool KFileItem::isFile() const
1250 {
1251  if (!d) {
1252  return false;
1253  }
1254 
1255  return !isDir();
1256 }
1257 
1258 #if KIOCORE_BUILD_DEPRECATED_SINCE(4, 0)
1260 {
1261  // A directory ?
1262  if (isDir()) {
1263  return isWritable();
1264  }
1265 
1266  // But only local .desktop files and executables
1267  if (!d->m_bIsLocalUrl) {
1268  return false;
1269  }
1270 
1271  if (mimetype() == QLatin1String("application/x-desktop")) {
1272  return true;
1273  }
1274 
1275  // Executable, shell script ... ?
1276  if (QFileInfo(d->m_url.toLocalFile()).isExecutable()) {
1277  return true;
1278  }
1279 
1280  return false;
1281 }
1282 #endif
1283 
1285 {
1286  if (!d) {
1287  return QString();
1288  }
1289 
1290  QString text = d->m_strText;
1291  const QString comment = mimeComment();
1292 
1293  if (d->m_bLink) {
1294  text += QLatin1Char(' ');
1295  if (comment.isEmpty()) {
1296  text += i18n("(Symbolic Link to %1)", linkDest());
1297  } else {
1298  text += i18n("(%1, Link to %2)", comment, linkDest());
1299  }
1300  } else if (targetUrl() != url()) {
1301  text += i18n(" (Points to %1)", targetUrl().toDisplayString());
1302  } else if ((d->m_fileMode & QT_STAT_MASK) == QT_STAT_REG) {
1303  text += QStringLiteral(" (%1, %2)").arg(comment, KIO::convertSize(size()));
1304  } else {
1305  text += QStringLiteral(" (%1)").arg(comment);
1306  }
1307  return text;
1308 }
1309 
1310 bool KFileItem::cmp(const KFileItem &item) const
1311 {
1312  if (!d && !item.d) {
1313  return true;
1314  }
1315 
1316  if (!d || !item.d) {
1317  return false;
1318  }
1319 
1320  return d->cmp(*item.d);
1321 }
1322 
1323 bool KFileItem::operator==(const KFileItem &other) const
1324 {
1325  if (!d && !other.d) {
1326  return true;
1327  }
1328 
1329  if (!d || !other.d) {
1330  return false;
1331  }
1332 
1333  return d->m_url == other.d->m_url;
1334 }
1335 
1336 bool KFileItem::operator!=(const KFileItem &other) const
1337 {
1338  return !operator==(other);
1339 }
1340 
1341 bool KFileItem::operator<(const KFileItem &other) const
1342 {
1343  if (!other.d) {
1344  return false;
1345  }
1346  if (!d) {
1347  return other.d->m_url.isValid();
1348  }
1349  return d->m_url < other.d->m_url;
1350 }
1351 
1352 bool KFileItem::operator<(const QUrl &other) const
1353 {
1354  if (!d) {
1355  return other.isValid();
1356  }
1357  return d->m_url < other;
1358 }
1359 
1360 KFileItem::operator QVariant() const
1361 {
1362  return QVariant::fromValue(*this);
1363 }
1364 
1366 {
1367  if (!d) {
1368  return QString();
1369  }
1370 
1371  d->ensureInitialized();
1372 
1373  if (d->m_access.isNull() && d->m_permissions != KFileItem::Unknown) {
1374  d->m_access = d->parsePermissions(d->m_permissions);
1375  }
1376 
1377  return d->m_access;
1378 }
1379 
1380 // check if we need to cache this
1382 {
1383  if (!d) {
1384  return QString();
1385  }
1386 
1387  return QLocale::system().toString(d->time(which), QLocale::LongFormat);
1388 }
1389 
1390 #if KIOCORE_BUILD_DEPRECATED_SINCE(4, 0)
1391 QString KFileItem::timeString(unsigned int which) const
1392 {
1393  if (!d) {
1394  return QString();
1395  }
1396 
1397  switch (which) {
1399  return timeString(AccessTime);
1401  return timeString(CreationTime);
1403  default:
1404  return timeString(ModificationTime);
1405  }
1406 }
1407 #endif
1408 
1409 #if KIOCORE_BUILD_DEPRECATED_SINCE(4, 0)
1410 void KFileItem::assign(const KFileItem &item)
1411 {
1412  *this = item;
1413 }
1414 #endif
1415 
1416 QUrl KFileItem::mostLocalUrl(bool *local) const
1417 {
1418  if (!d) {
1419  return QUrl();
1420  }
1421 
1422  const QString local_path = localPath();
1423  if (!local_path.isEmpty()) {
1424  if (local) {
1425  *local = true;
1426  }
1427  return QUrl::fromLocalFile(local_path);
1428  } else {
1429  if (local) {
1430  *local = d->m_bIsLocalUrl;
1431  }
1432  return d->m_url;
1433  }
1434 }
1435 
1436 QDataStream &operator<< (QDataStream &s, const KFileItem &a)
1437 {
1438  if (a.d) {
1439  // We don't need to save/restore anything that refresh() invalidates,
1440  // since that means we can re-determine those by ourselves.
1441  s << a.d->m_url;
1442  s << a.d->m_strName;
1443  s << a.d->m_strText;
1444  } else {
1445  s << QUrl();
1446  s << QString();
1447  s << QString();
1448  }
1449 
1450  return s;
1451 }
1452 
1453 QDataStream &operator>> (QDataStream &s, KFileItem &a)
1454 {
1455  QUrl url;
1456  QString strName, strText;
1457 
1458  s >> url;
1459  s >> strName;
1460  s >> strText;
1461 
1462  if (!a.d) {
1463  qCWarning(KIO_CORE) << "null item";
1464  return s;
1465  }
1466 
1467  if (url.isEmpty()) {
1468  a.d = nullptr;
1469  return s;
1470  }
1471 
1472  a.d->m_url = url;
1473  a.d->m_strName = strName;
1474  a.d->m_strText = strText;
1475  a.d->m_bIsLocalUrl = a.d->m_url.isLocalFile();
1476  a.d->m_bMimeTypeKnown = false;
1477  a.refresh();
1478 
1479  return s;
1480 }
1481 
1483 {
1484  if (!d) {
1485  return QUrl();
1486  }
1487 
1488  return d->m_url;
1489 }
1490 
1492 {
1493  if (!d) {
1494  return 0;
1495  }
1496 
1497  d->ensureInitialized();
1498 
1499  return d->m_permissions;
1500 }
1501 
1502 mode_t KFileItem::mode() const
1503 {
1504  if (!d) {
1505  return 0;
1506  }
1507 
1508  d->ensureInitialized();
1509 
1510  return d->m_fileMode;
1511 }
1512 
1513 bool KFileItem::isLink() const
1514 {
1515  if (!d) {
1516  return false;
1517  }
1518 
1519  d->ensureInitialized();
1520 
1521  return d->m_bLink;
1522 }
1523 
1525 {
1526  if (!d) {
1527  return false;
1528  }
1529 
1530  return d->m_bIsLocalUrl;
1531 }
1532 
1534 {
1535  if (!d) {
1536  return QString();
1537  }
1538 
1539  return d->m_strText;
1540 }
1541 
1542 QString KFileItem::name(bool lowerCase) const
1543 {
1544  if (!d) {
1545  return QString();
1546  }
1547 
1548  if (!lowerCase) {
1549  return d->m_strName;
1550  } else if (d->m_strLowerCaseName.isNull()) {
1551  d->m_strLowerCaseName = d->m_strName.toLower();
1552  }
1553  return d->m_strLowerCaseName;
1554 }
1555 
1557 {
1558  if (!d) {
1559  return QUrl();
1560  }
1561 
1562  const QString targetUrlStr = d->m_entry.stringValue(KIO::UDSEntry::UDS_TARGET_URL);
1563  if (!targetUrlStr.isEmpty()) {
1564  return QUrl(targetUrlStr);
1565  } else {
1566  return url();
1567  }
1568 }
1569 
1570 /*
1571  * Mimetype handling.
1572  *
1573  * Initial state: m_mimeType = QMimeType().
1574  * When currentMimeType() is called first: fast mimetype determination,
1575  * might either find an accurate mimetype (-> Final state), otherwise we
1576  * set m_mimeType but not m_bMimeTypeKnown (-> Intermediate state)
1577  * Intermediate state: determineMimeType() does the real determination -> Final state.
1578  *
1579  * If delayedMimeTypes isn't set, then we always go to the Final state directly.
1580  */
1581 
1583 {
1584  if (!d) {
1585  return QMimeType();
1586  }
1587 
1588  if (!d->m_mimeType.isValid()) {
1589  // On-demand fast (but not always accurate) mimetype determination
1590  Q_ASSERT(!d->m_url.isEmpty());
1591  QMimeDatabase db;
1592  if (isDir()) {
1593  d->m_mimeType = db.mimeTypeForName(QStringLiteral("inode/directory"));
1594  return d->m_mimeType;
1595  }
1596  const QUrl url = mostLocalUrl();
1597  if (d->m_delayedMimeTypes) {
1598  const QList<QMimeType> mimeTypes = db.mimeTypesForFileName(url.path());
1599  if (mimeTypes.isEmpty()) {
1600  d->m_mimeType = db.mimeTypeForName(QStringLiteral("application/octet-stream"));
1601  d->m_bMimeTypeKnown = false;
1602  } else {
1603  d->m_mimeType = mimeTypes.first();
1604  // If there were conflicting globs. determineMimeType will be able to do better.
1605  d->m_bMimeTypeKnown = (mimeTypes.count() == 1);
1606  }
1607  } else {
1608  // ## d->m_fileMode isn't used anymore (for remote urls)
1609  d->determineMimeTypeHelper(url);
1610  d->m_bMimeTypeKnown = true;
1611  }
1612  }
1613  return d->m_mimeType;
1614 }
1615 
1617 {
1618  if (!d) {
1619  return KIO::UDSEntry();
1620  }
1621 
1622  d->ensureInitialized();
1623 
1624  return d->m_entry;
1625 }
1626 
1627 bool KFileItem::isNull() const
1628 {
1629  return d == nullptr;
1630 }
1631 
1633 {
1634 }
1635 
1637  : QList<KFileItem>(items)
1638 {
1639 }
1640 
1642 {
1643  const_iterator it = begin();
1644  const const_iterator itend = end();
1645  for (; it != itend; ++it) {
1646  if ((*it).name() == fileName) {
1647  return *it;
1648  }
1649  }
1650  return KFileItem();
1651 }
1652 
1654 {
1655  const_iterator it = begin();
1656  const const_iterator itend = end();
1657  for (; it != itend; ++it) {
1658  if ((*it).url() == url) {
1659  return *it;
1660  }
1661  }
1662  return KFileItem();
1663 }
1664 
1666 {
1667  QList<QUrl> lst;
1668  const_iterator it = begin();
1669  const const_iterator itend = end();
1670  for (; it != itend; ++it) {
1671  lst.append((*it).url());
1672  }
1673  return lst;
1674 }
1675 
1677 {
1678  QList<QUrl> lst;
1679  const_iterator it = begin();
1680  const const_iterator itend = end();
1681  for (; it != itend; ++it) {
1682  lst.append((*it).targetUrl());
1683  }
1684  return lst;
1685 }
1686 
1688 {
1689  return checkDesktopFile(*this, true);
1690 }
1691 
1693 {
1694  if (!d) {
1695  return false;
1696  }
1697 
1698  d->ensureInitialized();
1699 
1700  return (d->m_fileMode & QT_STAT_MASK) == QT_STAT_REG;
1701 }
1702 
1703 QDebug operator<<(QDebug stream, const KFileItem &item)
1704 {
1705  QDebugStateSaver saver(stream);
1706  stream.nospace();
1707  if (item.isNull()) {
1708  stream << "[null KFileItem]";
1709  } else {
1710  stream << "[KFileItem for " << item.url() << "]";
1711  }
1712  return stream;
1713 }
An alternative URL (If different from the caption).
Definition: udsentry.h:277
QString next()
StripTrailingSlash
For folders, the recursize size of its content.
Definition: udsentry.h:335
qulonglong filesize_t
64-bit file size
Definition: global.h:40
bool isWritable() const
Checks whether the file or directory is writable.
Definition: kfileitem.cpp:1172
KFileItemList()
Creates an empty list of file items.
Definition: kfileitem.cpp:1632
void setUrl(const QUrl &url)
Sets the item&#39;s URL.
Definition: kfileitem.cpp:599
This file is a shortcut or mount, pointing to an URL in a different hierarchy.
Definition: udsentry.h:302
void setDelayedMimeTypes(bool b)
Sets mimetype determination to be immediate or on demand.
Definition: kfileitem.cpp:591
bool isDir() const
Returns true if this item represents a directory.
Definition: kfileitem.cpp:1229
FileTimes
The timestamps associated with a file.
Definition: kfileitem.h:46
QString toString(qlonglong i) const const
QString name() const
KCOREADDONS_EXPORT Type fileSystemType(const QString &path)
QString getStatusBarInfo() const
Returns the string to be displayed in the statusbar, e.g.
Definition: kfileitem.cpp:1284
Device number for this file, used to detect hardlinks.
Definition: udsentry.h:328
Universal Directory Service.
Definition: udsentry.h:77
QString mimetype() const
Returns the mimetype of the file item.
Definition: kfileitem.cpp:792
QString user() const
Returns the owner of the file.
Definition: kfileitem.cpp:751
The access control list serialized into a single string.
Definition: udsentry.h:290
A namespace for KIO globals.
Definition: authinfo.h:21
static List currentMountPoints(DetailsNeededFlags infoNeeded=BasicInfoNeeded)
This function gives a list of all currently used mountpoints.
void setLocalPath(const QString &path)
Sets the item&#39;s local path (UDS_LOCAL_PATH).
Definition: kfileitem.cpp:610
QList< QUrl > targetUrlList() const
Definition: kfileitem.cpp:1676
bool isNull() const
Return true if default-constructed.
Definition: kfileitem.cpp:1627
bool isFinalIconKnown() const
Definition: kfileitem.cpp:864
The default access control list serialized into a single string.
Definition: udsentry.h:293
void refresh()
Throw away and re-read (for local files) all information about the file.
Definition: kfileitem.cpp:560
File type, part of the mode returned by stat (for a link, this returns the file type of the pointed i...
Definition: udsentry.h:268
Ptr findByDevice(const QString &device) const
Returns the mount point associated with device, i.e.
QDebug & nospace()
bool inherits(const QString &mimeTypeName) const const
static KSambaShare * instance()
QString fileName() const const
A local file path if the ioslave display files sitting on the local filesystem (but in another hierar...
Definition: udsentry.h:253
QString comment() const
A comment which can contain anything - even rich text.
Definition: kfileitem.cpp:1126
void setName(const QString &name)
Sets the item&#39;s name (i.e.
Definition: kfileitem.cpp:620
mode_t permissions() const
Returns the permissions of the file (stat.st_mode containing only permissions).
Definition: kfileitem.cpp:1491
bool operator!=(const KFileItem &other) const
Returns true if both items do not share the same URL.
Definition: kfileitem.cpp:1336
QUrl targetUrl() const
Returns the target url of the file, which is the same as url() in cases where the slave doesn&#39;t speci...
Definition: kfileitem.cpp:1556
bool isReadable() const
Checks whether the file or directory is readable.
Definition: kfileitem.cpp:1135
KIOCORE_EXPORT QString convertSize(KIO::filesize_t size)
Converts size from bytes to the string representation.
Definition: global.cpp:43
KFileItem()
Null KFileItem.
Definition: kfileitem.cpp:510
QDateTime fromMSecsSinceEpoch(qint64 msecs)
Treat the file as a hidden file (if set to 1) or as a normal file (if set to 0).
Definition: udsentry.h:256
QDateTime time(FileTimes which) const
Requests the modification, access or creation time, depending on which.
Definition: kfileitem.cpp:742
QLocale system()
27 was used by the now removed UDS_NEPOMUK_QUERY
Definition: udsentry.h:324
User-readable type of file (if not specified, the mimetype&#39;s description is used) ...
Definition: udsentry.h:307
A mime type to be used for displaying only.
Definition: udsentry.h:283
KIO::filesize_t recursiveSize() const
For folders, its recursive size: the size of its files plus the recursiveSize of its folder...
Definition: kfileitem.cpp:690
QMimeType mimeTypeForFile(const QString &fileName, QMimeDatabase::MatchMode mode) const const
static bool isAuthorizedDesktopFile(const QString &path)
bool isLocalFile() const
Returns true if the file is a local file.
Definition: kfileitem.cpp:1524
void setPath(const QString &path, QUrl::ParsingMode mode)
QMimeType determineMimeType() const
Returns the mimetype of the file item.
Definition: kfileitem.cpp:802
bool isRegularFile() const
Return true if this item is a regular file, false otherwise (directory, link, character/block device...
Definition: kfileitem.cpp:1692
User ID of the file owner.
Definition: udsentry.h:235
KACL ACL() const
Returns the access control list for the file.
Definition: kfileitem.cpp:709
int count(const T &value) const const
int count() const
count fields
Definition: udsentry.cpp:424
void append(const T &value)
QString readDevice() const
KFileItem findByName(const QString &fileName) const
Find a KFileItem by name and return it.
Definition: kfileitem.cpp:1641
QMimeType mimeTypeForUrl(const QUrl &url) const const
bool hasDeviceType() const
void assign(const KFileItem &item)
Definition: kfileitem.cpp:1410
QString loginName() const
QString symLinkTarget() const const
bool isEmpty() const const
QString localPath() const
Returns the local path if isLocalFile() == true or the KIO item has a UDS_LOCAL_PATH atom...
Definition: kfileitem.cpp:672
QString linkDest() const
Returns the link destination if isLink() == true.
Definition: kfileitem.cpp:639
bool isEmpty() const const
const char * constData() const const
The last time the file was opened.
Definition: udsentry.h:262
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const const
QMimeType currentMimeType() const
Returns the currently known mimetype of the file item.
Definition: kfileitem.cpp:1582
QString stringValue(uint field) const
Definition: udsentry.cpp:353
QString path(QUrl::ComponentFormattingOptions options) const const
QString mimeComment() const
Returns the user-readable string representing the type of this file, like "OpenDocument Text File"...
Definition: kfileitem.cpp:873
bool acceptsDrops() const
Returns true if files can be dropped over this item.
Definition: kfileitem.cpp:1259
KIOCORE_EXPORT QString decodeFileName(const QString &str)
Decodes (from the filename to the text displayed) This doesn&#39;t do anything anymore, it used to do the opposite of encodeFileName when encodeFileName was using %2F for &#39;/&#39;.
Definition: global.cpp:148
~KFileItem()
Destructor.
T & first()
bool operator==(const KFileItem &other) const
Returns true if both items share the same URL.
Definition: kfileitem.cpp:1323
bool isFile() const
Returns true if this item represents a file (and not a directory)
Definition: kfileitem.cpp:1249
QString group() const
Returns the group of the file.
Definition: kfileitem.cpp:760
bool operator<(const KFileItem &other) const
Returns true if this item&#39;s URL is lexically less than other&#39;s URL; otherwise returns false...
Definition: kfileitem.cpp:1341
QString readUrl() const
KIO::filesize_t size() const
Returns the size of the file, if known.
Definition: kfileitem.cpp:681
QString iconName() const
Returns the full path name to the icon that represents this mime type.
Definition: kfileitem.cpp:976
QString scheme() const const
QMimeType mimeTypeForName(const QString &nameOrAlias) const const
QString permissionsString() const
Returns the access permissions for the file as a string.
Definition: kfileitem.cpp:1365
void refreshMimeType()
Re-reads mimetype information.
Definition: kfileitem.cpp:580
QList< QUrl > urlList() const
Definition: kfileitem.cpp:1665
Inode number for this file, used to detect hardlinks.
Definition: udsentry.h:331
QString toLocalFile() const const
The last time the file was modified.
Definition: udsentry.h:260
bool hasLinkType() const
QString text() const
Returns the text of the file item.
Definition: kfileitem.cpp:1533
QList::iterator end()
bool isDesktopFile() const
Checks whether the file is a readable local .desktop file, i.e.
Definition: kfileitem.cpp:1687
bool isLink() const
Returns true if this item represents a link in the UNIX sense of a link.
Definition: kfileitem.cpp:1513
SkipEmptyParts
25 was used by the now removed UDS_NEPOMUK_URI
Definition: udsentry.h:316
bool contains(uint field) const
check existence of a field
Definition: udsentry.cpp:429
QStringRef midRef(int position, int n) const const
QVariant fromValue(const T &value)
QCA_EXPORT void init()
bool hasKey(const QString &key) const
QString i18n(const char *text, const TYPE &arg...)
KConfigGroup group(const QString &group)
bool isValid() const const
bool hasExtendedACL() const
Tells if the file has extended access level information ( Posix ACL )
Definition: kfileitem.cpp:699
Access permissions (part of the mode returned by stat)
Definition: udsentry.h:258
KACL defaultACL() const
Returns the default access control list for the directory.
Definition: kfileitem.cpp:727
QList< KFileItem > & operator<<(const KFileItem &value)
qint64 toSecsSinceEpoch() const const
QString name(bool lowerCase=false) const
Return the name of the file item (without a path).
Definition: kfileitem.cpp:1542
KFileItem findByUrl(const QUrl &url) const
Find a KFileItem by URL and return it.
Definition: kfileitem.cpp:1653
Filename - as displayed in directory listings etc.
Definition: udsentry.h:250
The KACL class encapsulates a POSIX Access Control List.
Definition: kacl.h:35
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
Name of the file where the link points to Allows to check for a symlink (don&#39;t use S_ISLNK !) ...
Definition: udsentry.h:271
QUrl mostLocalUrl(bool *local=nullptr) const
Tries to give a local URL for this file item if possible.
Definition: kfileitem.cpp:1416
bool cmp(const KFileItem &item) const
Somewhat like a comparison operator, but more explicit, and it can detect that two fileitems differ i...
Definition: kfileitem.cpp:1310
The time the file was created.
Definition: udsentry.h:264
bool isHidden() const
Checks whether the file is hidden.
Definition: kfileitem.cpp:1203
int length() const const
Group ID of the file owner.
Definition: udsentry.h:240
QString timeString(FileTimes which=ModificationTime) const
Requests the modification, access or creation time as a string, depending on which.
Definition: kfileitem.cpp:1381
If set, contains the label to display instead of the &#39;real name&#39; in UDS_NAME.
Definition: udsentry.h:298
QString readIcon() const
QString fromLatin1(const char *str, int size)
mode_t mode() const
Returns the file type (stat.st_mode containing only S_IFDIR, S_IFLNK, ...).
Definition: kfileitem.cpp:1502
Indicates that the entry has extended ACL entries.
Definition: udsentry.h:288
QDateTime toLocalTime() const const
A mime type; the slave should set it if it&#39;s known.
Definition: udsentry.h:279
QUrl url() const
Returns the url of the file.
Definition: kfileitem.cpp:1482
bool isMimeTypeKnown() const
Definition: kfileitem.cpp:834
KFileItem & operator=(const KFileItem &)
Copy assignment.
bool isSlow() const
Definition: kfileitem.cpp:783
KIO::UDSEntry entry() const
Returns the UDS entry.
Definition: kfileitem.cpp:1616
static KNFSShare * instance()
Returns the one and only instance of KNFSShare.
Definition: knfsshare.cpp:215
bool hasNext() const const
T readEntry(const QString &key, const T &aDefault) const
Size of the file.
Definition: udsentry.h:231
QList::iterator begin()
QString fileName(QUrl::ComponentFormattingOptions options) const const
QStringList overlays() const
Returns the overlays (bitfield of KIconLoader::*Overlay flags) that are used for this item&#39;s pixmap...
Definition: kfileitem.cpp:1063
QByteArray encodeName(const QString &fileName)
A KFileItem is a generic class to handle a file, local or remote.
Definition: kfileitem.h:35
QUrl fromLocalFile(const QString &localFile)
Name of the icon, that should be used for displaying.
Definition: udsentry.h:238
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Wed Aug 12 2020 23:00:47 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.