diff options
author | Klaas Freitag <freitag@owncloud.com> | 2015-05-15 16:34:17 +0300 |
---|---|---|
committer | Klaas Freitag <freitag@owncloud.com> | 2015-05-19 18:09:40 +0300 |
commit | 830daa40d1dae9064975e20c9295660fb8337fce (patch) | |
tree | dcc143937808d8c6a812c2e2bb7b09850c434aa1 /src | |
parent | f016d25b4cc934fd539665a8beb86f301afd2b9a (diff) |
Add a class TransmissionChecksumValidator, incl. unit test.
This does all needed to manage checksums that go with http headers
ensuring that the transmission was correct.
Diffstat (limited to 'src')
-rw-r--r-- | src/libsync/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/libsync/transmissionchecksumvalidator.cpp | 152 | ||||
-rw-r--r-- | src/libsync/transmissionchecksumvalidator.h | 54 |
3 files changed, 207 insertions, 0 deletions
diff --git a/src/libsync/CMakeLists.txt b/src/libsync/CMakeLists.txt index aaa1d93ca..7247d16a6 100644 --- a/src/libsync/CMakeLists.txt +++ b/src/libsync/CMakeLists.txt @@ -61,6 +61,7 @@ set(libsync_SRCS theme.cpp utility.cpp ownsql.cpp + transmissionchecksumvalidator.cpp creds/dummycredentials.cpp creds/abstractcredentials.cpp creds/credentialsfactory.cpp diff --git a/src/libsync/transmissionchecksumvalidator.cpp b/src/libsync/transmissionchecksumvalidator.cpp new file mode 100644 index 000000000..e6fd6f338 --- /dev/null +++ b/src/libsync/transmissionchecksumvalidator.cpp @@ -0,0 +1,152 @@ +/* + * Copyright (C) by Klaas Freitag <freitag@owncloud.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ +#include "config.h" +#include "filesystem.h" +#include "transmissionchecksumvalidator.h" +#include "syncfileitem.h" +#include "propagatorjobs.h" +#include "configfile.h" + +#include <QtConcurrent> + +namespace OCC { + +TransmissionChecksumValidator::TransmissionChecksumValidator(const QString& filePath, QObject *parent) + :QObject(parent), + _filePath(filePath) +{ + +} + +void TransmissionChecksumValidator::setChecksumType( const QByteArray& type ) +{ + _checksumType = type; +} + +QString TransmissionChecksumValidator::checksumType() +{ + return _checksumType; +} + + +void TransmissionChecksumValidator::uploadValidation( SyncFileItem *item ) +{ + QString checksumType = _checksumType; + if( checksumType.isEmpty() ) { + ConfigFile cfg; + checksumType = cfg.transmissionChecksum(); + } + + if( checksumType.isEmpty() || !item ) { + // if there is no checksum defined, continue to upload + emit validated(); + } else { + _item = item; + // Calculate the checksum in a different thread first. + connect( &_watcher, SIGNAL(finished()), + this, SLOT(slotUploadChecksumCalculated())); + if( checksumType == checkSumMD5C ) { + item->_checksum = checkSumMD5C; + item->_checksum += ":"; + _watcher.setFuture(QtConcurrent::run(FileSystem::calcMd5Worker, _filePath)); + + } else if( checksumType == checkSumSHA1C ) { + item->_checksum = checkSumSHA1C; + item->_checksum += ":"; + _watcher.setFuture(QtConcurrent::run( FileSystem::calcSha1Worker, _filePath)); + } +#ifdef ZLIB_FOUND + else if( checksumType == checkSumAdlerC) { + item->_checksum = checkSumAdlerC; + item->_checksum += ":"; + _watcher.setFuture(QtConcurrent::run(FileSystem::calcAdler32Worker, _filePath)); + } +#endif + else { + // for an unknown checksum, continue to upload + emit validated(); + } + } +} + +void TransmissionChecksumValidator::slotUploadChecksumCalculated( ) +{ + QByteArray checksum = _watcher.future().result(); + + if( !checksum.isEmpty() ) { + _item->_checksum.append(checksum); + } else { + _item->_checksum.clear(); + } + + emit validated(); +} + + +void TransmissionChecksumValidator::downloadValidation( const QByteArray& checksumHeader ) +{ + // if the incoming header is empty, there was no checksum header, and + // no validation can happen. Just continue. + if( checksumHeader.isEmpty() ) { + emit validated(); + return; + } + + bool ok = true; + + int indx = checksumHeader.indexOf(':'); + if( indx < 0 ) { + qDebug() << "Checksum header malformed:" << checksumHeader; + emit validated(); // show must go on - even not validated. + } + + if( ok ) { + const QByteArray type = checksumHeader.left(indx).toUpper(); + _expectedHash = checksumHeader.mid(indx+1); + + connect( &_watcher, SIGNAL(finished()), this, SLOT(slotDownloadChecksumCalculated()) ); + + // start the calculation in different thread + if( type == checkSumMD5C ) { + _watcher.setFuture(QtConcurrent::run(FileSystem::calcMd5Worker, _filePath)); + } else if( type == checkSumSHA1C ) { + _watcher.setFuture(QtConcurrent::run(FileSystem::calcSha1Worker, _filePath)); + } +#ifdef ZLIB_FOUND + else if( type == checkSumAdlerUpperC ) { + _watcher.setFuture(QtConcurrent::run(FileSystem::calcAdler32Worker, _filePath)); + } +#endif + else { + qDebug() << "Unknown checksum type" << type; + emit validationFailed(tr("The checksum header was malformed.")); + return; + } + } +} + +void TransmissionChecksumValidator::slotDownloadChecksumCalculated() +{ + const QByteArray hash = _watcher.future().result(); + + if( hash != _expectedHash ) { + emit validationFailed(tr("The file downloaded with a broken checksum, will be redownloaded.")); + } else { + qDebug() << "Checksum checked and matching: " << _expectedHash; + emit validated(); + } +} + + +} diff --git a/src/libsync/transmissionchecksumvalidator.h b/src/libsync/transmissionchecksumvalidator.h new file mode 100644 index 000000000..dc9f7effc --- /dev/null +++ b/src/libsync/transmissionchecksumvalidator.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) by Klaas Freitag <freitag@owncloud.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#pragma once + +#include <QObject> +#include <QByteArray> +#include <QFutureWatcher> + +namespace OCC { +class SyncFileItem; + +class TransmissionChecksumValidator : public QObject +{ + Q_OBJECT +public: + explicit TransmissionChecksumValidator(const QString& filePath, QObject *parent = 0); + + void uploadValidation( SyncFileItem *item ); + void downloadValidation( const QByteArray& checksumHeader ); + + void setChecksumType(const QByteArray &type ); + QString checksumType(); + +signals: + void validated(); + void validationFailed( const QString& errMsg ); + +private slots: + void slotUploadChecksumCalculated(); + void slotDownloadChecksumCalculated(); + +private: + QByteArray _checksumType; + QByteArray _expectedHash; + QString _filePath; + SyncFileItem *_item; + + // watcher for the checksum calculation thread + QFutureWatcher<QByteArray> _watcher; +}; + +} |