Add download size & hash check (Issue #558) (#560)

* Check if the file that was downloaded to local disk equals the reported size & reported hash of the file on OneDrive. If sizes do not match, report an error and remove the local file as it is most likely corrupt.
This commit is contained in:
abraunegg 2019-06-28 13:13:32 +10:00 committed by GitHub
parent 15a2749382
commit 2f3804a3c0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 33 additions and 4 deletions

View file

@ -320,7 +320,7 @@ final class OneDriveApi
const(char)[] url;
// string driveByIdUrl = "https://graph.microsoft.com/v1.0/drives/";
url = driveByIdUrl ~ driveId ~ "/items/" ~ id;
url ~= "?select=size,malware";
url ~= "?select=size,malware,file";
return get(url);
}

View file

@ -79,6 +79,11 @@ private bool hasId(const ref JSONValue item)
return ("id" in item) != null;
}
private bool hasQuickXorHash(const ref JSONValue item)
{
return ("quickXorHash" in item["file"]["hashes"]) != null;
}
private bool isDotFile(string path)
{
// always allow the root
@ -1132,16 +1137,19 @@ final class SyncEngine
if (!dryRun) {
ulong fileSize = 0;
if ( (hasFileSize(fileDetails)) && (fileDetails.object()) ) {
string OneDriveFileHash;
if ( (hasFileSize(fileDetails)) && (hasQuickXorHash(fileDetails)) && (fileDetails.object()) ) {
// fileDetails is a valid JSON object with the elements we need
// Set the file size from the returned data
fileSize = fileDetails["size"].integer;
OneDriveFileHash = fileDetails["file"]["hashes"]["quickXorHash"].str;
} else {
// Issue #540 handling
log.vdebug("ERROR: onedrive.getFileDetails call returned a OneDriveException error");
// We want to return, cant download
return;
}
try {
onedrive.downloadById(item.driveId, item.id, path, fileSize);
} catch (OneDriveException e) {
@ -1174,7 +1182,28 @@ final class SyncEngine
}
// file has to have downloaded in order to set the times / data for the file
if (exists(path)) {
setTimes(path, item.mtime, item.mtime);
// A 'file' was downloaded - does what we downloaded = reported fileSize or if there is some sort of funky local disk compression going on
// does the file hash OneDrive reports match what we have locally?
string quickXorHash = computeQuickXorHash(path);
if ((getSize(path) == fileSize) || (OneDriveFileHash == quickXorHash)) {
// downloaded matches either size or hash
setTimes(path, item.mtime, item.mtime);
} else {
// size error?
if (getSize(path) != fileSize) {
// downloaded file size does not match
log.error("ERROR: File download size mis-match. Increase logging verbosity to determine why.");
}
// hash error?
if (OneDriveFileHash != quickXorHash) {
// downloaded file hash does not match
log.error("ERROR: File download hash mis-match. Increase logging verbosity to determine why.");
}
// we do not want this local file to remain on the local file system
safeRemove(path);
downloadFailed = true;
return;
}
} else {
log.error("ERROR: File failed to download. Increase logging verbosity to determine why.");
downloadFailed = true;