-
Notifications
You must be signed in to change notification settings - Fork 95
SHA-256 Hash #1725
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
SHA-256 Hash #1725
Changes from 11 commits
fbf52fc
5659f7f
012b77b
d277742
05ff4d8
3342d51
74784f5
b29e848
28b82f3
37f53e7
e9dfa54
e65b40b
b884185
43cfa96
3051d79
a4583c4
6a72e58
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,6 +9,7 @@ | |
import android.text.TextUtils; | ||
|
||
import com.owncloud.android.lib.common.OwnCloudClient; | ||
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory; | ||
import com.owncloud.android.lib.common.network.ChunkFromFileChannelRequestEntity; | ||
import com.owncloud.android.lib.common.network.ProgressiveDataTransfer; | ||
import com.owncloud.android.lib.common.network.WebdavEntry; | ||
|
@@ -36,6 +37,9 @@ | |
|
||
import androidx.annotation.VisibleForTesting; | ||
|
||
import java.security.MessageDigest; | ||
import java.nio.ByteBuffer; | ||
import java.math.BigInteger; | ||
|
||
public class ChunkedFileUploadRemoteOperation extends UploadFileRemoteOperation { | ||
|
||
|
@@ -216,6 +220,11 @@ protected RemoteOperationResult run(OwnCloudClient client) { | |
moveMethod = new MoveMethod(originUri, destinationUri, true); | ||
moveMethod.addRequestHeader(OC_X_OC_MTIME_HEADER, String.valueOf(lastModificationTimestamp)); | ||
|
||
String Hash = FileUtils.getHASHfromFile(this, new File(localPath), "SHA-256"); | ||
Alexander-Ger-Reich marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
if(Hash != null){ | ||
Alexander-Ger-Reich marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
putMethod.addRequestHeader("X-Content-Hash", Hash); | ||
Alexander-Ger-Reich marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
} | ||
|
||
if (creationTimestamp != null && creationTimestamp > 0) { | ||
moveMethod.addRequestHeader(OC_X_OC_CTIME_HEADER, String.valueOf(creationTimestamp)); | ||
} | ||
|
@@ -291,6 +300,24 @@ private RemoteOperationResult uploadChunk(OwnCloudClient client, Chunk chunk) th | |
putMethod.addRequestHeader(E2E_TOKEN, token); | ||
} | ||
|
||
if (OwnCloudClientManagerFactory.getHASHcheck()) { | ||
Alexander-Ger-Reich marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
try (RandomAccessFile hashRaf = new RandomAccessFile(file, "r")) { | ||
MessageDigest md = MessageDigest.getInstance("SHA-256"); | ||
|
||
FileChannel hashChannel = hashRaf.getChannel(); | ||
ByteBuffer buf = ByteBuffer.allocate((int) chunk.getLength()); | ||
hashChannel.position(chunk.getStart()); | ||
hashChannel.read(buf); | ||
md.update(buf.array()); | ||
|
||
String chunkHash = String.format("%064x", new BigInteger(1, md.digest())); | ||
|
||
putMethod.addRequestHeader("X-Content-Hash", chunkHash); | ||
} catch (Exception e) { | ||
Log_OC.w(TAG, "Could not compute chunk hash"); | ||
} | ||
} | ||
|
||
status = client.executeMethod(putMethod); | ||
|
||
result = new RemoteOperationResult(isSuccess(status), putMethod); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,7 @@ | |
package com.owncloud.android.lib.resources.files; | ||
|
||
import com.owncloud.android.lib.common.OwnCloudClient; | ||
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory; | ||
import com.owncloud.android.lib.common.network.OnDatatransferProgressListener; | ||
import com.owncloud.android.lib.common.network.WebdavUtils; | ||
import com.owncloud.android.lib.common.operations.OperationCancelledException; | ||
|
@@ -28,6 +29,8 @@ | |
import java.util.Set; | ||
import java.util.concurrent.atomic.AtomicBoolean; | ||
|
||
import java.util.Locale; | ||
|
||
/** | ||
* Remote operation performing the download of a remote file in the ownCloud server. | ||
* | ||
|
@@ -135,8 +138,55 @@ private int downloadFile(OwnCloudClient client, File targetFile) throws IOExcept | |
transferEncoding = "chunked".equals(transferEncodingHeader.getValue()); | ||
} | ||
|
||
if (transferred == totalToTransfer || transferEncoding) { | ||
savedFile = true; | ||
if (transferred == totalToTransfer || transferEncoding) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If possible, could you apply the fail fast here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What do you mean by that? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of having nested if-else blocks, you can return early. However, I think the downloadFile() function is too complex for that. We can skip it, if it’s too much work to refactor. e.g. Before:
After:
|
||
if (OwnCloudClientManagerFactory.getHASHcheck()){ | ||
Header hashHeader = getMethod.getResponseHeader("X-Content-Hash"); | ||
String expectedHash = hashHeader != null ? hashHeader.getValue() : null; | ||
if (expectedHash != null) { | ||
try { | ||
String[] entries = expectedHash.split(","); | ||
for (String entry : entries) { | ||
String[] parts = entry.split(";", 2); | ||
if (parts.length != 2) continue; | ||
String Algorithm = parts[0].trim().toLowerCase(Locale.ROOT); | ||
String hash = parts[1].trim(); | ||
|
||
String digestAlgorithm = null; | ||
|
||
switch (Algorithm) { | ||
case "sha256": | ||
|
||
digestAlgorithm = "SHA-256"; | ||
break; | ||
default: | ||
// Skip unknown algorithm | ||
continue; | ||
} | ||
|
||
String FileHash = FileUtils.getHASHfromFile(this, targetFile, digestAlgorithm); | ||
Alexander-Ger-Reich marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
if (!hash.equalsIgnoreCase(FileHash)) { | ||
Alexander-Ger-Reich marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
// Hash is incorrect: delete file and abort | ||
Log_OC.w(TAG, "Hash mismatch: expected="+ hash +" actual="+ FileHash); | ||
status = 418; | ||
savedFile = false; | ||
}else{ | ||
savedFile = true; | ||
break; | ||
} | ||
} | ||
} catch (Exception e) { | ||
Log_OC.w(TAG, "Could not compute chunk hash"); | ||
status = 418; | ||
savedFile = false; | ||
} | ||
}else { | ||
savedFile = true; | ||
} | ||
}else { | ||
savedFile = true; | ||
} | ||
|
||
Header modificationTime = getMethod.getResponseHeader("Last-Modified"); | ||
if (modificationTime == null) { | ||
modificationTime = getMethod.getResponseHeader("last-modified"); | ||
|
Uh oh!
There was an error while loading. Please reload this page.