Skip to content

Commit

Permalink
Merge pull request #13254 from nextcloud/bugfix/e2e-file-conflict-dup…
Browse files Browse the repository at this point in the history
…licated-files

Bug-Fix E2E File Conflict Duplicated Files
  • Loading branch information
AndyScherzinger committed Jul 12, 2024
2 parents 94f962f + d9a24d6 commit 666a418
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,25 @@ import com.nextcloud.client.jobs.upload.FileUploadWorker.Companion.currentUpload
import com.nextcloud.client.network.Connectivity
import com.nextcloud.client.network.ConnectivityService
import com.owncloud.android.MainApp
import com.owncloud.android.datamodel.FileDataStorageManager
import com.owncloud.android.datamodel.OCFile
import com.owncloud.android.datamodel.UploadsStorageManager
import com.owncloud.android.datamodel.UploadsStorageManager.UploadStatus
import com.owncloud.android.db.OCUpload
import com.owncloud.android.db.UploadResult
import com.owncloud.android.files.services.NameCollisionPolicy
import com.owncloud.android.lib.common.OwnCloudClient
import com.owncloud.android.lib.common.network.OnDatatransferProgressListener
import com.owncloud.android.lib.common.operations.RemoteOperationResult
import com.owncloud.android.lib.common.utils.Log_OC
import com.owncloud.android.lib.resources.files.ReadFileRemoteOperation
import com.owncloud.android.lib.resources.files.model.RemoteFile
import com.owncloud.android.operations.RemoveFileOperation
import com.owncloud.android.operations.UploadFileOperation
import com.owncloud.android.utils.FileUtil
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.io.File
import java.util.concurrent.Semaphore
import javax.inject.Inject
Expand All @@ -48,6 +54,9 @@ class FileUploadHelper {
@Inject
lateinit var uploadsStorageManager: UploadsStorageManager

@Inject
lateinit var fileStorageManager: FileDataStorageManager

init {
MainApp.getAppComponent().inject(this)
}
Expand Down Expand Up @@ -349,6 +358,41 @@ class FileUploadHelper {
backgroundJobManager.startFilesUploadJob(user)
}

/**
* Removes any existing file in the same directory that has the same name as the provided new file.
*
* This function checks the parent directory of the given `newFile` for any file with the same name.
* If such a file is found, it is removed using the `RemoveFileOperation`.
*
* @param duplicatedFile File to be deleted
* @param client Needed for executing RemoveFileOperation
* @param user Needed for creating client
*/
fun removeDuplicatedFile(duplicatedFile: OCFile, client: OwnCloudClient, user: User, onCompleted: () -> Unit) {
val job = CoroutineScope(Dispatchers.IO)

job.launch {
val removeFileOperation = RemoveFileOperation(
duplicatedFile,
false,
user,
true,
MainApp.getAppContext(),
fileStorageManager
)

val result = removeFileOperation.execute(client)

if (result.isSuccess) {
Log_OC.d(TAG, "Replaced file successfully removed")

launch(Dispatchers.Main) {
onCompleted()
}
}
}
}

fun retryUpload(upload: OCUpload, user: User) {
Log_OC.d(this, "retry upload")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import com.owncloud.android.lib.resources.files.model.GeoLocation;
import com.owncloud.android.lib.resources.files.model.ImageDimension;
import com.owncloud.android.lib.resources.files.model.RemoteFile;
import com.owncloud.android.lib.resources.files.model.ServerFileInterface;
import com.owncloud.android.lib.resources.shares.OCShare;
import com.owncloud.android.lib.resources.shares.ShareType;
import com.owncloud.android.lib.resources.shares.ShareeUser;
Expand Down Expand Up @@ -228,6 +229,23 @@ public List<OCFile> getFolderContent(OCFile ocFile, boolean onlyOnDevice) {
}
}

public OCFile findDuplicatedFile(OCFile parentFolder, ServerFileInterface newFile) {
List<OCFile> folderContent = getFolderContent(parentFolder, false);
if (folderContent == null || folderContent.isEmpty()) {
return null;
}

OCFile duplicatedFile = null;
for (OCFile file : folderContent) {
if (file.getFileName().equals(newFile.getFileName())) {
duplicatedFile = file;
break;
}
}

return duplicatedFile;
}

public List<OCFile> getFolderImages(OCFile folder, boolean onlyOnDevice) {
List<OCFile> imageList = new ArrayList<>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import com.nextcloud.client.account.User;
import com.nextcloud.client.device.BatteryStatus;
import com.nextcloud.client.device.PowerManagementService;
import com.nextcloud.client.jobs.upload.FileUploadHelper;
import com.nextcloud.client.jobs.upload.FileUploadWorker;
import com.nextcloud.client.network.Connectivity;
import com.nextcloud.client.network.ConnectivityService;
Expand Down Expand Up @@ -162,6 +163,7 @@ public class UploadFileOperation extends SyncOperation {
private final PowerManagementService powerManagementService;

private boolean encryptedAncestor;
private OCFile duplicatedEncryptedFile;

public static OCFile obtainNewOCFileToUpload(String remotePath, String localPath, String mimeType) {
OCFile newFile = new OCFile(remotePath);
Expand Down Expand Up @@ -492,7 +494,7 @@ private RemoteOperationResult encryptedUpload(OwnCloudClient client, OCFile pare

List<String> fileNames = getCollidedFileNames(object);

RemoteOperationResult collisionResult = checkNameCollision(client, fileNames, parentFile.isEncrypted());
RemoteOperationResult collisionResult = checkNameCollision(parentFile, client, fileNames, parentFile.isEncrypted());
if (collisionResult != null) {
result = collisionResult;
return collisionResult;
Expand Down Expand Up @@ -849,9 +851,16 @@ private void completeE2EUpload(RemoteOperationResult result, E2EFiles e2eFiles,
e2eFiles.deleteTemporalFile();
}

private void deleteDuplicatedFileAndSendRefreshFolderEvent(OwnCloudClient client) {
FileUploadHelper.Companion.instance().removeDuplicatedFile(duplicatedEncryptedFile, client, user, () -> {
duplicatedEncryptedFile = null;
sendRefreshFolderEventBroadcast();
return null;
});
}

private RemoteOperationResult cleanupE2EUpload(FileLock fileLock, E2EFiles e2eFiles, RemoteOperationResult result, Object object, OwnCloudClient client, String token) {
mUploadStarted.set(false);
sendRefreshFolderEventBroadcast();

if (fileLock != null) {
try {
Expand Down Expand Up @@ -881,6 +890,16 @@ private RemoteOperationResult cleanupE2EUpload(FileLock fileLock, E2EFiles e2eFi
result = unlockFolderResult;
}

if (unlockFolderResult != null && unlockFolderResult.isSuccess()) {
Log_OC.d(TAG, "Folder successfully unlocked: " + e2eFiles.getParentFile().getFileName());

if (duplicatedEncryptedFile != null) {
deleteDuplicatedFileAndSendRefreshFolderEvent(client);
} else {
sendRefreshFolderEventBroadcast();
}
}

e2eFiles.deleteEncryptedTempFile();

return result;
Expand Down Expand Up @@ -948,7 +967,7 @@ private RemoteOperationResult normalUpload(OwnCloudClient client) {
}

// check name collision
RemoteOperationResult collisionResult = checkNameCollision(client, null, false);
RemoteOperationResult collisionResult = checkNameCollision(null, client, null, false);
if (collisionResult != null) {
result = collisionResult;
return collisionResult;
Expand Down Expand Up @@ -1135,7 +1154,8 @@ private RemoteOperationResult copyFile(File originalFile, String expectedPath) t
}

@CheckResult
private RemoteOperationResult checkNameCollision(OwnCloudClient client,
private RemoteOperationResult checkNameCollision(OCFile parentFile,
OwnCloudClient client,
List<String> fileNames,
boolean encrypted)
throws OperationCancelledException {
Expand All @@ -1156,6 +1176,10 @@ private RemoteOperationResult checkNameCollision(OwnCloudClient client,
}
break;
case OVERWRITE:
if (parentFile != null && encrypted) {
duplicatedEncryptedFile = getStorageManager().findDuplicatedFile(parentFile, mFile);
}

Log_OC.d(TAG, "Overwriting file");
break;
case ASK_USER:
Expand Down

0 comments on commit 666a418

Please sign in to comment.