File indexing completed on 2024-05-05 17:57:23

0001 /*
0002     SPDX-FileCopyrightText: 2001 Shie Erlich <krusader@users.sourceforge.net>
0003     SPDX-FileCopyrightText: 2001 Rafi Yanai <krusader@users.sourceforge.net>
0004     SPDX-FileCopyrightText: 2004-2022 Krusader Krew <https://krusader.org>
0005 
0006     SPDX-License-Identifier: GPL-2.0-or-later
0007 */
0008 
0009 #include "krsearchmod.h"
0010 
0011 // QtCore
0012 #include <QDir>
0013 #include <QMimeDatabase>
0014 #include <QMimeType>
0015 #include <QRegExp>
0016 // QtWidgets
0017 #include <QApplication>
0018 #include <qplatformdefs.h>
0019 
0020 #include <KIO/Global>
0021 
0022 #include "../Archive/krarchandler.h"
0023 #include "../FileSystem/defaultfilesystem.h"
0024 #include "../FileSystem/fileitem.h"
0025 #include "../FileSystem/krpermhandler.h"
0026 #include "../FileSystem/krquery.h"
0027 #include "../FileSystem/virtualfilesystem.h"
0028 #include "../krglobal.h"
0029 
0030 #define EVENT_PROCESS_DELAY 250 // milliseconds
0031 
0032 static const QStringList TAR_TYPES = QStringList() << "tbz"
0033                                                    << "tgz"
0034                                                    << "tarz"
0035                                                    << "tar"
0036                                                    << "tlz";
0037 
0038 KrSearchMod::KrSearchMod(const KrQuery *query)
0039     : m_defaultFileSystem(nullptr)
0040     , m_virtualFileSystem(nullptr)
0041     , m_stopSearch(false)
0042 {
0043     m_query = new KrQuery(*query);
0044     connect(m_query, &KrQuery::status, this, &KrSearchMod::searching);
0045     connect(m_query, &KrQuery::processEvents, this, &KrSearchMod::slotProcessEvents);
0046 }
0047 
0048 KrSearchMod::~KrSearchMod()
0049 {
0050     delete m_query;
0051     if (m_defaultFileSystem)
0052         delete m_defaultFileSystem;
0053     if (m_virtualFileSystem)
0054         delete m_virtualFileSystem;
0055 }
0056 
0057 void KrSearchMod::start()
0058 {
0059     m_unScannedUrls.clear();
0060     m_scannedUrls.clear();
0061     m_timer.start();
0062 
0063     const QList<QUrl> whereToSearch = m_query->searchInDirs();
0064 
0065     // search every dir that needs to be searched
0066     for (int i = 0; i < whereToSearch.count(); ++i)
0067         scanUrl(whereToSearch[i]);
0068 
0069     emit finished();
0070 }
0071 
0072 void KrSearchMod::stop()
0073 {
0074     m_stopSearch = true;
0075 }
0076 
0077 void KrSearchMod::scanUrl(const QUrl &url)
0078 {
0079     if (m_stopSearch)
0080         return;
0081 
0082     m_unScannedUrls.push(url);
0083     while (!m_unScannedUrls.isEmpty()) {
0084         const QUrl url = m_unScannedUrls.pop();
0085 
0086         if (m_stopSearch)
0087             return;
0088 
0089         if (m_query->isExcluded(url)) {
0090             if (!m_query->searchInDirs().contains(url))
0091                 continue;
0092         }
0093 
0094         if (m_scannedUrls.contains(url))
0095             // avoid endless loop
0096             continue;
0097 
0098         m_scannedUrls.push(url);
0099 
0100         emit searching(url.toDisplayString(QUrl::PreferLocalFile));
0101 
0102         scanDirectory(url);
0103     }
0104 }
0105 
0106 void KrSearchMod::scanDirectory(const QUrl &url)
0107 {
0108     FileSystem *fileSystem = getFileSystem(url);
0109 
0110     // create file items
0111     const bool refreshed = fileSystem->scanDir(url);
0112     if (!refreshed) {
0113         emit error(url);
0114         return;
0115     }
0116 
0117     for (FileItem *fileItem : fileSystem->fileItems()) {
0118         const QUrl fileUrl = fileItem->getUrl();
0119 
0120         if (m_query->isRecursive() && ((!fileItem->isSymLink() && fileItem->isDir()) || (fileItem->isSymLink() && m_query->followLinks()))) {
0121             // query search in subdirectory
0122             m_unScannedUrls.push(fileUrl);
0123         }
0124 
0125         if (m_query->searchInArchives() && fileUrl.isLocalFile() && KrArcHandler::arcSupported(fileItem->getMime())) {
0126             // query search in archive; NOTE: only supported for local files
0127             QUrl archiveURL = fileUrl;
0128             bool encrypted;
0129             const QString type = krArcMan.getType(encrypted, fileUrl.path(), fileItem->getMime());
0130 
0131             if (!encrypted) {
0132                 archiveURL.setScheme(TAR_TYPES.contains(type) ? "tar" : "krarc");
0133                 m_unScannedUrls.push(archiveURL);
0134             }
0135         }
0136 
0137         if (m_query->match(fileItem)) {
0138             // found!
0139             emit found(*fileItem, m_query->foundText()); // emitting copy of file item
0140         }
0141 
0142         if (m_timer.elapsed() >= EVENT_PROCESS_DELAY) {
0143             qApp->processEvents();
0144             m_timer.start();
0145             if (m_stopSearch)
0146                 return;
0147         }
0148     }
0149 }
0150 
0151 FileSystem *KrSearchMod::getFileSystem(const QUrl &url)
0152 {
0153     FileSystem *fileSystem;
0154     if (url.scheme() == QStringLiteral("virt")) {
0155         if (!m_virtualFileSystem)
0156             m_virtualFileSystem = new VirtualFileSystem();
0157         fileSystem = m_virtualFileSystem;
0158     } else {
0159         if (!m_defaultFileSystem)
0160             m_defaultFileSystem = new DefaultFileSystem();
0161         fileSystem = m_defaultFileSystem;
0162     }
0163     return fileSystem;
0164 }
0165 
0166 void KrSearchMod::slotProcessEvents(bool &stopped)
0167 {
0168     qApp->processEvents();
0169     stopped = m_stopSearch;
0170 }