Skip to content

Commit

Permalink
Merge pull request #12796 from nextcloud/bugfix/e2e-upload-by-alper
Browse files Browse the repository at this point in the history
Fix Upload Problems For Encrypted Folder
  • Loading branch information
tobiasKaminsky committed Apr 4, 2024
2 parents a9ff057 + 0480b82 commit 4592c17
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ class FileUploadWorker(
}

private fun cleanupUploadProcess(result: RemoteOperationResult<Any?>, operation: UploadFileOperation) {
if (!(isStopped && result.isCancelled)) {
if (!isStopped || !result.isCancelled) {
uploadsStorageManager.updateDatabaseUploadResult(result, operation)
notifyUploadResult(operation, result)
notificationManager.dismissWorkerNotifications()
Expand Down Expand Up @@ -288,17 +288,18 @@ class FileUploadWorker(
context.resources
)

// FIXME SYNC_CONFLICT passes wrong OCFile, check ConflictsResolveActivity.createIntent usage
val conflictResolveIntent = if (uploadResult.code == ResultCode.SYNC_CONFLICT) {
intents.conflictResolveActionIntents(context, uploadFileOperation)
} else {
null
}

val credentialIntent: PendingIntent? = if (uploadResult.code == ResultCode.UNAUTHORIZED) {
intents.credentialIntent(uploadFileOperation)
} else {
null
}

notifyForFailedResult(uploadResult.code, conflictResolveIntent, credentialIntent, errorMessage)
showNewNotification(uploadFileOperation)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.text.TextUtils;

Expand Down Expand Up @@ -98,6 +99,9 @@

import androidx.annotation.CheckResult;
import androidx.annotation.Nullable;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;

import static com.owncloud.android.ui.activity.FileDisplayActivity.REFRESH_FOLDER_EVENT_RECEIVER;


/**
Expand Down Expand Up @@ -455,6 +459,7 @@ private RemoteOperationResult encryptedUpload(OwnCloudClient client, OCFile pare

boolean metadataExists = false;
String token = null;
Object object = null;

ArbitraryDataProvider arbitraryDataProvider = new ArbitraryDataProviderImpl(getContext());
String publicKey = arbitraryDataProvider.getValue(user.getAccountName(), EncryptionUtils.PUBLIC_KEY);
Expand All @@ -466,6 +471,7 @@ private RemoteOperationResult encryptedUpload(OwnCloudClient client, OCFile pare
if (result != null) {
return result;
}

/***** E2E *****/
// Only on V2+: whenever we change something, increase counter
long counter = -1;
Expand All @@ -485,13 +491,7 @@ private RemoteOperationResult encryptedUpload(OwnCloudClient client, OCFile pare

// Update metadata
EncryptionUtilsV2 encryptionUtilsV2 = new EncryptionUtilsV2();
// kotlin.Pair<Boolean, DecryptedFolderMetadataFile> metadataPair =
// encryptionUtilsV2.retrieveMetadata(parentFile,
// client,
// user,
// mContext);

Object object = EncryptionUtils.downloadFolderMetadata(parentFile, client, mContext, user);
object = EncryptionUtils.downloadFolderMetadata(parentFile, client, mContext, user);
if (object instanceof DecryptedFolderMetadataFileV1 decrypted && decrypted.getMetadata() != null) {
metadataExists = true;
}
Expand Down Expand Up @@ -703,13 +703,6 @@ private RemoteOperationResult encryptedUpload(OwnCloudClient client, OCFile pare
"",
arbitraryDataProvider,
user);

// unlock
result = EncryptionUtils.unlockFolderV1(parentFile, client, token);

if (result.isSuccess()) {
token = null;
}
} else {
DecryptedFolderMetadataFile metadata = (DecryptedFolderMetadataFile) object;
encryptionUtilsV2.addFileToMetadata(
Expand All @@ -730,13 +723,6 @@ private RemoteOperationResult encryptedUpload(OwnCloudClient client, OCFile pare
mContext,
user,
getStorageManager());

// unlock
result = EncryptionUtils.unlockFolder(parentFile, client, token);

if (result.isSuccess()) {
token = null;
}
}

encryptedTempFile.delete();
Expand All @@ -751,6 +737,7 @@ private RemoteOperationResult encryptedUpload(OwnCloudClient client, OCFile pare
result = new RemoteOperationResult(e);
} finally {
mUploadStarted.set(false);
sendRefreshFolderEventBroadcast();

if (fileLock != null) {
try {
Expand All @@ -768,6 +755,18 @@ private RemoteOperationResult encryptedUpload(OwnCloudClient client, OCFile pare
}

logResult(result, mFile.getStoragePath(), mFile.getRemotePath());

// Unlock must be done otherwise folder stays locked and user can't upload any file
RemoteOperationResult<Void> unlockFolderResult;
if (object instanceof DecryptedFolderMetadataFileV1) {
unlockFolderResult = EncryptionUtils.unlockFolderV1(parentFile, client, token);
} else {
unlockFolderResult = EncryptionUtils.unlockFolder(parentFile, client, token);
}

if (unlockFolderResult != null && !unlockFolderResult.isSuccess()) {
result = unlockFolderResult;
}
}

if (result.isSuccess()) {
Expand All @@ -776,17 +775,6 @@ private RemoteOperationResult encryptedUpload(OwnCloudClient client, OCFile pare
getStorageManager().saveConflict(mFile, mFile.getEtagInConflict());
}

// unlock must be done always
if (token != null) {
RemoteOperationResult unlockFolderResult = EncryptionUtils.unlockFolder(parentFile,
client,
token);

if (!unlockFolderResult.isSuccess()) {
return unlockFolderResult;
}
}

// delete temporal file
if (temporalFile != null && temporalFile.exists() && !temporalFile.delete()) {
Log_OC.e(TAG, "Could not delete temporal file " + temporalFile.getAbsolutePath());
Expand All @@ -795,6 +783,11 @@ private RemoteOperationResult encryptedUpload(OwnCloudClient client, OCFile pare
return result;
}

private void sendRefreshFolderEventBroadcast() {
Intent intent = new Intent(REFRESH_FOLDER_EVENT_RECEIVER);
LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
}

private RemoteOperationResult checkConditions(File originalFile) {
RemoteOperationResult remoteOperationResult = null;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
import com.nextcloud.client.jobs.download.FileDownloadWorker;
import com.nextcloud.client.jobs.upload.FileUploadHelper;
import com.nextcloud.client.jobs.upload.FileUploadWorker;
import com.nextcloud.client.jobs.upload.UploadNotificationManager;
import com.nextcloud.client.media.PlayerServiceConnection;
import com.nextcloud.client.network.ClientFactory;
import com.nextcloud.client.network.ConnectivityService;
Expand Down Expand Up @@ -229,13 +230,16 @@ public class FileDisplayActivity extends FileActivity
public static final String KEY_IS_SEARCH_OPEN = "IS_SEARCH_OPEN";
public static final String KEY_SEARCH_QUERY = "SEARCH_QUERY";

public static final String REFRESH_FOLDER_EVENT_RECEIVER = "REFRESH_FOLDER_EVENT";

private String searchQuery = "";
private boolean searchOpen;

private SearchView searchView;
private PlayerServiceConnection mPlayerConnection;
private Optional<User> lastDisplayedUser = Optional.empty();
private int menuItemId = -1;

@Inject AppPreferences preferences;

@Inject AppInfo appInfo;
Expand Down Expand Up @@ -283,6 +287,7 @@ protected void onCreate(Bundle savedInstanceState) {

initSyncBroadcastReceiver();
observeWorkerState();
registerRefreshFolderEventReceiver();
}

@SuppressWarnings("unchecked")
Expand Down Expand Up @@ -2296,6 +2301,24 @@ public void onStart() {
checkForNewDevVersionNecessary(getApplicationContext());
}

private void registerRefreshFolderEventReceiver() {
IntentFilter filter = new IntentFilter(REFRESH_FOLDER_EVENT_RECEIVER);
LocalBroadcastManager.getInstance(this).registerReceiver(refreshFolderEventReceiver, filter);
}

private final BroadcastReceiver refreshFolderEventReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
syncAndUpdateFolder(true);
}
};

@Override
protected void onDestroy() {
LocalBroadcastManager.getInstance(this).unregisterReceiver(refreshFolderEventReceiver);
super.onDestroy();
}

@Override
protected void onRestart() {
super.onRestart();
Expand Down
18 changes: 8 additions & 10 deletions app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,11 @@
package com.owncloud.android.utils;

import android.content.Context;
import android.os.Build;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Pair;

import com.google.common.collect.Lists;
import com.google.common.primitives.Bytes;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
Expand Down Expand Up @@ -73,17 +71,14 @@

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
Expand Down Expand Up @@ -114,7 +109,6 @@

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
Expand All @@ -127,7 +121,6 @@
import javax.crypto.spec.SecretKeySpec;

import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.annotation.VisibleForTesting;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;

Expand Down Expand Up @@ -516,8 +509,12 @@ public static E2EVersion determinateVersion(String metadata) {
new TypeToken<>() {
});

if ("2.0".equals(v2.getVersion()) || "2".equals(v2.getVersion())) {
return E2EVersion.V2_0;
if (v2 != null) {
if ("2.0".equals(v2.getVersion()) || "2".equals(v2.getVersion())) {
return E2EVersion.V2_0;
}
} else {
return E2EVersion.UNKNOWN;
}
}

Expand Down Expand Up @@ -565,7 +562,8 @@ public static byte[] decodeStringToBase64Bytes(String string) {
}

public static EncryptedFile encryptFile(File file, Cipher cipher) throws InvalidParameterSpecException {
File encryptedFile = new File(file.getAbsolutePath() + ".enc");
// FIXME this won't work on low or write-protected storage
File encryptedFile = new File(file.getAbsolutePath() + ".enc.jpg");
encryptFileWithGivenCipher(file, encryptedFile, cipher);
String authenticationTagString = getAuthenticationTag(cipher);
return new EncryptedFile(encryptedFile, authenticationTagString);
Expand Down

0 comments on commit 4592c17

Please sign in to comment.