diff --git a/library/src/androidTest/java/com/nextcloud/android/lib/resources/users/GenerateAppPasswordRemoteOperationIT.java b/library/src/androidTest/java/com/nextcloud/android/lib/resources/users/GenerateAppPasswordRemoteOperationIT.java index 685002ec7..a4f422432 100644 --- a/library/src/androidTest/java/com/nextcloud/android/lib/resources/users/GenerateAppPasswordRemoteOperationIT.java +++ b/library/src/androidTest/java/com/nextcloud/android/lib/resources/users/GenerateAppPasswordRemoteOperationIT.java @@ -17,7 +17,7 @@ import com.owncloud.android.lib.common.OwnCloudBasicCredentials; import com.owncloud.android.lib.common.OwnCloudCredentials; import com.owncloud.android.lib.common.operations.RemoteOperationResult; -import com.owncloud.android.lib.resources.files.ReadFolderRemoteOperation; +import com.owncloud.android.lib.resources.files.ReadFileRemoteOperation; import org.junit.Test; @@ -42,7 +42,7 @@ public void generateAppPassword() { client.setCredentials(newOwnCloudCredentials); - assertTrue(new ReadFolderRemoteOperation("/").execute(client).isSuccess()); + assertTrue(new ReadFileRemoteOperation("/").execute(client).isSuccess()); // using app password to generate new password should fail assertFalse(new GenerateAppPasswordRemoteOperation().execute(client).isSuccess()); diff --git a/library/src/androidTest/java/com/owncloud/android/AbstractIT.java b/library/src/androidTest/java/com/owncloud/android/AbstractIT.java index 59a163689..891b60b72 100644 --- a/library/src/androidTest/java/com/owncloud/android/AbstractIT.java +++ b/library/src/androidTest/java/com/owncloud/android/AbstractIT.java @@ -72,6 +72,7 @@ public abstract class AbstractIT { public static OwnCloudClient client; public static OwnCloudClient client2; protected static NextcloudClient nextcloudClient; + protected static NextcloudClient nextcloudClient2; protected static Context context; protected static Uri url; @@ -112,6 +113,9 @@ public static void beforeAll() throws InterruptedException, String credentials = Credentials.basic(loginName, password); nextcloudClient = new NextcloudClient(url, userId, credentials, context); + String credentials2 = Credentials.basic(loginName2, password2); + nextcloudClient2 = new NextcloudClient(url, loginName2, credentials2, context); + waitForServer(client, url); testConnection(); } @@ -262,20 +266,15 @@ public static File extractAsset(String fileName, Context context) throws IOExcep @After public void after() { - removeOnClient(client); - removeOnClient(client2); + removeOnClient(nextcloudClient); + removeOnClient(nextcloudClient2); } - private void removeOnClient(OwnCloudClient client) { - final var result = new ReadFolderRemoteOperation("/").execute(client); + private void removeOnClient(NextcloudClient nextcloudClient) { + final var result = new ReadFolderRemoteOperation("/").execute(nextcloudClient); assertTrue(result.getLogMessage(context), result.isSuccess()); - for (Object object : result.getData()) { - if (!(object instanceof RemoteFile remoteFile)) { - Log_OC.d(TAG, "Skipping removeOnClient: not instance of RemoteFile"); - continue; - } - + for (RemoteFile remoteFile : result.getResultData()) { String remotePath = remoteFile.getRemotePath(); if ("/".equals(remotePath) || remoteFile.getMountType() == WebdavEntry.MountType.GROUP) { @@ -284,7 +283,7 @@ private void removeOnClient(OwnCloudClient client) { } if (remoteFile.isEncrypted()) { - assertTrue(toggleEncryptionRemoteFile(remoteFile)); + assertTrue(toggleEncryptionRemoteFile(remoteFile, nextcloudClient)); } if (remoteFile.isLocked() && remotePath != null) { @@ -299,9 +298,9 @@ private void removeOnClient(OwnCloudClient client) { Log_OC.d(TAG, "KeyStore file deletion result: " + isKeyStoreDeleted); } - private boolean toggleEncryptionRemoteFile(RemoteFile remoteFile) { + private boolean toggleEncryptionRemoteFile(RemoteFile remoteFile, NextcloudClient nextcloudClient) { final var operation = new ToggleEncryptionRemoteOperation(remoteFile.getLocalId(), remoteFile.getRemotePath(), false); - final var result = operation.execute(client); + final var result = operation.execute(nextcloudClient); return result.isSuccess(); } diff --git a/library/src/androidTest/java/com/owncloud/android/FileIT.java b/library/src/androidTest/java/com/owncloud/android/FileIT.java index a3e87e196..90c4be075 100644 --- a/library/src/androidTest/java/com/owncloud/android/FileIT.java +++ b/library/src/androidTest/java/com/owncloud/android/FileIT.java @@ -13,7 +13,6 @@ import android.net.Uri; -import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.resources.files.CreateFolderRemoteOperation; import com.owncloud.android.lib.resources.files.ReadFolderRemoteOperation; import com.owncloud.android.lib.resources.files.RemoveFileRemoteOperation; @@ -43,7 +42,7 @@ public void testCreateFolderSuccess() { assertTrue(new CreateFolderRemoteOperation(path, true).execute(client).isSuccess()); // verify folder - assertTrue(new ReadFolderRemoteOperation(path).execute(client).isSuccess()); + assertTrue(new ReadFolderRemoteOperation(path).execute(nextcloudClient).isSuccess()); // remove folder assertTrue(new RemoveFileRemoteOperation(path).execute(client).isSuccess()); @@ -71,7 +70,7 @@ public void testCreateNonExistingSubFolder() { assertTrue(new CreateFolderRemoteOperation(path, true).execute(client).isSuccess()); // verify folder - assertTrue(new ReadFolderRemoteOperation(path).execute(client).isSuccess()); + assertTrue(new ReadFolderRemoteOperation(path).execute(nextcloudClient).isSuccess()); // remove folder assertTrue(new RemoveFileRemoteOperation(top).execute(client).isSuccess()); @@ -94,17 +93,17 @@ public void testZeroSharees() { // create & verify folder String path = "/testFolder/"; assertTrue(new CreateFolderRemoteOperation(path, true).execute(client).isSuccess()); - assertTrue(new ReadFolderRemoteOperation(path).execute(client).isSuccess()); + assertTrue(new ReadFolderRemoteOperation(path).execute(nextcloudClient).isSuccess()); // verify - RemoteOperationResult result = new ReadFolderRemoteOperation("/").execute(client); + var result = new ReadFolderRemoteOperation("/").execute(nextcloudClient); assertTrue(result.isSuccess()); - RemoteFile parentFolder = (RemoteFile) result.getData().get(0); + RemoteFile parentFolder = result.getResultData().get(0); assertEquals("/", parentFolder.getRemotePath()); - for (int i = 1; i < result.getData().size(); i++) { - RemoteFile child = (RemoteFile) result.getData().get(i); + for (int i = 1; i < result.getResultData().size(); i++) { + RemoteFile child = result.getResultData().get(i); if (path.equals(child.getRemotePath())) { assertEquals(0, child.getSharees().length); @@ -117,7 +116,7 @@ public void testShareViaLinkSharees() { // create & verify folder String path = "/testFolder/"; assertTrue(new CreateFolderRemoteOperation(path, true).execute(client).isSuccess()); - assertTrue(new ReadFolderRemoteOperation(path).execute(client).isSuccess()); + assertTrue(new ReadFolderRemoteOperation(path).execute(nextcloudClient).isSuccess()); // share folder assertTrue(new CreateShareRemoteOperation(path, @@ -129,16 +128,14 @@ public void testShareViaLinkSharees() { .execute(client).isSuccess()); // verify - final var result = new ReadFolderRemoteOperation("/").execute(client); + final var result = new ReadFolderRemoteOperation("/").execute(nextcloudClient); assertTrue(result.isSuccess()); - RemoteFile parentFolder = (RemoteFile) result.getData().get(0); + RemoteFile parentFolder = result.getResultData().get(0); assertEquals("/", parentFolder.getRemotePath()); - for (Object item : result.getData()) { - if (item instanceof RemoteFile child && - path.equals(child.getRemotePath()) && - child.getSharees() != null) { + for (RemoteFile child : result.getResultData()) { + if (path.equals(child.getRemotePath()) && child.getSharees() != null) { assertEquals(1, child.getSharees().length); } } @@ -149,7 +146,7 @@ public void testShareToGroupSharees() { // create & verify folder String path = "/testFolder/"; assertTrue(new CreateFolderRemoteOperation(path, true).execute(client).isSuccess()); - assertTrue(new ReadFolderRemoteOperation(path).execute(client).isSuccess()); + assertTrue(new ReadFolderRemoteOperation(path).execute(nextcloudClient).isSuccess()); ShareeUser sharee = new ShareeUser("users", "", ShareType.GROUP); @@ -169,14 +166,14 @@ public void testShareToGroupSharees() { .execute(client).isSuccess()); // verify - RemoteOperationResult result = new ReadFolderRemoteOperation("/").execute(client); + var result = new ReadFolderRemoteOperation("/").execute(nextcloudClient); assertTrue(result.isSuccess()); - RemoteFile parentFolder = (RemoteFile) result.getData().get(0); + RemoteFile parentFolder = result.getResultData().get(0); assertEquals("/", parentFolder.getRemotePath()); - for (int i = 1; i < result.getData().size(); i++) { - RemoteFile child = (RemoteFile) result.getData().get(i); + for (int i = 1; i < result.getResultData().size(); i++) { + RemoteFile child = result.getResultData().get(i); if (path.equals(child.getRemotePath())) { assertEquals(1, child.getSharees().length); @@ -190,7 +187,7 @@ public void testOneSharees() { // create & verify folder String path = "/testFolder/"; assertTrue(new CreateFolderRemoteOperation(path, true).execute(client).isSuccess()); - assertTrue(new ReadFolderRemoteOperation(path).execute(client).isSuccess()); + assertTrue(new ReadFolderRemoteOperation(path).execute(nextcloudClient).isSuccess()); ShareeUser sharee = new ShareeUser("user1", "User One", ShareType.USER); @@ -204,14 +201,14 @@ public void testOneSharees() { .execute(client).isSuccess()); // verify - RemoteOperationResult result = new ReadFolderRemoteOperation("/").execute(client); + var result = new ReadFolderRemoteOperation("/").execute(nextcloudClient); assertTrue(result.isSuccess()); - RemoteFile parentFolder = (RemoteFile) result.getData().get(0); + RemoteFile parentFolder = result.getResultData().get(0); assertEquals("/", parentFolder.getRemotePath()); - for (int i = 1; i < result.getData().size(); i++) { - RemoteFile child = (RemoteFile) result.getData().get(i); + for (int i = 1; i < result.getResultData().size(); i++) { + RemoteFile child = result.getResultData().get(i); if (path.equals(child.getRemotePath())) { assertEquals(1, child.getSharees().length); @@ -225,7 +222,7 @@ public void testTwoShareesOnParent() { // create & verify folder String path = "/testFolder/"; assertTrue(new CreateFolderRemoteOperation(path, true).execute(client).isSuccess()); - assertTrue(new ReadFolderRemoteOperation(path).execute(client).isSuccess()); + assertTrue(new ReadFolderRemoteOperation(path).execute(nextcloudClient).isSuccess()); List sharees = new ArrayList<>(); sharees.add(new ShareeUser("user1", "User One", ShareType.USER)); @@ -249,14 +246,14 @@ public void testTwoShareesOnParent() { .execute(client).isSuccess()); // verify - RemoteOperationResult result = new ReadFolderRemoteOperation("/").execute(client); + var result = new ReadFolderRemoteOperation("/").execute(nextcloudClient); assertTrue(result.isSuccess()); - RemoteFile parentFolder = (RemoteFile) result.getData().get(0); + RemoteFile parentFolder = result.getResultData().get(0); assertEquals("/", parentFolder.getRemotePath()); - for (int i = 1; i < result.getData().size(); i++) { - RemoteFile child = (RemoteFile) result.getData().get(i); + for (int i = 1; i < result.getResultData().size(); i++) { + RemoteFile child = result.getResultData().get(i); if (path.equals(child.getRemotePath())) { assertEquals(2, child.getSharees().length); @@ -273,7 +270,7 @@ public void testTwoSharees() { // create & verify folder String path = "/testFolder/"; assertTrue(new CreateFolderRemoteOperation(path, true).execute(client).isSuccess()); - assertTrue(new ReadFolderRemoteOperation(path).execute(client).isSuccess()); + assertTrue(new ReadFolderRemoteOperation(path).execute(nextcloudClient).isSuccess()); List sharees = new ArrayList<>(); sharees.add(new ShareeUser("user1", "User One", ShareType.USER)); @@ -297,10 +294,10 @@ public void testTwoSharees() { .execute(client).isSuccess()); // verify - RemoteOperationResult result = new ReadFolderRemoteOperation(path).execute(client); + var result = new ReadFolderRemoteOperation(path).execute(nextcloudClient); assertTrue(result.isSuccess()); - RemoteFile folder = (RemoteFile) result.getData().get(0); + RemoteFile folder = result.getResultData().get(0); assertEquals(path, folder.getRemotePath()); assertEquals(2, folder.getSharees().length); @@ -315,10 +312,10 @@ public void testLocalID() { String path = "/testFolder/"; assertTrue(new CreateFolderRemoteOperation(path, true).execute(client).isSuccess()); - RemoteOperationResult result = new ReadFolderRemoteOperation(path).execute(client); + var result = new ReadFolderRemoteOperation(path).execute(nextcloudClient); assertTrue(result.isSuccess()); - RemoteFile folder = (RemoteFile) result.getData().get(0); + RemoteFile folder = result.getResultData().get(0); // we do this only here for testing, this might not work on large installations int localId = Integer.parseInt(folder.getRemoteId().substring(0, 8).replaceAll("^0*", "")); diff --git a/library/src/androidTest/java/com/owncloud/android/lib/resources/e2ee/UpdateMetadataRemoteOperationIT.kt b/library/src/androidTest/java/com/owncloud/android/lib/resources/e2ee/UpdateMetadataRemoteOperationIT.kt index 855a52bc1..4bace29e4 100644 --- a/library/src/androidTest/java/com/owncloud/android/lib/resources/e2ee/UpdateMetadataRemoteOperationIT.kt +++ b/library/src/androidTest/java/com/owncloud/android/lib/resources/e2ee/UpdateMetadataRemoteOperationIT.kt @@ -44,7 +44,7 @@ class UpdateMetadataRemoteOperationIT : AbstractIT() { remoteFolder!!.localId, remoteFolder.remotePath, true - ).execute(client) + ).execute(nextcloudClient) .isSuccess ) @@ -128,7 +128,7 @@ class UpdateMetadataRemoteOperationIT : AbstractIT() { remoteFolder!!.localId, remoteFolder.remotePath, true - ).execute(client) + ).execute(nextcloudClient) .isSuccess ) diff --git a/library/src/androidTest/java/com/owncloud/android/lib/resources/files/ReadFileRemoteOperationIT.kt b/library/src/androidTest/java/com/owncloud/android/lib/resources/files/ReadFileRemoteOperationIT.kt index 891c9da29..3d0caf9b5 100644 --- a/library/src/androidTest/java/com/owncloud/android/lib/resources/files/ReadFileRemoteOperationIT.kt +++ b/library/src/androidTest/java/com/owncloud/android/lib/resources/files/ReadFileRemoteOperationIT.kt @@ -154,7 +154,7 @@ class ReadFileRemoteOperationIT : AbstractIT() { remoteFile.localId, remotePath, true - ).execute(client) + ).execute(nextcloudClient) .isSuccess ) diff --git a/library/src/androidTest/java/com/owncloud/android/lib/resources/files/ReadFolderRemoteOperationIT.kt b/library/src/androidTest/java/com/owncloud/android/lib/resources/files/ReadFolderRemoteOperationIT.kt index 17b804192..27c90e39d 100644 --- a/library/src/androidTest/java/com/owncloud/android/lib/resources/files/ReadFolderRemoteOperationIT.kt +++ b/library/src/androidTest/java/com/owncloud/android/lib/resources/files/ReadFolderRemoteOperationIT.kt @@ -9,7 +9,6 @@ package com.owncloud.android.lib.resources.files import com.nextcloud.test.RandomStringGenerator import com.owncloud.android.AbstractIT -import com.owncloud.android.lib.resources.files.model.RemoteFile import com.owncloud.android.lib.resources.status.NextcloudVersion import com.owncloud.android.lib.resources.tags.CreateTagRemoteOperation import com.owncloud.android.lib.resources.tags.GetTagsRemoteOperation @@ -37,21 +36,21 @@ class ReadFolderRemoteOperationIT : AbstractIT() { .isSuccess ) - var result = ReadFolderRemoteOperation(remotePath).execute(client) + var result = ReadFolderRemoteOperation(remotePath).execute(nextcloudClient) assertTrue(result.isSuccess) - assertEquals(2, result.data.size) + assertEquals(2, result.resultData.size) // tag testing only on NC27+ testOnlyOnServer(NextcloudVersion.nextcloud_27) // Folder - var remoteFolder = result.data[0] as RemoteFile + var remoteFolder = result.resultData[0] assertEquals(remotePath, remoteFolder.remotePath) assertEquals(0, remoteFolder.tags?.size) // File - var remoteFile = result.data[1] as RemoteFile + var remoteFile = result.resultData[1] assertEquals(remotePath + "1.txt", remoteFile.remotePath) assertEquals(0, remoteFile.tags?.size) @@ -79,18 +78,18 @@ class ReadFolderRemoteOperationIT : AbstractIT() { ) // check again - result = ReadFolderRemoteOperation(remotePath).execute(client) + result = ReadFolderRemoteOperation(remotePath).execute(nextcloudClient) assertTrue(result.isSuccess) - assertEquals(2, result.data.size) + assertEquals(2, result.resultData.size) // Folder - remoteFolder = result.data[0] as RemoteFile + remoteFolder = result.resultData[0] assertEquals(remotePath, remoteFolder.remotePath) assertEquals(0, remoteFolder.tags?.size) // File - remoteFile = result.data[1] as RemoteFile + remoteFile = result.resultData[1] assertEquals(remotePath + "1.txt", remoteFile.remotePath) assertEquals(2, remoteFile.tags?.size) diff --git a/library/src/androidTest/java/com/owncloud/android/lib/resources/files/UploadFileRemoteOperationIT.kt b/library/src/androidTest/java/com/owncloud/android/lib/resources/files/UploadFileRemoteOperationIT.kt index 065674de3..fd92b1b5f 100644 --- a/library/src/androidTest/java/com/owncloud/android/lib/resources/files/UploadFileRemoteOperationIT.kt +++ b/library/src/androidTest/java/com/owncloud/android/lib/resources/files/UploadFileRemoteOperationIT.kt @@ -52,10 +52,10 @@ class UploadFileRemoteOperationIT : AbstractIT() { assertTrue(uploadResult.isSuccess) // ReadFileRemoteOperation - var result = ReadFileRemoteOperation(remotePath).execute(client) - assertTrue(result.isSuccess) + val fileResult = ReadFileRemoteOperation(remotePath).execute(client) + assertTrue(fileResult.isSuccess) - var remoteFile = result.data[0] as RemoteFile + val remoteFile = fileResult.data[0] as RemoteFile assertEquals(remotePath, remoteFile.remotePath) assertEquals(creationTimestamp, remoteFile.creationTimestamp) @@ -66,16 +66,16 @@ class UploadFileRemoteOperationIT : AbstractIT() { ) // ReadFolderRemoteOperation - result = ReadFolderRemoteOperation(remotePath).execute(client) - assertTrue(result.isSuccess) + val folderResult = ReadFolderRemoteOperation(remotePath).execute(nextcloudClient) + assertTrue(folderResult.isSuccess) - remoteFile = result.data[0] as RemoteFile + val folderRemoteFile = folderResult.resultData[0] - assertEquals(remotePath, remoteFile.remotePath) - assertEquals(creationTimestamp, remoteFile.creationTimestamp) + assertEquals(remotePath, folderRemoteFile.remotePath) + assertEquals(creationTimestamp, folderRemoteFile.creationTimestamp) assertTrue( - uploadTimestamp - TIME_OFFSET < remoteFile.uploadTimestamp || - uploadTimestamp + TIME_OFFSET > remoteFile.uploadTimestamp + uploadTimestamp - TIME_OFFSET < folderRemoteFile.uploadTimestamp || + uploadTimestamp + TIME_OFFSET > folderRemoteFile.uploadTimestamp ) } diff --git a/library/src/androidTest/java/com/owncloud/android/lib/resources/tags/DeleteTagRemoteOperationIT.kt b/library/src/androidTest/java/com/owncloud/android/lib/resources/tags/DeleteTagRemoteOperationIT.kt index 673a1b665..c59857d28 100644 --- a/library/src/androidTest/java/com/owncloud/android/lib/resources/tags/DeleteTagRemoteOperationIT.kt +++ b/library/src/androidTest/java/com/owncloud/android/lib/resources/tags/DeleteTagRemoteOperationIT.kt @@ -54,9 +54,9 @@ class DeleteTagRemoteOperationIT : AbstractIT() { ) // verify the tag is on the folder - var rootMetadata = ReadFolderRemoteOperation("/").execute(client) + var rootMetadata = ReadFolderRemoteOperation("/").execute(nextcloudClient) var folderTags = - (rootMetadata.data as ArrayList) + rootMetadata.resultData .find { it.remotePath == folder } ?.tags assertEquals(1, folderTags?.size) @@ -70,9 +70,9 @@ class DeleteTagRemoteOperationIT : AbstractIT() { ) // verify the tag is no longer on the folder - rootMetadata = ReadFolderRemoteOperation("/").execute(client) + rootMetadata = ReadFolderRemoteOperation("/").execute(nextcloudClient) folderTags = - (rootMetadata.data as ArrayList) + rootMetadata.resultData .find { it.remotePath == folder } ?.tags assertTrue(folderTags.isNullOrEmpty()) diff --git a/library/src/androidTest/java/com/owncloud/android/lib/resources/tags/GetTagsRemoteOperationIT.kt b/library/src/androidTest/java/com/owncloud/android/lib/resources/tags/GetTagsRemoteOperationIT.kt index e518a1959..341f21af8 100644 --- a/library/src/androidTest/java/com/owncloud/android/lib/resources/tags/GetTagsRemoteOperationIT.kt +++ b/library/src/androidTest/java/com/owncloud/android/lib/resources/tags/GetTagsRemoteOperationIT.kt @@ -123,9 +123,9 @@ class GetTagsRemoteOperationIT : AbstractIT() { ) // read metadata - val rootMetadata = ReadFolderRemoteOperation("/").execute(client) + val rootMetadata = ReadFolderRemoteOperation("/").execute(nextcloudClient) val tags = - (rootMetadata.data as ArrayList) + rootMetadata.resultData .find { it.remotePath == tagFolder } ?.tags tags?.sortBy { it?.color } diff --git a/library/src/main/java/com/nextcloud/operations/PropfindMethod.kt b/library/src/main/java/com/nextcloud/operations/PropfindMethod.kt new file mode 100644 index 000000000..73270d04d --- /dev/null +++ b/library/src/main/java/com/nextcloud/operations/PropfindMethod.kt @@ -0,0 +1,36 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: MIT + */ +package com.nextcloud.operations + +import com.nextcloud.common.OkHttpMethodBase +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.Request +import okhttp3.RequestBody.Companion.toRequestBody + +/** + * HTTP PROPFIND method that uses OkHttp with new NextcloudClient + */ +class PropfindMethod( + uri: String, + useOcsApiRequestHeader: Boolean, + private val requestBody: ByteArray, + depth: Int +) : OkHttpMethodBase(uri, useOcsApiRequestHeader) { + init { + addRequestHeader(HEADER_DEPTH, depth.toString()) + } + + override fun applyType(temp: Request.Builder) { + temp.method(METHOD_NAME, requestBody.toRequestBody(CONTENT_TYPE)) + } + + companion object { + private const val METHOD_NAME = "PROPFIND" + private const val HEADER_DEPTH = "Depth" + private val CONTENT_TYPE = "text/xml; charset=UTF-8".toMediaTypeOrNull() + } +} diff --git a/library/src/main/java/com/owncloud/android/lib/resources/e2ee/ToggleEncryptionRemoteOperation.kt b/library/src/main/java/com/owncloud/android/lib/resources/e2ee/ToggleEncryptionRemoteOperation.kt index 0630129fb..41585bd28 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/e2ee/ToggleEncryptionRemoteOperation.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/e2ee/ToggleEncryptionRemoteOperation.kt @@ -6,17 +6,18 @@ */ package com.owncloud.android.lib.resources.e2ee +import com.nextcloud.common.NextcloudClient +import com.nextcloud.common.OkHttpMethodBase import com.nextcloud.common.SessionTimeOut import com.nextcloud.common.defaultSessionTimeOut -import com.owncloud.android.lib.common.OwnCloudClient +import com.nextcloud.operations.DeleteMethod +import com.nextcloud.operations.PutMethod 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.files.ReadFolderRemoteOperation -import org.apache.commons.httpclient.HttpMethodBase +import okhttp3.RequestBody.Companion.toRequestBody import org.apache.commons.httpclient.HttpStatus -import org.apache.commons.httpclient.methods.DeleteMethod -import org.apache.commons.httpclient.methods.PutMethod class ToggleEncryptionRemoteOperation @JvmOverloads @@ -26,11 +27,10 @@ class ToggleEncryptionRemoteOperation private val encryption: Boolean, private val sessionTimeOut: SessionTimeOut = defaultSessionTimeOut ) : RemoteOperation() { - @Deprecated("Deprecated in Java") - @Suppress("Detekt.TooGenericExceptionCaught", "DEPRECATION") - override fun run(client: OwnCloudClient): RemoteOperationResult { + @Suppress("TooGenericExceptionCaught") + override fun run(client: NextcloudClient): RemoteOperationResult { val folderResult = ReadFolderRemoteOperation(remotePath.orEmpty()).execute(client) - if (folderResult.isSuccess && folderResult.getData().size > 1) { + if (folderResult.isSuccess && folderResult.resultData.size > 1) { return RemoteOperationResult(false, "Non empty", HttpStatus.SC_FORBIDDEN) } @@ -41,15 +41,10 @@ class ToggleEncryptionRemoteOperation } } - private fun toggleEncryption(client: OwnCloudClient): RemoteOperationResult { + private fun toggleEncryption(client: NextcloudClient): RemoteOperationResult { val (status, method) = executeWithFallback(client) - return if (status == HttpStatus.SC_OK) { - RemoteOperationResult(true, method) - } else { - client.exhaustResponse(method.getResponseBodyAsStream()) - RemoteOperationResult(false, method) - }.also { + return RemoteOperationResult(status == HttpStatus.SC_OK, method).also { method.releaseConnection() } } @@ -58,33 +53,39 @@ class ToggleEncryptionRemoteOperation * Tries the v2 endpoint first, falling back to v1 on 404/500. * Returns the final status code and the method used. */ - private fun executeWithFallback(client: OwnCloudClient): Pair { + private fun executeWithFallback(client: NextcloudClient): Pair { + val timedClient = client.withSessionTimeOut(sessionTimeOut) + val v2Method = buildMethod(client, ENCRYPTED_URL_V2) - val v2Status = client.executeMethod(v2Method, sessionTimeOut.readTimeOut, sessionTimeOut.connectionTimeOut) + val v2Status = timedClient.execute(v2Method) val needsFallback = v2Status == HttpStatus.SC_NOT_FOUND || v2Status == HttpStatus.SC_INTERNAL_SERVER_ERROR if (!needsFallback) return v2Status to v2Method v2Method.releaseConnection() val v1Method = buildMethod(client, ENCRYPTED_URL_V1) - val v1Status = client.executeMethod(v1Method, sessionTimeOut.readTimeOut, sessionTimeOut.connectionTimeOut) + val v1Status = timedClient.execute(v1Method) return v1Status to v1Method } private fun buildMethod( - client: OwnCloudClient, + client: NextcloudClient, baseUrl: String - ): HttpMethodBase = - ( + ): OkHttpMethodBase { + val uri = "${client.baseUri}$baseUrl$localId" + + val method = if (encryption) { - PutMethod("${client.baseUri}$baseUrl$localId") + PutMethod(uri, false, "".toRequestBody(null)) } else { - DeleteMethod("${client.baseUri}$baseUrl$localId") + DeleteMethod(uri, false) } - ).apply { - addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE) - addRequestHeader(CONTENT_TYPE, FORM_URLENCODED) - } + + method.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE) + method.addRequestHeader(CONTENT_TYPE, FORM_URLENCODED) + + return method + } companion object { private val TAG = ToggleEncryptionRemoteOperation::class.java.simpleName diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/ReadFolderRemoteOperation.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/ReadFolderRemoteOperation.kt index b08eca2db..8fa9a2c6f 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/ReadFolderRemoteOperation.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/ReadFolderRemoteOperation.kt @@ -7,7 +7,8 @@ */ package com.owncloud.android.lib.resources.files -import com.owncloud.android.lib.common.OwnCloudClient +import com.nextcloud.common.NextcloudClient +import com.nextcloud.operations.PropfindMethod import com.owncloud.android.lib.common.network.WebdavEntry import com.owncloud.android.lib.common.network.WebdavUtils import com.owncloud.android.lib.common.operations.RemoteOperation @@ -17,59 +18,65 @@ import com.owncloud.android.lib.resources.files.model.RemoteFile import org.apache.commons.httpclient.HttpStatus import org.apache.jackrabbit.webdav.DavConstants import org.apache.jackrabbit.webdav.MultiStatus -import org.apache.jackrabbit.webdav.client.methods.PropFindMethod +import org.apache.jackrabbit.webdav.property.PropfindInfo +import org.apache.jackrabbit.webdav.xml.DomUtil +import java.io.ByteArrayOutputStream class ReadFolderRemoteOperation( private val remotePath: String -) : RemoteOperation() { - @Deprecated("Deprecated in Java") - @Suppress("TooGenericExceptionCaught", "DEPRECATION") - override fun run(client: OwnCloudClient): RemoteOperationResult { - var query: PropFindMethod? = null +) : RemoteOperation>() { + @Suppress("TooGenericExceptionCaught") + override fun run(client: NextcloudClient): RemoteOperationResult> { + val method = + PropfindMethod(client.getFilesDavUri(remotePath), false, buildPropfindRequestBody(), DavConstants.DEPTH_1) val result = try { - query = - PropFindMethod( - client.getFilesDavUri(remotePath), - WebdavUtils.getAllPropSet(), - DavConstants.DEPTH_1 - ) - val status = client.executeMethod(query) + val status = client.execute(method) - if (status == HttpStatus.SC_MULTI_STATUS || status == HttpStatus.SC_OK) { - val folderAndFiles = readData(query.responseBodyAsMultiStatus, client) - RemoteOperationResult(true, query).apply { data = folderAndFiles } - } else { - client.exhaustResponse(query.responseBodyAsStream) - RemoteOperationResult(false, query) + if (status != HttpStatus.SC_MULTI_STATUS && status != HttpStatus.SC_OK) { + return RemoteOperationResult(false, method) + } + + val document = DomUtil.parseDocument(method.getResponseBodyAsStream()) + val multiStatus = MultiStatus.createFromXml(document.documentElement) + val davUriPath = client.filesDavUri.encodedPath.orEmpty() + RemoteOperationResult>(true, method).apply { + resultData = readData(multiStatus, davUriPath) } - } catch (e: OutOfMemoryError) { - Log_OC.e(TAG, "Not enough memory to read the content of $remotePath", e) - RemoteOperationResult(RemoteOperationResult.ResultCode.OUT_OF_MEMORY) } catch (e: Exception) { RemoteOperationResult(e) } finally { - query?.releaseConnection() + method.releaseConnection() } return result.also { log(it) } } + private fun buildPropfindRequestBody(): ByteArray { + val propfindInfo = PropfindInfo(DavConstants.PROPFIND_BY_PROPERTY, WebdavUtils.getAllPropSet()) + val document = DomUtil.createDocument() + document.appendChild(propfindInfo.toXml(document)) + + return ByteArrayOutputStream().use { + DomUtil.transformDocument(document, it) + it.toByteArray() + } + } + fun isMultiStatus(status: Int): Boolean = status == HttpStatus.SC_MULTI_STATUS private fun readData( remoteData: MultiStatus, - client: OwnCloudClient - ): ArrayList { + davUriPath: String + ): ArrayList { val responses = remoteData.responses - val davUriPath = client.filesDavUri.encodedPath.orEmpty() return responses.mapTo(ArrayList(responses.size)) { RemoteFile(WebdavEntry(it, davUriPath)) } } @Suppress("DEPRECATION") - private fun log(result: RemoteOperationResult) { + private fun log(result: RemoteOperationResult>) { val message = "Synchronized $remotePath: ${result.logMessage}" when { result.isSuccess -> Log_OC.i(TAG, message)