File indexing completed on 2024-04-28 04:57:36

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 <KIO/ListJob>
0024 
0025 #include <QDir>
0026 
0027 FileHandlerThread::FileHandlerThread(QObject *parent)
0028     : QThread(parent)
0029     , abort(false)
0030 {
0031 }
0032 
0033 FileHandlerThread::~FileHandlerThread()
0034 {
0035     mutex.lock();
0036     abort = true;
0037     mutex.unlock();
0038 
0039     wait();
0040 }
0041 
0042 void FileHandlerThread::setData(const QList<FileData> &files,
0043                                 const QStringList &types,
0044                                 bool createPartial,
0045                                 const KGetMetalink::Resources &tempResources,
0046                                 const KGetMetalink::CommonData &tempCommonData)
0047 {
0048     QMutexLocker locker(&mutex);
0049     m_files.append(files);
0050     m_types.append(types);
0051     m_createPartial.append(createPartial);
0052     m_tempResources.append(tempResources);
0053     m_tempCommonDatas.append(tempCommonData);
0054 
0055     if (!isRunning()) {
0056         start();
0057     }
0058 }
0059 
0060 void FileHandlerThread::run()
0061 {
0062     mutex.lock();
0063     bool run = m_files.count();
0064     mutex.unlock();
0065 
0066     while (run && !abort) {
0067         mutex.lock();
0068         QList<FileData> files = m_files.takeFirst();
0069         QStringList types = m_types.takeFirst();
0070         bool createPartial = m_createPartial.takeFirst();
0071         KGetMetalink::Resources tempResources = m_tempResources.takeFirst();
0072         KGetMetalink::CommonData commonData = m_tempCommonDatas.takeFirst();
0073         mutex.unlock();
0074 
0075         while (files.count() && !abort) {
0076             // take the first file and try to handle it
0077             FileData data = files.takeFirst();
0078             const QUrl url = data.url;
0079             KGetMetalink::File file = data.file;
0080             file.data = commonData;
0081 
0082             foreach (const KGetMetalink::Url &metalinkUrl, tempResources.urls) {
0083                 KGetMetalink::Url mirror = metalinkUrl;
0084                 mirror.url.setPath(mirror.url.toString() + "/" + file.name);
0085 
0086                 // if the url has already been added, remove it and readd it
0087                 for (int i = 0; i < file.resources.urls.count(); ++i) {
0088                     if (file.resources.urls[i].url == mirror.url) {
0089                         file.resources.urls.removeAt(i);
0090                         break;
0091                     }
0092                 }
0093                 file.resources.urls.append(mirror);
0094             }
0095 
0096             foreach (const QString &type, types) {
0097                 if (abort) {
0098                     return;
0099                 }
0100 
0101                 const QString hash = Verifier::checksum(url, type, &abort);
0102                 if (!hash.isEmpty()) {
0103                     file.verification.hashes[type] = hash;
0104                 }
0105             }
0106 
0107             if (createPartial) {
0108                 foreach (const QString &type, types) {
0109                     if (abort) {
0110                         return;
0111                     }
0112 
0113                     const PartialChecksums partialChecksums = Verifier::partialChecksums(url, type, 0, &abort);
0114                     if (partialChecksums.isValid()) {
0115                         KGetMetalink::Pieces pieces;
0116                         pieces.type = type;
0117                         pieces.length = partialChecksums.length();
0118                         pieces.hashes = partialChecksums.checksums();
0119                         file.verification.pieces.append(pieces);
0120                     }
0121                 }
0122             }
0123             if (!abort) {
0124                 Q_EMIT fileResult(file);
0125             }
0126         }
0127         mutex.lock();
0128         run = m_files.count();
0129         mutex.unlock();
0130     }
0131 }
0132 
0133 DirectoryHandler::DirectoryHandler(QObject *parent)
0134     : QObject(parent)
0135     , m_allJobsStarted(false)
0136 {
0137 }
0138 
0139 DirectoryHandler::~DirectoryHandler()
0140 {
0141 }
0142 
0143 QList<FileData> DirectoryHandler::takeFiles()
0144 {
0145     QList<FileData> files = m_files;
0146     m_files.clear();
0147 
0148     return files;
0149 }
0150 
0151 void DirectoryHandler::slotFiles(const QList<QUrl> &files)
0152 {
0153     if (files.isEmpty()) {
0154         return;
0155     }
0156 
0157     m_allJobsStarted = false;
0158 
0159     foreach (const QUrl &url, files) {
0160         QDir dir(url.path());
0161         if (dir.exists()) {
0162             KIO::ListJob *listJob = KIO::listRecursive(url);
0163             m_jobs[listJob] = url;
0164 
0165             connect(listJob, &KIO::ListJob::entries, this, &DirectoryHandler::slotDirEntries);
0166             connect(listJob, &KIO::ListJob::result, this, &DirectoryHandler::slotFinished);
0167         } else {
0168             FileData data;
0169             data.url = url;
0170             data.file.name = url.fileName();
0171             QFile localFile(url.path());
0172             data.file.size = localFile.size();
0173 
0174             m_files.append(data);
0175         }
0176     }
0177 
0178     m_allJobsStarted = true;
0179     evaluateFileProcess();
0180 }
0181 
0182 void DirectoryHandler::slotDirEntries(KIO::Job *j, const KIO::UDSEntryList &entries)
0183 {
0184     KJob *job = j;
0185     if (!m_jobs.contains(job)) {
0186         return;
0187     }
0188 
0189     const QUrl baseUrl = m_jobs[job];
0190     const QString baseDir = baseUrl.fileName() + '/';
0191 
0192     foreach (const KIO::UDSEntry &entry, entries) {
0193         // skip all found dirs
0194         if (!entry.isDir()) {
0195             const QString name = entry.stringValue(KIO::UDSEntry::UDS_NAME);
0196             FileData data;
0197             data.url.setPath(baseUrl.toString() + "/" + name); // FIXME: Does this work?
0198             data.file.name = baseDir + name;
0199             data.file.size = entry.numberValue(KIO::UDSEntry::UDS_SIZE, -1);
0200 
0201             m_files.append(data);
0202         }
0203     }
0204 }
0205 
0206 void DirectoryHandler::slotFinished(KJob *job)
0207 {
0208     if (m_jobs.contains(job)) {
0209         m_jobs.remove(job);
0210         evaluateFileProcess();
0211     }
0212 }
0213 
0214 void DirectoryHandler::evaluateFileProcess()
0215 {
0216     // all jobs finished
0217     if (m_jobs.isEmpty() && m_allJobsStarted && !m_files.isEmpty()) {
0218         Q_EMIT finished();
0219     }
0220 }
0221 
0222 #include "moc_filehandler.cpp"