add support for transactional upload
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
package keepass2android.javafilestorage;
|
package keepass2android.javafilestorage;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import java.math.BigInteger;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
@@ -27,6 +28,7 @@ import java.security.KeyManagementException;
|
|||||||
import java.security.KeyStore;
|
import java.security.KeyStore;
|
||||||
import java.security.KeyStoreException;
|
import java.security.KeyStoreException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.SecureRandom;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
@@ -194,11 +196,73 @@ public class WebDavStorage extends JavaFileStorageBase {
|
|||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void renameOrMoveWebDavResource(String sourcePath, String destinationPath, boolean overwrite) throws Exception {
|
||||||
|
|
||||||
|
ConnectionInfo sourceCi = splitStringToConnectionInfo(sourcePath);
|
||||||
|
ConnectionInfo destinationCi = splitStringToConnectionInfo(destinationPath);
|
||||||
|
|
||||||
|
Request.Builder requestBuilder = new Request.Builder()
|
||||||
|
.url(new URL(sourceCi.URL))
|
||||||
|
.method("MOVE", null) // "MOVE" is the HTTP method
|
||||||
|
.header("Destination", destinationCi.URL); // New URI for the resource
|
||||||
|
|
||||||
|
// Add Overwrite header
|
||||||
|
if (overwrite) {
|
||||||
|
requestBuilder.header("Overwrite", "T"); // 'T' for true
|
||||||
|
} else {
|
||||||
|
requestBuilder.header("Overwrite", "F"); // 'F' for false
|
||||||
|
}
|
||||||
|
|
||||||
|
Request request = requestBuilder.build();
|
||||||
|
|
||||||
|
Response response = getClient(sourceCi).newCall(request).execute();
|
||||||
|
|
||||||
|
// Check the status code
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
// WebDAV MOVE can return 201 (Created) if a new resource was created at dest,
|
||||||
|
// or 204 (No Content) if moved to a pre-existing destination (e.g., just renamed).
|
||||||
|
// A 200 OK might also be returned by some servers, though 201/204 are more common.
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception("Rename/Move failed for " + sourceCi.URL + " to " + destinationCi.URL + ": " + response.code() + " " + response.message());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String generateRandomHexString(int length) {
|
||||||
|
SecureRandom secureRandom = new SecureRandom();
|
||||||
|
// Generate enough bytes to ensure we can get the desired number of hex characters.
|
||||||
|
// Each byte converts to two hex characters.
|
||||||
|
// For 8 hex characters, we need 4 bytes.
|
||||||
|
int numBytes = (int) Math.ceil(length / 2.0);
|
||||||
|
byte[] randomBytes = new byte[numBytes];
|
||||||
|
secureRandom.nextBytes(randomBytes);
|
||||||
|
|
||||||
|
// Convert the byte array to a hexadecimal string
|
||||||
|
// BigInteger(1, randomBytes) treats the byte array as a positive number.
|
||||||
|
// toString(16) converts it to a hexadecimal string.
|
||||||
|
String hexString = new BigInteger(1, randomBytes).toString(16);
|
||||||
|
|
||||||
|
// Pad with leading zeros if necessary (e.g., if the generated number is small)
|
||||||
|
// and then take the first 'length' characters.
|
||||||
|
// Using String.format to ensure leading zeros if the hexString is shorter.
|
||||||
|
return String.format("%0" + length + "d", new BigInteger(hexString, 16)).substring(0, length);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void uploadFile(String path, byte[] data, boolean writeTransactional)
|
public void uploadFile(String path, byte[] data, boolean writeTransactional)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
|
if (writeTransactional)
|
||||||
|
{
|
||||||
|
String randomSuffix = ".tmp." + generateRandomHexString(8);
|
||||||
|
uploadFile(path + randomSuffix, data, false);
|
||||||
|
renameOrMoveWebDavResource(path+randomSuffix, path, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ConnectionInfo ci = splitStringToConnectionInfo(path);
|
ConnectionInfo ci = splitStringToConnectionInfo(path);
|
||||||
|
|
||||||
@@ -245,8 +309,6 @@ public class WebDavStorage extends JavaFileStorageBase {
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
|
||||||
//TODO consider writeTransactional
|
|
||||||
//TODO check for error
|
|
||||||
|
|
||||||
Response response = getClient(ci).newCall(request).execute();
|
Response response = getClient(ci).newCall(request).execute();
|
||||||
checkStatus(response);
|
checkStatus(response);
|
||||||
|
|||||||
@@ -548,7 +548,7 @@ public class MainActivity extends Activity implements JavaFileStorage.FileStorag
|
|||||||
|
|
||||||
|
|
||||||
//storageToTest = new GoogleDriveAppDataFileStorage();
|
//storageToTest = new GoogleDriveAppDataFileStorage();
|
||||||
/*storageToTest = new WebDavStorage(new ICertificateErrorHandler() {
|
storageToTest = new WebDavStorage(new ICertificateErrorHandler() {
|
||||||
@Override
|
@Override
|
||||||
public boolean onValidationError(String error) {
|
public boolean onValidationError(String error) {
|
||||||
return false;
|
return false;
|
||||||
@@ -558,12 +558,12 @@ public class MainActivity extends Activity implements JavaFileStorage.FileStorag
|
|||||||
public boolean alwaysFailOnValidationError() {
|
public boolean alwaysFailOnValidationError() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
}, 64*1024);
|
||||||
*/
|
|
||||||
//storageToTest = new DropboxV2Storage(ctx,"4ybka4p4a1027n6", "1z5lv528un9nre8", !simulateRestart);
|
//storageToTest = new DropboxV2Storage(ctx,"4ybka4p4a1027n6", "1z5lv528un9nre8", !simulateRestart);
|
||||||
//storageToTest = new DropboxFileStorage(ctx,"4ybka4p4a1027n6", "1z5lv528un9nre8", !simulateRestart);
|
//storageToTest = new DropboxFileStorage(ctx,"4ybka4p4a1027n6", "1z5lv528un9nre8", !simulateRestart);
|
||||||
//storageToTest = new DropboxAppFolderFileStorage(ctx,"ax0268uydp1ya57", "3s86datjhkihwyc", true);
|
//storageToTest = new DropboxAppFolderFileStorage(ctx,"ax0268uydp1ya57", "3s86datjhkihwyc", true);
|
||||||
storageToTest = new GoogleDriveFullFileStorage();
|
// storageToTest = new GoogleDriveFullFileStorage();
|
||||||
|
|
||||||
|
|
||||||
return storageToTest;
|
return storageToTest;
|
||||||
|
|||||||
Reference in New Issue
Block a user