Skip to content
Open
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import com.owncloud.android.lib.resources.files.model.RemoteFile
import com.owncloud.android.lib.resources.shares.OCShare
import com.owncloud.android.lib.resources.status.OCCapability
import com.owncloud.android.utils.FileStorageUtils
import com.owncloud.android.utils.MimeType
import com.owncloud.android.utils.MimeTypeUtil
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
Expand Down Expand Up @@ -185,6 +186,36 @@ fun FileDataStorageManager.moveFiles(ocFile: OCFile?, targetPath: String, target
}
}

fun FileDataStorageManager.createDirectoryTree(remotePath: String, createdRemoteFolder: RemoteFile?) {
if (getFileByEncryptedRemotePath(FileStorageUtils.getParentPath(remotePath)) == null) {
// When parent of remote path is not created
val subFolders = remotePath.split(OCFile.PATH_SEPARATOR.toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
var composedRemotePath = OCFile.ROOT_PATH

// For each ancestor folders create them recursively
for (subFolder in subFolders) {
if (subFolder.isNotEmpty()) {
composedRemotePath = composedRemotePath + subFolder + OCFile.PATH_SEPARATOR
createDirectoryTree(composedRemotePath, createdRemoteFolder)
}
}
} else {
// Create directory on DB
with(OCFile(remotePath)) {
mimeType = MimeType.DIRECTORY
val parentId: Long = getFileByEncryptedRemotePath(FileStorageUtils.getParentPath(remotePath)).getFileId()
setParentId(parentId)
remoteId = createdRemoteFolder?.remoteId
modificationTimestamp = System.currentTimeMillis()
isEncrypted = FileStorageUtils.checkEncryptionStatus(this, this@createDirectoryTree)
permissions = createdRemoteFolder?.permissions
saveFile(this)
}

Log_OC.d(FileDataStorageManager.TAG, "createDirectoryTree: created $remotePath in Database")
}
}

@Suppress("ReturnCount")
private fun moveLocalFiles(accountName: String, ocFile: OCFile, defaultSavePath: String, targetPath: String): Boolean {
val localFile = File(FileStorageUtils.getDefaultSavePathFor(accountName, ocFile))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import com.nextcloud.client.account.User;
import com.nextcloud.utils.e2ee.E2ECounterHelper;
import com.nextcloud.utils.e2ee.E2EVersionHelper;
import com.nextcloud.utils.extensions.FileDataStorageManagerExtensionsKt;
import com.nextcloud.utils.extensions.OCFileExtensionsKt;
import com.owncloud.android.datamodel.ArbitraryDataProvider;
import com.owncloud.android.datamodel.ArbitraryDataProviderImpl;
Expand Down Expand Up @@ -552,33 +553,7 @@ private void onCreateRemoteFolderOperationFinish(RemoteOperationResult result) {
* Save new directory in local database.
*/
private void saveFolderInDB() {
if (getStorageManager().getFileByPath(FileStorageUtils.getParentPath(remotePath)) == null) {
// When parent of remote path is not created
String[] subFolders = remotePath.split(PATH_SEPARATOR);
String composedRemotePath = ROOT_PATH;

// For each ancestor folders create them recursively
for (String subFolder : subFolders) {
if (!subFolder.isEmpty()) {
composedRemotePath = composedRemotePath + subFolder + PATH_SEPARATOR;
remotePath = composedRemotePath;
saveFolderInDB();
}
}
} else {
// Create directory on DB
OCFile newDir = new OCFile(remotePath);
newDir.setMimeType(MimeType.DIRECTORY);
long parentId = getStorageManager().getFileByPath(FileStorageUtils.getParentPath(remotePath)).getFileId();
newDir.setParentId(parentId);
newDir.setRemoteId(createdRemoteFolder.getRemoteId());
newDir.setModificationTimestamp(System.currentTimeMillis());
newDir.setEncrypted(FileStorageUtils.checkEncryptionStatus(newDir, getStorageManager()));
newDir.setPermissions(createdRemoteFolder.getPermissions());
getStorageManager().saveFile(newDir);

Log_OC.d(TAG, "Create directory " + remotePath + " in Database");
}
FileDataStorageManagerExtensionsKt.createDirectoryTree(getStorageManager(), remotePath, createdRemoteFolder);
}

public String getRemotePath() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.nextcloud.utils.autoRename.AutoRename;
import com.nextcloud.utils.e2ee.E2ECounterHelper;
import com.nextcloud.utils.e2ee.E2EVersionHelper;
import com.nextcloud.utils.extensions.FileDataStorageManagerExtensionsKt;
import com.nextcloud.utils.extensions.RemoteOperationResultExtensionsKt;
import com.owncloud.android.datamodel.ArbitraryDataProvider;
import com.owncloud.android.datamodel.ArbitraryDataProviderImpl;
Expand Down Expand Up @@ -55,6 +56,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.NextcloudVersion;
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 @@ -474,45 +476,58 @@ protected RemoteOperationResult run(OwnCloudClient client) {
Log_OC.d(TAG, "parent lookup for path: " + remoteParentPath + " โ†’ " +
(parent == null ? "not found in DB" : "found, id=" + parent.getFileId()));

final boolean isResumingEncryptedUpload = (mFolderUnlockToken != null && !mFolderUnlockToken.isEmpty());
if (!isResumingEncryptedUpload && (parent == null || mRemoteFolderToBeCreated)) {
Log_OC.d(TAG, "verifying remote parent folder exists: " + remoteParentPath);
final var result = grantFolderExistence(remoteParentPath, client);

if (!result.isSuccess()) {
Log_OC.e(TAG, "grantFolderExistence failed for: " + remoteParentPath + ", code: " +
result.getCode() + ", message: " + result.getMessage());
return result;
// Create folders only for Nextcloud < 32; 32+ handles this automatically.
if (getCapabilities().getVersion().isOlderThan(NextcloudVersion.nextcloud_32)) {
final boolean isResumingEncryptedUpload = (mFolderUnlockToken != null && !mFolderUnlockToken.isEmpty());
if (!isResumingEncryptedUpload && (parent == null || mRemoteFolderToBeCreated)) {
Log_OC.d(TAG, "verifying remote parent folder exists: " + remoteParentPath);
final var result = grantFolderExistence(remoteParentPath, client);
Comment thread
daniele-verducci marked this conversation as resolved.

if (!result.isSuccess()) {
Log_OC.e(TAG, "grantFolderExistence failed for: " + remoteParentPath + ", code: " +
result.getCode() + ", message: " + result.getMessage());
return result;
}

parent = getStorageManager().getFileByPath(remoteParentPath);
if (parent == null) {
Log_OC.e(TAG, "parent still null after grantFolderExistence: " + remoteParentPath);
return new RemoteOperationResult<>(ResultCode.UNKNOWN_ERROR);
}

Log_OC.d(TAG, "remote parent folder confirmed: " + remoteParentPath + ", id=" + parent.getFileId());
}

parent = getStorageManager().getFileByPath(remoteParentPath);
if (parent == null) {
Log_OC.e(TAG, "parent still null after grantFolderExistence: " + remoteParentPath);
return new RemoteOperationResult<>(ResultCode.UNKNOWN_ERROR);
Log_OC.e(TAG, "parent is null, cannot proceed: " + remoteParentPath + "," + " unlock token: " + mFolderUnlockToken);
return new RemoteOperationResult<>(false, "Parent folder not found", HttpStatus.SC_NOT_FOUND);
}

Log_OC.d(TAG, "remote parent folder confirmed: " + remoteParentPath + ", id=" + parent.getFileId());
}

if (parent == null) {
Log_OC.e(TAG, "parent is null, cannot proceed: " + remoteParentPath + "," + " unlock token: " + mFolderUnlockToken);
return new RemoteOperationResult<>(false, "Parent folder not found", HttpStatus.SC_NOT_FOUND);
}

// - resume of encrypted upload, then parent file exists already as unlock is only for direct parent
mFile.setParentId(parent.getFileId());

// check if any parent is encrypted
encryptedAncestor = FileStorageUtils.checkEncryptionStatus(parent, getStorageManager());
mFile.setEncrypted(encryptedAncestor);
if (encryptedAncestor && parent != null) {
// - resume of encrypted upload, then parent file exists already as unlock is only for direct parent
mFile.setParentId(parent.getFileId());
}

RemoteOperationResult result;
if (encryptedAncestor) {
Log_OC.d(TAG, "โฌ†๏ธ๐Ÿ”—" + "encrypted upload");
return encryptedUpload(client, parent);
result = encryptedUpload(client, parent);
} else {
Log_OC.d(TAG, "โฌ†๏ธ" + "normal upload");
return normalUpload(client);
result = normalUpload(client);
}

if (result.isSuccess() && getCapabilities().getVersion().isNewerOrEqual(NextcloudVersion.nextcloud_32)) {
// Add the folders that the server creates automatically (from Nextcloud 32) to local db
FileDataStorageManagerExtensionsKt.createDirectoryTree(getStorageManager(), remoteParentPath, null);
}

return result;
}

// region E2E Upload
Expand Down
Loading