summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorkh1 <karsten.heimrich@nokia.com>2012-10-01 15:40:53 +0200
committerKarsten Heimrich <karsten.heimrich@digia.com>2012-10-17 09:19:26 +0200
commitb878ca377795e5e5bad16428683de711c3e60cdc (patch)
treec916da1b9620806c78050a073261a8b5c59a4a56 /src
parentba31ab511d9b1f5cfd581bf8ed2f35671dd26136 (diff)
Add data to the cryptographic hash while downloading.
Task-number: QTIFW-10 Add the data on the fly, fixes re-reading the whole file to compute the checksum. Change-Id: I764019ab051e1faef2868d13cb17da101fad2fa8 Reviewed-by: Niels Weber <niels.weber@digia.com> Reviewed-by: Tim Jenssen <tim.jenssen@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/libs/installer/downloadarchivesjob.cpp46
-rw-r--r--src/libs/kdtools/kdupdaterfiledownloader.cpp221
-rw-r--r--src/libs/kdtools/kdupdaterfiledownloader.h11
-rw-r--r--src/libs/kdtools/kdupdaterfiledownloader_p.h35
-rw-r--r--src/libs/kdtools/kdupdaterupdate.cpp2
5 files changed, 114 insertions, 201 deletions
diff --git a/src/libs/installer/downloadarchivesjob.cpp b/src/libs/installer/downloadarchivesjob.cpp
index 49abee339..f7aa2c896 100644
--- a/src/libs/installer/downloadarchivesjob.cpp
+++ b/src/libs/installer/downloadarchivesjob.cpp
@@ -217,31 +217,24 @@ void DownloadArchivesJob::registerFile()
{
Q_ASSERT(m_downloader != 0);
- const QString tempFile = m_downloader->downloadedFileName();
- if (m_core->testChecksum()) {
- QFile archiveFile(tempFile);
- if (archiveFile.open(QFile::ReadOnly)) {
- const QByteArray archiveHash = QInstaller::calculateHash(&archiveFile, QCryptographicHash::Sha1)
- .toHex();
- if ((archiveHash != m_currentHash) && (!m_canceled)) {
- //TODO: Maybe we should try to download the file again automatically
- const QMessageBox::Button res =
- MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(),
- QLatin1String("DownloadError"), tr("Download Error"), tr("Hash verification while "
- "downloading failed. This is a temporary error, please retry."),
- QMessageBox::Retry | QMessageBox::Cancel, QMessageBox::Cancel);
-
- if (res == QMessageBox::Cancel) {
- finishWithError(tr("Could not verify Hash"));
- return;
- }
-
- fetchNextArchiveHash();
- return;
- }
- } else {
- finishWithError(tr("Could not open %1").arg(tempFile));
+ if (m_canceled)
+ return;
+
+ if (m_core->testChecksum() && m_currentHash != m_downloader->sha1Sum().toHex()) {
+ //TODO: Maybe we should try to download the file again automatically
+ const QMessageBox::Button res =
+ MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(),
+ QLatin1String("DownloadError"), tr("Download Error"), tr("Hash verification while "
+ "downloading failed. This is a temporary error, please retry."),
+ QMessageBox::Retry | QMessageBox::Cancel, QMessageBox::Cancel);
+
+ if (res == QMessageBox::Cancel) {
+ finishWithError(tr("Could not verify Hash"));
+ return;
}
+
+ fetchNextArchiveHash();
+ return;
}
++m_archivesDownloaded;
@@ -251,9 +244,10 @@ void DownloadArchivesJob::registerFile()
emit progressChanged(double(m_archivesDownloaded) / m_archivesToDownloadCount);
}
- m_temporaryFiles.insert(tempFile);
+ m_temporaryFiles.insert(m_downloader->downloadedFileName());
const QPair<QString, QString> pair = m_archivesToDownload.takeFirst();
- QInstallerCreator::BinaryFormatEngineHandler::instance()->registerArchive(pair.first, tempFile);
+ QInstallerCreator::BinaryFormatEngineHandler::instance()->registerArchive(pair.first,
+ m_downloader->downloadedFileName());
fetchNextArchiveHash();
}
diff --git a/src/libs/kdtools/kdupdaterfiledownloader.cpp b/src/libs/kdtools/kdupdaterfiledownloader.cpp
index ec2293a2c..e9adb42b3 100644
--- a/src/libs/kdtools/kdupdaterfiledownloader.cpp
+++ b/src/libs/kdtools/kdupdaterfiledownloader.cpp
@@ -50,93 +50,6 @@ static double calcProgress(qint32 done, qint32 total)
}
-// -- HashVerificationJob
-
-class HashVerificationJob::Private
-{
-public:
- Private()
- : hash(QCryptographicHash::Sha1)
- , error(HashVerificationJob::ReadError)
- , timerId(-1) { }
-
- QPointer<QIODevice> device;
- QByteArray sha1Sum;
- QCryptographicHash hash;
- HashVerificationJob::Error error;
- int timerId;
-};
-
-HashVerificationJob::HashVerificationJob(QObject* parent)
- : QObject(parent)
- , d(new Private)
-{
-}
-
-HashVerificationJob::~HashVerificationJob()
-{
- delete d;
-}
-
-void HashVerificationJob::setDevice(QIODevice* dev)
-{
- d->device = dev;
-}
-
-void HashVerificationJob::setSha1Sum(const QByteArray &sum)
-{
- d->sha1Sum = sum;
-}
-
-int HashVerificationJob::error() const
-{
- return d->error;
-}
-
-bool HashVerificationJob::hasError() const
-{
- return d->error != NoError;
-}
-
-void HashVerificationJob::start()
-{
- Q_ASSERT(d->device);
- d->timerId = startTimer(0);
-}
-
-void HashVerificationJob::emitFinished()
-{
- emit finished(this);
- deleteLater();
-}
-
-void HashVerificationJob::timerEvent(QTimerEvent*)
-{
- Q_ASSERT(d->timerId >= 0);
- if (d->sha1Sum.isEmpty()) {
- killTimer(d->timerId);
- d->timerId = -1;
- d->error = NoError;
- d->device->close();
- emitFinished();
- return;
- }
-
- QByteArray buf;
- buf.resize(128 * 1024);
- const qint64 read = d->device->read(buf.data(), buf.size());
- if (read > 0) {
- d->hash.addData(buf.constData(), read);
- return;
- }
-
- d->error = d->hash.result() == d->sha1Sum ? NoError : SumsDifferError;
- killTimer(d->timerId);
- d->timerId = -1;
- emitFinished();
-}
-
-
// -- KDUpdater::FileDownloader
/*!
@@ -171,7 +84,9 @@ void HashVerificationJob::timerEvent(QTimerEvent*)
struct KDUpdater::FileDownloader::Private
{
Private()
- : autoRemove(true)
+ : m_hash(QCryptographicHash::Sha1)
+ , m_assumedSha1Sum("")
+ , autoRemove(true)
, m_speedTimerInterval(100)
, m_bytesReceived(0)
, m_bytesToReceive(0)
@@ -190,7 +105,10 @@ struct KDUpdater::FileDownloader::Private
QUrl url;
QString scheme;
- QByteArray sha1Sum;
+
+ QCryptographicHash m_hash;
+ QByteArray m_assumedSha1Sum;
+
QString errorString;
bool autoRemove;
bool followRedirect;
@@ -233,14 +151,19 @@ QUrl KDUpdater::FileDownloader::url() const
return d->url;
}
-void KDUpdater::FileDownloader::setSha1Sum(const QByteArray &sum)
+QByteArray KDUpdater::FileDownloader::sha1Sum() const
{
- d->sha1Sum = sum;
+ return d->m_hash.result();
}
-QByteArray KDUpdater::FileDownloader::sha1Sum() const
+QByteArray KDUpdater::FileDownloader::assumedSha1Sum() const
+{
+ return d->m_assumedSha1Sum;
+}
+
+void KDUpdater::FileDownloader::setAssumedSha1Sum(const QByteArray &sum)
{
- return d->sha1Sum;
+ d->m_assumedSha1Sum = sum;
}
QString FileDownloader::errorString() const
@@ -255,24 +178,16 @@ void FileDownloader::setDownloadAborted(const QString &error)
emit downloadAborted(error);
}
-void KDUpdater::FileDownloader::setDownloadCompleted(const QString &path)
+void KDUpdater::FileDownloader::setDownloadCompleted()
{
- HashVerificationJob *job = new HashVerificationJob;
- QFile *file = new QFile(path, job);
- if (!file->open(QIODevice::ReadOnly)) {
- emit downloadProgress(1);
+ if (d->m_assumedSha1Sum.isEmpty() || (d->m_assumedSha1Sum == sha1Sum())) {
+ onSuccess();
+ emit downloadCompleted();
+ emit downloadStatus(tr("Download finished."));
+ } else {
onError();
- setDownloadAborted(tr("Could not reopen downloaded file %1 for reading: %2").arg(path,
- file->errorString()));
- delete job;
- return;
+ setDownloadAborted(tr("Cryptographic hashes do not match."));
}
-
- job->setDevice(file);
- job->setSha1Sum(d->sha1Sum);
- connect(job, SIGNAL(finished(KDUpdater::HashVerificationJob*)), this,
- SLOT(sha1SumVerified(KDUpdater::HashVerificationJob*)));
- job->start();
}
void KDUpdater::FileDownloader::setDownloadCanceled()
@@ -281,18 +196,6 @@ void KDUpdater::FileDownloader::setDownloadCanceled()
emit downloadStatus(tr("Download canceled."));
}
-void KDUpdater::FileDownloader::sha1SumVerified(KDUpdater::HashVerificationJob *job)
-{
- if (job->hasError()) {
- onError();
- setDownloadAborted(tr("Cryptographic hashes do not match."));
- } else {
- onSuccess();
- emit downloadCompleted();
- emit downloadStatus(tr("Download finished."));
- }
-}
-
QString KDUpdater::FileDownloader::scheme() const
{
return d->scheme;
@@ -451,6 +354,16 @@ void KDUpdater::FileDownloader::emitEstimatedDownloadTime()
emit estimatedDownloadTime((d->m_bytesToReceive - d->m_bytesReceived) / d->m_downloadSpeed);
}
+void KDUpdater::FileDownloader::addCheckSumData(const QByteArray &data)
+{
+ d->m_hash.addData(data);
+}
+
+void KDUpdater::FileDownloader::addCheckSumData(const char *data, int length)
+{
+ d->m_hash.addData(data, length);
+}
+
/*!
Returns a copy of the proxy factory that this FileDownloader object is using to determine the proxies to
be used for requests.
@@ -649,6 +562,7 @@ void KDUpdater::LocalFileDownloader::timerEvent(QTimerEvent *event)
toWrite -= numWritten;
}
addSample(numRead);
+ addCheckSumData(buffer.data(), numRead);
if (numRead > 0) {
setProgress(d->source->pos(), d->source->size());
@@ -661,7 +575,7 @@ void KDUpdater::LocalFileDownloader::timerEvent(QTimerEvent *event)
killTimer(d->timerId);
d->timerId = -1;
- setDownloadCompleted(d->destination->fileName());
+ setDownloadCompleted();
} else if (event->timerId() == downloadSpeedTimerId()) {
emitDownloadSpeed();
emitDownloadStatus();
@@ -701,13 +615,13 @@ void LocalFileDownloader::onError()
struct KDUpdater::ResourceFileDownloader::Private
{
Private()
- : downloaded(false),
- timerId(-1)
+ : timerId(-1)
+ , downloaded(false)
{}
- QString destFileName;
- bool downloaded;
int timerId;
+ QFile destFile;
+ bool downloaded;
};
KDUpdater::ResourceFileDownloader::ResourceFileDownloader(QObject *parent)
@@ -748,17 +662,18 @@ void KDUpdater::ResourceFileDownloader::doDownload()
// Open source and destination files
QUrl url = this->url();
url.setScheme(QString::fromLatin1("file"));
- d->destFileName = QString::fromLatin1(":%1").arg(url.toLocalFile());
+ d->destFile.setFileName(QString::fromLatin1(":%1").arg(url.toLocalFile()));
- // Start a timer and kickoff the copy process
- d->timerId = startTimer(0); // as fast as possible
emit downloadStarted();
emit downloadProgress(0);
+
+ d->destFile.open(QIODevice::ReadOnly);
+ d->timerId = startTimer(0); // start as fast as possible
}
QString KDUpdater::ResourceFileDownloader::downloadedFileName() const
{
- return d->destFileName;
+ return d->destFile.fileName();
}
void KDUpdater::ResourceFileDownloader::setDownloadedFileName(const QString &/*name*/)
@@ -782,21 +697,55 @@ void KDUpdater::ResourceFileDownloader::cancelDownload()
setDownloadCanceled();
}
-void KDUpdater::ResourceFileDownloader::timerEvent(QTimerEvent *)
+void KDUpdater::ResourceFileDownloader::timerEvent(QTimerEvent *event)
{
- killTimer(d->timerId);
- d->timerId = -1;
- setDownloadCompleted(d->destFileName);
+ if (event->timerId() == d->timerId) {
+ if (!d->destFile.isOpen()) {
+ onError();
+ killTimer(d->timerId);
+ emit downloadProgress(1);
+ setDownloadAborted(tr("Could not read resource file \"%1\". Reason:").arg(downloadedFileName(),
+ d->destFile.errorString()));
+ return;
+ }
+
+ QByteArray buffer;
+ buffer.resize(32768);
+ const qint64 numRead = d->destFile.read(buffer.data(), buffer.size());
+
+ addSample(numRead);
+ addCheckSumData(buffer.data(), numRead);
+
+ if (numRead > 0) {
+ setProgress(d->destFile.pos(), d->destFile.size());
+ emit downloadProgress(calcProgress(d->destFile.pos(), d->destFile.size()));
+ return;
+ }
+
+ killTimer(d->timerId);
+ d->timerId = -1;
+ setDownloadCompleted();
+ } else if (event->timerId() == downloadSpeedTimerId()) {
+ emitDownloadSpeed();
+ emitDownloadStatus();
+ emitDownloadProgress();
+ emitEstimatedDownloadTime();
+ }
}
void KDUpdater::ResourceFileDownloader::onSuccess()
{
+ d->destFile.close();
d->downloaded = true;
+ stopDownloadSpeedTimer();
}
void KDUpdater::ResourceFileDownloader::onError()
{
+ d->destFile.close();
d->downloaded = false;
+ stopDownloadSpeedTimer();
+ d->destFile.setFileName(QString());
}
@@ -939,7 +888,7 @@ void KDUpdater::FtpDownloader::ftpCmdFinished(int id, bool error)
d->ftpCmdId = -1;
d->destination->flush();
- setDownloadCompleted(d->destination->fileName());
+ setDownloadCompleted();
}
void FtpDownloader::onSuccess()
@@ -1015,6 +964,7 @@ void KDUpdater::FtpDownloader::ftpReadyRead()
written += numWritten;
}
addSample(written);
+ addCheckSumData(buffer.data(), read);
}
}
@@ -1138,6 +1088,7 @@ void KDUpdater::HttpDownloader::httpReadyRead()
written += numWritten;
}
addSample(written);
+ addCheckSumData(buffer.data(), read);
}
}
@@ -1212,7 +1163,7 @@ void KDUpdater::HttpDownloader::httpReqFinished()
httpReadyRead();
d->destination->flush();
- setDownloadCompleted(d->destination->fileName());
+ setDownloadCompleted();
d->http->deleteLater();
d->http = 0;
}
diff --git a/src/libs/kdtools/kdupdaterfiledownloader.h b/src/libs/kdtools/kdupdaterfiledownloader.h
index 6f6d03cc5..5c5fab459 100644
--- a/src/libs/kdtools/kdupdaterfiledownloader.h
+++ b/src/libs/kdtools/kdupdaterfiledownloader.h
@@ -23,7 +23,6 @@
#ifndef KD_UPDATER_FILE_DOWNLOADER_H
#define KD_UPDATER_FILE_DOWNLOADER_H
-#include "kdupdater.h"
#include "kdtoolsglobal.h"
#include <QtCore/QObject>
@@ -51,7 +50,9 @@ public:
void setUrl(const QUrl &url);
QByteArray sha1Sum() const;
- void setSha1Sum(const QByteArray &sha1);
+
+ QByteArray assumedSha1Sum() const;
+ void setAssumedSha1Sum(const QByteArray &sha1);
QString scheme() const;
void setScheme(const QString &scheme);
@@ -80,7 +81,6 @@ public:
public Q_SLOTS:
virtual void cancelDownload();
- void sha1SumVerified(KDUpdater::HashVerificationJob *job);
protected:
virtual void onError() = 0;
@@ -105,7 +105,7 @@ private:
protected:
void setDownloadCanceled();
- void setDownloadCompleted(const QString &filepath);
+ void setDownloadCompleted();
void setDownloadAborted(const QString &error);
void runDownloadSpeedTimer();
@@ -120,6 +120,9 @@ protected:
void emitDownloadProgress();
void emitEstimatedDownloadTime();
+ void addCheckSumData(const QByteArray &data);
+ void addCheckSumData(const char *data, int length);
+
private Q_SLOTS:
virtual void doDownload() = 0;
diff --git a/src/libs/kdtools/kdupdaterfiledownloader_p.h b/src/libs/kdtools/kdupdaterfiledownloader_p.h
index c47663bd1..a8ceb65f6 100644
--- a/src/libs/kdtools/kdupdaterfiledownloader_p.h
+++ b/src/libs/kdtools/kdupdaterfiledownloader_p.h
@@ -31,41 +31,6 @@
namespace KDUpdater {
-//TODO make it a KDJob once merged
-class HashVerificationJob : public QObject
-{
- Q_OBJECT
-
-public:
- enum Error {
- NoError = 0,
- ReadError = 128,
- SumsDifferError
- };
-
- explicit HashVerificationJob(QObject *parent = 0);
- ~HashVerificationJob();
-
- void setDevice(QIODevice *dev);
- void setSha1Sum(const QByteArray &data);
-
- bool hasError() const;
- int error() const;
-
- void start();
-
-Q_SIGNALS:
- void finished(KDUpdater::HashVerificationJob *);
-
-private:
- void emitFinished();
- void timerEvent(QTimerEvent *te);
-
-private:
- class Private;
- Private *d;
-};
-
class LocalFileDownloader : public FileDownloader
{
Q_OBJECT
diff --git a/src/libs/kdtools/kdupdaterupdate.cpp b/src/libs/kdtools/kdupdaterupdate.cpp
index 3e560e0b4..0ae2ebfaf 100644
--- a/src/libs/kdtools/kdupdaterupdate.cpp
+++ b/src/libs/kdtools/kdupdaterupdate.cpp
@@ -95,7 +95,7 @@ Update::Update(Application *application, const UpdateSourceInfo &sourceInfo,
d->fileDownloader = FileDownloaderFactory::instance().create(updateUrl.scheme(), this);
if (d->fileDownloader) {
d->fileDownloader->setUrl(d->updateUrl);
- d->fileDownloader->setSha1Sum(d->sha1sum);
+ d->fileDownloader->setAssumedSha1Sum(d->sha1sum);
connect(d->fileDownloader, SIGNAL(downloadProgress(double)), this, SLOT(downloadProgress(double)));
connect(d->fileDownloader, SIGNAL(downloadCanceled()), this, SIGNAL(stopped()));
connect(d->fileDownloader, SIGNAL(downloadCompleted()), this, SIGNAL(finished()));