Checksum: Ignore unkown OC-Checksum header when downloading...

And if there are several checksums, pick the "best" one.

The case of several checksum was reported in
https://github.com/nextcloud/client_theming/issues/213
This commit is contained in:
Olivier Goffart 2017-11-20 08:18:52 +01:00 committed by Olivier Goffart
parent 529bcab009
commit 480932a58a
5 changed files with 42 additions and 24 deletions

View file

@ -90,6 +90,21 @@ QByteArray makeChecksumHeader(const QByteArray &checksumType, const QByteArray &
return header;
}
QByteArray findBestChecksum(const QByteArray &checksums)
{
int i = 0;
// The order of the searches here defines the preference ordering.
if (-1 != (i = checksums.indexOf("SHA1:"))
|| -1 != (i = checksums.indexOf("MD5:"))
|| -1 != (i = checksums.indexOf("Adler32:"))) {
// Now i is the start of the best checksum
// Grab it until the next space or end of string.
auto checksum = checksums.mid(i);
return checksum.mid(0, checksum.indexOf(" "));
}
return QByteArray();
}
bool parseChecksumHeader(const QByteArray &header, QByteArray *type, QByteArray *checksum)
{
if (header.isEmpty()) {

View file

@ -36,6 +36,16 @@ static const char checkSumAdlerC[] = "Adler32";
class SyncJournalDb;
/**
* Returns the highest-quality checksum in a 'checksums'
* property retrieved from the server.
*
* Example: "ADLER32:1231 SHA1:ab124124 MD5:2131affa21"
* -> "SHA1:ab124124"
*/
OCSYNC_EXPORT QByteArray findBestChecksum(const QByteArray &checksums);
/// Creates a checksum header from type and value.
OCSYNC_EXPORT QByteArray makeChecksumHeader(const QByteArray &checksumType, const QByteArray &checksum);

View file

@ -17,6 +17,7 @@
#include "account.h"
#include "theme.h"
#include "common/asserts.h"
#include "common/checksums.h"
#include <csync_private.h>
#include <csync_rename.h>
@ -300,28 +301,6 @@ void DiscoverySingleDirectoryJob::abort()
}
}
/**
* Returns the highest-quality checksum in a 'checksums'
* property retrieved from the server.
*
* Example: "ADLER32:1231 SHA1:ab124124 MD5:2131affa21"
* -> "SHA1:ab124124"
*/
static QByteArray findBestChecksum(const QByteArray &checksums)
{
int i = 0;
// The order of the searches here defines the preference ordering.
if (-1 != (i = checksums.indexOf("SHA1:"))
|| -1 != (i = checksums.indexOf("MD5:"))
|| -1 != (i = checksums.indexOf("Adler32:"))) {
// Now i is the start of the best checksum
// Grab it until the next space or end of string.
auto checksum = checksums.mid(i);
return checksum.mid(0, checksum.indexOf(" "));
}
return QByteArray();
}
static std::unique_ptr<csync_file_stat_t> propertyMapToFileStat(const QMap<QString, QString> &map)
{
std::unique_ptr<csync_file_stat_t> file_stat(new csync_file_stat_t);

View file

@ -647,7 +647,7 @@ void PropagateDownloadFile::slotGetFinished()
this, &PropagateDownloadFile::transmissionChecksumValidated);
connect(validator, &ValidateChecksumHeader::validationFailed,
this, &PropagateDownloadFile::slotChecksumFail);
auto checksumHeader = job->reply()->rawHeader(checkSumHeaderC);
auto checksumHeader = findBestChecksum(job->reply()->rawHeader(checkSumHeaderC));
auto contentMd5Header = job->reply()->rawHeader(contentMd5HeaderC);
if (checksumHeader.isEmpty() && !contentMd5Header.isEmpty())
checksumHeader = "MD5:" + contentMd5Header;

View file

@ -510,11 +510,25 @@ private slots:
QVERIFY(fakeFolder.syncOnce());
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
// OC-Checksum has preference
// Invalid OC-Checksum is ignored
checksumValue = "garbage";
// contentMd5Value is still good
fakeFolder.remoteModifier().create("A/a6", 16, 'A');
QVERIFY(fakeFolder.syncOnce());
contentMd5Value = "bad";
fakeFolder.remoteModifier().create("A/a7", 16, 'A');
QVERIFY(!fakeFolder.syncOnce());
contentMd5Value.clear();
QVERIFY(fakeFolder.syncOnce());
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
// OC-Checksum contains Unsupported checksums
checksumValue = "Unsupported:XXXX SHA1:invalid Invalid:XxX";
fakeFolder.remoteModifier().create("A/a8", 16, 'A');
QVERIFY(!fakeFolder.syncOnce()); // Since the supported SHA1 checksum is invalid, no download
checksumValue = "Unsupported:XXXX SHA1:19b1928d58a2030d08023f3d7054516dbc186f20 Invalid:XxX";
QVERIFY(fakeFolder.syncOnce()); // The supported SHA1 checksum is valid now, so the file are downloaded
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
}
// Tests the behavior of invalid filename detection