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

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 "checksumsearch.h"
0021 
0022 #include "core/verifier.h"
0023 #include "kget_debug.h"
0024 
0025 #include <QFile>
0026 #include <QFileInfo>
0027 #include <QRegularExpression>
0028 
0029 #include <KLocalizedString>
0030 
0031 const QStringList ChecksumSearch::URLCHANGEMODES = (QStringList() << i18n("Append") << i18n("Replace file") << i18n("Replace file-ending"));
0032 
0033 ChecksumSearch::ChecksumSearch(const QList<QUrl> &srcs, const QString &fileName, const QStringList &types, QObject *parent)
0034     : QObject(parent)
0035     , m_copyJob(nullptr)
0036     , m_srcs(srcs)
0037     , m_fileName(fileName)
0038     , m_types(types)
0039 {
0040     createDownload();
0041 }
0042 
0043 ChecksumSearch::~ChecksumSearch()
0044 {
0045     if (m_copyJob) {
0046         m_copyJob->kill(KJob::Quietly);
0047     }
0048 }
0049 
0050 void ChecksumSearch::createDownload()
0051 {
0052     if (m_srcs.isEmpty() || m_types.isEmpty()) {
0053         deleteLater();
0054     } else {
0055         m_src = m_srcs.takeFirst();
0056         m_type = m_types.takeFirst();
0057         m_isEmpty = m_type.isEmpty();
0058 
0059         m_copyJob = KIO::get(m_src, KIO::Reload, KIO::HideProgressInfo);
0060         m_copyJob->addMetaData("errorPage", "false");
0061         connect(m_copyJob, &KIO::TransferJob::data, this, &ChecksumSearch::slotData);
0062         connect(m_copyJob, &KJob::result, this, &ChecksumSearch::slotResult);
0063     }
0064 }
0065 
0066 void ChecksumSearch::slotData(KIO::Job *job, const QByteArray &data)
0067 {
0068     Q_UNUSED(job)
0069 
0070     if (m_dataBA.size() > 5 * 1024) {
0071         m_copyJob->kill(KJob::EmitResult);
0072     } else {
0073         m_dataBA.append(data);
0074     }
0075 }
0076 
0077 void ChecksumSearch::slotResult(KJob *job)
0078 {
0079     qCDebug(KGET_DEBUG);
0080 
0081     m_data.clear();
0082 
0083     switch (job->error()) {
0084     case 0: // The download has finished
0085     {
0086         qCDebug(KGET_DEBUG) << "Correctly downloaded" << m_src.toDisplayString();
0087         m_data = QString(m_dataBA);
0088         break;
0089     }
0090 
0091     default:
0092         qCDebug(KGET_DEBUG) << "There was error" << job->error() << "while downloading" << m_src.toDisplayString();
0093         break;
0094     }
0095 
0096     m_copyJob = nullptr;
0097     m_dataBA.clear();
0098 
0099     parseDownload();
0100 }
0101 
0102 void ChecksumSearch::parseDownload()
0103 {
0104     if (!m_data.isEmpty()) {
0105         qCDebug(KGET_DEBUG) << "*******Parse*******\n" << m_data << "*******************";
0106     }
0107 
0108     // no type has been specified
0109     if (m_type.isEmpty()) {
0110         parseDownloadEmpty();
0111         return;
0112     }
0113 
0114     const int length = Verifier::diggestLength(m_type);
0115 
0116     const QString patternChecksum = QString("\\w{%1}").arg(length);
0117     QRegularExpression rxChecksum(patternChecksum);
0118     QString hash;
0119 
0120     // find the correct line
0121     const QStringList lines = m_data.split('\n');
0122     for (const QString &line : lines) {
0123         if (line.contains(m_fileName, Qt::CaseInsensitive)) {
0124             auto match = rxChecksum.match(line);
0125             if (match.hasMatch()) {
0126                 hash = match.captured(0).toLower();
0127                 if (!m_fileName.contains(hash, Qt::CaseInsensitive)) {
0128                     qCDebug(KGET_DEBUG) << "Found hash: " << hash;
0129                     Q_EMIT data(m_type, hash);
0130                 }
0131             }
0132         }
0133     }
0134 
0135     // nothing found yet, so simply search for a word in the whole data that has the correct length
0136     auto match = rxChecksum.match(m_data);
0137     if (hash.isEmpty() && match.hasMatch()) {
0138         QString hash = match.captured(0);
0139         if (!m_fileName.contains(hash, Qt::CaseInsensitive)) {
0140             qCDebug(KGET_DEBUG) << "Found hash:" << hash;
0141             Q_EMIT data(m_type, hash);
0142         }
0143     }
0144 
0145     // only create a download here if type was specified, otherwise parseDownloadEmpty has to handle this
0146     if (!m_isEmpty) {
0147         createDownload();
0148     }
0149 }
0150 
0151 void ChecksumSearch::parseDownloadEmpty()
0152 {
0153     const QStringList lines = m_data.split('\n');
0154     const QStringList supportedTypes = Verifier::supportedVerficationTypes();
0155     foreach (const QString &type, supportedTypes) {
0156         if (m_data.contains(type, Qt::CaseInsensitive)) {
0157             m_type = type;
0158             parseDownload();
0159         }
0160     }
0161 
0162     createDownload();
0163 }
0164 
0165 QUrl ChecksumSearch::createUrl(const QUrl &src, const QString &change, ChecksumSearch::UrlChangeMode mode)
0166 {
0167     if (!src.isValid() || change.isEmpty()) {
0168         return QUrl();
0169     }
0170 
0171     QUrl url;
0172     if (mode == kg_Append) {
0173         url = QUrl(src.toString() + change);
0174     } else if (mode == kg_ReplaceFile) {
0175         QUrl temp = src.adjusted(QUrl::RemoveFilename);
0176         temp.setPath(temp.path() + change);
0177         url = temp;
0178     } else if (mode == kg_ReplaceEnding) {
0179         QString fileName = src.fileName();
0180         int index = fileName.lastIndexOf('.');
0181         if (index > -1) {
0182             fileName = fileName.left(index) + change;
0183             QUrl temp = src.adjusted(QUrl::RemoveFilename);
0184             temp.setPath(temp.path() + fileName);
0185             url = temp;
0186         }
0187     }
0188 
0189     return url;
0190 }
0191 
0192 #include "moc_checksumsearch.cpp"