File indexing completed on 2024-05-05 17:56:55

0001 /*
0002     SPDX-FileCopyrightText: 2000 Rafi Yanai <krusader@users.sourceforge.net>
0003     SPDX-FileCopyrightText: 2004-2022 Krusader Krew <https://krusader.org>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "fileitem.h"
0009 
0010 // QtCore
0011 #include <QCache>
0012 #include <QDateTime>
0013 #include <QMimeDatabase>
0014 #include <QMimeType>
0015 
0016 #include <KConfigCore/KDesktopFile>
0017 
0018 #include "../compat.h"
0019 #include "filesystemprovider.h"
0020 #include "krpermhandler.h"
0021 
0022 bool FileItem::userDefinedFolderIcons = true;
0023 
0024 // wrapper class; QCache needs objects
0025 class FileSize
0026 {
0027 public:
0028     const KIO::filesize_t m_size;
0029     FileSize(KIO::filesize_t size)
0030         : m_size(size)
0031     {
0032     }
0033 };
0034 
0035 // cache for calculated directory sizes;
0036 static QCache<const QUrl, FileSize> s_fileSizeCache(1000);
0037 
0038 FileItem::FileItem(const QString &name,
0039                    const QUrl &url,
0040                    bool isDir,
0041                    KIO::filesize_t size,
0042                    mode_t mode,
0043                    time_t mtime,
0044                    time_t ctime,
0045                    time_t atime,
0046                    time_t btime,
0047                    uid_t uid,
0048                    gid_t gid,
0049                    const QString &owner,
0050                    const QString &group,
0051                    bool isLink,
0052                    const QString &linkDest,
0053                    bool isBrokenLink,
0054                    const QString &acl,
0055                    const QString &defaultAcl)
0056     : m_name(name)
0057     , m_url(url)
0058     , m_isDir(isDir)
0059     , m_size(size)
0060     , m_mode(mode)
0061     , m_mtime(mtime)
0062     , m_ctime(ctime)
0063     , m_atime(atime)
0064     , m_btime(btime)
0065     , m_uid(uid)
0066     , m_gid(gid)
0067     , m_owner(owner)
0068     , m_group(group)
0069     , m_isLink(isLink)
0070     , m_linkDest(linkDest)
0071     , m_isBrokenLink(isBrokenLink)
0072     , m_acl(acl)
0073     , m_defaulfAcl(defaultAcl)
0074     , m_AclLoaded(false)
0075     , m_mimeType()
0076     , m_iconName()
0077 {
0078     m_permissions = KrPermHandler::mode2QString(mode);
0079 
0080     if (m_owner.isEmpty())
0081         m_owner = KrPermHandler::uid2user(m_uid);
0082 
0083     if (m_group.isEmpty())
0084         m_group = KrPermHandler::gid2group(m_gid);
0085 
0086     if (m_isDir && !m_isLink) {
0087         m_size = s_fileSizeCache.contains(m_url) ? s_fileSizeCache[m_url]->m_size : -1;
0088     }
0089 }
0090 
0091 FileItem *FileItem::createDummy()
0092 {
0093     FileItem *file = new FileItem("..", QUrl(), true, 0, 0, -1, -1, -1, -1);
0094     file->setIconName("go-up");
0095     return file;
0096 }
0097 
0098 FileItem *FileItem::createBroken(const QString &name, const QUrl &url)
0099 {
0100     FileItem *file = new FileItem(name, url, false, 0, 0, -1, -1, -1, -1);
0101     file->setIconName("file-broken");
0102     return file;
0103 }
0104 
0105 FileItem *FileItem::createVirtualDir(const QString &name, const QUrl &url)
0106 {
0107     return new FileItem(name, url, true, 0, 0700, -1, -1, -1, -1, getuid(), getgid());
0108 }
0109 
0110 FileItem *FileItem::createCopy(const FileItem &file, const QString &newName)
0111 {
0112     return new FileItem(newName,
0113                         file.getUrl(),
0114                         file.isDir(),
0115                         file.getSize(),
0116                         file.getMode(),
0117                         file.getModificationTime(),
0118                         file.getChangeTime(),
0119                         file.getAccessTime(),
0120                         file.getCreationTime(),
0121                         file.m_uid,
0122                         file.m_gid,
0123                         file.getOwner(),
0124                         file.getGroup(),
0125                         file.isSymLink(),
0126                         file.getSymDest(),
0127                         file.isBrokenLink());
0128 }
0129 
0130 char FileItem::isReadable() const
0131 {
0132     if (m_uid != (uid_t)-1 && m_gid != (gid_t)-1)
0133         return KrPermHandler::readable(m_permissions, m_gid, m_uid);
0134     else
0135         return KrPermHandler::ftpReadable(m_owner, m_url.userName(), m_permissions);
0136 }
0137 
0138 char FileItem::isWriteable() const
0139 {
0140     if (m_uid != (uid_t)-1 && m_gid != (gid_t)-1)
0141         return KrPermHandler::writeable(m_permissions, m_gid, m_uid);
0142     else
0143         return KrPermHandler::ftpWriteable(m_owner, m_url.userName(), m_permissions);
0144 }
0145 
0146 char FileItem::isExecutable() const
0147 {
0148     if (m_uid != (uid_t)-1 && m_gid != (gid_t)-1)
0149         return KrPermHandler::executable(m_permissions, m_gid, m_uid);
0150     else
0151         return KrPermHandler::ftpExecutable(m_owner, m_url.userName(), m_permissions);
0152 }
0153 
0154 void FileItem::setSize(KIO::filesize_t size)
0155 {
0156     m_size = size;
0157     s_fileSizeCache.insert(m_url, new FileSize(size));
0158 }
0159 
0160 const QString &FileItem::getMime()
0161 {
0162     if (m_mimeType.isEmpty()) {
0163         if (m_isDir) {
0164             m_mimeType = "inode/directory";
0165             m_iconName = "inode-directory";
0166         } else if (isBrokenLink()) {
0167             m_mimeType = "unknown";
0168             m_iconName = "file-broken";
0169         } else {
0170             const QMimeDatabase db;
0171             const QMimeType mt = db.mimeTypeForUrl(getUrl());
0172             m_mimeType = mt.isValid() ? mt.name() : "unknown";
0173             m_iconName = mt.isValid() ? mt.iconName() : "file-broken";
0174 
0175             if (m_mimeType == "inode/directory") {
0176                 // TODO view update needed? and does this ever happen?
0177                 m_isDir = true;
0178             }
0179         }
0180 
0181         if (m_isDir && userDefinedFolderIcons) {
0182             const QUrl url = getUrl();
0183             if (url.isLocalFile()) {
0184                 const QString file = url.toLocalFile() + "/.directory";
0185                 const KDesktopFile cfg(file);
0186                 const QString iconName = cfg.readIcon();
0187                 if (!iconName.isEmpty())
0188                     m_iconName = iconName.startsWith(QLatin1String("./")) ?
0189                                                                           // relative path
0190                         url.toLocalFile() + '/' + iconName
0191                                                                           : iconName;
0192             }
0193         }
0194     }
0195     return m_mimeType;
0196 }
0197 
0198 const QString &FileItem::getIcon()
0199 {
0200     if (m_iconName.isEmpty()) {
0201         getMime(); // sets the icon
0202     }
0203     return m_iconName;
0204 }
0205 
0206 const QString &FileItem::getACL()
0207 {
0208     if (!m_AclLoaded)
0209         loadACL();
0210     return m_acl;
0211 }
0212 
0213 void FileItem::loadACL()
0214 {
0215     if (m_url.isLocalFile()) {
0216         FileSystemProvider::getACL(this, m_acl, m_defaulfAcl);
0217     }
0218     m_AclLoaded = true;
0219 }
0220 
0221 const KIO::UDSEntry FileItem::getEntry()
0222 {
0223     KIO::UDSEntry entry;
0224 
0225     entry.fastInsert(KIO::UDSEntry::UDS_NAME, getName());
0226     entry.fastInsert(KIO::UDSEntry::UDS_SIZE, getSize());
0227     entry.fastInsert(KIO::UDSEntry::UDS_MODIFICATION_TIME, getModificationTime());
0228     if (m_btime != -1) {
0229         entry.fastInsert(KIO::UDSEntry::UDS_CREATION_TIME, getCreationTime());
0230     }
0231     entry.fastInsert(KIO::UDSEntry::UDS_ACCESS_TIME, getAccessTime());
0232     entry.fastInsert(KIO::UDSEntry::UDS_USER, getOwner());
0233     entry.fastInsert(KIO::UDSEntry::UDS_GROUP, getGroup());
0234     entry.fastInsert(KIO::UDSEntry::UDS_MIME_TYPE, getMime());
0235     entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, getMode() & S_IFMT);
0236     entry.fastInsert(KIO::UDSEntry::UDS_ACCESS, getMode() & 07777);
0237 
0238     if (isSymLink())
0239         entry.fastInsert(KIO::UDSEntry::UDS_LINK_DEST, getSymDest());
0240 
0241     if (!m_AclLoaded)
0242         loadACL();
0243     if (!m_acl.isNull() || !m_defaulfAcl.isNull()) {
0244         entry.fastInsert(KIO::UDSEntry::UDS_EXTENDED_ACL, 1);
0245 
0246         if (!m_acl.isNull())
0247             entry.fastInsert(KIO::UDSEntry::UDS_ACL_STRING, m_acl);
0248 
0249         if (!m_defaulfAcl.isNull())
0250             entry.fastInsert(KIO::UDSEntry::UDS_DEFAULT_ACL_STRING, m_defaulfAcl);
0251     }
0252 
0253     return entry;
0254 }