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"