From 8896e23762f383cbe52ffa44d74cafc764a94800 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Fri, 29 May 2026 09:58:04 +0300 Subject: [PATCH 1/2] fix(e2ee): version detection Signed-off-by: alperozturk96 --- .../nextcloud/utils/e2ee/E2EVersionHelper.kt | 23 ++++--------------- .../android/utils/EncryptionUtilsV2.kt | 3 ++- .../android/utils/E2EVersionHelperTest.kt | 18 +++++++-------- 3 files changed, 15 insertions(+), 29 deletions(-) diff --git a/app/src/main/java/com/nextcloud/utils/e2ee/E2EVersionHelper.kt b/app/src/main/java/com/nextcloud/utils/e2ee/E2EVersionHelper.kt index 90cd2a791c07..f85e0f203cab 100644 --- a/app/src/main/java/com/nextcloud/utils/e2ee/E2EVersionHelper.kt +++ b/app/src/main/java/com/nextcloud/utils/e2ee/E2EVersionHelper.kt @@ -48,21 +48,6 @@ object E2EVersionHelper { E2EVersion.V1_2 } - /** - * Maps a raw version string to an [E2EVersion]. - * - * @param version version string - * @return resolved [E2EVersion] or [E2EVersion.UNKNOWN] if unsupported - */ - fun fromVersionString(version: String?): E2EVersion = when (version?.trim()) { - "1.0" -> E2EVersion.V1_0 - "1.1" -> E2EVersion.V1_1 - "1.2" -> E2EVersion.V1_2 - "2", "2.0" -> E2EVersion.V2_0 - "2.1" -> E2EVersion.V2_1 - else -> E2EVersion.UNKNOWN - } - /** * Determines the E2EE version by inspecting encrypted folder metadata. * @@ -70,22 +55,22 @@ object E2EVersionHelper { * to [E2EVersion.UNKNOWN] if parsing fails. */ fun fromMetadata(metadata: String): E2EVersion = runCatching { - val v1 = EncryptionUtils.deserializeJSON( + val v1 = EncryptionUtils.deserializeJSON( metadata, object : TypeToken() {} ) - fromVersionString(v1?.metadata?.version.toString()).also { + E2EVersion.fromValue(v1?.metadata?.version.toString()).also { if (it == E2EVersion.UNKNOWN) { throw IllegalStateException("Unknown V1 version") } } }.recoverCatching { - val v2 = EncryptionUtils.deserializeJSON( + val v2 = EncryptionUtils.deserializeJSON( metadata, object : TypeToken() {} ) - fromVersionString(v2.version) + E2EVersion.fromValue(v2.version) }.getOrDefault(E2EVersion.UNKNOWN) } diff --git a/app/src/main/java/com/owncloud/android/utils/EncryptionUtilsV2.kt b/app/src/main/java/com/owncloud/android/utils/EncryptionUtilsV2.kt index 2a697c1e2bef..380c80114933 100644 --- a/app/src/main/java/com/owncloud/android/utils/EncryptionUtilsV2.kt +++ b/app/src/main/java/com/owncloud/android/utils/EncryptionUtilsV2.kt @@ -40,6 +40,7 @@ import com.owncloud.android.lib.resources.e2ee.GetMetadataRemoteOperation import com.owncloud.android.lib.resources.e2ee.MetadataResponse import com.owncloud.android.lib.resources.e2ee.StoreMetadataV2RemoteOperation import com.owncloud.android.lib.resources.e2ee.UpdateMetadataV2RemoteOperation +import com.owncloud.android.lib.resources.status.E2EVersion import com.owncloud.android.operations.UploadException import org.apache.commons.httpclient.HttpStatus import org.bouncycastle.asn1.ASN1Sequence @@ -611,7 +612,7 @@ class EncryptionUtilsV2 { object : TypeToken() {} ) - val e2eeVersion = E2EVersionHelper.fromVersionString(v2.version) + val e2eeVersion = E2EVersion.fromValue(v2.version) val decryptedFolderMetadata = if (E2EVersionHelper.isV2Plus(e2eeVersion)) { val userId = AccountManager.get(context).getUserData( diff --git a/app/src/test/java/com/owncloud/android/utils/E2EVersionHelperTest.kt b/app/src/test/java/com/owncloud/android/utils/E2EVersionHelperTest.kt index 3671e3f53b76..dc8872ac739b 100644 --- a/app/src/test/java/com/owncloud/android/utils/E2EVersionHelperTest.kt +++ b/app/src/test/java/com/owncloud/android/utils/E2EVersionHelperTest.kt @@ -159,19 +159,19 @@ class E2EVersionHelperTest { @Test fun `determineE2EFromVersionString maps versions correctly`() { - assertEquals(E2EVersion.V1_0, E2EVersionHelper.fromVersionString("1.0")) - assertEquals(E2EVersion.V1_1, E2EVersionHelper.fromVersionString("1.1")) - assertEquals(E2EVersion.V1_2, E2EVersionHelper.fromVersionString("1.2")) - assertEquals(E2EVersion.V2_0, E2EVersionHelper.fromVersionString("2")) - assertEquals(E2EVersion.V2_0, E2EVersionHelper.fromVersionString("2.0")) - assertEquals(E2EVersion.V2_1, E2EVersionHelper.fromVersionString("2.1")) + assertEquals(E2EVersion.V1_0, E2EVersion.fromValue("1.0")) + assertEquals(E2EVersion.V1_1, E2EVersion.fromValue("1.1")) + assertEquals(E2EVersion.V1_2, E2EVersion.fromValue("1.2")) + assertEquals(E2EVersion.V2_0, E2EVersion.fromValue("2")) + assertEquals(E2EVersion.V2_0, E2EVersion.fromValue("2.0")) + assertEquals(E2EVersion.V2_1, E2EVersion.fromValue("2.1")) } @Test fun `determineE2EFromVersionString returns UNKNOWN for invalid input`() { - assertEquals(E2EVersion.UNKNOWN, E2EVersionHelper.fromVersionString(null)) - assertEquals(E2EVersion.UNKNOWN, E2EVersionHelper.fromVersionString("")) - assertEquals(E2EVersion.UNKNOWN, E2EVersionHelper.fromVersionString("3.0")) + assertEquals(E2EVersion.UNKNOWN, E2EVersion.fromValue(null)) + assertEquals(E2EVersion.UNKNOWN, E2EVersion.fromValue("")) + assertEquals(E2EVersion.UNKNOWN, E2EVersion.fromValue("3.0")) } private fun mockV1(version: String) { From c86d00003f1d6c69756c420fb5fc9c6af4123480 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Fri, 29 May 2026 11:27:44 +0300 Subject: [PATCH 2/2] use capabilities e2e api version instead latest Signed-off-by: alperozturk96 --- .../android/utils/EncryptionUtilsV2IT.kt | 4 +- .../nextcloud/utils/e2ee/E2EVersionHelper.kt | 11 --- .../datamodel/FileDataStorageManager.java | 10 +++ .../decrypted/DecryptedFolderMetadataFile.kt | 7 +- .../encrypted/EncryptedFolderMetadataFile.kt | 2 +- .../operations/CreateFolderOperation.java | 10 ++- .../CreateShareWithShareeOperation.java | 3 +- .../operations/RefreshFolderOperation.java | 8 +- .../RemoveRemoteEncryptedFileOperation.kt | 6 +- .../operations/UploadFileOperation.java | 3 +- .../ui/activity/FileDisplayActivity.kt | 78 +++++++++++++++++++ .../ui/fragment/OCFileListFragment.java | 8 +- .../android/utils/EncryptionUtils.java | 12 ++- .../android/utils/EncryptionUtilsV2.kt | 43 ++++------ 14 files changed, 133 insertions(+), 72 deletions(-) diff --git a/app/src/androidTest/java/com/owncloud/android/utils/EncryptionUtilsV2IT.kt b/app/src/androidTest/java/com/owncloud/android/utils/EncryptionUtilsV2IT.kt index 3ab05fdeaf0e..8e09ee62dbcb 100644 --- a/app/src/androidTest/java/com/owncloud/android/utils/EncryptionUtilsV2IT.kt +++ b/app/src/androidTest/java/com/owncloud/android/utils/EncryptionUtilsV2IT.kt @@ -22,6 +22,7 @@ import com.owncloud.android.datamodel.e2e.v2.decrypted.DecryptedUser import com.owncloud.android.datamodel.e2e.v2.encrypted.EncryptedFiledrop import com.owncloud.android.datamodel.e2e.v2.encrypted.EncryptedFiledropUser import com.owncloud.android.datamodel.e2e.v2.encrypted.EncryptedFolderMetadataFile +import com.owncloud.android.lib.resources.status.E2EVersion import com.owncloud.android.operations.RefreshFolderOperation import com.owncloud.android.util.EncryptionTestIT import junit.framework.TestCase.assertEquals @@ -469,6 +470,7 @@ class EncryptionUtilsV2IT : EncryptionIT() { val v2 = encryptionUtilsV2.migrateV1ToV2( v1, enc1UserId, + storageManager.user, enc1Cert, folder, storageManager @@ -601,7 +603,7 @@ class EncryptionUtilsV2IT : EncryptionIT() { metadata.keyChecksums.add(encryptionUtilsV2.hashMetadataKey(metadata.metadataKey)) - return DecryptedFolderMetadataFile(metadata, users, mutableMapOf()) + return DecryptedFolderMetadataFile(metadata, users, mutableMapOf(), E2EVersion.V2_1.value) } @Test diff --git a/app/src/main/java/com/nextcloud/utils/e2ee/E2EVersionHelper.kt b/app/src/main/java/com/nextcloud/utils/e2ee/E2EVersionHelper.kt index f85e0f203cab..1d2af80c4073 100644 --- a/app/src/main/java/com/nextcloud/utils/e2ee/E2EVersionHelper.kt +++ b/app/src/main/java/com/nextcloud/utils/e2ee/E2EVersionHelper.kt @@ -37,17 +37,6 @@ object E2EVersionHelper { fun isV1(version: E2EVersion): Boolean = version == E2EVersion.V1_0 || version == E2EVersion.V1_1 || version == E2EVersion.V1_2 - /** - * Returns the latest supported E2EE version. - * - * @param isV2 indicates whether the E2EE v2 series should be used - */ - fun latestVersion(isV2: Boolean): E2EVersion = if (isV2) { - E2EVersion.V2_1 - } else { - E2EVersion.V1_2 - } - /** * Determines the E2EE version by inspecting encrypted folder metadata. * diff --git a/app/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java b/app/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java index a82ad391bb5d..b482e48e10b2 100644 --- a/app/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java +++ b/app/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java @@ -2452,6 +2452,16 @@ private Cursor getCapabilityCursorForAccount(String accountName) { return cursor; } + public String getE2EEVersion(@NonNull User user) { + final var capabilities = getCapability(user); + return capabilities.getEndToEndEncryptionApiVersion().getValue(); + } + + public E2EVersion getE2EEVersionObject(@NonNull User user) { + final var capabilities = getCapability(user); + return capabilities.getEndToEndEncryptionApiVersion(); + } + @NonNull public OCCapability getCapability(User user) { return getCapability(user.getAccountName()); diff --git a/app/src/main/java/com/owncloud/android/datamodel/e2e/v2/decrypted/DecryptedFolderMetadataFile.kt b/app/src/main/java/com/owncloud/android/datamodel/e2e/v2/decrypted/DecryptedFolderMetadataFile.kt index da5caae88827..54fc0cc69f12 100644 --- a/app/src/main/java/com/owncloud/android/datamodel/e2e/v2/decrypted/DecryptedFolderMetadataFile.kt +++ b/app/src/main/java/com/owncloud/android/datamodel/e2e/v2/decrypted/DecryptedFolderMetadataFile.kt @@ -7,15 +7,10 @@ */ package com.owncloud.android.datamodel.e2e.v2.decrypted -import com.nextcloud.utils.e2ee.E2EVersionHelper - -/** - * Decrypted class representation of metadata json of folder metadata. - */ data class DecryptedFolderMetadataFile( val metadata: DecryptedMetadata, var users: MutableList = mutableListOf(), @Transient val filedrop: MutableMap = HashMap(), - val version: String = E2EVersionHelper.latestVersion(true).value + val version: String ) diff --git a/app/src/main/java/com/owncloud/android/datamodel/e2e/v2/encrypted/EncryptedFolderMetadataFile.kt b/app/src/main/java/com/owncloud/android/datamodel/e2e/v2/encrypted/EncryptedFolderMetadataFile.kt index b7d13dfc13c9..347cd883ab81 100644 --- a/app/src/main/java/com/owncloud/android/datamodel/e2e/v2/encrypted/EncryptedFolderMetadataFile.kt +++ b/app/src/main/java/com/owncloud/android/datamodel/e2e/v2/encrypted/EncryptedFolderMetadataFile.kt @@ -16,5 +16,5 @@ data class EncryptedFolderMetadataFile( val metadata: EncryptedMetadata, val users: List, @Transient val filedrop: MutableMap?, - val version: String = E2EVersionHelper.latestVersion(true).value + val version: String ) diff --git a/app/src/main/java/com/owncloud/android/operations/CreateFolderOperation.java b/app/src/main/java/com/owncloud/android/operations/CreateFolderOperation.java index af0ed63b794f..5f7aaef3403b 100644 --- a/app/src/main/java/com/owncloud/android/operations/CreateFolderOperation.java +++ b/app/src/main/java/com/owncloud/android/operations/CreateFolderOperation.java @@ -34,6 +34,7 @@ import com.owncloud.android.lib.resources.files.CreateFolderRemoteOperation; import com.owncloud.android.lib.resources.files.ReadFolderRemoteOperation; import com.owncloud.android.lib.resources.files.model.RemoteFile; +import com.owncloud.android.lib.resources.status.E2EVersion; import com.owncloud.android.operations.common.SyncOperation; import com.owncloud.android.utils.EncryptionUtils; import com.owncloud.android.utils.EncryptionUtilsV2; @@ -145,8 +146,8 @@ private RemoteOperationResult encryptedCreateV1(OCFile parent, OwnCloudClient cl privateKey, publicKey, arbitraryDataProvider, - user - ); + user, + E2EVersion.V1_2.getValue()); metadataExists = metadataPair.first; metadata = metadataPair.second; @@ -183,7 +184,7 @@ private RemoteOperationResult encryptedCreateV1(OCFile parent, OwnCloudClient cl token, client, metadataExists, - E2EVersionHelper.INSTANCE.latestVersion(false), + E2EVersion.V1_2, "", arbitraryDataProvider, user); @@ -304,7 +305,8 @@ private RemoteOperationResult encryptedCreateV2(OCFile parent, OwnCloudClient cl String remoteId = result.getResultData(); if (result.isSuccess()) { - DecryptedFolderMetadataFile subFolderMetadata = encryptionUtilsV2.createDecryptedFolderMetadataFile(); + String e2eeVersion = getStorageManager().getE2EEVersion(user); + DecryptedFolderMetadataFile subFolderMetadata = encryptionUtilsV2.createDecryptedFolderMetadataFile(e2eeVersion); // upload metadata encryptionUtilsV2.serializeAndUploadMetadata(remoteId, diff --git a/app/src/main/java/com/owncloud/android/operations/CreateShareWithShareeOperation.java b/app/src/main/java/com/owncloud/android/operations/CreateShareWithShareeOperation.java index 28e732052c72..9f10b762af5e 100644 --- a/app/src/main/java/com/owncloud/android/operations/CreateShareWithShareeOperation.java +++ b/app/src/main/java/com/owncloud/android/operations/CreateShareWithShareeOperation.java @@ -188,7 +188,8 @@ protected RemoteOperationResult run(OwnCloudClient client) { boolean metadataExists; if (metadata == null) { String cert = EncryptionUtils.retrievePublicKeyForUser(user, context); - metadata = new EncryptionUtilsV2().createDecryptedFolderMetadataFile(); + String e2eeVersion = getStorageManager().getE2EEVersion(user); + metadata = new EncryptionUtilsV2().createDecryptedFolderMetadataFile(e2eeVersion); metadata.getUsers().add(new DecryptedUser(client.getUserId(), cert, null)); metadataExists = false; diff --git a/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java b/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java index 9dbfddc41289..510a780c2f54 100644 --- a/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java +++ b/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java @@ -549,12 +549,10 @@ private void synchronizeData(List folderAndFiles) { // get current data about local contents of the folder to synchronize Map localFilesMap; - E2EVersion e2EVersion; + E2EVersion e2EVersion = fileDataStorageManager.getE2EEVersionObject(user); if (object instanceof DecryptedFolderMetadataFileV1 metadataFileV1) { - e2EVersion = E2EVersionHelper.INSTANCE.latestVersion(false); localFilesMap = prefillLocalFilesMap(metadataFileV1, fileDataStorageManager.getFolderContent(mLocalFolder, false)); } else { - e2EVersion = E2EVersionHelper.INSTANCE.latestVersion(true); localFilesMap = prefillLocalFilesMap(object, fileDataStorageManager.getFolderContent(mLocalFolder, false)); // update counter @@ -601,7 +599,7 @@ private void synchronizeData(List folderAndFiles) { FileStorageUtils.searchForLocalFileInDefaultPath(updatedFile, user.getAccountName()); // update file name for encrypted files - if (e2EVersion == E2EVersionHelper.INSTANCE.latestVersion(false)) { + if (e2EVersion == E2EVersion.V1_2) { updateFileNameForEncryptedFileV1(fileDataStorageManager, (DecryptedFolderMetadataFileV1) object, updatedFile); @@ -624,7 +622,7 @@ private void synchronizeData(List folderAndFiles) { // save updated contents in local database // update file name for encrypted files - if (e2EVersion == E2EVersionHelper.INSTANCE.latestVersion(false)) { + if (e2EVersion == E2EVersion.V1_2) { updateFileNameForEncryptedFileV1(fileDataStorageManager, (DecryptedFolderMetadataFileV1) object, mLocalFolder); diff --git a/app/src/main/java/com/owncloud/android/operations/RemoveRemoteEncryptedFileOperation.kt b/app/src/main/java/com/owncloud/android/operations/RemoveRemoteEncryptedFileOperation.kt index 2bd1042ae4e9..077b9a4aef07 100644 --- a/app/src/main/java/com/owncloud/android/operations/RemoveRemoteEncryptedFileOperation.kt +++ b/app/src/main/java/com/owncloud/android/operations/RemoveRemoteEncryptedFileOperation.kt @@ -20,6 +20,7 @@ import com.owncloud.android.lib.common.OwnCloudClient import com.owncloud.android.lib.common.operations.RemoteOperation import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.common.utils.Log_OC +import com.owncloud.android.lib.resources.status.E2EVersion import com.owncloud.android.utils.EncryptionUtils import com.owncloud.android.utils.EncryptionUtilsV2 import com.owncloud.android.utils.theme.CapabilityUtils @@ -124,7 +125,8 @@ class RemoveRemoteEncryptedFileOperation internal constructor( privateKey, publicKey, arbitraryDataProvider, - user + user, + E2EVersion.V1_2.value ) val (result, delete) = deleteRemoteFile(client, token) @@ -149,7 +151,7 @@ class RemoveRemoteEncryptedFileOperation internal constructor( token, client, metadataExists, - E2EVersionHelper.latestVersion(false), + E2EVersion.V1_2, "", arbitraryDataProvider, user 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 3a9d0bc0a766..1165635d2dfc 100644 --- a/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java +++ b/app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java @@ -53,6 +53,7 @@ import com.owncloud.android.lib.resources.files.ReadFileRemoteOperation; import com.owncloud.android.lib.resources.files.UploadFileRemoteOperation; import com.owncloud.android.lib.resources.files.model.RemoteFile; +import com.owncloud.android.lib.resources.status.E2EVersion; import com.owncloud.android.lib.resources.status.OCCapability; import com.owncloud.android.operations.common.SyncOperation; import com.owncloud.android.operations.e2e.E2EClientData; @@ -883,7 +884,7 @@ private void updateMetadataForV1(DecryptedFolderMetadataFileV1 metadata, E2EData clientData.getToken(), clientData.getClient(), metadataExists, - E2EVersionHelper.INSTANCE.latestVersion(false), + E2EVersion.V1_2, "", arbitraryDataProvider, user); diff --git a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt index db6f451d3ef8..e7fe1f30b80e 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt +++ b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt @@ -60,6 +60,8 @@ import com.nextcloud.client.account.User import com.nextcloud.client.appinfo.AppInfo import com.nextcloud.client.core.AsyncRunner import com.nextcloud.client.core.Clock +import com.nextcloud.operations.GetMethod +import org.json.JSONObject import com.nextcloud.client.database.entity.SyncedFolderEntity import com.nextcloud.client.di.Injectable import com.nextcloud.client.editimage.EditImageActivity @@ -299,6 +301,82 @@ class FileDisplayActivity : startMetadataSyncForRoot() handleBackPress() setupDrawer(menuItemId) + logOcsCredentials() + // Debug helper: fetch raw capabilities JSON and dump `ocs`, `meta` and `data` nodes to logs + // This is temporary and used for debugging backend responses on activity create. + debugDumpCapabilities() + } + + private fun debugDumpCapabilities() { + lifecycleScope.launch(Dispatchers.IO) { + try { + val user = accountManager.user + val client = try { + clientFactory.createNextcloudClient(user) + } catch (e: Exception) { + Log_OC.e(this@FileDisplayActivity, "debugDumpCapabilities: failed creating client", e) + return@launch + } + + val requestUri = client.baseUri + val uriBuilder = requestUri.buildUpon() + uriBuilder.appendEncodedPath("ocs/v2.php/cloud/capabilities") + uriBuilder.appendQueryParameter("format", "json") + + val get = GetMethod(uriBuilder.build().toString(), true) + + val status = try { + client.execute(get) + } catch (e: Exception) { + Log_OC.e(this@FileDisplayActivity, "debugDumpCapabilities: execute failed", e) + return@launch + } + + if (status == 200) { + val response = get.getResponseBodyAsString() + try { + val respJSON = JSONObject(response) + val respOCS = respJSON.getJSONObject("ocs") + val respMeta = respOCS.getJSONObject("meta") + val respData = respOCS.getJSONObject("data") + + Log_OC.d(this@FileDisplayActivity, "[dbg] respOCS: $respOCS") + Log_OC.d(this@FileDisplayActivity, "[dbg] respMeta: $respMeta") + Log_OC.d(this@FileDisplayActivity, "[dbg] respData: $respData") + } catch (e: Exception) { + Log_OC.e(this@FileDisplayActivity, "debugDumpCapabilities: parsing failed", e) + Log_OC.d(this@FileDisplayActivity, "debugDumpCapabilities: raw response: $response") + } + } else { + Log_OC.e(this@FileDisplayActivity, "debugDumpCapabilities: unexpected status=$status") + } + } catch (e: Exception) { + Log_OC.e(this@FileDisplayActivity, "debugDumpCapabilities: unexpected error", e) + } + } + } + + @Suppress("DEPRECATION") + private fun logOcsCredentials() { + lifecycleScope.launch(Dispatchers.IO) { + val user = accountManager.user + val serverUrl = user.server.uri.toString() + val accountName = user.accountName + + try { + val client = clientFactory.create(user) + val username = client.userIdPlain + val authToken = client.credentials.authToken + Log_OC.d(TAG, "OCS credentials — serverUrl=$serverUrl") + Log_OC.d(TAG, "OCS credentials — accountName=$accountName username=$username authToken=$authToken") + } catch (e: CreationException) { + Log_OC.e( + TAG, + "OCS credentials — serverUrl=$serverUrl accountName=$accountName (client creation failed)", + e + ) + } + } } /** diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java index d31dd21f5fba..6914bc7b2bf6 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java +++ b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java @@ -1987,10 +1987,8 @@ private void encryptFolder(OCFile folder, DecryptedFolderMetadataFileV1 metadata = new DecryptedFolderMetadataFileV1(); metadata.setMetadata(new DecryptedMetadata()); - - final var latestV1E2EEVersion = E2EVersionHelper.INSTANCE.latestVersion(false); - - metadata.getMetadata().setVersion(Double.parseDouble(latestV1E2EEVersion.getValue())); + final var latestV1E2EEVersion = storageManager.getE2EEVersion(user); + metadata.getMetadata().setVersion(Double.parseDouble(latestV1E2EEVersion)); metadata.getMetadata().setMetadataKeys(new HashMap<>()); String metadataKey = EncryptionUtils.encodeBytesToBase64String(EncryptionUtils.generateKey()); String encryptedMetadataKey = EncryptionUtils.encryptStringAsymmetric(metadataKey, publicKey); @@ -2010,7 +2008,7 @@ private void encryptFolder(OCFile folder, token, client, false, - E2EVersionHelper.INSTANCE.latestVersion(false), + storageManager.getE2EEVersionObject(user), "", arbitraryDataProvider, user); 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 48d90c38981b..56cd7cc389de 100644 --- a/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java +++ b/app/src/main/java/com/owncloud/android/utils/EncryptionUtils.java @@ -1189,7 +1189,8 @@ public static Pair retrieveMetadataV1(OC String privateKey, String publicKey, ArbitraryDataProvider arbitraryDataProvider, - User user) + User user, + String e2eeVersion) throws UploadException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchPaddingException, BadPaddingException, IllegalBlockSizeException, InvalidKeyException, InvalidKeySpecException, CertificateException { @@ -1220,10 +1221,7 @@ public static Pair retrieveMetadataV1(OC // new metadata metadata = new DecryptedFolderMetadataFileV1(); metadata.setMetadata(new DecryptedMetadata()); - - final var latestV1E2EEVersion = E2EVersionHelper.INSTANCE.latestVersion(false); - - metadata.getMetadata().setVersion(Double.parseDouble(latestV1E2EEVersion.getValue())); + metadata.getMetadata().setVersion(Double.parseDouble(e2eeVersion)); metadata.getMetadata().setMetadataKeys(new HashMap<>()); String metadataKey = EncryptionUtils.encodeBytesToBase64String(EncryptionUtils.generateKey()); String encryptedMetadataKey = EncryptionUtils.encryptStringAsymmetric(metadataKey, publicKey); @@ -1282,13 +1280,13 @@ public static Pair retrieveMetadata(OCFile } else if (getMetadataOperationResult.getHttpCode() == HttpStatus.SC_NOT_FOUND || getMetadataOperationResult.getHttpCode() == HttpStatus.SC_INTERNAL_SERVER_ERROR) { - final var latestE2EEV2Version = E2EVersionHelper.INSTANCE.latestVersion(true); + final var latestE2EEV2Version = storageManager.getE2EEVersion(user); // new metadata metadata = new DecryptedFolderMetadataFile(new com.owncloud.android.datamodel.e2e.v2.decrypted.DecryptedMetadata(), new ArrayList<>(), new HashMap<>(), - latestE2EEV2Version.getValue()); + latestE2EEV2Version); metadata.getUsers().add(new DecryptedUser(client.getUserId(), publicKey, null)); byte[] metadataKey = EncryptionUtils.generateKey(); diff --git a/app/src/main/java/com/owncloud/android/utils/EncryptionUtilsV2.kt b/app/src/main/java/com/owncloud/android/utils/EncryptionUtilsV2.kt index 380c80114933..991d45247465 100644 --- a/app/src/main/java/com/owncloud/android/utils/EncryptionUtilsV2.kt +++ b/app/src/main/java/com/owncloud/android/utils/EncryptionUtilsV2.kt @@ -12,6 +12,7 @@ import android.content.Context import androidx.annotation.VisibleForTesting import com.google.gson.reflect.TypeToken import com.nextcloud.client.account.User +import com.nextcloud.client.account.UserAccountManagerImpl import com.nextcloud.utils.CmsSignatureVerifier import com.nextcloud.utils.autoRename.AutoRename import com.nextcloud.utils.e2ee.E2EVersionHelper @@ -136,27 +137,9 @@ class EncryptionUtilsV2 { return EncryptedFolderMetadataFile( encryptedMetadata, encryptedUsers, - mutableMapOf() + mutableMapOf(), + storageManager.getE2EEVersion(user) ) - - // if (metadataFile.users.isEmpty()) { - // // we are in a subfolder, re-use users array - // retrieveTopMostMetadata( - // ocFile, - // storageManager, - // client - // ) - // } else { - // val encryptedUsers = metadataFile.users.map { - // encryptUser(it, metadataFile.metadata.metadataKey) - // } - // - // return EncryptedFolderMetadataFile( - // encryptedMetadata, - // encryptedUsers, - // emptyMap() - // ) - // } } @Throws(IllegalStateException::class, UploadException::class, Throwable::class) @@ -205,7 +188,8 @@ class EncryptionUtilsV2 { decryptedMetadata, // subfolder do not store user array mutableListOf(), - mutableMapOf() + mutableMapOf(), + storageManager.getE2EEVersion(user) ) } else { // Top folder @@ -247,7 +231,8 @@ class EncryptionUtilsV2 { DecryptedFolderMetadataFile( decryptedMetadata, users, - mutableMapOf() + mutableMapOf(), + storageManager.getE2EEVersion(user) ) } @@ -573,16 +558,16 @@ class EncryptionUtilsV2 { // check parent folder val parentFolder = FileDataStorageManager(user, context.contentResolver).getFileById(folder.parentId) ?: throw IllegalStateException("Cannot retrieve metadata!") + val storageManager = FileDataStorageManager(user, context.contentResolver) val metadata = if (parentFolder.isEncrypted) { // new metadata but without sharing part - createDecryptedFolderMetadataFile() + createDecryptedFolderMetadataFile(storageManager.getE2EEVersion(user)) } else { // new metadata val arbitraryDataProvider: ArbitraryDataProvider = ArbitraryDataProviderImpl(context) val publicKey: String = arbitraryDataProvider.getValue(user.accountName, EncryptionUtils.PUBLIC_KEY) - - createDecryptedFolderMetadataFile().apply { + createDecryptedFolderMetadataFile(storageManager.getE2EEVersion(user)).apply { users = mutableListOf(DecryptedUser(client.userId, publicKey, null)) } } @@ -694,6 +679,7 @@ class EncryptionUtilsV2 { val newMetadata = migrateV1ToV2( v1, userId, + user, cert, folder, storageManager @@ -723,6 +709,7 @@ class EncryptionUtilsV2 { fun migrateV1ToV2( v1: DecryptedFolderMetadataFileV1, userId: String, + user: User, cert: String, folder: OCFile, storageManager: FileDataStorageManager @@ -762,7 +749,7 @@ class EncryptionUtilsV2 { // TODO val filedrop = mutableMapOf() - val newMetadata = DecryptedFolderMetadataFile(metadataV2, users, filedrop) + val newMetadata = DecryptedFolderMetadataFile(metadataV2, users, filedrop, storageManager.getE2EEVersion(user)) val metadataKey = EncryptionUtils.generateKey() ?: throw UploadException("Could not encrypt folder!") newMetadata.metadata.metadataKey = metadataKey @@ -1003,12 +990,12 @@ class EncryptionUtilsV2 { return EncryptionUtils.encodeBytesToBase64String(ans) } - fun createDecryptedFolderMetadataFile(): DecryptedFolderMetadataFile { + fun createDecryptedFolderMetadataFile(e2eeVersion: String): DecryptedFolderMetadataFile { val metadata = DecryptedMetadata().apply { keyChecksums.add(hashMetadataKey(metadataKey)) } - return DecryptedFolderMetadataFile(metadata) + return DecryptedFolderMetadataFile(metadata, mutableListOf(), hashMapOf(), e2eeVersion) } fun hashMetadataKey(metadataKey: ByteArray): String = MessageDigest