Propagate downloads: Handle checksum transmission header.
authorKlaas Freitag <freitag@owncloud.com>
Fri, 15 May 2015 08:50:55 +0000 (10:50 +0200)
committerKlaas Freitag <freitag@owncloud.com>
Tue, 19 May 2015 15:09:40 +0000 (17:09 +0200)
Read a checksum from the HTTP header, and if its there, compare the
downloaded tmp file against it. In case of corruption, schedule a
redownload.

src/libsync/propagatedownload.cpp
src/libsync/propagatedownload.h
src/libsync/propagateupload.cpp

index 65fc409a741e50a1d5635a356942fd9697a47e6b..8975b4156547f5b23be5ae6c8f2ab41d6eb47b8d 100644 (file)
@@ -12,6 +12,7 @@
  * for more details.
  */
 
+#include "config.h"
 #include "owncloudpropagator_p.h"
 #include "propagatedownload.h"
 #include "networkjobs.h"
 #include <QDir>
 #include <QDebug>
 #include <cmath>
+#include <qtconcurrentrun.h>
 
 namespace OCC {
 
-
 // Always coming in with forward slashes.
 // In csync_excluded_no_ctx we ignore all files with longer than 254 chars
 // This function also adds a dot at the begining of the filename to hide the file on OS X and Linux
@@ -484,6 +485,67 @@ void PropagateDownloadFileQNAM::slotGetFinished()
         return;
     }
 
+    /* Check if a checksum was transmitted */
+    if( job->reply()->hasRawHeader(checkSumHeaderC)) {
+        QByteArray header = job->reply()->rawHeader(checkSumHeaderC);
+
+        bool ok = true;
+
+        int indx = header.indexOf(':');
+        if( indx < 0 ) {
+            qDebug() << "Checksum header malformed:" << header;
+            ok = false;
+        }
+
+        if( ok ) {
+            const QByteArray type = header.left(indx).toUpper();
+            _expectedHash = header.mid(indx+1);
+
+            connect( &_watcher, SIGNAL(finished()), this, SLOT(slotDownloadChecksumCheckFinished()));
+
+            // start the calculation in different thread
+            if( type == checkSumMD5C ) {
+                _watcher.setFuture(QtConcurrent::run(FileSystem::calcMd5Worker, _tmpFile.fileName()));
+            } else if( type == checkSumSHA1C ) {
+                _watcher.setFuture(QtConcurrent::run(FileSystem::calcSha1Worker, _tmpFile.fileName()));
+            }
+#ifdef ZLIB_FOUND
+            else if( type == checkSumAdlerUpperC ) {
+                _watcher.setFuture(QtConcurrent::run(FileSystem::calcAdler32Worker, _tmpFile.fileName()));
+            }
+#endif
+            else {
+                qDebug() << "Unknown checksum type" << type;
+                ok = false;
+            }
+        }
+
+        if( !ok) {
+            _tmpFile.remove();
+            _propagator->_anotherSyncNeeded = true;
+            done(SyncFileItem::SoftError, tr("The checksum header was malformed."));
+            return;
+        }
+    } else {
+        // No OC-Checksum header, go directly to continue handle the download
+        downloadFinished();
+    }
+
+}
+
+void PropagateDownloadFileQNAM::slotDownloadChecksumCheckFinished()
+{
+    const QByteArray hash = _watcher.future().result();
+
+    if( hash != _expectedHash ) {
+        _tmpFile.remove();
+        _propagator->_anotherSyncNeeded = true;
+        done(SyncFileItem::SoftError, tr("The file downloaded with a broken checksum, will be redownloaded."));
+        return;
+    } else {
+        qDebug() << "Checksum checked and matching: " << _expectedHash;
+    }
+
     downloadFinished();
 }
 
index 47c60702ae062870bf61fc83e63f0b134728a171..65ef9aff3be34a6b0d0275dedb2172264b47c43b 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <QBuffer>
 #include <QFile>
+#include <QFutureWatcher>
 
 namespace OCC {
 
@@ -103,17 +104,24 @@ class PropagateDownloadFileQNAM : public PropagateItemJob {
     Q_OBJECT
     QPointer<GETFileJob> _job;
 
-//  QFile *_file;
     QFile _tmpFile;
 public:
     PropagateDownloadFileQNAM(OwncloudPropagator* propagator,const SyncFileItem& item)
         : PropagateItemJob(propagator, item) {}
     void start() Q_DECL_OVERRIDE;
+
 private slots:
     void slotGetFinished();
     void abort() Q_DECL_OVERRIDE;
     void downloadFinished();
     void slotDownloadProgress(qint64,qint64);
+    void slotDownloadChecksumCheckFinished();
+
+private:
+    QByteArray _expectedHash;
+    QFutureWatcher<QByteArray> _watcher;
+    Utility::StopWatch _stopWatch;
+
 };
 
 }
index bdd6a48607a46499dfe2e71bcde823745a4d61c9..0ebde657ab9ebf20e88670df0e88a568a902f163 100644 (file)
@@ -12,6 +12,7 @@
  * for more details.
  */
 
+#include "config.h"
 #include "propagateupload.h"
 #include "owncloudpropagator_p.h"
 #include "networkjobs.h"