diff --git a/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt b/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt index 9b8d6edcb783..e0c50de8c3bb 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt @@ -235,7 +235,7 @@ class FileUploadWorker( } private fun cleanupUploadProcess(result: RemoteOperationResult, operation: UploadFileOperation) { - if (!(isStopped && result.isCancelled)) { + if (!isStopped || !result.isCancelled) { uploadsStorageManager.updateDatabaseUploadResult(result, operation) notifyUploadResult(operation, result) notificationManager.dismissWorkerNotifications() @@ -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) } diff --git a/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java b/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java index 0181b4f4f5ae..0329979e2f76 100644 --- a/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java +++ b/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java @@ -23,6 +23,7 @@ import android.annotation.SuppressLint; import android.content.Context; +import android.content.Intent; import android.net.Uri; import android.text.TextUtils; @@ -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; /** @@ -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); @@ -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; @@ -485,13 +491,7 @@ private RemoteOperationResult encryptedUpload(OwnCloudClient client, OCFile pare // Update metadata EncryptionUtilsV2 encryptionUtilsV2 = new EncryptionUtilsV2(); -// kotlin.Pair 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; } @@ -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( @@ -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(); @@ -751,6 +737,7 @@ private RemoteOperationResult encryptedUpload(OwnCloudClient client, OCFile pare result = new RemoteOperationResult(e); } finally { mUploadStarted.set(false); + sendRefreshFolderEventBroadcast(); if (fileLock != null) { try { @@ -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 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()) { @@ -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()); @@ -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; diff --git a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java index de4d49f3660d..8290993b6813 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java +++ b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java @@ -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; @@ -229,6 +230,8 @@ 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; @@ -236,6 +239,7 @@ public class FileDisplayActivity extends FileActivity private PlayerServiceConnection mPlayerConnection; private Optional lastDisplayedUser = Optional.empty(); private int menuItemId = -1; + @Inject AppPreferences preferences; @Inject AppInfo appInfo; @@ -283,6 +287,7 @@ protected void onCreate(Bundle savedInstanceState) { initSyncBroadcastReceiver(); observeWorkerState(); + registerRefreshFolderEventReceiver(); } @SuppressWarnings("unchecked") @@ -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(); diff --git a/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java b/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java index 434bc5a83a89..1fe522e0926d 100644 --- a/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java +++ b/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java @@ -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; @@ -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; @@ -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; @@ -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; @@ -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; } } @@ -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);