Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions app/src/main/java/com/nextcloud/utils/e2ee/E2EVersionHelper.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2026 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

package com.nextcloud.utils.e2ee

import com.google.gson.reflect.TypeToken
import com.owncloud.android.datamodel.e2e.v1.encrypted.EncryptedFolderMetadataFileV1
import com.owncloud.android.datamodel.e2e.v2.encrypted.EncryptedFolderMetadataFile
import com.owncloud.android.lib.resources.status.E2EVersion
import com.owncloud.android.lib.resources.status.OCCapability
import com.owncloud.android.utils.EncryptionUtils

object E2EVersionHelper {

fun isV2orAbove(capability: OCCapability): Boolean = isV2orAbove(capability.endToEndEncryptionApiVersion)

fun isV2orAbove(version: E2EVersion): Boolean = version == E2EVersion.V2_0 || version == E2EVersion.V2_1

fun isV1(capability: OCCapability): Boolean = isV1(capability.endToEndEncryptionApiVersion)

fun isV1(version: E2EVersion): Boolean =
version == E2EVersion.V1_0 || version == E2EVersion.V1_1 || version == E2EVersion.V1_2

fun getLatestE2EVersion(isV2: Boolean): E2EVersion = if (isV2) {
E2EVersion.V2_1
} else {
E2EVersion.V1_2
}

fun determineE2EFromVersionString(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
}

fun determineE2EVersion(metadata: String): E2EVersion = runCatching {
val v1 = EncryptionUtils.deserializeJSON<EncryptedFolderMetadataFileV1>(
metadata,
object : TypeToken<EncryptedFolderMetadataFileV1>() {}
)

determineE2EFromVersionString(v1?.metadata?.version.toString()).also {
if (it == E2EVersion.UNKNOWN) {
throw IllegalStateException("Unknown V1 version")
}
}
}.recoverCatching {
val v2 = EncryptionUtils.deserializeJSON<EncryptedFolderMetadataFile>(
metadata,
object : TypeToken<EncryptedFolderMetadataFile>() {}
)

determineE2EFromVersionString(v2.version)
}.getOrDefault(E2EVersion.UNKNOWN)
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
*/
package com.owncloud.android.datamodel.e2e.v2.decrypted

import com.nextcloud.utils.e2ee.E2EVersionHelper

/**
* Decrypted class representation of metadata json of folder metadata.
*/
Expand All @@ -15,5 +17,5 @@ data class DecryptedFolderMetadataFile(
var users: MutableList<DecryptedUser> = mutableListOf(),
@Transient
val filedrop: MutableMap<String, DecryptedFile> = HashMap(),
val version: String = "2.0"
val version: String = E2EVersionHelper.getLatestE2EVersion(true).value
)
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@
*/
package com.owncloud.android.datamodel.e2e.v2.encrypted

import com.nextcloud.utils.e2ee.E2EVersionHelper

/**
* Decrypted class representation of metadata json of folder metadata.
*/
data class EncryptedFolderMetadataFile(
val metadata: EncryptedMetadata,
val users: List<EncryptedUser>,
@Transient val filedrop: MutableMap<String, EncryptedFiledrop>?,
val version: String = "2.0"
val version: String = E2EVersionHelper.getLatestE2EVersion(true).value
)
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import android.util.Pair;

import com.nextcloud.client.account.User;
import com.nextcloud.utils.e2ee.E2EVersionHelper;
import com.owncloud.android.datamodel.ArbitraryDataProvider;
import com.owncloud.android.datamodel.ArbitraryDataProviderImpl;
import com.owncloud.android.datamodel.FileDataStorageManager;
Expand Down Expand Up @@ -96,15 +97,15 @@ protected RemoteOperationResult run(OwnCloudClient client) {
boolean encryptedAncestor = FileStorageUtils.checkEncryptionStatus(parent, getStorageManager());

if (encryptedAncestor) {
E2EVersion e2EVersion = getStorageManager().getCapability(user).getEndToEndEncryptionApiVersion();
if (e2EVersion == E2EVersion.V1_0 ||
e2EVersion == E2EVersion.V1_1 ||
e2EVersion == E2EVersion.V1_2) {
return encryptedCreateV1(parent, client);
} else if (e2EVersion == E2EVersion.V2_0) {
final var capability = getStorageManager().getCapability(user);

if (E2EVersionHelper.INSTANCE.isV2orAbove(capability)) {
return encryptedCreateV2(parent, client);
} else if (E2EVersionHelper.INSTANCE.isV1(capability)) {
return encryptedCreateV1(parent, client);
}
return new RemoteOperationResult(new IllegalStateException("E2E not supported"));

return new RemoteOperationResult<>(new IllegalStateException("E2E not supported"));
} else {
return normalCreate(client);
}
Expand Down Expand Up @@ -174,7 +175,7 @@ private RemoteOperationResult encryptedCreateV1(OCFile parent, OwnCloudClient cl
token,
client,
metadataExists,
E2EVersion.V1_2,
E2EVersionHelper.INSTANCE.getLatestE2EVersion(false),
"",
arbitraryDataProvider,
user);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import com.nextcloud.android.lib.resources.directediting.DirectEditingObtainRemoteOperation;
import com.nextcloud.client.account.User;
import com.nextcloud.common.NextcloudClient;
import com.nextcloud.utils.e2ee.E2EVersionHelper;
import com.nextcloud.utils.extensions.StringExtensionsKt;
import com.owncloud.android.datamodel.ArbitraryDataProvider;
import com.owncloud.android.datamodel.ArbitraryDataProviderImpl;
Expand Down Expand Up @@ -538,7 +539,9 @@ private void synchronizeData(List<Object> folderAndFiles) {
mContext);
}

if (CapabilityUtils.getCapability(mContext).getEndToEndEncryptionApiVersion().compareTo(E2EVersion.V2_0) >= 0) {
final var capability = CapabilityUtils.getCapability(mContext);

if (E2EVersionHelper.INSTANCE.isV2orAbove(capability)) {
if (encryptedAncestor && object == null) {
throw new IllegalStateException("metadata is null!");
}
Expand All @@ -548,10 +551,10 @@ private void synchronizeData(List<Object> folderAndFiles) {
Map<String, OCFile> localFilesMap;
E2EVersion e2EVersion;
if (object instanceof DecryptedFolderMetadataFileV1 metadataFileV1) {
e2EVersion = E2EVersion.V1_2;
e2EVersion = E2EVersionHelper.INSTANCE.getLatestE2EVersion(false);
localFilesMap = prefillLocalFilesMap(metadataFileV1, fileDataStorageManager.getFolderContent(mLocalFolder, false));
} else {
e2EVersion = E2EVersion.V2_0;
e2EVersion = E2EVersionHelper.INSTANCE.getLatestE2EVersion(true);
localFilesMap = prefillLocalFilesMap(object, fileDataStorageManager.getFolderContent(mLocalFolder, false));

// update counter
Expand Down Expand Up @@ -598,7 +601,7 @@ private void synchronizeData(List<Object> folderAndFiles) {
FileStorageUtils.searchForLocalFileInDefaultPath(updatedFile, user.getAccountName());

// update file name for encrypted files
if (e2EVersion == E2EVersion.V1_2) {
if (e2EVersion == E2EVersionHelper.INSTANCE.getLatestE2EVersion(false)) {
updateFileNameForEncryptedFileV1(fileDataStorageManager,
(DecryptedFolderMetadataFileV1) object,
updatedFile);
Expand All @@ -621,7 +624,7 @@ private void synchronizeData(List<Object> folderAndFiles) {

// save updated contents in local database
// update file name for encrypted files
if (e2EVersion == E2EVersion.V1_2) {
if (e2EVersion == E2EVersionHelper.INSTANCE.getLatestE2EVersion(false)) {
updateFileNameForEncryptedFileV1(fileDataStorageManager,
(DecryptedFolderMetadataFileV1) object,
mLocalFolder);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import android.content.Context
import androidx.core.util.component1
import androidx.core.util.component2
import com.nextcloud.client.account.User
import com.nextcloud.utils.e2ee.E2EVersionHelper
import com.owncloud.android.datamodel.ArbitraryDataProvider
import com.owncloud.android.datamodel.ArbitraryDataProviderImpl
import com.owncloud.android.datamodel.FileDataStorageManager
Expand All @@ -19,7 +20,6 @@ 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
Expand Down Expand Up @@ -55,8 +55,8 @@ class RemoveRemoteEncryptedFileOperation internal constructor(
var result: RemoteOperationResult<Void>
var delete: DeleteMethod? = null
var token: String? = null
val e2eVersion = CapabilityUtils.getCapability(context).endToEndEncryptionApiVersion
val isE2EVersionAtLeast2 = e2eVersion >= E2EVersion.V2_0
val capability = CapabilityUtils.getCapability(context)
val isE2EVersionAtLeast2 = (E2EVersionHelper.isV2orAbove(capability))

try {
token = EncryptionUtils.lockFolder(parentFolder, client)
Expand Down Expand Up @@ -149,7 +149,7 @@ class RemoveRemoteEncryptedFileOperation internal constructor(
token,
client,
metadataExists,
E2EVersion.V1_2,
E2EVersionHelper.getLatestE2EVersion(false),
"",
arbitraryDataProvider,
user
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.nextcloud.client.network.Connectivity;
import com.nextcloud.client.network.ConnectivityService;
import com.nextcloud.utils.autoRename.AutoRename;
import com.nextcloud.utils.e2ee.E2EVersionHelper;
import com.owncloud.android.datamodel.ArbitraryDataProvider;
import com.owncloud.android.datamodel.ArbitraryDataProviderImpl;
import com.owncloud.android.datamodel.FileDataStorageManager;
Expand Down Expand Up @@ -51,7 +52,6 @@
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;
Expand Down Expand Up @@ -585,11 +585,8 @@ private RemoteOperationResult encryptedUpload(OwnCloudClient client, OCFile pare
}

private boolean isEndToEndVersionAtLeastV2() {
return getE2EVersion().compareTo(E2EVersion.V2_0) >= 0;
}

private E2EVersion getE2EVersion() {
return CapabilityUtils.getCapability(mContext).getEndToEndEncryptionApiVersion();
final var capability = CapabilityUtils.getCapability(mContext);
return E2EVersionHelper.INSTANCE.isV2orAbove(capability);
}

private long getE2ECounter(OCFile parentFile) {
Expand Down Expand Up @@ -854,7 +851,7 @@ private void updateMetadataForV1(DecryptedFolderMetadataFileV1 metadata, E2EData
clientData.getToken(),
clientData.getClient(),
metadataExists,
E2EVersion.V1_2,
E2EVersionHelper.INSTANCE.getLatestE2EVersion(false),
"",
arbitraryDataProvider,
user);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
import com.nextcloud.ui.fileactions.FileActionsBottomSheet;
import com.nextcloud.utils.EditorUtils;
import com.nextcloud.utils.ShortcutUtil;
import com.nextcloud.utils.e2ee.E2EVersionHelper;
import com.nextcloud.utils.extensions.BundleExtensionsKt;
import com.nextcloud.utils.extensions.FileExtensionsKt;
import com.nextcloud.utils.extensions.FragmentExtensionsKt;
Expand Down Expand Up @@ -1953,8 +1954,7 @@ private void encryptFolder(OCFile folder,
String token = EncryptionUtils.lockFolder(folder, client);

OCCapability ocCapability = mContainerActivity.getStorageManager().getCapability(user.getAccountName());

if (ocCapability.getEndToEndEncryptionApiVersion() == E2EVersion.V2_0) {
if (E2EVersionHelper.INSTANCE.isV2orAbove(ocCapability)) {
// Update metadata
Pair<Boolean, DecryptedFolderMetadataFile> metadataPair = EncryptionUtils.retrieveMetadata(folder,
client,
Expand All @@ -1980,10 +1980,8 @@ private void encryptFolder(OCFile folder,
// unlock folder
EncryptionUtils.unlockFolder(folder, client, token);

} else if (ocCapability.getEndToEndEncryptionApiVersion() == E2EVersion.V1_0 ||
ocCapability.getEndToEndEncryptionApiVersion() == E2EVersion.V1_1 ||
ocCapability.getEndToEndEncryptionApiVersion() == E2EVersion.V1_2
) {

} else if (E2EVersionHelper.INSTANCE.isV1(ocCapability)) {
// unlock folder
EncryptionUtils.unlockFolderV1(folder, client, token);
} else if (ocCapability.getEndToEndEncryptionApiVersion() == E2EVersion.UNKNOWN) {
Expand Down
Loading
Loading