File indexing completed on 2024-04-28 08:49:25

0001 /**************************************************************************
0002  *   Copyright (C) 2009-2011 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 "verificationthread.h"
0021 #include "verifier.h"
0022 
0023 #include "kget_debug.h"
0024 #include <QDebug>
0025 
0026 #include <QFile>
0027 
0028 VerificationThread::VerificationThread(QObject *parent)
0029     : QThread(parent)
0030     , m_abort(false)
0031     , m_length(0)
0032     , m_type(Nothing)
0033 {
0034 }
0035 
0036 VerificationThread::~VerificationThread()
0037 {
0038     m_mutex.lock();
0039     m_abort = true;
0040     m_mutex.unlock();
0041 
0042     wait();
0043 }
0044 
0045 void VerificationThread::verify(const QString &type, const QString &checksum, const QUrl &file)
0046 {
0047     QMutexLocker locker(&m_mutex);
0048     m_types.append(type);
0049     m_checksums.append(checksum);
0050     m_files.append(file);
0051     m_type = Verify;
0052 
0053     if (!isRunning()) {
0054         start();
0055     }
0056 }
0057 
0058 void VerificationThread::findBrokenPieces(const QString &type, const QList<QString> checksums, KIO::filesize_t length, const QUrl &file)
0059 {
0060     QMutexLocker locker(&m_mutex);
0061     m_types.clear();
0062     m_types.append(type);
0063     m_checksums = checksums;
0064     m_files.clear();
0065     m_files.append(file);
0066     m_length = length;
0067     m_type = BrokenPieces;
0068 
0069     if (!isRunning()) {
0070         start();
0071     }
0072 }
0073 
0074 void VerificationThread::run()
0075 {
0076     if (m_type == Nothing) {
0077         return;
0078     }
0079 
0080     if (m_type == Verify) {
0081         doVerify();
0082     } else if (m_type == BrokenPieces) {
0083         doBrokenPieces();
0084     }
0085 }
0086 
0087 void VerificationThread::doVerify()
0088 {
0089     m_mutex.lock();
0090     bool run = m_files.count();
0091     m_mutex.unlock();
0092 
0093     while (run && !m_abort) {
0094         m_mutex.lock();
0095         const QString type = m_types.takeFirst();
0096         const QString checksum = m_checksums.takeFirst();
0097         const QUrl url = m_files.takeFirst();
0098         m_mutex.unlock();
0099 
0100         if (type.isEmpty() || checksum.isEmpty()) {
0101             m_mutex.lock();
0102             run = m_files.count();
0103             m_mutex.unlock();
0104             continue;
0105         }
0106 
0107         const QString hash = Verifier::checksum(url, type, &m_abort);
0108         qCDebug(KGET_DEBUG) << "Type:" << type << "Calculated checksum:" << hash << "Entered checksum:" << checksum;
0109         const bool fileVerified = (hash == checksum);
0110 
0111         if (m_abort) {
0112             return;
0113         }
0114 
0115         m_mutex.lock();
0116         if (!m_abort) {
0117             Q_EMIT verified(type, fileVerified, url);
0118             Q_EMIT verified(fileVerified);
0119         }
0120         run = m_files.count();
0121         m_mutex.unlock();
0122     }
0123 }
0124 
0125 void VerificationThread::doBrokenPieces()
0126 {
0127     m_mutex.lock();
0128     const QString type = m_types.takeFirst();
0129     const QStringList checksums = m_checksums;
0130     m_checksums.clear();
0131     const QUrl url = m_files.takeFirst();
0132     const KIO::filesize_t length = m_length;
0133     m_mutex.unlock();
0134 
0135     QList<KIO::fileoffset_t> broken;
0136 
0137     const QString filePath = url.toLocalFile();
0138     if (QFile::exists(filePath)) {
0139         QFile file(filePath);
0140         if (!file.open(QIODevice::ReadOnly)) {
0141             Q_EMIT brokenPieces(broken, length);
0142             return;
0143         }
0144 
0145         const KIO::filesize_t fileSize = file.size();
0146         if (!length || !fileSize) {
0147             Q_EMIT brokenPieces(broken, length);
0148             return;
0149         }
0150 
0151         const QStringList fileChecksums = Verifier::partialChecksums(url, type, length, &m_abort).checksums();
0152         if (m_abort) {
0153             Q_EMIT brokenPieces(broken, length);
0154             return;
0155         }
0156 
0157         if (fileChecksums.size() != checksums.size()) {
0158             qCDebug(KGET_DEBUG) << "Number of checksums differs!";
0159             Q_EMIT brokenPieces(broken, length);
0160             return;
0161         }
0162 
0163         for (int i = 0; i < checksums.size(); ++i) {
0164             if (fileChecksums.at(i) != checksums.at(i)) {
0165                 const int brokenStart = length * i;
0166                 qCDebug(KGET_DEBUG) << url << "broken segment" << i << "start" << brokenStart << "length" << length;
0167                 broken.append(brokenStart);
0168             }
0169         }
0170     }
0171 
0172     Q_EMIT brokenPieces(broken, length);
0173 }
0174 
0175 #include "moc_verificationthread.cpp"