File indexing completed on 2023-12-03 08:26:47

0001 /***************************************************************************
0002  *   Copyright (C) 2009 Matthias Fuchs <mat69@gmx.net>                     *
0003  *                                                                         *
0004  *   This program is free software; you can redistribute it and/or modify  *
0005  *   it under the terms of the GNU General Public License as published by  *
0006  *   the Free Software Foundation; either version 2 of the License, or     *
0007  *   (at your option) any later version.                                   *
0008  *                                                                         *
0009  *   This program is distributed in the hope that it will be useful,       *
0010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0012  *   GNU General Public License for more details.                          *
0013  *                                                                         *
0014  *   You should have received a copy of the GNU General Public License     *
0015  *   along with this program; if not, write to the                         *
0016  *   Free Software Foundation, Inc.,                                       *
0017  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA .        *
0018  ***************************************************************************/
0019 
0020 #include "filehandler.h"
0021 #include "core/verifier.h"
0022 
0023 #include <QDir>
0024 
0025 FileHandlerThread::FileHandlerThread(QObject *parent)
0026     : QThread(parent)
0027     , abort(false)
0028 {
0029 }
0030 
0031 FileHandlerThread::~FileHandlerThread()
0032 {
0033     mutex.lock();
0034     abort = true;
0035     mutex.unlock();
0036 
0037     wait();
0038 }
0039 
0040 void FileHandlerThread::setData(const QList<FileData> &files,
0041                                 const QStringList &types,
0042                                 bool createPartial,
0043                                 const KGetMetalink::Resources &tempResources,
0044                                 const KGetMetalink::CommonData &tempCommonData)
0045 {
0046     QMutexLocker locker(&mutex);
0047     m_files.append(files);
0048     m_types.append(types);
0049     m_createPartial.append(createPartial);
0050     m_tempResources.append(tempResources);
0051     m_tempCommonDatas.append(tempCommonData);
0052 
0053     if (!isRunning()) {
0054         start();
0055     }
0056 }
0057 
0058 void FileHandlerThread::run()
0059 {
0060     mutex.lock();
0061     bool run = m_files.count();
0062     mutex.unlock();
0063 
0064     while (run && !abort) {
0065         mutex.lock();
0066         QList<FileData> files = m_files.takeFirst();
0067         QStringList types = m_types.takeFirst();
0068         bool createPartial = m_createPartial.takeFirst();
0069         KGetMetalink::Resources tempResources = m_tempResources.takeFirst();
0070         KGetMetalink::CommonData commonData = m_tempCommonDatas.takeFirst();
0071         mutex.unlock();
0072 
0073         while (files.count() && !abort) {
0074             // take the first file and try to handle it
0075             FileData data = files.takeFirst();
0076             const QUrl url = data.url;
0077             KGetMetalink::File file = data.file;
0078             file.data = commonData;
0079 
0080             foreach (const KGetMetalink::Url &metalinkUrl, tempResources.urls) {
0081                 KGetMetalink::Url mirror = metalinkUrl;
0082                 mirror.url.setPath(mirror.url.toString() + "/" + file.name);
0083 
0084                 // if the url has already been added, remove it and readd it
0085                 for (int i = 0; i < file.resources.urls.count(); ++i) {
0086                     if (file.resources.urls[i].url == mirror.url) {
0087                         file.resources.urls.removeAt(i);
0088                         break;
0089                     }
0090                 }
0091                 file.resources.urls.append(mirror);
0092             }
0093 
0094             foreach (const QString &type, types) {
0095                 if (abort) {
0096                     return;
0097                 }
0098 
0099                 const QString hash = Verifier::checksum(url, type, &abort);
0100                 if (!hash.isEmpty()) {
0101                     file.verification.hashes[type] = hash;
0102                 }
0103             }
0104 
0105             if (createPartial) {
0106                 foreach (const QString &type, types) {
0107                     if (abort) {
0108                         return;
0109                     }
0110 
0111                     const PartialChecksums partialChecksums = Verifier::partialChecksums(url, type, 0, &abort);
0112                     if (partialChecksums.isValid()) {
0113                         KGetMetalink::Pieces pieces;
0114                         pieces.type = type;
0115                         pieces.length = partialChecksums.length();
0116                         pieces.hashes = partialChecksums.checksums();
0117                         file.verification.pieces.append(pieces);
0118                     }
0119                 }
0120             }
0121             if (!abort) {
0122                 Q_EMIT fileResult(file);
0123             }
0124         }
0125         mutex.lock();
0126         run = m_files.count();
0127         mutex.unlock();
0128     }
0129 }
0130 
0131 DirectoryHandler::DirectoryHandler(QObject *parent)
0132     : QObject(parent)
0133     , m_allJobsStarted(false)
0134 {
0135 }
0136 
0137 DirectoryHandler::~DirectoryHandler()
0138 {
0139 }
0140 
0141 QList<FileData> DirectoryHandler::takeFiles()
0142 {
0143     QList<FileData> files = m_files;
0144     m_files.clear();
0145 
0146     return files;
0147 }
0148 
0149 void DirectoryHandler::slotFiles(const QList<QUrl> &files)
0150 {
0151     if (files.isEmpty()) {
0152         return;
0153     }
0154 
0155     m_allJobsStarted = false;
0156 
0157     foreach (const QUrl &url, files) {
0158         QDir dir(url.path());
0159         if (dir.exists()) {
0160             KIO::ListJob *listJob = KIO::listRecursive(url);
0161             m_jobs[listJob] = url;
0162 
0163             connect(listJob, &KIO::ListJob::entries, this, &DirectoryHandler::slotDirEntries);
0164             connect(listJob, &KIO::ListJob::result, this, &DirectoryHandler::slotFinished);
0165         } else {
0166             FileData data;
0167             data.url = url;
0168             data.file.name = url.fileName();
0169             QFile localFile(url.path());
0170             data.file.size = localFile.size();
0171 
0172             m_files.append(data);
0173         }
0174     }
0175 
0176     m_allJobsStarted = true;
0177     evaluateFileProcess();
0178 }
0179 
0180 void DirectoryHandler::slotDirEntries(KIO::Job *j, const KIO::UDSEntryList &entries)
0181 {
0182     KJob *job = j;
0183     if (!m_jobs.contains(job)) {
0184         return;
0185     }
0186 
0187     const QUrl baseUrl = m_jobs[job];
0188     const QString baseDir = baseUrl.fileName() + '/';
0189 
0190     foreach (const KIO::UDSEntry &entry, entries) {
0191         // skip all found dirs
0192         if (!entry.isDir()) {
0193             const QString name = entry.stringValue(KIO::UDSEntry::UDS_NAME);
0194             FileData data;
0195             data.url.setPath(baseUrl.toString() + "/" + name); // FIXME: Does this work?
0196             data.file.name = baseDir + name;
0197             data.file.size = entry.numberValue(KIO::UDSEntry::UDS_SIZE, -1);
0198 
0199             m_files.append(data);
0200         }
0201     }
0202 }
0203 
0204 void DirectoryHandler::slotFinished(KJob *job)
0205 {
0206     if (m_jobs.contains(job)) {
0207         m_jobs.remove(job);
0208         evaluateFileProcess();
0209     }
0210 }
0211 
0212 void DirectoryHandler::evaluateFileProcess()
0213 {
0214     // all jobs finished
0215     if (m_jobs.isEmpty() && m_allJobsStarted && !m_files.isEmpty()) {
0216         Q_EMIT finished();
0217     }
0218 }
0219 
0220 #include "moc_filehandler.cpp"